BibtexField * bibtex_reverse_field (BibtexField * field, gboolean use_braces, gboolean do_quote) { BibtexStruct * s = NULL; gchar * string, * tmp; gboolean is_upper, has_space, is_command, was_command; gint i; BibtexAuthor * author; static GString * st = NULL; static RECODE_OUTER outer = NULL; static RECODE_REQUEST request = NULL; g_return_val_if_fail (field != NULL, NULL); if (st == NULL) st = g_string_sized_new (16); if (outer == NULL) { outer = recode_new_outer (false); g_assert (outer != NULL); } if (request == NULL) { request = recode_new_request (outer); g_assert (request != NULL); if (! recode_scan_request (request, "latin1..latex")) { g_error ("can't create recoder"); } } if (field->structure) { bibtex_struct_destroy (field->structure, TRUE); field->structure = NULL; } field->loss = FALSE; switch (field->type) { case BIBTEX_OTHER: case BIBTEX_VERBATIM: g_return_val_if_fail (field->text != NULL, NULL); g_string_truncate (st, 0); if (! use_braces) { if (strchr (field->text, '"')) { use_braces = TRUE; } } if (use_braces) { g_string_append (st, "@preamble{{"); } else { g_string_append (st, "@preamble{\""); } if (do_quote) { tmp = recode_string (request, field->text); g_string_append (st, tmp); g_free (tmp); } else { g_string_append (st, field->text); } if (use_braces) { g_string_append (st, "}}"); } else { g_string_append (st, "\"}"); } s = text_to_struct (st->str); break; case BIBTEX_TITLE: g_return_val_if_fail (field->text != NULL, NULL); g_string_truncate (st, 0); if (! use_braces) { if (strchr (field->text, '"')) { use_braces = TRUE; } } tmp = recode_string (request, field->text); if (use_braces) { g_string_append (st, "@preamble{{"); } else { g_string_append (st, "@preamble{\""); } /* Put the first lower case between {} */ string = tmp; if (* tmp >= 'a' && * tmp <= 'z') { /* Put the beginning in lower cases */ g_string_append_c (st, '{'); g_string_append_c (st, * tmp); g_string_append_c (st, '}'); } else { /* The first character is done */ g_string_append_c (st, * tmp); } tmp ++; /* check for upper cases afterward */ is_upper = false; is_command = false; was_command = false; while (* tmp) { /* start a latex command */ if (* tmp == '\\') { /* eventually closes the bracket */ if (is_upper) { is_upper = false; g_string_append_c (st, '}'); } is_command = true; was_command = false; g_string_append_c (st, * tmp); tmp ++; continue; } if (is_command) { if (! ((* tmp >= 'a' && * tmp <= 'z') || (* tmp >= 'A' && * tmp <= 'Z'))) { is_command = false; was_command = true; } g_string_append_c (st, * tmp); tmp ++; continue; } if (* tmp >= 'A' && * tmp <= 'Z') { if (! is_upper) { g_string_append_c (st, '{'); g_string_append_c (st, * tmp); if (was_command) { g_string_append_c (st, '}'); } else { is_upper = true; } } else { g_string_append_c (st, * tmp); } } else { if (is_upper) { g_string_append_c (st, '}'); is_upper = false; } g_string_append_c (st, * tmp); } was_command = false; tmp ++; } /* eventually close the brackets */ if (is_upper) { g_string_append_c (st, '}'); is_upper = false; } g_free (string); if (use_braces) { g_string_append (st, "}}"); } else { g_string_append (st, "\"}"); } s = text_to_struct (st->str); break; case BIBTEX_AUTHOR: g_return_val_if_fail (field->field.author != NULL, NULL); g_string_truncate (st, 0); /* Create a simple preamble to parse */ if (! use_braces) { for (i = 0 ; i < field->field.author->len; i ++) { author = & g_array_index (field->field.author, BibtexAuthor, i); if (author->last && strchr (author->last, '"')) { use_braces = TRUE; break; } if (author->lineage && strchr (author->lineage, '"')) { use_braces = TRUE; break; } if (author->first && strchr (author->first, '"')) { use_braces = TRUE; break; } } } if (use_braces) { g_string_append (st, "@preamble{{"); } else { g_string_append (st, "@preamble{\""); } for (i = 0 ; i < field->field.author->len; i ++) { author = & g_array_index (field->field.author, BibtexAuthor, i); if (i != 0) { g_string_append (st, " and "); } if (author->last) { /* quotes if there is no first name */ has_space = author_needs_quotes (author->last) || (author->first == NULL && strpbrk (author->last, " \t") != NULL); if (has_space) { g_string_append_c (st, '{'); } tmp = recode_string (request, author->last); g_string_append (st, tmp); g_free (tmp); if (has_space) { g_string_append_c (st, '}'); } } if (author->lineage) { g_string_append (st, ", "); has_space = author_needs_quotes (author->lineage); if (has_space) { g_string_append_c (st, '{'); } tmp = recode_string (request, author->lineage); g_string_append (st, tmp); g_free (tmp); if (has_space) { g_string_append_c (st, '}'); } } if (author->first) { g_string_append (st, ", "); has_space = author_needs_quotes (author->first); if (has_space) { g_string_append_c (st, '{'); } tmp = recode_string (request, author->first); g_string_append (st, tmp); g_free (tmp); if (has_space) { g_string_append_c (st, '}'); } } } if (use_braces) { g_string_append (st, "}}"); } else { g_string_append (st, "\"}"); } s = text_to_struct (st->str); break; case BIBTEX_DATE: s = bibtex_struct_new (BIBTEX_STRUCT_TEXT); s->value.text = g_strdup_printf ("%d", field->field.date.year); break; default: g_assert_not_reached (); } field->structure = s; /* remove text field */ if (field->text) { g_free (field->text); field->text = NULL; field->converted = FALSE; } return field; }
/* caching request creator returns recode request either found in cache or, if not found, a newly created (and immediately put into the cache) returns NULL on failure */ static RECODE_REQUEST get_recode_request(const char *encreq) { static RecRequest *request_cache = NULL; /* recode request cache */ RECODE_REQUEST request; RecRequest *req; /* try to find the request in cache (bubble sorting it meanwhile) */ for (req = request_cache; req != NULL; req = req->next) { if (strcmp(req->request_string, encreq) == 0) break; if (req->next != NULL && req->count < req->next->count) { RecRequest tmpreq; /* it's easier to exchange contents instead of pointers here */ tmpreq.request = req->request; tmpreq.count = req->count; tmpreq.request_string = req->request_string; req->request = req->next->request; req->count = req->next->count; req->request_string = req->next->request_string; req->next->request = tmpreq.request; req->next->count = tmpreq.count; req->next->request_string = tmpreq.request_string; } } /* found, increment usage count and return it */ if (req != NULL) { req->count++; return req->request; } /* request not found, ask for a new one */ if ((request = recode_new_request(outer)) == NULL) { fprintf(stderr, "%s: recode library doesn't accept new requests\n", program_name); return NULL; /* maybe we could simply abort */ } /* Set some options. */ request->diacritics_only = request->ascii_graphics = true; /* create request from request string */ if (!recode_scan_request(request, encreq)) { if (options.verbosity_level) { fprintf(stderr, "%s: errorneous recoding request `%s'\n", program_name,encreq); } recode_delete_request(request); return NULL; } /* add it to end of cache */ if ((req = request_cache) != NULL) { while (req->next != NULL) req = req->next; req->next = NEW(RecRequest, 1); req = req->next; } else { req = NEW(RecRequest, 1); request_cache = req; } req->request = request; req->request_string = enca_strdup(encreq); req->count = 1; req->next = NULL; return request; }