aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/buffer_defs.h
blob: 0d8d8d581f60616792734e97e10f22ca78ced1d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
#pragma once

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

typedef struct file_buffer buf_T;

/// Reference to a buffer that stores the value of buf_free_count.
/// bufref_valid() only needs to check "buf" when the count differs.
typedef struct {
  buf_T *br_buf;
  int br_fnum;
  int br_buf_free_count;
} bufref_T;

#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/arglist_defs.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/extmark_defs.h"
#include "nvim/garray_defs.h"
#include "nvim/grid_defs.h"
#include "nvim/hashtab_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/map_defs.h"
#include "nvim/mapping_defs.h"
#include "nvim/mark_defs.h"
#include "nvim/marktree.h"
#include "nvim/option_vars.h"
#include "nvim/pos_defs.h"
#include "nvim/statusline_defs.h"
#include "nvim/undo_defs.h"

#define GETFILE_SUCCESS(x)    ((x) <= 0)
#define MODIFIABLE(buf) (buf->b_p_ma)

// 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)

// 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
#define BF_DUMMY        0x80    // dummy buffer, only used internally
#define BF_SYN_SET      0x200   // 'syntax' option was set

// Mask to check for flags that prevent normal writing
#define BF_WRITE_MASK   (BF_NOTEDITED + BF_NEW + BF_READERR)

typedef struct window_S win_T;
typedef struct wininfo_S wininfo_T;
typedef struct frame_S frame_T;
typedef uint64_t disptick_T;  // display tick type

#include "nvim/memline_defs.h"
#include "nvim/os/fs_defs.h"
#include "nvim/regexp_defs.h"
#include "nvim/sign_defs.h"
#include "nvim/syntax_defs.h"
#include "nvim/terminal.h"

typedef enum {
  kColorcolBehind = 1,
  kColorcolForeground = 2,
} colorcol_flags_T;

// Structure to define data associated with a colorcolumn.
typedef struct {
  int col;        // The column number to highlight.
  int ch;         // The character to draw in the column.

  char* syn_name; // The highlight group name. Must be free'd.
  int syn_attr;   // The attribute. Will be set before a redraw.

  int flags;      // Additional flags
} colorcol_T;

// The taggy struct is used to store the information about a :tag command.
typedef struct taggy {
  char *tagname;                // tag name
  fmark_T fmark;                // cursor position BEFORE ":tag"
  int cur_match;                // match number
  int cur_fnum;                 // buffer number used for cur_match
  char *user_data;              // used with tagfunc
} 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 {
  int wo_arab;
#define w_p_arab w_onebuf_opt.wo_arab  // 'arabic'
  int wo_bri;
#define w_p_bri w_onebuf_opt.wo_bri    // 'breakindent'
  char *wo_briopt;
#define w_p_briopt w_onebuf_opt.wo_briopt  // 'breakindentopt'
  int wo_diff;
#define w_p_diff w_onebuf_opt.wo_diff  // 'diff'
  char *wo_fdc;
#define w_p_fdc w_onebuf_opt.wo_fdc    // 'foldcolumn'
  char *wo_fdc_save;
#define w_p_fdc_save w_onebuf_opt.wo_fdc_save  // 'fdc' saved for diff mode
  int wo_fen;
#define w_p_fen w_onebuf_opt.wo_fen    // 'foldenable'
  int wo_fen_save;
  // 'foldenable' saved for diff mode
#define w_p_fen_save w_onebuf_opt.wo_fen_save
  char *wo_fdi;
#define w_p_fdi w_onebuf_opt.wo_fdi    // 'foldignore'
  OptInt wo_fdl;
#define w_p_fdl w_onebuf_opt.wo_fdl    // 'foldlevel'
  OptInt wo_fdl_save;
  // 'foldlevel' state saved for diff mode
#define w_p_fdl_save w_onebuf_opt.wo_fdl_save
  char *wo_fdm;
#define w_p_fdm w_onebuf_opt.wo_fdm    // 'foldmethod'
  char *wo_fdm_save;
#define w_p_fdm_save w_onebuf_opt.wo_fdm_save  // 'fdm' saved for diff mode
  OptInt wo_fml;
#define w_p_fml w_onebuf_opt.wo_fml    // 'foldminlines'
  OptInt wo_fdn;
#define w_p_fdn w_onebuf_opt.wo_fdn    // 'foldnestmax'
  char *wo_fde;
#define w_p_fde w_onebuf_opt.wo_fde    // 'foldexpr'
  char *wo_fdt;
#define w_p_fdt w_onebuf_opt.wo_fdt   // 'foldtext'
  char *wo_fmr;
#define w_p_fmr w_onebuf_opt.wo_fmr    // 'foldmarker'
  int wo_lbr;
#define w_p_lbr w_onebuf_opt.wo_lbr    // 'linebreak'
  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'
  int wo_rnu;
#define w_p_rnu w_onebuf_opt.wo_rnu     // 'relativenumber'
  char *wo_ve;
#define w_p_ve w_onebuf_opt.wo_ve       // 'virtualedit'
  unsigned wo_ve_flags;
#define w_ve_flags w_onebuf_opt.wo_ve_flags  // flags for 'virtualedit'
  OptInt wo_nuw;
#define w_p_nuw w_onebuf_opt.wo_nuw    // 'numberwidth'
  int wo_wfh;
#define w_p_wfh w_onebuf_opt.wo_wfh    // 'winfixheight'
  int wo_wfw;
#define w_p_wfw w_onebuf_opt.wo_wfw    // 'winfixwidth'
  int wo_pvw;
#define w_p_pvw w_onebuf_opt.wo_pvw    // 'previewwindow'
  int wo_rl;
#define w_p_rl w_onebuf_opt.wo_rl      // 'rightleft'
  char *wo_rlc;
#define w_p_rlc w_onebuf_opt.wo_rlc    // 'rightleftcmd'
  OptInt wo_scr;
#define w_p_scr w_onebuf_opt.wo_scr     // 'scroll'
  int wo_sms;
#define w_p_sms w_onebuf_opt.wo_sms     // 'smoothscroll'
  int wo_spell;
#define w_p_spell w_onebuf_opt.wo_spell  // 'spell'
  int wo_cuc;
#define w_p_cuc w_onebuf_opt.wo_cuc    // 'cursorcolumn'
  int wo_cul;
#define w_p_cul w_onebuf_opt.wo_cul    // 'cursorline'
  char *wo_culopt;
#define w_p_culopt w_onebuf_opt.wo_culopt  // 'cursorlineopt'
  char *wo_cc;
#define w_p_cc w_onebuf_opt.wo_cc      // 'colorcolumn'
  char *wo_sbr;
#define w_p_sbr w_onebuf_opt.wo_sbr    // 'showbreak'
  char *wo_stc;
#define w_p_stc w_onebuf_opt.wo_stc     // 'statuscolumn'
  char *wo_stl;
#define w_p_stl w_onebuf_opt.wo_stl     // 'statusline'
  char *wo_wbr;
#define w_p_wbr w_onebuf_opt.wo_wbr   // 'winbar'
  int wo_scb;
#define w_p_scb w_onebuf_opt.wo_scb    // 'scrollbind'
  int wo_diff_saved;           // options were saved for starting diff mode
#define w_p_diff_saved w_onebuf_opt.wo_diff_saved
  int wo_scb_save;              // 'scrollbind' saved for diff mode
#define w_p_scb_save w_onebuf_opt.wo_scb_save
  int wo_wrap;
#define w_p_wrap w_onebuf_opt.wo_wrap   // 'wrap'
  int wo_wrap_save;             // 'wrap' state saved for diff mode
#define w_p_wrap_save w_onebuf_opt.wo_wrap_save
  char *wo_cocu;                 // 'concealcursor'
#define w_p_cocu w_onebuf_opt.wo_cocu
  OptInt wo_cole;                         // 'conceallevel'
#define w_p_cole w_onebuf_opt.wo_cole
  int wo_crb;
#define w_p_crb w_onebuf_opt.wo_crb    // 'cursorbind'
  int wo_crb_save;              // 'cursorbind' state saved for diff mode
#define w_p_crb_save w_onebuf_opt.wo_crb_save
  char *wo_scl;
#define w_p_scl w_onebuf_opt.wo_scl    // 'signcolumn'
  OptInt wo_siso;
#define w_p_siso w_onebuf_opt.wo_siso  // 'sidescrolloff' local value
  OptInt wo_so;
#define w_p_so w_onebuf_opt.wo_so      // 'scrolloff' local value
  char *wo_winhl;
#define w_p_winhl w_onebuf_opt.wo_winhl    // 'winhighlight'
  char *wo_lcs;
#define w_p_lcs w_onebuf_opt.wo_lcs    // 'listchars'
  char *wo_fcs;
#define w_p_fcs w_onebuf_opt.wo_fcs    // 'fillchars'
  OptInt wo_winbl;
#define w_p_winbl w_onebuf_opt.wo_winbl  // 'winblend'

  LastSet wo_script_ctx[WV_COUNT];        // SCTXs for window-local options
#define w_p_script_ctx w_onebuf_opt.wo_script_ctx
} 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_S {
  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_mark
  fmark_T wi_mark;                // last cursor mark in the file
  bool wi_optset;               // true when wi_opt has useful values
  winopt_T wi_opt;              // local window options
  bool wi_fold_manual;          // copy of w_fold_manual
  garray_T wi_folds;            // clone of w_folds
  int wi_changelistidx;         // copy of w_changelistidx
};

#define ALIST(win)      (win)->w_alist
#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)

// values for b_syn_spell: what to do with toplevel text
#define SYNSPL_DEFAULT  0       // spell check if @Spell not defined
#define SYNSPL_TOP      1       // spell check toplevel text
#define SYNSPL_NOTOP    2       // don't spell check toplevel text

// values for b_syn_foldlevel: how to compute foldlevel on a line
#define SYNFLD_START    0       // use level of item at start of line
#define SYNFLD_MINIMUM  1       // use lowest local minimum level on line

typedef struct qf_info_S qf_info_T;

// Used for :syntime: timing of executing a syntax pattern.
typedef struct {
  proftime_T total;             // total time used
  proftime_T slowest;           // time of slowest call
  int count;                    // nr of times used
  int match;                    // nr of times matched
} syn_time_T;

// These are items normally related to a buffer.  But when using ":ownsyntax"
// a window may have its own instance.
typedef struct {
  hashtab_T b_keywtab;                  // syntax keywords hash table
  hashtab_T b_keywtab_ic;               // idem, ignore case
  bool b_syn_error;                     // true when error occurred in HL
  bool b_syn_slow;                      // true when 'redrawtime' reached
  int b_syn_ic;                         // ignore case for :syn cmds
  int b_syn_foldlevel;                  // how to compute foldlevel on a line
  int b_syn_spell;                      // SYNSPL_ values
  garray_T b_syn_patterns;              // table for syntax patterns
  garray_T b_syn_clusters;              // table for syntax clusters
  int b_spell_cluster_id;               // @Spell cluster ID or 0
  int b_nospell_cluster_id;             // @NoSpell cluster ID or 0
  int b_syn_containedin;                // true when there is an item with a
                                        // "containedin" argument
  int b_syn_sync_flags;                 // flags about how to sync
  int16_t b_syn_sync_id;                // group to sync on
  linenr_T b_syn_sync_minlines;         // minimal sync lines offset
  linenr_T b_syn_sync_maxlines;         // maximal sync lines offset
  linenr_T b_syn_sync_linebreaks;       // offset for multi-line pattern
  char *b_syn_linecont_pat;             // line continuation pattern
  regprog_T *b_syn_linecont_prog;       // line continuation program
  syn_time_T b_syn_linecont_time;
  int b_syn_linecont_ic;                // ignore-case flag for above
  int b_syn_topgrp;                     // for ":syntax include"
  int b_syn_conceal;                    // auto-conceal for :syn cmds
  int b_syn_folditems;                  // number of patterns with the HL_FOLD
                                        // flag set
  // 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;
  disptick_T b_sst_lasttick;    // last display tick

  // for spell checking
  garray_T b_langp;           // list of pointers to slang_T, see spell.c
  bool b_spell_ismw[256];     // flags: is midword char
  char *b_spell_ismw_mb;      // multi-byte midword chars
  char *b_p_spc;              // 'spellcapcheck'
  regprog_T *b_cap_prog;      // program for 'spellcapcheck'
  char *b_p_spf;              // 'spellfile'
  char *b_p_spl;              // 'spelllang'
  char *b_p_spo;              // 'spelloptions'
#define SPO_CAMEL  0x1
#define SPO_NPBUFFER 0x2
  unsigned b_p_spo_flags;      // 'spelloptions' flags
  int b_cjk;                  // all CJK letters as OK
  uint8_t b_syn_chartab[32];  // syntax iskeyword option
  char *b_syn_isk;            // iskeyword option
} synblock_T;

/// Type used for changedtick_di member in buf_T
///
/// Primary exists so that literals of relevant type can be made.
typedef TV_DICTITEM_STRUCT(sizeof("changedtick")) ChangedtickDictItem;

typedef struct {
  LuaRef on_lines;
  LuaRef on_bytes;
  LuaRef on_changedtick;
  LuaRef on_detach;
  LuaRef on_reload;
  bool utf_sizes;
  bool preview;
} BufUpdateCallbacks;
#define BUF_UPDATE_CALLBACKS_INIT { LUA_NOREF, LUA_NOREF, LUA_NOREF, \
                                    LUA_NOREF, LUA_NOREF, false, false }

EXTERN int curbuf_splice_pending INIT( = 0);

#define BUF_HAS_QF_ENTRY 1
#define BUF_HAS_LL_ENTRY 2

// Maximum number of maphash blocks we will have
#define MAX_MAPHASH 256

// 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.

struct file_buffer {
  handle_T handle;              // unique id for the buffer (buffer number)
#define b_fnum handle

  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
  int b_locked;                 // Buffer is being closed or referenced, don't
                                // let autocommands wipe it out.
  int b_locked_split;           // Buffer is being closed, don't allow opening
                                // a new window with it.
  int b_ro_locked;              // Non-zero when the buffer can't be changed.
                                // Used for FileChangedRO

  // 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 *b_ffname;          // full path file name, allocated
  char *b_sfname;          // short file name, allocated, may be equal to
                           // b_ffname
  char *b_fname;           // current file name, points to b_ffname or
                           // b_sfname

  bool file_id_valid;
  FileID file_id;

  int b_changed;                // 'modified': Set to true if something in the
                                // file has been changed and not written out.
  bool b_changed_invalid;       // Set if BufModified autocmd has not been
                                // triggered since the last time b_changed was
                                // modified.

  /// Change-identifier incremented for each change, including undo.
  ///
  /// This is a dictionary item used to store b:changedtick.
  ChangedtickDictItem changedtick_di;

  varnumber_T b_last_changedtick;       // b:changedtick when TextChanged was
                                        // last triggered.
  varnumber_T b_last_changedtick_i;     // b:changedtick for TextChangedI
  varnumber_T b_last_changedtick_pum;   // b:changedtick for TextChangedP

  bool 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.
  bool 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
  linenr_T 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
  disptick_T b_mod_tick_syn;    // last display tick syntax was updated
  disptick_T b_mod_tick_decor;  // last display tick decoration providers
                                // where invoked

  int64_t b_mtime;              // last change time of original file
  int64_t b_mtime_ns;           // nanoseconds of last change time
  int64_t b_mtime_read;         // last change time when reading
  int64_t b_mtime_read_ns;      // nanoseconds of last read time
  uint64_t b_orig_size;         // size of original file in bytes
  int b_orig_mode;              // mode of original file
  time_t b_last_used;           // time when the buffer was last used; used
                                // for viminfo

  fmark_T b_namedm[NMARKS];     // current named marks (mark.c)

  // These variables are set when VIsual_active becomes false
  visualinfo_T b_visual;
  int b_visual_mode_eval;            // b_visual.vi_mode for visualmode()

  fmark_T b_last_cursor;        // cursor position when last unloading this
                                // buffer
  fmark_T b_last_insert;        // where Insert mode was left
  fmark_T b_last_change;        // position of last change: '. mark

  // the changelist contains old change positions
  fmark_T b_changelist[JUMPLISTSIZE];
  int b_changelistlen;                  // number of active entries
  bool b_new_change;                    // set by u_savecommon()

  // Character table, only used in charset.c for 'iskeyword'
  // bitset with 4*64=256 bits: 1 bit per character 0-255.
  uint64_t b_chartab[4];

  // Table used for mappings local to a buffer.
  mapblock_T *(b_maphash[MAX_MAPHASH]);

  // First abbreviation local to a buffer.
  mapblock_T *b_first_abbr;
  // User commands local to the buffer.
  garray_T b_ucmds;
  // start and end of an operator, also used for '[ and ']
  pos_T b_op_start;
  pos_T b_op_start_orig;  // used for Insstart_orig
  pos_T b_op_end;

  bool b_marks_read;            // Have we read ShaDa marks yet?

  // 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; may not be valid
                               // if b_u_curhead is not NULL
  u_header_T *b_u_curhead;     // pointer to current header
  int b_u_numhead;             // current number of headers
  bool b_u_synced;             // entry lists are synced
  int b_u_seq_last;            // last used undo sequence number
  int b_u_save_nr_last;        // counter for last file write
  int b_u_seq_cur;             // uh_seq of header below which we are now
  time_t b_u_time_cur;         // uh_time of header below which we are now
  int b_u_save_nr_cur;         // file write nr after which we are now

  // variables for "U" command in undo.c
  char *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

  bool b_scanned;               // ^N/^P have scanned this buffer

  // flags for use of ":lmap" and IM control
  OptInt b_p_iminsert;          // input mode for insert
  OptInt 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
#define B_IMODE_LAST 1

  int16_t 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

  // Options local to a buffer.
  // They are here because their value depends on the type of file
  // or contents of the file being edited.
  bool b_p_initialized;                 // set when options initialized

  LastSet b_p_script_ctx[BV_COUNT];     // SCTXs for buffer-local options

  int b_p_ai;                   ///< 'autoindent'
  int b_p_ai_nopaste;           ///< b_p_ai saved for paste mode
  char *b_p_bkc;                ///< 'backupco
  unsigned b_bkc_flags;     ///< flags for 'backupco
  int b_p_ci;                   ///< 'copyindent'
  int b_p_bin;                  ///< 'binary'
  int b_p_bomb;                 ///< 'bomb'
  char *b_p_bh;                 ///< 'bufhidden'
  char *b_p_bt;                 ///< 'buftype'
  int b_has_qf_entry;           ///< quickfix exists for buffer
  int b_p_bl;                   ///< 'buflisted'
  OptInt b_p_channel;           ///< 'channel'
  int b_p_cin;                  ///< 'cindent'
  char *b_p_cino;               ///< 'cinoptions'
  char *b_p_cink;               ///< 'cinkeys'
  char *b_p_cinw;               ///< 'cinwords'
  char *b_p_cinsd;              ///< 'cinscopedecls'
  char *b_p_com;                ///< 'comments'
  char *b_p_cms;                ///< 'commentstring'
  char *b_p_cpt;                ///< 'complete'
#ifdef BACKSLASH_IN_FILENAME
  char *b_p_csl;                ///< 'completeslash'
#endif
  char *b_p_cfu;                ///< 'completefunc'
  Callback b_cfu_cb;            ///< 'completefunc' callback
  char *b_p_ofu;                ///< 'omnifunc'
  Callback b_ofu_cb;            ///< 'omnifunc' callback
  char *b_p_tfu;                ///< 'tagfunc'
  Callback b_tfu_cb;            ///< 'tagfunc' callback
  int b_p_eof;                  ///< 'endoffile'
  int b_p_eol;                  ///< 'endofline'
  int b_p_fixeol;               ///< 'fixendofline'
  int b_p_et;                   ///< 'expandtab'
  int b_p_et_nobin;             ///< b_p_et saved for binary mode
  int b_p_et_nopaste;           ///< b_p_et saved for paste mode
  char *b_p_fenc;               ///< 'fileencoding'
  char *b_p_ff;                 ///< 'fileformat'
  char *b_p_ft;                 ///< 'filetype'
  char *b_p_fo;                 ///< 'formatoptions'
  char *b_p_flp;                ///< 'formatlistpat'
  int b_p_inf;                  ///< 'infercase'
  char *b_p_isk;                ///< 'iskeyword'
  char *b_p_def;                ///< 'define' local value
  char *b_p_inc;                ///< 'include'
  char *b_p_inex;               ///< 'includeexpr'
  uint32_t b_p_inex_flags;      ///< flags for 'includeexpr'
  char *b_p_inde;               ///< 'indentexpr'
  uint32_t b_p_inde_flags;      ///< flags for 'indentexpr'
  char *b_p_indk;               ///< 'indentkeys'
  char *b_p_fp;                 ///< 'formatprg'
  char *b_p_fex;                ///< 'formatexpr'
  uint32_t b_p_fex_flags;       ///< flags for 'formatexpr'
  char *b_p_kp;                 ///< 'keywordprg'
  int b_p_lisp;                 ///< 'lisp'
  char *b_p_lop;                ///< 'lispoptions'
  char *b_p_menc;               ///< 'makeencoding'
  char *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 *b_p_nf;                 ///< 'nrformats'
  int b_p_pi;                   ///< 'preserveindent'
  char *b_p_qe;                 ///< 'quoteescape'
  int b_p_ro;                   ///< 'readonly'
  OptInt b_p_sw;                ///< 'shiftwidth'
  OptInt b_p_scbk;              ///< 'scrollback'
  int b_p_si;                   ///< 'smartindent'
  OptInt b_p_sts;               ///< 'softtabstop'
  OptInt b_p_sts_nopaste;       ///< b_p_sts saved for paste mode
  char *b_p_sua;                ///< 'suffixesadd'
  int b_p_swf;                  ///< 'swapfile'
  OptInt b_p_smc;               ///< 'synmaxcol'
  char *b_p_syn;                ///< 'syntax'
  OptInt b_p_ts;                ///< 'tabstop'
  OptInt b_p_tw;                ///< 'textwidth'
  OptInt b_p_tw_nobin;          ///< b_p_tw saved for binary mode
  OptInt b_p_tw_nopaste;        ///< b_p_tw saved for paste mode
  OptInt b_p_wm;                ///< 'wrapmargin'
  OptInt b_p_wm_nobin;          ///< b_p_wm saved for binary mode
  OptInt b_p_wm_nopaste;        ///< b_p_wm saved for paste mode
  char *b_p_vsts;               ///< 'varsofttabstop'
  colnr_T *b_p_vsts_array;      ///< 'varsofttabstop' in internal format
  char *b_p_vsts_nopaste;       ///< b_p_vsts saved for paste mode
  char *b_p_vts;                ///< 'vartabstop'
  colnr_T *b_p_vts_array;       ///< 'vartabstop' in internal format
  char *b_p_keymap;             ///< 'keymap'

  // local values for options which are normally global
  char *b_p_gp;                 ///< 'grepprg' local value
  char *b_p_mp;                 ///< 'makeprg' local value
  char *b_p_efm;                ///< 'errorformat' local value
  char *b_p_ep;                 ///< 'equalprg' local value
  char *b_p_path;               ///< 'path' local value
  int b_p_ar;                   ///< 'autoread' local value
  char *b_p_tags;               ///< 'tags' local value
  char *b_p_tc;                 ///< 'tagcase' local value
  unsigned b_tc_flags;          ///< flags for 'tagcase'
  char *b_p_dict;               ///< 'dictionary' local value
  char *b_p_tsr;                ///< 'thesaurus' local value
  char *b_p_tsrfu;              ///< 'thesaurusfunc' local value
  Callback b_tsrfu_cb;          ///< 'thesaurusfunc' callback
  OptInt b_p_ul;                ///< 'undolevels' local value
  int b_p_udf;                  ///< 'undofile'
  char *b_p_lw;                 ///< 'lispwords' local value

  // end of buffer options

  // values set from b_p_cino
  int b_ind_level;
  int b_ind_open_imag;
  int b_ind_no_brace;
  int b_ind_first_open;
  int b_ind_open_extra;
  int b_ind_close_extra;
  int b_ind_open_left_imag;
  int b_ind_jump_label;
  int b_ind_case;
  int b_ind_case_code;
  int b_ind_case_break;
  int b_ind_param;
  int b_ind_func_type;
  int b_ind_comment;
  int b_ind_in_comment;
  int b_ind_in_comment2;
  int b_ind_cpp_baseclass;
  int b_ind_continuation;
  int b_ind_unclosed;
  int b_ind_unclosed2;
  int b_ind_unclosed_noignore;
  int b_ind_unclosed_wrapped;
  int b_ind_unclosed_whiteok;
  int b_ind_matching_paren;
  int b_ind_paren_prev;
  int b_ind_maxparen;
  int b_ind_maxcomment;
  int b_ind_scopedecl;
  int b_ind_scopedecl_code;
  int b_ind_java;
  int b_ind_js;
  int b_ind_keep_case_label;
  int b_ind_hash_comment;
  int b_ind_cpp_namespace;
  int b_ind_if_for_while;
  int b_ind_cpp_extern_c;
  int b_ind_pragma;

  linenr_T b_no_eol_lnum;       // non-zero lnum when last line of next binary
                                // write should not have an end-of-line

  int b_start_eof;              // last line had eof (CTRL-Z) when it was read
  int b_start_eol;              // last line had eol when it was read
  int b_start_ffc;              // first char of 'ff' when edit started
  char *b_start_fenc;           // 'fileencoding' when edit started or NULL
  int b_bad_char;               // "++bad=" argument when edit started or 0
  int b_start_bomb;             // 'bomb' when it was read

  ScopeDictDictItem b_bufvar;  ///< Variable for "b:" Dictionary.
  dict_T *b_vars;  ///< b: scope dictionary.

  // 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.
  bool b_may_swap;
  bool b_did_warn;              // Set to true if user has been warned on first
                                // change of a read-only file

  // Two special kinds of buffers:
  // help buffer  - used for help files, won't use a swap file.
  // spell buffer - used for spell info, never displayed and doesn't have a
  //                file name.
  bool b_help;                  // true for help file buffer (when set b_p_bt
                                // is "help")
  bool b_spell;                 // True for a spell file buffer, most fields
                                // are not used!

  char *b_prompt_text;          // set by prompt_setprompt()
  Callback b_prompt_callback;   // set by prompt_setcallback()
  Callback b_prompt_interrupt;  // set by prompt_setinterrupt()
  int b_prompt_insert;          // value for restart_edit when entering
                                // a prompt buffer window.

  synblock_T b_s;               // Info related to syntax highlighting.  w_s
                                // normally points to this, but some windows
                                // may use a different synblock_T.

  struct {
    int size;                   // last calculated number of sign columns
    int max;                    // maximum value size is valid for.
    linenr_T sentinel;          // a line number which is holding up the signcolumn
    linenr_T invalid_top;       // first invalid line number that needs to be checked
    linenr_T invalid_bot;       // last invalid line number that needs to be checked
  } b_signcols;

  Terminal *terminal;           // Terminal instance associated with the buffer

  dict_T *additional_data;      // Additional data from shada file if any.

  int b_mapped_ctrl_c;          // modes where CTRL-C is mapped

  MarkTree b_marktree[1];
  Map(uint32_t, uint32_t) b_extmark_ns[1];         // extmark namespaces
  size_t b_virt_text_inline;                       // number of inline virtual texts
  size_t b_virt_line_blocks;    // number of virt_line blocks
  size_t b_signs;               // number of sign extmarks
  size_t b_signs_with_text;     // number of sign extmarks with text

  // array of channel_id:s which have asked to receive updates for this
  // buffer.
  kvec_t(uint64_t) update_channels;
  // array of lua callbacks for buffer updates.
  kvec_t(BufUpdateCallbacks) update_callbacks;

  // whether an update callback has requested codepoint size of deleted regions.
  bool update_need_codepoints;

  // Measurements of the deleted or replaced region since the last update
  // event. Some consumers of buffer changes need to know the byte size (like
  // tree-sitter) or the corresponding UTF-32/UTF-16 size (like LSP) of the
  // deleted text.
  size_t deleted_bytes;
  size_t deleted_bytes2;
  size_t deleted_codepoints;
  size_t deleted_codeunits;

  // The number for times the current line has been flushed in the memline.
  int flush_count;

  int b_diff_failed;    // internal diff failed for this buffer
};

// Stuff for diff mode.
#define DB_COUNT 8     // 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_S diff_T;
struct diffblock_S {
  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
  bool is_linematched;  // has the linematch algorithm ran on this diff hunk to divide it into
                        // smaller diff hunks?
};

#define SNAP_HELP_IDX   0
#define SNAP_AUCMD_IDX 1
#define SNAP_COUNT     2

/// Tab pages point to the top frame of each tab page.
/// Note: Most values are NOT valid for the current tab page!  Use "curwin",
/// "firstwin", etc. for that.  "tp_topframe" is always valid and can be
/// compared against "topframe" to find the current tab page.
typedef struct tabpage_S tabpage_T;
struct tabpage_S {
  handle_T handle;
  tabpage_T *tp_next;         ///< next tabpage or NULL
  frame_T *tp_topframe;       ///< topframe for the windows
  win_T *tp_curwin;           ///< current window in this Tab page
  win_T *tp_prevwin;          ///< previous window in this Tab page
  win_T *tp_firstwin;         ///< first window in this Tab page
  win_T *tp_lastwin;          ///< last window in this Tab page
  int64_t tp_old_Rows_avail;  ///< ROWS_AVAIL when Tab page was left
  int64_t tp_old_Columns;        ///< Columns when Tab page was left, -1 when
                                 ///< calling win_new_screen_cols() postponed
  OptInt tp_ch_used;          ///< value of 'cmdheight' when frame size was set

  diff_T *tp_first_diff;
  buf_T *(tp_diffbuf[DB_COUNT]);
  int tp_diff_invalid;              ///< list of diffs is outdated
  int tp_diff_update;               ///< update diffs before redrawing
  frame_T *(tp_snapshot[SNAP_COUNT]);    ///< window layout snapshots
  ScopeDictDictItem tp_winvar;      ///< Variable for "t:" Dictionary.
  dict_T *tp_vars;         ///< Internal variables, local to tab page.
  char *tp_localdir;       ///< Absolute path of local cwd or NULL.
  char *tp_prevdir;        ///< Previous directory.
};

// 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
  uint16_t wl_size;             // height in screen lines
  char wl_valid;                // true values are valid for text in buffer
  char wl_folded;               // true when this is a range of folded lines
  linenr_T wl_lastlnum;         // last buffer line number for logical line
} 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_S {
  char fr_layout;               // FR_LEAF, FR_COL or FR_ROW
  int fr_width;
  int fr_newwidth;              // new width used in win_equal_rec()
  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 last
  frame_T *fr_prev;         // frame left or above in same parent, NULL
                            // for first
  // fr_child and fr_win are mutually exclusive
  frame_T *fr_child;        // first contained frame
  win_T *fr_win;        // window that fills this frame; for a snapshot
                        // set to the current window
};

#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

// Struct used for highlighting 'hlsearch' matches, matches defined by
// ":match" and matches defined by match functions.
// For 'hlsearch' there is one pattern for all windows.  For ":match" and the
// match functions 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
  colnr_T startcol;     // in win_line() points to char where HL starts
  colnr_T endcol;       // in win_line() points to char where HL ends
  bool is_addpos;       // position specified directly by matchaddpos()
  bool has_cursor;      // true if the cursor is inside the match, used for CurSearch
  proftime_T tm;        // for a time limit
} match_T;

/// Same as lpos_T, but with additional field len.
typedef struct {
  linenr_T lnum;   ///< line number
  colnr_T col;    ///< column number
  int len;    ///< length: 0 - to the end of line
} llpos_T;

/// matchitem_T provides a linked list for storing match items for ":match",
/// matchadd() and matchaddpos().
typedef struct matchitem matchitem_T;
struct matchitem {
  matchitem_T *mit_next;
  int mit_id;              ///< match ID
  int mit_priority;        ///< match priority

  // Either a pattern is defined (mit_pattern is not NUL) or a list of
  // positions is given (mit_pos is not NULL and mit_pos_count > 0).
  char *mit_pattern;       ///< pattern to highlight
  regmmatch_T mit_match;   ///< regexp program for pattern

  llpos_T *mit_pos_array;  ///< array of positions
  int mit_pos_count;       ///< nr of entries in mit_pos
  int mit_pos_cur;         ///< internal position counter
  linenr_T mit_toplnum;    ///< top buffer line
  linenr_T mit_botlnum;    ///< bottom buffer line

  match_T mit_hl;          ///< struct for doing the actual highlighting
  int mit_hlg_id;          ///< highlight group ID
  int mit_conceal_char;    ///< cchar for Conceal highlighting
};

typedef int FloatAnchor;

enum {
  kFloatAnchorEast  = 1,
  kFloatAnchorSouth = 2,
};

// NW -> 0
// NE -> kFloatAnchorEast
// SW -> kFloatAnchorSouth
// SE -> kFloatAnchorSouth | kFloatAnchorEast
EXTERN const char *const float_anchor_str[] INIT( = { "NW", "NE", "SW", "SE" });

typedef enum {
  kFloatRelativeEditor = 0,
  kFloatRelativeWindow = 1,
  kFloatRelativeCursor = 2,
  kFloatRelativeMouse = 3,
} FloatRelative;

EXTERN const char *const float_relative_str[] INIT( = { "editor", "win",
                                                        "cursor", "mouse" });

typedef enum {
  kWinStyleUnused = 0,
  kWinStyleMinimal,  /// Minimal UI: no number column, eob markers, etc
} WinStyle;

typedef enum {
  kAlignLeft   = 0,
  kAlignCenter = 1,
  kAlignRight  = 2,
} AlignTextPos;

typedef enum {
  kBorderTextTitle = 0,
  kBorderTextFooter = 1,
} BorderTextType;

typedef struct {
  Window window;
  lpos_T bufpos;
  int height, width;
  double row, col;
  FloatAnchor anchor;
  FloatRelative relative;
  bool external;
  bool focusable;
  int zindex;
  WinStyle style;
  bool border;
  bool shadow;
  char border_chars[8][MAX_SCHAR_SIZE];
  int border_hl_ids[8];
  int border_attr[8];
  bool title;
  AlignTextPos title_pos;
  VirtText title_chunks;
  int title_width;
  bool footer;
  AlignTextPos footer_pos;
  VirtText footer_chunks;
  int footer_width;
  bool noautocmd;
  bool fixed;
  bool hide;
} FloatConfig;

#define FLOAT_CONFIG_INIT ((FloatConfig){ .height = 0, .width = 0, \
                                          .bufpos = { -1, 0 }, \
                                          .row = 0, .col = 0, .anchor = 0, \
                                          .relative = 0, .external = false, \
                                          .focusable = true, \
                                          .zindex = kZIndexFloatDefault, \
                                          .style = kWinStyleUnused, \
                                          .noautocmd = false, \
                                          .hide = false, \
                                          .fixed = false })

// Structure to store last cursor position and topline.  Used by check_lnums()
// and reset_lnums().
typedef struct {
  int w_topline_save;   // original topline value
  int w_topline_corr;   // corrected topline value
  pos_T w_cursor_save;  // original cursor position
  pos_T w_cursor_corr;  // corrected cursor position
} pos_save_T;

/// Characters from the 'listchars' option.
typedef struct {
  int eol;
  int ext;
  int prec;
  int nbsp;
  int space;
  int tab1;  ///< first tab character
  int tab2;  ///< second tab character
  int tab3;  ///< third tab character
  int lead;
  int trail;
  int *multispace;
  int *leadmultispace;
  int conceal;
} lcs_chars_T;

/// Characters from the 'fillchars' option.
typedef struct {
  int stl;
  int stlnc;
  int wbr;
  int horiz;
  int horizup;
  int horizdown;
  int vert;
  int vertleft;
  int vertright;
  int verthoriz;
  int fold;
  int foldopen;    ///< when fold is open
  int foldclosed;  ///< when fold is closed
  int foldsep;     ///< continuous fold marker
  int diff;
  int msgsep;
  int eob;
  int lastline;
} fcs_chars_T;

/// 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_S {
  handle_T handle;                  ///< unique identifier for the window

  buf_T *w_buffer;            ///< buffer we are a window into (used
                              ///< often, keep it the first item!)

  synblock_T *w_s;                 ///< for :ownsyntax

  int w_ns_hl;
  int w_ns_hl_winhl;
  int w_ns_hl_active;
  int *w_ns_hl_attr;

  int w_hl_id_normal;               ///< 'winhighlight' normal id
  int w_hl_attr_normal;             ///< 'winhighlight' normal final attrs
  int w_hl_attr_normalnc;           ///< 'winhighlight' NormalNC final attrs

  int w_hl_needs_update;            ///< attrs need to be recalculated

  win_T *w_prev;              ///< link to previous window
  win_T *w_next;              ///< link to next window
  bool w_closing;                   ///< window is being closed, don't let
                                    ///< autocommands close it too.

  frame_T *w_frame;             ///< frame containing this window

  pos_T w_cursor;                   ///< cursor position in buffer

  colnr_T w_curswant;               ///< Column we want 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

  linenr_T w_cursorline;            ///< Where 'cursorline' should be drawn,
                                    ///< can be different from w_cursor.lnum
                                    ///< for closed folds.
  linenr_T w_last_cursorline;       ///< where last 'cursorline' was drawn

  // the next seven 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_visual_col;         ///< last known start of visual part
  colnr_T w_old_curswant;           ///< last known value of Curswant

  linenr_T w_last_cursor_lnum_rnu;  ///< cursor lnum when 'rnu' was last redrawn

  /// 'listchars' characters. Defaults set in set_chars_option().
  lcs_chars_T w_p_lcs_chars;

  /// 'fillchars' characters. Defaults set in set_chars_option().
  fcs_chars_T w_p_fcs_chars;

  // "w_topline", "w_leftcol" and "w_skipcol" specify the offsets for
  // displaying the buffer.
  linenr_T w_topline;               // buffer line number of the line at the
                                    // top of the window
  char w_topline_was_set;           // flag set to true when topline is set,
                                    // e.g. by winrestview()
  int w_topfill;                    // number of filler lines above w_topline
  int w_old_topfill;                // w_topfill at last redraw
  bool w_botfill;                   // true when filler lines are actually
                                    // below w_topline (at end of file)
  bool w_old_botfill;               // w_botfill at last redraw
  colnr_T w_leftcol;                // screen column number of the left most
                                    // character in the window; used when
                                    // 'wrap' is off
  colnr_T w_skipcol;                // starting screen column for the first
                                    // line in the window; used when 'wrap' is
                                    // on; does not include win_col_off()

  // six fields that are only used when there is a WinScrolled autocommand
  linenr_T w_last_topline;          ///< last known value for w_topline
  int w_last_topfill;               ///< last known value for w_topfill
  colnr_T w_last_leftcol;           ///< last known value for w_leftcol
  colnr_T w_last_skipcol;           ///< last known value for w_skipcol
  int w_last_width;                 ///< last known value for w_width
  int w_last_height;                ///< last known value for w_height

  //
  // Layout of the window in the screen.
  // May need to add "msg_scrolled" to "w_winrow" in rare situations.
  //
  int w_winrow;                     // first row of window in screen
  int w_height;                     // number of rows in window, excluding
                                    // status/command line(s)
  int w_prev_winrow;                // previous winrow used for 'splitkeep'
  int w_prev_height;                // previous height used for 'splitkeep'
  int w_status_height;              // number of status lines (0 or 1)
  int w_winbar_height;              // number of window bars (0 or 1)
  int w_wincol;                     // Leftmost column of window in screen.
  int w_width;                      // Width of window, excluding separation.
  int w_hsep_height;                // Number of horizontal separator rows (0 or 1)
  int w_vsep_width;                 // Number of vertical separator columns (0 or 1).
  pos_save_T w_save_cursor;         // backup of cursor pos and topline
  bool w_do_win_fix_cursor;         // if true cursor may be invalid

  int w_winrow_off;  ///< offset from winrow to the inner window area
  int w_wincol_off;  ///< offset from wincol to the inner window area
                     ///< this includes float border but excludes special columns
                     ///< implemented in win_line() (i.e. signs, folds, numbers)

  // inner size of window, which can be overridden by external UI
  int w_height_inner;
  int w_width_inner;
  // external UI request. If non-zero, the inner size will use this.
  int w_height_request;
  int w_width_request;

  int w_border_adj[4];  // top, right, bottom, left
  // outer size of window grid, including border
  int w_height_outer;
  int w_width_outer;

  // === 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.
  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
  colnr_T w_valid_skipcol;          // last known w_skipcol

  bool w_viewport_invalid;
  linenr_T w_viewport_last_topline;  // topline when the viewport was last updated
  linenr_T w_viewport_last_botline;  // botline when the viewport was last updated
  linenr_T w_viewport_last_topfill;  // topfill when the viewport was last updated
  linenr_T w_viewport_last_skipcol;  // skipcol when the viewport was last updated

  // 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_win().
  int w_cline_height;               // current size of cursor line
  bool w_cline_folded;              // cursor line is folded

  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 window
  int w_empty_rows;                 // number of ~ rows in window
  int w_filler_rows;                // number of filler rows at the end of the
                                    // window

  // 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;

  garray_T w_folds;                 // array of nested folds
  bool w_fold_manual;               // when true: some folds are opened/closed
                                    // manually
  bool w_foldinvalid;               // when true: folding needs to be
                                    // recomputed
  int w_nrwidth;                    // width of 'number' and 'relativenumber'
                                    // column being used
  int w_scwidth;                    // width of 'signcolumn'
  int w_minscwidth;                 // minimum width or SCL_NO/SCL_NUM
  int w_maxscwidth;                 // maximum width or SCL_NO/SCL_NUM

  // === 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 UPD_REDRAW_TOP
  linenr_T w_redraw_top;            // when != 0: first line needing redraw
  linenr_T w_redraw_bot;            // when != 0: last line needing redraw
  bool w_redr_status;               // if true statusline/winbar must be redrawn
  bool w_redr_border;               // if true border must be redrawn
  bool w_redr_statuscol;            // if true 'statuscolumn' must be redrawn

  // remember what is shown in the 'statusline'-format elements
  pos_T w_stl_cursor;                // cursor position when last redrawn
  colnr_T w_stl_virtcol;             // virtcol when last redrawn
  linenr_T w_stl_topline;            // topline when last redrawn
  linenr_T w_stl_line_count;         // line count when last redrawn
  int w_stl_topfill;                 // topfill when last redrawn
  char w_stl_empty;                  // true if elements show 0-1 (empty line)
  int w_stl_recording;               // reg_recording when last redrawn
  int w_stl_state;                   // get_real_state() when last redrawn
  int w_stl_visual_mode;             // VIsual_mode when last redrawn

  int w_alt_fnum;                   // alternate file (for # and CTRL-^)

  alist_T *w_alist;             // pointer to arglist for this window
  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 *w_localdir;            // absolute path of local directory or NULL
  char *w_prevdir;             // previous directory
  // 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))

  // A few options have local flags for P_INSECURE.
  uint32_t w_p_stl_flags;           // flags for 'statusline'
  uint32_t w_p_wbr_flags;           // flags for 'winbar'
  uint32_t w_p_fde_flags;           // flags for 'foldexpr'
  uint32_t w_p_fdt_flags;           // flags for 'foldtext'
  colorcol_T *w_p_cc_cols;          // array of columns to highlight or NULL
  uint8_t w_p_culopt_flags;         // flags for cursorline highlighting

  int w_briopt_min;                 // minimum width for breakindent
  int w_briopt_shift;               // additional shift for breakindent
  bool w_briopt_sbr;                // sbr in 'briopt'
  int w_briopt_list;                // additional indent for lists
  int w_briopt_vcol;                // indent for specific column

  int w_scbind_pos;

  ScopeDictDictItem w_winvar;  ///< Variable for "w:" dictionary.
  dict_T *w_vars;  ///< Dictionary with w: variables.

  // 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

  // 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

  matchitem_T *w_match_head;            // head of match list
  int w_next_match_id;                  // next match ID

  // 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 active entry
  int w_tagstacklen;                    // number of tags on stack

  ScreenGrid w_grid;                    // the grid specific to the window
  ScreenGrid w_grid_alloc;              // the grid specific to the window
  bool w_pos_changed;                   // true if window position changed
  bool w_floating;                       ///< whether the window is floating
  FloatConfig w_float_config;

  // 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;

  linenr_T w_nrwidth_line_count;        // line count when ml_nrwidth_width was computed.
  linenr_T w_statuscol_line_count;      // line count when 'statuscolumn' width was computed.
  int w_nrwidth_width;                  // nr of chars to print line count.

  qf_info_T *w_llist;                 // Location list for this window
  // Location list reference used in the location list window.
  // In a non-location list window, w_llist_ref is NULL.
  qf_info_T *w_llist_ref;

  // Status line click definitions
  StlClickDefinition *w_status_click_defs;
  // Size of the w_status_click_defs array
  size_t w_status_click_defs_size;

  // Window bar click definitions
  StlClickDefinition *w_winbar_click_defs;
  // Size of the w_winbar_click_defs array
  size_t w_winbar_click_defs_size;

  // Status column click definitions
  StlClickDefinition *w_statuscol_click_defs;
  // Size of the w_statuscol_click_defs array
  size_t w_statuscol_click_defs_size;
};

/// Macros defined in Vim, but not in Neovim
// uncrustify:off
#define CHANGEDTICK(buf) \
  (=== Include buffer.h & use buf_(get|set|inc) _changedtick ===)
// uncrustify:on