#include "info.h"
#include "info-utils.h"
#include "filesys.h"
#include "tilde.h"
static void add_menu_to_file_buffer (), insert_text_into_fb_at_binding ();
static char *dirs_to_add[] = {
"dir", "localdir", (char *)NULL
};
typedef struct
{
unsigned long device;
unsigned long inode;
} dir_file_list_entry_type;
static int
new_dir_file_p (test)
struct stat *test;
{
static unsigned dir_file_list_len = 0;
static dir_file_list_entry_type *dir_file_list = NULL;
unsigned i;
for (i = 0; i < dir_file_list_len; i++)
{
dir_file_list_entry_type entry;
entry = dir_file_list[i];
if (entry.device == test->st_dev && entry.inode == test->st_ino)
return 0;
}
dir_file_list_len++;
dir_file_list = xrealloc (dir_file_list,
dir_file_list_len * sizeof (dir_file_list_entry_type));
dir_file_list[dir_file_list_len - 1].device = test->st_dev;
dir_file_list[dir_file_list_len - 1].inode = test->st_ino;
return 1;
}
void
maybe_build_dir_node (dirname)
char *dirname;
{
int path_index, update_tags;
char *this_dir;
FILE_BUFFER *dir_buffer = info_find_file (dirname);
if (!dir_buffer)
return;
if (dir_buffer->flags & N_CannotGC)
return;
new_dir_file_p (&dir_buffer->finfo);
path_index = update_tags = 0;
while ((this_dir = extract_colon_unit (infopath, &path_index)))
{
register int da_index;
char *from_file;
if (*this_dir == '~')
{
char *tilde_expanded_dirname;
tilde_expanded_dirname = tilde_expand_word (this_dir);
if (tilde_expanded_dirname != this_dir)
{
free (this_dir);
this_dir = tilde_expanded_dirname;
}
}
for (da_index = 0; (from_file = dirs_to_add[da_index]); da_index++)
{
struct stat finfo;
int statable;
int namelen = strlen (from_file);
char *fullpath = xmalloc (3 + strlen (this_dir) + namelen);
strcpy (fullpath, this_dir);
if (fullpath[strlen (fullpath) - 1] != '/')
strcat (fullpath, "/");
strcat (fullpath, from_file);
statable = (stat (fullpath, &finfo) == 0);
if (statable && S_ISREG (finfo.st_mode) && new_dir_file_p (&finfo))
{
long filesize;
char *contents = filesys_read_info_file (fullpath, &filesize,
&finfo);
if (contents)
{
update_tags++;
add_menu_to_file_buffer (contents, filesize, dir_buffer);
free (contents);
}
}
free (fullpath);
}
free (this_dir);
}
if (update_tags)
build_tags_and_nodes (dir_buffer);
dir_buffer->flags |= N_CannotGC;
}
static void
add_menu_to_file_buffer (contents, size, fb)
char *contents;
long size;
FILE_BUFFER *fb;
{
SEARCH_BINDING contents_binding, fb_binding;
long contents_offset, fb_offset;
contents_binding.buffer = contents;
contents_binding.start = 0;
contents_binding.end = size;
contents_binding.flags = S_FoldCase | S_SkipDest;
fb_binding.buffer = fb->contents;
fb_binding.start = 0;
fb_binding.end = fb->filesize;
fb_binding.flags = S_FoldCase | S_SkipDest;
contents_offset = search_forward (INFO_MENU_LABEL, &contents_binding);
fb_offset = search_forward (INFO_MENU_LABEL, &fb_binding);
if (contents_offset == -1)
return;
contents_offset += skip_whitespace_and_newlines (contents + contents_offset);
if (fb_offset == -1)
{
fb_offset = find_node_separator (&fb_binding);
if (fb_offset == -1)
return;
fb_binding.start = fb_offset;
fb_binding.start +=
skip_node_separator (fb_binding.buffer + fb_binding.start);
fb_offset = find_node_separator (&fb_binding);
if (fb_offset != -1)
fb_binding.start = fb_offset;
else
fb_binding.start = fb_binding.end;
insert_text_into_fb_at_binding
(fb, &fb_binding, INFO_MENU_LABEL, strlen (INFO_MENU_LABEL));
fb_binding.buffer = fb->contents;
fb_binding.start = 0;
fb_binding.end = fb->filesize;
fb_offset = search_forward (INFO_MENU_LABEL, &fb_binding);
if (fb_offset == -1)
abort ();
}
fb_binding.start = fb_offset;
fb_offset = find_node_separator (&fb_binding);
if (fb_offset != -1)
fb_binding.start = fb_offset;
else
fb_binding.start = fb_binding.end;
{
int num_found = 0;
while ((fb_binding.start > 0) &&
(whitespace_or_newline (fb_binding.buffer[fb_binding.start - 1])))
{
num_found++;
fb_binding.start--;
}
if (num_found >= 2)
{
fb_binding.buffer[fb_binding.start++] = '\n';
fb_binding.buffer[fb_binding.start++] = '\n';
}
else
{
insert_text_into_fb_at_binding (fb, &fb_binding, "\n\n", 2);
fb_binding.start += 2;
}
}
insert_text_into_fb_at_binding
(fb, &fb_binding, contents + contents_offset, size - contents_offset);
}
static void
insert_text_into_fb_at_binding (fb, binding, text, textlen)
FILE_BUFFER *fb;
SEARCH_BINDING *binding;
char *text;
int textlen;
{
char *contents;
long start, end;
start = binding->start;
end = fb->filesize;
contents = (char *)xmalloc (fb->filesize + textlen + 1);
memcpy (contents, fb->contents, start);
memcpy (contents + start, text, textlen);
memcpy (contents + start + textlen, fb->contents + start, end - start);
free (fb->contents);
fb->contents = contents;
fb->filesize += textlen;
fb->finfo.st_size = fb->filesize;
}