~ubuntu-branches/ubuntu/feisty/elinks/feisty-updates

« back to all changes in this revision

Viewing changes to src/viewer/dump/dump.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter Gervai
  • Date: 2004-01-21 22:13:45 UTC
  • Revision ID: james.westby@ubuntu.com-20040121221345-ju33hai1yhhqt6kn
Tags: upstream-0.9.1
ImportĀ upstreamĀ versionĀ 0.9.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Support for dumping to the file on startup (w/o bfu) */
 
2
/* $Id: dump.c,v 1.80.2.2 2004/01/17 22:33:02 pasky Exp $ */
 
3
 
 
4
#ifdef HAVE_CONFIG_H
 
5
#include "config.h"
 
6
#endif
 
7
 
 
8
#include <errno.h>
 
9
#include <stdio.h>
 
10
#include <string.h>
 
11
#include <sys/types.h> /* NetBSD flavour */
 
12
#ifdef HAVE_SYS_SIGNAL_H
 
13
#include <sys/signal.h>
 
14
#endif
 
15
#ifdef HAVE_FCNTL_H
 
16
#include <fcntl.h> /* OS/2 needs this after sys/types.h */
 
17
#endif
 
18
#ifdef HAVE_UNISTD_H
 
19
#include <unistd.h>
 
20
#endif
 
21
 
 
22
#include "elinks.h"
 
23
 
 
24
#include "main.h"
 
25
#include "config/options.h"
 
26
#include "cache/cache.h"
 
27
#include "document/document.h"
 
28
#include "document/options.h"
 
29
#include "document/renderer.h"
 
30
#include "document/view.h"
 
31
#include "intl/gettext/libintl.h"
 
32
#include "lowlevel/select.h"
 
33
#include "osdep/ascii.h"
 
34
#include "osdep/osdep.h"
 
35
#include "protocol/protocol.h"
 
36
#include "protocol/uri.h"
 
37
#include "sched/error.h"
 
38
#include "sched/connection.h"
 
39
#include "terminal/color.h"
 
40
#include "terminal/hardio.h"
 
41
#include "terminal/terminal.h"
 
42
#include "util/memory.h"
 
43
#include "util/string.h"
 
44
#include "viewer/dump/dump.h"
 
45
#include "viewer/text/view.h"
 
46
#include "viewer/text/vs.h"
 
47
 
 
48
 
 
49
static int dump_pos;
 
50
static struct download dump_download;
 
51
static int dump_redir_count = 0;
 
52
 
 
53
 
 
54
/* This dumps the given @ce's source onto @fd nothing more. It returns 0 if it
 
55
 * all went fine and 1 if something isn't quite right and we should terminate
 
56
 * ourselves ASAP. */
 
57
static int
 
58
dump_source(int fd, struct download *status, struct cache_entry *ce)
 
59
{
 
60
        struct fragment *frag;
 
61
 
 
62
        if (!ce) return 0;
 
63
 
 
64
nextfrag:
 
65
        foreach (frag, ce->frag) {
 
66
                int d = dump_pos - frag->offset;
 
67
                int l, w;
 
68
 
 
69
                if (d < 0 || frag->length <= d)
 
70
                        continue;
 
71
 
 
72
                l = frag->length - d;
 
73
                w = hard_write(fd, frag->data + d, l);
 
74
 
 
75
                if (w != l) {
 
76
                        detach_connection(status, dump_pos);
 
77
 
 
78
                        if (w < 0)
 
79
                                ERROR(gettext("Can't write to stdout: %s"),
 
80
                                      (unsigned char *) strerror(errno));
 
81
                        else
 
82
                                ERROR(gettext("Can't write to stdout."));
 
83
 
 
84
                        retval = RET_ERROR;
 
85
                        return 1;
 
86
                }
 
87
 
 
88
                dump_pos += w;
 
89
                detach_connection(status, dump_pos);
 
90
                goto nextfrag;
 
91
        }
 
92
 
 
93
        return 0;
 
94
}
 
95
 
 
96
/* This dumps the given @ce's formatted output onto @fd. It returns 0 if it all
 
97
 * went fine and 1 if something isn't quite right and we should terminate
 
98
 * ourselves ASAP. */
 
99
static int
 
100
dump_formatted(int fd, struct download *status, struct cache_entry *ce)
 
101
{
 
102
        struct document_options o;
 
103
        struct document_view formatted;
 
104
        struct view_state *vs;
 
105
 
 
106
        if (!ce) return 0;
 
107
 
 
108
        /* No need to add a byte for the \0 to the result of strlen():
 
109
         * struct view_state has an unsigned char url[1]. -- Miciah */
 
110
        vs = mem_alloc(sizeof(struct view_state) + strlen(get_cache_uri(ce)));
 
111
        if (!vs) return 1;
 
112
 
 
113
        memset(vs, 0, sizeof(struct view_state));
 
114
        memset(&formatted, 0, sizeof(struct document_view));
 
115
 
 
116
        get_opt_bool("document.browse.links.numbering") =
 
117
                !get_opt_bool_tree(cmdline_options, "no-numbering");
 
118
 
 
119
        init_document_options(&o);
 
120
        o.x = 0;
 
121
        o.y = 1;
 
122
        o.width = get_opt_int("document.dump.width");
 
123
        o.height = 25;
 
124
        o.cp = get_opt_int("document.dump.codepage");
 
125
        o.color_mode = COLOR_MODE_DUMP;
 
126
        o.plain = 0;
 
127
        o.frames = 0;
 
128
 
 
129
        init_vs(vs, get_cache_uri(ce), -1);
 
130
 
 
131
        render_document(vs, &formatted, &o);
 
132
        dump_to_file(formatted.document, fd);
 
133
 
 
134
        detach_formatted(&formatted);
 
135
        destroy_vs(vs);
 
136
        mem_free(vs);
 
137
 
 
138
        return 0;
 
139
}
 
140
 
 
141
void
 
142
dump_end(struct download *status, void *p)
 
143
{
 
144
        struct cache_entry *ce = status->ce;
 
145
        int fd = get_output_handle();
 
146
 
 
147
        if (fd == -1) return;
 
148
        if (ce && ce->redirect && dump_redir_count++ < MAX_REDIRECTS) {
 
149
                unsigned char *u;
 
150
 
 
151
                if (status->state >= 0)
 
152
                        change_connection(status, NULL, PRI_CANCEL, 0);
 
153
 
 
154
                u = join_urls(get_cache_uri(ce), ce->redirect);
 
155
                if (!u) return;
 
156
 
 
157
                if (!ce->redirect_get
 
158
                    && ce->valid
 
159
                    && !get_opt_int("protocol.http.bugs.broken_302_redirect")) {
 
160
                        unsigned char *pc = ce->uri.post;
 
161
 
 
162
                        if (pc) add_to_strn(&u, pc);
 
163
                }
 
164
 
 
165
                load_url(u, get_cache_uri(ce), status, PRI_MAIN, 0, -1);
 
166
                mem_free(u);
 
167
                return;
 
168
        }
 
169
 
 
170
        if (status->state >= 0 && status->state < S_TRANS) return;
 
171
        if (status->state >= S_TRANS
 
172
            && get_opt_int_tree(cmdline_options, "dump"))
 
173
                return;
 
174
 
 
175
        if (get_opt_int_tree(cmdline_options, "source")) {
 
176
                if (dump_source(fd, status, ce) > 0)
 
177
                        goto terminate;
 
178
 
 
179
                if (status->state >= 0)
 
180
                        return;
 
181
 
 
182
        } else {
 
183
                if (dump_formatted(fd, status, ce) > 0)
 
184
                        goto terminate;
 
185
        }
 
186
 
 
187
        if (status->state != S_OK) {
 
188
                ERROR(get_err_msg(status->state, NULL));
 
189
                retval = RET_ERROR;
 
190
                goto terminate;
 
191
        }
 
192
 
 
193
terminate:
 
194
        terminate = 1;
 
195
}
 
196
 
 
197
void
 
198
dump_start(unsigned char *url)
 
199
{
 
200
        unsigned char *real_url = NULL;
 
201
        unsigned char *wd;
 
202
 
 
203
        if (!*url) {
 
204
                ERROR(gettext("URL expected after %s."),
 
205
                        get_opt_int_tree(cmdline_options, "source")
 
206
                        ? "-source" : "-dump");
 
207
                goto terminate;
 
208
        }
 
209
 
 
210
        dump_download.end = dump_end;
 
211
        dump_pos = 0;
 
212
 
 
213
        wd = get_cwd();
 
214
        real_url = translate_url(url, wd);
 
215
        if (wd) mem_free(wd);
 
216
 
 
217
        if (!real_url) real_url = stracpy(url);
 
218
        if (!real_url
 
219
            || known_protocol(real_url, NULL) == PROTOCOL_UNKNOWN
 
220
            || load_url(real_url, NULL, &dump_download, PRI_MAIN, 0, -1)) {
 
221
terminate:
 
222
                terminate = 1;
 
223
                retval = RET_SYNTAX;
 
224
        }
 
225
 
 
226
        if (real_url) mem_free(real_url);
 
227
}
 
228
 
 
229
/* Using this function in dump_to_file() is unfortunately slightly slower than
 
230
 * the current code.  However having this here instead of in the scripting
 
231
 * backends is better. */
 
232
struct string *
 
233
add_document_to_string(struct string *string, struct document *document)
 
234
{
 
235
        int y;
 
236
 
 
237
        assert(string && document);
 
238
        if_assert_failed return NULL;
 
239
 
 
240
        for (y = 0; y < document->height; y++) {
 
241
                struct screen_char *pos = document->data[y].chars;
 
242
                int x;
 
243
 
 
244
                for (x = 0; x < document->data[y].length; x++) {
 
245
                        unsigned char data = pos->data;
 
246
                        unsigned int frame = (pos->attr & SCREEN_ATTR_FRAME);
 
247
 
 
248
                        if (data < ' ' || data == ASCII_DEL) {
 
249
                                data = ' ';
 
250
                        } else if (frame && data >= 176 && data < 224) {
 
251
                                data = frame_dumb[data - 176];
 
252
                        }
 
253
 
 
254
                        add_char_to_string(string, data);
 
255
                }
 
256
 
 
257
                add_char_to_string(string, '\n');
 
258
        }
 
259
 
 
260
        return string;
 
261
}
 
262
 
 
263
int
 
264
dump_to_file(struct document *document, int fd)
 
265
{
 
266
#define D_BUF   65536
 
267
 
 
268
        int x, y;
 
269
        int bptr = 0;
 
270
        unsigned char *buf = mem_alloc(D_BUF);
 
271
 
 
272
        if (!buf) return -1;
 
273
 
 
274
        for (y = 0; y < document->height; y++) {
 
275
                for (x = 0; x <= document->data[y].length; x++) {
 
276
                        unsigned char c;
 
277
 
 
278
                        if (x == document->data[y].length) {
 
279
                                c = '\n';
 
280
                        } else {
 
281
                                unsigned char attr = document->data[y].chars[x].attr;
 
282
 
 
283
                                c = document->data[y].chars[x].data;
 
284
 
 
285
                                if ((attr & SCREEN_ATTR_FRAME)
 
286
                                    && c >= 176 && c < 224)
 
287
                                        c = frame_dumb[c - 176];
 
288
                        }
 
289
 
 
290
                        buf[bptr++] = c;
 
291
                        if (bptr >= D_BUF) {
 
292
                                if (hard_write(fd, buf, bptr) != bptr)
 
293
                                        goto fail;
 
294
                                bptr = 0;
 
295
                        }
 
296
                }
 
297
        }
 
298
 
 
299
        if (hard_write(fd, buf, bptr) != bptr) {
 
300
fail:
 
301
                mem_free(buf);
 
302
                return -1;
 
303
        }
 
304
 
 
305
        if (get_opt_bool("document.browse.links.numbering")
 
306
            && document->nlinks) {
 
307
                char *header = "\nReferences\n\n   Visible links\n";
 
308
                int headlen = strlen(header);
 
309
 
 
310
                if (hard_write(fd, header, headlen) != headlen)
 
311
                        goto fail;
 
312
 
 
313
                for (x = 0; x < document->nlinks; x++) {
 
314
                        struct link *l = &document->links[x];
 
315
                        unsigned char *where = l->where;
 
316
 
 
317
                        if (!where) continue;
 
318
 
 
319
                        if (strlen(where) > 4 && !memcmp(where, "MAP@", 4))
 
320
                                where += 4;
 
321
 
 
322
                        if (l->title && *l->title)
 
323
                                snprintf(buf, D_BUF, "%4d. %s\n\t%s\n",
 
324
                                         x + 1, l->title, where);
 
325
                        else
 
326
                                snprintf(buf, D_BUF, "%4d. %s\n",
 
327
                                         x + 1, where);
 
328
                        bptr = strlen(buf);
 
329
                        if (hard_write(fd, buf, bptr) != bptr)
 
330
                                goto fail;
 
331
                }
 
332
        }
 
333
 
 
334
        mem_free(buf);
 
335
        return 0;
 
336
 
 
337
#undef D_BUF
 
338
}