]> git.neil.brown.name Git - edlib.git/blob - core.h
8a6fbc084c4b6cb52bc01dcad93640d62d225ed8
[edlib.git] / core.h
1 /*
2  * Copyright Neil Brown ©2015-2023 <neil@brown.name>
3  * May be distributed under terms of GPLv2 - see file:COPYING
4  *
5  * Core elements include:
6  * documents
7  * marks and points
8  * attributes
9  * panes
10  * keymaps
11  * commands
12  */
13
14 #include <wchar.h>
15 #include <limits.h>
16 #include <sys/stat.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <time.h>
20 #include "safe.h"
21 #include "misc.h"
22
23 #include "list.h"
24 #include "vfunc.h"
25
26 extern char edlib_version[];
27 #ifndef VERSION
28 #define VERSION "unreleased"
29 #endif
30 #ifndef VERS_DATE
31 #define VERS_DATE "unreleased"
32 #endif
33
34 struct doc;
35 struct mark;
36 struct attrset;
37 struct pane;
38 struct command;
39 struct cmd_info;
40
41 extern MEMPOOL_DECL(pane);
42
43 #ifndef PRIVATE_DOC_REF
44 struct doc_ref {
45         void            *p;
46         unsigned int    i;
47 };
48 #endif
49 struct generic_doc_ref {
50         void            *p;
51         unsigned int    i;
52 };
53
54 void LOG(char *fmt, ...);
55 void LOG_BT(void);
56
57 /* The 'editor' contains (by reference) everything else.
58  * This captures and documents the global states, and allows
59  * multiple "editors" in the one process, should that be valuable.
60  *
61  * Each document and contains a reference to the editor which is the root of the
62  * pane tree.
63  */
64 struct pane ;
65
66 struct command {
67         int             (*func)(const struct cmd_info *ci safe);
68         unsigned int    refcnt; /* only if 'free' is not NULL */
69         unsigned int    closed_ok:1;
70         void            (*free)(struct command *c safe);
71         const char       *name;
72 };
73
74 enum edlib_errors {
75         Efallthrough = 0,
76         Enoarg = -1000,
77         Einval,
78         Enosup,
79         Efail,
80         /* following errors are soft and don't create exceptions */
81         Efalse,
82         Eunused,
83 };
84
85 static inline struct command *safe command_get(struct command * safe c)
86 {
87         if (!(void*) c)
88                 return c;
89         if (c->free)
90                 c->refcnt += 1;
91         return c;
92 }
93
94 static inline void command_put(struct command *c)
95 {
96         if (c && c->free && --c->refcnt == 0)
97                 c->free(c);
98 }
99
100 struct notifier {
101         struct pane             *notifiee safe;
102         char                    *notification safe;
103         struct list_head        notifier_link, notifiee_link;
104         int                     noted;
105 };
106 void pane_add_notify(struct pane *target safe, struct pane *source safe,
107                      const char *msg safe);
108 int do_pane_notify(struct pane *home, const char *notification safe,
109                    struct pane *p safe,
110                    int num, struct mark *m, const char *str,
111                    int num2, struct mark *m2, const char *str2,
112                    struct command *comm2);
113 void pane_drop_notifiers(struct pane *p safe, char *notification);
114
115 struct pane *editor_new(const char *comm_name);
116 void * safe memsave(struct pane *p safe, const char *buf, int len);
117 char *strsave(struct pane *p safe, const char *buf);
118 char *strnsave(struct pane *p safe, const char *buf, int len);
119 char * safe do_strconcat(struct pane *p, const char *s1 safe, ...);
120 #define strconcat(p, ...) do_strconcat(p, __VA_ARGS__, NULL)
121 bool edlib_testing(struct pane *p safe);
122
123 /* This is declared here so sparse knows it is global */
124 void edlib_init(struct pane *ed safe);
125
126 struct doc {
127         struct hlist_head       marks;
128         struct tlist_head       points;
129         struct docview {
130                 struct tlist_head head;
131                 struct pane       *owner;
132         } /* safe iff nviews > 0 */ *views;
133         int                     nviews;
134         struct mark             *recent_points[8];
135         void                    (*refcnt)(struct mark *m safe, int cnt);
136         char                    *name;
137         bool                    autoclose;
138         bool                    readonly;
139 };
140
141 void doc_free(struct doc *d safe, struct pane *root safe);
142 extern struct map *doc_default_cmd safe;
143
144 #define CHAR_RET(_c) ((_c & 0x1FFFFF) | 0x200000)
145
146 #define is_eol(c) ({int _c = c; _c == '\n' || _c == '\v' || _c == '\f'; })
147
148 /* Points and Marks */
149
150 enum {
151         MARK_POINT = -1,
152         MARK_UNGROUPED = -2
153 };
154
155 enum {
156         GRP_HEAD = 0, // tlist_head list head
157         GRP_MARK = 1, // tlist_head in mark.view
158         GRP_LIST = 2, // tlist_head in point.lists
159 };
160
161 #ifndef MARK_DATA_PTR
162 #define MARK_DATA_PTR void
163 #endif
164 struct mark {
165         struct doc_ref          ref;
166         struct hlist_node       all;
167         struct tlist_head       view;
168         struct attrset          *attrs;
169         int                     seq;
170         short                   viewnum;
171         short                   flags;
172         MARK_DATA_PTR           *mdata;
173         void                    *mtype; /* can be used to validate
174                                          * type of mdata */
175         struct pane             *owner safe; /* document pane which
176                                               * understands .ref
177                                               */
178 };
179 #define MARK_FLAG_WATCHED       1
180
181 static inline bool mark_valid(struct mark *m)
182 {
183         /* When marks are freed, most fields including ->attrs are
184          * set to all 1's.  The memory isn't released until an
185          * idle time.
186          */
187         return m && m->attrs != (void*)~0UL;
188 }
189
190 /* A point uses this for the mdata */
191 struct point_links {
192         unsigned int            size;
193         struct mark             *pt safe;
194         struct tlist_head       lists[];
195 };
196
197 struct mark *safe mark_dup(struct mark *m safe);
198 struct mark *safe mark_dup_view(struct mark *m safe);
199 void mark_free(struct mark *m);
200 void mark_watch(struct mark *m);
201
202 struct mark *mark_first(struct doc *d safe);
203 struct mark *mark_next(struct mark *m safe);
204 struct mark *mark_prev(struct mark *m safe);
205 void mark_reset(struct pane *p safe, struct mark *m safe, int end);
206 void mark_to_end(struct pane *p safe, struct mark *m safe, int end);
207 void doc_check_consistent(struct doc *d safe);
208 void mark_to_mark(struct mark *m safe, struct mark *target safe);
209 void mark_to_mark_noref(struct mark *m safe, struct mark *target safe);
210 wint_t do_doc_step(struct pane *p safe, struct mark *m,
211                    int forward, int move);
212 void mark_step(struct mark *m safe, int forward);
213 void mark_step_sharesref(struct mark *m safe, int forward);
214 bool marks_validate(struct mark *m1 safe, struct mark *m2 safe);
215
216 static inline int mark_same(struct mark *m1 safe, struct mark *m2 safe)
217 {
218         struct generic_doc_ref *r1 = (void*)&m1->ref;
219         struct generic_doc_ref *r2 = (void*)&m2->ref;
220
221         /* Compile-time check that size of doc_ref is correct */
222         switch(0){
223         case 0: break;
224         case (sizeof(struct doc_ref) == sizeof(struct generic_doc_ref)):
225                 break;
226         }
227
228         return r1->p == r2->p && r1->i == r2->i;
229 }
230
231 struct mark *mark_at_point(struct pane *p safe, struct mark *pm, int view);
232 struct mark *vmark_next(struct mark *m safe);
233 struct mark *vmark_prev(struct mark *m safe);
234 struct mark *vmark_matching(struct mark *m safe);
235 struct mark *vmark_first(struct pane *p safe, int view,
236                          struct pane *owner safe);
237 struct mark *vmark_last(struct pane *p safe, int view, struct pane *owner safe);
238 struct mark *vmark_at_or_before(struct pane *p safe, struct mark *m safe,
239                                 int view, struct pane *owner);
240 struct mark *vmark_new(struct pane *p safe, int view, struct pane *owner);
241 static inline struct mark *mark_new(struct pane *p safe)
242 {
243         return vmark_new(p, MARK_UNGROUPED, NULL);
244 }
245 static inline struct mark *point_new(struct pane *p safe)
246 {
247         return vmark_new(p, MARK_POINT, NULL);
248 }
249 void mark_clip(struct mark *m safe, struct mark *start, struct mark *end,
250                bool tostart);
251 void marks_clip(struct pane *p safe, struct mark *start, struct mark *end,
252                 int view, struct pane *owner, bool tostart);
253
254 static inline int mark_ordered_or_same(struct mark *m1 safe,
255                                        struct mark *m2 safe)
256 {
257         return m1->seq < m2->seq || mark_same(m1, m2);
258 }
259
260 static inline int mark_ordered_not_same(struct mark *m1 safe,
261                                         struct mark *m2 safe)
262 {
263         return m1->seq < m2->seq && !mark_same(m1, m2);
264 }
265
266 static inline struct attrset **safe mark_attr(struct mark *m safe)
267 {
268         return &m->attrs;
269 }
270
271 /* Attributes */
272 char *attr_find(struct attrset *set, const char *key safe);
273 bool attr_del(struct attrset **setp safe, const char *key safe);
274 void attr_del_all(struct attrset **setp safe, const char *key safe,
275                   int low, int high);
276 int attr_set_str(struct attrset **setp safe,
277                  const char *key safe, const char *val);
278 int attr_set_str_key(struct attrset **setp safe, const char *key safe,
279                      const char *val, int keynum);
280 char *attr_get_str(struct attrset *setp, const char *key safe, int keynum);
281 const char *attr_get_next_key(struct attrset *set, const char *key safe,
282                               int keynum,
283                               const char **valp safe);
284 int attr_find_int(struct attrset *set, const char *key safe);
285 int attr_set_int(struct attrset **setp safe, const char *key safe, int val);
286 void attr_trim(struct attrset **setp safe, int nkey);
287 struct attrset *attr_copy_tail(struct attrset *set, int nkey);
288 struct attrset *attr_copy(struct attrset *set);
289 struct attrset *attr_collect(struct attrset *set, unsigned int pos, int prefix);
290 void attr_free(struct attrset **setp safe);
291
292 /* Commands */
293 struct lookup_cmd {
294         struct command  c;
295         struct map      **m safe;
296 };
297
298 #define CMD(_name) {                                    \
299                 .func = _name ## _func ,                \
300                 .refcnt = 0,                            \
301                 .closed_ok = 0,                         \
302                 .free = NULL,                           \
303                 .name = # _name,                        \
304         }
305 #define CMD_CLOSED(_name) {                             \
306                 .func = _name ## _func ,                \
307                 .refcnt = 0,                            \
308                 .closed_ok = 1,                         \
309                 .free = NULL,                           \
310                 .name = # _name,                        \
311         }
312 #define CB(_name) {.func = _name ## _func ,             \
313                    .refcnt = 0,                         \
314                    .closed_ok = 0,                      \
315                    .free = NULL,                        \
316                    .name = # _name,                     \
317         }
318
319 #define DEF_CMD(_name) \
320         static int _name ## _func(const struct cmd_info *ci safe); \
321         static struct command _name = CMD(_name);       \
322         static int _name ## _func(const struct cmd_info *ci safe)
323 #define DEF_CMD_CLOSED(_name) \
324         static int _name ## _func(const struct cmd_info *ci safe); \
325         static struct command _name = CMD_CLOSED(_name);        \
326         static int _name ## _func(const struct cmd_info *ci safe)
327 #define REDEF_CMD(_name) \
328         static int _name ## _func(const struct cmd_info *ci safe)
329 #define DEF_EXTERN_CMD(_name) \
330         static int _name ## _func(const struct cmd_info *ci safe); \
331         struct command _name = CMD(_name);              \
332         static int _name ## _func(const struct cmd_info *ci safe)
333 #define DECL_EXTERN_CMD(_name) \
334         extern struct command _name;
335 #define DEF_CB(_name) \
336         static int _name ## _func(const struct cmd_info *ci safe); \
337         static struct command _name = CB(_name);        \
338         static int _name ## _func(const struct cmd_info *ci safe)
339 #define REDEF_CB(_name) \
340         static int _name ## _func(const struct cmd_info *ci safe)
341
342 #define DEF_LOOKUP_CMD(_name, _map) \
343         static struct lookup_cmd _name = {              \
344                 .c.func = key_lookup_cmd_func,          \
345                 .c.refcnt = 0,                          \
346                 .c.closed_ok = 1,                       \
347                 .c.free = NULL,                         \
348                 .c.name = #_name,                       \
349                 .m = &_map,                             \
350         }
351
352 DECL_EXTERN_CMD(edlib_noop);
353
354 int key_lookup_cmd_func(const struct cmd_info *ci safe);
355
356 struct pfx_cmd {
357         struct command  c;
358         char            *pfx safe;
359 };
360
361 int key_pfx_func(const struct cmd_info *ci safe);
362
363 #define DEF_PFX_CMD(_name, _pfx)                        \
364         static struct pfx_cmd _name = {                 \
365                 .c.func = key_pfx_func,                 \
366                 .c.refcnt = 0,                          \
367                 .c.closed_ok = 1,                       \
368                 .c.free = NULL,                         \
369                 .c.name = "prefix" #_pfx,               \
370                 .pfx = _pfx,                            \
371         };
372
373 #define ARRAY_SIZE(ra) (sizeof(ra) / sizeof(ra[0]))
374
375 /* Each event (above) is accompanied by a cmd_info structure.
376  * 'key' and 'home' are always present, others only if relevant.
377  * Num is present for 'key' and 'move'.  INT_MAX/2 means no number was
378  *   requested so is usually treated like '1'.  Negative numbers are quite
379  *   possible.
380  * x,y are present for mouse events
381  * 'str' is inserted by 'replace' and sought by 'search'
382  * 'mark' is moved by 'move' and 'replace' deletes between point and mark.
383  */
384 struct cmd_info {
385         const char      *key safe;
386         struct pane     *home safe, *focus safe;
387         int             num, num2;
388         int             x,y;            /* relative to focus */
389         const char      *str, *str2;
390         struct mark     *mark, *mark2;
391         struct command  *comm safe;
392         struct command  *comm2;
393
394         /* An array of 2 hashes, one for the prefix of the key - all
395          * chars to first '-' or ':'.  One for the whole key.
396          */
397         unsigned int *hash;
398 };
399
400 #define NO_NUMERIC      (INT_MAX/2)
401 #define RPT_NUM(ci)     ((ci)->num == NO_NUMERIC ? 1 :          \
402                          (ci)->num == NO_NUMERIC + 1 ? 4 :      \
403                          (ci)->num == -NO_NUMERIC ? -1 : (ci)->num)
404
405 struct map *safe key_alloc(void);
406 void key_free(struct map *m safe);
407 int key_handle(const struct cmd_info *ci safe);
408 int key_lookup(struct map *m safe, const struct cmd_info *ci safe);
409 int key_lookup_prefix(struct map *m safe, const struct cmd_info *ci safe);
410 struct command *key_lookup_cmd(struct map *m safe, const char *c safe);
411 void key_add(struct map *map safe, const char *k safe, struct command *comm);
412 void key_add_range(struct map *map safe,
413                    const char *first safe, const char *last safe,
414                    struct command *comm);
415 #define key_add_prefix(map, prefix, comm) \
416         key_add_range(map, prefix, prefix "\xFF\xFF\xFF\xFF", comm)
417 void key_add_chain(struct map *map safe, struct map *chain);
418
419 static inline const char *safe ksuffix(const struct cmd_info *ci safe,
420                                        const char *prefix safe)
421 {
422         int l = strlen(prefix);
423         if (strncmp(ci->key, prefix, l) == 0)
424                 return ci->key + l;
425         return "";
426 }
427
428 /* DAMAGED_SIZE propagates down.
429  * If any flag is set on children, DAMAGED_CHILD is set.
430  */
431 #define BIT(n) (1 << (n))
432 enum {
433         DAMAGED_SIZE            = BIT(0), /* Size has changed */
434         DAMAGED_SIZE_CHILD      = BIT(1), /* a child has changed size */
435         DAMAGED_VIEW            = BIT(2), /* content has moved */
436         DAMAGED_VIEW_CHILD      = BIT(3), /* a child needs to adjust the view */
437
438         DAMAGED_REFRESH         = BIT(4), /* Content has changed */
439         DAMAGED_CHILD           = BIT(6), /* CONTENT in child */
440
441         DAMAGED_POSTORDER       = BIT(7), /* Pane wants to be called again */
442         DAMAGED_POSTORDER_CHILD = BIT(8), /* Child pane wants to be called again */
443
444         DAMAGED_CLOSED          = BIT(15),
445         DAMAGED_DEAD            = BIT(14), /* Fully closed, but not freed yet */
446         DAMAGED_NOT_HANDLED     = BIT(13), /* A for() loop is processing
447                                             * children, and this one
448                                             * hasn't been handled yet.
449                                             */
450         DAMAGED_DEBUG           = BIT(12),
451         DAMAGED_NOINIT          = BIT(11), /* Closing before pane_register
452                                             * had a chance to complete.
453                                             */
454 };
455 #define DAMAGED_NEED_CALL (DAMAGED_SIZE | DAMAGED_REFRESH)
456
457 struct xy {short x,y;};
458 struct pane * do_pane_register(struct pane *parent safe, short z,
459                                struct command *handle safe, void *data,
460                                short data_size);
461 #define pane_register(...) VFUNC(pane_register, __VA_ARGS__)
462 #ifdef PANE_DATA_TYPE
463 #define pane_register4(p,z,h,d) do_pane_register(p,z,h,d,sizeof(d))
464 #define pane_register3(p,z,h) do_pane_register(p,z,h,NULL, sizeof(PANE_DATA_TYPE))
465 #else
466 #ifdef PANE_DATA_PTR_TYPE
467 static inline struct pane *pane_register(struct pane *parent safe, short z,
468                                          struct command *handle safe,
469                                          PANE_DATA_PTR_TYPE data)
470 {
471         return do_pane_register(parent, z, handle, (void*)data, sizeof(data));
472 }
473 #else
474 #ifdef PANE_DATA_VOID
475 #define pane_register3(p,z,h) do_pane_register(p,z,h,NULL, 0)
476 #else
477 #define pane_register4(p,z,h,d) do_pane_register(p,z,h,d,sizeof((d)[0]))
478 #define pane_register3(p,z,h) do_pane_register(p,z,h,NULL, 0)
479 #endif
480 #endif
481 #endif
482
483 #ifdef PANE_DATA_TYPE_2
484 #define pane_register_2(p,z,h) do_pane_register(p,z,h,NULL, sizeof(PANE_DATA_TYPE_2))
485 #endif
486 #ifdef PANE_DATA_PTR_TYPE_2
487 static inline struct pane *pane_register_2(struct pane *parent safe, short z,
488                                            struct command *handle safe,
489                                            PANE_DATA_PTR_TYPE_2 data)
490 {
491         return do_pane_register(parent, z, handle, (void*)data, sizeof(data));
492 }
493 #endif
494 #ifdef PANE_DATA_VOID_2
495 #define pane_register_2(p,z,h) do_pane_register(p,z,h,NULL, 0)
496 #endif
497
498 #ifdef PANE_DATA_TYPE_3
499 #define pane_register_3(p,z,h) do_pane_register(p,z,h,NULL, sizeof(PANE_DATA_TYPE_3))
500 #endif
501 #ifdef PANE_DATA_PTR_TYPE_3
502 static inline struct pane *pane_register_3(struct pane *parent safe, short z,
503                                            struct command *handle safe,
504                                            PANE_DATA_PTR_TYPE_3 data)
505 {
506         return do_pane_register(parent, z, handle, (void*)data, sizeof(data));
507 }
508 #endif
509 #ifdef PANE_DATA_VOID_3
510 #define pane_register_3(p,z,h) do_pane_register(p,z,h,NULL, 0)
511 #endif
512
513 void pane_update_handle(struct pane *p safe, struct command *handle safe);
514
515
516 #ifdef DOC_DATA_TYPE
517 struct pane *do_doc_register(struct pane *parent safe,
518                              struct command *handle safe,
519                              unsigned short data_size);
520 #define doc_register(p,h) do_doc_register(p, h, sizeof(DOC_DATA_TYPE))
521 #endif
522
523 void pane_reparent(struct pane *p safe, struct pane *newparent safe);
524 void pane_move_after(struct pane *p safe, struct pane *after);
525 void pane_subsume(struct pane *p safe, struct pane *parent safe);
526 void pane_close(struct pane *p safe);
527 bool pane_resize(struct pane *p safe, int x, int y, int w, int h);
528 void pane_take_focus(struct pane *p);
529 bool do_pane_has_focus(struct pane *p, struct pane *root);
530 #define pane_has_focus(...) VFUNC(pane_has_focus, __VA_ARGS__)
531 #define pane_has_focus1(p) do_pane_has_focus(p, NULL)
532 #define pane_has_focus2(p,r) do_pane_has_focus(p, r)
533 void pane_damaged(struct pane *p, int type);
534 void pane_clone_children(struct pane *from, struct pane *to);
535 struct pane *pane_my_child(struct pane *p, struct pane *c);
536
537 char *pane_attr_get(struct pane *p, const char *key safe);
538 char *pane_mark_attr(struct pane *p safe, struct mark *m safe,
539                      const char *key safe);
540 struct xy pane_mapxy(struct pane *orig safe, struct pane *target safe,
541                      short x, short y, bool clip);
542
543 struct xy pane_scale(struct pane *p safe);
544
545 static inline int pane_attr_get_int(struct pane *p safe, const char *key safe,
546                                     int dflt)
547 {
548         char *c = pane_attr_get(p, key);
549         int rv;
550         char *end;
551         if (!c)
552                 return dflt;
553         rv = strtol(c, &end, 10);
554         if (end == c || !end || (*end && *end != ' '))
555                 return dflt;
556         return rv;
557 }
558 void pane_free(struct pane *p safe);
559 struct pane * safe pane_leaf(struct pane *p safe);
560
561 /* Inlines */
562
563 static inline wint_t doc_next(struct pane *p safe, struct mark *m)
564 {
565         return do_doc_step(p, m, 1, 1);
566 }
567
568 static inline wint_t doc_prev(struct pane *p safe, struct mark *m)
569 {
570         return do_doc_step(p, m, 0, 1);
571 }
572
573 static inline wint_t doc_following(struct pane *p safe, struct mark *m)
574 {
575         return do_doc_step(p, m, 1, 0);
576 }
577
578 static inline wint_t doc_prior(struct pane *p safe, struct mark *m)
579 {
580         return do_doc_step(p, m, 0, 0);
581 }
582
583 static inline wint_t doc_move(struct pane *p safe, struct mark *m, int n)
584 {
585         /* Move 'n' chars (backwards if negative) returning last character
586          * stepped over
587          */
588         wint_t wc = WEOF;
589         while (n < 0 && (wc = doc_prev(p, m)) != WEOF)
590                 n += 1;
591         while (n > 0 && (wc = doc_next(p, m)) != WEOF)
592                 n -= 1;
593         return wc;
594 }
595
596 static inline wint_t doc_pending(struct pane *p safe, struct mark *m, int n)
597 {
598         /* n must be <0 or >0.  Return the next char in that direction */
599         if (n > 0)
600                 return doc_following(p, m);
601         if (n < 0)
602                 return doc_prior(p, m);
603         return WEOF;
604 }
605
606 #if defined(DOC_NEXT)
607 #ifdef DOC_NEXT_DECL
608 static inline wint_t DOC_NEXT_DECL(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
609 static inline wint_t DOC_PREV_DECL(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
610 #else
611 static inline wint_t DOC_NEXT(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
612 static inline wint_t DOC_PREV(struct pane *p safe, struct mark *m safe, struct doc_ref *r safe, bool byte);
613 #endif
614 static inline int do_char_byte(const struct cmd_info *ci safe)
615 {
616         struct mark *m = ci->mark;
617         struct mark *end = ci->mark2;
618         struct pane *p = ci->home;
619         struct doc_ref r;
620         int steps = ci->num;
621         int forward = steps > 0;
622         wint_t ret = ' ';
623         int byte = strcmp(ci->key, "doc:byte") == 0;
624
625         if (!m)
626                 return Enoarg;
627         if (end && mark_same(m, end))
628                 return 1;
629         if (end && (end->seq < m->seq) != (steps < 0))
630                 /* Can never cross 'end' */
631                 return Einval;
632         while (steps && ret != CHAR_RET(WEOF) && (!end || !mark_same(m, end))) {
633                 #ifdef DOC_SHARESREF
634                 mark_step_sharesref(m, forward);
635                 #else
636                 mark_step(m, forward);
637                 #endif
638                 if (forward)
639                         ret = DOC_NEXT(p, m, &m->ref, byte);
640                 else
641                         ret = DOC_PREV(p, m, &m->ref, byte);
642                 steps -= forward*2 - 1;
643         }
644         if (end)
645                 return 1 + (forward ? ci->num - steps : steps - ci->num);
646         if (ret == WEOF || ci->num2 == 0)
647                 return CHAR_RET(ret);
648         if (ci->num && (ci->num2 < 0) == forward)
649                 return CHAR_RET(ret);
650         /* Want the 'next' char */
651         r = m->ref;
652         if (ci->num2 > 0)
653                 ret = DOC_NEXT(p, m, &r, byte);
654         else
655                 ret = DOC_PREV(p, m, &r, byte);
656         return CHAR_RET(ret);
657 }
658 #endif
659
660 struct call_return {
661         struct command c;
662         struct mark *m, *m2;
663         char *s;
664         struct pane *p;
665         int i, i2;
666         int x,y;
667         struct command *comm;
668         int ret;
669 };
670
671 enum target_type {
672         TYPE_focus,
673         TYPE_home,
674         TYPE_pane,
675         TYPE_comm,
676 };
677
678 struct pane *do_call_pane(enum target_type type, struct pane *home,
679                           struct command *comm2a,
680                           const char *key safe, struct pane *focus safe,
681                           int num,  struct mark *m,  const char *str,
682                           int num2, struct mark *m2, const char *str2,
683                           int x, int y, struct command *comm2b);
684 struct mark *do_call_mark(enum target_type type, struct pane *home,
685                           struct command *comm2a,
686                           const char *key safe, struct pane *focus safe,
687                           int num,  struct mark *m,  const char *str,
688                           int num2, struct mark *m2, const char *str2,
689                           int x, int y, struct command *comm2b);
690 struct mark *do_call_mark2(enum target_type type, struct pane *home,
691                            struct command *comm2a,
692                            const char *key safe, struct pane *focus safe,
693                            int num,  struct mark *m,  const char *str,
694                            int num2, struct mark *m2, const char *str2,
695                            int x, int y, struct command *comm2b);
696 struct command *do_call_comm(enum target_type type, struct pane *home,
697                              struct command *comm2a,
698                              const char *key safe, struct pane *focus safe,
699                              int num,  struct mark *m,  const char *str,
700                              int num2, struct mark *m2, const char *str2,
701                              int x, int y, struct command *comm2b);
702 struct call_return do_call_all(enum target_type type, struct pane *home,
703                                struct command *comm2a,
704                                const char *key safe, struct pane *focus safe,
705                                int num,  struct mark *m,  const char *str,
706                                int num2, struct mark *m2, const char *str2,
707                                int x, int y, struct command *comm2b);
708 char *do_call_str(enum target_type type, struct pane *home,
709                   struct command *comm2a,
710                   const char *key safe, struct pane *focus safe,
711                   int num,  struct mark *m,  const char *str,
712                   int num2, struct mark *m2, const char *str2,
713                   int x, int y, struct command *comm2b);
714 struct call_return do_call_bytes(enum target_type type, struct pane *home,
715                                  struct command *comm2a,
716                                  const char *key safe, struct pane *focus safe,
717                                  int num,  struct mark *m,  const char *str,
718                                  int num2, struct mark *m2, const char *str2,
719                                  int x, int y, struct command *comm2b);
720 char *do_call_strsave(enum target_type type, struct pane *home,
721                       struct command *comm2a,
722                       const char *key safe, struct pane *focus safe,
723                       int num,  struct mark *m,  const char *str,
724                       int num2, struct mark *m2, const char *str2,
725                       int x, int y, struct command *comm2b);
726
727 #define T_focus(_p, _c) _p
728 #define T_home(_p, _c) _p
729 #define T_pane(_p, _c) _p
730 #define T_comm(_p, _c) _c
731
732 #define CH(f,a,b) f(a,b)
733
734 #define _doCALL(...) VFUNC(CALL, __VA_ARGS__)
735 #define CALL15(ret, t_type, target, key, comm2a, focus, num, mark, str, \
736                num2, mark2, str2, x, y, comm2) \
737         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2,target), \
738                       key, focus, num, mark, str, num2, mark2, str2, x, y, comm2)
739 #define CALL14(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2, str2, x, y) \
740         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
741                       key, focus, num, mark, str, num2, mark2, str2, x, y, NULL)
742 #define CALL12(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2, str2) \
743         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
744                       key, focus, num, mark, str, num2, mark2, str2, 0, 0, NULL)
745 #define CALL11(ret, t_type, target, key, comm2a, focus, num, mark, str, num2, mark2) \
746         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
747                       key, focus, num, mark, str, num2, mark2, NULL, 0, 0, NULL)
748 #define CALL10(ret, t_type, target, key, comm2a, focus, num, mark, str, num2) \
749         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
750                       key, focus, num, mark, str, num2, NULL, NULL, 0, 0, NULL)
751 #define CALL9(ret, t_type, target, key, comm2a, focus, num, mark, str) \
752         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
753                       key, focus, num, mark, str, 0, NULL, NULL, 0, 0, NULL)
754 #define CALL8(ret, t_type, target, key, comm2a, focus, num, mark) \
755         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
756                       key, focus, num, mark, NULL, 0, NULL, NULL, 0, 0, NULL)
757 #define CALL7(ret, t_type, target, key, comm2a, focus, num) \
758         do_call_##ret(TYPE_##t_type, CH(T_##t_type, target, comm2a), CH(T_##t_type,comm2a,target), \
759                       key, focus, num, NULL, NULL, 0, NULL, NULL, 0, 0, NULL)
760 #define CALL6(ret, t_type, target, key, comm2a, focus) \
761         do_call_##ret(TYPE_##t_type, CH(T_##t_type,target, comm2a), CH(T_##t_type,comm2a,target), \
762                       key, focus, 0, NULL, NULL, 0, NULL, NULL, 0, 0, NULL)
763
764 #define CALL(ret, t_type, target, key, ...) _doCALL(ret, t_type, target, key, NULL, __VA_ARGS__)
765
766 #define call(key, _focus, ...) CALL(val, focus, _focus, key, _focus, ##__VA_ARGS__)
767 /* comm_call() is only for callbacks
768  * home_comm_call must be used if the focus must be closed already.
769  */
770 #define comm_call(_comm, key, ...) CALL(val, comm, _comm, key, ##__VA_ARGS__)
771 #define home_comm_call(_home, _comm, key, ...) _doCALL(val, comm, _comm, key, _home, __VA_ARGS__)
772
773 #define comm_call_ret(_ret, _comm, key, ...) CALL(_ret, comm, _comm, key, ##__VA_ARGS__)
774 #define home_comm_call_ret(_ret, _comm, key, ...) _doCALL(_ret, comm, _comm, key, _home, ##__VA_ARGS__)
775 /* pane_call() is used when a very specific pane must be informed, rather than
776  * the first responder in a chain of panes.  This mostly used for notifications,
777  * both generic notification, and special things like a child appearing or disappearing
778  * or the pane being closed.
779  */
780 #define pane_call(_pane, key, ...) CALL(val, pane, _pane, key, ##__VA_ARGS__)
781 #define pane_call_ret(_ret, _pane, key, ...) CALL(_ret, pane, _pane, key, ##__VA_ARGS__)
782 #define home_call(_home, key, ...) CALL(val, home, _home, key, ##__VA_ARGS__)
783 #define home_call_comm(_home, key, _focus, comm, ...) _doCALL(val, home, _home, key, comm, _focus, ##__VA_ARGS__)
784 #define home_call_ret(_ret, _home, key, ...) CALL(_ret, home, _home, key, ##__VA_ARGS__)
785 #define call_ret(_ret, key, _focus, ...) CALL(_ret, focus, _focus, key, _focus, ##__VA_ARGS__)
786 #define call_comm(key, _focus, comm, ...) _doCALL(val, focus, _focus, key, comm, _focus, ##__VA_ARGS__)
787
788
789 #define pane_notify(...) VFUNC(NOTIFY, __VA_ARGS__)
790 #define NOTIFY9(not, focus, num, m, str, num2, m2, str2, comm2) \
791         do_pane_notify(NULL, not, focus, num, m, str, num2, m2, str2, comm2)
792 #define NOTIFY8(not, focus, num, m, str, num2, m2, str2) \
793         do_pane_notify(NULL, not, focus, num, m, str, num2, m2, str2, NULL)
794 #define NOTIFY7(not, focus, num, m, str, num2, m2) \
795         do_pane_notify(NULL, not, focus, num, m, str, num2, m2, NULL, NULL)
796 #define NOTIFY6(not, focus, num, m, str, num2) \
797         do_pane_notify(NULL, not, focus, num, m, str, num2, NULL, NULL, NULL)
798 #define NOTIFY5(not, focus, num, m, str) \
799         do_pane_notify(NULL, not, focus, num, m, str, 0, NULL, NULL, NULL)
800 #define NOTIFY4(not, focus, num, m) \
801         do_pane_notify(NULL, not, focus, num, m, NULL, 0, NULL, NULL, NULL)
802 #define NOTIFY3(not, focus, num) \
803         do_pane_notify(NULL, not, focus, num, NULL, NULL, 0, NULL, NULL, NULL)
804 #define NOTIFY2(not, focus) \
805         do_pane_notify(NULL, not, focus, 0, NULL, NULL, 0, NULL, NULL, NULL)
806
807 #define home_pane_notify(...) VFUNC(HOMENOTIFY, __VA_ARGS__)
808 #define HOMENOTIFY10(home, not, focus, num, m, str, num2, m2, str2, comm2) \
809         do_pane_notify(home, not, focus, num, m, str, num2, m2, str2, comm2)
810 #define HOMENOTIFY9(home, not, focus, num, m, str, num2, m2, str2) \
811         do_pane_notify(home, not, focus, num, m, str, num2, m2, str2, NULL)
812 #define HOMENOTIFY8(home, not, focus, num, m, str, num2, m2) \
813         do_pane_notify(home, not, focus, num, m, str, num2, m2, NULL, NULL)
814 #define HOMENOTIFY7(home, not, focus, num, m, str, num2) \
815         do_pane_notify(home, not, focus, num, m, str, num2, NULL, NULL, NULL)
816 #define HOMENOTIFY6(home, not, focus, num, m, str) \
817         do_pane_notify(home, not, focus, num, m, str, 0, NULL, NULL, NULL)
818 #define HOMENOTIFY5(home, not, focus, num, m) \
819         do_pane_notify(home, not, focus, num, m, NULL, 0, NULL, NULL, NULL)
820 #define HOMENOTIFY4(home, not, focus, num) \
821         do_pane_notify(home, not, focus, num, NULL, NULL, 0, NULL, NULL, NULL)
822 #define HOMENOTIFY3(home, not, focus) \
823         do_pane_notify(home, not, focus, 0, NULL, NULL, 0, NULL, NULL, NULL)
824
825 #if !defined(PANE_DATA_TYPE) && !defined(DOC_DATA_TYPE) && !defined(PANE_DATA_PTR_TYPE)
826 /* If you define PANE_DATA_TYPEor DOC_DATA_TYPE, you need to include this yourself */
827 #include "core-pane.h"
828 #endif