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 /* 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); RETURN_UNGCPRO (list); }
int xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, struct timespec const *timeout, sigset_t const *sigmask) { fd_set all_rfds, all_wfds; struct timespec tmo; struct timespec const *tmop = timeout; GMainContext *context; int have_wfds = wfds != NULL; GPollFD gfds_buf[128]; GPollFD *gfds = gfds_buf; int gfds_size = sizeof gfds_buf / sizeof *gfds_buf; int n_gfds, retval = 0, our_fds = 0, max_fds = fds_lim - 1; bool context_acquired = false; int i, nfds, tmo_in_millisec = -1; bool need_to_dispatch; USE_SAFE_ALLOCA; context = g_main_context_default (); context_acquired = g_main_context_acquire (context); /* FIXME: If we couldn't acquire the context, we just silently proceed because this function handles more than just glib file descriptors. Note that, as implemented, this failure is completely silent: there is no feedback to the caller. */ if (rfds) all_rfds = *rfds; else FD_ZERO (&all_rfds); if (wfds) all_wfds = *wfds; else FD_ZERO (&all_wfds); n_gfds = (context_acquired ? g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size) : -1); if (gfds_size < n_gfds) { SAFE_NALLOCA (gfds, sizeof *gfds, n_gfds); gfds_size = n_gfds; n_gfds = g_main_context_query (context, G_PRIORITY_LOW, &tmo_in_millisec, gfds, gfds_size); } for (i = 0; i < n_gfds; ++i) { if (gfds[i].events & G_IO_IN) { FD_SET (gfds[i].fd, &all_rfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; } if (gfds[i].events & G_IO_OUT) { FD_SET (gfds[i].fd, &all_wfds); if (gfds[i].fd > max_fds) max_fds = gfds[i].fd; have_wfds = 1; } } SAFE_FREE (); if (tmo_in_millisec >= 0) { tmo = make_timespec (tmo_in_millisec / 1000, 1000 * 1000 * (tmo_in_millisec % 1000)); if (!timeout || timespec_cmp (tmo, *timeout) < 0) tmop = &tmo; } fds_lim = max_fds + 1; nfds = pselect (fds_lim, &all_rfds, have_wfds ? &all_wfds : NULL, efds, tmop, sigmask); if (nfds < 0) retval = nfds; else if (nfds > 0) { for (i = 0; i < fds_lim; ++i) { if (FD_ISSET (i, &all_rfds)) { if (rfds && FD_ISSET (i, rfds)) ++retval; else ++our_fds; } else if (rfds) FD_CLR (i, rfds); if (have_wfds && FD_ISSET (i, &all_wfds)) { if (wfds && FD_ISSET (i, wfds)) ++retval; else ++our_fds; } else if (wfds) FD_CLR (i, wfds); if (efds && FD_ISSET (i, efds)) ++retval; } } /* If Gtk+ is in use eventually gtk_main_iteration will be called, unless retval is zero. */ #ifdef USE_GTK need_to_dispatch = retval == 0; #else need_to_dispatch = true; #endif if (need_to_dispatch) { int pselect_errno = errno; /* Prevent g_main_dispatch recursion, that would occur without block_input wrapper, because event handlers call unblock_input. Event loop recursion was causing Bug#15801. */ block_input (); while (g_main_context_pending (context)) g_main_context_dispatch (context); unblock_input (); errno = pselect_errno; } if (context_acquired) g_main_context_release (context); /* To not have to recalculate timeout, return like this. */ if ((our_fds > 0 || (nfds == 0 && tmop == &tmo)) && (retval == 0)) { retval = -1; errno = EINTR; } return retval; }
static void x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, Lisp_Object frame) { struct frame *f = XFRAME (frame); struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); Time timestamp = last_event_timestamp; OSStatus err; Selection sel; struct gcpro gcpro1, gcpro2; Lisp_Object rest, handler_fn, value, target_type; GCPRO2 (selection_name, selection_value); block_input (); err = mac_get_selection_from_symbol (selection_name, 1, &sel); if (err == noErr && sel) { /* Don't allow a quit within the converter. When the user types C-g, he would be surprised if by luck it came during a converter. */ ptrdiff_t count = SPECPDL_INDEX (); specbind (Qinhibit_quit, Qt); for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest)) { if (!(CONSP (XCAR (rest)) && (target_type = XCAR (XCAR (rest)), SYMBOLP (target_type)) && mac_valid_selection_target_p (target_type) && (handler_fn = XCDR (XCAR (rest)), SYMBOLP (handler_fn)))) continue; if (!NILP (handler_fn)) value = call3 (handler_fn, selection_name, target_type, selection_value); else value = Qnil; if (NILP (value)) continue; if (mac_valid_selection_value_p (value, target_type)) err = mac_put_selection_value (sel, target_type, value); else if (CONSP (value) && EQ (XCAR (value), target_type) && mac_valid_selection_value_p (XCDR (value), target_type)) err = mac_put_selection_value (sel, target_type, XCDR (value)); } unbind_to (count, Qnil); } unblock_input (); UNGCPRO; if (sel && err != noErr) error ("Can't set selection"); /* Now update the local cache */ { Lisp_Object selection_data; Lisp_Object ownership_info; Lisp_Object prev_value; if (sel) { block_input (); ownership_info = mac_get_selection_ownership_info (sel); unblock_input (); } else ownership_info = Qnil; /* dummy value for local-only selection */ selection_data = list5 (selection_name, selection_value, INTEGER_TO_CONS (timestamp), frame, ownership_info); prev_value = LOCAL_SELECTION (selection_name, dpyinfo); tset_selection_alist (dpyinfo->terminal, Fcons (selection_data, dpyinfo->terminal->Vselection_alist)); /* If we already owned the selection, remove the old selection data. Don't use Fdelq as that may QUIT. */ if (!NILP (prev_value)) { /* We know it's not the CAR, so it's easy. */ Lisp_Object rest = dpyinfo->terminal->Vselection_alist; for (; CONSP (rest); rest = XCDR (rest)) if (EQ (prev_value, Fcar (XCDR (rest)))) { XSETCDR (rest, XCDR (XCDR (rest))); break; } } } }
static Lisp_Object xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) { FcResult result; Display *display = FRAME_X_DISPLAY (f); Lisp_Object val, filename, idx, font_object; FcPattern *pat = NULL, *match; struct xftfont_info *xftfont_info = NULL; struct font *font; double size = 0; XftFont *xftfont = NULL; int spacing; char name[256]; int len, i; XGlyphInfo extents; FT_Face ft_face; FcMatrix *matrix; val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX)); if (! CONSP (val)) return Qnil; val = XCDR (val); filename = XCAR (val); idx = XCDR (val); size = XINT (AREF (entity, FONT_SIZE_INDEX)); if (size == 0) size = pixel_size; pat = FcPatternCreate (); FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity)); i = FONT_SLANT_NUMERIC (entity) - 100; if (i < 0) i = 0; FcPatternAddInteger (pat, FC_SLANT, i); FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity)); FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size); val = AREF (entity, FONT_FAMILY_INDEX); if (! NILP (val)) FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); val = AREF (entity, FONT_FOUNDRY_INDEX); if (! NILP (val)) FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val))); val = AREF (entity, FONT_SPACING_INDEX); if (! NILP (val)) FcPatternAddInteger (pat, FC_SPACING, XINT (val)); val = AREF (entity, FONT_DPI_INDEX); if (! NILP (val)) { double dbl = XINT (val); FcPatternAddDouble (pat, FC_DPI, dbl); } val = AREF (entity, FONT_AVGWIDTH_INDEX); if (INTEGERP (val) && XINT (val) == 0) FcPatternAddBool (pat, FC_SCALABLE, FcTrue); /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz over 10x20-ISO8859-1.pcf.gz). */ FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity)); xftfont_add_rendering_parameters (pat, entity); FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename)); FcPatternAddInteger (pat, FC_INDEX, XINT (idx)); block_input (); /* Make sure that the Xrender extension is added before the Xft one. Otherwise, the close-display hook set by Xft is called after the one for Xrender, and the former tries to re-add the latter. This results in inconsistency of internal states and leads to X protocol error when one reconnects to the same X server. (Bug#1696) */ { int event_base, error_base; XRenderQueryExtension (display, &event_base, &error_base); } /* Substitute in values from X resources and XftDefaultSet. */ XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat); match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result); xftfont_fix_match (pat, match); FcPatternDestroy (pat); xftfont = XftFontOpenPattern (display, match); if (!xftfont) { unblock_input (); XftPatternDestroy (match); return Qnil; } ft_face = XftLockFace (xftfont); unblock_input (); /* We should not destroy PAT here because it is kept in XFTFONT and destroyed automatically when XFTFONT is closed. */ font_object = font_make_object (VECSIZE (struct xftfont_info), entity, size); ASET (font_object, FONT_TYPE_INDEX, Qxft); len = font_unparse_xlfd (entity, size, name, 256); if (len > 0) ASET (font_object, FONT_NAME_INDEX, make_string (name, len)); len = font_unparse_fcname (entity, size, name, 256); if (len > 0) ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len)); else ASET (font_object, FONT_FULLNAME_INDEX, AREF (font_object, FONT_NAME_INDEX)); ASET (font_object, FONT_FILE_INDEX, filename); ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (xftfont->pattern, filename)); font = XFONT_OBJECT (font_object); font->pixel_size = size; font->driver = &xftfont_driver; font->encoding_charset = font->repertory_charset = -1; xftfont_info = (struct xftfont_info *) font; xftfont_info->display = display; xftfont_info->xftfont = xftfont; /* This means that there's no need of transformation. */ xftfont_info->matrix.xx = 0; if (FcPatternGetMatrix (xftfont->pattern, FC_MATRIX, 0, &matrix) == FcResultMatch) { xftfont_info->matrix.xx = 0x10000L * matrix->xx; xftfont_info->matrix.yy = 0x10000L * matrix->yy; xftfont_info->matrix.xy = 0x10000L * matrix->xy; xftfont_info->matrix.yx = 0x10000L * matrix->yx; } if (INTEGERP (AREF (entity, FONT_SPACING_INDEX))) spacing = XINT (AREF (entity, FONT_SPACING_INDEX)); else spacing = FC_PROPORTIONAL; if (! ascii_printable[0]) { int ch; for (ch = 0; ch < 95; ch++) ascii_printable[ch] = ' ' + ch; } block_input (); /* Unfortunately Xft doesn't provide a way to get minimum char width. So, we set min_width to space_width. */ if (spacing != FC_PROPORTIONAL #ifdef FC_DUAL && spacing != FC_DUAL #endif /* FC_DUAL */ ) { font->min_width = font->max_width = font->average_width = font->space_width = xftfont->max_advance_width; XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents); } else { XftTextExtents8 (display, xftfont, ascii_printable, 1, &extents); font->min_width = font->max_width = font->space_width = extents.xOff; if (font->space_width <= 0) /* dirty workaround */ font->space_width = pixel_size; XftTextExtents8 (display, xftfont, ascii_printable + 1, 94, &extents); font->average_width = (font->space_width + extents.xOff) / 95; } unblock_input (); font->ascent = xftfont->ascent; font->descent = xftfont->descent; if (pixel_size >= 5) { /* The above condition is a dirty workaround because XftTextExtents8 behaves strangely for some fonts (e.g. "Dejavu Sans Mono") when pixel_size is less than 5. */ if (font->ascent < extents.y) font->ascent = extents.y; if (font->descent < extents.height - extents.y) font->descent = extents.height - extents.y; } font->height = font->ascent + font->descent; if (XINT (AREF (entity, FONT_SIZE_INDEX)) == 0) { int upEM = ft_face->units_per_EM; font->underline_position = -ft_face->underline_position * size / upEM; font->underline_thickness = ft_face->underline_thickness * size / upEM; if (font->underline_thickness > 2) font->underline_position -= font->underline_thickness / 2; } else { font->underline_position = -1; font->underline_thickness = 0; } #ifdef HAVE_LIBOTF xftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0; xftfont_info->otf = NULL; #endif /* HAVE_LIBOTF */ xftfont_info->ft_size = ft_face->size; font->baseline_offset = 0; font->relative_compose = 0; font->default_ascent = 0; font->vertical_centering = 0; #ifdef FT_BDF_H if (! (ft_face->face_flags & FT_FACE_FLAG_SFNT)) { BDF_PropertyRec rec; if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &rec) == 0 && rec.type == BDF_PROPERTY_TYPE_INTEGER) font->baseline_offset = rec.u.integer; if (FT_Get_BDF_Property (ft_face, "_MULE_RELATIVE_COMPOSE", &rec) == 0 && rec.type == BDF_PROPERTY_TYPE_INTEGER) font->relative_compose = rec.u.integer; if (FT_Get_BDF_Property (ft_face, "_MULE_DEFAULT_ASCENT", &rec) == 0 && rec.type == BDF_PROPERTY_TYPE_INTEGER) font->default_ascent = rec.u.integer; } #endif return font_object; }
int w32_console_read_socket (struct terminal *terminal, struct input_event *hold_quit) { int nev, add; int isdead; block_input (); for (;;) { int nfnotify = handle_file_notifications (hold_quit); nev = fill_queue (0); if (nev <= 0) { /* If nev == -1, there was some kind of error If nev == 0 then no events were available so return. */ if (nfnotify) nev = 0; break; } while (nev > 0) { struct input_event inev; /* Having a separate variable with this value makes debugging easier, as otherwise the compiler might rearrange the switch below in a way that makes it hard to track the event type. */ unsigned evtype = queue_ptr->EventType; EVENT_INIT (inev); inev.kind = NO_EVENT; inev.arg = Qnil; switch (evtype) { case KEY_EVENT: add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead); if (add == -1) /* 95.7.25 by himi */ { queue_ptr--; add = 1; } if (add) kbd_buffer_store_event_hold (&inev, hold_quit); break; case MOUSE_EVENT: add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev); if (add) kbd_buffer_store_event_hold (&inev, hold_quit); break; case WINDOW_BUFFER_SIZE_EVENT: if (w32_use_full_screen_buffer) resize_event (&queue_ptr->Event.WindowBufferSizeEvent); break; case MENU_EVENT: case FOCUS_EVENT: /* Internal event types, ignored. */ break; } queue_ptr++; nev--; } } /* We don't get told about changes in the window size (only the buffer size, which we no longer care about), so we have to check it periodically. */ if (!w32_use_full_screen_buffer) maybe_generate_resize_event (); unblock_input (); return nev; }
static int xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, bool with_background) { struct frame *f = s->f; struct face *face = s->face; struct xftfont_info *xftfont_info = (struct xftfont_info *) s->font; struct xftface_info *xftface_info = NULL; XftDraw *xft_draw = xftfont_get_xft_draw (f); FT_UInt *code; XftColor fg, bg; int len = to - from; int i; if (s->font == face->font) xftface_info = (struct xftface_info *) face->extra; xftfont_get_colors (f, face, s->gc, xftface_info, &fg, with_background ? &bg : NULL); block_input (); if (s->num_clips > 0) XftDrawSetClipRectangles (xft_draw, 0, 0, s->clip, s->num_clips); else XftDrawSetClip (xft_draw, NULL); if (with_background) { int height = FONT_HEIGHT (s->font), ascent = FONT_BASE (s->font); /* Font's global height and ascent values might be preposterously large for some fonts. We fix here the case when those fonts are used for display of glyphless characters, because drawing background with font dimensions in those cases makes the display illegible. There's only one more call to the draw method with with_background set to true, and that's in x_draw_glyph_string_foreground, when drawing the cursor, where we have no such heuristics available. FIXME. */ if (s->first_glyph->type == GLYPHLESS_GLYPH && (s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE || s->first_glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)) height = ascent = s->first_glyph->slice.glyphless.lower_yoff - s->first_glyph->slice.glyphless.upper_yoff; XftDrawRect (xft_draw, &bg, x, y - ascent, s->width, height); } code = alloca (sizeof (FT_UInt) * len); for (i = 0; i < len; i++) code[i] = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8) | XCHAR2B_BYTE2 (s->char2b + from + i)); if (s->padding_p) for (i = 0; i < len; i++) XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont, x + i, y, code + i, 1); else XftDrawGlyphs (xft_draw, &fg, xftfont_info->xftfont, x, y, code, len); unblock_input (); return len; }