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; struct re_pattern_buffer *bufp = NULL; bool needsep = 0; ptrdiff_t count = SPECPDL_INDEX (); struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; #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. */ dirfilename = ENCODE_FILE (dirfilename); encoded_directory = ENCODE_FILE (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! */ 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) { 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 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; struct gcpro gcpro1, gcpro2; 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; bool wanted = (NILP (match) || re_search (bufp, SSDATA (name), len, 0, len, 0) >= 0); 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); }
/*-----------------------------------------------------------------------------------*/ EK_EVENTHANDLER(directory_eventhandler, ev, data) { unsigned char i; EK_EVENTHANDLER_ARGS(ev, data); if(ev == EK_EVENT_INIT) { ctk_window_new(&window, width, height, "Directory"); /* loaddirectory();*/ makewindow(0); show_statustext("Loading directory..."); startloading(); ctk_window_open(&window); } else if(ev == EK_EVENT_CONTINUE) { read_dirent(); load_dirent(); if(loading != 0) { ek_post(id, EK_EVENT_CONTINUE, NULL); } } else if(ev == ctk_signal_widget_activate) { if(data == (ek_data_t)&reloadbutton) { for(i = 0; dscs[i] != NULL; ++i) { LOADER_UNLOAD_DSC(dscs[i]); dscs[i] = NULL; } /* loaddirectory();*/ startloading(); makewindow(0); ctk_window_open(&window); } else if(data == (ek_data_t)&morebutton) { makewindow(morestart); ctk_window_open(&window); } else if(data == (ek_data_t)&backbutton) { makewindow(0); ctk_window_open(&window); } else if(data == (ek_data_t)&autoexitbutton) { autoexit = 1 - autoexit; if(autoexit == 1) { ctk_label_set_text(&autoexitlabel, autoexiton); } else { ctk_label_set_text(&autoexitlabel, autoexitoff); } CTK_WIDGET_REDRAW(&autoexitlabel); } else { for(i = 0; dscs[i] != NULL; ++i) { if(data == (ek_data_t)(dscs[i]->icon)) { program_handler_load(dscs[i]->prgname, NULL); if(autoexit) { ctk_window_close(&window); quit(); } break; } } } } else if(ev == ctk_signal_widget_select) { if(data == (ek_data_t)&reloadbutton) { show_statustext("Reload directory"); } else if(data == (ek_data_t)&morebutton) { show_statustext("Show more files"); } else if(data == (ek_data_t)&backbutton) { show_statustext("Show first files"); } else if(data == (ek_data_t)&autoexitbutton) { show_statustext("Exit when loading program"); } else { for(i = 0; dscs[i] != NULL; ++i) { if(data == (ek_data_t)(dscs[i]->icon)) { show_statustext(dscs[i]->description); break; } } } } else if(ev == ctk_signal_window_close && data == (ek_data_t)&window) { quit(); } else if(ev == EK_EVENT_REQUEST_EXIT) { ctk_window_close(&window); quit(); } }
/*-----------------------------------------------------------------------------------*/ PROCESS_THREAD(directory_process, ev, data) { unsigned char i; PROCESS_BEGIN(); width = ctk_draw_width() - 2; height = ctk_draw_height() - 2 - CTK_CONF_MENUS; ctk_window_new(&window, width, height, "Directory"); /* loaddirectory();*/ makewindow(0); show_statustext("Loading directory..."); startloading(); ctk_window_open(&window); while(1) { PROCESS_WAIT_EVENT(); if(ev == PROCESS_EVENT_CONTINUE) { read_dirent(); load_dirent(); if(loading != 0) { process_post(&directory_process, PROCESS_EVENT_CONTINUE, NULL); } } else if(ev == ctk_signal_widget_activate) { if(data == (process_data_t)&reloadbutton) { for(i = 0; dscs[i] != NULL; ++i) { LOADER_UNLOAD_DSC(dscs[i]); dscs[i] = NULL; } /* loaddirectory();*/ startloading(); makewindow(0); ctk_window_open(&window); } else if(data == (process_data_t)&morebutton) { makewindow(morestart); ctk_window_open(&window); } else if(data == (process_data_t)&backbutton) { makewindow(0); ctk_window_open(&window); } else if(data == (process_data_t)&autoexitbutton) { autoexit = 1 - autoexit; if(autoexit == 1) { ctk_label_set_text(&autoexitlabel, autoexiton); } else { ctk_label_set_text(&autoexitlabel, autoexitoff); } CTK_WIDGET_REDRAW(&autoexitlabel); } else { for(i = 0; dscs[i] != NULL; ++i) { if(data == (process_data_t)(dscs[i]->icon)) { program_handler_load(dscs[i]->prgname, NULL); if(autoexit) { ctk_window_close(&window); quit(); } break; } } } } else if(ev == ctk_signal_widget_select) { if(data == (process_data_t)&reloadbutton) { show_statustext("Reload directory"); } else if(data == (process_data_t)&morebutton) { show_statustext("Show more files"); } else if(data == (process_data_t)&backbutton) { show_statustext("Show first files"); } else if(data == (process_data_t)&autoexitbutton) { show_statustext("Exit when loading program"); } else { for(i = 0; dscs[i] != NULL; ++i) { if(data == (process_data_t)(dscs[i]->icon)) { show_statustext(dscs[i]->description); break; } } } } else if(ev == ctk_signal_window_close && data == (process_data_t)&window) { quit(); } else if(ev == PROCESS_EVENT_EXIT) { ctk_window_close(&window); quit(); } } PROCESS_END(); }
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; }