NCBI C Toolkit Cross Reference

C/api/asn2gnb5.c


  1 /*   asn2gnb5.c
  2 * ===========================================================================
  3 *
  4 *                            PUBLIC DOMAIN NOTICE
  5 *            National Center for Biotechnology Information (NCBI)
  6 *
  7 *  This software/database is a "United States Government Work" under the
  8 *  terms of the United States Copyright Act.  It was written as part of
  9 *  the author's official duties as a United States Government employee and
 10 *  thus cannot be copyrighted.  This software/database is freely available
 11 *  to the public for use. The National Library of Medicine and the U.S.
 12 *  Government do not place any restriction on its use or reproduction.
 13 *  We would, however, appreciate having the NCBI and the author cited in
 14 *  any work or product based on this material
 15 *
 16 *  Although all reasonable efforts have been taken to ensure the accuracy
 17 *  and reliability of the software and data, the NLM and the U.S.
 18 *  Government do not and cannot warrant the performance or results that
 19 *  may be obtained by using this software or data. The NLM and the U.S.
 20 *  Government disclaim all warranties, express or implied, including
 21 *  warranties of performance, merchantability or fitness for any particular
 22 *  purpose.
 23 *
 24 * ===========================================================================
 25 *
 26 * File Name:  asn2gnb5.c
 27 *
 28 * Author:  Karl Sirotkin, Tom Madden, Tatiana Tatusov, Jonathan Kans,
 29 *          Mati Shomrat
 30 *
 31 * Version Creation Date:   10/21/98
 32 *
 33 * $Revision: 1.164 $
 34 *
 35 * File Description:  New GenBank flatfile generator - work in progress
 36 *
 37 * Modifications:
 38 * --------------------------------------------------------------------------
 39 * ==========================================================================
 40 */
 41 
 42 #include <ncbi.h>
 43 #include <objall.h>
 44 #include <objsset.h>
 45 #include <objsub.h>
 46 #include <objfdef.h>
 47 #include <objpubme.h>
 48 #include <seqport.h>
 49 #include <sequtil.h>
 50 #include <sqnutils.h>
 51 #include <subutil.h>
 52 #include <tofasta.h>
 53 #include <explore.h>
 54 #include <gbfeat.h>
 55 #include <gbftdef.h>
 56 #include <edutil.h>
 57 #include <alignmgr2.h>
 58 #include <asn2gnbi.h>
 59 
 60 #ifdef WIN_MAC
 61 #if __profile__
 62 #include <Profiler.h>
 63 #endif
 64 #endif
 65 
 66 /* URLs */
 67 
 68 
 69 static CharPtr link_muid = "http://www.ncbi.nlm.nih.gov/pubmed/";
 70 
 71 static CharPtr link_uspto = "http://patft.uspto.gov/netacgi/nph-Parser?patentnumber=";
 72 
 73 static CharPtr link_cambia = "http://www.patentlens.net/patentlens/simple.cgi?patnum=";
 74 
 75 
 76 
 77 /* www utility functions */
 78 
 79 NLM_EXTERN Boolean GetWWW (IntAsn2gbJobPtr ajp) {
 80     return ajp->www;
 81 }
 82 
 83 NLM_EXTERN void FiniWWW (IntAsn2gbJobPtr ajp) {
 84     ajp->www = FALSE;
 85 }
 86 
 87 NLM_EXTERN void InitWWW (IntAsn2gbJobPtr ajp)
 88 {
 89   ajp->www = TRUE;
 90 }
 91 
 92 NLM_EXTERN void FF_www_featloc(StringItemPtr ffstring, CharPtr loc)
 93 {
 94   CharPtr ptr;
 95 
 96   if (loc == NULL) return;
 97 
 98   for ( ptr = loc; *ptr != '\0'; ++ptr ) {
 99     switch (*ptr) {
100     case '<' :
101       /*FFAddOneString (ffstring, "<", FALSE, FALSE, TILDE_IGNORE);*/
102       FFAddOneString (ffstring, "&lt;", FALSE, FALSE, TILDE_IGNORE);
103       break;
104     case '>' :
105       /*FFAddOneString (ffstring, ">", FALSE, FALSE, TILDE_IGNORE);*/
106       FFAddOneString (ffstring, "&gt;", FALSE, FALSE, TILDE_IGNORE);
107       break;
108     default:
109       FFAddOneChar(ffstring, *ptr, FALSE);
110       break;
111     }
112   }
113 }
114 
115 
116 /* ************** */
117 
118 typedef struct dbxrefurldata {
119   CharPtr  tag;
120   CharPtr  url;
121 } UrlData, PNTR UrlDataPtr;
122 
123 static UrlData Nlm_url_base [] = {
124   {"AceView/WormGenes",     "http://www.ncbi.nlm.nih.gov/IEB/Research/Acembly/av.cgi?db=worm&c=gene&q="},
125   {"AFTOL",                 "http://aftol1.biology.duke.edu/pub/displayTaxonInfo?aftol_id="},
126   {"AntWeb",                "http://www.antweb.org/specimen.do?name="},
127   {"APHIDBASE",             "http://webapps1.genouest.org/grs-1.0/grs?reportID=chado_genome_report&objectID="},
128   {"ApiDB",                 "http://www.apidb.org/apidb/showRecord.do?name=GeneRecordClasses.ApiDBGeneRecordClass&primary_key="},
129   {"ApiDB_CryptoDB",        "http://cryptodb.org/cryptodb/showRecord.do?name=GeneRecordClasses.GeneRecordClass&project_id=&primary_key="},
130   {"ApiDB_PlasmoDB",        "http://www.plasmodb.org/plasmo/showRecord.do?name=GeneRecordClasses.GeneRecordClass&project_id=&primary_key="},
131   {"ApiDB_ToxoDB",          "http://www.toxodb.org/toxo/showRecord.do?name=GeneRecordClasses.GeneRecordClass&project_id=&primary_key="},
132   {"ASAP",                  "https://asap.ahabs.wisc.edu/annotation/php/feature_info.php?FeatureID="},
133   {"ATCC",                  "http://www.atcc.org/SearchCatalogs/linkin?id="},
134   {"Axeldb",                "http://www.dkfz-heidelberg.de/tbi/services/axeldb/clone/xenopus?name="},
135   {"BEETLEBASE",            "http://www.beetlebase.org/cgi-bin/report.cgi?name="},
136   {"BOLD",                  "http://www.boldsystems.org/connectivity/specimenlookup.php?processid="},
137   {"CCDS",                  "http://www.ncbi.nlm.nih.gov/CCDS/CcdsBrowse.cgi?REQUEST=CCDS&DATA="},
138   {"CDD",                   "http://www.ncbi.nlm.nih.gov/Structure/cdd/cddsrv.cgi?uid="},
139   {"CK",                    "http://flybane.berkeley.edu/cgi-bin/cDNA/CK_clone.pl?db=CK&dbid="},
140   {"COG",                   "http://www.ncbi.nlm.nih.gov/COG/new/release/cow.cgi?cog="},
141   {"dbClone",               "http://www.ncbi.nlm.nih.gov/sites/entrez?db=clone&cmd=Retrieve&list_uids="},
142   {"dbCloneLib",            "http://www.ncbi.nlm.nih.gov/sites/entrez?db=clonelib&cmd=Retrieve&list_uids="},
143   {"dbEST",                 "http://www.ncbi.nlm.nih.gov/nucest/"},
144   {"dbProbe",               "http://www.ncbi.nlm.nih.gov/sites/entrez?db=probe&cmd=Retrieve&list_uids="},
145   {"dbSNP",                 "http://www.ncbi.nlm.nih.gov/SNP/snp_ref.cgi?type=rs&rs="},
146   {"dbSTS",                 "http://www.ncbi.nlm.nih.gov/nuccore/"},
147   {"dictyBase",             "http://dictybase.org/db/cgi-bin/gene_page.pl?dictybaseid="},
148   {"ECOCYC",                "http://biocyc.org/ECOLI/new-image?type=GENE&object="},
149   {"EcoGene",               "http://ecogene.org/geneInfo.php?eg_id="},
150   {"ERIC",                  "http://www.ericbrc.org/genbank/dbxref/"},
151   {"FANTOM_DB",             "http://fantom.gsc.riken.jp/db/annotate/main.cgi?masterid="},
152   {"FLYBASE",               "http://flybase.bio.indiana.edu/.bin/fbidq.html?"},
153   {"GABI",                  "http://www.gabipd.org/database/cgi-bin/GreenCards.pl.cgi?Mode=ShowSequence&App=ncbi&SequenceId="},
154   {"GeneDB",                "http://www.genedb.org/genedb/Dispatcher?formType=navBar&submit=Search+for&organism=All%3Apombe%3Acerevisiae%3Adicty%3Aasp%3Atryp%3Aleish%3Amalaria%3Astyphi%3Aglossina&desc=yes&ohmr=%2F&name="},
155   {"GeneID",                "http://www.ncbi.nlm.nih.gov/sites/entrez?db=gene&cmd=Retrieve&dopt=full_report&list_uids="},
156   {"GO",                    "http://amigo.geneontology.org/cgi-bin/amigo/go.cgi?view=details&depth=1&query=GO:"},
157   {"GOA",                   "http://www.ebi.ac.uk/ego/GProtein?ac="},
158   {"Greengenes",            "http://greengenes.lbl.gov/cgi-bin/show_one_record_v2.pl?prokMSA_id="},
159   {"GRIN",                  "http://www.ars-grin.gov/cgi-bin/npgs/acc/display.pl?"},
160   {"H-InvDB",               "http://www.h-invitational.jp"},
161   {"HGNC",                  "http://www.genenames.org/data/hgnc_data.php?hgnc_id="},
162   {"HMP",                   "http://www.hmpdacc-resources.org/cgi-bin/hmp_catalog/main.cgi?section=HmpSummary&page=displayHmpProject&hmp_id="},
163   {"HOMD",                  "http://www.homd.org/"},
164   {"HPRD",                  "http://www.hprd.org/protein/"},
165   {"HSSP",                  "http://srs.ebi.ac.uk/srsbin/cgi-bin/wgetz?-newId+-e+hssp-ID:"},
166   {"IMGT/GENE-DB",          "http://imgt.cines.fr/cgi-bin/GENElect.jv?species=Homo+sapiens&query=2+"},
167   {"IMGT/LIGM",             "http://imgt.cines.fr:8104/cgi-bin/IMGTlect.jv?query=202+"},
168   {"InterimID",             "http://www.ncbi.nlm.nih.gov/LocusLink/LocRpt.cgi?l="},
169   {"InterPro",              "http://www.ebi.ac.uk/interpro/ISearch?mode=ipr&query="},
170   {"IRD",                   "http://www.fludb.org/brc/fluSegmentDetails.do?irdSubmissionId="},
171   {"ISD",                   "http://www.flu.lanl.gov/search/view_record.html?accession="},
172   {"ISFinder",              "http://www-is.biotoul.fr/scripts/is/is_spec.idc?name="},
173   {"JCM",                   "http://www.jcm.riken.go.jp/cgi-bin/jcm/jcm_number?JCM="},
174   {"JGIDB",                 "http://genome.jgi-psf.org/cgi-bin/jgrs?id="},
175   {"LocusID",               "http://www.ncbi.nlm.nih.gov/LocusLink/LocRpt.cgi?l="},
176   {"MaizeGDB",              "http://www.maizegdb.org/cgi-bin/displaylocusrecord.cgi?id="},
177   {"MGI",                   "http://www.informatics.jax.org/searches/accession_report.cgi?id=MGI:"},
178   {"MIM",                   "http://www.ncbi.nlm.nih.gov/entrez/dispomim.cgi?id="},
179   {"miRBase",               "http://microrna.sanger.ac.uk/cgi-bin/sequences/mirna_entry.pl?acc="},
180   {"MycoBank",              "http://www.mycobank.org/MycoTaxo.aspx?Link=T&Rec="},
181   {"NBRC",                  "http://www.nbrc.nite.go.jp/NBRC2/NBRCCatalogueDetailServlet?ID=NBRC&CAT="},
182   {"NextDB",                "http://nematode.lab.nig.ac.jp/cgi-bin/db/ShowGeneInfo.sh?celk="},
183   {"niaEST",                "http://lgsun.grc.nia.nih.gov/cgi-bin/pro3?sname1="},
184   {"NMPDR",                 "http://www.nmpdr.org/linkin.cgi?id="},
185   {"NRESTdb",               "http://genome.ukm.my/nrestdb/db/single_view_est.php?id="},
186   {"Osa1",                  "http://rice.plantbiology.msu.edu/cgi-bin/gbrowse/rice/?name="},
187   {"Pathema",               "http://pathema.jcvi.org/cgi-bin/Burkholderia/shared/GenePage.cgi?all=1&locus="},
188   {"PBmice",                "http://www.idmshanghai.cn/PBmice/DetailedSearch.do?type=insert&id="},
189   {"PBR",                   "http://www.poxvirus.org/query.asp?web_id="},
190   {"PDB",                   "http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId="},
191   {"PFAM",                  "http://pfam.sanger.ac.uk/family?acc="},
192   {"PGN",                   "http://pgn.cornell.edu/cgi-bin/search/seq_search_result.pl?identifier="},
193   {"PseudoCap",             "http://www.pseudomonas.com/getAnnotation.do?locusID="},
194   {"RAP-DB",                "http://rapdb.dna.affrc.go.jp/cgi-bin/gbrowse_details/latest?name="},
195   {"RATMAP",                "http://ratmap.gen.gu.se/ShowSingleLocus.htm?accno="},
196   {"REBASE",                "http://rebase.neb.com/rebase/enz/"},
197   {"RFAM",                  "http://www.sanger.ac.uk/cgi-bin/Rfam/getacc?"},
198   {"RGD",                   "http://rgd.mcw.edu/query/query.cgi?id="},
199   {"RiceGenes",             "http://ars-genome.cornell.edu/cgi-bin/WebAce/webace?db=ricegenes&class=Marker&object="},
200   {"SEED",                  "http://www.theseed.org/linkin.cgi?id="},
201   {"SGD",                   "http://db.yeastgenome.org/cgi-bin/SGD/locus.pl?locus="},
202   {"SGN",                   "http://www.sgn.cornell.edu/search/est.pl?request_type=7&request_id="},
203   {"SK-FST",                "http://aafc-aac.usask.ca/fst/"},
204   {"SubtiList",             "http://genolist.pasteur.fr/SubtiList/genome.cgi?external_query+"},
205   {"TAIR",                  "http://www.arabidopsis.org/servlets/TairObject?type=locus&name="},
206   {"taxon",                 "http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?"},
207   {"TIGRFAM",               "http://cmr.tigr.org/tigr-scripts/CMR/HmmReport.cgi?hmm_acc="},
208   {"UniGene",               "http://www.ncbi.nlm.nih.gov/sites/entrez?Db=unigene&Cmd=Search&Term="},
209   {"UniProtKB/Swiss-Prot",  "http://www.uniprot.org/uniprot/"},
210   {"UniProtKB/TrEMBL",      "http://www.uniprot.org/uniprot/"},
211   {"UniSTS",                "http://www.ncbi.nlm.nih.gov/genome/sts/sts.cgi?uid="},
212   {"UNITE",                 "http://unite.ut.ee/bl_forw.php?nimi="},
213   {"VBASE2",                "http://www.dnaplot.de/vbase2/vgene.php?id="},
214   {"VBRC",                  "http://vbrc.org/query.asp?web_view=curation&web_id="},
215   {"VectorBase",            "http://www.vectorbase.org/Genome/BRCGene/?feature="},
216   {"WorfDB",                "http://worfdb.dfci.harvard.edu/search.pl?form=1&search="},
217   {"WormBase",              "http://www.wormbase.org/db/gene/gene?class=CDS;name="},
218   {"Xenbase",               "http://www.xenbase.org/gene/showgene.do?method=display&geneId="},
219   {"ZFIN",                  "http://zfin.org/cgi-bin/webdriver?MIval=aa-markerview.apg&OID="},
220 };
221 
222 static Int2 DbNameIsValid (
223   CharPtr db
224 )
225 
226 {
227   Int2  L, R, mid;
228 
229   if (StringHasNoText (db)) return -1;
230 
231   L = 0;
232   R = sizeof (Nlm_url_base) / sizeof (Nlm_url_base [0]);
233 
234   while (L < R) {
235     mid = (L + R) / 2;
236     if (StringICmp (Nlm_url_base [mid].tag, db) < 0) {
237       L = mid + 1;
238     } else {
239       R = mid;
240     }
241   }
242 
243   /* case sensitive comparison at end enforces strictness */
244 
245   if (StringCmp (Nlm_url_base [R].tag, db) == 0) {
246     return R;
247   }
248 
249   return -1;
250 }
251 
252 static void FF_www_get_url (
253   StringItemPtr ffstring,
254   CharPtr db,
255   CharPtr identifier,
256   BioseqPtr bsp
257 )
258 
259 {
260   CharPtr  base = NULL, prefix = NULL, profix = NULL, ident = NULL, suffix = NULL, url = NULL, ptr, str;
261   Char     ch, buf [128], id [20], taxname [128];
262   /*
263   Boolean  is_numeric;
264   */
265   Int2     R;
266 
267   if (ffstring == NULL || StringHasNoText (db) || StringHasNoText (identifier)) return;
268 
269   while (*identifier == ' ') {
270     identifier++;
271   }
272   ident = identifier;
273 
274   R = DbNameIsValid (db);
275   if (R < 0) {
276     FFAddOneString (ffstring, identifier, FALSE, FALSE, TILDE_IGNORE);
277     return;
278   }
279 
280   url = Nlm_url_base [R].url;
281 
282   /* NCBI URL can be overridden by configuration file */
283 
284   if (StringNICmp (url, "http://www.ncbi.nlm.nih.gov/", 28) == 0) {
285     if (GetAppParam ("NCBI", "WWWENTREZ", "NCBI_URL_BASE", NULL, buf, sizeof (buf))) {
286       if (StringDoesHaveText (buf)) {
287         base = buf;
288         url += 28;
289       }
290     }
291   }
292 
293   /* special cases */
294 
295 
296   if (StringCmp (db, "IRD") == 0) {
297 
298     suffix = "&decorator=influenza";
299 
300   } else if (StringCmp (db, "dbSTS") == 0) {
301 
302     /*
303     is_numeric = TRUE;
304     str = identifier;
305     ch = *str;
306     while (ch != '\0') {
307       if (! IS_DIGIT (ch)) {
308         is_numeric = FALSE;
309       }
310       str++;
311       ch = *str;
312     }
313 
314     if (is_numeric) {
315       prefix = "val=gnl|dbsts|";
316     } else if (ValidateAccn (identifier) == 0) {
317       prefix = "val=";
318     } else {
319       FFAddOneString (ffstring, identifier, FALSE, FALSE, TILDE_IGNORE);
320       return;
321     }
322     */
323 
324   } else if (StringCmp (db, "FLYBASE") == 0) {
325 
326     if (StringStr (identifier, "FBa") != NULL ) {
327       url = "http://www.fruitfly.org/cgi-bin/annot/fban?";
328     }
329 
330   } else if (StringCmp (db, "dictyBase") == 0) {
331 
332     if (StringChr (identifier, '_') != NULL) {
333       url = "http://dictybase.org/db/cgi-bin/gene_page.pl?primary_id=";
334     }
335 
336   } else if (StringCmp (db, "GDB") == 0) {
337 
338     str = StringStr (identifier, "G00-");
339     if (str != NULL) {
340       ptr = id;
341       str += 4;
342       ch = *str;
343       while (ch != '\0') {
344         if (ch != '-') {
345           *ptr = ch;
346           ptr++;
347         }
348         str++;
349         ch = *str;
350       }
351       *ptr = '\0';
352       ident = id;
353     } else {
354       ch = *identifier;
355       if (! IS_DIGIT (ch)) {
356         FFAddOneString (ffstring, identifier, FALSE, FALSE, TILDE_IGNORE);
357         return;
358       }
359     }
360 
361   } else if (StringCmp (db, "H_InvDB") == 0) {
362 
363     if (StringStr (identifier, "HIT") != NULL) {
364       url = "http://www.jbirc.aist.go.jp/hinv/hinvsys/servlet/ExecServlet?KEN_INDEX=0&KEN_TYPE=30&KEN_STR=";
365     } else if (StringStr (identifier, "HIX") != NULL) {
366       url = "http://www.jbirc.aist.go.jp/hinv/hinvsys/servlet/ExecServlet?KEN_INDEX=0&KEN_TYPE=31&KEN_STR=";
367     }
368 
369 
370   } else if (StringCmp (db, "HOMD") == 0) {
371 
372     if (StringStr (identifier, "tax_") != NULL ) {
373       url = "http://www.homd.org/taxon=";
374       ident += 4;
375     } else if (StringStr (identifier, "seq_") != NULL ) {
376       url = "http://www.homd.org/seq=";
377       ident += 4;
378     }
379 
380   } else if (StringCmp (db, "IMGT/GENE-DB") == 0) {
381 
382     if (bsp != NULL && BioseqToGeneticCode (bsp, NULL, NULL, NULL, taxname, sizeof (taxname), NULL)) {
383       if (StringCmp (taxname, "Homo sapiens") == 0) {
384         url = "http://imgt.cines.fr/cgi-bin/GENElect.jv?species=Homo+sapiens&query=2+";
385       }
386       if (StringCmp (taxname, "Mus musculus") == 0) {
387         url = "http://imgt.cines.fr/cgi-bin/GENElect.jv?species=Mus+musculus&query=2+";
388       }
389     }
390 
391   } else if (StringCmp (db, "niaEST") == 0) {
392 
393     suffix = "&val=1";
394 
395   } else if (StringCmp (db, "RAP-DB") == 0) {
396 
397     suffix = ";class=locus_id";
398 
399   } else if (StringCmp (db, "REBASE") == 0) {
400 
401     suffix = ".html";
402 
403   } else if (StringCmp (db, "SK-FST") == 0) {
404 
405     ident = NULL;
406 
407   } else if (StringCmp (db, "taxon") == 0) {
408 
409     ch = *identifier;
410     if (IS_DIGIT (ch)) {
411       prefix = "id=";
412     } else {
413       prefix = "name=";
414     }
415 
416   }
417 
418   /* now generate URL */
419 
420   FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
421   if (StringDoesHaveText (base)) {
422     FFAddOneString (ffstring, base, FALSE, FALSE, TILDE_IGNORE);
423   }
424   FFAddOneString (ffstring, url, FALSE, FALSE, TILDE_IGNORE);
425   if (StringDoesHaveText (prefix)) {
426     FFAddOneString (ffstring, prefix, FALSE, FALSE, TILDE_IGNORE);
427   }
428   if (StringDoesHaveText (profix)) {
429     FFAddOneString (ffstring, profix, FALSE, FALSE, TILDE_IGNORE);
430   }
431   if (StringDoesHaveText (ident)) {
432     FFAddOneString (ffstring, ident, FALSE, FALSE, TILDE_IGNORE);
433   }
434   if (StringDoesHaveText (suffix)) {
435     FFAddOneString (ffstring, suffix, FALSE, FALSE, TILDE_IGNORE);
436   }
437   FFAddTextToString (ffstring, "\">", identifier, "</a>", FALSE, FALSE, TILDE_IGNORE);
438 }
439 
440 NLM_EXTERN void FF_www_db_xref (
441   IntAsn2gbJobPtr ajp,
442   StringItemPtr ffstring,
443   CharPtr db,
444   CharPtr identifier,
445   BioseqPtr bsp
446 )
447 {
448   if (ffstring == NULL || StringHasNoText (db) || StringHasNoText (identifier)) return;
449 
450   if (GetWWW (ajp)) {
451     FFAddTextToString (ffstring, db, ":", NULL, FALSE, FALSE, TILDE_IGNORE);
452     FF_www_get_url (ffstring, db, identifier, bsp);
453   } else {
454     FFAddTextToString (ffstring, db, ":", identifier, FALSE, FALSE, TILDE_IGNORE);
455   }
456 }
457 
458 NLM_EXTERN void FF_Add_NCBI_Base_URL (
459   StringItemPtr ffstring,
460   CharPtr url
461 )
462 
463 {
464   CharPtr  base = NULL;
465   Char     buf [128];
466 
467   if (ffstring == NULL || StringHasNoText (url)) return;
468 
469   /* NCBI URL can be overridden by configuration file */
470 
471   if (StringNICmp (url, "http://www.ncbi.nlm.nih.gov/", 28) == 0) {
472     if (GetAppParam ("NCBI", "WWWENTREZ", "NCBI_URL_BASE", NULL, buf, sizeof (buf))) {
473       if (StringDoesHaveText (buf)) {
474         base = buf;
475         url += 28;
476       }
477     }
478   }
479 
480   if (StringDoesHaveText (base)) {
481     FFAddOneString (ffstring, base, FALSE, FALSE, TILDE_IGNORE);
482   }
483   FFAddOneString (ffstring, url, FALSE, FALSE, TILDE_IGNORE);
484 }
485 
486 
487 /* ************** */
488 
489 
490 /* public function to get URLs for collaboration-approved db_xrefs */
491 
492 static Boolean links_loaded = FALSE;
493 
494 NLM_EXTERN CharPtr asn2gnbk_dbxref (
495   DbtagPtr dbt
496 )
497 
498 {
499   IntAsn2gbJobPtr  ajp;
500   Char             buf [80];
501   StringItemPtr    ffstring;
502   ObjectIdPtr      oip;
503   CharPtr          ptr;
504   CharPtr          str;
505   CharPtr          tmp;
506 
507   if (dbt == NULL) return NULL;
508   if (StringHasNoText (dbt->db)) return NULL;
509   oip = dbt->tag;
510   if (oip == NULL) return NULL;
511 
512   if (! StringHasNoText (oip->str)) {
513     if (StringLen (dbt->db) + StringLen (oip->str) < 80) {
514       sprintf (buf, "%s", oip->str);
515     }
516   } else {
517     sprintf (buf, "%ld", (long) oip->id);
518   }
519 
520   ajp = (IntAsn2gbJobPtr) MemNew (sizeof (IntAsn2gbJob));
521   if (ajp == NULL) return NULL;
522   ffstring = FFGetString (ajp);
523   if ( ffstring == NULL ) return NULL;
524 
525   if (! links_loaded) {
526     InitWWW (ajp);
527     links_loaded = TRUE;
528   }
529   ajp->www = TRUE;
530 
531   FF_www_db_xref (ajp, ffstring, dbt->db, buf, NULL);
532 
533   ajp->www = FALSE;
534 
535   str = FFToCharPtr (ffstring);
536 
537   FFRecycleString (ajp, ffstring);
538   /*
539   MemFree (ajp);
540   */
541   asn2gnbk_cleanup ((Asn2gbJobPtr) ajp);
542 
543   tmp = StringChr (str, '<');
544   if (tmp != NULL) {
545     ptr = StringSave (tmp);
546     tmp = StringChr (ptr, '>');
547     if (tmp != NULL) {
548       tmp++;
549       *tmp = '\0';
550     }
551     MemFree (str);
552     str = ptr;
553   } else {
554     str = MemFree (str);
555   }
556 
557   return str;
558 }
559 
560 /* format references section */
561 
562 NLM_EXTERN AuthListPtr GetAuthListPtr (
563   PubdescPtr pdp,
564   CitSubPtr csp
565 )
566 
567 {
568   AuthListPtr  alp = NULL;
569   CitArtPtr    cap;
570   CitBookPtr   cbp;
571   CitGenPtr    cgp;
572   CitPatPtr    cpp;
573   ValNodePtr   vnp;
574 
575   if (csp != NULL) {
576     alp = csp->authors;
577     if (alp != NULL) return alp;
578   }
579   if (pdp == NULL) return NULL;
580 
581   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
582     switch (vnp->choice) {
583       case PUB_Gen :
584         cgp = (CitGenPtr) vnp->data.ptrvalue;
585         if (cgp != NULL) {
586           alp = cgp->authors;
587         }
588         break;
589       case PUB_Sub :
590         csp = (CitSubPtr) vnp->data.ptrvalue;
591         if (csp != NULL) {
592           alp = csp->authors;
593         }
594         break;
595       case PUB_Article :
596         cap = (CitArtPtr) vnp->data.ptrvalue;
597         if (cap != NULL) {
598           alp = cap->authors;
599         }
600         break;
601       case PUB_Book :
602       case PUB_Proc :
603       case PUB_Man :
604         cbp = (CitBookPtr) vnp->data.ptrvalue;
605         if (cbp != NULL) {
606           alp = cbp->authors;
607         }
608         break;
609       case PUB_Patent :
610         cpp = (CitPatPtr) vnp->data.ptrvalue;
611         if (cpp != NULL) {
612           alp = cpp->authors;
613         }
614         break;
615       default :
616         break;
617     }
618 
619     if (alp != NULL) return alp;
620   }
621 
622   return NULL;
623 }
624 
625 static CharPtr MakeSingleAuthorString (
626   FmtType format,
627   CharPtr prefix,
628   CharPtr name,
629   CharPtr initials,
630   CharPtr suffix,
631   IndxPtr index,
632   GBReferencePtr gbref
633 )
634 
635 {
636   Char     ch;
637   Char     dummy [10];
638   size_t   len;
639   CharPtr  nametoindex;
640   CharPtr  ptr;
641   CharPtr  str;
642   CharPtr  tmp;
643 
644   if (name == NULL) return NULL;
645 
646   /* !!! clean up 'et al' as (presumably) last author !!! */
647 
648   /* !!! temporary to suppress diff !!! */
649   {
650   if (StringLen (name) <= 6 &&
651       (StringNICmp (name, "et al", 5) == 0 || StringNICmp (name, "et,al", 5) == 0)) {
652     if (StringCmp (prefix, " and ") == 0) {
653       prefix = NULL;
654       dummy [0] = ' ';
655       StringNCpy_0 (dummy + 1, name, sizeof (dummy) - 1);
656       name = dummy;
657     }
658   }
659   }
660   /*
661   if (StringLen (name) <= 6 &&
662       (StringNICmp (name, "et al", 5) == 0 || StringNICmp (name, "et,al", 5) == 0)) {
663     name = "et al.";
664     if (StringCmp (prefix, " and ") == 0) {
665       prefix = ", ";
666     }
667   }
668   */
669 
670   len = StringLen (name) + StringLen (initials) + StringLen (suffix) + StringLen (prefix);
671   str = MemNew (sizeof (Char) * (len + 4));
672   if (str == NULL) return NULL;
673 
674   ptr = str;
675   if (! StringHasNoText (prefix)) {
676     ptr = StringMove (ptr, prefix);
677   }
678   nametoindex = ptr;
679 
680   /* initials and suffix to support structured name fields */
681 
682   tmp = StringMove (ptr, name);
683   if (! StringHasNoText (initials)) {
684     tmp = StringMove (tmp, ",");
685     tmp = StringMove (tmp, initials);
686   }
687   if (! StringHasNoText (suffix)) {
688     tmp = StringMove (tmp, " ");
689     tmp = StringMove (tmp, suffix);
690   }
691 
692   /* optionally populate indexes for NCBI internal database */
693 
694   if (index != NULL) {
695     ValNodeCopyStrToHead (&(index->authors), 0, nametoindex);
696   }
697 
698   /* optionally populate gbseq for XML-ized GenBank format */
699 
700   if (gbref != NULL) {
701     ValNodeCopyStr (&(gbref->authors), 0, nametoindex);
702   }
703 
704   /* if embl, remove commas in individual names, starting after prefix */
705 
706   if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
707     tmp = ptr;
708     ch = *tmp;
709     while (ch != '\0') {
710       if (ch == ',') {
711         *tmp = ' ';
712       }
713       tmp++;
714       ch = *tmp;
715     }
716   }
717 
718   return str;
719 }
720 
721 NLM_EXTERN CharPtr GetAuthorsString (
722   FmtType format,
723   AuthListPtr alp,
724   CharPtr PNTR consortP,
725   IndxPtr index,
726   GBReferencePtr gbref
727 )
728 
729 {
730   AuthorPtr    ap;
731   ValNodePtr   clist;
732   ValNodePtr   conslist;
733   Int2         count;
734   ValNodePtr   head = NULL;
735   ValNodePtr   names;
736   ValNodePtr   next;
737   NameStdPtr   nsp;
738   PersonIdPtr  pid;
739   ValNodePtr   pidlist;
740   CharPtr      prefix = NULL;
741   CharPtr      str;
742   ValNodePtr   vnp;
743 
744   if (alp == NULL) return NULL;
745 
746   /*
747   alp = AsnIoMemCopy ((Pointer) alp,
748                       (AsnReadFunc) AuthListAsnRead,
749                       (AsnWriteFunc) AuthListAsnWrite);
750   if (alp == NULL) return NULL;
751   */
752 
753   count = 0;
754   if (alp->choice == 1) {
755 
756     pidlist = NULL;
757     conslist = NULL;
758 
759     for (names = alp->names; names != NULL; names = names->next) {
760       ap = (AuthorPtr) names->data.ptrvalue;
761       if (ap == NULL) continue;
762       pid = ap->name;
763       if (pid == NULL) continue;
764       if (pid->choice == 2 || pid->choice == 3 || pid->choice == 4) {
765         ValNodeAddPointer (&pidlist, 0, (Pointer) pid);
766       } else if (pid->choice == 5) {
767         ValNodeAddPointer (&conslist, 0, (Pointer) pid);
768       }
769     }
770 
771     for (vnp = pidlist; vnp != NULL; vnp = vnp->next) {
772       next = vnp->next;
773       if (next == NULL) {
774         if (format == GENBANK_FMT || format == GENPEPT_FMT) {
775           if (count == 0) {
776             prefix = NULL;
777           } else {
778             prefix = " and ";
779           }
780         }
781       }
782       str = NULL;
783       pid = (PersonIdPtr) vnp->data.ptrvalue;
784       if (pid->choice == 2) {
785         nsp = (NameStdPtr) pid->data;
786         if (nsp != NULL) {
787           if (! StringHasNoText (nsp->names [0])) {
788             str = MakeSingleAuthorString (format, prefix, nsp->names [0], nsp->names [4], nsp->names [5], index, gbref);
789           } else if (! StringHasNoText (nsp->names [3])) {
790             str = MakeSingleAuthorString (format, prefix, nsp->names [3], NULL, NULL, index, gbref);
791           }
792         }
793       } else if (pid->choice == 3 || pid->choice == 4) {
794         str = MakeSingleAuthorString (format, prefix, (CharPtr) pid->data, NULL, NULL, index, gbref);
795       }
796       if (str != NULL) {
797         ValNodeAddStr (&head, 0, str);
798         count++;
799       }
800       prefix = ", ";
801     }
802 
803     prefix = NULL;
804     clist = NULL;
805     for (vnp = conslist; vnp != NULL; vnp = vnp->next) {
806       str = NULL;
807       pid = (PersonIdPtr) vnp->data.ptrvalue;
808       if (pid->choice == 5) {
809         str = MakeSingleAuthorString (format, prefix, (CharPtr) pid->data, NULL, NULL, index, NULL);
810         if (str != NULL) {
811           ValNodeAddStr (&clist, 0, str);
812         }
813         prefix = "; ";
814       }
815     }
816     if (clist != NULL) {
817       str = MergeFFValNodeStrs (clist);
818       if ((! StringHasNoText (str)) && consortP != NULL && *consortP == NULL) {
819         *consortP = StringSave (str);
820       }
821 
822       /* optionally populate gbseq for XML-ized GenBank format */
823 
824       if (gbref != NULL) {
825         gbref->consortium = StringSave (str);
826       }
827 
828       str = MemFree (str);
829       ValNodeFreeData (clist);
830     }
831 
832     ValNodeFree (pidlist);
833     ValNodeFree (conslist);
834 
835   } else if (alp->choice == 2 || alp->choice == 3) {
836     for (vnp = alp->names; vnp != NULL; vnp = vnp->next) {
837       next = vnp->next;
838       if (next == NULL) {
839         if (format == GENBANK_FMT || format == GENPEPT_FMT) {
840           if (count == 0) {
841             prefix = NULL;
842           } else {
843             prefix = " and ";
844           }
845         }
846       }
847       str = MakeSingleAuthorString (format, prefix, (CharPtr) vnp->data.ptrvalue, NULL, NULL, index, gbref);
848       if (str != NULL) {
849         ValNodeAddStr (&head, 0, str);
850         count++;
851       }
852       prefix = ", ";
853     }
854   }
855 
856   str = MergeFFValNodeStrs (head);
857 
858   ValNodeFreeData (head);
859 
860   /*
861   AuthListFree (alp);
862   */
863 
864   return str;
865 }
866 
867 /*
868 Strips all spaces in string in following manner. If the function
869 meet several spaces (spaces and tabs) in succession it replaces them
870 with one space. Strips all spaces after '(' and before ')'
871 */
872 
873 static void StrStripSpaces (
874   CharPtr str
875 )
876 
877 {
878   CharPtr  new_str;
879 
880   if (str == NULL) return;
881 
882   new_str = str;
883   while (*str != '\0') {
884     *new_str++ = *str;
885     if (*str == ' ' || *str == '\t' || *str == '(') {
886       for (str++; *str == ' ' || *str == '\t'; str++) continue;
887       if (*str == ')' || *str == ',') {
888         new_str--;
889       }
890     } else {
891       str++;
892     }
893   }
894   *new_str = '\0';
895 }
896 
897 static Boolean AllCaps (
898   CharPtr p
899 )
900 
901 {
902   if (p == NULL) return FALSE;
903 
904   for (p++; p != NULL && *p != '\0'; p++) {
905     if (IS_LOWER (*p)) return FALSE;
906   }
907   return TRUE;
908 }
909 
910 static void CleanEquals (
911   CharPtr p
912 )
913 
914 {
915   if (p == NULL) return;
916 
917   for (; *p != '\0'; p++) {
918     if (*p == '\"') {
919       *p = '\'';
920     }
921   }
922 }
923 
924 static CharPtr GetPubTitle (
925   FmtType format,
926   PubdescPtr pdp,
927   CitSubPtr csp
928 )
929 
930 {
931   CitArtPtr        cap;
932   CitBookPtr       cbp;
933   CitGenPtr        cgp;
934   Char             ch;
935   CitPatPtr        cpp;
936   MedlineEntryPtr  mep;
937   CharPtr          ptr;
938   CharPtr          title = NULL;
939   ValNodePtr       ttl = NULL;
940   ValNodePtr       vnp;
941 
942   if (csp != NULL) {
943     if (format == GENBANK_FMT || format == GENPEPT_FMT) {
944       title = "Direct Submission";
945       return StringSave (title);
946     } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
947       return NULL;
948     }
949   }
950   if (pdp == NULL) return NULL;
951 
952   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
953     switch (vnp->choice) {
954       case PUB_Gen :
955         cgp = (CitGenPtr) vnp->data.ptrvalue;
956         if (cgp != NULL) {
957           if (! StringHasNoText (cgp->title)) return StringSave (cgp->title);
958           if (! StringHasNoText (cgp->cit)) {
959             ptr = StringStr (cgp->cit, "Title=\"");
960             if (ptr != NULL) {
961               title = StringSave (ptr + 7);
962               for (ptr = title; *ptr != '\0'; ptr++) {
963                 if (*ptr == '"') {
964                   *ptr = '\0';
965                   break;
966                 }
967               }
968               return title;
969             }
970           }
971         }
972         break;
973       case PUB_Sub :
974         csp = (CitSubPtr) vnp->data.ptrvalue;
975         if (csp != NULL) {
976           if (format == GENBANK_FMT || format == GENPEPT_FMT) {
977             title = "Direct Submission";
978             return StringSave (title);
979           } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
980             return NULL;
981           }
982         }
983         break;
984       case PUB_Medline :
985         mep = (MedlineEntryPtr) vnp->data.ptrvalue;
986         if (mep != NULL) {
987           cap = mep->cit;
988           if (cap != NULL) {
989             ttl = cap->title;
990           }
991         }
992         break;
993       case PUB_Article :
994         cap = (CitArtPtr) vnp->data.ptrvalue;
995         if (cap != NULL) {
996           ttl = cap->title;
997         }
998         break;
999       /* case PUB_Book : */
1000       case PUB_Proc :
1001       case PUB_Man :
1002         cbp = (CitBookPtr) vnp->data.ptrvalue;
1003         if (cbp != NULL) {
1004           ttl = cbp->title;
1005           if (ttl != NULL) {
1006             title = (CharPtr) ttl->data.ptrvalue;
1007             if (! StringHasNoText (title)) {
1008               title = StringSave (title);
1009               if (StringLen (title) > 3) {
1010                 ch = *title;
1011                 if (IS_LOWER (ch)) {
1012                   *title = TO_UPPER (ch);
1013                 }
1014                 ptr = title;
1015                 if (AllCaps (ptr)) {
1016                   for (ptr++; ptr != NULL && *ptr != '\0'; ptr++) {
1017                     ch = *ptr;
1018                     *ptr = TO_LOWER (ch);
1019                   }
1020                 }
1021               }
1022               return title;
1023             }
1024           }
1025         }
1026         break;
1027       case PUB_Patent :
1028         cpp = (CitPatPtr) vnp->data.ptrvalue;
1029         if (cpp != NULL) {
1030           title = cpp->title;
1031           if (! StringHasNoText (title)) {
1032             return StringSave (title);
1033           }
1034         }
1035         break;
1036       default :
1037         break;
1038     }
1039 
1040     if (ttl != NULL) {
1041       title = (CharPtr) ttl->data.ptrvalue;
1042       if (! StringHasNoText (title)) {
1043         return StringSave (title);
1044       }
1045     }
1046   }
1047 
1048   return NULL;
1049 }
1050 
1051 static void CleanPubTitle (
1052   CharPtr title
1053 )
1054 
1055 {
1056   CharPtr  p;
1057   Boolean  remove_it;
1058 
1059   if (title == NULL) return;
1060 
1061   CleanEquals (title);
1062 
1063   for (p = title + StringLen (title) - 1; p > title + 2; p--) {
1064     if (*p == ' ') {
1065       *p = '\0';
1066     } else if (*p == '.') {
1067       remove_it = FALSE;
1068       if (p > title + 5) {
1069         if (*(p - 1) != '.' || *(p - 2) != '.') {
1070           remove_it = TRUE;
1071         }
1072       }
1073       if (remove_it) {
1074         *p = '\0';
1075       }
1076       break;
1077     } else {
1078       break;
1079     }
1080   }
1081 }
1082 
1083 /*
1084 medline type page numbering is expanded (e.g., 125-35 -> 125-135,
1085 F124-34 -> F124-F134, 12a-c -> 12a-12c).
1086 If only one page is given, this is output without a dash.
1087 Expanded numbering is validated to ensure that the
1088 first number is smaller than or equal to the second and
1089 that the first letter is less than or identical to the second
1090 (i.e., a < c).  If the input is all letters (i.e., roman numerals)
1091 this is not validated.
1092 
1093 Return values:
1094  0 : valid page numbering.
1095 -1 : invalid page numbering.
1096 */
1097 
1098 #define MAX_PAGE_DIGITS 12
1099 
1100 static Int2 FixPages (
1101   CharPtr out_pages,
1102   CharPtr in_pages
1103 )
1104 
1105 {
1106   Boolean dash=TRUE, first_alpha;
1107   Char firstbegin[MAX_PAGE_DIGITS];
1108   Char secondbegin[MAX_PAGE_DIGITS];
1109   Char firstend[MAX_PAGE_DIGITS];
1110   Char secondend[MAX_PAGE_DIGITS];
1111   Char temp[MAX_PAGE_DIGITS];
1112   CharPtr alphabegin, numbegin, alphaend, numend, ptr, in=in_pages;
1113   Int2 diff, index, retval=0;
1114   Int2 length_nb, length_ab, length_ne, length_ae;
1115   Int4 num1=0, num2=0;
1116 
1117   if (in_pages == NULL) return retval;
1118 
1119   while (*in != '\0')
1120   {      /* Check for digits in input*/
1121     if (IS_DIGIT(*in))
1122       break;
1123     in++;
1124   }
1125 
1126   if (*in == '\0' || (in != in_pages && *(in-1) == ' '))
1127   {    /* if all letters (i.e. roman numerals), put out. */
1128     out_pages = StringCpy(out_pages, in_pages);
1129     return retval;
1130   }
1131 
1132   in = in_pages;
1133   if (IS_DIGIT(*in))
1134   {      /* Do digits come first? */
1135     first_alpha = FALSE;
1136     index=0;
1137     while (IS_DIGIT(*in) || *in == ' ')
1138     {
1139       firstbegin[index] = *in;
1140       if (*in != ' ')
1141         index++;
1142       in++;
1143       if (*in == '-')
1144         break;
1145 
1146     }
1147     firstbegin[index] = '\0';
1148     index=0;
1149     if (*in != '-')
1150     {    /* After digits look for letters. */
1151       while (IS_ALPHA(*in)  || *in == ' ')
1152       {
1153         secondbegin[index] = *in;
1154         index++;
1155         in++;
1156         if (*in == '-')
1157           break;
1158       }
1159     }
1160     secondbegin[index] = '\0';
1161     if (*in == '-')    /* if dash is not present, note */
1162       in++;
1163     else
1164       dash=FALSE;
1165     index=0;
1166     while (IS_DIGIT(*in) || *in == ' ')
1167     {      /* Look for digits.  */
1168       firstend[index] = *in;
1169       if (*in != ' ')
1170         index++;
1171       in++;
1172     }
1173     firstend[index] = '\0';
1174     index=0;
1175     if (*in != '\0')
1176     {      /* Look for letters again. */
1177       while (IS_ALPHA(*in)  || *in == ' ')
1178       {
1179         secondend[index] = *in;
1180         index++;
1181         in++;
1182       }
1183     }
1184     secondend[index] = '\0';
1185   }
1186   else
1187   {      /* Do letters come first? */
1188     first_alpha = TRUE;
1189     index=0;
1190     while (IS_ALPHA(*in) || *in == ' ')
1191     {
1192       firstbegin[index] = *in;
1193       index++;
1194       in++;
1195       if (*in == '-')
1196         break;
1197     }
1198     firstbegin[index] = '\0';
1199     index=0;
1200     if (*in != '-')
1201     {    /* After letters look for digits.   */
1202       while (IS_DIGIT(*in)  || *in == ' ')
1203       {
1204         secondbegin[index] = *in;
1205         if (*in != ' ')
1206           index++;
1207         in++;
1208         if (*in == '-')
1209           break;
1210       }
1211     }
1212     secondbegin[index] = '\0';
1213     if (*in == '-')    /* Note if dash is missing. */
1214       in++;
1215     else
1216       dash=FALSE;
1217     index=0;
1218     while (IS_ALPHA(*in) || *in == ' ')
1219     {    /* Look for letters again. */
1220       firstend[index] = *in;
1221       index++;
1222       in++;
1223     }
1224     firstend[index] = '\0';
1225     index=0;
1226     if (*in != '\0')
1227     {    /* Any digits here? */
1228       while (IS_DIGIT(*in)  || *in == ' ')
1229       {
1230         secondend[index] = *in;
1231         if (*in != ' ')
1232           index++;
1233         in++;
1234       }
1235     }
1236     secondend[index] = '\0';
1237   }
1238 
1239   if (first_alpha)
1240   {
1241     alphabegin = firstbegin;
1242     numbegin = secondbegin;
1243     alphaend = firstend;
1244     numend = secondend;
1245   }
1246   else
1247   {
1248     numbegin = firstbegin;
1249     alphabegin = secondbegin;
1250     numend = firstend;
1251     alphaend = secondend;
1252   }
1253 
1254   length_nb = StringLen(numbegin);
1255   length_ab = StringLen(alphabegin);
1256   length_ne = StringLen(numend);
1257   length_ae = StringLen(alphaend);
1258 
1259   /* If no dash, but second letters or numbers present, reject. */
1260   if (dash == FALSE)
1261   {
1262     if (length_ne != 0 || length_ae != 0)
1263       retval = -1;
1264   }
1265   /* Check for situations like "AAA-123" or "222-ABC". */
1266   if (dash == TRUE)
1267   {
1268     if (length_ne == 0 && length_ab == 0)
1269       retval = -1;
1270     else if (length_ae == 0 && length_nb == 0)
1271       retval = -1;
1272   }
1273 
1274   /* The following expands "F502-512" into "F502-F512" and
1275   checks, for entries like "12a-12c" that a > c.  "12aa-12ab",
1276   "125G-137A", "125-G137" would be rejected. */
1277   if (retval == 0)
1278   {
1279     if (length_ab > 0)
1280     {
1281       if (length_ae > 0)
1282       {
1283         if (StringCmp(alphabegin, alphaend) != 0)
1284         {
1285           if (length_ab != 1 || length_ae != 1)
1286             retval = -1;
1287           else if (*alphabegin > *alphaend)
1288             retval = -1;
1289         }
1290       }
1291       else
1292       {
1293         alphaend = alphabegin;
1294         length_ae = length_ab;
1295       }
1296     }
1297     else if (length_ae > 0)
1298       retval = -1;
1299   }
1300 
1301 /* The following expands "125-37" into "125-137".  */
1302   if (retval == 0)
1303   {
1304     if (length_nb > 0)
1305     {
1306       if (length_ne > 0)
1307       {
1308         diff = length_nb - length_ne;
1309         if (diff > 0)
1310         {
1311           index=0;
1312           while (numend[index] != '\0')
1313           {
1314             temp[index+diff] = numend[index];
1315             index++;
1316           }
1317           temp[index+diff] = numend[index];
1318           for (index=0; index<diff; index++)
1319             temp[index] = numbegin[index];
1320           index=0;
1321           while (temp[index] != '\0')
1322           {
1323             numend[index] = temp[index];
1324             index++;
1325           }
1326           numend[index] = temp[index];
1327         }
1328       }
1329       else
1330       {
1331         numend = numbegin;
1332         length_ne = length_nb;
1333       }
1334 
1335     }
1336     else if (length_ne > 0)
1337       retval = -1;
1338   /* Check that the first number is <= the second (expanded) number. */
1339     if (retval == 0)
1340     {
1341   /*    sscanf(numbegin, "%ld", &num_type);
1342       num1 = (Int4) num_type;
1343       sscanf(  numend, "%ld", &num_type);
1344       num2 = (Int4) num_type;
1345   */
1346       num1 = (Int4) atol(numbegin);
1347       num2 = (Int4) atol(numend);
1348       if (num2 < num1)
1349         retval = -1;
1350     }
1351   }
1352 
1353   if (retval == -1)
1354   {
1355     out_pages = StringCpy(out_pages, in_pages);
1356   }
1357   else
1358   {
1359     ptr = out_pages;
1360   /* Place expanded and validated page numbers into "out_pages". */
1361     if (first_alpha)
1362     {
1363       while (*alphabegin != '\0')
1364       {
1365         *ptr = *alphabegin;
1366         alphabegin++;
1367         ptr++;
1368       }
1369       while (*numbegin != '\0')
1370       {
1371         *ptr = *numbegin;
1372         numbegin++;
1373         ptr++;
1374       }
1375       if (dash == TRUE)
1376       {
1377         *ptr = '-';
1378         ptr++;
1379         while (*alphaend != '\0')
1380         {
1381           *ptr = *alphaend;
1382           alphaend++;
1383           ptr++;
1384         }
1385         while (*numend != '\0')
1386         {
1387           *ptr = *numend;
1388           numend++;
1389           ptr++;
1390         }
1391       }
1392       *ptr = '\0';
1393     }
1394     else
1395     {
1396       while (*numbegin != '\0')
1397       {
1398         *ptr = *numbegin;
1399         numbegin++;
1400         ptr++;
1401       }
1402       while (*alphabegin != '\0')
1403       {
1404         *ptr = *alphabegin;
1405         alphabegin++;
1406         ptr++;
1407       }
1408       if (dash == TRUE)
1409       {
1410         *ptr = '-';
1411         ptr++;
1412         while (*numend != '\0')
1413         {
1414           *ptr = *numend;
1415           numend++;
1416           ptr++;
1417         }
1418         while (*alphaend != '\0')
1419         {
1420           *ptr = *alphaend;
1421           alphaend++;
1422           ptr++;
1423         }
1424       }
1425       *ptr = '\0';
1426     }
1427   }
1428   return retval;
1429 }
1430 
1431 /* !!! still need to add StripParanthesis equivalent !!! */
1432 
1433 static void DoSup (
1434   ValNodePtr PNTR head,
1435   CharPtr issue,
1436   CharPtr part_sup,
1437   CharPtr part_supi
1438 )
1439 
1440 {
1441   size_t   len;
1442   CharPtr  str;
1443   CharPtr  temp;
1444 
1445   len = StringLen (issue) + StringLen (part_sup) + StringLen (part_supi) + 25;
1446   str = MemNew (sizeof (Char) * len);
1447   if (str == NULL) return;
1448   temp = str;
1449 
1450   if (! StringHasNoText (part_sup)) {
1451     *temp = ' ';
1452     temp++;
1453     temp = StringMove (temp, part_sup);
1454   }
1455   if (StringHasNoText (issue) && StringHasNoText (part_supi)) {
1456     ValNodeCopyStr (head, 0, str);
1457     MemFree (str);
1458     return;
1459   }
1460   *temp = ' ';
1461   temp++;
1462   *temp = '(';
1463   temp++;
1464   if (! StringHasNoText (issue)) {
1465     temp = StringMove (temp, issue);
1466   }
1467   if (! StringHasNoText (part_supi)) {
1468     *temp = ' ';
1469     temp++;
1470     temp = StringMove (temp, part_supi);
1471   }
1472   *temp = ')';
1473   temp++;
1474   ValNodeCopyStr (head, 0, str);
1475   MemFree (str);
1476 }
1477 
1478 static CharPtr FormatCitJour (
1479   FmtType format,
1480   Boolean citArtIsoJta,
1481   CitJourPtr cjp
1482 )
1483 
1484 {
1485   Char        buf [256];
1486   DatePtr     dp;
1487   Boolean     electronic_journal = FALSE;
1488   ValNodePtr  head = NULL;
1489   ImprintPtr  imp;
1490   CharPtr     issue = NULL;
1491   Char        pages [128];
1492   CharPtr     part_sup = NULL;
1493   CharPtr     part_supi = NULL;
1494   CharPtr     rsult = NULL;
1495   CharPtr     title = NULL;
1496   ValNodePtr  ttl;
1497   CharPtr     volume;
1498   Char        year [8];
1499 
1500   if (cjp == NULL) return NULL;
1501 
1502   ttl = cjp->title;
1503   if (ttl == NULL) return NULL;
1504 
1505   /* always use iso_jta title if present */
1506 
1507   while (ttl != NULL && ttl->choice != Cit_title_iso_jta) {
1508     ttl = ttl->next;
1509   }
1510 
1511   imp = cjp->imp;
1512   if (imp == NULL) return NULL;
1513 
1514   /* release mode requires iso_jta title */
1515 
1516   if (imp->pubstatus == 3 || imp->pubstatus == 10) {
1517     electronic_journal = TRUE;
1518   }
1519 
1520   if (ttl == NULL) {
1521     ttl = cjp->title;
1522     if (ttl != NULL && ttl->choice == Cit_title_name) {
1523       title = (CharPtr) ttl->data.ptrvalue;
1524       if (title != NULL && StringNCmp (title, "(er)", 4) == 0) {
1525         electronic_journal = TRUE;
1526       }
1527     }
1528     if (citArtIsoJta && (! electronic_journal)) return NULL;
1529   }
1530 
1531   dp = imp->date;
1532   year [0] = '\0';
1533   if (dp != NULL) {
1534     if (dp->data [0] == 1) {
1535       if (dp->data [1] != 0) {
1536         sprintf (year, " (%ld)", (long) (1900 + dp->data [1]));
1537       }
1538     } else {
1539       StringCpy (year, " (");
1540       StringNCat (year, dp->str, 4);
1541       StringCat (year, ")");
1542     }
1543   }
1544 
1545   if (imp->prepub == 1 || imp->prepub == 255) {
1546     sprintf (buf, "Unpublished %s", year);
1547     return StringSave (buf);
1548   }
1549 
1550   if (ttl != NULL) {
1551     title = (CharPtr) ttl->data.ptrvalue;
1552   }
1553   if (StringLen (title) < 3) return StringSave (".");
1554 
1555   /*
1556   if (imp->pubstatus == 3 || imp->pubstatus == 10) {
1557     ValNodeCopyStr (&head, 0, "(er) ");
1558   }
1559   */
1560 
1561   ValNodeCopyStr (&head, 0, title);
1562 
1563   volume = imp->volume;
1564   if (format == GENBANK_FMT || format == GENPEPT_FMT) {
1565     issue = imp->issue;
1566     part_sup = imp->part_sup;
1567     part_supi = imp->part_supi;
1568   }
1569   pages [0] = '\0';
1570   if (electronic_journal) {
1571     StringNCpy_0 (pages, imp->pages, sizeof (pages));
1572   } else {
1573     FixPages (pages, imp->pages);
1574   }
1575 
1576   if (! StringHasNoText (volume)) {
1577     AddValNodeString (&head, " ", volume, NULL);
1578   }
1579 
1580   if ((! StringHasNoText (volume)) || (! StringHasNoText (pages))) {
1581     DoSup (&head, issue, part_sup, part_supi);
1582   }
1583 
1584   if (format == GENBANK_FMT || format == GENPEPT_FMT) {
1585     if (! StringHasNoText (pages)) {
1586       AddValNodeString (&head, ", ", pages, NULL);
1587     }
1588   } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
1589     if (! StringHasNoText (pages)) {
1590       AddValNodeString (&head, ":", pages, NULL);
1591     } else if (imp->prepub == 2 || (StringHasNoText (volume))) {
1592       ValNodeCopyStr (&head, 0, " 0:0-0");
1593     }
1594   }
1595 
1596   ValNodeCopyStr (&head, 0, year);
1597 
1598   if (format == GENBANK_FMT || format == GENPEPT_FMT) {
1599     if (imp->prepub == 2) {
1600       ValNodeCopyStr (&head, 0, " In press");
1601     } else if (imp->pubstatus == 10 && StringHasNoText (pages)) {
1602       ValNodeCopyStr (&head, 0, " In press");
1603     }
1604   }
1605 
1606   rsult = MergeFFValNodeStrs (head);
1607   ValNodeFreeData (head);
1608 
1609   return rsult;
1610 }
1611 
1612 static CharPtr MakeAffilStr (
1613   AffilPtr afp
1614 )
1615 
1616 {
1617   ValNodePtr  head = NULL;
1618   CharPtr     prefix = "";
1619   CharPtr     rsult = NULL;
1620 
1621   if (afp == NULL) return NULL;
1622 
1623   if (! StringHasNoText (afp->affil)) {
1624     ValNodeCopyStr (&head, 0, afp->affil);
1625     prefix = ", ";
1626   }
1627 
1628   if (afp->choice == 2) {
1629     if (! StringHasNoText (afp->div)) {
1630       AddValNodeString (&head, prefix, afp->div, NULL);
1631       prefix = ", ";
1632     }
1633     if (! StringHasNoText (afp->street)) {
1634       AddValNodeString (&head, prefix, afp->street, NULL);
1635       prefix = ", ";
1636     }
1637     if (! StringHasNoText (afp->city)) {
1638       AddValNodeString (&head, prefix, afp->city, NULL);
1639       prefix = ", ";
1640     }
1641     if (! StringHasNoText (afp->sub)) {
1642       AddValNodeString (&head, prefix, afp->sub, NULL);
1643       prefix = ", ";
1644     }
1645     if (! StringHasNoText (afp->country)) {
1646       AddValNodeString (&head, prefix, afp->country, NULL);
1647       prefix = ", ";
1648     }
1649   }
1650 
1651   rsult = MergeFFValNodeStrs (head);
1652   ValNodeFreeData (head);
1653 
1654   return rsult;
1655 }
1656 
1657 static CharPtr GetAffil (
1658   AffilPtr afp
1659 )
1660 
1661 {
1662   Boolean need_comma=FALSE;
1663   CharPtr string=NULL, temp, ptr;
1664   Char ch;
1665   Int2 aflen=15;
1666 
1667   if (afp == NULL) return NULL;
1668   if (afp) {
1669     if (afp -> choice == 1){
1670       if (afp -> affil){
1671         aflen += StringLen(afp -> affil);
1672       }
1673     }else if (afp -> choice == 2){
1674       aflen += StringLen (afp -> affil) +
1675       StringLen (afp -> div) +
1676       StringLen (afp -> city) +
1677       StringLen (afp -> sub) +
1678       StringLen (afp -> street) +
1679       StringLen (afp -> country) + StringLen(afp->postal_code);
1680     }
1681 
1682     temp = string = MemNew(aflen);
1683 
1684     if ( afp -> choice == 1){
1685        if (afp -> affil){
1686         ptr = afp->affil;
1687         while ((*temp = *ptr) != '\0')
1688         {
1689           temp++; ptr++;
1690         }
1691        }
1692     }else if (afp -> choice == 2){
1693 
1694       if( afp -> div) {
1695         if (need_comma)
1696         {
1697           *temp = ','; temp++;
1698           *temp = ' '; temp++;
1699         }
1700         ptr = afp->div;
1701         while ((*temp = *ptr) != '\0')
1702         {
1703           temp++; ptr++;
1704         }
1705         need_comma = TRUE;
1706       }
1707 
1708       if(afp -> affil) {
1709         if (need_comma)
1710         {
1711           *temp = ','; temp++;
1712           *temp = ' '; temp++;
1713         }
1714         ptr = afp->affil;
1715         while ((*temp = *ptr) != '\0')
1716         {
1717           temp++; ptr++;
1718         }
1719         need_comma = TRUE;
1720       }
1721 
1722       if(afp -> street) {
1723         if (need_comma)
1724         {
1725           *temp = ','; temp++;
1726           *temp = ' '; temp++;
1727         }
1728         ptr = afp->street;
1729         while ((*temp = *ptr) != '\0')
1730         {
1731           temp++; ptr++;
1732         }
1733         need_comma = TRUE;
1734       }
1735 
1736       if( afp -> city) {
1737         if (need_comma)
1738         {
1739           *temp = ','; temp++;
1740           *temp = ' '; temp++;
1741         }
1742         ptr = afp->city;
1743         while ((*temp = *ptr) != '\0')
1744         {
1745           temp++; ptr++;
1746         }
1747         need_comma = TRUE;
1748       }
1749 
1750       if( afp -> sub) {
1751         if (need_comma)
1752         {
1753           *temp = ','; temp++;
1754           *temp = ' '; temp++;
1755         }
1756         ptr = afp->sub;
1757         while ((*temp = *ptr) != '\0')
1758         {
1759           temp++; ptr++;
1760         }
1761         need_comma = TRUE;
1762       }
1763 
1764       if( afp -> postal_code){
1765         *temp = ' ';
1766         temp++;
1767         ptr = afp->postal_code;
1768         while ((*temp = *ptr) != '\0')
1769         {
1770           temp++; ptr++;
1771         }
1772       }
1773 
1774       if( afp -> country){
1775         if (need_comma)
1776         {
1777           *temp = ','; temp++;
1778           *temp = ' '; temp++;
1779         }
1780         ptr = afp->country;
1781         while ((*temp = *ptr) != '\0')
1782         {
1783           temp++; ptr++;
1784         }
1785         need_comma = TRUE;
1786       }
1787     }
1788     temp++;
1789     *temp = '\0';
1790   }
1791 
1792     /* convert double quotes to single quotes */
1793 
1794     ptr = string;
1795     ch = *ptr;
1796     while (ch != '\0') {
1797       if (ch == '\"') {
1798         *ptr = '\'';
1799       }
1800       ptr++;
1801       ch = *ptr;
1802     }
1803 
1804   return string;
1805 }
1806 
1807 NLM_EXTERN CharPtr GetFlatFileAffilString (AffilPtr afp)
1808 {
1809   return GetAffil (afp);
1810 }
1811 
1812 
1813 static CharPtr FormatCitBookArt (
1814   FmtType format,
1815   CitBookPtr cbp
1816 )
1817 
1818 {
1819   AffilPtr     afp;
1820   AuthListPtr  alp;
1821   CharPtr      book_title = NULL;
1822   Char         buf [256];
1823   Char         ch;
1824   DatePtr      dp;
1825   ValNodePtr   head = NULL;
1826   ImprintPtr   imp;
1827   CharPtr      issue = NULL;
1828   ValNodePtr   names = NULL;
1829   Char         pages [128];
1830   CharPtr      part_sup = NULL;
1831   CharPtr      part_supi = NULL;
1832   CharPtr      rsult = NULL;
1833   CharPtr      str;
1834   CharPtr      title;
1835   ValNodePtr   ttl;
1836   ValNodePtr   vnp;
1837   CharPtr      volume;
1838   Char         year [8];
1839 
1840   if (cbp == NULL) return NULL;
1841 
1842   ttl = cbp->title;
1843   if (ttl == NULL) return NULL;
1844 
1845   imp = cbp->imp;
1846   if (imp == NULL) return NULL;
1847 
1848   dp = imp->date;
1849   year [0] = '\0';
1850   if (dp != NULL) {
1851     if (dp->data [0] == 1) {
1852       if (dp->data [1] != 0) {
1853         sprintf (year, "(%ld)", (long) (1900 + dp->data [1]));
1854       }
1855     } else {
1856       StringCpy (year, "(");
1857       StringNCat (year, dp->str, 4);
1858       StringNCat (year, ")", 1);
1859     }
1860   }
1861 
1862   if (imp->prepub == 1 || imp->prepub == 255) {
1863     sprintf (buf, "Unpublished %s", year);
1864     return StringSave (buf);
1865   }
1866 
1867   title = (CharPtr) ttl->data.ptrvalue;
1868   if (StringLen (title) < 3) return StringSave (".");
1869 
1870   ValNodeCopyStr (&head, 0, "(in) ");
1871 
1872   alp = cbp->authors;
1873   if (alp != NULL) {
1874     str = GetAuthorsString (format, alp, NULL, NULL, NULL);
1875     if (str != NULL) {
1876       ValNodeCopyStr (&head, 0, str);
1877       names = alp->names;
1878       if (names != NULL) {
1879         if (names->next != NULL) {
1880           ValNodeCopyStr (&head, 0, " (Eds.);");
1881         } else {
1882           ValNodeCopyStr (&head, 0, " (Ed.);");
1883         }
1884       }
1885       ValNodeCopyStr (&head, 0, "\n");
1886     }
1887     MemFree (str);
1888   }
1889 
1890   book_title = StringSaveNoNull (title);
1891   vnp = ValNodeAddStr (&head, 0, book_title);
1892   if (book_title != NULL) {
1893 
1894     /* make book title all caps */
1895 
1896     title = book_title;
1897     ch = *title;
1898     while (ch != '\0') {
1899       *title = TO_UPPER (ch);
1900       title++;
1901       ch = *title;
1902     }
1903   }
1904 
1905   volume = imp->volume;
1906   if (format == GENBANK_FMT || format == GENPEPT_FMT) {
1907     issue = imp->issue;
1908     part_sup = imp->part_sup;
1909     part_supi = imp->part_supi;
1910   }
1911   pages [0] = '\0';
1912   FixPages (pages, imp->pages);
1913 
1914   if ((! StringHasNoText (volume)) && (StringCmp (volume, "0") != 0)) {
1915     AddValNodeString (&head, ", Vol. ", volume, NULL);
1916     DoSup (&head, issue, part_sup, part_supi);
1917   }
1918 
1919   if (! StringHasNoText (pages)) {
1920     AddValNodeString (&head, ": ", pages, NULL);
1921   }
1922 
1923   if (book_title != NULL) {
1924     ValNodeCopyStr (&head, 0, ";\n");
1925   }
1926 
1927   afp = imp->pub;
1928   if (afp != NULL) {
1929     str = MakeAffilStr (afp);
1930     if (str != NULL) {
1931       ValNodeCopyStr (&head, 0, str);
1932       ValNodeCopyStr (&head, 0, " ");
1933       MemFree (str);
1934     }
1935   }
1936 
1937   AddValNodeString (&head, NULL, year, NULL);
1938 
1939   if (format == GENBANK_FMT || format == GENPEPT_FMT) {
1940     if (imp->prepub == 2) {
1941       ValNodeCopyStr (&head, 0, " In press");
1942     }
1943   }
1944 
1945   rsult = MergeFFValNodeStrs (head);
1946   ValNodeFreeData (head);
1947 
1948   return rsult;
1949 }
1950 
1951 static CharPtr FormatCitBook (
1952   FmtType format,
1953   CitBookPtr cbp
1954 )
1955 
1956 {
1957   AffilPtr   afp;
1958   char       year[5];
1959   CharPtr    bookTitle=NULL;
1960   CharPtr    retval = NULL;
1961   CharPtr    temp;
1962   DatePtr    dp;
1963   ImprintPtr ip;
1964   int        aflen = 0;
1965   CharPtr    p;
1966   CharPtr    affilStr = NULL;
1967 
1968   /* Check parameters */
1969 
1970   if (cbp == NULL)
1971     return NULL;
1972 
1973   if ( cbp -> othertype != 0)
1974     return NULL;
1975 
1976   ip = cbp -> imp;
1977 
1978   /* Format the year */
1979 
1980   dp = ip -> date;
1981   year[0] = '\0';
1982 
1983   if ( dp -> data[0] == 1)
1984     sprintf(year,"%ld",(long) ( 1900+dp -> data[1]));
1985   else
1986     {
1987       StringNCpy( (CharPtr) year, (CharPtr) dp -> str, (size_t) 4);
1988       year[4] = '\0';
1989     }
1990 
1991   /* Get the book title */
1992 
1993   if (cbp->title)
1994     bookTitle = StringSave(cbp -> title -> data.ptrvalue);
1995 
1996   /* Get the affiliation length */
1997 
1998   if ( ip -> pub){
1999     afp = ip -> pub;
2000     aflen = StringLen(afp -> affil)+ 5;
2001     if ( afp -> choice == 2){
2002       aflen += 3 + StringLen(afp -> div);
2003       aflen += 3 + StringLen(afp -> street);
2004       aflen += 3 + StringLen(afp -> city);
2005       aflen += 3 + StringLen(afp -> sub);
2006       aflen += 3 + StringLen(afp -> country);
2007     }
2008   } else{
2009     aflen = 22;
2010   }
2011   if (ip->prepub == 2)
2012     aflen += 10;
2013 
2014   /* Create a Char String big enough to hold */
2015   /* the title, year, and affiliation.       */
2016 
2017   temp = retval = MemNew( (size_t) (30+StringLen( bookTitle)+StringLen( year) + aflen) );
2018 
2019   /* Convert the title to upper case and */
2020   /* add it to the string.               */
2021 
2022   if (bookTitle != NULL) {
2023     for ( p = bookTitle; *p; p++) {
2024       *p = TO_UPPER(*p);
2025     }
2026   }
2027 
2028   /* temp = StringMove(temp, "Book: "); */
2029   temp = StringMove(temp, "(in) ");
2030   temp = StringMove(temp, bookTitle);
2031   temp = StringMove(temp, ".");
2032 
2033   /* Add the affiliation to the string */
2034 
2035   if ( ip -> pub)
2036     {
2037       afp = ip -> pub;
2038       *temp = ' ';
2039       temp++;
2040       affilStr = MakeAffilStr(afp);
2041       temp = StringMove(temp,affilStr);
2042     }
2043 
2044   /* Add the year to the string */
2045 
2046   if (year[0] != '\0')
2047     {
2048       if (affilStr != NULL)
2049         temp = StringMove(temp," (");
2050       else
2051         temp = StringMove(temp, "(");
2052       temp = StringMove(temp, year);
2053       temp = StringMove(temp, ")");
2054     }
2055 
2056   /* If in press, add note */
2057 
2058   if (ip->prepub == 2)
2059     temp = StringMove(temp, ", In press");
2060 
2061   /* Clean up and return */
2062 
2063   if (bookTitle)
2064     MemFree(bookTitle);
2065 
2066   return retval;
2067 
2068 }
2069 
2070 static CharPtr FormatThesis (
2071   FmtType format,
2072   CitBookPtr cbp
2073 )
2074 
2075 {
2076   AffilPtr     afp;
2077   Char         ch;
2078   DatePtr      dp;
2079   ValNodePtr   head = NULL;
2080   ImprintPtr   imp;
2081   CharPtr      ptr;
2082   CharPtr      rsult = NULL;
2083   CharPtr      str;
2084   CharPtr      suffix = NULL;
2085   Char         year [8];
2086 
2087   if (cbp == NULL) return NULL;
2088   if (cbp->othertype != 2 || cbp->let_type != 3) return NULL;
2089 
2090   imp = cbp->imp;
2091   if (imp == NULL) return NULL;
2092 
2093   dp = imp->date;
2094   year [0] = '\0';
2095   if (dp != NULL) {
2096     if (dp->data [0] == 1) {
2097       if (dp->data [1] != 0) {
2098         sprintf (year, "%ld", (long) (1900 + dp->data [1]));
2099       }
2100     } else {
2101       StringNCpy (year, dp->str, (size_t) 4);
2102       year [4] = '\0';
2103     }
2104   }
2105 
2106   AddValNodeString (&head, "Thesis (", year, ")");
2107 
2108   if (imp->prepub == 2) {
2109     suffix = ", In press";
2110   }
2111 
2112   str = NULL;
2113   afp = imp->pub;
2114   if (afp != NULL) {
2115     if (afp->choice == 1) {
2116       str = StringSave (afp->affil);
2117     } else if (afp->choice == 2) {
2118       str = MakeAffilStr (afp);
2119     }
2120   }
2121 
2122   if (str != NULL) {
2123 
2124     /* convert double quotes to single quotes */
2125 
2126     ptr = str;
2127     ch = *ptr;
2128     while (ch != '\0') {
2129       if (ch == '\"') {
2130         *ptr = '\'';
2131       }
2132       ptr++;
2133       ch = *ptr;
2134     }
2135     AddValNodeString (&head, " ", str, suffix);
2136     MemFree (str);
2137   }
2138 
2139   rsult = MergeFFValNodeStrs (head);
2140   ValNodeFreeData (head);
2141 
2142   return rsult;
2143 }
2144 
2145 static CharPtr FormatCitArt (
2146   FmtType format,
2147   Boolean citArtIsoJta,
2148   CitArtPtr cap
2149 )
2150 
2151 {
2152   CitBookPtr  cbp;
2153   CitJourPtr  cjp;
2154   CharPtr     rsult = NULL;
2155 
2156   if (cap == NULL) return NULL;
2157 
2158   switch (cap->from) {
2159     case 1 :
2160       cjp = (CitJourPtr) cap->fromptr;
2161       if (cjp != NULL) {
2162         rsult = FormatCitJour (format, citArtIsoJta, cjp);
2163       }
2164       break;
2165     case 2 :
2166       cbp = (CitBookPtr) cap->fromptr;
2167       if (cbp != NULL) {
2168         rsult = FormatCitBookArt (format, cbp);
2169       }
2170       break;
2171     case 3 :
2172       cbp = (CitBookPtr) cap->fromptr;
2173       if (cbp != NULL) {
2174         rsult = FormatCitBookArt (format, cbp);
2175       }
2176       break;
2177     default :
2178       break;
2179   }
2180 
2181   return rsult;
2182 }
2183 
2184 static CharPtr FormatCitPat (
2185   FmtType format,
2186   ModType mode,
2187   CitPatPtr cpp,
2188   SeqIdPtr seqidp,
2189   IntAsn2gbJobPtr ajp
2190 )
2191 
2192 {
2193   AffilPtr       afp;
2194   AuthListPtr    alp;
2195   IdPatPtr       cit;
2196   CharPtr        consortium = NULL;
2197   Char           date [40];
2198   ValNodePtr     head = NULL;
2199   Boolean        is_us_pre_grant = FALSE;
2200   CharPtr        prefix = NULL;
2201   CharPtr        rsult = NULL;
2202   SeqIdPtr       sip;
2203   CharPtr        str;
2204   CharPtr        suffix = NULL;
2205   PatentSeqIdPtr psip;
2206   Int4           pat_seqid = 0;
2207   Char           buf[10];
2208 
2209   if (cpp == NULL) return NULL;
2210 
2211   if (StringHasNoText (cpp->number) &&
2212       StringDoesHaveText (cpp->app_number) &&
2213       StringCmp (cpp->country, "US") == 0 &&
2214       mode != RELEASE_MODE) {
2215     for (sip = seqidp; sip != NULL; sip = sip->next) {
2216       if (sip->choice != SEQID_PATENT) continue;
2217       psip = (PatentSeqIdPtr) sip->data.ptrvalue;
2218       if (psip == NULL) continue;
2219       cit = psip->cit;
2220       if (cit == NULL) continue;
2221       if (StringDoesHaveText (cit->app_number)) {
2222         is_us_pre_grant = TRUE;
2223       }
2224     }
2225   }
2226 
2227   if (format == GENBANK_FMT || format == GENPEPT_FMT) {
2228     if (is_us_pre_grant) {
2229       ValNodeCopyStr (&head, 0, "Pre-Grant Patent: ");
2230       suffix = " ";
2231     } else {
2232       ValNodeCopyStr (&head, 0, "Patent: ");
2233       suffix = " ";
2234     }
2235   } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
2236     ValNodeCopyStr (&head, 0, "Patent number ");
2237   }
2238 
2239   if (! StringHasNoText (cpp->country)) {
2240     AddValNodeString (&head, NULL, cpp->country, suffix);
2241   }
2242 
2243   if (! StringHasNoText (cpp->number)) {
2244     if (ajp != NULL && GetWWW (ajp) && StringCmp (cpp->country, "US") == 0) {
2245       ValNodeCopyStr (&head, 0, "<a href=\"");
2246       ValNodeCopyStr (&head, 0, link_uspto);
2247       ValNodeCopyStr (&head, 0, cpp->number);
2248       ValNodeCopyStr (&head, 0, "\">");
2249       ValNodeCopyStr (&head, 0, cpp->number);
2250       ValNodeCopyStr (&head, 0, "</a>");
2251     } else {
2252       ValNodeCopyStr (&head, 0, cpp->number);
2253     }
2254   } else if (! StringHasNoText (cpp->app_number)) {
2255     if (is_us_pre_grant) {
2256       AddValNodeString (&head, NULL, cpp->app_number, NULL);
2257     } else {
2258       AddValNodeString (&head, "(", cpp->app_number, ")");
2259     }
2260   }
2261 
2262   if (! StringHasNoText (cpp->doc_type)) {
2263     AddValNodeString (&head, "-", cpp->doc_type, NULL);
2264   }
2265 
2266   /* pat_seqid test */
2267 
2268   for (sip = seqidp; sip != NULL; sip = sip->next) {
2269     if (sip->choice == SEQID_PATENT) {
2270       psip = (PatentSeqIdPtr) sip -> data.ptrvalue;
2271       if (psip != NULL) {
2272         pat_seqid = psip->seqid;
2273       }
2274     }
2275   }
2276   if (pat_seqid > 0) {
2277     if (format == EMBL_FMT) {
2278       sprintf(buf,"%s%ld%s", "/", (long) pat_seqid, ", ");
2279       ValNodeCopyStr (&head, 0, buf);
2280     } else {
2281       sprintf(buf,"%s%ld ", " ", (long) pat_seqid);
2282       ValNodeCopyStr (&head, 0, buf);
2283     }
2284   } else {
2285     ValNodeCopyStr (&head, 0, " ");
2286   }
2287 
2288   /* Date */
2289 
2290   date [0] = '\0';
2291   if (cpp->date_issue != NULL) {
2292     DateToFF (date, cpp->date_issue, FALSE);
2293   } else if (cpp->app_date != NULL) {
2294     DateToFF (date, cpp->app_date, FALSE);
2295   }
2296   if (! StringHasNoText (date)) {
2297     ValNodeCopyStr (&head, 0, date);
2298   }
2299 
2300   if (format == GENBANK_FMT || format == GENPEPT_FMT) {
2301     ValNodeCopyStr (&head, 0, ";");
2302   } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
2303     ValNodeCopyStr (&head, 0, ".");
2304   }
2305 
2306   alp = cpp->authors;
2307   if (alp != NULL) {
2308     afp = alp->affil;
2309     if (afp != NULL) {
2310       suffix = NULL;
2311       if (afp->choice == 2) {
2312         suffix = ";";
2313       }
2314 
2315       /* If any of the affiliation fields are */
2316       /* non-blank, put them on a new line.   */
2317 
2318       if ((! StringHasNoText (afp->affil)) ||
2319           (! StringHasNoText (afp->street)) ||
2320           (! StringHasNoText (afp->div)) ||
2321           (! StringHasNoText (afp->city)) ||
2322           (! StringHasNoText (afp->sub)) ||
2323           (! StringHasNoText (afp->country)))
2324         ValNodeCopyStr (&head, 0, "\n");
2325 
2326       /* Write out the affiliation fields */
2327 
2328       if (! StringHasNoText (afp->affil)) {
2329         AddValNodeString (&head, NULL, afp->affil, suffix);
2330         prefix = " ";
2331       }
2332       if (! StringHasNoText (afp->street)) {
2333         AddValNodeString (&head, prefix, afp->street, ";");
2334         prefix = " ";
2335       }
2336       if (! StringHasNoText (afp->div)) {
2337         AddValNodeString (&head, prefix, afp->div, ";");
2338         prefix = " ";
2339       }
2340       if (! StringHasNoText (afp->city)) {
2341         AddValNodeString (&head, prefix, afp->city, NULL);
2342         prefix = ", ";
2343       }
2344       if (! StringHasNoText (afp->sub)) {
2345         AddValNodeString (&head, prefix, afp->sub, NULL);
2346       }
2347       if (! StringHasNoText (afp->country)) {
2348         AddValNodeString (&head, ";\n", afp->country, ";");
2349       }
2350     }
2351   }
2352 
2353   alp = cpp->assignees;
2354   if (alp != NULL) {
2355     str = GetAuthorsString (format, alp, &consortium, NULL, NULL);
2356     afp = alp->affil;
2357     if (afp != NULL) {
2358       suffix = NULL;
2359       if (afp->choice == 2) {
2360         suffix = ";";
2361       }
2362 
2363       /* If any of the affiliation fields are */
2364       /* non-blank, put them on a new line.   */
2365 
2366       if ((! StringHasNoText (str)) ||
2367           (! StringHasNoText (consortium)) ||
2368           (! StringHasNoText (afp->affil)) ||
2369           (! StringHasNoText (afp->street)) ||
2370           (! StringHasNoText (afp->div)) ||
2371           (! StringHasNoText (afp->city)) ||
2372           (! StringHasNoText (afp->sub)) ||
2373           (! StringHasNoText (afp->country)))
2374         ValNodeCopyStr (&head, 0, "\n");
2375 
2376       if (! StringHasNoText (str)) {
2377         AddValNodeString (&head, NULL, str, ";");
2378         prefix = " ";
2379       }
2380       if (! StringHasNoText (consortium)) {
2381         AddValNodeString (&head, NULL, consortium, ";");
2382         prefix = " ";
2383       }
2384 
2385       /* Write out the affiliation fields */
2386 
2387       if (! StringHasNoText (afp->affil)) {
2388         AddValNodeString (&head, NULL, afp->affil, suffix);
2389         prefix = " ";
2390       }
2391       if (! StringHasNoText (afp->street)) {
2392         AddValNodeString (&head, prefix, afp->street, ";");
2393         prefix = " ";
2394       }
2395       if (! StringHasNoText (afp->div)) {
2396         AddValNodeString (&head, prefix, afp->div, ";");
2397         prefix = " ";
2398       }
2399       if (! StringHasNoText (afp->city)) {
2400         AddValNodeString (&head, prefix, afp->city, NULL);
2401         prefix = ", ";
2402       }
2403       if (! StringHasNoText (afp->sub)) {
2404         AddValNodeString (&head, prefix, afp->sub, NULL);
2405       }
2406       if (! StringHasNoText (afp->country)) {
2407         AddValNodeString (&head, ";\n", afp->country, ";");
2408       }
2409     }
2410     MemFree (consortium);
2411     MemFree (str);
2412   }
2413 
2414   rsult = MergeFFValNodeStrs (head);
2415   ValNodeFreeData (head);
2416 
2417   /*
2418   s_StringCleanup(rsult);
2419   */
2420 
2421   return rsult;
2422 }
2423 
2424 static CharPtr FormatCitGen (
2425   FmtType format,
2426   Boolean dropBadCitGens,
2427   Boolean noAffilOnUnpub,
2428   CitGenPtr cgp
2429 )
2430 
2431 {
2432   CharPtr      affil = NULL;
2433   AuthListPtr  alp = NULL;
2434   Char         ch;
2435   DatePtr      dp;
2436   ValNodePtr   head = NULL;
2437   CharPtr      inpress = NULL;
2438   CharPtr      journal = NULL;
2439   Char         pages [128];
2440   CharPtr      prefix = NULL;
2441   CharPtr      ptr;
2442   CharPtr      rsult = NULL;
2443   Char         year [8];
2444 
2445   if (cgp == NULL) return NULL;
2446 
2447   if (cgp->journal == NULL && StringNICmp (cgp->cit, "unpublished", 11) == 0) {
2448     if (noAffilOnUnpub) {
2449 
2450       /* !!! temporarily put date in unpublished citation for QA !!! */
2451 
2452       if (dropBadCitGens) {
2453         year [0] = '\0';
2454         dp = cgp->date;
2455         if (dp != NULL) {
2456           if (dp->data [0] == 1) {
2457             if (dp->data [1] != 0) {
2458               sprintf (year, " (%ld)", (long) (1900 + dp->data [1]));
2459             }
2460           } else {
2461             StringCpy (year, " (");
2462             StringNCat (year, dp->str, 4);
2463             StringCat (year, ")");
2464           }
2465         }
2466         AddValNodeString (&head, NULL, "Unpublished", NULL);
2467         AddValNodeString (&head, NULL, year, NULL);
2468         rsult = MergeFFValNodeStrs (head);
2469         ValNodeFreeData (head);
2470         return rsult;
2471       }
2472 
2473       /* !!! remove above section once QA against asn2ff is done !!! */
2474 
2475       return StringSave ("Unpublished");
2476     }
2477 
2478     alp = cgp->authors;
2479     if (alp != NULL) {
2480       affil = GetAffil (alp->affil);
2481       if (! StringHasNoText (affil)) {
2482         rsult = MemNew ((size_t) StringLen (affil) + (size_t) StringLen (cgp->cit) + 15);
2483         StringCpy (rsult, "Unpublished ");
2484         StringCat (rsult, affil);
2485         TrimSpacesAroundString (rsult);
2486         return rsult;
2487       }
2488     }
2489 
2490     rsult = StringSave (cgp->cit);
2491     TrimSpacesAroundString (rsult);
2492     return rsult;
2493   }
2494 
2495   year [0] = '\0';
2496   dp = cgp->date;
2497   if (dp != NULL) {
2498     if (dp->data [0] == 1) {
2499       if (dp->data [1] != 0) {
2500         sprintf (year, " (%ld)", (long) (1900 + dp->data [1]));
2501       }
2502     } else {
2503       StringCpy (year, " (");
2504       StringNCat (year, dp->str, 4);
2505       StringCat (year, ")");
2506     }
2507   }
2508 
2509   pages [0] = '\0';
2510   if (cgp->pages != NULL) {
2511     FixPages (pages, cgp->pages);
2512   }
2513 
2514   if (cgp->journal != NULL) {
2515     journal = (CharPtr) cgp->journal->data.ptrvalue;
2516   }
2517   if (cgp->cit != NULL) {
2518     ptr = StringStr (cgp->cit, "Journal=\"");
2519     if (ptr != NULL) {
2520       journal = ptr + 9;
2521     } else if (StringNICmp (cgp->cit, "submitted", 8) == 0 ||
2522                StringNICmp (cgp->cit, "unpublished", 11) == 0) {
2523 
2524       if ((! dropBadCitGens) || journal != NULL) {
2525         inpress = cgp->cit;
2526       } else {
2527         inpress = "Unpublished";
2528       }
2529     } else if (StringNICmp (cgp->cit, "Online Publication", 18) == 0 ||
2530                StringNICmp (cgp->cit, "Published Only in DataBase", 26) == 0 ||
2531                StringNICmp (cgp->cit, "In press", 8) == 0 ) {
2532       inpress = cgp->cit;
2533     } else if (StringNICmp (cgp->cit, "(er) ", 5) == 0) {
2534       journal = cgp->cit;
2535     } else if ((! dropBadCitGens) && journal == NULL) {
2536       journal = cgp->cit;
2537     }
2538   }
2539   if (journal != NULL) {
2540     journal = StringSave (journal);
2541     for (ptr = journal, ch = *ptr; ch != '\0'; ptr++, ch = *ptr) {
2542       if (ch == '=' || ch == '\"') {
2543         *ptr = '\0';
2544       }
2545     }
2546     ValNodeAddStr (&head, 0, journal);
2547     prefix = " ";
2548   }
2549 
2550   if (! StringHasNoText (inpress)) {
2551     AddValNodeString (&head, prefix, inpress, NULL);
2552     prefix = " ";
2553   }
2554 
2555   if (! StringHasNoText (cgp->volume)) {
2556     AddValNodeString (&head, prefix, cgp->volume, NULL);
2557   }
2558 
2559   if (! StringHasNoText (pages)) {
2560     if (format == GENBANK_FMT) {
2561       AddValNodeString (&head, ", ", pages, NULL);
2562     } else if (format == EMBL_FMT) {
2563       AddValNodeString (&head, ":", pages, NULL);
2564     }
2565   }
2566 
2567   if (! StringHasNoText (year)) {
2568     AddValNodeString (&head, NULL, year, NULL);
2569   }
2570 
2571   rsult = MergeFFValNodeStrs (head);
2572   ValNodeFreeData (head);
2573 
2574   return rsult;
2575 }
2576 
2577 static CharPtr FormatCitSub (
2578   FmtType format,
2579   CitSubPtr csp
2580 )
2581 
2582 {
2583   CharPtr      affil;
2584   AffilPtr     afp;
2585   AuthListPtr  alp;
2586   Char         buf [256];
2587   Char         date [40];
2588   ValNodePtr   head = NULL;
2589   CharPtr      rsult = NULL;
2590 
2591   if (csp == NULL) return NULL;
2592 
2593   date [0] = '\0';
2594   if (csp->date != NULL) {
2595     DateToFF (date, csp->date, TRUE);
2596   }
2597   if (StringHasNoText (date)) {
2598     StringCpy (date, "\?\?-\?\?\?-\?\?\?\?");
2599   }
2600 
2601   sprintf (buf, "Submitted (%s)", date);
2602   ValNodeCopyStr (&head, 0, buf);
2603 
2604   alp = csp->authors;
2605   if (alp != NULL) {
2606     afp = alp->affil;
2607     if (afp != NULL) {
2608       affil = GetAffil (afp);
2609       if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
2610         if (StringNCmp(affil, " to the EMBL/GenBank/DDBJ databases.", 36) != 0) {
2611           ValNodeCopyStr (&head, 0, " to the EMBL/GenBank/DDBJ databases.\n");
2612         } else {
2613           ValNodeCopyStr (&head, 0, " ");
2614         }
2615       } else {
2616         ValNodeCopyStr (&head, 0, " ");
2617       }
2618       ValNodeCopyStr (&head, 0, affil);
2619       MemFree (affil);
2620     } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
2621       ValNodeCopyStr (&head, 0, " to the EMBL/GenBank/DDBJ databases.\n");
2622     }
2623   }
2624 
2625   rsult = MergeFFValNodeStrs (head);
2626   ValNodeFreeData (head);
2627 
2628   return rsult;
2629 }
2630 
2631 static CharPtr GetPubJournal (
2632   FmtType format,
2633   ModType mode,
2634   Boolean dropBadCitGens,
2635   Boolean noAffilOnUnpub,
2636   Boolean citArtIsoJta,
2637   PubdescPtr pdp,
2638   CitSubPtr csp,
2639   SeqIdPtr seqidp,
2640   IndxPtr index,
2641   IntAsn2gbJobPtr ajp
2642 )
2643 
2644 {
2645   CitArtPtr        cap;
2646   CitBookPtr       cbp;
2647   CitGenPtr        cgp;
2648   CitPatPtr        cpp;
2649   CharPtr          journal = NULL;
2650   MedlineEntryPtr  mep;
2651   ValNodePtr       vnp;
2652 
2653   if (csp != NULL) {
2654     return FormatCitSub (format, csp);
2655   }
2656   if (pdp == NULL) return NULL;
2657 
2658   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
2659     switch (vnp->choice) {
2660       case PUB_Gen :
2661         cgp = (CitGenPtr) vnp->data.ptrvalue;
2662         if (cgp != NULL) {
2663           if (StringNICmp ("BackBone id_pub", cgp->cit, 15) != 0) {
2664             if (cgp->cit == NULL && cgp->journal == NULL && cgp->date == NULL && cgp->serial_number) {
2665               break; /* skip just serial number */
2666             }
2667           }
2668           journal = FormatCitGen (format, dropBadCitGens, noAffilOnUnpub, cgp);
2669         }
2670         break;
2671       case PUB_Sub :
2672         csp = (CitSubPtr) vnp->data.ptrvalue;
2673         if (csp != NULL) {
2674           journal = FormatCitSub (format, csp);
2675         }
2676         break;
2677       case PUB_Medline :
2678         mep = (MedlineEntryPtr) vnp->data.ptrvalue;
2679         if (mep != NULL) {
2680           cap = mep->cit;
2681           if (cap != NULL) {
2682             journal = FormatCitArt (format, citArtIsoJta, cap);
2683           }
2684         }
2685         break;
2686       case PUB_Article :
2687         cap = (CitArtPtr) vnp->data.ptrvalue;
2688         if (cap != NULL) {
2689           journal = FormatCitArt (format, citArtIsoJta, cap);
2690         }
2691         break;
2692       case PUB_Book :
2693       case PUB_Proc :
2694         cbp = (CitBookPtr) vnp->data.ptrvalue;
2695         if (cbp != NULL) {
2696           journal = FormatCitBook (format, cbp);
2697         }
2698         break;
2699       case PUB_Man :
2700         cbp = (CitBookPtr) vnp->data.ptrvalue;
2701         if (cbp != NULL) {
2702           journal = FormatThesis (format, cbp);
2703         }
2704         break;
2705       case PUB_Patent :
2706         cpp = (CitPatPtr) vnp->data.ptrvalue;
2707         if (cpp != NULL) {
2708           journal = FormatCitPat (format, mode, cpp, seqidp, ajp);
2709         }
2710         break;
2711       default :
2712         break;
2713     }
2714 
2715     /* optionally populate indexes for NCBI internal database */
2716 
2717     if (index != NULL && journal != NULL) {
2718 
2719       /* skip non-informative cit-gens */
2720 
2721       if (StringNICmp (journal, "submitted", 8) == 0 ||
2722           StringNICmp (journal, "unpublished", 11) == 0 ||
2723           StringNICmp (journal, "Online Publication", 18) == 0 ||
2724           StringNICmp (journal, "Published Only in DataBase", 26) == 0) {
2725       } else {
2726         ValNodeCopyStrToHead (&(index->journals), 0, journal);
2727       }
2728     }
2729 
2730     if (journal != NULL) return journal;
2731   }
2732 
2733   return NULL;
2734 }
2735 
2736 static Int4 GetMuid (
2737   PubdescPtr pdp
2738 )
2739 
2740 {
2741   ArticleIdPtr     aip;
2742   CitArtPtr        cap;
2743   MedlineEntryPtr  mep;
2744   ValNodePtr       vnp;
2745 
2746   if (pdp == NULL) return 0;
2747 
2748   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
2749     switch (vnp->choice) {
2750       case PUB_Medline :
2751         mep = (MedlineEntryPtr) vnp->data.ptrvalue;
2752         if (mep != NULL) {
2753           return mep->uid;
2754         }
2755         break;
2756       case PUB_Muid :
2757         return vnp->data.intvalue;
2758       case PUB_Article:
2759         cap = (CitArtPtr) vnp->data.ptrvalue;
2760         if (cap!= NULL && cap->ids != NULL) {
2761           for (aip = cap->ids; aip != NULL; aip = aip->next) {
2762             if (aip->choice == ARTICLEID_MEDLINE) {
2763               return aip->data.intvalue;
2764             }
2765           }
2766         }
2767       default :
2768         break;
2769     }
2770   }
2771 
2772   return 0;
2773 }
2774 
2775 static Int4 GetPmid (
2776   PubdescPtr pdp
2777 )
2778 
2779 {
2780   ArticleIdPtr       aip;
2781   CitArtPtr        cap;
2782   MedlineEntryPtr  mep;
2783   ValNodePtr       vnp;
2784 
2785   if (pdp == NULL) return 0;
2786 
2787   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
2788     switch (vnp->choice) {
2789       case PUB_Medline :
2790         mep = (MedlineEntryPtr) vnp->data.ptrvalue;
2791         if (mep != NULL) {
2792           return mep->pmid;
2793         }
2794         break;
2795       case PUB_PMid :
2796         return vnp->data.intvalue;
2797       case PUB_Article:
2798         cap = (CitArtPtr) vnp->data.ptrvalue;
2799         if (cap!= NULL && cap->ids != NULL) {
2800           for (aip = cap->ids; aip != NULL; aip = aip->next) {
2801             if (aip->choice == ARTICLEID_PUBMED) {
2802               return aip->data.intvalue;
2803             }
2804           }
2805         }
2806       default :
2807         break;
2808     }
2809   }
2810 
2811   return 0;
2812 }
2813 
2814 NLM_EXTERN CharPtr CleanQualValue (
2815   CharPtr str
2816 )
2817 
2818 {
2819   Char     ch;
2820   CharPtr  dst;
2821   CharPtr  ptr;
2822 
2823   if (str == NULL || str [0] == '\0') return NULL;
2824 
2825   dst = str;
2826   ptr = str;
2827   ch = *ptr;
2828   while (ch != '\0') {
2829     if (ch == '\n' || ch == '\r' || ch == '\t' || ch == '"') {
2830       *dst = ' ';
2831       dst++;
2832     } else {
2833       *dst = ch;
2834       dst++;
2835     }
2836     ptr++;
2837     ch = *ptr;
2838   }
2839   *dst = '\0';
2840 
2841   return str;
2842 }
2843 
2844 NLM_EXTERN CharPtr Asn2gnbkCompressSpaces (CharPtr str)
2845 
2846 {
2847   Char     ch;
2848   CharPtr  dst;
2849   Char     last;
2850   CharPtr  ptr;
2851 
2852   if (str != NULL && str [0] != '\0') {
2853     dst = str;
2854     ptr = str;
2855     ch = *ptr;
2856     while (ch != '\0' && ch <= ' ') {
2857       ptr++;
2858       ch = *ptr;
2859     }
2860     while (ch != '\0') {
2861       *dst = ch;
2862       dst++;
2863       ptr++;
2864       last = ch;
2865       ch = *ptr;
2866       if (ch != '\0' && ch < ' ') {
2867         *ptr = ' ';
2868         ch = *ptr;
2869       }
2870       while (ch != '\0' && last <= ' ' && ch <= ' ') {
2871         ptr++;
2872         ch = *ptr;
2873       }
2874     }
2875     *dst = '\0';
2876     dst = NULL;
2877     ptr = str;
2878     ch = *ptr;
2879     while (ch != '\0') {
2880       if (ch != ' ') {
2881         dst = NULL;
2882       } else if (dst == NULL) {
2883         dst = ptr;
2884       }
2885       ptr++;
2886       ch = *ptr;
2887     }
2888     if (dst != NULL) {
2889       *dst = '\0';
2890     }
2891   }
2892   return str;
2893 }
2894 
2895 NLM_EXTERN CharPtr StripAllSpaces (
2896   CharPtr str
2897 )
2898 
2899 {
2900   Char     ch;
2901   CharPtr  dst;
2902   CharPtr  ptr;
2903 
2904   if (str == NULL || str [0] == '\0') return NULL;
2905 
2906   dst = str;
2907   ptr = str;
2908   ch = *ptr;
2909   while (ch != '\0') {
2910     if (ch == ' ' || ch == '\t') {
2911     } else {
2912       *dst = ch;
2913       dst++;
2914     }
2915     ptr++;
2916     ch = *ptr;
2917   }
2918   *dst = '\0';
2919 
2920   return str;
2921 }
2922 
2923 static CharPtr remarksText [] = {
2924   "full automatic", "full staff_review", "full staff_entry",
2925   "simple staff_review", "simple staff_entry", "simple automatic",
2926   "unannotated automatic", "unannotated staff_review", "unannotated staff_entry",
2927   NULL
2928 };
2929 
2930 static void AddReferenceToGbseq (
2931   GBSeqPtr gbseq,
2932   GBReferencePtr gbref,
2933   CharPtr str,
2934   RefBlockPtr rbp,
2935   BioseqPtr bsp
2936 )
2937 
2938 {
2939   Char            buf [32];
2940   CharPtr         copy;
2941   ValNodePtr      head = NULL;
2942   IntRefBlockPtr  irp;
2943   SeqLocPtr       loc;
2944   CharPtr         ptr;
2945   CharPtr         ref;
2946   SeqLocPtr       slp;
2947   Int4            start;
2948   Int4            stop;
2949   CharPtr         tmp;
2950 
2951   if (gbseq == NULL || gbref == NULL || StringHasNoText (str) || rbp == NULL || bsp == NULL) return;
2952 
2953   copy = StringSave (str);
2954 
2955   /* link in reverse order, to be reversed in slash block */
2956 
2957   gbref->next = gbseq->references;
2958   gbseq->references = gbref;
2959 
2960   /* now parse or make ASN required default values for remaining fields */
2961 
2962   if (StringNCmp (copy, "REFERENCE   ", 12) == 0) {
2963     ref = copy + 12;
2964     ptr = StringStr (ref, "\n  AUTHORS");
2965     if (ptr == NULL) {
2966       ptr = StringStr (ref, "\n  CONSRTM");
2967     }
2968     if (ptr == NULL) {
2969       ptr = StringStr (ref, ")\n");
2970       if (ptr != NULL) {
2971         ptr++;
2972       }
2973     }
2974     if (ptr != NULL) {
2975       *ptr = '\0';
2976       /* gbref->reference = StringSave (ref); */
2977       sprintf (buf, "%d", (int) rbp->serial);
2978       gbref->reference = StringSave (buf);
2979     }
2980   }
2981 
2982   if (gbref->reference == NULL) {
2983     gbref->reference = StringSave ("?");
2984   }
2985 
2986   CleanQualValue (gbref->reference);
2987   Asn2gnbkCompressSpaces (gbref->reference);
2988 
2989   if (gbref->journal == NULL) {
2990     gbref->journal = StringSave ("?");
2991   }
2992 
2993   CleanQualValue (gbref->journal);
2994   Asn2gnbkCompressSpaces (gbref->journal);
2995 
2996   MemFree (copy);
2997 
2998   if (rbp->sites == 1 || rbp->sites == 2) {
2999     gbref->position = StringSave ("sites");
3000   } else if (rbp->sites == 3) {
3001   } else {
3002     irp = (IntRefBlockPtr) rbp;
3003     loc = irp->loc;
3004     if (loc != NULL) {
3005       slp = SeqLocFindNext (loc, NULL);
3006       while (slp != NULL) {
3007         start = SeqLocStart (slp) + 1;
3008         stop = SeqLocStop (slp) + 1;
3009         if (head == NULL) {
3010           sprintf (buf, "%ld..%ld", (long) start, (long) stop);
3011         } else {
3012           sprintf (buf, "; %ld..%ld", (long) start, (long) stop);
3013         }
3014         ValNodeCopyStr (&head, 0, buf);
3015         slp = SeqLocFindNext (loc, slp);
3016       }
3017       tmp = MergeFFValNodeStrs (head);
3018       ValNodeFreeData (head);
3019       gbref->position = tmp;
3020     } else {
3021       start = 1;
3022       stop = bsp->length;
3023       sprintf (buf, "%ld..%ld", (long) start, (long) stop);
3024       gbref->position = StringSave (buf);
3025     }
3026   }
3027 }
3028 
3029 static Boolean IsCitSub (
3030   PubdescPtr pdp,
3031   CitSubPtr csp
3032 )
3033 
3034 {
3035   ValNodePtr  vnp;
3036 
3037   if (csp != NULL) return TRUE;
3038   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
3039     if (vnp->choice == PUB_Sub) return TRUE;
3040   }
3041   return FALSE;
3042 }
3043 
3044 static void  FF_www_muid(
3045   IntAsn2gbJobPtr ajp,
3046   StringItemPtr ffstring,
3047   Int4 muid
3048 )
3049 {
3050   Char numbuf[40];
3051   
3052   if ( GetWWW(ajp) ) {
3053     FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
3054     FF_Add_NCBI_Base_URL (ffstring, link_muid);
3055     sprintf (numbuf, "%ld", (long)muid);
3056     FFAddTextToString (ffstring, NULL, numbuf, "\">", FALSE, FALSE, TILDE_IGNORE);
3057     FFAddOneString (ffstring, numbuf, FALSE, FALSE, TILDE_IGNORE);
3058     FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
3059   } else {
3060     sprintf(numbuf, "%ld", (long)muid);
3061     FFAddOneString (ffstring, numbuf, FALSE, FALSE, TILDE_IGNORE);
3062   }
3063 }
3064 
3065 static Uint1 GetJournalPubStatus (PubdescPtr pdp)
3066 
3067 {
3068   CitArtPtr   cap;
3069   CitJourPtr  cjp;
3070   ImprintPtr  imp;
3071   ValNodePtr  vnp;
3072 
3073   if (pdp == NULL) return 0;
3074 
3075   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
3076     if (vnp->choice != PUB_Article) continue;
3077     cap = (CitArtPtr) vnp->data.ptrvalue;
3078     if (cap == NULL) continue;
3079     if (cap->from != 1) continue;
3080     cjp = (CitJourPtr) cap->fromptr;
3081     if (cjp == NULL) continue;
3082     imp = cjp->imp;
3083     if (imp == NULL) continue;
3084     return imp->pubstatus;
3085   }
3086 
3087   return 0;
3088 }
3089 
3090 NLM_EXTERN CharPtr FormatReferenceBlock (
3091   Asn2gbFormatPtr afp,
3092   BaseBlockPtr bbp
3093 )
3094 
3095 {
3096   SeqMgrAndContext   acontext;
3097   AnnotDescPtr       adp;
3098   IntAsn2gbJobPtr    ajp;
3099   AuthListPtr        alp;
3100   Asn2gbSectPtr      asp;
3101   BioseqPtr          bsp;
3102   Char               buf [150];
3103   CitArtPtr          cap;
3104   Char               ch;
3105   CitJourPtr         cjp;
3106   Boolean            citArtIsoJta;
3107   CharPtr            consortium;
3108   CitPatPtr          cpp;
3109   CitRetractPtr      crp;
3110   CitSubPtr          csp = NULL;
3111   SeqMgrDescContext  dcontext;
3112   SeqMgrFeatContext  fcontext;
3113   Int4               gibbsq;
3114   GBReferencePtr     gbref = NULL;
3115   GBSeqPtr           gbseq;
3116   GBXrefPtr          gxp;
3117   ValNodePtr         head;
3118   Int2               i;
3119   ArticleIdPtr       ids;
3120   ImprintPtr         imp;
3121   IndxPtr            index;
3122   IntRefBlockPtr     irp;
3123   size_t             len;
3124   SeqLocPtr          loc = NULL;
3125   MedlineEntryPtr    mep;
3126   Int4               muid = 0;
3127   Boolean            needsPeriod = FALSE;
3128   SeqLocPtr          nextslp;
3129   Boolean            notFound;
3130   ObjMgrDataPtr      omdp;
3131   PubdescPtr         pdp = NULL;
3132   PubdescPtr         pdpcopy = NULL;
3133   PubmedEntryPtr     pep = NULL;
3134   Int4               pmid = 0;
3135   CharPtr            prefix = NULL;
3136   Uint1              pubstatus;
3137   CharPtr            pubstatnote;
3138   RefBlockPtr        rbp;
3139   ValNodePtr         remarks = NULL;
3140   CharPtr            remprefix = NULL;
3141   SubmitBlockPtr     sbp;
3142   SeqDescrPtr        sdp;
3143   SeqFeatPtr         sfp = NULL;
3144   SeqIdPtr           sip;
3145   SeqLocPtr          slp;
3146   SeqSubmitPtr       ssp;
3147   Int4               start;
3148   Int4               stop;
3149   CharPtr            str = NULL;
3150   Boolean            strict_isojta;
3151   CharPtr            suffix = NULL;
3152   BioseqPtr          target;
3153   CharPtr            tmp;
3154   Boolean            trailingPeriod = TRUE;
3155   ValNodePtr         vnp;
3156   StringItemPtr      ffstring, temp;
3157 
3158   if (afp == NULL || bbp == NULL) return NULL;
3159   rbp = (RefBlockPtr) bbp;
3160   ajp = afp->ajp;
3161   if (ajp == NULL) return NULL;
3162   asp = afp->asp;
3163   if (asp == NULL) return NULL;
3164   target = asp->target;
3165   bsp = asp->bsp;
3166   if (target == NULL || bsp == NULL) return NULL;
3167 
3168   /* five-column feature table uses special code for formatting */
3169 
3170   if (ajp->format == FTABLE_FMT) {
3171     irp = (IntRefBlockPtr) bbp;
3172     if (irp->loc != NULL) {
3173       if (irp->rb.pmid != 0 || irp->rb.muid != 0) {
3174         head = NULL;
3175         PrintFtableIntervals (&head, target, irp->loc, "REFERENCE");
3176         if (irp->rb.pmid != 0) {
3177           sprintf (buf, "\t\t\tpmid\t%ld\n", (long) irp->rb.pmid);
3178           ValNodeCopyStr (&head, 0, buf);
3179         } else if (irp->rb.muid != 0) {
3180           sprintf (buf, "\t\t\tmuid\t%ld\n", (long) irp->rb.muid);
3181           ValNodeCopyStr (&head, 0, buf);
3182         }
3183         str = MergeFFValNodeStrs (head);
3184         ValNodeFreeData (head);
3185       }
3186     }
3187     return str;
3188   }
3189 
3190   /* otherwise do regular flatfile formatting */
3191 
3192   ffstring = FFGetString(ajp);
3193   if ( ffstring == NULL ) return NULL;
3194 
3195   if (ajp->index) {
3196     index = &asp->index;
3197   } else {
3198     index = NULL;
3199   }
3200 
3201   if (ajp->gbseq) {
3202     gbseq = &asp->gbseq;
3203   } else {
3204     gbseq = NULL;
3205   }
3206 
3207   if (! StringHasNoText (rbp->string)) return StringSave (rbp->string);
3208 
3209   /* could be descriptor, feature, annotdesc, or submit block citation */
3210 
3211   if (rbp->itemtype == OBJ_SEQDESC) {
3212 
3213     sdp = SeqMgrGetDesiredDescriptor (rbp->entityID, NULL, rbp->itemID, 0, NULL, &dcontext);
3214     if (sdp != NULL && dcontext.seqdesctype == Seq_descr_pub) {
3215       pdp = (PubdescPtr) sdp->data.ptrvalue;
3216     }
3217 
3218   } else if (rbp->itemtype == OBJ_SEQFEAT) {
3219 
3220     sfp = SeqMgrGetDesiredFeature (rbp->entityID, NULL, rbp->itemID, 0, NULL, &fcontext);
3221     if (sfp != NULL && fcontext.seqfeattype == SEQFEAT_PUB) {
3222       pdp = (PubdescPtr) sfp->data.value.ptrvalue;
3223     }
3224 
3225   } else if (rbp->itemtype == OBJ_ANNOTDESC) {
3226 
3227     adp = SeqMgrGetDesiredAnnotDesc (rbp->entityID, NULL, rbp->itemID, &acontext);
3228     if (adp != NULL && acontext.annotdesctype == Annot_descr_pub) {
3229       pdp = (PubdescPtr) adp->data.ptrvalue;
3230     }
3231 
3232   } else if (rbp->itemtype == OBJ_SEQSUB_CIT) {
3233 
3234     omdp = ObjMgrGetData (rbp->entityID);
3235     if (omdp != NULL && omdp->datatype == OBJ_SEQSUB) {
3236       ssp = (SeqSubmitPtr) omdp->dataptr;
3237       if (ssp != NULL && ssp->datatype == 1) {
3238         sbp = ssp->sub;
3239         if (sbp != NULL) {
3240           csp = sbp->cit;
3241         }
3242       }
3243     }
3244   }
3245 
3246   if (pdp == NULL && csp == NULL) return NULL;
3247 
3248   temp = FFGetString(ajp);
3249   if ( temp == NULL ) {
3250     FFRecycleString(ajp, ffstring);
3251     return NULL;
3252   }
3253 
3254   /* any justuids left at this point is RefSeq protein, and should be fetched */
3255 
3256   irp = (IntRefBlockPtr) rbp;
3257   if (irp->justuids) {
3258     if (rbp->pmid != 0) {
3259       pep = GetPubMedForUid (rbp->pmid);
3260     } else if (rbp->muid != 0) {
3261       pep = GetPubMedForUid (rbp->muid);
3262     }
3263     if (pep != NULL) {
3264       mep = (MedlineEntryPtr) pep->medent;
3265       if (mep != NULL && mep->cit != NULL) {
3266         pdpcopy = AsnIoMemCopy ((Pointer) pdp,
3267                                  (AsnReadFunc) PubdescAsnRead,
3268                                  (AsnWriteFunc) PubdescAsnWrite);
3269         cap = AsnIoMemCopy ((Pointer) mep->cit,
3270                             (AsnReadFunc) CitArtAsnRead,
3271                             (AsnWriteFunc) CitArtAsnWrite);
3272         vnp = ValNodeAddPointer (&(pdpcopy->pub), PUB_Article, (Pointer) cap);
3273         pdp = pdpcopy;
3274       }
3275     }
3276   }
3277 
3278   /* print serial number */
3279   FFStartPrint(temp, afp->format, 0, 12, "REFERENCE", 12, 5, 5, "RN", TRUE);
3280 
3281   if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3282     if (rbp->serial > 99) {
3283       sprintf (buf, "%d ", (int) rbp->serial);
3284     } else {
3285       sprintf (buf, "%d", (int) rbp->serial);
3286     }
3287   } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3288     sprintf (buf, "[%d]", (int) rbp->serial);
3289   }
3290 
3291   FFAddOneString (temp, buf, FALSE, FALSE, TILDE_TO_SPACES);
3292 
3293   /* print base range */
3294 
3295   if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3296 
3297     if (rbp->sites != 3) {
3298       FFAddNChar(temp, ' ', 15 - temp->pos, FALSE);
3299     }
3300   } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3301 
3302     if (rbp->sites == 0) {
3303       FFLineWrap(ffstring, temp, 0, 5, ASN2FF_EMBL_MAX, "RN");   
3304       FFRecycleString(ajp, temp);
3305       temp = FFGetString(ajp);
3306       FFStartPrint(temp, afp->format, 0, 0, NULL, 0, 5, 5, "RP", FALSE);
3307     }
3308   }
3309 
3310   if (rbp->sites == 1 || rbp->sites == 2) {
3311 
3312     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3313       FFAddOneString (temp, "(sites)", FALSE, FALSE, TILDE_TO_SPACES);
3314       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3315     } else {
3316       FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RP");
3317     }
3318   } else if (rbp->sites == 3) {
3319     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3320       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3321     } else {
3322       FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RP");
3323     }
3324   } else {
3325     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3326       FFAddNChar(temp, ' ', 15 - temp->pos, FALSE);
3327       if (afp->format == GENBANK_FMT) {
3328         FFAddOneString (temp, "(bases ", FALSE, FALSE, TILDE_TO_SPACES);
3329       } else {
3330         FFAddOneString (temp, "(residues ", FALSE, FALSE, TILDE_TO_SPACES);
3331       }
3332     }
3333 
3334     irp = (IntRefBlockPtr) rbp;
3335     loc = irp->loc;
3336 
3337     if (loc != NULL) {
3338       if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3339         suffix = "; ";
3340       } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3341         suffix = ", ";
3342       }
3343 
3344       slp = SeqLocFindNext (loc, NULL);
3345       while (slp != NULL) {
3346         nextslp = SeqLocFindNext (loc, slp);
3347         start = SeqLocStart (slp) + 1;
3348         stop = SeqLocStop (slp) + 1;
3349         if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3350           sprintf (buf, "%ld to %ld", (long) start, (long) stop);
3351         } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3352           sprintf (buf, "%ld-%ld", (long) start, (long) stop);
3353         }
3354         if (nextslp == NULL) {
3355           suffix = NULL;
3356         }
3357         FFAddTextToString (temp, NULL, buf, suffix, FALSE, FALSE, TILDE_TO_SPACES);
3358         slp = nextslp;
3359       }
3360 
3361     } else {
3362 
3363       /* code still used for ssp->cit */
3364 
3365       start = 1;
3366       stop = bsp->length;
3367       if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3368         sprintf (buf, "%ld to %ld", (long) start, (long) stop);
3369       } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3370         sprintf (buf, "%ld-%ld", (long) start, (long) stop);
3371       }
3372       FFAddOneString (temp, buf, FALSE, FALSE, TILDE_TO_SPACES);
3373     }
3374 
3375     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3376       FFAddOneString (temp, ")", FALSE, FALSE, TILDE_TO_SPACES);
3377     }
3378     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3379       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3380     } else {
3381       FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RP");
3382     }
3383   }
3384 
3385   if (gbseq != NULL) {
3386     gbref = GBReferenceNew ();
3387   }
3388 
3389   /* print author list */
3390 
3391   str = NULL;
3392   consortium = NULL;
3393 
3394   alp = GetAuthListPtr (pdp, csp);
3395   if (alp != NULL) {
3396     str = GetAuthorsString (afp->format, alp, &consortium, index, gbref);
3397     TrimSpacesAroundString (str);
3398   }
3399 
3400   if (str != NULL || StringHasNoText (consortium)) {
3401     FFRecycleString(ajp, temp);
3402     temp = FFGetString(ajp);
3403     FFStartPrint(temp, afp->format, 2, 12, "AUTHORS", 12, 5, 5, "RA", FALSE);
3404 
3405     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3406       suffix = NULL;
3407       trailingPeriod = TRUE;
3408     } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3409       trailingPeriod = FALSE;
3410       len = StringLen (str);
3411       if (len > 0 && str != NULL && str [len - 1] != '.') {
3412         suffix = ".;";
3413       } else {
3414         suffix = ";";
3415       }
3416     }
3417 
3418     /* if no authors were found, period will still be added by this call */
3419     if (str != NULL) {
3420       FFAddTextToString (temp, NULL, str, suffix, trailingPeriod, FALSE, TILDE_TO_SPACES);
3421     } else if (StringHasNoText (consortium)) {
3422       if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3423         FFAddOneChar(temp, '.', FALSE);
3424       } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3425         FFAddOneChar(temp, ';', FALSE);
3426       }    
3427     }
3428 
3429     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3430       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3431     } else {
3432       FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RA");
3433     }
3434   }
3435   MemFree (str);
3436 
3437   /* print consortium */
3438 
3439   FFRecycleString(ajp, temp);
3440   temp = FFGetString(ajp);
3441   if (! StringHasNoText (consortium)) {
3442     FFStartPrint (temp, afp->format, 2, 12, "CONSRTM", 12, 5, 5, "RG", FALSE);
3443     FFAddTextToString (temp, NULL, consortium, suffix, FALSE, FALSE, TILDE_TO_SPACES);
3444     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3445       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3446     } else {
3447       FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RG");
3448     }
3449   }
3450   MemFree (consortium);
3451 
3452   /* print title */
3453   FFRecycleString(ajp, temp);
3454   temp = FFGetString(ajp);
3455 
3456   str = GetPubTitle (afp->format, pdp, csp);
3457   CleanPubTitle (str);
3458   StrStripSpaces (str);
3459 
3460   if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3461     prefix = NULL;
3462     suffix = NULL;
3463   } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3464     if (str != NULL) {
3465       prefix = "\"";
3466       suffix = "\";";
3467     } else {
3468       prefix = NULL;
3469       suffix = ";";
3470     }
3471   }
3472 
3473   if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3474     if (! StringHasNoText (str)) {
3475       FFStartPrint (temp, afp->format, 2, 12, "TITLE", 12, 5, 5, "RT", FALSE);
3476 
3477       FFAddTextToString (temp, prefix, str, suffix, FALSE, FALSE, TILDE_TO_SPACES);
3478       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3479     }
3480   } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3481     FFStartPrint (temp, afp->format, 2, 12, "TITLE", 12, 5, 5, "RT", FALSE);
3482     if (! StringHasNoText (str)) {
3483 
3484       FFAddTextToString (temp, prefix, str, suffix, FALSE, FALSE, TILDE_TO_SPACES);
3485 
3486     } else {
3487       FFAddOneChar (temp, ';', FALSE);
3488     }
3489     FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RT");
3490   }
3491 
3492   if (gbseq != NULL) {
3493     if (gbref != NULL) {
3494       gbref->title = StringSaveNoNull (str);
3495     }
3496   }
3497 
3498   MemFree (str);
3499 
3500   /* print journal */
3501   FFRecycleString(ajp, temp);
3502   temp = FFGetString(ajp);
3503 
3504   FFStartPrint (temp, afp->format, 2, 12, "JOURNAL", 12, 5, 5, "RL", FALSE);
3505 
3506   /* Only GenBank/EMBL/DDBJ require ISO JTA in ENTREZ/RELEASE modes (RefSeq should later) */
3507 
3508   citArtIsoJta = ajp->flags.citArtIsoJta;
3509   strict_isojta = FALSE;
3510   for (sip = bsp->id; sip != NULL; sip = sip->next) {
3511     if (sip->choice == SEQID_GENBANK ||
3512         sip->choice == SEQID_EMBL ||
3513         sip->choice == SEQID_DDBJ ||
3514         /* sip->choice == SEQID_OTHER || */
3515         sip->choice == SEQID_TPG ||
3516         sip->choice == SEQID_TPE ||
3517         sip->choice == SEQID_TPD) {
3518       strict_isojta = TRUE;
3519     }
3520   }
3521   if (! strict_isojta) {
3522     citArtIsoJta = FALSE;
3523   }
3524 
3525   str = GetPubJournal (afp->format, ajp->mode, ajp->flags.dropBadCitGens,
3526                        ajp->flags.noAffilOnUnpub, citArtIsoJta, pdp, csp,
3527                        bsp->id, index, ajp);
3528   if (str == NULL) {
3529     str = StringSave ("Unpublished");
3530   }
3531   StrStripSpaces (str);
3532   TrimSpacesAroundString (str);
3533 
3534   if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3535     needsPeriod = FALSE;
3536   } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3537     if (! IsCitSub (pdp, csp)) {
3538       needsPeriod = TRUE;
3539     }
3540   }
3541 
3542   FFAddOneString (temp, str, FALSE, FALSE, TILDE_IGNORE);
3543   if (needsPeriod) {
3544     FFAddOneChar(temp, '.', FALSE);
3545   }
3546 
3547   if (gbseq != NULL) {
3548     if (gbref != NULL) {
3549       gbref->journal = StringSaveNoNull (str);
3550       tmp = gbref->journal;
3551       if (tmp != NULL) {
3552         ch = *tmp;
3553         while (ch != '\0') {
3554           if (ch == '\n' || ch == '\r' || ch == '\t') {
3555             *tmp = ' ';
3556           }
3557           tmp++;
3558           ch = *tmp;
3559         }
3560         TrimSpacesAroundString (gbref->journal);
3561       }
3562     }
3563   }
3564 
3565   MemFree (str);
3566   if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3567     FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3568   } else {
3569     FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RL");
3570   }
3571 
3572   if (gbseq != NULL) {
3573     if (gbref != NULL) {
3574       if (pdp != NULL) {
3575         for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
3576           if (vnp->choice == PUB_Article) {
3577             cap = (CitArtPtr) vnp->data.ptrvalue;
3578             if (cap != NULL) {
3579               for (ids = cap->ids; ids != NULL; ids = ids->next) {
3580                 if (ids->choice == ARTICLEID_DOI) {
3581                   tmp = (CharPtr) ids->data.ptrvalue;
3582                   if (StringDoesHaveText (tmp)) {
3583                     gxp = GBXrefNew ();
3584                     if (gxp != NULL) {
3585                       gxp->dbname = StringSave ("doi");
3586                       gxp->id = StringSave (tmp);
3587                       gxp->next = gbref->xref;
3588                       gbref->xref = gxp;
3589                     }
3590                   }
3591                 }
3592               }
3593             }
3594           }
3595         }
3596       }
3597     }
3598   }
3599   
3600   /* print muid */
3601   FFRecycleString(ajp, temp);
3602   temp = FFGetString(ajp);
3603   
3604   pmid = GetPmid (pdp);
3605   muid = GetMuid (pdp);
3606 
3607   if (pmid == 0 && muid > 0) {
3608     FFStartPrint (temp, afp->format, 2, 12, "MEDLINE", 12, 5, 5, "RX", FALSE);
3609 
3610     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3611       FF_www_muid (ajp, temp, muid);
3612       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3613     } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3614       sprintf (buf, "MEDLINE; %ld.", (long) muid);
3615       FFAddOneString (temp, buf, FALSE, FALSE, TILDE_TO_SPACES);
3616       FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RX");
3617     }
3618   }
3619 
3620   FFRecycleString(ajp, temp);
3621   temp = FFGetString(ajp);
3622   
3623   if (pmid > 0) {
3624     FFStartPrint (temp, afp->format, 3, 12, "PUBMED", 12, 5, 5, "RX", FALSE);
3625     if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3626       FF_www_muid (ajp, temp, pmid);
3627       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3628     } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
3629       sprintf (buf, "PUBMED; %ld.", (long) pmid);
3630       FFAddOneString (temp, buf, FALSE, FALSE, TILDE_TO_SPACES);
3631       FFLineWrap(ffstring, temp, 5, 5, ASN2FF_EMBL_MAX, "RX");
3632     }
3633   }
3634   FFRecycleString(ajp, temp);
3635 
3636   if (gbseq != NULL) {
3637     if (gbref != NULL) {
3638       gbref->pubmed = pmid;
3639     }
3640   }
3641 
3642   if (pdp == NULL) {
3643 
3644     if (csp != NULL) {
3645       if (! StringHasNoText (csp->descr)) {
3646         FFRecycleString(ajp, temp);
3647         temp = FFGetString(ajp);
3648  
3649         ValNodeCopyStr (&remarks, 0, csp->descr);
3650         FFStartPrint (temp, afp->format, 2, 12, "REMARK", 12, 5, 5, NULL, FALSE);
3651         /* FFAddOneString (temp, csp->descr, FALSE, TRUE, TILDE_EXPAND); */
3652         AddCommentWithURLlinks(ajp, temp, NULL, csp->descr, NULL);
3653         FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3654       }
3655     }
3656 
3657     str = FFToCharPtr(ffstring);
3658 
3659     if (gbseq != NULL) {
3660       if (gbref != NULL) {
3661         AddReferenceToGbseq (gbseq, gbref, str, rbp, bsp);
3662       }
3663     }
3664 
3665     FFRecycleString(ajp, ffstring);
3666     FFRecycleString(ajp, temp);
3667     if (pep != NULL) {
3668       PubmedEntryFree (pep);
3669     }
3670     if (pdpcopy != NULL) {
3671       PubdescFree (pdpcopy);
3672     }
3673 
3674     return str;
3675   }
3676 
3677 
3678   /* !!! remainder of fields are only for GenBank !!! */
3679 
3680   if (afp->format == GENBANK_FMT || afp->format == GENPEPT_FMT) {
3681 
3682     prefix = "REMARK";
3683 
3684     cpp = NULL;
3685     for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
3686       if (vnp->choice == PUB_Patent) {
3687         cpp = (CitPatPtr) vnp->data.ptrvalue;
3688       }
3689     }
3690     if (cpp != NULL && ajp != NULL && ajp->mode == ENTREZ_MODE) {
3691       if (StringCmp (cpp->country, "US") == 0) {
3692         if (StringDoesHaveText (cpp->number)) {
3693           FFRecycleString(ajp, temp);
3694           temp = FFGetString(ajp);
3695 
3696           sprintf (buf, "CAMBIA Patent Lens: %s %s", cpp->country, cpp->number);
3697           if (remprefix != NULL) {
3698             ValNodeCopyStr (&remarks, 0, remprefix);
3699           }
3700           ValNodeCopyStr (&remarks, 0, buf);
3701           remprefix = "; ";
3702           FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3703           if (GetWWW (ajp)) {
3704             sprintf (buf, "CAMBIA Patent Lens: %s ", cpp->country);
3705             FFAddOneString (temp, buf, FALSE, FALSE, TILDE_EXPAND);
3706             FFAddOneString (temp, "<a href=\"", FALSE, FALSE, TILDE_EXPAND);
3707             FFAddOneString (temp, link_cambia, FALSE, FALSE, TILDE_EXPAND);
3708             FFAddOneString (temp, cpp->country, FALSE, FALSE, TILDE_EXPAND);
3709             FFAddOneString (temp, cpp->number, FALSE, FALSE, TILDE_EXPAND);
3710             FFAddOneString (temp, "#list\">", FALSE, FALSE, TILDE_EXPAND);
3711             FFAddOneString (temp, cpp->number, FALSE, FALSE, TILDE_EXPAND);
3712             FFAddOneString (temp, "</a>", FALSE, FALSE, TILDE_EXPAND);
3713           } else {
3714             FFAddOneString (temp, buf, FALSE, FALSE, TILDE_EXPAND);
3715           }
3716           FFLineWrap (ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3717           prefix = NULL;
3718         }
3719       }
3720     }
3721 
3722     if (pdp->comment != NULL) {
3723       for (i = 0, notFound = TRUE; notFound && remarksText [i] != NULL; i++) {
3724         if (StringCmp (pdp->comment, remarksText [i]) == 0) {
3725           notFound = FALSE;
3726         }
3727       }
3728       if (notFound) {
3729         FFRecycleString(ajp, temp);
3730         temp = FFGetString(ajp);
3731 
3732         if (remprefix != NULL) {
3733           ValNodeCopyStr (&remarks, 0, remprefix);
3734         }
3735         ValNodeCopyStr (&remarks, 0, pdp->comment);
3736         remprefix = "; ";
3737         FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3738         FFAddOneString (temp, pdp->comment, FALSE, TRUE, TILDE_EXPAND);
3739         /* AddCommentWithURLlinks(ajp, temp, NULL, pdp->comment, NULL); */
3740         FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3741         prefix = NULL;
3742 
3743         if (gbseq != NULL) {
3744           if (gbref != NULL) {
3745             /*
3746             gbref->remark = StringSave (pdp->comment);
3747             */
3748           }
3749         }
3750 
3751       }
3752     }
3753 
3754     gibbsq = 0;
3755     for (sip = bsp->id; sip != NULL; sip = sip->next) {
3756       if (sip->choice == SEQID_GIBBSQ) {
3757         gibbsq = sip->data.intvalue;
3758       }
3759     }
3760     csp = NULL;
3761     for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
3762       if (vnp->choice == PUB_Sub) {
3763         csp = (CitSubPtr) vnp->data.ptrvalue;
3764       }
3765     }
3766     if (gibbsq > 0 /* && csp == NULL */) {
3767       FFRecycleString(ajp, temp);
3768       temp = FFGetString(ajp);
3769 
3770       sprintf (buf, "GenBank staff at the National Library of Medicine created this entry [NCBI gibbsq %ld] from the original journal article.", (long) gibbsq);
3771       if (remprefix != NULL) {
3772         ValNodeCopyStr (&remarks, 0, remprefix);
3773       }
3774       ValNodeCopyStr (&remarks, 0, buf);
3775       remprefix = "; ";
3776       FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3777       FFAddOneString (temp, buf, FALSE, FALSE, TILDE_EXPAND);
3778       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3779       prefix = NULL;
3780 
3781       /* gibbsq comment section (fields may be copied from degenerate pubdesc) */
3782 
3783       str = pdp->fig;
3784       if (StringHasNoText (str)) {
3785         str = irp->fig;
3786       }
3787       if (! StringHasNoText (str)) {
3788         FFRecycleString(ajp, temp);
3789         temp = FFGetString(ajp);
3790 
3791         sprintf (buf, "This sequence comes from %s", str);
3792         if (remprefix != NULL) {
3793           ValNodeCopyStr (&remarks, 0, remprefix);
3794         }
3795         ValNodeCopyStr (&remarks, 0, buf);
3796         remprefix = "; ";
3797         FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3798         FFAddOneString (temp, buf, TRUE, TRUE, TILDE_EXPAND);
3799         FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3800         prefix = NULL;
3801       }
3802 
3803       if (pdp->poly_a || irp->poly_a) {
3804         FFRecycleString(ajp, temp);
3805         temp = FFGetString(ajp);
3806 
3807         if (remprefix != NULL) {
3808           ValNodeCopyStr (&remarks, 0, remprefix);
3809         }
3810         ValNodeCopyStr (&remarks, 0, "Polyadenylate residues occurring in the figure were omitted from the sequence.");
3811         remprefix = "; ";
3812         FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3813         FFAddOneString (temp, "Polyadenylate residues occurring in the figure were omitted from the sequence.", TRUE, TRUE, TILDE_EXPAND);
3814         FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3815         prefix = NULL;
3816       }
3817 
3818       str = pdp->maploc;
3819       if (StringHasNoText (str)) {
3820         str = irp->maploc;
3821       }
3822       if (! StringHasNoText (str)) {
3823         FFRecycleString(ajp, temp);
3824         temp = FFGetString(ajp);
3825 
3826         sprintf (buf, "Map location: %s", str);
3827         if (remprefix != NULL) {
3828           ValNodeCopyStr (&remarks, 0, remprefix);
3829         }
3830         ValNodeCopyStr (&remarks, 0, buf);
3831         remprefix = "; ";
3832         FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3833         FFAddOneString (temp, buf, TRUE, TRUE, TILDE_EXPAND);
3834         FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3835         prefix = NULL;
3836       }
3837 
3838     }
3839 
3840     for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
3841       if (vnp->choice == PUB_Article) {
3842         cap = (CitArtPtr) vnp->data.ptrvalue;
3843         if (cap != NULL && cap->from == 1) {
3844           cjp = (CitJourPtr) cap->fromptr;
3845           if (cjp != NULL) {
3846             imp = cjp->imp;
3847             if (imp != NULL) {
3848               crp = imp->retract;
3849               if (crp != NULL) {
3850                 if (crp->type == 1) {
3851                   FFRecycleString(ajp, temp);
3852                   temp = FFGetString(ajp);
3853 
3854                   len = StringLen (crp->exp) + 30;
3855                   str = MemNew (sizeof (Char) * len);
3856                   if (str != NULL) {
3857                     StringCpy (str, "Retracted");
3858                     if (StringDoesHaveText (crp->exp)) {
3859                       StringCat (str, ":[");
3860                       StringCat (str, crp->exp);
3861                       StringCat (str, "]");
3862                     }
3863                     if (remprefix != NULL) {
3864                       ValNodeCopyStr (&remarks, 0, remprefix);
3865                     }
3866                     ValNodeCopyStr (&remarks, 0, str);
3867                     remprefix = "; ";
3868                     str = MemFree (str);
3869                   }
3870                   FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3871                   FFAddOneString (temp, "Retracted", FALSE, FALSE, TILDE_TO_SPACES);
3872                   if (StringDoesHaveText (crp->exp)) {
3873                     FFAddTextToString (temp, ":[", crp->exp, "]", FALSE, TRUE, TILDE_EXPAND);
3874                   }
3875                   FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3876                   prefix = NULL;
3877                 } else if (crp->type == 3) {
3878                   FFRecycleString(ajp, temp);
3879                   temp = FFGetString(ajp);
3880 
3881                   len = StringLen (crp->exp) + 30;
3882                   str = MemNew (sizeof (Char) * len);
3883                   if (str != NULL) {
3884                     StringCpy (str, "Erratum");
3885                     if (StringDoesHaveText (crp->exp)) {
3886                       StringCat (str, ":[");
3887                       StringCat (str, crp->exp);
3888                       StringCat (str, "]");
3889                     }
3890                     if (remprefix != NULL) {
3891                       ValNodeCopyStr (&remarks, 0, remprefix);
3892                     }
3893                     ValNodeCopyStr (&remarks, 0, str);
3894                     remprefix = "; ";
3895                     str = MemFree (str);
3896                   }
3897                   FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3898                   FFAddOneString (temp, "Erratum", FALSE, FALSE, TILDE_TO_SPACES);
3899                   if (StringDoesHaveText (crp->exp)) {
3900                     FFAddTextToString (temp, ":[", crp->exp, "]", FALSE, TRUE, TILDE_EXPAND);
3901                   }
3902                   FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3903                   prefix = NULL;
3904                 } else if (crp->type == 4) {
3905                   FFRecycleString(ajp, temp);
3906                   temp = FFGetString(ajp);
3907 
3908                   len = StringLen (crp->exp) + 30;
3909                   str = MemNew (sizeof (Char) * len);
3910                   if (str != NULL) {
3911                     StringCpy (str, "Correction");
3912                     if (StringDoesHaveText (crp->exp)) {
3913                       StringCat (str, " to:[");
3914                       StringCat (str, crp->exp);
3915                       StringCat (str, "]");
3916                     }
3917                     if (remprefix != NULL) {
3918                       ValNodeCopyStr (&remarks, 0, remprefix);
3919                     }
3920                     ValNodeCopyStr (&remarks, 0, str);
3921                     remprefix = "; ";
3922                     str = MemFree (str);
3923                   }
3924                   FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3925                   FFAddOneString (temp, "Correction", FALSE, FALSE, TILDE_TO_SPACES);
3926                   if (StringDoesHaveText (crp->exp)) {
3927                     FFAddTextToString (temp, " to:[", crp->exp, "]", FALSE, TRUE, TILDE_EXPAND);
3928                   }
3929                   FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3930                   prefix = NULL;
3931                 }
3932               }
3933             }
3934           }
3935         }
3936       } else if (vnp->choice == PUB_Sub) {
3937         csp = (CitSubPtr) vnp->data.ptrvalue;
3938         if (csp != NULL) {
3939           if (! StringHasNoText (csp->descr)) {
3940             FFRecycleString(ajp, temp);
3941             temp = FFGetString(ajp);
3942 
3943             if (remprefix != NULL) {
3944               ValNodeCopyStr (&remarks, 0, remprefix);
3945             }
3946             ValNodeCopyStr (&remarks, 0, csp->descr);
3947             remprefix = "; ";
3948             FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3949             /* FFAddOneString (temp, csp->descr, FALSE, TRUE, TILDE_EXPAND); */
3950             AddCommentWithURLlinks(ajp, temp, NULL, csp->descr, NULL);
3951             FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3952             prefix = NULL;
3953           }
3954         }
3955       }
3956     }
3957 
3958     pubstatnote = NULL;
3959     pubstatus = GetJournalPubStatus (pdp);
3960     if (pubstatus == 3) {
3961       pubstatnote = "Publication Status: Online-Only";
3962     } else if (pubstatus == 10) {
3963       pubstatnote = "Publication Status: Available-Online prior to print";
3964     }
3965     if (StringDoesHaveText (pubstatnote)) {
3966       FFRecycleString(ajp, temp);
3967       temp = FFGetString(ajp);
3968 
3969       if (remprefix != NULL) {
3970         ValNodeCopyStr (&remarks, 0, remprefix);
3971       }
3972       ValNodeCopyStr (&remarks, 0, pubstatnote);
3973       remprefix = "; ";
3974       FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
3975       FFAddOneString (temp, pubstatnote, FALSE, FALSE, TILDE_EXPAND);
3976       FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
3977       prefix = NULL;
3978     }
3979 
3980   }
3981 
3982   str = FFToCharPtr(ffstring);
3983 
3984   if (gbseq != NULL) {
3985     if (gbref != NULL) {
3986       if (remarks != NULL) {
3987         gbref->remark = MergeFFValNodeStrs (remarks);
3988       }
3989 
3990       AddReferenceToGbseq (gbseq, gbref, str, rbp, bsp);
3991     }
3992   }
3993   ValNodeFreeData (remarks);
3994 
3995   FFRecycleString(ajp, ffstring);
3996   FFRecycleString(ajp, temp);
3997   if (pep != NULL) {
3998     PubmedEntryFree (pep);
3999   }
4000   if (pdpcopy != NULL) {
4001     PubdescFree (pdpcopy);
4002   }
4003 
4004   return str;
4005 }
4006 
4007 
4008 

source navigation ]   [ diff markup ]   [ identifier search ]   [ freetext search ]   [ file search ]  

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.