xref: /vim-8.2.3635/src/version.c (revision 3d1d6475)
1 /* vi:set ts=8 sts=4 sw=4 noet:
2  *
3  * VIM - Vi IMproved		by Bram Moolenaar
4  *
5  * Do ":help uganda"  in Vim to read copying and usage conditions.
6  * Do ":help credits" in Vim to see a list of people who contributed.
7  * See README.txt for an overview of the Vim source code.
8  */
9 
10 #include "vim.h"
11 
12 #ifdef AMIGA
13 # include <time.h>	/* for time() */
14 #endif
15 
16 /*
17  * Vim originated from Stevie version 3.6 (Fish disk 217) by GRWalter (Fred)
18  * It has been changed beyond recognition since then.
19  *
20  * Differences between version 7.4 and 8.x can be found with ":help version8".
21  * Differences between version 6.4 and 7.x can be found with ":help version7".
22  * Differences between version 5.8 and 6.x can be found with ":help version6".
23  * Differences between version 4.x and 5.x can be found with ":help version5".
24  * Differences between version 3.0 and 4.x can be found with ":help version4".
25  * All the remarks about older versions have been removed, they are not very
26  * interesting.
27  */
28 
29 #include "version.h"
30 
31 char		*Version = VIM_VERSION_SHORT;
32 static char	*mediumVersion = VIM_VERSION_MEDIUM;
33 
34 #if defined(HAVE_DATE_TIME) || defined(PROTO)
35 # if (defined(VMS) && defined(VAXC)) || defined(PROTO)
36 char	longVersion[sizeof(VIM_VERSION_LONG_DATE) + sizeof(__DATE__)
37 						      + sizeof(__TIME__) + 3];
38 
39     void
40 init_longVersion(void)
41 {
42     /*
43      * Construct the long version string.  Necessary because
44      * VAX C can't catenate strings in the preprocessor.
45      */
46     strcpy(longVersion, VIM_VERSION_LONG_DATE);
47     strcat(longVersion, __DATE__);
48     strcat(longVersion, " ");
49     strcat(longVersion, __TIME__);
50     strcat(longVersion, ")");
51 }
52 
53 # else
54     void
55 init_longVersion(void)
56 {
57     char *date_time = __DATE__ " " __TIME__;
58     char *msg = _("%s (%s, compiled %s)");
59     size_t len = strlen(msg)
60 		+ strlen(VIM_VERSION_LONG_ONLY)
61 		+ strlen(VIM_VERSION_DATE_ONLY)
62 		+ strlen(date_time);
63 
64     longVersion = (char *)alloc(len);
65     if (longVersion == NULL)
66 	longVersion = VIM_VERSION_LONG;
67     else
68 	vim_snprintf(longVersion, len, msg,
69 		      VIM_VERSION_LONG_ONLY, VIM_VERSION_DATE_ONLY, date_time);
70 }
71 # endif
72 #else
73 char	*longVersion = VIM_VERSION_LONG;
74 
75     void
76 init_longVersion(void)
77 {
78     // nothing to do
79 }
80 #endif
81 
82 static void list_features(void);
83 
84 static char *(features[]) =
85 {
86 #ifdef HAVE_ACL
87 	"+acl",
88 #else
89 	"-acl",
90 #endif
91 #ifdef AMIGA		/* only for Amiga systems */
92 # ifdef FEAT_ARP
93 	"+ARP",
94 # else
95 	"-ARP",
96 # endif
97 #endif
98 #ifdef FEAT_ARABIC
99 	"+arabic",
100 #else
101 	"-arabic",
102 #endif
103 	"+autocmd",
104 #ifdef FEAT_AUTOSERVERNAME
105 	"+autoservername",
106 #else
107 	"-autoservername",
108 #endif
109 #ifdef FEAT_BEVAL_GUI
110 	"+balloon_eval",
111 #else
112 	"-balloon_eval",
113 #endif
114 #ifdef FEAT_BEVAL_TERM
115 	"+balloon_eval_term",
116 #else
117 	"-balloon_eval_term",
118 #endif
119 #ifdef FEAT_BROWSE
120 	"+browse",
121 #else
122 	"-browse",
123 #endif
124 #ifdef NO_BUILTIN_TCAPS
125 	"-builtin_terms",
126 #endif
127 #ifdef SOME_BUILTIN_TCAPS
128 	"+builtin_terms",
129 #endif
130 #ifdef ALL_BUILTIN_TCAPS
131 	"++builtin_terms",
132 #endif
133 #ifdef FEAT_BYTEOFF
134 	"+byte_offset",
135 #else
136 	"-byte_offset",
137 #endif
138 #ifdef FEAT_JOB_CHANNEL
139 	"+channel",
140 #else
141 	"-channel",
142 #endif
143 #ifdef FEAT_CINDENT
144 	"+cindent",
145 #else
146 	"-cindent",
147 #endif
148 #ifdef FEAT_CLIENTSERVER
149 	"+clientserver",
150 #else
151 	"-clientserver",
152 #endif
153 #ifdef FEAT_CLIPBOARD
154 	"+clipboard",
155 #else
156 	"-clipboard",
157 #endif
158 #ifdef FEAT_CMDL_COMPL
159 	"+cmdline_compl",
160 #else
161 	"-cmdline_compl",
162 #endif
163 #ifdef FEAT_CMDHIST
164 	"+cmdline_hist",
165 #else
166 	"-cmdline_hist",
167 #endif
168 #ifdef FEAT_CMDL_INFO
169 	"+cmdline_info",
170 #else
171 	"-cmdline_info",
172 #endif
173 #ifdef FEAT_COMMENTS
174 	"+comments",
175 #else
176 	"-comments",
177 #endif
178 #ifdef FEAT_CONCEAL
179 	"+conceal",
180 #else
181 	"-conceal",
182 #endif
183 #ifdef FEAT_CRYPT
184 	"+cryptv",
185 #else
186 	"-cryptv",
187 #endif
188 #ifdef FEAT_CSCOPE
189 	"+cscope",
190 #else
191 	"-cscope",
192 #endif
193 	"+cursorbind",
194 #ifdef CURSOR_SHAPE
195 	"+cursorshape",
196 #else
197 	"-cursorshape",
198 #endif
199 #if defined(FEAT_CON_DIALOG) && defined(FEAT_GUI_DIALOG)
200 	"+dialog_con_gui",
201 #else
202 # if defined(FEAT_CON_DIALOG)
203 	"+dialog_con",
204 # else
205 #  if defined(FEAT_GUI_DIALOG)
206 	"+dialog_gui",
207 #  else
208 	"-dialog",
209 #  endif
210 # endif
211 #endif
212 #ifdef FEAT_DIFF
213 	"+diff",
214 #else
215 	"-diff",
216 #endif
217 #ifdef FEAT_DIGRAPHS
218 	"+digraphs",
219 #else
220 	"-digraphs",
221 #endif
222 #ifdef FEAT_GUI_W32
223 # ifdef FEAT_DIRECTX
224 	"+directx",
225 # else
226 	"-directx",
227 # endif
228 #endif
229 #ifdef FEAT_DND
230 	"+dnd",
231 #else
232 	"-dnd",
233 #endif
234 #ifdef EBCDIC
235 	"+ebcdic",
236 #else
237 	"-ebcdic",
238 #endif
239 #ifdef FEAT_EMACS_TAGS
240 	"+emacs_tags",
241 #else
242 	"-emacs_tags",
243 #endif
244 #ifdef FEAT_EVAL
245 	"+eval",
246 #else
247 	"-eval",
248 #endif
249 	"+ex_extra",
250 #ifdef FEAT_SEARCH_EXTRA
251 	"+extra_search",
252 #else
253 	"-extra_search",
254 #endif
255 #ifdef FEAT_FKMAP
256 	"+farsi",
257 #else
258 	"-farsi",
259 #endif
260 #ifdef FEAT_SEARCHPATH
261 	"+file_in_path",
262 #else
263 	"-file_in_path",
264 #endif
265 #ifdef FEAT_FIND_ID
266 	"+find_in_path",
267 #else
268 	"-find_in_path",
269 #endif
270 #ifdef FEAT_FLOAT
271 	"+float",
272 #else
273 	"-float",
274 #endif
275 #ifdef FEAT_FOLDING
276 	"+folding",
277 #else
278 	"-folding",
279 #endif
280 #ifdef FEAT_FOOTER
281 	"+footer",
282 #else
283 	"-footer",
284 #endif
285 	    /* only interesting on Unix systems */
286 #if !defined(USE_SYSTEM) && defined(UNIX)
287 	"+fork()",
288 #endif
289 #ifdef FEAT_GETTEXT
290 # ifdef DYNAMIC_GETTEXT
291 	"+gettext/dyn",
292 # else
293 	"+gettext",
294 # endif
295 #else
296 	"-gettext",
297 #endif
298 #ifdef FEAT_HANGULIN
299 	"+hangul_input",
300 #else
301 	"-hangul_input",
302 #endif
303 #if (defined(HAVE_ICONV_H) && defined(USE_ICONV)) || defined(DYNAMIC_ICONV)
304 # ifdef DYNAMIC_ICONV
305 	"+iconv/dyn",
306 # else
307 	"+iconv",
308 # endif
309 #else
310 	"-iconv",
311 #endif
312 #ifdef FEAT_INS_EXPAND
313 	"+insert_expand",
314 #else
315 	"-insert_expand",
316 #endif
317 #ifdef FEAT_JOB_CHANNEL
318 	"+job",
319 #else
320 	"-job",
321 #endif
322 #ifdef FEAT_JUMPLIST
323 	"+jumplist",
324 #else
325 	"-jumplist",
326 #endif
327 #ifdef FEAT_KEYMAP
328 	"+keymap",
329 #else
330 	"-keymap",
331 #endif
332 #ifdef FEAT_EVAL
333 	"+lambda",
334 #else
335 	"-lambda",
336 #endif
337 #ifdef FEAT_LANGMAP
338 	"+langmap",
339 #else
340 	"-langmap",
341 #endif
342 #ifdef FEAT_LIBCALL
343 	"+libcall",
344 #else
345 	"-libcall",
346 #endif
347 #ifdef FEAT_LINEBREAK
348 	"+linebreak",
349 #else
350 	"-linebreak",
351 #endif
352 #ifdef FEAT_LISP
353 	"+lispindent",
354 #else
355 	"-lispindent",
356 #endif
357 	"+listcmds",
358 #ifdef FEAT_LOCALMAP
359 	"+localmap",
360 #else
361 	"-localmap",
362 #endif
363 #ifdef FEAT_LUA
364 # ifdef DYNAMIC_LUA
365 	"+lua/dyn",
366 # else
367 	"+lua",
368 # endif
369 #else
370 	"-lua",
371 #endif
372 #ifdef FEAT_MENU
373 	"+menu",
374 #else
375 	"-menu",
376 #endif
377 #ifdef FEAT_SESSION
378 	"+mksession",
379 #else
380 	"-mksession",
381 #endif
382 #ifdef FEAT_MODIFY_FNAME
383 	"+modify_fname",
384 #else
385 	"-modify_fname",
386 #endif
387 #ifdef FEAT_MOUSE
388 	"+mouse",
389 #  ifdef FEAT_MOUSESHAPE
390 	"+mouseshape",
391 #  else
392 	"-mouseshape",
393 #  endif
394 # else
395 	"-mouse",
396 #endif
397 
398 #if defined(UNIX) || defined(VMS)
399 # ifdef FEAT_MOUSE_DEC
400 	"+mouse_dec",
401 # else
402 	"-mouse_dec",
403 # endif
404 # ifdef FEAT_MOUSE_GPM
405 	"+mouse_gpm",
406 # else
407 	"-mouse_gpm",
408 # endif
409 # ifdef FEAT_MOUSE_JSB
410 	"+mouse_jsbterm",
411 # else
412 	"-mouse_jsbterm",
413 # endif
414 # ifdef FEAT_MOUSE_NET
415 	"+mouse_netterm",
416 # else
417 	"-mouse_netterm",
418 # endif
419 #endif
420 
421 #ifdef __QNX__
422 # ifdef FEAT_MOUSE_PTERM
423 	"+mouse_pterm",
424 # else
425 	"-mouse_pterm",
426 # endif
427 #endif
428 
429 #if defined(UNIX) || defined(VMS)
430 # ifdef FEAT_MOUSE_SGR
431 	"+mouse_sgr",
432 # else
433 	"-mouse_sgr",
434 # endif
435 # ifdef FEAT_SYSMOUSE
436 	"+mouse_sysmouse",
437 # else
438 	"-mouse_sysmouse",
439 # endif
440 # ifdef FEAT_MOUSE_URXVT
441 	"+mouse_urxvt",
442 # else
443 	"-mouse_urxvt",
444 # endif
445 # ifdef FEAT_MOUSE_XTERM
446 	"+mouse_xterm",
447 # else
448 	"-mouse_xterm",
449 # endif
450 #endif
451 
452 #ifdef FEAT_MBYTE_IME
453 # ifdef DYNAMIC_IME
454 	"+multi_byte_ime/dyn",
455 # else
456 	"+multi_byte_ime",
457 # endif
458 #else
459 # ifdef FEAT_MBYTE
460 	"+multi_byte",
461 # else
462 	"-multi_byte",
463 # endif
464 #endif
465 #ifdef FEAT_MULTI_LANG
466 	"+multi_lang",
467 #else
468 	"-multi_lang",
469 #endif
470 #ifdef FEAT_MZSCHEME
471 # ifdef DYNAMIC_MZSCHEME
472 	"+mzscheme/dyn",
473 # else
474 	"+mzscheme",
475 # endif
476 #else
477 	"-mzscheme",
478 #endif
479 #ifdef FEAT_NETBEANS_INTG
480 	"+netbeans_intg",
481 #else
482 	"-netbeans_intg",
483 #endif
484 #ifdef FEAT_NUM64
485 	"+num64",
486 #else
487 	"-num64",
488 #endif
489 #ifdef FEAT_GUI_W32
490 # ifdef FEAT_OLE
491 	"+ole",
492 # else
493 	"-ole",
494 # endif
495 #endif
496 	"+packages",
497 #ifdef FEAT_PATH_EXTRA
498 	"+path_extra",
499 #else
500 	"-path_extra",
501 #endif
502 #ifdef FEAT_PERL
503 # ifdef DYNAMIC_PERL
504 	"+perl/dyn",
505 # else
506 	"+perl",
507 # endif
508 #else
509 	"-perl",
510 #endif
511 #ifdef FEAT_PERSISTENT_UNDO
512 	"+persistent_undo",
513 #else
514 	"-persistent_undo",
515 #endif
516 #ifdef FEAT_PRINTER
517 # ifdef FEAT_POSTSCRIPT
518 	"+postscript",
519 # else
520 	"-postscript",
521 # endif
522 	"+printer",
523 #else
524 	"-printer",
525 #endif
526 #ifdef FEAT_PROFILE
527 	"+profile",
528 #else
529 	"-profile",
530 #endif
531 #ifdef FEAT_PYTHON
532 # ifdef DYNAMIC_PYTHON
533 	"+python/dyn",
534 # else
535 	"+python",
536 # endif
537 #else
538 	"-python",
539 #endif
540 #ifdef FEAT_PYTHON3
541 # ifdef DYNAMIC_PYTHON3
542 	"+python3/dyn",
543 # else
544 	"+python3",
545 # endif
546 #else
547 	"-python3",
548 #endif
549 #ifdef FEAT_QUICKFIX
550 	"+quickfix",
551 #else
552 	"-quickfix",
553 #endif
554 #ifdef FEAT_RELTIME
555 	"+reltime",
556 #else
557 	"-reltime",
558 #endif
559 #ifdef FEAT_RIGHTLEFT
560 	"+rightleft",
561 #else
562 	"-rightleft",
563 #endif
564 #ifdef FEAT_RUBY
565 # ifdef DYNAMIC_RUBY
566 	"+ruby/dyn",
567 # else
568 	"+ruby",
569 # endif
570 #else
571 	"-ruby",
572 #endif
573 	"+scrollbind",
574 #ifdef FEAT_SIGNS
575 	"+signs",
576 #else
577 	"-signs",
578 #endif
579 #ifdef FEAT_SMARTINDENT
580 	"+smartindent",
581 #else
582 	"-smartindent",
583 #endif
584 #ifdef STARTUPTIME
585 	"+startuptime",
586 #else
587 	"-startuptime",
588 #endif
589 #ifdef FEAT_STL_OPT
590 	"+statusline",
591 #else
592 	"-statusline",
593 #endif
594 #ifdef FEAT_SUN_WORKSHOP
595 	"+sun_workshop",
596 #else
597 	"-sun_workshop",
598 #endif
599 #ifdef FEAT_SYN_HL
600 	"+syntax",
601 #else
602 	"-syntax",
603 #endif
604 	    /* only interesting on Unix systems */
605 #if defined(USE_SYSTEM) && defined(UNIX)
606 	"+system()",
607 #endif
608 #ifdef FEAT_TAG_BINS
609 	"+tag_binary",
610 #else
611 	"-tag_binary",
612 #endif
613 #ifdef FEAT_TAG_OLDSTATIC
614 	"+tag_old_static",
615 #else
616 	"-tag_old_static",
617 #endif
618 #ifdef FEAT_TAG_ANYWHITE
619 	"+tag_any_white",
620 #else
621 	"-tag_any_white",
622 #endif
623 #ifdef FEAT_TCL
624 # ifdef DYNAMIC_TCL
625 	"+tcl/dyn",
626 # else
627 	"+tcl",
628 # endif
629 #else
630 	"-tcl",
631 #endif
632 #ifdef FEAT_TERMGUICOLORS
633 	"+termguicolors",
634 #else
635 	"-termguicolors",
636 #endif
637 #ifdef FEAT_TERMINAL
638 	"+terminal",
639 #else
640 	"-terminal",
641 #endif
642 #if defined(UNIX)
643 /* only Unix can have terminfo instead of termcap */
644 # ifdef TERMINFO
645 	"+terminfo",
646 # else
647 	"-terminfo",
648 # endif
649 #else		    /* unix always includes termcap support */
650 # ifdef HAVE_TGETENT
651 	"+tgetent",
652 # else
653 	"-tgetent",
654 # endif
655 #endif
656 #ifdef FEAT_TERMRESPONSE
657 	"+termresponse",
658 #else
659 	"-termresponse",
660 #endif
661 #ifdef FEAT_TEXTOBJ
662 	"+textobjects",
663 #else
664 	"-textobjects",
665 #endif
666 #ifdef FEAT_TIMERS
667 	"+timers",
668 #else
669 	"-timers",
670 #endif
671 #ifdef FEAT_TITLE
672 	"+title",
673 #else
674 	"-title",
675 #endif
676 #ifdef FEAT_TOOLBAR
677 	"+toolbar",
678 #else
679 	"-toolbar",
680 #endif
681 #ifdef FEAT_USR_CMDS
682 	"+user_commands",
683 #else
684 	"-user_commands",
685 #endif
686 #ifdef FEAT_VARTABS
687 	"+vartabs",
688 #else
689 	"-vartabs",
690 #endif
691 	"+vertsplit",
692 #ifdef FEAT_VIRTUALEDIT
693 	"+virtualedit",
694 #else
695 	"-virtualedit",
696 #endif
697 	"+visual",
698 #ifdef FEAT_VISUALEXTRA
699 	"+visualextra",
700 #else
701 	"-visualextra",
702 #endif
703 #ifdef FEAT_VIMINFO
704 	"+viminfo",
705 #else
706 	"-viminfo",
707 #endif
708 #ifdef FEAT_VREPLACE
709 	"+vreplace",
710 #else
711 	"-vreplace",
712 #endif
713 #ifdef WIN3264
714 # ifdef FEAT_VTP
715 	"+vtp",
716 # else
717 	"-vtp",
718 # endif
719 #endif
720 #ifdef FEAT_WILDIGN
721 	"+wildignore",
722 #else
723 	"-wildignore",
724 #endif
725 #ifdef FEAT_WILDMENU
726 	"+wildmenu",
727 #else
728 	"-wildmenu",
729 #endif
730 	"+windows",
731 #ifdef FEAT_WRITEBACKUP
732 	"+writebackup",
733 #else
734 	"-writebackup",
735 #endif
736 #if defined(UNIX) || defined(VMS)
737 # ifdef FEAT_X11
738 	"+X11",
739 # else
740 	"-X11",
741 # endif
742 #endif
743 #ifdef FEAT_XFONTSET
744 	"+xfontset",
745 #else
746 	"-xfontset",
747 #endif
748 #ifdef FEAT_XIM
749 	"+xim",
750 #else
751 	"-xim",
752 #endif
753 #ifdef WIN3264
754 # ifdef FEAT_XPM_W32
755 	"+xpm_w32",
756 # else
757 	"-xpm_w32",
758 # endif
759 #else
760 # ifdef HAVE_XPM
761 	"+xpm",
762 # else
763 	"-xpm",
764 # endif
765 #endif
766 #if defined(UNIX) || defined(VMS)
767 # ifdef USE_XSMP_INTERACT
768 	"+xsmp_interact",
769 # else
770 #  ifdef USE_XSMP
771 	"+xsmp",
772 #  else
773 	"-xsmp",
774 #  endif
775 # endif
776 # ifdef FEAT_XCLIPBOARD
777 	"+xterm_clipboard",
778 # else
779 	"-xterm_clipboard",
780 # endif
781 #endif
782 #ifdef FEAT_XTERM_SAVE
783 	"+xterm_save",
784 #else
785 	"-xterm_save",
786 #endif
787 	NULL
788 };
789 
790 static int included_patches[] =
791 {   /* Add new patch number below this line */
792 /**/
793     143,
794 /**/
795     142,
796 /**/
797     141,
798 /**/
799     140,
800 /**/
801     139,
802 /**/
803     138,
804 /**/
805     137,
806 /**/
807     136,
808 /**/
809     135,
810 /**/
811     134,
812 /**/
813     133,
814 /**/
815     132,
816 /**/
817     131,
818 /**/
819     130,
820 /**/
821     129,
822 /**/
823     128,
824 /**/
825     127,
826 /**/
827     126,
828 /**/
829     125,
830 /**/
831     124,
832 /**/
833     123,
834 /**/
835     122,
836 /**/
837     121,
838 /**/
839     120,
840 /**/
841     119,
842 /**/
843     118,
844 /**/
845     117,
846 /**/
847     116,
848 /**/
849     115,
850 /**/
851     114,
852 /**/
853     113,
854 /**/
855     112,
856 /**/
857     111,
858 /**/
859     110,
860 /**/
861     109,
862 /**/
863     108,
864 /**/
865     107,
866 /**/
867     106,
868 /**/
869     105,
870 /**/
871     104,
872 /**/
873     103,
874 /**/
875     102,
876 /**/
877     101,
878 /**/
879     100,
880 /**/
881     99,
882 /**/
883     98,
884 /**/
885     97,
886 /**/
887     96,
888 /**/
889     95,
890 /**/
891     94,
892 /**/
893     93,
894 /**/
895     92,
896 /**/
897     91,
898 /**/
899     90,
900 /**/
901     89,
902 /**/
903     88,
904 /**/
905     87,
906 /**/
907     86,
908 /**/
909     85,
910 /**/
911     84,
912 /**/
913     83,
914 /**/
915     82,
916 /**/
917     81,
918 /**/
919     80,
920 /**/
921     79,
922 /**/
923     78,
924 /**/
925     77,
926 /**/
927     76,
928 /**/
929     75,
930 /**/
931     74,
932 /**/
933     73,
934 /**/
935     72,
936 /**/
937     71,
938 /**/
939     70,
940 /**/
941     69,
942 /**/
943     68,
944 /**/
945     67,
946 /**/
947     66,
948 /**/
949     65,
950 /**/
951     64,
952 /**/
953     63,
954 /**/
955     62,
956 /**/
957     61,
958 /**/
959     60,
960 /**/
961     59,
962 /**/
963     58,
964 /**/
965     57,
966 /**/
967     56,
968 /**/
969     55,
970 /**/
971     54,
972 /**/
973     53,
974 /**/
975     52,
976 /**/
977     51,
978 /**/
979     50,
980 /**/
981     49,
982 /**/
983     48,
984 /**/
985     47,
986 /**/
987     46,
988 /**/
989     45,
990 /**/
991     44,
992 /**/
993     43,
994 /**/
995     42,
996 /**/
997     41,
998 /**/
999     40,
1000 /**/
1001     39,
1002 /**/
1003     38,
1004 /**/
1005     37,
1006 /**/
1007     36,
1008 /**/
1009     35,
1010 /**/
1011     34,
1012 /**/
1013     33,
1014 /**/
1015     32,
1016 /**/
1017     31,
1018 /**/
1019     30,
1020 /**/
1021     29,
1022 /**/
1023     28,
1024 /**/
1025     27,
1026 /**/
1027     26,
1028 /**/
1029     25,
1030 /**/
1031     24,
1032 /**/
1033     23,
1034 /**/
1035     22,
1036 /**/
1037     21,
1038 /**/
1039     20,
1040 /**/
1041     19,
1042 /**/
1043     18,
1044 /**/
1045     17,
1046 /**/
1047     16,
1048 /**/
1049     15,
1050 /**/
1051     14,
1052 /**/
1053     13,
1054 /**/
1055     12,
1056 /**/
1057     11,
1058 /**/
1059     10,
1060 /**/
1061     9,
1062 /**/
1063     8,
1064 /**/
1065     7,
1066 /**/
1067     6,
1068 /**/
1069     5,
1070 /**/
1071     4,
1072 /**/
1073     3,
1074 /**/
1075     2,
1076 /**/
1077     1,
1078 /**/
1079     0
1080 };
1081 
1082 /*
1083  * Place to put a short description when adding a feature with a patch.
1084  * Keep it short, e.g.,: "relative numbers", "persistent undo".
1085  * Also add a comment marker to separate the lines.
1086  * See the official Vim patches for the diff format: It must use a context of
1087  * one line only.  Create it by hand or use "diff -C2" and edit the patch.
1088  */
1089 static char *(extra_patches[]) =
1090 {   /* Add your patch description below this line */
1091 /**/
1092     NULL
1093 };
1094 
1095     int
1096 highest_patch(void)
1097 {
1098     int		i;
1099     int		h = 0;
1100 
1101     for (i = 0; included_patches[i] != 0; ++i)
1102 	if (included_patches[i] > h)
1103 	    h = included_patches[i];
1104     return h;
1105 }
1106 
1107 #if defined(FEAT_EVAL) || defined(PROTO)
1108 /*
1109  * Return TRUE if patch "n" has been included.
1110  */
1111     int
1112 has_patch(int n)
1113 {
1114     int		i;
1115 
1116     for (i = 0; included_patches[i] != 0; ++i)
1117 	if (included_patches[i] == n)
1118 	    return TRUE;
1119     return FALSE;
1120 }
1121 #endif
1122 
1123     void
1124 ex_version(exarg_T *eap)
1125 {
1126     /*
1127      * Ignore a ":version 9.99" command.
1128      */
1129     if (*eap->arg == NUL)
1130     {
1131 	msg_putchar('\n');
1132 	list_version();
1133     }
1134 }
1135 
1136 /*
1137  * Output a string for the version message.  If it's going to wrap, output a
1138  * newline, unless the message is too long to fit on the screen anyway.
1139  * When "wrap" is TRUE wrap the string in [].
1140  */
1141     static void
1142 version_msg_wrap(char_u *s, int wrap)
1143 {
1144     int		len = (int)vim_strsize(s) + (wrap ? 2 : 0);
1145 
1146     if (!got_int && len < (int)Columns && msg_col + len >= (int)Columns
1147 								&& *s != '\n')
1148 	msg_putchar('\n');
1149     if (!got_int)
1150     {
1151 	if (wrap)
1152 	    MSG_PUTS("[");
1153 	MSG_PUTS(s);
1154 	if (wrap)
1155 	    MSG_PUTS("]");
1156     }
1157 }
1158 
1159     static void
1160 version_msg(char *s)
1161 {
1162     version_msg_wrap((char_u *)s, FALSE);
1163 }
1164 
1165 /*
1166  * List all features aligned in columns, dictionary style.
1167  */
1168     static void
1169 list_features(void)
1170 {
1171     list_in_columns((char_u **)features, -1, -1);
1172 }
1173 
1174 /*
1175  * List string items nicely aligned in columns.
1176  * When "size" is < 0 then the last entry is marked with NULL.
1177  * The entry with index "current" is inclosed in [].
1178  */
1179     void
1180 list_in_columns(char_u **items, int size, int current)
1181 {
1182     int		i;
1183     int		ncol;
1184     int		nrow;
1185     int		item_count = 0;
1186     int		width = 0;
1187 
1188     /* Find the length of the longest item, use that + 1 as the column
1189      * width. */
1190     for (i = 0; size < 0 ? items[i] != NULL : i < size; ++i)
1191     {
1192 	int l = (int)vim_strsize(items[i]) + (i == current ? 2 : 0);
1193 
1194 	if (l > width)
1195 	    width = l;
1196 	++item_count;
1197     }
1198     width += 1;
1199 
1200     if (Columns < width)
1201     {
1202 	/* Not enough screen columns - show one per line */
1203 	for (i = 0; items[i] != NULL; ++i)
1204 	{
1205 	    version_msg_wrap(items[i], i == current);
1206 	    if (msg_col > 0)
1207 		msg_putchar('\n');
1208 	}
1209 	return;
1210     }
1211 
1212     /* The rightmost column doesn't need a separator.
1213      * Sacrifice it to fit in one more column if possible. */
1214     ncol = (int) (Columns + 1) / width;
1215     nrow = item_count / ncol + (item_count % ncol ? 1 : 0);
1216 
1217     /* i counts columns then rows.  idx counts rows then columns. */
1218     for (i = 0; !got_int && i < nrow * ncol; ++i)
1219     {
1220 	int idx = (i / ncol) + (i % ncol) * nrow;
1221 
1222 	if (idx < item_count)
1223 	{
1224 	    int last_col = (i + 1) % ncol == 0;
1225 
1226 	    if (idx == current)
1227 		msg_putchar('[');
1228 	    msg_puts(items[idx]);
1229 	    if (idx == current)
1230 		msg_putchar(']');
1231 	    if (last_col)
1232 	    {
1233 		if (msg_col > 0)
1234 		    msg_putchar('\n');
1235 	    }
1236 	    else
1237 	    {
1238 		while (msg_col % width)
1239 		    msg_putchar(' ');
1240 	    }
1241 	}
1242 	else
1243 	{
1244 	    if (msg_col > 0)
1245 		msg_putchar('\n');
1246 	}
1247     }
1248 }
1249 
1250     void
1251 list_version(void)
1252 {
1253     int		i;
1254     int		first;
1255     char	*s = "";
1256 
1257     /*
1258      * When adding features here, don't forget to update the list of
1259      * internal variables in eval.c!
1260      */
1261     init_longVersion();
1262     MSG(longVersion);
1263 #ifdef WIN3264
1264 # ifdef FEAT_GUI_W32
1265 #  ifdef _WIN64
1266     MSG_PUTS(_("\nMS-Windows 64-bit GUI version"));
1267 #  else
1268     MSG_PUTS(_("\nMS-Windows 32-bit GUI version"));
1269 #  endif
1270 # ifdef FEAT_OLE
1271     MSG_PUTS(_(" with OLE support"));
1272 # endif
1273 # else
1274 #  ifdef _WIN64
1275     MSG_PUTS(_("\nMS-Windows 64-bit console version"));
1276 #  else
1277     MSG_PUTS(_("\nMS-Windows 32-bit console version"));
1278 #  endif
1279 # endif
1280 #endif
1281 #if defined(MACOS_X)
1282 # if defined(MACOS_X_DARWIN)
1283     MSG_PUTS(_("\nmacOS version"));
1284 # else
1285     MSG_PUTS(_("\nmacOS version w/o darwin feat."));
1286 # endif
1287 #endif
1288 
1289 #ifdef VMS
1290     MSG_PUTS(_("\nOpenVMS version"));
1291 # ifdef HAVE_PATHDEF
1292     if (*compiled_arch != NUL)
1293     {
1294 	MSG_PUTS(" - ");
1295 	MSG_PUTS(compiled_arch);
1296     }
1297 # endif
1298 
1299 #endif
1300 
1301     /* Print the list of patch numbers if there is at least one. */
1302     /* Print a range when patches are consecutive: "1-10, 12, 15-40, 42-45" */
1303     if (included_patches[0] != 0)
1304     {
1305 	MSG_PUTS(_("\nIncluded patches: "));
1306 	first = -1;
1307 	/* find last one */
1308 	for (i = 0; included_patches[i] != 0; ++i)
1309 	    ;
1310 	while (--i >= 0)
1311 	{
1312 	    if (first < 0)
1313 		first = included_patches[i];
1314 	    if (i == 0 || included_patches[i - 1] != included_patches[i] + 1)
1315 	    {
1316 		MSG_PUTS(s);
1317 		s = ", ";
1318 		msg_outnum((long)first);
1319 		if (first != included_patches[i])
1320 		{
1321 		    MSG_PUTS("-");
1322 		    msg_outnum((long)included_patches[i]);
1323 		}
1324 		first = -1;
1325 	    }
1326 	}
1327     }
1328 
1329     /* Print the list of extra patch descriptions if there is at least one. */
1330     if (extra_patches[0] != NULL)
1331     {
1332 	MSG_PUTS(_("\nExtra patches: "));
1333 	s = "";
1334 	for (i = 0; extra_patches[i] != NULL; ++i)
1335 	{
1336 	    MSG_PUTS(s);
1337 	    s = ", ";
1338 	    MSG_PUTS(extra_patches[i]);
1339 	}
1340     }
1341 
1342 #ifdef MODIFIED_BY
1343     MSG_PUTS("\n");
1344     MSG_PUTS(_("Modified by "));
1345     MSG_PUTS(MODIFIED_BY);
1346 #endif
1347 
1348 #ifdef HAVE_PATHDEF
1349     if (*compiled_user != NUL || *compiled_sys != NUL)
1350     {
1351 	MSG_PUTS(_("\nCompiled "));
1352 	if (*compiled_user != NUL)
1353 	{
1354 	    MSG_PUTS(_("by "));
1355 	    MSG_PUTS(compiled_user);
1356 	}
1357 	if (*compiled_sys != NUL)
1358 	{
1359 	    MSG_PUTS("@");
1360 	    MSG_PUTS(compiled_sys);
1361 	}
1362     }
1363 #endif
1364 
1365 #ifdef FEAT_HUGE
1366     MSG_PUTS(_("\nHuge version "));
1367 #else
1368 # ifdef FEAT_BIG
1369     MSG_PUTS(_("\nBig version "));
1370 # else
1371 #  ifdef FEAT_NORMAL
1372     MSG_PUTS(_("\nNormal version "));
1373 #  else
1374 #   ifdef FEAT_SMALL
1375     MSG_PUTS(_("\nSmall version "));
1376 #   else
1377     MSG_PUTS(_("\nTiny version "));
1378 #   endif
1379 #  endif
1380 # endif
1381 #endif
1382 #ifndef FEAT_GUI
1383     MSG_PUTS(_("without GUI."));
1384 #else
1385 # ifdef FEAT_GUI_GTK
1386 #  ifdef USE_GTK3
1387     MSG_PUTS(_("with GTK3 GUI."));
1388 #  else
1389 #   ifdef FEAT_GUI_GNOME
1390      MSG_PUTS(_("with GTK2-GNOME GUI."));
1391 #   else
1392      MSG_PUTS(_("with GTK2 GUI."));
1393 #   endif
1394 # endif
1395 # else
1396 #  ifdef FEAT_GUI_MOTIF
1397     MSG_PUTS(_("with X11-Motif GUI."));
1398 #  else
1399 #   ifdef FEAT_GUI_ATHENA
1400 #    ifdef FEAT_GUI_NEXTAW
1401     MSG_PUTS(_("with X11-neXtaw GUI."));
1402 #    else
1403     MSG_PUTS(_("with X11-Athena GUI."));
1404 #    endif
1405 #   else
1406 #     ifdef FEAT_GUI_PHOTON
1407     MSG_PUTS(_("with Photon GUI."));
1408 #     else
1409 #      if defined(MSWIN)
1410     MSG_PUTS(_("with GUI."));
1411 #      else
1412 #	if defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON
1413     MSG_PUTS(_("with Carbon GUI."));
1414 #	else
1415 #	 if defined(TARGET_API_MAC_OSX) && TARGET_API_MAC_OSX
1416     MSG_PUTS(_("with Cocoa GUI."));
1417 #	 else
1418 #	 endif
1419 #	endif
1420 #      endif
1421 #    endif
1422 #   endif
1423 #  endif
1424 # endif
1425 #endif
1426     version_msg(_("  Features included (+) or not (-):\n"));
1427 
1428     list_features();
1429 
1430 #ifdef SYS_VIMRC_FILE
1431     version_msg(_("   system vimrc file: \""));
1432     version_msg(SYS_VIMRC_FILE);
1433     version_msg("\"\n");
1434 #endif
1435 #ifdef USR_VIMRC_FILE
1436     version_msg(_("     user vimrc file: \""));
1437     version_msg(USR_VIMRC_FILE);
1438     version_msg("\"\n");
1439 #endif
1440 #ifdef USR_VIMRC_FILE2
1441     version_msg(_(" 2nd user vimrc file: \""));
1442     version_msg(USR_VIMRC_FILE2);
1443     version_msg("\"\n");
1444 #endif
1445 #ifdef USR_VIMRC_FILE3
1446     version_msg(_(" 3rd user vimrc file: \""));
1447     version_msg(USR_VIMRC_FILE3);
1448     version_msg("\"\n");
1449 #endif
1450 #ifdef USR_EXRC_FILE
1451     version_msg(_("      user exrc file: \""));
1452     version_msg(USR_EXRC_FILE);
1453     version_msg("\"\n");
1454 #endif
1455 #ifdef USR_EXRC_FILE2
1456     version_msg(_("  2nd user exrc file: \""));
1457     version_msg(USR_EXRC_FILE2);
1458     version_msg("\"\n");
1459 #endif
1460 #ifdef FEAT_GUI
1461 # ifdef SYS_GVIMRC_FILE
1462     version_msg(_("  system gvimrc file: \""));
1463     version_msg(SYS_GVIMRC_FILE);
1464     version_msg("\"\n");
1465 # endif
1466     version_msg(_("    user gvimrc file: \""));
1467     version_msg(USR_GVIMRC_FILE);
1468     version_msg("\"\n");
1469 # ifdef USR_GVIMRC_FILE2
1470     version_msg(_("2nd user gvimrc file: \""));
1471     version_msg(USR_GVIMRC_FILE2);
1472     version_msg("\"\n");
1473 # endif
1474 # ifdef USR_GVIMRC_FILE3
1475     version_msg(_("3rd user gvimrc file: \""));
1476     version_msg(USR_GVIMRC_FILE3);
1477     version_msg("\"\n");
1478 # endif
1479 #endif
1480     version_msg(_("       defaults file: \""));
1481     version_msg(VIM_DEFAULTS_FILE);
1482     version_msg("\"\n");
1483 #ifdef FEAT_GUI
1484 # ifdef SYS_MENU_FILE
1485     version_msg(_("    system menu file: \""));
1486     version_msg(SYS_MENU_FILE);
1487     version_msg("\"\n");
1488 # endif
1489 #endif
1490 #ifdef HAVE_PATHDEF
1491     if (*default_vim_dir != NUL)
1492     {
1493 	version_msg(_("  fall-back for $VIM: \""));
1494 	version_msg((char *)default_vim_dir);
1495 	version_msg("\"\n");
1496     }
1497     if (*default_vimruntime_dir != NUL)
1498     {
1499 	version_msg(_(" f-b for $VIMRUNTIME: \""));
1500 	version_msg((char *)default_vimruntime_dir);
1501 	version_msg("\"\n");
1502     }
1503     version_msg(_("Compilation: "));
1504     version_msg((char *)all_cflags);
1505     version_msg("\n");
1506 #ifdef VMS
1507     if (*compiler_version != NUL)
1508     {
1509 	version_msg(_("Compiler: "));
1510 	version_msg((char *)compiler_version);
1511 	version_msg("\n");
1512     }
1513 #endif
1514     version_msg(_("Linking: "));
1515     version_msg((char *)all_lflags);
1516 #endif
1517 #ifdef DEBUG
1518     version_msg("\n");
1519     version_msg(_("  DEBUG BUILD"));
1520 #endif
1521 }
1522 
1523 static void do_intro_line(int row, char_u *mesg, int add_version, int attr);
1524 
1525 /*
1526  * Show the intro message when not editing a file.
1527  */
1528     void
1529 maybe_intro_message(void)
1530 {
1531     if (BUFEMPTY()
1532 	    && curbuf->b_fname == NULL
1533 	    && firstwin->w_next == NULL
1534 	    && vim_strchr(p_shm, SHM_INTRO) == NULL)
1535 	intro_message(FALSE);
1536 }
1537 
1538 /*
1539  * Give an introductory message about Vim.
1540  * Only used when starting Vim on an empty file, without a file name.
1541  * Or with the ":intro" command (for Sven :-).
1542  */
1543     void
1544 intro_message(
1545     int		colon)		/* TRUE for ":intro" */
1546 {
1547     int		i;
1548     int		row;
1549     int		blanklines;
1550     int		sponsor;
1551     char	*p;
1552     static char	*(lines[]) =
1553     {
1554 	N_("VIM - Vi IMproved"),
1555 	"",
1556 	N_("version "),
1557 	N_("by Bram Moolenaar et al."),
1558 #ifdef MODIFIED_BY
1559 	" ",
1560 #endif
1561 	N_("Vim is open source and freely distributable"),
1562 	"",
1563 	N_("Help poor children in Uganda!"),
1564 	N_("type  :help iccf<Enter>       for information "),
1565 	"",
1566 	N_("type  :q<Enter>               to exit         "),
1567 	N_("type  :help<Enter>  or  <F1>  for on-line help"),
1568 	N_("type  :help version8<Enter>   for version info"),
1569 	NULL,
1570 	"",
1571 	N_("Running in Vi compatible mode"),
1572 	N_("type  :set nocp<Enter>        for Vim defaults"),
1573 	N_("type  :help cp-default<Enter> for info on this"),
1574     };
1575 #ifdef FEAT_GUI
1576     static char	*(gui_lines[]) =
1577     {
1578 	NULL,
1579 	NULL,
1580 	NULL,
1581 	NULL,
1582 #ifdef MODIFIED_BY
1583 	NULL,
1584 #endif
1585 	NULL,
1586 	NULL,
1587 	NULL,
1588 	N_("menu  Help->Orphans           for information    "),
1589 	NULL,
1590 	N_("Running modeless, typed text is inserted"),
1591 	N_("menu  Edit->Global Settings->Toggle Insert Mode  "),
1592 	N_("                              for two modes      "),
1593 	NULL,
1594 	NULL,
1595 	NULL,
1596 	N_("menu  Edit->Global Settings->Toggle Vi Compatible"),
1597 	N_("                              for Vim defaults   "),
1598     };
1599 #endif
1600 
1601     /* blanklines = screen height - # message lines */
1602     blanklines = (int)Rows - ((sizeof(lines) / sizeof(char *)) - 1);
1603     if (!p_cp)
1604 	blanklines += 4;  /* add 4 for not showing "Vi compatible" message */
1605 
1606     /* Don't overwrite a statusline.  Depends on 'cmdheight'. */
1607     if (p_ls > 1)
1608 	blanklines -= Rows - topframe->fr_height;
1609     if (blanklines < 0)
1610 	blanklines = 0;
1611 
1612     /* Show the sponsor and register message one out of four times, the Uganda
1613      * message two out of four times. */
1614     sponsor = (int)time(NULL);
1615     sponsor = ((sponsor & 2) == 0) - ((sponsor & 4) == 0);
1616 
1617     /* start displaying the message lines after half of the blank lines */
1618     row = blanklines / 2;
1619     if ((row >= 2 && Columns >= 50) || colon)
1620     {
1621 	for (i = 0; i < (int)(sizeof(lines) / sizeof(char *)); ++i)
1622 	{
1623 	    p = lines[i];
1624 #ifdef FEAT_GUI
1625 	    if (p_im && gui.in_use && gui_lines[i] != NULL)
1626 		p = gui_lines[i];
1627 #endif
1628 	    if (p == NULL)
1629 	    {
1630 		if (!p_cp)
1631 		    break;
1632 		continue;
1633 	    }
1634 	    if (sponsor != 0)
1635 	    {
1636 		if (strstr(p, "children") != NULL)
1637 		    p = sponsor < 0
1638 			? N_("Sponsor Vim development!")
1639 			: N_("Become a registered Vim user!");
1640 		else if (strstr(p, "iccf") != NULL)
1641 		    p = sponsor < 0
1642 			? N_("type  :help sponsor<Enter>    for information ")
1643 			: N_("type  :help register<Enter>   for information ");
1644 		else if (strstr(p, "Orphans") != NULL)
1645 		    p = N_("menu  Help->Sponsor/Register  for information    ");
1646 	    }
1647 	    if (*p != NUL)
1648 		do_intro_line(row, (char_u *)_(p), i == 2, 0);
1649 	    ++row;
1650 	}
1651     }
1652 
1653     /* Make the wait-return message appear just below the text. */
1654     if (colon)
1655 	msg_row = row;
1656 }
1657 
1658     static void
1659 do_intro_line(
1660     int		row,
1661     char_u	*mesg,
1662     int		add_version,
1663     int		attr)
1664 {
1665     char_u	vers[20];
1666     int		col;
1667     char_u	*p;
1668     int		l;
1669     int		clen;
1670 #ifdef MODIFIED_BY
1671 # define MODBY_LEN 150
1672     char_u	modby[MODBY_LEN];
1673 
1674     if (*mesg == ' ')
1675     {
1676 	vim_strncpy(modby, (char_u *)_("Modified by "), MODBY_LEN - 1);
1677 	l = (int)STRLEN(modby);
1678 	vim_strncpy(modby + l, (char_u *)MODIFIED_BY, MODBY_LEN - l - 1);
1679 	mesg = modby;
1680     }
1681 #endif
1682 
1683     /* Center the message horizontally. */
1684     col = vim_strsize(mesg);
1685     if (add_version)
1686     {
1687 	STRCPY(vers, mediumVersion);
1688 	if (highest_patch())
1689 	{
1690 	    /* Check for 9.9x or 9.9xx, alpha/beta version */
1691 	    if (isalpha((int)vers[3]))
1692 	    {
1693 		int len = (isalpha((int)vers[4])) ? 5 : 4;
1694 		sprintf((char *)vers + len, ".%d%s", highest_patch(),
1695 							 mediumVersion + len);
1696 	    }
1697 	    else
1698 		sprintf((char *)vers + 3, ".%d", highest_patch());
1699 	}
1700 	col += (int)STRLEN(vers);
1701     }
1702     col = (Columns - col) / 2;
1703     if (col < 0)
1704 	col = 0;
1705 
1706     /* Split up in parts to highlight <> items differently. */
1707     for (p = mesg; *p != NUL; p += l)
1708     {
1709 	clen = 0;
1710 	for (l = 0; p[l] != NUL
1711 			 && (l == 0 || (p[l] != '<' && p[l - 1] != '>')); ++l)
1712 	{
1713 #ifdef FEAT_MBYTE
1714 	    if (has_mbyte)
1715 	    {
1716 		clen += ptr2cells(p + l);
1717 		l += (*mb_ptr2len)(p + l) - 1;
1718 	    }
1719 	    else
1720 #endif
1721 		clen += byte2cells(p[l]);
1722 	}
1723 	screen_puts_len(p, l, row, col, *p == '<' ? HL_ATTR(HLF_8) : attr);
1724 	col += clen;
1725     }
1726 
1727     /* Add the version number to the version line. */
1728     if (add_version)
1729 	screen_puts(vers, row, col, 0);
1730 }
1731 
1732 /*
1733  * ":intro": clear screen, display intro screen and wait for return.
1734  */
1735     void
1736 ex_intro(exarg_T *eap UNUSED)
1737 {
1738     screenclear();
1739     intro_message(TRUE);
1740     wait_return(TRUE);
1741 }
1742