1 /*
2 * wordout.c
3 *
4 * (Word 2007 format)
5 *
6 * Copyright (c) Chris Putnam 2007-2021
7 *
8 * Source code released under the GPL version 2
9 *
10 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "str.h"
15 #include "fields.h"
16 #include "month.h"
17 #include "utf8.h"
18 #include "bibformats.h"
19
20 /*****************************************************
21 PUBLIC: int wordout_initparams()
22 *****************************************************/
23
24 static void wordout_writeheader( FILE *outptr, param *p );
25 static void wordout_writefooter( FILE *outptr );
26 static int wordout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs );
27
28 int
wordout_initparams(param * pm,const char * progname)29 wordout_initparams( param *pm, const char *progname )
30 {
31 pm->writeformat = BIBL_WORD2007OUT;
32 pm->format_opts = 0;
33 pm->charsetout = BIBL_CHARSET_UNICODE;
34 pm->charsetout_src = BIBL_SRC_DEFAULT;
35 pm->latexout = 0;
36 pm->utf8out = BIBL_CHARSET_UTF8_DEFAULT;
37 pm->utf8bom = BIBL_CHARSET_BOM_DEFAULT;
38 if ( !pm->utf8out )
39 pm->xmlout = BIBL_XMLOUT_ENTITIES;
40 else
41 pm->xmlout = BIBL_XMLOUT_TRUE;
42 pm->nosplittitle = 0;
43 pm->verbose = 0;
44 pm->addcount = 0;
45 pm->singlerefperfile = 0;
46
47 pm->headerf = wordout_writeheader;
48 pm->footerf = wordout_writefooter;
49 pm->assemblef = NULL;
50 pm->writef = wordout_write;
51
52 if ( !pm->progname ) {
53 if ( !progname ) pm->progname = NULL;
54 else {
55 pm->progname = strdup( progname );
56 if ( !pm->progname ) return BIBL_ERR_MEMERR;
57 }
58 }
59
60 return BIBL_OK;
61 }
62
63 /*****************************************************
64 PUBLIC: int wordout_write()
65 *****************************************************/
66
67 typedef struct convert {
68 char *oldtag;
69 char *newtag;
70 char *prefix;
71 int code;
72 } convert;
73
74 /*
75 At the moment 17 unique types of sources are defined:
76
77 {code}
78 Art
79 ArticleInAPeriodical
80 Book
81 BookSection
82 Case
83 Conference
84 DocumentFromInternetSite
85 ElectronicSource
86 Film
87 InternetSite
88 Interview
89 JournalArticle
90 Report
91 Misc
92 Patent
93 Performance
94 Proceedings
95 SoundRecording
96 {code}
97
98 */
99
100 enum {
101 TYPE_UNKNOWN = 0,
102 TYPE_ART,
103 TYPE_ARTICLEINAPERIODICAL,
104 TYPE_BOOK,
105 TYPE_BOOKSECTION,
106 TYPE_CASE,
107 TYPE_CONFERENCE,
108 TYPE_DOCUMENTFROMINTERNETSITE,
109 TYPE_ELECTRONICSOURCE,
110 TYPE_FILM,
111 TYPE_INTERNETSITE,
112 TYPE_INTERVIEW,
113 TYPE_JOURNALARTICLE,
114 TYPE_MISC,
115 TYPE_PATENT,
116 TYPE_PERFORMANCE,
117 TYPE_PROCEEDINGS,
118 TYPE_REPORT,
119 TYPE_SOUNDRECORDING,
120
121 TYPE_THESIS,
122 TYPE_MASTERSTHESIS,
123 TYPE_PHDTHESIS,
124 };
125
126 static void
output_level(FILE * outptr,int level)127 output_level( FILE *outptr, int level )
128 {
129 int i;
130 for ( i=0; i<level; ++i )
131 fprintf( outptr, " " );
132 }
133
134 /* fixed output
135 *
136 * <TAG>value</TAG>
137 */
138 static void
output_fixed(FILE * outptr,const char * tag,const char * value,int level)139 output_fixed( FILE *outptr, const char *tag, const char *value, int level )
140 {
141 output_level( outptr, level );
142 fprintf( outptr, "<%s>%s</%s>\n", tag, value, tag );
143 }
144
145 /* detail output
146 *
147 * <TAG>value</TAG>
148 */
149 static void
output_item(fields * info,FILE * outptr,const char * tag,const char * prefix,int item,int level)150 output_item( fields *info, FILE *outptr, const char *tag, const char *prefix, int item, int level )
151 {
152 if ( item!=-1 ) {
153 output_level( outptr, level );
154 fprintf( outptr, "<%s>%s%s</%s>\n",
155 tag,
156 prefix,
157 (char*) fields_value( info, item, FIELDS_CHRP ),
158 tag
159 );
160 }
161 }
162
163 static void
output_itemv(FILE * outptr,const char * tag,const char * item,int level)164 output_itemv( FILE *outptr, const char *tag, const char *item, int level )
165 {
166 output_level( outptr, level );
167 fprintf( outptr, "<%s>%s</%s>\n", tag, item, tag );
168 }
169
170 /* range output
171 *
172 * <TAG>start-end</TAG>
173 *
174 */
175 static void
output_nodash(FILE * outptr,const char * p)176 output_nodash( FILE *outptr, const char *p )
177 {
178 while ( *p ) {
179 /* -30 is the first character of a UTF8 em-dash and en-dash */
180 if ( *p==-30 && ( utf8_is_emdash( p ) || utf8_is_endash( p ) ) ) {
181 fprintf( outptr, "-" );
182 p+=3;
183 } else {
184 fprintf( outptr, "%c", *p );
185 p+=1;
186 }
187 }
188 }
189 static void
output_range(FILE * outptr,const char * tag,const char * start,const char * end,int level)190 output_range( FILE *outptr, const char *tag, const char *start, const char *end, int level )
191 {
192 if ( !start && !end ) return;
193 fprintf( outptr, "<%s>", tag );
194 if ( start ) output_nodash( outptr, start );
195 if ( start && end ) fprintf( outptr, "-" );
196 if ( end ) output_nodash( outptr, end );
197 fprintf( outptr, "</%s>\n", tag );
198 }
199
200 static void
output_list(fields * info,FILE * outptr,convert * c,int nc)201 output_list( fields *info, FILE *outptr, convert *c, int nc )
202 {
203 int i, n;
204 for ( i=0; i<nc; ++i ) {
205 n = fields_find( info, c[i].oldtag, c[i].code );
206 if ( n!=FIELDS_NOTFOUND ) output_item( info, outptr, c[i].newtag, c[i].prefix, n, 0 );
207 }
208
209 }
210
211 typedef struct outtype {
212 int value;
213 const char *out;
214 } outtype;
215
216 static
217 outtype genres[] = {
218 { TYPE_PATENT, "patent" },
219 { TYPE_REPORT, "report" },
220 { TYPE_REPORT, "technical report" },
221 { TYPE_CASE, "legal case and case notes" },
222 { TYPE_ART, "art original" },
223 { TYPE_ART, "art reproduction" },
224 { TYPE_ART, "comic strip" },
225 { TYPE_ART, "diorama" },
226 { TYPE_ART, "graphic" },
227 { TYPE_ART, "model" },
228 { TYPE_ART, "picture" },
229 { TYPE_ELECTRONICSOURCE, "electronic" },
230 { TYPE_FILM, "videorecording" },
231 { TYPE_FILM, "motion picture" },
232 { TYPE_SOUNDRECORDING, "sound" },
233 { TYPE_PERFORMANCE, "rehersal" },
234 { TYPE_INTERNETSITE, "web site" },
235 { TYPE_INTERVIEW, "interview" },
236 { TYPE_INTERVIEW, "communication" },
237 { TYPE_MISC, "misc" },
238 };
239 int ngenres = sizeof( genres ) / sizeof( genres[0] );
240
241 static int
get_type_from_genre(fields * info)242 get_type_from_genre( fields *info )
243 {
244 int type = TYPE_UNKNOWN, i, j, level;
245 const char *genre, *tag;
246 for ( i=0; i<info->n; ++i ) {
247 tag = (const char *) fields_tag( info, i, FIELDS_CHRP );
248 if ( strcasecmp( tag, "GENRE:MARC" ) && strcasecmp( tag, "GENRE:BIBUTILS" ) && strcasecmp( tag, "GENRE:UNKNOWN" ) ) continue;
249 genre = (const char *) fields_value( info, i, FIELDS_CHRP );
250 for ( j=0; j<ngenres; ++j ) {
251 if ( !strcasecmp( genres[j].out, genre ) )
252 type = genres[j].value;
253 }
254 if ( type==TYPE_UNKNOWN ) {
255 level = fields_level( info, i );
256 if ( !strcasecmp( genre, "academic journal" ) ) {
257 type = TYPE_JOURNALARTICLE;
258 }
259 else if ( !strcasecmp( genre, "periodical" ) ) {
260 if ( type == TYPE_UNKNOWN )
261 type = TYPE_ARTICLEINAPERIODICAL;
262 }
263 else if ( !strcasecmp( genre, "book" ) ||
264 !strcasecmp( genre, "collection" ) ) {
265 if ( fields_level( info, i ) == 0 ) type = TYPE_BOOK;
266 else type = TYPE_BOOKSECTION;
267 }
268 else if ( !strcasecmp( genre, "conference publication" ) ) {
269 if ( level==0 ) type=TYPE_CONFERENCE;
270 else type = TYPE_PROCEEDINGS;
271 }
272 else if ( !strcasecmp( genre, "thesis" ) ) {
273 if ( type==TYPE_UNKNOWN ) type=TYPE_THESIS;
274 }
275 else if ( !strcasecmp( genre, "Ph.D. thesis" ) ) {
276 type = TYPE_PHDTHESIS;
277 }
278 else if ( !strcasecmp( genre, "Masters thesis" ) ) {
279 type = TYPE_MASTERSTHESIS;
280 }
281 }
282 }
283 return type;
284 }
285
286 static int
get_type_from_resource(fields * info)287 get_type_from_resource( fields *info )
288 {
289 int type = TYPE_UNKNOWN, i;
290 char *tag, *resource;
291 for ( i=0; i<info->n; ++i ) {
292 tag = (char *) fields_tag( info, i, FIELDS_CHRP );
293 if ( strcasecmp( tag, "RESOURCE" ) ) continue;
294 resource = (char *) fields_value( info, i, FIELDS_CHRP );
295 if ( !strcasecmp( resource, "moving image" ) )
296 type = TYPE_FILM;
297 }
298 return type;
299 }
300
301 static int
get_type(fields * info)302 get_type( fields *info )
303 {
304 int type;
305 type = get_type_from_genre( info );
306 if ( type==TYPE_UNKNOWN )
307 type = get_type_from_resource( info );
308 return type;
309 }
310
311 static void
output_titlebits(const char * mainttl,const char * subttl,FILE * outptr)312 output_titlebits( const char *mainttl, const char *subttl, FILE *outptr )
313 {
314 if ( mainttl ) fprintf( outptr, "%s", mainttl );
315 if ( subttl ) {
316 if ( mainttl ) {
317 if ( mainttl[ strlen( mainttl ) - 1 ] != '?' )
318 fprintf( outptr, ": " );
319 else fprintf( outptr, " " );
320 }
321 fprintf( outptr, "%s", subttl );
322 }
323 }
324
325 static void
output_titleinfo(const char * mainttl,const char * subttl,FILE * outptr,const char * tag,int level)326 output_titleinfo( const char *mainttl, const char *subttl, FILE *outptr, const char *tag, int level )
327 {
328 if ( mainttl || subttl ) {
329 fprintf( outptr, "<%s>", tag );
330 output_titlebits( mainttl, subttl, outptr );
331 fprintf( outptr, "</%s>\n", tag );
332 }
333 }
334
335 static void
output_generaltitle(fields * info,FILE * outptr,const char * tag,int level)336 output_generaltitle( fields *info, FILE *outptr, const char *tag, int level )
337 {
338 const char *ttl = fields_findv( info, level, FIELDS_CHRP, "TITLE" );
339 const char *subttl = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );
340 const char *shrttl = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );
341 const char *shrsubttl = fields_findv( info, level, FIELDS_CHRP, "SHORTSUBTITLE" );
342
343 if ( ttl ) {
344 output_titleinfo( ttl, subttl, outptr, tag, level );
345 }
346 else if ( shrttl ) {
347 output_titleinfo( shrttl, shrsubttl, outptr, tag, level );
348 }
349 }
350
351 static void
output_maintitle(fields * info,FILE * outptr,int level)352 output_maintitle( fields *info, FILE *outptr, int level )
353 {
354 const char *ttl = fields_findv( info, level, FIELDS_CHRP, "TITLE" );
355 const char *subttl = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );
356 const char *shrttl = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );
357 const char *shrsubttl = fields_findv( info, level, FIELDS_CHRP, "SHORTSUBTITLE" );
358
359 if ( ttl ) {
360 output_titleinfo( ttl, subttl, outptr, "b:Title", level );
361
362 /* output shorttitle if it's different from normal title */
363 if ( shrttl ) {
364 if ( !ttl || ( strcmp( shrttl, ttl ) || subttl ) ) {
365 fprintf( outptr, " <b:ShortTitle>" );
366 output_titlebits( shrttl, shrsubttl, outptr );
367 fprintf( outptr, "</b:ShortTitle>\n" );
368 }
369 }
370 }
371 else if ( shrttl ) {
372 output_titleinfo( shrttl, shrsubttl, outptr, "b:Title", level );
373 }
374 }
375
376 static void
output_name_nomangle(FILE * outptr,const char * p)377 output_name_nomangle( FILE *outptr, const char *p )
378 {
379 fprintf( outptr, "<b:Person>" );
380 fprintf( outptr, "<b:Last>%s</b:Last>", p );
381 fprintf( outptr, "</b:Person>\n" );
382 }
383
384 static void
output_name(FILE * outptr,const char * p)385 output_name( FILE *outptr, const char *p )
386 {
387 str family, part;
388 int n=0, npart=0;
389
390 str_init( &family );
391 while ( *p && *p!='|' ) str_addchar( &family, *p++ );
392 if ( *p=='|' ) p++;
393 if ( str_has_value( &family ) ) {
394 fprintf( outptr, "<b:Person>" );
395 fprintf( outptr, "<b:Last>%s</b:Last>", str_cstr( &family ) );
396 n++;
397 }
398 str_free( &family );
399
400 str_init( &part );
401 while ( *p ) {
402 while ( *p && *p!='|' ) str_addchar( &part, *p++ );
403 if ( str_has_value( &part ) ) {
404 if ( n==0 ) fprintf( outptr, "<b:Person>" );
405 if ( npart==0 )
406 fprintf( outptr, "<b:First>%s</b:First>", str_cstr( &part ) );
407 else
408 fprintf( outptr, "<b:Middle>%s</b:Middle>", str_cstr( &part ) );
409 n++;
410 npart++;
411 }
412 if ( *p=='|' ) {
413 p++;
414 str_empty( &part );
415 }
416 }
417 if ( n ) fprintf( outptr, "</b:Person>\n" );
418
419 str_free( &part );
420 }
421
422
423 #define NAME (1)
424 #define NAME_ASIS (2)
425 #define NAME_CORP (4)
426
427 static int
extract_name_and_info(str * outtag,str * intag)428 extract_name_and_info( str *outtag, str *intag )
429 {
430 int code = NAME;
431 str_strcpy( outtag, intag );
432 if ( str_findreplace( outtag, ":ASIS", "" ) ) code = NAME_ASIS;
433 if ( str_findreplace( outtag, ":CORP", "" ) ) code = NAME_CORP;
434 return code;
435 }
436
437 static void
output_name_type(fields * info,FILE * outptr,int level,char * map[],int nmap,const char * tag)438 output_name_type( fields *info, FILE *outptr, int level, char *map[], int nmap, const char *tag )
439 {
440 str ntag;
441 int i, j, n=0, code, nfields;
442 str_init( &ntag );
443 nfields = fields_num( info );
444 for ( j=0; j<nmap; ++j ) {
445 for ( i=0; i<nfields; ++i ) {
446 code = extract_name_and_info( &ntag, fields_tag( info, i, FIELDS_STRP ) );
447 if ( strcasecmp( str_cstr( &ntag ), map[j] ) ) continue;
448 if ( n==0 )
449 fprintf( outptr, "<%s><b:NameList>\n", tag );
450 if ( code != NAME )
451 output_name_nomangle( outptr, (char *) fields_value( info, i, FIELDS_CHRP ) );
452 else
453 output_name( outptr, (char *) fields_value( info, i, FIELDS_CHRP ) );
454 n++;
455 }
456 }
457 str_free( &ntag );
458 if ( n )
459 fprintf( outptr, "</b:NameList></%s>\n", tag );
460 }
461
462 static void
output_names(fields * info,FILE * outptr,int level,int type)463 output_names( fields *info, FILE *outptr, int level, int type )
464 {
465 char *authors[] = { "AUTHOR", "WRITER", "ASSIGNEE", "ARTIST",
466 "CARTOGRAPHER", "INVENTOR", "ORGANIZER", "DIRECTOR",
467 "PERFORMER", "REPORTER", "TRANSLATOR", "ADDRESSEE",
468 "2ND_AUTHOR", "3RD_AUTHOR", "SUB_AUTHOR", "COMMITTEE",
469 "COURT", "LEGISLATIVEBODY" };
470 int nauthors = sizeof( authors ) / sizeof( authors[0] );
471
472 char *editors[] = { "EDITOR" };
473 int neditors = sizeof( editors ) / sizeof( editors[0] );
474
475 char author_default[] = "b:Author", inventor[] = "b:Inventor";
476 char *author_type = author_default;
477
478 if ( type == TYPE_PATENT ) author_type = inventor;
479
480 fprintf( outptr, "<b:Author>\n" );
481 output_name_type( info, outptr, level, authors, nauthors, author_type );
482 output_name_type( info, outptr, level, editors, neditors, "b:Editor" );
483 fprintf( outptr, "</b:Author>\n" );
484 }
485
486 static void
output_date(fields * info,FILE * outptr,int level)487 output_date( fields *info, FILE *outptr, int level )
488 {
489 const char *use;
490
491 const char *year = fields_findv_firstof( info, level, FIELDS_CHRP,
492 "PARTDATE:YEAR", "DATE:YEAR", NULL );
493 const char *month = fields_findv_firstof( info, level, FIELDS_CHRP,
494 "PARTDATE:MONTH", "DATE:MONTH", NULL );
495 const char *day = fields_findv_firstof( info, level, FIELDS_CHRP,
496 "PARTDATE:DAY", "DATE:DAY", NULL );
497 if ( year ) output_itemv( outptr, "b:Year", year, 0 );
498 if ( month ) {
499 (void) number_to_full_month( month, &use );
500 output_itemv( outptr, "b:Month", use, 0 );
501 }
502 if ( day ) output_itemv( outptr, "b:Day", day, 0 );
503 }
504
505 static void
output_pages(fields * info,FILE * outptr,int level)506 output_pages( fields *info, FILE *outptr, int level )
507 {
508 const char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGES:START" );
509 const char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGES:STOP" );
510 const char *ar = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
511 if ( sn || en )
512 output_range( outptr, "b:Pages", sn, en, level );
513 else if ( ar )
514 output_range( outptr, "b:Pages", ar, NULL, level );
515 }
516
517 static void
output_includedin(fields * info,FILE * outptr,int type)518 output_includedin( fields *info, FILE *outptr, int type )
519 {
520 if ( type==TYPE_JOURNALARTICLE ) {
521 output_generaltitle( info, outptr, "b:JournalName", 1 );
522 } else if ( type==TYPE_ARTICLEINAPERIODICAL ) {
523 output_generaltitle( info, outptr, "b:PeriodicalTitle", 1 );
524 } else if ( type==TYPE_BOOKSECTION ) {
525 output_generaltitle( info, outptr, "b:ConferenceName", 1 ); /*??*/
526 } else if ( type==TYPE_PROCEEDINGS ) {
527 output_generaltitle( info, outptr, "b:ConferenceName", 1 );
528 }
529 }
530
531 static int
type_is_thesis(int type)532 type_is_thesis( int type )
533 {
534 if ( type==TYPE_THESIS ||
535 type==TYPE_PHDTHESIS ||
536 type==TYPE_MASTERSTHESIS )
537 return 1;
538 else
539 return 0;
540 }
541
542 static void
output_thesisdetails(fields * info,FILE * outptr,int type)543 output_thesisdetails( fields *info, FILE *outptr, int type )
544 {
545 char *tag;
546 int i, n;
547
548 if ( type==TYPE_PHDTHESIS )
549 output_fixed( outptr, "b:ThesisType", "Ph.D. Thesis", 0 );
550 else if ( type==TYPE_MASTERSTHESIS )
551 output_fixed( outptr, "b:ThesisType", "Masters Thesis", 0 );
552
553 n = fields_num( info );
554 for ( i=0; i<n; ++i ) {
555 tag = fields_tag( info, i, FIELDS_CHRP );
556 if ( strcasecmp( tag, "DEGREEGRANTOR" ) &&
557 strcasecmp( tag, "DEGREEGRANTOR:ASIS") &
558 strcasecmp( tag, "DEGREEGRANTOR:CORP"))
559 continue;
560 output_item( info, outptr, "b:Institution", "", i, 0 );
561 }
562 }
563
564 static
565 outtype types[] = {
566 { TYPE_UNKNOWN, "Misc" },
567 { TYPE_MISC, "Misc" },
568 { TYPE_BOOK, "Book" },
569 { TYPE_BOOKSECTION, "BookSection" },
570 { TYPE_CASE, "Case" },
571 { TYPE_CONFERENCE, "Conference" },
572 { TYPE_ELECTRONICSOURCE, "ElectronicSource" },
573 { TYPE_FILM, "Film" },
574 { TYPE_INTERNETSITE, "InternetSite" },
575 { TYPE_INTERVIEW, "Interview" },
576 { TYPE_SOUNDRECORDING, "SoundRecording" },
577 { TYPE_ARTICLEINAPERIODICAL, "ArticleInAPeriodical" },
578 { TYPE_DOCUMENTFROMINTERNETSITE, "DocumentFromInternetSite" },
579 { TYPE_JOURNALARTICLE, "JournalArticle" },
580 { TYPE_REPORT, "Report" },
581 { TYPE_PATENT, "Patent" },
582 { TYPE_PERFORMANCE, "Performance" },
583 { TYPE_PROCEEDINGS, "Proceedings" },
584 };
585 static
586 int ntypes = sizeof( types ) / sizeof( types[0] );
587
588 static void
output_type(fields * info,FILE * outptr,int type)589 output_type( fields *info, FILE *outptr, int type )
590 {
591 int i, found = 0;
592 fprintf( outptr, "<b:SourceType>" );
593 for ( i=0; i<ntypes && !found; ++i ) {
594 if ( types[i].value!=type ) continue;
595 found = 1;
596 fprintf( outptr, "%s", types[i].out );
597 }
598 if ( !found ) {
599 if ( type_is_thesis( type ) ) fprintf( outptr, "Report" );
600 else fprintf( outptr, "Misc" );
601 }
602 fprintf( outptr, "</b:SourceType>\n" );
603
604 if ( type_is_thesis( type ) )
605 output_thesisdetails( info, outptr, type );
606 }
607
608 static void
output_comments(fields * info,FILE * outptr,int level)609 output_comments( fields *info, FILE *outptr, int level )
610 {
611 const char *abs;
612 vplist_index i;
613 vplist notes;
614
615 vplist_init( ¬es );
616
617 abs = fields_findv( info, level, FIELDS_CHRP, "ABSTRACT" );
618 fields_findv_each( info, level, FIELDS_CHRP, ¬es, "NOTES" );
619
620 if ( abs || notes.n ) fprintf( outptr, "<b:Comments>" );
621 if ( abs ) fprintf( outptr, "%s", abs );
622 for ( i=0; i<notes.n; ++i )
623 fprintf( outptr, "%s", (char*)vplist_get( ¬es, i ) );
624 if ( abs || notes.n ) fprintf( outptr, "</b:Comments>\n" );
625
626 vplist_free( ¬es );
627 }
628
629 static void
output_bibkey(fields * info,FILE * outptr)630 output_bibkey( fields *info, FILE *outptr )
631 {
632 const char *bibkey = fields_findv_firstof( info, LEVEL_ANY, FIELDS_CHRP,
633 "REFNUM", "BIBKEY", NULL );
634 if ( bibkey ) output_itemv( outptr, "b:Tag", bibkey, 0 );
635 }
636
637 static void
output_citeparts(fields * info,FILE * outptr,int level,int max,int type)638 output_citeparts( fields *info, FILE *outptr, int level, int max, int type )
639 {
640 convert origin[] = {
641 { "ADDRESS", "b:City", "", LEVEL_ANY },
642 { "PUBLISHER", "b:Publisher", "", LEVEL_ANY },
643 { "EDITION", "b:Edition", "", LEVEL_ANY }
644 };
645 int norigin = sizeof( origin ) / sizeof ( convert );
646
647 convert parts[] = {
648 { "VOLUME", "b:Volume", "", LEVEL_ANY },
649 { "SECTION", "b:Section", "", LEVEL_ANY },
650 { "ISSUE", "b:Issue", "", LEVEL_ANY },
651 { "NUMBER", "b:Issue", "", LEVEL_ANY },
652 { "PUBLICLAWNUMBER", "b:Volume", "", LEVEL_ANY },
653 { "SESSION", "b:Issue", "", LEVEL_ANY },
654 { "URL", "b:Url", "", LEVEL_ANY },
655 { "JSTOR", "b:Url", "http://www.jstor.org/stable/", LEVEL_ANY },
656 { "ARXIV", "b:Url", "http://arxiv.org/abs/", LEVEL_ANY },
657 { "PMID", "b:Url", "http://www.ncbi.nlm.nih.gov/pubmed/", LEVEL_ANY },
658 { "PMC", "b:Url", "http://www.ncbi.nlm.nih.gov/pmc/articles/", LEVEL_ANY },
659 { "DOI", "b:Url", "https://doi.org/", LEVEL_ANY },
660 { "MRNUMBER", "b:Url", "http://www.ams.org/mathscinet-getitem?mr=", LEVEL_ANY },
661 };
662 int nparts=sizeof(parts)/sizeof(convert);
663
664 output_bibkey( info, outptr );
665 output_type( info, outptr, type );
666 output_list( info, outptr, origin, norigin );
667 output_date( info, outptr, level );
668 output_includedin( info, outptr, type );
669 output_list( info, outptr, parts, nparts );
670 output_pages( info, outptr, level );
671 output_names( info, outptr, level, type );
672 output_maintitle( info, outptr, 0 );
673 output_comments( info, outptr, level );
674 }
675
676 static int
wordout_write(fields * info,FILE * outptr,param * p,unsigned long numrefs)677 wordout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs )
678 {
679 int max = fields_maxlevel( info );
680 int type = get_type( info );
681
682 fprintf( outptr, "<b:Source>\n" );
683 output_citeparts( info, outptr, -1, max, type );
684 fprintf( outptr, "</b:Source>\n" );
685
686 fflush( outptr );
687
688 return BIBL_OK;
689 }
690
691 /*****************************************************
692 PUBLIC: void wordout_writeheader()
693 *****************************************************/
694
695 static void
wordout_writeheader(FILE * outptr,param * p)696 wordout_writeheader( FILE *outptr, param *p )
697 {
698 if ( p->utf8bom ) utf8_writebom( outptr );
699 fprintf(outptr,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
700 fprintf(outptr,"<b:Sources SelectedStyle=\"\" "
701 "xmlns:b=\"http://schemas.openxmlformats.org/officeDocument/2006/bibliography\" "
702 " xmlns=\"http://schemas.openxmlformats.org/officeDocument/2006/bibliography\" >\n");
703 }
704
705 /*****************************************************
706 PUBLIC: void wordout_writefooter()
707 *****************************************************/
708
709 static void
wordout_writefooter(FILE * outptr)710 wordout_writefooter( FILE *outptr )
711 {
712 fprintf(outptr,"</b:Sources>\n");
713 fflush( outptr );
714 }
715