Improved layout generated record in SGML/XML format.
[yaz-moved-to-github.git] / retrieval / d1_write.c
1 /*
2  * Copyright (c) 1995-1999, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: d1_write.c,v $
7  * Revision 1.6  1999-07-06 12:16:00  adam
8  * Improved layout generated record in SGML/XML format.
9  *
10  * Revision 1.5  1998/06/05 08:57:43  adam
11  * Fixed problem with function wordlen.
12  *
13  * Revision 1.4  1998/05/18 13:07:08  adam
14  * Changed the way attribute sets are handled by the retriaval module.
15  * Extended Explain conversion / schema.
16  * Modified server and client to work with ASN.1 compiled protocol handlers.
17  *
18  * Revision 1.3  1997/09/17 12:10:39  adam
19  * YAZ version 1.4.
20  *
21  * Revision 1.2  1995/12/13 17:14:27  quinn
22  * *** empty log message ***
23  *
24  * Revision 1.1  1995/12/13  15:38:43  quinn
25  * Added SGML-output filter.
26  *
27  *
28  */
29
30 #include <string.h>
31 #include <ctype.h>
32
33 #include <data1.h>
34 #include <wrbuf.h>
35
36 #define IDSGML_MARGIN 75
37
38 static int wordlen(char *b, int max)
39 {
40     int l = 0;
41
42     while (l < max && !isspace(*b))
43         l++, b++;
44     return l;
45 }
46
47 static int nodetoidsgml(data1_node *n, int select, WRBUF b, int col)
48 {
49     data1_node *c;
50     char line[1024];
51
52     for (c = n->child; c; c = c->next)
53     {
54         char *tag;
55
56         if (c->which == DATA1N_tag)
57         {
58             if (select && c->u.tag.node_selected)
59                 continue;
60             if (c->u.tag.element && c->u.tag.element->tag)
61                 tag = c->u.tag.element->tag->names->name; /* first name */
62             else
63                 tag = c->u.tag.tag; /* local string tag */
64             if (!data1_matchstr(tag, "wellknown")) /* skip wellknown */
65             {
66                 if (nodetoidsgml(c, select, b, col) < 0)
67                     return -1;
68             }
69             else
70             {
71                 sprintf(line, "%*s<%s>\n", col, "", tag);
72                 wrbuf_write(b, line, strlen(line));
73                 if (nodetoidsgml(c, select, b, (col > 40) ? 40 : col+2) < 0)
74                     return -1;
75                 sprintf (line, "%*s</%s>\n", col, "", tag);
76                 wrbuf_write(b, line, strlen(line));
77             }
78         }
79         else if (c->which == DATA1N_data)
80         {
81             char *p = c->u.data.data;
82             int l = c->u.data.len;
83             int first = 1;
84             int lcol = col;
85
86             sprintf(line, "%*s", col, "");
87             wrbuf_write(b, line, strlen(line));
88             switch (c->u.data.what)
89             {
90             case DATA1I_text:
91                 while (l)
92                 {
93                     int wlen;
94                     
95                     while (l && isspace(*p))
96                         p++, l--;
97                     if (!l)
98                         break;
99                     /* break if we'll cross margin and word is not too long */
100                     if (lcol + (wlen = wordlen(p, l)) > IDSGML_MARGIN && wlen <
101                         IDSGML_MARGIN)
102                     {
103                         sprintf(line, "\n%*s", col, "");
104                         lcol = col;
105                         wrbuf_write(b, line, strlen(line));
106                         first = 1;
107                     }
108                     if (!first)
109                     {
110                         wrbuf_putc(b, ' ');
111                         lcol++;
112                     }
113                     while (l && !isspace(*p))
114                     {
115                         wrbuf_putc(b, *p);
116                         p++;
117                         l--;
118                         lcol++;
119                     }
120                     first = 0;
121                 }
122                 wrbuf_write(b, "\n", 1);
123                 break;
124             case DATA1I_num:
125                 wrbuf_write(b, c->u.data.data, c->u.data.len);
126                 break;
127             case DATA1I_oid:
128                 wrbuf_write(b, c->u.data.data, c->u.data.len);
129             }
130         }
131     }
132     return 0;
133 }
134
135 char *data1_nodetoidsgml (data1_handle dh, data1_node *n, int select, int *len)
136 {
137     WRBUF b = data1_get_wrbuf (dh);
138     char line[1024];
139     
140     wrbuf_rewind(b);
141     
142     sprintf(line, "<%s>\n", n->u.root.type);
143     wrbuf_write(b, line, strlen(line));
144     if (nodetoidsgml(n, select, b, 0))
145         return 0;
146     sprintf(line, "</%s>\n", n->u.root.type);
147     wrbuf_write(b, line, strlen(line));
148     *len = wrbuf_len(b);
149     return wrbuf_buf(b);
150 }