1 /* ffprint.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information (NCBI)
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government do not place any restriction on its use or reproduction.
13 * We would, however, appreciate having the NCBI and the author cited in
14 * any work or product based on this material
15 *
16 * Although all reasonable efforts have been taken to ensure the accuracy
17 * and reliability of the software and data, the NLM and the U.S.
18 * Government do not and cannot warrant the performance or results that
19 * may be obtained by using this software or data. The NLM and the U.S.
20 * Government disclaim all warranties, express or implied, including
21 * warranties of performance, merchantability or fitness for any particular
22 * purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name: ffprint.c
27 *
28 * Author: Karl Sirotkin, Tom Madden, Tatiana Tatusov
29 *
30 * Version Creation Date: 7/15/95
31 *
32 * $Revision: 6.8 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * $Log: ffprint.c,v $
39 * Revision 6.8 2003/07/15 14:35:56 dondosha
40 * Added #defines for substitutes to fprintf and fflush, needed for gzip compression of Web BLAST results
41 *
42 * Revision 6.7 2002/08/26 22:06:57 kans
43 * ff_RecalculateLinks (MS) to fix hotlink artifact
44 *
45 * Revision 6.6 1999/10/07 19:22:21 bazhin
46 * Changed Int2 to Int4 for one variable. To prevent coredump.
47 *
48 * Revision 6.5 1999/10/06 20:25:28 bazhin
49 * Removed memory leak.
50 *
51 * Revision 6.4 1999/08/31 14:36:06 tatiana
52 * ff_print_string_mem() added
53 *
54 * Revision 6.3 1999/04/09 21:17:18 bazhin
55 * Added functions "FFBSPrint()" and "BSAppend()" to parse ASN.1
56 * data to ByteStore.
57 *
58 * Revision 6.2 1999/04/01 20:44:13 kans
59 * Int2 lengths to Int4 to allow CountGapsInDeltaSeq with buffer > 32K
60 *
61 * Revision 6.1 1999/03/12 17:47:11 tatiana
62 * file was lost
63 *
64 * Revision 6.7 1999/02/02 17:29:20 kans
65 * added ff_MergeString
66 *
67 * Revision 6.6 1998/06/15 15:00:31 tatiana
68 * UNIX compiler warnings fixed
69 *
70 * Revision 6.5 1998/02/26 22:43:46 madden
71 * Used init_buff_ex in ff_StartPrint
72 *
73 * Revision 6.4 1998/02/19 01:54:51 ostell
74 * added use of Thread Local Storage to make functions thread safe
75 *
76 * Revision 6.3 1997/10/23 20:21:31 madden
77 * Fixed ByteStore leak
78 *
79 * Revision 6.2 1997/10/23 20:03:51 tatiana
80 * allocates byte store in init_buf_ex()
81 *
82 * Revision 6.1 1997/09/16 16:56:04 tatiana
83 * buffer reinit in ff_StartPrint
84 *
85 * Revision 6.0 1997/08/25 18:05:32 madden
86 * Revision changed to 6.0
87 *
88 * Revision 5.8 1997/08/04 22:56:21 tatiana
89 * init_buff_ex() added
90 *
91 * Revision 5.7 1997/07/18 20:11:16 vakatov
92 * Restored NLM_EXTERNs which were lost in R5.5
93 *
94 * Revision 5.6 1997/07/16 21:24:12 tatiana
95 * add AddPintLater
96 *
97 Revision 5.3 1997/02/25 22:08:59 tatiana
98 ff_AddStringWithTildes(0 will print out "`~" as real tilde
99
100 Revision 5.2 1997/01/08 18:52:45 madden
101 Added LIBCALL's.
102
103 Revision 5.1 1996/09/10 14:26:56 tatiana
104 init_buff() added to ff_StartPrint
105
106 Revision 4.8 1996/04/15 18:44:41 tatiana
107 free_buff() added
108
109 Revision 4.4 1996/01/29 22:41:20 tatiana
110 ChangeStringWithTildes function added
111
112 Revision 4.3 1995/12/13 21:04:47 kans
113 descriptors now store entityID/itemID/itemtype in proper array
114
115 Revision 4.2 1995/12/13 16:34:06 tatiana
116 itemID added to FFPrintArray structure
117
118 Revision 4.1 1995/11/17 21:28:35 kans
119 asn2ff now uses gather (Tatiana)
120
121 Revision 1.5 1995/07/17 19:33:20 kans
122 parameters combined into Asn2ffJobPtr structure
123 *
124 * ==========================================================================
125 */
126
127 #include <asn2ffp.h>
128 #include <ffprint.h>
129 #include <ncbithr.h>
130
131 int (*ff_fprintf)(FILE*, const char *, ...) = fprintf;
132 int (*ff_fflush)(FILE*) = fflush;
133
134 #define fprintf ff_fprintf
135 #define fflush ff_fflush
136
137 static TNlmTls ffprint_tls = NULL;
138
free_buff_contents(BuffStructPtr bfp)139 static void free_buff_contents(BuffStructPtr bfp)
140 {
141 if (bfp == NULL) return;
142 bfp->buffer = MemFree(bfp->buffer);
143 bfp->line_prefix = MemFree(bfp->line_prefix);
144 bfp->line_return = MemFree(bfp->line_return);
145 if (bfp->byte_sp)
146 bfp->byte_sp = BSFree(bfp->byte_sp);
147 return;
148 }
149
BuffStructCleanup(TNlmTls tls,VoidPtr ptr)150 static void BuffStructCleanup (TNlmTls tls, VoidPtr ptr)
151 {
152 BuffStructPtr bfp;
153
154 bfp = (BuffStructPtr)ptr;
155 free_buff_contents(bfp);
156 MemFree(bfp);
157 return;
158 }
159
160
GetBuffStruct(void)161 static BuffStruct PNTR NEAR GetBuffStruct ( void )
162 {
163 BuffStructPtr bfp = NULL;
164
165 if (NlmTlsGetValue( ffprint_tls, (VoidPtr *)(&bfp)))
166 {
167 if (bfp == NULL)
168 {
169 bfp = MemNew(sizeof(BuffStruct));
170 NlmTlsSetValue(&ffprint_tls, bfp, BuffStructCleanup);
171 }
172 }
173 return bfp;
174 }
175
176 /******************************************************************************
177 *
178 * print utilities to handle the printing of the asn2ff system.
179 *
180 *****************************************************************************/
init_buff(void)181 NLM_EXTERN void LIBCALL init_buff(void)
182 {
183 BuffStructPtr bfp;
184
185 bfp = GetBuffStruct();
186 bfp->buffer = (CharPtr) MemNew((MAX_BTP_BUF+2)*sizeof(Char));
187 bfp->line_prefix = (CharPtr) MemNew(3*sizeof(Char));
188 bfp->newline = NEWLINE;
189 }
190
init_buff_ex(Int2 init_size)191 NLM_EXTERN void LIBCALL init_buff_ex(Int2 init_size)
192 {
193 BuffStructPtr bfp;
194
195 bfp = GetBuffStruct();
196 bfp->buffer = (CharPtr) MemNew((init_size+2)*sizeof(Char));
197 bfp->line_prefix = (CharPtr) MemNew(3*sizeof(Char));
198 bfp->newline = NEWLINE;
199 bfp->byte_sp = BSNew(init_size+2);
200 }
201
free_buff(void)202 NLM_EXTERN void LIBCALL free_buff(void)
203 {
204 BuffStructPtr bfp;
205
206 bfp = GetBuffStruct();
207 free_buff_contents (bfp);
208 return;
209 }
210
211 /***********************************************************************
212 *void asn2ff_set_output (FILE * fp, CharPtr line_return)
213 *
214 **************************************************************************/
215
asn2ff_set_output(FILE * fp,CharPtr line_return)216 NLM_EXTERN void LIBCALL asn2ff_set_output (FILE *fp, CharPtr line_return)
217 {
218 BuffStructPtr bfp;
219
220 bfp = GetBuffStruct();
221 bfp->fp = fp;
222 if (line_return)
223 {
224 if(bfp->line_return != NULL)
225 MemFree(bfp->line_return);
226 bfp->line_return = StringSave(line_return);
227 }
228 }
229
ff_MergeString(void)230 NLM_EXTERN CharPtr LIBCALL ff_MergeString (void)
231
232 {
233 ByteStorePtr byte_sp=NULL;
234 CharPtr string=NULL;
235 BuffStructPtr bfp;
236
237 bfp = GetBuffStruct();
238
239 if (! bfp->fp)
240 {
241 byte_sp = bfp->byte_sp;
242
243 string = BSMerge(byte_sp, NULL);
244 bfp->byte_sp = BSFree(bfp->byte_sp);
245 }
246
247 return string;
248 }
249
FFPrint(FFPrintArrayPtr pap,Int4 index,Int4 pap_size)250 NLM_EXTERN CharPtr LIBCALL FFPrint (FFPrintArrayPtr pap, Int4 index, Int4 pap_size)
251 {
252 GBEntryPtr gbp;
253 Asn2ffJobPtr ajp;
254 ByteStorePtr byte_sp=NULL;
255 CharPtr string=NULL;
256 FFPrintArray pa=pap[index];
257 BuffStructPtr bfp;
258
259 bfp = GetBuffStruct();
260
261 gbp = pa.gbp;
262 ajp = pa.ajp;
263 if (ajp == NULL) {
264 return NULL;
265 }
266 ajp->pap_index = pa.index;
267 ajp->pap_last = pa.last;
268
269 if (index == 0 || index == (pap_size-1))
270 {
271 flat2asn_delete_locus_user_string();
272 flat2asn_install_locus_user_string(gbp->locus);
273 flat2asn_delete_accession_user_string();
274 flat2asn_install_accession_user_string(gbp->accession);
275 }
276
277 bfp->n_links = 0;
278 pa.fct(ajp, gbp);
279 if (pa.descr == NULL) {
280 pap[index].descr = gbp->descr;
281 }
282 if (pa.printxx == PRINTXX) {
283 PrintXX();
284 }
285 if (! bfp->fp) {
286 byte_sp = bfp->byte_sp;
287 string = BSMerge(byte_sp, NULL);
288 bfp->byte_sp = BSFree(bfp->byte_sp);
289 }
290
291 return string;
292 }
293
294 /**********************************************************/
BSAppend(ByteStorePtr to,ByteStorePtr from)295 static ByteStorePtr BSAppend(ByteStorePtr to, ByteStorePtr from)
296 {
297 Nlm_BSUnitPtr tobup;
298 Nlm_BSUnitPtr frombup;
299
300 if(from == NULL)
301 return(to);
302
303 if(to == NULL)
304 {
305 to = MemNew(sizeof(Nlm_ByteStore));
306 to->totlen = 0;
307 to->chain = NULL;
308 }
309
310 to->seekptr = 0;
311 to->chain_offset = 0;
312
313 if(to->chain != NULL)
314 for(tobup = to->chain; tobup->next != NULL; tobup = tobup->next)
315 continue;
316 else
317 tobup = NULL;
318
319 for(frombup = from->chain; frombup != NULL; frombup = frombup->next)
320 {
321 to->totlen += frombup->len;
322 if(tobup == NULL)
323 {
324 to->chain = MemNew(sizeof(Nlm_BSUnit));
325 tobup = to->chain;
326 }
327 else
328 {
329 tobup->next = MemNew(sizeof(Nlm_BSUnit));
330 tobup = tobup->next;
331 }
332 tobup->str = MemNew(frombup->len);
333 MemCpy(tobup->str, frombup->str, frombup->len);
334 tobup->len = frombup->len;
335 tobup->len_avail = frombup->len_avail;
336 }
337 to->curchain = to->chain;
338 return(to);
339 }
340
341 /**********************************************************/
FFBSPrint(FFPrintArrayPtr pap,Int4 index,Int4 pap_size)342 NLM_EXTERN void LIBCALL FFBSPrint(FFPrintArrayPtr pap, Int4 index,
343 Int4 pap_size)
344 {
345 GBEntryPtr gbp;
346 Asn2ffJobPtr ajp;
347 ByteStorePtr byte_sp = NULL;
348 FFPrintArray pa = pap[index];
349 BuffStructPtr bfp;
350
351 bfp = GetBuffStruct();
352
353 gbp = pa.gbp;
354 ajp = pa.ajp;
355 if(ajp == NULL)
356 return;
357
358 ajp->pap_index = pa.index;
359 ajp->pap_last = pa.last;
360
361 if(index == 0 || index == pap_size - 1)
362 {
363 flat2asn_delete_locus_user_string();
364 flat2asn_install_locus_user_string(gbp->locus);
365 flat2asn_delete_accession_user_string();
366 flat2asn_install_accession_user_string(gbp->accession);
367 }
368
369 bfp->n_links = 0;
370 pa.fct(ajp, gbp);
371 if(pa.descr == NULL)
372 pap[index].descr = gbp->descr;
373
374 if(pa.printxx == PRINTXX)
375 {
376 PrintXX();
377 }
378
379 ajp->byte_st = BSAppend(ajp->byte_st, bfp->byte_sp);
380 BSFree(bfp->byte_sp);
381 bfp->byte_sp = NULL;
382 }
383
ff_print_string(FILE * fp,CharPtr string,CharPtr line_return)384 NLM_EXTERN void LIBCALL ff_print_string (FILE *fp, CharPtr string, CharPtr line_return)
385
386 {
387 CharPtr s;
388 Int2 i, l;
389 BuffStructPtr bfp;
390
391 bfp = GetBuffStruct();
392
393 if (! fp) {
394 return;
395 }
396 if (! string || *string == *line_return) {
397 ErrPostEx(SEV_WARNING, 1, 1,
398 "CAUTION: NULL String in ff_print_string\n\n");
399 return;
400 }
401 for (s = string; (s = strchr(s, *line_return)) != NULL; s++) {
402 *s = '\n';
403 }
404 for (i = 0, s = string; i < bfp->n_links; i++) {
405 l = string - s + bfp->pos_links[i];
406 if (s[l-1] == '\n') {
407 for (; IS_WHITESP(s[l]); l++) ;
408 fwrite(s, 1, l, fp);
409 } else {
410 fwrite(s, 1, l, fp);
411 }
412 fwrite(bfp->links[i], 1, StringLen(bfp->links[i]), fp);
413 MemFree(bfp->links[i]);
414 s += l;
415 }
416 fwrite(s, 1, StringLen(s), fp);
417 BuffFree();
418 }
419
ff_print_insert(CharPtr str,CharPtr ins)420 static CharPtr ff_print_insert(CharPtr str, CharPtr ins)
421 {
422 CharPtr buff;
423
424 buff = (CharPtr) MemNew(StringLen(str) + StringLen(ins) + 1);
425 StringCpy(buff, ins);
426 StringCat(buff, str);
427 MemFree(str);
428 return buff;
429 }
430
ff_print_string_mem(CharPtr string)431 NLM_EXTERN CharPtr LIBCALL ff_print_string_mem (CharPtr string)
432
433 {
434 CharPtr s, buff, bu;
435 Int2 i, l;
436 Int4 ll;
437 BuffStructPtr bfp;
438
439 bfp = GetBuffStruct();
440
441 if (! string) {
442 ErrPostEx(SEV_WARNING, 1, 1,
443 "CAUTION: NULL String in ff_print_string\n\n");
444 return NULL;
445 }
446 ll = StringLen(string);
447 for (i = 0, s = string; i < bfp->n_links; i++) {
448 ll += StringLen(bfp->links[i]);
449 }
450 buff = (CharPtr) MemNew(ll+1);
451 bu = buff;
452 for (i = 0, s = string; i < bfp->n_links; i++) {
453 l = string - s + bfp->pos_links[i];
454 if (s[l-1] == '\n') {
455 for (; IS_WHITESP(s[l]); l++) ;
456 }
457 MemCpy(bu, s, l);
458 s += l;
459 bu += l;
460 StringCpy(bu, bfp->links[i]);
461 bu += StringLen(bfp->links[i]);
462 MemFree(bfp->links[i]);
463 }
464 StringCpy(bu, s);
465 BuffFree();
466 MemFree(string);
467 return buff;
468 }
469
ff_StartPrint(Int2 init_indent,Int2 cont_indent,Int2 line_max,CharPtr line_prefix)470 NLM_EXTERN Int2 LIBCALL ff_StartPrint (Int2 init_indent, Int2 cont_indent, Int2 line_max, CharPtr line_prefix)
471
472 {
473
474 CharPtr buffer;
475 Int2 indent_space;
476 BuffStructPtr bfp;
477
478 bfp = GetBuffStruct();
479
480 buffer = bfp->buffer;
481 if (buffer == NULL) {
482 if (line_max > MAX_BTP_BUF)
483 init_buff_ex(line_max);
484 else
485 init_buff();
486 buffer = bfp->buffer;
487 }
488
489 bfp->init_indent = init_indent;
490 bfp->cont_indent = cont_indent;
491
492 if (line_max > 0)
493 bfp->line_max = line_max;
494 else
495 bfp->line_max = MAX_BTP_BUF;
496
497 if (line_prefix) {
498 StringCpy(bfp->line_prefix, line_prefix);
499 *buffer = *line_prefix;
500 buffer++;
501 line_prefix++;
502 *buffer = *line_prefix;
503 buffer++;
504 line_prefix++;
505 indent_space = init_indent - StringLen(bfp->line_prefix);
506 } else {
507 bfp->line_prefix[0] = '\0';
508 indent_space = init_indent;
509 }
510
511 if (indent_space > 0) {
512 MemSet((VoidPtr) buffer, ' ', indent_space);
513 }
514 return init_indent;
515 } /* ff_StartPrint */
516
ff_AddString(CharPtr string)517 NLM_EXTERN void LIBCALL ff_AddString (CharPtr string)
518
519 {
520 Char newline;
521 CharPtr buffer;
522 Int2 increment_string=0, index, length_b/*, length_s -- UNUSED */, line_max;
523 BuffStructPtr bfp;
524
525 bfp = GetBuffStruct();
526 newline = bfp->newline;
527 line_max = bfp->line_max;
528
529 if (string == NULL)
530 return;
531
532 buffer = CheckBufferState(&increment_string, string[0]);
533
534 if (buffer == NULL)
535 return;
536
537 length_b = StringLen(bfp->buffer);
538
539 string += increment_string;
540 index = length_b;
541 while ((*buffer = *string) != '\0')
542 {
543 if (*string == newline)
544 {
545 *buffer = '\0';
546 *string = ' ';
547 NewContLine();
548 string++;
549 ff_AddString(string);
550 break;
551 }
552 else
553 {
554 buffer++;
555 string++;
556 index++;
557 if (index == line_max)
558 { /* return value for ff_AddString??????? */
559 ff_AddString(string);
560 break;
561 }
562 }
563 }
564
565 /* length_s = index - length_b; -- NO EFFECT */
566
567 return;
568 } /* ff_AddString */
569
AddLink(CharPtr str)570 NLM_EXTERN void LIBCALL AddLink (CharPtr str)
571 {
572 CharPtr buffer;
573 Int2 increment_string=0;
574 Int4 l;
575 CharPtr PNTR buf_links;
576 Int4 PNTR buf_pos;
577 BuffStructPtr bfp;
578
579 bfp = GetBuffStruct();
580
581 buffer = CheckBufferState(&increment_string, str[0]);
582 if (buffer == NULL) {
583 return;
584 }
585 l = (bfp->byte_sp == NULL) ? 0 : BSLen(bfp->byte_sp);
586 if (bfp->n_links >= bfp->buf_n_links) {
587 buf_pos = MemNew((bfp->buf_n_links + LINKS)*sizeof(buf_pos[0]));
588 buf_links = MemNew((bfp->buf_n_links + LINKS)*sizeof(buf_links[0]));
589 if (bfp->buf_n_links > 0) {
590 MemCpy(buf_pos, bfp->pos_links, bfp->buf_n_links*sizeof(buf_pos[0]));
591 MemFree(bfp->pos_links);
592 MemCpy(buf_links, bfp->links, bfp->buf_n_links*sizeof(buf_links[0]));
593 MemFree(bfp->links);
594 }
595 bfp->pos_links = buf_pos;
596 bfp->links = buf_links;
597 bfp->buf_n_links += LINKS;
598 }
599 bfp->pos_links[bfp->n_links] = (buffer - bfp->buffer + l);
600 bfp->links[bfp->n_links] = StringSave(str);
601 bfp->n_links++;
602 return;
603 }
604
AddLinkLater(CharPtr str,Int2 prevlen)605 NLM_EXTERN void LIBCALL AddLinkLater (CharPtr str, Int2 prevlen)
606 {
607 CharPtr buffer;
608 Int2 increment_string=0;
609 Int4 l;
610 CharPtr PNTR buf_links;
611 Int4 PNTR buf_pos;
612 BuffStructPtr bfp;
613
614 bfp = GetBuffStruct();
615
616 buffer = CheckBufferState(&increment_string, str[0]);
617 if (buffer == NULL) {
618 return;
619 }
620 l = (bfp->byte_sp == NULL) ? 0 : BSLen(bfp->byte_sp);
621 if (bfp->n_links >= bfp->buf_n_links) {
622 buf_pos = MemNew((bfp->buf_n_links + LINKS)*sizeof(buf_pos[0]));
623 buf_links = MemNew((bfp->buf_n_links + LINKS)*sizeof(buf_links[0]));
624 if (bfp->buf_n_links > 0) {
625 MemCpy(buf_pos, bfp->pos_links, bfp->buf_n_links*sizeof(buf_pos[0]));
626 MemFree(bfp->pos_links);
627 MemCpy(buf_links, bfp->links, bfp->buf_n_links*sizeof(buf_links[0]));
628 MemFree(bfp->links);
629 }
630 bfp->pos_links = buf_pos;
631 bfp->links = buf_links;
632 bfp->buf_n_links += LINKS;
633 }
634 bfp->pos_links[bfp->n_links] = buffer - bfp->buffer + l - prevlen;
635 bfp->links[bfp->n_links] = StringSave(str);
636 bfp->n_links++;
637 return;
638 }
639
ff_AddChar(Char character)640 NLM_EXTERN void LIBCALL ff_AddChar (Char character)
641 {
642 CharPtr buffer;
643 Int2 increment_string=0;
644 BuffStructPtr bfp;
645
646 bfp = GetBuffStruct();
647
648 if (character == NULLB)
649 return;
650
651 if (character == bfp->newline)
652 {
653 NewContLine();
654 }
655 else
656 {
657 buffer = CheckBufferState(&increment_string, character);
658 *buffer = character;
659 }
660
661 return ;
662 } /* ff_AddChar */
663
PrintXX(void)664 NLM_EXTERN void LIBCALL PrintXX(void)
665 {
666 ff_StartPrint(0, 0, ASN2FF_EMBL_MAX, "XX");
667 ff_EndPrint();
668 }
669
ff_AddInteger(CharPtr fmt,long integer)670 NLM_EXTERN void LIBCALL ff_AddInteger (CharPtr fmt, long integer)
671 {
672 Char buffer[10];
673
674 /* Only one integer read in */
675 sprintf(buffer, fmt, integer);
676 ff_AddString(buffer);
677 return;
678 } /* ff_AddInteger */
679
680 /***********************************************************************
681 *void ff_AddStringWithTildes (CharPtr string)
682 *
683 * This function prints out a string and replaces the tiles ("~")
684 * by new lines (by calling NewContLine). Before this function is
685 * called, printing must be initialized by calling ff_StartPrint;
686 * afterwards ff_EndPrint must be called!
687 *
688 * Use accent grave (ASCII 96) "`~" to print out real tilde
689 *
690 * Can't this be rewritten to use ff_AddString???? That would be faster!
691 ************************************************************************/
692
ff_AddStringWithTildes(CharPtr string)693 NLM_EXTERN void LIBCALL ff_AddStringWithTildes (CharPtr string)
694 {
695 /* One "~" is a new line, "~~" or "~~ ~~" means 2 returns */
696
697 while (*string != '\0') {
698 if (*string == '`' && *(string+1) == '~') {
699 ff_AddChar('~');
700 string += 2;
701 } else if (*string == '~') {
702 NewContLine();
703 string++;
704 if (*string == '~') {
705 NewContLine();
706 string++;
707 if (*string == ' ' && *(string+1) == '~' && *(string+2) == '~')
708 string += 3;
709 }
710 } else if (*string == '\"') {
711 *string = '\'';
712 ff_AddChar(*string);
713 string++;
714 } else {
715 ff_AddChar(*string);
716 string++;
717 }
718 }
719
720 } /* ff_AddStringWithTildes */
721
ChangeStringWithTildes(CharPtr string)722 NLM_EXTERN void LIBCALL ChangeStringWithTildes (CharPtr string)
723 {
724 while (*string != '\0') {
725 /* One "~" is a line return, "~~" or "~~ ~~" means 2 returns */
726 if (*string == '~') {
727 *string = '\n';
728 string++;
729 if (*string == '~') {
730 *string = '\n';
731 string++;
732 if (*string == ' ' && *(string+1) == '~' &&
733 *(string+2) == '~') {
734 string += 3;
735 }
736 }
737 } else if (*string == '\"') {
738 *string = '\'';
739 string++;
740 } else {
741 string++;
742 }
743 }
744
745 } /* ChangeStringWithTildes */
746
ff_RecalculateLinks(Int4 indent)747 NLM_EXTERN void LIBCALL ff_RecalculateLinks(Int4 indent) {
748 BuffStructPtr bfp = GetBuffStruct();
749 Int4 len = (bfp->byte_sp == NULL) ? 0 : BSLen(bfp->byte_sp);
750 Int2 i;
751
752 for ( i = bfp->n_links - 1; i >= 0; --i ) {
753 if ( bfp->pos_links[i] + 1 >= len ) {
754 bfp->pos_links[i] += indent;
755 } else {
756 break;
757 }
758 }
759 }
760
CheckBufferState(Int2Ptr increment_string,Char next_char)761 NLM_EXTERN CharPtr LIBCALL CheckBufferState(Int2Ptr increment_string, Char next_char)
762
763 {
764 CharPtr buffer, line_prefix;
765 CharPtr buf_ptr_comma=NULL, buf_ptr_dash=NULL, buf_ptr_space=NULL,
766 buf_ptr_start, ptr_index;
767 CharPtr temp_ptr, temp_ptr_start;
768 Char temp[MAX_TO_RT_SIDE+1];
769 Int2 length, cont_indent, indent_space;
770 Int2 line_max, line_index;
771 BuffStructPtr bfp;
772 Int2 IndentSize = 0;
773
774 bfp = GetBuffStruct();
775 cont_indent = bfp->cont_indent;
776 line_max = bfp->line_max;
777
778 *increment_string = 0;
779 temp_ptr = temp_ptr_start = temp;
780
781 buffer = bfp->buffer;
782 length=StringLen(buffer);
783
784 if (length < bfp->line_max) {
785 return buffer+length;
786 } else if (length == bfp->line_max && next_char == '\0') {
787 return buffer+length;
788 } else {
789 if (StringLen(bfp->line_prefix) > 0) {
790 line_prefix = bfp->line_prefix;
791 indent_space = cont_indent - StringLen(line_prefix);
792 } else {
793 line_prefix = NULL;
794 indent_space = cont_indent;
795 }
796
797 if (next_char == ' ') {
798 buf_ptr_space = buffer+line_max+1;
799 } else {
800 for (ptr_index=buffer+line_max, line_index=line_max-cont_indent;
801 ptr_index>buffer+line_max-MAX_TO_RT_SIDE &&
802 line_index > 0;
803 ptr_index--, line_index--) {
804 if (ptr_index[0] == ' ') {
805 buf_ptr_space = ptr_index;
806 break;
807 }
808 }
809
810 for (ptr_index=buffer+line_max, line_index=line_max-cont_indent;
811 ptr_index>buffer+line_max-MAX_TO_RT_SIDE &&
812 line_index > 0;
813 ptr_index--, line_index--) {
814 if (ptr_index[0] == ',') {
815 buf_ptr_comma = ptr_index;
816 /* Add one on the next line, otherwise the comma is lost, as space is. */
817 buf_ptr_comma++;
818 break;
819 }
820 }
821 for (ptr_index=buffer+line_max, line_index=line_max-cont_indent;
822 ptr_index>buffer+line_max-MAX_TO_RT_SIDE &&
823 line_index > 0;
824 ptr_index--, line_index--) {
825 if (ptr_index[0] == '-') {
826 /* Don't put "-" on next line! */
827 buf_ptr_dash = ptr_index + 1;
828 break;
829 }
830 }
831 }
832
833 if (next_char != ' ' &&
834 (buf_ptr_space || buf_ptr_comma || buf_ptr_dash)) {
835 if (buf_ptr_space) {
836 buf_ptr_start = buf_ptr_space;
837 buf_ptr_space++;
838 while((*temp_ptr = *buf_ptr_space) != '\0') {
839 temp_ptr++;
840 buf_ptr_space++;
841 }
842 buf_ptr_start[0] = '\0';
843 if (*(buf_ptr_start-1) == ' ') {
844 /* If there are two spaces in a row */
845 buf_ptr_start--;
846 buf_ptr_start[0] = '\0';
847 }
848 } else if (buf_ptr_comma) {
849 buf_ptr_start = buf_ptr_comma;
850 /* Check if a space follows the comma; if so, delete it; otherwise it shows
851 up on the next line and really looks stupid. */
852 if (*buf_ptr_comma == ' ') {
853 buf_ptr_comma++;
854 }
855 while((*temp_ptr = *buf_ptr_comma) != '\0') {
856 temp_ptr++;
857 buf_ptr_comma++;
858 }
859 buf_ptr_start[0] = '\0';
860 } else if (buf_ptr_dash) {
861 buf_ptr_start = buf_ptr_dash;
862 while((*temp_ptr = *buf_ptr_dash) != '\0') {
863 temp_ptr++;
864 buf_ptr_dash++;
865 }
866 buf_ptr_start[0] = '\0';
867 }
868
869
870 FlushBuffer();
871 if (line_prefix != NULL) {
872 *buffer = *line_prefix;
873 buffer++;
874 line_prefix++;
875 *buffer = *line_prefix;
876 buffer++;
877 line_prefix++;
878 }
879 if (indent_space > 0)
880 MemSet((VoidPtr) buffer, ' ', indent_space);
881 buffer += indent_space;
882 IndentSize = buffer - bfp->buffer + 1;
883 temp_ptr = temp_ptr_start;
884 while((*buffer = *temp_ptr) != '\0') {
885 temp_ptr++;
886 buffer++;
887 }
888
889 ff_RecalculateLinks(IndentSize);
890 return buffer;
891 } else if (next_char == ' ') {
892 FlushBuffer();
893 if (line_prefix) {
894 *buffer = *line_prefix;
895 buffer++;
896 line_prefix++;
897 *buffer = *line_prefix;
898 buffer++;
899 line_prefix++;
900 }
901 if (indent_space-1 > 0) {
902 MemSet((VoidPtr) buffer, ' ', indent_space-1);
903 ff_RecalculateLinks(buffer+indent_space-1 - bfp->buffer);
904 return buffer+indent_space-1;
905 } else if (indent_space-1 == 0) {
906 /* if there is one space indentation! */
907 ff_RecalculateLinks(buffer - bfp->buffer);
908 return buffer;
909 } else if (indent_space-1 < 0) {
910 /* if there is zero space indentation! */
911 *increment_string = 1;
912 ff_RecalculateLinks(buffer - bfp->buffer);
913 return buffer;
914 }
915 } else {
916 FlushBuffer();
917 if (line_prefix) {
918 *buffer = *line_prefix;
919 buffer++;
920 line_prefix++;
921 *buffer = *line_prefix;
922 buffer++;
923 line_prefix++;
924 }
925 if (indent_space > 0) {
926 MemSet((VoidPtr) buffer, ' ', indent_space);
927 }
928 ff_RecalculateLinks(buffer +indent_space - bfp->buffer);
929 return buffer+indent_space;
930 }
931 }
932 return buffer; /* never used! Only put in to make CodeWarrior happy*/
933 } /* CheckBufferState */
934
NewContLine(void)935 NLM_EXTERN Int2 LIBCALL NewContLine (void)
936
937 {
938 Int2 cont_indent, indent_space;
939 CharPtr buffer, line_prefix=NULL;
940 BuffStructPtr bfp;
941
942 bfp = GetBuffStruct();
943 cont_indent = bfp->cont_indent;
944
945 FlushBuffer();
946 buffer=bfp->buffer;
947
948 if (StringLen(bfp->line_prefix) > 0)
949 {
950 line_prefix = bfp->line_prefix;
951 indent_space = cont_indent - StringLen(line_prefix);
952 }
953 else
954 {
955 indent_space = cont_indent;
956 }
957
958 if (line_prefix)
959 {
960 *buffer = *line_prefix;
961 buffer++;
962 line_prefix++;
963 *buffer = *line_prefix;
964 buffer++;
965 line_prefix++;
966 }
967
968 if (indent_space > 0)
969 MemSet((VoidPtr) buffer, ' ', indent_space);
970 return cont_indent;
971 } /* NewContLine */
972
973
TabToColumn(Int2 column)974 NLM_EXTERN Int2 LIBCALL TabToColumn (Int2 column)
975
976 {
977 CharPtr start_buffer, buffer;
978 Int2 increment_string=0, length;
979 BuffStructPtr bfp;
980
981 bfp = GetBuffStruct();
982 start_buffer = bfp->buffer;
983
984 if ((length=StringLen(start_buffer)) > column)
985 return -1;
986
987 buffer = CheckBufferState(&increment_string, '\0');
988
989 if ((column-length-1) > 0)
990 MemSet((VoidPtr) buffer, ' ', (column-length-1));
991
992 return length;
993 }
994
ff_EndPrint(void)995 NLM_EXTERN void LIBCALL ff_EndPrint (void)
996
997 {
998 FlushBuffer();
999 }
1000
FlushBuffer(void)1001 NLM_EXTERN void LIBCALL FlushBuffer (void)
1002
1003 {
1004 ByteStorePtr byte_sp=NULL;
1005 CharPtr line_ret;
1006 BuffStructPtr bfp;
1007
1008 bfp = GetBuffStruct();
1009 line_ret = bfp->line_return;
1010
1011 if (bfp->fp)
1012 {
1013 fflush(bfp->fp);
1014 fprintf(bfp->fp, "%s\n", bfp->buffer);
1015 }
1016 else
1017 {
1018 byte_sp=bfp->byte_sp;
1019 if (! byte_sp) {
1020 bfp->byte_sp = byte_sp = BSNew(MAX_BTP_BUF);
1021 }
1022 BSWrite(byte_sp, bfp->buffer, StringLen(bfp->buffer));
1023 BSWrite(byte_sp, line_ret, StringLen(line_ret));
1024 }
1025 MemSet((VoidPtr) bfp->buffer, '\0', bfp->line_max);
1026 }
1027
1028
1029 /**************************************************************************
1030 *CheckEndPunctuation
1031 *
1032 * This code checks to ensure that the last character of a string
1033 * is the character passed. Any extra spaces or tabs at the end of
1034 * the string are eliminated.
1035 *
1036 **************************************************************************/
1037
CheckEndPunctuation(CharPtr string,Char end)1038 NLM_EXTERN CharPtr LIBCALL CheckEndPunctuation (CharPtr string, Char end)
1039
1040 {
1041 CharPtr stringptr, newstring;
1042 Int4 length;
1043
1044 if (string == NULL)
1045 return NULL;
1046
1047 length = StringLen(string);
1048 newstring = (CharPtr) MemNew((length+2)*sizeof(Char));
1049
1050 if (length > 0)
1051 {
1052 newstring = StringCpy(newstring, string);
1053 for (stringptr=newstring+length-1; stringptr > newstring; stringptr--)
1054 {
1055 if (*stringptr == ' ' || *stringptr == '\t' || *stringptr == '~')
1056 {
1057 *stringptr = '\0';
1058 }
1059 else
1060 {
1061 break;
1062 }
1063 }
1064
1065 if (*stringptr != end)
1066 {
1067 stringptr++;
1068 *stringptr = end;
1069 stringptr++;
1070 *stringptr = '\0';
1071 }
1072 }
1073 else
1074 {
1075 newstring[0] = end;
1076 newstring[1] = '\0';
1077 }
1078
1079 return newstring;
1080 }
1081
BuffFree(void)1082 NLM_EXTERN void LIBCALL BuffFree(void)
1083 {
1084 BuffStructPtr bfp;
1085
1086 bfp = GetBuffStruct();
1087 bfp->buffer[0] = '\0';
1088 bfp->n_links = 0;
1089
1090 }
1091
ReportPrint(FFPrintArrayPtr pap,Int4 index,Int4 pap_size)1092 NLM_EXTERN CharPtr LIBCALL ReportPrint (FFPrintArrayPtr pap, Int4 index, Int4 pap_size)
1093
1094 {
1095 GBEntryPtr gbp;
1096 Asn2ffJobPtr ajp;
1097 ByteStorePtr byte_sp=NULL;
1098 CharPtr string=NULL;
1099 FFPrintArray pa=pap[index];
1100 BuffStructPtr bfp;
1101
1102 bfp = GetBuffStruct();
1103
1104 gbp = pa.gbp;
1105 ajp = pa.ajp;
1106 ajp->pap_index = pa.index;
1107 ajp->pap_last = pa.last;
1108
1109 if (index == 0 || index == (pap_size-1))
1110 {
1111 flat2asn_delete_locus_user_string();
1112 flat2asn_install_locus_user_string(gbp->locus);
1113 flat2asn_delete_accession_user_string();
1114 flat2asn_install_accession_user_string(gbp->accession);
1115 }
1116
1117 pa.fct(ajp, gbp);
1118
1119 if (! bfp->fp)
1120 {
1121 byte_sp = bfp->byte_sp;
1122
1123 string = BSMerge(byte_sp, NULL);
1124 bfp->byte_sp = BSFree(bfp->byte_sp);
1125 }
1126
1127 return string;
1128 }
1129
1130 /*****************************************************************************
1131 *Boolean DoSpecialLineBreak (BiotablePtr btp, CharPtr string, Int2 indent)
1132 *
1133 * Look for line breaks in special cases, such as KEYWORDS, when
1134 * line breaks are only allowed after semi-colons.
1135 *
1136 * "length" is reset to zero if string is NULL, "indent" tells how
1137 * many spaces the line is indented from the left side.
1138 *****************************************************************************/
1139
DoSpecialLineBreak(CharPtr string,Int2 indent)1140 NLM_EXTERN Boolean LIBCALL DoSpecialLineBreak (CharPtr string, Int2 indent)
1141
1142 {
1143 Boolean retval;
1144 static Int2 length=0;
1145
1146 if (string == NULL)
1147 {
1148 length = 0;
1149 retval = FALSE;
1150 }
1151 else
1152 {
1153 length += StringLen(string);
1154 length += 2;
1155 if (length < (ASN2FF_GB_MAX-indent))
1156 {
1157 retval = FALSE;
1158 }
1159 else
1160 {
1161 length = StringLen(string);
1162 length += 2;
1163 retval = TRUE;
1164 }
1165 }
1166 return retval;
1167
1168 } /* DoSpecialLineBreak */
1169