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