void record_delete (ptrdiff_t beg, Lisp_Object string, bool record_markers) { Lisp_Object sbeg; if (EQ (BVAR (current_buffer, undo_list), Qt)) return; if (PT == beg + SCHARS (string)) { XSETINT (sbeg, -beg); record_point (PT); } else { XSETFASTINT (sbeg, beg); record_point (beg); } /* primitive-undo assumes marker adjustments are recorded immediately before the deletion is recorded. See bug 16818 discussion. */ if (record_markers) record_marker_adjustments (beg, beg + SCHARS (string)); bset_undo_list (current_buffer, Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list))); }
void record_property_change (ptrdiff_t beg, ptrdiff_t length, Lisp_Object prop, Lisp_Object value, Lisp_Object buffer) { Lisp_Object lbeg, lend, entry; struct buffer *obuf = current_buffer, *buf = XBUFFER (buffer); if (EQ (BVAR (buf, undo_list), Qt)) return; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); /* Switch temporarily to the buffer that was changed. */ set_buffer_internal (buf); run_undoable_change (); if (MODIFF <= SAVE_MODIFF) record_first_change (); XSETINT (lbeg, beg); XSETINT (lend, beg + length); entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend)))); bset_undo_list (current_buffer, Fcons (entry, BVAR (current_buffer, undo_list))); /* Reset the buffer */ set_buffer_internal (obuf); }
static void record_point (ptrdiff_t pt) { bool at_boundary; /* Don't record position of pt when undo_inhibit_record_point holds. */ if (undo_inhibit_record_point) return; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); run_undoable_change (); at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) || NILP (XCAR (BVAR (current_buffer, undo_list))); if (MODIFF <= SAVE_MODIFF) record_first_change (); /* If we are just after an undo boundary, and point wasn't at start of deleted range, record where it was. */ if (at_boundary && current_buffer == last_boundary_buffer && last_boundary_position != pt) bset_undo_list (current_buffer, Fcons (make_number (last_boundary_position), BVAR (current_buffer, undo_list))); }
void record_insert (ptrdiff_t beg, ptrdiff_t length) { Lisp_Object lbeg, lend; if (EQ (BVAR (current_buffer, undo_list), Qt)) return; record_point (beg); /* If this is following another insertion and consecutive with it in the buffer, combine the two. */ if (CONSP (BVAR (current_buffer, undo_list))) { Lisp_Object elt; elt = XCAR (BVAR (current_buffer, undo_list)); if (CONSP (elt) && INTEGERP (XCAR (elt)) && INTEGERP (XCDR (elt)) && XINT (XCDR (elt)) == beg) { XSETCDR (elt, make_number (beg + length)); return; } } XSETFASTINT (lbeg, beg); XSETINT (lend, beg + length); bset_undo_list (current_buffer, Fcons (Fcons (lbeg, lend), BVAR (current_buffer, undo_list))); }
Lisp_Object encode_current_directory (void) { Lisp_Object dir; dir = BVAR (current_buffer, directory); dir = Funhandled_file_name_directory (dir); /* If the file name handler says that dir is unreachable, use a sensible default. */ if (NILP (dir)) dir = build_string ("~"); dir = expand_and_dir_to_file (dir, Qnil); if (NILP (Ffile_accessible_directory_p (dir))) report_file_error ("Setting current directory", BVAR (current_buffer, directory)); /* Remove "/:" from DIR and encode it. */ dir = ENCODE_FILE (remove_slash_colon (dir)); if (! file_accessible_directory_p (dir)) report_file_error ("Setting current directory", BVAR (current_buffer, directory)); return dir; }
/* Record point, if necessary, as it was at beginning of this command. BEG is the position of point that will naturally occur as a result of the undo record that will be added just after this command terminates. */ static void record_point (ptrdiff_t beg) { /* Don't record position of pt when undo_inhibit_record_point holds. */ if (undo_inhibit_record_point) return; bool at_boundary; /* Check whether we are at a boundary now, in case we record the first change. FIXME: This check is currently dependent on being called before record_first_change, but could be made not to by ignoring timestamp undo entries */ at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) || NILP (XCAR (BVAR (current_buffer, undo_list))); /* If this is the first change since save, then record this.*/ if (MODIFF <= SAVE_MODIFF) record_first_change (); /* We may need to record point if we are immediately after a boundary, so that this will be restored correctly after undo. We do not need to do this if point is at the start of a change region since it will be restored there anyway, and we must not do this if the buffer has changed since the last command, since the value of point that we have will be for that buffer, not this.*/ if (at_boundary && point_before_last_command_or_undo != beg && buffer_before_last_command_or_undo == current_buffer ) bset_undo_list (current_buffer, Fcons (make_number (point_before_last_command_or_undo), BVAR (current_buffer, undo_list))); }
static void record_point (EMACS_INT pt) { int at_boundary; /* Don't record position of pt when undo_inhibit_record_point holds. */ if (undo_inhibit_record_point) return; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); if ((current_buffer != last_undo_buffer) /* Don't call Fundo_boundary for the first change. Otherwise we risk overwriting last_boundary_position in Fundo_boundary with PT of the current buffer and as a consequence not insert an undo boundary because last_boundary_position will equal pt in the test at the end of the present function (Bug#731). */ && (MODIFF > SAVE_MODIFF)) Fundo_boundary (); last_undo_buffer = current_buffer; if (CONSP (BVAR (current_buffer, undo_list))) { /* Set AT_BOUNDARY to 1 only when we have nothing other than marker adjustment before undo boundary. */ Lisp_Object tail = BVAR (current_buffer, undo_list), elt; while (1) { if (NILP (tail)) elt = Qnil; else elt = XCAR (tail); if (NILP (elt) || ! (CONSP (elt) && MARKERP (XCAR (elt)))) break; tail = XCDR (tail); } at_boundary = NILP (elt); } else at_boundary = 1; if (MODIFF <= SAVE_MODIFF) record_first_change (); /* If we are just after an undo boundary, and point wasn't at start of deleted range, record where it was. */ if (at_boundary && current_buffer == last_boundary_buffer && last_boundary_position != pt) BVAR (current_buffer, undo_list) = Fcons (make_number (last_boundary_position), BVAR (current_buffer, undo_list)); }
void record_first_change (void) { struct buffer *base_buffer = current_buffer; if (EQ (BVAR (current_buffer, undo_list), Qt)) return; if (base_buffer->base_buffer) base_buffer = base_buffer->base_buffer; bset_undo_list (current_buffer, Fcons (Fcons (Qt, Fvisited_file_modtime ()), BVAR (current_buffer, undo_list))); }
void unlock_all_files (void) { register Lisp_Object tail; register struct buffer *b; for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail)) { b = XBUFFER (XCDR (XCAR (tail))); if (STRINGP (BVAR (b, file_truename)) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) { unlock_file (BVAR (b, file_truename)); } } }
void record_marker_adjustment (Lisp_Object marker, EMACS_INT adjustment) { if (EQ (BVAR (current_buffer, undo_list), Qt)) return; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); if (current_buffer != last_undo_buffer) Fundo_boundary (); last_undo_buffer = current_buffer; BVAR (current_buffer, undo_list) = Fcons (Fcons (marker, make_number (adjustment)), BVAR (current_buffer, undo_list)); }
void record_first_change (void) { struct buffer *base_buffer = current_buffer; if (EQ (BVAR (current_buffer, undo_list), Qt)) return; if (current_buffer != last_undo_buffer) Fundo_boundary (); last_undo_buffer = current_buffer; if (base_buffer->base_buffer) base_buffer = base_buffer->base_buffer; BVAR (current_buffer, undo_list) = Fcons (Fcons (Qt, INTEGER_TO_CONS (base_buffer->modtime)), BVAR (current_buffer, undo_list)); }
/* Record point as it was at beginning of this command. PT is the position of point that will naturally occur as a result of the undo record that will be added just after this command terminates. */ static void record_point (ptrdiff_t pt) { /* Don't record position of pt when undo_inhibit_record_point holds. */ if (undo_inhibit_record_point) return; bool at_boundary; at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) || NILP (XCAR (BVAR (current_buffer, undo_list))); prepare_record (); /* If we are just after an undo boundary, and point wasn't at start of deleted range, record where it was. */ if (at_boundary) bset_undo_list (current_buffer, Fcons (make_number (pt), BVAR (current_buffer, undo_list))); }
void record_property_change (ptrdiff_t beg, ptrdiff_t length, Lisp_Object prop, Lisp_Object value, Lisp_Object buffer) { Lisp_Object lbeg, lend, entry; struct buffer *buf = XBUFFER (buffer); if (EQ (BVAR (buf, undo_list), Qt)) return; prepare_record(); if (MODIFF <= SAVE_MODIFF) record_first_change (); XSETINT (lbeg, beg); XSETINT (lend, beg + length); entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend)))); bset_undo_list (current_buffer, Fcons (entry, BVAR (current_buffer, undo_list))); }
void record_delete (EMACS_INT beg, Lisp_Object string) { Lisp_Object sbeg; if (EQ (BVAR (current_buffer, undo_list), Qt)) return; if (PT == beg + SCHARS (string)) { XSETINT (sbeg, -beg); record_point (PT); } else { XSETFASTINT (sbeg, beg); record_point (beg); } BVAR (current_buffer, undo_list) = Fcons (Fcons (string, sbeg), BVAR (current_buffer, undo_list)); }
static int get_logical_cursor_bitmap (struct window *w, Lisp_Object cursor) { Lisp_Object cmap, bm = Qnil; if ((cmap = BVAR (XBUFFER (w->buffer), fringe_cursor_alist)), !NILP (cmap)) { bm = Fassq (cursor, cmap); if (CONSP (bm)) { if ((bm = XCDR (bm)), NILP (bm)) return NO_FRINGE_BITMAP; return lookup_fringe_bitmap (bm); } } if (EQ (cmap, BVAR (&buffer_defaults, fringe_cursor_alist))) return NO_FRINGE_BITMAP; bm = Fassq (cursor, BVAR (&buffer_defaults, fringe_cursor_alist)); if (!CONSP (bm) || ((bm = XCDR (bm)), NILP (bm))) return NO_FRINGE_BITMAP; return lookup_fringe_bitmap (bm); }
static void record_point (ptrdiff_t pt) { bool at_boundary; /* Don't record position of pt when undo_inhibit_record_point holds. */ if (undo_inhibit_record_point) return; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); if ((current_buffer != last_undo_buffer) /* Don't call Fundo_boundary for the first change. Otherwise we risk overwriting last_boundary_position in Fundo_boundary with PT of the current buffer and as a consequence not insert an undo boundary because last_boundary_position will equal pt in the test at the end of the present function (Bug#731). */ && (MODIFF > SAVE_MODIFF)) Fundo_boundary (); last_undo_buffer = current_buffer; at_boundary = ! CONSP (BVAR (current_buffer, undo_list)) || NILP (XCAR (BVAR (current_buffer, undo_list))); if (MODIFF <= SAVE_MODIFF) record_first_change (); /* If we are just after an undo boundary, and point wasn't at start of deleted range, record where it was. */ if (at_boundary && current_buffer == last_boundary_buffer && last_boundary_position != pt) bset_undo_list (current_buffer, Fcons (make_number (last_boundary_position), BVAR (current_buffer, undo_list))); }
void record_property_change (EMACS_INT beg, EMACS_INT length, Lisp_Object prop, Lisp_Object value, Lisp_Object buffer) { Lisp_Object lbeg, lend, entry; struct buffer *obuf = current_buffer, *buf = XBUFFER (buffer); int boundary = 0; if (EQ (BVAR (buf, undo_list), Qt)) return; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); if (buf != last_undo_buffer) boundary = 1; last_undo_buffer = buf; /* Switch temporarily to the buffer that was changed. */ current_buffer = buf; if (boundary) Fundo_boundary (); if (MODIFF <= SAVE_MODIFF) record_first_change (); XSETINT (lbeg, beg); XSETINT (lend, beg + length); entry = Fcons (Qnil, Fcons (prop, Fcons (value, Fcons (lbeg, lend)))); BVAR (current_buffer, undo_list) = Fcons (entry, BVAR (current_buffer, undo_list)); current_buffer = obuf; }
static void record_marker_adjustments (ptrdiff_t from, ptrdiff_t to) { Lisp_Object marker; register struct Lisp_Marker *m; register ptrdiff_t charpos, adjustment; /* Allocate a cons cell to be the undo boundary after this command. */ if (NILP (pending_boundary)) pending_boundary = Fcons (Qnil, Qnil); if (current_buffer != last_undo_buffer) Fundo_boundary (); last_undo_buffer = current_buffer; for (m = BUF_MARKERS (current_buffer); m; m = m->next) { charpos = m->charpos; eassert (charpos <= Z); if (from <= charpos && charpos <= to) { /* insertion_type nil markers will end up at the beginning of the re-inserted text after undoing a deletion, and must be adjusted to move them to the correct place. insertion_type t markers will automatically move forward upon re-inserting the deleted text, so we have to arrange for them to move backward to the correct position. */ adjustment = (m->insertion_type ? to : from) - charpos; if (adjustment) { XSETMISC (marker, m); bset_undo_list (current_buffer, Fcons (Fcons (marker, make_number (adjustment)), BVAR (current_buffer, undo_list))); } } } }
static void byte_char_debug_check (struct buffer *b, ptrdiff_t charpos, ptrdiff_t bytepos) { ptrdiff_t nchars; if (NILP (BVAR (b, enable_multibyte_characters))) return; if (bytepos > BUF_GPT_BYTE (b)) nchars = multibyte_chars_in_text (BUF_BEG_ADDR (b), BUF_GPT_BYTE (b) - BUF_BEG_BYTE (b)) + multibyte_chars_in_text (BUF_GAP_END_ADDR (b), bytepos - BUF_GPT_BYTE (b)); else nchars = multibyte_chars_in_text (BUF_BEG_ADDR (b), bytepos - BUF_BEG_BYTE (b)); if (charpos - 1 != nchars) emacs_abort (); }
static Lisp_Object casify_object (enum case_action flag, Lisp_Object obj) { register int c, c1; register int inword = flag == CASE_DOWN; /* If the case table is flagged as modified, rescan it. */ if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1])) Fset_case_table (BVAR (current_buffer, downcase_table)); if (INTEGERP (obj)) { int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER | CHAR_SHIFT | CHAR_CTL | CHAR_META); int flags = XINT (obj) & flagbits; int multibyte = ! NILP (BVAR (current_buffer, enable_multibyte_characters)); /* If the character has higher bits set above the flags, return it unchanged. It is not a real character. */ if ((unsigned) XFASTINT (obj) > (unsigned) flagbits) return obj; c1 = XFASTINT (obj) & ~flagbits; /* FIXME: Even if enable-multibyte-characters is nil, we may manipulate multibyte chars. This means we have a bug for latin-1 chars since when we receive an int 128-255 we can't tell whether it's an eight-bit byte or a latin-1 char. */ if (c1 >= 256) multibyte = 1; if (! multibyte) MAKE_CHAR_MULTIBYTE (c1); c = downcase (c1); if (inword) XSETFASTINT (obj, c | flags); else if (c == (XFASTINT (obj) & ~flagbits)) { if (! inword) c = upcase1 (c1); if (! multibyte) MAKE_CHAR_UNIBYTE (c); XSETFASTINT (obj, c | flags); } return obj; } if (!STRINGP (obj)) wrong_type_argument (Qchar_or_string_p, obj); else if (!STRING_MULTIBYTE (obj)) { EMACS_INT i; EMACS_INT size = SCHARS (obj); obj = Fcopy_sequence (obj); for (i = 0; i < size; i++) { c = SREF (obj, i); MAKE_CHAR_MULTIBYTE (c); c1 = c; if (inword && flag != CASE_CAPITALIZE_UP) c = downcase (c); else if (!uppercasep (c) && (!inword || flag != CASE_CAPITALIZE_UP)) c = upcase1 (c1); if ((int) flag >= (int) CASE_CAPITALIZE) inword = (SYNTAX (c) == Sword); if (c != c1) { MAKE_CHAR_UNIBYTE (c); /* If the char can't be converted to a valid byte, just don't change it. */ if (c >= 0 && c < 256) SSET (obj, i, c); } } return obj; } else { EMACS_INT i, i_byte, size = SCHARS (obj); int len; USE_SAFE_ALLOCA; unsigned char *dst, *o; /* Over-allocate by 12%: this is a minor overhead, but should be sufficient in 99.999% of the cases to avoid a reallocation. */ EMACS_INT o_size = SBYTES (obj) + SBYTES (obj) / 8 + MAX_MULTIBYTE_LENGTH; SAFE_ALLOCA (dst, void *, o_size); o = dst; for (i = i_byte = 0; i < size; i++, i_byte += len) { if ((o - dst) + MAX_MULTIBYTE_LENGTH > o_size) { /* Not enough space for the next char: grow the destination. */ unsigned char *old_dst = dst; o_size += o_size; /* Probably overkill, but extremely rare. */ SAFE_ALLOCA (dst, void *, o_size); memcpy (dst, old_dst, o - old_dst); o = dst + (o - old_dst); } c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len); if (inword && flag != CASE_CAPITALIZE_UP) c = downcase (c); else if (!uppercasep (c) && (!inword || flag != CASE_CAPITALIZE_UP)) c = upcase1 (c); if ((int) flag >= (int) CASE_CAPITALIZE) inword = (SYNTAX (c) == Sword); o += CHAR_STRING (c, o); } eassert (o - dst <= o_size); obj = make_multibyte_string ((char *) dst, size, o - dst); SAFE_FREE (); return obj; } }
Lisp_Object directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, bool attrs, Lisp_Object id_format) { DIR *d; int fd; ptrdiff_t directory_nbytes; Lisp_Object list, dirfilename, encoded_directory; struct re_pattern_buffer *bufp = NULL; bool needsep = 0; ptrdiff_t count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; struct dirent *dp; #ifdef WINDOWSNT Lisp_Object w32_save = Qnil; #endif /* Don't let the compiler optimize away all copies of DIRECTORY, which would break GC; see Bug#16986. Although this is required only in the common case where GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS, it shouldn't break anything in the other cases. */ Lisp_Object volatile directory_volatile = directory; /* Because of file name handlers, these functions might call Ffuncall, and cause a GC. */ list = encoded_directory = dirfilename = Qnil; GCPRO5 (match, directory, list, dirfilename, encoded_directory); dirfilename = Fdirectory_file_name (directory); if (!NILP (match)) { CHECK_STRING (match); /* MATCH might be a flawed regular expression. Rather than catching and signaling our own errors, we just call compile_pattern to do the work for us. */ /* Pass 1 for the MULTIBYTE arg because we do make multibyte strings if the contents warrant. */ # ifdef WINDOWSNT /* Windows users want case-insensitive wildcards. */ bufp = compile_pattern (match, 0, BVAR (&buffer_defaults, case_canon_table), 0, 1); # else /* !WINDOWSNT */ bufp = compile_pattern (match, 0, Qnil, 0, 1); # endif /* !WINDOWSNT */ } /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run run_pre_post_conversion_on_str which calls Lisp directly and indirectly. */ if (STRING_MULTIBYTE (dirfilename)) dirfilename = ENCODE_FILE (dirfilename); encoded_directory = (STRING_MULTIBYTE (directory) ? ENCODE_FILE (directory) : directory); /* Now *bufp is the compiled form of MATCH; don't call anything which might compile a new regexp until we're done with the loop! */ d = open_directory (SSDATA (dirfilename), &fd); if (d == NULL) report_file_error ("Opening directory", directory); /* Unfortunately, we can now invoke expand-file-name and file-attributes on filenames, both of which can throw, so we must do a proper unwind-protect. */ record_unwind_protect_ptr (directory_files_internal_unwind, d); #ifdef WINDOWSNT if (attrs) { extern int is_slow_fs (const char *); /* Do this only once to avoid doing it (in w32.c:stat) for each file in the directory, when we call Ffile_attributes below. */ record_unwind_protect (directory_files_internal_w32_unwind, Vw32_get_true_file_attributes); w32_save = Vw32_get_true_file_attributes; if (EQ (Vw32_get_true_file_attributes, Qlocal)) { /* w32.c:stat will notice these bindings and avoid calling GetDriveType for each file. */ if (is_slow_fs (SDATA (dirfilename))) Vw32_get_true_file_attributes = Qnil; else Vw32_get_true_file_attributes = Qt; } } #endif directory_nbytes = SBYTES (directory); re_match_object = Qt; /* Decide whether we need to add a directory separator. */ if (directory_nbytes == 0 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1))) needsep = 1; /* Loop reading blocks until EOF or error. */ for (;;) { ptrdiff_t len; bool wanted = 0; Lisp_Object name, finalname; struct gcpro gcpro1, gcpro2; errno = 0; dp = readdir (d); if (!dp) { if (errno == EAGAIN || errno == EINTR) { QUIT; continue; } break; } len = dirent_namelen (dp); name = finalname = make_unibyte_string (dp->d_name, len); GCPRO2 (finalname, name); /* Note: DECODE_FILE can GC; it should protect its argument, though. */ name = DECODE_FILE (name); len = SBYTES (name); /* Now that we have unwind_protect in place, we might as well allow matching to be interrupted. */ immediate_quit = 1; QUIT; if (NILP (match) || re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0) wanted = 1; immediate_quit = 0; if (wanted) { if (!NILP (full)) { Lisp_Object fullname; ptrdiff_t nbytes = len + directory_nbytes + needsep; ptrdiff_t nchars; fullname = make_uninit_multibyte_string (nbytes, nbytes); memcpy (SDATA (fullname), SDATA (directory), directory_nbytes); if (needsep) SSET (fullname, directory_nbytes, DIRECTORY_SEP); memcpy (SDATA (fullname) + directory_nbytes + needsep, SDATA (name), len); nchars = multibyte_chars_in_text (SDATA (fullname), nbytes); /* Some bug somewhere. */ if (nchars > nbytes) emacs_abort (); STRING_SET_CHARS (fullname, nchars); if (nchars == nbytes) STRING_SET_UNIBYTE (fullname); finalname = fullname; } else finalname = name; if (attrs) { Lisp_Object fileattrs = file_attributes (fd, dp->d_name, id_format); list = Fcons (Fcons (finalname, fileattrs), list); } else list = Fcons (finalname, list); } UNGCPRO; } block_input (); closedir (d); unblock_input (); #ifdef WINDOWSNT if (attrs) Vw32_get_true_file_attributes = w32_save; #endif /* Discard the unwind protect. */ specpdl_ptr = specpdl + count; if (NILP (nosort)) list = Fsort (Fnreverse (list), attrs ? Qfile_attributes_lessp : Qstring_lessp); (void) directory_volatile; RETURN_UNGCPRO (list); }
static int get_logical_fringe_bitmap (struct window *w, Lisp_Object bitmap, int right_p, int partial_p) { Lisp_Object cmap, bm1 = Qnil, bm2 = Qnil, bm; int ln1 = 0, ln2 = 0; int ix1 = right_p; int ix2 = ix1 + (partial_p ? 2 : 0); /* Lookup in buffer-local fringe-indicator-alist before global alist. Elements are: BITMAP -- use for all (L R) -- use for left right (whether partial or not) (L R PL PR) -- use for left right partial-left partial-right If any value in local binding is not present or t, use global value. If partial, lookup partial bitmap in default value if not found here. If not partial, or no partial spec is present, use non-partial bitmap. */ if ((cmap = BVAR (XBUFFER (w->buffer), fringe_indicator_alist)), !NILP (cmap)) { bm1 = Fassq (bitmap, cmap); if (CONSP (bm1)) { if ((bm1 = XCDR (bm1)), NILP (bm1)) return NO_FRINGE_BITMAP; if (CONSP (bm1)) { ln1 = XINT (Flength (bm1)); if (partial_p) { if (ln1 > ix2) { bm = Fnth (make_number (ix2), bm1); if (!EQ (bm, Qt)) goto found; } } else { if (ln1 > ix1) { bm = Fnth (make_number (ix1), bm1); if (!EQ (bm, Qt)) goto found; } } } else if ((bm = bm1, !EQ (bm, Qt))) goto found; } } if (!EQ (cmap, BVAR (&buffer_defaults, fringe_indicator_alist)) && !NILP (BVAR (&buffer_defaults, fringe_indicator_alist))) { bm2 = Fassq (bitmap, BVAR (&buffer_defaults, fringe_indicator_alist)); if (CONSP (bm2)) { if ((bm2 = XCDR (bm2)), !NILP (bm2)) { if (CONSP (bm2)) { ln2 = XINT (Flength (bm2)); if (partial_p) { if (ln2 > ix2) { bm = Fnth (make_number (ix2), bm2); if (!EQ (bm, Qt)) goto found; } } } } } } if (ln1 > ix1) { bm = Fnth (make_number (ix1), bm1); if (!EQ (bm, Qt)) goto found; } if (ln2 > ix1) { bm = Fnth (make_number (ix1), bm2); if (!EQ (bm, Qt)) goto found; return NO_FRINGE_BITMAP; } else if ((bm = bm2, NILP (bm))) return NO_FRINGE_BITMAP; found: return lookup_fringe_bitmap (bm); }
if (STRINGP (BVAR (b, file_truename)) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) { unlock_file (BVAR (b, file_truename)); } } } DEFUN ("lock-buffer", Flock_buffer, Slock_buffer, 0, 1, 0, doc: /* Lock FILE, if current buffer is modified. FILE defaults to current buffer's visited file, or else nothing is done if current buffer isn't visiting a file. */) (Lisp_Object file) { if (NILP (file)) file = BVAR (current_buffer, file_truename); else CHECK_STRING (file); if (SAVE_MODIFF < MODIFF && !NILP (file)) lock_file (file); return Qnil; } DEFUN ("unlock-buffer", Funlock_buffer, Sunlock_buffer, 0, 0, 0, doc: /* Unlock the file visited in the current buffer. If the buffer is not modified, this does nothing because the file should not be locked in that case. */) (void) {
int update_window_fringes (struct window *w, int keep_current_p) { struct glyph_row *row, *cur = 0; int yb = window_text_bottom_y (w); int rn, nrows = w->current_matrix->nrows; int y; int redraw_p = 0; Lisp_Object boundary_top = Qnil, boundary_bot = Qnil; Lisp_Object arrow_top = Qnil, arrow_bot = Qnil; Lisp_Object empty_pos; Lisp_Object ind = Qnil; #define MAX_BITMAP_CACHE (8*4) int bitmap_cache[MAX_BITMAP_CACHE]; int top_ind_rn, bot_ind_rn; int top_ind_min_y, bot_ind_max_y; /* top_ind_rn is set to a nonnegative value whenver row->indicate_bob_p is set, so it's OK that top_row_ends_at_zv_p is not initialized here. Similarly for bot_ind_rn, row->indicate_eob_p and bot_row_ends_at_zv_p. */ int top_row_ends_at_zv_p IF_LINT (= 0), bot_row_ends_at_zv_p IF_LINT (= 0); if (w->pseudo_window_p) return 0; if (!MINI_WINDOW_P (w) && (ind = BVAR (XBUFFER (w->buffer), indicate_buffer_boundaries), !NILP (ind))) { if (EQ (ind, Qleft) || EQ (ind, Qright)) boundary_top = boundary_bot = arrow_top = arrow_bot = ind; else if (CONSP (ind) && CONSP (XCAR (ind))) { Lisp_Object pos; if (pos = Fassq (Qt, ind), !NILP (pos)) boundary_top = boundary_bot = arrow_top = arrow_bot = XCDR (pos); if (pos = Fassq (Qtop, ind), !NILP (pos)) boundary_top = XCDR (pos); if (pos = Fassq (Qbottom, ind), !NILP (pos)) boundary_bot = XCDR (pos); if (pos = Fassq (Qup, ind), !NILP (pos)) arrow_top = XCDR (pos); if (pos = Fassq (Qdown, ind), !NILP (pos)) arrow_bot = XCDR (pos); } else /* Anything else means boundary on left and no arrows. */ boundary_top = boundary_bot = Qleft; } top_ind_rn = bot_ind_rn = -1; if (!NILP (ind)) { for (y = w->vscroll, rn = 0; y < yb && rn < nrows; y += row->height, ++rn) { row = w->desired_matrix->rows + rn; if (!row->enabled_p) row = w->current_matrix->rows + rn; row->indicate_bob_p = row->indicate_top_line_p = 0; row->indicate_eob_p = row->indicate_bottom_line_p = 0; if (!row->mode_line_p) { if (top_ind_rn < 0 && row->visible_height > 0) { if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)) && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row)) row->indicate_bob_p = !NILP (boundary_top); else row->indicate_top_line_p = !NILP (arrow_top); top_ind_rn = rn; } if (bot_ind_rn < 0) { if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)) && !MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) row->indicate_eob_p = !NILP (boundary_bot), bot_ind_rn = rn; else if (y + row->height >= yb) row->indicate_bottom_line_p = !NILP (arrow_bot), bot_ind_rn = rn; } } } } empty_pos = BVAR (XBUFFER (w->buffer), indicate_empty_lines); if (!NILP (empty_pos) && !EQ (empty_pos, Qright)) empty_pos = WINDOW_LEFT_FRINGE_WIDTH (w) == 0 ? Qright : Qleft; for (y = 0; y < MAX_BITMAP_CACHE; y++) bitmap_cache[y] = -1; #define LEFT_FRINGE(cache, which, partial_p) \ (bitmap_cache[cache*4+partial_p] >= 0 \ ? bitmap_cache[cache*4+partial_p] \ : (bitmap_cache[cache*4+partial_p] = \ get_logical_fringe_bitmap (w, which, 0, partial_p))) #define RIGHT_FRINGE(cache, which, partial_p) \ (bitmap_cache[cache*4+2+partial_p] >= 0 \ ? bitmap_cache[cache*4+2+partial_p] \ : (bitmap_cache[cache*4+2+partial_p] = \ get_logical_fringe_bitmap (w, which, 1, partial_p))) /* Extend top-aligned top indicator (or bottom-aligned bottom indicator) to adjacent rows if it doesn't fit in one row. */ top_ind_min_y = bot_ind_max_y = -1; if (top_ind_rn >= 0) { int bn = NO_FRINGE_BITMAP; row = w->desired_matrix->rows + top_ind_rn; if (!row->enabled_p) row = w->current_matrix->rows + top_ind_rn; top_row_ends_at_zv_p = row->ends_at_zv_p; if (row->indicate_bob_p) { if (EQ (boundary_top, Qleft)) bn = ((row->indicate_eob_p && EQ (boundary_bot, Qleft)) ? LEFT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) : LEFT_FRINGE (2, Qtop, 0)); else bn = ((row->indicate_eob_p && EQ (boundary_bot, Qright)) ? RIGHT_FRINGE (1, Qtop_bottom, row->ends_at_zv_p) : RIGHT_FRINGE (2, Qtop, 0)); } else if (row->indicate_top_line_p) { if (EQ (arrow_top, Qleft)) bn = LEFT_FRINGE (6, Qup, 0); else bn = RIGHT_FRINGE (6, Qup, 0); } if (bn != NO_FRINGE_BITMAP) { struct fringe_bitmap *fb = get_fringe_bitmap_data (bn); if (fb->align == ALIGN_BITMAP_TOP && fb->period == 0) { struct glyph_row *row1; int top_ind_max_y; top_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w); top_ind_max_y = top_ind_min_y + fb->height; if (top_ind_max_y > yb) top_ind_max_y = yb; for (y = row->y + row->height, rn = top_ind_rn + 1; y < top_ind_max_y && rn < nrows; y += row1->height, rn++) { if (bot_ind_rn >= 0 && rn >= bot_ind_rn) break; row1 = w->desired_matrix->rows + rn; if (!row1->enabled_p) row1 = w->current_matrix->rows + rn; row1->indicate_bob_p = row->indicate_bob_p; row1->indicate_top_line_p = row->indicate_top_line_p; } } } } if (bot_ind_rn >= 0) { int bn = NO_FRINGE_BITMAP; row = w->desired_matrix->rows + bot_ind_rn; if (!row->enabled_p) row = w->current_matrix->rows + bot_ind_rn; bot_row_ends_at_zv_p = row->ends_at_zv_p; if (row->indicate_eob_p) { if (EQ (boundary_bot, Qleft)) bn = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p); else bn = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p); } else if (row->indicate_bottom_line_p) { if (EQ (arrow_bot, Qleft)) bn = LEFT_FRINGE (7, Qdown, 0); else bn = RIGHT_FRINGE (7, Qdown, 0); } if (bn != NO_FRINGE_BITMAP) { struct fringe_bitmap *fb = get_fringe_bitmap_data (bn); if (fb->align == ALIGN_BITMAP_BOTTOM && fb->period == 0) { struct glyph_row *row1; int bot_ind_min_y; bot_ind_max_y = row->y + row->visible_height; bot_ind_min_y = bot_ind_max_y - fb->height; if (bot_ind_min_y < WINDOW_HEADER_LINE_HEIGHT (w)) bot_ind_min_y = WINDOW_HEADER_LINE_HEIGHT (w); for (y = row->y, rn = bot_ind_rn - 1; y >= bot_ind_min_y && rn >= 0; y -= row1->height, rn--) { if (top_ind_rn >= 0 && rn <= top_ind_rn) break; row1 = w->desired_matrix->rows + rn; if (!row1->enabled_p) row1 = w->current_matrix->rows + rn; row1->indicate_eob_p = row->indicate_eob_p; row1->indicate_bottom_line_p = row->indicate_bottom_line_p; } } } } for (y = w->vscroll, rn = 0; y < yb && rn < nrows; y += row->height, rn++) { int left, right; unsigned left_face_id, right_face_id; int left_offset, right_offset; int periodic_p; row = w->desired_matrix->rows + rn; cur = w->current_matrix->rows + rn; if (!row->enabled_p) row = cur; left_face_id = right_face_id = DEFAULT_FACE_ID; left_offset = right_offset = 0; periodic_p = 0; /* Decide which bitmap to draw in the left fringe. */ if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0) left = NO_FRINGE_BITMAP; else if (row->left_user_fringe_bitmap != NO_FRINGE_BITMAP) { left = row->left_user_fringe_bitmap; left_face_id = row->left_user_fringe_face_id; } else if ((!row->reversed_p && row->truncated_on_left_p) || (row->reversed_p && row->truncated_on_right_p)) left = LEFT_FRINGE (0, Qtruncation, 0); else if (row->indicate_bob_p && EQ (boundary_top, Qleft)) { left = ((row->indicate_eob_p && EQ (boundary_bot, Qleft)) ? LEFT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p) : LEFT_FRINGE (2, Qtop, 0)); if (top_ind_min_y >= 0) left_offset = top_ind_min_y - row->y; } else if (row->indicate_eob_p && EQ (boundary_bot, Qleft)) { left = LEFT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p); if (bot_ind_max_y >= 0) left_offset = bot_ind_max_y - (row->y + row->visible_height); } else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)) || (row->reversed_p && row->continued_p)) left = LEFT_FRINGE (4, Qcontinuation, 0); else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft)) left = LEFT_FRINGE (5, Qempty_line, 0); else if (row->indicate_top_line_p && EQ (arrow_top, Qleft)) { left = LEFT_FRINGE (6, Qup, 0); if (top_ind_min_y >= 0) left_offset = top_ind_min_y - row->y; } else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qleft)) { left = LEFT_FRINGE (7, Qdown, 0); if (bot_ind_max_y >= 0) left_offset = bot_ind_max_y - (row->y + row->visible_height); } else left = NO_FRINGE_BITMAP; /* Decide which bitmap to draw in the right fringe. */ if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0) right = NO_FRINGE_BITMAP; else if (row->right_user_fringe_bitmap != NO_FRINGE_BITMAP) { right = row->right_user_fringe_bitmap; right_face_id = row->right_user_fringe_face_id; } else if ((!row->reversed_p && row->truncated_on_right_p) || (row->reversed_p && row->truncated_on_left_p)) right = RIGHT_FRINGE (0, Qtruncation, 0); else if (row->indicate_bob_p && EQ (boundary_top, Qright)) { right = ((row->indicate_eob_p && EQ (boundary_bot, Qright)) ? RIGHT_FRINGE (1, Qtop_bottom, top_row_ends_at_zv_p) : RIGHT_FRINGE (2, Qtop, 0)); if (top_ind_min_y >= 0) right_offset = top_ind_min_y - row->y; } else if (row->indicate_eob_p && EQ (boundary_bot, Qright)) { right = RIGHT_FRINGE (3, Qbottom, bot_row_ends_at_zv_p); if (bot_ind_max_y >= 0) right_offset = bot_ind_max_y - (row->y + row->visible_height); } else if ((!row->reversed_p && row->continued_p) || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))) right = RIGHT_FRINGE (4, Qcontinuation, 0); else if (row->indicate_top_line_p && EQ (arrow_top, Qright)) { right = RIGHT_FRINGE (6, Qup, 0); if (top_ind_min_y >= 0) right_offset = top_ind_min_y - row->y; } else if (row->indicate_bottom_line_p && EQ (arrow_bot, Qright)) { right = RIGHT_FRINGE (7, Qdown, 0); if (bot_ind_max_y >= 0) right_offset = bot_ind_max_y - (row->y + row->visible_height); } else if (row->indicate_empty_line_p && EQ (empty_pos, Qright)) right = RIGHT_FRINGE (5, Qempty_line, 0); else right = NO_FRINGE_BITMAP; periodic_p = (get_fringe_bitmap_data (left)->period != 0 || get_fringe_bitmap_data (right)->period != 0); if (row->y != cur->y || row->visible_height != cur->visible_height || row->ends_at_zv_p != cur->ends_at_zv_p || left != cur->left_fringe_bitmap || right != cur->right_fringe_bitmap || left_face_id != cur->left_fringe_face_id || right_face_id != cur->right_fringe_face_id || left_offset != cur->left_fringe_offset || right_offset != cur->right_fringe_offset || periodic_p != cur->fringe_bitmap_periodic_p || cur->redraw_fringe_bitmaps_p) { redraw_p = row->redraw_fringe_bitmaps_p = 1; if (!keep_current_p) { cur->redraw_fringe_bitmaps_p = 1; cur->left_fringe_bitmap = left; cur->right_fringe_bitmap = right; cur->left_fringe_face_id = left_face_id; cur->right_fringe_face_id = right_face_id; cur->left_fringe_offset = left_offset; cur->right_fringe_offset = right_offset; cur->fringe_bitmap_periodic_p = periodic_p; } } if (row->overlay_arrow_bitmap < 0) row->overlay_arrow_bitmap = get_logical_fringe_bitmap (w, Qoverlay_arrow, 0, 0); if (row->overlay_arrow_bitmap != cur->overlay_arrow_bitmap) { redraw_p = row->redraw_fringe_bitmaps_p = 1; if (!keep_current_p) { cur->redraw_fringe_bitmaps_p = 1; cur->overlay_arrow_bitmap = row->overlay_arrow_bitmap; } } row->left_fringe_bitmap = left; row->right_fringe_bitmap = right; row->left_fringe_face_id = left_face_id; row->right_fringe_face_id = right_face_id; row->left_fringe_offset = left_offset; row->right_fringe_offset = right_offset; row->fringe_bitmap_periodic_p = periodic_p; } return redraw_p && !keep_current_p; }
Lisp_Object directory_files_internal (Lisp_Object directory, Lisp_Object full, Lisp_Object match, Lisp_Object nosort, bool attrs, Lisp_Object id_format) { ptrdiff_t directory_nbytes; Lisp_Object list, dirfilename, encoded_directory; bool needsep = 0; ptrdiff_t count = SPECPDL_INDEX (); #ifdef WINDOWSNT Lisp_Object w32_save = Qnil; #endif /* Don't let the compiler optimize away all copies of DIRECTORY, which would break GC; see Bug#16986. */ Lisp_Object volatile directory_volatile = directory; /* Because of file name handlers, these functions might call Ffuncall, and cause a GC. */ list = encoded_directory = dirfilename = Qnil; dirfilename = Fdirectory_file_name (directory); /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run run_pre_post_conversion_on_str which calls Lisp directly and indirectly. */ dirfilename = ENCODE_FILE (dirfilename); encoded_directory = ENCODE_FILE (directory); int fd; DIR *d = open_directory (dirfilename, &fd); /* Unfortunately, we can now invoke expand-file-name and file-attributes on filenames, both of which can throw, so we must do a proper unwind-protect. */ record_unwind_protect_ptr (directory_files_internal_unwind, d); #ifdef WINDOWSNT if (attrs) { /* Do this only once to avoid doing it (in w32.c:stat) for each file in the directory, when we call file_attributes below. */ record_unwind_protect (directory_files_internal_w32_unwind, Vw32_get_true_file_attributes); w32_save = Vw32_get_true_file_attributes; if (EQ (Vw32_get_true_file_attributes, Qlocal)) { /* w32.c:stat will notice these bindings and avoid calling GetDriveType for each file. */ if (is_slow_fs (SSDATA (dirfilename))) Vw32_get_true_file_attributes = Qnil; else Vw32_get_true_file_attributes = Qt; } } #endif directory_nbytes = SBYTES (directory); re_match_object = Qt; /* Decide whether we need to add a directory separator. */ if (directory_nbytes == 0 || !IS_ANY_SEP (SREF (directory, directory_nbytes - 1))) needsep = 1; /* Windows users want case-insensitive wildcards. */ Lisp_Object case_table = #ifdef WINDOWSNT BVAR (&buffer_defaults, case_canon_table) #else Qnil #endif ; if (!NILP (match)) CHECK_STRING (match); /* Loop reading directory entries. */ for (struct dirent *dp; (dp = read_dirent (d, directory)); ) { ptrdiff_t len = dirent_namelen (dp); Lisp_Object name = make_unibyte_string (dp->d_name, len); Lisp_Object finalname = name; /* Note: DECODE_FILE can GC; it should protect its argument, though. */ name = DECODE_FILE (name); len = SBYTES (name); /* Now that we have unwind_protect in place, we might as well allow matching to be interrupted. */ maybe_quit (); bool wanted = (NILP (match) || fast_string_match_internal ( match, name, case_table) >= 0); if (wanted) { if (!NILP (full)) { Lisp_Object fullname; ptrdiff_t nbytes = len + directory_nbytes + needsep; ptrdiff_t nchars; fullname = make_uninit_multibyte_string (nbytes, nbytes); memcpy (SDATA (fullname), SDATA (directory), directory_nbytes); if (needsep) SSET (fullname, directory_nbytes, DIRECTORY_SEP); memcpy (SDATA (fullname) + directory_nbytes + needsep, SDATA (name), len); nchars = multibyte_chars_in_text (SDATA (fullname), nbytes); /* Some bug somewhere. */ if (nchars > nbytes) emacs_abort (); STRING_SET_CHARS (fullname, nchars); if (nchars == nbytes) STRING_SET_UNIBYTE (fullname); finalname = fullname; } else finalname = name; if (attrs) { Lisp_Object fileattrs = file_attributes (fd, dp->d_name, directory, name, id_format); list = Fcons (Fcons (finalname, fileattrs), list); } else list = Fcons (finalname, list); } } closedir (d); #ifdef WINDOWSNT if (attrs) Vw32_get_true_file_attributes = w32_save; #endif /* Discard the unwind protect. */ specpdl_ptr = specpdl + count; if (NILP (nosort)) list = Fsort (Fnreverse (list), attrs ? Qfile_attributes_lessp : Qstring_lessp); (void) directory_volatile; return list; }