~ubuntu-branches/ubuntu/precise/ncbi-tools6/precise

« back to all changes in this revision

Viewing changes to api/asn2gnb1.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2005-03-27 12:00:15 UTC
  • mfrom: (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050327120015-embhesp32nj73p9r
Tags: 6.1.20041020-3
* Fix FTBFS under GCC 4.0 caused by inconsistent use of "static" on
  functions.  (Closes: #295110.)
* Add a watch file, now that we can.  (Upstream's layout needs version=3.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*   asn2gnb1.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:  asn2gnb1.c
 
27
*
 
28
* Author:  Karl Sirotkin, Tom Madden, Tatiana Tatusov, Jonathan Kans,
 
29
*          Mati Shomrat
 
30
*
 
31
* Version Creation Date:   10/21/98
 
32
*
 
33
* $Revision: 1.32 $
 
34
*
 
35
* File Description:  New GenBank flatfile generator - work in progress
 
36
*
 
37
* Modifications:
 
38
* --------------------------------------------------------------------------
 
39
* ==========================================================================
 
40
*/
 
41
 
 
42
#include <ncbi.h>
 
43
#include <objall.h>
 
44
#include <objsset.h>
 
45
#include <objsub.h>
 
46
#include <objfdef.h>
 
47
#include <objpubme.h>
 
48
#include <seqport.h>
 
49
#include <sequtil.h>
 
50
#include <sqnutils.h>
 
51
#include <subutil.h>
 
52
#include <tofasta.h>
 
53
#include <explore.h>
 
54
#include <gbfeat.h>
 
55
#include <gbftdef.h>
 
56
#include <edutil.h>
 
57
#include <alignmgr2.h>
 
58
#include <asn2gnbi.h>
 
59
 
 
60
#ifdef WIN_MAC
 
61
#if __profile__
 
62
#include <Profiler.h>
 
63
#endif
 
64
#endif
 
65
 
 
66
/* utility functions */
 
67
 
 
68
NLM_EXTERN ValNodePtr ValNodeCopyStrToHead (ValNodePtr PNTR head, Int2 choice, CharPtr str)
 
69
 
 
70
{
 
71
  ValNodePtr newnode;
 
72
 
 
73
  if (head == NULL || str == NULL) return NULL;
 
74
 
 
75
  newnode = ValNodeNew (NULL);
 
76
  if (newnode == NULL) return NULL;
 
77
 
 
78
  newnode->choice = (Uint1) choice;
 
79
  newnode->data.ptrvalue = StringSave (str);
 
80
 
 
81
  newnode->next = *head;
 
82
  *head = newnode;
 
83
 
 
84
  return newnode;
 
85
}
 
86
 
 
87
/* the val node strings mechanism will be replaced by a more efficient method later  */
 
88
 
 
89
NLM_EXTERN CharPtr MergeFFValNodeStrs (
 
90
  ValNodePtr list
 
91
)
 
92
 
 
93
{
 
94
  size_t      len;
 
95
  CharPtr     ptr;
 
96
  CharPtr     str;
 
97
  CharPtr     tmp;
 
98
  ValNodePtr  vnp;
 
99
 
 
100
 
 
101
  if (list == NULL) return NULL;
 
102
 
 
103
  for (vnp = list, len = 0; vnp != NULL; vnp = vnp->next) {
 
104
    str = (CharPtr) vnp->data.ptrvalue;
 
105
    len += StringLen (str);
 
106
  }
 
107
  if (len == 0) return NULL;
 
108
 
 
109
  ptr = MemNew (sizeof (Char) * (len + 2));
 
110
  if (ptr == NULL) return NULL;
 
111
 
 
112
  for (vnp = list, tmp = ptr; vnp != NULL; vnp = vnp->next) {
 
113
    str = (CharPtr) vnp->data.ptrvalue;
 
114
    tmp = StringMove (tmp, str);
 
115
  }
 
116
 
 
117
  return ptr;
 
118
}
 
119
 
 
120
 
 
121
NLM_EXTERN void AddValNodeString (
 
122
  ValNodePtr PNTR head,
 
123
  CharPtr prefix,
 
124
  CharPtr string,
 
125
  CharPtr suffix
 
126
)
 
127
 
 
128
{
 
129
  Char     buf [256];
 
130
  CharPtr  freeme = NULL;
 
131
  size_t   len;
 
132
  CharPtr  newstr;
 
133
  CharPtr  strptr;
 
134
 
 
135
  len = StringLen (prefix) + StringLen (string) + StringLen (suffix);
 
136
  if (len == 0) return;
 
137
 
 
138
  if (len < sizeof (buf)) {
 
139
 
 
140
    /* if new string fits in stack buffer, no need to allocate */
 
141
 
 
142
    MemSet ((Pointer) buf, 0, sizeof (buf));
 
143
    newstr = buf;
 
144
 
 
145
  } else {
 
146
 
 
147
    /* new string bigger than stack buffer, so allocate sufficient string */
 
148
 
 
149
    newstr = (CharPtr) MemNew (sizeof (Char) * (len + 2));
 
150
    if (newstr == NULL) return;
 
151
 
 
152
    /* allocated string will be freed at end of function */
 
153
 
 
154
    freeme = newstr;
 
155
  }
 
156
 
 
157
  strptr = newstr;
 
158
 
 
159
  if (prefix != NULL) {
 
160
    strptr = StringMove (strptr, prefix);
 
161
  }
 
162
 
 
163
  if (string != NULL) {
 
164
    strptr = StringMove (strptr, string);
 
165
  }
 
166
 
 
167
  if (suffix != NULL) {
 
168
    strptr = StringMove (strptr, suffix);
 
169
  }
 
170
 
 
171
  /* currently just makes a valnode list, to be enhanced later */
 
172
 
 
173
  ValNodeCopyStr (head, 0, newstr);
 
174
 
 
175
  /* if large string was allocated, free it now */
 
176
 
 
177
  if (freeme != NULL) {
 
178
    MemFree (freeme);
 
179
  }
 
180
}
 
181
 
 
182
 
 
183
NLM_EXTERN void FFAddString_NoRedund (
 
184
  StringItemPtr unique,
 
185
  CharPtr prefix,
 
186
  CharPtr string,
 
187
  CharPtr suffix
 
188
)
 
189
{
 
190
  CharPtr    str = string;
 
191
  Int4       foundPos = 0;
 
192
  Boolean    wholeWord = FALSE;
 
193
 
 
194
  if ( StringHasNoText(prefix)  &&
 
195
       StringHasNoText(string)  &&
 
196
       StringHasNoText(suffix)  ) return;
 
197
 
 
198
  if (StringNICmp (string, "tRNA-", 5) == 0) {
 
199
    str = string+5;
 
200
    }
 
201
 
 
202
  while ( foundPos >= 0 && !wholeWord ) {
 
203
    foundPos = FFStringSearch(unique, str, foundPos);
 
204
    if ( foundPos >= 0 ) {
 
205
      wholeWord = IsWholeWordSubstr(unique, foundPos, str);
 
206
      foundPos += StringLen(str);
 
207
    }
 
208
  }
 
209
 
 
210
  if ( foundPos < 0 || !wholeWord ) {
 
211
      FFAddTextToString(unique, prefix, string, suffix, FALSE, FALSE, TILDE_IGNORE);
 
212
  }
 
213
}
 
214
 
 
215
 
 
216
 
 
217
/* s_AddPeriodToEnd () -- Adds a '.' to the end of a given string if */
 
218
/*                        there is not already one there.            */
 
219
/*                                                                   */
 
220
/*                        Note that this adds one character to the   */
 
221
/*                        length of the string, leading to a         */
 
222
/*                        memory overrun if space was not previously */
 
223
/*                        allocated for this.                        */
 
224
 
 
225
NLM_EXTERN void s_AddPeriodToEnd (CharPtr someString)
 
226
{
 
227
  Int4  len;
 
228
 
 
229
  if (StringHasNoText (someString)) return;
 
230
  len = StringLen (someString);
 
231
  if (len < 1) return;
 
232
  if (someString[len-1] != '.')
 
233
    {
 
234
      someString[len] = '.';
 
235
      someString[len+1] = '\0';
 
236
    }
 
237
}
 
238
 
 
239
/* s_RemovePeriodFromEnd () -- If the last character in a given      */
 
240
/*                             string is a '.', removes it.          */
 
241
 
 
242
NLM_EXTERN Boolean s_RemovePeriodFromEnd (CharPtr someString)
 
243
{
 
244
  Int4  len;
 
245
 
 
246
  if (StringHasNoText (someString)) return FALSE;
 
247
  len = StringLen (someString);
 
248
  if (len < 1) return FALSE;
 
249
  if (someString[len-1] == '.') {
 
250
    someString[len-1] = '\0';
 
251
    return TRUE;
 
252
  }
 
253
  return FALSE;
 
254
}
 
255
 
 
256
/**/
 
257
/*   isEllipsis () - Determines if a string ends in an ellipses */
 
258
/**/
 
259
 
 
260
NLM_EXTERN Boolean IsEllipsis (
 
261
  CharPtr str
 
262
)
 
263
 
 
264
{
 
265
  size_t   len;
 
266
  CharPtr  ptr;
 
267
 
 
268
  if (StringHasNoText (str)) return FALSE;
 
269
  len = StringLen (str);
 
270
  if (len < 3) return FALSE;
 
271
  ptr = str + len - 3;
 
272
  return (Boolean) (ptr [0] == '.' && ptr [1] == '.' && ptr [2] == '.');
 
273
}
 
274
 
 
275
NLM_EXTERN void A2GBSeqLocReplaceID (
 
276
  SeqLocPtr newloc,
 
277
  SeqLocPtr ajpslp
 
278
)
 
279
 
 
280
{
 
281
  BioseqPtr  bsp;
 
282
  SeqIdPtr   sip;
 
283
 
 
284
  bsp = BioseqFindFromSeqLoc (ajpslp);
 
285
  if (bsp == NULL) return;
 
286
  sip = SeqIdFindBest (bsp->id, 0);
 
287
  SeqLocReplaceID (newloc, sip);
 
288
}
 
289
 
 
290
NLM_EXTERN CharPtr asn2gb_PrintDate (
 
291
  DatePtr dp
 
292
)
 
293
 
 
294
{
 
295
  Char    buf [30];
 
296
  size_t  len;
 
297
 
 
298
  if (dp == NULL) return NULL;
 
299
 
 
300
  if (DatePrint (dp, buf)) {
 
301
    if (StringICmp (buf, "Not given") != 0) {
 
302
      len = StringLen (buf);
 
303
      if (len > 0) {
 
304
        if (buf [len - 1] == '\n') {
 
305
          if (buf [len - 2] == '.') {
 
306
            buf [len - 2] = '\0';
 
307
          } else {
 
308
            buf [len - 1] = '\0';
 
309
          }
 
310
        }
 
311
      }
 
312
      return StringSave (buf);
 
313
    }
 
314
  }
 
315
 
 
316
  return NULL;
 
317
}
 
318
 
 
319
static CharPtr month_names [] = {
 
320
  "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
 
321
  "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
 
322
  "??"
 
323
};
 
324
 
 
325
NLM_EXTERN CharPtr DateToFF (
 
326
  CharPtr buf,
 
327
  DatePtr dp,
 
328
  Boolean citSub
 
329
)
 
330
 
 
331
{
 
332
  Int2  day;
 
333
  Int2  month;
 
334
  Int2  year;
 
335
 
 
336
  if (buf != NULL) {
 
337
    *buf = '\0';
 
338
  }
 
339
  if (dp == NULL) return NULL;
 
340
 
 
341
  if (dp->data [0] == 0) {
 
342
 
 
343
    StringCpy (buf, dp->str);
 
344
 
 
345
  } else if (dp->data [0] == 1) {
 
346
 
 
347
    year = 1900 + (Int2) dp->data [1];
 
348
    month = (Int2) dp->data [2];
 
349
    day = (Int2) dp->data [3];
 
350
 
 
351
    if (citSub) {
 
352
      if (month < 1 || month > 12) {
 
353
        month = 13;
 
354
      }
 
355
      if (day < 1 || day > 31) {
 
356
        day = 0;
 
357
      }
 
358
    } else {
 
359
      if (month < 1 || month > 12) {
 
360
        month = 1;
 
361
      }
 
362
      if (day < 1 || day > 31) {
 
363
        day = 1;
 
364
      }
 
365
    }
 
366
 
 
367
    if (day < 1) {
 
368
      sprintf (buf, "??-%s-%ld",
 
369
               month_names [month-1], (long) year);
 
370
    } else if (day < 10) {
 
371
      sprintf (buf, "0%ld-%s-%ld",
 
372
               (long) day, month_names [month-1], (long) year);
 
373
    } else {
 
374
      sprintf(buf, "%ld-%s-%ld",
 
375
               (long) day, month_names [month-1], (long) year);
 
376
    }
 
377
  }
 
378
 
 
379
  return buf;
 
380
}
 
381
 
 
382
 
 
383
NLM_EXTERN StringItemPtr FFGetString (IntAsn2gbJobPtr ajp)
 
384
 
 
385
{
 
386
  StringItemPtr  sip;
 
387
 
 
388
  if (ajp == NULL) return NULL;
 
389
  if (ajp->pool != NULL) {
 
390
    sip = ajp->pool;
 
391
    ajp->pool = sip->next;
 
392
    sip->next = NULL;
 
393
    MemSet ((Pointer) sip, 0, sizeof (StringItem));
 
394
  } else {
 
395
    sip = (StringItemPtr) MemNew (sizeof (StringItem));
 
396
    if (sip == NULL) return NULL;
 
397
  }
 
398
  sip->curr = sip;
 
399
  sip->iajp = ajp;
 
400
  sip->pos = 0;
 
401
  return sip;
 
402
}
 
403
 
 
404
NLM_EXTERN void FFRecycleString (IntAsn2gbJobPtr ajp, StringItemPtr ffstring)
 
405
 
 
406
{
 
407
  StringItemPtr  nxt;
 
408
 
 
409
  if (ajp == NULL || ffstring == NULL) return;
 
410
  if ( ffstring->pos == -1 ) return;
 
411
  
 
412
  nxt = ffstring;
 
413
  nxt->pos = -1;
 
414
  while (nxt->next != NULL) {
 
415
    nxt->pos = -1;
 
416
    nxt = nxt->next;
 
417
  }
 
418
  nxt->next = ajp->pool;
 
419
  ajp->pool = ffstring;
 
420
 
 
421
  ffstring->curr = NULL;
 
422
}
 
423
 
 
424
NLM_EXTERN void FFAddOneChar (
 
425
  StringItemPtr sip, 
 
426
  Char ch,
 
427
  Boolean convertQuotes
 
428
)
 
429
{
 
430
  StringItemPtr current = sip->curr;
 
431
 
 
432
  if ( current->pos == STRING_BUF_LEN ) {
 
433
    current->next = FFGetString(sip->iajp);
 
434
    current = current->next;
 
435
    current->pos = 0;
 
436
    sip->curr = current;
 
437
  }
 
438
 
 
439
  if ( convertQuotes && ch == '\"' ) {
 
440
    ch = '\'';
 
441
  }
 
442
  current->buf[current->pos] = ch;
 
443
  current->pos++;
 
444
}
 
445
 
 
446
NLM_EXTERN void FFAddNewLine(StringItemPtr ffstring) {
 
447
  FFAddOneChar(ffstring, '\n', FALSE);
 
448
}
 
449
 
 
450
NLM_EXTERN void FFAddNChar (
 
451
  StringItemPtr sip, 
 
452
  Char ch,
 
453
  Int4 n,
 
454
  Boolean convertQuotes
 
455
)
 
456
{
 
457
  Int4 i;
 
458
 
 
459
  for ( i = 0; i < n; ++i ) {
 
460
    FFAddOneChar(sip, ch, convertQuotes);
 
461
  }
 
462
}
 
463
  
 
464
 
 
465
NLM_EXTERN void FFExpandTildes (StringItemPtr sip, CharPtr PNTR cpp) {
 
466
  Char replace = **cpp;
 
467
 
 
468
  if ( **cpp == '~' ) {
 
469
    if ( *((*cpp) + 1) == '~' ) {     /* "~~" -> '~' */
 
470
      replace = '~';
 
471
      (*cpp)++;
 
472
    } else {
 
473
      replace = '\n';
 
474
    }
 
475
  } 
 
476
 
 
477
  FFAddOneChar(sip, replace, FALSE);
 
478
}
 
479
 
 
480
 
 
481
NLM_EXTERN void FFReplaceTildesWithSpaces (StringItemPtr ffstring, CharPtr PNTR cpp) {
 
482
  Char replace = **cpp, lookahead;
 
483
  CharPtr cptr = *cpp;
 
484
  
 
485
  if ( *cptr == '`' ) {
 
486
    FFAddOneChar(ffstring, replace, FALSE);
 
487
    return;
 
488
  }
 
489
 
 
490
  replace = ' ';
 
491
  lookahead = *(cptr + 1);
 
492
 
 
493
  if ( IS_DIGIT(lookahead) ) {
 
494
    replace = '~';
 
495
  }
 
496
  else {
 
497
    if ( (lookahead == ' ') || (lookahead == '(') ) {
 
498
      if ( IS_DIGIT(*(cptr + 2)) ) {
 
499
        replace = '~';
 
500
      }
 
501
    }
 
502
  }
 
503
 
 
504
  FFAddOneChar(ffstring, replace, FALSE);
 
505
}
 
506
 
 
507
NLM_EXTERN void FFOldExpand (StringItemPtr sip, CharPtr PNTR cpp) {
 
508
  /* "~" -> "\n", "~~" or "~~ ~~" -> "\n\n" */ 
 
509
  CharPtr cp = *cpp;
 
510
  Char current = *cp;
 
511
  Char next = *(cp + 1);
 
512
  
 
513
  /* handle "'~" */
 
514
  if ( current == '`' ) {
 
515
    if ( next != '~' ) {
 
516
        FFAddOneChar(sip, current, FALSE);
 
517
    } else {
 
518
        FFAddOneChar(sip, '~', FALSE);
 
519
        (*cpp)++;
 
520
    }
 
521
    return;
 
522
  }
 
523
 
 
524
  /* handle "~", "~~" or "~~ ~~" */
 
525
  FFAddOneChar(sip, '\n', FALSE);
 
526
  if ( next == '~' ) {
 
527
    FFAddOneChar(sip, '\n', FALSE);
 
528
    cp++;
 
529
    *cpp = cp;
 
530
    cp++;
 
531
    if ( *cp == ' ' ) {
 
532
      cp++;
 
533
      if ( *cp == '~' ) {
 
534
        cp++;
 
535
        if ( *cp == '~' ) { /* saw "~~ ~~" */
 
536
          *cpp = cp;
 
537
        }
 
538
      }
 
539
    }
 
540
  }
 
541
}
 
542
 
 
543
NLM_EXTERN void AddCommentStringWithTildes (StringItemPtr ffstring, CharPtr string)
 
544
{
 
545
/* One "~" is a  new line, "~~" or "~~ ~~" means 2 returns */       
 
546
 
 
547
    /* Int2  i; */
 
548
 
 
549
    while (*string != '\0') {
 
550
        if (*string == '`' && *(string+1) == '~') {
 
551
            FFAddOneChar(ffstring, '~', FALSE);
 
552
            string += 2;
 
553
        } else if (*string == '~') {
 
554
            FFAddOneChar(ffstring, '\n', FALSE);
 
555
            string++;
 
556
            if (*string == '~') {
 
557
                /*
 
558
                for (i = 0; i < 12; i++) {
 
559
                    FFAddOneChar(ffstring, ' ', FALSE);
 
560
                }
 
561
                */
 
562
                FFAddOneChar(ffstring, '\n', FALSE);
 
563
                string++;
 
564
            if (*string == ' ' && *(string+1) == '~' && *(string+2) == '~') {
 
565
                    string += 3;
 
566
            }
 
567
          }
 
568
        } else if (*string == '\"') {   
 
569
            *string = '\'';
 
570
            FFAddOneChar(ffstring, *string, FALSE);
 
571
            string++;
 
572
        } else {  
 
573
            FFAddOneChar(ffstring, *string, FALSE);
 
574
            string++;
 
575
        }
 
576
    }
 
577
}    /* AddCommentStringWithTildes */
 
578
 
 
579
 
 
580
NLM_EXTERN void AddStringWithTildes (StringItemPtr ffstring, CharPtr string)
 
581
{
 
582
/* One "~" is a  new line, "~~" or "~~ ~~" means 2 returns */       
 
583
 
 
584
    while (*string != '\0') {
 
585
        if (*string == '`' && *(string+1) == '~') {
 
586
            FFAddOneChar(ffstring, '~', FALSE);
 
587
            string += 2;
 
588
        } else if (*string == '~') {
 
589
            FFAddOneChar(ffstring, '\n', FALSE);
 
590
            string++;
 
591
            if (*string == '~') {
 
592
                FFAddOneChar(ffstring, '\n', FALSE);
 
593
                string++;
 
594
        if (*string == ' ' && *(string+1) == '~' && *(string+2) == '~') {
 
595
                    string += 3;
 
596
        }
 
597
      }
 
598
        } else if (*string == '\"') {   
 
599
            *string = '\'';
 
600
            FFAddOneChar(ffstring, *string, FALSE);
 
601
            string++;
 
602
        } else {  
 
603
            FFAddOneChar(ffstring, *string, FALSE);
 
604
            string++;
 
605
        }
 
606
    }
 
607
}    /* AddStringWithTildes */
 
608
 
 
609
 
 
610
NLM_EXTERN void FFProcessTildes (StringItemPtr sip, CharPtr PNTR cpp, Int2 tildeAction) {
 
611
    
 
612
  switch (tildeAction) {
 
613
 
 
614
  case TILDE_EXPAND :
 
615
      FFExpandTildes(sip, cpp);
 
616
      break;
 
617
 
 
618
  case TILDE_OLD_EXPAND :
 
619
      FFOldExpand(sip, cpp);
 
620
      break;
 
621
 
 
622
  case TILDE_TO_SPACES :
 
623
      FFReplaceTildesWithSpaces (sip, cpp);
 
624
      break;
 
625
 
 
626
  case TILDE_IGNORE:
 
627
  default:
 
628
      FFAddOneChar(sip, **cpp, FALSE);
 
629
      break;
 
630
  }
 
631
}
 
632
 
 
633
NLM_EXTERN void FFAddPeriod (StringItemPtr sip) {
 
634
  Int4 i;
 
635
  Char ch  = '\0';
 
636
  StringItemPtr riter = sip->curr, prev;
 
637
  IntAsn2gbJobPtr ajp;
 
638
 
 
639
  if ( sip == NULL ) return;
 
640
  ajp = (IntAsn2gbJobPtr)sip->iajp;
 
641
  if ( ajp == NULL ) return;
 
642
 
 
643
  for ( i = riter->pos - 1; i >= 0; --i ) {
 
644
    ch = riter->buf[i];
 
645
 
 
646
    if ( (ch == ' ') || (ch == '\t')  || (ch == '~')  || (ch == '.') || (ch == '\n')) {
 
647
      riter->pos--;
 
648
      
 
649
      if ( i < 0 && riter != sip ) {
 
650
        for ( prev = sip; prev->next != NULL; prev = prev->next ) {
 
651
          if ( prev->next == riter ) {
 
652
            i = prev->pos - 1;
 
653
            FFRecycleString(ajp, riter);
 
654
            riter = prev;
 
655
            riter->next = NULL;
 
656
              sip->curr = riter;
 
657
            break;
 
658
          }
 
659
        }
 
660
      }
 
661
 
 
662
    } else {
 
663
      break;
 
664
    }
 
665
  }
 
666
 
 
667
  if (ch != '.') {
 
668
    FFAddOneChar(sip, '.', FALSE);
 
669
  }
 
670
}
 
671
 
 
672
NLM_EXTERN void FFAddOneString (
 
673
  StringItemPtr sip, 
 
674
  CharPtr string,
 
675
  Boolean addPeriod, 
 
676
  Boolean convertQuotes,
 
677
  Int2 tildeAction
 
678
)
 
679
{
 
680
  CharPtr strp = string;
 
681
 
 
682
  if ( string == NULL ) return;
 
683
  
 
684
  while ( *strp != '\0' ) {
 
685
    if ( (*strp == '`') || (*strp == '~') ) {
 
686
      FFProcessTildes(sip, &strp, tildeAction);
 
687
    } else {
 
688
      FFAddOneChar(sip, *strp, convertQuotes);
 
689
    }
 
690
    strp++;
 
691
  }
 
692
 
 
693
  if ( addPeriod ) {
 
694
    FFAddPeriod(sip);
 
695
  }
 
696
}
 
697
 
 
698
NLM_EXTERN void FFCatenateSubString (
 
699
  StringItemPtr dest,
 
700
  StringItemPtr start_sip, Int4 start_pos,
 
701
  StringItemPtr end_sip, Int4 end_pos
 
702
)
 
703
{
 
704
  Int4 max_i, min_i, i;
 
705
  StringItemPtr current;
 
706
  Boolean in_url = FALSE;
 
707
  IntAsn2gbJobPtr ajp = (IntAsn2gbJobPtr)dest->iajp;
 
708
 
 
709
  if ( GetWWW(ajp) ) {
 
710
    for ( current = start_sip, i = start_pos;
 
711
    current != NULL; 
 
712
    current = current->next ) {
 
713
      if ( current == start_sip ) {
 
714
        min_i = start_pos;
 
715
      } else {
 
716
        min_i = 0;
 
717
      }
 
718
      
 
719
      if ( current == end_sip ) {
 
720
        max_i = end_pos;
 
721
      } else {
 
722
        max_i = current->pos;
 
723
      }
 
724
      
 
725
      for ( i = min_i; i < max_i; ++i ) {
 
726
        if ( current->buf[i] == '<' ) {
 
727
          if ( !FFIsStartOfLink(current, i) ) {
 
728
            FFAddOneString(dest, "&lt;", FALSE, FALSE, TILDE_IGNORE);
 
729
            continue;
 
730
          } else {
 
731
            in_url = TRUE;
 
732
          }
 
733
        }
 
734
        if ( current->buf[i] == '>' ) {
 
735
          if ( !in_url ) {
 
736
            FFAddOneString(dest, "&gt;", FALSE, FALSE, TILDE_IGNORE);
 
737
            continue;
 
738
          } else {
 
739
            in_url = FALSE;
 
740
          }
 
741
        } 
 
742
 
 
743
        FFAddOneChar(dest, current->buf[i], FALSE);
 
744
      }
 
745
 
 
746
      if ( current == end_sip ) break;
 
747
    }
 
748
  } else {
 
749
    for ( current = start_sip, i = start_pos;
 
750
    current != NULL; 
 
751
    current = current->next ) {
 
752
      if ( current == start_sip ) {
 
753
        min_i = start_pos;
 
754
      } else {
 
755
        min_i = 0;
 
756
      }
 
757
      
 
758
      if ( current == end_sip ) {
 
759
        max_i = end_pos;
 
760
      } else {
 
761
        max_i = current->pos;
 
762
      }
 
763
      
 
764
      for ( i = min_i; i < max_i; ++i ) {
 
765
        FFAddOneChar(dest, current->buf[i], FALSE);
 
766
      }
 
767
      
 
768
      if ( current == end_sip ) break;
 
769
    }
 
770
  }
 
771
}
 
772
 
 
773
 
 
774
NLM_EXTERN CharPtr FFToCharPtr (StringItemPtr sip) {
 
775
  Int4 size = 0, i;
 
776
  StringItemPtr iter;
 
777
  CharPtr result, temp;
 
778
 
 
779
  for ( iter = sip; iter != NULL; iter = iter->next ) {
 
780
    size += iter->pos;
 
781
  }
 
782
 
 
783
  result = (CharPtr)MemNew(size + 2);
 
784
  temp = result;
 
785
 
 
786
  for ( iter = sip; iter != NULL; iter = iter->next ) {
 
787
    for ( i = 0; i < iter->pos; ++i ) {
 
788
      *temp = iter->buf[i];
 
789
      ++temp;
 
790
    }
 
791
  }
 
792
 
 
793
  *temp = '\0';
 
794
 
 
795
  return result;
 
796
}
 
797
 
 
798
 
 
799
/* word wrap functions */
 
800
 
 
801
NLM_EXTERN void FFSkipLink (StringItemPtr PNTR iterp, Int4Ptr ip) {
 
802
  StringItemPtr iter = *iterp;
 
803
  Int4 i = *ip;
 
804
 
 
805
  while ( (iter != NULL) && (iter->buf[i] != '>') ) {
 
806
    ++i;
 
807
 
 
808
    if ( i == iter->pos ) {
 
809
      iter = iter->next;
 
810
      i = 0;
 
811
    }
 
812
  }
 
813
  ++i;
 
814
  if ( i == iter->pos && iter->next != NULL ) {
 
815
    iter = iter->next;
 
816
    i = 0;
 
817
  }
 
818
 
 
819
  *iterp = iter;
 
820
  *ip = i;
 
821
}
 
822
 
 
823
NLM_EXTERN Boolean FFIsStartOfLink (StringItemPtr iter, Int4 pos)  {
 
824
  static CharPtr start_link = "<A HREF";
 
825
  static CharPtr end_link = "</A>";
 
826
  Int4 start_len = StringLen(start_link);
 
827
  Int4 end_len = StringLen(end_link);
 
828
  Char temp[10];
 
829
  Int4 i;
 
830
 
 
831
  if ( iter == NULL || pos >= iter->pos ) return FALSE;
 
832
  if ( iter->buf[pos] != '<' ) return FALSE;
 
833
 
 
834
  MemSet(temp, 0, sizeof(temp));
 
835
  for ( i = 0; i < start_len && iter != NULL; ++i ) {
 
836
    if ( pos + i < iter->pos ) {
 
837
      temp[i] = iter->buf[pos+i];
 
838
      if ( i == end_len - 1 ) {
 
839
        if ( StringNICmp(temp, end_link, end_len) == 0 ) {
 
840
          return TRUE;
 
841
        }
 
842
      }
 
843
    } else {
 
844
      iter = iter->next;
 
845
      pos = -i;
 
846
      --i;
 
847
    }
 
848
  }
 
849
 
 
850
  if ( i == start_len ) {
 
851
    if ( StringNICmp(temp, start_link, start_len) == 0 ) {
 
852
        return TRUE;
 
853
    }
 
854
  }
 
855
 
 
856
  return FALSE;
 
857
}
 
858
 
 
859
 
 
860
NLM_EXTERN void FFSavePosition(StringItemPtr ffstring, StringItemPtr PNTR bufptr, Int4 PNTR posptr) {
 
861
  *bufptr = ffstring->curr;
 
862
  *posptr = ffstring->curr->pos;
 
863
}
 
864
 
 
865
 
 
866
NLM_EXTERN void FFTrim (
 
867
    StringItemPtr ffstring,
 
868
    StringItemPtr line_start,
 
869
    Int4 line_pos,
 
870
    Int4 line_prefix_len
 
871
)
 
872
{
 
873
  StringItemPtr riter, iter;
 
874
  Int4 i;
 
875
  IntAsn2gbJobPtr ajp = (IntAsn2gbJobPtr)ffstring->iajp;
 
876
 
 
877
  for ( i = 0; i < line_prefix_len; ++i ) {
 
878
    ++line_pos;
 
879
    if ( line_pos == STRING_BUF_LEN ) {
 
880
      line_pos = 0;
 
881
      line_start= line_start->next;
 
882
    }
 
883
  }
 
884
 
 
885
  riter = ffstring->curr;
 
886
  while ( riter != NULL ) {
 
887
    for ( i = riter->pos - 1;
 
888
          (i >= 0) && !(riter == line_start && i <= line_pos);
 
889
          --i ) {
 
890
      if ( !IS_WHITESP(riter->buf[i]) || (riter->buf[i] == '\n') ) {
 
891
        break;
 
892
      }
 
893
    }
 
894
    if ( i < 0 ) {
 
895
      i = STRING_BUF_LEN - 1;
 
896
      for ( iter = ffstring; iter != NULL; iter = iter->next ) {
 
897
        if ( iter->next == riter ) {
 
898
          break;
 
899
        }
 
900
      }
 
901
      if ( iter == NULL ){
 
902
        ffstring->pos = 0;
 
903
        break;
 
904
      } else {
 
905
        
 
906
        riter = iter;
 
907
        ffstring->curr = riter;
 
908
      }
 
909
    } else {
 
910
      riter->pos = i + 1;
 
911
      FFRecycleString(ajp, riter->next);
 
912
      riter->next = NULL;
 
913
      break;
 
914
    }
 
915
  }
 
916
}
 
917
 
 
918
 
 
919
 
 
920
/* A line is wrapped when the visble text in th eline exceeds the line size. */
 
921
/* Visible text is text that is not an HTML hyper-link.                      */
 
922
/* A line may be broken in one of the following characters:                  */
 
923
/* space, comma and dash                                                     */
 
924
/* the oredr of search is first spaces, then commas and then dashes.         */
 
925
/* We nee to take into account the possiblity that a 'new-line' character    */
 
926
/* already exists in the line, in such case we break at the 'new-line'       */
 
927
/* spaces, dashes and new-lines will be broken at that character wheras for  */
 
928
/* commas we break at the character following the comma.                     */
 
929
 
 
930
NLM_EXTERN void FFCalculateLineBreak (
 
931
  StringItemPtr PNTR break_sip, Int4 PNTR break_pos,
 
932
  Int4 init_indent, Int4 visible
 
933
)
 
934
{
 
935
  StringItemPtr iter, prev;
 
936
  Int4 i,
 
937
       done = FALSE,
 
938
       copied = 0, 
 
939
       start = *break_pos;
 
940
  Char ch;
 
941
  Boolean found_comma = FALSE, found_dash = FALSE;
 
942
  /* each candidate is a pair of buffer and position withingh this buffer */
 
943
  StringItemPtr candidate_sip_space = NULL,
 
944
                candidate_sip_comma = NULL,
 
945
                candidate_sip_dash  = NULL;
 
946
  Int4          candidate_int_space = -1,  
 
947
                candidate_int_comma = -1,
 
948
                candidate_int_dash  = -1;
 
949
  
 
950
 
 
951
  iter = *break_sip;
 
952
  prev = iter;
 
953
 
 
954
  /* skip the first 'init_indent' characters of the line */
 
955
  while ( iter != NULL && !done ) {
 
956
    for ( i = start; i < iter->pos && init_indent > 0; ++i ) {
 
957
      if ( iter->buf[i] == '\n' ) {
 
958
        candidate_sip_space = iter;
 
959
        candidate_int_space = i;
 
960
        done = TRUE;
 
961
        break;
 
962
      }
 
963
      if ( FFIsStartOfLink(iter, i) ) {
 
964
        FFSkipLink(&iter, &i);
 
965
        --i;
 
966
        continue;
 
967
      }
 
968
 
 
969
      --init_indent;
 
970
      ++copied;
 
971
    }
 
972
    if ( init_indent > 0 ) {
 
973
      start = 0;
 
974
      iter = iter->next;
 
975
    } else {
 
976
      break;
 
977
    }
 
978
  }
 
979
  start = i;
 
980
 
 
981
  while ( iter != NULL && !done ) {
 
982
    for ( i = start; i < iter->pos; ++i ) {
 
983
      if ( found_comma ) {
 
984
        candidate_sip_comma = iter;
 
985
        candidate_int_comma = i;
 
986
        found_comma = FALSE;
 
987
      }
 
988
      if ( found_dash ) {
 
989
        candidate_sip_dash = iter;
 
990
        candidate_int_dash = i;
 
991
        found_dash= FALSE;
 
992
      }
 
993
 
 
994
      ch = iter->buf[i];
 
995
      if ( ch == '\n' ) {
 
996
        candidate_sip_space = iter;
 
997
        candidate_int_space = i;
 
998
        done = TRUE;
 
999
        break;
 
1000
      } else if ( ch == ' ' ) {
 
1001
        candidate_sip_space = iter;
 
1002
        candidate_int_space = i;
 
1003
      } else if ( ch == ',' ) {
 
1004
        found_comma = TRUE;
 
1005
      } else if ( ch == '-' ) {
 
1006
        found_dash = TRUE;
 
1007
        /*candidate_sip_dash = iter;
 
1008
        candidate_int_dash = i;*/
 
1009
      }
 
1010
 
 
1011
      if ( FFIsStartOfLink(iter, i) ) {
 
1012
        FFSkipLink(&iter, &i);
 
1013
        --i;
 
1014
        continue;
 
1015
      }
 
1016
 
 
1017
      ++copied;
 
1018
      if ( copied >= visible ) {
 
1019
        if ( (candidate_sip_space == NULL) && (candidate_int_space == -1) &&
 
1020
             (candidate_sip_comma == NULL) && (candidate_int_comma == -1) &&
 
1021
             (candidate_sip_dash == NULL)  && (candidate_int_dash == -1)  ) {
 
1022
          candidate_sip_space = iter;
 
1023
          candidate_int_space = i;
 
1024
        }
 
1025
        done = TRUE;
 
1026
        break;
 
1027
      }      
 
1028
    }
 
1029
    start = 0;
 
1030
    if ( !done ) {
 
1031
      prev = iter;
 
1032
      iter = iter->next;
 
1033
    }
 
1034
  }
 
1035
  
 
1036
  /* the order in which we examine the various candidate breaks is important */
 
1037
  if ( iter == NULL && !done) { /* reached the end */
 
1038
    *break_sip = prev;
 
1039
    *break_pos = prev->pos;
 
1040
  } else {
 
1041
    if( candidate_sip_space != NULL ) {
 
1042
        *break_sip = candidate_sip_space;
 
1043
        *break_pos = candidate_int_space;
 
1044
    } else if( candidate_sip_comma != NULL ) {
 
1045
        *break_sip = candidate_sip_comma;
 
1046
      *break_pos = candidate_int_comma;
 
1047
    } else if( candidate_sip_dash != NULL ) {
 
1048
      *break_sip = candidate_sip_dash;
 
1049
      *break_pos = candidate_int_dash;
 
1050
    }
 
1051
  }
 
1052
}
 
1053
 
 
1054
NLM_EXTERN void FFLineWrap (
 
1055
  StringItemPtr dest, 
 
1056
  StringItemPtr src, 
 
1057
  Int4 init_indent,
 
1058
  Int4 cont_indent, 
 
1059
  Int4 line_max,
 
1060
  CharPtr eb_line_prefix
 
1061
)
 
1062
{
 
1063
  /* line break candidate is a pair <StringItepPtr, position> */
 
1064
  StringItemPtr break_sip = src;
 
1065
  Int4          break_pos = 0;
 
1066
  StringItemPtr line_start = NULL;
 
1067
  Int4          line_pos = 0;
 
1068
  Int4          i, line_prefix_len = 0;
 
1069
  StringItemPtr iter;
 
1070
 
 
1071
  FFSavePosition(dest, &line_start, &line_pos);
 
1072
 
 
1073
  for ( iter = src; iter != NULL; iter = iter->next ) {
 
1074
    for ( i = 0; i < iter->pos; ) {
 
1075
      break_pos = i;
 
1076
      break_sip = iter;
 
1077
 
 
1078
      FFCalculateLineBreak(&break_sip, &break_pos, init_indent, line_max - line_prefix_len + 1);
 
1079
      FFCatenateSubString(dest, iter, i, break_sip, break_pos);
 
1080
      FFTrim(dest, line_start, line_pos, cont_indent);
 
1081
      FFAddOneChar(dest, '\n', FALSE);
 
1082
      
 
1083
      FFSavePosition(dest, &line_start, &line_pos);
 
1084
 
 
1085
      i = break_pos;
 
1086
      iter = break_sip;
 
1087
 
 
1088
      if ( iter->buf[i-1] == 'X' && iter->buf[i-2] == 'X') {
 
1089
        if ( (i == 2) || ((i > 2) && (iter->buf[i-3] == '\n')) ) {
 
1090
          ++i;
 
1091
          continue;
 
1092
        } 
 
1093
      }
 
1094
 
 
1095
      if ( IS_WHITESP(iter->buf[i]) ) {
 
1096
        i++;
 
1097
      }
 
1098
      if ( iter != src->curr || i < iter->pos ) {
 
1099
        if ( eb_line_prefix != NULL ) {
 
1100
          FFAddOneString(dest, eb_line_prefix, FALSE, FALSE, TILDE_IGNORE);
 
1101
        }
 
1102
        FFAddNChar(dest, ' ', cont_indent - StringLen(eb_line_prefix), FALSE);
 
1103
        init_indent = 0;
 
1104
        line_prefix_len = cont_indent;
 
1105
        /*FFSkipGarbage(&iter, &i);*/
 
1106
      }
 
1107
    }
 
1108
  }
 
1109
}
 
1110
 
 
1111
/* === */
 
1112
 
 
1113
NLM_EXTERN void FFStartPrint (
 
1114
  StringItemPtr sip,
 
1115
  FmtType format,
 
1116
  Int4 gb_init_indent,
 
1117
  Int4 gb_cont_indent,
 
1118
  CharPtr gb_label,
 
1119
  Int4 gb_tab_to,
 
1120
  Int4 eb_init_indent,
 
1121
  Int4 eb_cont_indent,
 
1122
  CharPtr eb_line_prefix,
 
1123
  Boolean eb_print_xx 
 
1124
)
 
1125
 
 
1126
{
 
1127
  if (format == GENBANK_FMT || format == GENPEPT_FMT) {
 
1128
    FFAddNChar(sip, ' ', gb_init_indent, FALSE);
 
1129
    FFAddOneString(sip, gb_label, FALSE, FALSE, TILDE_IGNORE);
 
1130
    FFAddNChar(sip, ' ', gb_tab_to - gb_init_indent - StringLen(gb_label), FALSE);
 
1131
  } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
 
1132
    if ( eb_print_xx ) {
 
1133
      FFAddOneString(sip, "XX\n", FALSE, FALSE, TILDE_IGNORE);
 
1134
    }
 
1135
    FFAddOneString(sip, eb_line_prefix, FALSE, FALSE, TILDE_IGNORE);
 
1136
    FFAddNChar(sip, ' ', eb_init_indent - StringLen(eb_line_prefix), FALSE);
 
1137
  }
 
1138
}
 
1139
 
 
1140
NLM_EXTERN void FFAddTextToString (
 
1141
  StringItemPtr ffstring, 
 
1142
  CharPtr prefix,
 
1143
  CharPtr string,
 
1144
  CharPtr suffix,
 
1145
  Boolean addPeriod,
 
1146
  Boolean convertQuotes,
 
1147
  Int2 tildeAction
 
1148
)
 
1149
 
 
1150
{
 
1151
  FFAddOneString (ffstring, prefix, FALSE, FALSE, TILDE_IGNORE);
 
1152
  FFAddOneString (ffstring, string, FALSE, convertQuotes, tildeAction);
 
1153
  FFAddOneString (ffstring, suffix, FALSE, FALSE, TILDE_IGNORE);
 
1154
 
 
1155
  if ( addPeriod ) {
 
1156
    FFAddPeriod(ffstring);
 
1157
  }
 
1158
}
 
1159
   
 
1160
 
 
1161
NLM_EXTERN CharPtr FFEndPrint (
 
1162
  IntAsn2gbJobPtr ajp,
 
1163
  StringItemPtr ffstring,
 
1164
  FmtType format,
 
1165
  Int2 gb_init_indent,
 
1166
  Int2 gb_cont_indent,
 
1167
  Int2 eb_init_indent,
 
1168
  Int2 eb_cont_indent,
 
1169
  CharPtr eb_line_prefix
 
1170
)
 
1171
{
 
1172
  StringItemPtr temp = FFGetString(ajp);
 
1173
  CharPtr result;
 
1174
 
 
1175
  if ( (ffstring == NULL) || (ajp == NULL) ) return NULL;
 
1176
 
 
1177
  if (format == GENBANK_FMT || format == GENPEPT_FMT) {
 
1178
    FFLineWrap(temp, ffstring, gb_init_indent, gb_cont_indent, ASN2FF_GB_MAX, NULL);
 
1179
  } else {
 
1180
    FFLineWrap(temp, ffstring, eb_init_indent, eb_cont_indent, ASN2FF_EMBL_MAX, eb_line_prefix);
 
1181
  }
 
1182
 
 
1183
  result = FFToCharPtr(temp);
 
1184
  FFRecycleString(ajp, temp);
 
1185
  return result;
 
1186
}
 
1187
 
 
1188
NLM_EXTERN Uint4 FFLength(StringItemPtr ffstring) {
 
1189
  Uint4 len = 0;
 
1190
  StringItemPtr current;
 
1191
 
 
1192
  for ( current = ffstring; current != NULL; current = current->next ) {
 
1193
    len += current->pos;
 
1194
  }
 
1195
 
 
1196
  return len;
 
1197
}
 
1198
 
 
1199
 
 
1200
NLM_EXTERN Char FFCharAt(StringItemPtr ffstring, Uint4 pos) {
 
1201
  Uint4 count = 0, inbufpos;
 
1202
  StringItemPtr current = NULL;
 
1203
 
 
1204
  inbufpos = pos % STRING_BUF_LEN;
 
1205
  
 
1206
  for ( current = ffstring; current != NULL; current = current->next ) {
 
1207
    count += current->pos;
 
1208
    if ( count > pos ) break;
 
1209
  }
 
1210
 
 
1211
  if ( current != NULL && inbufpos <= pos )  {
 
1212
    return current->buf[inbufpos];
 
1213
  }
 
1214
 
 
1215
  return '\0';
 
1216
}
 
1217
 
 
1218
 
 
1219
NLM_EXTERN Char FFFindChar (
 
1220
  StringItemPtr ffstring,   /* StringItem to search in */
 
1221
  StringItemPtr start_buf,  /* the position of the last char searched for (buffer) */
 
1222
  Uint4 start_pos,          /* the position of the last char searched for (pos) */
 
1223
  Uint4 old_pos,         /* the global position searched for */
 
1224
  Uint4 new_pos             /* new search position */
 
1225
)
 
1226
{
 
1227
  Uint4 delta;
 
1228
  Uint4 count;
 
1229
  StringItemPtr current = NULL;
 
1230
 
 
1231
  Char result = '\0';
 
1232
 
 
1233
  if ( new_pos == old_pos ) {
 
1234
    result = start_buf->buf[start_pos];
 
1235
  } 
 
1236
 
 
1237
  if ( new_pos > old_pos ) {
 
1238
    delta = new_pos - old_pos;
 
1239
    current = start_buf;
 
1240
    count = current->pos - start_pos - 1;
 
1241
    current = current->next;
 
1242
    
 
1243
    while ( delta > count && current != NULL ) {
 
1244
      current = current->next;
 
1245
      count += current->pos;
 
1246
    }
 
1247
    
 
1248
    if ( current != NULL  )  {
 
1249
      result = current->buf[new_pos % STRING_BUF_LEN];
 
1250
    }
 
1251
    
 
1252
  } else /* new_pos < old_pos */ {
 
1253
    delta = old_pos - new_pos;
 
1254
    if ( old_pos % STRING_BUF_LEN >= delta ) {
 
1255
      result = start_buf->buf[new_pos % STRING_BUF_LEN];
 
1256
    } else {
 
1257
      result = FFCharAt(ffstring, new_pos);
 
1258
    }
 
1259
  }
 
1260
 
 
1261
  return result;
 
1262
}
 
1263
 
 
1264
NLM_EXTERN Boolean FFEmpty(StringItemPtr ffstring) {
 
1265
  if ( ffstring != NULL && ffstring->pos != 0 ) {
 
1266
    return FALSE;
 
1267
  }
 
1268
  return TRUE;
 
1269
}
 
1270
 
 
1271
/*
 
1272
 * Compute the right-most position in the pattern at which character a occurs,
 
1273
 * for each character a in the alphabet (assumed ASCII-ISO 8859-1)
 
1274
 * 
 
1275
 * The result is returned in the supplied vector.
 
1276
 */
 
1277
static void ComputeLastOccurrence(const CharPtr pattern, Uint4 last_occurrence[])
 
1278
{
 
1279
    Uint4 i;
 
1280
    Uint4 pat_len;
 
1281
 
 
1282
    /* Initilalize vector */
 
1283
    for ( i = 0; i < 256; ++i ) {
 
1284
        last_occurrence[i] = 0;
 
1285
    }
 
1286
 
 
1287
    /* compute right-most occurrence */
 
1288
    pat_len = StringLen(pattern);
 
1289
    for ( i = 0; i < pat_len; ++i ) {
 
1290
        last_occurrence[(Uint1)pattern[i]] = i;
 
1291
    }
 
1292
}
 
1293
 
 
1294
static void ComputePrefix(const CharPtr pattern, Uint4 longest_prefix[])
 
1295
{
 
1296
    Uint4 pat_len = StringLen(pattern);
 
1297
    Uint4 k, q;
 
1298
 
 
1299
    longest_prefix[0] = 0;
 
1300
 
 
1301
    k = 0;
 
1302
    for ( q = 1; q < pat_len; ++q ) {
 
1303
        while ( k > 0 && pattern[k] != pattern[q] ) {
 
1304
            k = longest_prefix[k - 1];
 
1305
        }
 
1306
        if ( pattern[k] == pattern[q] ) {
 
1307
            ++k;
 
1308
        }
 
1309
        longest_prefix[q] = k;
 
1310
    }
 
1311
}
 
1312
 
 
1313
 
 
1314
static void ComputeGoodSuffix(const CharPtr pattern, Uint4 good_suffix[])
 
1315
{
 
1316
    Uint4 pat_len = StringLen(pattern);
 
1317
    Uint4Ptr longest_prefix, reverse_longest_prefix;
 
1318
    CharPtr reverse_pattern;
 
1319
    Uint4 i, j;
 
1320
 
 
1321
    /* allocate memory */
 
1322
    longest_prefix = MemNew(pat_len * sizeof(Uint4));
 
1323
    reverse_longest_prefix = MemNew(pat_len * sizeof(Uint4));
 
1324
    reverse_pattern = MemNew((pat_len + 1) * sizeof(Char));
 
1325
 
 
1326
    if ( longest_prefix == NULL  ||
 
1327
         reverse_longest_prefix == NULL  ||
 
1328
         reverse_pattern == NULL ) {
 
1329
      MemFree(longest_prefix);
 
1330
      MemFree(reverse_longest_prefix);
 
1331
      MemFree(reverse_pattern);
 
1332
      return;
 
1333
    }
 
1334
 
 
1335
    /* compute reverse pattern */
 
1336
    for ( i = 0; i < pat_len; ++i ) {
 
1337
      reverse_pattern[pat_len - i] = pattern[i];
 
1338
    }
 
1339
 
 
1340
    ComputePrefix(pattern, longest_prefix);
 
1341
    ComputePrefix(reverse_pattern, reverse_longest_prefix);
 
1342
 
 
1343
    for ( j = 0; j < pat_len; ++j) {
 
1344
        good_suffix[j] = pat_len - longest_prefix[pat_len-1];
 
1345
    }
 
1346
 
 
1347
    for ( i = 0; i < pat_len; ++i ) {
 
1348
        j = pat_len - reverse_longest_prefix[i] - 1;
 
1349
        if ( good_suffix[j] > i - reverse_longest_prefix[i] + 1) {
 
1350
            good_suffix[j] = i - reverse_longest_prefix[i] + 1;
 
1351
        }
 
1352
    }
 
1353
 
 
1354
    MemFree(longest_prefix);
 
1355
    MemFree(reverse_longest_prefix);
 
1356
    MemFree(reverse_pattern);
 
1357
}
 
1358
 
 
1359
 
 
1360
/*
 
1361
 * searches for a pattern in a StringItem.
 
1362
 * Using the Boyer-Moore algorithm for the search.
 
1363
 */
 
1364
NLM_EXTERN Int4 FFStringSearch (
 
1365
  StringItemPtr text,
 
1366
  const CharPtr pattern,
 
1367
  Uint4 position )
 
1368
{
 
1369
  Uint4 text_len = FFLength(text);
 
1370
  Uint4 pat_len = StringLen(pattern);
 
1371
  Uint4 last_occurrence[256];
 
1372
  Uint4Ptr good_suffix;
 
1373
  Uint4 shift;
 
1374
  Int4 j;
 
1375
 
 
1376
  if ( pat_len == 0 ) return 0;
 
1377
  if ( text_len == 0 || pat_len > text_len - position ) return -1;
 
1378
  
 
1379
  good_suffix = (Uint4Ptr)MemNew(pat_len * sizeof(Int4));
 
1380
  if ( good_suffix == NULL ) return -1;
 
1381
 
 
1382
  ComputeLastOccurrence(pattern, last_occurrence);
 
1383
  ComputeGoodSuffix(pattern, good_suffix);
 
1384
 
 
1385
  shift = position;
 
1386
  while ( shift <= text_len - pat_len ) {
 
1387
    j = pat_len - 1;
 
1388
    while( j >= 0 && pattern[j] == FFCharAt(text,shift + j) ) {
 
1389
      --j;
 
1390
    }
 
1391
    if ( j == -1 ) {
 
1392
      MemFree (good_suffix);
 
1393
      return shift;
 
1394
    } else {
 
1395
        shift += MAX( (Int4)good_suffix[j],
 
1396
              (Int4)(j - last_occurrence[FFCharAt(text,shift + j)]));
 
1397
    }
 
1398
  }
 
1399
  MemFree (good_suffix);
 
1400
 
 
1401
  return -1;
 
1402
}
 
1403
 
 
1404
 
 
1405
/*                                                                   */
 
1406
/* IsWholeWordSubstr () -- Determines if a substring that is         */
 
1407
/*                         contained in another string is a whole    */
 
1408
/*                         word or phrase -- i.e. is it both         */
 
1409
/*                         preceded and followed by white space.     */
 
1410
/*                                                                   */
 
1411
 
 
1412
NLM_EXTERN Boolean IsWholeWordSubstr (
 
1413
  StringItemPtr searchStr,
 
1414
  Uint4 foundPos,
 
1415
  CharPtr subStr
 
1416
)
 
1417
{
 
1418
    Boolean left, right;
 
1419
    Char ch;
 
1420
 
 
1421
 
 
1422
    /* check on the left only if there is a character there */
 
1423
    if (foundPos > 0) {
 
1424
        ch = FFCharAt(searchStr, foundPos - 1);
 
1425
        left = IS_WHITESP(ch) || ispunct(ch);
 
1426
    } else {
 
1427
        left = TRUE;
 
1428
    }
 
1429
 
 
1430
    foundPos += StringLen(subStr);
 
1431
  if ( foundPos == FFLength(searchStr) ) {
 
1432
    right = TRUE;
 
1433
  } else {
 
1434
    ch = FFCharAt(searchStr, foundPos);
 
1435
      right = IS_WHITESP(ch) || ispunct(ch);
 
1436
  }
 
1437
 
 
1438
    return left; /* see comment above */
 
1439
  /* return left && right;  this is how it should be!*/
 
1440
}
 
1441
 
 
1442
 
 
1443
/* functions to record sections or blocks in linked lists */
 
1444
 
 
1445
NLM_EXTERN BaseBlockPtr Asn2gbAddBlock (
 
1446
  Asn2gbWorkPtr awp,
 
1447
  BlockType blocktype,
 
1448
  size_t size
 
1449
)
 
1450
 
 
1451
{
 
1452
  BaseBlockPtr  bbp;
 
1453
  ValNodePtr    vnp;
 
1454
 
 
1455
  if (awp == NULL || size < 1) return NULL;
 
1456
 
 
1457
  bbp = (BaseBlockPtr) MemNew (size);
 
1458
  if (bbp == NULL) return NULL;
 
1459
  bbp->blocktype = blocktype;
 
1460
  bbp->section = awp->currsection;
 
1461
 
 
1462
  vnp = ValNodeAddPointer (&(awp->lastblock), 0, bbp);
 
1463
  if (vnp == NULL) return bbp;
 
1464
 
 
1465
  awp->lastblock = vnp;
 
1466
  if (awp->blockList == NULL) {
 
1467
    awp->blockList = vnp;
 
1468
  }
 
1469
 
 
1470
  return bbp;
 
1471
}
 
1472
 
 
1473
 
 
1474
/*--------------------------------------------------------*/
 
1475
/*                                                        */
 
1476
/*  s_LocusGetBaseName() -                                */
 
1477
/*                                                        */
 
1478
/*--------------------------------------------------------*/
 
1479
 
 
1480
static Boolean s_LocusGetBaseName (BioseqPtr parent, BioseqPtr segment, CharPtr baseName)
 
1481
{
 
1482
  Char          parentName[SEQID_MAX_LEN];
 
1483
  Char          segName[SEQID_MAX_LEN];
 
1484
  SeqIdPtr      sip;
 
1485
  TextSeqIdPtr  tsip;
 
1486
  Char          prefix[5];
 
1487
  Char          bufTmp[SEQID_MAX_LEN];
 
1488
  Int2          deleteChars;
 
1489
  Int2          newLength;
 
1490
  Int2          i;
 
1491
  Uint2         segNameLen;
 
1492
 
 
1493
  /* Get the parent Sequence ID */
 
1494
 
 
1495
  parentName [0] = '\0';
 
1496
  sip = NULL;
 
1497
  for (sip = parent->id; sip != NULL; sip = sip->next) {
 
1498
    if (sip->choice == SEQID_GENBANK ||
 
1499
        sip->choice == SEQID_EMBL ||
 
1500
        sip->choice == SEQID_DDBJ) break;
 
1501
    if (sip->choice == SEQID_TPG ||
 
1502
        sip->choice == SEQID_TPE ||
 
1503
        sip->choice == SEQID_TPD) break;
 
1504
  }
 
1505
 
 
1506
  if (sip != NULL) {
 
1507
    tsip = (TextSeqIdPtr) sip->data.ptrvalue;
 
1508
    if (tsip != NULL && (! StringHasNoText (tsip->name))) {
 
1509
      StringNCpy_0 (parentName, tsip->name, sizeof (parentName));
 
1510
    }
 
1511
  }
 
1512
 
 
1513
  if (StringHasNoText (parentName)) {
 
1514
    StringNCpy_0 (parentName, baseName, sizeof (parentName));
 
1515
  }
 
1516
 
 
1517
  /* Get segment id */
 
1518
 
 
1519
  segName [0] = '\0';
 
1520
  segNameLen = 0;
 
1521
  sip = NULL;
 
1522
  for (sip = segment->id; sip != NULL; sip = sip->next) {
 
1523
    if (sip->choice == SEQID_GENBANK ||
 
1524
        sip->choice == SEQID_EMBL ||
 
1525
        sip->choice == SEQID_DDBJ) break;
 
1526
    if (sip->choice == SEQID_TPG ||
 
1527
        sip->choice == SEQID_TPE ||
 
1528
        sip->choice == SEQID_TPD) break;
 
1529
    }
 
1530
 
 
1531
  if (sip != NULL) {
 
1532
    tsip = (TextSeqIdPtr) sip->data.ptrvalue;
 
1533
    if (tsip != NULL && (! StringHasNoText (tsip->name))) {
 
1534
      StringNCpy_0 (segName, tsip->name, sizeof (segName));
 
1535
      segNameLen = StringLen(segName);
 
1536
    }
 
1537
  }
 
1538
 
 
1539
  /* If there's no "SEG_" prefix, then */
 
1540
  /* just use the parent ID.           */
 
1541
 
 
1542
  StringNCpy_0 (prefix,parentName,sizeof (prefix));
 
1543
  prefix[4] = '\0';
 
1544
  if (StringCmp(prefix,"SEG_") != 0)
 
1545
    {
 
1546
      StringCpy(baseName,parentName);
 
1547
      return FALSE;
 
1548
    }
 
1549
 
 
1550
  /* Otherwise, eliminate the "SEG_" ... */
 
1551
 
 
1552
  StringCpy(bufTmp, &parentName[4]);
 
1553
  StringCpy(parentName,bufTmp);
 
1554
 
 
1555
  /* ... And calculate a base name */
 
1556
 
 
1557
  if (segNameLen > 0 &&
 
1558
      (segName[segNameLen-1] == '1') &&
 
1559
      (StringLen(parentName) == segNameLen) &&
 
1560
      (parentName[segNameLen-1] == segName[segNameLen-1]))
 
1561
    {
 
1562
      deleteChars = 1;
 
1563
      for (i = segNameLen-2; i >= 0; i--)
 
1564
    if (parentName[i] == '0')
 
1565
      deleteChars++;
 
1566
    else
 
1567
      break;
 
1568
      newLength = segNameLen - deleteChars;
 
1569
      StringNCpy (parentName,segName,newLength); /* not StringNCpy_0 */
 
1570
      parentName[newLength] = '\0';
 
1571
    }
 
1572
 
 
1573
  /* Return the base name in the basename parameter */
 
1574
 
 
1575
  StringCpy(baseName,parentName);
 
1576
  return TRUE;
 
1577
}
 
1578
 
 
1579
/* ********************************************************************** */
 
1580
 
 
1581
  static Uint1 fasta_order [NUM_SEQID] = {
 
1582
    33, /* 0 = not set */
 
1583
    20, /* 1 = local Object-id */
 
1584
    15, /* 2 = gibbsq */
 
1585
    16, /* 3 = gibbmt */
 
1586
    30, /* 4 = giim Giimport-id */
 
1587
    10, /* 5 = genbank */
 
1588
    10, /* 6 = embl */
 
1589
    10, /* 7 = pir */
 
1590
    10, /* 8 = swissprot */
 
1591
    15, /* 9 = patent */
 
1592
    20, /* 10 = other TextSeqId */
 
1593
    20, /* 11 = general Dbtag */
 
1594
    255, /* 12 = gi */
 
1595
    10, /* 13 = ddbj */
 
1596
    10, /* 14 = prf */
 
1597
    12, /* 15 = pdb */
 
1598
    10, /* 16 = tpg */
 
1599
    10, /* 17 = tpe */
 
1600
    10  /* 18 = tpd */
 
1601
  };
 
1602
 
 
1603
/* DoOneSection builds a single report for one bioseq or segment */
 
1604
 
 
1605
static Asn2gbSectPtr Asn2gbAddSection (
 
1606
  Asn2gbWorkPtr awp
 
1607
)
 
1608
 
 
1609
{
 
1610
  Asn2gbSectPtr  asp;
 
1611
  ValNodePtr     vnp;
 
1612
 
 
1613
  if (awp == NULL) return NULL;
 
1614
 
 
1615
  asp = (Asn2gbSectPtr) MemNew (sizeof (IntAsn2gbSect));
 
1616
  if (asp == NULL) return NULL;
 
1617
 
 
1618
  vnp = ValNodeAddPointer (&(awp->lastsection), 0, asp);
 
1619
  if (vnp == NULL) return asp;
 
1620
 
 
1621
  awp->lastsection = vnp;
 
1622
  if (awp->sectionList == NULL) {
 
1623
    awp->sectionList = vnp;
 
1624
  }
 
1625
 
 
1626
  return asp;
 
1627
}
 
1628
 
 
1629
static void LIBCALLBACK SaveGBSeqSequence (
 
1630
  CharPtr sequence,
 
1631
  Pointer userdata
 
1632
)
 
1633
 
 
1634
{
 
1635
  CharPtr       tmp;
 
1636
  CharPtr PNTR  tmpp;
 
1637
 
 
1638
  tmpp = (CharPtr PNTR) userdata;
 
1639
  tmp = *tmpp;
 
1640
 
 
1641
  tmp = StringMove (tmp, sequence);
 
1642
 
 
1643
  *tmpp = tmp;
 
1644
}
 
1645
 
 
1646
static CharPtr CompressNonBases (CharPtr str)
 
1647
 
 
1648
{
 
1649
  Char     ch;
 
1650
  CharPtr  dst;
 
1651
  CharPtr  ptr;
 
1652
 
 
1653
  if (str == NULL || str [0] == '\0') return NULL;
 
1654
 
 
1655
  dst = str;
 
1656
  ptr = str;
 
1657
  ch = *ptr;
 
1658
  while (ch != '\0') {
 
1659
    if (IS_ALPHA (ch)) {
 
1660
      *dst = ch;
 
1661
      dst++;
 
1662
    }
 
1663
    ptr++;
 
1664
    ch = *ptr;
 
1665
  }
 
1666
  *dst = '\0';
 
1667
 
 
1668
  return str;
 
1669
}
 
1670
 
 
1671
static CharPtr DoSeqPortStream (
 
1672
  BioseqPtr bsp
 
1673
)
 
1674
 
 
1675
{
 
1676
  Char     ch;
 
1677
  CharPtr  str;
 
1678
  CharPtr  tmp;
 
1679
 
 
1680
  if (bsp == NULL) return NULL;
 
1681
 
 
1682
  str = MemNew (sizeof (Char) * (bsp->length + 10));
 
1683
  if (str == NULL) return NULL;
 
1684
 
 
1685
  tmp = str;
 
1686
  SeqPortStream (bsp, STREAM_EXPAND_GAPS, (Pointer) &tmp, SaveGBSeqSequence);
 
1687
 
 
1688
  tmp = str;
 
1689
  if (tmp == NULL) return NULL;
 
1690
  ch = *tmp;
 
1691
  while (ch != '\0') {
 
1692
    if (ch == '\n' || ch == '\r' || ch == '\t') {
 
1693
      *tmp = ' ';
 
1694
    }
 
1695
    tmp++;
 
1696
    ch = *tmp;
 
1697
  }
 
1698
  TrimSpacesAroundString (str);
 
1699
  CompressNonBases (str);
 
1700
 
 
1701
  return str;
 
1702
}
 
1703
 
 
1704
static Boolean DeltaLitOnly (
 
1705
  BioseqPtr bsp
 
1706
)
 
1707
 
 
1708
{
 
1709
  ValNodePtr  vnp;
 
1710
 
 
1711
  if (bsp == NULL || bsp->repr != Seq_repr_delta) return FALSE;
 
1712
  for (vnp = (ValNodePtr)(bsp->seq_ext); vnp != NULL; vnp = vnp->next) {
 
1713
    if (vnp->choice == 1) return FALSE;
 
1714
  }
 
1715
  return TRUE;
 
1716
}
 
1717
 
 
1718
static Boolean SegHasParts (
 
1719
  BioseqPtr bsp
 
1720
)
 
1721
 
 
1722
{
 
1723
  BioseqSetPtr  bssp;
 
1724
  SeqEntryPtr   sep;
 
1725
 
 
1726
  if (bsp == NULL || bsp->repr != Seq_repr_seg) return FALSE;
 
1727
  sep = bsp->seqentry;
 
1728
  if (sep == NULL) return FALSE;
 
1729
  sep = sep->next;
 
1730
  if (sep == NULL || (! IS_Bioseq_set (sep))) return FALSE;
 
1731
  bssp = (BioseqSetPtr) sep->data.ptrvalue;
 
1732
  if (bssp != NULL && bssp->_class == BioseqseqSet_class_parts) return TRUE;
 
1733
  return FALSE;
 
1734
}
 
1735
 
 
1736
NLM_EXTERN void DoOneSection (
 
1737
  BioseqPtr target,
 
1738
  BioseqPtr parent,
 
1739
  BioseqPtr bsp,
 
1740
  BioseqPtr refs,
 
1741
  SeqLocPtr slp,
 
1742
  Uint2 seg,
 
1743
  Int4 from,
 
1744
  Int4 to,
 
1745
  Boolean contig,
 
1746
  Boolean onePartOfSeg,
 
1747
  Asn2gbWorkPtr awp
 
1748
)
 
1749
 
 
1750
{
 
1751
  size_t               acclen;
 
1752
  Asn2gbFormatPtr      afp;
 
1753
  IntAsn2gbJobPtr      ajp;
 
1754
  Asn2gbSectPtr        asp;
 
1755
  SeqMgrBioseqContext  bcontext;
 
1756
  BaseBlockPtr         PNTR blockArray;
 
1757
  SeqMgrDescContext    dcontext;
 
1758
  Boolean              hasRefs;
 
1759
  Int4                 i;
 
1760
  IntAsn2gbSectPtr     iasp;
 
1761
  Boolean              isRefSeq = FALSE;
 
1762
  MolInfoPtr           mip;
 
1763
  Boolean              nsgenome = FALSE;
 
1764
  Int4                 numBlocks;
 
1765
  Int4                 numsegs = 0;
 
1766
  SeqDescrPtr          sdp;
 
1767
  SeqIdPtr             sip;
 
1768
  TextSeqIdPtr         tsip;
 
1769
  ValNodePtr           vnp;
 
1770
  Boolean              wgsmaster = FALSE;
 
1771
  Boolean              wgstech = FALSE;
 
1772
 
 
1773
  if (target == NULL || parent == NULL || bsp == NULL || awp == NULL) return;
 
1774
  ajp = awp->ajp;
 
1775
  if (ajp == NULL) return;
 
1776
 
 
1777
  if (awp->mode == RELEASE_MODE && awp->style == CONTIG_STYLE) {
 
1778
    if (bsp->repr == Seq_repr_seg) {
 
1779
    } else if (bsp->repr == Seq_repr_delta && (! DeltaLitOnly (bsp))) {
 
1780
    } else return;
 
1781
  }
 
1782
 
 
1783
  if (ajp->flags.suppressLocalID) {
 
1784
    sip = SeqIdSelect (bsp->id, fasta_order, NUM_SEQID);
 
1785
    if (sip == NULL || sip->choice == SEQID_LOCAL) return;
 
1786
  }
 
1787
 
 
1788
  if (seg == 0) {
 
1789
    awp->basename[0] = '\0';
 
1790
  } else if (seg == 1) {
 
1791
    s_LocusGetBaseName (parent, bsp, awp->basename);
 
1792
  }
 
1793
 
 
1794
  asp = Asn2gbAddSection (awp);
 
1795
  if (asp == NULL) return;
 
1796
 
 
1797
  afp = awp->afp;
 
1798
  if (afp != NULL) {
 
1799
    afp->asp = asp;
 
1800
  }
 
1801
 
 
1802
  numsegs = awp->partcount;
 
1803
  if (numsegs == 0 && SeqMgrGetBioseqContext (parent, &bcontext)) {
 
1804
    numsegs = bcontext.numsegs;
 
1805
  }
 
1806
 
 
1807
  /* set working data fields */
 
1808
 
 
1809
  awp->asp = asp;
 
1810
 
 
1811
  awp->target = target;
 
1812
  awp->parent = parent;
 
1813
  awp->bsp = bsp;
 
1814
  awp->refs = refs;
 
1815
  awp->slp = slp;
 
1816
  awp->seg = seg;
 
1817
  awp->numsegs = numsegs;
 
1818
  awp->from = from;
 
1819
  awp->to = to;
 
1820
  awp->contig = contig;
 
1821
 
 
1822
  awp->firstfeat = TRUE;
 
1823
  awp->featseen = FALSE;
 
1824
 
 
1825
  /* initialize empty blockList for this section */
 
1826
 
 
1827
  awp->blockList = NULL;
 
1828
  awp->lastblock = NULL;
 
1829
 
 
1830
  /* and store section data into section fields */
 
1831
 
 
1832
  asp->target = target;
 
1833
  asp->bsp = bsp;
 
1834
  asp->slp = slp;
 
1835
  asp->seg = seg;
 
1836
  asp->numsegs = numsegs;
 
1837
  asp->from = from;
 
1838
  asp->to = to;
 
1839
 
 
1840
  iasp = (IntAsn2gbSectPtr) asp;
 
1841
 
 
1842
  asp->blockArray = NULL;
 
1843
  asp->numBlocks = 0;
 
1844
 
 
1845
  /* WGS master and NS_ virtual records treated differently */
 
1846
 
 
1847
  if (bsp->repr == Seq_repr_virtual) {
 
1848
 
 
1849
    /* check for certain ID types */
 
1850
 
 
1851
    for (sip = bsp->id; sip != NULL; sip = sip->next) {
 
1852
      if (sip->choice == SEQID_GENBANK ||
 
1853
          sip->choice == SEQID_EMBL ||
 
1854
          sip->choice == SEQID_DDBJ) {
 
1855
        tsip = (TextSeqIdPtr) sip->data.ptrvalue;
 
1856
        if (tsip != NULL && tsip->accession != NULL) {
 
1857
          acclen = StringLen (tsip->accession);
 
1858
          if (acclen == 12) {
 
1859
            if (StringCmp (tsip->accession + 6, "000000") == 0) {
 
1860
              wgsmaster = TRUE;
 
1861
            }
 
1862
          } else if (acclen == 13) {
 
1863
            if (StringCmp (tsip->accession + 6, "0000000") == 0) {
 
1864
              wgsmaster = TRUE;
 
1865
            }
 
1866
          }
 
1867
        }
 
1868
     } else if (sip->choice == SEQID_OTHER) {
 
1869
        tsip = (TextSeqIdPtr) sip->data.ptrvalue;
 
1870
        if (tsip != NULL && tsip->accession != NULL) {
 
1871
          if (StringNICmp (tsip->accession, "NC_", 3) == 0) {
 
1872
            wgsmaster = TRUE;
 
1873
          } else if (StringNICmp (tsip->accession, "NS_", 3) == 0) {
 
1874
            nsgenome = TRUE;
 
1875
          } else if (StringNICmp (tsip->accession, "NZ_", 3) == 0) {
 
1876
            if (StringLen (tsip->accession) == 15) {
 
1877
              if (StringCmp (tsip->accession + 9, "000000") == 0) {
 
1878
                wgsmaster = TRUE;
 
1879
              }
 
1880
            }
 
1881
          }
 
1882
        }
 
1883
      }
 
1884
    }
 
1885
 
 
1886
    sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &dcontext);
 
1887
    if (sdp != NULL) {
 
1888
      mip = (MolInfoPtr) sdp->data.ptrvalue;
 
1889
      if (mip != NULL && mip->tech == MI_TECH_wgs) {
 
1890
        wgstech = TRUE;
 
1891
      }
 
1892
    }
 
1893
  }
 
1894
 
 
1895
  for (sip = bsp->id; sip != NULL; sip = sip->next) {
 
1896
    if (sip->choice == SEQID_OTHER) {
 
1897
      isRefSeq = TRUE;
 
1898
    }
 
1899
  }
 
1900
 
 
1901
  /* start exploring and populating paragraphs */
 
1902
 
 
1903
  if (awp->format == FTABLE_FMT) {
 
1904
    AddFeatHeaderBlock (awp);
 
1905
    if (awp->showRefs) {
 
1906
      AddReferenceBlock (awp, isRefSeq);
 
1907
    }
 
1908
    AddSourceFeatBlock (awp);
 
1909
    AddFeatureBlock (awp);
 
1910
 
 
1911
  } else {
 
1912
 
 
1913
    AddLocusBlock (awp);
 
1914
 
 
1915
    if (awp->format == GENBANK_FMT || awp->format == GENPEPT_FMT) {
 
1916
 
 
1917
      AddDeflineBlock (awp);
 
1918
      AddAccessionBlock (awp);
 
1919
 
 
1920
      if (ISA_aa (bsp->mol)) {
 
1921
        /*
 
1922
        AddPidBlock (awp);
 
1923
        */
 
1924
      }
 
1925
 
 
1926
      AddVersionBlock (awp);
 
1927
 
 
1928
      if (ISA_aa (bsp->mol)) {
 
1929
        AddDbsourceBlock (awp);
 
1930
      }
 
1931
 
 
1932
    } else if (awp->format == EMBL_FMT || awp->format == EMBLPEPT_FMT) {
 
1933
 
 
1934
      AddAccessionBlock (awp);
 
1935
 
 
1936
      if (ISA_na (bsp->mol)) {
 
1937
        AddVersionBlock (awp);
 
1938
      }
 
1939
 
 
1940
      if (ISA_aa (bsp->mol)) {
 
1941
        /* AddPidBlock (awp); */
 
1942
        /* AddDbsourceBlock (awp); */
 
1943
      }
 
1944
 
 
1945
      AddDateBlock (awp);
 
1946
 
 
1947
      AddDeflineBlock (awp);
 
1948
    }
 
1949
 
 
1950
    AddKeywordsBlock (awp);
 
1951
 
 
1952
    if (awp->format == GENBANK_FMT || awp->format == GENPEPT_FMT) {
 
1953
      AddSegmentBlock (awp, onePartOfSeg);
 
1954
    }
 
1955
 
 
1956
    AddSourceBlock (awp);
 
1957
    AddOrganismBlock (awp);
 
1958
 
 
1959
    /* !!! RELEASE_MODE should check return value of AddReferenceBlock !!! */
 
1960
 
 
1961
    hasRefs = AddReferenceBlock (awp, isRefSeq);
 
1962
    if (! hasRefs) {
 
1963
      if (ajp->flags.needAtLeastOneRef) {
 
1964
        /* RefSeq does not require a publication */
 
1965
        if (! isRefSeq) {
 
1966
          awp->failed = TRUE;
 
1967
        }
 
1968
      }
 
1969
    }
 
1970
    AddCommentBlock (awp);
 
1971
    AddPrimaryBlock (awp);
 
1972
 
 
1973
    AddFeatHeaderBlock (awp);
 
1974
    AddSourceFeatBlock (awp);
 
1975
 
 
1976
    if (wgsmaster && wgstech) {
 
1977
 
 
1978
      AddWGSBlock (awp);
 
1979
 
 
1980
    } else if (nsgenome) {
 
1981
 
 
1982
      AddGenomeBlock (awp);
 
1983
 
 
1984
    } else if (contig) {
 
1985
 
 
1986
      if (awp->showconfeats) {
 
1987
        AddFeatureBlock (awp);
 
1988
      } else if (awp->smartconfeats && bsp->length <= 1000000) {
 
1989
        AddFeatureBlock (awp);
 
1990
      }
 
1991
      AddContigBlock (awp);
 
1992
 
 
1993
      if (awp->showContigAndSeq) {
 
1994
        if (ISA_na (bsp->mol) && ajp->gbseq == NULL) {
 
1995
          if (awp->showBaseCount) {
 
1996
            AddBasecountBlock (awp);
 
1997
          }
 
1998
        }
 
1999
        AddOriginBlock (awp);
 
2000
 
 
2001
        AddSequenceBlock (awp);
 
2002
      }
 
2003
 
 
2004
    } else {
 
2005
 
 
2006
      AddFeatureBlock (awp);
 
2007
 
 
2008
      if (awp->showContigAndSeq) {
 
2009
        if (bsp->repr == Seq_repr_seg && (! SegHasParts (bsp))) {
 
2010
          AddContigBlock (awp);
 
2011
        } else if (bsp->repr == Seq_repr_delta && (! DeltaLitOnly (bsp))) {
 
2012
          AddContigBlock (awp);
 
2013
        }
 
2014
      }
 
2015
 
 
2016
      if (ISA_na (bsp->mol) && ajp->gbseq == NULL) {
 
2017
        if (awp->showBaseCount) {
 
2018
          AddBasecountBlock (awp );
 
2019
        }
 
2020
      }
 
2021
      AddOriginBlock (awp);
 
2022
 
 
2023
      AddSequenceBlock (awp);
 
2024
    }
 
2025
 
 
2026
    AddSlashBlock (awp);
 
2027
  }
 
2028
 
 
2029
  /* allocate block array for this section */
 
2030
 
 
2031
  numBlocks = ValNodeLen (awp->blockList);
 
2032
  asp->numBlocks = numBlocks;
 
2033
 
 
2034
  if (numBlocks > 0) {
 
2035
    blockArray = (BaseBlockPtr PNTR) MemNew (sizeof (BaseBlockPtr) * (numBlocks + 1));
 
2036
    asp->blockArray = blockArray;
 
2037
 
 
2038
    if (blockArray != NULL) {
 
2039
      for (vnp = awp->blockList, i = 0; vnp != NULL; vnp = vnp->next, i++) {
 
2040
        blockArray [i] = (BaseBlockPtr) vnp->data.ptrvalue;
 
2041
      }
 
2042
    }
 
2043
  }
 
2044
 
 
2045
  /* free blockList, but leave data, now pointed to by blockArray elements */
 
2046
 
 
2047
  awp->blockList = ValNodeFree (awp->blockList);
 
2048
  awp->lastblock = NULL;
 
2049
 
 
2050
  (awp->currsection)++;
 
2051
}
 
2052
 
 
2053
/* ********************************************************************** */
 
2054
 
 
2055
/*
 
2056
the following functions handle various kinds of input, all calling
 
2057
DoOneSection once for each component that gets its own report
 
2058
*/
 
2059
 
 
2060
static Boolean LIBCALLBACK Asn2Seg (
 
2061
  SeqLocPtr slp,
 
2062
  SeqMgrSegmentContextPtr context
 
2063
)
 
2064
 
 
2065
{
 
2066
  Asn2gbWorkPtr  awp;
 
2067
  BioseqPtr      bsp = NULL;
 
2068
  Uint2          entityID;
 
2069
  Int4           from;
 
2070
  SeqLocPtr      loc;
 
2071
  BioseqPtr      parent;
 
2072
  SeqIdPtr       sip;
 
2073
  Int4           to;
 
2074
 
 
2075
  if (slp == NULL || context == NULL) return FALSE;
 
2076
  awp = (Asn2gbWorkPtr) context->userdata;
 
2077
 
 
2078
  parent = context->parent;
 
2079
 
 
2080
  from = context->cumOffset;
 
2081
  to = from + context->to - context->from;
 
2082
 
 
2083
  sip = SeqLocId (slp);
 
2084
  if (sip == NULL) {
 
2085
    loc = SeqLocFindNext (slp, NULL);
 
2086
    if (loc != NULL) {
 
2087
      sip = SeqLocId (loc);
 
2088
    }
 
2089
  }
 
2090
  if (sip == NULL) return TRUE;
 
2091
 
 
2092
  /* may remote fetch genome component if not already in memory */
 
2093
 
 
2094
  bsp = BioseqLockById (sip);
 
2095
 
 
2096
  if (bsp == NULL) return TRUE;
 
2097
 
 
2098
  entityID = ObjMgrGetEntityIDForPointer (bsp);
 
2099
 
 
2100
  if (entityID != awp->entityID) {
 
2101
 
 
2102
    /* if segment not packaged in record, may need to feature index it */
 
2103
 
 
2104
    if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
 
2105
      SeqMgrIndexFeatures (entityID, NULL);
 
2106
    }
 
2107
 
 
2108
    /* collect features indexed on the remote bioseq */
 
2109
 
 
2110
    parent = bsp;
 
2111
    from = 0;
 
2112
    to = bsp->length - 1;
 
2113
  }
 
2114
 
 
2115
  if (bsp->repr != Seq_repr_virtual) {
 
2116
    (awp->seg)++;
 
2117
    DoOneSection (bsp, parent, bsp, bsp, /* slp */ NULL, awp->seg, from, to, FALSE, FALSE, awp);
 
2118
  }
 
2119
 
 
2120
  BioseqUnlock (bsp);
 
2121
 
 
2122
  return TRUE;
 
2123
}
 
2124
 
 
2125
static Int4 CountRealParts (
 
2126
  SeqLocPtr slp_head
 
2127
)
 
2128
 
 
2129
{
 
2130
  SeqIdPtr   id;
 
2131
  Int4       numparts;
 
2132
  BioseqPtr  part;
 
2133
  SeqIdPtr   sip;
 
2134
  SeqLocPtr  slp;
 
2135
 
 
2136
  numparts = 0;
 
2137
  for (slp = (SeqLocPtr) slp_head; slp != NULL; slp = slp->next) {
 
2138
    sip = SeqLocId (slp);
 
2139
    if (sip == NULL) continue;
 
2140
    if (sip->choice == SEQID_GI) {
 
2141
      part = BioseqFind (sip);
 
2142
      if (part == NULL) continue;
 
2143
      for (id = part->id; id != NULL; id = id->next) {
 
2144
        if (id->choice == SEQID_GIBBSQ ||
 
2145
            id->choice == SEQID_GIBBMT ||
 
2146
            id->choice == SEQID_GIIM) break;
 
2147
      }
 
2148
      if (id != NULL && part->repr == Seq_repr_virtual) continue;
 
2149
    }
 
2150
    numparts++;
 
2151
  }
 
2152
  return numparts;
 
2153
}
 
2154
 
 
2155
typedef struct findseg {
 
2156
  BioseqPtr  bsp;
 
2157
  Uint2      seg;
 
2158
} FindSeg, PNTR FindSegPtr;
 
2159
 
 
2160
static Boolean LIBCALLBACK FindSegForPart (
 
2161
  SeqLocPtr slp,
 
2162
  SeqMgrSegmentContextPtr context
 
2163
)
 
2164
 
 
2165
{
 
2166
  FindSegPtr  fsp;
 
2167
  BioseqPtr   bsp = NULL;
 
2168
  SeqLocPtr   loc;
 
2169
  SeqIdPtr    sip;
 
2170
 
 
2171
  if (slp == NULL || context == NULL) return TRUE;
 
2172
  fsp = (FindSegPtr) context->userdata;
 
2173
 
 
2174
  sip = SeqLocId (slp);
 
2175
  if (sip == NULL) {
 
2176
    loc = SeqLocFindNext (slp, NULL);
 
2177
    if (loc != NULL) {
 
2178
      sip = SeqLocId (loc);
 
2179
    }
 
2180
  }
 
2181
  if (sip == NULL) return TRUE;
 
2182
 
 
2183
  bsp = BioseqFind (sip);
 
2184
  if (bsp == NULL) return TRUE;
 
2185
 
 
2186
  if (bsp->repr != Seq_repr_virtual) {
 
2187
    (fsp->seg)++;
 
2188
  }
 
2189
 
 
2190
  if (bsp != fsp->bsp) return TRUE;
 
2191
 
 
2192
  return FALSE;
 
2193
}
 
2194
 
 
2195
NLM_EXTERN void DoOneBioseq (
 
2196
  BioseqPtr bsp,
 
2197
  Pointer userdata
 
2198
)
 
2199
 
 
2200
{
 
2201
  IntAsn2gbJobPtr       ajp;
 
2202
  Asn2gbWorkPtr         awp;
 
2203
  BioseqSetPtr          bssp;
 
2204
  SeqMgrSegmentContext  context;
 
2205
  Boolean               contig = FALSE;
 
2206
  Int4                  from;
 
2207
  FindSeg               fs;
 
2208
  SeqEntryPtr           oldscope;
 
2209
  BioseqPtr             parent;
 
2210
  Boolean               segmented = FALSE;
 
2211
  SeqEntryPtr           sep;
 
2212
  Int4                  to;
 
2213
 
 
2214
  if (bsp == NULL) return;
 
2215
  awp = (Asn2gbWorkPtr) userdata;
 
2216
  if (awp == NULL) return;
 
2217
  ajp = awp->ajp;
 
2218
  if (ajp == NULL) return;
 
2219
 
 
2220
  /* return if molecule not right for format */
 
2221
 
 
2222
  if (ISA_na (bsp->mol)) {
 
2223
    if (ajp->format == GENPEPT_FMT || ajp->format == EMBLPEPT_FMT) return;
 
2224
 
 
2225
    /* only do mRNA feature tables in GPS if targeted to a specific mRNA */
 
2226
 
 
2227
    if (ajp->format == FTABLE_FMT && ajp->skipMrnas) {
 
2228
      if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
 
2229
        bssp = (BioseqSetPtr) bsp->idx.parentptr;
 
2230
        if (bssp != NULL && bssp->_class == BioseqseqSet_class_nuc_prot) {
 
2231
          if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
 
2232
            bssp = (BioseqSetPtr) bsp->idx.parentptr;
 
2233
            if (bssp != NULL && bssp->_class == BioseqseqSet_class_gen_prod_set) {
 
2234
              return;
 
2235
            }
 
2236
          }
 
2237
        }
 
2238
      }
 
2239
    }
 
2240
 
 
2241
  } else if (ISA_aa (bsp->mol)) {
 
2242
    if (ajp->format == GENBANK_FMT || ajp->format == EMBL_FMT) return;
 
2243
 
 
2244
    /* only do protein feature tables if targeted to a specific protein */
 
2245
 
 
2246
    if (ajp->format == FTABLE_FMT && ajp->skipProts) return;
 
2247
  }
 
2248
 
 
2249
  if (awp->style == SEGMENT_STYLE) {
 
2250
    segmented = TRUE;
 
2251
  }
 
2252
  if (awp->style == CONTIG_STYLE) {
 
2253
    contig = TRUE;
 
2254
  }
 
2255
  // Never do segmented style in FTABLE format
 
2256
  if (awp->format == FTABLE_FMT) {
 
2257
      segmented = FALSE;
 
2258
      contig = FALSE;
 
2259
  }
 
2260
 
 
2261
  awp->partcount = 0;
 
2262
 
 
2263
  if (bsp->repr == Seq_repr_seg && awp->style == NORMAL_STYLE) {
 
2264
 
 
2265
    /* if bsp followed by parts set, then do not default to contig style */
 
2266
 
 
2267
    if (SegHasParts (bsp)) {
 
2268
      segmented = TRUE;
 
2269
      contig = FALSE;
 
2270
 
 
2271
      if (bsp->seq_ext_type == 1) {
 
2272
 
 
2273
        /* count only non-virtual parts */
 
2274
 
 
2275
        sep = GetTopSeqEntryForEntityID (awp->entityID);
 
2276
        oldscope = SeqEntrySetScope (sep);
 
2277
        awp->partcount = CountRealParts ((SeqLocPtr) bsp->seq_ext);
 
2278
        SeqEntrySetScope (oldscope);
 
2279
      }
 
2280
    } else {
 
2281
      segmented = FALSE;
 
2282
      contig = TRUE;
 
2283
    }
 
2284
  }
 
2285
  if (bsp->repr == Seq_repr_delta && awp->style == NORMAL_STYLE) {
 
2286
    if (! DeltaLitOnly (bsp)) {
 
2287
      contig = TRUE;
 
2288
    }
 
2289
  }
 
2290
 
 
2291
  if (bsp->repr == Seq_repr_seg) {
 
2292
 
 
2293
    /* this is a segmented bioseq */
 
2294
 
 
2295
    if (segmented) {
 
2296
 
 
2297
      /* show all segments individually */
 
2298
 
 
2299
      awp->seg = 0;
 
2300
      SeqMgrExploreSegments (bsp, (Pointer) awp, Asn2Seg);
 
2301
 
 
2302
    } else {
 
2303
 
 
2304
      /* show as single bioseq */
 
2305
 
 
2306
      parent = bsp;
 
2307
      from = 0;
 
2308
      to = bsp->length - 1;
 
2309
 
 
2310
      DoOneSection (parent, parent, bsp, parent, ajp->ajp.slp, 0, from, to, contig, FALSE, awp);
 
2311
    }
 
2312
 
 
2313
  } else if (bsp->repr == Seq_repr_raw ||
 
2314
             bsp->repr == Seq_repr_const ||
 
2315
             bsp->repr == Seq_repr_delta ||
 
2316
             bsp->repr == Seq_repr_virtual) {
 
2317
 
 
2318
    parent = SeqMgrGetParentOfPart (bsp, &context);
 
2319
    if (parent != NULL) {
 
2320
 
 
2321
      /* this is a part of an indexed segmented bioseq */
 
2322
 
 
2323
      from = context.cumOffset;
 
2324
      to = from + context.to - context.from;
 
2325
 
 
2326
      s_LocusGetBaseName (parent, bsp, awp->basename);
 
2327
 
 
2328
      fs.bsp = bsp;
 
2329
      fs.seg = 0;
 
2330
      SeqMgrExploreSegments (parent, (Pointer) &fs, FindSegForPart);
 
2331
      awp->showAllFeats = TRUE;
 
2332
 
 
2333
      DoOneSection (bsp, parent, bsp, parent, ajp->ajp.slp, fs.seg, from, to, contig, TRUE, awp);
 
2334
 
 
2335
    } else {
 
2336
 
 
2337
      /* this is a regular non-segmented bioseq */
 
2338
 
 
2339
      parent = bsp;
 
2340
      from = 0;
 
2341
      to = bsp->length - 1;
 
2342
 
 
2343
      DoOneSection (bsp, parent, bsp, parent, ajp->ajp.slp, 0, from, to, contig, FALSE, awp);
 
2344
    }
 
2345
  }
 
2346
}
 
2347
 
 
2348
static void DoBioseqSetList (
 
2349
  SeqEntryPtr seq_set,
 
2350
  Asn2gbWorkPtr awp
 
2351
)
 
2352
 
 
2353
{
 
2354
  BioseqSetPtr  bssp;
 
2355
  SeqEntryPtr   sep;
 
2356
 
 
2357
  if (seq_set == NULL || awp == NULL) return;
 
2358
 
 
2359
  /* iterate rather than recurse unless multiple nested sets > nuc-prot */
 
2360
 
 
2361
  for (sep = seq_set; sep != NULL; sep = sep->next) {
 
2362
 
 
2363
    if (IS_Bioseq_set (sep)) {
 
2364
      bssp = (BioseqSetPtr) sep->data.ptrvalue;
 
2365
      if (bssp == NULL) continue;
 
2366
 
 
2367
      if (bssp->_class == BioseqseqSet_class_genbank ||
 
2368
          bssp->_class == BioseqseqSet_class_mut_set ||
 
2369
          bssp->_class == BioseqseqSet_class_pop_set ||
 
2370
          bssp->_class == BioseqseqSet_class_phy_set ||
 
2371
          bssp->_class == BioseqseqSet_class_eco_set ||
 
2372
          bssp->_class == BioseqseqSet_class_wgs_set ||
 
2373
          bssp->_class == BioseqseqSet_class_gen_prod_set) {
 
2374
 
 
2375
        /* if popset within genbank set, for example, recurse */
 
2376
 
 
2377
        DoBioseqSetList (bssp->seq_set, awp);
 
2378
 
 
2379
        continue;
 
2380
      }
 
2381
    }
 
2382
 
 
2383
    /* at most nuc-prot set, so do main bioseqs that fit the format */
 
2384
 
 
2385
    VisitSequencesInSep (sep, (Pointer) awp, VISIT_MAINS, DoOneBioseq);
 
2386
  }
 
2387
}
 
2388
 
 
2389
static void DoOneBioseqSet (
 
2390
  SeqEntryPtr sep,
 
2391
  Asn2gbWorkPtr awp
 
2392
)
 
2393
 
 
2394
{
 
2395
  BioseqSetPtr  bssp;
 
2396
 
 
2397
  if (sep == NULL || awp == NULL) return;
 
2398
 
 
2399
  if (IS_Bioseq_set (sep)) {
 
2400
    bssp = (BioseqSetPtr) sep->data.ptrvalue;
 
2401
    if (bssp == NULL) return;
 
2402
 
 
2403
    if (bssp->_class == BioseqseqSet_class_genbank ||
 
2404
        bssp->_class == BioseqseqSet_class_mut_set ||
 
2405
        bssp->_class == BioseqseqSet_class_pop_set ||
 
2406
        bssp->_class == BioseqseqSet_class_phy_set ||
 
2407
        bssp->_class == BioseqseqSet_class_eco_set ||
 
2408
        bssp->_class == BioseqseqSet_class_wgs_set ||
 
2409
        bssp->_class == BioseqseqSet_class_gen_prod_set) {
 
2410
 
 
2411
      /* this is a pop/phy/mut/eco set, catenate separate reports */
 
2412
 
 
2413
      DoBioseqSetList (bssp->seq_set, awp);
 
2414
 
 
2415
      return;
 
2416
    }
 
2417
  }
 
2418
 
 
2419
  /* at most nuc-prot set, so do main bioseqs that fit the format */
 
2420
 
 
2421
  VisitSequencesInSep (sep, (Pointer) awp, VISIT_MAINS, DoOneBioseq);
 
2422
}
 
2423
 
 
2424
 
 
2425
 
 
2426
 
 
2427
/* ********************************************************************** */
 
2428
 
 
2429
/* public functions */
 
2430
 
 
2431
static int LIBCALLBACK SortParagraphByIDProc (
 
2432
  VoidPtr vp1,
 
2433
  VoidPtr vp2
 
2434
)
 
2435
 
 
2436
{
 
2437
  BaseBlockPtr  bbp1, bbp2;
 
2438
 
 
2439
  if (vp1 == NULL || vp2 == NULL) return 0;
 
2440
  bbp1 = *((BaseBlockPtr PNTR) vp1);
 
2441
  bbp2 = *((BaseBlockPtr PNTR) vp2);
 
2442
  if (bbp1 == NULL || bbp2 == NULL) return 0;
 
2443
 
 
2444
  if (bbp1->entityID > bbp2->entityID) return 1;
 
2445
  if (bbp1->entityID < bbp2->entityID) return -1;
 
2446
 
 
2447
  if (bbp1->itemtype > bbp2->itemtype) return 1;
 
2448
  if (bbp1->itemtype < bbp2->itemtype) return -1;
 
2449
 
 
2450
  if (bbp1->itemID > bbp2->itemID) return 1;
 
2451
  if (bbp1->itemID < bbp2->itemID) return -1;
 
2452
 
 
2453
  if (bbp1->paragraph > bbp2->paragraph) return 1;
 
2454
  if (bbp1->paragraph < bbp2->paragraph) return -1;
 
2455
 
 
2456
  return 0;
 
2457
}
 
2458
 
 
2459
static void IsBspRefseq (
 
2460
  BioseqPtr bsp,
 
2461
  Pointer userdata
 
2462
)
 
2463
 
 
2464
{
 
2465
  BoolPtr   has_refseqP;
 
2466
  SeqIdPtr  sip;
 
2467
 
 
2468
  if (bsp == NULL || userdata == NULL) return;
 
2469
  has_refseqP = (BoolPtr) userdata;
 
2470
  for (sip = bsp->id; sip != NULL; sip = sip->next) {
 
2471
    if (sip->choice == SEQID_OTHER) {
 
2472
      *has_refseqP = TRUE;
 
2473
    }
 
2474
  }
 
2475
}
 
2476
 
 
2477
static Boolean IsSepRefseq (
 
2478
  SeqEntryPtr sep
 
2479
)
 
2480
 
 
2481
{
 
2482
  Boolean  is_refseq = FALSE;
 
2483
 
 
2484
  if (sep == NULL) return FALSE;
 
2485
  VisitBioseqsInSep (sep, (Pointer) &is_refseq, IsBspRefseq);
 
2486
  return is_refseq;
 
2487
}
 
2488
 
 
2489
typedef struct modeflags {
 
2490
  Boolean  flags [26];
 
2491
} ModeFlags, PNTR ModeFlagsPtr;
 
2492
 
 
2493
static ModeFlags flagTable [] = {
 
2494
 
 
2495
  /* RELEASE_MODE */
 
2496
  {TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
 
2497
   TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
 
2498
   TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
 
2499
   TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
 
2500
   TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
 
2501
   TRUE},
 
2502
 
 
2503
  /* ENTREZ_MODE */
 
2504
  {FALSE, TRUE,  TRUE,  TRUE,  TRUE,
 
2505
   FALSE, TRUE,  TRUE,  TRUE,  TRUE,
 
2506
   TRUE,  TRUE,  FALSE, TRUE,  TRUE,
 
2507
   TRUE,  TRUE,  FALSE, FALSE, TRUE,
 
2508
   TRUE,  TRUE,  TRUE,  TRUE,  TRUE,
 
2509
   FALSE},
 
2510
 
 
2511
  /* SEQUIN_MODE */
 
2512
  {FALSE, FALSE, FALSE, FALSE, FALSE,
 
2513
   FALSE, FALSE, TRUE,  FALSE, FALSE,
 
2514
   FALSE, FALSE, FALSE, FALSE, FALSE,
 
2515
   FALSE, FALSE, FALSE, FALSE, FALSE,
 
2516
   FALSE, FALSE, FALSE, FALSE, TRUE,
 
2517
   FALSE},
 
2518
 
 
2519
  /* DUMP_MODE */
 
2520
  {FALSE, FALSE, FALSE, FALSE, FALSE,
 
2521
   FALSE, FALSE, FALSE, FALSE, FALSE,
 
2522
   FALSE, FALSE, FALSE, FALSE, FALSE,
 
2523
   FALSE, FALSE, FALSE, FALSE, FALSE,
 
2524
   FALSE, FALSE, FALSE, FALSE, FALSE,
 
2525
   FALSE}
 
2526
};
 
2527
 
 
2528
static void SetFlagsFromMode (
 
2529
  IntAsn2gbJobPtr ajp,
 
2530
  ModType mode
 
2531
)
 
2532
 
 
2533
{
 
2534
  BoolPtr       bp;
 
2535
  ModeFlagsPtr  mfp;
 
2536
  SeqEntryPtr   sep;
 
2537
 
 
2538
  if (ajp == NULL) return;
 
2539
  if (! (mode >= RELEASE_MODE && mode <= DUMP_MODE)) {
 
2540
    mode = DUMP_MODE;
 
2541
  }
 
2542
  mfp = &(flagTable [(int) (mode - 1)]);
 
2543
  bp = &(mfp->flags [0]);
 
2544
 
 
2545
  ajp->flags.suppressLocalID = *(bp++);
 
2546
  ajp->flags.validateFeats = *(bp++);
 
2547
  ajp->flags.ignorePatPubs = *(bp++);
 
2548
  ajp->flags.dropShortAA = *(bp++);
 
2549
  ajp->flags.avoidLocusColl = *(bp++);
 
2550
 
 
2551
  ajp->flags.iupacaaOnly = *(bp++);
 
2552
  ajp->flags.dropBadCitGens = *(bp++);
 
2553
  ajp->flags.noAffilOnUnpub = *(bp++);
 
2554
  ajp->flags.dropIllegalQuals = *(bp++);
 
2555
  ajp->flags.checkQualSyntax = *(bp++);
 
2556
 
 
2557
  ajp->flags.needRequiredQuals = *(bp++);
 
2558
  ajp->flags.needOrganismQual = *(bp++);
 
2559
  ajp->flags.needAtLeastOneRef = *(bp++);
 
2560
  ajp->flags.citArtIsoJta = *(bp++);
 
2561
  ajp->flags.dropBadDbxref = *(bp++);
 
2562
 
 
2563
  ajp->flags.useEmblMolType = *(bp++);
 
2564
  ajp->flags.hideBankItComment = *(bp++);
 
2565
  ajp->flags.checkCDSproductID = *(bp++);
 
2566
  ajp->flags.suppressSegLoc = *(bp++);
 
2567
  ajp->flags.srcQualsToNote = *(bp)++;
 
2568
 
 
2569
  ajp->flags.hideEmptySource = *(bp++);
 
2570
  ajp->flags.goQualsToNote = *(bp++);
 
2571
  ajp->flags.geneSynsToNote = *(bp++);
 
2572
  ajp->flags.selenocysteineToNote = *(bp++);
 
2573
  ajp->flags.extraProductsToNote = *(bp++);
 
2574
 
 
2575
  ajp->flags.forGbRelease = *(bp++);
 
2576
 
 
2577
  /* unapproved qualifiers suppressed for flatfile, okay for GBSeq XML */
 
2578
 
 
2579
  if (ajp->gbseq == NULL) {
 
2580
 
 
2581
    /* collaboration unapproved source quals on their own line only in indexer Sequin - relaxed */
 
2582
 
 
2583
    /*
 
2584
    if (GetAppProperty ("InternalNcbiSequin") == NULL) {
 
2585
 
 
2586
      ajp->flags.srcQualsToNote = TRUE;
 
2587
    }
 
2588
    */
 
2589
 
 
2590
    sep = GetTopSeqEntryForEntityID (ajp->ajp.entityID);
 
2591
    if (IsSepRefseq (sep)) {
 
2592
 
 
2593
      ajp->flags.srcQualsToNote = FALSE;
 
2594
 
 
2595
      /* selenocysteine always a separate qualifier for RefSeq */
 
2596
 
 
2597
      ajp->flags.selenocysteineToNote = FALSE;
 
2598
 
 
2599
    } else {
 
2600
 
 
2601
      /* collaboration unapproved Gene Ontology quals on their own line only for RefSeq */
 
2602
 
 
2603
      /* ajp->flags.goQualsToNote = TRUE; */
 
2604
      ajp->flags.geneSynsToNote = TRUE;
 
2605
    }
 
2606
 
 
2607
  } else {
 
2608
 
 
2609
    sep = GetTopSeqEntryForEntityID (ajp->ajp.entityID);
 
2610
    if (IsSepRefseq (sep)) {
 
2611
 
 
2612
      ajp->flags.srcQualsToNote = FALSE;
 
2613
 
 
2614
      /* selenocysteine always a separate qualifier for RefSeq */
 
2615
 
 
2616
      ajp->flags.selenocysteineToNote = FALSE;
 
2617
 
 
2618
    }
 
2619
  }
 
2620
}
 
2621
 
 
2622
static void CheckVersionWithGi (BioseqPtr bsp, Pointer userdata)
 
2623
 
 
2624
{
 
2625
  Boolean       hasGi = FALSE;
 
2626
  BoolPtr       missingVersion;
 
2627
  SeqIdPtr      sip;
 
2628
  TextSeqIdPtr  tsip;
 
2629
  Boolean       zeroVersion = FALSE;
 
2630
 
 
2631
  for (sip = bsp->id; sip != NULL; sip = sip->next) {
 
2632
    switch (sip->choice) {
 
2633
      case SEQID_TPG:
 
2634
      case SEQID_TPE:
 
2635
      case SEQID_TPD:
 
2636
      case SEQID_GENBANK:
 
2637
      case SEQID_EMBL:
 
2638
      case SEQID_DDBJ:
 
2639
        tsip = (TextSeqIdPtr) sip->data.ptrvalue;
 
2640
        if (tsip != NULL && tsip->version == 0) {
 
2641
          zeroVersion = TRUE;
 
2642
        }
 
2643
        break;
 
2644
      case SEQID_GI :
 
2645
        hasGi = TRUE;
 
2646
        break;
 
2647
      default :
 
2648
        break;
 
2649
    }
 
2650
  }
 
2651
  if (hasGi && zeroVersion) {
 
2652
    missingVersion = (BoolPtr) userdata;
 
2653
    *missingVersion = TRUE;
 
2654
  }
 
2655
}
 
2656
 
 
2657
 
 
2658
typedef struct lookforids {
 
2659
  Boolean isGED;
 
2660
  Boolean isNTorNW;
 
2661
  Boolean isNC;
 
2662
  Boolean isTPA;
 
2663
  Boolean isNuc;
 
2664
  Boolean isProt;
 
2665
} LookForIDs, PNTR LookForIDsPtr;
 
2666
 
 
2667
static void LookForSeqIDs (BioseqPtr bsp, Pointer userdata)
 
2668
 
 
2669
{
 
2670
  LookForIDsPtr  lfip;
 
2671
  SeqIdPtr       sip;
 
2672
  TextSeqIdPtr   tsip;
 
2673
 
 
2674
  lfip = (LookForIDsPtr) userdata;
 
2675
  if (ISA_na (bsp->mol)) {
 
2676
    lfip->isNuc = TRUE;
 
2677
  }
 
2678
  if (ISA_aa (bsp->mol)) {
 
2679
    lfip->isProt = TRUE;
 
2680
  }
 
2681
  for (sip = bsp->id; sip != NULL; sip = sip->next) {
 
2682
    switch (sip->choice) {
 
2683
      case SEQID_GENBANK :
 
2684
      case SEQID_EMBL :
 
2685
      case SEQID_DDBJ :
 
2686
        lfip->isGED = TRUE;
 
2687
        break;
 
2688
      case SEQID_TPG :
 
2689
      case SEQID_TPE :
 
2690
      case SEQID_TPD :
 
2691
        lfip->isTPA = TRUE;
 
2692
        break;
 
2693
      case SEQID_OTHER :
 
2694
        tsip = (TextSeqIdPtr) sip->data.ptrvalue;
 
2695
        if (tsip != NULL) {
 
2696
          if (StringNCmp (tsip->accession, "NC_", 3) == 0) {
 
2697
            lfip->isNC = TRUE;
 
2698
          } else if (StringNCmp (tsip->accession, "NT_", 3) == 0) {
 
2699
            lfip->isNTorNW = TRUE;
 
2700
          } else if (StringNCmp (tsip->accession, "NW_", 3) == 0) {
 
2701
            lfip->isNTorNW = TRUE;
 
2702
          }
 
2703
        }
 
2704
        break;
 
2705
      default :
 
2706
        break;
 
2707
    }
 
2708
  }
 
2709
}
 
2710
 
 
2711
static void LookForGEDetc (
 
2712
  SeqEntryPtr topsep,
 
2713
  BoolPtr isGED,
 
2714
  BoolPtr isNTorNW,
 
2715
  BoolPtr isNC,
 
2716
  BoolPtr isTPA,
 
2717
  BoolPtr isNuc,
 
2718
  BoolPtr isProt
 
2719
)
 
2720
 
 
2721
{
 
2722
  LookForIDs  lfi;
 
2723
 
 
2724
  MemSet ((Pointer) &lfi, 0, sizeof (LookForIDs));
 
2725
  VisitBioseqsInSep (topsep, (Pointer) &lfi, LookForSeqIDs);
 
2726
  *isGED = lfi.isGED;
 
2727
  *isNTorNW = lfi.isNTorNW;
 
2728
  *isNC = lfi.isNC;
 
2729
  *isTPA = lfi.isTPA;
 
2730
  *isNuc = lfi.isNuc;
 
2731
  *isProt = lfi.isProt;
 
2732
}
 
2733
 
 
2734
static CharPtr defHead = "\
 
2735
Content-type: text/html\n\n\
 
2736
<HTML>\n\
 
2737
<HEAD><TITLE>GenBank entry</TITLE></HEAD>\n\
 
2738
<BODY>\n\
 
2739
<hr>\n\
 
2740
<pre>";
 
2741
 
 
2742
static CharPtr defTail = "\
 
2743
</pre>\n\
 
2744
<hr>\n\
 
2745
</BODY>\n\
 
2746
</HTML>\n";
 
2747
 
 
2748
#define FEAT_FETCH_MASK (ONLY_NEAR_FEATURES | FAR_FEATURES_SUPPRESS | NEAR_FEATURES_SUPPRESS)
 
2749
#define HTML_XML_ASN_MASK (CREATE_HTML_FLATFILE | CREATE_XML_GBSEQ_FILE | CREATE_ASN_GBSEQ_FILE)
 
2750
#define GENE_RIF_MASK (HIDE_GENE_RIFS | ONLY_GENE_RIFS | LATEST_GENE_RIFS)
 
2751
 
 
2752
static Asn2gbJobPtr asn2gnbk_setup_ex (
 
2753
  BioseqPtr bsp,
 
2754
  BioseqSetPtr bssp,
 
2755
  SeqLocPtr slp,
 
2756
  FmtType format,
 
2757
  ModType mode,
 
2758
  StlType style,
 
2759
  FlgType flags,
 
2760
  LckType locks,
 
2761
  CstType custom,
 
2762
  XtraPtr extra,
 
2763
  Boolean stream,
 
2764
  FILE *fp,
 
2765
  AsnIoPtr aip,
 
2766
  AsnTypePtr atp
 
2767
)
 
2768
 
 
2769
{
 
2770
  Asn2gbFormat     af;
 
2771
  IntAsn2gbJobPtr  ajp = NULL;
 
2772
  Asn2gbSectPtr    asp;
 
2773
  Asn2gbWork       aw;
 
2774
  BaseBlockPtr     bbp;
 
2775
  BaseBlockPtr     PNTR blockArray;
 
2776
  Uint2            entityID = 0;
 
2777
  CharPtr          ffhead = NULL;
 
2778
  CharPtr          fftail = NULL;
 
2779
  Asn2gbWriteFunc  ffwrite = NULL;
 
2780
  GBSeqPtr         gbseq = NULL;
 
2781
  Int4             i;
 
2782
  IndxPtr          index = NULL;
 
2783
  Boolean          isGED;
 
2784
  Boolean          isNTorNW;
 
2785
  Boolean          isNC;
 
2786
  Boolean          isNuc;
 
2787
  Boolean          isProt;
 
2788
  Boolean          isTPA;
 
2789
  Int4             j;
 
2790
  Int4             k;
 
2791
  Boolean          lockFarComp;
 
2792
  Boolean          lockFarLocs;
 
2793
  Boolean          lockFarProd;
 
2794
  Boolean          lookupFarComp;
 
2795
  Boolean          lookupFarHist;
 
2796
  Boolean          lookupFarLocs;
 
2797
  Boolean          lookupFarProd;
 
2798
  Boolean          missingVersion;
 
2799
  Int4             numBlocks;
 
2800
  Int4             numSections;
 
2801
  SeqEntryPtr      oldscope;
 
2802
  ObjMgrDataPtr    omdp;
 
2803
  BaseBlockPtr     PNTR paragraphArray;
 
2804
  BaseBlockPtr     PNTR paragraphByIDs;
 
2805
  Int4             numParagraphs;
 
2806
  Pointer          remotedata = NULL;
 
2807
  Asn2gbFreeFunc   remotefree = NULL;
 
2808
  Asn2gbLockFunc   remotelock = NULL;
 
2809
  Asn2gbSectPtr    PNTR sectionArray;
 
2810
  SubmitBlockPtr   sbp;
 
2811
  SeqEntryPtr      sep;
 
2812
  SeqIntPtr        sintp;
 
2813
  Boolean          skipMrnas = FALSE;
 
2814
  Boolean          skipProts = FALSE;
 
2815
  SeqSubmitPtr     ssp;
 
2816
  BioseqSetPtr     topbssp;
 
2817
  Pointer          userdata = NULL;
 
2818
  ValNodePtr       vnp;
 
2819
  Boolean          is_html = FALSE;
 
2820
 
 
2821
  if (format == 0) {
 
2822
    format = GENBANK_FMT;
 
2823
  }
 
2824
  if (mode == 0) {
 
2825
    mode = SEQUIN_MODE;
 
2826
  }
 
2827
  if (style == 0) {
 
2828
    style = NORMAL_STYLE;
 
2829
  }
 
2830
 
 
2831
  if (extra != NULL) {
 
2832
    ffwrite = extra->ffwrite;
 
2833
    ffhead = extra->ffhead;
 
2834
    fftail = extra->fftail;
 
2835
    index = extra->index;
 
2836
    gbseq = extra->gbseq;
 
2837
    userdata = extra->userdata;
 
2838
    remotelock = extra->remotelock;
 
2839
    remotefree = extra->remotefree;
 
2840
    remotedata = extra->remotedata;
 
2841
  }
 
2842
 
 
2843
  if (slp != NULL) {
 
2844
    bsp = BioseqFind (SeqLocId (slp));
 
2845
    if (bsp == NULL) {
 
2846
      bsp = BioseqFindFromSeqLoc (slp);
 
2847
    }
 
2848
    if (bsp == NULL) return NULL;
 
2849
 
 
2850
    /* if location is whole, generate normal bioseq report */
 
2851
 
 
2852
    if (slp->choice == SEQLOC_WHOLE) {
 
2853
      slp = NULL;
 
2854
    } else if (slp->choice == SEQLOC_INT) {
 
2855
      sintp = (SeqIntPtr) slp->data.ptrvalue;
 
2856
      if (sintp != NULL &&
 
2857
          sintp->from == 0 &&
 
2858
          sintp->to == bsp->length - 1 &&
 
2859
          sintp->strand == Seq_strand_plus) {
 
2860
        slp = NULL;
 
2861
      }
 
2862
    }
 
2863
  }
 
2864
 
 
2865
  if (bsp != NULL) {
 
2866
    bssp = NULL;
 
2867
    entityID = ObjMgrGetEntityIDForPointer (bsp);
 
2868
  } else if (bssp != NULL) {
 
2869
    entityID = ObjMgrGetEntityIDForPointer (bssp);
 
2870
    if (format == FTABLE_FMT) {
 
2871
      skipProts = TRUE;
 
2872
      skipMrnas = TRUE;
 
2873
    }
 
2874
  }
 
2875
  if ((Boolean) ((custom & SHOW_PROT_FTABLE) != 0)) {
 
2876
    skipProts = FALSE;
 
2877
    skipMrnas = FALSE;
 
2878
  }
 
2879
 
 
2880
  if (entityID == 0) return NULL;
 
2881
 
 
2882
  if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
 
2883
    SeqMgrIndexFeatures (entityID, NULL);
 
2884
  }
 
2885
 
 
2886
  if (mode == RELEASE_MODE) {
 
2887
    sep = GetTopSeqEntryForEntityID (entityID);
 
2888
    missingVersion = FALSE;
 
2889
    VisitBioseqsInSep (sep, (Pointer) &missingVersion, CheckVersionWithGi);
 
2890
    if (missingVersion) return NULL;
 
2891
  }
 
2892
 
 
2893
  ajp = (IntAsn2gbJobPtr) MemNew (sizeof (IntAsn2gbJob));
 
2894
  if (ajp == NULL) return NULL;
 
2895
 
 
2896
  is_html = (Boolean) ((flags & HTML_XML_ASN_MASK) == CREATE_HTML_FLATFILE);
 
2897
  if (is_html) {
 
2898
    InitWWW(ajp);
 
2899
  }
 
2900
 
 
2901
  ajp->ajp.entityID = entityID;
 
2902
  ajp->ajp.bsp = bsp;
 
2903
  ajp->ajp.bssp = bssp;
 
2904
  if (slp != NULL) {
 
2905
    ajp->ajp.slp = AsnIoMemCopy ((Pointer) slp,
 
2906
                                 (AsnReadFunc) SeqLocAsnRead,
 
2907
                                 (AsnWriteFunc) SeqLocAsnWrite);
 
2908
  } else {
 
2909
    ajp->ajp.slp = NULL;
 
2910
  }
 
2911
 
 
2912
  /* if location specified, normal defaults to master style */
 
2913
 
 
2914
  if (ajp->ajp.slp != NULL && style == NORMAL_STYLE) {
 
2915
    style = MASTER_STYLE;
 
2916
  }
 
2917
 
 
2918
  ajp->format = format;
 
2919
  ajp->mode = mode; /* for showing new qualifiers before quarantine ends */
 
2920
 
 
2921
  ajp->index = index;
 
2922
  ajp->gbseq = gbseq; /* gbseq output can relax srcQualsToNote or goQualsToNote strictness */
 
2923
  ajp->aip = aip;
 
2924
  ajp->atp = atp;
 
2925
 
 
2926
  SetFlagsFromMode (ajp, mode);
 
2927
 
 
2928
  lockFarComp = (Boolean) ((locks & LOCK_FAR_COMPONENTS) != 0);
 
2929
  lockFarLocs = (Boolean) ((locks & LOCK_FAR_LOCATIONS) != 0);
 
2930
  lockFarProd = (Boolean) ((locks & LOCK_FAR_PRODUCTS) != 0);
 
2931
 
 
2932
  if (lockFarComp || lockFarLocs || lockFarProd) {
 
2933
 
 
2934
    /* lock all bioseqs in advance, including remote genome components */
 
2935
 
 
2936
    sep = GetTopSeqEntryForEntityID (entityID);
 
2937
    if (ajp->ajp.slp != NULL && lockFarComp) {
 
2938
      ajp->lockedBspList = LockFarComponentsEx (sep, FALSE, lockFarLocs, lockFarProd, ajp->ajp.slp);
 
2939
    } else {
 
2940
      ajp->lockedBspList = LockFarComponentsEx (sep, lockFarComp, lockFarLocs, lockFarProd, NULL);
 
2941
    }
 
2942
  }
 
2943
 
 
2944
  lookupFarComp = (Boolean) ((locks & LOOKUP_FAR_COMPONENTS) != 0);
 
2945
  lookupFarLocs = (Boolean) ((locks & LOOKUP_FAR_LOCATIONS) != 0);
 
2946
  lookupFarProd = (Boolean) ((locks & LOOKUP_FAR_PRODUCTS) != 0);
 
2947
  lookupFarHist = (Boolean) ((locks & LOOKUP_FAR_HISTORY) != 0);
 
2948
 
 
2949
  if (lookupFarComp || lookupFarLocs || lookupFarProd || lookupFarHist) {
 
2950
 
 
2951
    /* lookukp all far SeqIDs in advance */
 
2952
 
 
2953
    sep = GetTopSeqEntryForEntityID (entityID);
 
2954
    LookupFarSeqIDs (sep, lookupFarComp, lookupFarLocs, lookupFarProd, FALSE, lookupFarHist);
 
2955
  }
 
2956
 
 
2957
  ajp->showFarTransl = (Boolean) ((flags & SHOW_FAR_TRANSLATION) != 0);
 
2958
  ajp->transIfNoProd = (Boolean) ((flags & TRANSLATE_IF_NO_PRODUCT) != 0);
 
2959
  ajp->alwaysTranslCds = (Boolean) ((flags & ALWAYS_TRANSLATE_CDS) != 0);
 
2960
 
 
2961
  ajp->masterStyle = (Boolean) (style == MASTER_STYLE);
 
2962
  if (format == GENBANK_FMT || format == GENPEPT_FMT) {
 
2963
    ajp->newSourceOrg = (Boolean) ((flags & USE_OLD_SOURCE_ORG) == 0);
 
2964
  }
 
2965
  ajp->produceInsdSeq = (Boolean) ((flags & PRODUCE_OLD_GBSEQ) == 0);
 
2966
 
 
2967
  ajp->relModeError = FALSE;
 
2968
  ajp->skipProts = skipProts;
 
2969
  ajp->skipMrnas = skipMrnas;
 
2970
 
 
2971
  MemSet ((Pointer) (&aw), 0, sizeof (Asn2gbWork));
 
2972
  aw.ajp = ajp;
 
2973
  aw.entityID = entityID;
 
2974
 
 
2975
  aw.sectionList = NULL;
 
2976
  aw.lastsection = NULL;
 
2977
 
 
2978
  aw.currsection = 0;
 
2979
  aw.showAllFeats = FALSE;
 
2980
 
 
2981
  aw.showconfeats = (Boolean) ((flags & SHOW_CONTIG_FEATURES) != 0);
 
2982
  aw.showconsource = (Boolean) ((flags & SHOW_CONTIG_SOURCES) != 0);
 
2983
 
 
2984
  aw.format = format;
 
2985
  aw.mode = mode;
 
2986
  aw.style = style;
 
2987
 
 
2988
  /* internal format pointer if writing at time of creation */
 
2989
 
 
2990
  if (stream) {
 
2991
    MemSet ((Pointer) &af, 0, sizeof (Asn2gbFormat));
 
2992
    af.ajp = ajp;
 
2993
    af.asp = NULL;
 
2994
    af.qvp = NULL;
 
2995
    af.format = format;
 
2996
    af.ffwrite = ffwrite;
 
2997
    af.userdata = userdata;
 
2998
    af.remotelock = remotelock;
 
2999
    af.remotefree = remotefree;
 
3000
    af.remotedata = remotedata;
 
3001
    af.fp = fp;
 
3002
    af.aip = aip;
 
3003
    af.atp = atp;
 
3004
 
 
3005
    aw.afp = &af;
 
3006
  }
 
3007
 
 
3008
  sep = GetTopSeqEntryForEntityID (entityID);
 
3009
 
 
3010
  /* special types of records override feature fetching and contig display parameters */
 
3011
 
 
3012
  if (mode == ENTREZ_MODE) {
 
3013
    if (! aw.showconfeats) {
 
3014
      aw.smartconfeats = TRUE;  /* features suppressed if CONTIG style and length > 1 MB */
 
3015
      aw.showconfeats = FALSE;
 
3016
      aw.showconsource = FALSE;
 
3017
    }
 
3018
  }
 
3019
 
 
3020
  aw.onlyNearFeats = FALSE;
 
3021
  aw.farFeatsSuppress = FALSE;
 
3022
  aw.nearFeatsSuppress = FALSE;
 
3023
 
 
3024
  LookForGEDetc (sep, &isGED, &isNTorNW, &isNC, &isTPA, &isNuc, &isProt);
 
3025
 
 
3026
  if (isNC) {
 
3027
 
 
3028
    if ((Boolean) ((flags & FEAT_FETCH_MASK) == ONLY_NEAR_FEATURES)) {
 
3029
      aw.onlyNearFeats = TRUE;
 
3030
    } else {
 
3031
      aw.nearFeatsSuppress = TRUE;
 
3032
    }
 
3033
 
 
3034
  } else if (isNTorNW || isTPA) {
 
3035
 
 
3036
    aw.onlyNearFeats = TRUE;
 
3037
 
 
3038
  } else if (isGED) {
 
3039
 
 
3040
    aw.nearFeatsSuppress = TRUE;
 
3041
    ajp->showFarTransl = TRUE;
 
3042
 
 
3043
  } else {
 
3044
 
 
3045
    aw.onlyNearFeats = (Boolean) ((flags & FEAT_FETCH_MASK) == ONLY_NEAR_FEATURES);
 
3046
    aw.farFeatsSuppress = (Boolean) ((flags & FEAT_FETCH_MASK) == FAR_FEATURES_SUPPRESS);
 
3047
    aw.nearFeatsSuppress = (Boolean) ((flags & FEAT_FETCH_MASK) == NEAR_FEATURES_SUPPRESS);
 
3048
  }
 
3049
 
 
3050
  /* continue setting flags */
 
3051
 
 
3052
  aw.hideImpFeats = (Boolean) ((custom & HIDE_IMP_FEATS) != 0);
 
3053
  aw.hideRemImpFeats = (Boolean) ((custom & HIDE_REM_IMP_FEATS) != 0);
 
3054
 
 
3055
  aw.hideSnpFeats = (Boolean) ((custom & HIDE_SNP_FEATS) != 0);
 
3056
  aw.hideExonFeats = (Boolean) ((custom & HIDE_EXON_FEATS) != 0);
 
3057
  aw.hideIntronFeats = (Boolean) ((custom & HIDE_INTRON_FEATS) != 0);
 
3058
  aw.hideMiscFeats = (Boolean) ((custom & HIDE_MISC_FEATS) != 0);
 
3059
 
 
3060
  aw.hideCddFeats = (Boolean) ((custom & HIDE_CDD_FEATS) != 0);
 
3061
  aw.hideCdsProdFeats = (Boolean) ((custom & HIDE_CDS_PROD_FEATS) != 0);
 
3062
 
 
3063
  ajp->showTranscript = (Boolean) ((custom & SHOW_TRANCRIPTION) != 0);
 
3064
  ajp->showPeptide = (Boolean) ((custom & SHOW_PEPTIDE) != 0);
 
3065
 
 
3066
  aw.hideGeneRIFs = (Boolean) ((custom & GENE_RIF_MASK) == HIDE_GENE_RIFS);
 
3067
  aw.onlyGeneRIFs = (Boolean) ((custom & GENE_RIF_MASK) == ONLY_GENE_RIFS);
 
3068
  aw.latestGeneRIFs = (Boolean) ((custom & GENE_RIF_MASK) == LATEST_GENE_RIFS);
 
3069
 
 
3070
  aw.showRefs = (Boolean) ((custom & SHOW_FTABLE_REFS) != 0);
 
3071
 
 
3072
  aw.isGPS = FALSE;
 
3073
  if (sep != NULL && IS_Bioseq_set (sep)) {
 
3074
    topbssp = (BioseqSetPtr) sep->data.ptrvalue;
 
3075
    if (topbssp != NULL && topbssp->_class == BioseqseqSet_class_gen_prod_set) {
 
3076
      aw.isGPS = TRUE;
 
3077
      aw.copyGpsCdsUp = (Boolean) ((flags & COPY_GPS_CDS_UP) != 0);
 
3078
      aw.copyGpsGeneDown = (Boolean) ((flags & COPY_GPS_GENE_DOWN) != 0);
 
3079
    }
 
3080
  }
 
3081
 
 
3082
  aw.showContigAndSeq = (Boolean) ((flags & SHOW_CONTIG_AND_SEQ) != 0);
 
3083
  /*
 
3084
  if (style != MASTER_STYLE && style != SEGMENT_STYLE) {
 
3085
    aw.showContigAndSeq = FALSE;
 
3086
  }
 
3087
  */
 
3088
 
 
3089
  aw.newLocusLine = TRUE;
 
3090
  aw.showBaseCount = FALSE;
 
3091
 
 
3092
  if ((Boolean) ((flags & DDBJ_VARIANT_FORMAT) != 0)) {
 
3093
    aw.citSubsFirst = TRUE;
 
3094
    aw.hideGeneFeats = TRUE;
 
3095
    aw.newLocusLine = FALSE;
 
3096
    aw.showBaseCount = TRUE;
 
3097
    ajp->newSourceOrg = FALSE;
 
3098
  }
 
3099
  if (mode == SEQUIN_MODE || mode == DUMP_MODE) {
 
3100
    aw.showBaseCount = TRUE;
 
3101
  }
 
3102
 
 
3103
  aw.hup = FALSE;
 
3104
  aw.ssp = NULL;
 
3105
 
 
3106
  aw.failed = FALSE;
 
3107
 
 
3108
  omdp = ObjMgrGetData (entityID);
 
3109
  if (omdp != NULL && omdp->datatype == OBJ_SEQSUB) {
 
3110
    ssp = (SeqSubmitPtr) omdp->dataptr;
 
3111
    if (ssp != NULL && ssp->datatype == 1) {
 
3112
      aw.ssp = ssp;
 
3113
      sbp = ssp->sub;
 
3114
      if (sbp != NULL) {
 
3115
        aw.hup = sbp->hup;
 
3116
      }
 
3117
    }
 
3118
  }
 
3119
 
 
3120
  oldscope = SeqEntrySetScope (sep);
 
3121
 
 
3122
  if (stream) {
 
3123
    /* send optional head string */
 
3124
 
 
3125
    is_html = (Boolean) ((flags & HTML_XML_ASN_MASK) == CREATE_HTML_FLATFILE);
 
3126
    if (ffhead == NULL && is_html) {
 
3127
      ffhead = defHead;
 
3128
    }
 
3129
    if (ffhead != NULL) {
 
3130
      if (fp != NULL) {
 
3131
        fprintf (fp, ffhead);
 
3132
      }
 
3133
    }
 
3134
    if (ffwrite != NULL) {
 
3135
      ffwrite (ffhead, userdata, HEAD_BLOCK);
 
3136
    }
 
3137
  }
 
3138
 
 
3139
  if (bssp != NULL) {
 
3140
 
 
3141
    /* handle all components of a pop/phy/mut/eco set */
 
3142
 
 
3143
    sep = SeqMgrGetSeqEntryForData (bssp);
 
3144
    DoOneBioseqSet (sep, &aw);
 
3145
 
 
3146
  } else {
 
3147
 
 
3148
    /* handle single bioseq, which may be segmented or a local part */
 
3149
 
 
3150
    DoOneBioseq (bsp, &aw);
 
3151
  }
 
3152
 
 
3153
  if (stream) {
 
3154
    /* send optional tail string */
 
3155
 
 
3156
    if (fftail == NULL && is_html) {
 
3157
      fftail = defTail;
 
3158
    }
 
3159
    if (fftail != NULL) {
 
3160
      if (fp != NULL) {
 
3161
        fprintf (fp, fftail);
 
3162
      }
 
3163
    }
 
3164
    if (ffwrite != NULL) {
 
3165
      ffwrite (fftail, userdata, TAIL_BLOCK);
 
3166
    }
 
3167
  }
 
3168
 
 
3169
  SeqEntrySetScope (oldscope);
 
3170
 
 
3171
  /* check for failure to populate anything */
 
3172
 
 
3173
  if (ajp->flags.needAtLeastOneRef && aw.failed) return asn2gnbk_cleanup ((Asn2gbJobPtr) ajp);
 
3174
 
 
3175
  numSections = ValNodeLen (aw.sectionList);
 
3176
  ajp->ajp.numSections = numSections;
 
3177
 
 
3178
  if (numSections == 0) return asn2gnbk_cleanup ((Asn2gbJobPtr) ajp);
 
3179
 
 
3180
  /* allocate section array for this job */
 
3181
 
 
3182
  sectionArray = (Asn2gbSectPtr PNTR) MemNew (sizeof (Asn2gbSectPtr) * (numSections + 1));
 
3183
  ajp->ajp.sectionArray = sectionArray;
 
3184
 
 
3185
  if (sectionArray == NULL) return asn2gnbk_cleanup ((Asn2gbJobPtr) ajp);
 
3186
 
 
3187
  /* fill in section and paragraph arrays */
 
3188
 
 
3189
  numParagraphs = 0;
 
3190
  for (vnp = aw.sectionList, i = 0; vnp != NULL && i < numSections; vnp = vnp->next, i++) {
 
3191
    asp = (Asn2gbSectPtr) vnp->data.ptrvalue;
 
3192
    sectionArray [i] = asp;
 
3193
    if (asp != NULL) {
 
3194
      numParagraphs += asp->numBlocks;
 
3195
    }
 
3196
  }
 
3197
 
 
3198
  /* allocate paragraph array pointing to all blocks in all sections */
 
3199
 
 
3200
  ajp->ajp.numParagraphs = numParagraphs;
 
3201
  if (numParagraphs == 0) return asn2gnbk_cleanup ((Asn2gbJobPtr) ajp);
 
3202
 
 
3203
  paragraphArray = (BaseBlockPtr PNTR) MemNew (sizeof (BaseBlockPtr) * (numParagraphs + 1));
 
3204
  ajp->ajp.paragraphArray = paragraphArray;
 
3205
 
 
3206
  paragraphByIDs = (BaseBlockPtr PNTR) MemNew (sizeof (BaseBlockPtr) * (numParagraphs + 1));
 
3207
  ajp->ajp.paragraphByIDs = paragraphByIDs;
 
3208
 
 
3209
  if (paragraphArray == NULL || paragraphByIDs == NULL) return asn2gnbk_cleanup ((Asn2gbJobPtr) ajp);
 
3210
 
 
3211
  k = 0;
 
3212
  for (i = 0; i < numSections; i++) {
 
3213
    asp = sectionArray [i];
 
3214
    if (asp != NULL) {
 
3215
 
 
3216
      numBlocks = asp->numBlocks;
 
3217
      blockArray = asp->blockArray;
 
3218
      if (blockArray != NULL) {
 
3219
 
 
3220
        for (j = 0; j < numBlocks; j++) {
 
3221
          bbp = blockArray [j];
 
3222
 
 
3223
          paragraphArray [k] = bbp;
 
3224
          paragraphByIDs [k] = bbp;
 
3225
          bbp->paragraph = k;
 
3226
          k++;
 
3227
        }
 
3228
      }
 
3229
    }
 
3230
  }
 
3231
 
 
3232
  /* sort paragraphByIDs array by entityID/itemtype/itemID/paragraph */
 
3233
 
 
3234
  HeapSort (paragraphByIDs, (size_t) numParagraphs, sizeof (BaseBlockPtr), SortParagraphByIDProc);
 
3235
 
 
3236
  /* free sectionList, but leave data, now pointed to by sectionArray elements */
 
3237
 
 
3238
  ValNodeFree (aw.sectionList);
 
3239
 
 
3240
  return (Asn2gbJobPtr) ajp;
 
3241
}
 
3242
 
 
3243
NLM_EXTERN Asn2gbJobPtr asn2gnbk_setup (
 
3244
  BioseqPtr bsp,
 
3245
  BioseqSetPtr bssp,
 
3246
  SeqLocPtr slp,
 
3247
  FmtType format,
 
3248
  ModType mode,
 
3249
  StlType style,
 
3250
  FlgType flags,
 
3251
  LckType locks,
 
3252
  CstType custom,
 
3253
  XtraPtr extra
 
3254
)
 
3255
 
 
3256
{
 
3257
  return asn2gnbk_setup_ex (bsp, bssp, slp, format, mode, style,
 
3258
                            flags, locks, custom, extra,
 
3259
                            FALSE, NULL, NULL, NULL);
 
3260
}
 
3261
 
 
3262
/* ********************************************************************** */
 
3263
 
 
3264
/* format functions allocate printable string for given paragraph */
 
3265
 
 
3266
NLM_EXTERN CharPtr DefaultFormatBlock (
 
3267
  Asn2gbFormatPtr afp,
 
3268
  BaseBlockPtr bbp
 
3269
)
 
3270
 
 
3271
{
 
3272
  if (afp == NULL || bbp == NULL) return NULL;
 
3273
 
 
3274
  /* default format function assumes string pre-allocated by add block function */
 
3275
 
 
3276
  return StringSaveNoNull (bbp->string);
 
3277
}
 
3278
 
 
3279
typedef CharPtr (*FormatProc) (Asn2gbFormatPtr afp, BaseBlockPtr bbp);
 
3280
 
 
3281
static FormatProc asn2gnbk_fmt_functions [27] = {
 
3282
  NULL, NULL,
 
3283
  DefaultFormatBlock, DefaultFormatBlock, DefaultFormatBlock,
 
3284
  DefaultFormatBlock, DefaultFormatBlock, DefaultFormatBlock,
 
3285
  DefaultFormatBlock, DefaultFormatBlock, DefaultFormatBlock,
 
3286
  FormatSourceBlock, FormatOrganismBlock, FormatReferenceBlock,
 
3287
  DefaultFormatBlock, FormatCommentBlock, FormatFeatHeaderBlock,
 
3288
  FormatSourceFeatBlock, FormatFeatureBlock, FormatBasecountBlock,
 
3289
  DefaultFormatBlock, FormatSequenceBlock, FormatContigBlock,
 
3290
  DefaultFormatBlock, DefaultFormatBlock, FormatSlashBlock,
 
3291
  NULL
 
3292
};
 
3293
 
 
3294
NLM_EXTERN void PrintFtableIntervals (
 
3295
  ValNodePtr PNTR head,
 
3296
  BioseqPtr target,
 
3297
  SeqLocPtr location,
 
3298
  CharPtr label
 
3299
)
 
3300
 
 
3301
{
 
3302
  IntFuzzPtr  ifp;
 
3303
  Boolean     partial5;
 
3304
  Boolean     partial3;
 
3305
  SeqLocPtr   slp;
 
3306
  SeqPntPtr   spp;
 
3307
  Int4        start;
 
3308
  Int4        stop;
 
3309
  Char        str [64];
 
3310
  Char        str1 [32];
 
3311
  Char        str2 [32];
 
3312
 
 
3313
  if (head == NULL || target == NULL || location == NULL || label == NULL) return;
 
3314
 
 
3315
  if (location->choice == SEQLOC_PNT) {
 
3316
    spp = (SeqPntPtr) location->data.ptrvalue;
 
3317
    if (spp != NULL) {
 
3318
      ifp = spp->fuzz;
 
3319
      if (ifp != NULL && ifp->choice == 4 && ifp->a == 3) {
 
3320
        sprintf (str, "%ld^\t%ld\t%s\n", (long) (spp->point + 1),
 
3321
                 (long) (spp->point + 2), label);
 
3322
        ValNodeCopyStr (head, 0, str);
 
3323
        return;
 
3324
      }
 
3325
    }
 
3326
  }
 
3327
 
 
3328
  slp = SeqLocFindNext (location, NULL);
 
3329
  if (slp == NULL) return;
 
3330
 
 
3331
  start = GetOffsetInBioseq (slp, target, SEQLOC_START) + 1;
 
3332
  stop = GetOffsetInBioseq (slp, target, SEQLOC_STOP) + 1;
 
3333
  CheckSeqLocForPartial (slp, &partial5, &partial3);
 
3334
  if (partial5) {
 
3335
    sprintf (str1, "<%ld", (long) start);
 
3336
  } else {
 
3337
    sprintf (str1, "%ld", (long) start);
 
3338
  }
 
3339
  if (partial3) {
 
3340
    sprintf (str2, ">%ld", (long) stop);
 
3341
  } else {
 
3342
    sprintf (str2, "%ld", (long) stop);
 
3343
  }
 
3344
  sprintf (str, "%s\t%s\t%s\n", str1, str2, label);
 
3345
  ValNodeCopyStr (head, 0, str);
 
3346
 
 
3347
  while ((slp = SeqLocFindNext (location, slp)) != NULL) {
 
3348
    start = GetOffsetInBioseq (slp, target, SEQLOC_START) + 1;
 
3349
    stop = GetOffsetInBioseq (slp, target, SEQLOC_STOP) + 1;
 
3350
    CheckSeqLocForPartial (slp, &partial5, &partial3);
 
3351
    if (partial5) {
 
3352
      sprintf (str1, "<%ld", (long) start);
 
3353
    } else {
 
3354
      sprintf (str1, "%ld", (long) start);
 
3355
    }
 
3356
    if (partial3) {
 
3357
      sprintf (str2, ">%ld", (long) stop);
 
3358
    } else {
 
3359
      sprintf (str2, "%ld", (long) stop);
 
3360
    }
 
3361
    if (start != 0 && stop != 0) {
 
3362
      sprintf (str, "%s\t%s\n", str1, str2);
 
3363
      ValNodeCopyStr (head, 0, str);
 
3364
    }
 
3365
  }
 
3366
}
 
3367
 
 
3368
static CharPtr goQualList [] = {
 
3369
  "", "go_process", "go_component", "go_function", NULL
 
3370
};
 
3371
 
 
3372
static void PrintFTUserFld (
 
3373
  UserFieldPtr ufp,
 
3374
  Pointer userdata
 
3375
)
 
3376
 
 
3377
{
 
3378
  UserFieldPtr     entry;
 
3379
  CharPtr          evidence = NULL;
 
3380
  Char             gid [32];
 
3381
  CharPtr          goid = NULL;
 
3382
  ValNodePtr PNTR  head;
 
3383
  Int2             i;
 
3384
  Int2             j;
 
3385
  size_t           len;
 
3386
  ObjectIdPtr      oip;
 
3387
  Int4             pmid = 0;
 
3388
  CharPtr          str;
 
3389
  CharPtr          textstr = NULL;
 
3390
  Char             tmp [16];
 
3391
 
 
3392
  if (ufp == NULL || ufp->choice != 11) return;
 
3393
  oip = ufp->label;
 
3394
  if (oip == NULL) return;
 
3395
  for (i = 0; goQualType [i] != NULL; i++) {
 
3396
    if (StringICmp (oip->str, goQualType [i]) == 0) break;
 
3397
  }
 
3398
  if (goQualType [i] == NULL) return;
 
3399
 
 
3400
  /* loop to allow multiple entries for each type of GO term */
 
3401
  for (entry = ufp->data.ptrvalue; entry != NULL; entry = entry->next) {
 
3402
    if (entry == NULL || entry->choice != 11) break;
 
3403
  
 
3404
    pmid = 0;
 
3405
    goid = NULL;
 
3406
    evidence = NULL;
 
3407
    textstr = NULL;
 
3408
 
 
3409
    for (ufp = (UserFieldPtr) entry->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
 
3410
      oip = ufp->label;
 
3411
      if (oip == NULL) continue;
 
3412
      for (j = 0; goFieldType [j] != NULL; j++) {
 
3413
        if (StringICmp (oip->str, goFieldType [j]) == 0) break;
 
3414
      }
 
3415
      if (goFieldType [j] == NULL) continue;
 
3416
      switch (j) {
 
3417
        case 1 :
 
3418
          if (ufp->choice == 1) {
 
3419
            textstr = (CharPtr) ufp->data.ptrvalue;
 
3420
          }
 
3421
          break;
 
3422
        case 2 :
 
3423
          if (ufp->choice == 1) {
 
3424
            goid = (CharPtr) ufp->data.ptrvalue;
 
3425
          } else if (ufp->choice == 2) {
 
3426
            sprintf (gid, "%ld", (long) (Int4) ufp->data.intvalue);
 
3427
            goid = (CharPtr) gid;
 
3428
          }
 
3429
          break;
 
3430
        case 3 :
 
3431
          if (ufp->choice == 2) {
 
3432
            pmid = (Int4) ufp->data.intvalue;
 
3433
          }
 
3434
          break;
 
3435
        case 4 :
 
3436
          if (ufp->choice == 1) {
 
3437
            evidence = (CharPtr) ufp->data.ptrvalue;
 
3438
          }
 
3439
          break;
 
3440
        default :
 
3441
          break;
 
3442
      }
 
3443
    }
 
3444
    /* if (StringHasNoText (textstr)) break; */
 
3445
  
 
3446
    str = (CharPtr) MemNew (StringLen (textstr) + StringLen (goid) + StringLen (evidence) + 40);
 
3447
    if (str == NULL) return;
 
3448
    StringCpy (str, "\t\t\t");
 
3449
    StringCat (str, goQualList [i]);
 
3450
    StringCat (str, "\t");
 
3451
    StringCat (str, textstr);
 
3452
    if (! StringHasNoText (goid)) {
 
3453
      StringCat (str, "|");
 
3454
      StringCat (str, goid);
 
3455
    } else {
 
3456
      StringCat (str, "|");
 
3457
    }
 
3458
    if (pmid != 0) {
 
3459
      sprintf (tmp, "|%ld", (long) pmid);
 
3460
      StringCat (str, tmp);
 
3461
    } else {
 
3462
      StringCat (str, "|");
 
3463
    }
 
3464
    if (! StringHasNoText (evidence)) {
 
3465
      StringCat (str, "|");
 
3466
      StringCat (str, evidence);
 
3467
    }
 
3468
    len = StringLen (str);
 
3469
    while (len > 0 && str [len - 1] == '|') {
 
3470
      str [len - 1] = '\0';
 
3471
      len--;
 
3472
    }
 
3473
  
 
3474
    head = (ValNodePtr PNTR) userdata;
 
3475
    StringCat (str, "\n");
 
3476
    ValNodeCopyStr (head, 0, str);
 
3477
  }
 
3478
}
 
3479
 
 
3480
static void PrintFTUserObj (
 
3481
  UserObjectPtr uop,
 
3482
  Pointer userdata
 
3483
)
 
3484
 
 
3485
{
 
3486
  ObjectIdPtr  oip;
 
3487
 
 
3488
  if (uop == NULL) return;
 
3489
  oip = uop->type;
 
3490
  if (oip == NULL || StringICmp (oip->str, "GeneOntology") != 0) return;
 
3491
  VisitUserFieldsInUop (uop, userdata, PrintFTUserFld);
 
3492
}
 
3493
 
 
3494
static void PrintFTCodeBreak (
 
3495
  ValNodePtr PNTR head,
 
3496
  CodeBreakPtr cbp,
 
3497
  BioseqPtr target
 
3498
)
 
3499
 
 
3500
{
 
3501
  Char             buf [80];
 
3502
  Choice           cbaa;
 
3503
  IntAsn2gbJob     iaj;
 
3504
  CharPtr          ptr;
 
3505
  Uint1            residue;
 
3506
  SeqCodeTablePtr  sctp;
 
3507
  Uint1            seqcode;
 
3508
  SeqLocPtr        slp;
 
3509
  CharPtr          str;
 
3510
 
 
3511
  seqcode = 0;
 
3512
  sctp = NULL;
 
3513
  cbaa = cbp->aa;
 
3514
  switch (cbaa.choice) {
 
3515
    case 1 :
 
3516
      seqcode = Seq_code_ncbieaa;
 
3517
      break;
 
3518
    case 2 :
 
3519
      seqcode = Seq_code_ncbi8aa;
 
3520
      break;
 
3521
    case 3 :
 
3522
      seqcode = Seq_code_ncbistdaa;
 
3523
      break;
 
3524
    default :
 
3525
      break;
 
3526
  }
 
3527
  if (seqcode == 0) return;
 
3528
  sctp = SeqCodeTableFind (seqcode);
 
3529
  if (sctp == NULL) return;
 
3530
 
 
3531
  MemSet ((Pointer) &iaj, 0, sizeof (IntAsn2gbJob));
 
3532
  iaj.flags.iupacaaOnly = FALSE;
 
3533
  iaj.relModeError = FALSE;
 
3534
 
 
3535
  slp = SeqLocFindNext (cbp->loc, NULL);
 
3536
  while (slp != NULL) {
 
3537
    str = FFFlatLoc (&iaj, target, slp, FALSE);
 
3538
    if (str != NULL) {
 
3539
      residue = cbaa.value.intvalue;
 
3540
      ptr = Get3LetterSymbol (&iaj, seqcode, sctp, residue);
 
3541
      if (ptr == NULL) {
 
3542
        ptr = "OTHER";
 
3543
      }
 
3544
      sprintf (buf, "\t\t\ttransl_except\t(pos:%s,aa:%s)\n", str, ptr);
 
3545
      ValNodeCopyStr (head, 0, buf);
 
3546
      MemFree (str);
 
3547
    }
 
3548
    slp = SeqLocFindNext (cbp->loc, slp);
 
3549
  }
 
3550
}
 
3551
 
 
3552
static Boolean SeqIdWriteForTable (SeqIdPtr sip, CharPtr buf, size_t buflen, IntAsn2gbJobPtr ajp, Boolean giOK)
 
3553
 
 
3554
{
 
3555
  SeqIdPtr  accn = NULL, local = NULL, patent = NULL,
 
3556
            pdb = NULL, general = NULL, gi = NULL;
 
3557
  DbtagPtr  dbt;
 
3558
  Char      id [41], str [64];
 
3559
  Int2      numids;
 
3560
  CharPtr   prefix = NULL;
 
3561
 
 
3562
  if (sip == NULL || buf == NULL || ajp == NULL) return FALSE;
 
3563
 
 
3564
  while (sip != NULL) {
 
3565
    switch (sip->choice) {
 
3566
      case SEQID_LOCAL :
 
3567
        local = sip;
 
3568
        break;
 
3569
      case SEQID_GENBANK :
 
3570
      case SEQID_EMBL :
 
3571
      case SEQID_PIR :
 
3572
      case SEQID_SWISSPROT :
 
3573
      case SEQID_DDBJ :
 
3574
      case SEQID_PRF :
 
3575
      case SEQID_TPG :
 
3576
      case SEQID_TPE :
 
3577
      case SEQID_TPD :
 
3578
      case SEQID_OTHER :
 
3579
        accn = sip;
 
3580
        break;
 
3581
      case SEQID_PATENT :
 
3582
        patent = sip;
 
3583
        break;
 
3584
      case SEQID_GENERAL :
 
3585
        dbt = (DbtagPtr) sip->data.ptrvalue;
 
3586
        if (dbt != NULL) {
 
3587
          if (StringICmp (dbt->db, "TMSMART") != 0 && StringICmp (dbt->db, "BankIt") != 0) {
 
3588
            general = sip;
 
3589
          }
 
3590
        }
 
3591
        break;
 
3592
      case SEQID_PDB :
 
3593
        pdb = sip;
 
3594
        break;
 
3595
      case SEQID_GI :
 
3596
        gi = sip;
 
3597
        break;
 
3598
      default :
 
3599
        break;
 
3600
    }
 
3601
    sip = sip->next;
 
3602
  }
 
3603
 
 
3604
  str [0] = '\0';
 
3605
  numids = 0;
 
3606
 
 
3607
  if (accn != NULL) {
 
3608
    if (SeqIdWrite (accn, id, PRINTID_FASTA_SHORT, sizeof (id) - 1) != NULL) {
 
3609
      StringCat (str, prefix);
 
3610
      StringCat (str, id);
 
3611
      prefix = "|";
 
3612
      numids++;
 
3613
    }
 
3614
  }
 
3615
 
 
3616
  if (general != NULL) {
 
3617
    if (SeqIdWrite (general, id, PRINTID_FASTA_SHORT, sizeof (id) - 1) != NULL) {
 
3618
      StringCat (str, prefix);
 
3619
      StringCat (str, id);
 
3620
      prefix = "|";
 
3621
      numids++;
 
3622
    }
 
3623
  }
 
3624
 
 
3625
  if (local != NULL && (! ajp->flags.suppressLocalID) && numids == 0) {
 
3626
    if (SeqIdWrite (local, id, PRINTID_FASTA_SHORT, sizeof (id) - 1) != NULL) {
 
3627
      StringCat (str, prefix);
 
3628
      StringCat (str, id);
 
3629
      prefix = "|";
 
3630
      numids++;
 
3631
    }
 
3632
  }
 
3633
 
 
3634
  if (gi != NULL && giOK && numids == 0) {
 
3635
    if (SeqIdWrite (accn, id, PRINTID_FASTA_SHORT, sizeof (id) - 1) != NULL) {
 
3636
      StringCat (str, prefix);
 
3637
      StringCat (str, id);
 
3638
      prefix = "|";
 
3639
      numids++;
 
3640
    }
 
3641
  }
 
3642
 
 
3643
  StringNCpy_0 (buf, str, buflen);
 
3644
  if (StringHasNoText (buf)) return FALSE;
 
3645
 
 
3646
  return TRUE;
 
3647
}
 
3648
 
 
3649
static void PrintBioSourceFtableEntry (
 
3650
  ValNodePtr PNTR head,
 
3651
  BioSourcePtr    biop
 
3652
)
 
3653
{
 
3654
  OrgModPtr    mod;
 
3655
  SubSourcePtr ssp;
 
3656
  Char         str [256];
 
3657
 
 
3658
  if (head == NULL || biop == NULL) return;
 
3659
 
 
3660
  if (biop->org != NULL && ! StringHasNoText (biop->org->taxname))
 
3661
  {
 
3662
    sprintf (str, "\t\t\torganism\t%s\n", biop->org->taxname);
 
3663
    ValNodeCopyStr (head, 0, str);
 
3664
  }
 
3665
 
 
3666
  /* add OrgMods */
 
3667
  if (biop->org != NULL && biop->org->orgname != NULL)
 
3668
  {
 
3669
    for (mod = biop->org->orgname->mod;
 
3670
         mod != NULL;
 
3671
         mod = mod->next)
 
3672
    {
 
3673
      switch (mod->subtype)
 
3674
      {
 
3675
        case ORGMOD_strain :
 
3676
          sprintf (str, "\t\t\tstrain\t");
 
3677
          break;
 
3678
        case ORGMOD_substrain :
 
3679
          sprintf (str, "\t\t\tsubstrain\t");
 
3680
          break;
 
3681
        case ORGMOD_type :
 
3682
          sprintf (str, "\t\t\ttype\t");
 
3683
          break;
 
3684
        case ORGMOD_subtype :
 
3685
          sprintf (str, "\t\t\tsubtype\t");
 
3686
          break;
 
3687
        case ORGMOD_variety :
 
3688
          sprintf (str, "\t\t\tvariety\t");
 
3689
          break;
 
3690
        case ORGMOD_serotype :
 
3691
          sprintf (str, "\t\t\tserotype\t");
 
3692
          break;
 
3693
        case ORGMOD_serogroup :
 
3694
          sprintf (str, "\t\t\tserogroup\t");
 
3695
          break;
 
3696
        case ORGMOD_serovar :
 
3697
          sprintf (str, "\t\t\tserovar\t");
 
3698
          break;
 
3699
        case ORGMOD_cultivar :
 
3700
          sprintf (str, "\t\t\tcultivar\t");
 
3701
          break;
 
3702
        case ORGMOD_pathovar :
 
3703
          sprintf (str, "\t\t\tpathovar\t");
 
3704
          break;
 
3705
        case ORGMOD_chemovar :
 
3706
          sprintf (str, "\t\t\tchemovar\t");
 
3707
          break;
 
3708
        case ORGMOD_biovar :
 
3709
          sprintf (str, "\t\t\tbiovar\t");
 
3710
          break;
 
3711
        case ORGMOD_biotype :
 
3712
          sprintf (str, "\t\t\tbiotype\t");
 
3713
          break;
 
3714
        case ORGMOD_group :
 
3715
          sprintf (str, "\t\t\tgroup\t");
 
3716
          break;
 
3717
        case ORGMOD_subgroup :
 
3718
          sprintf (str, "\t\t\tsubgroup\t");
 
3719
          break;
 
3720
        case ORGMOD_isolate :
 
3721
          sprintf (str, "\t\t\tisolate\t");
 
3722
          break;
 
3723
        case ORGMOD_common :
 
3724
          sprintf (str, "\t\t\tcommon\t");
 
3725
          break;
 
3726
        case ORGMOD_acronym :
 
3727
          sprintf (str, "\t\t\tacronym\t");
 
3728
          break;
 
3729
        case ORGMOD_dosage :
 
3730
          sprintf (str, "\t\t\tdosage\t");
 
3731
          break;
 
3732
        case ORGMOD_nat_host :
 
3733
          sprintf (str, "\t\t\tnat_host\t");
 
3734
          break;
 
3735
        case ORGMOD_sub_species :
 
3736
          sprintf (str, "\t\t\tsub_species\t");
 
3737
          break;
 
3738
        case ORGMOD_specimen_voucher :
 
3739
          sprintf (str, "\t\t\tspecimen_voucher\t");
 
3740
          break;
 
3741
        case ORGMOD_authority :
 
3742
          sprintf (str, "\t\t\tauthority\t");
 
3743
          break;
 
3744
        case ORGMOD_forma :
 
3745
          sprintf (str, "\t\t\tforma\t");
 
3746
          break;
 
3747
        case ORGMOD_forma_specialis :
 
3748
          sprintf (str, "\t\t\tforma_specialis\t");
 
3749
          break;
 
3750
        case ORGMOD_ecotype :
 
3751
          sprintf (str, "\t\t\tecotype\t");
 
3752
          break;
 
3753
        case ORGMOD_synonym :
 
3754
          sprintf (str, "\t\t\tsynonym\t");
 
3755
          break;
 
3756
        case ORGMOD_anamorph :
 
3757
          sprintf (str, "\t\t\tanamorph\t");
 
3758
          break;
 
3759
        case ORGMOD_teleomorph :
 
3760
          sprintf (str, "\t\t\tteleomorph\t");
 
3761
          break;
 
3762
        case ORGMOD_breed :
 
3763
          sprintf (str, "\t\t\tbreed\t");
 
3764
          break;
 
3765
        case ORGMOD_gb_acronym :
 
3766
          sprintf (str, "\t\t\tgb_acronym\t");
 
3767
          break;
 
3768
        case ORGMOD_gb_anamorph :
 
3769
          sprintf (str, "\t\t\tgb_anamorph\t");
 
3770
          break;
 
3771
        case ORGMOD_old_lineage :
 
3772
          sprintf (str, "\t\t\told_lineage\t");
 
3773
          break;
 
3774
        case ORGMOD_old_name :
 
3775
          sprintf (str, "\t\t\told_name\t");
 
3776
          break;
 
3777
        case ORGMOD_other :
 
3778
          sprintf (str, "\t\t\tnote\t");
 
3779
          break;
 
3780
        default :
 
3781
          str [0] = 0;
 
3782
      }
 
3783
      if ( str [0] == 0) continue;
 
3784
      if (! StringHasNoText (mod->subname))
 
3785
      {
 
3786
        StringNCat (str, mod->subname, sizeof (str) - StringLen (str) - 2);
 
3787
        str [sizeof (str) - 2] = 0;
 
3788
      }
 
3789
      StringCat (str, "\n");
 
3790
      ValNodeCopyStr (head, 0, str);
 
3791
    }
 
3792
  }
 
3793
   
 
3794
  for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next)
 
3795
  {
 
3796
    switch (ssp->subtype)
 
3797
    {
 
3798
      case SUBSRC_chromosome :
 
3799
        sprintf (str, "\t\t\tchromosome\t");
 
3800
        break;
 
3801
      case SUBSRC_map :
 
3802
        sprintf (str, "\t\t\tmap\t");
 
3803
        break;
 
3804
      case SUBSRC_clone :
 
3805
        sprintf (str, "\t\t\tclone\t");
 
3806
        break;
 
3807
      case SUBSRC_haplotype :
 
3808
        sprintf (str, "\t\t\thaplotype\t");
 
3809
        break;
 
3810
      case SUBSRC_genotype :
 
3811
        sprintf (str, "\t\t\tgenotype\t");
 
3812
        break;
 
3813
      case SUBSRC_sex :
 
3814
        sprintf (str, "\t\t\tsex\t");
 
3815
        break;
 
3816
      case SUBSRC_cell_line :
 
3817
        sprintf (str, "\t\t\tcell_line\t");
 
3818
        break;
 
3819
      case SUBSRC_cell_type :
 
3820
        sprintf (str, "\t\t\tcell_type\t");
 
3821
        break;
 
3822
      case SUBSRC_tissue_type :
 
3823
        sprintf (str, "\t\t\ttissue_type\t");
 
3824
        break;
 
3825
      case SUBSRC_clone_lib :
 
3826
        sprintf (str, "\t\t\tclone_lib\t");
 
3827
        break;
 
3828
      case SUBSRC_dev_stage :
 
3829
        sprintf (str, "\t\t\tdev_stage\t");
 
3830
        break;
 
3831
      case SUBSRC_frequency :
 
3832
        sprintf (str, "\t\t\tfrequency\t");
 
3833
        break;
 
3834
      case SUBSRC_germline :
 
3835
        sprintf (str, "\t\t\tgermline\t");
 
3836
        break;
 
3837
      case SUBSRC_rearranged :
 
3838
        sprintf (str, "\t\t\trearranged\t");
 
3839
        break;
 
3840
      case SUBSRC_lab_host :
 
3841
        sprintf (str, "\t\t\tlab_host\t");
 
3842
        break;
 
3843
      case SUBSRC_pop_variant :
 
3844
        sprintf (str, "\t\t\tpop_variant\t");
 
3845
        break;
 
3846
      case SUBSRC_tissue_lib :
 
3847
        sprintf (str, "\t\t\ttissue_lib\t");
 
3848
        break;
 
3849
      case SUBSRC_plasmid_name :
 
3850
        sprintf (str, "\t\t\tplasmid_name\t");
 
3851
        break;
 
3852
      case SUBSRC_transposon_name :
 
3853
        sprintf (str, "\t\t\ttransposon_name\t");
 
3854
        break;
 
3855
      case SUBSRC_insertion_seq_name :
 
3856
        sprintf (str, "\t\t\tinsertion_seq_name\t");
 
3857
        break;
 
3858
      case SUBSRC_plastid_name :
 
3859
        sprintf (str, "\t\t\tplastid_name\t");
 
3860
        break;
 
3861
      case SUBSRC_country :
 
3862
        sprintf (str, "\t\t\tcountry\t");
 
3863
        break;
 
3864
      case SUBSRC_segment :
 
3865
        sprintf (str, "\t\t\tsegment\t");
 
3866
        break;
 
3867
      case SUBSRC_endogenous_virus_name :
 
3868
        sprintf (str, "\t\t\tendogenous_virus_name\t");
 
3869
        break;
 
3870
      case SUBSRC_transgenic :
 
3871
        sprintf (str, "\t\t\ttransgenic\t");
 
3872
        break;
 
3873
      case SUBSRC_environmental_sample :
 
3874
        sprintf (str, "\t\t\tenvironmental_sample\t");
 
3875
        break;
 
3876
      case SUBSRC_isolation_source :
 
3877
        sprintf (str, "\t\t\tisolation_source\t");
 
3878
        break;
 
3879
      case SUBSRC_other :
 
3880
          sprintf (str, "\t\t\tnote\t");
 
3881
          break;
 
3882
      default :
 
3883
        str [0] = 0;
 
3884
    }
 
3885
    if ( str [0] == 0) continue;
 
3886
    if (! StringHasNoText (ssp->name))
 
3887
    {
 
3888
      StringNCat (str, ssp->name, sizeof (str) - StringLen (str) - 2);
 
3889
      str [sizeof (str) - 2] = 0;
 
3890
    }
 
3891
    StringCat (str, "\n");
 
3892
    ValNodeCopyStr (head, 0, str);
 
3893
  }  
 
3894
}
 
3895
 
 
3896
NLM_EXTERN void PrintFtableLocAndQuals (
 
3897
  IntAsn2gbJobPtr ajp,
 
3898
  ValNodePtr PNTR head,
 
3899
  BioseqPtr target,
 
3900
  SeqFeatPtr sfp,
 
3901
  SeqMgrFeatContextPtr context
 
3902
)
 
3903
 
 
3904
{
 
3905
  CharPtr            aa;
 
3906
  Int2               bondidx;
 
3907
  BioseqSetPtr       bssp;
 
3908
  CodeBreakPtr       cbp;
 
3909
  BioseqPtr          cdna;
 
3910
  SeqFeatPtr         cds;
 
3911
  CdRegionPtr        crp;
 
3912
  SeqMgrDescContext  dcontext;
 
3913
  DbtagPtr           dbt;
 
3914
  SeqMgrFeatContext  fcontext;
 
3915
  GBQualPtr          gbq;
 
3916
  ValNodePtr         geneorprotdb;
 
3917
  GeneRefPtr         grp;
 
3918
  Boolean            is_gps_genomic = FALSE;
 
3919
  CharPtr            label;
 
3920
  MolInfoPtr         mip;
 
3921
  SeqLocPtr          newloc;
 
3922
  Char               numbuf [32];
 
3923
  Int2               numcodons;
 
3924
  ObjectIdPtr        oip;
 
3925
  BioseqPtr          prod;
 
3926
  SeqFeatPtr         prot;
 
3927
  ProtRefPtr         prp;
 
3928
  Boolean            pseudo;
 
3929
  RnaRefPtr          rrp;
 
3930
  SeqDescrPtr        sdp;
 
3931
  Int4               sec_str;
 
3932
  SeqIdPtr           sip;
 
3933
  SeqIdPtr           sip2;
 
3934
  Int2               siteidx;
 
3935
  SeqLocPtr          slp;
 
3936
  Char               str [256];
 
3937
  Char               tmp [300];
 
3938
  CharPtr            tmpx;
 
3939
  tRNAPtr            trp;
 
3940
  ValNodePtr         vnp;
 
3941
 
 
3942
  if (head == NULL || target == NULL || sfp == NULL || context == NULL) return;
 
3943
  /* label = (CharPtr) FeatDefTypeLabel (sfp); */
 
3944
  label = FindKeyFromFeatDefType (sfp->idx.subtype, FALSE);
 
3945
  if (StringCmp (label, "Gene") == 0) {
 
3946
    label = "gene";
 
3947
  }
 
3948
  else if (StringCmp (label, "Src") == 0) {
 
3949
    label = "source";
 
3950
  }
 
3951
  if (StringHasNoText (label)) {
 
3952
    label = "???";
 
3953
  }
 
3954
 
 
3955
  /* check if genomic sequence in genomic product set */
 
3956
 
 
3957
  if (target->idx.parenttype == OBJ_BIOSEQSET) {
 
3958
    bssp = (BioseqSetPtr) target->idx.parentptr;
 
3959
    if (bssp != NULL && bssp->_class == BioseqseqSet_class_gen_prod_set) {
 
3960
      sdp = SeqMgrGetNextDescriptor (target, NULL, Seq_descr_molinfo, &dcontext);
 
3961
      if (sdp != NULL) {
 
3962
        mip = (MolInfoPtr) sdp->data.ptrvalue;
 
3963
        if (mip != NULL && mip->biomol == MOLECULE_TYPE_GENOMIC) {
 
3964
          is_gps_genomic = TRUE;
 
3965
        }
 
3966
      }
 
3967
    }
 
3968
  }
 
3969
 
 
3970
  PrintFtableIntervals (head, target, sfp->location, label);
 
3971
 
 
3972
  geneorprotdb = NULL;
 
3973
  pseudo = sfp->pseudo;
 
3974
 
 
3975
  switch (context->seqfeattype) {
 
3976
    case SEQFEAT_GENE :
 
3977
      grp = (GeneRefPtr) sfp->data.value.ptrvalue;
 
3978
      if (grp != NULL) {
 
3979
        geneorprotdb = grp->db;
 
3980
        pseudo |= grp->pseudo;
 
3981
 
 
3982
        StringNCpy_0 (str, (CharPtr) grp->locus, sizeof (str));
 
3983
        if (! StringHasNoText (str)) {
 
3984
          sprintf (tmp, "\t\t\tgene\t%s\n", str);
 
3985
          ValNodeCopyStr (head, 0, tmp);
 
3986
        }
 
3987
        for (vnp = grp->syn; vnp != NULL; vnp = vnp->next) {
 
3988
          StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
 
3989
          if (! StringHasNoText (str)) {
 
3990
            sprintf (tmp, "\t\t\tgene_syn\t%s\n", str);
 
3991
            ValNodeCopyStr (head, 0, tmp);
 
3992
          }
 
3993
        }
 
3994
        if (! StringHasNoText (grp->desc)) {
 
3995
          sprintf (tmp, "\t\t\tgene_desc\t%s\n", grp->desc);
 
3996
          ValNodeCopyStr (head, 0, tmp);
 
3997
        }
 
3998
        if (! StringHasNoText (grp->maploc)) {
 
3999
          sprintf (tmp, "\t\t\tmap\t%s\n", grp->maploc);
 
4000
          ValNodeCopyStr (head, 0, tmp);
 
4001
        }
 
4002
        if (! StringHasNoText (grp->locus_tag)) {
 
4003
          sprintf (tmp, "\t\t\tlocus_tag\t%s\n", grp->locus_tag);
 
4004
          ValNodeCopyStr (head, 0, tmp);
 
4005
        }
 
4006
      }
 
4007
      break;
 
4008
    case SEQFEAT_CDREGION :
 
4009
      prod = BioseqFind (SeqLocId (sfp->product));
 
4010
      prot = SeqMgrGetBestProteinFeature (prod, NULL);
 
4011
      if (prot != NULL) {
 
4012
        prp = (ProtRefPtr) prot->data.value.ptrvalue;
 
4013
        if (prp != NULL) {
 
4014
          geneorprotdb = prp->db;
 
4015
          if (prp->name != NULL) {
 
4016
            for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
 
4017
              StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
 
4018
              if (! StringHasNoText (str)) {
 
4019
                sprintf (tmp, "\t\t\tproduct\t%s\n", str);
 
4020
                ValNodeCopyStr (head, 0, tmp);
 
4021
              }
 
4022
            }
 
4023
          }
 
4024
          if (prp->desc != NULL) {
 
4025
            StringNCpy_0 (str, prp->desc, sizeof (str));
 
4026
            if (! StringHasNoText (str)) {
 
4027
              sprintf (tmp, "\t\t\tprot_desc\t%s\n", str);
 
4028
              ValNodeCopyStr (head, 0, tmp);
 
4029
            }
 
4030
          }
 
4031
          for (vnp = prp->activity; vnp != NULL; vnp = vnp->next) {
 
4032
            StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
 
4033
            if (! StringHasNoText (str)) {
 
4034
              sprintf (tmp, "\t\t\tfunction\t%s\n", str);
 
4035
              ValNodeCopyStr (head, 0, tmp);
 
4036
            }
 
4037
          }
 
4038
          for (vnp = prp->ec; vnp != NULL; vnp = vnp->next) {
 
4039
            StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
 
4040
            if (! StringHasNoText (str)) {
 
4041
              sprintf (tmp, "\t\t\tEC_number\t%s\n", str);
 
4042
              ValNodeCopyStr (head, 0, tmp);
 
4043
            }
 
4044
          }
 
4045
        }
 
4046
        StringNCpy_0 (str, prot->comment, sizeof (str));
 
4047
        if (! StringHasNoText (str)) {
 
4048
          sprintf (tmp, "\t\t\tprot_note\t%s\n", str);
 
4049
          ValNodeCopyStr (head, 0, tmp);
 
4050
        }
 
4051
      }
 
4052
      crp = (CdRegionPtr) sfp->data.value.ptrvalue;
 
4053
      if (crp != NULL) {
 
4054
        if (crp->frame > 1 && crp->frame <= 3) {
 
4055
          sprintf (tmp, "\t\t\tcodon_start\t%d\n", (int) crp->frame);
 
4056
          ValNodeCopyStr (head, 0, tmp);
 
4057
        }
 
4058
        for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
 
4059
          PrintFTCodeBreak (head, cbp, target);
 
4060
        }
 
4061
      }
 
4062
      if (prod != NULL) {
 
4063
        if (SeqIdWriteForTable (prod->id, str, sizeof (str), ajp, FALSE)) {
 
4064
          sprintf (tmp, "\t\t\tprotein_id\t%s\n", str);
 
4065
          ValNodeCopyStr (head, 0, tmp);
 
4066
        }
 
4067
        if (is_gps_genomic) {
 
4068
          cds = SeqMgrGetCDSgivenProduct (prod, NULL);
 
4069
          if (cds != NULL) {
 
4070
            cdna = BioseqFindFromSeqLoc (cds->location);
 
4071
            if (cdna != NULL) {
 
4072
              if (SeqIdWriteForTable (cdna->id, str, sizeof (str), ajp, FALSE)) {
 
4073
                sprintf (tmp, "\t\t\ttranscript_id\t%s\n", str);
 
4074
                ValNodeCopyStr (head, 0, tmp);
 
4075
              }
 
4076
            }
 
4077
          }
 
4078
        }
 
4079
      } else if (sfp->product != NULL) {
 
4080
        sip = SeqLocId (sfp->product);
 
4081
        if (sip != NULL) {
 
4082
          if (sip->choice == SEQID_GI) {
 
4083
            sip2 = GetSeqIdForGI (sip->data.intvalue);
 
4084
            if (sip2 != NULL) {
 
4085
              sip = sip2;
 
4086
            }
 
4087
          }
 
4088
          if (SeqIdWriteForTable (sip, str, sizeof (str), ajp, TRUE)) {
 
4089
            sprintf (tmp, "\t\t\tprotein_id\t%s\n", str);
 
4090
            ValNodeCopyStr (head, 0, tmp);
 
4091
          }
 
4092
        }
 
4093
      }
 
4094
      break;
 
4095
    case SEQFEAT_RNA :
 
4096
      prod = BioseqFind (SeqLocId (sfp->product));
 
4097
      rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
 
4098
      if (rrp != NULL) {
 
4099
        switch (rrp->ext.choice) {
 
4100
          case 1 :
 
4101
            StringNCpy_0 (str, (CharPtr) rrp->ext.value.ptrvalue, sizeof (str));
 
4102
            if (! StringHasNoText (str)) {
 
4103
              sprintf (tmp, "\t\t\tproduct\t%s\n", str);
 
4104
              ValNodeCopyStr (head, 0, tmp);
 
4105
            }
 
4106
            break;
 
4107
          case 2 :
 
4108
            trp = rrp->ext.value.ptrvalue;
 
4109
            if (trp != NULL) {
 
4110
              FeatDefLabel (sfp, str, sizeof (str) - 1, OM_LABEL_CONTENT);
 
4111
              if (! StringHasNoText (str)) {
 
4112
                sprintf (tmp, "\t\t\tproduct\t%s\n", str);
 
4113
                ValNodeCopyStr (head, 0, tmp);
 
4114
              }
 
4115
              numcodons = ComposeCodonsRecognizedString (trp, numbuf, sizeof (numbuf));
 
4116
              if (numcodons > 0 && StringDoesHaveText (numbuf)) {
 
4117
                sprintf (tmp, "\t\t\tcodon_recognized\t%s\n", numbuf);
 
4118
                ValNodeCopyStr (head, 0, tmp);
 
4119
              }
 
4120
              slp = trp->anticodon;
 
4121
              newloc = NULL;
 
4122
              if (slp != NULL && ajp->ajp.slp != NULL) {
 
4123
                sip = SeqIdParse ("lcl|dummy");
 
4124
                newloc = SeqLocReMapEx (sip, ajp->ajp.slp, slp, 0, FALSE, ajp->masterStyle);
 
4125
                SeqIdFree (sip);
 
4126
                slp = newloc;
 
4127
                if (newloc != NULL) {
 
4128
                  A2GBSeqLocReplaceID (newloc, ajp->ajp.slp);
 
4129
                }
 
4130
              }
 
4131
              aa = str;
 
4132
              if (StringNICmp (aa, "tRNA-", 5) == 0) {
 
4133
                aa += 5;
 
4134
              }
 
4135
              if (slp != NULL && StringDoesHaveText (aa)) {
 
4136
                tmpx = FFFlatLoc (ajp, target, slp, ajp->masterStyle);
 
4137
                if (tmpx != NULL) {
 
4138
                  sprintf (tmp, "\t\t\tanticodon\t(pos:%s,aa:%s)\n", tmpx, aa);
 
4139
                  ValNodeCopyStr (head, 0, tmp);
 
4140
                }
 
4141
                MemFree (tmpx);
 
4142
              }
 
4143
              if (newloc != NULL) {
 
4144
                SeqLocFree (newloc);
 
4145
              }
 
4146
            }
 
4147
            break;
 
4148
          default :
 
4149
            break;
 
4150
        }
 
4151
      }
 
4152
      if (prod != NULL) {
 
4153
        if (SeqIdWriteForTable (prod->id, str, sizeof (str), ajp, FALSE)) {
 
4154
          sprintf (tmp, "\t\t\ttranscript_id\t%s\n", str);
 
4155
          ValNodeCopyStr (head, 0, tmp);
 
4156
        }
 
4157
        if (is_gps_genomic) {
 
4158
          cds = SeqMgrGetNextFeature (prod, NULL, SEQFEAT_CDREGION, 0, &fcontext);
 
4159
          if (cds != NULL && SeqMgrGetNextFeature (prod, cds, SEQFEAT_CDREGION, 0, &fcontext) == NULL) {
 
4160
            prod = BioseqFindFromSeqLoc (cds->product);
 
4161
            if (prod != NULL) {
 
4162
              if (SeqIdWriteForTable (prod->id, str, sizeof (str), ajp, FALSE)) {
 
4163
                sprintf (tmp, "\t\t\tprotein_id\t%s\n", str);
 
4164
                ValNodeCopyStr (head, 0, tmp);
 
4165
              }
 
4166
            }
 
4167
          }
 
4168
        }
 
4169
      } else if (sfp->product != NULL) {
 
4170
        sip = SeqLocId (sfp->product);
 
4171
        if (sip != NULL) {
 
4172
          if (sip->choice == SEQID_GI) {
 
4173
            sip2 = GetSeqIdForGI (sip->data.intvalue);
 
4174
            if (sip2 != NULL) {
 
4175
              sip = sip2;
 
4176
            }
 
4177
          }
 
4178
          if (SeqIdWriteForTable (sip, str, sizeof (str), ajp, TRUE)) {
 
4179
            sprintf (tmp, "\t\t\ttranscript_id\t%s\n", str);
 
4180
            ValNodeCopyStr (head, 0, tmp);
 
4181
          }
 
4182
        }
 
4183
      }
 
4184
      break;
 
4185
    case SEQFEAT_PROT :
 
4186
      prp = (ProtRefPtr) sfp->data.value.ptrvalue;
 
4187
      if (prp != NULL) {
 
4188
        if (prp->name != NULL) {
 
4189
          for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
 
4190
            StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
 
4191
            if (! StringHasNoText (str)) {
 
4192
              sprintf (tmp, "\t\t\tproduct\t%s\n", str);
 
4193
              ValNodeCopyStr (head, 0, tmp);
 
4194
            }
 
4195
          }
 
4196
        }
 
4197
        if (prp->desc != NULL) {
 
4198
          StringNCpy_0 (str, prp->desc, sizeof (str));
 
4199
          if (! StringHasNoText (str)) {
 
4200
            sprintf (tmp, "\t\t\tprot_desc\t%s\n", str);
 
4201
            ValNodeCopyStr (head, 0, tmp);
 
4202
          }
 
4203
        }
 
4204
        for (vnp = prp->activity; vnp != NULL; vnp = vnp->next) {
 
4205
          StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
 
4206
          if (! StringHasNoText (str)) {
 
4207
            sprintf (tmp, "\t\t\tfunction\t%s\n", str);
 
4208
            ValNodeCopyStr (head, 0, tmp);
 
4209
          }
 
4210
        }
 
4211
        for (vnp = prp->ec; vnp != NULL; vnp = vnp->next) {
 
4212
          StringNCpy_0 (str, (CharPtr) vnp->data.ptrvalue, sizeof (str));
 
4213
          if (! StringHasNoText (str)) {
 
4214
            sprintf (tmp, "\t\t\tEC_number\t%s\n", str);
 
4215
            ValNodeCopyStr (head, 0, tmp);
 
4216
          }
 
4217
        }
 
4218
      }
 
4219
      StringNCpy_0 (str, sfp->comment, sizeof (str));
 
4220
      if (! StringHasNoText (str)) {
 
4221
        sprintf (tmp, "\t\t\tprot_note\t%s\n", str);
 
4222
        ValNodeCopyStr (head, 0, tmp);
 
4223
      }
 
4224
      break;
 
4225
    case SEQFEAT_REGION :
 
4226
      StringNCpy_0 (str, (CharPtr) sfp->data.value.ptrvalue, sizeof (str));
 
4227
      if (! StringHasNoText (str)) {
 
4228
        sprintf (tmp, "\t\t\tregion\t%s\n", str);
 
4229
        ValNodeCopyStr (head, 0, tmp);
 
4230
      }
 
4231
      break;
 
4232
    case SEQFEAT_BOND :
 
4233
      bondidx = (Int2) sfp->data.value.intvalue;
 
4234
      if (bondidx == 255) {
 
4235
        bondidx = 5;
 
4236
      }
 
4237
      if (bondidx > 0 && bondidx < 6) {
 
4238
        sprintf (tmp, "\t\t\tbond_type\t%s\n", bondList [bondidx]);
 
4239
        ValNodeCopyStr (head, 0, tmp);
 
4240
      }
 
4241
      break;
 
4242
    case SEQFEAT_SITE :
 
4243
      siteidx = (Int2) sfp->data.value.intvalue;
 
4244
      if (siteidx == 255) {
 
4245
        siteidx = 26;
 
4246
      }
 
4247
      if (siteidx > 0 && siteidx < 27) {
 
4248
        sprintf (tmp, "\t\t\tsite_type\t%s\n", siteList [siteidx]);
 
4249
        ValNodeCopyStr (head, 0, tmp);
 
4250
      }
 
4251
      break;
 
4252
    case SEQFEAT_PSEC_STR :
 
4253
      sec_str = (Int2) sfp->data.value.intvalue;
 
4254
      if (sec_str > 0 && sec_str <= 3) {
 
4255
        sprintf (tmp, "\t\t\tsec_str_type\t%s\n", secStrText [sec_str]);
 
4256
        ValNodeCopyStr (head, 0, tmp);
 
4257
      }
 
4258
      break;
 
4259
    case SEQFEAT_HET :
 
4260
      StringNCpy_0 (str, (CharPtr) sfp->data.value.ptrvalue, sizeof (str));
 
4261
      if (! StringHasNoText (str)) {
 
4262
        sprintf (tmp, "\t\t\theterogen\t%s\n", str);
 
4263
        ValNodeCopyStr (head, 0, tmp);
 
4264
      }
 
4265
      break;
 
4266
    case SEQFEAT_BIOSRC :
 
4267
      PrintBioSourceFtableEntry (head, sfp->data.value.ptrvalue);
 
4268
      break;
 
4269
    default :
 
4270
      break;
 
4271
  }
 
4272
  if (pseudo) {
 
4273
    ValNodeCopyStr (head, 0, "\t\t\tpseudo\n");
 
4274
  }
 
4275
  grp = SeqMgrGetGeneXref (sfp);
 
4276
  if (grp != NULL) {
 
4277
    if (SeqMgrGeneIsSuppressed (grp)) {
 
4278
      ValNodeCopyStr (head, 0, "\t\t\tgene\t-\n");
 
4279
    } else {
 
4280
      if (StringDoesHaveText (grp->locus)) {
 
4281
        sprintf (tmp, "\t\t\tgene\t%s\n", grp->locus);
 
4282
        ValNodeCopyStr (head, 0, tmp);
 
4283
      }
 
4284
      if (StringDoesHaveText (grp->locus_tag)) {
 
4285
        sprintf (tmp, "\t\t\tlocus_tag\t%s\n", grp->locus_tag);
 
4286
        ValNodeCopyStr (head, 0, tmp);
 
4287
      }
 
4288
    }
 
4289
  }
 
4290
  if (! StringHasNoText (sfp->comment)) {
 
4291
    ValNodeCopyStr (head, 0, "\t\t\tnote\t");
 
4292
    ValNodeCopyStr (head, 0, sfp->comment);
 
4293
    ValNodeCopyStr (head, 0, "\n");
 
4294
  }
 
4295
  switch (sfp->exp_ev) {
 
4296
    case 1 :
 
4297
      ValNodeCopyStr (head, 0, "\t\t\tevidence\texperimental\n");
 
4298
      break;
 
4299
    case 2 :
 
4300
      ValNodeCopyStr (head, 0, "\t\t\tevidence\tnot_experimental\n");
 
4301
      break;
 
4302
    default :
 
4303
      break;
 
4304
  }
 
4305
  if (! StringHasNoText (sfp->except_text)) {
 
4306
    ValNodeCopyStr (head, 0, "\t\t\texception\t");
 
4307
    ValNodeCopyStr (head, 0, sfp->except_text);
 
4308
    ValNodeCopyStr (head, 0, "\n");
 
4309
  } else if (sfp->excpt) {
 
4310
    ValNodeCopyStr (head, 0, "\t\t\texception\n");
 
4311
  }
 
4312
  for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
 
4313
    if (! StringHasNoText (gbq->qual)) {
 
4314
      if (! StringHasNoText (gbq->val)) {
 
4315
        sprintf (tmp, "\t\t\t%s\t%s\n", gbq->qual, gbq->val);
 
4316
        ValNodeCopyStr (head, 0, tmp);
 
4317
      }
 
4318
    }
 
4319
  }
 
4320
  VisitUserObjectsInUop (sfp->ext, (Pointer) head, PrintFTUserObj);
 
4321
  for (vnp = geneorprotdb; vnp != NULL; vnp = vnp->next) {
 
4322
    dbt = (DbtagPtr) vnp->data.ptrvalue;
 
4323
    if (dbt != NULL) {
 
4324
      if (! StringHasNoText (dbt->db)) {
 
4325
        oip = dbt->tag;
 
4326
        if (oip->str != NULL && (! StringHasNoText (oip->str))) {
 
4327
          sprintf (tmp, "\t\t\tdb_xref\t%s:%s\n", dbt->db, oip->str);
 
4328
          ValNodeCopyStr (head, 0, tmp);
 
4329
        } else {
 
4330
          sprintf (tmp, "\t\t\tdb_xref\t%s:%ld\n", dbt->db, (long) oip->id);
 
4331
          ValNodeCopyStr (head, 0, tmp);
 
4332
        }
 
4333
      }
 
4334
    }
 
4335
  }
 
4336
  for (vnp = sfp->dbxref; vnp != NULL; vnp = vnp->next) {
 
4337
    dbt = (DbtagPtr) vnp->data.ptrvalue;
 
4338
    if (dbt != NULL) {
 
4339
      if (! StringHasNoText (dbt->db)) {
 
4340
        oip = dbt->tag;
 
4341
        if (oip->str != NULL && (! StringHasNoText (oip->str))) {
 
4342
          sprintf (tmp, "\t\t\tdb_xref\t%s:%s\n", dbt->db, oip->str);
 
4343
          ValNodeCopyStr (head, 0, tmp);
 
4344
        } else {
 
4345
          sprintf (tmp, "\t\t\tdb_xref\t%s:%ld\n", dbt->db, (long) oip->id);
 
4346
          ValNodeCopyStr (head, 0, tmp);
 
4347
        }
 
4348
      }
 
4349
    }
 
4350
  }
 
4351
}
 
4352
 
 
4353
static BioseqPtr FindFirstBioseq (SeqEntryPtr sep)
 
4354
 
 
4355
{
 
4356
  BioseqPtr     bsp;
 
4357
  BioseqSetPtr  bssp;
 
4358
 
 
4359
  if (sep == NULL || sep->data.ptrvalue == NULL ||
 
4360
      /* sep->choice < 0 || */ sep->choice > 2) return NULL;
 
4361
  if (IS_Bioseq (sep)) {
 
4362
    bsp = (BioseqPtr) sep->data.ptrvalue;
 
4363
    return bsp;
 
4364
  }
 
4365
  bssp = (BioseqSetPtr) sep->data.ptrvalue;
 
4366
  for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
 
4367
    bsp = FindFirstBioseq (sep);
 
4368
    if (bsp != NULL) return bsp;
 
4369
  }
 
4370
  return NULL;
 
4371
}
 
4372
 
 
4373
static BioseqPtr BioseqLockAndIndexByEntity (Uint2 entityID)
 
4374
 
 
4375
{
 
4376
  BioseqPtr    bsp;
 
4377
  SeqEntryPtr  sep;
 
4378
  SeqIdPtr     sip;
 
4379
 
 
4380
  if (entityID < 1) return NULL;
 
4381
 
 
4382
  sep = SeqMgrGetSeqEntryForEntityID (entityID);
 
4383
  if (sep == NULL) return NULL;
 
4384
 
 
4385
  bsp = FindFirstBioseq (sep);
 
4386
  if (bsp == NULL) return NULL;
 
4387
 
 
4388
  sip = SeqIdFindBest (bsp->id, 0);
 
4389
  if (sip == NULL) return NULL;
 
4390
 
 
4391
  bsp = BioseqLockById (sip);
 
4392
  if (bsp == NULL) return NULL;
 
4393
 
 
4394
  if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
 
4395
    SeqMgrIndexFeatures (entityID, NULL);
 
4396
  }
 
4397
 
 
4398
  return bsp;
 
4399
}
 
4400
 
 
4401
NLM_EXTERN CharPtr FormatFtableSourceFeatBlock (
 
4402
  BaseBlockPtr bbp,
 
4403
  BioseqPtr target
 
4404
)
 
4405
 
 
4406
{
 
4407
  SeqFeatPtr        sfp;
 
4408
  SeqDescPtr        sdp;
 
4409
  SeqMgrDescContext dcontext;
 
4410
  SeqMgrFeatContext fcontext;
 
4411
  BioSourcePtr      biop;
 
4412
  ValNodePtr        head;
 
4413
  IntSrcBlockPtr    isp;
 
4414
  CharPtr           str;
 
4415
 
 
4416
  if (bbp == NULL) return NULL;
 
4417
 
 
4418
  isp = (IntSrcBlockPtr) bbp;
 
4419
  head = NULL;
 
4420
  biop = NULL;
 
4421
 
 
4422
  if (bbp->itemtype == OBJ_SEQDESC) {
 
4423
    sdp = SeqMgrGetDesiredDescriptor (bbp->entityID, NULL, bbp->itemID,
 
4424
                                      0, NULL, &dcontext);
 
4425
    if (sdp == NULL) return NULL;
 
4426
    biop = sdp->data.ptrvalue;
 
4427
  } else if (bbp->itemtype == OBJ_SEQFEAT) {
 
4428
    sfp = SeqMgrGetDesiredFeature (bbp->entityID, NULL, bbp->itemID, 0, NULL, &fcontext);
 
4429
    if (sfp == NULL) return NULL;
 
4430
    biop = sfp->data.value.ptrvalue;
 
4431
  }
 
4432
  if (biop == NULL) return NULL;
 
4433
  PrintFtableIntervals (&head, target, isp->loc, "source");
 
4434
  PrintBioSourceFtableEntry (&head, biop);
 
4435
 
 
4436
  str = MergeFFValNodeStrs (head);
 
4437
  ValNodeFreeData (head);
 
4438
 
 
4439
  return str;
 
4440
}
 
4441
 
 
4442
NLM_EXTERN void DoImmediateFormat (
 
4443
  Asn2gbFormatPtr afp,
 
4444
  BaseBlockPtr bbp
 
4445
)
 
4446
 
 
4447
{
 
4448
  BlockType    blocktype;
 
4449
  BioseqPtr    bsp;
 
4450
  FormatProc   fmt;
 
4451
  size_t       max;
 
4452
  SeqEntryPtr  oldscope;
 
4453
  QualValPtr   qv = NULL;
 
4454
  SeqEntryPtr  sep;
 
4455
  CharPtr      str = NULL;
 
4456
 
 
4457
  if (afp == NULL || bbp == NULL) return;
 
4458
 
 
4459
  blocktype = bbp->blocktype;
 
4460
  if (blocktype < LOCUS_BLOCK || blocktype > SLASH_BLOCK) return;
 
4461
  fmt = asn2gnbk_fmt_functions [(int) blocktype];
 
4462
  if (fmt == NULL) return;
 
4463
 
 
4464
  max = (size_t) (MAX (ASN2GNBK_TOTAL_SOURCE, ASN2GNBK_TOTAL_FEATUR));
 
4465
  qv = MemNew (sizeof (QualVal) * (max + 5));
 
4466
  if (qv == NULL) return;
 
4467
 
 
4468
  sep = GetTopSeqEntryForEntityID (bbp->entityID);
 
4469
 
 
4470
  bsp = BioseqLockAndIndexByEntity (bbp->entityID);
 
4471
  oldscope = SeqEntrySetScope (sep);
 
4472
 
 
4473
  afp->qvp = qv;
 
4474
  str = fmt (afp, bbp);
 
4475
  afp->qvp = NULL;
 
4476
 
 
4477
  SeqEntrySetScope (oldscope);
 
4478
  BioseqUnlock (bsp);
 
4479
 
 
4480
  if (str != NULL) {
 
4481
    if (afp->fp != NULL) {
 
4482
      fprintf (afp->fp, "%s", str);
 
4483
    }
 
4484
    if (afp->ffwrite != NULL) {
 
4485
      afp->ffwrite (str, afp->userdata, blocktype);
 
4486
    }
 
4487
  } else {
 
4488
    if (afp->fp != NULL) {
 
4489
      fprintf (afp->fp, "?\n");
 
4490
    }
 
4491
    if (afp->ffwrite != NULL) {
 
4492
      afp->ffwrite ("?\n", afp->userdata, blocktype);
 
4493
    }
 
4494
  }
 
4495
 
 
4496
  MemFree (str);
 
4497
  MemFree (qv);
 
4498
}
 
4499
 
 
4500
NLM_EXTERN CharPtr asn2gnbk_format (
 
4501
  Asn2gbJobPtr ajp,
 
4502
  Int4 paragraph
 
4503
)
 
4504
 
 
4505
{
 
4506
  Asn2gbFormat     af;
 
4507
  Asn2gbSectPtr    asp;
 
4508
  BaseBlockPtr     bbp;
 
4509
  BlockType        blocktype;
 
4510
  BioseqPtr        bsp;
 
4511
  FormatProc       fmt;
 
4512
  IntAsn2gbJobPtr  iajp;
 
4513
  size_t           max;
 
4514
  SeqEntryPtr      oldscope;
 
4515
  QualValPtr       qv;
 
4516
  Int4             section;
 
4517
  SeqEntryPtr      sep;
 
4518
  CharPtr          str = NULL;
 
4519
 
 
4520
  /* qv must hold MAX (ASN2GNBK_TOTAL_SOURCE, ASN2GNBK_TOTAL_FEATUR) */
 
4521
 
 
4522
  iajp = (IntAsn2gbJobPtr) ajp;
 
4523
  if (iajp == NULL || ajp->sectionArray == NULL || ajp->paragraphArray == NULL) return NULL;
 
4524
  if (paragraph < 0 || paragraph >= ajp->numParagraphs) return NULL;
 
4525
 
 
4526
  bbp = ajp->paragraphArray [paragraph];
 
4527
  if (bbp == NULL) return NULL;
 
4528
 
 
4529
  section = bbp->section;
 
4530
  if (section < 0 || section >= ajp->numSections) return NULL;
 
4531
 
 
4532
  asp = ajp->sectionArray [section];
 
4533
  if (asp == NULL) return NULL;
 
4534
 
 
4535
  blocktype = bbp->blocktype;
 
4536
  if (blocktype < LOCUS_BLOCK || blocktype > SLASH_BLOCK) return NULL;
 
4537
 
 
4538
  max = (size_t) (MAX (ASN2GNBK_TOTAL_SOURCE, ASN2GNBK_TOTAL_FEATUR));
 
4539
  qv = MemNew (sizeof (QualVal) * (max + 5));
 
4540
  if (qv == NULL) return NULL;
 
4541
 
 
4542
  MemSet ((Pointer) &af, 0, sizeof (Asn2gbFormat));
 
4543
  af.ajp = (IntAsn2gbJobPtr) ajp;
 
4544
  af.asp = asp;
 
4545
  af.qvp = qv;
 
4546
  af.format = iajp->format;
 
4547
  af.aip = iajp->aip;
 
4548
  af.atp = iajp->atp;
 
4549
 
 
4550
  sep = GetTopSeqEntryForEntityID (bbp->entityID);
 
4551
 
 
4552
  fmt = asn2gnbk_fmt_functions [(int) blocktype];
 
4553
  if (fmt == NULL) return NULL;
 
4554
 
 
4555
  bsp = BioseqLockAndIndexByEntity (bbp->entityID);
 
4556
  oldscope = SeqEntrySetScope (sep);
 
4557
 
 
4558
  str = fmt (&af, bbp);
 
4559
 
 
4560
  SeqEntrySetScope (oldscope);
 
4561
  BioseqUnlock (bsp);
 
4562
 
 
4563
  if (str == NULL) {
 
4564
    str = StringSave ("???\n");
 
4565
  }
 
4566
 
 
4567
  MemFree (qv);
 
4568
 
 
4569
  return str;
 
4570
}
 
4571
 
 
4572
NLM_EXTERN Asn2gbJobPtr asn2gnbk_cleanup (
 
4573
  Asn2gbJobPtr ajp
 
4574
)
 
4575
 
 
4576
{
 
4577
  Asn2gbSectPtr     asp;
 
4578
  BaseBlockPtr      bbp;
 
4579
  BaseBlockPtr      PNTR blockArray;
 
4580
  Int4              i;
 
4581
  IntAsn2gbJobPtr   iajp;
 
4582
  IntAsn2gbSectPtr  iasp;
 
4583
  IntCdsBlockPtr    icp;
 
4584
  IntFeatBlockPtr   ifp;
 
4585
  IntRefBlockPtr    irp;
 
4586
  IntSrcBlockPtr    isp;
 
4587
  Int4              j;
 
4588
  Int4              numBlocks;
 
4589
  Int4              numSections;
 
4590
  RefBlockPtr       rbp;
 
4591
  Asn2gbSectPtr     PNTR sectionArray;
 
4592
  StringItemPtr     sip, nxt;
 
4593
  SeqBlockPtr       sbp;
 
4594
 
 
4595
  iajp = (IntAsn2gbJobPtr) ajp;
 
4596
  if (iajp == NULL) return NULL;
 
4597
 
 
4598
  SeqLocFree (iajp->ajp.slp);
 
4599
 
 
4600
  numSections = ajp->numSections;
 
4601
  sectionArray = ajp->sectionArray;
 
4602
 
 
4603
  if (sectionArray != NULL) {
 
4604
 
 
4605
    for (i = 0; i < numSections; i++) {
 
4606
      asp = sectionArray [i];
 
4607
      if (asp != NULL) {
 
4608
        iasp = (IntAsn2gbSectPtr) asp;
 
4609
 
 
4610
        numBlocks = asp->numBlocks;
 
4611
        blockArray = asp->blockArray;
 
4612
        if (blockArray != NULL) {
 
4613
 
 
4614
          for (j = 0; j < numBlocks; j++) {
 
4615
            bbp = blockArray [j];
 
4616
            if (bbp != NULL) {
 
4617
 
 
4618
              MemFree (bbp->string);
 
4619
 
 
4620
              if (bbp->blocktype == REFERENCE_BLOCK) {
 
4621
                rbp = (RefBlockPtr) bbp;
 
4622
                MemFree (rbp->uniquestr);
 
4623
                irp = (IntRefBlockPtr) rbp;
 
4624
                DateFree (irp->date);
 
4625
                SeqLocFree (irp->loc);
 
4626
                MemFree (irp->authstr);
 
4627
                MemFree (irp->fig);
 
4628
                MemFree (irp->maploc);
 
4629
 
 
4630
              } else if (bbp->blocktype == SOURCEFEAT_BLOCK) {
 
4631
 
 
4632
                isp = (IntSrcBlockPtr) bbp;
 
4633
                SeqLocFree (isp->loc);
 
4634
 
 
4635
              } else if (bbp->blocktype == FEATURE_BLOCK) {
 
4636
 
 
4637
                ifp = (IntFeatBlockPtr) bbp;
 
4638
                if (ifp->isCDS) {
 
4639
                  icp = (IntCdsBlockPtr) ifp;
 
4640
                  MemFree (icp->fig);
 
4641
                  MemFree (icp->maploc);
 
4642
                }
 
4643
 
 
4644
              } else if (bbp->blocktype == SEQUENCE_BLOCK) {
 
4645
 
 
4646
                sbp = (SeqBlockPtr) bbp;
 
4647
                MemFree (sbp->bases);
 
4648
              }
 
4649
 
 
4650
              MemFree (bbp);
 
4651
            }
 
4652
          }
 
4653
        }
 
4654
        MemFree (asp->blockArray);
 
4655
        MemFree (asp->referenceArray);
 
4656
        MemFree (asp);
 
4657
      }
 
4658
    }
 
4659
  }
 
4660
 
 
4661
  MemFree (ajp->sectionArray);
 
4662
  MemFree (ajp->paragraphArray);
 
4663
  MemFree (ajp->paragraphByIDs);
 
4664
 
 
4665
  sip = iajp->pool;
 
4666
  while (sip != NULL) {
 
4667
    nxt = sip->next;
 
4668
    MemFree (sip);
 
4669
    sip = nxt;
 
4670
  }
 
4671
 
 
4672
  if (iajp->lockedBspList != NULL) {
 
4673
    UnlockFarComponents (iajp->lockedBspList);
 
4674
  }
 
4675
 
 
4676
  free_buff ();
 
4677
  FiniWWW (iajp);
 
4678
 
 
4679
  MemFree (iajp);
 
4680
 
 
4681
  return NULL;
 
4682
}
 
4683
 
 
4684
NLM_EXTERN Boolean SeqEntryToGnbk (
 
4685
  SeqEntryPtr sep,
 
4686
  SeqLocPtr slp,
 
4687
  FmtType format,
 
4688
  ModType mode,
 
4689
  StlType style,
 
4690
  FlgType flags,
 
4691
  LckType locks,
 
4692
  CstType custom,
 
4693
  XtraPtr extra,
 
4694
  FILE *fp
 
4695
)
 
4696
 
 
4697
{
 
4698
  AsnIoPtr           aip = NULL;
 
4699
  AsnIoPtr           aipfree = NULL;
 
4700
  Asn2gbJobPtr       ajp;
 
4701
  AsnTypePtr         atp = NULL;
 
4702
  BioseqPtr          bsp = NULL;
 
4703
  BioseqSetPtr       bssp = NULL;
 
4704
  Boolean            do_gbseq_asn = FALSE;
 
4705
  Boolean            do_gbseq_xml = FALSE;
 
4706
  Asn2gbWriteFunc    ffwrite = NULL;
 
4707
  GBSeqPtr           gbseq = NULL;
 
4708
  GBSeq              gbsq;
 
4709
  IntAsn2gbJobPtr    iajp;
 
4710
  Boolean            rsult = FALSE;
 
4711
  Int1               type = ASNIO_TEXT_OUT;
 
4712
  Pointer            userdata = NULL;
 
4713
  XtraBlock          xtra;
 
4714
  /*
 
4715
  BaseBlockPtr       bbp;
 
4716
  BlockType          block;
 
4717
  CharPtr            ffhead = NULL;
 
4718
  CharPtr            fftail = NULL;
 
4719
  Int4               i;
 
4720
  Boolean            is_html;
 
4721
  Int4               numParagraphs;
 
4722
  BaseBlockPtr PNTR  paragraphArray;
 
4723
  CharPtr            str;
 
4724
  */
 
4725
#ifdef WIN_MAC
 
4726
#if __profile__
 
4727
  ValNodePtr         bsplist = NULL;
 
4728
  Uint2              entityID;
 
4729
  Boolean            lockFarComp;
 
4730
  Boolean            lockFarLocs;
 
4731
  Boolean            lockFarProd;
 
4732
  Boolean            lookupFarComp;
 
4733
  Boolean            lookupFarHist;
 
4734
  Boolean            lookupFarLocs;
 
4735
  Boolean            lookupFarProd;
 
4736
#endif
 
4737
#endif
 
4738
 
 
4739
  if (extra != NULL) {
 
4740
    ffwrite = extra->ffwrite;
 
4741
    /*
 
4742
    ffhead = extra->ffhead;
 
4743
    fftail = extra->fftail;
 
4744
    */
 
4745
    gbseq = extra->gbseq;
 
4746
    aip = extra->aip;
 
4747
    atp = extra->atp;
 
4748
    userdata = extra->userdata;
 
4749
  }
 
4750
  if (fp == NULL && ffwrite == NULL && aip == NULL) return FALSE;
 
4751
  if (sep == NULL && slp == NULL) return FALSE;
 
4752
  if (sep != NULL) {
 
4753
    if (IS_Bioseq (sep)) {
 
4754
      bsp = (BioseqPtr) sep->data.ptrvalue;
 
4755
    } else if (IS_Bioseq_set (sep)) {
 
4756
      bssp = (BioseqSetPtr) sep->data.ptrvalue;
 
4757
    }
 
4758
  }
 
4759
 
 
4760
#ifdef WIN_MAC
 
4761
#if __profile__
 
4762
  /* this allows profiling of just the formatter, without feature indexing, on the Mac */
 
4763
 
 
4764
  if (sep != NULL) {
 
4765
    entityID = ObjMgrGetEntityIDForPointer (sep->data.ptrvalue);
 
4766
    if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
 
4767
      SeqMgrIndexFeatures (entityID, NULL);
 
4768
    }
 
4769
  }
 
4770
 
 
4771
  lockFarComp = (Boolean) ((locks & LOCK_FAR_COMPONENTS) != 0);
 
4772
  lockFarLocs = (Boolean) ((locks & LOCK_FAR_LOCATIONS) != 0);
 
4773
  lockFarProd = (Boolean) ((locks & LOCK_FAR_PRODUCTS) != 0);
 
4774
 
 
4775
  if (lockFarComp || lockFarLocs || lockFarProd) {
 
4776
    locks = locks ^ (LOCK_FAR_COMPONENTS | LOCK_FAR_LOCATIONS | LOCK_FAR_PRODUCTS);
 
4777
    if (slp != NULL && lockFarComp) {
 
4778
      bsplist = LockFarComponentsEx (sep, FALSE, lockFarLocs, lockFarProd, slp);
 
4779
    } else {
 
4780
      bsplist = LockFarComponentsEx (sep, lockFarComp, lockFarLocs, lockFarProd, NULL);
 
4781
    }
 
4782
  }
 
4783
 
 
4784
  lookupFarComp = (Boolean) ((locks & LOOKUP_FAR_COMPONENTS) != 0);
 
4785
  lookupFarLocs = (Boolean) ((locks & LOOKUP_FAR_LOCATIONS) != 0);
 
4786
  lookupFarProd = (Boolean) ((locks & LOOKUP_FAR_PRODUCTS) != 0);
 
4787
  lookupFarHist = (Boolean) ((locks & LOOKUP_FAR_HISTORY) != 0);
 
4788
 
 
4789
  if (lookupFarComp || lookupFarLocs || lookupFarProd || lookupFarHist) {
 
4790
    locks = locks ^ (LOOKUP_FAR_COMPONENTS | LOOKUP_FAR_LOCATIONS | LOOKUP_FAR_PRODUCTS | LOOKUP_FAR_HISTORY);
 
4791
    LookupFarSeqIDs (sep, lookupFarComp, lookupFarLocs, lookupFarProd, FALSE, lookupFarHist);
 
4792
  }
 
4793
 
 
4794
  ProfilerSetStatus (TRUE);
 
4795
#endif
 
4796
#endif
 
4797
 
 
4798
  do_gbseq_xml = (Boolean) ((flags & HTML_XML_ASN_MASK) == CREATE_XML_GBSEQ_FILE);
 
4799
  do_gbseq_asn = (Boolean) ((flags & HTML_XML_ASN_MASK) == CREATE_ASN_GBSEQ_FILE);
 
4800
 
 
4801
  if (do_gbseq_xml || do_gbseq_asn) {
 
4802
    if (fp != NULL && aip == NULL) {
 
4803
      if (do_gbseq_xml) {
 
4804
        type |= ASNIO_XML;
 
4805
      }
 
4806
      aip = AsnIoNew (type, fp, NULL, NULL, NULL);
 
4807
      aipfree = aip;
 
4808
      fp = NULL;
 
4809
    }
 
4810
    if (extra == NULL) {
 
4811
      MemSet ((Pointer) &xtra, 0, sizeof (XtraBlock));
 
4812
      extra = &xtra;
 
4813
    }
 
4814
    if (extra->gbseq == NULL) {
 
4815
      MemSet ((Pointer) &gbsq, 0, sizeof (GBSeq));
 
4816
      extra->gbseq = &gbsq;
 
4817
      gbseq = extra->gbseq;
 
4818
    }
 
4819
  }
 
4820
 
 
4821
  /* pass TRUE for stream to do immediate write at time of creation for speed */
 
4822
 
 
4823
  ajp = asn2gnbk_setup_ex (bsp, bssp, slp, format, mode, style,
 
4824
                           flags, locks, custom, extra,
 
4825
                           TRUE, fp, aip, atp);
 
4826
 
 
4827
  if (ajp != NULL) {
 
4828
    rsult = TRUE;
 
4829
    iajp = (IntAsn2gbJobPtr) ajp;
 
4830
 
 
4831
#if 0
 
4832
    /* if streaming, all output was written in setup function, otherwise output here */
 
4833
 
 
4834
    if (! stream) {
 
4835
 
 
4836
      /* send optional head string */
 
4837
 
 
4838
      is_html = (Boolean) ((flags & HTML_XML_ASN_MASK) == CREATE_HTML_FLATFILE);
 
4839
      if (ffhead == NULL && is_html) {
 
4840
        ffhead = defHead;
 
4841
      }
 
4842
      if (ffhead != NULL) {
 
4843
        if (fp != NULL) {
 
4844
          fprintf (fp, ffhead);
 
4845
        }
 
4846
      }
 
4847
      if (ffwrite != NULL) {
 
4848
        ffwrite (ffhead, userdata, HEAD_BLOCK);
 
4849
      }
 
4850
 
 
4851
      /* send each paragraph */
 
4852
 
 
4853
      numParagraphs = ajp->numParagraphs;
 
4854
      paragraphArray = ajp->paragraphArray;
 
4855
 
 
4856
      for (i = 0; i < numParagraphs; i++) {
 
4857
        str = asn2gnbk_format (ajp, i);
 
4858
        block = (BlockType) 0;
 
4859
        if (paragraphArray != NULL) {
 
4860
          bbp = paragraphArray [i];
 
4861
          if (bbp != NULL) {
 
4862
            block = bbp->blocktype;
 
4863
          }
 
4864
        }
 
4865
        if (str != NULL) {
 
4866
          if (fp != NULL) {
 
4867
            fprintf (fp, "%s", str);
 
4868
          }
 
4869
          if (ffwrite != NULL) {
 
4870
            ffwrite (str, userdata, block);
 
4871
          }
 
4872
        } else {
 
4873
          if (fp != NULL) {
 
4874
            fprintf (fp, "?\n");
 
4875
          }
 
4876
          if (ffwrite != NULL) {
 
4877
            ffwrite ("?\n", userdata, block);
 
4878
          }
 
4879
        }
 
4880
 
 
4881
        MemFree (str);
 
4882
      }
 
4883
 
 
4884
      /* send optional tail string */
 
4885
 
 
4886
      if (fftail == NULL && is_html) {
 
4887
        fftail = defTail;
 
4888
      }
 
4889
      if (fftail != NULL) {
 
4890
        if (fp != NULL) {
 
4891
          fprintf (fp, fftail);
 
4892
        }
 
4893
      }
 
4894
      if (ffwrite != NULL) {
 
4895
        ffwrite (fftail, userdata, TAIL_BLOCK);
 
4896
      }
 
4897
    }
 
4898
#endif
 
4899
 
 
4900
    /* if RELEASE_MODE, warn if unresolved gi numbers, missing translation, etc. */
 
4901
    
 
4902
    if (iajp->relModeError && mode == RELEASE_MODE) {
 
4903
      rsult = FALSE;
 
4904
    }
 
4905
 
 
4906
    asn2gnbk_cleanup (ajp);
 
4907
  }
 
4908
 
 
4909
  if (aipfree != NULL) {
 
4910
    AsnIoFree (aipfree, FALSE);
 
4911
  }
 
4912
 
 
4913
#ifdef WIN_MAC
 
4914
#if __profile__
 
4915
  ProfilerSetStatus (FALSE);
 
4916
 
 
4917
  UnlockFarComponents (bsplist);
 
4918
#endif
 
4919
#endif
 
4920
 
 
4921
  return rsult;
 
4922
}
 
4923
 
 
4924
NLM_EXTERN Boolean BioseqToGnbk (
 
4925
  BioseqPtr bsp,
 
4926
  SeqLocPtr slp,
 
4927
  FmtType format,
 
4928
  ModType mode,
 
4929
  StlType style,
 
4930
  FlgType flags,
 
4931
  LckType locks,
 
4932
  CstType custom,
 
4933
  XtraPtr extra,
 
4934
  FILE *fp
 
4935
)
 
4936
 
 
4937
{
 
4938
  SeqEntryPtr  sep = NULL;
 
4939
 
 
4940
  if (bsp == NULL && slp == NULL) return FALSE;
 
4941
  if (bsp != NULL) {
 
4942
    sep = SeqMgrGetSeqEntryForData (bsp);
 
4943
  }
 
4944
  return SeqEntryToGnbk (sep, slp, format, mode, style, flags, locks, custom, extra, fp);
 
4945
}
 
4946