-/* Opens a file handle for writing as a data file. */
-int
-dfm_open_for_writing (struct file_handle *h)
-{
- struct dfm_fhuser_ext *ext;
-
- if (h->class != NULL)
- {
- if (h->class == &dfm_w_class)
- return 1;
- else
- {
- msg (ME, _("Cannot write to file %s already opened for %s."),
- handle_get_name (h), gettext (h->class->name));
- err_cond_fail ();
- return 0;
- }
- }
-
- ext = xmalloc (sizeof *ext);
- ext->where.filename = handle_get_filename (h);
- ext->where.line_number = 0;
- ext->file.file = NULL;
- ext->line = NULL;
- ext->len = 0;
- ext->ptr = NULL;
- ext->size = 0;
- ext->advance = 0;
-
- msg (VM (1), _("%s: Opening data-file handle %s for writing."),
- handle_get_filename (h), handle_get_name (h));
-
- assert (h != NULL);
- if (h == inline_file)
- {
- msg (ME, _("Cannot open the inline file for writing."));
- goto error;
- }
-
- ext->file.filename = xstrdup (handle_get_filename (h));
- ext->file.mode = "wb";
- ext->file.file = NULL;
- ext->file.sequence_no = NULL;
- ext->file.param = NULL;
- ext->file.postopen = NULL;
- ext->file.preclose = NULL;
-
- if (!fn_open_ext (&ext->file))
- {
- msg (ME, _("An error occurred while opening \"%s\" for writing "
- "as a data file: %s."),
- handle_get_filename (h), strerror (errno));
- goto error;
- }
-
- h->class = &dfm_w_class;
- h->ext = ext;
- return 1;
-
- error:
- free (ext);
- err_cond_fail ();
- return 0;
-}
-
-/* Ensures that the line buffer in file handle with extension EXT is
- big enough to hold a line of length EXT->LEN characters not
- including null terminator. */
-#define force_line_buffer_expansion() \
- do \
- { \
- if (ext->len + 1 > ext->size) \
- { \
- ext->size = ext->len * 2; \
- ext->line = xrealloc (ext->line, ext->size); \
- } \
- } \
- while (0)
-
-/* Counts the number of tabs in string STRING of length LEN. */
-static inline int
-count_tabs (char *s, size_t len)
-{
- int n_tabs = 0;
-
- for (;;)
- {
- char *cp = memchr (s, '\t', len);
- if (cp == NULL)
- return n_tabs;
- n_tabs++;
- len -= cp - s + 1;
- s = cp + 1;
- }
-}
-
-/* Converts all the tabs in H->EXT->LINE to an equivalent number of
- spaces, if necessary. */
-static void
-tabs_to_spaces (struct file_handle *h)
-{
- struct dfm_fhuser_ext *ext = h->ext;
-
- char *first_tab; /* Location of first tab (if any). */
- char *second_tab; /* Location of second tab (if any). */
- size_t orig_len; /* Line length at function entry. */
-
- /* If there aren't any tabs then there's nothing to do. */
- first_tab = memchr (ext->line, '\t', ext->len);
- if (first_tab == NULL)
- return;
- orig_len = ext->len;
-
- /* If there's just one tab then expand it inline. Otherwise do a
- full string copy to another buffer. */
- second_tab = memchr (first_tab + 1, '\t',
- ext->len - (first_tab - ext->line + 1));
- if (second_tab == NULL)
- {
- int n_spaces = 8 - (first_tab - ext->line) % 8;
-
- ext->len += n_spaces - 1;
-
- /* Expand the line if necessary, keeping the first_tab pointer
- valid. */
- {
- size_t ofs = first_tab - ext->line;
- force_line_buffer_expansion ();
- first_tab = ext->line + ofs;
- }
-
- memmove (first_tab + n_spaces, first_tab + 1,
- orig_len - (first_tab - ext->line + 1));
- memset (first_tab, ' ', n_spaces);
- } else {
- /* Make a local copy of original text. */
- char *orig_line = local_alloc (ext->len + 1);
- memcpy (orig_line, ext->line, ext->len);
-
- /* Allocate memory assuming we need to add 8 spaces for every tab. */
- ext->len += 2 + count_tabs (second_tab + 1,
- ext->len - (second_tab - ext->line + 1));
-
- /* Expand the line if necessary, keeping the first_tab pointer
- valid. */
- {
- size_t ofs = first_tab - ext->line;
- force_line_buffer_expansion ();
- first_tab = ext->line + ofs;
- }
-
- /* Walk through orig_line, expanding tabs into ext->line. */
- {
- char *src_p = orig_line + (first_tab - ext->line);
- char *dest_p = first_tab;
-
- for (; src_p < orig_line + orig_len; src_p++)
- {
- /* Most characters simply pass through untouched. */
- if (*src_p != '\t')
- {
- *dest_p++ = *src_p;
- continue;
- }
-
- /* Tabs are expanded into an equivalent number of
- spaces. */
- {
- int n_spaces = 8 - (dest_p - ext->line) % 8;
-
- memset (dest_p, ' ', n_spaces);
- dest_p += n_spaces;
- }
- }
-
- /* Supply null terminator and actual string length. */
- *dest_p = 0;
- ext->len = dest_p - ext->line;
- }
-
- local_free (orig_line);
- }
-}
-