1 /* vi:set ts=8 sts=4 sw=4 noet: 2 * 3 * VIM - Vi IMproved by Bram Moolenaar 4 * 5 * Do ":help uganda" in Vim to read copying and usage conditions. 6 * Do ":help credits" in Vim to see a list of people who contributed. 7 */ 8 9 /* 10 * macros.h: macro definitions for often used code 11 * 12 * Macros should be ALL_CAPS. An exception is for where a function is 13 * replaced and an argument is not used more than once. 14 */ 15 16 /* 17 * PBYTE(lp, c) - put byte 'c' at position 'lp' 18 */ 19 #define PBYTE(lp, c) (*(ml_get_buf(curbuf, (lp).lnum, TRUE) + (lp).col) = (c)) 20 21 /* 22 * Position comparisons 23 */ 24 #define LT_POS(a, b) (((a).lnum != (b).lnum) \ 25 ? (a).lnum < (b).lnum \ 26 : (a).col != (b).col \ 27 ? (a).col < (b).col \ 28 : (a).coladd < (b).coladd) 29 #define LT_POSP(a, b) (((a)->lnum != (b)->lnum) \ 30 ? (a)->lnum < (b)->lnum \ 31 : (a)->col != (b)->col \ 32 ? (a)->col < (b)->col \ 33 : (a)->coladd < (b)->coladd) 34 #define EQUAL_POS(a, b) (((a).lnum == (b).lnum) && ((a).col == (b).col) && ((a).coladd == (b).coladd)) 35 #define CLEAR_POS(a) do {(a)->lnum = 0; (a)->col = 0; (a)->coladd = 0;} while (0) 36 #define EMPTY_POS(a) ((a).lnum == 0 && (a).col == 0 && (a).coladd == 0) 37 38 #define LTOREQ_POS(a, b) (LT_POS(a, b) || EQUAL_POS(a, b)) 39 40 /* 41 * VIM_ISWHITE() differs from isspace() because it doesn't include <CR> and 42 * <LF> and the like. 43 */ 44 #define VIM_ISWHITE(x) ((x) == ' ' || (x) == '\t') 45 #define IS_WHITE_OR_NUL(x) ((x) == ' ' || (x) == '\t' || (x) == NUL) 46 47 /* 48 * LINEEMPTY() - return TRUE if the line is empty 49 */ 50 #define LINEEMPTY(p) (*ml_get(p) == NUL) 51 52 /* 53 * BUFEMPTY() - return TRUE if the current buffer is empty 54 */ 55 #define BUFEMPTY() (curbuf->b_ml.ml_line_count == 1 && *ml_get((linenr_T)1) == NUL) 56 57 /* 58 * toupper() and tolower() that use the current locale. 59 * On some systems toupper()/tolower() only work on lower/uppercase 60 * characters, first use islower() or isupper() then. 61 * Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the 62 * range 0 - 255. toupper()/tolower() on some systems can't handle others. 63 * Note: It is often better to use MB_TOLOWER() and MB_TOUPPER(), because many 64 * toupper() and tolower() implementations only work for ASCII. 65 */ 66 #ifdef MSWIN 67 # define TOUPPER_LOC(c) toupper_tab[(c) & 255] 68 # define TOLOWER_LOC(c) tolower_tab[(c) & 255] 69 #else 70 # ifdef BROKEN_TOUPPER 71 # define TOUPPER_LOC(c) (islower(c) ? toupper(c) : (c)) 72 # define TOLOWER_LOC(c) (isupper(c) ? tolower(c) : (c)) 73 # else 74 # define TOUPPER_LOC toupper 75 # define TOLOWER_LOC tolower 76 # endif 77 #endif 78 79 // toupper() and tolower() for ASCII only and ignore the current locale. 80 #ifdef EBCDIC 81 # define TOUPPER_ASC(c) (islower(c) ? toupper(c) : (c)) 82 # define TOLOWER_ASC(c) (isupper(c) ? tolower(c) : (c)) 83 #else 84 # define TOUPPER_ASC(c) (((c) < 'a' || (c) > 'z') ? (c) : (c) - ('a' - 'A')) 85 # define TOLOWER_ASC(c) (((c) < 'A' || (c) > 'Z') ? (c) : (c) + ('a' - 'A')) 86 #endif 87 88 /* 89 * MB_ISLOWER() and MB_ISUPPER() are to be used on multi-byte characters. But 90 * don't use them for negative values! 91 */ 92 #define MB_ISLOWER(c) vim_islower(c) 93 #define MB_ISUPPER(c) vim_isupper(c) 94 #define MB_TOLOWER(c) vim_tolower(c) 95 #define MB_TOUPPER(c) vim_toupper(c) 96 #define MB_CASEFOLD(c) (enc_utf8 ? utf_fold(c) : MB_TOLOWER(c)) 97 98 // Use our own isdigit() replacement, because on MS-Windows isdigit() returns 99 // non-zero for superscript 1. Also avoids that isdigit() crashes for numbers 100 // below 0 and above 255. 101 #define VIM_ISDIGIT(c) ((unsigned)(c) - '0' < 10) 102 103 // Like isalpha() but reject non-ASCII characters. Can't be used with a 104 // special key (negative value). 105 #ifdef EBCDIC 106 # define ASCII_ISALPHA(c) isalpha(c) 107 # define ASCII_ISALNUM(c) isalnum(c) 108 # define ASCII_ISLOWER(c) islower(c) 109 # define ASCII_ISUPPER(c) isupper(c) 110 #else 111 # define ASCII_ISLOWER(c) ((unsigned)(c) - 'a' < 26) 112 # define ASCII_ISUPPER(c) ((unsigned)(c) - 'A' < 26) 113 # define ASCII_ISALPHA(c) (ASCII_ISUPPER(c) || ASCII_ISLOWER(c)) 114 # define ASCII_ISALNUM(c) (ASCII_ISALPHA(c) || VIM_ISDIGIT(c)) 115 #endif 116 117 // Returns empty string if it is NULL. 118 #define EMPTY_IF_NULL(x) ((x) ? (x) : (char_u *)"") 119 120 #ifdef FEAT_LANGMAP 121 /* 122 * Adjust chars in a language according to 'langmap' option. 123 * NOTE that there is no noticeable overhead if 'langmap' is not set. 124 * When set the overhead for characters < 256 is small. 125 * Don't apply 'langmap' if the character comes from the Stuff buffer or from 126 * a mapping and the langnoremap option was set. 127 * The do-while is just to ignore a ';' after the macro. 128 */ 129 # define LANGMAP_ADJUST(c, condition) \ 130 do { \ 131 if (*p_langmap \ 132 && (condition) \ 133 && (p_lrm || (!p_lrm && KeyTyped)) \ 134 && !KeyStuffed \ 135 && (c) >= 0) \ 136 { \ 137 if ((c) < 256) \ 138 c = langmap_mapchar[c]; \ 139 else \ 140 c = langmap_adjust_mb(c); \ 141 } \ 142 } while (0) 143 #else 144 # define LANGMAP_ADJUST(c, condition) // nop 145 #endif 146 147 /* 148 * VIM_ISBREAK() is used very often if 'linebreak' is set, use a macro to make 149 * it work fast. Only works for single byte characters! 150 */ 151 #define VIM_ISBREAK(c) ((c) < 256 && breakat_flags[(char_u)(c)]) 152 153 /* 154 * On VMS file names are different and require a translation. 155 * On the Mac open() has only two arguments. 156 */ 157 #ifdef VMS 158 # define mch_access(n, p) access(vms_fixfilename(n), (p)) 159 // see mch_open() comment 160 # define mch_fopen(n, p) fopen(vms_fixfilename(n), (p)) 161 # define mch_fstat(n, p) fstat((n), (p)) 162 # undef HAVE_LSTAT // VMS does not have lstat() 163 # define mch_stat(n, p) stat(vms_fixfilename(n), (p)) 164 #else 165 # ifndef MSWIN 166 # define mch_access(n, p) access((n), (p)) 167 # endif 168 169 // Use 64-bit fstat function if available. 170 // NOTE: This condition is the same as for the stat_T type. 171 # if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__) 172 # define mch_fstat(n, p) _fstat64((n), (p)) 173 # else 174 # define mch_fstat(n, p) fstat((n), (p)) 175 # endif 176 177 # ifdef MSWIN // has its own mch_stat() function 178 # define mch_stat(n, p) vim_stat((n), (p)) 179 # else 180 # ifdef STAT_IGNORES_SLASH 181 # define mch_stat(n, p) vim_stat((n), (p)) 182 # else 183 # define mch_stat(n, p) stat((n), (p)) 184 # endif 185 # endif 186 #endif 187 188 #ifdef HAVE_LSTAT 189 # define mch_lstat(n, p) lstat((n), (p)) 190 #else 191 # define mch_lstat(n, p) mch_stat((n), (p)) 192 #endif 193 194 #ifdef VMS 195 /* 196 * It is possible to force some record format with: 197 * # define mch_open(n, m, p) open(vms_fixfilename(n), (m), (p)), "rat=cr", "rfm=stmlf", "mrs=0") 198 * but it is not recommended, because it can destroy indexes etc. 199 */ 200 # define mch_open(n, m, p) open(vms_fixfilename(n), (m), (p)) 201 #endif 202 203 // mch_open_rw(): invoke mch_open() with third argument for user R/W. 204 #if defined(UNIX) || defined(VMS) // open in rw------- mode 205 # define mch_open_rw(n, f) mch_open((n), (f), (mode_t)0600) 206 #else 207 # if defined(MSWIN) // open read/write 208 # define mch_open_rw(n, f) mch_open((n), (f), S_IREAD | S_IWRITE) 209 # else 210 # define mch_open_rw(n, f) mch_open((n), (f), 0) 211 # endif 212 #endif 213 214 #ifdef STARTUPTIME 215 # define TIME_MSG(s) do { if (time_fd != NULL) time_msg(s, NULL); } while (0) 216 #else 217 # define TIME_MSG(s) do { /**/ } while (0) 218 #endif 219 220 #define REPLACE_NORMAL(s) (((s) & REPLACE_FLAG) && !((s) & VREPLACE_FLAG)) 221 222 #ifdef FEAT_ARABIC 223 # define ARABIC_CHAR(ch) (((ch) & 0xFF00) == 0x0600) 224 # define UTF_COMPOSINGLIKE(p1, p2) utf_composinglike((p1), (p2)) 225 #else 226 # define UTF_COMPOSINGLIKE(p1, p2) utf_iscomposing(utf_ptr2char(p2)) 227 #endif 228 229 #ifdef FEAT_RIGHTLEFT 230 // Whether to draw the vertical bar on the right side of the cell. 231 # define CURSOR_BAR_RIGHT (curwin->w_p_rl && (!(State & CMDLINE) || cmdmsg_rl)) 232 #endif 233 234 /* 235 * MB_PTR_ADV(): advance a pointer to the next character, taking care of 236 * multi-byte characters if needed. 237 * MB_PTR_BACK(): backup a pointer to the previous character, taking care of 238 * multi-byte characters if needed. 239 * MB_COPY_CHAR(f, t): copy one char from "f" to "t" and advance the pointers. 240 * PTR2CHAR(): get character from pointer. 241 */ 242 // Advance multi-byte pointer, skip over composing chars. 243 #define MB_PTR_ADV(p) p += (*mb_ptr2len)(p) 244 // Advance multi-byte pointer, do not skip over composing chars. 245 #define MB_CPTR_ADV(p) p += enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p) 246 // Backup multi-byte pointer. Only use with "p" > "s" ! 247 #define MB_PTR_BACK(s, p) p -= has_mbyte ? ((*mb_head_off)(s, p - 1) + 1) : 1 248 // get length of multi-byte char, not including composing chars 249 #define MB_CPTR2LEN(p) (enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p)) 250 251 #define MB_COPY_CHAR(f, t) do { if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++; } while (0) 252 #define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p)) 253 #define MB_CHAR2LEN(c) (has_mbyte ? mb_char2len(c) : 1) 254 #define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p)) 255 #define MB_CHAR2BYTES(c, b) do { if (has_mbyte) (b) += (*mb_char2bytes)((c), (b)); else *(b)++ = (c); } while(0) 256 257 #ifdef FEAT_AUTOCHDIR 258 # define DO_AUTOCHDIR do { if (p_acd) do_autochdir(); } while (0) 259 #else 260 # define DO_AUTOCHDIR do { /**/ } while (0) 261 #endif 262 263 #define RESET_BINDING(wp) do { (wp)->w_p_scb = FALSE; (wp)->w_p_crb = FALSE; \ 264 } while (0) 265 266 #ifdef FEAT_DIFF 267 # define PLINES_NOFILL(x) plines_nofill(x) 268 #else 269 # define PLINES_NOFILL(x) plines(x) 270 #endif 271 272 #if defined(FEAT_JOB_CHANNEL) || defined(FEAT_CLIENTSERVER) 273 # define MESSAGE_QUEUE 274 #endif 275 276 #if defined(FEAT_EVAL) && defined(FEAT_FLOAT) 277 # include <float.h> 278 # if defined(HAVE_MATH_H) 279 // for isnan() and isinf() 280 # include <math.h> 281 # endif 282 # ifdef USING_FLOAT_STUFF 283 # ifdef MSWIN 284 # ifndef isnan 285 # define isnan(x) _isnan(x) isinf(double x)286 static __inline int isinf(double x) { return !_finite(x) && !_isnan(x); } 287 # endif 288 # else 289 # ifndef HAVE_ISNAN isnan(double x)290 static inline int isnan(double x) { return x != x; } 291 # endif 292 # ifndef HAVE_ISINF isinf(double x)293 static inline int isinf(double x) { return !isnan(x) && isnan(x - x); } 294 # endif 295 # endif 296 # if !defined(INFINITY) 297 # if defined(DBL_MAX) 298 # ifdef VMS 299 # define INFINITY DBL_MAX 300 # else 301 # define INFINITY (DBL_MAX+DBL_MAX) 302 # endif 303 # else 304 # define INFINITY (1.0 / 0.0) 305 # endif 306 # endif 307 # if !defined(NAN) 308 # define NAN (INFINITY-INFINITY) 309 # endif 310 # if !defined(DBL_EPSILON) 311 # define DBL_EPSILON 2.2204460492503131e-16 312 # endif 313 # endif 314 #endif 315 316 #ifdef FEAT_EVAL 317 # define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j] 318 #endif 319 320 /* 321 * In a hashtab item "hi_key" points to "di_key" in a dictitem. 322 * This avoids adding a pointer to the hashtab item. 323 * DI2HIKEY() converts a dictitem pointer to a hashitem key pointer. 324 * HIKEY2DI() converts a hashitem key pointer to a dictitem pointer. 325 * HI2DI() converts a hashitem pointer to a dictitem pointer. 326 */ 327 #define DI2HIKEY(di) ((di)->di_key) 328 #define HIKEY2DI(p) ((dictitem_T *)(p - offsetof(dictitem_T, di_key))) 329 #define HI2DI(hi) HIKEY2DI((hi)->hi_key) 330 331 /* 332 * Flush control functions. 333 */ 334 #ifdef FEAT_GUI 335 # define mch_enable_flush() gui_enable_flush() 336 # define mch_disable_flush() gui_disable_flush() 337 #else 338 # define mch_enable_flush() 339 # define mch_disable_flush() 340 #endif 341 342 /* 343 * Like vim_free(), and also set the pointer to NULL. 344 */ 345 #define VIM_CLEAR(p) \ 346 do { \ 347 if ((p) != NULL) { \ 348 vim_free(p); \ 349 (p) = NULL; \ 350 } \ 351 } while (0) 352 353 // Whether a command index indicates a user command. 354 #define IS_USER_CMDIDX(idx) ((int)(idx) < 0) 355 356 // Give an error in curwin is a popup window and evaluate to TRUE. 357 #ifdef FEAT_PROP_POPUP 358 # define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0) 359 # define ERROR_IF_POPUP_WINDOW error_if_popup_window(FALSE) 360 # define ERROR_IF_ANY_POPUP_WINDOW error_if_popup_window(TRUE) 361 #else 362 # define WIN_IS_POPUP(wp) 0 363 # define ERROR_IF_POPUP_WINDOW 0 364 # define ERROR_IF_ANY_POPUP_WINDOW 0 365 #endif 366 #if defined(FEAT_PROP_POPUP) && defined(FEAT_TERMINAL) 367 # define ERROR_IF_TERM_POPUP_WINDOW error_if_term_popup_window() 368 #else 369 # define ERROR_IF_TERM_POPUP_WINDOW 0 370 #endif 371 372 373 #ifdef ABORT_ON_INTERNAL_ERROR 374 # define ESTACK_CHECK_DECLARATION int estack_len_before; 375 # define ESTACK_CHECK_SETUP estack_len_before = exestack.ga_len; 376 # define ESTACK_CHECK_NOW if (estack_len_before != exestack.ga_len) \ 377 siemsg("Exestack length expected: %d, actual: %d", estack_len_before, exestack.ga_len); 378 # define CHECK_CURBUF if (curwin != NULL && curwin->w_buffer != curbuf) \ 379 iemsg("curbuf != curwin->w_buffer") 380 #else 381 # define ESTACK_CHECK_DECLARATION 382 # define ESTACK_CHECK_SETUP 383 # define ESTACK_CHECK_NOW 384 # define CHECK_CURBUF 385 #endif 386 387 // Inline the condition for performance. 388 #define CHECK_LIST_MATERIALIZE(l) if ((l)->lv_first == &range_list_item) range_list_materialize(l) 389 390 // Inlined version of ga_grow() with optimized condition that it fails. 391 #define GA_GROW_FAILS(gap, n) unlikely((((gap)->ga_maxlen - (gap)->ga_len < n) ? ga_grow_inner((gap), (n)) : OK) == FAIL) 392 // Inlined version of ga_grow() with optimized condition that it succeeds. 393 #define GA_GROW_OK(gap, n) likely((((gap)->ga_maxlen - (gap)->ga_len < n) ? ga_grow_inner((gap), (n)) : OK) == OK) 394 395 #ifndef MIN 396 # define MIN(a, b) ((a) < (b) ? (a) : (b)) 397 #endif 398 #ifndef MAX 399 # define MAX(a, b) ((a) > (b) ? (a) : (b)) 400 #endif 401 402 // Length of the array. 403 #define ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) 404