1 | #ifndef NVIM_MACROS_H |
2 | #define NVIM_MACROS_H |
3 | |
4 | // EXTERN is only defined in main.c. That's where global variables are |
5 | // actually defined and initialized. |
6 | #ifndef EXTERN |
7 | # define EXTERN extern |
8 | # define INIT(...) |
9 | #else |
10 | # ifndef INIT |
11 | # define INIT(...) __VA_ARGS__ |
12 | # define COMMA , |
13 | # endif |
14 | #endif |
15 | |
16 | #ifndef MIN |
17 | # define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) |
18 | #endif |
19 | #ifndef MAX |
20 | # define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) |
21 | #endif |
22 | |
23 | /// String with length |
24 | /// |
25 | /// For use in functions which accept (char *s, size_t len) pair in arguments. |
26 | /// |
27 | /// @param[in] s Static string. |
28 | /// |
29 | /// @return `s, sizeof(s) - 1` |
30 | #define S_LEN(s) (s), (sizeof(s) - 1) |
31 | |
32 | /// LINEEMPTY() - return TRUE if the line is empty |
33 | #define LINEEMPTY(p) (*ml_get(p) == NUL) |
34 | |
35 | /// BUFEMPTY() - return TRUE if the current buffer is empty |
36 | #define BUFEMPTY() (curbuf->b_ml.ml_line_count == 1 && *ml_get((linenr_T)1) == \ |
37 | NUL) |
38 | |
39 | /* |
40 | * toupper() and tolower() that use the current locale. |
41 | * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the |
42 | * range 0 - 255. toupper()/tolower() on some systems can't handle others. |
43 | * Note: It is often better to use mb_tolower() and mb_toupper(), because many |
44 | * toupper() and tolower() implementations only work for ASCII. |
45 | */ |
46 | #define TOUPPER_LOC toupper |
47 | #define TOLOWER_LOC tolower |
48 | |
49 | /* toupper() and tolower() for ASCII only and ignore the current locale. */ |
50 | # define TOUPPER_ASC(c) (((c) < 'a' || (c) > 'z') ? (c) : (c) - ('a' - 'A')) |
51 | # define TOLOWER_ASC(c) (((c) < 'A' || (c) > 'Z') ? (c) : (c) + ('a' - 'A')) |
52 | |
53 | /* Like isalpha() but reject non-ASCII characters. Can't be used with a |
54 | * special key (negative value). */ |
55 | # define ASCII_ISLOWER(c) ((unsigned)(c) >= 'a' && (unsigned)(c) <= 'z') |
56 | # define ASCII_ISUPPER(c) ((unsigned)(c) >= 'A' && (unsigned)(c) <= 'Z') |
57 | # define ASCII_ISALPHA(c) (ASCII_ISUPPER(c) || ASCII_ISLOWER(c)) |
58 | # define ASCII_ISALNUM(c) (ASCII_ISALPHA(c) || ascii_isdigit(c)) |
59 | |
60 | /* Returns empty string if it is NULL. */ |
61 | #define EMPTY_IF_NULL(x) ((x) ? (x) : (char_u *)"") |
62 | |
63 | /* |
64 | * Adjust chars in a language according to 'langmap' option. |
65 | * NOTE that there is no noticeable overhead if 'langmap' is not set. |
66 | * When set the overhead for characters < 256 is small. |
67 | * Don't apply 'langmap' if the character comes from the Stuff buffer or from a |
68 | * mapping and the langnoremap option was set. |
69 | * The do-while is just to ignore a ';' after the macro. |
70 | */ |
71 | # define LANGMAP_ADJUST(c, condition) \ |
72 | do { \ |
73 | if (*p_langmap \ |
74 | && (condition) \ |
75 | && (p_lrm || (vgetc_busy ? typebuf_maplen() == 0 : KeyTyped)) \ |
76 | && !KeyStuffed \ |
77 | && (c) >= 0) \ |
78 | { \ |
79 | if ((c) < 256) \ |
80 | c = langmap_mapchar[c]; \ |
81 | else \ |
82 | c = langmap_adjust_mb(c); \ |
83 | } \ |
84 | } while (0) |
85 | |
86 | #define WRITEBIN "wb" /* no CR-LF translation */ |
87 | #define READBIN "rb" |
88 | #define APPENDBIN "ab" |
89 | |
90 | /* mch_open_rw(): invoke os_open() with third argument for user R/W. */ |
91 | #if defined(UNIX) /* open in rw------- mode */ |
92 | # define mch_open_rw(n, f) os_open((n), (f), (mode_t)0600) |
93 | #elif defined(WIN32) |
94 | # define mch_open_rw(n, f) os_open((n), (f), S_IREAD | S_IWRITE) |
95 | #else |
96 | # define mch_open_rw(n, f) os_open((n), (f), 0) |
97 | #endif |
98 | |
99 | # define REPLACE_NORMAL(s) (((s) & REPLACE_FLAG) && !((s) & VREPLACE_FLAG)) |
100 | |
101 | # define UTF_COMPOSINGLIKE(p1, p2) utf_composinglike((p1), (p2)) |
102 | |
103 | /* Whether to draw the vertical bar on the right side of the cell. */ |
104 | # define CURSOR_BAR_RIGHT (curwin->w_p_rl && (!(State & CMDLINE) || cmdmsg_rl)) |
105 | |
106 | // MB_PTR_ADV(): advance a pointer to the next character, taking care of |
107 | // multi-byte characters if needed. |
108 | // MB_PTR_BACK(): backup a pointer to the previous character, taking care of |
109 | // multi-byte characters if needed. |
110 | // MB_COPY_CHAR(f, t): copy one char from "f" to "t" and advance the pointers. |
111 | // PTR2CHAR(): get character from pointer. |
112 | |
113 | // Get the length of the character p points to, including composing chars. |
114 | # define MB_PTR2LEN(p) mb_ptr2len(p) |
115 | // Advance multi-byte pointer, skip over composing chars. |
116 | # define MB_PTR_ADV(p) (p += mb_ptr2len((char_u *)p)) |
117 | // Advance multi-byte pointer, do not skip over composing chars. |
118 | # define MB_CPTR_ADV(p) (p += utf_ptr2len(p)) |
119 | // Backup multi-byte pointer. Only use with "p" > "s" ! |
120 | # define MB_PTR_BACK(s, p) \ |
121 | (p -= utf_head_off((char_u *)s, (char_u *)p - 1) + 1) |
122 | // get length of multi-byte char, not including composing chars |
123 | # define MB_CPTR2LEN(p) utf_ptr2len(p) |
124 | |
125 | # define MB_COPY_CHAR(f, t) mb_copy_char((const char_u **)(&f), &t); |
126 | |
127 | # define MB_CHARLEN(p) mb_charlen(p) |
128 | # define MB_CHAR2LEN(c) mb_char2len(c) |
129 | # define PTR2CHAR(p) utf_ptr2char(p) |
130 | |
131 | # define RESET_BINDING(wp) \ |
132 | do { \ |
133 | (wp)->w_p_scb = false; \ |
134 | (wp)->w_p_crb = false; \ |
135 | } while (0) |
136 | |
137 | /// Calculate the length of a C array |
138 | /// |
139 | /// This should be called with a real array. Calling this with a pointer is an |
140 | /// error. A mechanism to detect many (though not all) of those errors at |
141 | /// compile time is implemented. It works by the second division producing |
142 | /// a division by zero in those cases (-Wdiv-by-zero in GCC). |
143 | #define ARRAY_SIZE(arr) \ |
144 | ((sizeof(arr)/sizeof((arr)[0])) \ |
145 | / ((size_t)(!(sizeof(arr) % sizeof((arr)[0]))))) |
146 | |
147 | /// Get last array entry |
148 | /// |
149 | /// This should be called with a real array. Calling this with a pointer is an |
150 | /// error. |
151 | #define ARRAY_LAST_ENTRY(arr) (arr)[ARRAY_SIZE(arr) - 1] |
152 | |
153 | // Duplicated in os/win_defs.h to avoid include-order sensitivity. |
154 | #define RGB_(r, g, b) ((r << 16) | (g << 8) | b) |
155 | |
156 | #define STR_(x) #x |
157 | #define STR(x) STR_(x) |
158 | |
159 | #ifndef __has_attribute |
160 | # define NVIM_HAS_ATTRIBUTE(x) 0 |
161 | #elif defined(__clang__) && __clang__ == 1 \ |
162 | && (__clang_major__ < 3 || (__clang_major__ == 3 && __clang_minor__ <= 5)) |
163 | // Starting in Clang 3.6, __has_attribute was fixed to only report true for |
164 | // GNU-style attributes. Prior to that, it reported true if _any_ backend |
165 | // supported the attribute. |
166 | # define NVIM_HAS_ATTRIBUTE(x) 0 |
167 | #else |
168 | # define NVIM_HAS_ATTRIBUTE __has_attribute |
169 | #endif |
170 | |
171 | #if NVIM_HAS_ATTRIBUTE(fallthrough) \ |
172 | && (!defined(__apple_build_version__) || __apple_build_version__ >= 7000000) |
173 | # define FALLTHROUGH __attribute__((fallthrough)) |
174 | #else |
175 | # define FALLTHROUGH |
176 | #endif |
177 | |
178 | // -V:STRUCT_CAST:641 |
179 | |
180 | /// Change type of structure pointers: cast `struct a *` to `struct b *` |
181 | /// |
182 | /// Used to silence PVS errors. |
183 | /// |
184 | /// @param Type Structure to cast to. |
185 | /// @param obj Object to cast. |
186 | /// |
187 | /// @return ((Type *)obj). |
188 | #define STRUCT_CAST(Type, obj) ((Type *)(obj)) |
189 | |
190 | // Type of uv_buf_t.len is platform-dependent. |
191 | // Related: https://github.com/libuv/libuv/pull/1236 |
192 | #if defined(WIN32) |
193 | # define UV_BUF_LEN(x) (ULONG)(x) |
194 | #else |
195 | # define UV_BUF_LEN(x) (x) |
196 | #endif |
197 | |
198 | // Type of read()/write() `count` param is platform-dependent. |
199 | #if defined(WIN32) |
200 | # define IO_COUNT(x) (unsigned)(x) |
201 | #else |
202 | # define IO_COUNT(x) (x) |
203 | #endif |
204 | |
205 | /// |
206 | /// PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES |
207 | /// |
208 | #if defined(__clang__) && __clang__ == 1 |
209 | # define PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES \ |
210 | _Pragma("clang diagnostic push") \ |
211 | _Pragma("clang diagnostic ignored \"-Wmissing-prototypes\"") |
212 | # define PRAGMA_DIAG_POP \ |
213 | _Pragma("clang diagnostic pop") |
214 | #elif defined(__GNUC__) |
215 | # define PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES \ |
216 | _Pragma("GCC diagnostic push") \ |
217 | _Pragma("GCC diagnostic ignored \"-Wmissing-prototypes\"") |
218 | # define PRAGMA_DIAG_POP \ |
219 | _Pragma("GCC diagnostic pop") |
220 | #else |
221 | # define PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES |
222 | # define PRAGMA_DIAG_POP |
223 | #endif |
224 | |
225 | |
226 | #endif // NVIM_MACROS_H |
227 | |