]> git.neil.brown.name Git - edlib.git/blob - core-pane.h
display-x11-xcb: don't use Free
[edlib.git] / core-pane.h
1 struct pane {
2         const char              *name; /* For easy discovery in gdb */
3         struct pane             *parent safe;
4         struct list_head        siblings;
5         struct list_head        children;
6         struct pane             *focus;
7         short                   x,y,z;
8         short                   h,w;
9         short                   cx, cy; /* cursor position */
10         short                   abs_z;
11
12         short                   damaged;
13         short                   alloc_size;
14
15         int                     marks;
16         int                     refs;
17         /* timestamp is low bits of time in milliseconds when some
18          * command started.  This makes it easy to check when we
19          * have done too much work.
20          * 0 means nothing is running.
21          * 1 means time is exhausted
22          */
23         unsigned int            timestamp;
24
25         struct pane             *root safe;
26         struct command          *handle;
27         struct attrset          *attrs;
28         struct list_head        notifiers, notifiees;
29         union {
30                 struct doc      doc;
31 #ifdef PANE_DATA_TYPE
32                 PANE_DATA_TYPE  data[1];
33 #else
34                 void            *data safe;
35 #endif
36 #ifdef DOC_DATA_TYPE
37                 DOC_DATA_TYPE   doc_data[1];
38 #endif
39 #ifdef PANE_DATA_TYPE_2
40                 PANE_DATA_TYPE_2 data2[1];
41 #endif
42                 void            *_data safe;
43         };
44 };
45
46 bool pane_too_long(struct pane *p safe, unsigned int msec);
47 void pane_set_time(struct pane *p safe);
48 static inline void pane_end_time(struct pane *p safe)
49 {
50         p->timestamp = 0;
51 }
52
53 static inline struct pane * safe pane_root(struct pane *p safe)
54 {
55         return p->root;
56 }
57
58 static inline void time_starts(struct pane *p safe)
59 {
60         pane_set_time(pane_root(p));
61 }
62
63 static inline void time_ends(struct pane *p safe)
64 {
65         pane_end_time(pane_root(p));
66 }
67
68 static inline bool times_up(struct pane *p safe)
69 {
70         return pane_too_long(pane_root(p), 15000);
71 }
72
73 static inline bool times_up_fast(struct pane *p safe)
74 {
75         return pane_root(p)->timestamp == 1;
76 }
77
78 static inline struct pane *safe pane_leaf(struct pane *p safe)
79 {
80         struct pane *f;
81
82         while ((f = p->focus) != NULL)
83                 p = f;
84         return p;
85 }
86
87 static inline struct pane *pane_get(struct pane *p safe) safe
88 {
89         p->refs += 1;
90         return p;
91 }
92 static inline void pane_put(struct pane *p safe)
93 {
94         p->refs -= 1;
95         pane_free(p);
96 }
97
98 static inline int do_call_val(enum target_type type, struct pane *home,
99                               struct command *comm2a,
100                               const char *key safe, struct pane *focus safe,
101                               int num,  struct mark *m,  const char *str,
102                               int num2, struct mark *m2, const char *str2,
103                               int x, int y, struct command *comm2b)
104 {
105         struct cmd_info ci = {.key = key, .focus = focus, .home = focus,
106                               .num = num, .mark = m, .str = str,
107                               .num2 = num2, .mark2 = m2, .str2 = str2,
108                               .comm2 = comm2a ?: comm2b, .x = x, .y = y,
109                               .comm = safe_cast NULL};
110         int ret;
111
112         if ((type == TYPE_pane || type == TYPE_home) && !home)
113                 return 0;
114         if (type == TYPE_comm && !comm2a)
115                 return 0;
116         ASSERT(!comm2a || !comm2b || comm2a == comm2b || type == TYPE_comm);
117
118         switch(type) {
119         default:
120         case TYPE_home:
121                 if (home)
122                         ci.home = home;
123                 /* fall-through */
124         case TYPE_focus:
125                 ret = key_handle(&ci);
126                 break;
127         case TYPE_pane:
128                 if (!home->handle || (home->damaged & DAMAGED_DEAD))
129                         return Efail;
130                 if (times_up_fast(focus))
131                         return Efail;
132                 if (home)
133                         ci.home = home;
134                 if ((home->damaged & DAMAGED_CLOSED) &&
135                     strncmp(ci.key, "Close", 5) != 0 &&
136                     strcmp(ci.key, "Notify:Close") != 0 &&
137                     strcmp(ci.key, "Free") != 0)
138                         /* This pane cannot accept anything but
139                          * "Close" or "Close:mark" or "Free"
140                          */
141                         return Efail;
142                 ci.comm = home->handle;
143                 ret = ci.comm->func(&ci);
144                 break;
145         case TYPE_comm:
146                 if (times_up_fast(focus))
147                         return Efail;
148                 if (home)
149                         ci.home = home;
150                 if (ci.home->damaged & DAMAGED_CLOSED)
151                         return Efail;
152                 ci.comm = comm2a;
153                 ci.comm2 = comm2b;
154                 ret = ci.comm->func(&ci);
155                 break;
156         }
157         return ret;
158 }