1 /** for ErrPostEx() ****/
2
3 static char *this_module = "utilpub";
4
5 #ifdef THIS_MODULE
6 #undef THIS_MODULE
7 #endif
8
9 #define THIS_MODULE this_module
10 static char *this_file = __FILE__;
11 #define THIS_FILE this_file
12
13 #include <objmgr.h>
14 #include <sequtil.h>
15 #include <objpub.h>
16 #include <toasn3.h>
17 #include <tfuns.h>
18 #include <utilpub.h>
19 #include <puberr.h>
20
21 #define BUFLEN 120
22
tie_next(ValNodePtr head,ValNodePtr next)23 NLM_EXTERN ValNodePtr tie_next(ValNodePtr head, ValNodePtr next)
24 {
25 ValNodePtr v;
26
27 if (head == NULL) {
28 return next;
29 }
30 for (v = head; v->next != NULL; v = v->next) {
31 v = v;
32 }
33 v->next = next;
34 return head;
35 }
36
37 /***************************************************************
38 *static void CpPubDescr (PubdescPtr new_desc, PubdescPtr old_desc)
39 *
40 *Copy the old_desc to the new_desc. fields are allocated!!
41 ***************************************************************/
42
CpPubDescr(PubdescPtr new_desc,PubdescPtr old_desc)43 static void CpPubDescr (PubdescPtr new_desc, PubdescPtr old_desc)
44
45 {
46 if (new_desc && old_desc)
47 {
48 new_desc->pub = old_desc->pub;
49 new_desc->name = old_desc->name;
50 new_desc->fig = old_desc->fig;
51 new_desc->num = old_desc->num;
52 new_desc->numexc = old_desc->numexc;
53 new_desc->poly_a = old_desc->poly_a;
54 new_desc->align_group = old_desc->align_group;
55 new_desc->maploc = old_desc->maploc;
56 new_desc->seq_raw = old_desc->seq_raw;
57 new_desc->comment = old_desc->comment;
58 new_desc->reftype = old_desc->reftype;
59 }
60
61 return;
62 }
63
GetSerialNumber(ValNodePtr pub)64 static Int2 GetSerialNumber (ValNodePtr pub)
65 {
66 CitGenPtr cgp;
67 ValNodePtr vnp;
68
69 if (pub == NULL)
70 return -1;
71
72 if (pub->choice == PUB_Equiv)
73 {
74 for (vnp=(pub->data.ptrvalue); vnp != NULL; vnp = vnp->next)
75 {
76 if (vnp->choice == PUB_Gen)
77 {
78 cgp = vnp->data.ptrvalue;
79 return cgp->serial_number;
80 }
81 }
82 }
83 else if (pub->choice == PUB_Gen)
84 {
85 cgp = pub->data.ptrvalue;
86 return cgp->serial_number;
87 }
88
89 return -1; /* -1 if no serial number available */
90 }
91
GetPubChoice(ValNodePtr pub)92 static Int2 GetPubChoice (ValNodePtr pub)
93 {
94 CitGenPtr cgp;
95 ValNodePtr vnp;
96
97 if (pub == NULL)
98 return -1;
99
100 if (pub->choice == PUB_Equiv)
101 {
102 for (vnp=(pub->data.ptrvalue); vnp != NULL; vnp = vnp->next)
103 {
104 if (vnp->choice == PUB_Gen) {
105 if ((cgp = vnp->data.ptrvalue) != NULL) {
106 if (cgp->cit != NULL) {
107 return PUB_Gen; /* 1 */
108 }
109 }
110 } else if (vnp->choice == PUB_Sub) {
111 return PUB_Sub; /* 2 */
112 }
113 }
114 }
115 else if (pub->choice == PUB_Gen)
116 {
117 if ((cgp = pub->data.ptrvalue) != NULL) {
118 if (cgp->cit != NULL) {
119 return PUB_Gen; /* 1 */
120 }
121 }
122 }
123 else if (pub->choice == PUB_Sub)
124 {
125 return PUB_Sub; /* 2 */
126 }
127 return -1; /* -1 not PUB_Sub and not unpublis */
128 }
129
GetPubDate(ValNodePtr pub)130 static DatePtr GetPubDate (ValNodePtr pub)
131 {
132 ValNodePtr vnp;
133 CitGenPtr cgp = NULL;
134 CitArtPtr cap = NULL;
135 CitBookPtr cbp = NULL;
136 CitJourPtr cjp = NULL;
137 CitSubPtr csp = NULL;
138 CitPatPtr cpp = NULL;
139 ImprintPtr imp = NULL;
140 DatePtr dp = NULL;
141
142 if (pub == NULL) {
143 return NULL;
144 }
145 if (pub->choice == PUB_Equiv)
146 {
147 for (vnp=pub->data.ptrvalue; vnp != NULL; vnp = vnp->next) {
148 switch (vnp->choice)
149 {
150 case (PUB_Gen):
151 if ((cgp = (CitGenPtr) vnp->data.ptrvalue) != NULL) {
152 dp = (DatePtr) cgp->date;
153 }
154 break;
155 case (PUB_Sub):
156 if ((csp = (CitSubPtr) vnp->data.ptrvalue) != NULL) {
157 imp = (ImprintPtr) csp->imp;
158 if (imp) {
159 dp = (DatePtr) imp->date;
160 }
161 if (csp->date) {
162 dp = (DatePtr) csp->date;
163 }
164 }
165 break;
166 case (PUB_Article):
167 if ((cap = (CitArtPtr) vnp->data.ptrvalue) != NULL) {
168 if (cap->from == 1)
169 {
170 cjp = (CitJourPtr) (cap->fromptr);
171 if (cjp && cjp->imp) {
172 dp = cjp->imp->date;
173 }
174 } else if (cap->from == 2 || cap->from == 3) {
175 cbp = (CitBookPtr) (cap->fromptr);
176 if (cbp && cbp->imp) {
177 dp = cbp->imp->date;
178 }
179 }
180 }
181 break;
182 case (PUB_Patent):
183 if ((cpp = (CitPatPtr) vnp->data.ptrvalue) != NULL) {
184 dp = (DatePtr) cpp->date_issue;
185 }
186 break;
187 case (PUB_Equiv):
188 case (PUB_Muid):
189 case (PUB_Man):
190 case (PUB_Proc):
191 case (PUB_PMid):
192 default:
193 break;
194 }
195 if (dp != NULL) {
196 return DateDup(dp);
197 }
198 }
199 } else {
200 switch (pub->choice)
201 {
202 case (PUB_Gen):
203 if ((cgp = (CitGenPtr) pub->data.ptrvalue) != NULL) {
204 dp = (DatePtr) cgp->date;
205 }
206 break;
207 case (PUB_Sub):
208 if ((csp = (CitSubPtr) pub->data.ptrvalue) != NULL) {
209 if (imp) {
210 dp = (DatePtr) imp->date;
211 }
212 if (csp->date) {
213 dp = (DatePtr) csp->date;
214 }
215 }
216 break;
217 case (PUB_Article):
218 if ((cap = (CitArtPtr) pub->data.ptrvalue) != NULL) {
219 if (cap->from == 1) {
220 cjp = (CitJourPtr) (cap->fromptr);
221 if (cjp && cjp->imp) {
222 dp = cjp->imp->date;
223 }
224 } else if (cap->from == 2) {
225 cbp = (CitBookPtr) (cap->fromptr);
226 if (cbp && cbp->imp) {
227 dp = cbp->imp->date;
228 }
229 }
230 }
231 break;
232 case (PUB_Patent):
233 if ((cpp = (CitPatPtr) pub->data.ptrvalue) != NULL) {
234 dp = (DatePtr) cpp->date_issue;
235 }
236 break;
237 case (PUB_Equiv):
238 case (PUB_Muid):
239 case (PUB_Man):
240 case (PUB_Proc):
241 case (PUB_PMid):
242 default:
243 break;
244 }
245 }
246 if (dp != NULL) {
247 return DateDup(dp);
248 }
249 return NULL;
250 }
251
CreatePubStruct(PubdescPtr pdp,ValNodePtr pub,Uint2 entityID,Uint4 itemID,Uint2 itemtype)252 static PubStructPtr CreatePubStruct(PubdescPtr pdp, ValNodePtr pub,
253 Uint2 entityID, Uint4 itemID, Uint2 itemtype)
254 {
255 PubStructPtr psp = NULL;
256 PubdescPtr descr=NULL;
257 ValNodePtr vnp;
258
259 if (pdp) {
260 descr = AsnIoMemCopy(pdp, (AsnReadFunc) PubdescAsnRead,
261 (AsnWriteFunc) PubdescAsnWrite);
262 if (descr == NULL) return NULL;
263 vnp = ValNodeNew(NULL);
264 vnp->choice = PUB_Equiv;
265 vnp->data.ptrvalue = descr->pub;
266 psp = (PubStructPtr) MemNew(sizeof(PubStruct));
267 psp->pub = vnp;
268 psp->no_free = TRUE;
269 } else if (pub) {
270 psp = (PubStructPtr) MemNew(sizeof(PubStruct));
271 psp->no_free = FALSE;
272 psp->pub = AsnIoMemCopy(pub, (AsnReadFunc) PubAsnRead,
273 (AsnWriteFunc) PubAsnWrite);
274 }
275 if (psp) {
276 psp->descr = descr;
277 psp->number = GetSerialNumber(psp->pub);
278 psp->date = GetPubDate(psp->pub);
279 psp->choice = GetPubChoice(psp->pub);
280 psp->entityID = entityID;
281 psp->itemID = itemID;
282 psp->itemtype = itemtype;
283 }
284
285 return psp;
286 }
287
AddCitFeat(PubStructPtr psp,SeqFeatPtr sfp)288 static void AddCitFeat (PubStructPtr psp, SeqFeatPtr sfp)
289
290 {
291 Int2 i, count=psp->citcount;
292 SeqFeatPtr PNTR tmp;
293
294 if (sfp == NULL) {
295 return;
296 }
297 tmp = (SeqFeatPtr PNTR) MemNew((count+1)*sizeof(SeqFeatPtr));
298 if (count != 0) {
299 for (i=0; i < count; i++) {
300 tmp[i] = psp->citfeat[i];
301 }
302 MemFree(psp->citfeat);
303 }
304
305 psp->citfeat = tmp;
306
307 psp->citfeat[count] = sfp;
308 (psp->citcount)++;
309
310 return;
311
312 }
313
AddPubBsp(PubStructPtr psp,BioseqPtr bsp)314 static void AddPubBsp (PubStructPtr psp, BioseqPtr bsp)
315
316 {
317 Boolean match=FALSE;
318 Int2 i, count=psp->bspcount;
319 BioseqPtr PNTR tmp;
320
321 if (bsp == NULL) {
322 return;
323 }
324 if (count != 0)
325 { /* Look to see if this BioseqPtr is already in the list. */
326 for (i = 0; i < count; i++) {
327 if (bsp == psp->bsp[i]) {
328 match = TRUE;
329 break;
330 }
331 }
332 }
333
334 if (match == TRUE) {
335 return;
336 }
337 if (count != 0) {
338 tmp = (BioseqPtr PNTR) MemNew(count*sizeof(BioseqPtr));
339 for (i=0; i<count; i++)
340 tmp[i] = psp->bsp[i];
341
342 MemFree(psp->bsp);
343 }
344
345 psp->bsp =
346 (BioseqPtr PNTR) MemNew((count+1)*sizeof(BioseqPtr));
347
348 if (count != 0) {
349 for (i=0; i<count; i++)
350 psp->bsp[i] = tmp[i];
351
352 MemFree(tmp);
353 }
354
355 psp->bsp[count] = bsp;
356 (psp->bspcount)++;
357
358 return;
359 }
360
StorePub(BioseqPtr bsp,ValNodePtr vnp,ValNodePtr pub,SeqFeatPtr sfp,Int2 start,Uint2 entityID,Uint4 itemID,Uint2 itemtype)361 NLM_EXTERN ValNodePtr StorePub(BioseqPtr bsp, ValNodePtr vnp, ValNodePtr pub, SeqFeatPtr sfp, Int2 start, Uint2 entityID, Uint4 itemID, Uint2 itemtype)
362 {
363 PubdescPtr pdp, descr = NULL;
364 PubStructPtr psp;
365 ValNodePtr v, PubSet, Pub;
366 ImpFeatPtr ifp;
367
368 if (pub) {
369 pdp = (PubdescPtr) pub->data.ptrvalue;
370 if ((psp = CreatePubStruct(pdp, NULL, entityID, itemID, itemtype)) != NULL) {
371 ValNodeAddPointer(&(vnp), 0, psp);
372 psp->start = start;
373 AddPubBsp (psp, bsp);
374 }
375 } else if (sfp && start == 2) {
376 pdp = (PubdescPtr) sfp->data.value.ptrvalue;
377 if ((psp = CreatePubStruct(pdp, NULL, entityID, itemID, itemtype))
378 != NULL) {
379 ValNodeAddPointer(&(vnp), 0, psp);
380 psp->start = start;
381 AddPubBsp (psp, bsp);
382 AddCitFeat(psp, sfp);
383 }
384 } else if (sfp) {
385 PubSet = (ValNodePtr) sfp->cit;
386 Pub = (ValNodePtr) PubSet->data.ptrvalue;
387 for (v=Pub; v; v=v->next) {
388 if ((psp = CreatePubStruct(NULL, v, entityID, itemID, itemtype))
389 != NULL) {
390 ValNodeAddPointer(&(vnp), 0, psp);
391 AddPubBsp (psp, bsp);
392 psp->Pub = Pub;
393 psp->start = start;
394 if (sfp->data.choice == SEQFEAT_IMP) {
395 ifp = (ImpFeatPtr) sfp->data.value.ptrvalue;
396 if (StringCmp(ifp->key, "Site-ref") == 0
397 && sfp->comment) {
398 descr = PubdescNew();
399 descr->comment = StringSave(sfp->comment);
400 psp->descr = descr;
401 }
402 }
403 }
404 }
405 }
406 return vnp;
407 }
408 /***************************************************************
409 *ValNodePtr StoreNAPubCit(ValNodePtr PubOnCit, BioseqPtr bsp, SeqFeatPtr sfp)
410 *
411 * major KLUDGE warning! This function stores the pub
412 * from an sfp as though it were a pub that covered the
413 * entire entry. This is acceptable, as the Pub-feat
414 * (on a nucleotide entry) WILL cover the entire PROTEIN entry.
415 *
416 * To ensure clickability of the GenPept flat file in Sequin,
417 * the original SeqFeatPtr is also stored. This will allow
418 * Sequin to identify the pub. To avoid "misuse", psp->SeqDescr
419 * is set equal to NULL. These variables are used in GetPapRefPtr.
420 *
421 ***************************************************************/
422
StoreNAPubCit(ValNodePtr PubOnCit,BioseqPtr bsp,SeqFeatPtr sfp)423 NLM_EXTERN ValNodePtr StoreNAPubCit(ValNodePtr PubOnCit, BioseqPtr bsp, SeqFeatPtr sfp)
424
425 {
426 PubdescPtr pdp, descr;
427 PubStructPtr psp;
428 ValNodePtr vnp;
429
430 psp = (PubStructPtr) MemNew(sizeof(PubStruct));
431 ValNodeAddPointer(&(PubOnCit), 0, psp);
432
433 pdp = (PubdescPtr) (sfp->data.value.ptrvalue);
434 descr = PubdescNew();
435 CpPubDescr(descr, pdp);
436 psp->descr = descr;
437 vnp = ValNodeNew(NULL);
438 vnp->choice = PUB_Equiv;
439 vnp->data.ptrvalue = AsnIoMemCopy(pdp->pub,
440 (AsnReadFunc) PubEquivAsnRead, (AsnWriteFunc) PubEquivAsnWrite);
441 psp->pub = vnp;
442 psp->start = 1;
443 psp->number = GetSerialNumber(psp->pub);
444 psp->date = GetPubDate(psp->pub);
445 psp->choice = GetPubChoice(psp->pub);
446 AddPubBsp (psp, bsp);
447
448 return PubOnCit;
449 }
450
451 /******Unique********/
452 /****************************************************************************
453 *
454 * "CatSfpStacks" concatenates two SeqFeatPtr PNTR's and returns
455 * the result to replace sfpp1.
456 *
457 ****************************************************************************/
458
CatSfpStacks(SeqFeatPtr PNTR sfpp1,Int2 * count1,SeqFeatPtr PNTR sfpp2,Int2 count2)459 static SeqFeatPtr PNTR CatSfpStacks
460 (SeqFeatPtr PNTR sfpp1, Int2 *count1, SeqFeatPtr PNTR sfpp2, Int2 count2)
461
462 {
463
464 Int2 i, j, count=(*count1);
465 SeqFeatPtr PNTR tmp;
466 Boolean redundant;
467
468 if (count2 == 0)
469 return sfpp1;
470
471 tmp = (SeqFeatPtr PNTR) MemNew((*count1+count2)*sizeof(SeqFeatPtr));
472
473 for (i=0; i<count; i++)
474 tmp[i] = sfpp1[i];
475
476 for (i=0; i<count2; i++)
477 {
478 redundant = FALSE;
479 for (j=0; j<count; j++)
480 {
481 if (sfpp1[j] == sfpp2[i])
482 {
483 redundant = TRUE;
484 break;
485 }
486 }
487 if (redundant == FALSE)
488 {
489 tmp[(*count1)] = sfpp2[i];
490 (*count1)++;
491 }
492 }
493
494 if (count != 0)
495 MemFree(sfpp1);
496
497 return tmp;
498 }
499
500 /****************************************************************************
501 *
502 * "CatBspStacks" concatenates two BioseqPtr PNTR's and returns
503 * the result to replace bspp1.
504 *
505 ****************************************************************************/
506
CatBspStacks(BioseqPtr PNTR bspp1,Int2 * count1,BioseqPtr PNTR bspp2,Int2 count2)507 static BioseqPtr PNTR CatBspStacks
508 (BioseqPtr PNTR bspp1, Int2 *count1, BioseqPtr PNTR bspp2, Int2 count2)
509
510 {
511
512 Int2 i, j, count=(*count1);
513 BioseqPtr PNTR tmp;
514 Boolean redundant;
515
516 if (count2 == 0)
517 return bspp1;
518
519 tmp = (BioseqPtr PNTR) MemNew((*count1+count2)*sizeof(BioseqPtr));
520
521 for (i=0; i<count; i++)
522 tmp[i] = bspp1[i];
523
524 for (i=0; i<count2; i++)
525 {
526 redundant = FALSE;
527 for (j=0; j<count; j++)
528 {
529 if (bspp1[j] == bspp2[i])
530 {
531 redundant = TRUE;
532 break;
533 }
534 }
535 if (redundant == FALSE)
536 {
537 tmp[(*count1)] = bspp2[i];
538 (*count1)++;
539 }
540 }
541
542 if (count != 0)
543 MemFree(bspp1);
544
545 return tmp;
546 }
547
548 /***************************************************************************
549 *void CatPspInfo (PubStructPtr psp1, PubStructPtr psp2)
550 *
551 * Concatenate some of the information from two different PubStructs
552 * that refer to the same publication.
553 **************************************************************************/
554
CatPspInfo(PubStructPtr psp1,PubStructPtr psp2)555 static void CatPspInfo (PubStructPtr psp1, PubStructPtr psp2)
556
557 {
558 psp2->citfeat =
559 CatSfpStacks(psp2->citfeat, &(psp2->citcount), psp1->citfeat, psp1->citcount);
560 psp2->pubfeat =
561 CatSfpStacks(psp2->pubfeat, &(psp2->pubcount), psp1->pubfeat, psp1->pubcount);
562 psp2->bsp =
563 CatBspStacks(psp2->bsp, &(psp2->bspcount), psp1->bsp, psp1->bspcount);
564 if (psp2->start > psp1->start)
565 psp2->start = psp1->start;
566 if (psp1->descr && psp2->descr)
567 {
568 if (psp2->descr->name == NULL && psp1->descr->name)
569 psp2->descr->name = StringSave(psp1->descr->name);
570 if (psp2->descr->fig == NULL && psp1->descr->fig)
571 psp2->descr->fig = StringSave(psp1->descr->fig);
572 if (psp2->descr->poly_a == FALSE && psp1->descr->poly_a)
573 psp2->descr->poly_a = psp1->descr->poly_a;
574 if (psp2->descr->comment == NULL && psp1->descr->comment)
575 psp2->descr->comment = StringSave(psp1->descr->comment);
576 if (psp2->descr->maploc == NULL && psp1->descr->maploc)
577 psp2->descr->maploc = StringSave(psp1->descr->maploc);
578 }
579 return;
580 }
581
GetPubScore(ValNodePtr pub)582 static Int2 GetPubScore (ValNodePtr pub)
583
584 {
585 /* Below are the scores assigned to each pub following (roughly)
586 Sirotkin's FlatRefBest. Here 0 (not set) is given a score of 0, 1
587 (gen) a score of 6, 2 (sub) a score of 11 etc. The higher the score
588 the better the pub. */
589 static Int2 scores[14] =
590 {0, 6, 11, 7, 1, 8, 4, 3, 5, 9, 2, 10, 12, 1};
591
592 if (pub == NULL || pub->choice > 13)
593 return 0;
594
595 return scores[pub->choice];
596
597 }
598
599 /**************************************************************************
600 *
601 * "SelectBestPub" selects the best of two publications in terms
602 * of the most complete record (e.g., title etc.). To be used
603 * with "UniquePubs"
604 * return values are:
605 * >0: pub1 is better than pub2
606 * 0: pub1 and pub2 are equivalent (i.e., pub1->choice = pub2->choice)
607 * <0: pub2 is better than pub1
608 *
609 ***************************************************************************/
610
SelectBestPub(ValNodePtr pub1,ValNodePtr pub2)611 NLM_EXTERN Int2 SelectBestPub (ValNodePtr pub1, ValNodePtr pub2)
612
613 {
614 CitArtPtr ca=NULL;
615 CitJourPtr jp;
616 ImprintPtr imp;
617 Int2 score1, score2, temp;
618 MedlineEntryPtr ml;
619 ValNodePtr vnp, int_pub1 = NULL, int_pub2 = NULL;
620
621 score1=0;
622 if (pub1 == NULL || pub2 == NULL) {
623 return 0;
624 }
625 if (pub1->choice == PUB_Equiv)
626 {
627 for (vnp=pub1->data.ptrvalue; vnp; vnp=vnp->next)
628 {
629 temp = GetPubScore(vnp);
630 if (temp > score1)
631 {
632 score1 = temp;
633 int_pub1 = vnp;
634 }
635 }
636 }
637 else
638 {
639 score1 = GetPubScore(pub1);
640 int_pub1 = pub1;
641 }
642
643 score2=0;
644 if (pub2->choice == PUB_Equiv)
645 {
646 for (vnp=pub2->data.ptrvalue; vnp; vnp=vnp->next)
647 {
648 temp = GetPubScore(vnp);
649 if (temp > score2)
650 {
651 score2 = temp;
652 int_pub2 = vnp;
653 }
654 }
655 }
656 else
657 {
658 score2 = GetPubScore(pub2);
659 int_pub2 = pub2;
660 }
661
662 /* The following should be improved to encompass other prepub situations
663 (i.e., books etc.) as well as (possibly) check for page numbering etc. ????*/
664
665 if (int_pub1 == NULL || int_pub2 == NULL) {
666 return 0;
667 }
668 if (score1 == score2)
669 { /* If the scores are the same, see if one of them is a prepub */
670 if ( int_pub1 -> choice == PUB_Medline){
671 ml = (MedlineEntryPtr) int_pub1 -> data.ptrvalue;
672 ca = (CitArtPtr) ml -> cit;
673 }else if (int_pub1->choice == PUB_Article) {
674 ca = (CitArtPtr) int_pub1 -> data.ptrvalue;
675 }
676 if(ca && ca ->fromptr && ca ->from ==1)
677 {
678 jp = (CitJourPtr) ca -> fromptr;
679 if ( jp && (imp=jp->imp) != NULL)
680 if (imp->prepub == 1 || imp->prepub == 2)
681 score1 = score2-1;
682 }
683 if ( int_pub2 -> choice == PUB_Medline){
684 ml = (MedlineEntryPtr) int_pub2 -> data.ptrvalue;
685 ca = (CitArtPtr) ml -> cit;
686 }else if (int_pub2->choice == PUB_Article) {
687 ca = (CitArtPtr) int_pub2 -> data.ptrvalue;
688 }
689 if(ca && ca ->fromptr && ca ->from ==1)
690 {
691 jp = (CitJourPtr) ca -> fromptr;
692 if ( jp && (imp=jp->imp) != NULL)
693 if (imp->prepub == 1 || imp->prepub == 2)
694 score2 = score1-1;
695 }
696 }
697 return score1-score2;
698
699 }
700
701 /************************************************************************
702 *
703 * "Unique Pubs" to unique the pubs in the PubStructPtr PNTR
704 * and then concatenate the information (seqfeats etc.) in
705 * two elements that share a pub.
706 *
707 ***********************************************************************/
708
UniquePubs(ValNodePtr PNTR vnpp)709 NLM_EXTERN void UniquePubs (ValNodePtr PNTR vnpp)
710 {
711 Int2 status, status1;
712 PubStructPtr psp1, psp2;
713 ValNodePtr vnp1, vnp2, vnp2next;
714
715 for (vnp1 = *vnpp; vnp1; vnp1 = vnp1->next) {
716 for (vnp2=*vnpp; vnp2; vnp2=vnp2next) {
717 vnp2next = vnp2->next;
718 if (vnp1 == vnp2) {
719 continue;
720 }
721 psp1 = vnp1->data.ptrvalue;
722 psp2 = vnp2->data.ptrvalue;
723 status = PubMatch(psp1->pub, psp2->pub);
724 if (! ABS(status)) {
725 status1 = SelectBestPub(psp1->pub, psp2->pub);
726 if (status1 >= 0) {
727 CatPspInfo(psp2, psp1);
728 FreePubStruct(vnp2->data.ptrvalue);
729 *vnpp = remove_node(*vnpp, vnp2);
730 }
731 }
732 }
733 }
734 } /* UniquePubs */
735
FreePubStruct(PubStructPtr psp)736 NLM_EXTERN void FreePubStruct(PubStructPtr psp)
737
738 {
739 if (psp == NULL) {
740 return;
741 }
742 if (psp->bspcount)
743 MemFree(psp->bsp);
744 if (psp->citcount)
745 MemFree(psp->citfeat);
746 if (psp->pubcount)
747 MemFree(psp->pubfeat);
748 if (psp->descr) {
749 psp->descr = PubdescFree(psp->descr);
750 }
751 if (psp->pub) {
752 if (psp->no_free)
753 ValNodeFree(psp->pub);
754 else
755 PubFree(psp->pub);
756 }
757 if (psp->date) {
758 DateFree(psp->date);
759 }
760 psp = MemFree(psp);
761 return;
762 }
763
GetPMFromPub(ValNodePtr v,Int4Ptr m,Int4Ptr p)764 static Boolean GetPMFromPub(ValNodePtr v, Int4Ptr m, Int4Ptr p)
765 {
766
767 *m = 0;
768 *p = 0;
769 switch (v->choice) {
770 case PUB_Muid:
771 *m = v->data.intvalue;
772 return TRUE;
773 case PUB_PMid:
774 *p = v->data.intvalue;
775 return TRUE;
776 case PUB_Equiv:
777 for (v = v->data.ptrvalue; v; v = v->next) {
778 if (v->choice == PUB_Muid) {
779 *m = v->data.intvalue;
780 }
781 if (v->choice == PUB_PMid) {
782 *p = v->data.intvalue;
783 }
784 }
785 break;
786 }
787 return (*m != 0 || *p != 0);
788 }
789
CitGenTitlesMatch(ValNodePtr pub1,ValNodePtr pub2)790 static Boolean CitGenTitlesMatch (ValNodePtr pub1, ValNodePtr pub2)
791
792 {
793 CitGenPtr cgp1, cgp2;
794
795 if (pub1->choice == PUB_Gen) {
796 cgp1 = (CitGenPtr) pub1->data.ptrvalue;
797 if (cgp1->serial_number != -1 && pub1->next != NULL) {
798 pub1 = pub1->next;
799 }
800 }
801 if (pub2->choice == PUB_Gen) {
802 cgp2 = (CitGenPtr) pub2->data.ptrvalue;
803 if (cgp2->serial_number != -1 && pub2->next != NULL) {
804 pub2 = pub2->next;
805 }
806 }
807
808 if (pub1->choice != PUB_Gen || pub2->choice != PUB_Gen) return TRUE;
809 cgp1 = (CitGenPtr) pub1->data.ptrvalue;
810 cgp2 = (CitGenPtr) pub2->data.ptrvalue;
811 if (cgp1->title == NULL || cgp2->title == NULL) return TRUE;
812 if (StringCmp (cgp1->title, cgp2->title) != 0) return FALSE;
813 return TRUE;
814 }
815
PubLabelMatch(ValNodePtr pub1,ValNodePtr pub2)816 NLM_EXTERN Int2 PubLabelMatch (ValNodePtr pub1, ValNodePtr pub2)
817 {
818 ValNodePtr m1, m2;
819 CitGenPtr g1, g2;
820 size_t len;
821 Int4 am, bm, ap, bp;
822
823 if ((m1 = MinimizePub(pub1)) == NULL) {
824 return -1;
825 }
826 if ((m2 = MinimizePub(pub2)) == NULL) {
827 PubFree(m1);
828 return -1;
829 }
830 if (GetPMFromPub(m1, &am, &ap) && GetPMFromPub(m2, &bm, &bp)) {
831 PubFree(m2);
832 PubFree(m1);
833 if (ap != 0 && ap == bp) {
834 return 0;
835 } else if (am != 0 && am == bm) {
836 return 0;
837 } else {
838 /* ERROR */
839 return -1;
840 }
841 }
842 if (m1->choice == PUB_Gen) {
843 if (m2->choice != PUB_Gen) {
844 PubFree(m1);
845 if (m2->choice == PUB_Equiv)
846 PubFree(m2);
847 else
848 ValNodeFree(m2);
849 return -1;
850 }
851 if ((g1 = m1->data.ptrvalue) == NULL) {
852 ValNodeFree(m1);
853 PubFree(m2);
854 return -1;
855 }
856 if ((g2 = m2->data.ptrvalue) == NULL) {
857 ValNodeFree(m2);
858 PubFree(m1);
859 return -1;
860 }
861 if (g1->cit == NULL || g2->cit == NULL) {
862 PubFree(m1);
863 PubFree(m2);
864 return -1;
865 }
866 len = StringLen (g2->cit);
867 if (len > 1 && g2->cit [len - 1] == '>') {
868 g2->cit [len - 1] = '\0';
869 }
870 len = StringLen (g1->cit);
871 if (len > 1 && g1->cit [len - 1] == '>') {
872 g1->cit [len - 1] = '\0';
873 }
874 len = MIN (StringLen (g1->cit), StringLen (g2->cit));
875 if (StringNICmp(g1->cit, g2->cit, len) == 0) {
876 if (CitGenTitlesMatch (pub1, pub2)) {
877 PubFree(m1);
878 PubFree(m2);
879 return 0;
880 }
881 }
882 }
883 PubFree(m1);
884 PubFree(m2);
885 return -1;
886 }
887
space_save(CharPtr str)888 static CharPtr space_save(CharPtr str)
889 /* deletes spaces from the begining and the end and returns Nlm_StringSave */ {
890 CharPtr s, ss;
891
892 if (str == NULL) {
893 return NULL;
894 }
895 for (; isspace(*str) || *str == ','; str++) continue;
896 for (s = str; *s != '\0'; s++) {
897 if (*s == '\n') {
898 for (ss = s+1; isspace(*ss); ss++) continue;
899 *s = ' ';
900 strcpy(s+1, ss);
901 }
902 }
903 for (s=str+StringLen(str)-1; s >= str && (*s == ' ' || *s == ';' ||
904 *s == ',' || *s == '\"' || *s == '\t'); s--) {
905 *s = '\0';
906 }
907
908 if (*str == '\0') {
909 return NULL;
910 } else {
911 return Nlm_StringSave(str);
912 }
913 }
914
MinimizePub(ValNodePtr pub)915 NLM_EXTERN ValNodePtr MinimizePub(ValNodePtr pub)
916 {
917 ValNodePtr v, min_pub = NULL, epub, apub;
918 Char buffer[BUFLEN+1];
919 CitGenPtr cit_gen, gen;
920
921 if (pub == NULL) {
922 return NULL;
923 }
924 if (pub->choice == PUB_Equiv) {
925 for (v = pub->data.ptrvalue; v != NULL; v= v->next) {
926 if (v->choice == PUB_Muid) {
927 if (min_pub == NULL) {
928 min_pub = AsnIoMemCopy(v, (AsnReadFunc) PubAsnRead,
929 (AsnWriteFunc) PubAsnWrite);
930 } else {
931 epub = ValNodeNew(NULL);
932 epub->choice = PUB_Equiv;
933 apub = AsnIoMemCopy(v, (AsnReadFunc) PubAsnRead,
934 (AsnWriteFunc) PubAsnWrite);
935 min_pub->next = apub;
936 epub->data.ptrvalue = min_pub;
937 return epub;
938 }
939 }
940 if (v->choice == PUB_PMid) {
941 if (min_pub == NULL) {
942 min_pub = AsnIoMemCopy(v, (AsnReadFunc) PubAsnRead,
943 (AsnWriteFunc) PubAsnWrite);
944 } else {
945 epub = ValNodeNew(NULL);
946 epub->choice = PUB_Equiv;
947 apub = AsnIoMemCopy(v, (AsnReadFunc) PubAsnRead,
948 (AsnWriteFunc) PubAsnWrite);
949 min_pub->next = apub;
950 epub->data.ptrvalue = min_pub;
951 return epub;
952 }
953 }
954 }
955 v = pub->data.ptrvalue;
956 } else {
957 v = pub;
958 }
959 if (min_pub != NULL) {
960 return min_pub;
961 }
962 if (v->choice == PUB_Gen) {
963 gen = v->data.ptrvalue;
964 if (gen->serial_number != -1 && v->next != NULL) {
965 v = v->next;
966 }
967 }
968 if (v->choice == PUB_Muid || v->choice == PUB_PMid) {
969 min_pub = AsnIoMemCopy(v, (AsnReadFunc) PubAsnRead,
970 (AsnWriteFunc) PubAsnWrite);
971 return min_pub;
972 }
973 if ((PubLabelUnique(v, buffer, BUFLEN, OM_LABEL_CONTENT, TRUE)) == 0) {
974 min_pub = AsnIoMemCopy(v, (AsnReadFunc) PubAsnRead,
975 (AsnWriteFunc) PubAsnWrite);
976 return min_pub;
977 }
978 min_pub = ValNodeNew(NULL);
979 min_pub->choice = PUB_Gen;
980 cit_gen = CitGenNew();
981 cit_gen->cit = space_save(buffer);
982 min_pub->data.ptrvalue = cit_gen;
983
984 return min_pub;
985 }
986
987 /**********************************************************
988 * store all pubs in a chain of PubStruct using StorePub()
989 *
990 ***********************************************************/
FindCit(SeqEntryPtr sep,Pointer data,Int4 index,Int2 indent)991 NLM_EXTERN void FindCit (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
992 {
993 BioseqPtr bsp_sfp, bsp = NULL;
994 BioseqSetPtr bssp;
995 SeqAnnotPtr sap, ap;
996 SeqFeatPtr head, sfp;
997 ValNodePtr PNTR vnpp, descr, tmp;
998 ImpFeatPtr /*UNUSED*/ifp;
999 SeqLocPtr slp;
1000
1001 vnpp = (ValNodePtr PNTR) data;
1002 if (IS_Bioseq(sep)) {
1003 bsp = (BioseqPtr)(sep->data.ptrvalue);
1004 descr = bsp->descr;
1005 sap = bsp->annot;
1006 }
1007 else {
1008 bssp = (BioseqSetPtr)(sep->data.ptrvalue);
1009 descr = bssp->descr;
1010 sap = bssp->annot;
1011 }
1012 for (tmp = descr; tmp != NULL; tmp = tmp->next) {
1013 if (tmp->choice == Seq_descr_pub) {
1014 *vnpp = StorePub(bsp, *vnpp, tmp, NULL, 1, 0, 0 ,0);
1015 }
1016 }
1017 for (ap = sap; ap != NULL; ap = ap->next) {
1018 if (ap->type != 1) {
1019 continue;
1020 }
1021 head = (SeqFeatPtr)(ap->data);
1022 for (sfp = head; sfp; sfp = sfp->next) {
1023 if (sfp->data.choice == SEQFEAT_PUB) {
1024 slp = sfp->location;
1025 bsp_sfp = BioseqFindCore(SeqLocId(slp));
1026 *vnpp = StorePub(bsp_sfp, *vnpp, NULL, sfp, 2, 0, 0, 0);
1027 }
1028 if (sfp->data.choice == SEQFEAT_IMP) {
1029 ifp = sfp->data.value.ptrvalue;
1030 if (sfp->cit != NULL) {
1031 slp = sfp->location;
1032 bsp_sfp = BioseqFindCore(SeqLocId(slp));
1033 *vnpp = StorePub(bsp_sfp, *vnpp, NULL, sfp, 3, 0, 0, 0);
1034 }
1035 }
1036 }
1037 }
1038
1039 }
1040
1041 /**********************************************************
1042 * find citation on features and find pub with matching serial number
1043 * change all /citation to minimum pubs
1044 *
1045 ***********************************************************/
ChangeCitQual(SeqEntryPtr sep,Pointer data,Int4 index,Int2 indent)1046 NLM_EXTERN void ChangeCitQual (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
1047 {
1048 BioseqPtr bsp = NULL;
1049 BioseqSetPtr bssp;
1050 SeqAnnotPtr sap, ap;
1051 SeqFeatPtr sfp, head;
1052 ValNodePtr PNTR vnpp, /*UNUSED*/descr;
1053 ValNodePtr vnp, pubset = NULL, pub_min, /*UNUSED*/pub;
1054 PubStructPtr psp;
1055 Int2 snum;
1056 CharPtr qval, s;
1057 Boolean first, found;
1058
1059 vnpp = (ValNodePtr PNTR) data;
1060 if (IS_Bioseq(sep)) {
1061 bsp = (BioseqPtr)(sep->data.ptrvalue);
1062 descr = bsp->descr;
1063 sap = bsp->annot;
1064 }
1065 else {
1066 bssp = (BioseqSetPtr)(sep->data.ptrvalue);
1067 descr = bssp->descr;
1068 sap = bssp->annot;
1069 }
1070 for (ap = sap; ap != NULL; ap = ap->next) {
1071 if (ap->type != 1) {
1072 continue;
1073 }
1074 head = (SeqFeatPtr)(ap->data);
1075 for (sfp = head; sfp; sfp = sfp->next) {
1076 first = TRUE;
1077 while ((qval = qvalue_extract(&(sfp->qual), "citation"))
1078 != NULL) {
1079 found = FALSE;
1080 for (s = qval; *s != '\0' && !IS_DIGIT(*s); s++)
1081 continue;
1082 snum = atoi(s);
1083 MemFree(qval);
1084 for (vnp = *vnpp; vnp != NULL; vnp = vnp->next) {
1085 psp = (PubStructPtr) (vnp->data.ptrvalue);
1086 if (psp->number == snum) {
1087 if (bsp && psp->bsp ) {
1088 if (psp->bsp[0] != NULL) {
1089 if( bsp != psp->bsp[0]) {
1090 continue;
1091 }
1092 }
1093 }
1094 pub_min = MinimizePub(psp->pub);
1095 if (first) {
1096 pubset = ValNodeNew(NULL);
1097 pubset->choice = 1; /* Pub-set, pub */
1098 pubset->data.ptrvalue = pub_min;
1099 sfp->cit = pubset;
1100 first = FALSE;
1101 } else {
1102 pubset->data.ptrvalue =
1103 tie_next(pubset->data.ptrvalue, pub_min);
1104 pub = pubset->data.ptrvalue;
1105 }
1106 found = TRUE;
1107 break;
1108 }
1109 } /* vnpp*/
1110 if (found == FALSE) {
1111 ErrPostEx(SEV_ERROR, ERR_QUALIFIER_NoRefForCiteQual,
1112 "No Reference found for Citation qualifier [%d]", snum);
1113 }
1114 }
1115 }
1116 } /* sap*/
1117 }
1118
1119 /***************************************************************************
1120 * DeleteSites:
1121 * -- deletes all ImpFeat "sites"
1122 ****************************************************************************/
DeleteSites(SeqEntryPtr sep,Pointer data,Int4 index,Int2 indent)1123 NLM_EXTERN void DeleteSites (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
1124 {
1125 BioseqPtr bsp = NULL;
1126 BioseqSetPtr bssp = NULL;
1127 SeqAnnotPtr sap, ap, apnext;
1128 SeqFeatPtr sfp, cur, curnext;
1129 ImpFeatPtr ifp;
1130
1131 if (IS_Bioseq(sep)) {
1132 bsp = (BioseqPtr)(sep->data.ptrvalue);
1133 sap = bsp->annot;
1134 }
1135 else {
1136 bssp = (BioseqSetPtr)(sep->data.ptrvalue);
1137 sap = bssp->annot;
1138 }
1139 for (ap = sap; ap != NULL; ap = apnext) {
1140 apnext = ap->next;
1141 sfp = (SeqFeatPtr)(ap->data);
1142 if (ap->type != 1) {
1143 continue;
1144 }
1145 for (cur = sfp; cur; cur = curnext) {
1146 curnext = cur->next;
1147 if (cur->data.choice != SEQFEAT_IMP) {
1148 continue;
1149 }
1150 ifp = cur->data.value.ptrvalue;
1151 if (StringCmp(ifp->key, "Site-ref") != 0) {
1152 continue;
1153 }
1154 sfp = remove_feat(sfp, cur);
1155 if (sfp == NULL) {
1156 break;
1157 }
1158 }
1159 ap->data = sfp;
1160 }
1161
1162 for (ap = sap; ap != NULL; ap = apnext) {
1163 apnext = ap->next;
1164 /* now keep empty annot if annot_descr present */
1165 if (ap->data == NULL && ap->desc == NULL) {
1166 sap = remove_annot(sap, ap);
1167 }
1168 }
1169
1170 if (bssp != NULL) {
1171 bssp->annot = sap;
1172 } else {
1173 bsp->annot = sap;
1174 }
1175 return;
1176 }
1177
CompareByDate(VoidPtr vp1,VoidPtr vp2)1178 static int LIBCALLBACK CompareByDate (VoidPtr vp1, VoidPtr vp2)
1179 {
1180
1181 PubStructPtr psp1, psp2;
1182 Int2 status;
1183 ValNodePtr vnp1, vnp2;
1184 ValNodePtr PNTR vnpp1;
1185 ValNodePtr PNTR vnpp2;
1186
1187 vnpp1 = (ValNodePtr PNTR) vp1;
1188 vnpp2 = (ValNodePtr PNTR) vp2;
1189 vnp1 = *vnpp1;
1190 vnp2 = *vnpp2;
1191
1192 psp1 = vnp1->data.ptrvalue;
1193 psp2 = vnp2->data.ptrvalue;
1194
1195 /* First, three cases that should not be, need to be checked for. */
1196 if (psp1 == NULL && psp2 != NULL)
1197 return 1;
1198 if (psp1 != NULL && psp2 == NULL)
1199 return -1;
1200 if (psp1 == NULL && psp2 == NULL)
1201 return 0;
1202 status = DateMatch(psp1->date, psp2->date, FALSE);
1203 if (status == -2) {
1204 status = 2;
1205 }
1206
1207 return status;
1208 }
1209
1210 /***************************************************************************
1211 *
1212 * "CompareSnForHeap" compares serial numbers, if they exist,
1213 * to sort pubs in that manner.
1214 *
1215 ***************************************************************************/
1216
CompareSnForHeap(VoidPtr vp1,VoidPtr vp2)1217 static int LIBCALLBACK CompareSnForHeap (VoidPtr vp1, VoidPtr vp2)
1218
1219 {
1220 PubStructPtr psp1, psp2;
1221 ValNodePtr vnp1, vnp2;
1222 ValNodePtr PNTR vnpp1;
1223 ValNodePtr PNTR vnpp2;
1224
1225 vnpp1 = (ValNodePtr PNTR) vp1;
1226 vnpp2 = (ValNodePtr PNTR) vp2;
1227 vnp1 = *vnpp1;
1228 vnp2 = *vnpp2;
1229
1230 psp1 = vnp1->data.ptrvalue;
1231 psp2 = vnp2->data.ptrvalue;
1232
1233 /* First, three cases that should not be, need to be checked for. */
1234 if (psp1 == NULL && psp2 != NULL)
1235 return 1;
1236 if (psp1 != NULL && psp2 == NULL)
1237 return -1;
1238 if (psp1 == NULL && psp2 == NULL)
1239 return 0;
1240
1241 if (psp1->number > psp2->number)
1242 return 1;
1243 else if (psp1->number < psp2->number)
1244 return -1;
1245 else
1246 return 0;
1247 /* Two pubs should not have the same serial number, but that case is covered
1248 anyway by the line above.*/
1249 }
1250
1251 /***************************************************************************
1252 *
1253 * "CompareStartForHeap" compares "start" numbers, found in
1254 * the PubStruct, so that pubs are sorted into the order
1255 * descrip, cit, and feat.
1256 *
1257 ***************************************************************************/
1258 /*______________________________________________________________________
1259 **
1260 ** This code is not currently used.
1261 ** I do not remove this piece of code, just comment it out.
1262 ** -- Dmitri Lukyanov
1263 */
1264 #if 0
1265
1266 static int LIBCALLBACK CompareStartForHeap (VoidPtr vp1, VoidPtr vp2)
1267
1268 {
1269 PubStructPtr psp1, psp2;
1270 ValNodePtr vnp1, vnp2;
1271 ValNodePtr PNTR vnpp1;
1272 ValNodePtr PNTR vnpp2;
1273
1274 vnpp1 = (ValNodePtr PNTR) vp1;
1275 vnpp2 = (ValNodePtr PNTR) vp2;
1276 vnp1 = *vnpp1;
1277 vnp2 = *vnpp2;
1278
1279 psp1 = vnp1->data.ptrvalue;
1280 psp2 = vnp2->data.ptrvalue;
1281
1282
1283 /* First, three cases that should not be, need to be checked for. */
1284 if (psp1 == NULL && psp2 != NULL)
1285 return 1;
1286 if (psp1 != NULL && psp2 == NULL)
1287 return -1;
1288 if (psp1 == NULL && psp2 == NULL)
1289 return 0;
1290
1291 if (psp1->start > psp2->start)
1292 return 1;
1293 else if (psp1->start < psp2->start)
1294 return -1;
1295 else /* If the two start values are equal */
1296 return 0;
1297
1298 }
1299
1300 #endif
1301 /*______________________________________________________________________
1302 */
1303
VnpHeapSort(ValNodePtr PNTR vnp,int (LIBCALLBACK * compar)PROTO ((Nlm_VoidPtr,Nlm_VoidPtr)))1304 void VnpHeapSort (ValNodePtr PNTR vnp, int (LIBCALLBACK *compar )PROTO ((Nlm_VoidPtr, Nlm_VoidPtr )))
1305
1306 {
1307 Int4 index, total;
1308 ValNodePtr vnp1;
1309 ValNodePtr PNTR temp;
1310
1311 if (vnp == NULL || *vnp == NULL) return; /* do nothing */
1312
1313 total=0;
1314 for (vnp1 = *vnp; vnp1; vnp1=vnp1->next)
1315 total++;
1316
1317 temp = (ValNodePtr PNTR) MemNew(total*sizeof(ValNodePtr));
1318
1319 index=0;
1320 for (vnp1 = *vnp; vnp1; vnp1=vnp1->next)
1321 {
1322 temp[index] = vnp1;
1323 index++;
1324 }
1325
1326 HeapSort ((VoidPtr) temp, (size_t) index, sizeof(ValNodePtr), compar);
1327
1328 *vnp = temp[0];
1329 for (vnp1 = *vnp, index=0; index<(total-1); vnp1=vnp1->next, index++)
1330 {
1331 vnp1->next = temp[index+1];
1332 }
1333 vnp1 = temp[total-1];
1334 vnp1->next = NULL;
1335
1336 temp = MemFree(temp);
1337 }
1338
PubHeapSort(ValNodePtr PNTR vnp,int (LIBCALLBACK * compar)PROTO ((Nlm_VoidPtr,Nlm_VoidPtr)))1339 static void PubHeapSort (ValNodePtr PNTR vnp, int (LIBCALLBACK *compar )PROTO ((Nlm_VoidPtr, Nlm_VoidPtr )))
1340
1341 {
1342 PubStructPtr psp;
1343 ValNodePtr v, ex_v, v_sub=NULL, v_unp=NULL, vnext;
1344
1345 for (v = *vnp; v != NULL; v = vnext) {
1346 vnext = v->next;
1347 psp = (PubStructPtr) v->data.ptrvalue;
1348 if(psp->choice == PUB_Sub) {
1349 ex_v = extract_node(vnp, v);
1350 v_sub = tie_next(v_sub, ex_v);
1351 } else if (psp->choice == PUB_Gen) {
1352 ex_v = extract_node(vnp, v);
1353 v_unp = tie_next(v_unp, ex_v);
1354 }
1355 }
1356 if (*vnp) {
1357 VnpHeapSort(vnp, compar);
1358 }
1359 if (v_unp) {
1360 VnpHeapSort(&(v_unp), compar);
1361 }
1362 if (v_sub) {
1363 VnpHeapSort(&(v_sub), compar);
1364 }
1365
1366 *vnp = tie_next(*vnp, v_unp);
1367 *vnp = tie_next(*vnp, v_sub);
1368
1369 }
1370
1371 /**************************************************************************
1372 * "OrganizePubList" sorts the pubs (that is a chain of ValNodes with
1373 * PubStructPtr in data.ptrvalue.
1374 * First a check is done for serial numbers and, if they exist, the pubs are
1375 * output in order without further work. If not, they are and
1376 * sorted by date.
1377 * No unique here because it's already done in CheckPubs (Tatiana)
1378 **************************************************************************/
OrganizePubList(ValNodePtr vnp)1379 NLM_EXTERN ValNodePtr OrganizePubList(ValNodePtr vnp)
1380 {
1381 Int2 index;
1382 PubStructPtr psp;
1383 ValNodePtr vnp1;
1384 Boolean numbered=TRUE, ordered=TRUE;
1385
1386 for (vnp1=vnp; vnp1; vnp1=vnp1->next)
1387 {
1388 psp = vnp1->data.ptrvalue;
1389 if (psp->number == -1)
1390 {
1391 numbered = FALSE;
1392 break;
1393 }
1394 }
1395
1396 if (numbered == TRUE)
1397 {
1398 for (vnp1=vnp, index=0; vnp1; vnp1=vnp1->next)
1399 {
1400 index++;
1401 psp = vnp1->data.ptrvalue;
1402 if (psp->number != index)
1403 {
1404 ordered = FALSE;
1405 break;
1406 }
1407 }
1408
1409 if (ordered != TRUE)
1410 {
1411 VnpHeapSort(&(vnp), CompareSnForHeap);
1412 }
1413 }
1414 else
1415 {
1416 /* VnpHeapSort(&(vnp), CompareStartForHeap); */
1417 PubHeapSort(&(vnp), CompareByDate);
1418 }
1419
1420 /* New serial numbers are assigned for both non-ordered and non-numbered,
1421 as an numbered set of pubs could all have redundant serial numbers.
1422 Could this cause problems if serial numbers are referenced in the feature
1423 table?????????*/
1424 if (!ordered || !numbered)
1425 {
1426 for (vnp1=vnp, index=0; vnp1; vnp1=vnp1->next)
1427 {
1428 index++;
1429 psp = vnp1->data.ptrvalue;
1430 psp->number = index;
1431 }
1432 }
1433 return vnp;
1434
1435 }
1436
cleanup_pub(ValNodePtr pub)1437 NLM_EXTERN void cleanup_pub(ValNodePtr pub)
1438 {
1439 ValNodePtr vnp;
1440
1441 for (vnp = pub; vnp; vnp=vnp->next) {
1442 FreePubStruct(vnp->data.ptrvalue);
1443
1444 }
1445 }
1446
empty_citgen(CitGenPtr cit)1447 NLM_EXTERN Boolean empty_citgen(CitGenPtr cit)
1448 {
1449 if (cit == NULL)
1450 return TRUE;
1451 if (cit->cit)
1452 return FALSE;
1453 if (cit->authors)
1454 return FALSE;
1455 if (cit->muid > 0)
1456 return FALSE;
1457 if (cit->journal)
1458 return FALSE;
1459 if (cit->volume)
1460 return FALSE;
1461 if (cit->issue)
1462 return FALSE;
1463 if (cit->pages)
1464 return FALSE;
1465 if (cit->date)
1466 return FALSE;
1467 if (cit->serial_number > 0)
1468 return FALSE;
1469 if (cit->title)
1470 return FALSE;
1471 if (cit->pmid > 0)
1472 return FALSE;
1473 return TRUE;
1474 }
1475
del_serial_number(ValNodePtr pub)1476 static ValNodePtr del_serial_number(ValNodePtr pub)
1477 {
1478 CitGenPtr cit;
1479 ValNodePtr head = NULL, next, prev = NULL;
1480
1481 while (pub != NULL)
1482 {
1483 next = pub->next;
1484 pub->next = NULL;
1485
1486 if (pub->choice == PUB_Gen) {
1487 cit = pub->data.ptrvalue;
1488 if (cit != NULL) {
1489 if (cit->serial_number != -1) {
1490 cit->serial_number = -1;
1491 }
1492 }
1493 if (empty_citgen(cit)) {
1494 PubFree(pub);
1495 pub = NULL;
1496 }
1497 }
1498 if (pub != NULL) /* still have one */
1499 {
1500 if (head == NULL)
1501 head = pub;
1502 else
1503 prev->next = pub;
1504 prev = pub;
1505 }
1506 pub = next;
1507 }
1508 return head;
1509 }
1510 /*****************************************************************************
1511 *
1512 * remove all Cit-Gen with serial numbers. Pubs will be sorted by date and
1513 * serial numbers reassigned in flat file generator
1514 *
1515 *****************************************************************************/
StripSerialNumber(SeqEntryPtr sep,Pointer data,Int4 index,Int2 indent)1516 static void StripSerialNumber (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
1517 {
1518 BioseqPtr bsp;
1519 BioseqSetPtr bssp;
1520 ValNodePtr tmp, descr;
1521 SeqAnnotPtr sap, annot;
1522 SeqFeatPtr sfp;
1523 ImpFeatPtr ifp;
1524 PubdescPtr pdp;
1525 ValNodePtr pubset, pub_e, pub;
1526
1527 if (IS_Bioseq(sep)) {
1528 bsp = (BioseqPtr)(sep->data.ptrvalue);
1529 descr = bsp->descr;
1530 annot = bsp->annot;
1531 } else {
1532 bssp = (BioseqSetPtr)(sep->data.ptrvalue);
1533 descr = bssp->descr;
1534 annot = bssp->annot;
1535 }
1536 for (tmp = descr; tmp != NULL; tmp = tmp->next) {
1537 if (tmp->choice == Seq_descr_pub) {
1538 pdp = tmp->data.ptrvalue;
1539 if (pdp != NULL) {
1540 pdp->pub = del_serial_number(pdp->pub);
1541 }
1542 }
1543 }
1544 for (sap = annot; sap != NULL; sap = sap->next) {
1545 if (sap->type != 1) {
1546 continue;
1547 }
1548 for (sfp = sap->data; sfp != NULL; sfp = sfp->next) {
1549 if (sfp->data.choice == SEQFEAT_PUB) {
1550 pdp = sfp->data.value.ptrvalue;
1551 pdp->pub = del_serial_number(pdp->pub);
1552 }
1553 if (sfp->data.choice == SEQFEAT_IMP) {
1554 ifp = sfp->data.value.ptrvalue;
1555 if (StringCmp(ifp->key,"Site-ref") == 0) {
1556 pubset = sfp->cit;
1557 pub_e = pubset->data.ptrvalue;
1558 for (; pub_e != NULL; pub_e = pub_e->next) {
1559 pub = pub_e->data.ptrvalue;
1560 pub_e->data.ptrvalue = del_serial_number(pub);
1561 }
1562 }
1563 }
1564 }
1565 }
1566 }
1567
CheckForSwissProtID(SeqEntryPtr sep,Pointer mydata,Int4 index,Int2 indent)1568 static void CheckForSwissProtID (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
1569
1570 {
1571 BioseqPtr bsp;
1572 SeqIdPtr sip;
1573 BoolPtr stripSerial;
1574
1575 if (sep == NULL) return;
1576 if (IS_Bioseq (sep)) {
1577 bsp = (BioseqPtr) sep->data.ptrvalue;
1578 if (bsp == NULL) return;
1579 stripSerial = (BoolPtr) mydata;
1580 if (stripSerial == NULL) return;
1581 for (sip = bsp->id; sip != NULL; sip = sip->next) {
1582 if (sip->choice == SEQID_SWISSPROT) {
1583 *stripSerial = FALSE;
1584 }
1585 }
1586 }
1587 }
1588
EntryStripSerialNumber(SeqEntryPtr sep)1589 NLM_EXTERN void EntryStripSerialNumber (SeqEntryPtr sep)
1590 {
1591 Boolean stripSerial = TRUE;
1592
1593 if (sep == NULL) return;
1594 SeqEntryExplore (sep, (Pointer) &stripSerial, CheckForSwissProtID);
1595 if (stripSerial) {
1596 SeqEntryExplore(sep, NULL, StripSerialNumber);
1597 }
1598 }
1599
ForceStripSerialNumber(SeqEntryPtr sep)1600 NLM_EXTERN void ForceStripSerialNumber (SeqEntryPtr sep)
1601 {
1602 if (sep == NULL) return;
1603 SeqEntryExplore(sep, NULL, StripSerialNumber);
1604 }
1605
remove_node(ValNodePtr head,ValNodePtr x)1606 NLM_EXTERN ValNodePtr remove_node(ValNodePtr head, ValNodePtr x)
1607 {
1608 ValNodePtr v, p;
1609
1610 if (head == NULL) {
1611 return NULL;
1612 }
1613 if (x == head) {
1614 head = x->next;
1615 x->next = NULL;
1616 ValNodeFree(x);
1617 return head;
1618 }
1619 for (v = head; v != NULL && v != x; v = v->next) {
1620 p = v;
1621 }
1622 if (v != NULL) {
1623 p->next = x->next;
1624 x->next = NULL;
1625 ValNodeFree(x);
1626 }
1627 return head;
1628 }
1629
remove_annot(SeqAnnotPtr head,SeqAnnotPtr x)1630 NLM_EXTERN SeqAnnotPtr remove_annot(SeqAnnotPtr head, SeqAnnotPtr x)
1631 {
1632 SeqAnnotPtr v, p;
1633
1634 if (head == NULL) {
1635 return NULL;
1636 }
1637 if (x == head) {
1638 head = x->next;
1639 x->next = NULL;
1640 SeqAnnotFree(x);
1641 return head;
1642 }
1643 for (v = head; v != NULL && v != x; v = v->next) {
1644 p = v;
1645 }
1646 if (v != NULL) {
1647 p->next = x->next;
1648 x->next = NULL;
1649 SeqAnnotFree(x);
1650 }
1651 return head;
1652 }
1653
extract_node(ValNodePtr PNTR head,ValNodePtr x)1654 NLM_EXTERN ValNodePtr extract_node(ValNodePtr PNTR head, ValNodePtr x)
1655 {
1656 ValNodePtr v, p;
1657
1658 if (*head == NULL) {
1659 return NULL;
1660 }
1661 if (x == *head) {
1662 *head = x->next;
1663 x->next = NULL;
1664 return x;
1665 }
1666 for (v = *head; v != NULL && v != x; v = v->next) {
1667 p = v;
1668 }
1669 if (v == NULL) {
1670 return NULL;
1671 }
1672 p->next = x->next;
1673 x->next = NULL;
1674 return x;
1675 }
1676
remove_feat(SeqFeatPtr head,SeqFeatPtr x)1677 NLM_EXTERN SeqFeatPtr remove_feat(SeqFeatPtr head, SeqFeatPtr x)
1678 {
1679 SeqFeatPtr v, p;
1680
1681 if (head == NULL) {
1682 return NULL;
1683 }
1684 if (x == head) {
1685 head = x->next;
1686 x->next = NULL;
1687 SeqFeatFree(x);
1688 return head;
1689 }
1690 for (v = head; v != NULL && v != x; v = v->next) {
1691 p = v;
1692 }
1693 if (v != NULL) {
1694 p->next = x->next;
1695 x->next = NULL;
1696 SeqFeatFree(x);
1697 }
1698 return head;
1699 }
1700
1701
1702 /***************************************************************************
1703 * qvalue_extract:
1704 * -- return qual's value if found the "qual" in the "qlist", and remove
1705 * the "qual" from the qlist; Otherwise, return NULL
1706 ***************************************************************************/
qvalue_extract(GBQualPtr PNTR qlist,CharPtr qual)1707 NLM_EXTERN CharPtr qvalue_extract(GBQualPtr PNTR qlist, CharPtr qual)
1708 {
1709 GBQualPtr curq, preq;
1710 CharPtr qvalue = NULL;
1711
1712 for (preq = NULL, curq = *qlist; curq != NULL; curq = curq->next) {
1713 if (StringCmp(curq->qual, qual) == 0) {
1714 if (preq == NULL)
1715 preq = *qlist = curq->next;
1716 else
1717 preq->next = curq->next;
1718
1719 curq->next = NULL;
1720 qvalue = StringSave(curq->val);
1721
1722 GBQualFree(curq);
1723 curq = NULL;
1724
1725 return (qvalue);
1726 }
1727
1728 preq = curq;
1729 }
1730
1731 return (qvalue);
1732
1733 }
1734