 .gitignore                                         |    6 +
 VERSION                                            |    2 +-
 access/ent2api.c                                   |    7 +-
 access/makeacc.unx                                 |    2 +-
 access/mla2api.c                                   |    3 +-
 access/objtax3.c                                   |  131 +-
 access/objtax3.h                                   |   23 +-
 access/pmfapi.c                                    |   20 +-
 access/tax3api.c                                   |  192 +-
 access/tax3api.h                                   |   15 +-
 access/taxon3.asn                                  |    7 +-
 algo/blast/api/blast_returns.c                     |   18 +-
 algo/blast/api/blast_seqalign.c                    |   10 +-
 algo/blast/api/blast_seqalign.h                    |    6 +-
 .../composition_adjustment/compo_mode_condition.h  |    5 +-
 .../composition_adjustment.c                       |  121 +-
 .../composition_adjustment/composition_constants.h |   19 +-
 algo/blast/composition_adjustment/redo_alignment.h |    9 +-
 algo/blast/core/aa_ungapped.c                      |   32 +-
 algo/blast/core/blast_aalookup.c                   |    6 +-
 algo/blast/core/blast_aascan.c                     |   52 +-
 algo/blast/core/blast_aascan.h                     |    6 +-
 algo/blast/core/blast_def.h                        |   17 +-
 algo/blast/core/blast_engine.c                     |  483 +-
 algo/blast/core/blast_filter.c                     |   41 +-
 algo/blast/core/blast_filter.h                     |    5 +-
 algo/blast/core/blast_gapalign.c                   |   32 +-
 algo/blast/core/blast_hits.c                       |  161 +-
 algo/blast/core/blast_hits.h                       |   43 +-
 algo/blast/core/blast_hspstream.c                  |   51 +-
 algo/blast/core/blast_hspstream.h                  |    3 +-
 algo/blast/core/blast_itree.c                      |   69 +-
 algo/blast/core/blast_itree.h                      |    5 +-
 algo/blast/core/blast_kappa.c                      |   12 +-
 algo/blast/core/blast_message.c                    |   11 +-
 algo/blast/core/blast_message.h                    |    5 +-
 algo/blast/core/blast_nascan.c                     |  968 ++---
 algo/blast/core/blast_nascan.h                     |    5 +-
 algo/blast/core/blast_options.c                    |   14 +-
 algo/blast/core/blast_options.h                    |    6 +-
 algo/blast/core/blast_parameters.c                 |   19 +-
 algo/blast/core/blast_psi_priv.h                   |   42 +-
 algo/blast/core/blast_seg.c                        |  123 +-
 algo/blast/core/blast_setup.c                      |   24 +-
 algo/blast/core/blast_stat.c                       |   31 +-
 algo/blast/core/blast_stat.h                       |   10 +-
 algo/blast/core/blast_traceback.c                  |   19 +-
 algo/blast/core/blast_util.c                       |   89 +-
 algo/blast/core/blast_util.h                       |   28 +-
 algo/blast/core/greedy_align.h                     |    6 +-
 algo/blast/core/hspfilter_collector.c              |    7 +-
 algo/blast/core/index_ungapped.c                   |    6 +-
 algo/blast/core/lookup_wrap.h                      |    8 +-
 algo/blast/core/masksubj.inl                       |   43 +-
 algo/blast/core/na_ungapped.c                      |  972 ++--
 algo/blast/core/na_ungapped.h                      |    4 +-
 algo/blast/core/split_query.c                      |   13 +-
 algo/blast/core/split_query.h                      |    5 +-
 api/aceread.c                                      |   55 +-
 api/aceread.h                                      |    7 +-
 api/alignmgr2.h                                    |    7 +-
 api/alignval.c                                     |   23 +-
 api/asn2gnb1.c                                     |  266 +-
 api/asn2gnb2.c                                     |  499 ++-
 api/asn2gnb3.c                                     |  418 +-
 api/asn2gnb4.c                                     |  194 +-
 api/asn2gnb5.c                                     |  155 +-
 api/asn2gnb6.c                                     |  996 +++-
 api/asn2gnbi.h                                     |   20 +-
 api/asn2gnbk.h                                     |   12 +-
 api/asn2gnbp.h                                     |    7 +-
 api/ecnum_ambiguous.inc                            |  702 +++
 api/ecnum_deleted.inc                              |  199 +
 api/ecnum_replaced.inc                             |  624 +++
 api/ecnum_specific.inc                             | 4292 +++++++++++++++
 api/edutil.c                                       |  101 +-
 api/edutil.h                                       |   19 +-
 api/findrepl.c                                     |   13 +
 api/gather.c                                       |   26 +-
 api/gbftdef.h                                      |    6 +-
 api/gbftglob.c                                     |  172 +-
 api/gbparint.c                                     |    5 +-
 api/macroapi.c                                     | 4670 +++++++++++++++--
 api/macroapi.h                                     |   60 +-
 api/objmgr.c                                       |   55 +-
 api/objmgr.h                                       |  181 +-
 api/salstruc.c                                     |  354 +--
 api/salutil.c                                      |  136 +-
 api/salutil.h                                      |    6 +-
 api/seqmgr.c                                       |  195 +-
 api/seqmgr.h                                       |    7 +-
 api/seqport.c                                      |   48 +-
 api/seqport.h                                      |    5 +-
 api/sequtil.c                                      | 1506 +++++-
 api/sequtil.h                                      |    6 +-
 api/sqnutil1.c                                     | 1559 +++++-
 api/sqnutil2.c                                     | 3932 +++++++++++++-
 api/sqnutil3.c                                     | 5539 ++++++++++++++++----
 api/sqnutil4.c                                     | 2983 ++++++++++-
 api/sqnutils.h                                     |  238 +-
 api/subutil.c                                      |  246 +-
 api/subutil.h                                      |   32 +-
 api/tofasta.c                                      |  344 +-
 api/tofasta.h                                      |   18 +-
 api/valapi.c                                       |  551 ++-
 api/valapi.h                                       |   20 +-
 api/valid.c                                        | 4431 ++++++++++------
 api/valid.h                                        |    7 +-
 api/valid.msg                                      |   66 +
 api/validerr.h                                     |   21 +
 asn/asn.all                                        |  729 +++-
 asn/gbseq.asn                                      |   81 +-
 asn/insdseq.asn                                    |   86 +-
 asn/seq.asn                                        |    4 +-
 asn/seqfeat.asn                                    |  463 ++-
 asn/seqloc.asn                                     |    4 +-
 asn/valid.asn                                      |   30 +-
 asnlib/asn.h                                       |  104 +-
 asnlib/asncode.c                                   |   15 +-
 asnlib/asngenob.c                                  |  111 +-
 asnlib/asnout.c                                    |    7 +-
 asnlib/asnprint.c                                  |  118 +-
 asnlib/asntool.c                                   |   12 +-
 asnlib/asntool.h                                   |    6 +-
 biostruc/cdd/cdd.asn                               |   23 +-
 checkout.date                                      |    2 +-
 connect/ncbi_ansi_ext.h                            |   27 +-
 connect/ncbi_base64.c                              |  204 +
 connect/ncbi_base64.h                              |   99 +
 connect/ncbi_buffer.c                              |   33 +-
 connect/ncbi_comm.h                                |   58 +-
 connect/ncbi_config.h                              |    6 +-
 connect/ncbi_connection.c                          |  391 +-
 connect/ncbi_connection.h                          |  106 +-
 connect/ncbi_connector.h                           |   39 +-
 connect/ncbi_connutil.c                            |  600 ++-
 connect/ncbi_connutil.h                            |   69 +-
 connect/ncbi_file_connector.c                      |  191 +-
 connect/ncbi_ftp_connector.c                       | 1130 +++-
 connect/ncbi_ftp_connector.h                       |   25 +-
 connect/ncbi_host_info.h                           |    8 +-
 connect/ncbi_http_connector.c                      |  536 ++-
 connect/ncbi_memory_connector.c                    |   61 +-
 connect/ncbi_priv.c                                |   28 +-
 connect/ncbi_priv.h                                |   33 +-
 connect/ncbi_sendmail.c                            |   24 +-
 connect/ncbi_sendmail.h                            |   81 +-
 connect/ncbi_server_info.c                         |   29 +-
 connect/ncbi_service.c                             |   70 +-
 connect/ncbi_service.h                             |   10 +-
 connect/ncbi_service_connector.c                   |   61 +-
 connect/ncbi_socket.c                              | 2640 ++++++----
 connect/ncbi_socket.h                              |  198 +-
 connect/ncbi_socket_connector.c                    |  180 +-
 connect/ncbi_socket_connector.h                    |   32 +-
 connect/ncbi_socketp.h                             |   61 +-
 connect/ncbi_types.h                               |    6 +-
 connect/ncbi_util.c                                |   91 +-
 connect/ncbi_util.h                                |   43 +-
 connect/ncbi_version.c                             |   61 +
 connect/{version.h => ncbi_version.h}              |   54 +-
 connect/test/http_connector_hit.c                  |   99 +-
 connect/test/ncbi_conntest.c                       |  105 +-
 connect/test/socket_io_bouncer.c                   |    8 +-
 connect/test/test_assert.h                         |    2 +-
 connect/test/test_assert_impl.h                    |   31 +-
 connect/test/test_ncbi_connutil_hit.c              |   58 +-
 connect/test/test_ncbi_connutil_misc.c             |   56 +-
 connect/test/test_ncbi_core.c                      |    4 +-
 connect/test/test_ncbi_disp.c                      |    7 +-
 connect/test/test_ncbi_dsock.c                     |   17 +-
 connect/test/test_ncbi_file_connector.c            |    8 +-
 connect/test/test_ncbi_ftp_connector.c             |  127 +-
 connect/test/test_ncbi_heapmgr.c                   |   70 +-
 connect/test/test_ncbi_http_connector.c            |   72 +-
 connect/test/test_ncbi_http_get.c                  |   52 +-
 connect/test/test_ncbi_memory_connector.c          |   31 +-
 connect/test/test_ncbi_sendmail.c                  |   29 +-
 connect/test/test_ncbi_service_connector.c         |  148 +-
 connect/test/test_ncbi_socket.c                    |   94 +-
 connect/test/test_ncbi_socket_connector.c          |   17 +-
 connect/urlquery.c                                 |  203 +-
 connect/urlquery.h                                 |   20 +-
 corelib/ncbiargs.c                                 |    9 +
 corelib/ncbienv.c                                  |   31 +-
 corelib/ncbierr.c                                  |    9 +-
 corelib/ncbifile.c                                 |    8 +-
 corelib/ncbilcl.lnx                                |    6 +-
 corelib/ncbimisc.c                                 |  151 +-
 corelib/ncbimisc.h                                 |  102 +-
 corelib/ncbimsg.c                                  |   10 +-
 corelib/ncbiprop.h                                 |    8 +-
 corelib/ncbistr.c                                  |  228 +-
 corelib/ncbistr.h                                  |   99 +-
 corelib/ncbiwin.h                                  |    8 +-
 ctools/asn_connection.c                            |   52 +-
 ctools/asn_connection.h                            |   11 +-
 debian/.gitignore                                  |   18 +
 debian/changelog                                   |   26 +
 debian/control                                     |    9 +-
 debian/libncbi6.symbols                            |  443 ++-
 debian/libvibrant6a.symbols                        |   34 +-
 debian/ncbi-tools-bin.install                      |    1 +
 debian/rules                                       |   20 +-
 demo/.BLAST_VERSION                                |    2 +-
 demo/aceread_tst.c                                 |   35 +-
 demo/asn2all.c                                     |  103 +-
 demo/asn2fsa.c                                     |    4 +-
 demo/asn2gb.c                                      |   42 +-
 demo/asnbarval.c                                   |   12 +-
 demo/asndisc.c                                     |   58 +-
 demo/asnmacro.c                                    |    4 +-
 demo/asnval.c                                      |  192 +-
 demo/cleanasn.c                                    | 5496 +++++++++++++++++++-
 demo/cspeedtest.c                                  |  116 +-
 demo/entrez2.c                                     |    4 +-
 demo/gene2xml.c                                    |    8 +-
 demo/scantest.c                                    |   44 +-
 demo/src_chk.c                                     |  959 +++-
 demo/tbl2asn.c                                     |  785 +++-
 demo/tbl_chk.c                                     | 1459 ++++++
 desktop/asn2graphic.c                              |   19 +-
 desktop/biosrc.c                                   |   48 +-
 desktop/bspview.c                                  |   72 +-
 desktop/bspview.h                                  |    5 +-
 desktop/cdrgn.c                                    | 1469 +++---
 desktop/cdrgn.h                                    |    8 +-
 desktop/dlgutil1.c                                 |  693 +++-
 desktop/dlgutil2.c                                 |  161 +-
 desktop/dlogutil.h                                 |   11 +-
 desktop/e2docsum.c                                 |   11 +-
 desktop/e2trmlst.c                                 |    6 +-
 desktop/gbfview.c                                  |   40 +-
 desktop/import.c                                   |   14 +-
 desktop/macrodlg.c                                 | 3754 +++++++-------
 desktop/macrodlg.h                                 |   24 +-
 desktop/pubdesc.c                                  |  343 ++-
 desktop/pubdesc.h                                  |    5 +-
 desktop/salpanel.c                                 |    6 +-
 desktop/salsa.c                                    |    3 +-
 desktop/seqpanel.c                                 |   87 +-
 desktop/seqpanel.h                                 |    9 +-
 desktop/seqsub.c                                   |    8 +-
 desktop/valdlg.c                                   |    5 +-
 desktop/vsmfile.c                                  |  129 +-
 desktop/vsmfile.h                                  |    3 +-
 desktop/vsmutil.c                                  |  107 +-
 desktop/vsmutil.h                                  |   20 +-
 doc/FAQ.txt                                        |   31 +
 doc/blast/blast.html                               |   46 +-
 doc/blast/blastall.html                            |    6 +-
 doc/dispatcher.html                                |    8 +-
 doc/firewall.html                                  |   24 +-
 doc/fwd_check.sh                                   |   65 +-
 doc/gene2xml.txt                                   |   19 +
 doc/images/affil.png                               |  Bin 6736 -> 6736 bytes
 doc/images/annot.png                               |  Bin 7264 -> 7264 bytes
 doc/images/authors.png                             |  Bin 7926 -> 7926 bytes
 doc/images/cds_edit.png                            |  Bin 11612 -> 11612 bytes
 doc/images/contact.png                             |  Bin 6311 -> 6311 bytes
 doc/images/desktop.png                             |  Bin 16275 -> 16275 bytes
 doc/images/format.png                              |  Bin 6762 -> 6762 bytes
 doc/images/genbank.png                             |  Bin 28763 -> 28763 bytes
 doc/images/graphic.png                             |  Bin 7651 -> 7651 bytes
 doc/images/loc_page.png                            |  Bin 8587 -> 8587 bytes
 doc/images/net_cfg.png                             |  Bin 4891 -> 4891 bytes
 doc/images/nucaln.png                              |  Bin 8672 -> 8672 bytes
 doc/images/nucset.png                              |  Bin 10779 -> 10779 bytes
 doc/images/nucsing1.png                            |  Bin 10516 -> 10516 bytes
 doc/images/nucsing2.png                            |  Bin 11381 -> 11381 bytes
 doc/images/organism.png                            |  Bin 10958 -> 10958 bytes
 doc/images/props_pg.png                            |  Bin 8444 -> 8444 bytes
 doc/images/protein1.png                            |  Bin 10712 -> 10712 bytes
 doc/images/protein2.png                            |  Bin 11731 -> 11731 bytes
 doc/images/sequence.png                            |  Bin 17497 -> 17497 bytes
 doc/images/update.png                              |  Bin 15403 -> 15403 bytes
 doc/images/validate.png                            |  Bin 20211 -> 20211 bytes
 doc/images/welcome.png                             |  Bin 8176 -> 8176 bytes
 doc/man/asn2all.1                                  |    4 +-
 doc/man/asndisc.1                                  |  188 +
 doc/man/asntool.1                                  |    6 +-
 doc/man/asnval.1                                   |    9 +-
 doc/man/cleanasn.1                                 |  143 +-
 doc/man/tbl2asn.1                                  |   12 +-
 errmsg/flat2asn.msg                                |  326 --
 errmsg/indx_err.msg                                |  106 -
 errmsg/medarch.msg                                 |   13 -
 errmsg/valid.msg                                   |   66 +
 link/mswin/ncbilogo.ico                            |  Bin 25214 -> 285478 bytes
 link/mswin/streamer.rc                             |   10 +
 make/makeall.unx                                   |   13 +-
 make/makedis.csh                                   |    8 +-
 make/makenet.unx                                   |   53 +-
 network/id2arch/id2.asn                            |    7 +-
 network/id2arch/id2.c                              |   16 +-
 network/id2arch/id2.patch                          |  143 +
 network/id2arch/makefile                           |    2 +
 network/id2arch/seqsplit.asn                       |    5 +-
 object/objalign.c                                  |   26 +-
 object/objbibli.c                                  |    7 +-
 object/objfdef.c                                   |   16 +-
 object/objfdef.h                                   |    5 +-
 object/objfeat.c                                   | 3068 +++++++++++-
 object/objfeat.h                                   |  337 ++-
 object/objgbseq.c                                  | 1197 +++--
 object/objgbseq.h                                  |  225 +-
 object/objgen.c                                    |  125 +-
 object/objgen.h                                    |   63 +-
 object/objinsdseq.c                                | 1197 +++--
 object/objinsdseq.h                                |  225 +-
 object/objmacro.c                                  | 1316 +++++-
 object/objmacro.h                                  |  127 +-
 object/objmedli.c                                  |    9 +-
 object/objpub.c                                    |   22 +-
 object/objvalid.c                                  |  352 ++-
 object/objvalid.h                                  |   55 +-
 platform/darwin-univ.ncbi.mk                       |    7 +-
 platform/darwin.ncbi.mk                            |    5 +-
 platform/linux.ncbi.mk                             |    4 +-
 platform/linux64.ncbi.mk                           |    4 +-
 platform/linux64_icc9.ncbi.mk                      |    4 +-
 platform/linux_icc.ncbi.mk                         |    4 +-
 platform/linux_icc9.ncbi.mk                        |    4 +-
 sequin/macro.asn                                   |   91 +-
 sequin/sbtedit.c                                   |    4 +-
 sequin/sequin.h                                    |   94 +-
 sequin/sequin1.c                                   |  319 +-
 sequin/sequin10.c                                  | 3335 +++++++++++-
 sequin/sequin2.c                                   |  240 +-
 sequin/sequin3.c                                   | 1631 +++++-
 sequin/sequin4.c                                   | 1727 ++++++-
 sequin/sequin5.c                                   | 1405 ++---
 sequin/sequin6.c                                   |  649 ++-
 sequin/sequin7.c                                   | 1729 ++++++-
 sequin/sequin8.c                                   | 1457 +++++-
 sequin/sequin9.c                                   |   71 +-
 sequin/sequiny.c                                   |    4 +-
 sequin/streamer.c                                  | 1240 +++++
 tools/blfmtutl.c                                   |   15 +-
 tools/readdb.c                                     |  118 +-
 tools/toasn3.c                                     |  119 +-
 tools/toasn3.h                                     |   14 +-
 tools/toporg.c                                     |  464 ++-
 tools/toporg.h                                     |    4 +-
 util/creaders/alnread.c                            |  128 +-
 vibrant/mapping.c                                  |   15 +-
 vibrant/ncbidraw.c                                 |    8 +-
 vibrant/vibutils.c                                 |    9 +-
 vibrant/vibwndws.c                                 |   62 +-
 .../designs/cubby/storedsearch/Templates/edit.gif  |  Bin 138 -> 138 bytes
 .../designs/cubby/storedsearch/Templates/mail.gif  |  Bin 96 -> 96 bytes
 .../designs/cubby/storedsearch/Templates/plus.gif  |  Bin 135 -> 135 bytes
 .../designs/cubby/storedsearch/Templates/run.gif   |  Bin 139 -> 139 bytes
 .../cubby/storedsearch/Templates/whatsnew.gif      |  Bin 824 -> 824 bytes
 .../designs/cubby/storedsearch/Templates/x.gif     |  Bin 132 -> 132 bytes
 355 files changed, 73998 insertions(+), 18797 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..460a322
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+bin
+build
+include
+lib
+shlib
+*-stamp
diff --git a/VERSION b/VERSION
index 84dcfd0..a9902d7 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-Sun Aug 9 10:13:45 EDT 2009
+Sun Aug 8 10:13:55 EDT 2010
diff --git a/access/ent2api.c b/access/ent2api.c
index 7c5125f..8551999 100644
--- a/access/ent2api.c
+++ b/access/ent2api.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/29/99
 *
-* $Revision: 1.114 $
+* $Revision: 1.117 $
 *
 * File Description: 
 *
@@ -1079,8 +1079,10 @@ NLM_EXTERN Boolean ValidateEntrez2InfoPtrEx (
           StringICmp (db, "nuccore") != 0 &&
           StringICmp (db, "nucgss") != 0 &&
           StringICmp (db, "nucest") != 0 &&
+          StringICmp (db, "seqannot") != 0 &&
           StringICmp (db, "toolkit") != 0 &&
-          StringICmp (db, "blastdbinfo") != 0) {
+          StringICmp (db, "blastdbinfo") != 0 &&
+          StringICmp (db, "virus") != 0) {
         sprintf (buf, "Database %s has no links", db);
         ValNodeCopyStr (head, 0, buf);
         rsult = FALSE;
@@ -1352,6 +1354,7 @@ NLM_EXTERN Boolean ValidateEntrez2InfoPtrEx (
             } else if (StringICmp (last, "SID") == 0 && StringICmp (str, "SidExternalID") == 0) {
             } else if (StringICmp (last, "Platform") == 0 && StringICmp (str, "Platform Reporter Type") == 0) {
             } else if (StringICmp (last, "Database") == 0 && StringICmp (str, "Database Name") == 0) {
+            } else if (StringICmp (last, "Date") == 0 && StringICmp (str, "Date Discontinued") == 0) {
             } else {
               sprintf (buf, "Menu names %s [%s] and %s [%s] may be unintended variants", last, dbnames [lastvnp->choice], str, dbnames [vnp->choice]);
               ValNodeCopyStr (head, 0, buf);
diff --git a/access/makeacc.unx b/access/makeacc.unx
index d657b22..573be9c 100644
--- a/access/makeacc.unx
+++ b/access/makeacc.unx
@@ -9,7 +9,7 @@ asntool -m mim.asn -G -B objmim -K asnmim.h
 
 asntool -m taxon3.asn -o asntax3.h
 mv asntax3.h ../asnstat
-asntool -m taxon3.asn -M ../asn/seqfeat.asn -G -B objtax3 -K asntax3.h
+asntool -m taxon3.asn -M ../asn/seqfeat.asn,../asn/general.asn -G -B objtax3 -K asntax3.h
 
 asntool -m entrezgene.asn -o asnentgene.h
 mv asnentgene.h ../asnstat
diff --git a/access/mla2api.c b/access/mla2api.c
index c778381..ef70bbb 100644
--- a/access/mla2api.c
+++ b/access/mla2api.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/30/07
 *
-* $Revision: 1.15 $
+* $Revision: 1.16 $
 *
 * File Description: 
 *
@@ -720,7 +720,6 @@ static EjourData mla2_ejour_list [] = {
  {"Hum. Genomics",                                              2004 },
  {"Infect. Agents Cancer",                                         0 },
  {"J. Exp. Clin. Assist. Reprod.",                                 0 },
- {"J. Plankton Res.",                                              0 },
  {"JOP",                                                           0 },
  {"Kinetoplastid Biol Dis",                                        0 },
  {"Malar. J.",                                                     0 },
diff --git a/access/objtax3.c b/access/objtax3.c
index b8f2dcb..e7d357c 100644
--- a/access/objtax3.c
+++ b/access/objtax3.c
@@ -32,7 +32,7 @@ objtax3AsnLoad(void)
 
 /**************************************************
 *    Generated object loaders for Module NCBI-Taxon3
-*    Generated using ASNCODE Revision: 6.14 at Jul 8, 2004 11:45 AM
+*    Generated using ASNCODE Revision: 6.17 at Dec 8, 2009  9:36 AM
 *
 **************************************************/
 
@@ -214,6 +214,9 @@ T3RequestFree(ValNodePtr anp)
    case T3Request_org:
       OrgRefFree(anp -> data.ptrvalue);
       break;
+   case T3Request_join:
+      SequenceOfIntFree(anp -> data.ptrvalue);
+      break;
    }
    return MemFree(anp);
 }
@@ -232,7 +235,6 @@ T3RequestAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    AsnTypePtr atp;
    ValNodePtr anp;
    Uint1 choice;
-   Boolean isError = FALSE;
    Boolean nullIsError = FALSE;
    AsnReadFunc func;
 
@@ -288,6 +290,10 @@ T3RequestAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       choice = T3Request_org;
       func = (AsnReadFunc) OrgRefAsnRead;
    }
+   else if (atp == T3REQUEST_join) {
+      choice = T3Request_join;
+      func = (AsnReadFunc) SequenceOfIntAsnRead;
+   }
    anp->choice = choice;
    if (func != NULL)
    {
@@ -361,6 +367,10 @@ T3RequestAsnWrite(T3RequestPtr anp, AsnIoPtr aip, AsnTypePtr orig)
       writetype = T3REQUEST_org;
       func = (AsnWriteFunc) OrgRefAsnWrite;
       break;
+   case T3Request_join:
+      writetype = T3REQUEST_join;
+      func = (AsnWriteFunc) SequenceOfIntAsnWrite;
+      break;
    }
    if (writetype != NULL) {
       retval = (* func)(pnt, aip, writetype);   /* write it out */
@@ -378,6 +388,118 @@ erret:
 
 /**************************************************
 *
+*    SequenceOfIntFree()
+*
+**************************************************/
+NLM_EXTERN 
+SequenceOfIntPtr LIBCALL
+SequenceOfIntFree(SequenceOfIntPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   AsnGenericBaseSeqOfFree(ptr,ASNCODE_INTVAL_SLOT);
+   return NULL;
+}
+
+
+/**************************************************
+*
+*    SequenceOfIntAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+SequenceOfIntPtr LIBCALL
+SequenceOfIntAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   SequenceOfIntPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objtax3AsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* SequenceOfInt ::= (self contained) */
+      atp = AsnReadId(aip, amp, SEQUENCEOFINT);
+   } else {
+      atp = AsnLinkType(orig, SEQUENCEOFINT);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   func = NULL;
+
+   ptr  = AsnGenericBaseSeqOfAsnRead(aip, amp, atp, ASNCODE_INTVAL_SLOT, &isError);
+   if (isError && ptr  == NULL) {
+      goto erret;
+   }
+
+
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = SequenceOfIntFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    SequenceOfIntAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+SequenceOfIntAsnWrite(SequenceOfIntPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objtax3AsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, SEQUENCEOFINT);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   retval = AsnGenericBaseSeqOfAsnWrite(ptr, ASNCODE_INTVAL_SLOT, aip, atp, SEQUENCEOFINT_E);
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
 *    Taxon3ReplyNew()
 *
 **************************************************/
@@ -571,7 +693,6 @@ T3ReplyAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    AsnTypePtr atp;
    ValNodePtr anp;
    Uint1 choice;
-   Boolean isError = FALSE;
    Boolean nullIsError = FALSE;
    AsnReadFunc func;
 
@@ -748,7 +869,6 @@ T3ErrorAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
    T3ErrorPtr ptr;
 
@@ -1159,7 +1279,6 @@ T3StatusFlagsAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
    T3StatusFlagsPtr ptr;
 
@@ -1240,7 +1359,6 @@ Value_valueAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    AsnTypePtr atp;
    ValNodePtr anp;
    Uint1 choice;
-   Boolean isError = FALSE;
    Boolean nullIsError = FALSE;
    AsnReadFunc func;
 
@@ -1485,7 +1603,6 @@ T3RefreshFlagsAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
    T3RefreshFlagsPtr ptr;
 
diff --git a/access/objtax3.h b/access/objtax3.h
index 94a53d6..a3ad70b 100644
--- a/access/objtax3.h
+++ b/access/objtax3.h
@@ -17,7 +17,7 @@ extern "C" { /* } */
 /**************************************************
 *
 *    Generated objects for Module NCBI-Taxon3
-*    Generated using ASNCODE Revision: 6.14 at Jul 8, 2004 11:45 AM
+*    Generated using ASNCODE Revision: 6.17 at Dec 8, 2009  9:36 AM
 *
 **************************************************/
 
@@ -45,6 +45,7 @@ typedef ValNode T3Request;
 #define T3Request_taxid 1
 #define T3Request_name 2
 #define T3Request_org 3
+#define T3Request_join 4
 
 
 NLM_EXTERN T3RequestPtr LIBCALL T3RequestFree PROTO ((T3RequestPtr ));
@@ -55,6 +56,26 @@ NLM_EXTERN Boolean LIBCALL T3RequestAsnWrite PROTO (( T3RequestPtr , AsnIoPtr, A
 
 /**************************************************
 *
+*    SequenceOfInt
+*
+**************************************************/
+typedef ValNode SequenceOfInt;
+typedef ValNodePtr SequenceOfIntPtr;
+#define SequenceOfIntNew() ValNodeNew(NULL) 
+
+#ifdef NLM_GENERATED_CODE_PROTO
+
+NLM_EXTERN SequenceOfIntPtr LIBCALL SequenceOfIntFree PROTO ((SequenceOfIntPtr ));
+NLM_EXTERN SequenceOfIntPtr LIBCALL SequenceOfIntNew PROTO (( void ));
+NLM_EXTERN SequenceOfIntPtr LIBCALL SequenceOfIntAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL SequenceOfIntAsnWrite PROTO (( SequenceOfIntPtr , AsnIoPtr, AsnTypePtr));
+
+#endif /* NLM_GENERATED_CODE_PROTO */
+
+
+
+/**************************************************
+*
 *    Taxon3Reply
 *
 **************************************************/
diff --git a/access/pmfapi.c b/access/pmfapi.c
index b332e32..4d90291 100644
--- a/access/pmfapi.c
+++ b/access/pmfapi.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   5/5/00
 *
-* $Revision: 1.103 $
+* $Revision: 1.106 $
 *
 * File Description: 
 *
@@ -2212,7 +2212,7 @@ static Int2 LIBCALLBACK PubSeqSeqIdForGiFunc (Pointer data)
   }
   *ptr = '\0';
 
-  if (StringNCmp (str, "ERROR", 5) != 0) {
+  if (StringNCmp (str, "ERROR", 5) != 0 && StringNCmp (str, "<!DOCTYPE", 9) != 0) {
     sid = SeqIdParse (str);
   }
   MemFree (str);
@@ -2388,6 +2388,8 @@ NLM_EXTERN Int4 CacheAccnList (
 
   if (str == NULL) return 0;
 
+  if (StringNCmp (str, "<!DOCTYPE", 9) == 0) return 0;
+
   /* parse output */
 
   i = 0;
@@ -2404,7 +2406,10 @@ NLM_EXTERN Int4 CacheAccnList (
       ptr++;
       ch = *ptr;
     }
-    if (StringNCmp (tmp, "ERROR", 5) != 0 && StringNCmp (tmp, "Sorry", 5) != 0 && StringChr (tmp, '|') != NULL) {
+    if (StringNCmp (tmp, "ERROR", 5) != 0 &&
+        StringNCmp (tmp, "<!DOCTYPE", 9) != 0 &&
+        StringNCmp (tmp, "Sorry", 5) != 0 &&
+        StringChr (tmp, '|') != NULL) {
       ids = SeqIdParse (tmp);
       if (ids != NULL) {
         gi = 0;
@@ -2494,6 +2499,8 @@ static Int4 IntPreLoadSeqIdGiCache (
   str = GiAccVerSynchronousQuery (0, num, ids);
   if (str == NULL) return 0;
 
+  if (StringNCmp (str, "<!DOCTYPE", 9) == 0) return 0;
+
   /* parse output */
 
   i = 0;
@@ -2510,7 +2517,7 @@ static Int4 IntPreLoadSeqIdGiCache (
       ptr++;
       ch = *ptr;
     }
-    if (StringNCmp (tmp, "ERROR", 5) != 0) {
+    if (StringNCmp (tmp, "ERROR", 5) != 0 && StringNCmp (tmp, "<!DOCTYPE", 9) != 0) {
       gi = ids [i];
 
       sip = NULL;
@@ -2905,12 +2912,15 @@ static void LookupHistory (BioseqPtr bsp, Pointer userdata)
 {
   SeqHistPtr  hist;
   SeqIdPtr    sip;
+  SeqAlignPtr salp;
 
   if (bsp == NULL) return;
   hist = bsp->hist;
   if (hist == NULL) return;
   if (hist->assembly != NULL) {
-    LookupAlignments (hist->assembly, userdata);
+    for (salp = hist->assembly; salp != NULL; salp = salp->next) {
+      LookupAlignments (salp, userdata);
+    }
   }
   for (sip = hist->replace_ids; sip != NULL; sip = sip->next) {
     LookupSegments (NULL, sip, userdata);
diff --git a/access/tax3api.c b/access/tax3api.c
index 8b57085..89f94c7 100644
--- a/access/tax3api.c
+++ b/access/tax3api.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/8/04
 *
-* $Revision: 1.46 $
+* $Revision: 1.59 $
 *
 * File Description: 
 *
@@ -64,6 +64,30 @@ static const CharPtr tax3servicename = "TaxService3";
 static const CharPtr tax3servicename = "TaxService3Test";
 #endif
 
+static void Tax3ReplyFixup (
+  Taxon3ReplyPtr t3ry
+)
+
+{
+  OrgNamePtr  onp;
+  OrgRefPtr   orp;
+  T3DataPtr   tdp;
+  T3ReplyPtr  trp;
+
+  if (t3ry == NULL) return;
+
+  for (trp = t3ry->reply; trp != NULL; trp = trp->next) {
+    if (trp->choice != T3Reply_data) continue;
+    tdp = (T3DataPtr) trp->data.ptrvalue;
+    if (tdp == NULL) continue;
+    orp = (OrgRefPtr) tdp->org;
+    if (orp == NULL) continue;
+    onp = orp->orgname;
+    if (onp == NULL) continue;
+    onp->pgcode = GetSpecialPlastidGenCode (orp->taxname, onp->lineage);
+  }
+}
+
 NLM_EXTERN CONN Tax3OpenConnection (
   void
 )
@@ -126,6 +150,7 @@ NLM_EXTERN Taxon3ReplyPtr Tax3WaitForReply (
   if (status == eIO_Success) {
     aicp = QUERY_AsnIoConnOpen (text_tax_asn ? "r" : "rb", conn);
     t3ry = Taxon3ReplyAsnRead (aicp->aip, NULL);
+    Tax3ReplyFixup (t3ry);
     QUERY_AsnIoConnClose (aicp);
   }
   CONN_Close (conn);
@@ -143,6 +168,7 @@ NLM_EXTERN Taxon3ReplyPtr Tax3SynchronousQuery (
   AsnIoConnPtr    aicp;
   CONN            conn;
   Taxon3ReplyPtr  t3ry;
+  time_t          t1, t2, t3;
 
   if (t3rq == NULL) return NULL;
 
@@ -159,7 +185,10 @@ NLM_EXTERN Taxon3ReplyPtr Tax3SynchronousQuery (
 
   QUERY_SendQuery (conn);
 
+  t1 = time(NULL);
   t3ry = Tax3WaitForReply (conn);
+  t2 = time(NULL);
+  t3 = t2 - t1;
 
   return t3ry;
 }
@@ -215,6 +244,7 @@ NLM_EXTERN Taxon3ReplyPtr Tax3ReadReply (
   if (conn != NULL && status == eIO_Success) {
     aicp = QUERY_AsnIoConnOpen (text_tax_asn ? "r" : "rb", conn);
     t3ry = Taxon3ReplyAsnRead (aicp->aip, NULL);
+    Tax3ReplyFixup (t3ry);
     QUERY_AsnIoConnClose (aicp);
   }
   return t3ry;
@@ -246,6 +276,20 @@ NLM_EXTERN Taxon3RequestPtr CreateTaxon3Request (
   return t2rp;
 }
 
+
+static void SaveTaxon3Request (Taxon3RequestPtr t3rp, CharPtr path)
+{
+  AsnIoPtr aip;
+
+  if (t3rp != NULL) {
+    aip = AsnIoOpen (path, "w");
+    if (aip != NULL) {
+      Taxon3RequestAsnWrite (t3rp, aip, NULL);
+      AsnIoClose (aip);
+    }
+  }
+}
+
 NLM_EXTERN Taxon3RequestPtr CreateMultiTaxon3Request (ValNodePtr org_list)
 {
   ValNodePtr vnp;
@@ -259,20 +303,40 @@ NLM_EXTERN Taxon3RequestPtr CreateMultiTaxon3Request (ValNodePtr org_list)
   {
     switch (vnp->choice)
     {
-      case 1:
-        ValNodeAddInt (&(t3rp->request), 1, vnp->data.intvalue);
+      case T3Request_taxid:
+        ValNodeAddInt (&(t3rp->request), T3Request_taxid, vnp->data.intvalue);
         break;
-      case 2:
-        ValNodeCopyStr (&(t3rp->request), 2, vnp->data.ptrvalue);
+      case T3Request_name:
+        ValNodeCopyStr (&(t3rp->request), T3Request_name, vnp->data.ptrvalue);
         break;
-      case 3:
+      case T3Request_org:
         orp = AsnIoMemCopy (vnp->data.ptrvalue,
                         (AsnReadFunc) OrgRefAsnRead,
                         (AsnWriteFunc) OrgRefAsnWrite);
-        ValNodeAddPointer (&(t3rp->request), 3, (Pointer) orp);
+        ValNodeAddPointer (&(t3rp->request), T3Request_org, (Pointer) orp);
         break;
     }
   }
+
+  /* SaveTaxon3Request(t3rp, "request.txt"); */
+  return t3rp;
+}
+
+/* takes ValNode list of integers, creates request */
+NLM_EXTERN Taxon3RequestPtr CreateJoinRequest (ValNodePtr taxon_list)
+{
+  Taxon3RequestPtr t3rp;
+  ValNodePtr vnp, data = NULL;
+
+  t3rp = Taxon3RequestNew();
+  if (t3rp == NULL) return NULL;
+
+  for (vnp = taxon_list; vnp != NULL; vnp = vnp->next) {
+    ValNodeAddInt (&data, T3Request_join, vnp->data.intvalue);
+  }
+  ValNodeAddPointer ((&t3rp->request), T3Request_join, data);
+
+/*  SaveTaxon3Request(t3rp, "join_request.txt"); */
   return t3rp;
 }
 
@@ -293,6 +357,29 @@ static Boolean HasMisspellingFlag (T3DataPtr t)
 }
 
 
+static Uint1 GetStatusFlags (T3DataPtr t)
+{
+  Uint1 flags = 0;
+  T3StatusFlagsPtr status;
+
+  if (t == NULL) return FALSE;
+  status = t->status;
+  while (status != NULL) {
+    if (StringCmp (status->property, "unpublished_name") == 0) {
+      flags |= eReturnedOrgFlag_unpublished;
+    } else if (StringCmp (status->property, "misspelled_name") == 0) {
+      flags |= eReturnedOrgFlag_misspelled;
+    }
+    status = status->next;
+  }
+  if (flags == 0) {
+    flags = eReturnedOrgFlag_normal;
+  }
+  return flags;
+}
+
+
+
 static int LIBCALLBACK SortVnpByOrgRef (VoidPtr ptr1, VoidPtr ptr2)
 
 {
@@ -323,11 +410,15 @@ NLM_EXTERN ValNodePtr Taxon3GetOrgRefList (ValNodePtr org_list)
   ValNodePtr PNTR  ptr_array;
   ValNodePtr       vnp, vnp_rq, vnp_rp;
   Int4             i, num_orgs;
+  Uint1            choice;
+  TextFsaPtr       tags;
 
   if (org_list == NULL) {
     return NULL;
   }
 
+  tags = GetOrgModSearch();
+
   /* make a copy of the original list - we will prepare the response list by substituting the OrgRef */
   org_list = ValNodeCopyPtr (org_list);
 
@@ -383,11 +474,9 @@ NLM_EXTERN ValNodePtr Taxon3GetOrgRefList (ValNodePtr org_list)
             tdp = (T3DataPtr) trp->data.ptrvalue;
             if (tdp != NULL) {
               t3orp = (OrgRefPtr)(tdp->org);
-              if (HasMisspellingFlag (tdp)) {
-                ValNodeAddPointer (&response_list, eReturnedOrgFlag_misspelled, (Pointer) t3orp);
-              } else {
-                ValNodeAddPointer (&response_list, eReturnedOrgFlag_normal, (Pointer) t3orp);
-              }
+              choice = GetStatusFlags (tdp);
+              ParseTaxNameToQuals(t3orp, tags);
+              ValNodeAddPointer (&response_list, choice, (Pointer) t3orp);
               tdp->org = NULL;
             }
             break;
@@ -439,6 +528,7 @@ NLM_EXTERN ValNodePtr Taxon3GetOrgRefList (ValNodePtr org_list)
   ptr_array[num_orgs - 1]->next = NULL;
   org_list = ptr_array[0];
   ptr_array = MemFree (ptr_array);
+  tags = TextFsaFree (tags);
   
   return org_list;
 }
@@ -697,12 +787,14 @@ static void CheckSuggestedFixes (ValNodePtr tax_fix_list)
     }
     if (t != NULL) {
       t->suggested_fix = MemFree (t->suggested_fix);
+      if (vnp_rq != NULL) {
       t->suggested_fix = vnp_rp->data.ptrvalue;
       vnp_rp->data.ptrvalue = NULL;
       vnp_rq = vnp_rq->next;
       vnp_rp = vnp_rp->next;
     }
   }
+  }
   rp_list = ValNodeFreeData (rp_list);
 }
 
@@ -1187,7 +1279,7 @@ static void AddBioSourceToList (BioSourcePtr biop, Pointer userdata)
   ValNodeAddPointer (list, 4, (Pointer) biop);
 }
 
-NLM_EXTERN void Taxon3ReplaceOrgInSeqEntry (SeqEntryPtr sep, Boolean keep_syn)
+NLM_EXTERN void Taxon3ReplaceOrgInSeqEntryEx (SeqEntryPtr sep, Boolean keep_syn, Boolean replace_unpub)
 {
   ValNodePtr   biop_list = NULL;
   ValNodePtr   request_list = NULL;
@@ -1218,7 +1310,8 @@ NLM_EXTERN void Taxon3ReplaceOrgInSeqEntry (SeqEntryPtr sep, Boolean keep_syn)
     biop = (BioSourcePtr) biop_vnp->data.ptrvalue;
     swap_org = biop->org;
     response_org = response_vnp->data.ptrvalue;
-    if (response_org != NULL)
+    if (response_org != NULL
+        && (replace_unpub || !(response_vnp->choice & eReturnedOrgFlag_unpublished)))
     {
       biop->org = response_org;
       response_vnp->data.ptrvalue = NULL;
@@ -1235,6 +1328,12 @@ NLM_EXTERN void Taxon3ReplaceOrgInSeqEntry (SeqEntryPtr sep, Boolean keep_syn)
 }
 
 
+NLM_EXTERN void Taxon3ReplaceOrgInSeqEntry (SeqEntryPtr sep, Boolean keep_syn)
+{
+  Taxon3ReplaceOrgInSeqEntryEx (sep, keep_syn, TRUE);
+}
+
+
 static void GetBioSourceFeaturesForCheck (SeqFeatPtr sfp, Pointer userdata)
 {
   ValNodePtr PNTR list = (ValNodePtr PNTR) userdata;
@@ -2673,3 +2772,68 @@ NLM_EXTERN ValNodePtr GetOrganismTaxLookupFailuresInSeqEntry (SeqEntryPtr sep)
   return failed_list;  
 }
 
+
+static void CollectTaxIds (BioSourcePtr biop, Pointer data)
+{
+  ValNodePtr vnp;
+  DbtagPtr   dbtag;
+
+  if (biop == NULL || biop->org == NULL || data == NULL) {
+    return;
+  }
+  for (vnp = biop->org->db; vnp != NULL; vnp = vnp->next) {
+    dbtag = (DbtagPtr) vnp->data.ptrvalue;
+    if (dbtag != NULL && StringCmp ("taxon", dbtag->db) == 0 && dbtag->tag->id > 0) {
+      ValNodeAddInt ((ValNodePtr PNTR) data, 0, dbtag->tag->id);
+    }
+  }
+}
+
+
+NLM_EXTERN OrgRefPtr GetCommonOrgRefForSeqEntry (SeqEntryPtr sep)
+{
+  ValNodePtr       list = NULL;
+  Taxon3RequestPtr t3rq;
+  T3ReplyPtr       trp;
+  Taxon3ReplyPtr   t3ry;
+  T3DataPtr        tdp;
+  T3ErrorPtr       tep;
+  OrgRefPtr        org = NULL;
+
+  VisitBioSourcesInSep (sep, &list, CollectTaxIds);
+  if (list == NULL) {
+    ErrPostEx (SEV_ERROR, 0, 0, "No tax IDs found - cannot create PopSet Title");
+    return NULL;
+  }
+  ValNodeUnique (&list, SortByIntvalue, ValNodeFree);
+
+  t3rq = CreateJoinRequest (list);
+  list = ValNodeFree (list);
+
+  t3ry = Tax3SynchronousQuery (t3rq);
+  Taxon3RequestFree (t3rq);
+  if (t3ry != NULL) {
+    for (trp = t3ry->reply; trp != NULL; trp = trp->next) {
+      switch (trp->choice) {
+        case T3Reply_error :
+          tep = (T3ErrorPtr) trp->data.ptrvalue;
+          if (tep != NULL) {
+            ErrPostEx (SEV_ERROR, 0, 0, tep->message);
+          }
+          break;
+        case T3Reply_data :
+          tdp = (T3DataPtr) trp->data.ptrvalue;
+          if (tdp != NULL) {
+            org = (OrgRefPtr)(tdp->org);
+            tdp->org = NULL;
+          }
+          break;
+        default :
+          break;
+      }
+    }
+    Taxon3ReplyFree (t3ry);
+  }
+  return org;
+}
+
diff --git a/access/tax3api.h b/access/tax3api.h
index 910180c..01bba2f 100644
--- a/access/tax3api.h
+++ b/access/tax3api.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/8/04
 *
-* $Revision: 1.19 $
+* $Revision: 1.22 $
 *
 * File Description: 
 *
@@ -126,6 +126,8 @@ NLM_EXTERN Taxon3RequestPtr CreateTaxon3Request (
 
 NLM_EXTERN Taxon3RequestPtr CreateMultiTaxon3Request (ValNodePtr org_list);
 
+NLM_EXTERN Taxon3RequestPtr CreateJoinRequest (ValNodePtr taxon_list);
+
 NLM_EXTERN OrgRefPtr Taxon3GetOrg (OrgRefPtr orp);
 NLM_EXTERN ValNodePtr Taxon3GetOrgRefList (ValNodePtr org_list);
 NLM_EXTERN void Tax3MergeSourceDescr (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent);
@@ -133,15 +135,17 @@ NLM_EXTERN Int4 Taxon3GetTaxIdByOrgRef (OrgRefPtr orp);
 NLM_EXTERN OrgRefPtr Taxon3GetOrgRefByName (CharPtr orgname);
 NLM_EXTERN Int4 Taxon3GetTaxIdByName (CharPtr orgname);
 NLM_EXTERN void Taxon3ReplaceOrgInSeqEntry (SeqEntryPtr sep, Boolean keep_syn);
+NLM_EXTERN void Taxon3ReplaceOrgInSeqEntryEx (SeqEntryPtr sep, Boolean keep_syn, Boolean replace_unpub);
 
 NLM_EXTERN void Taxon3CheckOrgInSeqEntry (SeqEntryPtr sep, ValNodePtr PNTR not_found, ValNodePtr PNTR bad_match);
 NLM_EXTERN void CheckTaxNamesAgainstTaxDatabase (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
 
 typedef enum {
-  eReturnedOrgFlag_normal = 3,
-  eReturnedOrgFlag_misspelled = 4,
-  eReturnedOrgFlag_ambiguous = 5,
-  eReturnedOrgFlag_error
+  eReturnedOrgFlag_normal =      0x004,
+  eReturnedOrgFlag_misspelled =  0x008,
+  eReturnedOrgFlag_ambiguous =   0x010,
+  eReturnedOrgFlag_unpublished = 0x020,
+  eReturnedOrgFlag_error =       0x040
 } EReturnedOrgFlag;
 
 typedef enum {
@@ -191,6 +195,7 @@ NLM_EXTERN TaxFixItemPtr TaxFixItemFree (TaxFixItemPtr t);
 NLM_EXTERN ValNodePtr LIBCALLBACK TaxFixItemListFree (ValNodePtr vnp);
 NLM_EXTERN ValNodePtr Taxon3GetTaxFixList (ValNodePtr biop_list);
 
+NLM_EXTERN OrgRefPtr GetCommonOrgRefForSeqEntry (SeqEntryPtr sep);
 
 
 #ifdef __cplusplus
diff --git a/access/taxon3.asn b/access/taxon3.asn
index f5f1199..d821b41 100644
--- a/access/taxon3.asn
+++ b/access/taxon3.asn
@@ -1,4 +1,4 @@
---$Revision: 1.2 $
+--$Revision: 1.3 $
 --**********************************************************************
 --
 --  NCBI Taxonomy Server
@@ -17,10 +17,13 @@ Taxon3-request ::= SEQUENCE {
     request SEQUENCE OF T3Request
 }
 
+SequenceOfInt ::= SEQUENCE OF INTEGER
+
 T3Request ::= CHOICE {
     taxid INTEGER ,
     name VisibleString ,
-    org Org-ref
+    org Org-ref ,
+    join SequenceOfInt
 }
 
 Taxon3-reply ::= SEQUENCE {
diff --git a/algo/blast/api/blast_returns.c b/algo/blast/api/blast_returns.c
index 186f054..c4dd7b0 100644
--- a/algo/blast/api/blast_returns.c
+++ b/algo/blast/api/blast_returns.c
@@ -1,4 +1,4 @@
-/* $Id: blast_returns.c,v 1.38 2007/07/10 15:28:07 papadopo Exp $
+/* $Id: blast_returns.c,v 1.39 2010/06/10 13:44:46 madden Exp $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
@@ -29,7 +29,7 @@
  */
 
 #ifndef SKIP_DOXYGEN_PROCESSING
-static char const rcsid[] = "$Id: blast_returns.c,v 1.38 2007/07/10 15:28:07 papadopo Exp $";
+static char const rcsid[] = "$Id: blast_returns.c,v 1.39 2010/06/10 13:44:46 madden Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/api/blast_returns.h>
@@ -110,9 +110,19 @@ Blast_GetParametersBuffer(EBlastProgramType program_number,
    }
 
    if (search_params->gapped_search) {
+      if (search_params->gap_extension == 0 && program_number == eBlastTypeBlastn)
+      { /* Formula from PMID 10890397 applies if both gap values are zero. */
+           double gap_extension = (double) search_params->gap_extension;
+           gap_extension = -2*search_params->mismatch + search_params->match; 
+           gap_extension /= 2.0;
+           sprintf(buffer, "Gap Penalties: Existence: %ld, Extension: %4.1f",
+              (long) search_params->gap_open, gap_extension);
+      }
+      else
+      {
       sprintf(buffer, "Gap Penalties: Existence: %ld, Extension: %ld",
-              (long) search_params->gap_open, 
-              (long) search_params->gap_extension);
+              (long) search_params->gap_open, (long) search_params->gap_extension);
+      }
       add_string_to_buffer(buffer, &ret_buffer, &ret_buffer_length);
    }
    
diff --git a/algo/blast/api/blast_seqalign.c b/algo/blast/api/blast_seqalign.c
index bbf2c09..2537af1 100644
--- a/algo/blast/api/blast_seqalign.c
+++ b/algo/blast/api/blast_seqalign.c
@@ -1,4 +1,4 @@
-/* $Id: blast_seqalign.c,v 1.62 2007/02/26 14:52:50 papadopo Exp $
+/* $Id: blast_seqalign.c,v 1.64 2010/02/12 20:54:54 maning Exp $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
@@ -29,7 +29,7 @@
  */
 
 #ifndef SKIP_DOXYGEN_PROCESSING
-static char const rcsid[] = "$Id: blast_seqalign.c,v 1.62 2007/02/26 14:52:50 papadopo Exp $";
+static char const rcsid[] = "$Id: blast_seqalign.c,v 1.64 2010/02/12 20:54:54 maning Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/api/blast_seqalign.h>
@@ -712,7 +712,7 @@ s_GapMakeSeqAlign(SeqIdPtr query_id, SeqIdPtr subject_id,
 
 SeqAlignPtr
 BlastHSPToSeqAlign(EBlastProgramType program, BlastHSP* hsp, 
-                   SeqIdPtr subject_id, SeqIdPtr query_id,
+                   SeqIdPtr query_id, SeqIdPtr subject_id,
                    Int4 query_length, Int4 subject_length)
 
 {
@@ -1271,8 +1271,8 @@ s_HSPListToSeqAlignGapped(EBlastProgramType program_number,
          /* The following line is needed for negative frames of translated 
             query */
          seqalign = 
-             BlastHSPToSeqAlign(program_number, hsp_array[index], subject_id, 
-                                query_id, query_length, subject_length);
+             BlastHSPToSeqAlign(program_number, hsp_array[index], query_id, 
+                                subject_id, query_length, subject_length);
       }
       if (index==0) {
          *head_seqalign = last_seqalign = seqalign;
diff --git a/algo/blast/api/blast_seqalign.h b/algo/blast/api/blast_seqalign.h
index d6ddf5d..b727c65 100644
--- a/algo/blast/api/blast_seqalign.h
+++ b/algo/blast/api/blast_seqalign.h
@@ -1,4 +1,4 @@
-/* $Id: blast_seqalign.h,v 1.31 2006/06/09 17:40:41 papadopo Exp $
+/* $Id: blast_seqalign.h,v 1.32 2010/02/12 20:36:18 maning Exp $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
@@ -112,15 +112,15 @@ GapCollectDataForSeqalign(BlastHSP* hsp, GapEditScript* esp, Int4 start,
  * deletions).  
  * @param program Type of BLAST program [in]
  * @param hsp HSP structure to convert. [in]
- * @param subject_id Seq-id of the subject sequence [in]
  * @param query_id Seq-id of the query sequence [in]
+ * @param subject_id Seq-id of the subject sequence [in]
  * @param query_length Length of query sequence [in]
  * @param subject_length Length of subject sequence [in]
  * @return Seq-align corresponding to this alignment.
  */
 SeqAlignPtr
 BlastHSPToSeqAlign(EBlastProgramType program, BlastHSP* hsp, 
-                   SeqIdPtr subject_id, SeqIdPtr query_id,
+                   SeqIdPtr query_id, SeqIdPtr subject_id,
                    Int4 query_length, Int4 subject_length);
 
 
diff --git a/algo/blast/composition_adjustment/compo_mode_condition.h b/algo/blast/composition_adjustment/compo_mode_condition.h
index f520a1f..79c853e 100644
--- a/algo/blast/composition_adjustment/compo_mode_condition.h
+++ b/algo/blast/composition_adjustment/compo_mode_condition.h
@@ -1,4 +1,4 @@
-/* $Id: compo_mode_condition.h,v 1.7 2006/01/30 14:47:57 gertz Exp $
+/* $Id: compo_mode_condition.h,v 1.8 2010/03/26 14:54:33 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,13 +34,12 @@
 #define __COMPO_MODE_CONDITION__
 
 #include <algo/blast/core/blast_export.h>
+#include <algo/blast/composition_adjustment/composition_constants.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#include <algo/blast/composition_adjustment/composition_constants.h>
-
 
 /**
  * Choose how the relative entropy should be constrained based on
diff --git a/algo/blast/composition_adjustment/composition_adjustment.c b/algo/blast/composition_adjustment/composition_adjustment.c
index ac7048b..badcb7e 100644
--- a/algo/blast/composition_adjustment/composition_adjustment.c
+++ b/algo/blast/composition_adjustment/composition_adjustment.c
@@ -30,7 +30,7 @@
  */
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-    "$Id: composition_adjustment.c,v 1.25 2008/08/21 19:55:43 kazimird Exp $";
+    "$Id: composition_adjustment.c,v 1.26 2010/03/22 11:39:31 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <limits.h>
@@ -1335,60 +1335,37 @@ Blast_CompositionMatrixAdj(int ** matrix,
                            Blast_CompositionWorkspace * NRrecord,
                            const Blast_MatrixInfo * matrixInfo)
 {
-    int i;                         /* loop indices */
-    static int total_iterations = 0;   /* total iterations among all
-                                          calls to
-                                          compute_new_score_matrix */
-    int new_iterations = 0;        /* number of iterations in the most
-                                      recent call to
-                                      compute_new_score_matrix */
-    static int max_iterations = 0; /* maximum number of iterations
-                                      observed in a call to
-                                      compute_new_score_matrix */
-    int status;                    /* status code for operations that may
-                                      fail */
-    double row_probs[COMPO_NUM_TRUE_AA];
-    double col_probs[COMPO_NUM_TRUE_AA];
-    double RE_final;
-
-    /*Is the relative entropy constrained? Behaves as boolean for now*/
-    int constrain_rel_entropy =
-        eUnconstrainedRelEntropy != matrix_adjust_rule;
+    int iteration_count, status;
+    double row_probs[COMPO_NUM_TRUE_AA], col_probs[COMPO_NUM_TRUE_AA];
+    /* Target RE when optimizing the matrix; zero if the relative
+       entropy should not be constrained. */
+    double dummy, desired_re = 0.0;
 
     s_GatherLetterProbs(row_probs, stdaa_row_probs, alphsize);
     s_GatherLetterProbs(col_probs, stdaa_col_probs, alphsize);
 
     switch (matrix_adjust_rule) {
     case eUnconstrainedRelEntropy:
-        /* Initialize to a arbitrary value; it won't be used */
-        RE_final = 0.0;
+        desired_re = 0.0;
         break;
     case eRelEntropyOldMatrixNewContext:
-        {
-            double entropy, Lambda;
-            int iter_count;
-            status = Blast_EntropyOldFreqNewContext(&entropy, &Lambda,
-                                                    &iter_count,
+        /* Calculate the desired re using the new marginal probs with
+           the old matrix */
+        status = Blast_EntropyOldFreqNewContext(&desired_re, &dummy,
+                                                &iteration_count,
                                                     NRrecord->mat_b,
                                                     row_probs, col_probs);
-            if (status < 0) {
+        if (status < 0)     /* Error, e.g. memory */
                 return status;
-            } else if (status > 0) {
-                /* Failed to compute the entropy; leave the entropy
-                 * unconstrained */
-                status = 0;
-                constrain_rel_entropy = 0;
-                RE_final = 0.0;
-            } else {
-                RE_final = entropy;
-            }
-        }
+        else if (status > 0) /* we could not calculate the desired re */
+            desired_re = 0.0; /* so, leave the re unconstrained */
+
         break;
     case eRelEntropyOldMatrixOldContext:
-        RE_final = Blast_TargetFreqEntropy(NRrecord->mat_b);
+        desired_re = Blast_TargetFreqEntropy(NRrecord->mat_b);
         break;
     case eUserSpecifiedRelEntropy:
-        RE_final = specifiedRE;
+        desired_re = specifiedRE;
         break;
     default:  /* I assert that we can't get here */
         fprintf(stderr, "Unknown flag for setting relative entropy"
@@ -1403,39 +1380,22 @@ Blast_CompositionMatrixAdj(int ** matrix,
     status =
         Blast_OptimizeTargetFrequencies(&NRrecord->mat_final[0][0],
                                         COMPO_NUM_TRUE_AA,
-                                        &new_iterations,
+                                        &iteration_count,
                                         &NRrecord->mat_b[0][0],
                                         row_probs, col_probs,
-                                        constrain_rel_entropy,
-                                        RE_final,
+                                        (desired_re > 0.0),
+                                        desired_re,
                                         kCompoAdjustErrTolerance,
                                         kCompoAdjustIterationLimit);
-    total_iterations += new_iterations;
-    if (new_iterations > max_iterations)
-        max_iterations = new_iterations;
 
-    if (status == 0) {
-        status = s_ScoresStdAlphabet(matrix, alphsize, NRrecord->mat_final,
+    if (status != 0)            /* Did not compute the target freqs */
+        return status;
+
+    return
+        s_ScoresStdAlphabet(matrix, alphsize, NRrecord->mat_final,
                                      matrixInfo->startMatrix,
                                      row_probs, col_probs,
                                      matrixInfo->ungappedLambda);
-    } else if (status == -1) {
-        /* out of memory */
-        status = -1;
-    } else {
-        /* Iteration did not converge */
-        fprintf(stderr, "bad probabilities from sequence 1, length %d\n",
-                length1);
-        for (i = 0;  i < COMPO_NUM_TRUE_AA;  i++)
-            fprintf(stderr, "%15.12f\n", row_probs[i]);
-        fprintf(stderr, "bad probabilities from sequence 2, length %d\n",
-                length2);
-        for (i = 0;  i < COMPO_NUM_TRUE_AA;  i++)
-            fprintf(stderr, "%15.12f\n", col_probs[i]);
-        fflush(stderr);
-        status = 1;
-    }
-    return status;
 }
 
 
@@ -1497,8 +1457,8 @@ Blast_AdjustScores(int ** matrix,
         Blast_CalcLambdaFullPrecision(&lambdaForPair, &iter_count,
                                       scores,
                                       COMPO_NUM_TRUE_AA,
-                                      &(permutedQueryProbs[0]),
-                                      &(permutedMatchProbs[0]),
+                                      permutedQueryProbs,
+                                      permutedMatchProbs,
                                       kLambdaErrorTolerance,
                                       kLambdaFunctionTolerance,
                                       kLambdaIterationLimit);
@@ -1528,15 +1488,10 @@ Blast_AdjustScores(int ** matrix,
                                          composition_adjust_mode);
     }  /* end else call Yi-Kuo's code to choose mode for matrix adjustment. */
 
-    if (eCompoScaleOldMatrix == *matrix_adjust_rule) {
-        return Blast_CompositionBasedStats(matrix, ratioToPassBack, matrixInfo,
-                                           query_composition->prob,
-                                           subject_composition->prob,
-                                           calc_lambda,
-                                           (compositionTestIndex > 0));
-    } else {
-        *ratioToPassBack = 1.0;    /* meaningless for this mode */
-        return
+    if (eCompoScaleOldMatrix != *matrix_adjust_rule) {
+        /* Try matrix optimization, if it fails to converge, we
+           fall back to traditional scaling below */
+        int status =
             Blast_CompositionMatrixAdj(matrix,
                                        alphsize,
                                        *matrix_adjust_rule,
@@ -1550,5 +1505,17 @@ Blast_AdjustScores(int ** matrix,
                                        kFixedReBlosum62,
                                        NRrecord,
                                        matrixInfo);
-    }
+
+        *ratioToPassBack = 1.0;    /* meaningless for this mode */
+        if (status <= 0)
+            return status;      /* Success (=0) or fatal error (<0)*/
+            
+    } /* End try matrix optimization */
+
+    *matrix_adjust_rule = eCompoScaleOldMatrix; 
+    return Blast_CompositionBasedStats(matrix, ratioToPassBack, matrixInfo,
+                                       query_composition->prob,
+                                       subject_composition->prob,
+                                       calc_lambda,
+                                       (compositionTestIndex > 0));
 }
diff --git a/algo/blast/composition_adjustment/composition_constants.h b/algo/blast/composition_adjustment/composition_constants.h
index af54d12..ffff425 100644
--- a/algo/blast/composition_adjustment/composition_constants.h
+++ b/algo/blast/composition_adjustment/composition_constants.h
@@ -1,4 +1,4 @@
-/* $Id: composition_constants.h,v 1.8 2006/06/29 16:50:24 gertz Exp $
+/* $Id: composition_constants.h,v 1.9 2010/03/26 14:54:33 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -35,6 +35,10 @@
 
 #include <algo/blast/core/ncbi_std.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /** Minimum score in a matrix */
 #define COMPO_SCORE_MIN INT2_MIN
 
@@ -46,12 +50,22 @@
     structures that are statically allocated. */
 #define COMPO_LARGEST_ALPHABET 28
 
+/* NOTE: Please keep these comments in sync with argument descriptions in
+ * CCompositionBasedStatsArgs::SetArgumentDescriptions()
+ */
+
 /** An collection of constants that specify all permissible
  * modes of composition adjustment */
 typedef enum ECompoAdjustModes {
+    /** Don't use composition based statistics */
     eNoCompositionBasedStats       = 0,
+    /** Composition-based statistics as in NAR 29:2994-3005, 2001 */
     eCompositionBasedStats         = 1,
+    /** Composition-based score adjustment as in Bioinformatics 21:902-911,
+     * 2005, conditioned on sequence properties. Cannot be applied to PSSMs. */
     eCompositionMatrixAdjust       = 2,
+    /** Composition-based score adjustment as in Bioinformatics 21:902-911,
+     * 2005, unconditionally. Cannot be applied to PSSMs. */
     eCompoForceFullMatrixAdjust    = 3,
     eNumCompoAdjustModes
 } ECompoAdjustModes;
@@ -69,5 +83,8 @@ typedef enum EMatrixAdjustRule {
 } EMatrixAdjustRule;
 
 
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff --git a/algo/blast/composition_adjustment/redo_alignment.h b/algo/blast/composition_adjustment/redo_alignment.h
index 27467e6..fe242a8 100644
--- a/algo/blast/composition_adjustment/redo_alignment.h
+++ b/algo/blast/composition_adjustment/redo_alignment.h
@@ -1,4 +1,4 @@
-/* $Id: redo_alignment.h,v 1.12 2007/10/11 14:25:37 kazimird Exp $
+/* $Id: redo_alignment.h,v 1.13 2010/03/26 14:54:33 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -43,6 +43,9 @@
 #include <algo/blast/composition_adjustment/smith_waterman.h>
 #include <algo/blast/composition_adjustment/compo_heap.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /**
  * Within the composition adjustment module, an object of type
@@ -463,4 +466,8 @@ int BlastCompo_EarlyTermination(double evalue,
                                 BlastCompo_Heap significantMatches[],
                                 int numQueries);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/algo/blast/core/aa_ungapped.c b/algo/blast/core/aa_ungapped.c
index ca0c051..8218cb3 100644
--- a/algo/blast/core/aa_ungapped.c
+++ b/algo/blast/core/aa_ungapped.c
@@ -1,4 +1,4 @@
-/* $Id: aa_ungapped.c,v 1.59 2007/03/07 19:25:34 kazimird Exp $
+/* $Id: aa_ungapped.c,v 1.62 2010/07/27 18:24:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,7 +30,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-    "$Id: aa_ungapped.c,v 1.59 2007/03/07 19:25:34 kazimird Exp $";
+    "$Id: aa_ungapped.c,v 1.62 2010/07/27 18:24:31 kazimird Exp $";
 #endif                          /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/aa_ungapped.h>
@@ -459,8 +459,6 @@ s_BlastAaWordFinder_TwoHit(const BLAST_SequenceBlk * subject,
     Int4 i;
     Int4 hits = 0;
     Int4 totalhits = 0;
-    Int4 first_offset = 0;
-    Int4 last_offset;
     Int4 score;
     Int4 hsp_q, hsp_s, hsp_len = 0;
     Int4 window;
@@ -473,6 +471,7 @@ s_BlastAaWordFinder_TwoHit(const BLAST_SequenceBlk * subject,
     BlastUngappedCutoffs *cutoffs;
     BLAST_DiagTable * diag = ewp->diag_table;
     TAaScanSubjectFunction scansub;
+    Int4 scan_range[3];
 
     ASSERT(diag != NULL);
 
@@ -497,12 +496,15 @@ s_BlastAaWordFinder_TwoHit(const BLAST_SequenceBlk * subject,
         scansub = (TAaScanSubjectFunction)(lookup->scansub_callback);
         wordsize = lookup->word_length;
     }
-    last_offset = subject->length - wordsize;
 
-    while (first_offset <= last_offset) {
+    scan_range[0] = 0;
+    scan_range[1] = subject->seq_ranges[0].left;
+    scan_range[2] = subject->seq_ranges[0].right - wordsize;
+
+    while (scan_range[1] <= scan_range[2]) {
         /* scan the subject sequence for hits */
-        hits = scansub(lookup_wrap, subject, &first_offset,
-                                  offset_pairs, array_size);
+        hits = scansub(lookup_wrap, subject, 
+                                  offset_pairs, array_size, scan_range);
 
         totalhits += hits;
         /* for each hit, */
@@ -712,8 +714,6 @@ s_BlastAaWordFinder_OneHit(const BLAST_SequenceBlk * subject,
     Int4 wordsize;
     Int4 hits = 0;
     Int4 totalhits = 0;
-    Int4 first_offset = 0;
-    Int4 last_offset;
     Int4 hsp_q, hsp_s, hsp_len;
     Int4 s_last_off;
     Int4 i;
@@ -723,6 +723,7 @@ s_BlastAaWordFinder_OneHit(const BLAST_SequenceBlk * subject,
     Int4 hits_extended = 0;
     BLAST_DiagTable * diag = ewp->diag_table;
     TAaScanSubjectFunction scansub;
+    Int4 scan_range[3];
 
     ASSERT(diag != NULL);
 
@@ -745,12 +746,15 @@ s_BlastAaWordFinder_OneHit(const BLAST_SequenceBlk * subject,
         scansub = (TAaScanSubjectFunction)(lookup->scansub_callback);
         wordsize = lookup->word_length;
     }
-    last_offset = subject->length - wordsize;
 
-    while (first_offset <= last_offset) {
+    scan_range[0] = 0;
+    scan_range[1] = subject->seq_ranges[0].left;
+    scan_range[2] = subject->seq_ranges[0].right - wordsize;
+
+    while (scan_range[1] <= scan_range[2]) {
         /* scan the subject sequence for hits */
-        hits = scansub(lookup_wrap, subject, &first_offset,
-                       offset_pairs, array_size);
+        hits = scansub(lookup_wrap, subject,
+                       offset_pairs, array_size, scan_range);
 
         totalhits += hits;
         /* for each hit, */
diff --git a/algo/blast/core/blast_aalookup.c b/algo/blast/core/blast_aalookup.c
index b7cde67..45de77b 100644
--- a/algo/blast/core/blast_aalookup.c
+++ b/algo/blast/core/blast_aalookup.c
@@ -1,4 +1,4 @@
-/* $Id: blast_aalookup.c,v 1.12 2008/11/04 14:54:34 kazimird Exp $
+/* $Id: blast_aalookup.c,v 1.13 2009/10/01 17:55:38 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-    "$Id: blast_aalookup.c,v 1.12 2008/11/04 14:54:34 kazimird Exp $";
+    "$Id: blast_aalookup.c,v 1.13 2009/10/01 17:55:38 kazimird Exp $";
 #endif                          /* SKIP_DOXYGEN_PROCESSING */
 
 /** Structure containing information needed for adding neighboring words. 
@@ -961,7 +961,7 @@ typedef struct LetterAndScoreDifferencePair{
 } LetterAndScoreDifferencePair;
 
 /** callback for the "sort" */
-int ScoreDifferenceSort(const void * a, const void *b ){
+static int ScoreDifferenceSort(const void * a, const void *b ){
     return (((LetterAndScoreDifferencePair*)a)->diff - 
             ((LetterAndScoreDifferencePair*)b)->diff);
 }
diff --git a/algo/blast/core/blast_aascan.c b/algo/blast/core/blast_aascan.c
index 5e13246..edff07c 100644
--- a/algo/blast/core/blast_aascan.c
+++ b/algo/blast/core/blast_aascan.c
@@ -1,4 +1,4 @@
-/* $Id: blast_aascan.c,v 1.13 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: blast_aascan.c,v 1.16 2010/07/23 14:36:34 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-    "$Id: blast_aascan.c,v 1.13 2009/05/27 17:39:36 kazimird Exp $";
+    "$Id: blast_aascan.c,v 1.16 2010/07/23 14:36:34 kazimird Exp $";
 #endif                          /* SKIP_DOXYGEN_PROCESSING */
 
 /**
@@ -46,22 +46,20 @@ static char const rcsid[] =
  *
  * @param lookup_wrap the lookup table [in]
  * @param subject the subject sequence [in]
- * @param offset the offset in the subject at which to begin scanning [in/out]
  * @param offset_pairs Array to which hits will be copied [out]
  * @param array_size length of the offset arrays [in]
  * @return The number of hits found.
  */
 static Int4 s_BlastAaScanSubject(const LookupTableWrap * lookup_wrap,
                                  const BLAST_SequenceBlk * subject,
-                                 Int4 * offset,
                                  BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                 Int4 array_size)
+                                 Int4 array_size,
+                                 Int4 * s_range)
 {
     Int4 index;
     Uint1 *s = NULL;
     Uint1 *s_first = NULL;
     Uint1 *s_last = NULL;
-    Int4 s_range[5]; 
     Int4 numhits = 0;           /* number of hits found for a given subject
                                    offset */
     Int4 totalhits = 0;         /* cumulative number of hits found */
@@ -79,12 +77,6 @@ static Int4 s_BlastAaScanSubject(const LookupTableWrap * lookup_wrap,
     ovfl = (Int4 *) lookup->overflow;
     word_length = lookup->word_length;
 	
-    s_range[0] = 0;
-    s_range[1] = *offset;
-    s_range[2] = subject->length - word_length;
-    s_range[3] = 0;
-    s_range[4] = subject->length;
-
     while (s_DetermineScanningOffsets(subject, word_length, word_length, s_range)) {
     s_first=subject->sequence + s_range[1];
     s_last=subject->sequence + s_range[2];
@@ -131,7 +123,7 @@ static Int4 s_BlastAaScanSubject(const LookupTableWrap * lookup_wrap,
             } else
                 /* not enough space in the destination array; return early */
             {
-                *offset = s - subject->sequence;
+                s_range[1] = s - subject->sequence;
                 return totalhits;
             }
         }
@@ -140,23 +132,20 @@ static Int4 s_BlastAaScanSubject(const LookupTableWrap * lookup_wrap,
     } /* end while */
 
     /* if we get here, we fell off the end of the sequence */
-    *offset = subject->length - word_length + 1;
-
     return totalhits;
 }
 
 /** same function for small lookup table */
 static Int4 s_BlastSmallAaScanSubject(const LookupTableWrap * lookup_wrap,
                                  const BLAST_SequenceBlk * subject,
-                                 Int4 * offset,
                                  BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                 Int4 array_size)
+                                 Int4 array_size,
+                                 Int4 * s_range)
 {
     Int4 index;
     Uint1 *s = NULL;
     Uint1 *s_first = NULL;
     Uint1 *s_last = NULL;
-    Int4 s_range[5];
     Int4 numhits = 0;           /* number of hits found for a given subject
                                    offset */
     Int4 totalhits = 0;         /* cumulative number of hits found */
@@ -174,12 +163,6 @@ static Int4 s_BlastSmallAaScanSubject(const LookupTableWrap * lookup_wrap,
     ovfl = (Uint2 *) lookup->overflow;
     word_length = lookup->word_length;
 	
-    s_range[0] = 0;
-    s_range[1] = *offset;
-    s_range[2] = subject->length - word_length;
-    s_range[3] = 0;
-    s_range[4] = subject->length;
-
     while (s_DetermineScanningOffsets(subject, word_length, word_length, s_range)) {
     s_first=subject->sequence + s_range[1];
     s_last=subject->sequence + s_range[2];
@@ -226,17 +209,15 @@ static Int4 s_BlastSmallAaScanSubject(const LookupTableWrap * lookup_wrap,
             } else
                 /* not enough space in the destination array; return early */
             {
-		*offset = s - subject->sequence;
+                s_range[1] = s - subject->sequence;
 		return totalhits;
             }
         }
     } /* end for */
     s_range[1] = s - subject->sequence;
-    } /* end while */
 
+    } /* end while */
     /* if we get here, we fell off the end of the sequence */
-    *offset = subject->length - word_length + 1;
-
     return totalhits;
 }
 
@@ -258,16 +239,15 @@ static Int4 s_BlastSmallAaScanSubject(const LookupTableWrap * lookup_wrap,
 static Int4 s_BlastCompressedAaScanSubject(
                               const LookupTableWrap * lookup_wrap,
                               const BLAST_SequenceBlk * subject,
-                              Int4 * offset,
                               BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                              Int4 array_size)
+                              Int4 array_size,
+                              Int4 * s_range)
 {
     Int4 index=0;
     Int4 preshift; /* used for 2-stage index calculation */
     Uint1 *s = NULL;
     Uint1 *s_first = NULL;
     Uint1 *s_last = NULL;
-    Int4 s_range[5];
     Int4 numhits = 0;     /* number of hits found for one subject offset */
     Int4 totalhits = 0;         /* cumulative number of hits found */
     PV_ARRAY_TYPE *pv;
@@ -286,12 +266,6 @@ static Int4 s_BlastCompressedAaScanSubject(
     lookup = (BlastCompressedAaLookupTable *) lookup_wrap->lut;
     word_length = lookup->word_length;
 
-    s_range[0] = 0;
-    s_range[1] = *offset;
-    s_range[2] = subject->length - word_length;
-    s_range[3] = 0;
-    s_range[4] = subject->length;
-
     while (s_DetermineScanningOffsets(subject, word_length, word_length, s_range)) {
     s_first=subject->sequence + s_range[1];
     s_last=subject->sequence + s_range[2];
@@ -440,7 +414,7 @@ static Int4 s_BlastCompressedAaScanSubject(
           else
               /* not enough space in the destination array */
 	 {
-              *offset = s - subject->sequence;
+              s_range[1] = s - subject->sequence;
               return totalhits;
           }
        }
@@ -449,8 +423,6 @@ static Int4 s_BlastCompressedAaScanSubject(
     } /* end while */
 
     /* if we get here, we fell off the end of the sequence */
-    *offset = subject->length - word_length + 1;
-
     return totalhits;
 }
 
diff --git a/algo/blast/core/blast_aascan.h b/algo/blast/core/blast_aascan.h
index e532e2f..54528c8 100644
--- a/algo/blast/core/blast_aascan.h
+++ b/algo/blast/core/blast_aascan.h
@@ -1,4 +1,4 @@
-/* $Id: blast_aascan.h,v 1.4 2008/07/23 16:55:47 kazimird Exp $
+/* $Id: blast_aascan.h,v 1.6 2010/07/23 14:36:34 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -44,9 +44,9 @@ extern "C" {
 /** Generic prototype for nucleotide subject scanning routines */
 typedef Int4 (*TAaScanSubjectFunction)(const LookupTableWrap* lookup_wrap,
                                   const BLAST_SequenceBlk* subject,
-                                  Int4 *start_offset,
                                   BlastOffsetPair* NCBI_RESTRICT offset_pairs,
-                                  Int4 max_hits);
+                                  Int4 max_hits,
+                                  Int4 * s_range);
 
 /** Choose the most appropriate function to scan through
  * protein subject sequences
diff --git a/algo/blast/core/blast_def.h b/algo/blast/core/blast_def.h
index e979f86..7ab1cf7 100644
--- a/algo/blast/core/blast_def.h
+++ b/algo/blast/core/blast_def.h
@@ -1,4 +1,4 @@
-/* $Id: blast_def.h,v 1.89 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: blast_def.h,v 1.91 2010/07/27 18:24:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -116,6 +116,12 @@ NCBI_XBLAST_EXPORT extern const int kUngappedHSPNumMax;
 NCBI_XBLAST_EXPORT
 void __sfree(void** x);
 
+/** This symbol enables the verbose option in makeblastdb and other BLAST+
+ * search command line applications, as well as the option to submit searches
+ * to the test server in NCBI for remote BLAST searches 
+#define _BLAST_DEBUG 1
+*/
+
 #if 0
 /** Define this symbol to enable debugging APIs in the BlastSeqSrc interface to
  * allow diagnostics/debugging to be performed in the composition based
@@ -225,6 +231,10 @@ typedef struct BlastMaskLoc {
    BlastSeqLoc** seqloc_array; 
 } BlastMaskLoc;
 
+#define DB_MASK_NONE 0   /* no db mask */
+#define DB_MASK_SOFT 1   /* soft db mask */
+#define DB_MASK_HARD 2   /* hard db mask */
+
 /** Structure to hold a sequence. */
 typedef struct BLAST_SequenceBlk {
    Uint1* sequence; /**< Sequence used for search (could be translation). */
@@ -239,6 +249,10 @@ typedef struct BLAST_SequenceBlk {
                                   sequence */
    Boolean sequence_start_allocated; /**< TRUE if memory has been allocated 
                                         for sequence_start */
+   Uint1* sequence_start_nomask; /**< Query sequence without masking. */
+   Uint1* sequence_nomask; /**< Start of query sequence without masking. */
+   Boolean nomask_allocated; /**< If false the two above are just pointers to
+                                   sequence and sequence_start. */
    Uint1* oof_sequence; /**< Mixed-frame protein representation of a
                              nucleotide sequence for out-of-frame alignment */
    Boolean oof_sequence_allocated; /**< TRUE if memory has been allocated 
@@ -264,6 +278,7 @@ typedef struct BLAST_SequenceBlk {
    Uint4 num_seq_ranges;    /**< Number of elements in seq_ranges */
    Boolean seq_ranges_allocated;   /**< TRUE if memory has been allocated for
                                       seq_ranges */
+   Int4 mask_type;          /**< type of subject masking */
    /* END: Data members needed for masking subjects from a BLAST database */
 } BLAST_SequenceBlk;
 
diff --git a/algo/blast/core/blast_engine.c b/algo/blast/core/blast_engine.c
index d4c9326..8c56b18 100644
--- a/algo/blast/core/blast_engine.c
+++ b/algo/blast/core/blast_engine.c
@@ -1,4 +1,4 @@
-/* $Id: blast_engine.c,v 1.257 2009/05/27 21:59:29 kazimird Exp $
+/* $Id: blast_engine.c,v 1.270 2010/08/06 14:24:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -37,7 +37,7 @@
  *        BLAST_PreliminarySearchEngine
  *            if (RPS BLAST) {
  *                s_RPSPreliminarySearchEngine
-                      s_BlastSearchEngineCore
+ *                    s_BlastSearchEngineCore
  *            } else {
  *                for (all sequences in the database) 
  *                    s_BlastSearchEngineCore
@@ -55,7 +55,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_engine.c,v 1.257 2009/05/27 21:59:29 kazimird Exp $";
+    "$Id: blast_engine.c,v 1.270 2010/08/06 14:24:46 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_engine.h>
@@ -79,10 +79,13 @@ static char const rcsid[] =
 #include <algo/blast/core/gencode_singleton.h>
 #include "blast_gapalign_priv.h"
 
+/** Converts nucleotide coordinates to protein */
+#define CONV_NUCL2PROT_COORDINATES(length) (length) / CODON_LENGTH
+
 NCBI_XBLAST_EXPORT const int   kBlastMajorVersion = 2;
 NCBI_XBLAST_EXPORT const int   kBlastMinorVersion = 2;
-NCBI_XBLAST_EXPORT const int   kBlastPatchVersion = 21;
-NCBI_XBLAST_EXPORT const char* kBlastReleaseDate = "May-27-2009";
+NCBI_XBLAST_EXPORT const int   kBlastPatchVersion = 24;
+NCBI_XBLAST_EXPORT const char* kBlastReleaseDate = "Aug-02-2010";
 
 /** Structure to be passed to s_BlastSearchEngineCore, containing pointers 
     to various preallocated structures and arrays. */
@@ -115,6 +118,188 @@ s_BlastCoreAuxStructFree(BlastCoreAuxStruct* aux_struct)
    return NULL;
 }
 
+/** Structure used for subject sequence split */
+typedef struct SubjectSplitStruct {
+
+    Uint1* sequence;        /**< backup of original sequence */
+    SSeqRange  full_range;  /**< full sequence range */
+
+    SSeqRange* seq_ranges;  /**< backup of original sequence range */
+    Int4 num_seq_ranges;    /**< backup of original number of items in seq_ranges */
+    Int4 allocated;         /**< number of seq_range allocated for subject */
+
+    SSeqRange* hard_ranges; /**< sequence ranges for hard masking */
+    Int4 num_hard_ranges;   /**< number of hard masking ranges */
+    Int4 hm_index;          /**< the current hard masking range index*/
+
+    SSeqRange* soft_ranges; /**< sequence ranges for soft masking */
+    Int4 num_soft_ranges;   /**< number of soft masking ranges */
+    Int4 sm_index;          /**< the current soft masking range index*/
+
+    Int4 offset;            /**< the offset of current chunk */
+    Int4 next;              /**< the offset of next chunk */
+
+} SubjectSplitStruct;
+
+static void s_BackupSubject(BLAST_SequenceBlk* subject,
+                            SubjectSplitStruct* backup)
+{
+    if (backup->sequence) return;
+
+    backup->sequence = subject->sequence;
+    backup->full_range.left = 0;
+    backup->full_range.right = subject->length;
+
+    backup->seq_ranges = subject->seq_ranges;
+    backup->num_seq_ranges = subject->num_seq_ranges;
+    backup->allocated = 0;
+
+    backup->hard_ranges = &(backup->full_range);
+    backup->num_hard_ranges = 1;
+    backup->hm_index = 0;
+
+    backup->soft_ranges = &(backup->full_range);
+    backup->num_soft_ranges = 1;
+    backup->sm_index = 0;
+
+    if (subject->mask_type == DB_MASK_SOFT) {
+        ASSERT (backup->seq_ranges);
+        ASSERT (backup->num_seq_ranges >= 1);
+        backup->soft_ranges = backup->seq_ranges;
+        backup->num_soft_ranges = backup->num_seq_ranges;
+    } else if (subject->mask_type == DB_MASK_HARD) {
+        ASSERT (backup->seq_ranges);
+        ASSERT (backup->num_seq_ranges >= 1);
+        backup->hard_ranges = backup->seq_ranges;
+        backup->num_hard_ranges = backup->num_seq_ranges;
+    } 
+
+    backup->offset = backup->hard_ranges[0].left;
+    backup->next = backup->offset;
+    subject->chunk = -1; 
+
+}
+
+static void s_AllocateSeqRange(BLAST_SequenceBlk* subject,
+                               SubjectSplitStruct* backup,
+                               Int4 num_seq_ranges)
+{
+    ASSERT(num_seq_ranges >= 1);
+    subject->num_seq_ranges = num_seq_ranges;
+    if (backup->allocated >= num_seq_ranges) return;
+    if (backup->allocated) {
+        sfree(subject->seq_ranges);
+    }
+
+    backup->allocated = num_seq_ranges;
+    subject->seq_ranges = (SSeqRange *) calloc(backup->allocated,
+                                   sizeof(SSeqRange));
+}
+
+static void s_RestoreSubject(BLAST_SequenceBlk* subject,
+                             SubjectSplitStruct* backup)
+{
+    if (! backup->sequence) return;
+
+    subject->sequence = backup->sequence;
+    subject->length = backup->full_range.right;
+
+    if (backup->allocated) {
+        sfree(subject->seq_ranges);
+    }
+    subject->seq_ranges = backup->seq_ranges;
+    subject->num_seq_ranges = backup->num_seq_ranges;
+
+    backup->sequence = NULL;
+}
+
+const Int2 SUBJECT_SPLIT_DONE = 0;      /**< return value indicating hitting the end */
+const Int2 SUBJECT_SPLIT_OK = 1;        /**< return value indicating OK */
+const Int2 SUBJECT_SPLIT_NO_RANGE = 2;  /**< return value indicating all masked out */
+
+static Int2 s_GetNextSubjectChunk(BLAST_SequenceBlk* subject,
+                                  SubjectSplitStruct *backup,
+                                  Boolean is_nucleotide)
+{
+    int start, len, i, residual;
+
+    ASSERT(subject);
+    ASSERT(backup);
+
+    if (backup->next >= backup->full_range.right) return SUBJECT_SPLIT_DONE;
+
+    residual = is_nucleotide ?  backup->next % COMPRESSION_RATIO : 0;
+    backup->offset = backup->next - residual;
+    subject->sequence = backup->sequence + ((is_nucleotide) ?
+                        backup->offset /COMPRESSION_RATIO : backup->offset);
+
+    if (backup->offset + MAX_DBSEQ_LEN < 
+        backup->hard_ranges[backup->hm_index].right) {
+
+        subject->length = MAX_DBSEQ_LEN;
+        backup->next = backup->offset + MAX_DBSEQ_LEN - DBSEQ_CHUNK_OVERLAP;
+
+    } else {
+
+        subject->length = backup->hard_ranges[backup->hm_index].right 
+                        - backup->offset;
+        backup->hm_index++;
+        backup->next = (backup->hm_index < backup->num_hard_ranges) ?
+                        backup->hard_ranges[backup->hm_index].left :
+                        backup->full_range.right;
+    }
+
+    (subject->chunk)++;
+
+    /* if no chunking is performed */
+    if (backup->offset == 0 && backup->next == backup->full_range.right) {
+        subject->seq_ranges = backup->soft_ranges;
+        subject->num_seq_ranges = backup->num_soft_ranges;
+        return SUBJECT_SPLIT_OK;
+    }
+
+    /* if soft masking is off */
+    if (subject->mask_type != DB_MASK_SOFT) {
+        s_AllocateSeqRange(subject, backup, 1);
+        subject->seq_ranges[0].left = residual;
+        subject->seq_ranges[0].right = subject->length;
+        return SUBJECT_SPLIT_OK;
+    }
+      
+    /* soft masking is on, sequence is chunked, must re-allocate and adjust */
+    ASSERT (residual == 0);
+    start = backup->offset;
+    len = start + subject->length;
+    i = backup->sm_index;
+
+    while (backup->soft_ranges[i].right < start) ++i;
+    start = i;
+
+    while (i < backup->num_soft_ranges
+        && backup->soft_ranges[i].left < len) ++i;
+    len = i - start;
+    backup->sm_index = i - 1;
+
+    ASSERT(len >= 0);
+    ASSERT(backup->sm_index >= 0);
+
+    if (len == 0) return SUBJECT_SPLIT_NO_RANGE;
+
+    s_AllocateSeqRange(subject, backup, len);
+
+    for (i=0; i<len; i++) {
+        subject->seq_ranges[i].left = backup->soft_ranges[i+start].left - backup->offset;
+        subject->seq_ranges[i].right = backup->soft_ranges[i+start].right - backup->offset;
+    }
+
+    if (subject->seq_ranges[0].left < 0) 
+        subject->seq_ranges[0].left = 0;
+    if (subject->seq_ranges[len-1].right > subject->length)
+        subject->seq_ranges[len-1].right = subject->length;
+
+    return SUBJECT_SPLIT_OK;
+}
+
 /** Adjust HSP coordinates for out-of-frame gapped extension.
  * @param program One of blastx or tblastn [in]
  * @param init_hitlist List of hits after ungapped extension [in]
@@ -201,140 +386,6 @@ s_RPSOffsetArrayToContextOffsets(BlastQueryInfo    * info,
    OffsetArrayToContextOffsets(info, new_offsets, kProgram);
 }
 
-/** 
- * @brief Adjust the data that is relevant to processing  the subject chunks
- * 
- * @param total_subject_length total 'unchunked' length of subject [in]
- * @param is_nucleotide whether the sequence is nucleotide or not [in]
- * @param offset offset at which the subject is being examined [in|out]
- * @param subject subject sequence block to be modified [in|out]
- * @param seq_ranges_backup Backup of BLAST_SequenceBlk::seq_ranges
- * (initialized on first call for each subject sequence) as this data can be
- * modified if multiple chunks are present [in|out]
- * @param num_seq_ranges_backup number of elements in the seq_ranges_backup
- * array [in|out]
- */
-static void
-s_AdjustSubjectChunks(Int4 total_subject_length, 
-                      Boolean is_nucleotide, Int4* offset, 
-                      BLAST_SequenceBlk* subject,
-                      SSeqRange** seq_ranges_backup,
-                      Int4* num_seq_ranges_backup)
-{
-    ASSERT(offset);
-    ASSERT(subject);
-    if (subject->chunk > 0) {
-        *offset += subject->length - DBSEQ_CHUNK_OVERLAP;
-        if (is_nucleotide) {
-           subject->sequence += 
-              (subject->length - DBSEQ_CHUNK_OVERLAP)/COMPRESSION_RATIO;
-        } else {
-           subject->sequence += (subject->length - DBSEQ_CHUNK_OVERLAP);
-        }
-    }
-    subject->length = MIN(total_subject_length - *offset, MAX_DBSEQ_LEN);
-
-    if (total_subject_length <= MAX_DBSEQ_LEN) {
-        ASSERT(subject->chunk == 0);
-        return;
-    }
-
-    /* Save a copy of the BLAST_SequenceBlk::seq_ranges */
-    if ( (*seq_ranges_backup == NULL) && (subject->num_seq_ranges) ) {
-        size_t num_bytes = sizeof(*subject->seq_ranges)*subject->num_seq_ranges;
-        ASSERT(subject->num_seq_ranges);
-        *num_seq_ranges_backup = subject->num_seq_ranges;
-        *seq_ranges_backup = (SSeqRange*)malloc(num_bytes);
-        ASSERT(*seq_ranges_backup);
-        memcpy((void*)*seq_ranges_backup, (void*)subject->seq_ranges,
-               num_bytes);
-    }
-
-    /* Adjust BLAST_SequenceBlk::seq_ranges so that they correspond to the
-     * subject chunk being processed */
-    if (*num_seq_ranges_backup) {
-        const Int4 start = subject->chunk * MAX_DBSEQ_LEN - 
-            subject->chunk * DBSEQ_CHUNK_OVERLAP;
-        const Int4 stop = start + subject->length;
-
-        Int4 i = 0, starting_idx = 0, ending_idx = 0;
-
-        ASSERT(start < stop);
-        ASSERT(*num_seq_ranges_backup >= 1);
-
-        starting_idx = SSeqRangeArrayLessThanOrEqual(*seq_ranges_backup,
-                                           *num_seq_ranges_backup, start);
-        ending_idx = SSeqRangeArrayLessThanOrEqual(*seq_ranges_backup,
-                                         *num_seq_ranges_backup, stop);
-
-		/* fix up SSeqRangeArrayLessThanOrEqual() output */
-		if (stop < (*seq_ranges_backup)[ending_idx].left) {
-			if (ending_idx) ending_idx--;
-			}
-
-        subject->num_seq_ranges = ending_idx - starting_idx + 1;
-
-		ASSERT(starting_idx >= 0);
-		ASSERT(ending_idx >= 0);
-		ASSERT(starting_idx < *num_seq_ranges_backup);
-		ASSERT(ending_idx < *num_seq_ranges_backup);
-
-		/* sanity check cases where masks lie outside the subject chunk */
-		
-		/* if the subject starts after the last mask ends, there's nothing to mask. */
-		if (start > (*seq_ranges_backup)[ending_idx].right)
-			return;
-	
-		/* if the subject ends before the first mask begins, there's nothing to mask. */
-		if (stop < (*seq_ranges_backup)[starting_idx].left)
-			return;
-		
-        /* copy the relevant ranges ... */
-        if (subject->num_seq_ranges > 0) {
-            memcpy((void*)subject->seq_ranges,
-                   (void*)&(*seq_ranges_backup)[starting_idx], 
-                   sizeof(*subject->seq_ranges)*subject->num_seq_ranges);
-        }
-
-        /* ... and adjust so that they are in chunk's coordinates */
-        for (i = 0; i < (Int4)subject->num_seq_ranges; i++) {
-            subject->seq_ranges[i].left = 
-                MAX(subject->seq_ranges[i].left - start, 0);
-            subject->seq_ranges[i].right = 
-                MIN(subject->seq_ranges[i].right - start, subject->length);
-
-            ASSERT(subject->seq_ranges[i].left >= 0);
-            ASSERT(subject->seq_ranges[i].left <= MAX_DBSEQ_LEN);
-            ASSERT(subject->seq_ranges[i].right >= 0);
-            ASSERT(subject->seq_ranges[i].right <= MAX_DBSEQ_LEN);
-        }
-    }
-}
-
-/** 
- * @brief Restore the BLAST_SequenceBlk::{seq_ranges,num_seq_ranges} fields
- * backed up in s_AdjustSubjectChunks
- * 
- * @param subject subject sequence block to be modified [in|out]
- * @param seq_ranges_backup original data in BLAST_SequenceBlk::seq_ranges [in]
- * @param num_seq_ranges_backup original data in
- * BLAST_SequenceBlk::num_seq_ranges [in]
- * @sa s_AdjustSubjectChunks
- */
-static void
-s_RestoreSeqRanges(BLAST_SequenceBlk* subject, 
-                   SSeqRange** seq_ranges_backup, 
-                   Int4 num_seq_ranges_backup)
-{
-    if (*seq_ranges_backup != NULL) {
-        ASSERT(num_seq_ranges_backup >= 1);
-        subject->num_seq_ranges = num_seq_ranges_backup;
-        memcpy((void*)subject->seq_ranges, (void*)*seq_ranges_backup,
-               sizeof(*subject->seq_ranges) * subject->num_seq_ranges);
-        sfree(*seq_ranges_backup);
-    }
-}
-
 /** Searches only one context of a database sequence, but does all chunks if it is split.
  * @param program_number BLAST program type [in]
  * @param query Query sequence structure [in]
@@ -374,50 +425,43 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number,
    SBlastProgress* progress_info)
 {
       Int2 status = 0; /* return value */
-      Int4 num_chunks; /* loop variable below. */
-      Int4 offset = 0; /* Used as offset into subject sequence (if chunked) */
-      Int4 total_subject_length; /* Length of subject sequence used when split. */
       BlastHSPList* combined_hsp_list = NULL;
       BlastHSPList* hsp_list = NULL;
       BlastInitHitList* init_hitlist = aux_struct->init_hitlist;
       BlastScoringOptions* score_options = score_params->options;
       BlastUngappedStats* ungapped_stats = NULL;
       BlastGappedStats* gapped_stats = NULL;
-      Int4 **matrix;
-      /* Back up of BLAST_SequenceBlk::seq_ranges, as this data needs to be
-       * modified if the subject sequence is long enough that it is split into
-       * chunks */
-      SSeqRange* seq_ranges_backup = NULL;
-      /* Number of elements in the seq_ranges_backup array */
-      Int4 num_seq_ranges_backup = 0;
+    Int4 **matrix = (gap_align->positionBased) ?
+                     gap_align->sbp->psi_matrix->pssm->data :
+                     gap_align->sbp->matrix->data;
       const Boolean kTranslatedSubject = 
         (Blast_SubjectIsTranslated(program_number) || program_number == eBlastTypeRpsTblastn);
       const Boolean kNucleotide = (program_number == eBlastTypeBlastn ||
                                 program_number == eBlastTypePhiBlastn);
       const int kHspNumMax = BlastHspNumMax(score_options->gapped_calculation, hit_params->options);
       const int kScanSubjectOffsetArraySize = GetOffsetArraySize(lookup);
+    Int4 overlap;
+
+    SubjectSplitStruct backup; 
+    backup.sequence = NULL;
      
       if (diagnostics) {
          ungapped_stats = diagnostics->ungapped_stat;
          gapped_stats = diagnostics->gapped_stat;
       }
 
-      if (gap_align->positionBased)
-         matrix = gap_align->sbp->psi_matrix->pssm->data;
-      else
-         matrix = gap_align->sbp->matrix->data;
+    s_BackupSubject(subject, &backup);
 
-      /* Split subject sequence into chunks if it is too long */
-      num_chunks = (subject->length - DBSEQ_CHUNK_OVERLAP) / 
-         (MAX_DBSEQ_LEN - DBSEQ_CHUNK_OVERLAP) + 1;
-      total_subject_length = subject->length;
+    while (TRUE) {
+        status = s_GetNextSubjectChunk(subject, &backup, kNucleotide);
+        if (status == SUBJECT_SPLIT_DONE) break;
+        if (status == SUBJECT_SPLIT_NO_RANGE) continue;
+        ASSERT(status == SUBJECT_SPLIT_OK);
+        ASSERT(subject->num_seq_ranges >= 1);
+        ASSERT(subject->seq_ranges);
       
-      for (subject->chunk = 0; subject->chunk < num_chunks; subject->chunk++) {
          /* Delete if not done in last loop iteration to prevent memory leak. */
-         hsp_list = Blast_HSPListFree(hsp_list);  /* In case this was not freed in above loop. */
-         s_AdjustSubjectChunks(total_subject_length, kNucleotide,
-                               &offset, subject, &seq_ranges_backup,
-                               &num_seq_ranges_backup);
+        hsp_list = Blast_HSPListFree(hsp_list);
          
          BlastInitHitListReset(init_hitlist);
          
@@ -428,8 +472,7 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number,
                                    kScanSubjectOffsetArraySize,
                                    init_hitlist, ungapped_stats);
             
-            if (init_hitlist->total == 0)
-               continue;
+            if (init_hitlist->total == 0) continue;
          }
 
          if (score_options->gapped_calculation) {
@@ -438,7 +481,7 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number,
                /* Convert query offsets in all HSPs into the mixed-frame  
                   coordinates */
                s_TranslateHSPsToDNAPCoord(program_number, init_hitlist, 
-                  query_info, subject->frame, orig_length, offset);
+                       query_info, subject->frame, orig_length, backup.offset);
                if (kTranslatedSubject) {
                   prot_length = subject->length;
                   subject->length = orig_length;
@@ -451,9 +494,10 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number,
              * are saved.
             */
             /* fence_hit is null, since this is only for prelim stage. */
-            aux_struct->GetGappedScore(program_number, query, query_info, 
+        status = aux_struct->GetGappedScore(program_number, query, query_info, 
                subject, gap_align, score_params, ext_params, hit_params, 
                init_hitlist, &hsp_list, gapped_stats, NULL);
+        if (status) break;
 
             /* Removes redundant HSPs. */
              Blast_HSPListPurgeHSPsWithCommonEndpoints(program_number, hsp_list);
@@ -471,8 +515,7 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number,
                                      hit_params->options, &hsp_list);
          }
 
-         if (hsp_list->hspcnt == 0)
-            continue;
+        if (hsp_list->hspcnt == 0) continue;
          
          /* The subject ordinal id is not yet filled in this HSP list */
          hsp_list->oid = subject->oid;
@@ -485,13 +528,15 @@ s_BlastSearchEngineOneContext(EBlastProgramType program_number,
             break;
          }
 
-         Blast_HSPListAdjustOffsets(hsp_list, offset);
+        Blast_HSPListAdjustOffsets(hsp_list, backup.offset);
+        overlap = (backup.offset == backup.hard_ranges[backup.hm_index].left) ?
+                  0 : DBSEQ_CHUNK_OVERLAP;
          status = Blast_HSPListsMerge(&hsp_list, &combined_hsp_list,  
-                                      kHspNumMax, &offset, INT4_MIN,
-                                      DBSEQ_CHUNK_OVERLAP);
+                     kHspNumMax, &(backup.offset), INT4_MIN,
+                     overlap, score_options->gapped_calculation);
       } /* End loop on chunks of subject sequence */
 
-      s_RestoreSeqRanges(subject, &seq_ranges_backup, num_seq_ranges_backup);
+    s_RestoreSubject(subject, &backup);
 
       hsp_list = Blast_HSPListFree(hsp_list);  /* In case this was not freed in above loop. */
 
@@ -585,9 +630,8 @@ s_BlastSearchEngineCore(EBlastProgramType program_number,
    BlastScoringOptions* score_options = score_params->options;
    Int2 status = 0;
    Uint4 context, first_context, last_context;
-   Int4 orig_length = subject->length;
-   Uint1* orig_sequence = subject->sequence;
    BlastQueryInfo* query_info = query_info_in;
+    Int4 orig_length = subject->length;
 
    const Boolean kTranslatedSubject = 
         (Blast_SubjectIsTranslated(program_number) || program_number == eBlastTypeRpsTblastn);
@@ -595,36 +639,46 @@ s_BlastSearchEngineCore(EBlastProgramType program_number,
                                 program_number == eBlastTypePhiBlastn);
    const int kHspNumMax = BlastHspNumMax(score_options->gapped_calculation, hit_options);
 
+    SubjectSplitStruct backup;
+    backup.sequence = NULL;
+
    *hsp_list_out_ptr = NULL;
 
    if (kTranslatedSubject) {
+
+        s_BackupSubject(subject, &backup);
+        if (subject->mask_type) {
+            s_AllocateSeqRange(subject, &backup, backup.num_seq_ranges);
+        } else {
+            subject->num_seq_ranges = 0;
+            subject->seq_ranges = NULL;
+        }
+
       first_context = 0;
       last_context = 5;
       if (score_options->is_ooframe) {
-         BLAST_GetAllTranslations(orig_sequence, eBlastEncodingNcbi2na,
-            orig_length, subject->gen_code_string, &translation_buffer,
+            BLAST_GetAllTranslations(backup.sequence, eBlastEncodingNcbi2na,
+                                     backup.full_range.right, 
+                                     subject->gen_code_string, &translation_buffer,
             &frame_offsets, &subject->oof_sequence);
          subject->oof_sequence_allocated = TRUE;
          frame_offsets_a = frame_offsets;
       } else if (program_number == eBlastTypeRpsTblastn ) {
           /* For RPS tblastn, subject is actually query, which has already 
              been translated during the setup stage. */
-          translation_buffer = orig_sequence - 1;
-          frame_offsets_a = frame_offsets =
-              ContextOffsetsToOffsetArray(query_info_in);
+            translation_buffer = backup.sequence - 1;
+            frame_offsets_a = frame_offsets = ContextOffsetsToOffsetArray(query_info_in);
       } else {
-         BLAST_GetAllTranslations(orig_sequence, eBlastEncodingNcbi2na,
-            orig_length, subject->gen_code_string, &translation_buffer,
+            BLAST_GetAllTranslations(backup.sequence, eBlastEncodingNcbi2na,
+                                     backup.full_range.right, 
+                                     subject->gen_code_string, &translation_buffer,
             &frame_offsets, NULL);
          frame_offsets_a = frame_offsets;
          /* The following limits the search to plus or minus strand if desired. */
-         if (subject->subject_strand == 1)
-         {
+            if (subject->subject_strand == 1) {
              first_context = 0;
              last_context = 2;
-         }
-         else if (subject->subject_strand == 2)
-         {
+            } else if (subject->subject_strand == 2) {
              first_context = 3;
              last_context = 5;
          }
@@ -650,16 +704,33 @@ s_BlastSearchEngineCore(EBlastProgramType program_number,
    /* Loop over frames of the subject sequence */
    for (context=first_context; context<=last_context; context++) {
       BlastHSPList* hsp_list_for_chunks = NULL;
+
       if (kTranslatedSubject) {
-         subject->frame =
-             BLAST_ContextToFrame(eBlastTypeBlastx, context);
-         subject->sequence = 
-            translation_buffer + frame_offsets[context] + 1;
-         subject->length = 
-           frame_offsets[context+1] - frame_offsets[context] - 1;
+            Uint4 i;
+            subject->frame = BLAST_ContextToFrame(eBlastTypeBlastx, context);
+            subject->sequence = translation_buffer + frame_offsets[context] + 1;
+            subject->length = frame_offsets[context+1] - frame_offsets[context] - 1;
+
+            /* perform per-context mask translation */
+            if (context == 0) { /* first positive context */
+                for (i = 0; i < subject->num_seq_ranges; i++) {
+                    subject->seq_ranges[i].left =
+                        CONV_NUCL2PROT_COORDINATES(backup.seq_ranges[i].left);
+                    subject->seq_ranges[i].right =
+                        CONV_NUCL2PROT_COORDINATES(backup.seq_ranges[i].right);
+                }
+            } else if (context == 3) { /* first negative context */
+                for (i = 0; i < subject->num_seq_ranges; i++) {
+                    subject->seq_ranges[subject->num_seq_ranges-i-1].left = 
+                        subject->length - CONV_NUCL2PROT_COORDINATES(backup.seq_ranges[i].right);
+                    subject->seq_ranges[subject->num_seq_ranges-i-1].right = 
+                        subject->length - CONV_NUCL2PROT_COORDINATES(backup.seq_ranges[i].left);
+                }
+            }
       } else {
          subject->frame = context;
       }
+
       status = s_BlastSearchEngineOneContext(program_number, query, query_info, 
                                              subject, orig_length, lookup, 
                                              gap_align, score_params, 
@@ -667,9 +738,7 @@ s_BlastSearchEngineCore(EBlastProgramType program_number,
                                              hit_params, diagnostics, 
                                              aux_struct, &hsp_list_for_chunks,
                                              interrupt_search, progress_info);
-      if (status != 0) {
-          break;
-      }
+        if (status != 0)  break;
      
       if (Blast_HSPListAppend(&hsp_list_for_chunks, &hsp_list_out, kHspNumMax)) {
          status = 1;
@@ -684,9 +753,10 @@ s_BlastSearchEngineCore(EBlastProgramType program_number,
       }
    } /* End loop on frames */
 
-   /* Restore the original contents of the subject block */
-   subject->length = orig_length;
-   subject->sequence = orig_sequence;
+    /* restore mask ranges  */
+    if (kTranslatedSubject) {
+        s_RestoreSubject(subject, &backup);
+    }
 
    if (status) {
        hsp_list_out = Blast_HSPListFree(hsp_list_out);
@@ -979,9 +1049,6 @@ s_RPSPreliminarySearchEngine(EBlastProgramType program_number,
    return status;
 }
 
-/** Converts nucleotide coordinates to protein */
-#define CONV_NUCL2PROT_COORDINATES(length) \
-    ((length) == 0 ? 0 : (length) / CODON_LENGTH)
 
 Int4 
 BLAST_PreliminarySearchEngine(EBlastProgramType program_number, 
@@ -1081,17 +1148,7 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number,
             seq_arg.seq->length); 
       }
 
-
       if (Blast_SubjectIsTranslated(program_number)) {
-          /* Convert the subject sequence ranges to protein coordinates */
-          Uint4 i;
-          for (i = 0; i < seq_arg.seq->num_seq_ranges; i++) {
-              seq_arg.seq->seq_ranges[i].left = 
-                  CONV_NUCL2PROT_COORDINATES(seq_arg.seq->seq_ranges[i].left);
-              seq_arg.seq->seq_ranges[i].right = 
-                  CONV_NUCL2PROT_COORDINATES(seq_arg.seq->seq_ranges[i].right);
-          }
-
           /* If the subject is translated and the BlastSeqSrc implementation
            * doesn't provide a genetic code string, use the default genetic
            * code for all subjects (as in the C toolkit) */
@@ -1114,9 +1171,8 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number,
          if (!gapped_calculation) {
             /* The following must be performed for any ungapped 
                search with a nucleotide database. */
-	     if (Blast_SubjectIsNucleotide(program_number)) {
                status = 
-                  Blast_HSPListReevaluateWithAmbiguitiesUngapped(
+                  Blast_HSPListReevaluateUngapped(
                             program_number, hsp_list, query, 
                             seq_arg.seq, word_params, hit_params, 
                             query_info, sbp, score_params, seq_src, 
@@ -1143,7 +1199,6 @@ BLAST_PreliminarySearchEngine(EBlastProgramType program_number,
                }
                status = Blast_HSPListReapByEvalue(hsp_list, 
                                           hit_params->options);
-            }
              
             /* Calculate and fill the bit scores, since there will be no
                traceback stage where this can be done. */
diff --git a/algo/blast/core/blast_filter.c b/algo/blast/core/blast_filter.c
index 2a02cdb..dfacebf 100644
--- a/algo/blast/core/blast_filter.c
+++ b/algo/blast/core/blast_filter.c
@@ -1,4 +1,4 @@
-/* $Id: blast_filter.c,v 1.95 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: blast_filter.c,v 1.99 2010/03/31 16:14:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,7 +30,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_filter.c,v 1.95 2009/05/27 17:39:36 kazimird Exp $";
+    "$Id: blast_filter.c,v 1.99 2010/03/31 16:14:46 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_util.h>
@@ -415,11 +415,20 @@ BlastFilteringOptionsToString(const SBlastFilterOptions* filtering_options)
 
     /* Mask at hash is a modifier for other filtering options, as such it
      * doesn't make sense to apply it by itself */
-    if (SBlastFilterOptionsMaskAtHash(filtering_options) && 
-        strlen(retval) != 0 ) {
+    if (SBlastFilterOptionsMaskAtHash(filtering_options)) {
+        if (strlen(retval) != 0) {
+            /* Add mask at hash as a modifier for other filtering options */
         if (!s_SafeStrCat(&retval, &retval_size, "m;")) {
             return 0;
         }
+        } else {
+            /* We still need to set "m" in a filter string (WB-391, WB-394) */
+            /* The string below can be modified into "mF" or "mL" or
+               whatever is decided to be the conventional meaning */
+            if (!s_SafeStrCat(&retval, &retval_size, "m;")) {
+                return 0;
+            }
+        }
     }
 
     return strlen(retval) == 0 
@@ -1338,11 +1347,35 @@ BlastSetUp_MaskQuery(BLAST_SequenceBlk* query_blk,
 {
     const Boolean kIsNucl = (program_number == eBlastTypeBlastn);
     Int4 context; /* loop variable. */
+    Int4 total_length = 2; /* Length to copy, adding one for beginning and end. */
+    Boolean has_mask = FALSE; /* Check for whether filter_maskloc is empty. */
+    Int4 index; /* loop variable. */
 
     ASSERT(query_blk);
     ASSERT(query_info);
     ASSERT(filter_maskloc);
 
+    
+    for (index=0; index<filter_maskloc->total_size; index++)
+    {
+         if (filter_maskloc->seqloc_array[index])
+         {
+            has_mask = TRUE;
+            break;
+         }
+    }
+    if (has_mask == FALSE)
+       return;
+
+
+    for (context = query_info->first_context;
+         context <= query_info->last_context; ++context) {
+        total_length += query_info->contexts[context].query_length;
+    }
+    query_blk->sequence_start_nomask = BlastMemDup(query_blk->sequence_start, total_length);
+    query_blk->sequence_nomask = query_blk->sequence_start_nomask + 1;
+    query_blk->nomask_allocated = TRUE;
+
     for (context = query_info->first_context;
          context <= query_info->last_context; ++context) {
       
diff --git a/algo/blast/core/blast_filter.h b/algo/blast/core/blast_filter.h
index 1643268..24040b3 100644
--- a/algo/blast/core/blast_filter.h
+++ b/algo/blast/core/blast_filter.h
@@ -1,4 +1,4 @@
-/* $Id: blast_filter.h,v 1.42 2008/11/03 20:59:44 kazimird Exp $
+/* $Id: blast_filter.h,v 1.46 2010/05/12 12:54:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -54,7 +54,8 @@ NCBI_XBLAST_EXPORT
 extern const Uint1 kProtMask;
 
 /** Repeats filtering default options. */
-#define REPEATS_SEARCH_EVALUE 0.1       /**< Default e-value threshold */
+#define REPEATS_SEARCH_EVALUE 0.1       /**< Default e-value threshold, keep for C toolkit */
+#define REPEATS_SEARCH_MINSCORE 26       /**< Default score cutoff */
 #define REPEATS_SEARCH_PENALTY -1       /**< Default mismatch penalty */
 #define REPEATS_SEARCH_REWARD 1       /**< Default match reward */
 #define REPEATS_SEARCH_GAP_OPEN 2       /**< Default gap opening cost */
diff --git a/algo/blast/core/blast_gapalign.c b/algo/blast/core/blast_gapalign.c
index 24118e6..9e500a0 100644
--- a/algo/blast/core/blast_gapalign.c
+++ b/algo/blast/core/blast_gapalign.c
@@ -1,4 +1,4 @@
-/* $Id: blast_gapalign.c,v 1.195 2009/01/05 16:54:38 kazimird Exp $
+/* $Id: blast_gapalign.c,v 1.199 2010/07/06 17:29:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -32,7 +32,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_gapalign.c,v 1.195 2009/01/05 16:54:38 kazimird Exp $";
+    "$Id: blast_gapalign.c,v 1.199 2010/07/06 17:29:31 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/ncbi_math.h>
@@ -2651,12 +2651,12 @@ BLAST_GreedyGappedAlignment(const Uint1* query, const Uint1* subject,
        }
 
        if (valid_seed_len_r > valid_seed_len_l) {
-           q_seed_start += valid_seed_len_r;
-           s_seed_start += valid_seed_len_r;
+           q_seed_start = q_seed_start_r + valid_seed_len_r;
+           s_seed_start = s_seed_start_r + valid_seed_len_r;
        }
        else {
-           q_seed_start -= valid_seed_len_l;
-           s_seed_start -= valid_seed_len_l;
+           q_seed_start = q_seed_start_l - valid_seed_len_l;
+           s_seed_start = s_seed_start_l - valid_seed_len_l;
        }
    }
    
@@ -3125,6 +3125,8 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number,
       tree = Blast_IntervalTreeInit(0, query->length+1,
                                     0, subject->length+1);
    }
+   if (!tree)
+     return BLASTERR_MEMORY;
 
    for (index=0; index<init_hitlist->total; index++)
    {
@@ -3233,6 +3235,12 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number,
                 continue;
             }
          } else if (is_greedy) {
+            if (init_hsp->ungapped_data) {
+                init_hsp->offsets.qs_offsets.q_off = 
+                    init_hsp->ungapped_data->q_start + init_hsp->ungapped_data->length/2;
+                init_hsp->offsets.qs_offsets.s_off = 
+                    init_hsp->ungapped_data->s_start + init_hsp->ungapped_data->length/2;
+            }
             status = BLAST_GreedyGappedAlignment(
                          query_tmp.sequence, subject->sequence, 
                          query_tmp.length, subject->length, 
@@ -3283,16 +3291,22 @@ Int2 BLAST_GetGappedScore (EBlastProgramType program_number,
                  query_frame = query_info->contexts[context].frame;
              }
 
-             Blast_HSPInit(gap_align->query_start, 
+             status = Blast_HSPInit(gap_align->query_start, 
                            gap_align->query_stop, gap_align->subject_start, 
                            gap_align->subject_stop, 
                            init_hsp->offsets.qs_offsets.q_off, 
                            init_hsp->offsets.qs_offsets.s_off, context, 
                            query_frame, subject->frame, gap_align->score, 
                            &(gap_align->edit_script), &new_hsp);
-             Blast_HSPListSaveHSP(hsp_list, new_hsp);
-             BlastIntervalTreeAddHSP(new_hsp, tree, query_info, 
+             if (status)
+                return status;
+             status = Blast_HSPListSaveHSP(hsp_list, new_hsp);
+             if (status)
+                 break;
+             status = BlastIntervalTreeAddHSP(new_hsp, tree, query_info, 
                                      eQueryAndSubject);
+             if (status)
+                 break;
          }
          else {
             /* a greedy alignment may have traceback associated with it;
diff --git a/algo/blast/core/blast_hits.c b/algo/blast/core/blast_hits.c
index 6e50886..87b90e1 100644
--- a/algo/blast/core/blast_hits.c
+++ b/algo/blast/core/blast_hits.c
@@ -1,4 +1,4 @@
-/* $Id: blast_hits.c,v 1.226 2009/07/13 18:19:32 kazimird Exp $
+/* $Id: blast_hits.c,v 1.234 2010/07/30 17:44:35 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -32,7 +32,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_hits.c,v 1.226 2009/07/13 18:19:32 kazimird Exp $";
+    "$Id: blast_hits.c,v 1.234 2010/07/30 17:44:35 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/ncbi_math.h>
@@ -142,7 +142,7 @@ Blast_HSPInit(Int4 query_start, Int4 query_end, Int4 subject_start,
    *ret_hsp = NULL;
 
    if (new_hsp == NULL)
-	return -1;
+	return BLASTERR_MEMORY;
 
 
    new_hsp->query.offset = query_start;
@@ -875,6 +875,7 @@ Blast_HSPGetTargetTranslation(SBlastTargetTranslation* target_t,
                               const BlastHSP* hsp, Int4* translated_length)
 {
     Int4 context = -1;
+    Int4 start, stop;
 
     ASSERT(target_t != NULL);
 
@@ -882,12 +883,14 @@ Blast_HSPGetTargetTranslation(SBlastTargetTranslation* target_t,
        return NULL;
 
     context = BLAST_FrameToContext(hsp->subject.frame, target_t->program_number);
+    start = target_t->range[2*context];
+    stop = target_t->range[2*context+1];
 
-    if (target_t->partial == TRUE) /* partial == FALSE translation has already been done. */
+    /* skip translation if full translation has already been done */
+    if (target_t->partial && (start || 
+        (stop < target_t->subject_blk->length / CODON_LENGTH -3))) 
     {  
     	 const int kMaxTranslation = 2100; /* Needs to be divisible by three (?) */
-         Int4 start = target_t->range[2*context];
-         Int4 stop = target_t->range[2*context+1];
          Int4 nucl_length = 0;
          Int4 translation_length = 0;
          Int4 nucl_start = 0;
@@ -896,17 +899,21 @@ Blast_HSPGetTargetTranslation(SBlastTargetTranslation* target_t,
     	 Int4 start_shift = 0;
 
          /* HSP coordinates are in terms of protein sequences. */
-         if (hsp->subject.offset < 0 ) {
+         if (hsp->subject.offset < 0) {
              nucl_start = 0;
              nucl_end = target_t->subject_blk->length;
          } else {
              nucl_start = MAX(0, 3*hsp->subject.offset - kMaxTranslation);
              nucl_end = MIN(target_t->subject_blk->length, 3*hsp->subject.end + kMaxTranslation);
+             /* extend to the end of the sequence if close */
+             if (target_t->subject_blk->length - nucl_end <= 21) {
+                 nucl_end = target_t->subject_blk->length;
+             }
          }
 
          nucl_length = nucl_end - nucl_start;
 
-         translation_length = 1+nucl_length/3;
+         translation_length = 1+nucl_length/CODON_LENGTH;
          start_shift = nucl_start/CODON_LENGTH;
 
          if (hsp->subject.frame < 0)
@@ -1202,10 +1209,17 @@ s_HSPEndDiag(const BlastHSP *hsp)
  * @return TRUE if a merge was performed, FALSE if not
  */
 static Boolean 
-s_BlastMergeTwoHSPs(BlastHSP* hsp1, BlastHSP* hsp2)
+s_BlastMergeTwoHSPs(BlastHSP* hsp1, BlastHSP* hsp2, Boolean allow_gap)
 {
    ASSERT(!hsp1->gap_info || !hsp2->gap_info);
 
+   /* do not merge off-diagonal hsps for ungapped search */
+   if (!allow_gap && 
+       hsp1->subject.offset - hsp2->subject.offset -hsp1->query.offset + hsp2->query.offset) 
+   {  
+       return FALSE;
+   }
+
    /* combine the boundaries of the two HSPs, 
       assuming they intersect at all */
    if (CONTAINED_IN_HSP(hsp1->query.offset, hsp1->query.end,
@@ -1216,6 +1230,7 @@ s_BlastMergeTwoHSPs(BlastHSP* hsp1, BlastHSP* hsp2)
                         hsp2->query.end,
                         hsp1->subject.offset, hsp1->subject.end,
                         hsp2->subject.end)) {
+
       hsp1->query.offset = MIN(hsp1->query.offset, hsp2->query.offset);
       hsp1->subject.offset = MIN(hsp1->subject.offset, hsp2->subject.offset);
       hsp1->query.end = MAX(hsp1->query.end, hsp2->query.end);
@@ -1406,6 +1421,7 @@ s_BlastHSPListInsertHSPInHeap(BlastHSPList* hsp_list,
     }
 }
 
+#ifndef NDEBUG
 /** Verifies that the best_evalue field on the BlastHSPList is correct.
  * @param hsp_list object to check [in]
  * @return TRUE if OK, FALSE otherwise.
@@ -1430,6 +1446,7 @@ s_BlastCheckBestEvalue(const BlastHSPList* hsp_list)
 
     return TRUE;
 }
+#endif /* _DEBUG */
 
 /** Gets the best (lowest) evalue from the BlastHSPList.
  * @param hsp_list object containing the evalues [in]
@@ -1676,7 +1693,7 @@ static int s_SortHSPListByOid(const void *x, const void *y)
 Int2 Blast_HitListMerge(BlastHitList** old_hit_list_ptr,
                         BlastHitList** combined_hit_list_ptr,
                         Int4 contexts_per_query, Int4 *split_offsets,
-                        Int4 chunk_overlap_size)
+                        Int4 chunk_overlap_size, Boolean allow_gap)
 {
     Int4 i, j;
     Boolean query_is_split;
@@ -1744,7 +1761,8 @@ Int2 Blast_HitListMerge(BlastHitList** old_hit_list_ptr,
                                     hitlist2->hsplist_array + j,
                                     hsplist2->hsp_max, split_offsets,
                                     contexts_per_query,
-                                    chunk_overlap_size);
+                                    chunk_overlap_size,
+                                    allow_gap);
             }
             else {
                 Blast_HSPListAppend(hitlist1->hsplist_array + i,
@@ -2002,7 +2020,7 @@ Blast_HSPListPurgeHSPsWithCommonEndpoints(EBlastProgramType program,
 }
 
 Int2 
-Blast_HSPListReevaluateWithAmbiguitiesUngapped(EBlastProgramType program, 
+Blast_HSPListReevaluateUngapped(EBlastProgramType program, 
    BlastHSPList* hsp_list, BLAST_SequenceBlk* query_blk, 
    BLAST_SequenceBlk* subject_blk, 
    const BlastInitialWordParameters* word_params,
@@ -2014,9 +2032,10 @@ Blast_HSPListReevaluateWithAmbiguitiesUngapped(EBlastProgramType program,
    const Uint1* subject_start = NULL;
    Uint1* query_start;
    Int4 index, context, hspcnt;
-   Boolean purge, delete_hsp;
+   Boolean purge;
    Int2 status = 0;
    const Boolean kTranslateSubject = Blast_SubjectIsTranslated(program);
+   const Boolean kNucleotideSubject = Blast_SubjectIsNucleotide(program);
    SBlastTargetTranslation* target_t = NULL;
 
    ASSERT(!score_params->options->gapped_calculation);
@@ -2038,11 +2057,15 @@ Blast_HSPListReevaluateWithAmbiguitiesUngapped(EBlastProgramType program,
    if (seq_src) {
       /* Wrap subject sequence block into a BlastSeqSrcGetSeqArg structure, which is 
          needed by the BlastSeqSrc API. */
+      /* If this was a protein subject, leave as is. */
+      if (kNucleotideSubject)
+      {
       BlastSeqSrcGetSeqArg seq_arg;
       memset((void*) &seq_arg, 0, sizeof(seq_arg));
       seq_arg.oid = subject_blk->oid;
       seq_arg.encoding =
          (kTranslateSubject ? eBlastEncodingNcbi4na : eBlastEncodingNucleotide);
+        seq_arg.check_oid_exclusion = TRUE;
       seq_arg.seq = subject_blk;
       /* Return the packed sequence to the database */
       BlastSeqSrcReleaseSequence(seq_src, &seq_arg);
@@ -2050,6 +2073,7 @@ Blast_HSPListReevaluateWithAmbiguitiesUngapped(EBlastProgramType program,
       if ((status=BlastSeqSrcGetSequence(seq_src, &seq_arg)))
           return status;
    }
+   }
 
    if (kTranslateSubject) {
       if (!gen_code_string)
@@ -2059,11 +2083,15 @@ Blast_HSPListReevaluateWithAmbiguitiesUngapped(EBlastProgramType program,
                    score_params->options->is_ooframe, &target_t);
    } else {
       /* Store sequence in blastna encoding in sequence_start */
+      if (subject_blk->sequence_start)
       subject_start = subject_blk->sequence_start + 1;
+      else
+          subject_start = subject_blk->sequence;
    }
 
    purge = FALSE;
    for (index = 0; index < hspcnt; ++index) {
+      Boolean delete_hsp = FALSE;
       if (hsp_array[index] == NULL)
          continue;
       else
@@ -2077,13 +2105,17 @@ Blast_HSPListReevaluateWithAmbiguitiesUngapped(EBlastProgramType program,
       if (kTranslateSubject)
          subject_start = Blast_HSPGetTargetTranslation(target_t, hsp, NULL);
 
+      if (kNucleotideSubject) {
       delete_hsp = 
          Blast_HSPReevaluateWithAmbiguitiesUngapped(hsp, query_start, 
             subject_start, word_params, sbp, kTranslateSubject);
+      }
    
       if (!delete_hsp) {
+          const Uint1* query_nomask = query_blk->sequence_nomask +
+              query_info->contexts[context].query_offset;
           delete_hsp = 
-              Blast_HSPTestIdentityAndLength(program, hsp, query_start, 
+              Blast_HSPTestIdentityAndLength(program, hsp, query_nomask, 
                                              subject_start, 
                                              score_params->options, 
                                              hit_params->options);
@@ -2227,7 +2259,8 @@ Int2 Blast_HSPListAppend(BlastHSPList** old_hsp_list_ptr,
 Int2 Blast_HSPListsMerge(BlastHSPList** hsp_list_ptr, 
                    BlastHSPList** combined_hsp_list_ptr,
                    Int4 hsp_num_max, Int4 *split_offsets, 
-                   Int4 contexts_per_query, Int4 chunk_overlap_size)
+                   Int4 contexts_per_query, Int4 chunk_overlap_size,
+                   Boolean allow_gap)
 {
    BlastHSPList* combined_hsp_list = *combined_hsp_list_ptr;
    BlastHSPList* hsp_list = *hsp_list_ptr;
@@ -2351,7 +2384,7 @@ Int2 Blast_HSPListsMerge(BlastHSPList** hsp_list_ptr,
             }
    
             if (ABS(end_diag - start_diag) < OVERLAP_DIAG_CLOSE) {
-               if (s_BlastMergeTwoHSPs(hsp1, hsp2)) {
+               if (s_BlastMergeTwoHSPs(hsp1, hsp2, allow_gap)) {
                   /* Free the second HSP. */
                   hspp2[index2] = Blast_HSPFree(hsp2);
                }
@@ -2607,7 +2640,9 @@ Int2 Blast_HitListUpdate(BlastHitList* hit_list,
 {
    hsp_list->best_evalue = s_BlastGetBestEvalue(hsp_list);
 
-   ASSERT(s_BlastCheckBestEvalue(hsp_list) == TRUE);
+#ifndef NDEBUG
+   ASSERT(s_BlastCheckBestEvalue(hsp_list) == TRUE); /* NCBI_FAKE_WARNING */
+#endif /* _DEBUG */
  
    if (hit_list->hsplist_count < hit_list->hsplist_max) {
       /* If the array of HSP lists for this query is not yet allocated, 
@@ -2799,98 +2834,6 @@ static int s_SortHspWrapEvalue(const void *x, const void *y)
 }
 
 
-Int2 Blast_HSPResultsPerformCulling(BlastHSPResults *results,
-                                    const BlastQueryInfo *query_info,
-                                    Int4 culling_limit, Int4 query_length)
-{
-   Int4 i, j, k, m;
-   Int4 hsp_count;
-   SHspWrap *hsp_array;
-   BlastIntervalTree *tree;
-
-   /* set up the interval tree; subject offsets are not needed */
-
-   tree = Blast_IntervalTreeInit(0, query_length + 1, 0, 0);
-
-   for (i = 0; i < results->num_queries; i++) {
-      BlastHitList *hitlist = results->hitlist_array[i];
-      if (hitlist == NULL)
-         continue;
-
-      /* count the number of HSPs in this hitlist. If this is
-         less than the culling limit, no HSPs will be pruned */
-
-      for (j = hsp_count = 0; j < hitlist->hsplist_count; j++) {
-         BlastHSPList *hsplist = hitlist->hsplist_array[j];
-         hsp_count += hsplist->hspcnt;
-      }
-      if (hsp_count < culling_limit)
-          continue;
-
-      /* empty each HSP into a combined HSP array, then
-         sort the array by e-value */
-
-      hsp_array = (SHspWrap *)malloc(hsp_count * sizeof(SHspWrap));
-
-      for (j = k = 0; j < hitlist->hsplist_count; j++) {
-         BlastHSPList *hsplist = hitlist->hsplist_array[j];
-         for (m = 0; m < hsplist->hspcnt; k++, m++) {
-            BlastHSP *hsp = hsplist->hsp_array[m];
-            hsp_array[k].hsplist = hsplist;
-            hsp_array[k].hsp = hsp;
-         }
-         hsplist->hspcnt = 0;
-      }
-
-      qsort(hsp_array, hsp_count, sizeof(SHspWrap), s_SortHspWrapEvalue);
-
-      /* Starting with the best HSP, use the interval tree to
-         check that the query range of each HSP in the list has
-         not already been enveloped by too many higher-scoring
-         HSPs. If this is not the case, add the HSP back into results */
-
-      Blast_IntervalTreeReset(tree);
-
-      for (j = 0; j < hsp_count; j++) {
-         BlastHSPList *hsplist = hsp_array[j].hsplist;
-         BlastHSP *hsp = hsp_array[j].hsp;
-
-         if (BlastIntervalTreeNumRedundant(tree, 
-                         hsp, query_info) >= culling_limit) {
-             Blast_HSPFree(hsp);
-         }
-         else {
-             BlastIntervalTreeAddHSP(hsp, tree, query_info, eQueryOnly);
-             Blast_HSPListSaveHSP(hsplist, hsp);
-
-             /* the first HSP added back into an HSPList
-                automatically has the best e-value */
-             if (hsplist->hspcnt == 1)
-                 hsplist->best_evalue = hsp->evalue;
-         }
-      }
-      sfree(hsp_array);
-
-      /* remove any HSPLists that are still empty after the 
-         culling process. Sort any remaining lists by score */
-
-      for (j = 0; j < hitlist->hsplist_count; j++) {
-         BlastHSPList *hsplist = hitlist->hsplist_array[j];
-         if (hsplist->hspcnt == 0) {
-             hitlist->hsplist_array[j] = 
-                   Blast_HSPListFree(hitlist->hsplist_array[j]);
-         }
-         else {
-             Blast_HSPListSortByScore(hitlist->hsplist_array[j]);
-         }
-      }
-      Blast_HitListPurgeNullHSPLists(hitlist);
-   }
-
-   tree = Blast_IntervalTreeFree(tree);
-   return 0;
-}
-
 Int2 Blast_HSPResultsInsertHSPList(BlastHSPResults* results, 
         BlastHSPList* hsp_list, Int4 hitlist_size)
 {
diff --git a/algo/blast/core/blast_hits.h b/algo/blast/core/blast_hits.h
index 231bb16..b870964 100644
--- a/algo/blast/core/blast_hits.h
+++ b/algo/blast/core/blast_hits.h
@@ -1,4 +1,4 @@
-/* $Id: blast_hits.h,v 1.111 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: blast_hits.h,v 1.114 2010/06/25 17:14:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -57,8 +57,7 @@ typedef struct SBlastHitsParameters {
    Int4 hsp_num_max; /**< number of HSPs to save per db sequence. */
 } SBlastHitsParameters; 
 
-/** Sets up small structures used by blast_hit.c and hspstream_collector.c
- * for saving HSPs.
+/** Sets up small structures used by blast_hit.c for saving HSPs.
  * @param hit_options field hitlist_size and hsp_num_max needed, a pointer to 
  *      this structure will be stored on resulting structure.[in]
  * @param ext_options field compositionBasedStats needed here. [in]
@@ -501,11 +500,12 @@ Int4
 Blast_HSPListPurgeHSPsWithCommonEndpoints(EBlastProgramType program, 
                                           BlastHSPList* hsp_list);
 
-/** Reevaluate all ungapped HSPs in an HSP list, using ambiguity information. 
- * This is/can only done either for an ungapped search, or if traceback is 
+/** Reevaluate all ungapped HSPs in an HSP list.  
+ * This is only done for an ungapped search, or if traceback is 
  * already available.
- * Subject sequence is uncompressed and saved here. Number of identities is
- * calculated for each HSP along the way. 
+ * Subject sequence is uncompressed and saved here (for nucleotide sequences). 
+ * The number of identities is calculated for each HSP along the way,
+ * hence this function is called for all programs. 
  * @param program Type of BLAST program [in]
  * @param hsp_list The list of HSPs for one subject sequence [in] [out]
  * @param query_blk The query sequence [in]
@@ -523,7 +523,7 @@ Blast_HSPListPurgeHSPsWithCommonEndpoints(EBlastProgramType program,
  */
 NCBI_XBLAST_EXPORT
 Int2 
-Blast_HSPListReevaluateWithAmbiguitiesUngapped(EBlastProgramType program, 
+Blast_HSPListReevaluateUngapped(EBlastProgramType program, 
    BlastHSPList* hsp_list, BLAST_SequenceBlk* query_blk, 
    BLAST_SequenceBlk* subject_blk, 
    const BlastInitialWordParameters* word_params,
@@ -556,6 +556,7 @@ Int2 Blast_HSPListAppend(BlastHSPList** old_hsp_list_ptr,
  * @param chunk_overlap_size The length of the overlap region between the
  *                    sequence region containing hsp_list and that
  *                    containing combined_hsp_list [in]
+ * @param allow_gap Allow merging HSPs at different diagonals [in]
  * @return 0 if HSP lists have been merged successfully, -1 otherwise.
  */
 NCBI_XBLAST_EXPORT
@@ -563,7 +564,8 @@ Int2 Blast_HSPListsMerge(BlastHSPList** hsp_list,
                    BlastHSPList** combined_hsp_list_ptr, 
                    Int4 hsp_num_max, Int4* split_points, 
                    Int4 contexts_per_query,
-                   Int4 chunk_overlap_size);
+                   Int4 chunk_overlap_size,
+                   Boolean allow_gap);
                    
 /** Adjust subject offsets in an HSP list if only part of the subject sequence
  * was searched. Used when long subject sequence is split into more manageable
@@ -659,12 +661,13 @@ Int2 Blast_HitListUpdate(BlastHitList* hit_list, BlastHSPList* hsp_list);
  * @param chunk_overlap_size The length of the overlap region between the
  *                    sequence region containing hit_list and that
  *                    containing combined_hit_list [in]
+ * @param allow_gap Allow merging HSPs at different diagonals [in]
 */
 NCBI_XBLAST_EXPORT
 Int2 Blast_HitListMerge(BlastHitList** old_hit_list_ptr,
                         BlastHitList** combined_hit_list_ptr,
                         Int4 contexts_per_query, Int4 *split_offsets,
-                        Int4 chunk_overlap_size);
+                        Int4 chunk_overlap_size, Boolean allow_gap);
 
 /** Purges a BlastHitList of NULL HSP lists.
  * @param hit_list BLAST hit list to purge. [in] [out]
@@ -702,26 +705,6 @@ Int2 Blast_HSPResultsReverseSort(BlastHSPResults* results);
 NCBI_XBLAST_EXPORT
 Int2 Blast_HSPResultsReverseOrder(BlastHSPResults* results);
 
-/** For each query sequence in the BLAST results, remove any hits
- *  whose query range is enveloped by too many other higher-scoring
- *  hits. All hits to a query sequence are considered together.
- *  For more details see Berman P. et. al, "Winnowing Sequences
- *  from a Database Search" Journal of Computational Biology
- *  vol 7(2000) pp 293-302
- *
- * @param results The collection of results to cull [in][out]
- * @param query_info Query offset information [in]
- * @param culling_limit Maximum number of hits allowed to envelop
- *                      the query range of an HSP before the HSP is removed
- * @param query_length Length of concatenated query [in]
- * @return 0 on success
- */
-NCBI_XBLAST_EXPORT
-Int2 Blast_HSPResultsPerformCulling(BlastHSPResults *results,
-                                    const BlastQueryInfo *query_info,
-                                    Int4 culling_limit,
-                                    Int4 query_length);
-
 /** Blast_HSPResultsInsertHSPList
  * Insert an HSP list to the appropriate place in the results structure.
  * All HSPs in this list must be from the same query and same subject; the oid
diff --git a/algo/blast/core/blast_hspstream.c b/algo/blast/core/blast_hspstream.c
index 2f51bdb..3bd8bc6 100644
--- a/algo/blast/core/blast_hspstream.c
+++ b/algo/blast/core/blast_hspstream.c
@@ -1,4 +1,4 @@
-/*  $Id: blast_hspstream.c,v 1.12 2009/07/15 17:29:31 kazimird Exp $
+/*  $Id: blast_hspstream.c,v 1.14 2010/07/16 18:45:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_hspstream.c,v 1.12 2009/07/15 17:29:31 kazimird Exp $";
+    "$Id: blast_hspstream.c,v 1.14 2010/07/16 18:45:46 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 
@@ -99,18 +99,13 @@ static int s_SortHSPListByOid(const void *x, const void *y)
                 return (*yy)->oid - (*xx)->oid;
 }
 
-/** Prohibit any future writing to the HSP stream when all results are written.
- * Also perform sorting of results here to prepare them for reading.
- * @param hsp_stream The HSP stream to close [in] [out]
+/** certain hspstreams (such as besthit and culling) uses its own data structure
+ * and therefore must be finalized before reading/merging 
  */ 
-void BlastHSPStreamClose(BlastHSPStream* hsp_stream)
+static void s_FinalizeWriter(BlastHSPStream* hsp_stream)
 {
-   Int4 i, j, k;
-   Int4 num_hsplists;
-   BlastHSPResults *results;
    BlastHSPPipe *pipe;
-
-   if (!hsp_stream || !hsp_stream->results || hsp_stream->results_sorted)
+   if (!hsp_stream || !hsp_stream->results || hsp_stream->writer_finalized) 
       return;
 
    /* perform post-writer clean ups */
@@ -132,6 +127,24 @@ void BlastHSPStreamClose(BlastHSPStream* hsp_stream)
        (pipe->FreeFnPtr) (pipe);
    }
 
+   hsp_stream->writer_finalized = TRUE;
+}
+
+/** Prohibit any future writing to the HSP stream when all results are written.
+ * Also perform sorting of results here to prepare them for reading.
+ * @param hsp_stream The HSP stream to close [in] [out]
+ */ 
+void BlastHSPStreamClose(BlastHSPStream* hsp_stream)
+{
+   Int4 i, j, k;
+   Int4 num_hsplists;
+   BlastHSPResults *results;
+
+   if (!hsp_stream || !hsp_stream->results || hsp_stream->results_sorted)
+      return;
+
+   s_FinalizeWriter(hsp_stream);
+
    if (hsp_stream->sort_by_score) {
        if (hsp_stream->sort_by_score->sort_on_read) {
            Blast_HSPResultsReverseSort(hsp_stream->results);
@@ -381,8 +394,12 @@ int BlastHSPStreamMerge(SSplitQueryBlk *squery_blk,
    if (!stream1 || !stream2) 
        return kBlastHSPStream_Error;
 
+   s_FinalizeWriter(stream1);
+   s_FinalizeWriter(stream2);
+
    results1 = stream1->results;
    results2 = stream2->results;
+
    contexts_per_query = BLAST_GetNumberOfContexts(stream2->program);
 
    SplitQueryBlk_GetQueryIndicesForChunk(squery_blk, chunk_num, &query_list);
@@ -479,7 +496,8 @@ fprintf(stderr, "No hits to query %d\n", global_query);
        Blast_HitListMerge(results1->hitlist_array + i,
                           results2->hitlist_array + global_query,
                           contexts_per_query, split_points,
-                          SplitQueryBlk_GetChunkOverlapSize(squery_blk));
+                          SplitQueryBlk_GetChunkOverlapSize(squery_blk),
+                          SplitQueryBlk_AllowGap(squery_blk));
    }
 
    /* Sort to the canonical order, which the merge may not have done. */
@@ -542,10 +560,6 @@ int BlastHSPStreamBatchRead(BlastHSPStream* hsp_stream,
    if (!hsp_stream || !batch)
        return kBlastHSPStream_Error;
 
-   batch->num_hsplists = 0;
-   if (!hsp_stream->results)
-      return kBlastHSPStream_Eof;
-
    /* If this stream is not yet closed for writing, close it. In particular,
       this includes sorting of results. 
       NB: to lift the prohibition on write after the first read, the 
@@ -554,6 +568,10 @@ int BlastHSPStreamBatchRead(BlastHSPStream* hsp_stream,
    if (!hsp_stream->results_sorted)
       BlastHSPStreamClose(hsp_stream);
 
+   batch->num_hsplists = 0;
+   if (!hsp_stream->results)
+      return kBlastHSPStream_Eof;
+
    /* return all the HSPlists with the same subject OID as the
       last HSPList in the collection stored. We assume there is
       at most one HSPList per query sequence */
@@ -645,6 +663,7 @@ BlastHSPStreamNew(EBlastProgramType program,
     hsp_stream->x_lock = NULL;
     hsp_stream->writer = writer;
     hsp_stream->writer_initialized = FALSE;
+    hsp_stream->writer_finalized = FALSE;
     hsp_stream->pre_pipe = NULL;
     hsp_stream->tback_pipe = NULL;
 
diff --git a/algo/blast/core/blast_hspstream.h b/algo/blast/core/blast_hspstream.h
index 2c07c34..c794fb9 100644
--- a/algo/blast/core/blast_hspstream.h
+++ b/algo/blast/core/blast_hspstream.h
@@ -1,4 +1,4 @@
-/*  $Id: blast_hspstream.h,v 1.9 2009/05/27 17:39:36 kazimird Exp $
+/*  $Id: blast_hspstream.h,v 1.10 2010/07/16 18:45:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -105,6 +105,7 @@ typedef struct BlastHSPStream {
    /* support for writer and pipes */
    BlastHSPWriter* writer;         /**< writer to be applied when writing*/
    Boolean writer_initialized;     /**< Is writer already initialized? */
+   Boolean writer_finalized;       /**< Is writer ever finalized? */
    BlastHSPPipe *pre_pipe;         /**< registered preliminary pipeline (unused
                                     for now) */
    BlastHSPPipe *tback_pipe;       /**< registered traceback pipeline */
diff --git a/algo/blast/core/blast_itree.c b/algo/blast/core/blast_itree.c
index 613ad54..42a2a13 100644
--- a/algo/blast/core/blast_itree.c
+++ b/algo/blast/core/blast_itree.c
@@ -1,4 +1,4 @@
-/* $Id: blast_itree.c,v 1.13 2006/11/21 17:03:13 papadopo Exp $
+/* $Id: blast_itree.c,v 1.14 2010/05/06 18:54:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -33,7 +33,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_itree.c,v 1.13 2006/11/21 17:03:13 papadopo Exp $";
+    "$Id: blast_itree.c,v 1.14 2010/05/06 18:54:32 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include "blast_itree.h"
@@ -62,19 +62,28 @@ enum EIntervalDirection {
 static Int4
 s_IntervalNodeInit(BlastIntervalTree *tree, 
                    Int4 parent_index,
-                   enum EIntervalDirection dir)
+                   enum EIntervalDirection dir,
+                   Int2* ret_status)
 {
     Int4 new_index;
     Int4 midpt;
     SIntervalNode *new_node;
     SIntervalNode *parent_node;
 
+    *ret_status = 0;
+
     if (tree->num_used == tree->num_alloc) {
         tree->num_alloc = 2 * tree->num_alloc;
         tree->nodes = (SIntervalNode *)realloc(tree->nodes, tree->num_alloc *
                                                      sizeof(SIntervalNode));
     }
 
+    if(tree->nodes == NULL)
+    {
+         *ret_status = BLASTERR_MEMORY;
+         return 0;
+    }
+
     new_index = tree->num_used++;
     if (dir == eIntervalTreeNeither)
         return new_index;
@@ -118,12 +127,15 @@ s_IntervalNodeInit(BlastIntervalTree *tree,
  */
 static Int4
 s_IntervalRootNodeInit(BlastIntervalTree *tree, 
-                       Int4 region_start, Int4 region_end)
+                       Int4 region_start, Int4 region_end, Int2* retval)
 {
     Int4 new_index;
     SIntervalNode *new_node;
 
-    new_index = s_IntervalNodeInit(tree, 0, eIntervalTreeNeither);
+    new_index = s_IntervalNodeInit(tree, 0, eIntervalTreeNeither, retval);
+    if(*retval != 0)
+       return 0;
+
     new_node = tree->nodes + new_index;
     new_node->leftptr = 0;
     new_node->midptr = 0;
@@ -141,16 +153,31 @@ Blast_IntervalTreeInit(Int4 q_start, Int4 q_end,
 {
     Int4 size = 100;
     BlastIntervalTree *tree;
+    Int2 retval=0;
 
     tree = (BlastIntervalTree *)malloc(sizeof(BlastIntervalTree));
+    if (tree == NULL)
+    {
+          return NULL;
+    }
     tree->nodes = (SIntervalNode *)malloc(size * sizeof(SIntervalNode));
+    if (tree->nodes == NULL)
+    {
+          sfree(tree);
+          return NULL;
+    }
     tree->num_alloc = size;
     tree->num_used = 0;
     tree->s_min = s_start;
     tree->s_max = s_end;
 
     /* The first structure in tree->nodes is the root */
-    s_IntervalRootNodeInit(tree, q_start, q_end);
+    s_IntervalRootNodeInit(tree, q_start, q_end, &retval);
+    if(retval)
+    {
+       Blast_IntervalTreeFree(tree);
+       return NULL;
+    }
     return tree;
 }
 
@@ -485,7 +512,7 @@ s_IntervalTreeHasHSPEndpoint(BlastIntervalTree *tree,
 
 
 /* see blast_itree.h for description */
-void 
+Int2 
 BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
                         const BlastQueryInfo *query_info,
                         EITreeIndexMethod index_method)
@@ -504,6 +531,7 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
     Int4 middle;
     enum EIntervalDirection which_half;
     Boolean index_subject_range = FALSE;
+    Int2 retval = 0;
 
     /* Determine the query strand containing the input HSP.
        Only the strand matters for containment purposes,
@@ -541,11 +569,11 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
     
         if (s_IntervalTreeHasHSPEndpoint(tree, hsp, query_start,
                                          eIntervalTreeLeft)) {
-            return;
+            return retval;
         }
         if (s_IntervalTreeHasHSPEndpoint(tree, hsp, query_start,
                                          eIntervalTreeRight)) {
-            return;
+            return retval;
         }
     }
 
@@ -555,7 +583,9 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
 
     /* encapsulate the input HSP in an SIntervalNode */
     root_index = 0;
-    new_index = s_IntervalNodeInit(tree, 0, eIntervalTreeNeither);
+    new_index = s_IntervalNodeInit(tree, 0, eIntervalTreeNeither, &retval);
+    if (retval)
+         return retval;
     nodes = tree->nodes;
     nodes[new_index].leftptr = query_start;
     nodes[new_index].midptr = 0;
@@ -578,7 +608,7 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
 
             if (nodes[root_index].leftptr == 0) {
                 nodes[root_index].leftptr = new_index;
-                return;
+                return retval;
             }
 
             /* A node is already in this subtree. If it is not a 
@@ -602,7 +632,7 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
 
             if (nodes[root_index].rightptr == 0) {
                 nodes[root_index].rightptr = new_index;
-                return;
+                return retval;
             }
 
             /* A node is already in this subtree. If it is not a 
@@ -633,7 +663,7 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
 
                 nodes[new_index].midptr = nodes[root_index].midptr;
                 nodes[root_index].midptr = new_index;
-                return;
+                return retval;
             }
             else {
 
@@ -644,7 +674,9 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
 
                 if (nodes[root_index].midptr == 0) {
                     mid_index = s_IntervalRootNodeInit(tree, tree->s_min,
-                                                       tree->s_max);
+                                                       tree->s_max, &retval);
+                    if (retval)
+                      return retval;   
                     nodes = tree->nodes;
                     nodes[root_index].midptr = mid_index;
                 }
@@ -665,7 +697,9 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
            First allocate the new node. Update the pointer to 
            the pool of nodes, since it may change */
 
-        mid_index = s_IntervalNodeInit(tree, root_index, which_half);
+        mid_index = s_IntervalNodeInit(tree, root_index, which_half, &retval);
+        if (retval)
+          return retval;
         nodes = tree->nodes;
         old_hsp = nodes[old_index].hsp;
 
@@ -716,7 +750,9 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
             }
             else {
                 Int4 mid_index2 = s_IntervalRootNodeInit(tree, tree->s_min,
-                                                         tree->s_max);
+                                                         tree->s_max, &retval);
+                if (retval)
+                      return retval;   
                 old_region_start = old_hsp->subject.offset; 
                 old_region_end =  old_hsp->subject.end;
                 nodes = tree->nodes;
@@ -733,6 +769,7 @@ BlastIntervalTreeAddHSP(BlastHSP *hsp, BlastIntervalTree *tree,
             }
         }
     }
+    return retval;
 }
 
 /** Determine whether an HSP is contained within another HSP.
diff --git a/algo/blast/core/blast_itree.h b/algo/blast/core/blast_itree.h
index f55f9bf..74d5848 100644
--- a/algo/blast/core/blast_itree.h
+++ b/algo/blast/core/blast_itree.h
@@ -1,4 +1,4 @@
-/* $Id: blast_itree.h,v 1.6 2006/11/21 17:03:23 papadopo Exp $
+/* $Id: blast_itree.h,v 1.7 2010/05/06 18:54:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -115,8 +115,9 @@ Blast_IntervalTreeReset(BlastIntervalTree *tree);
  * @param tree The tree to update [in][out]
  * @param query_info Structure with query offset information [in]
  * @param index_method How HSP will be indexed within the tree [in]
+ * @return zero if succes, otherwise indicates an error
  */
-void 
+Int2 
 BlastIntervalTreeAddHSP(BlastHSP *hsp, 
                         BlastIntervalTree *tree,
                         const BlastQueryInfo *query_info,
diff --git a/algo/blast/core/blast_kappa.c b/algo/blast/core/blast_kappa.c
index 4873a2e..5bb6824 100644
--- a/algo/blast/core/blast_kappa.c
+++ b/algo/blast/core/blast_kappa.c
@@ -1,4 +1,4 @@
-/* $Id: blast_kappa.c,v 1.98 2009/01/05 16:54:38 kazimird Exp $
+/* $Id: blast_kappa.c,v 1.100 2010/07/30 17:44:35 kazimird Exp $
  * ==========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-"$Id: blast_kappa.c,v 1.98 2009/01/05 16:54:38 kazimird Exp $";
+"$Id: blast_kappa.c,v 1.100 2010/07/30 17:44:35 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <float.h>
@@ -447,6 +447,7 @@ s_ComputeNumIdentities(const BLAST_SequenceBlk* query_blk,
                        const Uint1* gen_code_string)
 {
     Uint1* query = NULL;
+    Uint1* query_nomask = NULL;
     Uint1* subject = NULL;
     const EBlastProgramType program_number = scoring_options->program_number;
     const Boolean kIsOutOfFrame = scoring_options->is_ooframe;
@@ -465,6 +466,7 @@ s_ComputeNumIdentities(const BLAST_SequenceBlk* query_blk,
         memset((void*) &seq_arg, 0, sizeof(seq_arg));
         seq_arg.oid = hsp_list->oid;
         seq_arg.encoding = encoding;
+        seq_arg.check_oid_exclusion = TRUE;
         status = BlastSeqSrcGetSequence(seq_src, (void*) &seq_arg);
         ASSERT(status == 0);
     }
@@ -486,9 +488,12 @@ s_ComputeNumIdentities(const BLAST_SequenceBlk* query_blk,
             Int4 context = hsp->context - hsp->context % CODON_LENGTH;
             Int4 context_offset = query_info->contexts[context].query_offset;
             query = query_blk->oof_sequence + CODON_LENGTH + context_offset;
+            query_nomask = query_blk->oof_sequence + CODON_LENGTH + context_offset;
         } else {
             query = query_blk->sequence + 
                 query_info->contexts[hsp->context].query_offset;
+            query_nomask = query_blk->sequence_nomask + 
+                query_info->contexts[hsp->context].query_offset;
         }
 
         /* Translate subject if needed. */
@@ -497,7 +502,7 @@ s_ComputeNumIdentities(const BLAST_SequenceBlk* query_blk,
             status = Blast_HSPGetNumIdentities(query, target_sequence, hsp, scoring_options, 0);
         }
         else
-            status = Blast_HSPGetNumIdentities(query, subject, hsp, scoring_options, 0);
+            status = Blast_HSPGetNumIdentities(query_nomask, subject, hsp, scoring_options, 0);
 
         ASSERT(status == 0);
     }
@@ -958,6 +963,7 @@ s_MatchingSequenceInitialize(BlastCompo_MatchingSequence * self,
 
         memset((void*) &seq_info->seq_arg, 0, sizeof(seq_info->seq_arg));
         seq_info->seq_arg.oid = self->index = subject_index;
+        seq_info->seq_arg.check_oid_exclusion = TRUE;
 
         if( program_number == eBlastTypeTblastn ) {
             seq_info->seq_arg.encoding = eBlastEncodingNcbi4na;
diff --git a/algo/blast/core/blast_message.c b/algo/blast/core/blast_message.c
index 4876b69..ab4246b 100644
--- a/algo/blast/core/blast_message.c
+++ b/algo/blast/core/blast_message.c
@@ -1,4 +1,4 @@
-/* $Id: blast_message.c,v 1.25 2008/07/17 17:55:44 kazimird Exp $
+/* $Id: blast_message.c,v 1.26 2010/03/23 15:44:41 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -31,7 +31,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_message.c,v 1.25 2008/07/17 17:55:44 kazimird Exp $";
+    "$Id: blast_message.c,v 1.26 2010/03/23 15:44:41 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_def.h>
@@ -181,6 +181,13 @@ Blast_PerrorEx(Blast_Message* *msg,
         new_msg->severity = eBlastSevInfo;
         new_msg->context = context;
         break;
+    case BLASTERR_NOVALIDKARLINALTSCHUL:
+        new_msg->message = strdup("Warning: Could not calculate ungapped Karlin-Altschul "
+                               "parameters due to an invalid query sequence or its translation. "
+                               "Please verify the query sequence(s) and/or filtering options");
+        new_msg->severity = eBlastSevError;
+        new_msg->context = context;
+        break;
 
     /* Fatal errors */
     case BLASTERR_MEMORY:
diff --git a/algo/blast/core/blast_message.h b/algo/blast/core/blast_message.h
index f2563cb..42a13cc 100644
--- a/algo/blast/core/blast_message.h
+++ b/algo/blast/core/blast_message.h
@@ -1,4 +1,4 @@
-/* $Id: blast_message.h,v 1.19 2008/07/23 18:55:44 kazimird Exp $
+/* $Id: blast_message.h,v 1.20 2010/03/23 16:04:51 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -154,6 +154,9 @@ void Blast_PerrorEx(Blast_Message* *msg,
 /** BLAST search was interrupted via a user-provided callback */
 #define BLASTERR_INTERRUPTED                        103
 
+/** Could not calculate Karlin-Altschul statistics for any context. */
+#define BLASTERR_NOVALIDKARLINALTSCHUL              104
+
 /** The option is not supported with the specified program. */
 #define BLASTERR_OPTION_PROGRAM_INVALID             201  
 
diff --git a/algo/blast/core/blast_nascan.c b/algo/blast/core/blast_nascan.c
index 296122b..cd4ccfe 100644
--- a/algo/blast/core/blast_nascan.c
+++ b/algo/blast/core/blast_nascan.c
@@ -1,4 +1,4 @@
-/* $Id: blast_nascan.c,v 1.14 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: blast_nascan.c,v 1.18 2010/07/27 18:24:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-    "$Id: blast_nascan.c,v 1.14 2009/05/27 17:39:36 kazimird Exp $";
+    "$Id: blast_nascan.c,v 1.18 2010/07/27 18:24:31 kazimird Exp $";
 #endif                          /* SKIP_DOXYGEN_PROCESSING */
 
 /**
@@ -90,18 +90,17 @@ static NCBI_INLINE void s_BlastLookupRetrieve(BlastNaLookupTable * lookup,
  * with stride 4. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastNaScanSubject_8_4(const LookupTableWrap * lookup_wrap,
                         const BLAST_SequenceBlk * subject,
-                        Int4 start_offset,
                         BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                        Int4 max_hits, Int4 * end_offset)
+                        Int4 max_hits, Int4 * scan_range)
 {
     Uint1 *s;
     Uint1 *abs_start, *s_end;
@@ -117,9 +116,8 @@ static Int4 s_BlastNaScanSubject_8_4(const LookupTableWrap * lookup_wrap,
     ASSERT(lut_word_length == 8);
 
     abs_start = subject->sequence;
-    s = abs_start + start_offset / COMPRESSION_RATIO;
-    s_end = abs_start + (subject->length - lut_word_length) /
-        COMPRESSION_RATIO;
+    s = abs_start + scan_range[0] / COMPRESSION_RATIO;
+    s_end = abs_start + scan_range[1] / COMPRESSION_RATIO;
 
     for (; s <= s_end; s++) {
 
@@ -137,7 +135,7 @@ static Int4 s_BlastNaScanSubject_8_4(const LookupTableWrap * lookup_wrap,
                               (s - abs_start) * COMPRESSION_RATIO);
         total_hits += num_hits;
     }
-    *end_offset = (s - abs_start) * COMPRESSION_RATIO;
+    scan_range[0] = (s - abs_start) * COMPRESSION_RATIO;
 
     return total_hits;
 }
@@ -146,30 +144,27 @@ static Int4 s_BlastNaScanSubject_8_4(const LookupTableWrap * lookup_wrap,
  * at arbitrary stride. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                            const BLAST_SequenceBlk * subject,
-                           Int4 start_offset,
                            BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                           Int4 max_hits, Int4 * end_offset)
+                           Int4 max_hits, Int4 * scan_range)
 {
     BlastNaLookupTable *lookup;
     Uint1 *s;
     Uint1 *abs_start;
-    Int4 s_off;
     Int4 num_hits;
     Int4 index;
     Int4 total_hits = 0;
     Int4 scan_step;
     Int4 mask;
     Int4 lut_word_length;
-    Int4 last_offset = *end_offset;
 
     ASSERT(lookup_wrap->lut_type == eNaLookupTable);
     lookup = (BlastNaLookupTable *) lookup_wrap->lut;
@@ -187,7 +182,7 @@ static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
            widths require two bytes of the compressed subject sequence, and
            possibly a third if the word is not aligned on a 4-base boundary */
 
-        if (scan_step % COMPRESSION_RATIO == 0 && !(subject->num_seq_ranges)) {
+        if (scan_step % COMPRESSION_RATIO == 0 && !subject->mask_type) {
 
             /* for strides that are a multiple of 4, words are always aligned 
                and two bytes of the subject sequence will always hold a
@@ -196,9 +191,9 @@ static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                subject, so we will never fetch the byte beyond the end of
                subject */
 
-            Uint1 *s_end = abs_start + last_offset / COMPRESSION_RATIO;
+            Uint1 *s_end = abs_start + scan_range[1] / COMPRESSION_RATIO;
             Int4 shift = 2 * (8 - lut_word_length);
-            s = abs_start + start_offset / COMPRESSION_RATIO;
+            s = abs_start + scan_range[0] / COMPRESSION_RATIO;
             scan_step = scan_step / COMPRESSION_RATIO;
 
             for (; s <= s_end; s += scan_step) {
@@ -217,7 +212,7 @@ static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                                       (s - abs_start) * COMPRESSION_RATIO);
                 total_hits += num_hits;
             }
-            *end_offset = (s - abs_start) * COMPRESSION_RATIO;
+            scan_range[0] = (s - abs_start) * COMPRESSION_RATIO;
         } else {
             /* when the stride is not a multiple of 4, extra bases may occur
                both before and after every word read from the subject
@@ -232,10 +227,10 @@ static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                this by first handling all the cases where 12-base regions
                fit, then handling the last few offsets separately */
 
-            for (s_off = start_offset; s_off < last_offset; s_off += scan_step) {
+            for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) {
 
-                Int4 shift = 2*(12 - (s_off % COMPRESSION_RATIO + lut_word_length));
-                s = abs_start + (s_off / COMPRESSION_RATIO);
+                Int4 shift = 2*(12 - (scan_range[0] % COMPRESSION_RATIO + lut_word_length));
+                s = abs_start + (scan_range[0] / COMPRESSION_RATIO);
 
                 index = s[0] << 16 | s[1] << 8 | s[2];
                 index = (index >> shift) & mask;
@@ -249,37 +244,9 @@ static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
 
                 s_BlastLookupRetrieve(lookup,
                                       index,
-                                      offset_pairs + total_hits, s_off);
-                total_hits += num_hits;
-            }
-
-            /* make sure the last_offset is scanned, this is necessary for
-               db masked case */
-
-            if (total_hits < max_hits) {
-                Int4 shift = 0;
-                s_off = last_offset;
-
-                shift = 2*(12 - (s_off % COMPRESSION_RATIO + lut_word_length));
-                s = abs_start + (s_off / COMPRESSION_RATIO);
-
-                index = s[0] << 16 | s[1] << 8 | s[2];
-                index = (index >> shift) & mask;
-
-                num_hits = s_BlastLookupGetNumHits(lookup, index);
-
-                if (num_hits <= (max_hits - total_hits)) {
-                    if (num_hits) {
-                        s_BlastLookupRetrieve(lookup,
-                                              index,
-                                              offset_pairs + total_hits, s_off);
+                                      offset_pairs + total_hits, scan_range[0]);
                         total_hits += num_hits;
                     }
-                    s_off += scan_step;
-                }
-            }
-
-            *end_offset = s_off;
         }
     } else {
         /* perform scanning for lookup tables of width 4 and 5. Here the
@@ -290,10 +257,10 @@ static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
            the following does not need to be corrected when scanning near the 
            end of the subject sequence */
 
-        for (s_off = start_offset; s_off < last_offset; s_off += scan_step) {
+        for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) {
 
-            Int4 shift = 2*(8 - (s_off % COMPRESSION_RATIO + lut_word_length));
-            s = abs_start + (s_off / COMPRESSION_RATIO);
+            Int4 shift = 2*(8 - (scan_range[0] % COMPRESSION_RATIO + lut_word_length));
+            s = abs_start + (scan_range[0] / COMPRESSION_RATIO);
 
             index = s[0] << 8 | s[1];
             index = (index >> shift) & mask;
@@ -308,37 +275,9 @@ static Int4 s_BlastNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
             s_BlastLookupRetrieve(lookup,
                                   index,
                                   offset_pairs + total_hits,
-                                  s_off);
+                                  scan_range[0]);
             total_hits += num_hits;
         }
-
-        /* make sure the last_offset is scanned, this is necessary for
-           db masked case */
-
-        if (total_hits < max_hits) {
-            Int4 shift = 0;
-            s_off = last_offset;
-
-            shift = 2*(8 - (s_off % COMPRESSION_RATIO + lut_word_length));
-            s = abs_start + (s_off / COMPRESSION_RATIO);
-
-            index = s[0] << 8 | s[1];
-            index = (index >> shift) & mask;
-
-            num_hits = s_BlastLookupGetNumHits(lookup, index);
-
-            if (num_hits <= (max_hits - total_hits)) {
-                if (num_hits) {
-                    s_BlastLookupRetrieve(lookup,
-                                          index,
-                                          offset_pairs + total_hits, s_off);
-                    total_hits += num_hits;
-                }
-                s_off += scan_step;
-            }
-        }
-
-        *end_offset = s_off;
     }
 
     return total_hits;
@@ -398,11 +337,11 @@ static NCBI_INLINE Int4 s_BlastSmallNaRetrieveHits(
 #define SMALL_NA_ACCESS_HITS(x)                                 \
     if (index != -1) {                                          \
         if (total_hits > max_hits) {                            \
-            s_off += (x);                                       \
+            scan_range[0] += (x);                                       \
             break;                                              \
         }                                                       \
         total_hits += s_BlastSmallNaRetrieveHits(offset_pairs,  \
-                                                 index, s_off + (x),  \
+                                                 index, scan_range[0] + (x),  \
                                                  total_hits,    \
                                                  overflow);     \
     }
@@ -411,27 +350,24 @@ static NCBI_INLINE Int4 s_BlastSmallNaRetrieveHits(
  * with stride 4. Assumes a small-query nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_8_4(const LookupTableWrap * lookup_wrap,
                              const BLAST_SequenceBlk * subject,
-                             Int4 start_offset,
                              BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                             Int4 max_hits, Int4 * end_offset)
+                             Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 8;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
-    Int4 num_words = (last_offset - start_offset) / 4 + 1;
-    Uint1 *s = subject->sequence + start_offset / COMPRESSION_RATIO;
+    Int4 num_words = (scan_range[1] - scan_range[0]) / 4 + 1;
+    Uint1 *s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     Int4 total_hits = 0;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
@@ -445,16 +381,16 @@ static Int4 s_BlastSmallNaScanSubject_8_4(const LookupTableWrap * lookup_wrap,
 
     init_index = s[0];
     switch (num_words % 8) {
-    case 1: s -= 7; s_off -= 28; goto byte_7;
-    case 2: s -= 6; s_off -= 24; goto byte_6;
-    case 3: s -= 5; s_off -= 20; goto byte_5;
-    case 4: s -= 4; s_off -= 16; goto byte_4;
-    case 5: s -= 3; s_off -= 12; goto byte_3;
-    case 6: s -= 2; s_off -=  8; goto byte_2;
-    case 7: s -= 1; s_off -=  4; goto byte_1;
+    case 1: s -= 7; scan_range[0] -= 28; goto byte_7;
+    case 2: s -= 6; scan_range[0] -= 24; goto byte_6;
+    case 3: s -= 5; scan_range[0] -= 20; goto byte_5;
+    case 4: s -= 4; scan_range[0] -= 16; goto byte_4;
+    case 5: s -= 3; scan_range[0] -= 12; goto byte_3;
+    case 6: s -= 2; scan_range[0] -=  8; goto byte_2;
+    case 7: s -= 1; scan_range[0] -=  4; goto byte_1;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = init_index << 8 | s[1];
         index = backbone[init_index & kLutWordMask];
@@ -488,10 +424,9 @@ byte_7:
         s += 8;
         index = backbone[init_index & kLutWordMask];
         SMALL_NA_ACCESS_HITS(28);
-        s_off += 32;
+        scan_range[0] += 32;
     }
 
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -499,18 +434,17 @@ byte_7:
  * with arbitrary stride. Assumes a small-query nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
@@ -522,7 +456,6 @@ static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
     Int4 scan_step = lookup->scan_step;
     Int4 mask = lookup->mask;
     Int4 lut_word_length = lookup->lut_word_length;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
 
@@ -536,7 +469,7 @@ static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
            widths require two bytes of the compressed subject sequence, and
            possibly a third if the word is not aligned on a 4-base boundary */
 
-        if (scan_step % COMPRESSION_RATIO == 0 && !(subject->num_seq_ranges)) {
+        if (scan_step % COMPRESSION_RATIO == 0 && !subject->mask_type) {
 
             /* for strides that are a multiple of 4, words are always aligned 
                and two bytes of the subject sequence will always hold a
@@ -545,9 +478,9 @@ static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                subject, so we will never fetch the byte beyond the end of
                subject */
 
-            Uint1 *s_end = abs_start + last_offset / COMPRESSION_RATIO;
+            Uint1 *s_end = abs_start + scan_range[1] / COMPRESSION_RATIO;
             Int4 shift = 2 * (8 - lut_word_length);
-            s = abs_start + start_offset / COMPRESSION_RATIO;
+            s = abs_start + scan_range[0] / COMPRESSION_RATIO;
             scan_step = scan_step / COMPRESSION_RATIO;
 
             for (; s <= s_end; s += scan_step) {
@@ -564,7 +497,7 @@ static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                                                              overflow);
                 }
             }
-            *end_offset = (s - abs_start) * COMPRESSION_RATIO;
+            scan_range[0] = (s - abs_start) * COMPRESSION_RATIO;
         } else {
             /* when the stride is not a multiple of 4, extra bases may occur
                both before and after every word read from the subject
@@ -579,38 +512,15 @@ static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
                this by first handling all the cases where 12-base regions
                fit, then handling the last few offsets separately */
 
-            for (s_off = start_offset; s_off < last_offset; s_off += scan_step) {
+            for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) {
 
-                Int4 shift = 2*(12 - (s_off % COMPRESSION_RATIO + lut_word_length));
-                s = abs_start + (s_off / COMPRESSION_RATIO);
+                Int4 shift = 2*(12 - (scan_range[0] % COMPRESSION_RATIO + lut_word_length));
+                s = abs_start + (scan_range[0] / COMPRESSION_RATIO);
 
                 index = s[0] << 16 | s[1] << 8 | s[2];
                 index = backbone[(index >> shift) & mask];
                 SMALL_NA_ACCESS_HITS(0);
             }
-
-            /* make sure the last_offset is scanned, this is necessary for
-               db masked case */
-            if (total_hits < max_hits) {
-                Int4 shift = 0;
-                s_off = last_offset;
-
-                shift = 2*(12 - (s_off % COMPRESSION_RATIO + lut_word_length));
-                s = abs_start + (s_off / COMPRESSION_RATIO);
-
-                index = s[0] << 16 | s[1] << 8 | s[2];
-                index = backbone[(index >> shift) & mask];
-
-                if (index != -1) {
-                    total_hits += s_BlastSmallNaRetrieveHits(offset_pairs,
-                                                             index, s_off,
-                                                             total_hits,
-                                                             overflow);
-                }
-                s_off += scan_step;
-            }
-
-            *end_offset = s_off;
         }
     } else {
         /* perform scanning for lookup tables of width 4 and 5. Here the
@@ -621,38 +531,15 @@ static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
            the following does not need to be corrected when scanning near the 
            end of the subject sequence */
 
-        for (s_off = start_offset; s_off < last_offset; s_off += scan_step) {
+        for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) {
 
-            Int4 shift = 2*(8 - (s_off % COMPRESSION_RATIO + lut_word_length));
-            s = abs_start + (s_off / COMPRESSION_RATIO);
+            Int4 shift = 2*(8 - (scan_range[0] % COMPRESSION_RATIO + lut_word_length));
+            s = abs_start + (scan_range[0] / COMPRESSION_RATIO);
 
             index = s[0] << 8 | s[1];
             index = backbone[(index >> shift) & mask];
             SMALL_NA_ACCESS_HITS(0);
         }
-
-        /* make sure the last_offset is scanned, this is necessary for
-           db masked case */
-        if (total_hits < max_hits) {
-            Int4 shift = 0;
-            s_off = last_offset;
-
-            shift = 2*(8 - (s_off % COMPRESSION_RATIO + lut_word_length));
-            s = abs_start + (s_off / COMPRESSION_RATIO);
-
-            index = s[0] << 8 | s[1];
-            index = backbone[(index >> shift) & mask];
-
-            if (index != -1) {
-                total_hits += s_BlastSmallNaRetrieveHits(offset_pairs,
-                                                         index, s_off,
-                                                         total_hits,
-                                                         overflow);
-            }
-            s_off += scan_step;
-        }
-
-        *end_offset = s_off + scan_step;
     }
 
     return total_hits;
@@ -662,28 +549,25 @@ static Int4 s_BlastSmallNaScanSubject_Any(const LookupTableWrap * lookup_wrap,
  * with stride 1. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_4_1(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 4;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Uint1 *s = subject->sequence + (s_off / COMPRESSION_RATIO);
+    Uint1 *s = subject->sequence + (scan_range[0] / COMPRESSION_RATIO);
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -694,7 +578,7 @@ static Int4 s_BlastSmallNaScanSubject_4_1(
     ASSERT(lookup->lut_word_length == 4);
     ASSERT(lookup->scan_step == 1);
 
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1:
         init_index = s[0];
         goto base_1;
@@ -706,41 +590,40 @@ static Int4 s_BlastSmallNaScanSubject_4_1(
         goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0];
         index = backbone[init_index];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[1];
         index = backbone[(init_index >> 6) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = backbone[(init_index >> 4) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         s++;
         index = backbone[(init_index >> 2) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
     }
 
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -748,28 +631,25 @@ base_3:
  * with stride 1. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_5_1(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 5;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Uint1 *s = subject->sequence + (s_off / COMPRESSION_RATIO);
+    Uint1 *s = subject->sequence + (scan_range[0] / COMPRESSION_RATIO);
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -780,7 +660,7 @@ static Int4 s_BlastSmallNaScanSubject_5_1(
     ASSERT(lookup->lut_word_length == 5);
     ASSERT(lookup->scan_step == 1);
 
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1:
         init_index = s[0] << 8 | s[1];
         goto base_1;
@@ -792,40 +672,38 @@ static Int4 s_BlastSmallNaScanSubject_5_1(
         goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 8 | s[1];
         index = backbone[init_index >> 6];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = backbone[(init_index >> 4) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = backbone[(init_index >> 2) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         s++;
         index = backbone[init_index & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -833,28 +711,25 @@ base_3:
  * with stride 1. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_6_1(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 6;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Uint1 *s = subject->sequence + (s_off / COMPRESSION_RATIO);
+    Uint1 *s = subject->sequence + (scan_range[0] / COMPRESSION_RATIO);
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -865,7 +740,7 @@ static Int4 s_BlastSmallNaScanSubject_6_1(
     ASSERT(lookup->lut_word_length == 6);
     ASSERT(lookup->scan_step == 1);
 
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1:
         init_index = s[0] << 8 | s[1];
         goto base_1;
@@ -877,41 +752,39 @@ static Int4 s_BlastSmallNaScanSubject_6_1(
         goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 8 | s[1];
         index = backbone[init_index >> 4];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = backbone[(init_index >> 2) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = backbone[init_index & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[2];
         s++;
         index = backbone[(init_index >> 6) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -919,28 +792,25 @@ base_3:
  * with stride 2. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_6_2(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 6;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Uint1 *s = subject->sequence + (s_off / COMPRESSION_RATIO);
+    Uint1 *s = subject->sequence + (scan_range[0] / COMPRESSION_RATIO);
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -951,29 +821,27 @@ static Int4 s_BlastSmallNaScanSubject_6_2(
     ASSERT(lookup->lut_word_length == 6);
     ASSERT(lookup->scan_step == 2);
 
-    if (s_off % COMPRESSION_RATIO == 2) {
+    if (scan_range[0] % COMPRESSION_RATIO == 2) {
         init_index = s[0] << 8 | s[1];
         goto base_2;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 8 | s[1];
         index = backbone[init_index >> 4];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 2;
+        scan_range[0] += 2;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         s++;
         index = backbone[init_index & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 2;
+        scan_range[0] += 2;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -981,28 +849,25 @@ base_2:
  * with stride 1. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_7_1(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 7;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Uint1 *s = subject->sequence + (s_off / COMPRESSION_RATIO);
+    Uint1 *s = subject->sequence + (scan_range[0] / COMPRESSION_RATIO);
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -1013,7 +878,7 @@ static Int4 s_BlastSmallNaScanSubject_7_1(
     ASSERT(lookup->lut_word_length == 7);
     ASSERT(lookup->scan_step == 1);
 
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1:
         init_index = s[0] << 8 | s[1];
         goto base_1;
@@ -1025,41 +890,39 @@ static Int4 s_BlastSmallNaScanSubject_7_1(
         goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 8 | s[1];
         index = backbone[init_index >> 2];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = backbone[init_index & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[2];
         index = backbone[(init_index >> 6) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         s++;
         index = backbone[(init_index >> 4) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off++;
+        scan_range[0]++;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -1067,28 +930,25 @@ base_3:
  * with stride 2. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_7_2(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 7;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Uint1 *s = subject->sequence + (s_off / COMPRESSION_RATIO);
+    Uint1 *s = subject->sequence + (scan_range[0] / COMPRESSION_RATIO);
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -1099,30 +959,28 @@ static Int4 s_BlastSmallNaScanSubject_7_2(
     ASSERT(lookup->lut_word_length == 7);
     ASSERT(lookup->scan_step == 2);
 
-    if (s_off % COMPRESSION_RATIO == 2) {
+    if (scan_range[0] % COMPRESSION_RATIO == 2) {
         init_index = s[0] << 8 | s[1];
         goto base_2;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 8 | s[1];
         index = backbone[init_index >> 2];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 2;
+        scan_range[0] += 2;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[2];
         s++;
         index = backbone[(init_index >> 6) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 2;
+        scan_range[0] += 2;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -1130,28 +988,25 @@ base_2:
  * with stride 3. Assumes a standard nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_7_3(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 7;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
-    Uint1 *s = subject->sequence + (s_off / COMPRESSION_RATIO);
+    Uint1 *s = subject->sequence + (scan_range[0] / COMPRESSION_RATIO);
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -1162,7 +1017,7 @@ static Int4 s_BlastSmallNaScanSubject_7_3(
     ASSERT(lookup->lut_word_length == 7);
     ASSERT(lookup->scan_step == 3);
 
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1:
         init_index = s[0] << 8 | s[1];
         s -= 2;
@@ -1176,42 +1031,40 @@ static Int4 s_BlastSmallNaScanSubject_7_3(
         goto base_1;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 8 | s[1];
         index = backbone[(init_index >> 2) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 3;
+        scan_range[0] += 3;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[2];
         index = backbone[(init_index >> 4) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 3;
+        scan_range[0] += 3;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[3];
         index = backbone[(init_index >> 6) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 3;
+        scan_range[0] += 3;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         s += 3;
         index = backbone[init_index & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += 3;
+        scan_range[0] += 3;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -1220,30 +1073,27 @@ base_3:
  * nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_8_1Mod4(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 8;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
     Int4 scan_step = lookup->scan_step;
     Int4 scan_step_byte = scan_step / COMPRESSION_RATIO;
-    Uint1 *s = subject->sequence + s_off / COMPRESSION_RATIO;
+    Uint1 *s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -1253,52 +1103,50 @@ static Int4 s_BlastSmallNaScanSubject_8_1Mod4(
     ASSERT(lookup->lut_word_length == 8);
     ASSERT(lookup->scan_step % COMPRESSION_RATIO == 1);
 
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1: goto base_1;
     case 2: goto base_2;
     case 3: goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         index = s[0] << 8 | s[1];
         s += scan_step_byte;
         index = backbone[index];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         s += scan_step_byte;
         index = backbone[(index >> 6) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         s += scan_step_byte;
         index = backbone[(index >> 4) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         s += scan_step_byte + 1;
         index = backbone[(index >> 2) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -1307,30 +1155,27 @@ base_3:
  * nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_8_2Mod4(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 8;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
     Int4 scan_step = lookup->scan_step;
     Int4 scan_step_byte = scan_step / COMPRESSION_RATIO;
-    Uint1 *s = subject->sequence + s_off / COMPRESSION_RATIO;
+    Uint1 *s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -1340,29 +1185,27 @@ static Int4 s_BlastSmallNaScanSubject_8_2Mod4(
     ASSERT(lookup->lut_word_length == 8);
     ASSERT(lookup->scan_step % COMPRESSION_RATIO == 2);
 
-    if (s_off % COMPRESSION_RATIO == 2)
+    if (scan_range[0] % COMPRESSION_RATIO == 2)
         goto base_2;
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         index = s[0] << 8 | s[1];
         s += scan_step_byte;
         index = backbone[index];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         s += scan_step_byte + 1;
         index = backbone[(index >> 4) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -1371,30 +1214,27 @@ base_2:
  * nucleotide lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_BlastSmallNaScanSubject_8_3Mod4(
                                 const LookupTableWrap * lookup_wrap,
                                 const BLAST_SequenceBlk * subject,
-                                Int4 start_offset,
                                 BlastOffsetPair * NCBI_RESTRICT offset_pairs,
-                                Int4 max_hits, Int4 * end_offset)
+                                Int4 max_hits, Int4 * scan_range)
 {
     BlastSmallNaLookupTable *lookup = 
                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
     const Int4 kLutWordLength = 8;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
-    Int4 s_off = start_offset;
     Int4 scan_step = lookup->scan_step;
     Int4 scan_step_byte = scan_step / COMPRESSION_RATIO;
-    Uint1 *s = subject->sequence + s_off / COMPRESSION_RATIO;
+    Uint1 *s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     Int4 total_hits = 0;
-    Int4 last_offset = *end_offset;
     Int2 *backbone = lookup->final_backbone;
     Int2 *overflow = lookup->overflow;
     Int4 index; 
@@ -1404,7 +1244,7 @@ static Int4 s_BlastSmallNaScanSubject_8_3Mod4(
     ASSERT(lookup->lut_word_length == 8);
     ASSERT(lookup->scan_step % COMPRESSION_RATIO == 3);
 
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1: 
         s -= 2;
         goto base_3;
@@ -1415,46 +1255,44 @@ static Int4 s_BlastSmallNaScanSubject_8_3Mod4(
         goto base_1;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         index = s[0] << 8 | s[1];
         s += scan_step_byte;
         index = backbone[index];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         s += scan_step_byte;
         index = backbone[(index >> 2) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[1] << 16 | s[2] << 8 | s[3];
         s += scan_step_byte;
         index = backbone[(index >> 4) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[2] << 16 | s[3] << 8 | s[4];
         s += scan_step_byte + 3;
         index = backbone[(index >> 6) & kLutWordMask];
         SMALL_NA_ACCESS_HITS(0);
-        s_off += scan_step;
+        scan_range[0] += scan_step;
     }
-
-    *end_offset = s_off;
     return total_hits;
 }
 
@@ -1617,7 +1455,7 @@ static NCBI_INLINE Int4 s_BlastMBLookupRetrieve2(BlastMBLookupTable * lookup,
            break;                                       \
        total_hits += s_BlastMBLookupRetrieve(mb_lt,     \
                   index, offset_pairs + total_hits,     \
-                  s_off);                               \
+                  scan_range[0]);                               \
    }
 
 /** access the megablast lookup table with two templates */
@@ -1627,29 +1465,29 @@ static NCBI_INLINE Int4 s_BlastMBLookupRetrieve2(BlastMBLookupTable * lookup,
    if (s_BlastMBLookupHasHits(mb_lt, index)) {          \
        total_hits += s_BlastMBLookupRetrieve(mb_lt,     \
                   index, offset_pairs + total_hits,     \
-                  s_off);                               \
+                  scan_range[0]);                               \
    }                                                    \
    if (s_BlastMBLookupHasHits(mb_lt, index2)) {         \
        total_hits += s_BlastMBLookupRetrieve2(mb_lt,    \
                   index2, offset_pairs + total_hits,    \
-                  s_off);                               \
+                  scan_range[0]);                               \
    }
 
 /** Scan the compressed subject sequence, returning 9-to-12 letter word hits
  * with arbitrary stride. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject, 
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
    BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
    Uint1* s;
@@ -1659,10 +1497,7 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
    Int4 mask = mb_lt->hashsize - 1;
    Int4 total_hits = 0;
    Int4 lut_word_length = mb_lt->lut_word_length;
-   Int4 last_offset = *end_offset;
    Int4 scan_step = mb_lt->scan_step;
-//printf("%d -- %d -- %d  %d\n",mb_lt->lut_word_length, mb_lt->word_length, scan_step, mb_lt->);
-//if(mb_lt->discontiguous) printf("discontiguous\n");
    
    ASSERT(lookup_wrap->lut_type == eMBLookupTable);
    ASSERT(lut_word_length == 9 || 
@@ -1674,7 +1509,7 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
       subtract the longest chain length from the allowed offset array size. */
    max_hits -= mb_lt->longest_chain;
 
-   if (scan_step % COMPRESSION_RATIO == 0 && !(subject->num_seq_ranges)) {
+   if (scan_step % COMPRESSION_RATIO == 0 && !subject->mask_type) {
 
       /* for strides that are a multiple of 4, words are
          always aligned and three bytes of the subject sequence 
@@ -1683,10 +1518,9 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
          the third-to-last byte of the subject sequence, so we will
          never fetch the byte beyond the end of subject */
 
-      Uint1* s_end = abs_start + (subject->length - lut_word_length) /
-                                                COMPRESSION_RATIO;
+      Uint1 *s_end = abs_start + scan_range[1] / COMPRESSION_RATIO;
       Int4 shift = 2 * (12 - lut_word_length);
-      s = abs_start + start_offset / COMPRESSION_RATIO;
+      s = abs_start + scan_range[0] / COMPRESSION_RATIO;
       scan_step = scan_step / COMPRESSION_RATIO;
 
       for ( ; s <= s_end; s += scan_step) {
@@ -1704,7 +1538,7 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
                  s_off);
          }
       }
-      *end_offset = (s - abs_start)*COMPRESSION_RATIO;
+      scan_range[0] = (s - abs_start)*COMPRESSION_RATIO;
 
    } else if (lut_word_length > 9) {
 
@@ -1723,38 +1557,15 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
          the cases where 16-base regions fit, then handling the 
          last few offsets separately */
 
-      for (s_off = start_offset; s_off < last_offset; s_off += scan_step) {
+      for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) {
    
-         Int4 shift = 2*(16 - (s_off % COMPRESSION_RATIO + lut_word_length));
-         s = abs_start + (s_off / COMPRESSION_RATIO);
+         Int4 shift = 2*(16 - (scan_range[0] % COMPRESSION_RATIO + lut_word_length));
+         s = abs_start + (scan_range[0] / COMPRESSION_RATIO);
    
          index = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
          index = (index >> shift) & mask;
          MB_ACCESS_HITS();
       }
-
-      /* make sure the last_offset is scanned, this is necessary for
-         db masked case */
-      if (total_hits < max_hits) {
-         Int4 shift = 0;
-         s_off = last_offset;
-   
-         shift = 2*(16 - (s_off % COMPRESSION_RATIO + lut_word_length));
-         s = abs_start + (s_off / COMPRESSION_RATIO);
-   
-         index = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
-         index = (index >> shift) & mask;
-
-         if (s_BlastMBLookupHasHits(mb_lt, index)) {
-             total_hits += s_BlastMBLookupRetrieve(mb_lt, index,
-                                                   offset_pairs + total_hits,
-                                                   s_off);
-         } 
-         s_off += scan_step;
-      }
-
-      *end_offset = s_off;
-
    } else {
       /* perform scanning for a lookup table of width 9 with
          stride not a multiple of 4. The last word is always 
@@ -1762,38 +1573,15 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
          following does not need to be corrected when scanning 
          near the end of the subject sequence */
 
-      for (s_off = start_offset; s_off < last_offset; s_off += scan_step) {
+      for (; scan_range[0] <= scan_range[1]; scan_range[0] += scan_step) {
    
-         Int4 shift = 2*(12 - (s_off % COMPRESSION_RATIO + lut_word_length));
-         s = abs_start + (s_off / COMPRESSION_RATIO);
+         Int4 shift = 2*(12 - (scan_range[0] % COMPRESSION_RATIO + lut_word_length));
+         s = abs_start + (scan_range[0] / COMPRESSION_RATIO);
    
          index = s[0] << 16 | s[1] << 8 | s[2];
          index = (index >> shift) & mask;
          MB_ACCESS_HITS();
       }
-
-      /* make sure the last_offset is scanned, this is necessary for
-         db masked case */
-
-      if (total_hits < max_hits) {
-         Int4 shift = 0;
-         s_off = last_offset;
-
-         shift = 2*(12 - (s_off % COMPRESSION_RATIO + lut_word_length));
-         s = abs_start + (s_off / COMPRESSION_RATIO);
-   
-         index = s[0] << 16 | s[1] << 8 | s[2];
-         index = (index >> shift) & mask;
-
-         if (s_BlastMBLookupHasHits(mb_lt, index)) {
-             total_hits += s_BlastMBLookupRetrieve(mb_lt, index,
-                                                   offset_pairs + total_hits,
-                                                   s_off);
-         } 
-         s_off += scan_step;
-      }
- 
-      *end_offset = s_off;
    }
 
    return total_hits;
@@ -1803,17 +1591,17 @@ static Int4 s_MBScanSubject_Any(const LookupTableWrap* lookup_wrap,
  * with stride 1. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_9_1(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 9;
@@ -1821,16 +1609,14 @@ static Int4 s_MBScanSubject_9_1(const LookupTableWrap* lookup_wrap,
     Int4 index;
     Int4 init_index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     
     max_hits -= mb_lt->longest_chain;
     ASSERT(lookup_wrap->lut_type == eMBLookupTable);
     ASSERT(mb_lt->lut_word_length == 9);
     ASSERT(mb_lt->scan_step == 1);
  
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1: 
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         goto base_1;
@@ -1842,40 +1628,38 @@ static Int4 s_MBScanSubject_9_1(const LookupTableWrap* lookup_wrap,
         goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         index = init_index >> 6;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = (init_index >> 4) & kLutWordMask;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = (init_index >> 2) & kLutWordMask;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = init_index & kLutWordMask;
         s++;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -1883,17 +1667,17 @@ base_3:
  * with stride 2. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_9_2(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 9;
@@ -1901,38 +1685,34 @@ static Int4 s_MBScanSubject_9_2(const LookupTableWrap* lookup_wrap,
     Int4 index;
     Int4 init_index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     
     max_hits -= mb_lt->longest_chain;
     ASSERT(lookup_wrap->lut_type == eMBLookupTable);
     ASSERT(mb_lt->lut_word_length == 9);
     ASSERT(mb_lt->scan_step == 2);
  
-    if (s_off % COMPRESSION_RATIO == 2) {
+    if (scan_range[0] % COMPRESSION_RATIO == 2) {
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         goto base_2;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         index = init_index >> 6;
         MB_ACCESS_HITS();
-        s_off += 2;
+        scan_range[0] += 2;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = (init_index >> 2) & kLutWordMask;
         s++;
         MB_ACCESS_HITS();
-        s_off += 2;
+        scan_range[0] += 2;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -1940,17 +1720,17 @@ base_2:
  * with stride 1. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_10_1(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 10;
@@ -1958,16 +1738,14 @@ static Int4 s_MBScanSubject_10_1(const LookupTableWrap* lookup_wrap,
     Int4 index;
     Int4 init_index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     
     max_hits -= mb_lt->longest_chain;
     ASSERT(lookup_wrap->lut_type == eMBLookupTable);
     ASSERT(mb_lt->lut_word_length == 10);
     ASSERT(mb_lt->scan_step == 1);
  
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1: 
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         goto base_1;
@@ -1979,41 +1757,39 @@ static Int4 s_MBScanSubject_10_1(const LookupTableWrap* lookup_wrap,
         goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         index = init_index >> 4;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = (init_index >> 2) & kLutWordMask;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = init_index & kLutWordMask;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[3];
         index = (init_index >> 6) & kLutWordMask;
         s++;
         MB_ACCESS_HITS();
-        s_off++;
+        scan_range[0]++;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2021,17 +1797,17 @@ base_3:
  * with stride 2. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_10_2(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 10;
@@ -2039,38 +1815,34 @@ static Int4 s_MBScanSubject_10_2(const LookupTableWrap* lookup_wrap,
     Int4 index;
     Int4 init_index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     
     max_hits -= mb_lt->longest_chain;
     ASSERT(lookup_wrap->lut_type == eMBLookupTable);
     ASSERT(mb_lt->lut_word_length == 10);
     ASSERT(mb_lt->scan_step == 2);
  
-    if (s_off % COMPRESSION_RATIO == 2) {
+    if (scan_range[0] % COMPRESSION_RATIO == 2) {
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         goto base_2;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         index = init_index >> 4;
         MB_ACCESS_HITS();
-        s_off += 2;
+        scan_range[0] += 2;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = init_index & kLutWordMask;
         s++;
         MB_ACCESS_HITS();
-        s_off += 2;
+        scan_range[0] += 2;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2078,17 +1850,17 @@ base_2:
  * with stride 3. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_10_3(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 10;
@@ -2096,16 +1868,14 @@ static Int4 s_MBScanSubject_10_3(const LookupTableWrap* lookup_wrap,
     Int4 index;
     Int4 init_index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     
     max_hits -= mb_lt->longest_chain;
     ASSERT(lookup_wrap->lut_type == eMBLookupTable);
     ASSERT(mb_lt->lut_word_length == 10);
     ASSERT(mb_lt->scan_step == 3);
  
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1: 
        init_index = s[0] << 8 | s[1];
        s -= 2;
@@ -2119,42 +1889,40 @@ static Int4 s_MBScanSubject_10_3(const LookupTableWrap* lookup_wrap,
        goto base_1;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         init_index = s[0] << 16 | s[1] << 8 | s[2];
         index = init_index >> 4;
         MB_ACCESS_HITS();
-        s_off += 3;
+        scan_range[0] += 3;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[3];
         index = (init_index >> 6) & kLutWordMask;
         MB_ACCESS_HITS();
-        s_off += 3;
+        scan_range[0] += 3;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = init_index & kLutWordMask;
         MB_ACCESS_HITS();
-        s_off += 3;
+        scan_range[0] += 3;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         init_index = init_index << 8 | s[4];
         index = (init_index >> 2) & kLutWordMask;
         s += 3;
         MB_ACCESS_HITS();
-        s_off += 3;
+        scan_range[0] += 3;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2162,26 +1930,24 @@ base_3:
  * with stride one plus a multiple of four. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_11_1Mod4(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 11;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
     Int4 index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     Int4 scan_step = mb_lt->scan_step;
     Int4 scan_step_byte = scan_step / COMPRESSION_RATIO;
     
@@ -2190,52 +1956,50 @@ static Int4 s_MBScanSubject_11_1Mod4(const LookupTableWrap* lookup_wrap,
     ASSERT(mb_lt->lut_word_length == 11);
     ASSERT(scan_step % COMPRESSION_RATIO == 1);
  
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1: goto base_1;
     case 2: goto base_2;
     case 3: goto base_3;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         index = index >> 2;
         s += scan_step_byte;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         index = index & kLutWordMask;
         s += scan_step_byte;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
         index = (index >> 6) & kLutWordMask;
         s += scan_step_byte;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
         index = (index >> 4) & kLutWordMask;
         s += scan_step_byte + 1;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2243,26 +2007,24 @@ base_3:
  * with stride two plus a multiple of four. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_11_2Mod4(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 11;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
     Int4 index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     Int4 scan_step = mb_lt->scan_step;
     Int4 scan_step_byte = scan_step / COMPRESSION_RATIO;
     Int4 top_shift, bottom_shift;
@@ -2272,7 +2034,7 @@ static Int4 s_MBScanSubject_11_2Mod4(const LookupTableWrap* lookup_wrap,
     ASSERT(mb_lt->lut_word_length == 11);
     ASSERT(scan_step % COMPRESSION_RATIO == 2);
 
-    if ( (start_offset % 2) == 0)
+    if ( (scan_range[0] % 2) == 0)
         {
         top_shift = 2;
         bottom_shift = 6;
@@ -2283,28 +2045,26 @@ static Int4 s_MBScanSubject_11_2Mod4(const LookupTableWrap* lookup_wrap,
         bottom_shift = 4;
         }
 
-    if ( (s_off % COMPRESSION_RATIO == 2) || (s_off % COMPRESSION_RATIO == 3) )
+    if ( (scan_range[0] % COMPRESSION_RATIO == 2) || (scan_range[0] % COMPRESSION_RATIO == 3) )
         goto base_23;
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
         index = s[0] << 16 | s[1] << 8 | s[2];
         index = (index >> top_shift) & kLutWordMask;
         s += scan_step_byte;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_23:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
         index = (index >> bottom_shift) & kLutWordMask;
         s += scan_step_byte + 1;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2312,26 +2072,24 @@ base_23:
  * with stride three plus a multiple of four. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MBScanSubject_11_3Mod4(const LookupTableWrap* lookup_wrap,
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits,  
-       Int4* end_offset)
+       Int4* scan_range)
 {
     BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
     const Int4 kLutWordLength = 11;
     const Int4 kLutWordMask = (1 << (2 * kLutWordLength)) - 1;
     Int4 index;
     Int4 total_hits = 0;
-    Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
-    Int4 s_off = start_offset;
-    Int4 last_offset = *end_offset;
+    Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
     Int4 scan_step = mb_lt->scan_step;
     Int4 scan_step_byte = scan_step / COMPRESSION_RATIO;
     
@@ -2340,7 +2098,7 @@ static Int4 s_MBScanSubject_11_3Mod4(const LookupTableWrap* lookup_wrap,
     ASSERT(mb_lt->lut_word_length == 11);
     ASSERT(scan_step % COMPRESSION_RATIO == 3);
  
-    switch (s_off % COMPRESSION_RATIO) {
+    switch (scan_range[0] % COMPRESSION_RATIO) {
     case 1: 
        s -= 2;
        goto base_3;
@@ -2351,46 +2109,44 @@ static Int4 s_MBScanSubject_11_3Mod4(const LookupTableWrap* lookup_wrap,
        goto base_1;
     }
 
-    while (s_off <= last_offset) {
+    while (scan_range[0] <= scan_range[1]) {
 
         index = s[0] << 16 | s[1] << 8 | s[2];
         index = index >> 2;
         s += scan_step_byte;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_1:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
         index = (index >> 4) & kLutWordMask;
         s += scan_step_byte;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_2:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[1] << 24 | s[2] << 16 | s[3] << 8 | s[4];
         index = (index >> 6) & kLutWordMask;
         s += scan_step_byte;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
 
 base_3:
-        if (s_off > last_offset)
+        if (scan_range[0] > scan_range[1])
             break;
 
         index = s[2] << 16 | s[3] << 8 | s[4];
         index = index & kLutWordMask;
         s += scan_step_byte + 3;
         MB_ACCESS_HITS();
-        s_off += scan_step;
+        scan_range[0] += scan_step;
     }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2398,42 +2154,40 @@ base_3:
  * discontiguous words with stride 1. Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MB_DiscWordScanSubject_1(const LookupTableWrap* lookup_wrap, 
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits, 
-       Int4* end_offset)
+       Int4* scan_range)
 {
    BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
-   Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
+   Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
    Int4 total_hits = 0;
-   Int4 s_off = start_offset;
    Int4 index;
    Uint8 accum = 0;
    EDiscTemplateType template_type = mb_lt->template_type;
    Int4 template_length = mb_lt->template_length;
-   Int4 last_offset = *end_offset;
 
    ASSERT(lookup_wrap->lut_type == eMBLookupTable);
    max_hits -= mb_lt->longest_chain;
 
    /* fill the accumulator */
-   index = s_off - (s_off % COMPRESSION_RATIO);
-   while(index < s_off + template_length) {
+   index = scan_range[0] - (scan_range[0] % COMPRESSION_RATIO);
+   while(index < scan_range[0] + template_length) {
       accum = accum << 8 | *s++;
       index += COMPRESSION_RATIO;
    }
 
    /* note that the part of the loop we jump to will
       depend on the number of extra bases (0-3) in the 
-      accumulator, and not on the value of s_off */
-   switch (index - (s_off + template_length)) {
+      accumulator, and not on the value of scan_range[0] */
+   switch (index - (scan_range[0] + template_length)) {
    case 1: 
        goto base_3;
    case 2: 
@@ -2447,39 +2201,37 @@ static Int4 s_MB_DiscWordScanSubject_1(const LookupTableWrap* lookup_wrap,
        goto base_1;
    }
 
-   while (s_off <= last_offset) {
+   while (scan_range[0] <= scan_range[1]) {
 
       index = ComputeDiscontiguousIndex(accum, template_type);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_1:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       accum = accum << 8 | *s++;
       index = ComputeDiscontiguousIndex(accum >> 6, template_type);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_2:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ComputeDiscontiguousIndex(accum >> 4, template_type);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_3:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ComputeDiscontiguousIndex(accum >> 2, template_type);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
    }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2489,44 +2241,42 @@ base_3:
  * the same wordsize and length
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MB_DiscWordScanSubject_TwoTemplates_1(
        const LookupTableWrap* lookup_wrap, 
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits, 
-       Int4* end_offset)
+       Int4* scan_range)
 {
    BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
-   Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
+   Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
    Int4 total_hits = 0;
-   Int4 s_off = start_offset;
    Int4 index, index2;
    Uint8 accum = 0;
    EDiscTemplateType template_type = mb_lt->template_type;
    EDiscTemplateType second_template_type = mb_lt->second_template_type;
    Int4 template_length = mb_lt->template_length;
-   Int4 last_offset = *end_offset;
   
    ASSERT(lookup_wrap->lut_type == eMBLookupTable);
    max_hits -= mb_lt->longest_chain;
 
    /* fill the accumulator */
-   index = s_off - (s_off % COMPRESSION_RATIO);
-   while(index < s_off + template_length) {
+   index = scan_range[0] - (scan_range[0] % COMPRESSION_RATIO);
+   while(index < scan_range[0] + template_length) {
       accum = accum << 8 | *s++;
       index += COMPRESSION_RATIO;
    }
 
    /* note that the part of the loop we jump to will
       depend on the number of extra bases (0-3) in the 
-      accumulator, and not on the value of s_off */
-   switch (index - (s_off + template_length)) {
+      accumulator, and not on the value of scan_range[0] */
+   switch (index - (scan_range[0] + template_length)) {
    case 1: 
        goto base_3;
    case 2: 
@@ -2540,43 +2290,41 @@ static Int4 s_MB_DiscWordScanSubject_TwoTemplates_1(
        goto base_1;
    }
 
-   while (s_off <= last_offset) {
+   while (scan_range[0] <= scan_range[1]) {
 
       index = ComputeDiscontiguousIndex(accum, template_type);
       index2 = ComputeDiscontiguousIndex(accum, second_template_type);
       MB_ACCESS_HITS2();
-      s_off++;
+      scan_range[0]++;
 
 base_1:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       accum = accum << 8 | *s++;
       index = ComputeDiscontiguousIndex(accum >> 6, template_type);
       index2 = ComputeDiscontiguousIndex(accum >> 6, second_template_type);
       MB_ACCESS_HITS2();
-      s_off++;
+      scan_range[0]++;
 
 base_2:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ComputeDiscontiguousIndex(accum >> 4, template_type);
       index2 = ComputeDiscontiguousIndex(accum >> 4, second_template_type);
       MB_ACCESS_HITS2();
-      s_off++;
+      scan_range[0]++;
 
 base_3:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ComputeDiscontiguousIndex(accum >> 2, template_type);
       index2 = ComputeDiscontiguousIndex(accum >> 2, second_template_type);
       MB_ACCESS_HITS2();
-      s_off++;
+      scan_range[0]++;
    }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2585,26 +2333,24 @@ base_3:
  * Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MB_DiscWordScanSubject_11_18_1(
        const LookupTableWrap* lookup_wrap, 
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits, 
-       Int4* end_offset)
+       Int4* scan_range)
 {
    BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
-   Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
+   Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
    Int4 total_hits = 0;
-   Int4 s_off = start_offset;
    Int4 index;
    const Int4 kTemplateLength = 18;
-   Int4 last_offset = *end_offset;
    Uint4 lo = 0; 
    Uint4 hi = 0;
 
@@ -2615,14 +2361,14 @@ static Int4 s_MB_DiscWordScanSubject_11_18_1(
    max_hits -= mb_lt->longest_chain;
 
    /* fill the accumulator */
-   index = s_off - (s_off % COMPRESSION_RATIO);
-   while(index < s_off + kTemplateLength) {
+   index = scan_range[0] - (scan_range[0] % COMPRESSION_RATIO);
+   while(index < scan_range[0] + kTemplateLength) {
       hi = (hi << 8) | (lo >> 24);
       lo = lo << 8 | *s++;
       index += COMPRESSION_RATIO;
    }
 
-   switch (index - (s_off + kTemplateLength)) {
+   switch (index - (scan_range[0] + kTemplateLength)) {
    case 1: 
        goto base_3;
    case 2: 
@@ -2634,7 +2380,7 @@ static Int4 s_MB_DiscWordScanSubject_11_18_1(
        goto base_1;
    }
 
-   while (s_off <= last_offset) {
+   while (scan_range[0] <= scan_range[1]) {
 
       index = ((lo & 0x00000003)      ) |
               ((lo & 0x000000f0) >>  2) |
@@ -2644,10 +2390,10 @@ static Int4 s_MB_DiscWordScanSubject_11_18_1(
               ((lo & 0xf0000000) >> 12) |
               ((hi & 0x0000000c) << 18);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_1:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       hi = (hi << 8) | (lo >> 24);
@@ -2661,10 +2407,10 @@ base_1:
               ((hi & 0x0000003c) << 14) |
               ((hi & 0x00000300) << 12);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_2:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ((lo & 0x00000030) >>  4) |
@@ -2675,10 +2421,10 @@ base_2:
               ((hi & 0x0000000f) << 16) |
               ((hi & 0x000000c0) << 14);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_3:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ((lo & 0x0000000c) >>  2) |
@@ -2690,10 +2436,8 @@ base_3:
               ((hi & 0x00000003) << 18) |
               ((hi & 0x00000030) << 16);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
    }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
@@ -2702,26 +2446,24 @@ base_3:
  * Assumes a megablast lookup table
  * @param lookup_wrap Pointer to the (wrapper to) lookup table [in]
  * @param subject The (compressed) sequence to be scanned for words [in]
- * @param start_offset The offset into the sequence in actual coordinates [in]
  * @param offset_pairs Array of query and subject positions where words are 
  *                found [out]
  * @param max_hits The allocated size of the above array - how many offsets 
  *        can be returned [in]
- * @param end_offset Where the scanning should stop [in], has stopped [out]
+ * @param scan_range The starting and ending pos to be scanned [in] 
+ *        on exit, scan_range[0] is updated to be the stopping pos [out]
 */
 static Int4 s_MB_DiscWordScanSubject_11_21_1(
        const LookupTableWrap* lookup_wrap, 
-       const BLAST_SequenceBlk* subject, Int4 start_offset,
+       const BLAST_SequenceBlk* subject,
        BlastOffsetPair* NCBI_RESTRICT offset_pairs, Int4 max_hits, 
-       Int4* end_offset)
+       Int4* scan_range)
 {
    BlastMBLookupTable* mb_lt = (BlastMBLookupTable*) lookup_wrap->lut;
-   Uint1* s = subject->sequence + start_offset / COMPRESSION_RATIO;
+   Uint1* s = subject->sequence + scan_range[0] / COMPRESSION_RATIO;
    Int4 total_hits = 0;
-   Int4 s_off = start_offset;
    Int4 index;
    const Int4 kTemplateLength = 21;
-   Int4 last_offset = *end_offset;
    Uint4 lo = 0; 
    Uint4 hi = 0;
 
@@ -2731,14 +2473,14 @@ static Int4 s_MB_DiscWordScanSubject_11_21_1(
    ASSERT(mb_lt->template_type == eDiscTemplate_11_21_Coding);
    max_hits -= mb_lt->longest_chain;
 
-   index = s_off - (s_off % COMPRESSION_RATIO);
-   while(index < s_off + kTemplateLength) {
+   index = scan_range[0] - (scan_range[0] % COMPRESSION_RATIO);
+   while(index < scan_range[0] + kTemplateLength) {
       hi = (hi << 8) | (lo >> 24);
       lo = lo << 8 | *s++;
       index += COMPRESSION_RATIO;
    }
 
-   switch (index - (s_off + kTemplateLength)) {
+   switch (index - (scan_range[0] + kTemplateLength)) {
    case 1: 
        goto base_3;
    case 2: 
@@ -2750,7 +2492,7 @@ static Int4 s_MB_DiscWordScanSubject_11_21_1(
        goto base_1;
    }
 
-   while (s_off <= last_offset) {
+   while (scan_range[0] <= scan_range[1]) {
 
       index = ((lo & 0x00000003)      ) |
               ((lo & 0x000000f0) >>  2) |
@@ -2761,10 +2503,10 @@ static Int4 s_MB_DiscWordScanSubject_11_21_1(
               ((hi & 0x0000000c) << 16) |
               ((hi & 0x00000300) << 12);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_1:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       hi = (hi << 8) | (lo >> 24);
@@ -2779,10 +2521,10 @@ base_1:
               ((hi & 0x00000300) << 10) |
               ((hi & 0x0000c000) <<  6);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_2:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ((lo & 0x00000030) >>  4) |
@@ -2794,10 +2536,10 @@ base_2:
               ((hi & 0x000000c0) << 12) |
               ((hi & 0x00003000) <<  8);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
 
 base_3:
-      if (s_off > last_offset)
+      if (scan_range[0] > scan_range[1])
          break;
 
       index = ((lo & 0x0000000c) >>  2) |
@@ -2810,10 +2552,8 @@ base_3:
               ((hi & 0x00000030) << 14) |
               ((hi & 0x00000c00) << 10);
       MB_ACCESS_HITS();
-      s_off++;
+      scan_range[0]++;
    }
-
-   *end_offset = s_off;
    return total_hits;
 }
 
diff --git a/algo/blast/core/blast_nascan.h b/algo/blast/core/blast_nascan.h
index 7c84bd5..ad68b0e 100644
--- a/algo/blast/core/blast_nascan.h
+++ b/algo/blast/core/blast_nascan.h
@@ -1,4 +1,4 @@
-/* $Id: blast_nascan.h,v 1.6 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: blast_nascan.h,v 1.7 2009/10/01 16:04:52 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -42,10 +42,9 @@ extern "C" {
 /** Generic prototype for nucleotide subject scanning routines */
 typedef Int4 (*TNaScanSubjectFunction)(const LookupTableWrap* lookup_wrap,
                                   const BLAST_SequenceBlk* subject,
-                                  Int4 start_offset,
                                   BlastOffsetPair* NCBI_RESTRICT offset_pairs,
                                   Int4 max_hits, 
-                                  Int4* end_offset);
+                                  Int4* scan_range);
 
 /** Choose the most appropriate function to scan through
  * nucleotide subject sequences
diff --git a/algo/blast/core/blast_options.c b/algo/blast/core/blast_options.c
index cf4ee2b..730cfda 100644
--- a/algo/blast/core/blast_options.c
+++ b/algo/blast/core/blast_options.c
@@ -1,4 +1,4 @@
-/* $Id: blast_options.c,v 1.213 2009/06/15 18:34:32 kazimird Exp $
+/* $Id: blast_options.c,v 1.214 2009/08/13 19:09:34 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_options.c,v 1.213 2009/06/15 18:34:32 kazimird Exp $";
+    "$Id: blast_options.c,v 1.214 2009/08/13 19:09:34 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_options.h>
@@ -558,6 +558,7 @@ BlastInitialWordOptionsNew(EBlastProgramType program,
       (*options)->gap_trigger = BLAST_GAP_TRIGGER_PROT;
    } else {
       (*options)->window_size = BLAST_WINDOW_SIZE_NUCL;
+      (*options)->scan_range =  BLAST_SCAN_RANGE_NUCL;
       (*options)->gap_trigger = BLAST_GAP_TRIGGER_NUCL;
       (*options)->x_dropoff = BLAST_UNGAPPED_X_DROPOFF_NUCL;
    }
@@ -587,6 +588,15 @@ BlastInitialWordOptionsValidate(EBlastProgramType program_number,
          return BLASTERR_OPTION_VALUE_INVALID;
    }
    
+   if (program_number == eBlastTypeBlastn && 
+       options->scan_range && !options->window_size)
+   {
+      Blast_MessageWrite(blast_msg, eBlastSevError, kBlastMessageNoContext,
+                            "off_diagonal_range is only useful in 2-hit algorithm");
+         return BLASTERR_OPTION_VALUE_INVALID;
+   }
+                
+   
    return 0;
 }
 
diff --git a/algo/blast/core/blast_options.h b/algo/blast/core/blast_options.h
index 5ff8422..65bb59e 100644
--- a/algo/blast/core/blast_options.h
+++ b/algo/blast/core/blast_options.h
@@ -1,4 +1,4 @@
-/* $Id: blast_options.h,v 1.154 2009/06/15 18:34:32 kazimird Exp $
+/* $Id: blast_options.h,v 1.156 2010/03/16 17:59:36 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -60,6 +60,7 @@ extern "C" {
                                           (contiguous megablast) */
 #define BLAST_WINDOW_SIZE_DISC 40  /**< default window size 
                                           (discontiguous megablast) */
+#define BLAST_SCAN_RANGE_NUCL 0   /**< default scan range (blastn) */
 
 /** length of word to trigger an extension. */
 #define BLAST_WORDSIZE_PROT 3   /**< default word size (all protein searches) */
@@ -207,7 +208,7 @@ typedef struct SSegOptions {
 } SSegOptions;
 
 /// Default value for repeats database filtering
-#define kDefaultRepeatFilterDb "humrep"
+#define kDefaultRepeatFilterDb "repeat/repeat_9606"
 
 /** Filtering options for organsim specific repeats filtering.   
     Currently this consist of only the db name but could be expanded
@@ -254,6 +255,7 @@ typedef struct BlastInitialWordOptions {
    double gap_trigger; /**< Score in bits for starting gapped extension */
    Int4 window_size; /**< Maximal allowed distance between 2 hits in case 2 
                         hits are required to trigger the extension */
+   Int4 scan_range;  /**< Maximal number of gaps allowed between 2 hits */
    double x_dropoff; /**< X-dropoff value (in bits) for the ungapped 
                          extension */
    EBlastProgramType program_number; /**< indicates blastn, blastp, etc. */
diff --git a/algo/blast/core/blast_parameters.c b/algo/blast/core/blast_parameters.c
index d1f832b..52af3ad 100644
--- a/algo/blast/core/blast_parameters.c
+++ b/algo/blast/core/blast_parameters.c
@@ -1,4 +1,4 @@
-/* $Id: blast_parameters.c,v 1.38 2007/10/25 15:55:36 kazimird Exp $
+/* $Id: blast_parameters.c,v 1.39 2010/03/23 15:44:41 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,7 +30,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_parameters.c,v 1.38 2007/10/25 15:55:36 kazimird Exp $";
+    "$Id: blast_parameters.c,v 1.39 2010/03/23 15:44:41 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_parameters.h>
@@ -67,7 +67,9 @@ static Int2
 s_BlastFindValidKarlinBlk(Blast_KarlinBlk** kbp_in, const BlastQueryInfo* query_info, Blast_KarlinBlk** kbp_ret)
 {
     Int4 i;   /* Look for the first valid kbp. */
-    Int2 status=1;  /* 1 means no valid block found. */
+
+    /* BLASTERR_NOVALIDKARLINALTSCHUL means no valid block found (blast_message.h) */
+    Int2 status=BLASTERR_NOVALIDKARLINALTSCHUL;  
 
     ASSERT(kbp_in && query_info && kbp_ret);
 
@@ -180,8 +182,8 @@ BlastInitialWordParametersNew(EBlastProgramType program_number,
 
    ASSERT(word_options);
    ASSERT(sbp);
-   if (s_BlastFindValidKarlinBlk(sbp->kbp, query_info, &kbp) != 0)
-         return -1;
+   if ((status=s_BlastFindValidKarlinBlk(sbp->kbp, query_info, &kbp)) != 0)
+         return status;
 
    p = *parameters = (BlastInitialWordParameters*)calloc(1, 
                                      sizeof(BlastInitialWordParameters));
@@ -390,8 +392,9 @@ Int2 BlastExtensionParametersNew(EBlastProgramType program_number,
  
    if (sbp->kbp) {
       Blast_KarlinBlk* kbp = NULL;
-      if (s_BlastFindValidKarlinBlk(sbp->kbp, query_info, &kbp) != 0)
-         return -1;
+      Int2 status=0;
+      if ((status=s_BlastFindValidKarlinBlk(sbp->kbp, query_info, &kbp)) != 0)
+         return status;
    } else {
       /* The Karlin block is not found, can't do any calculations */
       *parameters = NULL;
@@ -947,7 +950,7 @@ CalculateLinkHSPCutoffs(EBlastProgramType program, BlastQueryInfo* query_info,
  * ===========================================================================
  *
  * $Log: blast_parameters.c,v $
- * Revision 1.38  2007/10/25 15:55:36  kazimird
+ * Revision 1.39  2010/03/23 15:44:41  kazimird
  * Synchronized with the C++ Toolkit.
  *
  * Revision 1.36  2007/05/22 20:55:36  kazimird
diff --git a/algo/blast/core/blast_psi_priv.h b/algo/blast/core/blast_psi_priv.h
index 5f4238d..faeea80 100644
--- a/algo/blast/core/blast_psi_priv.h
+++ b/algo/blast/core/blast_psi_priv.h
@@ -1,4 +1,4 @@
-/*  $Id: blast_psi_priv.h,v 1.37 2009/05/27 17:39:36 kazimird Exp $
+/*  $Id: blast_psi_priv.h,v 1.38 2009/09/02 18:29:30 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -64,23 +64,30 @@ extern "C" {
 /* Extern declarations for constants (defined in blast_psi_priv.c) */
 
 /** Percent identity threshold for discarding near-identical matches */
+NCBI_XBLAST_EXPORT 
 extern const double kPSINearIdentical;
 
 /** Percent identity threshold for discarding identical matches */
+NCBI_XBLAST_EXPORT 
 extern const double kPSIIdentical;
 
 /** Index into multiple sequence alignment structure for the query sequence */
+NCBI_XBLAST_EXPORT 
 extern const unsigned int kQueryIndex;
 
 /** Small constant to test against 0 */
+NCBI_XBLAST_EXPORT 
 extern const double kEpsilon;
 
 /** Successor to POSIT_SCALE_FACTOR  */
+NCBI_XBLAST_EXPORT 
 extern const int kPSIScaleFactor;
 
 /** Constant used in scaling PSSM routines: Successor to POSIT_PERCENT */
+NCBI_XBLAST_EXPORT 
 extern const double kPositScalingPercent;
 /** Constant used in scaling PSSM routines: Successor to POSIT_NUM_ITERATIONS */
+NCBI_XBLAST_EXPORT 
 extern const Uint4 kPositScalingNumIterations;
 
 /****************************************************************************/
@@ -95,6 +102,7 @@ extern const Uint4 kPositScalingNumIterations;
  *          element in the matrix [in]
  * @return pointer to allocated memory or NULL in case of failure
  */
+NCBI_XBLAST_EXPORT 
 void**
 _PSIAllocateMatrix(unsigned int ncols, unsigned int nrows, 
                    unsigned int data_type_sz);
@@ -105,6 +113,7 @@ _PSIAllocateMatrix(unsigned int ncols, unsigned int nrows,
  * @param ncols number of columns in the matrix [in]
  * @return NULL
  */
+NCBI_XBLAST_EXPORT 
 void**
 _PSIDeallocateMatrix(void** matrix, unsigned int ncols);
 
@@ -115,6 +124,7 @@ _PSIDeallocateMatrix(void** matrix, unsigned int ncols);
  * @param ncols Number of columns to copy   [in]
  * @param nrows Number of rows to copy      [in]
  */
+NCBI_XBLAST_EXPORT 
 void
 _PSICopyMatrix_int(int** dest, int** src,
                    unsigned int ncols, unsigned int nrows);
@@ -126,6 +136,7 @@ _PSICopyMatrix_int(int** dest, int** src,
  * @param ncols Number of columns to copy   [in]
  * @param nrows Number of rows to copy      [in]
  */
+NCBI_XBLAST_EXPORT 
 void
 _PSICopyMatrix_double(double** dest, double** src,
                       unsigned int ncols, unsigned int nrows);
@@ -159,6 +170,7 @@ typedef struct _PSIPackedMsa {
  * @return newly allocated structure or NULL in case of memory allocation
  * failure
  */
+NCBI_XBLAST_EXPORT 
 _PSIPackedMsa*
 _PSIPackedMsaNew(const PSIMsa* msa);
 
@@ -166,6 +178,7 @@ _PSIPackedMsaNew(const PSIMsa* msa);
  * @param msa multiple sequence alignment data structure to deallocate [in] 
  * @return NULL
  */
+NCBI_XBLAST_EXPORT 
 _PSIPackedMsa*
 _PSIPackedMsaFree(_PSIPackedMsa* msa);
 
@@ -173,6 +186,7 @@ _PSIPackedMsaFree(_PSIPackedMsa* msa);
  * alignment
  * @param msa multiple sequence alignment data structure to deallocate [in] 
  */
+NCBI_XBLAST_EXPORT 
 unsigned int
 _PSIPackedMsaGetNumberOfAlignedSeqs(const _PSIPackedMsa* msa);
 
@@ -215,6 +229,7 @@ typedef struct _PSIMsa {
  * @return newly allocated structure or NULL in case of memory allocation
  * failure
  */
+NCBI_XBLAST_EXPORT 
 _PSIMsa*
 _PSIMsaNew(const _PSIPackedMsa* packed_msa, Uint4 alphabet_size);
 
@@ -222,6 +237,7 @@ _PSIMsaNew(const _PSIPackedMsa* packed_msa, Uint4 alphabet_size);
  * @param msa multiple sequence alignment data structure to deallocate [in] 
  * @return NULL
  */
+NCBI_XBLAST_EXPORT 
 _PSIMsa*
 _PSIMsaFree(_PSIMsa* msa);
 
@@ -241,6 +257,7 @@ typedef struct _PSIInternalPssmData {
  * @return newly allocated structure or NULL in case of memory allocation
  * failure 
  */
+NCBI_XBLAST_EXPORT 
 _PSIInternalPssmData*
 _PSIInternalPssmDataNew(Uint4 query_length, Uint4 alphabet_size);
 
@@ -248,6 +265,7 @@ _PSIInternalPssmDataNew(Uint4 query_length, Uint4 alphabet_size);
  * @param pssm data structure to deallocate [in] 
  * @return NULL
  */
+NCBI_XBLAST_EXPORT 
 _PSIInternalPssmData*
 _PSIInternalPssmDataFree(_PSIInternalPssmData* pssm);
 
@@ -270,6 +288,7 @@ typedef struct _PSIAlignedBlock {
  * @return newly allocated structure or NULL in case of memory allocation
  * failure 
  */
+NCBI_XBLAST_EXPORT 
 _PSIAlignedBlock*
 _PSIAlignedBlockNew(Uint4 query_length);
 
@@ -277,6 +296,7 @@ _PSIAlignedBlockNew(Uint4 query_length);
  * @param aligned_blocks data structure to deallocate [in] 
  * @return NULL
  */
+NCBI_XBLAST_EXPORT 
 _PSIAlignedBlock*
 _PSIAlignedBlockFree(_PSIAlignedBlock* aligned_blocks);
 
@@ -324,6 +344,7 @@ typedef struct _PSISequenceWeights {
  * @return newly allocated structure or NULL in case of memory allocation
  * failure 
  */
+NCBI_XBLAST_EXPORT 
 _PSISequenceWeights*
 _PSISequenceWeightsNew(const PSIMsaDimensions* dims, const BlastScoreBlk* sbp);
 
@@ -331,6 +352,7 @@ _PSISequenceWeightsNew(const PSIMsaDimensions* dims, const BlastScoreBlk* sbp);
  * @param seq_weights data structure to deallocate [in] 
  * @return NULL
  */
+NCBI_XBLAST_EXPORT 
 _PSISequenceWeights*
 _PSISequenceWeightsFree(_PSISequenceWeights* seq_weights);
 
@@ -373,6 +395,7 @@ _PSISequenceWeightsFree(_PSISequenceWeights* seq_weights);
  * @param msa multiple sequence alignment data structure [in]
  * @return PSIERR_BADPARAM if alignment is NULL; PSI_SUCCESS otherwise
  */
+NCBI_XBLAST_EXPORT 
 int 
 _PSIPurgeBiasedSegments(_PSIPackedMsa* msa);
 
@@ -384,6 +407,7 @@ _PSIPurgeBiasedSegments(_PSIPackedMsa* msa);
  * @return One of the errors defined above if validation fails or bad
  * parameter is passed in, else PSI_SUCCESS
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIValidateMSA(const _PSIMsa* msa, Boolean ignored_unaligned_positions);
 
@@ -396,6 +420,7 @@ _PSIValidateMSA(const _PSIMsa* msa, Boolean ignored_unaligned_positions);
  * @return PSIERR_BADPARAM if arguments are NULL
  *         PSI_SUCCESS otherwise
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIComputeAlignmentBlocks(const _PSIMsa* msa,
                            _PSIAlignedBlock* aligned_block);
@@ -415,6 +440,7 @@ _PSIComputeAlignmentBlocks(const _PSIMsa* msa,
  * memory allocation failure, PSIERR_BADSEQWEIGHTS if the sequence weights fail
  * to add up to 1.0, PSI_SUCCESS otherwise
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIComputeSequenceWeights(const _PSIMsa* msa,
                            const _PSIAlignedBlock* aligned_blocks,
@@ -437,6 +463,7 @@ _PSIComputeSequenceWeights(const _PSIMsa* msa,
  * @param internal_pssm PSSM being computed [out]
  * @return PSIERR_BADPARAM if arguments are NULL, PSI_SUCCESS otherwise
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIComputeFreqRatios(const _PSIMsa* msa,
                       const _PSISequenceWeights* seq_weights,
@@ -456,6 +483,7 @@ _PSIComputeFreqRatios(const _PSIMsa* msa,
  * @param std_probs array containing the standard residue probabilities [in]
  * @return PSIERR_BADPARAM if arguments are NULL, PSI_SUCCESS otherwise
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIConvertFreqRatiosToPSSM(_PSIInternalPssmData* internal_pssm,
                             const Uint1* query,
@@ -473,6 +501,7 @@ _PSIConvertFreqRatiosToPSSM(_PSIInternalPssmData* internal_pssm,
  * @return PSIERR_BADPARAM if arguments are NULL, PSIERR_POSITIVEAVGSCORE if
  * the average score of the generated PSSM is positive, PSI_SUCCESS otherwise
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIScaleMatrix(const Uint1* query,
                 const double* std_probs,
@@ -493,6 +522,7 @@ _PSIScaleMatrix(const Uint1* query,
  * @param sbp Score block structure where the calculated lambda and K will be
  * returned [in|out]
  */
+NCBI_XBLAST_EXPORT 
 void
 _PSIUpdateLambdaK(const int** pssm,
                   const Uint1* query,
@@ -508,6 +538,7 @@ _PSIUpdateLambdaK(const int** pssm,
  * blast_kappa.c's scalePosMatrix also does something very similar.
  * @todo remove std_probs as it's not used
  */
+NCBI_XBLAST_EXPORT 
 int
 _IMPALAScaleMatrix(const Uint1* query, const double* std_probs,
                    _PSIInternalPssmData* internal_pssm, 
@@ -524,6 +555,7 @@ _IMPALAScaleMatrix(const Uint1* query, const double* std_probs,
  * @return  PSIERR_BADPARAM if no alignment is given, or if seq_index or stop
  *          are invalid, PSI_SUCCESS otherwise
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIPurgeAlignedRegion(_PSIPackedMsa* msa,
                        unsigned int seq_index,
@@ -537,6 +569,7 @@ _PSIPurgeAlignedRegion(_PSIPackedMsa* msa,
  * sequences.
  * @param msa multiple sequence alignment structure [in|out]
  */
+NCBI_XBLAST_EXPORT 
 void
 _PSIUpdatePositionCounts(_PSIMsa* msa);
 
@@ -546,6 +579,7 @@ _PSIUpdatePositionCounts(_PSIMsa* msa);
  * @param length length of the sequence above [in]
  * @return number of non-X residues in the sequence
  */
+NCBI_XBLAST_EXPORT 
 Uint4
 _PSISequenceLengthWithoutX(const Uint1* seq, Uint4 length);
 
@@ -562,6 +596,7 @@ _PSISequenceLengthWithoutX(const Uint1* seq, Uint4 length);
  * with the query sequence [in]
  * @return structure containing the score frequencies, or NULL in case of error
  */
+NCBI_XBLAST_EXPORT 
 Blast_ScoreFreq*
 _PSIComputeScoreProbabilities(const int** pssm,
                               const Uint1* query,
@@ -578,6 +613,7 @@ _PSIComputeScoreProbabilities(const int** pssm,
  * @return PSI_SUCCESS on success, PSIERR_OUTOFMEM if memory allocation fails
  * or PSIERR_BADPARAM if any of its arguments is NULL
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSISaveDiagnostics(const _PSIMsa* msa,
                     const _PSIAlignedBlock* aligned_block,
@@ -595,6 +631,7 @@ _PSISaveDiagnostics(const _PSIMsa* msa,
  * @return array of length query_length containing the information content per
  * query position or NULL on error (e.g.: out-of-memory or NULL parameters)
  */
+NCBI_XBLAST_EXPORT 
 double*
 _PSICalculateInformationContentFromScoreMatrix(
     Int4** score_mat,
@@ -616,6 +653,7 @@ _PSICalculateInformationContentFromScoreMatrix(
  * @return array of length query_length containing the information content per
  * query position or NULL on error (e.g.: out-of-memory or NULL parameters)
  */
+NCBI_XBLAST_EXPORT 
 double*
 _PSICalculateInformationContentFromFreqRatios(
     double** freq_ratios,
@@ -633,6 +671,7 @@ void __printMsaFP(FILE* fp, const _PSIPackedMsa* msa);
  * artificial consensus sequence of the multiple sequence alignment
  * constructed by them. This should be called after _PSIPurgeBiasedSegments.
  */
+NCBI_XBLAST_EXPORT 
 void
 _PSIStructureGroupCustomization(_PSIMsa* msa);
 
@@ -642,6 +681,7 @@ _PSIStructureGroupCustomization(_PSIMsa* msa);
  * @return One of the errors defined above if validation fails or bad
  * parameter is passed in, else PSI_SUCCESS
  */
+NCBI_XBLAST_EXPORT 
 int
 _PSIValidateMSA_StructureGroup(const _PSIMsa* msa);
 
diff --git a/algo/blast/core/blast_seg.c b/algo/blast/core/blast_seg.c
index df58db4..3be19cf 100644
--- a/algo/blast/core/blast_seg.c
+++ b/algo/blast/core/blast_seg.c
@@ -1,4 +1,4 @@
-/* $Id: blast_seg.c,v 1.39 2009/02/03 18:14:30 kazimird Exp $
+/* $Id: blast_seg.c,v 1.43 2009/09/14 18:49:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE                          
@@ -36,7 +36,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_seg.c,v 1.39 2009/02/03 18:14:30 kazimird Exp $";
+    "$Id: blast_seg.c,v 1.43 2009/09/14 18:49:32 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_seg.h>
@@ -1778,31 +1778,6 @@ s_SeqEntropy(SSequence* seq, Int4 window, Int4 maxbogus)
    return(H);
 }
 
-/** Appends second arg to end of first one.
- * @param segs structure to be appended to [in]
- * @param seg structure to append [in]
- */
-static void
-s_AppendSeg(SSeg* segs, SSeg* seg)
-{
-   SSeg* temp = segs;
-
-   while (TRUE)
-   {
-      if (temp->next==NULL)
-      {
-         temp->next = seg;
-         break;
-      }
-      else
-      {
-         temp = temp->next;
-      }
-   }
-
-   return;
-}
-
 /*---------------------------------------------------------------(s_FindLow)---*/
 
 /** Finds the first element above hicut, looks from i to limit.
@@ -1850,6 +1825,16 @@ static Int4 s_FindHigh(Int4 i, Int4 limit, double hicut, double* H)
    return(j-1);
   }
 
+/** calculate log(n!) using either tabulated data or Sterling's formula
+ * @param n [in]
+ * @return log(n!)
+ */
+static double
+s_lnfact(Int4 n) {
+  if (n < sizeof(lnfact)/sizeof(*lnfact))
+     return lnfact[n];
+  else return ((n+0.5)*log(n) - n + 0.9189385332);
+}
 
 /** calculate "K2" entropy per equation 3 of Wootton and Federhen
  * (Comput. Chem. 17, 149 (1993).
@@ -1864,12 +1849,11 @@ s_LnPerm(const Int4* sv, Int4 window_length)
    double ans;
    Int4 i;
 
-   ASSERT(window_length < sizeof(lnfact)/sizeof(*lnfact));
-   ans = lnfact[window_length];
+   ans = s_lnfact(window_length);
 
    for (i=0; sv[i]!=0; i++) 
      {
-      ans -= lnfact[sv[i]];
+      ans -= s_lnfact(sv[i]);
      }
 
    return(ans);
@@ -1892,7 +1876,6 @@ s_LnAss(const Int4* sv, Int4 alphasize)
 	int	class, total;
 	int    i;
 
-    ASSERT(alphasize < sizeof(lnfact)/sizeof(*lnfact));
 	ans = lnfact[alphasize];
 	if (sv[0] == 0)
 		return ans;
@@ -1903,7 +1886,7 @@ s_LnAss(const Int4* sv, Int4 alphasize)
 	svim1 = sv[0];
 	for (i=0;; svim1 = svi) {
 	        if (++i==alphasize) {
-		        ans -= lnfact[class];
+		        ans -= s_lnfact(class);
 			break;
 		      }
 		else if ((svi = *++sv) == svim1) {
@@ -1912,9 +1895,9 @@ s_LnAss(const Int4* sv, Int4 alphasize)
 		}
 		else {
 			total -= class;
-			ans -= lnfact[class];
+			ans -= s_lnfact(class);
 			if (svi == 0) {
-				ans -= lnfact[total];
+				ans -= s_lnfact(total);
 				break;
 			}
 			else {
@@ -1983,10 +1966,6 @@ s_Trim(SSequence* seq, Int4* leftend, Int4* rightend, const SegParameters* spara
    if ((seq->length-maxtrim)>minlen) 
         minlen = seq->length-maxtrim;
 
-   /* probably a nucleotide sequence.  s_GetProb cannot handle */
-   if (seq->length > sizeof(lnfact)/sizeof(*lnfact))
-      return -1;
-
    minprob = 1.;
    for (len=seq->length; len>minlen; len--)
    {
@@ -2026,7 +2005,7 @@ s_Trim(SSequence* seq, Int4* leftend, Int4* rightend, const SegParameters* spara
  * @param offset offset of sequence passed in [in]
  */
 static Int2 
-s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg* *segs,
+s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg **segs,
                    Int4 offset)
 {
    SSeg* seg = (SSeg*) NULL;
@@ -2070,8 +2049,8 @@ s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg* *segs,
          rightend = hii + upset - 1;
 
          temp_seq = s_OpenWin(seq, leftend, rightend-leftend+1);
-         status = s_Trim(temp_seq, &leftend, &rightend,
-              sparamsp);
+         status = s_Trim(temp_seq, &leftend, &rightend, sparamsp);
+
          if (status < 0) {
              s_CloseWin(temp_seq);
              break;
@@ -2087,10 +2066,12 @@ s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg* *segs,
             status = s_SegSeq(leftseq, sparamsp, &leftsegs, offset+lend);
             if (status < 0)
               return status;
+
+            /* prepend here, order will be restored in s_SegToSeqLoc */
             if (leftsegs!=NULL)
             {
-               if (*segs==NULL) *segs = leftsegs;
-               else s_AppendSeg(*segs, leftsegs);
+               leftsegs->next = *segs;
+               *segs = leftsegs;
             }
             s_CloseWin(leftseq);
 
@@ -2099,11 +2080,8 @@ s_SegSeq(SSequence* seq, SegParameters* sparamsp, SSeg* *segs,
          seg = (SSeg*) calloc(1, sizeof(SSeg));
          seg->begin = leftend + offset;
          seg->end = rightend + offset;
-         seg->next = (SSeg*) NULL;
-
-         if (*segs==NULL) *segs = seg;
-         else s_AppendSeg(*segs, seg);
-
+         seg->next = *segs;
+         *segs = seg;
          i = MIN(hii, rightend+downset);
          lowlim = i + 1;
         }
@@ -2123,49 +2101,30 @@ s_MergeSegs(SSequence* seq, SSeg* segs)
 {
    SSeg* seg,* nextseg;
    Int4 hilenmin;		/* hilenmin yet unset */
-   Int4 len;
 
    hilenmin = 0;               /* hilenmin - temporary default */
 
    if (segs==NULL) return;
 
-   if (segs->begin<hilenmin) segs->begin = 0;
+   if (seq->length -1 - segs->end < hilenmin) 
+       segs->end = seq->length -1;
 
    seg = segs;
    nextseg = seg->next;
 
-   while (nextseg!=NULL)
-     {
-      if (seg->end>=nextseg->begin && seg->end>=nextseg->end)
-        {
-         seg->next = nextseg->next;
-         sfree(nextseg);
-         nextseg = seg->next;
-         continue;
-        }
-      if (seg->end>=nextseg->begin)               /* overlapping segments */
-        {
-         seg->end = nextseg->end;
+   while (nextseg!=NULL) {
+      if (seg->begin - nextseg->end - 1 < hilenmin) {
+         if (seg->end < nextseg->end) seg->end = nextseg->end;
+         if (seg->begin > nextseg->begin) seg->begin = nextseg->begin;
          seg->next = nextseg->next;
          sfree(nextseg);
-         nextseg = seg->next;
-         continue;
-        }
-      len = nextseg->begin - seg->end - 1;
-      if (len<hilenmin)                            /* short hient segment */
-        {
-         seg->end = nextseg->end;
-         seg->next = nextseg->next;
-         sfree(nextseg);
-         nextseg = seg->next;
-         continue;
-        }
+      } else {
       seg = nextseg;
+      }
       nextseg = seg->next;
      }
 
-   len = seq->length - seg->end - 1;
-   if (len<hilenmin) seg->end = seq->length - 1;
+   if (seg->begin < hilenmin) seg->begin = 0;
 
    return;
 }
@@ -2181,12 +2140,12 @@ static Int2
 s_SegsToBlastSeqLoc(SSeg* segs, Int4 offset, BlastSeqLoc** seg_locs)
 {
    for ( ; segs; segs = segs->next) {
-      Int4 left = segs->begin + offset;
-      Int4 right = segs->end + offset;
-
-      /* Check that allocation succeeded. */
-      if (BlastSeqLocNew(seg_locs, left, right) == NULL)
-          break;
+      BlastSeqLoc *loc = (BlastSeqLoc*) calloc(1, sizeof(BlastSeqLoc));
+      loc->ssr = (SSeqRange*) calloc(1,sizeof(SSeqRange));
+      loc->ssr->left = segs->begin + offset;
+      loc->ssr->right = segs->end  + offset;
+      loc->next = *seg_locs;
+      *seg_locs = loc;
    }
    /* If not all segs have been processed, it means that memory allocation 
       failed, hence return error status. */
diff --git a/algo/blast/core/blast_setup.c b/algo/blast/core/blast_setup.c
index cd68d98..8c86ef6 100644
--- a/algo/blast/core/blast_setup.c
+++ b/algo/blast/core/blast_setup.c
@@ -1,4 +1,4 @@
-/* $Id: blast_setup.c,v 1.152 2008/07/17 17:55:44 kazimird Exp $
+/* $Id: blast_setup.c,v 1.153 2010/03/23 15:44:41 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-    "$Id: blast_setup.c,v 1.152 2008/07/17 17:55:44 kazimird Exp $";
+    "$Id: blast_setup.c,v 1.153 2010/03/23 15:44:41 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_setup.h>
@@ -745,12 +745,26 @@ BLAST_GapAlignSetUp(EBlastProgramType program_number,
    /* Effective lengths are calculated for all programs except PHI BLAST. */
    if ((status = BLAST_CalcEffLengths(program_number, scoring_options, 
                      *eff_len_params, sbp, query_info, NULL)) != 0)
+   {
+      *eff_len_params = BlastEffectiveLengthsParametersFree(*eff_len_params);
       return status;
+   }
 
-   BlastScoringParametersNew(scoring_options, sbp, score_params);
+   if((status=BlastScoringParametersNew(scoring_options, sbp, score_params)) != 0)
+   {
+      *eff_len_params = BlastEffectiveLengthsParametersFree(*eff_len_params);
+      *score_params = BlastScoringParametersFree(*score_params); 
+      return status;
+   }
 
-   BlastExtensionParametersNew(program_number, ext_options, sbp, 
-                               query_info, ext_params);
+   if((status=BlastExtensionParametersNew(program_number, ext_options, sbp, 
+                               query_info, ext_params)) != 0)
+   {
+      *eff_len_params = BlastEffectiveLengthsParametersFree(*eff_len_params);
+      *score_params = BlastScoringParametersFree(*score_params); 
+      *ext_params = BlastExtensionParametersFree(*ext_params); 
+      return status;
+   }
 
    BlastHitSavingParametersNew(program_number, hit_options, sbp, query_info, 
                                (Int4)(total_length/num_seqs), hit_params);
diff --git a/algo/blast/core/blast_stat.c b/algo/blast/core/blast_stat.c
index 17bfc65..e0cfaac 100644
--- a/algo/blast/core/blast_stat.c
+++ b/algo/blast/core/blast_stat.c
@@ -1,4 +1,4 @@
-/* $Id: blast_stat.c,v 1.163 2008/11/03 20:59:44 kazimird Exp $
+/* $Id: blast_stat.c,v 1.165 2009/09/30 17:19:47 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -50,7 +50,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_stat.c,v 1.163 2008/11/03 20:59:44 kazimird Exp $";
+    "$Id: blast_stat.c,v 1.165 2009/09/30 17:19:47 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_stat.h>
@@ -776,6 +776,33 @@ SPsiBlastScoreMatrixNew(size_t ncols)
     return retval;
 }
 
+int
+BlastScoreBlkCheck(BlastScoreBlk* sbp)
+{
+    int index = 0;
+    Boolean found = FALSE;
+
+    if (sbp == NULL)
+       return -1;
+    
+    if (sbp->kbp == NULL || sbp->sfp == NULL)
+      return 1;
+
+    for (index=0; index<sbp->number_of_contexts; index++)
+    {
+       if (sbp->kbp[index] || sbp->sfp[index])
+       {
+           found = TRUE;
+           break;
+       }
+    }
+
+    if (found)
+	return 0;
+    else
+        return 1;
+}
+
 /*
    Allocates memory for the BlastScoreBlk*.
 */
diff --git a/algo/blast/core/blast_stat.h b/algo/blast/core/blast_stat.h
index 78bc6e4..c4f11f4 100644
--- a/algo/blast/core/blast_stat.h
+++ b/algo/blast/core/blast_stat.h
@@ -1,4 +1,4 @@
-/*  $Id: blast_stat.h,v 1.88 2008/11/03 20:59:44 kazimird Exp $
+/*  $Id: blast_stat.h,v 1.89 2009/09/24 16:09:34 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -210,6 +210,14 @@ typedef struct Blast_ResFreq {
 } Blast_ResFreq;
 
 /**
+ * Check that score blk is valid, returns zero if it is.
+ * @param sbp ScoreBlk to check [in]
+ * @return zero if valid
+*/
+NCBI_XBLAST_EXPORT
+int BlastScoreBlkCheck(BlastScoreBlk* sbp);
+
+/**
  *   Allocates and initializes BlastScoreBlk
  * @param alphabet either BLASTAA_SEQ_CODE or BLASTNA_SEQ_CODE [in]
  * @param number_of_contexts how many strands or sequences [in]
diff --git a/algo/blast/core/blast_traceback.c b/algo/blast/core/blast_traceback.c
index 182c203..56cfb9b 100644
--- a/algo/blast/core/blast_traceback.c
+++ b/algo/blast/core/blast_traceback.c
@@ -1,4 +1,4 @@
-/* $Id: blast_traceback.c,v 1.212 2009/07/09 15:49:31 kazimird Exp $
+/* $Id: blast_traceback.c,v 1.214 2010/05/06 18:54:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -50,7 +50,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_traceback.c,v 1.212 2009/07/09 15:49:31 kazimird Exp $";
+    "$Id: blast_traceback.c,v 1.214 2010/05/06 18:54:32 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_traceback.h>
@@ -344,6 +344,7 @@ Blast_TracebackFromHSPList(EBlastProgramType program_number,
    Int4 index;
    BlastHSP* hsp;
    Uint1* query;
+   Uint1* query_nomask = NULL;
    const Uint1* subject = NULL;
    Int4 query_length;
    BlastHSP** hsp_array;
@@ -369,6 +370,7 @@ Blast_TracebackFromHSPList(EBlastProgramType program_number,
    BlastHSPList * orig_hsplist = NULL;
    Boolean fence_error = FALSE;
    SBlastTargetTranslation* target_t = NULL;
+   Int2 status = 0;
    
    if (num_initial_hsps == 0) {
       return 0;
@@ -443,11 +445,14 @@ Blast_TracebackFromHSPList(EBlastProgramType program_number,
           Int4 context_offset = query_info->contexts[context].query_offset;
          
           query = query_blk->oof_sequence + CODON_LENGTH + context_offset;
+          query_nomask = query;
           query_length = query_info->contexts[context+2].query_offset +
               query_info->contexts[context+2].query_length - context_offset;
       } else {
           query = query_blk->sequence + 
               query_info->contexts[hsp->context].query_offset;
+          query_nomask = query_blk->sequence_nomask + 
+              query_info->contexts[hsp->context].query_offset;
           query_length = query_info->contexts[hsp->context].query_length;
       }
 
@@ -593,14 +598,16 @@ Blast_TracebackFromHSPList(EBlastProgramType program_number,
                 /* Calculate number of identities and check if this HSP meets the
                    percent identity and length criteria. */
                 delete_hsp = 
-                    Blast_HSPTestIdentityAndLength(program_number, hsp, query, 
+                    Blast_HSPTestIdentityAndLength(program_number, hsp, query_nomask, 
                                                    adjusted_subject, 
                                                    score_options, hit_options);
             }
             if (!delete_hsp) {
                Blast_HSPAdjustSubjectOffset(hsp, start_shift);
-               BlastIntervalTreeAddHSP(hsp, tree, query_info, 
+               status = BlastIntervalTreeAddHSP(hsp, tree, query_info, 
                                        eQueryAndSubject);
+               if (status)
+                  return status;
             } else {
                hsp_array[index] = Blast_HSPFree(hsp);
             }
@@ -654,8 +661,10 @@ Blast_TracebackFromHSPList(EBlastProgramType program_number,
                hsp_array[index] = Blast_HSPFree(hsp);
            }
            else {
-               BlastIntervalTreeAddHSP(hsp, tree, query_info, 
+               status = BlastIntervalTreeAddHSP(hsp, tree, query_info, 
                                        eQueryAndSubject);
+               if (status)
+                  return status;
            }
        }
    }
diff --git a/algo/blast/core/blast_util.c b/algo/blast/core/blast_util.c
index 7fef37e..9dc51d1 100644
--- a/algo/blast/core/blast_util.c
+++ b/algo/blast/core/blast_util.c
@@ -1,4 +1,4 @@
-/* $Id: blast_util.c,v 1.128 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: blast_util.c,v 1.133 2010/07/27 18:24:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: blast_util.c,v 1.128 2009/05/27 17:39:36 kazimird Exp $";
+    "$Id: blast_util.c,v 1.133 2010/07/27 18:24:31 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/blast_util.h>
@@ -119,11 +119,16 @@ BlastSetUp_SeqBlkNew (const Uint1* buffer, Int4 length,
         (*seq_blk)->sequence_start = (Uint1 *) buffer;
         /* The first byte is a sentinel byte. */
         (*seq_blk)->sequence = (*seq_blk)->sequence_start+1;
+
     } else {
         (*seq_blk)->sequence = (Uint1 *) buffer;
         (*seq_blk)->sequence_start = NULL;
     }
     
+    (*seq_blk)->sequence_start_nomask = (*seq_blk)->sequence_start;
+    (*seq_blk)->sequence_nomask = (*seq_blk)->sequence;
+    (*seq_blk)->nomask_allocated = FALSE;
+    
     (*seq_blk)->length = length;
    
     return 0;
@@ -154,6 +159,9 @@ Int2 BlastSeqBlkSetSequence(BLAST_SequenceBlk* seq_blk,
     seq_blk->sequence_start_allocated = TRUE;
     seq_blk->sequence_start = (Uint1*) sequence;
     seq_blk->sequence = (Uint1*) sequence + 1;
+    seq_blk->sequence_start_nomask = seq_blk->sequence_start;
+    seq_blk->sequence_nomask = seq_blk->sequence_start_nomask + 1;
+    seq_blk->nomask_allocated = FALSE;
     seq_blk->length = seqlen;
     seq_blk->oof_sequence = NULL;
 
@@ -178,32 +186,38 @@ Int2
 BlastSeqBlkSetSeqRanges(BLAST_SequenceBlk* seq_blk,
                         SSeqRange* seq_ranges,
                         Uint4 num_seq_ranges,
-                        Boolean copy_seq_ranges)
+                        Boolean copy_seq_ranges,
+                        Int4 mask_type)
 {
+    SSeqRange* tmp;
+
     if ( !seq_blk || !seq_ranges ) {
         return -1;
     }
+
     ASSERT(num_seq_ranges >= 1);
 
-    if (copy_seq_ranges) {
-        SSeqRange* tmp = (SSeqRange*) calloc(num_seq_ranges,
-                                             sizeof(*seq_ranges));
-        if ( !tmp ) {
-            return -1;
-        }
         s_BlastSequenceBlkFreeSeqRanges(seq_blk);
-        seq_blk->seq_ranges = tmp;
-        memcpy((void*) seq_blk->seq_ranges,
+    if (copy_seq_ranges) {
+        // allocate one more space for easy complimentary operations
+        seq_blk->seq_ranges_allocated = TRUE;
+        tmp = (SSeqRange *) calloc(num_seq_ranges, sizeof(SSeqRange));
+        if ( !tmp ) { return -1; }
+        memcpy((void*) tmp,
                (void*) seq_ranges,
                num_seq_ranges * sizeof(*seq_ranges));
-        seq_blk->num_seq_ranges = num_seq_ranges;
-        seq_blk->seq_ranges_allocated = TRUE;
     } else {
-        s_BlastSequenceBlkFreeSeqRanges(seq_blk);
-        seq_blk->seq_ranges = seq_ranges;
+        // CSeqDB has allocated one more space before and after seq_range
         seq_blk->seq_ranges_allocated = FALSE;
-        seq_blk->num_seq_ranges = num_seq_ranges;
+        tmp = seq_ranges;
     }
+        
+    // Fill out the boundary of the sequence to compliment the masks
+    tmp[0].left = 0;
+    tmp[num_seq_ranges - 1].right = seq_blk->length;
+    seq_blk->seq_ranges = tmp;
+    seq_blk->num_seq_ranges = num_seq_ranges; 
+    seq_blk->mask_type = mask_type;
     return 0;
 }
 
@@ -224,6 +238,10 @@ void BlastSequenceBlkClean(BLAST_SequenceBlk* seq_blk)
        sfree(seq_blk->oof_sequence);
        seq_blk->oof_sequence_allocated = FALSE;
    }
+   if (seq_blk->nomask_allocated) {
+       sfree(seq_blk->sequence_start_nomask);
+       seq_blk->nomask_allocated = FALSE;
+   }
    s_BlastSequenceBlkFreeSeqRanges(seq_blk);
    return;
 }
@@ -1207,45 +1225,6 @@ Int4 BSearchInt4(Int4 n, Int4* A, Int4 size)
     return b;
 }
 
-Int2
-Blast_SetUpSubjectTranslation(BLAST_SequenceBlk* subject_blk, 
-                              const Uint1* gen_code_string,
-                              Uint1** translation_buffer_ptr, 
-                              Int4** frame_offsets_ptr,
-                              Boolean* partial_translation_ptr)
-{
-   Boolean partial_translation;
-   Boolean is_ooframe = (frame_offsets_ptr == NULL);
-
-   if (!gen_code_string)
-      return -1;
-
-   if (is_ooframe && subject_blk->oof_sequence) {
-      /* If mixed-frame sequence is already available (two-sequences case),
-         then no need to translate again */
-      *partial_translation_ptr = FALSE;
-      return 0;
-   } 
-
-   *partial_translation_ptr = partial_translation = 
-      (subject_blk->length > MAX_FULL_TRANSLATION);
-      
-   if (!partial_translation) {
-      if (is_ooframe) {
-         BLAST_GetAllTranslations(subject_blk->sequence_start, 
-            eBlastEncodingNcbi4na, subject_blk->length, gen_code_string, 
-            NULL, NULL, &subject_blk->oof_sequence);
-         subject_blk->oof_sequence_allocated = TRUE;
-      } else {
-         BLAST_GetAllTranslations(subject_blk->sequence_start, 
-            eBlastEncodingNcbi4na, subject_blk->length, gen_code_string, 
-            translation_buffer_ptr, frame_offsets_ptr, NULL);
-      }
-   }
-
-   return 0;
-}
-
 SBlastTargetTranslation*
 BlastTargetTranslationFree(SBlastTargetTranslation* target_t)
 {
diff --git a/algo/blast/core/blast_util.h b/algo/blast/core/blast_util.h
index d319ee8..53a9b6b 100644
--- a/algo/blast/core/blast_util.h
+++ b/algo/blast/core/blast_util.h
@@ -1,4 +1,4 @@
-/* $Id: blast_util.h,v 1.84 2009/01/07 16:29:41 kazimird Exp $
+/* $Id: blast_util.h,v 1.86 2010/07/27 18:24:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -135,6 +135,7 @@ Int2 BlastSeqBlkSetCompressedSequence(BLAST_SequenceBlk* seq_blk,
  * @param seq_ranges sequence ranges to copy [in]
  * @param num_seq_ranges number of elements in array above [in]
  * @param copy_seq_ranges set to TRUE if seq_ranges should be copied to the
+ * @param mask_type either kSoftDBMask or kHardDBMask [in]
  * BLAST_SequenceBlk and assume its ownership, set to FALSE if the pointer
  * should be copied and the ownership of the seq_ranges remains in the caller's
  * possession.
@@ -147,7 +148,8 @@ NCBI_XBLAST_EXPORT
 Int2 BlastSeqBlkSetSeqRanges(BLAST_SequenceBlk* seq_blk,
                              SSeqRange* seq_ranges,
                              Uint4 num_seq_ranges,
-                             Boolean copy_seq_ranges);
+                             Boolean copy_seq_ranges,
+                             Int4 mask_type);
                             
 /** Adds a specialized representation of sequence data to a sequence
  * block. In the specialized representation, the byte at offset i 
@@ -357,30 +359,10 @@ BLAST_StrToUpper(const char* string);
  * of partially decoded sequences.  If an alignment finds this value
  * in a subject sequence, the fence_hit flag should be used to request
  * a refetch of the whole sequence, and the alignment restarted.
+ * @note this value is repeated in seqdbgeneral.hpp
  */
 #define FENCE_SENTRY 201
 
-
-/** Translate the subject sequence into 6 frames, and create a mixed-frame 
- * sequence, if out-of-frame gapping will be used.
- * @param subject_blk Subject sequence structure [in]
- * @param gen_code_string Genetic code to use for translation [in]
- * @param translation_buffer Pointer to buffer to hold the translated 
- *                           sequence(s) [out]
- * @param frame_offsets Pointer to an array to hold offsets into the
- *                      translation buffer for each frame. Mixed-frame 
- *                      sequence is to be returned, if NULL. [in] [out]
- * @param partial_translation Should partial translations be performed later
- *                            for each HSP instead of a full translation? [out]
- */
-NCBI_XBLAST_EXPORT
-Int2
-Blast_SetUpSubjectTranslation(BLAST_SequenceBlk* subject_blk, 
-                              const Uint1* gen_code_string,
-                              Uint1** translation_buffer, 
-                              Int4** frame_offsets,
-                              Boolean* partial_translation);
-
 /** Get the number of contexts for a given program. This corresponds to the
  * number of translation frames or strands whenever applicable. 
  * @return 0 on unsupported program, non-zero otherwise
diff --git a/algo/blast/core/greedy_align.h b/algo/blast/core/greedy_align.h
index 6a4c313..ed8399d 100644
--- a/algo/blast/core/greedy_align.h
+++ b/algo/blast/core/greedy_align.h
@@ -1,4 +1,4 @@
-/* $Id: greedy_align.h,v 1.26 2007/04/17 16:55:32 kazimird Exp $
+/* $Id: greedy_align.h,v 1.27 2009/09/23 18:34:37 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -76,11 +76,13 @@ typedef struct SMBSpace {
  *  @param num_space_arrays number of array elements to allocated [in]
  *  @return Pointer to allocated structure, or NULL upon failure
  */
+NCBI_XBLAST_EXPORT
 SMBSpace* MBSpaceNew(int num_space_arrays);
 
 /** Free the space structure 
     @param sp Linked list of structures to free
 */
+NCBI_XBLAST_EXPORT
 void MBSpaceFree(SMBSpace* sp);
 
 /** All auxiliary memory needed for the greedy extension algorithm. */
@@ -122,6 +124,7 @@ typedef struct SGreedySeed {
  * @return The minimum distance between the two sequences, i.e.
  *          the number of mismatches plus gaps in the resulting alignment
  */
+NCBI_XBLAST_EXPORT
 Int4 
 BLAST_GreedyAlign (const Uint1* seq1, Int4 len1,
                    const Uint1* seq2, Int4 len2,
@@ -154,6 +157,7 @@ BLAST_GreedyAlign (const Uint1* seq1, Int4 len1,
  * @param seed Structure to remember longest run of exact matches [out]
  * @return The score of the alignment
  */
+NCBI_XBLAST_EXPORT
 Int4 
 BLAST_AffineGreedyAlign (const Uint1* seq1, Int4 len1,
                          const Uint1* seq2, Int4 len2,
diff --git a/algo/blast/core/hspfilter_collector.c b/algo/blast/core/hspfilter_collector.c
index fb504d6..62ef0e0 100644
--- a/algo/blast/core/hspfilter_collector.c
+++ b/algo/blast/core/hspfilter_collector.c
@@ -1,4 +1,4 @@
-/*  $Id: hspfilter_collector.c,v 1.1 2009/06/01 15:32:08 kazimird Exp $
+/*  $Id: hspfilter_collector.c,v 1.2 2009/10/01 17:55:38 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: hspfilter_collector.c,v 1.1 2009/06/01 15:32:08 kazimird Exp $";
+    "$Id: hspfilter_collector.c,v 1.2 2009/10/01 17:55:38 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 
@@ -235,7 +235,6 @@ s_BlastHSPCollectorRun_RPS(void* data, BlastHSPList* hsplist_in)
    BlastHSPCollectorData * col_data = data;
    BlastHSPResults* results = col_data->results;
    BlastHSPCollectorParams* params = col_data->params;
-   EBlastProgramType program = params->program;
 
    if (!hsplist_in || hsplist_in->hspcnt == 0)
       return 0;
@@ -244,7 +243,7 @@ s_BlastHSPCollectorRun_RPS(void* data, BlastHSPList* hsplist_in)
    ASSERT(hsplist_in->query_index < results->num_queries);
 
    /* Check that program is indeed RPS Blast */
-   ASSERT(Blast_ProgramIsRpsBlast(program));
+   ASSERT(Blast_ProgramIsRpsBlast(params->program));
 
    /* If hit list for this query has not yet been allocated, do it here. */
    hit_list = results->hitlist_array[hsplist_in->query_index];
diff --git a/algo/blast/core/index_ungapped.c b/algo/blast/core/index_ungapped.c
index 940b522..50038be 100644
--- a/algo/blast/core/index_ungapped.c
+++ b/algo/blast/core/index_ungapped.c
@@ -1,4 +1,4 @@
-/* $Id: index_ungapped.c,v 1.1 2007/03/30 14:56:05 kazimird Exp $
+/* $Id: index_ungapped.c,v 1.2 2009/10/01 17:55:38 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -42,7 +42,7 @@
 
     @return NULL.
   */
-ir_fp_entry * ir_fp_entry_destroy( ir_fp_entry * e )
+static ir_fp_entry * ir_fp_entry_destroy( ir_fp_entry * e )
 {
     if( e != 0 ) {
         free( e->entries );
@@ -57,7 +57,7 @@ ir_fp_entry * ir_fp_entry_destroy( ir_fp_entry * e )
 
     @return Pointer to a newly allocated free memory block.
 */
-ir_fp_entry * ir_fp_entry_create( void )
+static ir_fp_entry * ir_fp_entry_create( void )
 {
     ir_fp_entry * result = (ir_fp_entry *)malloc( sizeof( ir_fp_entry ) );
     
diff --git a/algo/blast/core/lookup_wrap.h b/algo/blast/core/lookup_wrap.h
index 98b4cde..b9e8460 100644
--- a/algo/blast/core/lookup_wrap.h
+++ b/algo/blast/core/lookup_wrap.h
@@ -1,4 +1,4 @@
-/* $Id: lookup_wrap.h,v 1.18 2008/01/31 23:55:42 kazimird Exp $
+/* $Id: lookup_wrap.h,v 1.19 2009/12/16 19:49:33 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -50,11 +50,17 @@ typedef struct LookupTableWrap {
    void* lut; /**< Pointer to the actual lookup table structure */
    void* read_indexed_db; /**< function used to retrieve hits
                               from an indexed database */
+   void* lookup_callback;    /**< function used to look up an
+                                  index->q_off pair */
 } LookupTableWrap;
 
+/** Function pointer type to check the presence of index->q_off pair */
+typedef Boolean (*T_Lookup_Callback)(const LookupTableWrap *, Int4, Int4);
+
 /** Create the lookup table for all query words.
  * @param query The query sequence [in]
  * @param lookup_options What kind of lookup table to build? [in]
+ * @param query_options options for query setup [in]
  * @param lookup_segments Locations on query to be used for lookup table
  *                        construction [in]
  * @param sbp Scoring block containing matrix [in]
diff --git a/algo/blast/core/masksubj.inl b/algo/blast/core/masksubj.inl
index ca69233..72fb85e 100644
--- a/algo/blast/core/masksubj.inl
+++ b/algo/blast/core/masksubj.inl
@@ -1,4 +1,4 @@
-/* $Id: masksubj.inl,v 1.1 2009/05/27 20:31:32 kazimird Exp $
+/* $Id: masksubj.inl,v 1.2 2010/07/28 14:49:44 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -45,42 +45,15 @@ s_DetermineScanningOffsets(const BLAST_SequenceBlk* subject,
                            Int4  lut_word_length,
                            Int4* range)
 {
-    /* for masked db, we use (length - word_length) instead */
-    for (; range[0] < subject->num_seq_ranges; (range[0])++) {
-        /* handle case where s_last is beyond a masked region */
-        if (range[2] + word_length > subject->seq_ranges[range[0]].left) {
-            range[2] = subject->seq_ranges[range[0]].left - word_length;
-            range[4] = range[2] + word_length;
-        }
-
-        /* if s_first is in a masked region, try the next one. */
-        if (range[1] + lut_word_length >= subject->seq_ranges[range[0]].left) {
-            range[1] = subject->seq_ranges[range[0]].right + word_length - lut_word_length;
-            range[3] = range[1] - word_length + lut_word_length;
-            range[2] = subject->length - word_length;
-            range[4] = range[2] + word_length;
-            continue;
-        }
-
-        /* if the range to scan is smaller than the word size, don't bother. */
-        if ( (range[2]-range[1]+1) < word_length ) {
-			range[1] = subject->seq_ranges[range[0]].right + word_length - lut_word_length;
-            range[3] = range[1] - word_length + lut_word_length;
-			range[2] = subject->length - word_length;
-			range[4] = range[2] + word_length;
-            continue;
-            }
- 
-        break;
-    } /* end for */
-
-    if (range[1] + lut_word_length > subject->length) {
+    ASSERT(subject->seq_ranges);
+    ASSERT(subject->num_seq_ranges >= 1);
+    while (range[1] > range[2]) {
+        range[0]++;
+        if (range[0] >= subject->num_seq_ranges) {
         return FALSE;
 		}
-			
-    if ( (range[2]-range[1]+1) < word_length ) {
-        return FALSE;
+        range[1] = subject->seq_ranges[range[0]].left + word_length - lut_word_length;
+        range[2] = subject->seq_ranges[range[0]].right - lut_word_length;
 		}
-
     return TRUE;
 }
diff --git a/algo/blast/core/na_ungapped.c b/algo/blast/core/na_ungapped.c
index 308fc13..f75310b 100644
--- a/algo/blast/core/na_ungapped.c
+++ b/algo/blast/core/na_ungapped.c
@@ -1,4 +1,4 @@
-/* $Id: na_ungapped.c,v 1.21 2009/07/30 19:34:30 kazimird Exp $
+/* $Id: na_ungapped.c,v 1.39 2010/07/27 18:24:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,7 +30,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] =
-    "$Id: na_ungapped.c,v 1.21 2009/07/30 19:34:30 kazimird Exp $";
+    "$Id: na_ungapped.c,v 1.39 2010/07/27 18:24:31 kazimird Exp $";
 #endif                          /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/na_ungapped.h>
@@ -42,6 +42,103 @@ static char const rcsid[] =
 #include "index_ungapped.h"
 #include "masksubj.inl"
 
+/** Check to see if an index->q_pos pair exists in MB lookup table 
+ * @param lookup_wrap The lookup table wrap structure [in]
+ * @param index The index to the lookup table [in]
+ * @param q_pos The offset of query to be looked up [in]
+ * @return TRUE if the pair is found to exist in the lookup table 
+ */
+static Boolean
+s_MBLookup(const LookupTableWrap *lookup_wrap,
+           Int4                   index,
+           Int4                   q_pos)
+{
+    BlastMBLookupTable* mb_lt = (BlastMBLookupTable *) lookup_wrap->lut;
+    PV_ARRAY_TYPE *pv = mb_lt->pv_array;
+    Int4 q_off;
+
+    index &= (mb_lt->hashsize-1);
+    ++q_pos;
+
+    if (! PV_TEST(pv, index, mb_lt->pv_array_bts)) {
+        return FALSE;
+    }
+
+    q_off = mb_lt->hashtable[index];
+    while (q_off) {
+        if (q_off == q_pos) return TRUE;
+        q_off = mb_lt->next_pos[q_off];
+    }
+
+    return FALSE;
+}
+
+/** Check to see if an index->q_pos pair exists in SmallNa lookup table
+ * @param lookup_wrap The lookup table wrap structure [in]
+ * @param index The index to the lookup table [in]
+ * @param q_pos The offset of query to be looked up [in]
+ * @return TRUE if the pair is found to exist in the lookup table 
+ */
+static Boolean
+s_SmallNaLookup(const LookupTableWrap *lookup_wrap,
+                Int4                   index,
+                Int4                   q_pos)
+{
+    BlastSmallNaLookupTable* lookup = 
+                         (BlastSmallNaLookupTable *) lookup_wrap->lut;
+    Int2 *overflow = lookup->overflow;
+    Int4 src_off;
+
+    index = lookup->final_backbone[index & lookup->mask];
+
+    if (index == q_pos) return TRUE;
+    if (index == -1 || index >= 0) return FALSE;
+
+    src_off = -index;
+    index = overflow[src_off++];
+    do {
+        if (index == q_pos) return TRUE;
+        index = overflow[src_off++];
+    } while (index >=0);
+
+    return FALSE;
+}
+        
+/** Check to see if an index->q_pos pair exists in Na lookup table 
+ * @param lookup_wrap The lookup table wrap structure [in]
+ * @param index The index to the lookup table [in]
+ * @param q_pos The offset of query to be looked up [in]
+ * @return TRUE if the pair is found to exist in the lookup table 
+ */
+static Boolean
+s_NaLookup(const LookupTableWrap *lookup_wrap,
+           Int4                   index,
+           Int4                   q_pos)
+{
+    BlastNaLookupTable* lookup = (BlastNaLookupTable *) lookup_wrap->lut;
+    PV_ARRAY_TYPE *pv = lookup->pv;
+    Int4 num_hits, i;
+    Int4 *lookup_pos;
+
+    index &= (lookup->mask);
+
+    if (! PV_TEST(pv, index, PV_ARRAY_BTS)) {
+        return FALSE;
+    }
+
+    num_hits = lookup->thick_backbone[index].num_used;
+
+    lookup_pos = (num_hits <= NA_HITS_PER_CELL) ?
+                 lookup->thick_backbone[index].payload.entries :
+                 lookup->overflow + lookup->thick_backbone[index].payload.overflow_cursor;
+
+    for (i=0; i<num_hits; ++i) {
+        if (lookup_pos[i] == q_pos) return TRUE;
+    }
+        
+    return FALSE;
+}    
+
 /** Perform ungapped extension of a word hit, using a score
  *  matrix and extending one base at a time
  * @param query The query sequence [in]
@@ -84,6 +181,14 @@ s_NuclUngappedExtendExact(BLAST_SequenceBlk * query,
     score = 0;
     sum = 0;
 
+/*
+   There is a trick in the loop below that you can't see from the code.
+   X is negative and when sum becomes more negative than X we break out of
+   the loop.  The reason that X is guaranteed to become negative is because
+   there is a sentinel at the beginning of the query sequence, so if you hit
+   that you get a big negative value.
+*/
+
     /* extend to the left */
     while ((s > start) || (s == start && base < remainder)) {
         if (base == 3) {
@@ -345,47 +450,140 @@ static NCBI_INLINE Int4 s_BlastDiagHashInsert(BLAST_DiagHash * table,
     return 1;
 }
 
-/** Extends the 1st hit to the right.  Used only in 2-hit algorithm.
- * This is called when 1st hit is identified.  It will scan areas that
- * are relevant to 2-hit algorithm (overlap_size, window_size, etc.),
- * which are nevertheless skipped by the strided scan.
+/** Test to see if seed->q_off exists in lookup table
+ * @param lookup_wrap The lookup table wrap structure [in]
+ * @param subject Subject sequence data [in]
+ * @s_off The starting offset of the seed [in]
+ * @lut_word_length The length of the lookup word [in]
+ */
+static NCBI_INLINE Boolean
+s_IsSeedMasked(const LookupTableWrap   * lookup_wrap,
+               const BLAST_SequenceBlk * subject,
+               Int4                      s_off,
+               Int4                      lut_word_length,
+               Int4                      q_pos)
+{
+    Uint1 *s  = subject->sequence + s_off / COMPRESSION_RATIO;
+    Int4 shift = 2* (16 - s_off % COMPRESSION_RATIO - lut_word_length);
+    Int4 index = (s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]) >> shift;
+    return !(((T_Lookup_Callback)(lookup_wrap->lookup_callback))
+                                         (lookup_wrap, index, q_pos));
+}
+
+/** Check the mini-extended word against masked query regions, and do right
+ * extension if necessary.
  * @param query Query sequence data [in]
  * @param subject Subject sequence data [in]
- * @param q_end Query ending offset (starting point for right extension) [in]
- * @param s_end Subject ending offset (starting point for right extension) [in]
- * @param query_info Structure containing query context ranges [in]
- * @param max_ext  The maximum number of bases to extend [in]
- * @return Actual number of bases extended 
+ * @param q_off Query offset [in][out]
+ * @param s_off Subject offset [in][out]
+ * @param locations of the masked query regions [in]
+ * @param query_info of the masked query regions [in]
+ * @param s_range the open bound of subject region [in]
+ * @param word_length length of word [in]
+ * @param lut_word_length length of lookup table word [in]
+ * @param check_double check to see if it is a double word [in]
+ * @param extended if successful, the actual bases extended [out]
+ * @return 0,1,2  for non-word, single word, and double word
  */
-static Uint4
-s_BlastRightExtend(BLAST_SequenceBlk * query,
+static Int4
+s_TypeOfWord(BLAST_SequenceBlk * query,
                    BLAST_SequenceBlk * subject,
-                   Uint4 q_end, Uint4 s_end,
+             Int4 *q_off, Int4 *s_off,
+             BlastSeqLoc* locations, 
                    BlastQueryInfo * query_info,
-                   Uint4 max_ext)
+             Uint4 s_range,
+             Uint4 word_length,
+             Uint4 lut_word_length,
+             const LookupTableWrap* lookup_wrap,
+             Boolean check_double,
+             Int4 * extended)
 {
-    Uint1 *q = query->sequence + q_end;
-    Uint1 *s = subject->sequence + s_end / COMPRESSION_RATIO;
-    Uint4 extended;
-
-    /* reduce the max_ext to prevent hitting the sequence boundary */
-    /* note: we probably can return immediately if full extent can not be achieved*/
-    /* TODO: subject masking is ignored, to be fixed */
-    if (query_info) {
-        Uint4 context = BSearchContextInfo(q_end, query_info);
-        Uint4 context_i = query_info->contexts[context].query_offset;
-        Uint4 context_f = context_i + query_info->contexts[context].query_length;
-        Uint4 subject_length = subject->length;
-        max_ext = MIN(max_ext, MIN(context_f - q_end, subject_length - s_end));
-    }
- 
-    for (extended = 0; extended < max_ext; extended++, q++) {
-        if (((Uint1) (*s << (2 * (s_end % COMPRESSION_RATIO))) >> 6) != *q)
-            break;
-        s_end++;
-        if (s_end % COMPRESSION_RATIO == 0) s++;
+    Int4 context, q_range;
+    Int4 ext_to, ext_max;
+    Int4 q_end = *q_off + word_length;
+    Int4 s_end = *s_off + word_length;
+    Int4 s_pos, q_pos;
+
+    *extended = 0;
+
+    /* No need to check if mini-extension is not performed.
+       It turns out that we may skip checking for double-hit in 2-hit 
+       algo case as well -- they will come in as 2 hits naturally*/
+    if (word_length == lut_word_length) return 1;
+
+    /* Find the query context boundary */
+    context = BSearchContextInfo(q_end, query_info);
+    q_range = query_info->contexts[context].query_offset 
+            + query_info->contexts[context].query_length;
+
+    /* check query mask at two ends */
+    if (locations) {
+        /* check for right end first */
+        if (s_IsSeedMasked(lookup_wrap, subject, 
+                           s_end - lut_word_length, 
+                           lut_word_length, 
+                           q_end - lut_word_length)) return 0;
+
+        /* search for valid left end and reposition q_off */
+        for (; TRUE; ++(*s_off), ++(*q_off)) {
+            if (!s_IsSeedMasked(lookup_wrap, subject,
+                                *s_off, lut_word_length, *q_off)) break;
+        }
+    }
+
+    ext_to = word_length - (q_end - (*q_off));
+    ext_max = MIN(q_range - q_end, s_range - s_end);
+
+    /* shift to the right, and check query mask inside */
+    if (ext_to || locations) {
+
+        if (ext_to > ext_max) return 0;
+        q_end += ext_to;
+        s_end += ext_to;
+
+        for (s_pos = s_end - lut_word_length, 
+             q_pos = q_end - lut_word_length;
+             s_pos > *s_off; 
+             s_pos -= lut_word_length,
+             q_pos -= lut_word_length) {
+             if (s_IsSeedMasked(lookup_wrap, subject,
+                           s_pos, lut_word_length, q_pos)) return 0;
     }
-    return extended;
+
+        (*extended) = ext_to;
+    }
+
+    /* if we get here, single word check is passed */
+    if (!check_double) return 1;
+
+    /* do right extension to double word
+       Note: unlike the single word check, here we need to determine the 
+       precise value of maximal possible *extend */
+    ext_to += word_length;
+    ext_max = MIN(ext_max, ext_to);
+
+    /* try seed by seed */
+    for (s_pos = s_end, q_pos = q_end; 
+         *extended + lut_word_length <= ext_max; 
+         s_pos += lut_word_length, 
+         q_pos += lut_word_length,
+         (*extended) += lut_word_length) {
+         if (s_IsSeedMasked(lookup_wrap, subject, s_pos, 
+                            lut_word_length, q_pos)) break;
+    }
+
+    /* try base by base */
+    s_pos -= (lut_word_length - 1);
+    q_pos -= (lut_word_length - 1);
+    while (*extended < ext_max) {
+        if (s_IsSeedMasked(lookup_wrap, subject, s_pos,
+                               lut_word_length, q_pos)) return 1;
+        (*extended)++;
+        ++s_pos;
+        ++q_pos;
+    }
+        
+    return ((ext_max == ext_to) ? 2 : 1);
 }
 
 /** Perform ungapped extension given an offset pair, and save the initial 
@@ -395,15 +593,17 @@ s_BlastRightExtend(BLAST_SequenceBlk * query,
  * are detected within a window.
  * @param query The query sequence [in]
  * @param subject The subject sequence [in]
- * @param contiguous Is this a contiguous blastn? [in]
+ * @param q_off The offset in the query sequence [in]
+ * @param s_off The offset in the subject sequence [in]
+ * @param query_mask Structure containing query mask ranges [in]
+ * @param query_info Structure containing query context ranges [in]
+ * @param s_range Subject range [in]
+ * @param word_length The length of the hit [in]
+ * @param word_lut_length The length of the lookup table word [in]
  * @param word_params The parameters related to initial word extension [in]
  * @param matrix the substitution matrix for ungapped extension [in]
- * @param query_info Structure containing query context ranges [in]
  * @param diag_table Structure containing diagonal table with word extension 
  *                   information [in]
- * @param q_off The offset in the query sequence [in]
- * @param s_off The offset in the subject sequence [in]
- * @param word_length The length of the hit [in]
  * @param init_hitlist The structure containing information about all 
  *                     initial hits [in] [out]
  * @return 1 if hit was extended, 0 if not
@@ -411,16 +611,21 @@ s_BlastRightExtend(BLAST_SequenceBlk * query,
 static Int4
 s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query,
                              BLAST_SequenceBlk * subject, 
-                             Boolean contiguous,
+                             Int4 q_off, Int4 s_off, 
+                             BlastSeqLoc* query_mask,
+                             BlastQueryInfo * query_info,
+                             Int4 s_range,
+                             Int4 word_length, Int4 lut_word_length,
+                             const LookupTableWrap * lut,
                              const BlastInitialWordParameters * word_params,
-                             Int4 ** matrix, BlastQueryInfo * query_info,
+                             Int4 ** matrix, 
                              BLAST_DiagTable * diag_table,
-                             Int4 q_off, Int4 s_off, Int4 word_length,
                              BlastInitHitList * init_hitlist)
 {
     Int4 diag, real_diag;
     Int4 s_end, s_off_pos, s_end_pos;
-    Int4 ext_right = 0;
+    Int4 word_type = 0;
+    Int4 extended = 0;
     BlastUngappedData *ungapped_data;
     BlastUngappedData dummy_ungapped_data;
     Int4 window_size = word_params->options->window_size;
@@ -429,8 +634,8 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query,
     DiagStruct *hit_level_array;
     BlastUngappedCutoffs *cutoffs = NULL;
     Boolean two_hits = (window_size > 0);
-    Boolean found = FALSE;
-    Int4 Delta = MIN(5, window_size - word_length);
+    Boolean off_found = FALSE;
+    Int4 Delta = MIN(word_params->options->scan_range, window_size - word_length);
 
     hit_level_array = diag_table->hit_level_array;
     ASSERT(hit_level_array);
@@ -447,31 +652,32 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query,
     if (s_off_pos < last_hit) return 0;
 
     if (two_hits && (hit_saved || s_end_pos > last_hit + window_size )) {
-        /* check to see if it can be extended to the right by
-           word_length and therefore qualifies for a double-hit */
-        if (contiguous) {
-            ext_right = s_BlastRightExtend(query, subject,
-                  q_off + word_length, s_end, query_info, word_length);
+        /* check the masks for the word; also check to see if this
+           first hit qualifies for a double-word */
+        word_type = s_TypeOfWord(query, subject, &q_off, &s_off,
+                                 query_mask, query_info, s_range, 
+                                 word_length, lut_word_length, lut, TRUE, &extended);
+        if (!word_type) return 0;
             /* update the right end*/
-            s_end += ext_right;
-            s_end_pos += ext_right;
-        }
+        s_end += extended;
+        s_end_pos += extended;
 
-        if (ext_right < word_length) {
+        /* for single word, also try off diagonals */
+        if (word_type == 1) {
             /* try off-diagonals */
             Int4 orig_diag = real_diag + diag_table->diag_array_length;
             Int4 s_a = s_off_pos + word_length - window_size;
             Int4 s_b = s_end_pos - 2 * word_length;
             Int4 delta;
             if (Delta < 0) Delta = 0;
-            for (delta = 1; delta < Delta ; ++delta) {
+            for (delta = 1; delta <= Delta ; ++delta) {
                 Int4 off_diag  = (orig_diag + delta) & diag_table->diag_mask;
                 Int4 off_s_end = hit_level_array[off_diag].last_hit;
                 Int4 off_s_l   = diag_table->hit_len_array[off_diag];
                 if ( off_s_l
                  && off_s_end - delta >= s_a 
                  && off_s_end - off_s_l <= s_b) {
-                    found = TRUE;
+                    off_found = TRUE;
                     break;
                 }
                 off_diag  = (orig_diag - delta) & diag_table->diag_mask;
@@ -480,15 +686,23 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query,
                 if ( off_s_l
                  && off_s_end >= s_a 
                  && off_s_end - off_s_l + delta <= s_b) {
-                    found = TRUE;
+                    off_found = TRUE;
                     break;
                 }
             }
-            if (!found) {
+            if (!off_found) {
                 /* This is a new hit */
                 hit_ready = 0;
             }
         }
+    } else {
+        /* check the masks for the word */
+        if(!s_TypeOfWord(query, subject, &q_off, &s_off,
+                        query_mask, query_info, s_range, 
+                        word_length, lut_word_length, lut, FALSE, &extended)) return 0;
+        /* update the right end*/
+        s_end += extended;
+        s_end_pos += extended;
     }
 
     if (hit_ready) {
@@ -501,7 +715,7 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query,
                                  word_params->nucl_score_table,
                                  cutoffs->reduced_nucl_cutoff_score);
 
-            if (found || ungapped_data->score >= cutoffs->cutoff_score) {
+            if (off_found || ungapped_data->score >= cutoffs->cutoff_score) {
                 BlastUngappedData *final_data =
                     (BlastUngappedData *) malloc(sizeof(BlastUngappedData));
                 *final_data = *ungapped_data;
@@ -533,14 +747,16 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query,
  * are detected within a window.
  * @param query The query sequence [in]
  * @param subject The subject sequence [in]
- * @param contiguous Is this a contiguous blastn? [in]
- * @param word_params The parameters related to initial word extension [in]
- * @param matrix the substitution matrix for ungapped extension [in]
- * @param query_info Structure containing query context ranges [in]
- * @param hash_table Structure containing initial hits [in] [out]
  * @param q_off The offset in the query sequence [in]
  * @param s_off The offset in the subject sequence [in]
+ * @param query_mask Structure containing query mask ranges [in]
+ * @param query_info Structure containing query context ranges [in]
+ * @param s_range Subject range [in]
  * @param word_length The length of the hit [in]
+ * @param word_lut_length The length of the lookup table word [in]
+ * @param word_params The parameters related to initial word extension [in]
+ * @param matrix the substitution matrix for ungapped extension [in]
+ * @param hash_table Structure containing initial hits [in] [out]
  * @param init_hitlist The structure containing information about all 
  *                     initial hits [in] [out]
  * @return 1 if hit was extended, 0 if not
@@ -548,16 +764,21 @@ s_BlastnDiagTableExtendInitialHit(BLAST_SequenceBlk * query,
 static Int4
 s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query,
                                BLAST_SequenceBlk * subject, 
-                               Boolean contiguous, 
+                               Int4 q_off, Int4 s_off, 
+                               BlastSeqLoc* query_mask,
+                               BlastQueryInfo * query_info,
+                               Int4 s_range,
+                               Int4 word_length, Int4 lut_word_length,
+                               const LookupTableWrap * lut,
                                const BlastInitialWordParameters * word_params,
-                               Int4 ** matrix, BlastQueryInfo * query_info,
+                               Int4 ** matrix,
                                BLAST_DiagHash * hash_table,
-                               Int4 q_off, Int4 s_off, Int4 word_length,
                                BlastInitHitList * init_hitlist)
 {
     Int4 diag;
     Int4 s_end, s_off_pos, s_end_pos, s_l;
-    Int4 ext_right = 0;
+    Int4 word_type = 0;
+    Int4 extended = 0;
     BlastUngappedData *ungapped_data;
     BlastUngappedData dummy_ungapped_data;
     Int4 window_size = word_params->options->window_size;
@@ -565,8 +786,8 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query,
     Int4 last_hit, hit_saved = 0;
     BlastUngappedCutoffs *cutoffs = NULL;
     Boolean two_hits = (window_size > 0);
-    Boolean found = FALSE;
-    Int4 Delta = MIN(5, window_size - word_length);
+    Boolean off_found = FALSE;
+    Int4 Delta = MIN(word_params->options->scan_range, window_size - word_length);
     Int4 rc;
 
     diag = s_off - q_off;
@@ -583,24 +804,24 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query,
     if (s_off_pos < last_hit) return 0;
 
     if (two_hits && (hit_saved || s_end_pos > last_hit + window_size )) {
-        /* this must be the 1st hit */
-        /* check to see if it can be extended to the right by
-           word_length and therefore qualifies for a double-hit */
-        if (contiguous) {
-            ext_right = s_BlastRightExtend(query, subject,
-                  q_off + word_length, s_end, query_info, word_length);
+        /* check the masks for the word; also check to see if this
+           first hit qualifies for a double-hit */
+        word_type = s_TypeOfWord(query, subject, &q_off, &s_off,
+                                 query_mask, query_info, s_range,
+                                 word_length, lut_word_length, lut, TRUE, &extended);
+        if (!word_type) return 0;
             /* update the right end*/
-            s_end += ext_right;
-            s_end_pos += ext_right;
-        }
+        s_end += extended;
+        s_end_pos += extended;
 
-        if (ext_right < word_length) {
+        /* for single word, also try off diagonals */
+        if (word_type == 1) {
             /* try off-diagonal */
             Int4 s_a = s_off_pos + word_length - window_size;
             Int4 s_b = s_end_pos - 2 * word_length;
             Int4 delta;
             if (Delta < 0) Delta = 0;
-            for (delta = 1; delta < Delta; ++delta) {
+            for (delta = 1; delta <= Delta; ++delta) {
                 Int4 off_s_end = 0;
                 Int4 off_s_l = 0;
                 Int4 off_hit_saved = 0;
@@ -610,7 +831,7 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query,
                   && off_s_l
                   && off_s_end - delta >= s_a
                   && off_s_end - off_s_l <= s_b) {
-                     found = TRUE;
+                     off_found = TRUE;
                      break;
                 }
                 off_rc = s_BlastDiagHashRetrieve(hash_table, diag - delta, 
@@ -619,15 +840,23 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query,
                   && off_s_l
                   && off_s_end >= s_a
                   && off_s_end - off_s_l + delta <= s_b) {
-                     found = TRUE;
+                     off_found = TRUE;
                      break;
                 }
             }
-            if (!found) {
+            if (!off_found) {
                 /* This is a new hit */
                 hit_ready = 0;
             }
         }
+    } else {
+        /* check the masks for the word */
+        if (!s_TypeOfWord(query, subject, &q_off, &s_off,
+                          query_mask, query_info, s_range,
+                          word_length, lut_word_length, lut, FALSE, &extended)) return 0;
+        /* update the right end*/
+        s_end += extended;
+        s_end_pos += extended;
     }
 
     if (hit_ready) {
@@ -641,7 +870,7 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query,
                                  ungapped_data,
                                  word_params->nucl_score_table,
                                  cutoffs->reduced_nucl_cutoff_score);
-            if (found || ungapped_data->score >= cutoffs->cutoff_score) {
+            if (off_found || ungapped_data->score >= cutoffs->cutoff_score) {
                 BlastUngappedData *final_data =
                     (BlastUngappedData *) malloc(sizeof(BlastUngappedData));
                 *final_data = *ungapped_data;
@@ -659,58 +888,11 @@ s_BlastnDiagHashExtendInitialHit(BLAST_SequenceBlk * query,
     
     s_BlastDiagHashInsert(hash_table, diag, s_end_pos, 
                           (hit_ready) ? 0 : s_end_pos - s_off_pos,
-                          hit_ready, s_off_pos, window_size + Delta);
+                          hit_ready, s_off_pos, window_size + Delta + 1);
 
     return hit_ready;
 }
 
-/** Check that word just found is not part of a soft-masked region.
- * This check only happens for soft masking for certain word sizes
- * @param locations not masked regions [in]
- * @param query query sequence [in]
- * @param subject subject sequence [in]
- * @param q_off query start [in]
- * @param word_length length of word [in]
- * @param s_end subject end (starting pos to extend) [in]
- * @param max_ext maxium possible right extension [in]
- */
-static Boolean 
-s_IsWordSeedMasked(BlastSeqLoc* locations, 
-                   BLAST_SequenceBlk * query,
-                   BLAST_SequenceBlk * subject,
-                   Uint4 q_off, 
-                   Uint4 word_length,
-                   Uint4 s_end,
-                   Uint4 max_ext)
-{
-    Int4 q_end = q_off + word_length;
-    while (locations) {
-       if (q_end-1 >= locations->ssr->left && q_end-1 <= locations->ssr->right) {
-          /* since we have exhausted left extension, this hit is hopeless */
-          return TRUE;
-       } 
-       if (q_off >= locations->ssr->left && q_off <= locations->ssr->right) {
-          /* determine the right boundary for extension*/
-          if (locations->next) {
-              max_ext = MIN (max_ext, locations->next->ssr->left - q_end);
-          } 
-          if (locations->ssr->right+1 - q_off > max_ext) {
-              /*  query range too short to contain a word  */
-              return TRUE;
-          }
-          /* try to extend to the right */
-          max_ext = locations->ssr->right+1 - q_off;
-          if (s_BlastRightExtend(query, subject, q_end, s_end, NULL, max_ext) < max_ext) {
-              return TRUE;
-          }
-          /* extension sucessful, (TODO should we update new q_off? )*/
-          return FALSE;
-       }
-       locations = locations->next;
-    }
-    return FALSE;
-}
-
 /** Perform ungapped extensions on the hits retrieved from
  * blastn/megablast lookup tables, skipping the mini-extension process
  * @param offset_pairs Array of query and subject offsets. [in]
@@ -725,7 +907,7 @@ s_IsWordSeedMasked(BlastSeqLoc* locations,
  *            extent of already processed hits on each diagonal [in]
  * @param init_hitlist Structure to keep the extended hits. 
  *                     Must be allocated outside of this function [in] [out]
- * @param range the subject range [in]
+ * @param s_range The subject range [in]
  * @return Number of hits extended. 
  */
 static Int4
@@ -737,20 +919,15 @@ s_BlastNaExtendDirect(const BlastOffsetPair * offset_pairs, Int4 num_hits,
                       BlastQueryInfo * query_info,
                       Blast_ExtendWord * ewp,
                       BlastInitHitList * init_hitlist,
-                      Int4 * range)
+                      Uint4 s_range)
 {
-    Int4 index;
+    Int4 index = 0;
     Int4 hits_extended = 0;
     Int4 word_length;
-    Boolean contiguous = TRUE;
 
     if (lookup_wrap->lut_type == eMBLookupTable) {
         BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut;
-        word_length = lut->word_length;
-        if (lut->discontiguous) {
-            word_length = lut->template_length;
-            contiguous = FALSE;
-        }
+        word_length = (lut->discontiguous) ? lut->template_length : lut->word_length;
         ASSERT(word_length == lut->lut_word_length || lut->discontiguous);
     } 
     else if (lookup_wrap->lut_type == eSmallNaLookupTable) {
@@ -764,30 +941,34 @@ s_BlastNaExtendDirect(const BlastOffsetPair * offset_pairs, Int4 num_hits,
     }
 
     if (word_params->container_type == eDiagHash) {
-        for (index = 0; index < num_hits; ++index) {
-            Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
-            Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
+        for (; index < num_hits; ++index) {
+            Int4 s_offset = offset_pairs[index].qs_offsets.s_off;
+            Int4 q_offset = offset_pairs[index].qs_offsets.q_off;
 
             hits_extended += s_BlastnDiagHashExtendInitialHit(query, subject, 
-                                                   contiguous, 
+                                                q_offset, s_offset,  
+                                                NULL,
+                                                query_info, s_range, 
+                                                word_length, word_length,
+                                                lookup_wrap,
                                                    word_params, matrix,
-                                                   query_info, ewp->hash_table,
-                                                   q_offset, 
-                                                   s_offset,  word_length,
+                                                ewp->hash_table,
                                                    init_hitlist);
         }
     } 
     else {
-        for (index = 0; index < num_hits; ++index) {
-            Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
-            Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
+        for (; index < num_hits; ++index) {
+            Int4 s_offset = offset_pairs[index].qs_offsets.s_off;
+            Int4 q_offset = offset_pairs[index].qs_offsets.q_off;
 
             hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, 
-                                                 contiguous,
+                                                q_offset, s_offset,  
+                                                NULL,
+                                                query_info, s_range, 
+                                                word_length, word_length,
+                                                lookup_wrap,
                                                  word_params, matrix, 
-                                                 query_info, ewp->diag_table, 
-                                                 q_offset,
-                                                 s_offset,  word_length,
+                                                ewp->diag_table,
                                                  init_hitlist);
         }
     }
@@ -810,7 +991,7 @@ s_BlastNaExtendDirect(const BlastOffsetPair * offset_pairs, Int4 num_hits,
  *            extent of already processed hits on each diagonal [in]
  * @param init_hitlist Structure to keep the extended hits. 
  *                     Must be allocated outside of this function [in] [out]
- * @param range The subject range
+ * @param s_range The subject range [in]
  * @return Number of hits extended. 
  */
 static Int4
@@ -822,20 +1003,12 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
                 BlastQueryInfo * query_info,
                 Blast_ExtendWord * ewp,
                 BlastInitHitList * init_hitlist,
-                Int4 * range)
+                Uint4 s_range)
 {
-    Int4 index;
-    Uint1 *q_start = query->sequence;
-    Uint1 *s_start = subject->sequence;
-    Uint4 word_length, lut_word_length;
-    Uint4 q_off, s_off;
-    Uint4 max_bases_left, max_bases_right;
-    Uint4 extended_left, extended_right;
-    Uint4 extra_bases;
-    Uint1 *q, *s;
+    Int4 index = 0;
     Int4 hits_extended = 0;
+    Int4 word_length, lut_word_length, ext_to;
     BlastSeqLoc* masked_locations = NULL;
-    Int4 max_ext;
 
     if (lookup_wrap->lut_type == eMBLookupTable) {
         BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut;
@@ -849,7 +1022,7 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
         lut_word_length = lut->lut_word_length;
         masked_locations = lut->masked_locations;
     }
-    extra_bases = word_length - lut_word_length;
+    ext_to = word_length - lut_word_length;
 
     /* We trust that the bases of the hit itself are exact matches, 
        and look only for exact matches before and after the hit.
@@ -861,24 +1034,20 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
        is critical to reduce as much as possible all work that is not the 
        actual examination of sequence data */
 
-    for (index = 0; index < num_hits; ++index) {
-        Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
-        Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
+    for (; index < num_hits; ++index) {
+        Int4 s_offset = offset_pairs[index].qs_offsets.s_off;
+        Int4 q_offset = offset_pairs[index].qs_offsets.q_off;
 
         /* begin with the left extension; the initialization is slightly
            faster. Point to the first base of the lookup table hit and
            work backwards */
 
-        Int4 context = BSearchContextInfo(q_offset, query_info);
-        Int4 context_i = query_info->contexts[context].query_offset;
-        Int4 context_f = context_i + query_info->contexts[context].query_length;
-        max_bases_left = MIN(extra_bases, MIN(q_offset - context_i, s_offset - range[0]));
-        q = q_start + q_offset;
-        s = s_start + s_offset / COMPRESSION_RATIO;
-        s_off = s_offset;
+        Int4 ext_left = 0;
+        Int4 s_off = s_offset;
+        Uint1 *q = query->sequence + q_offset;
+        Uint1 *s = subject->sequence + s_off / COMPRESSION_RATIO;
 
-        for (extended_left = 0; extended_left < max_bases_left;
-             extended_left++) {
+        for (; ext_left < MIN(ext_to, s_offset); ++ext_left) {
             s_off--;
             q--;
             if (s_off % COMPRESSION_RATIO == 3)
@@ -892,17 +1061,15 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
            the bases required. Begin at the first base beyond the lookup
            table hit and move forwards */
 
-        q_off = q_offset + lut_word_length;
+        if (ext_left < ext_to) {
+            Int4 ext_right = 0;
         s_off = s_offset + lut_word_length;
-        max_ext = MIN(context_f - q_off, range[1] - s_off);
-
-        if (extended_left < extra_bases) {
-            q = q_start + q_off;
-            s = s_start + s_off / COMPRESSION_RATIO;
-            max_bases_right = MIN(extra_bases - extended_left, max_ext);
+            if (s_off + ext_to - ext_left > s_range) 
+                continue;
+            q = query->sequence + q_offset + lut_word_length;
+            s = subject->sequence + s_off / COMPRESSION_RATIO;
 
-            for (extended_right = 0; extended_right < max_bases_right;
-                 extended_right++) {
+            for (; ext_right < ext_to - ext_left; ++ext_right) {
                 if (((Uint1) (*s << (2 * (s_off % COMPRESSION_RATIO))) >>
                      6) != *q)
                     break;
@@ -913,40 +1080,35 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
             }
 
             /* check if enough extra matches were found */
-
-            if (extended_left + extended_right < extra_bases)
-                continue;
-            max_ext -= extended_right;
-        }
-        
-        /* Check that the exact match was not masked out. */
-        if (word_length > lut_word_length && 
-            s_IsWordSeedMasked(masked_locations, query, subject, q_offset-extended_left,
-                               word_length, s_off, max_ext)) {
+            if (ext_left + ext_right < ext_to)
             continue; 
         }
 
+        q_offset -= ext_left;
+        s_offset -= ext_left;
         /* check the diagonal on which the hit lies. The boundaries
            extend from the first match of the hit to one beyond the last
            match */
 
         if (word_params->container_type == eDiagHash) {
             hits_extended += s_BlastnDiagHashExtendInitialHit(query, subject, 
-                                               TRUE,
+                                                q_offset, s_offset,  
+                                                masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
                                                word_params, matrix,
-                                               query_info, ewp->hash_table,
-                                               q_offset - extended_left,
-                                               s_offset - extended_left,
-                                               word_length,
+                                                ewp->hash_table,
                                                init_hitlist);
         } else {
             hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, 
-                                               TRUE,
-                                               word_params, matrix, query_info,
+                                                q_offset, s_offset,  
+                                                masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
+                                                word_params, matrix,
                                                ewp->diag_table,
-                                               q_offset - extended_left,
-                                               s_offset - extended_left,
-                                               word_length,
                                                init_hitlist);
         }
     }
@@ -969,7 +1131,7 @@ s_BlastNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
  *            extent of already processed hits on each diagonal [in]
  * @param init_hitlist Structure to keep the extended hits. 
  *                     Must be allocated outside of this function [in] [out]
- * @param range The subject range [in]
+ * @param s_range The subject range [in]
  * @return Number of hits extended. 
  */
 static Int4
@@ -980,20 +1142,12 @@ s_BlastNaExtendAligned(const BlastOffsetPair * offset_pairs, Int4 num_hits,
                        Int4 ** matrix, BlastQueryInfo * query_info,
                        Blast_ExtendWord * ewp,
                        BlastInitHitList * init_hitlist,
-                       Int4 * range)
+                       Uint4 s_range)
 {
-    Int4 index;
-    Uint1 *q_start = query->sequence;
-    Uint1 *s_start = subject->sequence;
-    Uint4 word_length, lut_word_length;
-    Uint4 q_off, s_off;
-    Uint4 max_bases_left, max_bases_right;
-    Uint4 extended_left, extended_right;
-    Uint4 extra_bases;
-    Uint1 *q, *s;
+    Int4 index = 0;
     Int4 hits_extended = 0;
+    Int4 word_length, lut_word_length, ext_to;
     BlastSeqLoc* masked_locations = NULL;
-    Int4 max_ext;
 
     if (lookup_wrap->lut_type == eMBLookupTable) {
         BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut;
@@ -1002,13 +1156,12 @@ s_BlastNaExtendAligned(const BlastOffsetPair * offset_pairs, Int4 num_hits,
         masked_locations = lut->masked_locations;
     } 
     else {
-        BlastNaLookupTable *lut = 
-                             (BlastNaLookupTable *) lookup_wrap->lut;
+        BlastNaLookupTable *lut = (BlastNaLookupTable *) lookup_wrap->lut;
         word_length = lut->word_length;
         lut_word_length = lut->lut_word_length;
         masked_locations = lut->masked_locations;
     }
-    extra_bases = word_length - lut_word_length;
+    ext_to = word_length - lut_word_length;
 
     /* We trust that the bases of the hit itself are exact matches, 
        and look only for exact matches before and after the hit.
@@ -1020,33 +1173,28 @@ s_BlastNaExtendAligned(const BlastOffsetPair * offset_pairs, Int4 num_hits,
        is critical to reduce as much as possible all work that is not the 
        actual examination of sequence data */
 
-    for (index = 0; index < num_hits; ++index) {
-        Uint4 s_offset = offset_pairs[index].qs_offsets.s_off;
-        Uint4 q_offset = offset_pairs[index].qs_offsets.q_off;
+    for (; index < num_hits; ++index) {
+        Int4 s_offset = offset_pairs[index].qs_offsets.s_off;
+        Int4 q_offset = offset_pairs[index].qs_offsets.q_off;
 
         /* begin with the left extension; the initialization is slightly
            faster. q below points to the first base of the lookup table hit
            and s points to the first four bases of the hit (which is
            guaranteed to be aligned on a byte boundary) */
 
-        Int4 context = BSearchContextInfo(q_offset, query_info);
-        Int4 context_i = query_info->contexts[context].query_offset;
-        Int4 context_f = context_i + query_info->contexts[context].query_length;
-        max_bases_left = MIN(extra_bases, MIN(q_offset - context_i, s_offset - range[0]));
-        q = q_start + q_offset;
-        s = s_start + s_offset / COMPRESSION_RATIO;
-
-        for (extended_left = 0; extended_left < max_bases_left;
-             s--, q -= 4, extended_left++) {
+        Int4 ext_left = 0;
+        Int4 ext_max = MIN(ext_to, s_offset);
+        Uint1 *q = query->sequence + q_offset;
+        Uint1 *s = subject->sequence + s_offset / COMPRESSION_RATIO;
+
+        for (; ext_left < ext_max; s--, q -= 4, ++ext_left) {
             Uint1 byte = s[-1];
 
-            if ((byte & 3) != q[-1] || ++extended_left == max_bases_left)
+            if ((byte & 3) != q[-1] || ++ext_left == ext_max)
                 break;
-            if (((byte >> 2) & 3) != q[-2]
-                || ++extended_left == max_bases_left)
+            if (((byte >> 2) & 3) != q[-2] || ++ext_left == ext_max)
                 break;
-            if (((byte >> 4) & 3) != q[-3]
-                || ++extended_left == max_bases_left)
+            if (((byte >> 4) & 3) != q[-3] || ++ext_left == ext_max)
                 break;
             if ((byte >> 6) != q[-4])
                 break;
@@ -1056,71 +1204,57 @@ s_BlastNaExtendAligned(const BlastOffsetPair * offset_pairs, Int4 num_hits,
            bases required. Begin at the first base past the lookup table hit 
            and move forwards */
 
-        s_off = s_offset + lut_word_length;
-        extended_right = 0;
-
-        if (extended_left < extra_bases) {
-            q_off = q_offset + lut_word_length;
-            q = q_start + q_off;
-            s = s_start + s_off / COMPRESSION_RATIO;
-            max_bases_right = MIN(extra_bases - extended_left,
-                                  MIN(context_f - q_off,
-                                      range[1]  - s_off));
-
-            for (; extended_right < max_bases_right;
-                 s++, q += 4, extended_right++) {
+        if (ext_left < ext_to) {
+            Int4 ext_right = 0;
+            ext_max = ext_to -ext_left;
+            if (s_offset + lut_word_length + ext_max > s_range) 
+                continue;
+            q = query->sequence + q_offset + lut_word_length;
+            s = subject->sequence + (s_offset + lut_word_length) / COMPRESSION_RATIO;
+
+            for (; ext_right < ext_max; s++, q += 4, ++ext_right) {
                 Uint1 byte = s[0];
 
-                if ((byte >> 6) != q[0]
-                    || ++extended_right == max_bases_right)
+                if ((byte >> 6) != q[0] || ++ext_right == ext_max)
                     break;
-                if (((byte >> 4) & 3) != q[1]
-                    || ++extended_right == max_bases_right)
+                if (((byte >> 4) & 3) != q[1] || ++ext_right == ext_max)
                     break;
-                if (((byte >> 2) & 3) != q[2]
-                    || ++extended_right == max_bases_right)
+                if (((byte >> 2) & 3) != q[2] || ++ext_right == ext_max)
                     break;
                 if ((byte & 3) != q[3])
                     break;
             }
 
             /* check if enough extra matches were found */
-
-            if (extended_left + extended_right < extra_bases)
+            if (ext_left + ext_right < ext_to)
                 continue;
         }
 
-        q_off = q_offset - extended_left;
-        s_off = s_offset - extended_left;
-        max_ext = MIN(context_f - q_off, range[1] - s_off) - word_length;
-        /* Check that the exact match was not masked out. */
-        if (word_length > lut_word_length && 
-            s_IsWordSeedMasked(masked_locations, query, subject, q_off,
-                               word_length, s_off + word_length, max_ext)) {
-            continue; 
-        }
+        q_offset -= ext_left;
+        s_offset -= ext_left;
 
         /* check the diagonal on which the hit lies. The boundaries extend
            from the first match of the hit to one beyond the last match */
 
         if (word_params->container_type == eDiagHash) {
             hits_extended += s_BlastnDiagHashExtendInitialHit(query, subject, 
-                                               TRUE,
-                                               word_params, matrix, query_info,
+                                                q_offset, s_offset,  
+                                                masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
+                                                word_params, matrix,
                                                ewp->hash_table,
-                                               q_off,
-                                               s_off,
-                                               word_length,
                                                init_hitlist);
         } else {
             hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, 
-                                               TRUE,
+                                                q_offset, s_offset,  
+                                                masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
                                                word_params, matrix,
-                                               query_info,
                                                ewp->diag_table,
-                                               q_off,
-                                               s_off,
-                                               word_length,
                                                init_hitlist);
         }
     }
@@ -1178,7 +1312,7 @@ static const Uint1 s_ExactMatchExtendRight[256] = {
  *            extent of already processed hits on each diagonal [in]
  * @param init_hitlist Structure to keep the extended hits. 
  *                     Must be allocated outside of this function [in] [out]
- * @param range The subject range
+ * @param s_range The subject range [in]
  * @return Number of hits extended. 
  */
 static Int4
@@ -1190,24 +1324,25 @@ s_BlastSmallNaExtendAlignedOneByte(const BlastOffsetPair * offset_pairs,
                        Int4 ** matrix, BlastQueryInfo * query_info,
                        Blast_ExtendWord * ewp,
                        BlastInitHitList * init_hitlist,
-                       Int4 * range)
+                       Uint4 s_range)
 {
+    Int4 index = 0;
+    Int4 hits_extended = 0;
     BlastSmallNaLookupTable *lut = (BlastSmallNaLookupTable *) lookup_wrap->lut;
-    Int4 i;
-    Int4 subject_length = subject->length;
+    Int4 word_length = lut->word_length;
+    Int4 lut_word_length = lut->lut_word_length;
+    Int4 ext_to = word_length - lut_word_length;
     Uint1 *q = query->compressed_nuc_seq;
     Uint1 *s = subject->sequence;
-    Int4 lut_word_length = lut->lut_word_length;
-    Int4 word_length = lut->word_length;
-    Int4 extra_bases = word_length - lut_word_length;
-    Int4 hits_extended = 0;
-    Int4 max_ext;
 
-    for (i = 0; i < num_hits; i++) {
-        Int4 s_off = offset_pairs[i].qs_offsets.s_off;
-        Int4 q_off = offset_pairs[i].qs_offsets.q_off;
-        Int4 extended_left = 0;
-        Int4 extended_right = 0;
+    for (; index < num_hits; ++index) {
+        Int4 s_offset = offset_pairs[index].qs_offsets.s_off;
+        Int4 q_offset = offset_pairs[index].qs_offsets.q_off;
+        Int4 ext_left = 0;
+
+        Int4 context = BSearchContextInfo(q_offset, query_info);
+        Int4 q_start = query_info->contexts[context].query_offset;
+        Int4 q_range = q_start + query_info->contexts[context].query_length;
 
         /* the seed is assumed to start on a multiple of 4 bases
            in the subject sequence. Look for up to 4 exact matches
@@ -1215,66 +1350,48 @@ s_BlastSmallNaExtendAlignedOneByte(const BlastOffsetPair * offset_pairs,
            technically be negative, but the compressed version
            of the query has extra pad bytes before q[0] */
 
-        Int4 context = BSearchContextInfo(q_off, query_info);
-        Int4 context_i = query_info->contexts[context].query_offset;
-        Int4 context_f = context_i + query_info->contexts[context].query_length;
-        if (q_off > context_i  && s_off > 0) {
-            Uint1 q_byte = q[q_off - 4];
-            Uint1 s_byte = s[s_off / COMPRESSION_RATIO - 1];
-            extended_left = s_ExactMatchExtendLeft[q_byte ^ s_byte];
-            extended_left = MIN(extended_left, extra_bases);
-            extended_left = MIN(extended_left, q_off - context_i);
+        if (s_offset > 0) {
+            Uint1 q_byte = q[q_offset - 4];
+            Uint1 s_byte = s[s_offset / COMPRESSION_RATIO - 1];
+            ext_left = s_ExactMatchExtendLeft[q_byte ^ s_byte];
+            ext_left = MIN(MIN(ext_left, ext_to), q_offset - q_start);
         }
 
         /* look for up to 4 exact matches to the right of the seed */
 
-        if (extended_left < extra_bases) {
-            Int4 q_end = q_off + lut_word_length;
-            Int4 s_end = s_off + lut_word_length;
-            Uint1 q_byte, s_byte;
-
-            if (q_end == context_f || s_end == subject_length)
-                continue;
-
-            q_byte = q[q_end];
-            s_byte = s[s_end / COMPRESSION_RATIO];
-            extended_right = s_ExactMatchExtendRight[q_byte ^ s_byte];
-            extended_right = MIN(extended_right, 
-                                 extra_bases - extended_left);
-            extended_right = MIN(extended_right, context_f - q_end);
-            extended_right = MIN(extended_right, subject_length - s_end);
-            if (extended_left + extended_right < extra_bases)
+        if (ext_left < ext_to) {
+            Uint1 q_byte = q[q_offset + lut_word_length];
+            Uint1 s_byte = s[(s_offset + lut_word_length) / COMPRESSION_RATIO];
+            Int4 ext_right = s_ExactMatchExtendRight[q_byte ^ s_byte];
+            ext_right = MIN(MIN(ext_right, s_range - (s_offset + lut_word_length)), 
+                                           q_range - (q_offset + lut_word_length));
+            if (ext_left + ext_right < ext_to)
                 continue;
         }
 
-        q_off -= extended_left;
-        s_off -= extended_left;
-        max_ext = MIN(context_f - q_off, subject_length - s_off) - word_length;
-        /* Check that the exact match was not masked out. */
-        if (word_length > lut_word_length && 
-            s_IsWordSeedMasked(lut->masked_locations, query, subject, q_off,
-                               word_length, s_off + word_length, max_ext)) {
-                continue; 
-        }
+        q_offset -= ext_left;
+        s_offset -= ext_left;
         
         if (word_params->container_type == eDiagHash) {
-            hits_extended += s_BlastnDiagHashExtendInitialHit(query, 
-                                           subject, TRUE,  word_params, 
-                                           matrix, query_info,
+            hits_extended += s_BlastnDiagHashExtendInitialHit(query, subject,
+                                                q_offset, s_offset,  
+                                                lut->masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
+                                                word_params, matrix,
                                            ewp->hash_table,
-                                           q_off,
-                                           s_off,
-                                           word_length,
                                            init_hitlist);
         }
         else {
-            hits_extended += s_BlastnDiagTableExtendInitialHit(query, 
-                                           subject, TRUE,  word_params, 
-                                           matrix, query_info,
+            hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, 
+                                                q_offset, s_offset,  
+                                                lut->masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
+                                                word_params, matrix,
                                            ewp->diag_table,
-                                           q_off,
-                                           s_off,
-                                           word_length,
                                            init_hitlist);
         }
     }
@@ -1298,7 +1415,7 @@ s_BlastSmallNaExtendAlignedOneByte(const BlastOffsetPair * offset_pairs,
  *            extent of already processed hits on each diagonal [in]
  * @param init_hitlist Structure to keep the extended hits. 
  *                     Must be allocated outside of this function [in] [out]
- * @param range The subject range [in]
+ * @param s_range The subject range [in]
  * @return Number of hits extended. 
  */
 static Int4
@@ -1310,33 +1427,27 @@ s_BlastSmallNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
                      BlastQueryInfo * query_info,
                      Blast_ExtendWord * ewp,
                      BlastInitHitList * init_hitlist,
-                     Int4 * range)
+                     Uint4 s_range)
 {
+    Int4 index = 0;
+    Int4 hits_extended = 0;
     BlastSmallNaLookupTable *lut = (BlastSmallNaLookupTable *) lookup_wrap->lut;
-    Int4 i;
-    Uint1 *q = query->compressed_nuc_seq;
-    Uint1 *s = subject->sequence;
     Int4 word_length = lut->word_length; 
     Int4 lut_word_length = lut->lut_word_length; 
-    Int4 hits_extended = 0;
-    Int4 max_ext;
-
-    for (i = 0; i < num_hits; i++) {
-        Int4 s_off = offset_pairs[i].qs_offsets.s_off;
-        Int4 q_off = offset_pairs[i].qs_offsets.q_off;
-
-        Int4 context = BSearchContextInfo(q_off, query_info);
-        Int4 context_i = query_info->contexts[context].query_offset;
-        Int4 context_f = context_i + query_info->contexts[context].query_length;
-
-        Int4 s_start;
-        Int4 q_start;
-        Int4 extended_left = 0;
-        Int4 extended_right = 0;
-        Int4 extra_bases = COMPRESSION_RATIO - (s_off % COMPRESSION_RATIO);
+    Uint1 *q = query->compressed_nuc_seq;
+    Uint1 *s = subject->sequence;
 
-        s_off += extra_bases;
-        q_off += extra_bases;
+    for (; index < num_hits; ++index) {
+        Int4 s_offset = offset_pairs[index].qs_offsets.s_off;
+        Int4 q_offset = offset_pairs[index].qs_offsets.q_off;
+        Int4 s_off;
+        Int4 q_off;
+        Int4 ext_left = 0;
+        Int4 ext_right = 0;
+        Int4 context = BSearchContextInfo(q_offset, query_info);
+        Int4 q_start = query_info->contexts[context].query_offset;
+        Int4 q_range = q_start + query_info->contexts[context].query_length;
+        Int4 ext_max = MIN(MIN(word_length - lut_word_length, s_offset), q_offset - q_start);
 
         /* Start the extension at the first multiple of 4 bases in
            the subject sequence to the right of the seed.
@@ -1346,71 +1457,69 @@ s_BlastSmallNaExtend(const BlastOffsetPair * offset_pairs, Int4 num_hits,
            technically be negative, but the compressed version
            of the query has extra pad bytes before q[0] */
 
-        extra_bases = MIN(word_length - lut_word_length + extra_bases, 
-                          MIN(q_off - context_i, s_off - range[0]));
-        s_start = s_off;
-        q_start = q_off;
-        while (extended_left < extra_bases) {
-            Uint1 q_byte = q[q_start - 4];
-            Uint1 s_byte = s[s_start / COMPRESSION_RATIO - 1];
+        Int4 rsdl = COMPRESSION_RATIO - (s_offset % COMPRESSION_RATIO);
+        s_offset += rsdl;
+        q_offset += rsdl;
+        ext_max  += rsdl;
+
+        s_off = s_offset;
+        q_off = q_offset;
+
+        while (ext_left < ext_max) {
+            Uint1 q_byte = q[q_off - 4];
+            Uint1 s_byte = s[s_off / COMPRESSION_RATIO - 1];
             Uint1 bases = s_ExactMatchExtendLeft[q_byte ^ s_byte];
-            extended_left += bases;
+            ext_left += bases;
             if (bases < 4)
                 break;
-            q_start -= 4;
-            s_start -= 4;
+            q_off -= 4;
+            s_off -= 4;
         }
-        extended_left = MIN(extended_left, extra_bases);
+        ext_left = MIN(ext_left, ext_max);
 
         /* extend to the right. The extension begins at the first
            base not examined by the left extension */
 
-        extra_bases = word_length - extended_left;
-        extra_bases = MIN(extra_bases, context_f - q_off);
-        extra_bases = MIN(extra_bases, range[1] - s_off);
-        s_start = s_off;
-        q_start = q_off;
-        while (extended_right < extra_bases) {
-            Uint1 q_byte = q[q_start];
-            Uint1 s_byte = s[s_start / COMPRESSION_RATIO];
+        s_off = s_offset;
+        q_off = q_offset;
+        ext_max = MIN(MIN(word_length - ext_left, s_range - s_off), q_range - q_off);
+        while (ext_right < ext_max) {
+            Uint1 q_byte = q[q_off];
+            Uint1 s_byte = s[s_off / COMPRESSION_RATIO];
             Uint1 bases = s_ExactMatchExtendRight[q_byte ^ s_byte];
-            extended_right += bases;
+            ext_right += bases;
             if (bases < 4)
                 break;
-            q_start += 4;
-            s_start += 4;
+            q_off += 4;
+            s_off += 4;
         }
-        extended_right = MIN(extended_right, extra_bases);
-
-        if (extended_left + extended_right < word_length)
-            continue;
+        ext_right = MIN(ext_right, ext_max);
 
-        q_off -= extended_left;
-        s_off -= extended_left;
-        max_ext = MIN(context_f - q_off, range[1] - s_off) - word_length;
-        /* Check that the exact match was not masked out. */
-        if (word_length > lut_word_length && 
-            s_IsWordSeedMasked(lut->masked_locations, query, subject, q_off,
-                               word_length, s_off + word_length, max_ext)) {
+        if (ext_left + ext_right < word_length)
             continue; 
-        }
         
+        q_offset -= ext_left;
+        s_offset -= ext_left;
 
         if (word_params->container_type == eDiagHash) {
             hits_extended += s_BlastnDiagHashExtendInitialHit(query, subject, 
-                                               TRUE, word_params, matrix,
-                                               query_info, ewp->hash_table,
-                                               q_off,
-                                               s_off,
-                                               word_length,
+                                                q_offset, s_offset,  
+                                                lut->masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
+                                                word_params, matrix,
+                                                ewp->hash_table,
                                                init_hitlist);
         } else {
             hits_extended += s_BlastnDiagTableExtendInitialHit(query, subject, 
-                                               TRUE, word_params, matrix,
-                                               query_info, ewp->diag_table,
-                                               q_off,
-                                               s_off,
-                                               word_length,
+                                                q_offset, s_offset,  
+                                                lut->masked_locations, 
+                                                query_info, s_range, 
+                                                word_length, lut_word_length,
+                                                lookup_wrap,
+                                                word_params, matrix,
+                                                ewp->diag_table,
                                                init_hitlist);
         }
     }
@@ -1435,7 +1544,7 @@ Int2 BlastNaWordFinder(BLAST_SequenceBlk * subject,
     Int4 hits_extended = 0;
     TNaScanSubjectFunction scansub = NULL;
     TNaExtendFunction extend = NULL;
-    Int4 scan_range[5];
+    Int4 scan_range[3];
     Int4 word_length;
     Int4 lut_word_length;
 
@@ -1471,42 +1580,36 @@ Int2 BlastNaWordFinder(BLAST_SequenceBlk * subject,
 
     scan_range[0] = 0;  /* subject seq mask index */
     scan_range[1] = 0;	/* start pos of scan */
-    scan_range[2] = subject->length - lut_word_length; /*end pos of scan*/
-    scan_range[3] = 0;  /* current subject seq range start */
-    scan_range[4] = subject->length;  /* current subject seq range end */
+    scan_range[2] = subject->length - lut_word_length; /*end pos (inclusive) of scan*/
 
     /* if sequence is masked, fall back to generic scanner and extender */
-    if (subject->num_seq_ranges) {
+    if (subject->mask_type) {
         scansub = (TNaScanSubjectFunction) 
                   BlastChooseNucleotideScanSubjectAny(lookup_wrap);
-        if (extend != s_BlastNaExtendDirect) {
+        if (extend != (TNaExtendFunction)s_BlastNaExtendDirect) {
              extend = (lookup_wrap->lut_type == eSmallNaLookupTable) 
-                    ? s_BlastSmallNaExtend
-                    : s_BlastNaExtend;
+                    ? (TNaExtendFunction)s_BlastSmallNaExtend
+                    : (TNaExtendFunction)s_BlastNaExtend;
         }
-        scan_range[1] = word_length - lut_word_length;
-        scan_range[2] = subject->length - word_length; 
+        /* generic scanner permits any (non-aligned) starting offset */
+        scan_range[1] = subject->seq_ranges[0].left + word_length - lut_word_length;
+        scan_range[2] = subject->seq_ranges[0].right - lut_word_length;
     }
 
     ASSERT(scansub);
     ASSERT(extend);
 
     while(s_DetermineScanningOffsets(subject, word_length, lut_word_length, scan_range)) {
-        Int4 next_start;
 
-        /* Pass the last word ending offset */
-        next_start = scan_range[2];
+        hitsfound = scansub(lookup_wrap, subject, offset_pairs, max_hits, &scan_range[1]);
 
-        hitsfound = scansub(lookup_wrap, subject, scan_range[1], 
-                            offset_pairs, max_hits, &next_start);
-        scan_range[1] = next_start;
         if (hitsfound == 0)
             continue;
 
         total_hits += hitsfound;
         hits_extended += extend(offset_pairs, hitsfound, word_params,
                                 lookup_wrap, query, subject, matrix, 
-                                query_info, ewp, init_hitlist, &scan_range[3]);
+                                query_info, ewp, init_hitlist, scan_range[2] + lut_word_length);
     }
 
     Blast_ExtendWordExit(ewp, subject->length);
@@ -1604,7 +1707,9 @@ Int2 MB_IndexedWordFinder(
 void BlastChooseNaExtend(LookupTableWrap * lookup_wrap)
 {
     if (lookup_wrap->lut_type == eMBLookupTable) {
-        BlastMBLookupTable *lut = (BlastMBLookupTable *) lookup_wrap->lut;
+        BlastMBLookupTable *lut;
+        lookup_wrap->lookup_callback = (void *)s_MBLookup;
+        lut = (BlastMBLookupTable *) lookup_wrap->lut;
 
         if (lut->lut_word_length == lut->word_length || lut->discontiguous)
             lut->extend_callback = (void *)s_BlastNaExtendDirect;
@@ -1615,8 +1720,9 @@ void BlastChooseNaExtend(LookupTableWrap * lookup_wrap)
             lut->extend_callback = (void *)s_BlastNaExtend;
     } 
     else if (lookup_wrap->lut_type == eSmallNaLookupTable) {
-        BlastSmallNaLookupTable *lut = 
-                             (BlastSmallNaLookupTable *) lookup_wrap->lut;
+        BlastSmallNaLookupTable *lut;
+        lookup_wrap->lookup_callback = (void *)s_SmallNaLookup;
+        lut = (BlastSmallNaLookupTable *) lookup_wrap->lut;
 
         if (lut->lut_word_length == lut->word_length)
             lut->extend_callback = (void *)s_BlastNaExtendDirect;
@@ -1628,7 +1734,9 @@ void BlastChooseNaExtend(LookupTableWrap * lookup_wrap)
             lut->extend_callback = (void *)s_BlastSmallNaExtend;
     }
     else {
-        BlastNaLookupTable *lut = (BlastNaLookupTable *) lookup_wrap->lut;
+        BlastNaLookupTable *lut;
+        lookup_wrap->lookup_callback = (void *)s_NaLookup;
+        lut = (BlastNaLookupTable *) lookup_wrap->lut;
 
         if (lut->lut_word_length == lut->word_length)
             lut->extend_callback = (void *)s_BlastNaExtendDirect;
diff --git a/algo/blast/core/na_ungapped.h b/algo/blast/core/na_ungapped.h
index e4c04cf..afc6b1e 100644
--- a/algo/blast/core/na_ungapped.h
+++ b/algo/blast/core/na_ungapped.h
@@ -1,4 +1,4 @@
-/* $Id: na_ungapped.h,v 1.5 2009/05/27 17:39:36 kazimird Exp $
+/* $Id: na_ungapped.h,v 1.6 2009/10/02 15:21:51 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -56,7 +56,7 @@ typedef Int4 (*TNaExtendFunction)(const BlastOffsetPair* offset_pairs,
                     Int4** matrix, BlastQueryInfo* query_info,
                     Blast_ExtendWord* ewp, 
                     BlastInitHitList* init_hitlist,
-                    Int4 * range);
+                    Int4 range);
 
 /** Find all words for a given subject sequence and perform 
  * ungapped extensions, assuming ordinary blastn.
diff --git a/algo/blast/core/split_query.c b/algo/blast/core/split_query.c
index 317da33..98776cc 100644
--- a/algo/blast/core/split_query.c
+++ b/algo/blast/core/split_query.c
@@ -1,4 +1,4 @@
-/*  $Id: split_query.c,v 1.1 2007/03/12 19:55:42 kazimird Exp $
+/*  $Id: split_query.c,v 1.2 2010/06/25 17:14:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -32,7 +32,7 @@
 
 #ifndef SKIP_DOXYGEN_PROCESSING
 static char const rcsid[] = 
-    "$Id: split_query.c,v 1.1 2007/03/12 19:55:42 kazimird Exp $";
+    "$Id: split_query.c,v 1.2 2010/06/25 17:14:31 kazimird Exp $";
 #endif /* SKIP_DOXYGEN_PROCESSING */
 
 #include <algo/blast/core/split_query.h>
@@ -44,7 +44,7 @@ const Int2 kOutOfMemory = -2;
 const Int4 kInvalidContext = -1;
 
 SSplitQueryBlk* 
-SplitQueryBlkNew(Uint4 num_chunks)
+SplitQueryBlkNew(Uint4 num_chunks, Boolean gapped_merge)
 {
     SSplitQueryBlk* retval = NULL;
 
@@ -57,6 +57,7 @@ SplitQueryBlkNew(Uint4 num_chunks)
         return SplitQueryBlkFree(retval);
     }
     retval->num_chunks = num_chunks;
+    retval->gapped_merge = gapped_merge;
 
     retval->chunk_query_map = 
         (SQueriesPerChunk**) calloc(num_chunks, sizeof(SQueriesPerChunk*));
@@ -155,6 +156,12 @@ SplitQueryBlkFree(SSplitQueryBlk* squery_blk)
     return NULL;
 }
 
+Boolean SplitQueryBlk_AllowGap(SSplitQueryBlk* squery_blk) 
+{
+    if ( squery_blk && squery_blk->gapped_merge) return TRUE;
+    return FALSE;
+}
+
 Int2 SplitQueryBlk_SetChunkBounds(SSplitQueryBlk* squery_blk,
                                   Uint4 chunk_num,
                                   Uint4 starting_offset,
diff --git a/algo/blast/core/split_query.h b/algo/blast/core/split_query.h
index 9583881..cfbbc35 100644
--- a/algo/blast/core/split_query.h
+++ b/algo/blast/core/split_query.h
@@ -1,7 +1,7 @@
 #ifndef ALGO_BLAST_CORE__SPLIT_QUERY_H
 #define ALGO_BLAST_CORE__SPLIT_QUERY_H
 
-/*  $Id: split_query.h,v 1.3 2009/04/06 20:19:30 kazimird Exp $
+/*  $Id: split_query.h,v 1.4 2010/06/25 17:14:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -65,6 +65,7 @@ typedef struct SSplitQueryBlk {
     SQueryChunkBoundary* chunk_bounds;  /**< This chunk's boundaries */
     size_t chunk_overlap_sz;            /**< Size (# of bases/residues) of
                                           overlap between query chunks */
+    Boolean gapped_merge;   /**< Allows merging HSPs with gap */
 } SSplitQueryBlk;
 
 /** Allocate a new split query chunk structure
@@ -73,7 +74,7 @@ typedef struct SSplitQueryBlk {
  * failure
  */
 NCBI_XBLAST_EXPORT
-SSplitQueryBlk* SplitQueryBlkNew(Uint4 num_chunks);
+SSplitQueryBlk* SplitQueryBlkNew(Uint4 num_chunks, Boolean gapped_merge);
 
 /** Deallocate a split query chunk structure
  * @param squery_blk structure to deallocate [in]
diff --git a/api/aceread.c b/api/aceread.c
index 285d9b6..045acca 100644
--- a/api/aceread.c
+++ b/api/aceread.c
@@ -1,5 +1,5 @@
 /*
- * $Id: aceread.c,v 1.16 2008/12/22 22:40:30 bollin Exp $
+ * $Id: aceread.c,v 1.19 2010/05/26 15:13:01 bollin Exp $
  *
  * ===========================================================================
  *
@@ -755,7 +755,7 @@ extern void ACEFileFree (TACEFilePtr afp)
 
 static char s_IsSeqChar (char ch)
 {
-    if (ch == '*' || isalpha (ch)) {
+    if (ch == '*' || ch == '-' || isalpha (ch)) {
         return 1;
     } else {
         return 0;
@@ -795,6 +795,8 @@ s_ReadSequenceFromFile
         while (s_IsSeqChar (*cp) && pos < len) {
             if (isalpha (*cp)) {
                 seq [pos] = toupper (*cp);
+            } else if (*cp == '-') {
+                seq [pos] = '*';
             } else {
                 seq [pos] = *cp;
             }
@@ -995,19 +997,19 @@ static EFound s_ReadAFLines
 static EFound s_ReadBaseSegs
 (TContigPtr           contig,
  int                  num_base_segs,
- char *               firstline,
+ char **              firstline,
  FReadLineFunction    readfunc,
  void *               userdata)
 {
     char * linestring;
 
-    if (contig == NULL || readfunc == NULL || num_base_segs == 0) return eNone;
+    if (contig == NULL || readfunc == NULL || num_base_segs == 0 || firstline == NULL) return eNone;
 
     contig->base_segs = malloc (sizeof (TBaseSegPtr) * num_base_segs);
     contig->num_base_segs = 0;
 
     /* get BS lines */
-    linestring = firstline;
+    linestring = *firstline;
     while (s_LineIsEmptyButNotEof (linestring)) {
         free (linestring);
         linestring = readfunc (userdata);
@@ -1022,9 +1024,10 @@ static EFound s_ReadBaseSegs
         free (linestring);
         linestring = readfunc (userdata);
     }
+    *firstline = linestring;
     if (contig->num_base_segs < num_base_segs) {
         return eTooFew;
-    } else if (linestring != NULL && linestring [0] != EOF && ! s_LineIsEmptyButNotEof (linestring)) {
+    } else if (linestring != NULL && linestring [0] == 'B' && linestring[1] == 'S') {
         return eTooMany;
     } else {
         return eJustRight;
@@ -1260,9 +1263,15 @@ static char * s_AddToTagComment (char *orig, char *extra)
 }
 
 
+typedef enum {
+    eTagCommentStatus_ok = 0,
+    eTagCommentStatus_runon
+} ETagCommentStatus;
+
 static char * s_ReadTagComment
 (FReadLineFunction    readfunc,
- void *               userdata)
+ void *               userdata,
+ ETagCommentStatus    *comment_status)
 {
     char *linestring;
     char *tag = NULL;
@@ -1286,6 +1295,11 @@ static char * s_ReadTagComment
             tag = tmp;
         }
         free (linestring);
+        if (tag_len > 1000) {
+           *comment_status = eTagCommentStatus_runon;
+           free (tag);
+           return NULL;
+        }
         linestring = readfunc (userdata);
     }
     if (cp != NULL && cp > linestring) {
@@ -1318,10 +1332,11 @@ static TContigPtr s_ReadContig
     char      *linestring;
     char      *firstline;
     char      *cp;
-    int        len = 0, read_num = 0, num_base_segs = 0;
+    int        len = 0, read_num = 0, num_base_segs = 0, report_read_num = 0;
     EFound     val;
     char       found_comp_char = 0;
     TContigPtr contig = NULL;
+    ETagCommentStatus comment_status = eTagCommentStatus_ok;
 
     if (initline == NULL) return NULL;
     firstline = *initline;
@@ -1412,7 +1427,7 @@ static TContigPtr s_ReadContig
     }
  
     if (num_base_segs > 0) {
-        val = s_ReadBaseSegs (contig, num_base_segs, linestring, readfunc, userdata);
+        val = s_ReadBaseSegs (contig, num_base_segs, &linestring, readfunc, userdata);
         if (val != eJustRight) {
             s_ReportFound (val, "base segments", contig->consensus_id, has_errors);
             ContigFree (contig);
@@ -1422,7 +1437,6 @@ static TContigPtr s_ReadContig
 
     
     read_num = 0;
-    linestring = readfunc (userdata);
     while (linestring != NULL  &&  linestring [0] != EOF) {
         if (linestring [0] == 'R' && linestring[1] == 'D' && isspace (linestring [2])) {
             len = strlen (contig->reads[read_num]->read_id);
@@ -1442,26 +1456,27 @@ static TContigPtr s_ReadContig
             contig->reads[read_num]->read_len = s_GetUngappedSeqLen (contig->reads[read_num]->read_seq, "*");
             contig->reads[read_num]->gaps = GapInfoFromSequenceString (contig->reads[read_num]->read_seq, "*");
             read_num++;
+            report_read_num = read_num - 1;
         } else if (linestring [0] == 'Q' && linestring[1] == 'A' && isspace (linestring[2])) {
             if (read_num < 1) {
                 PrintACEFormatErrorXML ("Found QA line before RD!", contig->consensus_id, has_errors);
                 ContigFree (contig);
                 return NULL;
-            } else if (!ApplyQALineToRead (contig->reads[read_num - 1], linestring, contig->reads[read_num - 1]->read_id, has_errors)) {
-                PrintACEFormatErrorXML ("Error in QA line format!", contig->reads[read_num - 1]->read_id, has_errors);
+            } else if (!ApplyQALineToRead (contig->reads[report_read_num], linestring, contig->reads[report_read_num]->read_id, has_errors)) {
+                PrintACEFormatErrorXML ("Error in QA line format!", contig->reads[report_read_num]->read_id, has_errors);
                 ContigFree (contig);
                 return NULL;
             }
-        } else if (linestring[0] == 'D' && linestring[1] == 'S' && isspace (linestring[2])) {
+        } else if (linestring[0] == 'D' && linestring[1] == 'S' && (isspace (linestring[2]) || linestring[2] == 0)) {
             /* skip DS lines */
         } else if (strncmp (linestring, "RT{", 3) == 0) {
-            contig->reads[read_num - 1]->tag = s_AddToTagComment (contig->reads[read_num - 1]->tag, s_ReadTagComment (readfunc, userdata));
+            contig->reads[read_num - 1]->tag = s_AddToTagComment (contig->reads[report_read_num]->tag, s_ReadTagComment (readfunc, userdata, &comment_status));
         } else if (strncmp (linestring, "WR{", 3) == 0) {
-            contig->reads[read_num - 1]->tag = s_AddToTagComment (contig->reads[read_num - 1]->tag, s_ReadTagComment (readfunc, userdata));
+            contig->reads[read_num - 1]->tag = s_AddToTagComment (contig->reads[report_read_num]->tag, s_ReadTagComment (readfunc, userdata, &comment_status));
         } else if (strncmp (linestring, "CT{", 3) == 0) {
-            contig->tag = s_AddToTagComment (contig->tag, s_ReadTagComment (readfunc, userdata));
+            contig->tag = s_AddToTagComment (contig->tag, s_ReadTagComment (readfunc, userdata, &comment_status));
         } else if (strncmp (linestring, "WA{", 3) == 0) {
-            contig->tag = s_AddToTagComment (contig->tag, s_ReadTagComment (readfunc, userdata));
+            contig->tag = s_AddToTagComment (contig->tag, s_ReadTagComment (readfunc, userdata, &comment_status));
         } else if (linestring[0] != 0) {
             /* found next line */
             *initline = linestring;
@@ -1470,6 +1485,12 @@ static TContigPtr s_ReadContig
             return contig;
         }
         free (linestring);
+        if (comment_status == eTagCommentStatus_runon) {
+            PrintACEFormatErrorXML ("Error in CT line - comment tag is unusally long, suspect missing terminating }", contig->reads[report_read_num]->read_id, has_errors);
+            ContigFree (contig);
+            return NULL;
+        }
+
         linestring = readfunc (userdata);
     }
     *initline = NULL;
diff --git a/api/aceread.h b/api/aceread.h
index a4f1177..982a304 100644
--- a/api/aceread.h
+++ b/api/aceread.h
@@ -2,7 +2,7 @@
 #define API_ACEREAD__H
 
 /*
- * $Id: aceread.h,v 1.12 2008/12/02 18:58:24 bollin Exp $
+ * $Id: aceread.h,v 1.13 2010/03/03 18:46:08 bollin Exp $
  *
  * ===========================================================================
  *
@@ -143,7 +143,7 @@ extern TContigPtr ContigNew (void);
 extern void ContigFree (TContigPtr c);
    
 typedef struct SACEFile {
-    int        num_contigs;
+    unsigned int num_contigs;
     TContigPtr * contigs;
 } SACEFile, * TACEFilePtr;
 
@@ -291,6 +291,9 @@ ProcessLargeACEFileForContigFastaAndQualScores
  * ==========================================================================
  *
  * $Log: aceread.h,v $
+ * Revision 1.13  2010/03/03 18:46:08  bollin
+ * use unsigned int to keep track of the number of contigs.
+ *
  * Revision 1.12  2008/12/02 18:58:24  bollin
  * Added argument to WriteTraceAssemblyHeader for assembly type.
  *
diff --git a/api/alignmgr2.h b/api/alignmgr2.h
index 2bd1dd3..227fe9b 100644
--- a/api/alignmgr2.h
+++ b/api/alignmgr2.h
@@ -28,13 +28,16 @@
 *
 * Version Creation Date:  10/01 
 *
-* $Revision: 6.21 $
+* $Revision: 6.22 $
 *
 * File Description: SeqAlign indexing, access, and manipulation functions
 *
 * Modifications:
 * --------------------------------------------------------------------------
 * $Log: alignmgr2.h,v $
+* Revision 6.22  2010/04/22 11:15:13  bollin
+* Increased number of possible protein residues.
+*
 * Revision 6.21  2003/10/09 13:46:39  rsmith
 * Add AlnMgr2GetFirstNForSipList.
 *
@@ -124,7 +127,7 @@ extern "C" {
 
 /* defines for frequency matrix sizes */
 #define AM_NUCSIZE   6
-#define AM_PROTSIZE  26
+#define AM_PROTSIZE  30
 
 /* max seqport window */
 #define AM_SEQPORTSIZE 20000
diff --git a/api/alignval.c b/api/alignval.c
index 522fc50..e602baa 100644
--- a/api/alignval.c
+++ b/api/alignval.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   6/3/99
 *
-* $Revision: 6.72 $
+* $Revision: 6.77 $
 *
 * File Description:  To validate sequence alignment.
 *
@@ -205,8 +205,11 @@ static Int4 valmsggetseqpos(SeqAlignPtr sap, Int4 segment, SeqIdPtr sip)
    SeqLocPtr     slp;
    StdSegPtr     ssp;
 
-   if (sap == NULL || sap->segs == NULL || segment == 0)
+   if (sap == NULL || sap->segs == NULL) {
       return -1;
+   } else if (segment == 0) {
+      return 0;
+   }
    if (sap->segtype == SAS_DENSEG)
    {
       dsp = (DenseSegPtr)sap->segs;
@@ -503,8 +506,10 @@ static void ValMessage (SeqAlignPtr salp, Int1 MessageCode, ErrSev errlevel, Seq
       break;
 
     case Err_Segtype :
+      /* ignore new segtype warnings in genomic gpipe sequence */
+      if (useValErr && useVsp != NULL && useVsp->is_gpipe_in_sep && useVsp->bsp_genomic_in_sep) return;
       sprintf(string1, "Segs");
-      sprintf(string2, "This alignment has a undefined or unsupported Seqalign segtype %ld", (long) Intvalue);
+      sprintf(string2, "This alignment has an undefined or unsupported Seqalign segtype %ld", (long) Intvalue);
       break;
       
     case Err_Pcnt_ID :
@@ -1826,7 +1831,7 @@ static Boolean IsAlignmentTPA (SeqAlignPtr salp)
 {
   Boolean isTPA = FALSE;
   BioseqPtr bsp;
-  SeqIdPtr  sip, tmp_sip;
+  SeqIdPtr  sip = NULL, tmp_sip;
   SeqEntryPtr oldscope;
   DenseDiagPtr ddp;
   StdSegPtr    ssp;
@@ -2269,7 +2274,7 @@ static void PopulateSample (Uint1Ptr seqbuf_list, Int4Ptr start_list,
                     start_list[row], 
                     MIN (start_list[row] + sample_len - 1, bsp_list[row]->length - 1), 
                     Seq_strand_plus,
-                    0,
+                    STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL,
                     seqbuf_list + row * sample_len,
                     NULL);
 
@@ -2535,6 +2540,7 @@ static Uint2 AlignmentPercentIdentityEx (SeqAlignPtr salp, Boolean internal_gaps
   Uint1Ptr       seqbuf_list;
   Int4           sample_len = 50;
   Int4Ptr        starts, stops;
+  Int4           match_25 = 0;
   
   if (salp == NULL) return 0;
  
@@ -2631,11 +2637,18 @@ static Uint2 AlignmentPercentIdentityEx (SeqAlignPtr salp, Boolean internal_gaps
           }
         }
       }
+      if (!row_match) {
+        break;
+      }
     }
     if (row_match) {
       num_match++;
+      match_25++;
     }
     col_count++;
+    if (col_count % 25 == 0) {
+      match_25 = 0;
+    }
   }
   
   for (row = 0; row < num_rows; row++) {
diff --git a/api/asn2gnb1.c b/api/asn2gnb1.c
index d187dbb..2b03644 100644
--- a/api/asn2gnb1.c
+++ b/api/asn2gnb1.c
@@ -31,7 +31,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 1.179 $
+* $Revision: 1.198 $
 *
 * File Description:  New GenBank flatfile generator - work in progress
 *
@@ -867,6 +867,7 @@ NLM_EXTERN CharPtr FFToCharPtr (StringItemPtr sip) {
 
 static CharPtr url_anchor_strings [] = {
   "</A>",
+ "</ACRONYM>",
   "<A HREF=/",
   "<A HREF=\"/",
   "<A HREF=FTP://",
@@ -875,6 +876,7 @@ static CharPtr url_anchor_strings [] = {
   "<A HREF=HTTPS://",
   "<A HREF=\"HTTP://",
   "<A HREF=\"HTTPS://",
+  "<ACRONYM TITLE=\"",
   NULL
 };
 
@@ -1132,7 +1134,8 @@ NLM_EXTERN void FFCalculateLineBreak (
   Int4 i,
        done = FALSE,
        copied = 0, 
-       start = *break_pos;
+       start = *break_pos,
+       pos = 0;
   Char ch;
   Boolean found_comma = FALSE, found_dash = FALSE, found_lb = FALSE;
   /* each candidate is a pair of buffer and position withingh this buffer */
@@ -1177,7 +1180,7 @@ NLM_EXTERN void FFCalculateLineBreak (
   start = i;
 
   while ( iter != NULL && !done ) {
-    for ( i = start; i < iter->pos; ++i ) {
+    for ( i = start; iter != NULL && i < iter->pos; ++i ) {
       if ( found_comma ) {
         candidate_sip_comma = iter;
         candidate_int_comma = i;
@@ -1226,8 +1229,9 @@ NLM_EXTERN void FFCalculateLineBreak (
       }      
     }
     start = 0;
-    if ( !done ) {
+    if ( iter != NULL && !done ) {
       prev = iter;
+      pos = prev->pos;
       iter = iter->next;
     }
   }
@@ -1235,7 +1239,7 @@ NLM_EXTERN void FFCalculateLineBreak (
   /* the order in which we examine the various candidate breaks is important */
   if ( iter == NULL && !done) { /* reached the end */
     *break_sip = prev;
-    *break_pos = prev->pos;
+    *break_pos = pos;
   } else {
     if( candidate_sip_space != NULL ) {
         *break_sip = candidate_sip_space;
@@ -2168,6 +2172,7 @@ NLM_EXTERN void DoOneSection (
   SeqMgrBioseqContext  bcontext;
   BlockMask            bkmask;
   BaseBlockPtr         PNTR blockArray;
+  Boolean              cagemaster = FALSE;
   SeqMgrDescContext    dcontext;
   Boolean              hasRefs;
   Int4                 i;
@@ -2184,6 +2189,7 @@ NLM_EXTERN void DoOneSection (
   ValNodePtr           vnp;
   Boolean              wgsmaster = FALSE;
   Boolean              wgstech = FALSE;
+  Boolean              willshowcage = FALSE;
   Boolean              willshowwgs = FALSE;
   Boolean              willshowgenome = FALSE;
   Boolean              willshowcontig = FALSE;
@@ -2275,7 +2281,10 @@ NLM_EXTERN void DoOneSection (
     for (sip = bsp->id; sip != NULL; sip = sip->next) {
       if (sip->choice == SEQID_GENBANK ||
           sip->choice == SEQID_EMBL ||
-          sip->choice == SEQID_DDBJ) {
+          sip->choice == SEQID_DDBJ ||
+          sip->choice == SEQID_TPG ||
+          sip->choice == SEQID_TPE ||
+          sip->choice == SEQID_TPD) {
         tsip = (TextSeqIdPtr) sip->data.ptrvalue;
         if (tsip != NULL && tsip->accession != NULL) {
           acclen = StringLen (tsip->accession);
@@ -2314,8 +2323,12 @@ NLM_EXTERN void DoOneSection (
     sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &dcontext);
     if (sdp != NULL) {
       mip = (MolInfoPtr) sdp->data.ptrvalue;
-      if (mip != NULL && mip->tech == MI_TECH_wgs) {
+      if (mip != NULL) {
+        if (mip->tech == MI_TECH_wgs) {
         wgstech = TRUE;
+        } else if (mip->tech == MI_TECH_other && StringCmp (mip->techexp, "cage") == 0) {
+          cagemaster = TRUE;
+        }
       }
     }
   }
@@ -2348,6 +2361,8 @@ NLM_EXTERN void DoOneSection (
 
     if (wgsmaster && wgstech) {
       willshowwgs = TRUE;
+    } else if (cagemaster) {
+      willshowcage = TRUE;
     } else if (nsgenome) {
       willshowgenome = TRUE;
     } else if (contig) {
@@ -2370,7 +2385,7 @@ NLM_EXTERN void DoOneSection (
       }
     }
 
-    AddLocusBlock (awp, willshowwgs, willshowgenome, willshowcontig, willshowsequence);
+    AddLocusBlock (awp, willshowwgs, willshowcage, willshowgenome, willshowcontig, willshowsequence);
 
     if (awp->format == GENBANK_FMT || awp->format == GENPEPT_FMT) {
 
@@ -2459,6 +2474,10 @@ NLM_EXTERN void DoOneSection (
 
       AddWGSBlock (awp);
 
+    } else if (cagemaster) {
+
+      AddCAGEBlock (awp);
+
     } else if (nsgenome) {
 
       AddGenomeBlock (awp);
@@ -3640,6 +3659,7 @@ static void MakeGapFeatsBase (
 
   if (bsp == NULL || bsp->repr != Seq_repr_delta) return;
   gapvnp = (ValNodePtr PNTR) userdata;
+  if (gapvnp == NULL) return;
   sip = SeqIdFindBest (bsp->id, 0);
   if (sip == NULL) return;
   /* no longer suppress on far delta contigs */
@@ -3737,20 +3757,94 @@ static void MakeGapFeats (
   MakeGapFeatsBase (bsp, userdata, FALSE);
 }
 
+static CharPtr gapstr1 = "     gap             ";
+static CharPtr gapstr2 = "                     /estimated_length=";
+static CharPtr gapstr3 = "unknown";
+
+static void MakeFarGapFeats (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  Char             buf [256];
+  Int4             currpos = 0;
+  ValNodePtr PNTR  fargaps;
+  IntFuzzPtr       fuzz;
+  SeqLitPtr        litp;
+  Boolean          notFar = FALSE;
+  SeqIdPtr         sip;
+  SeqLocPtr        slp;
+  ValNodePtr       vnp;
+
+  if (bsp == NULL || bsp->repr != Seq_repr_delta) return;
+  fargaps = (ValNodePtr PNTR) userdata;
+  if (fargaps == NULL) return;
+  sip = SeqIdFindBest (bsp->id, 0);
+  if (sip == NULL) return;
+  /* no longer suppress on far delta contigs */
+  /* if (! DeltaLitOnly (bsp)) return; */
+
+  /* empty string at beginning for GetFeatsOnSeg to skip over */
+  ValNodeAddPointer (fargaps, 0, NULL);
+
+  for (vnp = (ValNodePtr)(bsp->seq_ext); vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == 1) {
+      slp = (SeqLocPtr) vnp->data.ptrvalue;
+      if (slp == NULL) continue;
+      currpos += SeqLocLen (slp);
+    }
+    if (vnp->choice == 2) {
+      litp = (SeqLitPtr) vnp->data.ptrvalue;
+      if (litp == NULL) continue;
+      if (litp->seq_data == NULL || litp->seq_data_type == Seq_code_gap) {
+        if (litp->length > 0) {
+          fuzz = litp->fuzz;
+          if (fuzz != NULL && fuzz->choice == 4 && fuzz->a == 0) {
+            sprintf (buf, "%s%ld..%ld\n%s%s\n",
+                     gapstr1, (long) currpos + 1, (long) currpos + litp->length,
+                     gapstr2, gapstr3);
+          } else {
+            sprintf (buf, "%s%ld..%ld\n%s%ld\n",
+                     gapstr1, (long) currpos + 1, (long) currpos + litp->length,
+                     gapstr2, (long) litp->length);
+          }
+          ValNodeCopyStr (fargaps, 0, (Pointer) buf);
+        }
+      } else {
+        notFar = TRUE;
+      }
+      currpos += litp->length;
+    }
+  }
+
+  if (notFar) {
+    for (vnp = *fargaps; vnp != NULL; vnp = vnp->next) {
+      vnp->choice = 1;
+    }
+  }
+}
+
+typedef struct featpolicy {
+  Boolean  forceOnlyNearFeats;
+  Boolean  forceAllowFarFeats;
+} FeatPolicy, PNTR FeatPolicyPtr;
+
 static void LookFarFeatFetchPolicy (
   SeqDescrPtr sdp,
   Pointer userdata
 )
 
 {
-  BoolPtr        forceOnlyNearFeatsP;
+  FeatPolicyPtr  fpP;
   ObjectIdPtr    oip;
+  CharPtr        str;
   UserFieldPtr   ufp;
   UserObjectPtr  uop;
 
   if (sdp == NULL || sdp->choice != Seq_descr_user) return;
-  forceOnlyNearFeatsP = (BoolPtr) userdata;
-  if (forceOnlyNearFeatsP == NULL) return;
+  fpP = (FeatPolicyPtr) userdata;
+  if (fpP == NULL) return;
 
   uop = (UserObjectPtr) sdp->data.ptrvalue;
   if (uop == NULL) return;
@@ -3762,13 +3856,43 @@ static void LookFarFeatFetchPolicy (
     oip = ufp->label;
     if (oip == NULL || ufp->data.ptrvalue == NULL) continue;
     if (StringCmp (oip->str, "Policy") == 0) {
-      if (StringICmp ((CharPtr) ufp->data.ptrvalue, "OnlyNearFeatures") == 0) {
-        *forceOnlyNearFeatsP = TRUE;
+      str = (CharPtr) ufp->data.ptrvalue;
+      if (StringICmp (str, "OnlyNearFeatures") == 0) {
+        fpP->forceOnlyNearFeats = TRUE;
+      } else if (StringICmp (str, "AllowFarFeatures") == 0) {
+        fpP->forceAllowFarFeats = TRUE;
       }
     }
   }
 }
 
+static void FindMultiIntervalGenes (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  BoolPtr    multiIntervalGenesP;
+  SeqLocPtr  slp;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_GENE) return;
+  multiIntervalGenesP = (BoolPtr) userdata;
+  if (multiIntervalGenesP == NULL) return;
+
+  slp = sfp->location;
+  if (slp == NULL) return;
+  switch (slp->choice) {
+    case SEQLOC_PACKED_INT :
+    case SEQLOC_PACKED_PNT :
+    case SEQLOC_MIX :
+    case SEQLOC_EQUIV :
+      *multiIntervalGenesP = TRUE;
+      break;
+    default :
+      break;
+  }
+}
+
 static CharPtr bad_html_strings [] = {
   "<script", "<object", "<applet", "<embed", "<form", "javascript:", "vbscript:", NULL
 };
@@ -3790,7 +3914,7 @@ static CharPtr defTail = "\
 </html>\n";
 
 #define FAR_TRANS_MASK (SHOW_FAR_TRANSLATION | TRANSLATE_IF_NO_PRODUCT | ALWAYS_TRANSLATE_CDS)
-#define FEAT_FETCH_MASK (ONLY_NEAR_FEATURES | FAR_FEATURES_SUPPRESS | NEAR_FEATURES_SUPPRESS)
+#define FEAT_FETCH_MASK (ONLY_NEAR_FEATURES | FAR_FEATURES_SUPPRESS | NEAR_FEATURES_SUPPRESS | FORCE_ALLOW_FAR_FEATS)
 #define HTML_XML_ASN_MASK (CREATE_HTML_FLATFILE | CREATE_XML_GBSEQ_FILE | CREATE_ASN_GBSEQ_FILE)
 #define PUBLICATION_MASK (HIDE_GENE_RIFS | ONLY_GENE_RIFS | ONLY_REVIEW_PUBS | NEWEST_PUBS | OLDEST_PUBS | HIDE_ALL_PUBS)
 
@@ -3823,10 +3947,11 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
   Uint2            entityID = 0;
   Uint2            item_type = 0;
   Uint4            item_id = 0;
+  ValNodePtr       fargaps = NULL;
   CharPtr          ffhead = NULL;
   CharPtr          fftail = NULL;
   Asn2gbWriteFunc  ffwrite = NULL;
-  Boolean          forceOnlyNearFeats = FALSE;
+  FeatPolicy       featpolicy;
   ValNodePtr       gapvnp = NULL;
   GBSeqPtr         gbseq = NULL;
   Int4             i;
@@ -3856,6 +3981,7 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
   Boolean          lookupFarOthers;
   Boolean          lookupFarProd;
   Boolean          missingVersion;
+  Boolean          multiIntervalGenes = FALSE;
   Int4             nextGi = 0;
   Boolean          noLeft;
   Boolean          noRight;
@@ -3877,6 +4003,7 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
   Asn2gbSectPtr    PNTR sectionArray;
   SubmitBlockPtr   sbp;
   SeqEntryPtr      sep;
+  Boolean          seqspans = FALSE;
   SeqIntPtr        sintp;
   SeqIdPtr         sip;
   Boolean          skipMrnas = FALSE;
@@ -3912,6 +4039,7 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
     nextGi = extra->nextGi;
     bkmask = extra->bkmask;
     reindex = extra->reindex;
+    seqspans = extra->seqspans;
   }
 
   if (slp != NULL) {
@@ -4006,10 +4134,25 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
   ajp = (IntAsn2gbJobPtr) MemNew (sizeof (IntAsn2gbJob));
   if (ajp == NULL) return NULL;
 
-  VisitDescriptorsInSep (sep, (Pointer) &forceOnlyNearFeats, LookFarFeatFetchPolicy);
+  featpolicy.forceOnlyNearFeats = FALSE;
+  featpolicy.forceAllowFarFeats = FALSE;
+  VisitDescriptorsInSep (sep, (Pointer) &featpolicy, LookFarFeatFetchPolicy);
 
-  gapvnp = NULL;
+  fargaps = NULL;
   if (format != FTABLE_FMT) {
+    if (isRefSeq && isNC && VisitFeaturesInSep (sep, NULL, NULL) == 0) {
+      if ((Boolean) ((custom & HIDE_GAP_FEATS) == 0)) {
+        VisitBioseqsInSep (sep, (Pointer) &fargaps, MakeFarGapFeats);
+      }
+    }
+  }
+  if (fargaps != NULL && fargaps->choice == 1) {
+    fargaps = ValNodeFreeData (fargaps);
+  }
+  ajp->fargaps = fargaps;
+
+  gapvnp = NULL;
+  if (fargaps == NULL && format != FTABLE_FMT) {
     if (isGED /* was isG */ || isTPG || isOnlyLocal || isRefSeq || isSP || (isGeneral && (! isGED))) {
       if ((Boolean) ((custom & HIDE_GAP_FEATS) == 0)) {
         if (isSP) {
@@ -4107,6 +4250,7 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
   }
   ajp->bkmask = bkmask;
   ajp->reindex = reindex;
+  ajp->seqspans = seqspans;
   ajp->aip = aip;
   ajp->atp = atp;
 
@@ -4168,7 +4312,8 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
   }
   ajp->seqGapCurrLen = 0;
 
-  ajp->produceInsdSeq = (Boolean) ((flags & PRODUCE_OLD_GBSEQ) == 0);
+  ajp->produceInsdSeq = (Boolean) (((flags & PRODUCE_OLD_GBSEQ) == 0) && ((custom & OLD_GBSEQ_XML) == 0));
+  ajp->oldXmlPolicy = (Boolean) ((custom & NEW_XML_POLICY) == 0);
 
   ajp->gihead = NULL;
   ajp->gitail = NULL;
@@ -4180,6 +4325,9 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
     ajp->newSourceOrg = TRUE;
   }
 
+  VisitFeaturesInSep (sep, (Pointer) &multiIntervalGenes, FindMultiIntervalGenes);
+  ajp->multiIntervalGenes = multiIntervalGenes;
+
   ajp->relModeError = FALSE;
   ajp->skipProts = skipProts;
   ajp->skipMrnas = skipMrnas;
@@ -4242,11 +4390,19 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
   aw.farFeatsSuppress = FALSE;
   aw.nearFeatsSuppress = FALSE;
 
-  if (isNC) {
+  if (featpolicy.forceAllowFarFeats) {
+
+    /* do not set other flags */
+
+  } else if ((Boolean) ((flags & FEAT_FETCH_MASK) == FORCE_ALLOW_FAR_FEATS)) {
+
+    /* do not set other flags */
+
+  } else if (isNC) {
 
     if ((Boolean) ((flags & FEAT_FETCH_MASK) == ONLY_NEAR_FEATURES)) {
       aw.onlyNearFeats = TRUE;
-    } else if (forceOnlyNearFeats) {
+    } else if (featpolicy.forceOnlyNearFeats) {
       aw.onlyNearFeats = TRUE;
     } else {
       aw.nearFeatsSuppress = TRUE;
@@ -4260,14 +4416,14 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
 
     if ((Boolean) ((flags & FEAT_FETCH_MASK) == ONLY_NEAR_FEATURES)) {
       aw.onlyNearFeats = TRUE;
-    } else if (forceOnlyNearFeats) {
+    } else if (featpolicy.forceOnlyNearFeats) {
       aw.onlyNearFeats = TRUE;
     } else {
       aw.nearFeatsSuppress = TRUE;
     }
     ajp->showFarTransl = TRUE;
 
-  } else if (forceOnlyNearFeats) {
+  } else if (featpolicy.forceOnlyNearFeats) {
 
     aw.onlyNearFeats = TRUE;
     
@@ -4377,11 +4533,11 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
     }
     if (ffhead != NULL) {
       if (fp != NULL) {
-        fprintf (fp, ffhead);
+        fprintf (fp, "%s", ffhead);
       }
     }
     if (ffwrite != NULL) {
-      ffwrite (ffhead, userdata, HEAD_BLOCK, entityID, item_type, item_id);
+      ffwrite (ffhead, userdata, HEAD_BLOCK, entityID, item_type, item_id, 0, 0);
     }
     if (is_html) {
       DoQuickLinkFormat (aw.afp, "<div class=\"sequence\">");
@@ -4428,11 +4584,11 @@ static Asn2gbJobPtr asn2gnbk_setup_ex (
     }
     if (fftail != NULL) {
       if (fp != NULL) {
-        fprintf (fp, fftail);
+        fprintf (fp, "%s", fftail);
       }
     }
     if (ffwrite != NULL) {
-      ffwrite (fftail, userdata, TAIL_BLOCK, entityID, item_type, item_id);
+      ffwrite (fftail, userdata, TAIL_BLOCK, entityID, item_type, item_id, 0, 0);
     }
   }
 
@@ -4921,7 +5077,7 @@ static void PrintFTUserObj (
   }
 }
 
-static void PrintFTCodeBreak (
+NLM_EXTERN void PrintFTCodeBreak (
   ValNodePtr PNTR head,
   CodeBreakPtr cbp,
   BioseqPtr target
@@ -4964,7 +5120,7 @@ static void PrintFTCodeBreak (
 
   slp = SeqLocFindNext (cbp->loc, NULL);
   while (slp != NULL) {
-    str = FFFlatLoc (&iaj, target, slp, FALSE);
+    str = FFFlatLoc (&iaj, target, slp, FALSE, FALSE);
     if (str != NULL) {
       residue = cbaa.value.intvalue;
       ptr = Get3LetterSymbol (&iaj, seqcode, sctp, residue);
@@ -5427,6 +5583,8 @@ NLM_EXTERN void PrintFtableLocAndQuals (
   SeqFeatPtr         prot;
   ProtRefPtr         prp = NULL;
   Boolean            pseudo;
+  RNAGenPtr          rgp;
+  RNAQualPtr         rqp;
   RnaRefPtr          rrp;
   SeqDescrPtr        sdp;
   Int4               sec_str;
@@ -5435,7 +5593,7 @@ NLM_EXTERN void PrintFtableLocAndQuals (
   Int2               siteidx;
   SeqLocPtr          slp;
   Char               str [256];
-  Char               tmp [300];
+  Char               tmp [512];
   CharPtr            tmpx;
   tRNAPtr            trp;
   ValNodePtr         vnp;
@@ -5621,7 +5779,7 @@ NLM_EXTERN void PrintFtableLocAndQuals (
             }
             break;
           case 2 :
-            trp = rrp->ext.value.ptrvalue;
+            trp = (tRNAPtr) rrp->ext.value.ptrvalue;
             if (trp != NULL) {
               FeatDefLabel (sfp, str, sizeof (str) - 1, OM_LABEL_CONTENT);
               if (! StringHasNoText (str)) {
@@ -5649,7 +5807,7 @@ NLM_EXTERN void PrintFtableLocAndQuals (
                 aa += 5;
               }
               if (slp != NULL && StringDoesHaveText (aa)) {
-                tmpx = FFFlatLoc (ajp, target, slp, ajp->masterStyle);
+                tmpx = FFFlatLoc (ajp, target, slp, ajp->masterStyle, FALSE);
                 if (tmpx != NULL) {
                   sprintf (tmp, "\t\t\tanticodon\t(pos:%s,aa:%s)\n", tmpx, aa);
                   ValNodeCopyStr (head, 0, tmp);
@@ -5661,6 +5819,25 @@ NLM_EXTERN void PrintFtableLocAndQuals (
               }
             }
             break;
+          case 3 :
+            rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+            if (rgp != NULL) {
+              StringNCpy_0 (str, rgp->_class, sizeof (str));
+              if (StringDoesHaveText (str)) {
+                sprintf (tmp, "\t\t\tncRNA_class\t%s\n", str);
+                ValNodeCopyStr (head, 0, tmp);
+              }
+              StringNCpy_0 (str, rgp->product, sizeof (str));
+              if (StringDoesHaveText (str)) {
+                sprintf (tmp, "\t\t\tproduct\t%s\n", str);
+                ValNodeCopyStr (head, 0, tmp);
+              }
+              for (rqp = rgp->quals; rqp != NULL; rqp = rqp->next) {
+                if (StringDoesHaveText (rqp->qual) && StringDoesHaveText (rqp->val)) {
+                  AddOneFtableQual (head, rqp->qual, rqp->val);
+                }
+              }
+            }
           default :
             break;
         }
@@ -5992,10 +6169,13 @@ NLM_EXTERN void DoImmediateFormat (
   BlockType        blocktype;
   BioseqPtr        bsp;
   FormatProc       fmt;
+  IntFeatBlockPtr  ifp;
   Boolean          is_www;
+  Int4             left = 0;
   size_t           max;
   SeqEntryPtr      oldscope;
   QualValPtr       qv = NULL;
+  Int4             right = 0;
   SeqEntryPtr      sep;
   CharPtr          str = NULL;
   Uint2            itemtype;
@@ -6035,19 +6215,25 @@ NLM_EXTERN void DoImmediateFormat (
   SeqEntrySetScope (oldscope);
   BioseqUnlock (bsp);
 
+  if (blocktype == FEATURE_BLOCK && afp->ffwrite != NULL) {
+    ifp = (IntFeatBlockPtr) bbp;
+    left = ifp->left + 1;
+    right = ifp->right + 1;
+  }
+
   if (str != NULL) {
     if (afp->fp != NULL) {
       fprintf (afp->fp, "%s", str);
     }
     if (afp->ffwrite != NULL) {
-      afp->ffwrite (str, afp->userdata, blocktype, bbp->entityID, itemtype, itemID);
+      afp->ffwrite (str, afp->userdata, blocktype, bbp->entityID, itemtype, itemID, left, right);
     }
   } else {
     if (afp->fp != NULL) {
       fprintf (afp->fp, "?\n");
     }
     if (afp->ffwrite != NULL) {
-      afp->ffwrite ("?\n", afp->userdata, blocktype, bbp->entityID, itemtype, itemID);
+      afp->ffwrite ("?\n", afp->userdata, blocktype, bbp->entityID, itemtype, itemID, left, right);
     }
   }
 
@@ -6083,7 +6269,7 @@ NLM_EXTERN void DoQuickLinkFormat (
       fprintf (afp->fp, "%s", str);
     }
     if (afp->ffwrite != NULL) {
-      afp->ffwrite (str, afp->userdata, (BlockType) 0, entityID, item_type, itemID);
+      afp->ffwrite (str, afp->userdata, (BlockType) 0, entityID, item_type, itemID, 0, 0);
     }
   }
 }
@@ -6271,6 +6457,10 @@ NLM_EXTERN Asn2gbJobPtr asn2gnbk_cleanup (
     UnlockFarComponents (iajp->lockedBspList);
   }
 
+  if (iajp->fargaps != NULL) {
+    ValNodeFreeData (iajp->fargaps);
+  }
+
   if (iajp->gapvnp != NULL || iajp->remotevnp != NULL) {
     SeqMgrClearFeatureIndexes (ajp->entityID, NULL);
     if (iajp->reindex) {
@@ -6494,7 +6684,7 @@ NLM_EXTERN Boolean SeqEntryToGnbk (
         }
       }
       if (ffwrite != NULL) {
-        ffwrite (ffhead, userdata, HEAD_BLOCK, 0, 0, 0);
+        ffwrite (ffhead, userdata, HEAD_BLOCK, 0, 0, 0, 0, 0, 0, 0);
       }
 
       /* send each paragraph */
@@ -6516,14 +6706,14 @@ NLM_EXTERN Boolean SeqEntryToGnbk (
             fprintf (fp, "%s", str);
           }
           if (ffwrite != NULL) {
-            ffwrite (str, userdata, block, 0, 0, 0);
+            ffwrite (str, userdata, block, 0, 0, 0, 0, 0);
           }
         } else {
           if (fp != NULL) {
             fprintf (fp, "?\n");
           }
           if (ffwrite != NULL) {
-            ffwrite ("?\n", userdata, block, 0, 0, 0);
+            ffwrite ("?\n", userdata, block, 0, 0, 0, 0, 0);
           }
         }
 
@@ -6541,7 +6731,7 @@ NLM_EXTERN Boolean SeqEntryToGnbk (
         }
       }
       if (ffwrite != NULL) {
-        ffwrite (fftail, userdata, TAIL_BLOCK, 0, 0, 0);
+        ffwrite (fftail, userdata, TAIL_BLOCK, 0, 0, 0, 0, 0);
       }
     }
 #endif
diff --git a/api/asn2gnb2.c b/api/asn2gnb2.c
index 9485143..e435d2b 100644
--- a/api/asn2gnb2.c
+++ b/api/asn2gnb2.c
@@ -30,7 +30,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 1.125 $
+* $Revision: 1.147 $
 *
 * File Description:  New GenBank flatfile generator - work in progress
 *
@@ -65,7 +65,14 @@
 
 static CharPtr link_projid = "http://www.ncbi.nlm.nih.gov/sites/entrez?db=genomeprj&cmd=Retrieve&dopt=Overview&list_uids=";
 
-static CharPtr link_wgs = "http://www.ncbi.nlm.nih.gov/sites/entrez?";
+static CharPtr link_srr = "http://www.ncbi.nlm.nih.gov/sites/entrez?db=sra&term=";
+
+static CharPtr link_accn = "http://www.ncbi.nlm.nih.gov/sites/entrez?";
+
+static CharPtr link_wgs = "http://www.ncbi.nlm.nih.gov/Traces/wgs?";
+static CharPtr link_wgsscaf = "http://www.ncbi.nlm.nih.gov/nuccore?";
+
+static CharPtr link_cage = "http://www.ncbi.nlm.nih.gov/sites/entrez?";
 
 static CharPtr link_sp = "http://www.uniprot.org/uniprot/";
 
@@ -92,8 +99,8 @@ static CharPtr strd [4] = {
 };
 
 static CharPtr gnbk_mol [16] = {
-  "    ", "DNA ", "RNA ", "mRNA", "rRNA", "tRNA", "snRNA", "scRNA",
-  " AA ", "DNA ", "DNA ", "cRNA ", "snoRNA", "RNA ", "RNA ", "tmRNA "
+  "    ", "DNA ", "RNA ", "mRNA", "rRNA", "tRNA", /* "snRNA" */ "RNA", /* "scRNA" */ "RNA",
+  " AA ", "DNA ", "DNA ", "cRNA ", /* "snoRNA" */ "RNA", "RNA ", "RNA ", "tmRNA "
 };
 
 /* EMBL_FMT in RELEASE_MODE or ENTREZ_MODE, otherwise use gnbk_mol */
@@ -117,8 +124,8 @@ static CharPtr gbseq_strd [4] = {
 };
 
 static CharPtr gbseq_mol [16] = {
-  "?", "DNA", "RNA", "mRNA", "rRNA", "tRNA", "snRNA", "scRNA",
-  "AA", "DNA", "DNA", "cRNA", "snoRNA", "RNA", "ncRNA", "tmRNA "
+  "?", "DNA", "RNA", "mRNA", "rRNA", "tRNA", /* "snRNA" */ "RNA", /* "scRNA" */ "RNA",
+  "AA", "DNA", "DNA", "cRNA", /* "snoRNA" */ "RNA", "RNA", /* "ncRNA" */ "RNA", "tmRNA "
 };
 
 static CharPtr gbseq_top [3] = {
@@ -385,7 +392,7 @@ static Boolean LocusHasBadChars (
   ptr = locus;
   ch = *ptr;
   while (ch != '\0') {
-    if (! IS_ALPHANUM (ch)) {
+    if (! (IS_ALPHA(ch) || IS_DIGIT(ch) || ch == '_')) {
       return TRUE;
     }
     ptr++;
@@ -424,6 +431,7 @@ static void LookupAccnForNavLink (
 NLM_EXTERN void AddLocusBlock (
   Asn2gbWorkPtr awp,
   Boolean willshowwgs,
+  Boolean willshowcage,
   Boolean willshowgenome,
   Boolean willshowcontig,
   Boolean willshowsequence
@@ -439,6 +447,7 @@ NLM_EXTERN void AddLocusBlock (
   Int2               bmol = 0;
   BioseqPtr          bsp;
   Char               buf [1024];
+  Boolean            cagemaster = FALSE;
   SeqFeatPtr         cds;
   Int4               currGi;
   Char               dataclass [10];
@@ -716,6 +725,31 @@ NLM_EXTERN void AddLocusBlock (
           }
         }
       }
+
+      if (tech == MI_TECH_other && willshowcage && bsp->repr == Seq_repr_virtual) {
+
+        /* check for TAG master record */
+
+        for (sip = bsp->id; sip != NULL; sip = sip->next) {
+          switch (sip->choice) {
+            case SEQID_GENBANK :
+            case SEQID_EMBL :
+            case SEQID_DDBJ :
+              tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+              if (tsip != NULL && tsip->accession != NULL) {
+                acclen = StringLen (tsip->accession);
+                if (acclen == 12) {
+                  if (StringCmp (tsip->accession + 5, "0000000") == 0) {
+                    cagemaster = TRUE;
+                  }
+                }
+              }
+              break;
+            default :
+              break;
+          }
+        }
+      }
     }
   }
 
@@ -765,6 +799,8 @@ NLM_EXTERN void AddLocusBlock (
 
       if (wgsmaster && (! is_nz)) {
         sprintf (len, "%ld rc", (long) length);
+      } else if (cagemaster) {
+        sprintf (len, "%ld rc", (long) length);
       } else {
         sprintf (len, "%ld bp", (long) length);
       }
@@ -1676,9 +1712,11 @@ static ValNodePtr GetSecondaryAccessions(ValNodePtr extra_access)
     if (!IsSuccessor(curr, prev)) {
       bin = ValNodeAdd(&bins);
     }
+    if (bin != NULL) {
     temp = (ValNodePtr)bin->data.ptrvalue;
     ValNodeAddStr(&temp, 0, curr);
     bin->data.ptrvalue = temp;
+    }
 
     prev = curr;
   }
@@ -1770,6 +1808,9 @@ NLM_EXTERN void AddAccessionBlock (
       case SEQID_GENBANK :
       case SEQID_EMBL :
       case SEQID_DDBJ :
+      case SEQID_TPG :
+      case SEQID_TPE :
+      case SEQID_TPD :
         accn = sip;
         tsip = (TextSeqIdPtr) sip->data.ptrvalue;
         if (tsip != NULL) {
@@ -1799,11 +1840,6 @@ NLM_EXTERN void AddAccessionBlock (
       case SEQID_PDB :
         accn = sip;
         break;
-      case SEQID_TPG :
-      case SEQID_TPE :
-      case SEQID_TPD :
-        accn = sip;
-        break;
       case SEQID_GPIPE :
         /* should not override better accession */
         gpp = sip;
@@ -1860,7 +1896,7 @@ NLM_EXTERN void AddAccessionBlock (
 
   } else if (ajp->ajp.slp != NULL) {
     FF_www_accession (ajp, ffstring, buf, is_na);
-    flatloc =  FFFlatLoc (ajp, bsp, ajp->ajp.slp, ajp->masterStyle);
+    flatloc =  FFFlatLoc (ajp, bsp, ajp->ajp.slp, ajp->masterStyle, FALSE);
     FFAddTextToString (ffstring, " REGION: ", flatloc, NULL, FALSE, FALSE, TILDE_TO_SPACES);
     MemFree (flatloc);
   } else {
@@ -1927,7 +1963,7 @@ NLM_EXTERN void AddAccessionBlock (
         if (! StringHasNoText (buf)) {
           if ( GetWWW(ajp) ) {
             FFAddTextToString(ffstring, separator, "<a href=\"", NULL, FALSE, FALSE, TILDE_IGNORE);
-            FF_Add_NCBI_Base_URL (ffstring, link_wgs);
+            FF_Add_NCBI_Base_URL (ffstring, link_accn);
             FFAddTextToString(ffstring, "db=Nucleotide&cmd=Search&term=", buf, "\">", FALSE, FALSE, TILDE_IGNORE);
             FFAddOneString (ffstring, buf, FALSE, FALSE, TILDE_TO_SPACES);
             FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_TO_SPACES);
@@ -2220,14 +2256,59 @@ static void FF_asn2gb_www_projID (
   FFAddOneString(ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
 }
 
+static void FF_asn2gb_www_SRR (
+  IntAsn2gbJobPtr ajp,
+  CharPtr buf,
+  CharPtr str
+)
+
+{
+  Char           ch;
+  StringItemPtr  ffstring;
+  CharPtr        ptr;
+  CharPtr        tmp;
+
+  if (ajp == NULL || buf == NULL || StringHasNoText (str)) return;
+
+  ffstring = FFGetString (ajp);
+  if (ffstring == NULL) return;
+
+  FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
+  FF_Add_NCBI_Base_URL (ffstring, link_srr);
+  FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_IGNORE);
+  FFAddOneString(ffstring, "\">", FALSE, FALSE, TILDE_IGNORE);
+  FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_IGNORE);
+  FFAddOneString(ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
+
+  tmp = FFEndPrint (ajp, ffstring, ajp->format, 21, 21, 21, 21, NULL);
+  FFRecycleString (ajp, ffstring);
+
+  if (tmp != NULL) {
+    ptr = tmp;
+    ch = *ptr;
+    while (ch != '\0') {
+      if (ch == '\n' || ch == '\r' || ch == '\t') {
+        *ptr = ' ';
+      }
+      ptr++;
+      ch = *ptr;
+    }
+    TrimSpacesAroundString (tmp);
+    StringCat (buf, tmp);
+    MemFree (tmp);
+  }
+}
+
 static CharPtr GetDBLinkString (
+  IntAsn2gbJobPtr ajp,
   UserObjectPtr uop
 )
 
 {
-  Char          buf1 [256];
-  Char          buf2 [256];
-  Char          buf3 [256];
+  Char          buf1 [512];
+  Char          buf2 [512];
+  Char          buf3 [512];
+  Char          buf4 [1024];
   CharPtr PNTR  cpp;
   Int4          i;
   Int4Ptr       ip;
@@ -2235,7 +2316,7 @@ static CharPtr GetDBLinkString (
   ObjectIdPtr   oip;
   CharPtr       prefix;
   CharPtr       str;
-  Char          tmp [32];
+  Char          tmp [256];
   UserFieldPtr  ufp;
   Int4          val;
 
@@ -2244,6 +2325,7 @@ static CharPtr GetDBLinkString (
   buf1 [0] = '\0';
   buf2 [0] = '\0';
   buf3 [0] = '\0';
+  buf4 [0] = '\0';
 
   for (ufp = uop->data; ufp != NULL; ufp = ufp->next) {
     oip = ufp->label;
@@ -2253,11 +2335,11 @@ static CharPtr GetDBLinkString (
       if (ufp->num > 0 && ip != NULL) {
         val = ip [0];
         if (val > 0) {
-          sprintf (buf1, "Trace Assembly Archive:%ld", (long) val);
+          sprintf (buf1, "Trace Assembly Archive: %ld", (long) val);
           for (i = 1; i < ufp->num; i++) {
             val = ip [i];
             if (val > 0) {
-              sprintf (tmp, ",%ld", (long) val);
+              sprintf (tmp, ", %ld", (long) val);
               StringCat (buf1, tmp);
             }
           }
@@ -2269,11 +2351,11 @@ static CharPtr GetDBLinkString (
       if (ufp->num > 0 && cpp != NULL) {
         str = cpp [0];
         if (StringDoesHaveText (str)) {
-          sprintf (buf2, "Bio Sample:%s", str);
+          sprintf (buf2, "Bio Sample: %s", str);
           for (i = 1; i < ufp->num; i++) {
             str = cpp [i];
             if (StringDoesHaveText (str)) {
-              sprintf (tmp, ",%s", str);
+              sprintf (tmp, ", %s", str);
               StringCat (buf2, tmp);
             }
           }
@@ -2285,22 +2367,50 @@ static CharPtr GetDBLinkString (
       if (ufp->num > 0 && cpp != NULL) {
         str = cpp [0];
         if (StringDoesHaveText (str)) {
-          sprintf (buf3, "ProbeDB:%s", str);
+          sprintf (buf3, "ProbeDB: %s", str);
           for (i = 1; i < ufp->num; i++) {
             str = cpp [i];
             if (StringDoesHaveText (str)) {
-              sprintf (tmp, ",%s", str);
+              sprintf (tmp, ", %s", str);
               StringCat (buf3, tmp);
             }
           }
         }
       }
     }
+    if (StringICmp (oip->str, "Sequence Read Archive") == 0 && ufp->choice == 7) {
+      cpp = (CharPtr PNTR) ufp->data.ptrvalue;
+      if (ufp->num > 0 && cpp != NULL) {
+        str = cpp [0];
+        if (StringDoesHaveText (str)) {
+          tmp [0] = '\0';
+          if (ajp != NULL && GetWWW (ajp)) {
+            FF_asn2gb_www_SRR (ajp, tmp, str);
+          } else {
+            StringCpy (tmp, str);
+          }
+          sprintf (buf4, "Sequence Read Archive: %s", tmp);
+          for (i = 1; i < ufp->num; i++) {
+            str = cpp [i];
+            if (StringDoesHaveText (str)) {
+              tmp [0] = '\0';
+              if (ajp != NULL && GetWWW (ajp)) {
+                FF_asn2gb_www_SRR (ajp, tmp, str);
+              } else {
+                StringCpy (tmp, str);
+              }
+              StringCat (buf4, ", ");
+              StringCat (buf4, tmp);
+            }
+          }
+        }
+      }
+    }
   }
 
-  if (StringHasNoText (buf1) && StringHasNoText (buf2) && StringHasNoText (buf3)) return NULL;
+  if (StringHasNoText (buf1) && StringHasNoText (buf2) && StringHasNoText (buf3) && StringHasNoText (buf4)) return NULL;
 
-  len = StringLen (buf1) + StringLen (buf2) + StringLen (buf3);
+  len = StringLen (buf1) + StringLen (buf2) + StringLen (buf3) + StringLen (buf4);
   str = (CharPtr) MemNew (sizeof (Char) * (len + 2));
   if (str == NULL) return NULL;
 
@@ -2323,6 +2433,12 @@ static CharPtr GetDBLinkString (
     prefix = "\n";
   }
 
+  if (StringDoesHaveText (buf4)) {
+    StringCat (str, prefix);
+    StringCat (str, buf4);
+    prefix = "\n";
+  }
+
   return str;
 }
 
@@ -2413,7 +2529,7 @@ NLM_EXTERN void AddDblinkBlock (
     }
     first = FALSE;
 
-    prefix = "Project:";
+    prefix = "Project: ";
     projectID = 0;
     parentID = 0;
     for (curr = gpuop->data; curr != NULL; curr = curr->next) {
@@ -2441,7 +2557,7 @@ NLM_EXTERN void AddDblinkBlock (
               }
               ValNodeCopyStr (&head, 0, buf);
             }
-            prefix = ",";
+            prefix = ", ";
             parentID = 0;
           }
           projectID = val;
@@ -2484,7 +2600,7 @@ NLM_EXTERN void AddDblinkBlock (
   }
 
   if (dbuop != NULL) {
-    str = GetDBLinkString (dbuop);
+    str = GetDBLinkString (ajp, dbuop);
     if (StringDoesHaveText (str)) {
       bbp = Asn2gbAddBlock (awp, PROJECT_BLOCK, sizeof (BaseBlock));
       if (bbp == NULL) return;
@@ -3544,6 +3660,7 @@ NLM_EXTERN void AddDbsourceBlock (
         break;
     }
 
+    if (sip != NULL) {
     switch (sip->choice) {
       case SEQID_PIR :
         AddPIRBlock (ajp, ffstring, bsp);
@@ -3561,6 +3678,7 @@ NLM_EXTERN void AddDbsourceBlock (
         break;
     }
   }
+  }
 
   if (unknown) {
     FFAddOneString (ffstring, "UNKNOWN", FALSE, FALSE, TILDE_TO_SPACES);
@@ -3745,6 +3863,54 @@ static Boolean KeywordAlreadyInList (
   return FALSE;
 }
 
+typedef struct finstatdata {
+  CharPtr  inuserobj;
+  CharPtr  inkeyword;
+} FinStatData, PNTR FinStatPtr;
+
+static FinStatData finStatKywds [] = {
+  {"Standard-Draft",              "STANDARD_DRAFT"},
+  {"High-quality-draft",          "HIGH_QUALITY_DRAFT"},
+  {"Improved-high-quality-draft", "IMPROVED_HIGH_QUALITY_DRAFT"},
+  {"Annotation-grade",            "ANNOTATION_GRADE"},
+  {"Non-contiguous-finished",     "NON_CONTIGUOUS_FINISHED"},
+  /*
+  {"Finished",                    "FINISHED"},
+  */
+  {NULL, NULL}
+};
+
+static CharPtr GetFinishingStatus (
+  CharPtr str
+)
+
+{
+  Char     buf [64];
+  Char     ch;
+  Int2     i;
+  CharPtr  ptr;
+
+  if (StringHasNoText (str)) return NULL;
+
+  StringNCpy_0 (buf, str, sizeof (buf));
+  ptr = buf;
+  ch = *ptr;
+  while (ch != '\0') {
+    if (ch == ' ') {
+      *ptr = '-';
+    }
+    ptr++;
+    ch = *ptr;
+  }
+
+  for (i = 0; finStatKywds [i].inuserobj != NULL; i++) {
+    if (StringICmp (buf, finStatKywds [i].inuserobj) == 0) {
+      return finStatKywds [i].inkeyword;
+    }
+  }
+
+  return NULL;
+}
 
 NLM_EXTERN void AddKeywordsBlock (
   Asn2gbWorkPtr awp
@@ -3757,8 +3923,11 @@ NLM_EXTERN void AddKeywordsBlock (
   BaseBlockPtr       bbp;
   BioseqPtr          bsp;
   BioSourcePtr       biop;
+  UserFieldPtr       curr;
   SeqMgrDescContext  dcontext;
   EMBLBlockPtr       ebp;
+  CharPtr            field;
+  CharPtr            finishing_status = NULL;
   GBBlockPtr         gbp;
   GBSeqPtr           gbseq;
   ValNodePtr         head = NULL;
@@ -3767,6 +3936,7 @@ NLM_EXTERN void AddKeywordsBlock (
   Boolean            is_gss = FALSE;
   Boolean            is_sts = FALSE;
   Boolean            is_env_sample = FALSE;
+  Boolean            is_genome_assembly = FALSE;
   ValNodePtr         keywords;
   CharPtr            kwd;
   MolInfoPtr         mip;
@@ -3938,6 +4108,22 @@ NLM_EXTERN void AddKeywordsBlock (
       oip = uop->type;
       if (oip != NULL && StringICmp (oip->str, "ENCODE") == 0) {
         add_encode = TRUE;
+      } else if (oip != NULL && StringICmp (oip->str, "StructuredComment") == 0) {
+        for (curr = uop->data; curr != NULL; curr = curr->next) {
+          if (curr->choice != 1) continue;
+          oip = curr->label;
+          if (oip == NULL) continue;
+          field = oip->str;
+          if (StringHasNoText (field)) continue;
+          if (StringCmp (field, "StructuredCommentPrefix") == 0) {
+            if (StringCmp ((CharPtr) curr->data.ptrvalue, "##Genome-Assembly-Data-START##") == 0) {
+              is_genome_assembly = TRUE;
+            }
+          }
+          if (StringCmp (field, "Current Finishing Status") == 0) {
+            finishing_status = GetFinishingStatus ((CharPtr) curr->data.ptrvalue);
+          }
+        }
       }
     }
     sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &dcontext);
@@ -3948,6 +4134,12 @@ NLM_EXTERN void AddKeywordsBlock (
     }
     ValNodeCopyStr (&head, 0, "ENCODE");
   }
+  if (is_genome_assembly && StringDoesHaveText (finishing_status)) {
+    if (head != NULL) {
+      ValNodeCopyStr (&head, 0, "; ");
+    }
+    ValNodeCopyStr (&head, 0, finishing_status);
+  }
 
   for (sip = bsp->id; sip != NULL; sip = sip->next) {
     if (sip->choice == SEQID_TPG || sip->choice == SEQID_TPE || sip->choice == SEQID_TPD) {
@@ -5050,7 +5242,7 @@ static void GetRefsOnBioseq (
         }
       }
       if (awp->format == FTABLE_FMT) {
-        pdp = (PubdescPtr) sdp->data.ptrvalue;
+        pdp = (PubdescPtr) sfp->data.value.ptrvalue;
         if (HasNoPmidOrMuid (pdp)) {
           takeIt = FALSE;
         }
@@ -5593,11 +5785,15 @@ NLM_EXTERN void AddWGSBlock (
 
 {
   IntAsn2gbJobPtr    ajp;
+  Asn2gbSectPtr      asp;
   BaseBlockPtr       bbp;
   BioseqPtr          bsp;
   Char               buf [80];
   SeqMgrDescContext  dcontext;
   CharPtr            first;
+  GBAltSeqItemPtr    gbaip;
+  GBAltSeqDataPtr    gbasp, asphead = NULL, asplast = NULL;
+  GBSeqPtr           gbseq;
   CharPtr            last;
   ObjectIdPtr        oip;
   SeqDescrPtr        sdp;
@@ -5611,6 +5807,8 @@ NLM_EXTERN void AddWGSBlock (
   if ( ajp == NULL ) return;
   bsp = awp->bsp;
   if (bsp == NULL) return;
+  asp = awp->asp;
+  if (asp == NULL) return;
 
   if (awp->format == EMBL_FMT || awp->format == EMBLPEPT_FMT) return;
 
@@ -5620,6 +5818,12 @@ NLM_EXTERN void AddWGSBlock (
     DoQuickLinkFormat (awp->afp, buf);
   }
 
+  if (ajp->gbseq) {
+    gbseq = &asp->gbseq;
+  } else {
+    gbseq = NULL;
+  }
+
   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &dcontext);
   while (sdp != NULL) {
     uop = (UserObjectPtr) sdp->data.ptrvalue;
@@ -5651,6 +5855,33 @@ NLM_EXTERN void AddWGSBlock (
             }
           }
           if (first != NULL && last != NULL) {
+            if (gbseq != NULL) {
+              gbasp = (GBAltSeqDataPtr) MemNew (sizeof (GBAltSeqData));
+              if (gbasp != NULL) {
+                if (asphead == NULL) {
+                  asphead = gbasp;
+                }
+                if (asplast != NULL) {
+                  asplast->next = gbasp;
+                }
+                asplast = gbasp;
+                if (wgstype == 1) {
+                  gbasp->name = StringSave ("WGS");
+                } else if (wgstype == 2) {
+                  gbasp->name = StringSave ("WGS_SCAFLD");
+                } else if (wgstype == 3) {
+                  gbasp->name = StringSave ("WGS_CONTIG");
+                }
+                gbaip = GBAltSeqItemNew ();
+                if (gbaip != NULL) {
+                  gbaip->first_accn = StringSave (first);
+                  if (StringCmp (first, last) != 0) {
+                    gbaip->last_accn = StringSave (last);
+                  }
+                  gbasp->items = gbaip;
+                }
+              }
+            }
             bbp = Asn2gbAddBlock (awp, WGS_BLOCK, sizeof (BaseBlock));
             if (bbp != NULL) {
               ffstring = FFGetString (ajp);
@@ -5665,8 +5896,172 @@ NLM_EXTERN void AddWGSBlock (
               
                 if ( GetWWW(ajp) ) {
                   if (StringCmp (first, last) != 0) {
+                    if (wgstype == 1) {
                     FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
                     FF_Add_NCBI_Base_URL (ffstring, link_wgs);
+                      StringCpy (buf, first);
+                      if (buf [2] == '_') {
+                        buf [9] = '\0';
+                      } else {
+                        buf [6] = '\0';
+                      }
+                      FFAddTextToString(ffstring, "val=", buf, "\">", FALSE, FALSE, TILDE_IGNORE);
+                      sprintf (buf, "%s-%s", first, last);
+                      FFAddOneString (ffstring, buf, FALSE, FALSE, TILDE_TO_SPACES);
+                      FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_TO_SPACES);
+                    } else {
+                      FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
+                      FF_Add_NCBI_Base_URL (ffstring, link_wgsscaf);
+                      sprintf (buf, "%s:%s", first, last);
+                      FFAddTextToString(ffstring, "term=", buf, "[PACC]\">", FALSE, FALSE, TILDE_IGNORE);
+                      sprintf (buf, "%s-%s", first, last);
+                      FFAddOneString (ffstring, buf, FALSE, FALSE, TILDE_TO_SPACES);
+                      FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_TO_SPACES);
+                    }
+                  } else {
+                    FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
+                    FF_Add_NCBI_Base_URL (ffstring, link_seqn);
+                    FFAddTextToString(ffstring, /* "val=" */ NULL, first, "\">", FALSE, FALSE, TILDE_IGNORE);
+                    sprintf (buf, "%s", first);
+                    FFAddOneString (ffstring, buf, FALSE, FALSE, TILDE_TO_SPACES);
+                    FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_TO_SPACES);
+                  }
+                } else {
+                  if (StringCmp (first, last) != 0) {
+                    sprintf (buf, "%s-%s", first, last);
+                    FFAddOneString (ffstring, buf, FALSE, FALSE, TILDE_TO_SPACES);
+                  } else {
+                    sprintf (buf, "%s", first);
+                    FFAddOneString (ffstring, buf, FALSE, FALSE, TILDE_TO_SPACES);
+                  }
+                }
+
+                bbp->string = FFEndPrint(ajp, ffstring, awp->format, 12, 12, 0, 0, NULL);
+                FFRecycleString(ajp, ffstring);
+              }
+
+              bbp->entityID = dcontext.entityID;
+              bbp->itemtype = OBJ_SEQDESC;
+              bbp->itemID = dcontext.itemID;
+              if (awp->afp != NULL) {
+                DoImmediateFormat (awp->afp, bbp);
+              }
+            }
+          }
+        }
+      }
+    }
+    sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &dcontext);
+  }
+
+  if (gbseq != NULL) {
+    gbseq->alt_seq = asphead;
+  }
+}
+
+NLM_EXTERN void AddCAGEBlock (
+  Asn2gbWorkPtr awp
+)
+
+{
+  IntAsn2gbJobPtr    ajp;
+  Asn2gbSectPtr      asp;
+  BaseBlockPtr       bbp;
+  BioseqPtr          bsp;
+  Char               buf [80];
+  Int2               cagetype;
+  SeqMgrDescContext  dcontext;
+  CharPtr            first;
+  GBAltSeqItemPtr    gbaip;
+  GBAltSeqDataPtr    gbasp, asphead = NULL, asplast = NULL;
+  GBSeqPtr           gbseq;
+  CharPtr            last;
+  ObjectIdPtr        oip;
+  SeqDescrPtr        sdp;
+  UserFieldPtr       ufp;
+  UserObjectPtr      uop;
+  StringItemPtr      ffstring;
+
+  if (awp == NULL) return;
+  ajp = awp->ajp;
+  if ( ajp == NULL ) return;
+  bsp = awp->bsp;
+  if (bsp == NULL) return;
+  asp = awp->asp;
+  if (asp == NULL) return;
+
+  if (awp->format == EMBL_FMT || awp->format == EMBLPEPT_FMT) return;
+
+  if (GetWWW (ajp) && awp->mode == ENTREZ_MODE && awp->afp != NULL &&
+      (awp->format == GENBANK_FMT || awp->format == GENPEPT_FMT)) {
+    sprintf (buf, "<a name=\"wgs_%ld\"></a>", (long) awp->currGi);
+    DoQuickLinkFormat (awp->afp, buf);
+  }
+
+  if (ajp->gbseq) {
+    gbseq = &asp->gbseq;
+  } else {
+    gbseq = NULL;
+  }
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &dcontext);
+  while (sdp != NULL) {
+    uop = (UserObjectPtr) sdp->data.ptrvalue;
+    if (uop != NULL) {
+      oip = uop->type;
+      first = NULL;
+      last = NULL;
+      cagetype = 0;
+      if (oip != NULL) {
+        if (StringICmp (oip->str, "CAGE-Tag-List") == 0) {
+          cagetype = 1;
+        }
+        if (cagetype != 0) {
+          for (ufp = uop->data; ufp != NULL; ufp = ufp->next) {
+            oip = ufp->label;
+            if (oip == NULL || oip->str == NULL || ufp->choice != 1) continue;
+            if (StringICmp (oip->str, "CAGE_accession_first") == 0) {
+              first = (CharPtr) ufp->data.ptrvalue;
+            } else if (StringICmp (oip->str, "CAGE_accession_last") == 0) {
+              last = (CharPtr) ufp->data.ptrvalue;
+            }
+          }
+          if (first != NULL && last != NULL) {
+            if (gbseq != NULL) {
+              gbasp = (GBAltSeqDataPtr) MemNew (sizeof (GBAltSeqData));
+              if (gbasp != NULL) {
+                if (asphead == NULL) {
+                  asphead = gbasp;
+                }
+                if (asplast != NULL) {
+                  asplast->next = gbasp;
+                }
+                asplast = gbasp;
+                if (cagetype == 1) {
+                  gbasp->name = StringSave ("TAG");
+                }
+                gbaip = GBAltSeqItemNew ();
+                if (gbaip != NULL) {
+                  gbaip->first_accn = StringSave (first);
+                  if (StringCmp (first, last) != 0) {
+                    gbaip->last_accn = StringSave (last);
+                  }
+                  gbasp->items = gbaip;
+                }
+              }
+            }
+            bbp = Asn2gbAddBlock (awp, WGS_BLOCK, sizeof (BaseBlock));
+            if (bbp != NULL) {
+              ffstring = FFGetString (ajp);
+              if (ffstring != NULL) {
+                if (cagetype == 1) {
+                  FFStartPrint (ffstring, awp->format, 0, 12, "TAG", 12, 0, 0, NULL, FALSE);
+                }
+              
+                if ( GetWWW(ajp) ) {
+                  if (StringCmp (first, last) != 0) {
+                    FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
+                    FF_Add_NCBI_Base_URL (ffstring, link_cage);
                     FFAddTextToString(ffstring, "db=Nucleotide&cmd=Search&term=", first, NULL, FALSE, FALSE, TILDE_IGNORE);
                     FFAddTextToString(ffstring, ":", last, "[PACC]\">", FALSE, FALSE, TILDE_IGNORE);
                     sprintf (buf, "%s-%s", first, last);
@@ -5707,6 +6102,10 @@ NLM_EXTERN void AddWGSBlock (
     }
     sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &dcontext);
   }
+
+  if (gbseq != NULL) {
+    gbseq->alt_seq = asphead;
+  }
 }
 
 NLM_EXTERN void AddGenomeBlock (
@@ -5716,11 +6115,15 @@ NLM_EXTERN void AddGenomeBlock (
 {
   CharPtr            accn;
   IntAsn2gbJobPtr    ajp;
+  Asn2gbSectPtr      asp;
   BaseBlockPtr       bbp;
   BioseqPtr          bsp;
   Char               buf [128];
   SeqMgrDescContext  dcontext;
   Boolean            first = TRUE;
+  GBAltSeqItemPtr    gbaip;
+  GBAltSeqDataPtr    gbasp, asphead = NULL, asplast = NULL;
+  GBSeqPtr           gbseq;
   CharPtr            moltype;
   ObjectIdPtr        oip;
   SeqDescrPtr        sdp;
@@ -5734,6 +6137,8 @@ NLM_EXTERN void AddGenomeBlock (
   if ( ajp == NULL ) return;
   bsp = awp->bsp;
   if (bsp == NULL) return;
+  asp = awp->asp;
+  if (asp == NULL) return;
 
   if (awp->format == EMBL_FMT || awp->format == EMBLPEPT_FMT) return;
 
@@ -5743,6 +6148,12 @@ NLM_EXTERN void AddGenomeBlock (
     DoQuickLinkFormat (awp->afp, buf);
   }
 
+  if (ajp->gbseq) {
+    gbseq = &asp->gbseq;
+  } else {
+    gbseq = NULL;
+  }
+
   bbp = Asn2gbAddBlock (awp, GENOME_BLOCK, sizeof (BaseBlock));
   if (bbp == NULL) return;
 
@@ -5773,6 +6184,30 @@ NLM_EXTERN void AddGenomeBlock (
             }
           }
           if (! StringHasNoText (accn)) {
+            if (gbseq != NULL) {
+              gbasp = (GBAltSeqDataPtr) MemNew (sizeof (GBAltSeqData));
+              if (gbasp != NULL) {
+                if (asphead == NULL) {
+                  asphead = gbasp;
+                }
+                if (asplast != NULL) {
+                  asplast->next = gbasp;
+                }
+                asplast = gbasp;
+                gbasp->name = StringSave ("GENOME");
+                gbaip = GBAltSeqItemNew ();
+                if (gbaip != NULL) {
+                  if (! StringHasNoText (moltype)) {
+                    sprintf (buf, "%s (%s)", accn, moltype);
+                    gbaip->value = StringSave (buf);
+                  } else {
+                    sprintf (buf, "%s", accn);
+                    gbaip->value = StringSave (buf);
+                  }
+                  gbasp->items = gbaip;
+                }
+              }
+            }
             if (! first) {
               FFAddNewLine(ffstring);
             }
@@ -5794,6 +6229,10 @@ NLM_EXTERN void AddGenomeBlock (
   if (awp->afp != NULL) {
     DoImmediateFormat (awp->afp, bbp);
   }
+
+  if (gbseq != NULL) {
+    gbseq->alt_seq = asphead;
+  }
 }
 
 NLM_EXTERN void AddBasecountBlock (
diff --git a/api/asn2gnb3.c b/api/asn2gnb3.c
index 3fd8987..5a12103 100644
--- a/api/asn2gnb3.c
+++ b/api/asn2gnb3.c
@@ -30,7 +30,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 1.113 $
+* $Revision: 1.129 $
 *
 * File Description:  New GenBank flatfile generator - work in progress
 *
@@ -74,8 +74,6 @@ static CharPtr link_encode = "http://www.nhgri.nih.gov/10005107";
 static CharPtr link_seqn = "http://www.ncbi.nlm.nih.gov/nuccore/";
 static CharPtr link_seqp = "http://www.ncbi.nlm.nih.gov/protein/";
 
-static CharPtr link_gold_stamp_id = "http://genomesonline.org/GOLD_CARDS/";
-
 
 /* ********************************************************************** */
 
@@ -411,7 +409,8 @@ static CharPtr GetMolInfoCommentString (
 }
 
 static CharPtr GetStrForBankit (
-  UserObjectPtr uop
+  UserObjectPtr uop,
+  Boolean dumpMode
 )
 
 {
@@ -429,6 +428,8 @@ static CharPtr GetStrForBankit (
       uvc = ufp->data.ptrvalue;
     } else if (StringCmp(oip->str, "AdditionalComment") == 0) {
       bic = ufp->data.ptrvalue;
+    } else if (StringCmp(oip->str, "SmartComment") == 0 && dumpMode) {
+      bic = ufp->data.ptrvalue;
     }
   }
 
@@ -457,7 +458,7 @@ static CharPtr reftxt5 = " This record has been curated by ";
 static CharPtr reftxt6 = " This record is predicted by automated computational analysis.";
 static CharPtr reftxt7 = " This record is provided to represent a collection of whole genome shotgun sequences.";
 static CharPtr reftxt9 = " This record is derived from an annotated genomic sequence (";
-static CharPtr reftxt21 = "NCBI contigs are derived from assembled genomic sequence data.";
+static CharPtr reftxt21 = " NCBI contigs are derived from assembled genomic sequence data.";
 static CharPtr reftxt22 = " Features on this sequence have been produced for build ";
 static CharPtr reftxt23 = " of the NCBI's genome annotation";
 static CharPtr reftxt41 = " This record is based on preliminary annotation provided by ";
@@ -743,7 +744,7 @@ static void AddStrForRefTrack (
         FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
       }
 
-      FFAddOneString (ffstring, "].  ", FALSE, FALSE, TILDE_EXPAND);
+      FFAddOneString (ffstring, "].", FALSE, FALSE, TILDE_EXPAND);
     }
     if (generated) {
       FFAddOneString (ffstring, reftxtg, FALSE, FALSE, TILDE_IGNORE);
@@ -1299,11 +1300,13 @@ static CharPtr GetPrimaryStrForDelta (
 static CharPtr GetStrForTpaOrRefSeqHist (
   BioseqPtr bsp,
   Boolean isRefSeq,
-  Boolean isTsa
+  Boolean isTsa,
+  Boolean forcePrimaryBlock
 )
 
 {
   Boolean      accn;
+  Char         bfr [100];
   Char         buf [100];
   DbtagPtr     dbt;
   Int4         gi;
@@ -1339,6 +1342,7 @@ static CharPtr GetStrForTpaOrRefSeqHist (
       if (sip != NULL) {
         id = NULL;
         accn = FALSE;
+        buf [0] = '\0';
         if (sip->choice == SEQID_GI) {
           gi = (Int4) sip->data.intvalue;
           if (GetAccnVerFromServer (gi, buf)) {
@@ -1346,6 +1350,9 @@ static CharPtr GetStrForTpaOrRefSeqHist (
           } else {
             id = GetSeqIdForGI (gi);
           }
+          if (id == NULL && forcePrimaryBlock) {
+            id = SeqIdDup (sip);
+          }
         } else {
           id = SeqIdDup (sip);
         }
@@ -1363,58 +1370,58 @@ static CharPtr GetStrForTpaOrRefSeqHist (
             sprintf (tmp, "~%ld-%ld                                        ",
                      (long) (oldstop + 1), (long) (start));
             tmp [21] = '\0';
-            StringCpy (buf, "                                        ");
+            StringCpy (bfr, "                                        ");
             k = 0;
             if (StreamCacheSetup (bsp, NULL, 0, &sc)) {
               if (start - oldstop < 15) {
                 StreamCacheSetPosition (&sc, oldstop);
-                buf [k] = '"';
+                bfr [k] = '"';
                 k++;
                 max = start - oldstop;
                 for (j = 0; j < max; j++) {
                   residue = StreamCacheGetResidue (&sc);
-                  buf [k] = (Char) residue;
+                  bfr [k] = (Char) residue;
                   k++;
                 }
-                buf [k] = '"';
+                bfr [k] = '"';
                 k++;
               } else {
                 StreamCacheSetPosition (&sc, oldstop);
-                buf [k] = '"';
+                bfr [k] = '"';
                 k++;
                 for (j = 0; j < 4; j++) {
                   residue = StreamCacheGetResidue (&sc);
-                  buf [k] = (Char) residue;
+                  bfr [k] = (Char) residue;
                   k++;
                 }
-                buf [k] = '.';
+                bfr [k] = '.';
                 k++;
-                buf [k] = '.';
+                bfr [k] = '.';
                 k++;
-                buf [k] = '.';
+                bfr [k] = '.';
                 k++;
                 StreamCacheSetPosition (&sc, start - 4);
                 for (j = 0; j < 4; j++) {
                   residue = StreamCacheGetResidue (&sc);
-                  buf [k] = (Char) residue;
+                  bfr [k] = (Char) residue;
                   k++;
                 }
-                buf [k] = '"';
+                bfr [k] = '"';
                 k++;
               }
             } else {
               /*
-              StringCpy (buf, "inserted base(s)");
+              StringCpy (bfr, "inserted base(s)");
               */
             }
-            buf [k] = '\0';
-            StringCat (buf, "                                        ");
-            buf [18] = '\0';
-            StringCat (tmp, buf);
-            sprintf (buf, " %ld-%ld                                        ",
+            bfr [k] = '\0';
+            StringCat (bfr, "                                        ");
+            bfr [18] = '\0';
+            StringCat (tmp, bfr);
+            sprintf (bfr, " %ld-%ld                                        ",
                      (long) 1, (long) (start - oldstop));
-            buf [21] = '\0';
-            StringCat (tmp, buf);
+            bfr [21] = '\0';
+            StringCat (tmp, bfr);
             ValNodeCopyStr (&head, 0, tmp);
           }
           oldstop = stop + 1;
@@ -1578,183 +1585,6 @@ static CharPtr GetStrForGenome (
   return NULL;
 }
 
-static CharPtr StrucCommentFFEndPrint (
-  IntAsn2gbJobPtr ajp,
-  StringItemPtr ffstring,
-  FmtType format,
-  Int2 gb_init_indent,
-  Int2 gb_cont_indent,
-  Int2 eb_init_indent,
-  Int2 eb_cont_indent,
-  CharPtr eb_line_prefix
-)
-{
-  StringItemPtr temp = FFGetString(ajp);
-  CharPtr result;
-
-  if ( (ffstring == NULL) || (ajp == NULL) ) return NULL;
-
-  if (format == GENBANK_FMT || format == GENPEPT_FMT) {
-    FFLineWrap (temp, ffstring, gb_init_indent, gb_cont_indent, ASN2FF_GB_MAX - 12, NULL);
-  } else {
-    FFLineWrap (temp, ffstring, eb_init_indent, eb_cont_indent, ASN2FF_EMBL_MAX - 5, eb_line_prefix);
-  }
-  result = FFToCharPtr (temp);
-  FFRecycleString (ajp, temp);
-  return result;
-}
-
-static CharPtr GetStrForStructuredComment (
-  Asn2gbWorkPtr awp,
-  IntAsn2gbJobPtr ajp,
-  UserObjectPtr uop,
-  BioseqPtr bsp
-)
-
-{
-  UserFieldPtr   curr;
-  StringItemPtr  ffstring;
-  CharPtr        field;
-  ValNodePtr     head = NULL;
-  size_t         len;
-  size_t         max = 0;
-  ObjectIdPtr    oip;
-  CharPtr        prefix = NULL;
-  CharPtr        str;
-  CharPtr        suffix = NULL;
-  CharPtr        tmp;
-
-  if (awp == NULL || ajp == NULL || uop == NULL) return NULL;
-  if ((oip = uop->type) == NULL) return NULL;
-  if (StringCmp (oip->str, "StructuredComment") != 0) return NULL;
-
-  ffstring = FFGetString (ajp);
-  if (ffstring == NULL) return NULL;
-
-  for (curr = uop->data; curr != NULL; curr = curr->next) {
-   if (curr->choice != 1) continue;
-    oip = curr->label;
-    if (oip == NULL) continue;
-    field = oip->str;
-    if (StringHasNoText (field)) continue;
-    if (StringCmp (field, "StructuredCommentPrefix") == 0) {
-      str = (CharPtr) curr->data.ptrvalue;
-      if (StringDoesHaveText (str)) {
-        prefix = str;
-      }
-      continue;
-    }
-    if (StringCmp (field, "StructuredCommentSuffix") == 0) {
-      str = (CharPtr) curr->data.ptrvalue;
-      if (StringDoesHaveText (str)) {
-        suffix = str;
-      }
-      continue;
-    }
-    len = StringLen (field);
-    if (len > max) {
-      max = len;
-    }
-  }
-
-  if (StringHasNoText (prefix)) {
-    prefix = "##Metadata-START##";
-  }
-  if (StringHasNoText (suffix)) {
-    suffix = "##Metadata-END##";
-  }
-
-  if (StringDoesHaveText (prefix)) {
-    tmp = (CharPtr) MemNew (StringLen (prefix) + 4);
-    if (tmp != NULL) {
-      sprintf (tmp, "%s\n", prefix);
-      ValNodeAddStr (&head, 0, tmp);  
-    }
-  }
-  if (max > 79) {
-    for (curr = uop->data; curr != NULL; curr = curr->next) {
-     if (curr->choice != 1) continue;
-      oip = curr->label;
-      if (oip == NULL) continue;
-      field = oip->str;
-      if (StringHasNoText (field)) continue;
-      if (StringCmp (field, "StructuredCommentPrefix") == 0) continue;
-      if (StringCmp (field, "StructuredCommentSuffix") == 0) continue;
-      str = (CharPtr) curr->data.ptrvalue;
-      if (StringHasNoText (str)) continue;
-      ValNodeCopyStr (&head, 0, field);
-      ValNodeCopyStr (&head, 0, " ");
-      ValNodeCopyStr (&head, 0, str);
-      ValNodeCopyStr (&head, 0, "\n");
-    }
-  } else {
-    for (curr = uop->data; curr != NULL; curr = curr->next) {
-     if (curr->choice != 1) continue;
-      oip = curr->label;
-      if (oip == NULL) continue;
-      field = oip->str;
-      if (StringHasNoText (field)) continue;
-      if (StringCmp (field, "StructuredCommentPrefix") == 0) continue;
-      if (StringCmp (field, "StructuredCommentSuffix") == 0) continue;
-      str = (CharPtr) curr->data.ptrvalue;
-      if (StringHasNoText (str)) continue;
-      len = max + StringLen (str) + 4;
-      FFStartPrint (ffstring, GENBANK_FMT, 0, max + 1, field, max + 1, 0, max + 1, field, TRUE);
-      if (GetWWW (ajp) && StringCmp (field, "GOLD Stamp ID") == 0 && StringNCmp (str, "Gi", 2) == 0) {
-        FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
-        FF_Add_NCBI_Base_URL (ffstring, link_gold_stamp_id);
-        FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
-        FFAddOneString (ffstring, ".html", FALSE, FALSE, TILDE_EXPAND);
-        FFAddOneString (ffstring, "\">", FALSE, FALSE, TILDE_IGNORE);
-        FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
-        FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
-      } else {
-        FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
-      }
-      /*
-      FFAddOneString (ffstring, "\n", FALSE, FALSE, TILDE_EXPAND);
-      */
-      tmp = StrucCommentFFEndPrint (ajp, ffstring, awp->format, max + 1, max + 1, 0, max + 1, NULL);
-      ValNodeCopyStr (&head, 0, tmp);
-      MemFree (tmp);
-      FFRecycleString (ajp, ffstring);
-      ffstring = FFGetString (ajp);
-      /*
-      tmp = (CharPtr) MemNew (len);
-      if (tmp == NULL) continue;
-      StringCpy (tmp, field);
-      len = StringLen (tmp);
-      while (len < max) {
-        tmp [len] = ' ';
-        len++;
-      }
-      tmp [len] = '\0';
-      StringCat (tmp, " ");
-      StringCat (tmp, str);
-      StringCat (tmp, "\n");
-      ValNodeCopyStr (&head, 0, tmp);
-      MemFree (tmp);
-      */
-    }
-  }
-  if (StringDoesHaveText (suffix)) {
-    tmp = (CharPtr) MemNew (StringLen (suffix) + 4);
-    if (tmp != NULL) {
-      sprintf (tmp, "%s\n", suffix);
-      ValNodeAddStr (&head, 0, tmp);  
-    }
-  }
-
-  if (head == NULL) return NULL;
-
-  str = MergeFFValNodeStrs (head);
-  ValNodeFreeData (head);
-
-  FFRecycleString (ajp, ffstring);
-
-  return str;
-}
-
 static void AddAltPrimaryBlock (
   Asn2gbWorkPtr awp
 )
@@ -2022,7 +1852,7 @@ NLM_EXTERN void AddPrimaryBlock (
   ffstring = FFGetString(ajp);
   if ( ffstring == NULL ) return;
 
-  str = GetStrForTpaOrRefSeqHist (bsp, isRefSeq, isTsa);
+  str = GetStrForTpaOrRefSeqHist (bsp, isRefSeq, isTsa, awp->forcePrimaryBlock);
   if (str != NULL) {
 
     bbp = (BaseBlockPtr) Asn2gbAddBlock (awp, PRIMARY_BLOCK, sizeof (BaseBlock));
@@ -2212,6 +2042,7 @@ NLM_EXTERN void AddCommentBlock (
   Boolean            is_other = FALSE;
   Boolean            is_tpa = FALSE;
   Boolean            is_wgs = FALSE;
+  Boolean            isRefSeqStandard = FALSE;
   SeqLitPtr          litp;
   ObjectIdPtr        localID = NULL;
   Char               locusID [32];
@@ -2227,6 +2058,7 @@ NLM_EXTERN void AddCommentBlock (
   /*
   SeqFeatPtr         sfp;
   */
+  Boolean            showedLocalID = FALSE;
   Boolean            showGBBSource = FALSE;
   SeqIdPtr           sip;
   CharPtr            str;
@@ -2234,7 +2066,7 @@ NLM_EXTERN void AddCommentBlock (
   Char               tmp [32];
   TextSeqIdPtr       tsip;
   UserFieldPtr       ufp;
-  UserObjectPtr      uop = NULL;
+  UserObjectPtr      uop;
   CharPtr            wgsaccn = NULL;
   CharPtr            wgsname = NULL;
   StringItemPtr      ffstring = NULL;
@@ -2349,7 +2181,7 @@ NLM_EXTERN void AddCommentBlock (
               if ( GetWWW(ajp) ) {
                 FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
               }
-              FFAddOneString (ffstring, ": ", FALSE, FALSE, TILDE_IGNORE);
+              FFAddOneString (ffstring, ":", FALSE, FALSE, TILDE_IGNORE);
 
               FFAddOneString (ffstring, reftxt22, FALSE, FALSE, TILDE_EXPAND);
               FFAddOneString (ffstring, genomeBuildNumber, FALSE, FALSE, TILDE_EXPAND);
@@ -2457,7 +2289,7 @@ NLM_EXTERN void AddCommentBlock (
               if ( GetWWW(ajp) ) {
                 FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
               }
-              FFAddOneString (ffstring, ":  ", FALSE, FALSE, TILDE_IGNORE);
+              FFAddOneString (ffstring, ":", FALSE, FALSE, TILDE_IGNORE);
 
               if (! StringHasNoText (genomeBuildNumber)) {
                 FFAddOneString (ffstring, reftxt22, FALSE, FALSE, TILDE_EXPAND);
@@ -2651,6 +2483,29 @@ NLM_EXTERN void AddCommentBlock (
 
       is_tpa = TRUE;
 
+      tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+      if (tsip != NULL && tsip->accession != NULL) {
+        acclen = StringLen (tsip->accession);
+        if (acclen == 12) {
+          is_wgs = TRUE;
+          if (StringCmp (tsip->accession + 6, "000000") == 0) {
+            wgsaccn = tsip->accession;
+            wgsname = tsip->name; /* master accession has 8 zeroes, name has project version plus 6 zeroes */
+          }
+        } else if (acclen == 13) {
+          is_wgs = TRUE;
+          if (StringCmp (tsip->accession + 6, "0000000") == 0) {
+            wgsaccn = tsip->accession;
+            wgsname = tsip->name; /* master accession has 9 zeroes, name has project version plus 7 zeroes */
+          }
+        } else if (ajp->newSourceOrg && StringLen (tsip->accession) == 6) {
+          ch = tsip->accession [0];
+          if (ch == 'J' || ch == 'K' || ch == 'L' || ch == 'M') {
+            showGBBSource = TRUE;
+          }
+        }
+      }
+
     } else if (sip->choice == SEQID_GENBANK || sip->choice == SEQID_EMBL || sip->choice == SEQID_DDBJ) {
 
       is_collab = TRUE;
@@ -2733,11 +2588,13 @@ NLM_EXTERN void AddCommentBlock (
         if (! StringHasNoText (localID->str)) {
           if (StringLen (localID->str) < 1000) {
             sprintf (buf, "LocalID: %s", localID->str);
+            showedLocalID = TRUE;
           } else {
             sprintf (buf, "LocalID string too large");
           }
         } else {
           sprintf (buf, "LocalID: %ld", (long) localID->id);
+          showedLocalID = TRUE;
         }
 
         cbp = (CommentBlockPtr) Asn2gbAddBlock (awp, COMMENT_BLOCK, sizeof (CommentBlock));
@@ -2851,7 +2708,12 @@ NLM_EXTERN void AddCommentBlock (
       }
 
       if (! ajp->flags.hideBankItComment) {
-        str = GetStrForBankit (uop);
+        str = GetStrForBankit (uop, (Boolean) (awp->mode == DUMP_MODE));
+        if (str != NULL && showedLocalID && awp->mode == SEQUIN_MODE) {
+          if (StringNICmp (str, "Bankit Comment: LocalID:", 24) == 0) {
+            str = NULL;
+          }
+        }
         if (str != NULL) {
 
           cbp = (CommentBlockPtr) Asn2gbAddBlock (awp, COMMENT_BLOCK, sizeof (CommentBlock));
@@ -2958,6 +2820,62 @@ NLM_EXTERN void AddCommentBlock (
     sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &dcontext);
   }
 
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &dcontext);
+  while (sdp != NULL) {
+    uop = (UserObjectPtr) sdp->data.ptrvalue;
+    if (uop != NULL) {
+      oip = uop->type;
+      if (oip != NULL && StringCmp (oip->str, "RefSeqGene") == 0) {
+        for (ufp = uop->data; ufp != NULL; ufp = ufp->next) {
+          oip = ufp->label;
+          if (oip != NULL && StringCmp(oip->str, "Status") == 0 && ufp->choice == 1) {
+            str = (CharPtr) ufp->data.ptrvalue;
+            if (str != NULL && StringICmp (str, "Reference Standard") == 0) {
+              isRefSeqStandard = TRUE;
+            }
+          }
+        }
+      }
+    }
+    sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &dcontext);
+  }
+  if (isRefSeqStandard) {
+    cbp = (CommentBlockPtr) Asn2gbAddBlock (awp, COMMENT_BLOCK, sizeof (CommentBlock));
+    if (cbp != NULL) {
+
+      cbp->entityID = awp->entityID;
+      cbp->first = first;
+      first = FALSE;
+
+      if (cbp->first) {
+        FFStartPrint (ffstring, awp->format, 0, 12, "COMMENT", 12, 5, 5, "CC", TRUE);
+      } else {
+        FFStartPrint (ffstring, awp->format, 0, 12, NULL, 12, 5, 5, "CC", FALSE);
+      }
+
+        FFAddOneString (ffstring, "This sequence is a reference standard in the ",
+                        FALSE, FALSE, TILDE_IGNORE);
+      if ( GetWWW(ajp) ) {
+        FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
+        FF_Add_NCBI_Base_URL (ffstring, "http://www.ncbi.nlm.nih.gov/RefSeq/RSG");
+        FFAddOneString (ffstring, "\">", FALSE, FALSE, TILDE_IGNORE);
+        FFAddOneString (ffstring, "RefSeqGene", FALSE, FALSE, TILDE_IGNORE);
+        FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
+      } else {
+        FFAddOneString (ffstring, "RefSeqGene", FALSE, FALSE, TILDE_IGNORE);
+      }
+      FFAddOneString (ffstring, " project.", FALSE, FALSE, TILDE_IGNORE);
+
+      cbp->string = FFEndPrint(ajp, ffstring, awp->format, 12, 12, 5, 5, "CC");
+      FFRecycleString(ajp, ffstring);
+      ffstring = FFGetString(ajp);
+
+      if (awp->afp != NULL) {
+        DoImmediateFormat (awp->afp, (BaseBlockPtr) cbp);
+      }
+    }
+  }
+
   if (bsp->repr == Seq_repr_delta && bsp->seq_ext_type == 4 && is_wgs) {
     has_gaps = FALSE;
     for (dsp = (DeltaSeqPtr) bsp->seq_ext; dsp; dsp=dsp->next) {
@@ -3275,13 +3193,10 @@ NLM_EXTERN void AddCommentBlock (
 
   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &dcontext);
   while (sdp != NULL) {
-
     uop = (UserObjectPtr) sdp->data.ptrvalue;
     if (uop != NULL) {
-
-      str = GetStrForStructuredComment (awp, ajp, uop, bsp);
-      if (str != NULL) {
-
+      oip = uop->type;
+      if (oip != NULL && StringCmp (oip->str, "StructuredComment") == 0) {
         cbp = (CommentBlockPtr) Asn2gbAddBlock (awp, COMMENT_BLOCK, sizeof (CommentBlock));
         if (cbp != NULL) {
 
@@ -3291,24 +3206,10 @@ NLM_EXTERN void AddCommentBlock (
           cbp->first = first;
           first = FALSE;
 
-          if (cbp->first) {
-            FFStartPrint (ffstring, awp->format, 0, 12, "COMMENT", 12, 5, 5, "CC", TRUE);
-          } else {
-            FFStartPrint (ffstring, awp->format, 0, 12, NULL, 12, 5, 5, "CC", FALSE);
-            FFAddOneString (ffstring, "\n", FALSE, FALSE, TILDE_EXPAND);
-          }
-
-          FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
-
-          cbp->string = FFEndPrint(ajp, ffstring, awp->format, 12, 12, 5, 5, "CC");
-          FFRecycleString(ajp, ffstring);
-          ffstring = FFGetString(ajp);
-
           if (awp->afp != NULL) {
             DoImmediateFormat (awp->afp, (BaseBlockPtr) cbp);
           }
         }
-        MemFree (str);
       }
     }
     sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &dcontext);
@@ -4381,7 +4282,7 @@ NLM_EXTERN void AddSourceFeatBlock (
       }
     }
 
-    str = FFFlatLoc (ajp, bsp, &vn, (Boolean) (awp->style == MASTER_STYLE));
+    str = FFFlatLoc (ajp, bsp, &vn, (Boolean) (awp->style == MASTER_STYLE), FALSE);
     if ( GetWWW(ajp) ) {
       FF_www_featloc (ffstring, str);
     } else {
@@ -4732,6 +4633,8 @@ static void GetFeatsOnCdsProduct (
             ifp->mapToGen = FALSE;
             ifp->mapToMrna = FALSE;
             ifp->mapToPep = FALSE;
+            ifp->left = 0;
+            ifp->right = 0;
             ifp->firstfeat = awp->firstfeat;
             awp->firstfeat = FALSE;
 
@@ -4809,7 +4712,7 @@ static void GetRemoteFeatsOnCdsProduct (
       if (sap->type != 1) continue;
       for (sfp = (SeqFeatPtr) sap->data; sfp != NULL; sfp = sfp->next) {
         publist = NULL;
-        CleanUpSeqFeat (sfp, FALSE, FALSE, TRUE, &publist);
+        CleanUpSeqFeat (sfp, FALSE, FALSE, TRUE, TRUE, &publist);
         sfp->idx.subtype = FindFeatDefType (sfp);
         ValNodeFreeData (publist);
         ValNodeAddPointer (&head, 0, (Pointer) sfp);
@@ -4897,6 +4800,8 @@ static void GetRemoteFeatsOnCdsProduct (
             ifp->mapToGen = FALSE;
             ifp->mapToMrna = FALSE;
             ifp->mapToPep = FALSE;
+            ifp->left = 0;
+            ifp->right = 0;
             ifp->firstfeat = awp->firstfeat;
             awp->firstfeat = FALSE;
 
@@ -5347,6 +5252,18 @@ static Boolean LIBCALLBACK GetFeatsOnBioseq (
       }
       break;
 
+    case FEATDEF_operon:
+      /* operon requires FTQUAL_operon */
+      gbq = sfp->qual;
+      while (gbq != NULL) {
+        if (StringICmp (gbq->qual, "operon") == 0 && (StringDoesHaveText (gbq->val))) {
+          okay = TRUE;
+          break;
+        }
+        gbq = gbq->next;
+      }
+      break;
+
     case FEATDEF_ncRNA:
       /* ncRNA requires FTQUAL_ncRNA_class */
       gbq = sfp->qual;
@@ -5419,8 +5336,11 @@ static Boolean LIBCALLBACK GetFeatsOnBioseq (
   ifp->mapToGen = FALSE;
   ifp->mapToMrna = FALSE;
   ifp->mapToPep = FALSE;
+  ifp->left = 0;
+  ifp->right = 0;
   ifp->firstfeat = awp->firstfeat;
   awp->firstfeat = FALSE;
+
   /* this allows remote SNP, CDD, MGC, etc., not to be treated as local annotation */
   if (awp->entityID != fbp->entityID || fbp->itemID <= awp->localFeatCount) {
     awp->featseen = TRUE;
@@ -5444,6 +5364,7 @@ static Boolean LIBCALLBACK GetFeatsOnBioseq (
           } else if (slp->choice == SEQLOC_INT) {
             sintp = (SeqIntPtr) slp->data.ptrvalue;
             if (sintp != NULL &&
+                bsp != NULL &&
                 sintp->from == 0 &&
                 sintp->to == bsp->length - 1) {
               is_whole = TRUE;
@@ -5472,7 +5393,7 @@ static Boolean LIBCALLBACK GetFeatsOnBioseq (
 
   /* optionally map CDS from cDNA onto genomic */
 
-  if (awp->isGPS && ISA_na (bsp->mol) && awp->copyGpsCdsUp &&
+  if (awp->isGPS && bsp != NULL && ISA_na (bsp->mol) && awp->copyGpsCdsUp &&
       fcontext->featdeftype == FEATDEF_mRNA) {
     sip = SeqLocIdForProduct (sfp->product);
     bsp = BioseqFind (sip);
@@ -5492,6 +5413,8 @@ static Boolean LIBCALLBACK GetFeatsOnBioseq (
           ifp->mapToGen = TRUE;
           ifp->mapToMrna = FALSE;
           ifp->mapToPep = FALSE;
+          ifp->left = 0;
+          ifp->right = 0;
           ifp->firstfeat = awp->firstfeat;
           awp->firstfeat = FALSE;
 
@@ -5605,16 +5528,19 @@ static Boolean LIBCALLBACK GetFeatsOnSeg (
   Uint4            accntype;
   IntAsn2gbJobPtr  ajp;
   Asn2gbWorkPtr    awp;
+  BaseBlockPtr     bbp;
   BioseqPtr        bsp;
   time_t           currTime;
   Uint2            entityID;
   Int4             from;
+  ValNodePtr       gap;
   Int4             gi;
   Int4             left;
   SeqLocPtr        loc;
   CharPtr          ptr;
   Int4             right;
   SeqIdPtr         sip;
+  CharPtr          str;
   Int4             to;
   WgsAccnPtr       wap = NULL;
 
@@ -5624,6 +5550,26 @@ static Boolean LIBCALLBACK GetFeatsOnSeg (
   ajp = awp->ajp;
   if (ajp == NULL) return FALSE;
 
+  gap = awp->currfargap;
+  if (gap != NULL) {
+    awp->currfargap = gap->next;
+
+    str = (CharPtr) gap->data.ptrvalue;
+    if (StringDoesHaveText (str)) {
+
+      bbp = Asn2gbAddBlock (awp, FEATHEADER_BLOCK, sizeof (BaseBlock));
+      if (bbp != NULL) {
+
+        bbp->entityID = awp->entityID;
+        bbp->string = StringSave (str);
+
+        if (awp->afp != NULL) {
+          DoImmediateFormat (awp->afp, bbp);
+        }
+      }
+    }
+  }
+
   /* do not fetch outside of desired component */
 
   if (ajp->ajp.slp != NULL) {
@@ -5809,6 +5755,8 @@ NLM_EXTERN void AddFeatureBlock (
                 ifp->mapToMrna = TRUE;
                 ifp->mapToPep = FALSE;
                 ifp->isCDS = TRUE;
+                ifp->left = 0;
+                ifp->right = 0;
                 ifp->firstfeat = awp->firstfeat;
                 awp->firstfeat = FALSE;
 
@@ -5852,6 +5800,8 @@ NLM_EXTERN void AddFeatureBlock (
           awp->farFeatStartTime = GetSecs ();
         }
 
+        awp->currfargap = ajp->fargaps;
+
         /* if farFeatsSuppress first collect features on remote segments in MASTER_STYLE */
 
         SeqMgrExploreSegments (bsp, (Pointer) awp, GetFeatsOnSeg);
@@ -5894,6 +5844,8 @@ NLM_EXTERN void AddFeatureBlock (
           ifp->mapToMrna = FALSE;
           ifp->mapToPep = FALSE;
           ifp->isCDS = TRUE;
+          ifp->left = 0;
+          ifp->right = 0;
           ifp->firstfeat = awp->firstfeat;
           awp->firstfeat = FALSE;
 
@@ -5919,6 +5871,8 @@ NLM_EXTERN void AddFeatureBlock (
           ifp->mapToMrna = FALSE;
           ifp->mapToPep = FALSE;
           ifp->isCDS = TRUE;
+          ifp->left = 0;
+          ifp->right = 0;
           ifp->firstfeat = awp->firstfeat;
           awp->firstfeat = FALSE;
 
@@ -5954,6 +5908,8 @@ NLM_EXTERN void AddFeatureBlock (
           ifp->mapToGen = FALSE;
           ifp->mapToMrna = FALSE;
           ifp->mapToPep = TRUE;
+          ifp->left = 0;
+          ifp->right = 0;
           ifp->firstfeat = awp->firstfeat;
           awp->firstfeat = FALSE;
 
@@ -5979,6 +5935,8 @@ NLM_EXTERN void AddFeatureBlock (
         awp->farFeatStartTime = GetSecs ();
       }
 
+      awp->currfargap = ajp->fargaps;
+
       /* if not farFeatsSuppress now collect features on remote segments in MASTER_STYLE */
 
       SeqMgrExploreSegments (bsp, (Pointer) awp, GetFeatsOnSeg);
diff --git a/api/asn2gnb4.c b/api/asn2gnb4.c
index 5564f1e..6491f6d 100644
--- a/api/asn2gnb4.c
+++ b/api/asn2gnb4.c
@@ -30,7 +30,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 1.201 $
+* $Revision: 1.215 $
 *
 * File Description:  New GenBank flatfile generator - work in progress
 *
@@ -132,6 +132,7 @@ static FtQualType feat_qual_order [] = {
   FTQUAL_exception,
   FTQUAL_ribosomal_slippage,
   FTQUAL_trans_splicing,
+  FTQUAL_artificial_location,
 
   FTQUAL_note, 
   FTQUAL_citation,
@@ -259,6 +260,7 @@ static FeaturQual asn2gnbk_featur_quals [ASN2GNBK_TOTAL_FEATUR]  =  {
   { "",                   Qual_class_ignore         },
   { "allele",             Qual_class_quote          },
   { "anticodon",          Qual_class_anti_codon     },
+  { "artificial_location", Qual_class_boolean        },
   { "bond",               Qual_class_bond           },
   { "bond_type",          Qual_class_bond           },
   { "bound_moiety",       Qual_class_quote          },
@@ -955,6 +957,7 @@ static ValQual legalGbqualList [] = {
   { FEATDEF_tRNA , FTQUAL_label },
   { FEATDEF_tRNA , FTQUAL_map },
   { FEATDEF_tRNA , FTQUAL_old_locus_tag },
+  { FEATDEF_tRNA , FTQUAL_operon },
   { FEATDEF_tRNA , FTQUAL_product },
   { FEATDEF_tRNA , FTQUAL_standard_name },
 
@@ -1042,6 +1045,7 @@ static ValQual legalGbqualList [] = {
   { FEATDEF_D_segment , FTQUAL_standard_name },
 
   { FEATDEF_enhancer , FTQUAL_allele },
+  { FEATDEF_enhancer , FTQUAL_bound_moiety },
   { FEATDEF_enhancer , FTQUAL_label },
   { FEATDEF_enhancer , FTQUAL_map },
   { FEATDEF_enhancer , FTQUAL_old_locus_tag },
@@ -1198,6 +1202,7 @@ static ValQual legalGbqualList [] = {
   { FEATDEF_primer_bind , FTQUAL_standard_name },
 
   { FEATDEF_promoter , FTQUAL_allele },
+  { FEATDEF_promoter , FTQUAL_bound_moiety },
   { FEATDEF_promoter , FTQUAL_function },
   { FEATDEF_promoter , FTQUAL_label },
   { FEATDEF_promoter , FTQUAL_map },
@@ -1444,6 +1449,7 @@ static ValQual legalGbqualList [] = {
   { FEATDEF_operon , FTQUAL_standard_name },
 
   { FEATDEF_oriT , FTQUAL_allele },
+  { FEATDEF_oriT , FTQUAL_bound_moiety },
   { FEATDEF_oriT , FTQUAL_direction },
   { FEATDEF_oriT , FTQUAL_label },
   { FEATDEF_oriT , FTQUAL_map },
@@ -2657,6 +2663,7 @@ static FloatHi MolWtForProtFeat (
   CharPtr     str;
 
   if (bsp == NULL || sfp == NULL || ipp == NULL) return 0.0;
+  if (sfp->partial) return 0.0;
   prp = (ProtRefPtr) sfp->data.value.ptrvalue;
   if (prp == NULL) return 0.0;
 
@@ -2862,7 +2869,7 @@ static void FormatFeatureBlockQuals (
   Int2                 numcodons;
   Int2                 numsyns;
   ObjectIdPtr          oip;
-  Boolean              okay;
+  Boolean              okay = FALSE;
   Boolean              only_digits;
   BioseqPtr            pbsp;
   Int4                 pmid;
@@ -3689,7 +3696,7 @@ static void FormatFeatureBlockQuals (
         if (slp != NULL) {
           FFAddTextToString(ffstring, "/", asn2gnbk_featur_quals[idx].name, "=",
                             FALSE, TRUE, TILDE_IGNORE);
-          str = FFFlatLoc (ajp, target, slp, /* ajp->masterStyle */ FALSE);
+          str = FFFlatLoc (ajp, target, slp, /* ajp->masterStyle */ FALSE, FALSE);
           FFAddTextToString(ffstring, "\"", str, "\"", 
                             FALSE, TRUE, TILDE_TO_SPACES);
           FFAddOneChar(ffstring, '\n', FALSE);
@@ -3730,11 +3737,11 @@ static void FormatFeatureBlockQuals (
                   SeqIdFree (sip);
                   if (newloc != NULL) {
                     A2GBSeqLocReplaceID (newloc, ajp->ajp.slp);
-                    str = FFFlatLoc (ajp, target, newloc, ajp->masterStyle);
+                    str = FFFlatLoc (ajp, target, newloc, ajp->masterStyle, FALSE);
                     SeqLocFree (newloc);
                   }
                 } else {
-                  str = FFFlatLoc (ajp, target, slp, ajp->masterStyle);
+                  str = FFFlatLoc (ajp, target, slp, ajp->masterStyle, FALSE);
                 }
                 if (str != NULL) {
                   residue = cbaa.value.intvalue;
@@ -3797,7 +3804,7 @@ static void FormatFeatureBlockQuals (
               }
             }
           } else {
-            tmp = FFFlatLoc (ajp, target, slp, ajp->masterStyle);
+            tmp = FFFlatLoc (ajp, target, slp, ajp->masterStyle, FALSE);
             if (tmp != NULL) {
               FFAddTextToString (ffstring, "/anticodon=(pos:", tmp, ",",
                                  FALSE, FALSE, TILDE_IGNORE);
@@ -3987,11 +3994,13 @@ static void FormatFeatureBlockQuals (
           if (! StringHasNoText (buf)) {
             if (StringICmp (buf, protein_pid_g) != 0) {
               /* already sorted and uniqued by BasicSeqEntryCleanup, per feature */
+              if (dbt != NULL) {
               if (StringICmp (dbt->db, "LocusID") == 0 || StringICmp (dbt->db, "InterimID") == 0) {
                 if (FFStringSearch (ffstring, dbt->db, 0) >= 0) {
                   okay = FALSE;
                 }
               }
+              }
               if (okay) {
                 FFAddOneString(ffstring, "/db_xref=\"", FALSE, FALSE, TILDE_IGNORE);
                 FF_www_db_xref(ajp, ffstring, dbt->db, buf, bsp);
@@ -5242,7 +5251,7 @@ NLM_EXTERN void AddIntervalsToGbfeat (
           gbint->accession = StringSave (accn);
           if (gbfeat->intervals == NULL) {
             gbfeat->intervals = gbint;
-          } else {
+          } else if (last != NULL) {
             last->next = gbint;
           }
           last = gbint;
@@ -5259,6 +5268,7 @@ static CharPtr validExceptionString [] = {
   "RNA editing",
   "reasons given in citation",
   "rearrangement required for product",
+  "annotated by transcript or proteomic data",
   NULL
 };
 
@@ -5277,14 +5287,15 @@ static CharPtr validRefSeqExceptionString [] = {
   "transcribed product replaced",
   "translated product replaced",
   "transcribed pseudogene",
-  "annotated by transcript or proteomic data",
+  /*
   "heterogeneous population sequenced",
   "low-quality sequence region",
+  */
   "unextendable partial coding region",
   NULL
 };
 
-/* ribosomal slippage and trans-splicing now are separate qualifiers */
+/* ribosomal slippage, trans-splicing, and artificial location now are separate qualifiers */
 
 static void ParseException (
   CharPtr original,
@@ -5294,7 +5305,8 @@ static void ParseException (
   Boolean isRelaxed,
   Uint1 subtype,
   BoolPtr riboSlipP,
-  BoolPtr transSpliceP
+  BoolPtr transSpliceP,
+  BoolPtr artLocP
 )
 
 {
@@ -5308,6 +5320,7 @@ static void ParseException (
   *exception_note = NULL;
   *riboSlipP = FALSE;
   *transSpliceP = FALSE;
+  *artLocP = FALSE;
 
   if (StringHasNoText (original)) return;
 
@@ -5340,9 +5353,6 @@ static void ParseException (
           if (StringICmp (tmp, validRefSeqExceptionString [i]) == 0) {
             if (isRefSeq || isRelaxed) {
               ValNodeCopyStr (&excpt, 0, tmp);
-            } else if (StringICmp (tmp, "annotated by transcript or proteomic data") == 0) {
-              ValNodeCopyStr (&excpt, 0, "reasons given in citation");
-              ValNodeCopyStr (&note, 0, tmp);
             } else {
               ValNodeCopyStr (&note, 0, tmp);
             }
@@ -5375,6 +5385,24 @@ static void ParseException (
             ValNodeCopyStr (&note, 0, tmp);
           }
           found = TRUE;
+        } else if (StringICmp (tmp, "artificial location") == 0) {
+          if (subtype == FEATDEF_CDS ||
+              subtype == FEATDEF_mRNA) {
+            *artLocP = TRUE;
+          } else {
+            ValNodeCopyStr (&note, 0, tmp);
+          }
+          found = TRUE;
+        } else if (StringICmp (tmp, "heterogeneous population sequenced") == 0 ||
+                   StringICmp (tmp, "low-quality sequence region") == 0) {
+          if (subtype == FEATDEF_CDS ||
+              subtype == FEATDEF_mRNA) {
+            *artLocP = TRUE;
+            ValNodeCopyStr (&note, 0, tmp); /* also copy to note */
+          } else {
+            ValNodeCopyStr (&note, 0, tmp);
+          }
+          found = TRUE;
         }
       }
       if (! found) {
@@ -5534,7 +5562,8 @@ static SeqFeatPtr GetOverlappingGeneInEntity (
   Uint2 entityID,
   SeqMgrFeatContextPtr fcontext,
   SeqMgrFeatContextPtr gcontext,
-  SeqLocPtr locforgene
+  SeqLocPtr locforgene,
+  IntAsn2gbJobPtr ajp
 )
 
 {
@@ -5588,6 +5617,11 @@ static SeqFeatPtr GetOverlappingGeneInEntity (
   } else {
     if (fcontext->bad_order || fcontext->mixed_strand) {
       gene = SeqMgrGetOverlappingFeature (locforgene, FEATDEF_GENE, NULL, 0, NULL, LOCATION_SUBSET, gcontext);
+    } else if (ajp->multiIntervalGenes) {
+      gene = SeqMgrGetOverlappingFeature (locforgene, FEATDEF_GENE, NULL, 0, NULL, LOCATION_SUBSET, gcontext);
+      if (gene == NULL) {
+        gene = SeqMgrGetOverlappingGene (locforgene, gcontext);
+      }
     } else {
       gene = SeqMgrGetOverlappingGene (locforgene, gcontext);
     }
@@ -5613,6 +5647,52 @@ static Boolean LocStrandsMatch (SeqLocPtr loc1, SeqLocPtr loc2)
   return FALSE;
 }
 
+/*
+static CharPtr SeqLoc2Str (
+  SeqLocPtr slp
+)
+
+{
+  AsnIoBSPtr    aibp;
+  ByteStorePtr  bs;
+  Char          ch;
+  CharPtr       ptr;
+  CharPtr       str;
+
+  if (slp == NULL) return NULL;
+
+  bs = BSNew (1000);
+  if (bs == NULL) return NULL;
+  aibp = AsnIoBSOpen ("w", bs);
+  if (aibp == NULL) return NULL;
+
+  SeqLocAsnWrite (slp, aibp->aip, NULL);
+
+  AsnIoFlush (aibp->aip);
+  AsnIoBSClose (aibp);
+
+  str = BSMerge (bs, NULL);
+  BSFree (bs);
+
+  if (str == NULL) return NULL;
+
+  ptr = str;
+  ch = *ptr;
+  while (ch != '\0') {
+    if (ch == '\n' || ch == '\r' || ch == '\t') {
+      *ptr = ' ';
+    }
+    ptr++;
+    ch = *ptr;
+  }
+
+  TrimSpacesAndSemicolons (str);
+  Asn2gnbkCompressSpaces (str);
+
+  return str;
+}
+*/
+
 static CharPtr FormatFeatureBlockEx (
   IntAsn2gbJobPtr ajp,
   Asn2gbSectPtr asp,
@@ -5631,6 +5711,7 @@ static CharPtr FormatFeatureBlockEx (
   Uint1              aa;
   AnnotDescrPtr      adp;
   Boolean            annotDescCommentToComment;
+  Boolean            artLoc = FALSE;
   ValNodePtr         bad_inference = NULL;
   Int2               bondidx;
   BioseqPtr          bspx = NULL;
@@ -5668,6 +5749,7 @@ static CharPtr FormatFeatureBlockEx (
   Boolean            is_journalscan = FALSE;
   Boolean            is_other = FALSE;
   Boolean            is_misc_rna = FALSE;
+  Boolean            isGap = FALSE;
   Uint4              itemID;
   CharPtr            its_prod = NULL;
   CharPtr            key = NULL;
@@ -5728,7 +5810,11 @@ static CharPtr FormatFeatureBlockEx (
   UserObjectPtr      uop;
   ValNodePtr         vnp;
   StringItemPtr      ffstring;
-
+  /*
+  CharPtr            firstloc = NULL;
+  CharPtr            secondloc = NULL;
+  CharPtr            thirdloc = NULL;
+  */
 
   if (ajp == NULL || fcontext == NULL || qvp == NULL || ifp == NULL) return NULL;
 
@@ -5843,7 +5929,7 @@ static CharPtr FormatFeatureBlockEx (
     if (location == NULL) return NULL;
   
     sep = GetTopSeqEntryForEntityID (ajp->ajp.entityID);
-    if (sep == NULL && IS_Bioseq_set (sep)) {
+    if (sep != NULL && IS_Bioseq_set (sep)) {
       bssp = (BioseqSetPtr) sep->data.ptrvalue;
       if (bssp != NULL && bssp->_class == BioseqseqSet_class_gen_prod_set) {
         is_gps = TRUE;
@@ -5873,9 +5959,12 @@ static CharPtr FormatFeatureBlockEx (
             is_ed = TRUE;
             break;
           case SEQID_TPG :
+            is_ged = TRUE;
+            break;
           case SEQID_TPE :
           case SEQID_TPD :
             is_ged = TRUE;
+            is_ed = TRUE;
             break;
           default :
           break;
@@ -5888,6 +5977,7 @@ static CharPtr FormatFeatureBlockEx (
     }
 
     key = FindKeyFromFeatDefType (featdeftype, TRUE);
+    isGap = (Boolean) (featdeftype == FEATDEF_gap);
   
     if (format == GENPEPT_FMT && isProt) {
       if (featdeftype == FEATDEF_REGION) {
@@ -5917,6 +6007,11 @@ static CharPtr FormatFeatureBlockEx (
         key = "misc_feature";
       }
     }
+    if (featdeftype == FEATDEF_VARIATIONREF) {
+      if (ajp->mode == RELEASE_MODE || ajp->mode == ENTREZ_MODE) {
+        key = "misc_feature";
+      }
+    }
   
     /* deal with unmappable impfeats */
   
@@ -5965,11 +6060,33 @@ static CharPtr FormatFeatureBlockEx (
         */
         SeqIdFree (sip);
         if (newloc == NULL) return NULL;
+        /*
+        firstloc = SeqLoc2Str (newloc);
+        */
         A2GBSeqLocReplaceID (newloc, ajp->ajp.slp);
-        str = FFFlatLoc (ajp, target, newloc, ajp->masterStyle);
+        /*
+        secondloc = SeqLoc2Str (newloc);
+        */
+        str = FFFlatLoc (ajp, target, newloc, ajp->masterStyle, isGap);
         SeqLocFree (newloc);
+        /*
+        thirdloc = SeqLoc2Str (ajp->ajp.slp);
+        if (StringCmp (str, "?") != 0) {
+          firstloc = MemFree (firstloc);
+          secondloc = MemFree (secondloc);
+          thirdloc = MemFree (thirdloc);
+        }
+        */
       } else {
-        str = FFFlatLoc (ajp, target, location, ajp->masterStyle);
+        str = FFFlatLoc (ajp, target, location, ajp->masterStyle, isGap);
+        /*
+        if (StringCmp (str, "?") == 0) {
+          firstloc = SeqLoc2Str (location);
+          SeqIdWrite (target->id, buf, PRINTID_FASTA_LONG, sizeof (buf));
+          secondloc = StringSave (buf);
+          thirdloc = NULL;
+        }
+        */
       }
     } else {
       str = StringSave (imp->loc);
@@ -6008,6 +6125,11 @@ static CharPtr FormatFeatureBlockEx (
     locforgene = sfp->location;
   }
 
+  if (location != NULL) {
+   ifp->left = GetOffsetInBioseq (location, bsp, SEQLOC_LEFT_END);
+   ifp->right = GetOffsetInBioseq (location, bsp, SEQLOC_RIGHT_END);
+  }
+
   /* populate qualifier table from feature fields */
 
   /*
@@ -6146,9 +6268,9 @@ static CharPtr FormatFeatureBlockEx (
       /* first look for gene that exactly matches mat_peptide DNA projection */
 
       if (gene == NULL && grp == NULL && locformatpep != NULL) {
-        gene = GetOverlappingGeneInEntity (ajp->ajp.entityID, fcontext, &gcontext, locformatpep);
+        gene = GetOverlappingGeneInEntity (ajp->ajp.entityID, fcontext, &gcontext, locformatpep, ajp);
         if (gene == NULL && ajp->ajp.entityID != sfp->idx.entityID) {
-          gene = GetOverlappingGeneInEntity (sfp->idx.entityID, fcontext, &gcontext, locformatpep);
+          gene = GetOverlappingGeneInEntity (sfp->idx.entityID, fcontext, &gcontext, locformatpep, ajp);
         }
 
         if (gene != NULL) {
@@ -6175,9 +6297,9 @@ static CharPtr FormatFeatureBlockEx (
 
       if (gene == NULL && grp == NULL) {
         if (featdeftype != FEATDEF_primer_bind) {
-          gene = GetOverlappingGeneInEntity (ajp->ajp.entityID, fcontext, &gcontext, locforgene);
+          gene = GetOverlappingGeneInEntity (ajp->ajp.entityID, fcontext, &gcontext, locforgene, ajp);
           if (gene == NULL && ajp->ajp.entityID != sfp->idx.entityID) {
-            gene = GetOverlappingGeneInEntity (sfp->idx.entityID, fcontext, &gcontext, locforgene);
+            gene = GetOverlappingGeneInEntity (sfp->idx.entityID, fcontext, &gcontext, locforgene, ajp);
           }
         }
 
@@ -6760,8 +6882,8 @@ static CharPtr FormatFeatureBlockEx (
             if (rrp->ext.choice == 1) {
               if (rrp->type == 255) {
                 str = (CharPtr) rrp->ext.value.ptrvalue;
-                if (StringICmp (str, "ncRNA") == 0 ||
-                    StringICmp (str, "tmRNA") == 0) {
+                if (StringCmp (str, "ncRNA") == 0 ||
+                    StringCmp (str, "tmRNA") == 0) {
                    /* pick up product from gbqual */
                  } else if (StringICmp (str, "misc_RNA") == 0) {
                    is_misc_rna = TRUE;
@@ -6803,7 +6925,7 @@ static CharPtr FormatFeatureBlockEx (
             }
           }
         }
-        if (rrp->ext.choice == 3) {
+        if (rrp != NULL && rrp->ext.choice == 3) {
           rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
           if (rgp != NULL) {
             if (StringDoesHaveText (rgp->product)) {
@@ -7023,12 +7145,14 @@ static CharPtr FormatFeatureBlockEx (
                     (Boolean) (! ajp->flags.dropIllegalQuals),
                     sfp->idx.subtype,
                     &riboSlippage,
-                    &transSplice);
+                    &transSplice,
+                    &artLoc);
 
     qvp [FTQUAL_exception].str = exception_string;
     qvp [FTQUAL_exception_note].str = exception_note;
     qvp [FTQUAL_ribosomal_slippage].ble = riboSlippage;
     qvp [FTQUAL_trans_splicing].ble = transSplice;
+    qvp [FTQUAL_artificial_location].ble = artLoc;
 
     /*
     if (StringHasNoText (qvp [FTQUAL_exception].str)) {
@@ -7342,6 +7466,12 @@ static CharPtr FormatFeatureBlockEx (
   s_DisplayQVP(qvp, feat_qual_order);
 #endif
 
+  /*
+  qvp[FTQUAL_loc_debug_str1].str = firstloc;
+  qvp[FTQUAL_loc_debug_str2].str = secondloc;
+  qvp[FTQUAL_loc_debug_str3].str = thirdloc;
+  */
+
   /* optionally populate indexes for NCBI internal database */
 
   if (index != NULL) {
@@ -7368,6 +7498,12 @@ static CharPtr FormatFeatureBlockEx (
 
   SeqLocFree (loc);
 
+  /*
+  MemFree (firstloc);
+  MemFree (secondloc);
+  MemFree (thirdloc);
+  */
+
   ValNodeFreeData (illegal);
   MemFree (exception_string);
   MemFree (exception_note);
@@ -7617,14 +7753,16 @@ NLM_EXTERN void DoImmediateRemoteFeatureFormat (
       fprintf (afp->fp, "%s", str);
     }
     if (afp->ffwrite != NULL) {
-      afp->ffwrite (str, afp->userdata, blocktype, sfp->idx.entityID, OBJ_SEQFEAT, sfp->idx.itemID);
+      afp->ffwrite (str, afp->userdata, blocktype, sfp->idx.entityID, OBJ_SEQFEAT,
+                    sfp->idx.itemID, fcontext.left, fcontext.right);
     }
   } else {
     if (afp->fp != NULL) {
       fprintf (afp->fp, "?\n");
     }
     if (afp->ffwrite != NULL) {
-      afp->ffwrite ("?\n", afp->userdata, blocktype, sfp->idx.entityID, OBJ_SEQFEAT, sfp->idx.itemID);
+      afp->ffwrite ("?\n", afp->userdata, blocktype, sfp->idx.entityID, OBJ_SEQFEAT,
+                    sfp->idx.itemID, fcontext.left, fcontext.right);
     }
   }
 
diff --git a/api/asn2gnb5.c b/api/asn2gnb5.c
index 99b3b6f..724eab3 100644
--- a/api/asn2gnb5.c
+++ b/api/asn2gnb5.c
@@ -30,7 +30,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 1.155 $
+* $Revision: 1.171 $
 *
 * File Description:  New GenBank flatfile generator - work in progress
 *
@@ -72,6 +72,7 @@ static CharPtr link_uspto = "http://patft.uspto.gov/netacgi/nph-Parser?patentnum
 
 static CharPtr link_cambia = "http://www.patentlens.net/patentlens/simple.cgi?patnum=";
 
+static CharPtr link_doi = "http://dx.doi.org/";
 
 
 /* www utility functions */
@@ -122,7 +123,9 @@ typedef struct dbxrefurldata {
 
 static UrlData Nlm_url_base [] = {
   {"AceView/WormGenes",     "http://www.ncbi.nlm.nih.gov/IEB/Research/Acembly/av.cgi?db=worm&c=gene&q="},
-  {"AFTOL",                 "http://aftol.biology.duke.edu/pub/displayTaxonInfo?aftol_id="},
+  {"AFTOL",                 "http://aftol1.biology.duke.edu/pub/displayTaxonInfo?aftol_id="},
+  {"AntWeb",                "http://www.antweb.org/specimen.do?name="},
+  {"APHIDBASE",             "http://webapps1.genouest.org/grs-1.0/grs?reportID=chado_genome_report&objectID="},
   {"ApiDB",                 "http://www.apidb.org/apidb/showRecord.do?name=GeneRecordClasses.ApiDBGeneRecordClass&primary_key="},
   {"ApiDB_CryptoDB",        "http://cryptodb.org/cryptodb/showRecord.do?name=GeneRecordClasses.GeneRecordClass&project_id=&primary_key="},
   {"ApiDB_PlasmoDB",        "http://www.plasmodb.org/plasmo/showRecord.do?name=GeneRecordClasses.GeneRecordClass&project_id=&primary_key="},
@@ -130,8 +133,8 @@ static UrlData Nlm_url_base [] = {
   {"ASAP",                  "https://asap.ahabs.wisc.edu/annotation/php/feature_info.php?FeatureID="},
   {"ATCC",                  "http://www.atcc.org/SearchCatalogs/linkin?id="},
   {"Axeldb",                "http://www.dkfz-heidelberg.de/tbi/services/axeldb/clone/xenopus?name="},
+  {"BEEBASE",               "http://genomes.arc.georgetown.edu/cgi-bin/gbrowse/bee_genome4/?name="},
   {"BEETLEBASE",            "http://www.beetlebase.org/cgi-bin/report.cgi?name="},
-  {"BioHealthBase",         "http://www.biohealthbase.org/GSearch/fluSegmentDetails.do?bhbSubmissionId="},
   {"BOLD",                  "http://www.boldsystems.org/connectivity/specimenlookup.php?processid="},
   {"CCDS",                  "http://www.ncbi.nlm.nih.gov/CCDS/CcdsBrowse.cgi?REQUEST=CCDS&DATA="},
   {"CDD",                   "http://www.ncbi.nlm.nih.gov/Structure/cdd/cddsrv.cgi?uid="},
@@ -150,15 +153,15 @@ static UrlData Nlm_url_base [] = {
   {"FANTOM_DB",             "http://fantom.gsc.riken.jp/db/annotate/main.cgi?masterid="},
   {"FLYBASE",               "http://flybase.bio.indiana.edu/.bin/fbidq.html?"},
   {"GABI",                  "http://www.gabipd.org/database/cgi-bin/GreenCards.pl.cgi?Mode=ShowSequence&App=ncbi&SequenceId="},
-  {"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="},
+  {"GeneDB",                "http://old.genedb.org/genedb/Search?organism=All%3A*&name="},
   {"GeneID",                "http://www.ncbi.nlm.nih.gov/sites/entrez?db=gene&cmd=Retrieve&dopt=full_report&list_uids="},
   {"GO",                    "http://amigo.geneontology.org/cgi-bin/amigo/go.cgi?view=details&depth=1&query=GO:"},
   {"GOA",                   "http://www.ebi.ac.uk/ego/GProtein?ac="},
-  {"GreengenesID",          "http://greengenes.lbl.gov/cgi-bin/show_one_record_v2.pl?prokMSA_id="},
+  {"Greengenes",            "http://greengenes.lbl.gov/cgi-bin/show_one_record_v2.pl?prokMSA_id="},
   {"GRIN",                  "http://www.ars-grin.gov/cgi-bin/npgs/acc/display.pl?"},
   {"H-InvDB",               "http://www.h-invitational.jp"},
   {"HGNC",                  "http://www.genenames.org/data/hgnc_data.php?hgnc_id="},
-  {"HMPID",                 "http://www.hmpdacc-resources.org/cgi-bin/hmp_catalog/main.cgi?section=HmpSummary&page=displayHmpProject&hmp_id="},
+  {"HMP",                   "http://www.hmpdacc-resources.org/cgi-bin/hmp_catalog/main.cgi?section=HmpSummary&page=displayHmpProject&hmp_id="},
   {"HOMD",                  "http://www.homd.org/"},
   {"HPRD",                  "http://www.hprd.org/protein/"},
   {"HSSP",                  "http://srs.ebi.ac.uk/srsbin/cgi-bin/wgetz?-newId+-e+hssp-ID:"},
@@ -166,16 +169,18 @@ static UrlData Nlm_url_base [] = {
   {"IMGT/LIGM",             "http://imgt.cines.fr:8104/cgi-bin/IMGTlect.jv?query=202+"},
   {"InterimID",             "http://www.ncbi.nlm.nih.gov/LocusLink/LocRpt.cgi?l="},
   {"InterPro",              "http://www.ebi.ac.uk/interpro/ISearch?mode=ipr&query="},
+  {"IRD",                   "http://www.fludb.org/brc/fluSegmentDetails.do?irdSubmissionId="},
   {"ISD",                   "http://www.flu.lanl.gov/search/view_record.html?accession="},
   {"ISFinder",              "http://www-is.biotoul.fr/scripts/is/is_spec.idc?name="},
   {"JCM",                   "http://www.jcm.riken.go.jp/cgi-bin/jcm/jcm_number?JCM="},
   {"JGIDB",                 "http://genome.jgi-psf.org/cgi-bin/jgrs?id="},
   {"LocusID",               "http://www.ncbi.nlm.nih.gov/LocusLink/LocRpt.cgi?l="},
-  {"MaizeGDB",              "http://www.maizegdb.org/cgi-bin/displaylocusrecord.cgi?id="},
+  {"MaizeGDB",              "http://www.maizegdb.org/supersearch.php?show=loc&pattern="},
   {"MGI",                   "http://www.informatics.jax.org/searches/accession_report.cgi?id=MGI:"},
   {"MIM",                   "http://www.ncbi.nlm.nih.gov/entrez/dispomim.cgi?id="},
-  {"miRBase",               "http://microrna.sanger.ac.uk/cgi-bin/sequences/mirna_entry.pl?acc="},
+  {"miRBase",               "http://www.mirbase.org/cgi-bin/mirna_entry.pl?acc="},
   {"MycoBank",              "http://www.mycobank.org/MycoTaxo.aspx?Link=T&Rec="},
+  {"NASONIABASE",           "http://genomes.arc.georgetown.edu/cgi-bin/gbrowse/nasonia10_scaffold/?name="},
   {"NBRC",                  "http://www.nbrc.nite.go.jp/NBRC2/NBRCCatalogueDetailServlet?ID=NBRC&CAT="},
   {"NextDB",                "http://nematode.lab.nig.ac.jp/cgi-bin/db/ShowGeneInfo.sh?celk="},
   {"niaEST",                "http://lgsun.grc.nia.nih.gov/cgi-bin/pro3?sname1="},
@@ -198,6 +203,7 @@ static UrlData Nlm_url_base [] = {
   {"SEED",                  "http://www.theseed.org/linkin.cgi?id="},
   {"SGD",                   "http://db.yeastgenome.org/cgi-bin/SGD/locus.pl?locus="},
   {"SGN",                   "http://www.sgn.cornell.edu/search/est.pl?request_type=7&request_id="},
+  {"SK-FST",                "http://aafc-aac.usask.ca/fst/"},
   {"SubtiList",             "http://genolist.pasteur.fr/SubtiList/genome.cgi?external_query+"},
   {"TAIR",                  "http://www.arabidopsis.org/servlets/TairObject?type=locus&name="},
   {"taxon",                 "http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi?"},
@@ -256,13 +262,10 @@ static void FF_www_get_url (
 {
   CharPtr       base = NULL, prefix = NULL, profix = NULL, ident = NULL, suffix = NULL, url = NULL, ptr, str;
   Char          ch, buf [128], id [20], taxname [128];
-  Boolean       is_accession;
   /*
   Boolean       is_numeric;
   */
   Int2          R;
-  SeqIdPtr      sip;
-  TextSeqIdPtr  tsip;
 
   if (ffstring == NULL || StringHasNoText (db) || StringHasNoText (identifier)) return;
 
@@ -293,53 +296,9 @@ static void FF_www_get_url (
   /* special cases */
 
 
-  if (StringCmp (db, "BioHealthBase") == 0) {
-
-    is_accession = FALSE;
+  if (StringCmp (db, "IRD") == 0) {
 
-    if (bsp != NULL && ValidateAccn (identifier) == 0) {
-      for (sip = bsp->id; sip != NULL; sip = sip->next) {
-        switch (sip->choice) {
-          case SEQID_GENBANK :
-          case SEQID_EMBL :
-          case SEQID_DDBJ :
-          case SEQID_TPG :
-          case SEQID_TPE :
-          case SEQID_TPD :
-          case SEQID_OTHER :
-            tsip = (TextSeqIdPtr) sip->data.ptrvalue;
-            if (tsip != NULL) {
-              if (StringICmp (tsip->accession, identifier) == 0) {
-                is_accession = TRUE;
-              }
-            }
-            break;
-          default :
-            break;
-        }
-      }
-    }
-
-    if (is_accession && bsp != NULL &&
-        BioseqToGeneticCode (bsp, NULL, NULL, NULL, taxname, sizeof (taxname), NULL)) {
-      ptr = StringChr (taxname, ' ');
-      if (ptr != NULL) {
-        *ptr = '\0';
-      }
-      ch = taxname [0];
-      if (IS_UPPER (ch)) {
-        taxname [0] = TO_LOWER (ch);
-      }
-      if (StringNICmp (taxname, "influenza", 9) == 0) {
-        url = "http://www.biohealthbase.org/GSearch/fluSegmentDetails.do?decorator=";
-        prefix = taxname;
-        profix = "&ncbiGenomicAccession=";
-      } else {
-        url = "http://www.biohealthbase.org/GSearch/details.do?decorator=";
-        prefix = taxname;
-        profix = "&locus=";
-      }
-    }
+    suffix = "&decorator=influenza";
 
   } else if (StringCmp (db, "dbSTS") == 0) {
 
@@ -373,11 +332,9 @@ static void FF_www_get_url (
 
   } else if (StringCmp (db, "dictyBase") == 0) {
 
-    /*
-    if (StringChr (identifier, '_') == NULL) {
-      url = "http://dictybase.org/db/cgi-bin/feature_page.pl?primary_id=";
+    if (StringChr (identifier, '_') != NULL) {
+      url = "http://dictybase.org/db/cgi-bin/gene_page.pl?primary_id=";
     }
-    */
 
   } else if (StringCmp (db, "GDB") == 0) {
 
@@ -446,6 +403,10 @@ static void FF_www_get_url (
 
     suffix = ".html";
 
+  } else if (StringCmp (db, "SK-FST") == 0) {
+
+    ident = NULL;
+
   } else if (StringCmp (db, "taxon") == 0) {
 
     ch = *identifier;
@@ -1534,7 +1495,7 @@ static CharPtr FormatCitJour (
   CharPtr     part_sup = NULL;
   CharPtr     part_supi = NULL;
   CharPtr     rsult = NULL;
-  CharPtr     title;
+  CharPtr     title = NULL;
   ValNodePtr  ttl;
   CharPtr     volume;
   Char        year [8];
@@ -1589,7 +1550,9 @@ static CharPtr FormatCitJour (
     return StringSave (buf);
   }
 
+  if (ttl != NULL) {
   title = (CharPtr) ttl->data.ptrvalue;
+  }
   if (StringLen (title) < 3) return StringSave (".");
 
   /*
@@ -2059,8 +2022,11 @@ static CharPtr FormatCitBook (
   /* Convert the title to upper case and */
   /* add it to the string.               */
 
-  for ( p = bookTitle; *p; p++)
+  if (bookTitle != NULL) {
+    for ( p = bookTitle; *p; p++) {
     *p = TO_UPPER(*p);
+    }
+  }
 
   /* temp = StringMove(temp, "Book: "); */
   temp = StringMove(temp, "(in) ");
@@ -2848,6 +2814,36 @@ static Int4 GetPmid (
   return 0;
 }
 
+static CharPtr GetDOI (
+  PubdescPtr pdp
+)
+
+{
+  ArticleIdPtr  aip;
+  CitArtPtr     cap;
+  ValNodePtr    vnp;
+
+  if (pdp == NULL) return 0;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    switch (vnp->choice) {
+      case PUB_Article:
+        cap = (CitArtPtr) vnp->data.ptrvalue;
+        if (cap!= NULL && cap->ids != NULL) {
+          for (aip = cap->ids; aip != NULL; aip = aip->next) {
+            if (aip->choice == ARTICLEID_DOI) {
+              return (CharPtr) aip->data.ptrvalue;
+            }
+          }
+        }
+      default :
+        break;
+    }
+  }
+
+  return 0;
+}
+
 NLM_EXTERN CharPtr CleanQualValue (
   CharPtr str
 )
@@ -3146,6 +3142,7 @@ NLM_EXTERN CharPtr FormatReferenceBlock (
   CitRetractPtr      crp;
   CitSubPtr          csp = NULL;
   SeqMgrDescContext  dcontext;
+  CharPtr            doi = NULL;
   SeqMgrFeatContext  fcontext;
   Int4               gibbsq;
   GBReferencePtr     gbref = NULL;
@@ -3445,7 +3442,7 @@ NLM_EXTERN CharPtr FormatReferenceBlock (
     } else if (afp->format == EMBL_FMT || afp->format == EMBLPEPT_FMT) {
       trailingPeriod = FALSE;
       len = StringLen (str);
-      if (len > 0 && str [len - 1] != '.') {
+      if (len > 0 && str != NULL && str [len - 1] != '.') {
         suffix = ".;";
       } else {
         suffix = ";";
@@ -3616,7 +3613,7 @@ NLM_EXTERN CharPtr FormatReferenceBlock (
               for (ids = cap->ids; ids != NULL; ids = ids->next) {
                 if (ids->choice == ARTICLEID_DOI) {
                   tmp = (CharPtr) ids->data.ptrvalue;
-                  if (StringDoesHaveText (tmp)) {
+                  if (StringDoesHaveText (tmp) && StringNCmp (tmp, "10.", 3) == 0) {
                     gxp = GBXrefNew ();
                     if (gxp != NULL) {
                       gxp->dbname = StringSave ("doi");
@@ -4016,6 +4013,34 @@ NLM_EXTERN CharPtr FormatReferenceBlock (
 
   }
 
+    if (pmid == 0 && muid == 0) {
+      doi = GetDOI (pdp);
+      if (StringDoesHaveText (doi) && StringNCmp (doi, "10.", 3) == 0) {
+        FFRecycleString(ajp, temp);
+        temp = FFGetString(ajp);
+
+        if (remprefix != NULL) {
+          ValNodeCopyStr (&remarks, 0, remprefix);
+        }
+        remprefix = "; ";
+        FFStartPrint (temp, afp->format, 2, 12, prefix, 12, 5, 5, NULL, FALSE);
+        if (GetWWW (ajp) && (! CommentHasSuspiciousHtml (ajp, doi))) {
+          FFAddOneString (temp, "DOI: ", FALSE, FALSE, TILDE_EXPAND);
+          FFAddOneString (temp, "<a href=\"", FALSE, FALSE, TILDE_EXPAND);
+          FFAddOneString (temp, link_doi, FALSE, FALSE, TILDE_EXPAND);
+          FFAddOneString (temp, doi, FALSE, FALSE, TILDE_EXPAND);
+          FFAddOneString (temp, "\">", FALSE, FALSE, TILDE_EXPAND);
+          FFAddOneString (temp, doi, FALSE, FALSE, TILDE_EXPAND);
+          FFAddOneString (temp, "</a>", FALSE, FALSE, TILDE_EXPAND);
+        } else {
+          FFAddOneString (temp, "DOI: ", FALSE, FALSE, TILDE_EXPAND);
+          FFAddOneString (temp, doi, FALSE, FALSE, TILDE_EXPAND);
+        }
+        FFLineWrap(ffstring, temp, 12, 12, ASN2FF_GB_MAX, NULL);
+        prefix = NULL;
+      }
+    }
+
   str = FFToCharPtr(ffstring);
 
   if (gbseq != NULL) {
diff --git a/api/asn2gnb6.c b/api/asn2gnb6.c
index 3abbb4f..a70c1f5 100644
--- a/api/asn2gnb6.c
+++ b/api/asn2gnb6.c
@@ -30,7 +30,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 1.198 $
+* $Revision: 1.227 $
 *
 * File Description:  New GenBank flatfile generator - work in progress
 *
@@ -73,7 +73,7 @@ static CharPtr link_seqp = "http://www.ncbi.nlm.nih.gov/protein/";
 
 static CharPtr link_lat_lon = "http://www.ncbi.nlm.nih.gov/projects/Sequin/latlonview.html?";
 
-
+static CharPtr link_gold_stamp_id = "http://genomesonline.org/GOLD_CARDS/";
 
 
 /* ordering arrays for qualifiers and note components */
@@ -111,6 +111,7 @@ static SourceType source_qual_order [] = {
   SCQUAL_clone,
   SCQUAL_sub_clone,
   SCQUAL_haplotype,
+  SCQUAL_haplogroup,
   SCQUAL_sex,
   SCQUAL_mating_type,
   SCQUAL_cell_line,
@@ -190,8 +191,6 @@ static SourceType source_desc_note_order [] = {
   SCQUAL_teleomorph,
   SCQUAL_breed,
 
-  SCQUAL_haplogroup,
-
   SCQUAL_metagenome_source,
   SCQUAL_metagenome_note,
 
@@ -244,8 +243,6 @@ static SourceType source_feat_note_order [] = {
   SCQUAL_teleomorph,
   SCQUAL_breed,
   
-  SCQUAL_haplogroup,
-  
   SCQUAL_metagenome_source,
   SCQUAL_metagenome_note,
 
@@ -436,6 +433,8 @@ NLM_EXTERN SourceType subSourceToSourceIdx [42] = {
 NLM_EXTERN CharPtr legalDbXrefs [] = {
   "AceView/WormGenes",
   "AFTOL",
+  "AntWeb",
+  "APHIDBASE",
   "ApiDB",
   "ApiDB_CryptoDB",
   "ApiDB_PlasmoDB",
@@ -448,7 +447,6 @@ NLM_EXTERN CharPtr legalDbXrefs [] = {
   "BDGP_EST",
   "BDGP_INS",
   "BEETLEBASE",
-  "BioHealthBase",
   "BOLD",
   "CDD",
   "CK",
@@ -472,11 +470,11 @@ NLM_EXTERN CharPtr legalDbXrefs [] = {
   "GeneID",
   "GO",
   "GOA",
-  "GreengenesID",
+  "Greengenes",
   "GRIN",
   "H-InvDB",
   "HGNC",
-  "HMPID",
+  "HMP",
   "HOMD",
   "HSSP",
   "IMGT/GENE-DB",
@@ -484,6 +482,7 @@ NLM_EXTERN CharPtr legalDbXrefs [] = {
   "IMGT/LIGM",
   "InterimID",
   "InterPro",
+  "IRD",
   "ISD",
   "ISFinder",
   "JCM",
@@ -537,13 +536,16 @@ NLM_EXTERN CharPtr legalDbXrefs [] = {
 
 NLM_EXTERN CharPtr legalSrcDbXrefs [] = {
   "AFTOL",
+  "AntWeb",
   "ATCC",
   "ATCC(dna)",
   "ATCC(in host)",
   "BOLD",
   "FANTOM_DB",
   "FLYBASE",
+  "Greengenes",
   "GRIN",
+  "HMP",
   "HOMD",
   "IMGT/HLA",
   "IMGT/LIGM",
@@ -559,14 +561,18 @@ NLM_EXTERN CharPtr legalSrcDbXrefs [] = {
 };
 
 NLM_EXTERN CharPtr legalRefSeqDbXrefs [] = {
+  "BEEBASE",
   "CCDS",
   "CGNC",
   "CloneID",
   "ECOCYC",
   "HPRD",
+  "LRG",
   "miRBase",
+  "NASONIABASE",
   "PBR",
   "REBASE",
+  "SK-FST",
   "TAIR",
   "VBRC",
   NULL
@@ -1313,7 +1319,7 @@ static CharPtr FindUrlEnding(CharPtr str) {
   return ptr;
 }
 
-static Boolean CommentHasSuspiciousHtml (
+NLM_EXTERN Boolean CommentHasSuspiciousHtml (
   IntAsn2gbJobPtr ajp,
   CharPtr searchString
 )
@@ -1405,48 +1411,439 @@ NLM_EXTERN void AddCommentWithURLlinks (
   }
 }
 
+static CharPtr StrucCommentFFEndPrint (
+  IntAsn2gbJobPtr ajp,
+  StringItemPtr ffstring,
+  FmtType format,
+  Int2 gb_init_indent,
+  Int2 gb_cont_indent,
+  Int2 eb_init_indent,
+  Int2 eb_cont_indent,
+  CharPtr eb_line_prefix
+)
+{
+  StringItemPtr temp = FFGetString(ajp);
+  CharPtr result;
+
+  if ( (ffstring == NULL) || (ajp == NULL) ) return NULL;
+
+  if (format == GENBANK_FMT || format == GENPEPT_FMT) {
+    FFLineWrap (temp, ffstring, gb_init_indent, gb_cont_indent, ASN2FF_GB_MAX - 12, NULL);
+  } else {
+    FFLineWrap (temp, ffstring, eb_init_indent, eb_cont_indent, ASN2FF_EMBL_MAX - 5, eb_line_prefix);
+  }
+  result = FFToCharPtr (temp);
+  FFRecycleString (ajp, temp);
+  return result;
+}
+
+static size_t ThresholdForStructuredCommentColumnarDisplay (
+  FmtType format
+)
+{
+  // We are trying to make those structured comments look pretty. However, if the first column gets
+  //  too big, the printout starts to look ugly. This function attempts to define the first column
+  //  extent at which pretty turns into ugly.
+  
+  const size_t MAX_COLUMN_WIDTH = 45;
+  switch ( format ) {
+  
+    case GENBANK_FMT:
+    case GENPEPT_FMT:
+      return MIN( MAX_COLUMN_WIDTH, ASN2FF_GB_MAX - 12 );
+      
+    default:
+      return MIN( MAX_COLUMN_WIDTH, ASN2FF_EMBL_MAX - 5 );
+  }
+}
+
+static CharPtr GetStrForStructuredComment (
+  IntAsn2gbJobPtr ajp,
+  UserObjectPtr uop
+)
+
+{
+  Char           buf [120];
+  UserFieldPtr   curr;
+  StringItemPtr  ffstring;
+  CharPtr        field;
+  ValNodePtr     head = NULL;
+  size_t         len;
+  size_t         max = 0;
+  ObjectIdPtr    oip;
+  CharPtr        prefix = NULL;
+  CharPtr        str;
+  CharPtr        suffix = NULL;
+  CharPtr        tmp;
+
+  if (ajp == NULL || uop == NULL) return NULL;
+  if ((oip = uop->type) == NULL) return NULL;
+  if (StringCmp (oip->str, "StructuredComment") != 0) return NULL;
+
+  ffstring = FFGetString (ajp);
+  if (ffstring == NULL) return NULL;
+
+  for (curr = uop->data; curr != NULL; curr = curr->next) {
+   if (curr->choice != 1) continue;
+    oip = curr->label;
+    if (oip == NULL) continue;
+    field = oip->str;
+    if (StringHasNoText (field)) continue;
+    if (StringCmp (field, "StructuredCommentPrefix") == 0) {
+      str = (CharPtr) curr->data.ptrvalue;
+      if (StringDoesHaveText (str)) {
+        prefix = str;
+      }
+      continue;
+    }
+    if (StringCmp (field, "StructuredCommentSuffix") == 0) {
+      str = (CharPtr) curr->data.ptrvalue;
+      if (StringDoesHaveText (str)) {
+        suffix = str;
+      }
+      continue;
+    }
+    len = StringLen (field);
+    if (len > max) {
+      max = len;
+    }
+  }
+
+  if (StringHasNoText (prefix)) {
+    prefix = "##Metadata-START##";
+  }
+  if (StringHasNoText (suffix)) {
+    suffix = "##Metadata-END##";
+  }
+
+  if (StringDoesHaveText (prefix)) {
+    tmp = (CharPtr) MemNew (StringLen (prefix) + 4);
+    if (tmp != NULL) {
+      sprintf (tmp, "%s\n", prefix);
+      ValNodeAddStr (&head, 0, tmp);  
+    }
+  }
+  if (max > ThresholdForStructuredCommentColumnarDisplay (ajp->format)) {
+    for (curr = uop->data; curr != NULL; curr = curr->next) {
+     if (curr->choice != 1) continue;
+      oip = curr->label;
+      if (oip == NULL) continue;
+      field = oip->str;
+      if (StringHasNoText (field)) continue;
+      if (StringCmp (field, "StructuredCommentPrefix") == 0) continue;
+      if (StringCmp (field, "StructuredCommentSuffix") == 0) continue;
+      str = (CharPtr) curr->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      ValNodeCopyStr (&head, 0, field);
+      /*
+      ValNodeCopyStr (&head, 0, " ");
+      */
+      ValNodeCopyStr (&head, 0, " :: ");
+      ValNodeCopyStr (&head, 0, str);
+      ValNodeCopyStr (&head, 0, "\n");
+    }
+  } else {
+    for (curr = uop->data; curr != NULL; curr = curr->next) {
+     if (curr->choice != 1) continue;
+      oip = curr->label;
+      if (oip == NULL) continue;
+      field = oip->str;
+      if (StringHasNoText (field)) continue;
+      if (StringCmp (field, "StructuredCommentPrefix") == 0) continue;
+      if (StringCmp (field, "StructuredCommentSuffix") == 0) continue;
+      str = (CharPtr) curr->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      len = max + StringLen (str) + 4;
+      /*
+      FFStartPrint (ffstring, GENBANK_FMT, 0, max + 1, field, max + 1, 0, max + 1, field, TRUE);
+      */
+      StringNCpy_0 (buf, field, sizeof (buf) - 40);
+      StringCat (buf, "                                   ");
+      buf [max + 1] = ':';
+      buf [max + 2] = ':';
+      buf [max + 3] = '\0';
+      FFStartPrint (ffstring, GENBANK_FMT, 0, max + 4, buf, max + 4, 0, max + 4, buf, TRUE);
+      if (GetWWW (ajp) && StringCmp (field, "GOLD Stamp ID") == 0 && StringNCmp (str, "Gi", 2) == 0) {
+        FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
+        FF_Add_NCBI_Base_URL (ffstring, link_gold_stamp_id);
+        FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
+        FFAddOneString (ffstring, ".html", FALSE, FALSE, TILDE_EXPAND);
+        FFAddOneString (ffstring, "\">", FALSE, FALSE, TILDE_IGNORE);
+        FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
+        FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
+      } else if (GetWWW (ajp) && StringCmp (field, "url") == 0) {
+        AddCommentWithURLlinks (ajp, ffstring, NULL, str, NULL);
+      } else {
+        FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
+      }
+      /*
+      FFAddOneString (ffstring, "\n", FALSE, FALSE, TILDE_EXPAND);
+      */
+      /*
+      tmp = StrucCommentFFEndPrint (ajp, ffstring, ajp->format, max + 1, max + 1, 0, max + 1, NULL);
+      */
+      tmp = StrucCommentFFEndPrint (ajp, ffstring, ajp->format, max + 4, max + 4, 0, max + 4, NULL);
+      ValNodeCopyStr (&head, 0, tmp);
+      MemFree (tmp);
+      FFRecycleString (ajp, ffstring);
+      ffstring = FFGetString (ajp);
+      /*
+      tmp = (CharPtr) MemNew (len);
+      if (tmp == NULL) continue;
+      StringCpy (tmp, field);
+      len = StringLen (tmp);
+      while (len < max) {
+        tmp [len] = ' ';
+        len++;
+      }
+      tmp [len] = '\0';
+      StringCat (tmp, " ");
+      StringCat (tmp, str);
+      StringCat (tmp, "\n");
+      ValNodeCopyStr (&head, 0, tmp);
+      MemFree (tmp);
+      */
+    }
+  }
+  if (StringDoesHaveText (suffix)) {
+    tmp = (CharPtr) MemNew (StringLen (suffix) + 4);
+    if (tmp != NULL) {
+      sprintf (tmp, "%s\n", suffix);
+      ValNodeAddStr (&head, 0, tmp);  
+    }
+  }
+
+  if (head == NULL) return NULL;
+
+  str = MergeFFValNodeStrs (head);
+  ValNodeFreeData (head);
+
+  FFRecycleString (ajp, ffstring);
+
+  return str;
+}
+
+static CharPtr GetStructuredCommentTable (
+  IntAsn2gbJobPtr ajp,
+  UserObjectPtr uop
+)
+
+{
+  UserFieldPtr  curr;
+  CharPtr       field;
+  ValNodePtr    head = NULL;
+  ObjectIdPtr   oip;
+  CharPtr       prefix = NULL;
+  CharPtr       str;
+  CharPtr       suffix = NULL;
+
+  if (ajp == NULL || uop == NULL) return NULL;
+  if ((oip = uop->type) == NULL) return NULL;
+  if (StringCmp (oip->str, "StructuredComment") != 0) return NULL;
+
+  for (curr = uop->data; curr != NULL; curr = curr->next) {
+   if (curr->choice != 1) continue;
+    oip = curr->label;
+    if (oip == NULL) continue;
+    field = oip->str;
+    if (StringHasNoText (field)) continue;
+    if (StringCmp (field, "StructuredCommentPrefix") == 0) {
+      str = (CharPtr) curr->data.ptrvalue;
+      if (StringDoesHaveText (str)) {
+        prefix = str;
+      }
+      continue;
+    }
+    if (StringCmp (field, "StructuredCommentSuffix") == 0) {
+      str = (CharPtr) curr->data.ptrvalue;
+      if (StringDoesHaveText (str)) {
+        suffix = str;
+      }
+      continue;
+    }
+  }
+
+  if (StringHasNoText (prefix)) {
+    prefix = "##Metadata-START##";
+  }
+  if (StringHasNoText (suffix)) {
+    suffix = "##Metadata-END##";
+  }
+
+  if (StringDoesHaveText (prefix)) {
+    ValNodeCopyStr (&head, 0, prefix);
+    if (ajp->oldXmlPolicy) {
+      ValNodeCopyStr (&head, 0, "\n");
+    } else {
+      ValNodeCopyStr (&head, 0, "\\n");
+    }
+  }
+
+  for (curr = uop->data; curr != NULL; curr = curr->next) {
+   if (curr->choice != 1) continue;
+    oip = curr->label;
+    if (oip == NULL) continue;
+    field = oip->str;
+    if (StringHasNoText (field)) continue;
+    if (StringCmp (field, "StructuredCommentPrefix") == 0) continue;
+    if (StringCmp (field, "StructuredCommentSuffix") == 0) continue;
+    str = (CharPtr) curr->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    ValNodeCopyStr (&head, 0, field);
+    if (ajp->oldXmlPolicy) {
+      ValNodeCopyStr (&head, 0, "\t");
+    } else {
+      ValNodeCopyStr (&head, 0, "\\t");
+    }
+    ValNodeCopyStr (&head, 0, str);
+    if (ajp->oldXmlPolicy) {
+      ValNodeCopyStr (&head, 0, "\n");
+    } else {
+      ValNodeCopyStr (&head, 0, "\\n");
+    }
+  }
+
+  if (StringDoesHaveText (suffix)) {
+    ValNodeCopyStr (&head, 0, suffix);
+    if (ajp->oldXmlPolicy) {
+      ValNodeCopyStr (&head, 0, "\n");
+    } else {
+      ValNodeCopyStr (&head, 0, "\\n");
+    }
+  }
+
+  if (head == NULL) return NULL;
+
+  str = MergeFFValNodeStrs (head);
+  ValNodeFreeData (head);
+
+  return str;
+}
+
+static size_t CountSlashableChars (
+  CharPtr str
+)
+
+{
+  Char    ch;
+  size_t  count = 0;
+
+  if (str == NULL) return 0;
+
+  ch = *str;
+  while (ch != '\0') {
+    if (ch == '\n' || ch == '\r' || ch == '\t' || ch == '~' || ch == '\\') {
+      count++;
+    }
+    str++;
+    ch = *str;
+  } 
+
+  return count;
+}
+
 static void CatenateCommentInGbseq (
+  IntAsn2gbJobPtr ajp,
   GBSeqPtr gbseq,
   CharPtr str,
-  Boolean compress
+  Boolean compress,
+  Boolean protectSlash
 )
 
 {
   Char     ch;
-  CharPtr  tmp;
+  CharPtr  cpy, dst, ptr, src, tmp;
 
-  if (gbseq == NULL || StringHasNoText (str)) return;
+  if (ajp == NULL || gbseq == NULL || StringHasNoText (str)) return;
 
   if (StringNCmp (str, "COMMENT     ", 12) == 0) {
     str += 12;
   }
-  if (gbseq->comment == NULL) {
-    gbseq->comment = StringSave (str);
-  } else {
-    tmp = (CharPtr) MemNew (StringLen (gbseq->comment) + StringLen (str) + 4);
-    StringCpy (tmp, gbseq->comment);
-    StringCat (tmp, "; ");
-    StringCat (tmp, str);
-    gbseq->comment = MemFree (gbseq->comment);
-    gbseq->comment = tmp;
-  }
 
-  tmp = gbseq->comment;
-  if (tmp == NULL) return;
-  ch = *tmp;
+  cpy = StringSave (str);
+  if (cpy == NULL) return;
+
+  ptr = cpy;
+  ch = *ptr;
   while (ch != '\0') {
     if (ch == '\n' || ch == '\r' || ch == '\t') {
-      *tmp = ' ';
+      *ptr = ' ';
     }
-    tmp++;
-    ch = *tmp;
+    ptr++;
+    ch = *ptr;
   }
-  TrimSpacesAroundString (gbseq->comment);
+
   if (compress) {
-    Asn2gnbkCompressSpaces (gbseq->comment);
+    Asn2gnbkCompressSpaces (cpy);
   }
-}
 
+  if (! ajp->oldXmlPolicy) {
+    tmp = (CharPtr) MemNew (StringLen (cpy) + CountSlashableChars (cpy) + 10);
+    if (tmp == NULL) return;
+
+    dst = tmp;
+    src = cpy;
+    ch = *src;
+    while (ch != '\0') {
+       if (ch == '~') {
+        *dst = '\\';
+        dst++;
+        *dst = 'n';
+        dst++;
+        src++;
+        ch = *src;
+        while (ch == ' ') {
+          *dst = ch;
+          dst++;
+          src++;
+          ch = *src;
+        }
+      } else if (ch == ' ') {
+        *dst = ch;
+        dst++;
+        src++;
+        ch = *src;
+        while (ch == ' ') {
+          src++;
+          ch = *src;
+        }
+      } else if (ch == '\\' && protectSlash) {
+        *dst = '\\';
+        dst++;
+        *dst = '\\';
+        dst++;
+        src++;
+        ch = *src;
+      } else {
+        *dst = ch;
+        dst++;
+        src++;
+        ch = *src;
+      }
+    }
+    *dst = '\0';
+
+    MemFree (cpy);
+    cpy = tmp;
+  }
+
+  if (gbseq->comment == NULL) {
+    gbseq->comment = cpy;
+  } else {
+    tmp = (CharPtr) MemNew (StringLen (gbseq->comment) + StringLen (str) + 10);
+    if (tmp == NULL) return;
+    StringCpy (tmp, gbseq->comment);
+    if (ajp->oldXmlPolicy) {
+      StringCat (tmp, "; ");
+    } else {
+      StringCat (tmp, "\\r");
+    }
+    StringCat (tmp, cpy);
+    MemFree (cpy);
+    gbseq->comment = MemFree (gbseq->comment);
+    gbseq->comment = tmp;
+  }
+}
 
 NLM_EXTERN CharPtr FormatCommentBlock (
   Asn2gbFormatPtr afp,
@@ -1457,10 +1854,13 @@ NLM_EXTERN CharPtr FormatCommentBlock (
   Boolean            add_period;
   IntAsn2gbJobPtr    ajp;
   Asn2gbSectPtr      asp;
+  Boolean            as_string = FALSE;
+  Boolean            blank_before = FALSE;
   CommentBlockPtr    cbp;
+  SeqMgrDescContext  dcontext;
   CharPtr            db;
   DbtagPtr           dbt;
-  SeqMgrDescContext  dcontext;
+  Boolean            do_gbseq = TRUE;
   SeqMgrFeatContext  fcontext;
   GBSeqPtr           gbseq;
   size_t             len;
@@ -1472,6 +1872,7 @@ NLM_EXTERN CharPtr FormatCommentBlock (
   CharPtr            str;
   CharPtr            suffix;
   CharPtr            title;
+  UserObjectPtr      uop = NULL;
   StringItemPtr      ffstring;
 
   if (afp == NULL || bbp == NULL) return NULL;
@@ -1494,7 +1895,7 @@ NLM_EXTERN CharPtr FormatCommentBlock (
 
   if (! StringHasNoText (bbp->string)) {
     str = StringSave (bbp->string);
-    CatenateCommentInGbseq (gbseq, str, TRUE);
+    CatenateCommentInGbseq (ajp, gbseq, str, TRUE, FALSE);
     return str;
   }
 
@@ -1548,6 +1949,21 @@ NLM_EXTERN CharPtr FormatCommentBlock (
         title = (CharPtr) sdp->data.ptrvalue;
         prefix = "Name: ";
 
+      } else if (dcontext.seqdesctype == Seq_descr_user) {
+
+        uop = (UserObjectPtr) sdp->data.ptrvalue;
+        if (uop != NULL) {
+          title = GetStrForStructuredComment (ajp, uop);
+          if (title != NULL) {
+            str = GetStructuredCommentTable (ajp, uop);
+            CatenateCommentInGbseq (ajp, gbseq, str, TRUE, FALSE);
+            MemFree (str);
+            blank_before = TRUE;
+            as_string = TRUE;
+            do_gbseq = FALSE;
+          }
+        }
+
       }
     }
 
@@ -1571,10 +1987,17 @@ NLM_EXTERN CharPtr FormatCommentBlock (
     FFStartPrint (ffstring, afp->format, 0, 12, "COMMENT", 12, 5, 5, "CC", TRUE);
   } else {
     FFStartPrint (ffstring, afp->format, 0, 12, NULL, 12, 5, 5, "CC", FALSE);
+    if (blank_before) {
+      FFAddOneString (ffstring, "\n", FALSE, FALSE, TILDE_EXPAND);
+    }
   }
 
   str = StringSave (title);
   TrimSpacesAndJunkFromEnds (str, TRUE);
+
+  if (as_string) {
+    FFAddOneString (ffstring, str, FALSE, FALSE, TILDE_EXPAND);
+  } else {
   if (! IsEllipsis (str)) {
     s_RemovePeriodFromEnd (str);
     len = StringLen (str);
@@ -1583,25 +2006,18 @@ NLM_EXTERN CharPtr FormatCommentBlock (
     }
   }
   AddCommentWithURLlinks(ajp, ffstring, prefix, str, suffix);
-  /*
-  if ( GetWWW(ajp) && prefix == NULL && suffix == NULL) {
-    
-    AddCommentWithURLlinks (ffstring, str);
-  } else {
-    FFAddTextToString (ffstring, prefix, str, suffix, FALSE, TRUE, TILDE_OLD_EXPAND);
-  }
-  */
   if (add_period) {
-    FFAddOneChar (ffstring, '.',FALSE);
+      FFAddOneChar (ffstring, '.', FALSE);
   }
+  }
+
   MemFree (str);
 
   str = FFEndPrint(ajp, ffstring, afp->format, 12, 12, 5, 5, "CC");
 
-  /*
-  CatenateCommentInGbseq (gbseq, str);
-  */
-  CatenateCommentInGbseq (gbseq, title, FALSE);
+  if (do_gbseq) {
+    CatenateCommentInGbseq (ajp, gbseq, title, ajp->oldXmlPolicy, TRUE);
+  }
 
   FFRecycleString(ajp, ffstring);
   return str;
@@ -1914,7 +2330,9 @@ static void FlatLocElement (
   IntAsn2gbJobPtr ajp,
   StringItemPtr ffstring,
   BioseqPtr bsp,
-  SeqLocPtr location
+  SeqLocPtr location,
+  Boolean isGap
+
 )
 
 {
@@ -1955,7 +2373,8 @@ static void FlatLocElement (
         if (sintp->to > 0 &&
             (sintp->to != sintp->from ||
              sintp->if_from != NULL ||
-             sintp->if_to != NULL)) {
+             sintp->if_to != NULL) ||
+             isGap) {
           FFAddOneString(ffstring, "..", FALSE, FALSE, TILDE_IGNORE);
           FlatLocPoint (ajp, ffstring, NULL, bsp->id, sintp->to, sintp->if_to);
         }
@@ -2012,7 +2431,8 @@ static void FF_FlatPackedPoint (
   IntAsn2gbJobPtr ajp,
   StringItemPtr ffstring,
   PackSeqPntPtr pspp,
-  BioseqPtr bsp
+  BioseqPtr bsp,
+  Boolean isGap
 )
 
 {
@@ -2031,7 +2451,8 @@ static void FF_DoFlatLoc (
   StringItemPtr ffstring,
   BioseqPtr bsp,
   SeqLocPtr location,
-  Boolean ok_to_complement
+  Boolean ok_to_complement,
+  Boolean isGap
 );
 
 static void FF_GroupFlatLoc (
@@ -2040,7 +2461,8 @@ static void FF_GroupFlatLoc (
   BioseqPtr bsp,
   SeqLocPtr location,
   CharPtr prefix,
-  Boolean is_flat_order
+  Boolean is_flat_order,
+  Boolean isGap
 )
 
 {
@@ -2089,7 +2511,7 @@ static void FF_GroupFlatLoc (
             }
           }
         } else {
-          FlatLocElement (ajp, ffstring, bsp, slp);
+          FlatLocElement (ajp, ffstring, bsp, slp, isGap);
         }
         break;
       case SEQLOC_INT :
@@ -2099,13 +2521,13 @@ static void FF_GroupFlatLoc (
           FFAddOneString(ffstring, "join(", FALSE, FALSE, TILDE_IGNORE);
           parens++;
         }
-        FlatLocElement (ajp, ffstring, bsp, slp);
+        FlatLocElement (ajp, ffstring, bsp, slp, isGap);
         break;
       case SEQLOC_PACKED_PNT :
         found_non_virt = TRUE;
         pspp = (PackSeqPntPtr) slp->data.ptrvalue;
         if (pspp != NULL) {
-          FF_FlatPackedPoint (ajp, ffstring, pspp, bsp);
+          FF_FlatPackedPoint (ajp, ffstring, pspp, bsp, isGap);
         }
         break;
       case SEQLOC_PACKED_INT :
@@ -2114,7 +2536,7 @@ static void FF_GroupFlatLoc (
         found_non_virt = TRUE;
         hold_next = slp->next;
         slp->next = NULL;
-        FF_DoFlatLoc (ajp, ffstring, bsp, slp, FALSE);
+        FF_DoFlatLoc (ajp, ffstring, bsp, slp, FALSE, isGap);
         slp->next = hold_next;
         break;
       default :
@@ -2137,7 +2559,9 @@ static void FF_DoFlatLoc (
   StringItemPtr ffstring,
   BioseqPtr bsp,
   SeqLocPtr location,
-  Boolean ok_to_complement
+  Boolean ok_to_complement,
+  Boolean isGap
+
 )
 
 {
@@ -2157,7 +2581,7 @@ static void FF_DoFlatLoc (
     if (slp != NULL) {
       SeqLocRevCmp (slp);
       FFAddOneString(ffstring, "complement(", FALSE, FALSE, TILDE_IGNORE);
-      FF_DoFlatLoc (ajp, ffstring, bsp, slp, FALSE);
+      FF_DoFlatLoc (ajp, ffstring, bsp, slp, FALSE, isGap);
       FFAddOneString(ffstring, ")", FALSE, FALSE, TILDE_IGNORE);
     }
     SeqLocFree (slp);
@@ -2189,22 +2613,22 @@ static void FF_DoFlatLoc (
             found_null = TRUE;
         }
         if (found_null) {
-          FF_GroupFlatLoc (ajp, ffstring, bsp, slp, "order(", TRUE);
+          FF_GroupFlatLoc (ajp, ffstring, bsp, slp, "order(", TRUE, isGap);
         } else {
-          FF_GroupFlatLoc (ajp, ffstring, bsp, slp, "join(", FALSE);
+          FF_GroupFlatLoc (ajp, ffstring, bsp, slp, "join(", FALSE, isGap);
         }
         break;
       case SEQLOC_EQUIV :
-        FF_GroupFlatLoc (ajp, ffstring, bsp, slp, "one-of(", FALSE);
+        FF_GroupFlatLoc (ajp, ffstring, bsp, slp, "one-of(", FALSE, isGap);
         break;
       case SEQLOC_PACKED_PNT :
         pspp = (PackSeqPntPtr) slp->data.ptrvalue;
         if (pspp != NULL) {
-          FF_FlatPackedPoint (ajp, ffstring, pspp, bsp);
+          FF_FlatPackedPoint (ajp, ffstring, pspp, bsp, isGap);
         }
         break;
       default :
-        FlatLocElement (ajp, ffstring, bsp, slp);
+        FlatLocElement (ajp, ffstring, bsp, slp, isGap);
         break;
     }
 
@@ -2218,7 +2642,8 @@ NLM_EXTERN CharPtr FFFlatLoc (
   IntAsn2gbJobPtr ajp,
   BioseqPtr bsp,
   SeqLocPtr location,
-  Boolean masterStyle
+  Boolean masterStyle,
+  Boolean isGap
 )
 
 {
@@ -2228,6 +2653,7 @@ NLM_EXTERN CharPtr FFFlatLoc (
   Boolean     noLeft;
   Boolean     noRight;
   Uint1       num = 1;
+  ValNodePtr  partiallist = NULL, emptypartials = NULL;
   SeqPntPtr   spp;
   CharPtr     str;
   SeqLocPtr   tmp;
@@ -2271,6 +2697,7 @@ NLM_EXTERN CharPtr FFFlatLoc (
       }
     }
 
+    partiallist = GetSeqLocPartialSet (location);
     CheckSeqLocForPartial (location, &noLeft, &noRight);
     hasNulls = LocationHasNullsBetween (location);
     loc = SeqLocMergeExEx (bsp, location, NULL, FALSE, TRUE, FALSE, hasNulls, FALSE, FALSE);
@@ -2280,10 +2707,17 @@ NLM_EXTERN CharPtr FFFlatLoc (
       SeqLocFree (tmp);
     }
     if (loc == NULL) {
+      ValNodeFree (partiallist);
       return StringSave ("?");
     }
+    emptypartials = GetSeqLocPartialSet (loc);
     FreeAllFuzz (loc);
     SetSeqLocPartial (loc, noLeft, noRight);
+    if (ValNodeLen (partiallist) == ValNodeLen (emptypartials)) {
+      SetSeqLocPartialSet (loc, partiallist);
+    }
+    ValNodeFree (partiallist);
+    ValNodeFree (emptypartials);
 
     if (loc->choice == SEQLOC_PNT && fuzz != NULL) {
       spp = (SeqPntPtr) loc->data.ptrvalue;
@@ -2294,12 +2728,12 @@ NLM_EXTERN CharPtr FFFlatLoc (
       }
     }
 
-    FF_DoFlatLoc (ajp, ffstring, bsp, loc, TRUE);
+    FF_DoFlatLoc (ajp, ffstring, bsp, loc, TRUE, isGap);
 
     SeqLocFree (loc);
 
   } else {
-    FF_DoFlatLoc (ajp, ffstring, bsp, location, TRUE);
+    FF_DoFlatLoc (ajp, ffstring, bsp, location, TRUE, isGap);
   }
 
   str = FFToCharPtr(ffstring);
@@ -3103,6 +3537,161 @@ static CharPtr NextPCRReaction (
   return str;
 }
 
+/* specimen_voucher, culture_collection, bio_material default institution mouseover */
+
+typedef struct instcodedata {
+  CharPtr  code;
+  CharPtr  name;
+} IcCodeData, PNTR IcCodePtr;
+
+static ValNodePtr      ic_code_list = NULL;
+static IcCodePtr PNTR  ic_code_data = NULL;
+static Int4            ic_code_len = 0;
+static Boolean         ic_code_loaded = FALSE;
+
+static int LIBCALLBACK SortVnpByInstCode (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  int         compare;
+  IcCodePtr   irp1, irp2;
+  CharPtr     str1, str2;
+  ValNodePtr  vnp1, vnp2;
+
+  if (ptr1 == NULL || ptr2 == NULL) return 0;
+  vnp1 = *((ValNodePtr PNTR) ptr1);
+  vnp2 = *((ValNodePtr PNTR) ptr2);
+  if (vnp1 == NULL || vnp2 == NULL) return 0;
+  irp1 = (IcCodePtr) vnp1->data.ptrvalue;
+  irp2 = (IcCodePtr) vnp2->data.ptrvalue;
+  if (irp1 == NULL || irp2 == NULL) return 0;
+  str1 = irp1->code;
+  str2 = irp2->code;
+  if (str1 == NULL || str2 == NULL) return 0;
+  compare = StringCmp (str1, str2);
+  if (compare > 0) {
+    return 1;
+  } else if (compare < 0) {
+    return -1;
+  }
+  str1 = irp1->name;
+  str2 = irp2->name;
+  if (str1 == NULL || str2 == NULL) return 0;
+  compare = StringCmp (str1, str2);
+  if (compare > 0) {
+    return 1;
+  } else if (compare < 0) {
+    return -1;
+  }
+  return 0;
+}
+
+static void SetupInstCodeNameTable (void)
+
+{
+  FileCache   fc;
+  CharPtr     file = "institution_codes.txt";
+  FILE        *fp = NULL;
+  Int4        i;
+  IcCodePtr   irp;
+  ValNodePtr  last = NULL;
+  Char        line [512];
+  Char        path [PATH_MAX];
+  CharPtr     ptr;
+  ErrSev      sev;
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (ic_code_loaded) return;
+  if (ic_code_data != NULL) return;
+
+  if (FindPath ("ncbi", "ncbi", "data", path, sizeof (path))) {
+    FileBuildPath (path, NULL, file);
+    sev = ErrSetMessageLevel (SEV_ERROR);
+    fp = FileOpen (path, "r");
+    ErrSetMessageLevel (sev);
+    if (fp != NULL) {
+      FileCacheSetup (&fc, fp);
+  
+      str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+      while (str != NULL) {
+        if (StringDoesHaveText (str)) {
+          ptr = StringChr (str, '\t');
+          if (ptr != NULL) {
+            *ptr = '\0';
+            ptr++;
+            ptr = StringChr (ptr, '\t');
+            if (ptr != NULL) {
+              *ptr = '\0';
+              ptr++;
+              irp = (IcCodePtr) MemNew (sizeof (IcCodeData));
+              if (irp != NULL) {
+                TrimSpacesAroundString (str);
+                TrimSpacesAroundString (ptr);
+                irp->code = StringSave (str);
+                irp->name = StringSave (ptr);
+                vnp = ValNodeAddPointer (&last, 0, (Pointer) irp);
+                if (ic_code_list == NULL) {
+                  ic_code_list = vnp;
+                }
+                last = vnp;
+              }
+            }
+          }
+        }
+        str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+      }
+
+      FileClose (fp);
+      ic_code_len = ValNodeLen (ic_code_list);
+      if (ic_code_len > 0) {
+        ic_code_list = ValNodeSort (ic_code_list, SortVnpByInstCode);
+        ic_code_data = (IcCodePtr PNTR) MemNew (sizeof (IcCodePtr) * (ic_code_len + 1));
+        if (ic_code_data != NULL) {
+          for (vnp = ic_code_list, i = 0; vnp != NULL; vnp = vnp->next, i++) {
+            irp = (IcCodePtr) vnp->data.ptrvalue;
+            ic_code_data [i] = irp;
+          }
+        }
+      }
+    }
+  }
+
+  ic_code_loaded = TRUE;
+}
+
+static CharPtr FullNameFromInstCode (CharPtr code)
+
+{
+  CharPtr    name = NULL;
+  IcCodePtr  irp;
+  Int4       L, R, mid;
+
+  if (StringHasNoText (code)) return NULL;
+
+  if (ic_code_data == NULL) {
+    SetupInstCodeNameTable ();
+  }
+  if (ic_code_data == NULL) return NULL;
+
+  L = 0;
+  R = ic_code_len - 1;
+  while (L < R) {
+    mid = (L + R) / 2;
+    irp = ic_code_data [(int) mid];
+    if (irp != NULL && StringCmp (irp->code, code) < 0) {
+      L = mid + 1;
+    } else {
+      R = mid;
+    }
+  }
+  irp = ic_code_data [(int) R];
+  if (irp != NULL && StringCmp (irp->code, code) == 0) {
+    name = irp->name;
+  }
+
+  return name;
+}
+
 /* specimen_voucher, culture_collection, bio_material hyperlinks */
 
 #define s_atcc_base "http://www.atcc.org/SearchCatalogs/linkin?id="
@@ -3111,96 +3700,94 @@ static CharPtr NextPCRReaction (
 #define s_ccug_base "http://www.ccug.se/default.cfm?page=search_record.cfm&db=mc&s_tests=1&ccugno="
 #define s_dsmz_base "http://www.dsmz.de/microorganisms/search_no.php?q="
 #define s_fsu_base  "http://www.prz.uni-jena.de/data.php?fsu="
+#define s_icmp_base  "http://nzfungi.landcareresearch.co.nz/icmp/results_cultures.asp?ID=&icmpVAR="
 #define s_ku_base   "http://collections.nhm.ku.edu/"
 #define s_pcc_base  "http://www.pasteur.fr/recherche/banques/PCC/docs/pcc"
 #define s_pcmb_base "http://www2.bishopmuseum.org/HBS/PCMB/results3.asp?searchterm3="
+#define s_pdd_base   "http://nzfungi.landcareresearch.co.nz/html/data_collections_details.asp?CID="
 #define s_tgrc_base "http://tgrc.ucdavis.edu/Data/Acc/AccDetail.aspx?AccessionNum="
 #define s_uam_base  "http://arctos.database.museum/guid/"
+#define s_ypm_base   "http://peabody.research.yale.edu/cgi-bin/Query.Ledger?"
 
 #define s_colon_pfx ":"
 
 #define s_kui_pfx   "KU_Fish/detail.jsp?record="
 #define s_kuit_pfx  "KU_Tissue/detail.jsp?record="
+#define s_psu_pfx    "PSU:Mamm:"
+
+#define s_ypment_pfx "LE=ent&ID="
+#define s_ypmher_pfx "LE=her&ID="
+#define s_ypmich_pfx "LE=ich&ID="
+#define s_ypmiz_pfx  "LE=iz&ID="
+#define s_ypmmam_pfx "LE=mam&ID="
+#define s_ypmorn_pfx "LE=orn&ID="
 
 #define s_bcrc_sfx  "&type_id=6&keyword=;;"
 #define s_pcc_sfx   ".htm"
 
-#define s_atcc_inst  "American Type Culture Collection"
-#define s_bcrc_inst  "Bioresource Collection and Research Center"
-#define s_ccmp_inst  "Provasoli-Guillard National Center for Culture of Marine Phytoplankton"
-#define s_ccug_inst  "Culture Collection, University of Goteborg, Department of Clinical Bacteriology"
-#define s_crcm_inst  "Charles R. Conner Museum, Washington State University"
-#define s_dgr_inst   "Division of Genomic Resources, University of New Mexico"
-#define s_dsmz_inst  "German Resource Center for Biological Material"
-#define s_fsu_inst   "Fungal Reference Center, University of Jena"
-#define s_ku_inst    "University of Kansas, Museum of Natural History"
-#define s_kwp_inst   "Kenelm W. Philip Collection, University of Alaska Museum of the North"
-#define s_msb_inst   "Museum of Southwestern Biology, University of New Mexico"
-#define s_mvz_inst   "Museum of Vertebrate Zoology, University of California"
-#define s_nbsb_inst  "National Biomonitoring Specimen Bank, U.S. Geological Survey"
-#define s_pcc_inst   "Pasteur Culture Collection of Cyanobacteria"
-#define s_pcmb_inst  "Pacific Center for Molecular Biodiversity"
-#define s_psu_inst   "Portland State University"
-#define s_tgrc_inst  "Tomato Genetics Resource Center, University of California"
-#define s_uam_inst   "University of Alaska Museum of the North"
-#define s_wmnu_inst  "Western New Mexico University Museum"
-
 typedef struct vouch {
   CharPtr  sites;
   CharPtr  links;
   Boolean  prepend_institute;
   CharPtr  prefix;
   CharPtr  suffix;
-  CharPtr  mouseover;
 } VouchData, PNTR VouchDataPtr;
 
 static VouchData Nlm_spec_vouchers [] = {
- { "ATCC",        s_atcc_base, FALSE, NULL,         NULL,       s_atcc_inst },
- { "BCRC",        s_bcrc_base, FALSE, NULL,         s_bcrc_sfx, s_bcrc_inst },
- { "CCMP",        s_ccmp_base, FALSE, NULL,         NULL,       s_ccmp_inst },
- { "CCUG",        s_ccug_base, FALSE, NULL,         NULL,       s_ccug_inst },
- { "CRCM:Bird",   s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_crcm_inst },
- { "DGR:Bird",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_dgr_inst  },
- { "DGR:Ento",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_dgr_inst  },
- { "DGR:Fish",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_dgr_inst  },
- { "DGR:Herp",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_dgr_inst  },
- { "DGR:Mamm",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_dgr_inst  },
- { "DSM",         s_dsmz_base, FALSE, NULL,         NULL,       s_dsmz_inst },
- { "FSU<DEU>",    s_fsu_base,  FALSE, NULL,         NULL,       s_fsu_inst  },
- { "KU:I",        s_ku_base,   FALSE, s_kui_pfx,    NULL,       s_ku_inst   },
- { "KU:IT",       s_ku_base,   FALSE, s_kuit_pfx,   NULL,       s_ku_inst   },
- { "KWP:Ento",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_kwp_inst  },
- { "MSB:Bird",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_msb_inst  },
- { "MSB:Mamm",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_msb_inst  },
- { "MSB:Para",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_msb_inst  },
- { "MVZ:Bird",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "MVZ:Egg",     s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "MVZ:Herp",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "MVZ:Hild",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "MVZ:Img",     s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "MVZ:Mamm",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "MVZ:Page",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "MVZObs:Herp", s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_mvz_inst  },
- { "NBSB:Bird",   s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_nbsb_inst },
- { "PCC",         s_pcc_base,  FALSE, NULL,         s_pcc_sfx,  s_pcc_inst  },
- { "PCMB",        s_pcmb_base, FALSE, NULL,         NULL,       s_pcmb_inst },
- { "TGRC",        s_tgrc_base, FALSE, NULL,         NULL,       s_tgrc_inst },
- { "PSU:Mamm",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_psu_inst  },
- { "UAM:Bird",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Bryo",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Crus",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Ento",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Fish",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Herb",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Herp",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Mamm",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Moll",    s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAM:Paleo",   s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "UAMObs:Mamm", s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_uam_inst  },
- { "WNMU:Bird",   s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_wmnu_inst },
- { "WNMU:Fish",   s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_wmnu_inst },
- { "WNMU:Mamm",   s_uam_base,  TRUE,  s_colon_pfx,  NULL,       s_wmnu_inst },
- { NULL,          NULL,        FALSE, NULL,         NULL,       NULL        }
+  {  "ATCC",              s_atcc_base,  FALSE,  NULL,          NULL        },
+  {  "BCRC",              s_bcrc_base,  FALSE,  NULL,          s_bcrc_sfx  },
+  {  "CCMP",              s_ccmp_base,  FALSE,  NULL,          NULL        },
+  {  "CCUG",              s_ccug_base,  FALSE,  NULL,          NULL        },
+  {  "CRCM:Bird",         s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "DGR:Bird",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "DGR:Ento",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "DGR:Fish",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "DGR:Herp",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "DGR:Mamm",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "DSM",               s_dsmz_base,  FALSE,  NULL,          NULL        },
+  {  "FSU<DEU>",          s_fsu_base,   FALSE,  NULL,          NULL        },
+  {  "ICMP",              s_icmp_base,  FALSE,  NULL,          NULL        },
+  {  "KU:I",              s_ku_base,    FALSE,  s_kui_pfx,     NULL        },
+  {  "KU:IT",             s_ku_base,    FALSE,  s_kuit_pfx,    NULL        },
+  {  "KWP:Ento",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MSB:Bird",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MSB:Mamm",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MSB:Para",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZ:Bird",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZ:Egg",           s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZ:Herp",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZ:Hild",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZ:Img",           s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZ:Mamm",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZ:Page",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "MVZObs:Herp",       s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "NBSB:Bird",         s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "PCC",               s_pcc_base,   FALSE,  NULL,          s_pcc_sfx   },
+  {  "PCMB",              s_pcmb_base,  FALSE,  NULL,          NULL        },
+  {  "PDD",               s_pdd_base,   FALSE,  NULL,          NULL        },
+  {  "PSU<USA-OR>:Mamm",  s_uam_base,   FALSE,  s_psu_pfx,     NULL        },
+  {  "TGRC",              s_tgrc_base,  FALSE,  NULL,          NULL        },
+  {  "UAM:Bird",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Bryo",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Crus",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Ento",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Fish",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Herb",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Herp",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Mamm",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Moll",          s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAM:Paleo",         s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "UAMObs:Mamm",       s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "WNMU:Bird",         s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "WNMU:Fish",         s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "WNMU:Mamm",         s_uam_base,   TRUE,   s_colon_pfx,   NULL        },
+  {  "YPM:ENT",           s_ypm_base,   FALSE,  s_ypment_pfx,  NULL        },
+  {  "YPM:HER",           s_ypm_base,   FALSE,  s_ypmher_pfx,  NULL        },
+  {  "YPM:ICH",           s_ypm_base,   FALSE,  s_ypmich_pfx,  NULL        },
+  {  "YPM:IZ",            s_ypm_base,   FALSE,  s_ypmiz_pfx,   NULL        },
+  {  "YPM:MAM",           s_ypm_base,   FALSE,  s_ypmmam_pfx,  NULL        },
+  {  "YPM:ORN",           s_ypm_base,   FALSE,  s_ypmorn_pfx,  NULL        },
+  {  NULL,                NULL,         FALSE,  NULL,          NULL        }
 };
 
 static Int2 VoucherNameIsValid (
@@ -3287,9 +3874,20 @@ static void Do_www_specimen_voucher (
 )
 
 {
+  CharPtr  mouseover = NULL;
+
   if ( ffstring == NULL || inst == NULL || id == NULL || vdp == NULL || vdp->links == NULL ) return;
 
+  mouseover = FullNameFromInstCode (inst);
+  if (mouseover != NULL) {
+    FFAddOneString (ffstring, "<acronym title=\"", FALSE, FALSE, TILDE_IGNORE);
+    FFAddOneString (ffstring, mouseover, FALSE, FALSE, TILDE_IGNORE);
+    FFAddOneString(ffstring, "\" class=\"voucher\">", FALSE, FALSE, TILDE_IGNORE);
   FFAddOneString (ffstring, inst, FALSE, FALSE, TILDE_IGNORE);
+    FFAddOneString (ffstring, "</acronym>", FALSE, FALSE, TILDE_IGNORE);
+  } else {
+    FFAddOneString (ffstring, inst, FALSE, FALSE, TILDE_IGNORE);
+  }
   FFAddOneString (ffstring, ":", FALSE, FALSE, TILDE_IGNORE);
   FFAddOneString (ffstring, "<a href=\"", FALSE, FALSE, TILDE_IGNORE);
   FFAddOneString (ffstring, vdp->links, FALSE, FALSE, TILDE_IGNORE);
@@ -3303,12 +3901,9 @@ static void Do_www_specimen_voucher (
   if (vdp->suffix != NULL) {
     FFAddOneString (ffstring, vdp->suffix, FALSE, FALSE, TILDE_IGNORE);
   }
-  FFAddOneString(ffstring, "\"", FALSE, FALSE, TILDE_IGNORE);
-  if (vdp->mouseover != NULL) {
-    FFAddTextToString (ffstring, " title=\"", vdp->mouseover, "\"",
-                       FALSE, FALSE, TILDE_IGNORE);
-  }
-  FFAddTextToString (ffstring, ">", id, "</a>", FALSE, FALSE, TILDE_IGNORE);
+  FFAddOneString(ffstring, "\">", FALSE, FALSE, TILDE_IGNORE);
+  FFAddOneString (ffstring, id, FALSE, FALSE, TILDE_IGNORE);
+  FFAddOneString (ffstring, "</a>", FALSE, FALSE, TILDE_IGNORE);
 }
 
 NLM_EXTERN void FF_www_specimen_voucher (
@@ -3319,7 +3914,7 @@ NLM_EXTERN void FF_www_specimen_voucher (
 
 {
   Char          buf [512];
-  CharPtr       inst = NULL, id = NULL;
+  CharPtr       inst = NULL, id = NULL, mouseover = NULL;
   Int2          R;
   VouchDataPtr  vdp;
 
@@ -3335,7 +3930,18 @@ NLM_EXTERN void FF_www_specimen_voucher (
   }
   R = VoucherNameIsValid (inst);
   if (R < 0) {
+    mouseover = FullNameFromInstCode (inst);
+    if (mouseover != NULL) {
+      FFAddOneString (ffstring, "<acronym title=\"", FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, mouseover, FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString(ffstring, "\" class=\"voucher\">", FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, inst, FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, "</acronym>", FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, ":", FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, id, FALSE, FALSE, TILDE_IGNORE);
+    } else {
     FFAddTextToString (ffstring, NULL, subname, NULL, FALSE, TRUE, TILDE_TO_SPACES);
+    }
     return;
   }
   vdp = &(Nlm_spec_vouchers [R]);
@@ -3570,7 +4176,7 @@ NLM_EXTERN CharPtr FormatSourceFeatBlock (
 
   location = isp->loc;
 
-  str = FFFlatLoc (ajp, bsp, location, ajp->masterStyle);
+  str = FFFlatLoc (ajp, bsp, location, ajp->masterStyle, FALSE);
   if ( GetWWW(ajp) ) {
     FF_www_featloc (ffstring, str);
   } else {
@@ -3613,7 +4219,9 @@ NLM_EXTERN CharPtr FormatSourceFeatBlock (
   if (StringHasNoText (taxname)) {
     if (ajp->flags.needOrganismQual) {
       taxname = "unknown";
+      if (orp != NULL) {
       common = orp->common;
+      }
 #ifdef ASN2GNBK_PRINT_UNKNOWN_ORG
     } else {
       taxname = "unknown";
@@ -3623,7 +4231,7 @@ NLM_EXTERN CharPtr FormatSourceFeatBlock (
   }
 
   sep = GetTopSeqEntryForEntityID (ajp->ajp.entityID);
-  if (sep == NULL && IS_Bioseq_set (sep)) {
+  if (sep != NULL && IS_Bioseq_set (sep)) {
     bssp = (BioseqSetPtr) sep->data.ptrvalue;
     if (bssp != NULL && bssp->_class == BioseqseqSet_class_gen_prod_set) {
       is_gps = TRUE;
@@ -3988,7 +4596,7 @@ NLM_EXTERN CharPtr FormatSourceFeatBlock (
               }
             }
           }
-          if (! StringHasNoText (buf)) {
+          if (StringDoesHaveText (buf) && dbt != NULL) {
             FFAddOneString(ffstring, "/db_xref=\"", FALSE, FALSE, TILDE_IGNORE);
             FF_www_db_xref(ajp, ffstring, dbt->db, buf, bsp);
             FFAddOneString(ffstring, "\"\n", FALSE, FALSE, TILDE_IGNORE);
@@ -4401,9 +5009,11 @@ NLM_EXTERN CharPtr FormatBasecountBlock (
 }
 
 static void PrintSeqLine (
+  IntAsn2gbJobPtr ajp,
   StringItemPtr ffstring,
   FmtType format,
   CharPtr buf,
+  Int4 gi,
   Int4 start,
   Int4 stop
 )
@@ -4412,6 +5022,7 @@ static void PrintSeqLine (
   size_t  len;
   Char    pos [16];
   Int4    pad;
+  Char    tmp [64];
 
   len = StringLen (buf);
   if (len > 0 && buf [len - 1] == ' ') {
@@ -4423,7 +5034,14 @@ static void PrintSeqLine (
     sprintf (pos, "%9ld", (long) (start + 1));
     FFAddOneString(ffstring, pos, FALSE, FALSE, TILDE_TO_SPACES);
     FFAddOneChar(ffstring, ' ', FALSE);
+    if (ajp != NULL && ajp->seqspans) {
+      sprintf (tmp, "<span class=\"ff_line\" id=\"gi_%ld_%ld\">", (long) gi, (long) (start + 1));
+      FFAddOneString(ffstring, tmp, FALSE, FALSE, TILDE_TO_SPACES);
+    }
     FFAddOneString(ffstring, buf, FALSE, FALSE, TILDE_TO_SPACES);
+    if (ajp != NULL && ajp->seqspans) {
+      FFAddOneString(ffstring, "</span>", FALSE, FALSE, TILDE_TO_SPACES);
+    }
     FFAddOneChar(ffstring, '\n', FALSE);
   } else if (format == EMBL_FMT || format == EMBLPEPT_FMT) {
 
@@ -4495,23 +5113,26 @@ static void PrintGenome (
   Boolean is_na
 )
 {
-  Char         buf[40], gibuf [32], val[166];
+  Char         buf[40], gibuf [32], vbuf [80];
   Boolean      first = TRUE;
-  SeqIdPtr     freeid, sid, newid;
-  SeqLocPtr    slp;
-  Int4         from, to, start, stop, gi;
+  SeqIdPtr     freeid = NULL, sid = NULL, newid = NULL;
+  SeqLocPtr    slp = NULL;
+  Int4         from = 0, to = 0, start = 0, stop = 0, gi = 0;
   BioseqPtr    bsp = NULL;
-  Int2         p1=0, p2=0;
+  Int2         p1 = 0, p2 = 0;
 
+  buf [0] = '\0';
+  gibuf [0] = '\0';
+  vbuf [0] = '\0';
   for (slp = slp_head; slp; slp = slp->next) {
     from = to = 0;
-    sid = SeqLocId(slp);
+    sid = SeqLocId (slp);
     if (slp->choice == SEQLOC_INT || slp->choice == SEQLOC_WHOLE) {
-      start = from = SeqLocStart(slp);
-      stop = to = SeqLocStop(slp);
+      start = from = SeqLocStart (slp);
+      stop = to = SeqLocStop (slp);
     } else if (slp->choice == SEQLOC_NULL){
-      sprintf(val, ",%s", "gap()");
-      FFAddOneString(ffstring, val, FALSE, FALSE, TILDE_IGNORE);
+      sprintf (vbuf, ",%s", "gap()");
+      FFAddOneString (ffstring, vbuf, FALSE, FALSE, TILDE_IGNORE);
       continue;
     } else {
       continue;
@@ -4539,11 +5160,11 @@ static void PrintGenome (
             bsp = BioseqFind (newid);
             if (bsp != NULL && bsp->repr == Seq_repr_virtual) {
               if (bsp->length > 0) {
-                sprintf (val, ",gap(%ld)", (long) bsp->length);
+                sprintf (vbuf, ",gap(%ld)", (long) bsp->length);
               } else {
-                sprintf(val, ",%s", "gap()");
+                sprintf (vbuf, ",%s", "gap()");
               }
-              FFAddOneString(ffstring, val, FALSE, FALSE, TILDE_IGNORE);
+              FFAddOneString (ffstring, vbuf, FALSE, FALSE, TILDE_IGNORE);
               continue;
             }
           }
@@ -4556,12 +5177,12 @@ static void PrintGenome (
       gi = GetGIForSeqId (sid);
     }
     if (prefix != NULL) {
-      FFAddOneString(ffstring, prefix, FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, prefix, FALSE, FALSE, TILDE_IGNORE);
     }
     if (first) {
       first = FALSE;
     } else {
-      FFAddOneChar(ffstring, ',', FALSE);
+      FFAddOneChar (ffstring, ',', FALSE);
       /*ff_AddChar(',');*/
     }
     if (! StringHasNoText (buf)) {
@@ -4574,9 +5195,9 @@ static void PrintGenome (
     }
 
     if (SeqLocStrand (slp) == Seq_strand_minus) {
-      FFAddOneString(ffstring, "complement(", FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, "complement(", FALSE, FALSE, TILDE_IGNORE);
     }
-    if ( GetWWW(ajp) && gi > 0) {
+    if ( GetWWW (ajp) && gi > 0) {
       if (newid == NULL) {
         newid = sid;
       }
@@ -4588,21 +5209,21 @@ static void PrintGenome (
           FF_Add_NCBI_Base_URL (ffstring, link_seqp);
         }
         sprintf (gibuf, "%ld", (long) gi);
-        FFAddTextToString(ffstring, /* "val=" */ NULL, gibuf, "\">", FALSE, FALSE, TILDE_IGNORE);
-        FFAddTextToString(ffstring, NULL, buf, "</a>", FALSE, FALSE, TILDE_IGNORE);
+        FFAddTextToString (ffstring, /* "val=" */ NULL, gibuf, "\">", FALSE, FALSE, TILDE_IGNORE);
+        FFAddTextToString (ffstring, NULL, buf, "</a>", FALSE, FALSE, TILDE_IGNORE);
       }
     } else {
-      FFAddOneString(ffstring, buf, FALSE, FALSE, TILDE_IGNORE);
+      FFAddOneString (ffstring, buf, FALSE, FALSE, TILDE_IGNORE);
     }
 
-    if (SeqLocStrand(slp) == Seq_strand_minus) {
-      sprintf (val,":%ld..%ld)", (long) start+1, (long) stop+1);
+    if (SeqLocStrand (slp) == Seq_strand_minus) {
+      sprintf (vbuf,":%ld..%ld)", (long) start+1, (long) stop+1);
     } else {
-      sprintf (val,":%ld..%ld", (long) start+1, (long) stop+1);
+      sprintf (vbuf,":%ld..%ld", (long) start+1, (long) stop+1);
     }
-    FFAddOneString(ffstring, val, FALSE, FALSE, TILDE_IGNORE);
-    p1 += StringLen (val);
-    p2 += StringLen (val);
+    FFAddOneString (ffstring, vbuf, FALSE, FALSE, TILDE_IGNORE);
+    p1 += StringLen (vbuf);
+    p2 += StringLen (vbuf);
     if (freeid != NULL) {
       freeid = SeqIdFree (freeid);
     }
@@ -4629,7 +5250,7 @@ NLM_EXTERN CharPtr FormatContigBlock (
   CharPtr          str;
   Char             tmp [16];
   Boolean          unknown;
-  Char             val [32];
+  Char             vbuf [32];
   StringItemPtr    ffstring;
 /*  CharPtr          label;*/
 
@@ -4641,7 +5262,7 @@ NLM_EXTERN CharPtr FormatContigBlock (
   bsp = (asp->bsp);
   if (bsp == NULL) return NULL;
 
-  ffstring = FFGetString(ajp);
+  ffstring = FFGetString (ajp);
   if ( ffstring == NULL ) return NULL;
 
   is_na = ISA_na (bsp->mol);
@@ -4658,7 +5279,7 @@ NLM_EXTERN CharPtr FormatContigBlock (
   FFAddNChar(ffstring, ' ', 12 - StringLen(label), FALSE);
   */
 
-  FFAddOneString(ffstring, "join(", FALSE, FALSE, TILDE_IGNORE);
+  FFAddOneString (ffstring, "join(", FALSE, FALSE, TILDE_IGNORE);
 
   if (bsp->seq_ext_type == 1) {
 
@@ -4683,8 +5304,8 @@ NLM_EXTERN CharPtr FormatContigBlock (
         if (litp != NULL) {
           if (litp->seq_data != NULL && litp->seq_data_type != Seq_code_gap) {
             if (litp->length == 0) {
-              sprintf (val, "gap(%ld)", (long) litp->length);
-              FFAddOneString(ffstring, val, FALSE, FALSE, TILDE_IGNORE);
+              sprintf (vbuf, "gap(%ld)", (long) litp->length);
+              FFAddOneString (ffstring, vbuf, FALSE, FALSE, TILDE_IGNORE);
             } else {
               /* don't know what to do here */
             }
@@ -4700,11 +5321,11 @@ NLM_EXTERN CharPtr FormatContigBlock (
               sprintf (tmp, "%ld", (long) litp->length);
             }
             if (prefix != NULL) {
-              sprintf (val, "%sgap(%s)", prefix, tmp);
+              sprintf (vbuf, "%sgap(%s)", prefix, tmp);
             } else {
-              sprintf (val, "gap(%s)", tmp);
+              sprintf (vbuf, "gap(%s)", tmp);
             }
-            FFAddOneString(ffstring, val, FALSE, FALSE, TILDE_IGNORE);
+            FFAddOneString (ffstring, vbuf, FALSE, FALSE, TILDE_IGNORE);
           }
         }
       }
@@ -4713,10 +5334,10 @@ NLM_EXTERN CharPtr FormatContigBlock (
     }
   }
 
-  FFAddOneChar(ffstring, ')', FALSE);
+  FFAddOneChar (ffstring, ')', FALSE);
 
-  str = FFEndPrint(ajp, ffstring, afp->format, 12, 12, 5, 5, "CO");
-  FFRecycleString(ajp, ffstring);
+  str = FFEndPrint (ajp, ffstring, afp->format, 12, 12, 5, 5, "CO");
+  FFRecycleString (ajp, ffstring);
 
   /* optionally populate gbseq for XML-ized GenBank format */
 
@@ -5027,6 +5648,7 @@ NLM_EXTERN CharPtr FormatSequenceBlock (
   Int4              extend;
   StreamFlgType     flags = STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL;
   GBSeqPtr          gbseq;
+  Int4              gi = 0;
   IntAsn2gbSectPtr  iasp;
   Int2              lin;
   SeqLocPtr         loc;
@@ -5034,6 +5656,7 @@ NLM_EXTERN CharPtr FormatSequenceBlock (
   CharPtr           ptr;
   Int4              remaining;
   SeqBlockPtr       sbp;
+  SeqIdPtr          sip;
   SeqLoc            sl;
   SeqLocPtr         slp;
   Int4              start;
@@ -5160,6 +5783,11 @@ NLM_EXTERN CharPtr FormatSequenceBlock (
 
   if (sbp->bases == NULL) return NULL;
 
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+   if (sip->choice != SEQID_GI) continue;
+   gi = (Int4) sip->data.intvalue;
+  }
+
   /* format subsequence cached with SeqPortStream */
 
   ffstring = FFGetString (ajp);
@@ -5193,7 +5821,7 @@ NLM_EXTERN CharPtr FormatSequenceBlock (
       }
       if (StringDoesHaveText (buf)) {
         ExpandSeqLine (buf);
-        PrintSeqLine (ffstring, afp->format, buf, start + startgapgap, start + lin);
+        PrintSeqLine (ajp, ffstring, afp->format, buf, gi, start + startgapgap, start + lin);
       }
       count = 0;
       blk = 0;
@@ -5210,7 +5838,7 @@ NLM_EXTERN CharPtr FormatSequenceBlock (
     }
     if (StringDoesHaveText (buf)) {
       ExpandSeqLine (buf);
-      PrintSeqLine (ffstring, afp->format, buf, start + startgapgap, start + lin);
+      PrintSeqLine (ajp, ffstring, afp->format, buf, gi, start + startgapgap, start + lin);
     }
   }
 
@@ -5362,12 +5990,16 @@ NLM_EXTERN CharPtr FormatSlashBlock (
       is.taxonomy = gbseq->taxonomy;
       is.references = (INSDReferencePtr) gbseq->references;
       is.comment = gbseq->comment;
+      is.comment_set = (INSDCommentPtr) gbseq->comment_set;
+      is.struc_comments = (INSDStrucCommentPtr) gbseq->struc_comments;
       is.primary = gbseq->primary;
       is.source_db = gbseq->source_db;
       is.database_reference = gbseq->database_reference;
       is.feature_table = (INSDFeaturePtr) gbseq->feature_table;
+      is.feature_set = (INSDFeatureSetPtr) gbseq->feature_set;
       is.sequence = gbseq->sequence;
       is.contig = gbseq->contig;
+      is.alt_seq = (INSDAltSeqDataPtr) gbseq->alt_seq;
       INSDSeqAsnWrite (&is, afp->aip, afp->atp);
     } else {
       GBSeqAsnWrite (gbseq, afp->aip, afp->atp);
diff --git a/api/asn2gnbi.h b/api/asn2gnbi.h
index fb2848c..a9e09d8 100644
--- a/api/asn2gnbi.h
+++ b/api/asn2gnbi.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   12/30/03
 *
-* $Revision: 1.112 $
+* $Revision: 1.123 $
 *
 * File Description:  New GenBank flatfile generator, internal header
 *
@@ -138,8 +138,10 @@ typedef struct int_asn2gb_job {
   Boolean         masterStyle;
   Boolean         newSourceOrg;
   Boolean         produceInsdSeq;
+  Boolean         oldXmlPolicy;
   Boolean         refseqConventions;
   ValNodePtr      lockedBspList;
+  ValNodePtr      fargaps;
   ValNodePtr      gapvnp;
   ValNodePtr      remotevnp;
   Asn2gbLockFunc  remotelock;
@@ -157,11 +159,13 @@ typedef struct int_asn2gb_job {
   Boolean         www;
   Boolean         specialGapFormat;
   Boolean         hideGoTerms;
+  Boolean         multiIntervalGenes;
   Boolean         reindex;
   Int4            seqGapCurrLen;
   ValNodePtr      gihead;
   ValNodePtr      gitail;
   TextFsaPtr      bad_html_fsa;
+  Boolean         seqspans;
 } IntAsn2gbJob, PNTR IntAsn2gbJobPtr;
 
 /* array for assigning biosource and feature data fields to qualifiers */
@@ -306,6 +310,8 @@ typedef struct asn2gbwork {
 
   Char             basename [SEQID_MAX_LEN];
 
+  ValNodePtr       currfargap;
+
   SeqFeatPtr       lastsfp;
   SeqAnnotPtr      lastsap;
   Int4             lastleft;
@@ -392,6 +398,8 @@ typedef struct int_feat_block {
   Boolean     isCDS;     /* set if using IntCdsBlock */
   Boolean     isPrt;     /* set if using IntPrtBlock */
   Boolean     firstfeat;
+  Int4       left;
+  Int4       right;
 } IntFeatBlock, PNTR IntFeatBlockPtr;
 
 /* internal cds block has fields on top of IntFeatBlock fields */
@@ -600,6 +608,7 @@ NLM_EXTERN SourceType orgModToSourceIdx [41];
 typedef enum {
   FTQUAL_allele = 1,
   FTQUAL_anticodon,
+  FTQUAL_artificial_location,
   FTQUAL_bond,
   FTQUAL_bond_type,
   FTQUAL_bound_moiety,
@@ -786,6 +795,8 @@ NLM_EXTERN void InitWWW (IntAsn2gbJobPtr ajp);
 NLM_EXTERN void FiniWWW (IntAsn2gbJobPtr ajp);
 NLM_EXTERN Boolean GetWWW (IntAsn2gbJobPtr ajp);
 
+NLM_EXTERN Boolean CommentHasSuspiciousHtml (IntAsn2gbJobPtr ajp, CharPtr searchString);
+
 NLM_EXTERN StringItemPtr FFGetString (IntAsn2gbJobPtr ajp);
 NLM_EXTERN void FFRecycleString (IntAsn2gbJobPtr ajp, StringItemPtr ffstring);
 NLM_EXTERN void FFAddOneChar (
@@ -1018,7 +1029,8 @@ NLM_EXTERN CharPtr FFFlatLoc (
   IntAsn2gbJobPtr ajp,
   BioseqPtr bsp,
   SeqLocPtr location,
-  Boolean masterStyle
+  Boolean masterStyle,
+  Boolean isGap
 );
 
 NLM_EXTERN void FF_www_featloc(StringItemPtr ffstring, CharPtr loc);
@@ -1131,6 +1143,7 @@ NLM_EXTERN void AddFeatureBlock (
 NLM_EXTERN void AddLocusBlock (
   Asn2gbWorkPtr awp,
   Boolean willshowwgs,
+  Boolean willshowcage,
   Boolean willshowgenome,
   Boolean willshowcontig,
   Boolean willshowsequence
@@ -1182,6 +1195,9 @@ NLM_EXTERN void AddSourceFeatBlock (
 NLM_EXTERN void AddWGSBlock (
   Asn2gbWorkPtr awp
 );
+NLM_EXTERN void AddCAGEBlock (
+  Asn2gbWorkPtr awp
+);
 NLM_EXTERN void AddGenomeBlock (
   Asn2gbWorkPtr awp
 );
diff --git a/api/asn2gnbk.h b/api/asn2gnbk.h
index 5f9ab5f..55d0698 100644
--- a/api/asn2gnbk.h
+++ b/api/asn2gnbk.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 6.79 $
+* $Revision: 6.84 $
 *
 * File Description:  New GenBank flatfile generator
 *
@@ -119,6 +119,7 @@ typedef unsigned long FlgType;
 #define SPECIAL_GAP_DISPLAY    65536
 
 #define FORCE_PRIMARY_BLOCK   131072
+#define FORCE_ALLOW_FAR_FEATS 262144
 
 /* locking behavior for system performance */
 
@@ -169,6 +170,9 @@ typedef unsigned long CstType;
 
 #define HIDE_EVIDENCE_QUALS   524288
 
+#define NEW_XML_POLICY       1048576
+#define OLD_GBSEQ_XML        2097152
+
 /* opaque pointer for special extensions */
 
 struct XtraData;
@@ -204,6 +208,12 @@ NLM_EXTERN Boolean BioseqToGnbk (
 
 NLM_EXTERN CharPtr GetFlatFileAffilString (AffilPtr afp);
 
+NLM_EXTERN void PrintFTCodeBreak (
+  ValNodePtr PNTR head,
+  CodeBreakPtr cbp,
+  BioseqPtr target
+);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/api/asn2gnbp.h b/api/asn2gnbp.h
index a8c18f5..fab325e 100644
--- a/api/asn2gnbp.h
+++ b/api/asn2gnbp.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 6.44 $
+* $Revision: 6.46 $
 *
 * File Description:  New GenBank flatfile generator, private header
 *
@@ -264,7 +264,9 @@ typedef void (*Asn2gbWriteFunc) (
   BlockType blocktype,
   Uint2 entityID,
   Uint2 itemtype,
-  Uint4 itemID
+  Uint4 itemID,
+  Int4 left,
+  Int4 right
 );
 
 typedef ValNodePtr (*Asn2gbLockFunc) (SeqIdPtr sip, Pointer remotedata);
@@ -286,6 +288,7 @@ typedef struct XtraData {
   Int4             nextGi;
   BlockMask        bkmask;
   Boolean          reindex;
+  Boolean          seqspans;
 } XtraBlock;
 
 
diff --git a/api/ecnum_ambiguous.inc b/api/ecnum_ambiguous.inc
new file mode 100644
index 0000000..a9408e2
--- /dev/null
+++ b/api/ecnum_ambiguous.inc
@@ -0,0 +1,702 @@
+/*  $Id: ecnum_ambiguous.inc,v 1.1 2010/07/09 16:36:07 ucko Exp $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  The Enzyme Commission
+ *
+ * File Description:
+ *   Built-in copy of ecnum_ambiguous.txt.
+ *
+ */
+
+static const char* const kECNum_ambiguous[] = {
+    "1.-.-.-",
+    "1.1.-.-",
+    "1.1.1.-",
+    "1.1.1.n",
+    "1.1.2.-",
+    "1.1.2.n",
+    "1.1.3.-",
+    "1.1.3.n",
+    "1.1.4.-",
+    "1.1.4.n",
+    "1.1.5.-",
+    "1.1.5.n",
+    "1.1.98.-",
+    "1.1.98.n",
+    "1.1.99.-",
+    "1.1.99.n",
+    "1.1.n.n",
+    "1.2.-.-",
+    "1.2.1.-",
+    "1.2.1.n",
+    "1.2.2.-",
+    "1.2.2.n",
+    "1.2.3.-",
+    "1.2.3.n",
+    "1.2.4.-",
+    "1.2.4.n",
+    "1.2.7.-",
+    "1.2.7.n",
+    "1.2.99.-",
+    "1.2.99.n",
+    "1.2.n.n",
+    "1.3.-.-",
+    "1.3.1.-",
+    "1.3.1.n",
+    "1.3.2.-",
+    "1.3.2.n",
+    "1.3.3.-",
+    "1.3.3.n",
+    "1.3.5.-",
+    "1.3.5.n",
+    "1.3.7.-",
+    "1.3.7.n",
+    "1.3.99.-",
+    "1.3.99.n",
+    "1.3.n.n",
+    "1.4.-.-",
+    "1.4.1.-",
+    "1.4.1.n",
+    "1.4.2.-",
+    "1.4.2.n",
+    "1.4.3.-",
+    "1.4.3.n",
+    "1.4.4.-",
+    "1.4.4.n",
+    "1.4.5.-",
+    "1.4.5.n",
+    "1.4.7.-",
+    "1.4.7.n",
+    "1.4.99.-",
+    "1.4.99.n",
+    "1.4.n.n",
+    "1.5.-.-",
+    "1.5.1.-",
+    "1.5.1.n",
+    "1.5.3.-",
+    "1.5.3.n",
+    "1.5.4.-",
+    "1.5.4.n",
+    "1.5.5.-",
+    "1.5.5.n",
+    "1.5.7.-",
+    "1.5.7.n",
+    "1.5.8.-",
+    "1.5.8.n",
+    "1.5.99.-",
+    "1.5.99.n",
+    "1.5.n.n",
+    "1.6.-.-",
+    "1.6.1.-",
+    "1.6.1.n",
+    "1.6.2.-",
+    "1.6.2.n",
+    "1.6.3.-",
+    "1.6.3.n",
+    "1.6.4.-",
+    "1.6.4.n",
+    "1.6.5.-",
+    "1.6.5.n",
+    "1.6.6.-",
+    "1.6.6.n",
+    "1.6.7.-",
+    "1.6.7.n",
+    "1.6.8.-",
+    "1.6.8.n",
+    "1.6.99.-",
+    "1.6.99.n",
+    "1.6.n.n",
+    "1.7.-.-",
+    "1.7.1.-",
+    "1.7.1.n",
+    "1.7.2.-",
+    "1.7.2.n",
+    "1.7.3.-",
+    "1.7.3.n",
+    "1.7.5.-",
+    "1.7.5.n",
+    "1.7.7.-",
+    "1.7.7.n",
+    "1.7.99.-",
+    "1.7.99.n",
+    "1.7.n.n",
+    "1.8.-.-",
+    "1.8.1.-",
+    "1.8.1.n",
+    "1.8.2.-",
+    "1.8.2.n",
+    "1.8.3.-",
+    "1.8.3.n",
+    "1.8.4.-",
+    "1.8.4.n",
+    "1.8.5.-",
+    "1.8.5.n",
+    "1.8.6.-",
+    "1.8.6.n",
+    "1.8.7.-",
+    "1.8.7.n",
+    "1.8.98.-",
+    "1.8.98.n",
+    "1.8.99.-",
+    "1.8.99.n",
+    "1.8.n.n",
+    "1.9.-.-",
+    "1.9.3.-",
+    "1.9.3.n",
+    "1.9.6.-",
+    "1.9.6.n",
+    "1.9.99.-",
+    "1.9.99.n",
+    "1.9.n.n",
+    "1.10.-.-",
+    "1.10.1.-",
+    "1.10.1.n",
+    "1.10.2.-",
+    "1.10.2.n",
+    "1.10.3.-",
+    "1.10.3.n",
+    "1.10.99.-",
+    "1.10.99.n",
+    "1.10.n.n",
+    "1.11.-.-",
+    "1.11.1.-",
+    "1.11.1.n",
+    "1.11.n.n",
+    "1.12.-.-",
+    "1.12.1.-",
+    "1.12.1.n",
+    "1.12.2.-",
+    "1.12.2.n",
+    "1.12.5.-",
+    "1.12.5.n",
+    "1.12.7.-",
+    "1.12.7.n",
+    "1.12.98.-",
+    "1.12.98.n",
+    "1.12.99.-",
+    "1.12.99.n",
+    "1.12.n.n",
+    "1.13.-.-",
+    "1.13.1.-",
+    "1.13.1.n",
+    "1.13.11.-",
+    "1.13.11.n",
+    "1.13.12.-",
+    "1.13.12.n",
+    "1.13.99.-",
+    "1.13.99.n",
+    "1.13.n.n",
+    "1.14.-.-",
+    "1.14.1.-",
+    "1.14.1.n",
+    "1.14.2.-",
+    "1.14.2.n",
+    "1.14.3.-",
+    "1.14.3.n",
+    "1.14.11.-",
+    "1.14.11.n",
+    "1.14.12.-",
+    "1.14.12.n",
+    "1.14.13.-",
+    "1.14.13.n",
+    "1.14.14.-",
+    "1.14.14.n",
+    "1.14.15.-",
+    "1.14.15.n",
+    "1.14.16.-",
+    "1.14.16.n",
+    "1.14.17.-",
+    "1.14.17.n",
+    "1.14.18.-",
+    "1.14.18.n",
+    "1.14.19.-",
+    "1.14.19.n",
+    "1.14.20.-",
+    "1.14.20.n",
+    "1.14.21.-",
+    "1.14.21.n",
+    "1.14.99.-",
+    "1.14.99.n",
+    "1.14.n.n",
+    "1.15.-.-",
+    "1.15.1.-",
+    "1.15.1.n",
+    "1.15.n.n",
+    "1.16.-.-",
+    "1.16.1.-",
+    "1.16.1.n",
+    "1.16.3.-",
+    "1.16.3.n",
+    "1.16.8.-",
+    "1.16.8.n",
+    "1.16.n.n",
+    "1.17.-.-",
+    "1.17.1.-",
+    "1.17.1.n",
+    "1.17.3.-",
+    "1.17.3.n",
+    "1.17.4.-",
+    "1.17.4.n",
+    "1.17.5.-",
+    "1.17.5.n",
+    "1.17.7.-",
+    "1.17.7.n",
+    "1.17.99.-",
+    "1.17.99.n",
+    "1.17.n.n",
+    "1.18.-.-",
+    "1.18.1.-",
+    "1.18.1.n",
+    "1.18.2.-",
+    "1.18.2.n",
+    "1.18.3.-",
+    "1.18.3.n",
+    "1.18.6.-",
+    "1.18.6.n",
+    "1.18.96.-",
+    "1.18.96.n",
+    "1.18.99.-",
+    "1.18.99.n",
+    "1.18.n.n",
+    "1.19.-.-",
+    "1.19.6.-",
+    "1.19.6.n",
+    "1.19.n.n",
+    "1.20.-.-",
+    "1.20.1.-",
+    "1.20.1.n",
+    "1.20.4.-",
+    "1.20.4.n",
+    "1.20.98.-",
+    "1.20.98.n",
+    "1.20.99.-",
+    "1.20.99.n",
+    "1.20.n.n",
+    "1.21.-.-",
+    "1.21.3.-",
+    "1.21.3.n",
+    "1.21.4.-",
+    "1.21.4.n",
+    "1.21.99.-",
+    "1.21.99.n",
+    "1.21.n.n",
+    "1.22.-.-",
+    "1.22.1.-",
+    "1.22.1.n",
+    "1.22.n.n",
+    "1.97.-.-",
+    "1.97.1.-",
+    "1.97.1.n",
+    "1.97.n.n",
+    "1.98.-.-",
+    "1.98.1.-",
+    "1.98.1.n",
+    "1.98.n.n",
+    "1.99.-.-",
+    "1.99.1.-",
+    "1.99.1.n",
+    "1.99.2.-",
+    "1.99.2.n",
+    "1.99.n.n",
+    "1.n.n.n",
+    "2.-.-.-",
+    "2.1.-.-",
+    "2.1.1.-",
+    "2.1.1.n",
+    "2.1.2.-",
+    "2.1.2.n",
+    "2.1.3.-",
+    "2.1.3.n",
+    "2.1.4.-",
+    "2.1.4.n",
+    "2.1.n.n",
+    "2.2.-.-",
+    "2.2.1.-",
+    "2.2.1.n",
+    "2.2.n.n",
+    "2.3.-.-",
+    "2.3.1.-",
+    "2.3.1.n",
+    "2.3.2.-",
+    "2.3.2.n",
+    "2.3.3.-",
+    "2.3.3.n",
+    "2.3.n.n",
+    "2.4.-.-",
+    "2.4.1.-",
+    "2.4.1.n",
+    "2.4.2.-",
+    "2.4.2.n",
+    "2.4.99.-",
+    "2.4.99.n",
+    "2.4.n.n",
+    "2.5.-.-",
+    "2.5.1.-",
+    "2.5.1.n",
+    "2.5.n.n",
+    "2.6.-.-",
+    "2.6.1.-",
+    "2.6.1.n",
+    "2.6.2.-",
+    "2.6.2.n",
+    "2.6.3.-",
+    "2.6.3.n",
+    "2.6.99.-",
+    "2.6.99.n",
+    "2.6.n.n",
+    "2.7.-.-",
+    "2.7.1.-",
+    "2.7.1.n",
+    "2.7.2.-",
+    "2.7.2.n",
+    "2.7.3.-",
+    "2.7.3.n",
+    "2.7.4.-",
+    "2.7.4.n",
+    "2.7.5.-",
+    "2.7.5.n",
+    "2.7.6.-",
+    "2.7.6.n",
+    "2.7.7.-",
+    "2.7.7.n",
+    "2.7.8.-",
+    "2.7.8.n",
+    "2.7.9.-",
+    "2.7.9.n",
+    "2.7.10.-",
+    "2.7.10.n",
+    "2.7.11.-",
+    "2.7.11.n",
+    "2.7.12.-",
+    "2.7.12.n",
+    "2.7.13.-",
+    "2.7.13.n",
+    "2.7.99.-",
+    "2.7.99.n",
+    "2.7.n.n",
+    "2.8.-.-",
+    "2.8.1.-",
+    "2.8.1.n",
+    "2.8.2.-",
+    "2.8.2.n",
+    "2.8.3.-",
+    "2.8.3.n",
+    "2.8.4.-",
+    "2.8.4.n",
+    "2.8.n.n",
+    "2.9.-.-",
+    "2.9.1.-",
+    "2.9.1.n",
+    "2.9.n.n",
+    "2.n.n.n",
+    "3.-.-.-",
+    "3.1.-.-",
+    "3.1.1.-",
+    "3.1.1.n",
+    "3.1.2.-",
+    "3.1.2.n",
+    "3.1.3.-",
+    "3.1.3.n",
+    "3.1.4.-",
+    "3.1.4.n",
+    "3.1.5.-",
+    "3.1.5.n",
+    "3.1.6.-",
+    "3.1.6.n",
+    "3.1.7.-",
+    "3.1.7.n",
+    "3.1.8.-",
+    "3.1.8.n",
+    "3.1.11.-",
+    "3.1.11.n",
+    "3.1.13.-",
+    "3.1.13.n",
+    "3.1.14.-",
+    "3.1.14.n",
+    "3.1.15.-",
+    "3.1.15.n",
+    "3.1.16.-",
+    "3.1.16.n",
+    "3.1.21.-",
+    "3.1.21.n",
+    "3.1.22.-",
+    "3.1.22.n",
+    "3.1.23.-",
+    "3.1.23.n",
+    "3.1.24.-",
+    "3.1.24.n",
+    "3.1.25.-",
+    "3.1.25.n",
+    "3.1.26.-",
+    "3.1.26.n",
+    "3.1.27.-",
+    "3.1.27.n",
+    "3.1.30.-",
+    "3.1.30.n",
+    "3.1.31.-",
+    "3.1.31.n",
+    "3.1.n.n",
+    "3.2.-.-",
+    "3.2.1.-",
+    "3.2.1.n",
+    "3.2.2.-",
+    "3.2.2.n",
+    "3.2.3.-",
+    "3.2.3.n",
+    "3.2.n.n",
+    "3.3.-.-",
+    "3.3.1.-",
+    "3.3.1.n",
+    "3.3.2.-",
+    "3.3.2.n",
+    "3.3.n.n",
+    "3.4.-.-",
+    "3.4.1.-",
+    "3.4.1.n",
+    "3.4.2.-",
+    "3.4.2.n",
+    "3.4.3.-",
+    "3.4.3.n",
+    "3.4.4.-",
+    "3.4.4.n",
+    "3.4.11.-",
+    "3.4.11.n",
+    "3.4.12.-",
+    "3.4.12.n",
+    "3.4.13.-",
+    "3.4.13.n",
+    "3.4.14.-",
+    "3.4.14.n",
+    "3.4.15.-",
+    "3.4.15.n",
+    "3.4.16.-",
+    "3.4.16.n",
+    "3.4.17.-",
+    "3.4.17.n",
+    "3.4.18.-",
+    "3.4.18.n",
+    "3.4.19.-",
+    "3.4.19.n",
+    "3.4.21.-",
+    "3.4.21.n",
+    "3.4.22.-",
+    "3.4.22.n",
+    "3.4.23.-",
+    "3.4.23.n",
+    "3.4.24.-",
+    "3.4.24.n",
+    "3.4.25.-",
+    "3.4.25.n",
+    "3.4.99.-",
+    "3.4.99.n",
+    "3.4.n.n",
+    "3.5.-.-",
+    "3.5.1.-",
+    "3.5.1.n",
+    "3.5.2.-",
+    "3.5.2.n",
+    "3.5.3.-",
+    "3.5.3.n",
+    "3.5.4.-",
+    "3.5.4.n",
+    "3.5.5.-",
+    "3.5.5.n",
+    "3.5.99.-",
+    "3.5.99.n",
+    "3.5.n.n",
+    "3.6.-.-",
+    "3.6.1.-",
+    "3.6.1.n",
+    "3.6.2.-",
+    "3.6.2.n",
+    "3.6.3.-",
+    "3.6.3.n",
+    "3.6.4.-",
+    "3.6.4.n",
+    "3.6.5.-",
+    "3.6.5.n",
+    "3.6.n.n",
+    "3.7.-.-",
+    "3.7.1.-",
+    "3.7.1.n",
+    "3.7.n.n",
+    "3.8.-.-",
+    "3.8.1.-",
+    "3.8.1.n",
+    "3.8.2.-",
+    "3.8.2.n",
+    "3.8.n.n",
+    "3.9.-.-",
+    "3.9.1.-",
+    "3.9.1.n",
+    "3.9.n.n",
+    "3.10.-.-",
+    "3.10.1.-",
+    "3.10.1.n",
+    "3.10.n.n",
+    "3.11.-.-",
+    "3.11.1.-",
+    "3.11.1.n",
+    "3.11.n.n",
+    "3.12.-.-",
+    "3.12.1.-",
+    "3.12.1.n",
+    "3.12.n.n",
+    "3.13.-.-",
+    "3.13.1.-",
+    "3.13.1.n",
+    "3.13.n.n",
+    "3.n.n.n",
+    "4.-.-.-",
+    "4.1.-.-",
+    "4.1.1.-",
+    "4.1.1.n",
+    "4.1.2.-",
+    "4.1.2.n",
+    "4.1.3.-",
+    "4.1.3.n",
+    "4.1.99.-",
+    "4.1.99.n",
+    "4.1.n.n",
+    "4.2.-.-",
+    "4.2.1.-",
+    "4.2.1.n",
+    "4.2.2.-",
+    "4.2.2.n",
+    "4.2.3.-",
+    "4.2.3.n",
+    "4.2.99.-",
+    "4.2.99.n",
+    "4.2.n.n",
+    "4.3.-.-",
+    "4.3.1.-",
+    "4.3.1.n",
+    "4.3.2.-",
+    "4.3.2.n",
+    "4.3.3.-",
+    "4.3.3.n",
+    "4.3.99.-",
+    "4.3.99.n",
+    "4.3.n.n",
+    "4.4.-.-",
+    "4.4.1.-",
+    "4.4.1.n",
+    "4.4.n.n",
+    "4.5.-.-",
+    "4.5.1.-",
+    "4.5.1.n",
+    "4.5.n.n",
+    "4.6.-.-",
+    "4.6.1.-",
+    "4.6.1.n",
+    "4.6.n.n",
+    "4.99.-.-",
+    "4.99.1.-",
+    "4.99.1.n",
+    "4.99.n.n",
+    "4.n.n.n",
+    "5.-.-.-",
+    "5.1.-.-",
+    "5.1.1.-",
+    "5.1.1.n",
+    "5.1.2.-",
+    "5.1.2.n",
+    "5.1.3.-",
+    "5.1.3.n",
+    "5.1.99.-",
+    "5.1.99.n",
+    "5.1.n.n",
+    "5.2.-.-",
+    "5.2.1.-",
+    "5.2.1.n",
+    "5.2.n.n",
+    "5.3.-.-",
+    "5.3.1.-",
+    "5.3.1.n",
+    "5.3.2.-",
+    "5.3.2.n",
+    "5.3.3.-",
+    "5.3.3.n",
+    "5.3.4.-",
+    "5.3.4.n",
+    "5.3.99.-",
+    "5.3.99.n",
+    "5.3.n.n",
+    "5.4.-.-",
+    "5.4.1.-",
+    "5.4.1.n",
+    "5.4.2.-",
+    "5.4.2.n",
+    "5.4.3.-",
+    "5.4.3.n",
+    "5.4.4.-",
+    "5.4.4.n",
+    "5.4.99.-",
+    "5.4.99.n",
+    "5.4.n.n",
+    "5.5.-.-",
+    "5.5.1.-",
+    "5.5.1.n",
+    "5.5.n.n",
+    "5.99.-.-",
+    "5.99.1.-",
+    "5.99.1.n",
+    "5.99.n.n",
+    "5.n.n.n",
+    "6.-.-.-",
+    "6.1.-.-",
+    "6.1.1.-",
+    "6.1.1.n",
+    "6.1.n.n",
+    "6.2.-.-",
+    "6.2.1.-",
+    "6.2.1.n",
+    "6.2.n.n",
+    "6.3.-.-",
+    "6.3.1.-",
+    "6.3.1.n",
+    "6.3.2.-",
+    "6.3.2.n",
+    "6.3.3.-",
+    "6.3.3.n",
+    "6.3.4.-",
+    "6.3.4.n",
+    "6.3.5.-",
+    "6.3.5.n",
+    "6.3.n.n",
+    "6.4.-.-",
+    "6.4.1.-",
+    "6.4.1.n",
+    "6.4.n.n",
+    "6.5.-.-",
+    "6.5.1.-",
+    "6.5.1.n",
+    "6.5.n.n",
+    "6.6.-.-",
+    "6.6.1.-",
+    "6.6.1.n",
+    "6.6.n.n",
+    "6.n.n.n"
+};
diff --git a/api/ecnum_deleted.inc b/api/ecnum_deleted.inc
new file mode 100644
index 0000000..4a6b6a9
--- /dev/null
+++ b/api/ecnum_deleted.inc
@@ -0,0 +1,199 @@
+/*  $Id: ecnum_deleted.inc,v 1.1 2010/07/09 16:36:07 ucko Exp $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  The Enzyme Commission
+ *
+ * File Description:
+ *   Built-in copy of ecnum_deleted.txt.
+ *
+ */
+
+static const char* const kECNum_deleted[] = {
+    "1.1.1.74",
+    "1.1.1.155",
+    "1.1.1.249",
+    "1.1.3.25",
+    "1.1.3.31",
+    "1.1.5.1",
+    "1.2.1.6",
+    "1.2.3.10",
+    "1.2.7.9",
+    "1.3.1.23",
+    "1.3.1.55",
+    "1.3.1.59",
+    "1.3.1.61",
+    "1.4.3.6",
+    "1.4.3.18",
+    "1.5.3.3",
+    "1.6.2.3",
+    "1.6.5.1",
+    "1.7.1.8",
+    "1.7.99.2",
+    "1.7.99.5",
+    "1.8.1.1",
+    "1.12.99.2",
+    "1.12.99.5",
+    "1.13.1.7",
+    "1.13.11.7",
+    "1.13.11.42",
+    "1.13.12.10",
+    "1.13.12.11",
+    "1.14.1.9",
+    "1.14.1.11",
+    "1.14.11.5",
+    "1.14.13.65",
+    "1.14.14.4",
+    "1.14.99.18",
+    "1.99.1.3",
+    "1.99.1.4",
+    "1.99.1.6",
+    "1.99.1.8",
+    "1.99.1.10",
+    "1.99.1.12",
+    "2.1.1.30",
+    "2.1.1.73",
+    "2.1.1.92",
+    "2.1.1.93",
+    "2.1.1.138",
+    "2.1.3.4",
+    "2.3.1.70",
+    "2.3.1.120",
+    "2.3.1.124",
+    "2.4.1.6",
+    "2.4.1.75",
+    "2.4.1.112",
+    "2.4.1.112",
+    "2.4.1.154",
+    "2.4.1.233",
+    "2.4.1.235",
+    "2.5.1.64",
+    "2.6.1.20",
+    "2.6.1.61",
+    "2.6.1.69",
+    "2.7.1.9",
+    "2.7.1.57",
+    "2.7.1.70",
+    "2.7.1.97",
+    "2.7.1.98",
+    "2.7.1.120",
+    "2.7.7.20",
+    "2.7.7.29",
+    "2.8.2.12",
+    "2.8.3.4",
+    "3.1.1.9",
+    "3.1.1.16",
+    "3.1.2.9",
+    "3.1.3.61",
+    "3.1.4.24",
+    "3.1.4.26",
+    "3.1.4.29",
+    "3.1.4.32",
+    "3.1.4.33",
+    "3.1.4.34",
+    "3.1.6.5",
+    "3.2.1.5",
+    "3.2.1.9",
+    "3.2.1.16",
+    "3.2.1.19",
+    "3.2.1.27",
+    "3.2.1.90",
+    "3.4.4.25",
+    "3.4.11.11",
+    "3.4.11.12",
+    "3.4.12.9",
+    "3.4.12.13",
+    "3.4.13.14",
+    "3.4.13.16",
+    "3.4.14.7",
+    "3.4.17.5",
+    "3.4.19.4",
+    "3.4.21.16",
+    "3.4.21.17",
+    "3.4.21.18",
+    "3.4.21.23",
+    "3.4.21.24",
+    "3.4.21.33",
+    "3.4.21.40",
+    "3.4.21.51",
+    "3.4.21.52",
+    "3.4.21.56",
+    "3.4.21.58",
+    "3.4.22.13",
+    "3.4.22.20",
+    "3.4.23.11",
+    "3.4.23.13",
+    "3.4.23.14",
+    "3.4.24.2",
+    "3.4.24.9",
+    "3.4.24.10",
+    "3.4.99.2",
+    "3.4.99.3",
+    "3.4.99.7",
+    "3.4.99.8",
+    "3.4.99.9",
+    "3.4.99.11",
+    "3.4.99.12",
+    "3.4.99.14",
+    "3.4.99.15",
+    "3.4.99.16",
+    "3.4.99.17",
+    "3.4.99.18",
+    "3.4.99.20",
+    "3.4.99.21",
+    "3.4.99.23",
+    "3.4.99.24",
+    "3.4.99.27",
+    "3.4.99.29",
+    "3.4.99.33",
+    "3.4.99.34",
+    "3.4.99.37",
+    "3.4.99.39",
+    "3.4.99.40",
+    "3.4.99.42",
+    "3.5.1.80",
+    "3.6.3.13",
+    "3.6.3.45",
+    "3.13.1.2",
+    "4.1.1.13",
+    "4.1.2.3",
+    "4.1.2.6",
+    "4.2.1.23",
+    "4.2.1.71",
+    "4.2.1.86",
+    "4.2.99.5",
+    "4.3.1.5",
+    "4.3.1.11",
+    "4.3.1.21",
+    "4.4.1.12",
+    "5.2.1.11",
+    "5.3.1.2",
+    "5.3.1.11",
+    "5.3.1.18",
+    "5.3.99.1",
+    "5.4.3.1",
+    "6.1.1.8",
+    "6.2.1.29",
+    "6.3.2.15"
+};
diff --git a/api/ecnum_replaced.inc b/api/ecnum_replaced.inc
new file mode 100644
index 0000000..3aea7c1
--- /dev/null
+++ b/api/ecnum_replaced.inc
@@ -0,0 +1,624 @@
+/*  $Id: ecnum_replaced.inc,v 1.1 2010/07/09 16:36:07 ucko Exp $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  The Enzyme Commission
+ *
+ * File Description:
+ *   Built-in copy of ecnum_replaced.txt.
+ *
+ */
+
+static const char* const kECNum_replaced[] = {
+    "1.1.1.5	1.1.1.303",
+    "1.1.1.68	1.5.1.20",
+    "1.1.1.70	1.2.1.3",
+    "1.1.1.89	1.1.1.86",
+    "1.1.1.109	1.3.1.28",
+    "1.1.1.139	1.1.1.21",
+    "1.1.1.171	1.5.1.20",
+    "1.1.1.180	1.1.1.131",
+    "1.1.1.182	1.1.1.228",
+    "1.1.1.204	1.17.1.4",
+    "1.1.1.242	1.3.1.69",
+    "1.1.1.253	1.5.1.33",
+    "1.1.2.1	1.1.5.3",
+    "1.1.3.1	1.1.3.15",
+    "1.1.3.2	1.13.12.4",
+    "1.1.3.22	1.17.3.2",
+    "1.1.3.24	1.3.3.12",
+    "1.1.3.26	1.21.3.2",
+    "1.1.3.32	1.14.21.1",
+    "1.1.3.33	1.14.21.2",
+    "1.1.3.34	1.14.21.3",
+    "1.1.3.35	1.14.21.4",
+    "1.1.3.36	1.14.21.5",
+    "1.1.99.5	1.1.5.3",
+    "1.1.99.15	1.5.1.20",
+    "1.1.99.16	1.1.5.4",
+    "1.1.99.17	1.1.5.2",
+    "1.1.99.19	1.17.99.4",
+    "1.2.1.1	1.1.1.284",
+    "1.2.1.14	1.1.1.205",
+    "1.2.1.34	1.1.1.131",
+    "1.2.1.35	1.1.1.203",
+    "1.2.1.37	1.17.1.4",
+    "1.2.1.55	1.1.1.279",
+    "1.2.1.56	1.1.1.280",
+    "1.2.3.2	1.17.3.2",
+    "1.2.3.12	1.14.13.82",
+    "1.2.4.3	1.2.4.4",
+    "1.2.99.1	1.17.99.4",
+    "1.3.1.50	1.1.1.252",
+    "1.3.2.1	1.3.99.2",
+    "1.3.2.2	1.3.99.3",
+    "1.3.3.2	1.14.21.6",
+    "1.3.99.9	1.21.99.1",
+    "1.3.99.11	1.3.5.2",
+    "1.4.1.6	1.21.4.1",
+    "1.4.3.9	1.4.3.4",
+    "1.4.3.17	1.3.3.10",
+    "1.4.4.1	1.21.4.1",
+    "1.5.1.4	1.5.1.3",
+    "1.5.1.13	1.17.1.5",
+    "1.5.1.14	1.5.1.21",
+    "1.5.1.35	1.2.1.19",
+    "1.5.3.8	1.3.3.8",
+    "1.5.3.9	1.21.3.3",
+    "1.5.99.7	1.5.8.2",
+    "1.5.99.10	1.5.8.1",
+    "1.6.2.1	1.6.99.3",
+    "1.6.4.1	1.8.1.6",
+    "1.6.4.2	1.8.1.7",
+    "1.6.4.3	1.8.1.4",
+    "1.6.4.4	1.8.1.8",
+    "1.6.4.5	1.8.1.9",
+    "1.6.4.6	1.8.1.10",
+    "1.6.4.7	1.8.1.11",
+    "1.6.4.8	1.8.1.12",
+    "1.6.4.9	1.8.1.13",
+    "1.6.4.10	1.8.1.14",
+    "1.6.6.1	1.7.1.1",
+    "1.6.6.2	1.7.1.2",
+    "1.6.6.3	1.7.1.3",
+    "1.6.6.4	1.7.1.4",
+    "1.6.6.5	1.7.2.1",
+    "1.6.6.6	1.7.1.5",
+    "1.6.6.7	1.7.1.6",
+    "1.6.6.8	1.7.1.7",
+    "1.6.6.10	1.7.1.9",
+    "1.6.6.11	1.7.1.10",
+    "1.6.6.12	1.7.1.11",
+    "1.6.6.13	1.7.1.12",
+    "1.6.7.1	1.18.1.2",
+    "1.6.7.2	1.18.1.1",
+    "1.6.8.1	1.5.1.29",
+    "1.6.8.2	1.5.1.30",
+    "1.6.99.2	1.6.5.2",
+    "1.6.99.4	1.18.1.2",
+    "1.6.99.7	1.5.1.34",
+    "1.6.99.8	1.16.1.3",
+    "1.6.99.9	1.16.1.4",
+    "1.6.99.10	1.5.1.34",
+    "1.6.99.11	1.16.1.5",
+    "1.6.99.12	1.16.1.6",
+    "1.6.99.13	1.16.1.7",
+    "1.7.99.3	1.7.2.1",
+    "1.8.4.5	1.8.4.13",
+    "1.8.4.6	1.8.4.11",
+    "1.8.6.1	2.5.1.18",
+    "1.8.99.4	1.8.4.8",
+    "1.9.3.2	1.7.2.1",
+    "1.10.3.7	1.21.3.4",
+    "1.10.3.8	1.21.3.5",
+    "1.11.1.4	1.13.11.11",
+    "1.12.1.1	1.12.7.2",
+    "1.12.7.1	1.12.7.2",
+    "1.12.99.1	1.12.98.1",
+    "1.12.99.3	1.12.5.1",
+    "1.12.99.4	1.12.98.2",
+    "1.13.1.1	1.13.11.1",
+    "1.13.1.2	1.13.11.2",
+    "1.13.1.3	1.13.11.3",
+    "1.13.1.4	1.13.11.4",
+    "1.13.1.5	1.13.11.5",
+    "1.13.1.6	1.13.11.6",
+    "1.13.1.8	1.13.11.8",
+    "1.13.1.9	1.13.11.9",
+    "1.13.1.10	1.13.11.10",
+    "1.13.1.11	1.13.99.1",
+    "1.13.1.12	1.13.11.11",
+    "1.13.1.13	1.13.11.12",
+    "1.13.11.21	1.14.99.36",
+    "1.13.11.32	1.13.12.16",
+    "1.13.99.2	1.14.12.10",
+    "1.13.99.4	1.14.12.9",
+    "1.13.99.5	1.13.11.47",
+    "1.14.1.1	1.14.14.1",
+    "1.14.1.2	1.14.13.9",
+    "1.14.1.3	1.14.99.7",
+    "1.14.1.4	1.14.99.2",
+    "1.14.1.5	1.14.13.5",
+    "1.14.1.6	1.14.15.4",
+    "1.14.1.7	1.14.99.9",
+    "1.14.1.8	1.14.99.10",
+    "1.14.1.10	1.14.99.11",
+    "1.14.2.1	1.14.17.1",
+    "1.14.2.2	1.13.11.27",
+    "1.14.3.1	1.14.16.1",
+    "1.14.12.2	1.14.13.35",
+    "1.14.12.6	1.14.13.66",
+    "1.14.13.45	1.14.18.2",
+    "1.14.14.2	1.14.14.1",
+    "1.14.14.6	1.14.13.111",
+    "1.14.17.2	1.14.18.1",
+    "1.14.99.5	1.14.19.1",
+    "1.14.99.6	1.14.19.2",
+    "1.14.99.8	1.14.14.1",
+    "1.14.99.13	1.14.13.23",
+    "1.14.99.16	1.14.13.72",
+    "1.14.99.17	1.14.16.5",
+    "1.14.99.25	1.14.19.3",
+    "1.17.1.6	1.17.99.5",
+    "1.17.4.3	1.17.7.1",
+    "1.18.2.1	1.18.6.1",
+    "1.18.3.1	1.12.7.2",
+    "1.18.96.1	1.15.1.2",
+    "1.18.99.1	1.12.7.2",
+    "1.97.1.5	1.20.4.1",
+    "1.97.1.6	1.20.99.1",
+    "1.97.1.7	1.20.4.2",
+    "1.98.1.1	1.12.7.2",
+    "1.99.1.1	1.14.14.1",
+    "1.99.1.2	1.14.16.1",
+    "1.99.1.5	1.14.13.9",
+    "1.99.1.7	1.14.15.4",
+    "1.99.1.9	1.14.99.9",
+    "1.99.1.11	1.14.99.10",
+    "1.99.1.13	1.14.99.7",
+    "1.99.1.14	1.13.11.27",
+    "1.99.2.1	1.13.11.12",
+    "1.99.2.2	1.13.11.1",
+    "1.99.2.3	1.13.11.3",
+    "1.99.2.4	1.13.11.4",
+    "1.99.2.5	1.13.11.5",
+    "1.99.2.6	1.13.99.1",
+    "2.1.1.23	2.1.1.126",
+    "2.1.1.24	2.1.1.100",
+    "2.1.1.58	2.6.1.5",
+    "2.1.1.81	2.1.1.49",
+    "2.1.1.134	2.1.1.129",
+    "2.1.1.135	1.16.1.8",
+    "2.1.2.6	2.1.2.5",
+    "2.1.2.12	2.1.1.74",
+    "2.3.1.55	2.3.1.82",
+    "2.4.1.3	2.4.1.25",
+    "2.4.1.42	2.4.1.17",
+    "2.4.1.51	2.4.1.145",
+    "2.4.1.55	2.7.8.14",
+    "2.4.1.59	2.4.1.17",
+    "2.4.1.61	2.4.1.17",
+    "2.4.1.72	2.4.2.24",
+    "2.4.1.76	2.4.1.17",
+    "2.4.1.77	2.4.1.17",
+    "2.4.1.84	2.4.1.17",
+    "2.4.1.89	2.4.1.69",
+    "2.4.1.93	4.2.2.18",
+    "2.4.1.98	2.4.1.90",
+    "2.4.1.107	2.4.1.17",
+    "2.4.1.108	2.4.1.17",
+    "2.4.1.124	2.4.1.87",
+    "2.4.1.151	2.4.1.87",
+    "2.4.1.169	2.4.2.39",
+    "2.4.1.200	4.2.2.17",
+    "2.4.1.204	2.4.2.40",
+    "2.4.2.13	2.5.1.6",
+    "2.5.1.8	2.5.1.75",
+    "2.5.1.12	2.5.1.18",
+    "2.5.1.13	2.5.1.18",
+    "2.5.1.14	2.5.1.18",
+    "2.5.1.37	4.4.1.20",
+    "2.5.1.40	4.2.3.9",
+    "2.6.1.10	2.6.1.21",
+    "2.6.1.25	2.6.1.24",
+    "2.6.1.53	1.4.1.13",
+    "2.6.2.1	2.1.4.1",
+    "2.7.1.37	2.7.11.1",
+    "2.7.1.38	2.7.11.19",
+    "2.7.1.75	2.7.1.21",
+    "2.7.1.96	2.7.1.86",
+    "2.7.1.99	2.7.11.2",
+    "2.7.1.104	2.7.99.1",
+    "2.7.1.109	2.7.11.31",
+    "2.7.1.110	2.7.11.3",
+    "2.7.1.111	2.7.11.27",
+    "2.7.1.112	2.7.10.1",
+    "2.7.1.115	2.7.11.4",
+    "2.7.1.116	2.7.11.5",
+    "2.7.1.117	2.7.11.18",
+    "2.7.1.123	2.7.11.17",
+    "2.7.1.124	2.7.11.6",
+    "2.7.1.125	2.7.11.14",
+    "2.7.1.126	2.7.11.15",
+    "2.7.1.128	2.7.11.27",
+    "2.7.1.129	2.7.11.7",
+    "2.7.1.131	2.7.11.29",
+    "2.7.1.132	2.7.11.28",
+    "2.7.1.133	2.7.1.134",
+    "2.7.1.135	2.7.11.26",
+    "2.7.1.139	2.7.1.134",
+    "2.7.1.141	2.7.11.23",
+    "2.7.1.152	2.7.4.21",
+    "2.7.1.155	2.7.4.24",
+    "2.7.2.5	6.3.4.16",
+    "2.7.2.9	6.3.5.5",
+    "2.7.3.11	2.7.13.1",
+    "2.7.3.12	2.7.13.2",
+    "2.7.4.5	2.7.4.14",
+    "2.7.5.1	5.4.2.2",
+    "2.7.5.2	5.4.2.3",
+    "2.7.5.3	5.4.2.1",
+    "2.7.5.4	5.4.2.4",
+    "2.7.5.5	5.4.2.5",
+    "2.7.5.6	5.4.2.7",
+    "2.7.5.7	5.4.2.8",
+    "2.7.7.16	3.1.27.5",
+    "2.7.7.17	3.1.27.1",
+    "2.7.7.26	3.1.27.3",
+    "2.7.8.16	2.7.8.2",
+    "3.1.1.12	3.1.1.1",
+    "3.1.1.18	3.1.1.17",
+    "3.1.1.62	3.5.1.47",
+    "3.1.1.69	3.5.1.89",
+    "3.1.2.8	3.1.2.6",
+    "3.1.2.24	3.13.1.3",
+    "3.1.3.30	3.1.3.7",
+    "3.1.3.65	3.1.3.64",
+    "3.1.4.5	3.1.21.1",
+    "3.1.4.6	3.1.22.1",
+    "3.1.4.7	3.1.31.1",
+    "3.1.4.8	3.1.27.3",
+    "3.1.4.9	3.1.30.2",
+    "3.1.4.10	4.6.1.13",
+    "3.1.4.18	3.1.16.1",
+    "3.1.4.19	3.1.13.3",
+    "3.1.4.20	3.1.13.1",
+    "3.1.4.21	3.1.30.1",
+    "3.1.4.22	3.1.27.5",
+    "3.1.4.23	3.1.27.1",
+    "3.1.4.25	3.1.11.1",
+    "3.1.4.27	3.1.11.2",
+    "3.1.4.28	3.1.11.3",
+    "3.1.4.30	3.1.21.2",
+    "3.1.4.31	3.1.11.4",
+    "3.1.4.36	3.1.4.43",
+    "3.1.4.47	4.6.1.14",
+    "3.1.22.3	3.1.21.7",
+    "3.1.23.1	3.1.21.4",
+    "3.1.23.2	3.1.21.4",
+    "3.1.23.3	3.1.21.4",
+    "3.1.23.4	3.1.21.4",
+    "3.1.23.5	3.1.21.4",
+    "3.1.23.6	3.1.21.4",
+    "3.1.23.7	3.1.21.4",
+    "3.1.23.8	3.1.21.4",
+    "3.1.23.9	3.1.21.4",
+    "3.1.23.10	3.1.21.4",
+    "3.1.23.11	3.1.21.4",
+    "3.1.23.12	3.1.21.4",
+    "3.1.23.13	3.1.21.4",
+    "3.1.23.14	3.1.21.4",
+    "3.1.23.15	3.1.21.4",
+    "3.1.23.16	3.1.21.4",
+    "3.1.23.17	3.1.21.4",
+    "3.1.23.18	3.1.21.4",
+    "3.1.23.19	3.1.21.4",
+    "3.1.23.20	3.1.21.4",
+    "3.1.23.21	3.1.21.4",
+    "3.1.23.22	3.1.21.4",
+    "3.1.23.23	3.1.21.4",
+    "3.1.23.24	3.1.21.4",
+    "3.1.23.25	3.1.21.4",
+    "3.1.23.26	3.1.21.4",
+    "3.1.23.27	3.1.21.4",
+    "3.1.23.28	3.1.21.4",
+    "3.1.23.29	3.1.21.4",
+    "3.1.23.30	3.1.21.4",
+    "3.1.23.31	3.1.21.4",
+    "3.1.23.32	3.1.21.4",
+    "3.1.23.33	3.1.21.4",
+    "3.1.23.34	3.1.21.4",
+    "3.1.23.35	3.1.21.4",
+    "3.1.23.36	3.1.21.4",
+    "3.1.23.37	3.1.21.4",
+    "3.1.23.38	3.1.21.4",
+    "3.1.23.39	3.1.21.4",
+    "3.1.23.40	3.1.21.4",
+    "3.1.23.41	3.1.21.4",
+    "3.1.23.42	3.1.21.4",
+    "3.1.23.43	3.1.21.4",
+    "3.1.23.44	3.1.21.4",
+    "3.1.23.45	3.1.21.4",
+    "3.1.23.46	3.1.21.4",
+    "3.1.23.47	3.1.21.4",
+    "3.1.23.48	3.1.21.4",
+    "3.1.23.49	3.1.21.4",
+    "3.1.23.50	3.1.21.4",
+    "3.1.23.51	3.1.21.4",
+    "3.1.23.52	3.1.21.4",
+    "3.1.23.53	3.1.21.4",
+    "3.1.23.54	3.1.21.4",
+    "3.1.23.55	3.1.21.4",
+    "3.1.23.56	3.1.21.4",
+    "3.1.23.57	3.1.21.4",
+    "3.1.23.58	3.1.21.4",
+    "3.1.23.59	3.1.21.4",
+    "3.1.24.1	3.1.21.3",
+    "3.1.24.2	3.1.21.3",
+    "3.1.24.3	3.1.21.5",
+    "3.1.24.4	3.1.21.5",
+    "3.1.25.2	4.2.99.18",
+    "3.2.1.12	3.2.1.54",
+    "3.2.1.13	3.2.1.54",
+    "3.2.1.29	3.2.1.52",
+    "3.2.1.30	3.2.1.52",
+    "3.2.1.34	3.2.1.35",
+    "3.2.1.69	3.2.1.41",
+    "3.2.1.79	3.2.1.55",
+    "3.2.1.110	3.2.1.97",
+    "3.2.1.138	4.2.2.15",
+    "3.2.1.148	4.4.1.21",
+    "3.2.1.160	3.2.1.155",
+    "3.2.2.18	3.5.1.52",
+    "3.2.3.1	3.2.1.147",
+    "3.3.1.3	4.4.1.21",
+    "3.3.2.3	3.3.2.9",
+    "3.4.1.1	3.4.11.1",
+    "3.4.1.2	3.4.11.2",
+    "3.4.1.3	3.4.11.4",
+    "3.4.1.4	3.4.11.5",
+    "3.4.2.1	3.4.17.1",
+    "3.4.2.2	3.4.17.2",
+    "3.4.2.3	3.4.17.4",
+    "3.4.3.1	3.4.13.18",
+    "3.4.3.2	3.4.13.18",
+    "3.4.3.3	3.4.13.3",
+    "3.4.3.4	3.4.13.5",
+    "3.4.3.5	3.4.11.2",
+    "3.4.3.6	3.4.13.18",
+    "3.4.3.7	3.4.13.9",
+    "3.4.4.1	3.4.23.1",
+    "3.4.4.2	3.4.23.2",
+    "3.4.4.3	3.4.23.4",
+    "3.4.4.4	3.4.21.4",
+    "3.4.4.5	3.4.21.1",
+    "3.4.4.6	3.4.21.1",
+    "3.4.4.7	3.4.21.36",
+    "3.4.4.8	3.4.21.9",
+    "3.4.4.9	3.4.14.1",
+    "3.4.4.10	3.4.22.2",
+    "3.4.4.11	3.4.22.6",
+    "3.4.4.12	3.4.22.3",
+    "3.4.4.13	3.4.21.5",
+    "3.4.4.14	3.4.21.7",
+    "3.4.4.15	3.4.23.15",
+    "3.4.4.16	3.4.21.62",
+    "3.4.4.17	3.4.23.20",
+    "3.4.4.18	3.4.22.10",
+    "3.4.4.19	3.4.24.3",
+    "3.4.4.20	3.4.22.8",
+    "3.4.4.21	3.4.21.34",
+    "3.4.4.22	3.4.23.3",
+    "3.4.4.23	3.4.23.5",
+    "3.4.4.24	3.4.22.32",
+    "3.4.11.8	3.4.19.3",
+    "3.4.12.1	3.4.16.5",
+    "3.4.12.2	3.4.17.1",
+    "3.4.12.3	3.4.17.2",
+    "3.4.12.4	3.4.16.2",
+    "3.4.12.5	3.5.1.28",
+    "3.4.12.6	3.4.17.8",
+    "3.4.12.7	3.4.17.3",
+    "3.4.12.8	3.4.17.4",
+    "3.4.12.10	3.4.19.9",
+    "3.4.12.11	3.4.17.6",
+    "3.4.12.12	3.4.16.5",
+    "3.4.13.1	3.4.13.18",
+    "3.4.13.2	3.4.13.18",
+    "3.4.13.6	3.4.11.2",
+    "3.4.13.8	3.4.13.18",
+    "3.4.13.10	3.4.19.5",
+    "3.4.13.11	3.4.13.18",
+    "3.4.13.13	3.4.13.3",
+    "3.4.13.15	3.4.13.18",
+    "3.4.14.3	3.4.19.1",
+    "3.4.14.8	3.4.14.9",
+    "3.4.15.2	3.4.19.2",
+    "3.4.15.3	3.4.15.5",
+    "3.4.16.1	3.4.16.5",
+    "3.4.16.3	3.4.16.5",
+    "3.4.17.7	3.5.1.28",
+    "3.4.17.9	3.4.17.4",
+    "3.4.19.8	3.4.17.21",
+    "3.4.19.10	3.5.1.28",
+    "3.4.21.8	3.4.21.35",
+    "3.4.21.11	3.4.21.36",
+    "3.4.21.13	3.4.16.5",
+    "3.4.21.14	3.4.21.62",
+    "3.4.21.15	3.4.21.63",
+    "3.4.21.28	3.4.21.74",
+    "3.4.21.29	3.4.21.74",
+    "3.4.21.30	3.4.21.74",
+    "3.4.21.31	3.4.21.68",
+    "3.4.21.44	3.4.21.43",
+    "3.4.21.87	3.4.23.49",
+    "3.4.22.4	3.4.22.32",
+    "3.4.22.5	3.4.22.33",
+    "3.4.22.9	3.4.21.48",
+    "3.4.22.11	3.4.24.56",
+    "3.4.22.12	3.4.19.9",
+    "3.4.22.17	3.4.22.52",
+    "3.4.22.18	3.4.21.26",
+    "3.4.22.19	3.4.24.15",
+    "3.4.22.21	3.4.25.1",
+    "3.4.22.22	3.4.24.37",
+    "3.4.22.23	3.4.21.61",
+    "3.4.23.6	3.4.23.18",
+    "3.4.23.7	3.4.23.20",
+    "3.4.23.8	3.4.23.25",
+    "3.4.23.9	3.4.23.21",
+    "3.4.23.10	3.4.23.22",
+    "3.4.23.27	3.4.21.103",
+    "3.4.23.33	3.4.21.101",
+    "3.4.23.37	3.4.21.100",
+    "3.4.24.4	3.4.24.25",
+    "3.4.24.5	3.4.25.1",
+    "3.4.24.8	3.4.24.3",
+    "3.4.99.1	3.4.23.28",
+    "3.4.99.4	3.4.23.12",
+    "3.4.99.5	3.4.24.3",
+    "3.4.99.6	3.4.24.21",
+    "3.4.99.10	3.4.24.56",
+    "3.4.99.13	3.4.24.32",
+    "3.4.99.19	3.4.23.15",
+    "3.4.99.22	3.4.24.29",
+    "3.4.99.25	3.4.23.21",
+    "3.4.99.26	3.4.21.73",
+    "3.4.99.28	3.4.21.60",
+    "3.4.99.30	3.4.24.20",
+    "3.4.99.31	3.4.24.15",
+    "3.4.99.32	3.4.24.20",
+    "3.4.99.35	3.4.23.36",
+    "3.4.99.36	3.4.21.89",
+    "3.4.99.38	3.4.23.17",
+    "3.4.99.41	3.4.24.64",
+    "3.4.99.43	3.4.23.42",
+    "3.4.99.44	3.4.24.55",
+    "3.4.99.45	3.4.24.56",
+    "3.4.99.46	3.4.25.1",
+    "3.5.1.34	3.4.13.5",
+    "3.5.1.37	3.5.1.26",
+    "3.5.1.45	6.3.4.6",
+    "3.5.2.8	3.5.2.6",
+    "3.5.5.3	4.2.1.104",
+    "3.6.1.4	3.6.1.3",
+    "3.6.1.32	3.6.4.1",
+    "3.6.1.33	3.6.4.2",
+    "3.6.1.34	3.6.3.14",
+    "3.6.1.35	3.6.3.6",
+    "3.6.1.36	3.6.3.10",
+    "3.6.1.37	3.6.3.9",
+    "3.6.1.38	3.6.3.8",
+    "3.6.1.46	3.6.5.1",
+    "3.6.1.47	3.6.5.2",
+    "3.6.1.48	3.6.5.3",
+    "3.6.1.49	3.6.5.4",
+    "3.6.1.50	3.6.5.5",
+    "3.6.1.51	3.6.5.6",
+    "3.8.1.4	1.97.1.10",
+    "3.8.2.1	3.1.8.2",
+    "4.1.1.10	4.1.1.12",
+    "4.1.1.26	4.1.1.28",
+    "4.1.1.27	4.1.1.28",
+    "4.1.2.1	4.1.3.16",
+    "4.1.2.7	4.1.2.13",
+    "4.1.2.15	2.5.1.54",
+    "4.1.2.16	2.5.1.55",
+    "4.1.2.31	4.1.3.16",
+    "4.1.2.39	4.1.2.37",
+    "4.1.3.2	2.3.3.9",
+    "4.1.3.5	2.3.3.10",
+    "4.1.3.7	2.3.3.1",
+    "4.1.3.8	2.3.3.8",
+    "4.1.3.9	2.3.3.11",
+    "4.1.3.10	2.3.3.7",
+    "4.1.3.11	2.3.3.12",
+    "4.1.3.12	2.3.3.13",
+    "4.1.3.15	2.2.1.5",
+    "4.1.3.18	2.2.1.6",
+    "4.1.3.19	2.5.1.56",
+    "4.1.3.20	2.5.1.57",
+    "4.1.3.21	2.3.3.14",
+    "4.1.3.23	2.3.3.2",
+    "4.1.3.28	2.3.3.3",
+    "4.1.3.29	2.3.3.4",
+    "4.1.3.31	2.3.3.5",
+    "4.1.3.33	2.3.3.6",
+    "4.1.3.37	2.2.1.7",
+    "4.1.99.4	3.5.99.7",
+    "4.1.99.6	4.2.3.6",
+    "4.1.99.7	4.2.3.9",
+    "4.1.99.8	4.2.3.14",
+    "4.1.99.9	4.2.3.15",
+    "4.1.99.10	4.2.3.16",
+    "4.2.1.13	4.3.1.17",
+    "4.2.1.14	4.3.1.18",
+    "4.2.1.15	4.4.1.1",
+    "4.2.1.16	4.3.1.19",
+    "4.2.1.21	4.2.1.22",
+    "4.2.1.26	4.3.1.9",
+    "4.2.1.29	4.99.1.6",
+    "4.2.1.37	3.3.2.4",
+    "4.2.1.38	4.3.1.20",
+    "4.2.1.63	3.3.2.9",
+    "4.2.1.64	3.3.2.9",
+    "4.2.1.72	4.1.1.78",
+    "4.2.1.102	4.2.1.100",
+    "4.2.2.4	4.2.2.20",
+    "4.2.99.1	4.2.2.1",
+    "4.2.99.2	4.2.3.1",
+    "4.2.99.3	4.2.2.2",
+    "4.2.99.4	4.2.2.3",
+    "4.2.99.6	4.2.2.5",
+    "4.2.99.7	4.2.3.2",
+    "4.2.99.8	2.5.1.47",
+    "4.2.99.9	2.5.1.48",
+    "4.2.99.10	2.5.1.49",
+    "4.2.99.11	4.2.3.3",
+    "4.2.99.13	2.5.1.50",
+    "4.2.99.14	2.5.1.51",
+    "4.2.99.15	2.5.1.52",
+    "4.2.99.16	2.5.1.53",
+    "4.2.99.17	2.5.1.51",
+    "4.2.99.19	4.4.1.23",
+    "4.3.1.8	2.5.1.61",
+    "4.3.99.1	4.2.1.104",
+    "4.4.1.7	2.5.1.18",
+    "4.4.1.18	1.8.3.5",
+    "4.6.1.3	4.2.3.4",
+    "4.6.1.4	4.2.3.5",
+    "4.6.1.5	4.2.3.7",
+    "4.6.1.7	4.2.3.8",
+    "4.6.1.8	4.2.3.10",
+    "4.6.1.9	4.2.3.11",
+    "4.6.1.10	4.2.3.12",
+    "4.6.1.11	4.2.3.13",
+    "5.3.1.10	3.5.99.6",
+    "5.3.1.19	2.6.1.16",
+    "5.4.99.6	5.4.4.2",
+    "5.4.99.10	5.4.99.11",
+    "6.2.1.21	6.2.1.30",
+    "6.3.1.3	6.3.4.13",
+    "6.3.5.8	2.6.1.85"
+};
diff --git a/api/ecnum_specific.inc b/api/ecnum_specific.inc
new file mode 100644
index 0000000..b7f0d4f
--- /dev/null
+++ b/api/ecnum_specific.inc
@@ -0,0 +1,4292 @@
+/*  $Id: ecnum_specific.inc,v 1.1 2010/07/09 16:36:07 ucko Exp $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  The Enzyme Commission
+ *
+ * File Description:
+ *   Built-in copy of ecnum_specific.txt.
+ *
+ */
+
+static const char* const kECNum_specific[] = {
+    "1.1.1.1",
+    "1.1.1.2",
+    "1.1.1.3",
+    "1.1.1.4",
+    "1.1.1.6",
+    "1.1.1.7",
+    "1.1.1.8",
+    "1.1.1.9",
+    "1.1.1.10",
+    "1.1.1.11",
+    "1.1.1.12",
+    "1.1.1.13",
+    "1.1.1.14",
+    "1.1.1.15",
+    "1.1.1.16",
+    "1.1.1.17",
+    "1.1.1.18",
+    "1.1.1.19",
+    "1.1.1.20",
+    "1.1.1.21",
+    "1.1.1.22",
+    "1.1.1.23",
+    "1.1.1.24",
+    "1.1.1.25",
+    "1.1.1.26",
+    "1.1.1.27",
+    "1.1.1.28",
+    "1.1.1.29",
+    "1.1.1.30",
+    "1.1.1.31",
+    "1.1.1.32",
+    "1.1.1.33",
+    "1.1.1.34",
+    "1.1.1.35",
+    "1.1.1.36",
+    "1.1.1.37",
+    "1.1.1.38",
+    "1.1.1.39",
+    "1.1.1.40",
+    "1.1.1.41",
+    "1.1.1.42",
+    "1.1.1.43",
+    "1.1.1.44",
+    "1.1.1.45",
+    "1.1.1.46",
+    "1.1.1.47",
+    "1.1.1.48",
+    "1.1.1.49",
+    "1.1.1.50",
+    "1.1.1.51",
+    "1.1.1.52",
+    "1.1.1.53",
+    "1.1.1.54",
+    "1.1.1.55",
+    "1.1.1.56",
+    "1.1.1.57",
+    "1.1.1.58",
+    "1.1.1.59",
+    "1.1.1.60",
+    "1.1.1.61",
+    "1.1.1.62",
+    "1.1.1.63",
+    "1.1.1.64",
+    "1.1.1.65",
+    "1.1.1.66",
+    "1.1.1.67",
+    "1.1.1.69",
+    "1.1.1.71",
+    "1.1.1.72",
+    "1.1.1.73",
+    "1.1.1.75",
+    "1.1.1.76",
+    "1.1.1.77",
+    "1.1.1.78",
+    "1.1.1.79",
+    "1.1.1.80",
+    "1.1.1.81",
+    "1.1.1.82",
+    "1.1.1.83",
+    "1.1.1.84",
+    "1.1.1.85",
+    "1.1.1.86",
+    "1.1.1.87",
+    "1.1.1.88",
+    "1.1.1.90",
+    "1.1.1.91",
+    "1.1.1.92",
+    "1.1.1.93",
+    "1.1.1.94",
+    "1.1.1.95",
+    "1.1.1.96",
+    "1.1.1.97",
+    "1.1.1.98",
+    "1.1.1.99",
+    "1.1.1.100",
+    "1.1.1.101",
+    "1.1.1.102",
+    "1.1.1.103",
+    "1.1.1.104",
+    "1.1.1.105",
+    "1.1.1.106",
+    "1.1.1.107",
+    "1.1.1.108",
+    "1.1.1.110",
+    "1.1.1.111",
+    "1.1.1.112",
+    "1.1.1.113",
+    "1.1.1.114",
+    "1.1.1.115",
+    "1.1.1.116",
+    "1.1.1.117",
+    "1.1.1.118",
+    "1.1.1.119",
+    "1.1.1.120",
+    "1.1.1.121",
+    "1.1.1.122",
+    "1.1.1.123",
+    "1.1.1.124",
+    "1.1.1.125",
+    "1.1.1.126",
+    "1.1.1.127",
+    "1.1.1.128",
+    "1.1.1.129",
+    "1.1.1.130",
+    "1.1.1.131",
+    "1.1.1.132",
+    "1.1.1.133",
+    "1.1.1.134",
+    "1.1.1.135",
+    "1.1.1.136",
+    "1.1.1.137",
+    "1.1.1.138",
+    "1.1.1.140",
+    "1.1.1.141",
+    "1.1.1.142",
+    "1.1.1.143",
+    "1.1.1.144",
+    "1.1.1.145",
+    "1.1.1.146",
+    "1.1.1.147",
+    "1.1.1.148",
+    "1.1.1.149",
+    "1.1.1.150",
+    "1.1.1.151",
+    "1.1.1.152",
+    "1.1.1.153",
+    "1.1.1.154",
+    "1.1.1.156",
+    "1.1.1.157",
+    "1.1.1.158",
+    "1.1.1.159",
+    "1.1.1.160",
+    "1.1.1.161",
+    "1.1.1.162",
+    "1.1.1.163",
+    "1.1.1.164",
+    "1.1.1.165",
+    "1.1.1.166",
+    "1.1.1.167",
+    "1.1.1.168",
+    "1.1.1.169",
+    "1.1.1.170",
+    "1.1.1.172",
+    "1.1.1.173",
+    "1.1.1.174",
+    "1.1.1.175",
+    "1.1.1.176",
+    "1.1.1.177",
+    "1.1.1.178",
+    "1.1.1.179",
+    "1.1.1.181",
+    "1.1.1.183",
+    "1.1.1.184",
+    "1.1.1.185",
+    "1.1.1.186",
+    "1.1.1.187",
+    "1.1.1.188",
+    "1.1.1.189",
+    "1.1.1.190",
+    "1.1.1.191",
+    "1.1.1.192",
+    "1.1.1.193",
+    "1.1.1.194",
+    "1.1.1.195",
+    "1.1.1.196",
+    "1.1.1.197",
+    "1.1.1.198",
+    "1.1.1.199",
+    "1.1.1.200",
+    "1.1.1.201",
+    "1.1.1.202",
+    "1.1.1.203",
+    "1.1.1.205",
+    "1.1.1.206",
+    "1.1.1.207",
+    "1.1.1.208",
+    "1.1.1.209",
+    "1.1.1.210",
+    "1.1.1.211",
+    "1.1.1.212",
+    "1.1.1.213",
+    "1.1.1.214",
+    "1.1.1.215",
+    "1.1.1.216",
+    "1.1.1.217",
+    "1.1.1.218",
+    "1.1.1.219",
+    "1.1.1.220",
+    "1.1.1.221",
+    "1.1.1.222",
+    "1.1.1.223",
+    "1.1.1.224",
+    "1.1.1.225",
+    "1.1.1.226",
+    "1.1.1.227",
+    "1.1.1.228",
+    "1.1.1.229",
+    "1.1.1.230",
+    "1.1.1.231",
+    "1.1.1.232",
+    "1.1.1.233",
+    "1.1.1.234",
+    "1.1.1.235",
+    "1.1.1.236",
+    "1.1.1.237",
+    "1.1.1.238",
+    "1.1.1.239",
+    "1.1.1.240",
+    "1.1.1.241",
+    "1.1.1.243",
+    "1.1.1.244",
+    "1.1.1.245",
+    "1.1.1.246",
+    "1.1.1.247",
+    "1.1.1.248",
+    "1.1.1.250",
+    "1.1.1.251",
+    "1.1.1.252",
+    "1.1.1.254",
+    "1.1.1.255",
+    "1.1.1.256",
+    "1.1.1.257",
+    "1.1.1.258",
+    "1.1.1.259",
+    "1.1.1.260",
+    "1.1.1.261",
+    "1.1.1.262",
+    "1.1.1.263",
+    "1.1.1.264",
+    "1.1.1.265",
+    "1.1.1.266",
+    "1.1.1.267",
+    "1.1.1.268",
+    "1.1.1.269",
+    "1.1.1.270",
+    "1.1.1.271",
+    "1.1.1.272",
+    "1.1.1.273",
+    "1.1.1.274",
+    "1.1.1.275",
+    "1.1.1.276",
+    "1.1.1.277",
+    "1.1.1.278",
+    "1.1.1.279",
+    "1.1.1.280",
+    "1.1.1.281",
+    "1.1.1.282",
+    "1.1.1.283",
+    "1.1.1.284",
+    "1.1.1.285",
+    "1.1.1.286",
+    "1.1.1.287",
+    "1.1.1.288",
+    "1.1.1.289",
+    "1.1.1.290",
+    "1.1.1.291",
+    "1.1.1.292",
+    "1.1.1.294",
+    "1.1.1.295",
+    "1.1.1.296",
+    "1.1.1.297",
+    "1.1.1.298",
+    "1.1.1.299",
+    "1.1.1.300",
+    "1.1.1.301",
+    "1.1.1.302",
+    "1.1.1.303",
+    "1.1.1.304",
+    "1.1.2.2",
+    "1.1.2.3",
+    "1.1.2.4",
+    "1.1.2.5",
+    "1.1.3.3",
+    "1.1.3.4",
+    "1.1.3.5",
+    "1.1.3.6",
+    "1.1.3.7",
+    "1.1.3.8",
+    "1.1.3.9",
+    "1.1.3.10",
+    "1.1.3.11",
+    "1.1.3.12",
+    "1.1.3.13",
+    "1.1.3.14",
+    "1.1.3.15",
+    "1.1.3.16",
+    "1.1.3.17",
+    "1.1.3.18",
+    "1.1.3.19",
+    "1.1.3.20",
+    "1.1.3.21",
+    "1.1.3.23",
+    "1.1.3.27",
+    "1.1.3.28",
+    "1.1.3.29",
+    "1.1.3.30",
+    "1.1.3.37",
+    "1.1.3.38",
+    "1.1.3.39",
+    "1.1.3.40",
+    "1.1.3.41",
+    "1.1.4.1",
+    "1.1.4.2",
+    "1.1.5.2",
+    "1.1.5.3",
+    "1.1.5.4",
+    "1.1.5.5",
+    "1.1.5.6",
+    "1.1.5.7",
+    "1.1.99.1",
+    "1.1.99.2",
+    "1.1.99.3",
+    "1.1.99.4",
+    "1.1.99.6",
+    "1.1.99.7",
+    "1.1.99.8",
+    "1.1.99.9",
+    "1.1.99.10",
+    "1.1.99.11",
+    "1.1.99.12",
+    "1.1.99.13",
+    "1.1.99.14",
+    "1.1.99.18",
+    "1.1.99.20",
+    "1.1.99.21",
+    "1.1.99.22",
+    "1.1.99.23",
+    "1.1.99.24",
+    "1.1.99.25",
+    "1.1.99.26",
+    "1.1.99.27",
+    "1.1.99.28",
+    "1.1.99.29",
+    "1.1.99.30",
+    "1.1.99.31",
+    "1.1.99.32",
+    "1.1.99.33",
+    "1.2.1.2",
+    "1.2.1.3",
+    "1.2.1.4",
+    "1.2.1.5",
+    "1.2.1.7",
+    "1.2.1.8",
+    "1.2.1.9",
+    "1.2.1.10",
+    "1.2.1.11",
+    "1.2.1.12",
+    "1.2.1.13",
+    "1.2.1.15",
+    "1.2.1.16",
+    "1.2.1.17",
+    "1.2.1.18",
+    "1.2.1.19",
+    "1.2.1.20",
+    "1.2.1.21",
+    "1.2.1.22",
+    "1.2.1.23",
+    "1.2.1.24",
+    "1.2.1.25",
+    "1.2.1.26",
+    "1.2.1.27",
+    "1.2.1.28",
+    "1.2.1.29",
+    "1.2.1.30",
+    "1.2.1.31",
+    "1.2.1.32",
+    "1.2.1.33",
+    "1.2.1.36",
+    "1.2.1.38",
+    "1.2.1.39",
+    "1.2.1.40",
+    "1.2.1.41",
+    "1.2.1.42",
+    "1.2.1.43",
+    "1.2.1.44",
+    "1.2.1.45",
+    "1.2.1.46",
+    "1.2.1.47",
+    "1.2.1.48",
+    "1.2.1.49",
+    "1.2.1.50",
+    "1.2.1.51",
+    "1.2.1.52",
+    "1.2.1.53",
+    "1.2.1.54",
+    "1.2.1.57",
+    "1.2.1.58",
+    "1.2.1.59",
+    "1.2.1.60",
+    "1.2.1.61",
+    "1.2.1.62",
+    "1.2.1.63",
+    "1.2.1.64",
+    "1.2.1.65",
+    "1.2.1.66",
+    "1.2.1.67",
+    "1.2.1.68",
+    "1.2.1.69",
+    "1.2.1.70",
+    "1.2.1.71",
+    "1.2.1.72",
+    "1.2.1.73",
+    "1.2.1.74",
+    "1.2.1.75",
+    "1.2.1.76",
+    "1.2.1.77",
+    "1.2.1.78",
+    "1.2.2.1",
+    "1.2.2.2",
+    "1.2.2.3",
+    "1.2.2.4",
+    "1.2.3.1",
+    "1.2.3.3",
+    "1.2.3.4",
+    "1.2.3.5",
+    "1.2.3.6",
+    "1.2.3.7",
+    "1.2.3.8",
+    "1.2.3.9",
+    "1.2.3.11",
+    "1.2.3.13",
+    "1.2.3.14",
+    "1.2.4.1",
+    "1.2.4.2",
+    "1.2.4.4",
+    "1.2.7.1",
+    "1.2.7.2",
+    "1.2.7.3",
+    "1.2.7.4",
+    "1.2.7.5",
+    "1.2.7.6",
+    "1.2.7.7",
+    "1.2.7.8",
+    "1.2.99.2",
+    "1.2.99.3",
+    "1.2.99.4",
+    "1.2.99.5",
+    "1.2.99.6",
+    "1.2.99.7",
+    "1.3.1.1",
+    "1.3.1.2",
+    "1.3.1.3",
+    "1.3.1.4",
+    "1.3.1.5",
+    "1.3.1.6",
+    "1.3.1.7",
+    "1.3.1.8",
+    "1.3.1.9",
+    "1.3.1.10",
+    "1.3.1.11",
+    "1.3.1.12",
+    "1.3.1.13",
+    "1.3.1.14",
+    "1.3.1.15",
+    "1.3.1.16",
+    "1.3.1.17",
+    "1.3.1.18",
+    "1.3.1.19",
+    "1.3.1.20",
+    "1.3.1.21",
+    "1.3.1.22",
+    "1.3.1.24",
+    "1.3.1.25",
+    "1.3.1.26",
+    "1.3.1.27",
+    "1.3.1.28",
+    "1.3.1.29",
+    "1.3.1.30",
+    "1.3.1.31",
+    "1.3.1.32",
+    "1.3.1.33",
+    "1.3.1.34",
+    "1.3.1.35",
+    "1.3.1.36",
+    "1.3.1.37",
+    "1.3.1.38",
+    "1.3.1.39",
+    "1.3.1.40",
+    "1.3.1.41",
+    "1.3.1.42",
+    "1.3.1.43",
+    "1.3.1.44",
+    "1.3.1.45",
+    "1.3.1.46",
+    "1.3.1.47",
+    "1.3.1.48",
+    "1.3.1.49",
+    "1.3.1.51",
+    "1.3.1.52",
+    "1.3.1.53",
+    "1.3.1.54",
+    "1.3.1.56",
+    "1.3.1.57",
+    "1.3.1.58",
+    "1.3.1.60",
+    "1.3.1.62",
+    "1.3.1.63",
+    "1.3.1.64",
+    "1.3.1.65",
+    "1.3.1.66",
+    "1.3.1.67",
+    "1.3.1.68",
+    "1.3.1.69",
+    "1.3.1.70",
+    "1.3.1.71",
+    "1.3.1.72",
+    "1.3.1.73",
+    "1.3.1.74",
+    "1.3.1.75",
+    "1.3.1.76",
+    "1.3.1.77",
+    "1.3.1.78",
+    "1.3.1.79",
+    "1.3.1.80",
+    "1.3.1.81",
+    "1.3.1.82",
+    "1.3.1.83",
+    "1.3.1.84",
+    "1.3.2.3",
+    "1.3.3.1",
+    "1.3.3.3",
+    "1.3.3.4",
+    "1.3.3.5",
+    "1.3.3.6",
+    "1.3.3.7",
+    "1.3.3.8",
+    "1.3.3.9",
+    "1.3.3.10",
+    "1.3.3.11",
+    "1.3.3.12",
+    "1.3.5.1",
+    "1.3.5.2",
+    "1.3.7.1",
+    "1.3.7.2",
+    "1.3.7.3",
+    "1.3.7.4",
+    "1.3.7.5",
+    "1.3.7.6",
+    "1.3.99.1",
+    "1.3.99.2",
+    "1.3.99.3",
+    "1.3.99.4",
+    "1.3.99.5",
+    "1.3.99.6",
+    "1.3.99.7",
+    "1.3.99.8",
+    "1.3.99.10",
+    "1.3.99.12",
+    "1.3.99.13",
+    "1.3.99.14",
+    "1.3.99.15",
+    "1.3.99.16",
+    "1.3.99.17",
+    "1.3.99.18",
+    "1.3.99.19",
+    "1.3.99.20",
+    "1.3.99.21",
+    "1.3.99.22",
+    "1.3.99.23",
+    "1.3.99.24",
+    "1.3.99.25",
+    "1.4.1.1",
+    "1.4.1.2",
+    "1.4.1.3",
+    "1.4.1.4",
+    "1.4.1.5",
+    "1.4.1.7",
+    "1.4.1.8",
+    "1.4.1.9",
+    "1.4.1.10",
+    "1.4.1.11",
+    "1.4.1.12",
+    "1.4.1.13",
+    "1.4.1.14",
+    "1.4.1.15",
+    "1.4.1.16",
+    "1.4.1.17",
+    "1.4.1.18",
+    "1.4.1.19",
+    "1.4.1.20",
+    "1.4.1.21",
+    "1.4.2.1",
+    "1.4.3.1",
+    "1.4.3.2",
+    "1.4.3.3",
+    "1.4.3.4",
+    "1.4.3.5",
+    "1.4.3.7",
+    "1.4.3.8",
+    "1.4.3.10",
+    "1.4.3.11",
+    "1.4.3.12",
+    "1.4.3.13",
+    "1.4.3.14",
+    "1.4.3.15",
+    "1.4.3.16",
+    "1.4.3.19",
+    "1.4.3.20",
+    "1.4.3.21",
+    "1.4.3.22",
+    "1.4.3.23",
+    "1.4.4.2",
+    "1.4.5.1",
+    "1.4.7.1",
+    "1.4.99.1",
+    "1.4.99.2",
+    "1.4.99.3",
+    "1.4.99.4",
+    "1.4.99.5",
+    "1.5.1.1",
+    "1.5.1.2",
+    "1.5.1.3",
+    "1.5.1.5",
+    "1.5.1.6",
+    "1.5.1.7",
+    "1.5.1.8",
+    "1.5.1.9",
+    "1.5.1.10",
+    "1.5.1.11",
+    "1.5.1.12",
+    "1.5.1.15",
+    "1.5.1.16",
+    "1.5.1.17",
+    "1.5.1.18",
+    "1.5.1.19",
+    "1.5.1.20",
+    "1.5.1.21",
+    "1.5.1.22",
+    "1.5.1.23",
+    "1.5.1.24",
+    "1.5.1.25",
+    "1.5.1.26",
+    "1.5.1.27",
+    "1.5.1.28",
+    "1.5.1.29",
+    "1.5.1.30",
+    "1.5.1.31",
+    "1.5.1.32",
+    "1.5.1.33",
+    "1.5.1.34",
+    "1.5.3.1",
+    "1.5.3.2",
+    "1.5.3.4",
+    "1.5.3.5",
+    "1.5.3.6",
+    "1.5.3.7",
+    "1.5.3.10",
+    "1.5.3.11",
+    "1.5.3.12",
+    "1.5.3.13",
+    "1.5.3.14",
+    "1.5.3.15",
+    "1.5.3.16",
+    "1.5.3.17",
+    "1.5.4.1",
+    "1.5.5.1",
+    "1.5.7.1",
+    "1.5.8.1",
+    "1.5.8.2",
+    "1.5.99.1",
+    "1.5.99.2",
+    "1.5.99.3",
+    "1.5.99.4",
+    "1.5.99.5",
+    "1.5.99.6",
+    "1.5.99.8",
+    "1.5.99.9",
+    "1.5.99.11",
+    "1.5.99.12",
+    "1.5.99.13",
+    "1.6.1.1",
+    "1.6.1.2",
+    "1.6.2.2",
+    "1.6.2.4",
+    "1.6.2.5",
+    "1.6.2.6",
+    "1.6.3.1",
+    "1.6.5.2",
+    "1.6.5.3",
+    "1.6.5.4",
+    "1.6.5.5",
+    "1.6.5.6",
+    "1.6.5.7",
+    "1.6.6.9",
+    "1.6.99.1",
+    "1.6.99.3",
+    "1.6.99.5",
+    "1.6.99.6",
+    "1.7.1.1",
+    "1.7.1.2",
+    "1.7.1.3",
+    "1.7.1.4",
+    "1.7.1.5",
+    "1.7.1.6",
+    "1.7.1.7",
+    "1.7.1.9",
+    "1.7.1.10",
+    "1.7.1.11",
+    "1.7.1.12",
+    "1.7.1.13",
+    "1.7.2.1",
+    "1.7.2.2",
+    "1.7.2.3",
+    "1.7.3.1",
+    "1.7.3.2",
+    "1.7.3.3",
+    "1.7.3.4",
+    "1.7.3.5",
+    "1.7.5.1",
+    "1.7.7.1",
+    "1.7.7.2",
+    "1.7.99.1",
+    "1.7.99.4",
+    "1.7.99.6",
+    "1.7.99.7",
+    "1.7.99.8",
+    "1.8.1.2",
+    "1.8.1.3",
+    "1.8.1.4",
+    "1.8.1.5",
+    "1.8.1.6",
+    "1.8.1.7",
+    "1.8.1.8",
+    "1.8.1.9",
+    "1.8.1.10",
+    "1.8.1.11",
+    "1.8.1.12",
+    "1.8.1.13",
+    "1.8.1.14",
+    "1.8.1.15",
+    "1.8.1.16",
+    "1.8.2.1",
+    "1.8.2.2",
+    "1.8.3.1",
+    "1.8.3.2",
+    "1.8.3.3",
+    "1.8.3.4",
+    "1.8.3.5",
+    "1.8.4.1",
+    "1.8.4.2",
+    "1.8.4.3",
+    "1.8.4.4",
+    "1.8.4.7",
+    "1.8.4.8",
+    "1.8.4.9",
+    "1.8.4.10",
+    "1.8.4.11",
+    "1.8.4.12",
+    "1.8.4.13",
+    "1.8.4.14",
+    "1.8.5.1",
+    "1.8.5.2",
+    "1.8.7.1",
+    "1.8.98.1",
+    "1.8.98.2",
+    "1.8.99.1",
+    "1.8.99.2",
+    "1.8.99.3",
+    "1.9.3.1",
+    "1.9.6.1",
+    "1.9.99.1",
+    "1.10.1.1",
+    "1.10.2.1",
+    "1.10.2.2",
+    "1.10.3.1",
+    "1.10.3.2",
+    "1.10.3.3",
+    "1.10.3.4",
+    "1.10.3.5",
+    "1.10.3.6",
+    "1.10.99.1",
+    "1.10.99.2",
+    "1.10.99.3",
+    "1.11.1.1",
+    "1.11.1.2",
+    "1.11.1.3",
+    "1.11.1.5",
+    "1.11.1.6",
+    "1.11.1.7",
+    "1.11.1.8",
+    "1.11.1.9",
+    "1.11.1.10",
+    "1.11.1.11",
+    "1.11.1.12",
+    "1.11.1.13",
+    "1.11.1.14",
+    "1.11.1.15",
+    "1.11.1.16",
+    "1.11.1.17",
+    "1.12.1.2",
+    "1.12.1.3",
+    "1.12.2.1",
+    "1.12.5.1",
+    "1.12.7.2",
+    "1.12.98.1",
+    "1.12.98.2",
+    "1.12.98.3",
+    "1.12.99.6",
+    "1.13.11.1",
+    "1.13.11.2",
+    "1.13.11.3",
+    "1.13.11.4",
+    "1.13.11.5",
+    "1.13.11.6",
+    "1.13.11.8",
+    "1.13.11.9",
+    "1.13.11.10",
+    "1.13.11.11",
+    "1.13.11.12",
+    "1.13.11.13",
+    "1.13.11.14",
+    "1.13.11.15",
+    "1.13.11.16",
+    "1.13.11.17",
+    "1.13.11.18",
+    "1.13.11.19",
+    "1.13.11.20",
+    "1.13.11.22",
+    "1.13.11.23",
+    "1.13.11.24",
+    "1.13.11.25",
+    "1.13.11.26",
+    "1.13.11.27",
+    "1.13.11.28",
+    "1.13.11.29",
+    "1.13.11.30",
+    "1.13.11.31",
+    "1.13.11.33",
+    "1.13.11.34",
+    "1.13.11.35",
+    "1.13.11.36",
+    "1.13.11.37",
+    "1.13.11.38",
+    "1.13.11.39",
+    "1.13.11.40",
+    "1.13.11.41",
+    "1.13.11.43",
+    "1.13.11.44",
+    "1.13.11.45",
+    "1.13.11.46",
+    "1.13.11.47",
+    "1.13.11.48",
+    "1.13.11.49",
+    "1.13.11.50",
+    "1.13.11.51",
+    "1.13.11.52",
+    "1.13.11.53",
+    "1.13.11.54",
+    "1.13.11.55",
+    "1.13.11.56",
+    "1.13.12.1",
+    "1.13.12.2",
+    "1.13.12.3",
+    "1.13.12.4",
+    "1.13.12.5",
+    "1.13.12.6",
+    "1.13.12.7",
+    "1.13.12.8",
+    "1.13.12.9",
+    "1.13.12.12",
+    "1.13.12.13",
+    "1.13.12.14",
+    "1.13.12.15",
+    "1.13.12.16",
+    "1.13.12.17",
+    "1.13.99.1",
+    "1.13.99.3",
+    "1.14.11.1",
+    "1.14.11.2",
+    "1.14.11.3",
+    "1.14.11.4",
+    "1.14.11.6",
+    "1.14.11.7",
+    "1.14.11.8",
+    "1.14.11.9",
+    "1.14.11.10",
+    "1.14.11.11",
+    "1.14.11.12",
+    "1.14.11.13",
+    "1.14.11.14",
+    "1.14.11.15",
+    "1.14.11.16",
+    "1.14.11.17",
+    "1.14.11.18",
+    "1.14.11.19",
+    "1.14.11.20",
+    "1.14.11.21",
+    "1.14.11.22",
+    "1.14.11.23",
+    "1.14.11.24",
+    "1.14.11.25",
+    "1.14.11.26",
+    "1.14.11.27",
+    "1.14.11.28",
+    "1.14.12.1",
+    "1.14.12.3",
+    "1.14.12.4",
+    "1.14.12.5",
+    "1.14.12.7",
+    "1.14.12.8",
+    "1.14.12.9",
+    "1.14.12.10",
+    "1.14.12.11",
+    "1.14.12.12",
+    "1.14.12.13",
+    "1.14.12.14",
+    "1.14.12.15",
+    "1.14.12.16",
+    "1.14.12.17",
+    "1.14.12.18",
+    "1.14.12.19",
+    "1.14.12.20",
+    "1.14.12.21",
+    "1.14.13.1",
+    "1.14.13.2",
+    "1.14.13.3",
+    "1.14.13.4",
+    "1.14.13.5",
+    "1.14.13.6",
+    "1.14.13.7",
+    "1.14.13.8",
+    "1.14.13.9",
+    "1.14.13.10",
+    "1.14.13.11",
+    "1.14.13.12",
+    "1.14.13.13",
+    "1.14.13.14",
+    "1.14.13.15",
+    "1.14.13.16",
+    "1.14.13.17",
+    "1.14.13.18",
+    "1.14.13.19",
+    "1.14.13.20",
+    "1.14.13.21",
+    "1.14.13.22",
+    "1.14.13.23",
+    "1.14.13.24",
+    "1.14.13.25",
+    "1.14.13.26",
+    "1.14.13.27",
+    "1.14.13.28",
+    "1.14.13.29",
+    "1.14.13.30",
+    "1.14.13.31",
+    "1.14.13.32",
+    "1.14.13.33",
+    "1.14.13.34",
+    "1.14.13.35",
+    "1.14.13.36",
+    "1.14.13.37",
+    "1.14.13.38",
+    "1.14.13.39",
+    "1.14.13.40",
+    "1.14.13.41",
+    "1.14.13.42",
+    "1.14.13.43",
+    "1.14.13.44",
+    "1.14.13.46",
+    "1.14.13.47",
+    "1.14.13.48",
+    "1.14.13.49",
+    "1.14.13.50",
+    "1.14.13.51",
+    "1.14.13.52",
+    "1.14.13.53",
+    "1.14.13.54",
+    "1.14.13.55",
+    "1.14.13.56",
+    "1.14.13.57",
+    "1.14.13.58",
+    "1.14.13.59",
+    "1.14.13.60",
+    "1.14.13.61",
+    "1.14.13.62",
+    "1.14.13.63",
+    "1.14.13.64",
+    "1.14.13.66",
+    "1.14.13.67",
+    "1.14.13.68",
+    "1.14.13.69",
+    "1.14.13.70",
+    "1.14.13.71",
+    "1.14.13.72",
+    "1.14.13.73",
+    "1.14.13.74",
+    "1.14.13.75",
+    "1.14.13.76",
+    "1.14.13.77",
+    "1.14.13.78",
+    "1.14.13.79",
+    "1.14.13.80",
+    "1.14.13.81",
+    "1.14.13.82",
+    "1.14.13.83",
+    "1.14.13.84",
+    "1.14.13.85",
+    "1.14.13.86",
+    "1.14.13.87",
+    "1.14.13.88",
+    "1.14.13.89",
+    "1.14.13.90",
+    "1.14.13.91",
+    "1.14.13.92",
+    "1.14.13.93",
+    "1.14.13.94",
+    "1.14.13.95",
+    "1.14.13.96",
+    "1.14.13.97",
+    "1.14.13.98",
+    "1.14.13.99",
+    "1.14.13.100",
+    "1.14.13.101",
+    "1.14.13.102",
+    "1.14.13.103",
+    "1.14.13.104",
+    "1.14.13.105",
+    "1.14.13.106",
+    "1.14.13.107",
+    "1.14.13.108",
+    "1.14.13.109",
+    "1.14.13.110",
+    "1.14.13.111",
+    "1.14.13.112",
+    "1.14.13.113",
+    "1.14.14.1",
+    "1.14.14.3",
+    "1.14.14.5",
+    "1.14.14.7",
+    "1.14.15.1",
+    "1.14.15.2",
+    "1.14.15.3",
+    "1.14.15.4",
+    "1.14.15.5",
+    "1.14.15.6",
+    "1.14.15.7",
+    "1.14.15.8",
+    "1.14.16.1",
+    "1.14.16.2",
+    "1.14.16.3",
+    "1.14.16.4",
+    "1.14.16.5",
+    "1.14.16.6",
+    "1.14.17.1",
+    "1.14.17.3",
+    "1.14.17.4",
+    "1.14.18.1",
+    "1.14.18.2",
+    "1.14.19.1",
+    "1.14.19.2",
+    "1.14.19.3",
+    "1.14.19.4",
+    "1.14.19.5",
+    "1.14.19.6",
+    "1.14.20.1",
+    "1.14.21.1",
+    "1.14.21.2",
+    "1.14.21.3",
+    "1.14.21.4",
+    "1.14.21.5",
+    "1.14.21.6",
+    "1.14.21.7",
+    "1.14.99.1",
+    "1.14.99.2",
+    "1.14.99.3",
+    "1.14.99.4",
+    "1.14.99.7",
+    "1.14.99.9",
+    "1.14.99.10",
+    "1.14.99.11",
+    "1.14.99.12",
+    "1.14.99.14",
+    "1.14.99.15",
+    "1.14.99.19",
+    "1.14.99.20",
+    "1.14.99.21",
+    "1.14.99.22",
+    "1.14.99.23",
+    "1.14.99.24",
+    "1.14.99.26",
+    "1.14.99.27",
+    "1.14.99.28",
+    "1.14.99.29",
+    "1.14.99.30",
+    "1.14.99.31",
+    "1.14.99.32",
+    "1.14.99.33",
+    "1.14.99.34",
+    "1.14.99.35",
+    "1.14.99.36",
+    "1.14.99.37",
+    "1.14.99.38",
+    "1.14.99.39",
+    "1.14.99.40",
+    "1.15.1.1",
+    "1.15.1.2",
+    "1.16.1.1",
+    "1.16.1.2",
+    "1.16.1.3",
+    "1.16.1.4",
+    "1.16.1.5",
+    "1.16.1.6",
+    "1.16.1.7",
+    "1.16.1.8",
+    "1.16.3.1",
+    "1.16.8.1",
+    "1.17.1.1",
+    "1.17.1.2",
+    "1.17.1.3",
+    "1.17.1.4",
+    "1.17.1.5",
+    "1.17.3.1",
+    "1.17.3.2",
+    "1.17.3.3",
+    "1.17.4.1",
+    "1.17.4.2",
+    "1.17.5.1",
+    "1.17.7.1",
+    "1.17.99.1",
+    "1.17.99.2",
+    "1.17.99.3",
+    "1.17.99.4",
+    "1.17.99.5",
+    "1.18.1.1",
+    "1.18.1.2",
+    "1.18.1.3",
+    "1.18.1.4",
+    "1.18.6.1",
+    "1.19.6.1",
+    "1.20.1.1",
+    "1.20.4.1",
+    "1.20.4.2",
+    "1.20.4.3",
+    "1.20.98.1",
+    "1.20.99.1",
+    "1.21.3.1",
+    "1.21.3.2",
+    "1.21.3.3",
+    "1.21.3.4",
+    "1.21.3.5",
+    "1.21.3.6",
+    "1.21.4.1",
+    "1.21.4.2",
+    "1.21.4.3",
+    "1.21.4.4",
+    "1.21.99.1",
+    "1.22.1.1",
+    "1.97.1.1",
+    "1.97.1.2",
+    "1.97.1.3",
+    "1.97.1.4",
+    "1.97.1.8",
+    "1.97.1.9",
+    "1.97.1.10",
+    "1.97.1.11",
+    "2.1.1.1",
+    "2.1.1.2",
+    "2.1.1.3",
+    "2.1.1.4",
+    "2.1.1.5",
+    "2.1.1.6",
+    "2.1.1.7",
+    "2.1.1.8",
+    "2.1.1.9",
+    "2.1.1.10",
+    "2.1.1.11",
+    "2.1.1.12",
+    "2.1.1.13",
+    "2.1.1.14",
+    "2.1.1.15",
+    "2.1.1.16",
+    "2.1.1.17",
+    "2.1.1.18",
+    "2.1.1.19",
+    "2.1.1.20",
+    "2.1.1.21",
+    "2.1.1.22",
+    "2.1.1.25",
+    "2.1.1.26",
+    "2.1.1.27",
+    "2.1.1.28",
+    "2.1.1.29",
+    "2.1.1.31",
+    "2.1.1.32",
+    "2.1.1.33",
+    "2.1.1.34",
+    "2.1.1.35",
+    "2.1.1.36",
+    "2.1.1.37",
+    "2.1.1.38",
+    "2.1.1.39",
+    "2.1.1.40",
+    "2.1.1.41",
+    "2.1.1.42",
+    "2.1.1.43",
+    "2.1.1.44",
+    "2.1.1.45",
+    "2.1.1.46",
+    "2.1.1.47",
+    "2.1.1.48",
+    "2.1.1.49",
+    "2.1.1.50",
+    "2.1.1.51",
+    "2.1.1.52",
+    "2.1.1.53",
+    "2.1.1.54",
+    "2.1.1.55",
+    "2.1.1.56",
+    "2.1.1.57",
+    "2.1.1.59",
+    "2.1.1.60",
+    "2.1.1.61",
+    "2.1.1.62",
+    "2.1.1.63",
+    "2.1.1.64",
+    "2.1.1.65",
+    "2.1.1.66",
+    "2.1.1.67",
+    "2.1.1.68",
+    "2.1.1.69",
+    "2.1.1.70",
+    "2.1.1.71",
+    "2.1.1.72",
+    "2.1.1.74",
+    "2.1.1.75",
+    "2.1.1.76",
+    "2.1.1.77",
+    "2.1.1.78",
+    "2.1.1.79",
+    "2.1.1.80",
+    "2.1.1.82",
+    "2.1.1.83",
+    "2.1.1.84",
+    "2.1.1.85",
+    "2.1.1.86",
+    "2.1.1.87",
+    "2.1.1.88",
+    "2.1.1.89",
+    "2.1.1.90",
+    "2.1.1.91",
+    "2.1.1.94",
+    "2.1.1.95",
+    "2.1.1.96",
+    "2.1.1.97",
+    "2.1.1.98",
+    "2.1.1.99",
+    "2.1.1.100",
+    "2.1.1.101",
+    "2.1.1.102",
+    "2.1.1.103",
+    "2.1.1.104",
+    "2.1.1.105",
+    "2.1.1.106",
+    "2.1.1.107",
+    "2.1.1.108",
+    "2.1.1.109",
+    "2.1.1.110",
+    "2.1.1.111",
+    "2.1.1.112",
+    "2.1.1.113",
+    "2.1.1.114",
+    "2.1.1.115",
+    "2.1.1.116",
+    "2.1.1.117",
+    "2.1.1.118",
+    "2.1.1.119",
+    "2.1.1.120",
+    "2.1.1.121",
+    "2.1.1.122",
+    "2.1.1.123",
+    "2.1.1.124",
+    "2.1.1.125",
+    "2.1.1.126",
+    "2.1.1.127",
+    "2.1.1.128",
+    "2.1.1.129",
+    "2.1.1.130",
+    "2.1.1.131",
+    "2.1.1.132",
+    "2.1.1.133",
+    "2.1.1.136",
+    "2.1.1.137",
+    "2.1.1.139",
+    "2.1.1.140",
+    "2.1.1.141",
+    "2.1.1.142",
+    "2.1.1.143",
+    "2.1.1.144",
+    "2.1.1.145",
+    "2.1.1.146",
+    "2.1.1.147",
+    "2.1.1.148",
+    "2.1.1.149",
+    "2.1.1.150",
+    "2.1.1.151",
+    "2.1.1.152",
+    "2.1.1.153",
+    "2.1.1.154",
+    "2.1.1.155",
+    "2.1.1.156",
+    "2.1.1.157",
+    "2.1.1.158",
+    "2.1.1.159",
+    "2.1.1.160",
+    "2.1.1.161",
+    "2.1.1.162",
+    "2.1.1.163",
+    "2.1.1.164",
+    "2.1.1.165",
+    "2.1.2.1",
+    "2.1.2.2",
+    "2.1.2.3",
+    "2.1.2.4",
+    "2.1.2.5",
+    "2.1.2.7",
+    "2.1.2.8",
+    "2.1.2.9",
+    "2.1.2.10",
+    "2.1.2.11",
+    "2.1.3.1",
+    "2.1.3.2",
+    "2.1.3.3",
+    "2.1.3.5",
+    "2.1.3.6",
+    "2.1.3.7",
+    "2.1.3.8",
+    "2.1.3.9",
+    "2.1.3.10",
+    "2.1.3.11",
+    "2.1.4.1",
+    "2.1.4.2",
+    "2.2.1.1",
+    "2.2.1.2",
+    "2.2.1.3",
+    "2.2.1.4",
+    "2.2.1.5",
+    "2.2.1.6",
+    "2.2.1.7",
+    "2.2.1.8",
+    "2.2.1.9",
+    "2.3.1.1",
+    "2.3.1.2",
+    "2.3.1.3",
+    "2.3.1.4",
+    "2.3.1.5",
+    "2.3.1.6",
+    "2.3.1.7",
+    "2.3.1.8",
+    "2.3.1.9",
+    "2.3.1.10",
+    "2.3.1.11",
+    "2.3.1.12",
+    "2.3.1.13",
+    "2.3.1.14",
+    "2.3.1.15",
+    "2.3.1.16",
+    "2.3.1.17",
+    "2.3.1.18",
+    "2.3.1.19",
+    "2.3.1.20",
+    "2.3.1.21",
+    "2.3.1.22",
+    "2.3.1.23",
+    "2.3.1.24",
+    "2.3.1.25",
+    "2.3.1.26",
+    "2.3.1.27",
+    "2.3.1.28",
+    "2.3.1.29",
+    "2.3.1.30",
+    "2.3.1.31",
+    "2.3.1.32",
+    "2.3.1.33",
+    "2.3.1.34",
+    "2.3.1.35",
+    "2.3.1.36",
+    "2.3.1.37",
+    "2.3.1.38",
+    "2.3.1.39",
+    "2.3.1.40",
+    "2.3.1.41",
+    "2.3.1.42",
+    "2.3.1.43",
+    "2.3.1.44",
+    "2.3.1.45",
+    "2.3.1.46",
+    "2.3.1.47",
+    "2.3.1.48",
+    "2.3.1.49",
+    "2.3.1.50",
+    "2.3.1.51",
+    "2.3.1.52",
+    "2.3.1.53",
+    "2.3.1.54",
+    "2.3.1.56",
+    "2.3.1.57",
+    "2.3.1.58",
+    "2.3.1.59",
+    "2.3.1.60",
+    "2.3.1.61",
+    "2.3.1.62",
+    "2.3.1.63",
+    "2.3.1.64",
+    "2.3.1.65",
+    "2.3.1.66",
+    "2.3.1.67",
+    "2.3.1.68",
+    "2.3.1.69",
+    "2.3.1.71",
+    "2.3.1.72",
+    "2.3.1.73",
+    "2.3.1.74",
+    "2.3.1.75",
+    "2.3.1.76",
+    "2.3.1.77",
+    "2.3.1.78",
+    "2.3.1.79",
+    "2.3.1.80",
+    "2.3.1.81",
+    "2.3.1.82",
+    "2.3.1.83",
+    "2.3.1.84",
+    "2.3.1.85",
+    "2.3.1.86",
+    "2.3.1.87",
+    "2.3.1.88",
+    "2.3.1.89",
+    "2.3.1.90",
+    "2.3.1.91",
+    "2.3.1.92",
+    "2.3.1.93",
+    "2.3.1.94",
+    "2.3.1.95",
+    "2.3.1.96",
+    "2.3.1.97",
+    "2.3.1.98",
+    "2.3.1.99",
+    "2.3.1.100",
+    "2.3.1.101",
+    "2.3.1.102",
+    "2.3.1.103",
+    "2.3.1.104",
+    "2.3.1.105",
+    "2.3.1.106",
+    "2.3.1.107",
+    "2.3.1.108",
+    "2.3.1.109",
+    "2.3.1.110",
+    "2.3.1.111",
+    "2.3.1.112",
+    "2.3.1.113",
+    "2.3.1.114",
+    "2.3.1.115",
+    "2.3.1.116",
+    "2.3.1.117",
+    "2.3.1.118",
+    "2.3.1.119",
+    "2.3.1.121",
+    "2.3.1.122",
+    "2.3.1.123",
+    "2.3.1.125",
+    "2.3.1.126",
+    "2.3.1.127",
+    "2.3.1.128",
+    "2.3.1.129",
+    "2.3.1.130",
+    "2.3.1.131",
+    "2.3.1.132",
+    "2.3.1.133",
+    "2.3.1.134",
+    "2.3.1.135",
+    "2.3.1.136",
+    "2.3.1.137",
+    "2.3.1.138",
+    "2.3.1.139",
+    "2.3.1.140",
+    "2.3.1.141",
+    "2.3.1.142",
+    "2.3.1.143",
+    "2.3.1.144",
+    "2.3.1.145",
+    "2.3.1.146",
+    "2.3.1.147",
+    "2.3.1.148",
+    "2.3.1.149",
+    "2.3.1.150",
+    "2.3.1.151",
+    "2.3.1.152",
+    "2.3.1.153",
+    "2.3.1.154",
+    "2.3.1.155",
+    "2.3.1.156",
+    "2.3.1.157",
+    "2.3.1.158",
+    "2.3.1.159",
+    "2.3.1.160",
+    "2.3.1.161",
+    "2.3.1.162",
+    "2.3.1.163",
+    "2.3.1.164",
+    "2.3.1.165",
+    "2.3.1.166",
+    "2.3.1.167",
+    "2.3.1.168",
+    "2.3.1.169",
+    "2.3.1.170",
+    "2.3.1.171",
+    "2.3.1.172",
+    "2.3.1.173",
+    "2.3.1.174",
+    "2.3.1.175",
+    "2.3.1.176",
+    "2.3.1.177",
+    "2.3.1.178",
+    "2.3.1.179",
+    "2.3.1.180",
+    "2.3.1.181",
+    "2.3.1.182",
+    "2.3.1.183",
+    "2.3.1.184",
+    "2.3.1.185",
+    "2.3.1.186",
+    "2.3.1.187",
+    "2.3.1.188",
+    "2.3.1.189",
+    "2.3.1.190",
+    "2.3.2.1",
+    "2.3.2.2",
+    "2.3.2.3",
+    "2.3.2.4",
+    "2.3.2.5",
+    "2.3.2.6",
+    "2.3.2.7",
+    "2.3.2.8",
+    "2.3.2.9",
+    "2.3.2.10",
+    "2.3.2.11",
+    "2.3.2.12",
+    "2.3.2.13",
+    "2.3.2.14",
+    "2.3.2.15",
+    "2.3.3.1",
+    "2.3.3.2",
+    "2.3.3.3",
+    "2.3.3.4",
+    "2.3.3.5",
+    "2.3.3.6",
+    "2.3.3.7",
+    "2.3.3.8",
+    "2.3.3.9",
+    "2.3.3.10",
+    "2.3.3.11",
+    "2.3.3.12",
+    "2.3.3.13",
+    "2.3.3.14",
+    "2.3.3.15",
+    "2.4.1.1",
+    "2.4.1.2",
+    "2.4.1.4",
+    "2.4.1.5",
+    "2.4.1.7",
+    "2.4.1.8",
+    "2.4.1.9",
+    "2.4.1.10",
+    "2.4.1.11",
+    "2.4.1.12",
+    "2.4.1.13",
+    "2.4.1.14",
+    "2.4.1.15",
+    "2.4.1.16",
+    "2.4.1.17",
+    "2.4.1.18",
+    "2.4.1.19",
+    "2.4.1.20",
+    "2.4.1.21",
+    "2.4.1.22",
+    "2.4.1.23",
+    "2.4.1.24",
+    "2.4.1.25",
+    "2.4.1.26",
+    "2.4.1.27",
+    "2.4.1.28",
+    "2.4.1.29",
+    "2.4.1.30",
+    "2.4.1.31",
+    "2.4.1.32",
+    "2.4.1.33",
+    "2.4.1.34",
+    "2.4.1.35",
+    "2.4.1.36",
+    "2.4.1.37",
+    "2.4.1.38",
+    "2.4.1.39",
+    "2.4.1.40",
+    "2.4.1.41",
+    "2.4.1.43",
+    "2.4.1.44",
+    "2.4.1.45",
+    "2.4.1.46",
+    "2.4.1.47",
+    "2.4.1.48",
+    "2.4.1.49",
+    "2.4.1.50",
+    "2.4.1.52",
+    "2.4.1.53",
+    "2.4.1.54",
+    "2.4.1.56",
+    "2.4.1.57",
+    "2.4.1.58",
+    "2.4.1.60",
+    "2.4.1.62",
+    "2.4.1.63",
+    "2.4.1.64",
+    "2.4.1.65",
+    "2.4.1.66",
+    "2.4.1.67",
+    "2.4.1.68",
+    "2.4.1.69",
+    "2.4.1.70",
+    "2.4.1.71",
+    "2.4.1.73",
+    "2.4.1.74",
+    "2.4.1.78",
+    "2.4.1.79",
+    "2.4.1.80",
+    "2.4.1.81",
+    "2.4.1.82",
+    "2.4.1.83",
+    "2.4.1.85",
+    "2.4.1.86",
+    "2.4.1.87",
+    "2.4.1.88",
+    "2.4.1.90",
+    "2.4.1.91",
+    "2.4.1.92",
+    "2.4.1.94",
+    "2.4.1.95",
+    "2.4.1.96",
+    "2.4.1.97",
+    "2.4.1.99",
+    "2.4.1.100",
+    "2.4.1.101",
+    "2.4.1.102",
+    "2.4.1.103",
+    "2.4.1.104",
+    "2.4.1.105",
+    "2.4.1.106",
+    "2.4.1.109",
+    "2.4.1.110",
+    "2.4.1.111",
+    "2.4.1.113",
+    "2.4.1.114",
+    "2.4.1.115",
+    "2.4.1.116",
+    "2.4.1.117",
+    "2.4.1.118",
+    "2.4.1.119",
+    "2.4.1.120",
+    "2.4.1.121",
+    "2.4.1.122",
+    "2.4.1.123",
+    "2.4.1.125",
+    "2.4.1.126",
+    "2.4.1.127",
+    "2.4.1.128",
+    "2.4.1.129",
+    "2.4.1.130",
+    "2.4.1.131",
+    "2.4.1.132",
+    "2.4.1.133",
+    "2.4.1.134",
+    "2.4.1.135",
+    "2.4.1.136",
+    "2.4.1.137",
+    "2.4.1.138",
+    "2.4.1.139",
+    "2.4.1.140",
+    "2.4.1.141",
+    "2.4.1.142",
+    "2.4.1.143",
+    "2.4.1.144",
+    "2.4.1.145",
+    "2.4.1.146",
+    "2.4.1.147",
+    "2.4.1.148",
+    "2.4.1.149",
+    "2.4.1.150",
+    "2.4.1.152",
+    "2.4.1.153",
+    "2.4.1.155",
+    "2.4.1.156",
+    "2.4.1.157",
+    "2.4.1.158",
+    "2.4.1.159",
+    "2.4.1.160",
+    "2.4.1.161",
+    "2.4.1.162",
+    "2.4.1.163",
+    "2.4.1.164",
+    "2.4.1.165",
+    "2.4.1.166",
+    "2.4.1.167",
+    "2.4.1.168",
+    "2.4.1.170",
+    "2.4.1.171",
+    "2.4.1.172",
+    "2.4.1.173",
+    "2.4.1.174",
+    "2.4.1.175",
+    "2.4.1.176",
+    "2.4.1.177",
+    "2.4.1.178",
+    "2.4.1.179",
+    "2.4.1.180",
+    "2.4.1.181",
+    "2.4.1.182",
+    "2.4.1.183",
+    "2.4.1.184",
+    "2.4.1.185",
+    "2.4.1.186",
+    "2.4.1.187",
+    "2.4.1.188",
+    "2.4.1.189",
+    "2.4.1.190",
+    "2.4.1.191",
+    "2.4.1.192",
+    "2.4.1.193",
+    "2.4.1.194",
+    "2.4.1.195",
+    "2.4.1.196",
+    "2.4.1.197",
+    "2.4.1.198",
+    "2.4.1.199",
+    "2.4.1.201",
+    "2.4.1.202",
+    "2.4.1.203",
+    "2.4.1.205",
+    "2.4.1.206",
+    "2.4.1.207",
+    "2.4.1.208",
+    "2.4.1.209",
+    "2.4.1.210",
+    "2.4.1.211",
+    "2.4.1.212",
+    "2.4.1.213",
+    "2.4.1.214",
+    "2.4.1.215",
+    "2.4.1.216",
+    "2.4.1.217",
+    "2.4.1.218",
+    "2.4.1.219",
+    "2.4.1.220",
+    "2.4.1.221",
+    "2.4.1.222",
+    "2.4.1.223",
+    "2.4.1.224",
+    "2.4.1.225",
+    "2.4.1.226",
+    "2.4.1.227",
+    "2.4.1.228",
+    "2.4.1.229",
+    "2.4.1.230",
+    "2.4.1.231",
+    "2.4.1.232",
+    "2.4.1.234",
+    "2.4.1.236",
+    "2.4.1.237",
+    "2.4.1.238",
+    "2.4.1.239",
+    "2.4.1.240",
+    "2.4.1.241",
+    "2.4.1.242",
+    "2.4.1.243",
+    "2.4.1.244",
+    "2.4.1.245",
+    "2.4.1.246",
+    "2.4.1.247",
+    "2.4.1.248",
+    "2.4.1.249",
+    "2.4.1.250",
+    "2.4.2.1",
+    "2.4.2.2",
+    "2.4.2.3",
+    "2.4.2.4",
+    "2.4.2.5",
+    "2.4.2.6",
+    "2.4.2.7",
+    "2.4.2.8",
+    "2.4.2.9",
+    "2.4.2.10",
+    "2.4.2.11",
+    "2.4.2.12",
+    "2.4.2.14",
+    "2.4.2.15",
+    "2.4.2.16",
+    "2.4.2.17",
+    "2.4.2.18",
+    "2.4.2.19",
+    "2.4.2.20",
+    "2.4.2.21",
+    "2.4.2.22",
+    "2.4.2.23",
+    "2.4.2.24",
+    "2.4.2.25",
+    "2.4.2.26",
+    "2.4.2.27",
+    "2.4.2.28",
+    "2.4.2.29",
+    "2.4.2.30",
+    "2.4.2.31",
+    "2.4.2.32",
+    "2.4.2.33",
+    "2.4.2.34",
+    "2.4.2.35",
+    "2.4.2.36",
+    "2.4.2.37",
+    "2.4.2.38",
+    "2.4.2.39",
+    "2.4.2.40",
+    "2.4.2.41",
+    "2.4.2.42",
+    "2.4.99.1",
+    "2.4.99.2",
+    "2.4.99.3",
+    "2.4.99.4",
+    "2.4.99.5",
+    "2.4.99.6",
+    "2.4.99.7",
+    "2.4.99.8",
+    "2.4.99.9",
+    "2.4.99.10",
+    "2.4.99.11",
+    "2.5.1.1",
+    "2.5.1.2",
+    "2.5.1.3",
+    "2.5.1.4",
+    "2.5.1.5",
+    "2.5.1.6",
+    "2.5.1.7",
+    "2.5.1.9",
+    "2.5.1.10",
+    "2.5.1.11",
+    "2.5.1.15",
+    "2.5.1.16",
+    "2.5.1.17",
+    "2.5.1.18",
+    "2.5.1.19",
+    "2.5.1.20",
+    "2.5.1.21",
+    "2.5.1.22",
+    "2.5.1.23",
+    "2.5.1.24",
+    "2.5.1.25",
+    "2.5.1.26",
+    "2.5.1.27",
+    "2.5.1.28",
+    "2.5.1.29",
+    "2.5.1.30",
+    "2.5.1.31",
+    "2.5.1.32",
+    "2.5.1.33",
+    "2.5.1.34",
+    "2.5.1.35",
+    "2.5.1.36",
+    "2.5.1.38",
+    "2.5.1.39",
+    "2.5.1.41",
+    "2.5.1.42",
+    "2.5.1.43",
+    "2.5.1.44",
+    "2.5.1.45",
+    "2.5.1.46",
+    "2.5.1.47",
+    "2.5.1.48",
+    "2.5.1.49",
+    "2.5.1.50",
+    "2.5.1.51",
+    "2.5.1.52",
+    "2.5.1.53",
+    "2.5.1.54",
+    "2.5.1.55",
+    "2.5.1.56",
+    "2.5.1.57",
+    "2.5.1.58",
+    "2.5.1.59",
+    "2.5.1.60",
+    "2.5.1.61",
+    "2.5.1.62",
+    "2.5.1.63",
+    "2.5.1.65",
+    "2.5.1.66",
+    "2.5.1.67",
+    "2.5.1.68",
+    "2.5.1.69",
+    "2.5.1.70",
+    "2.5.1.71",
+    "2.5.1.72",
+    "2.5.1.73",
+    "2.5.1.74",
+    "2.5.1.75",
+    "2.5.1.76",
+    "2.5.1.77",
+    "2.5.1.78",
+    "2.5.1.79",
+    "2.5.1.80",
+    "2.6.1.1",
+    "2.6.1.2",
+    "2.6.1.3",
+    "2.6.1.4",
+    "2.6.1.5",
+    "2.6.1.6",
+    "2.6.1.7",
+    "2.6.1.8",
+    "2.6.1.9",
+    "2.6.1.11",
+    "2.6.1.12",
+    "2.6.1.13",
+    "2.6.1.14",
+    "2.6.1.15",
+    "2.6.1.16",
+    "2.6.1.17",
+    "2.6.1.18",
+    "2.6.1.19",
+    "2.6.1.21",
+    "2.6.1.22",
+    "2.6.1.23",
+    "2.6.1.24",
+    "2.6.1.26",
+    "2.6.1.27",
+    "2.6.1.28",
+    "2.6.1.29",
+    "2.6.1.30",
+    "2.6.1.31",
+    "2.6.1.32",
+    "2.6.1.33",
+    "2.6.1.34",
+    "2.6.1.35",
+    "2.6.1.36",
+    "2.6.1.37",
+    "2.6.1.38",
+    "2.6.1.39",
+    "2.6.1.40",
+    "2.6.1.41",
+    "2.6.1.42",
+    "2.6.1.43",
+    "2.6.1.44",
+    "2.6.1.45",
+    "2.6.1.46",
+    "2.6.1.47",
+    "2.6.1.48",
+    "2.6.1.49",
+    "2.6.1.50",
+    "2.6.1.51",
+    "2.6.1.52",
+    "2.6.1.54",
+    "2.6.1.55",
+    "2.6.1.56",
+    "2.6.1.57",
+    "2.6.1.58",
+    "2.6.1.59",
+    "2.6.1.60",
+    "2.6.1.62",
+    "2.6.1.63",
+    "2.6.1.64",
+    "2.6.1.65",
+    "2.6.1.66",
+    "2.6.1.67",
+    "2.6.1.68",
+    "2.6.1.70",
+    "2.6.1.71",
+    "2.6.1.72",
+    "2.6.1.73",
+    "2.6.1.74",
+    "2.6.1.75",
+    "2.6.1.76",
+    "2.6.1.77",
+    "2.6.1.78",
+    "2.6.1.79",
+    "2.6.1.80",
+    "2.6.1.81",
+    "2.6.1.82",
+    "2.6.1.83",
+    "2.6.1.84",
+    "2.6.1.85",
+    "2.6.1.86",
+    "2.6.3.1",
+    "2.6.99.1",
+    "2.6.99.2",
+    "2.7.1.1",
+    "2.7.1.2",
+    "2.7.1.3",
+    "2.7.1.4",
+    "2.7.1.5",
+    "2.7.1.6",
+    "2.7.1.7",
+    "2.7.1.8",
+    "2.7.1.10",
+    "2.7.1.11",
+    "2.7.1.12",
+    "2.7.1.13",
+    "2.7.1.14",
+    "2.7.1.15",
+    "2.7.1.16",
+    "2.7.1.17",
+    "2.7.1.18",
+    "2.7.1.19",
+    "2.7.1.20",
+    "2.7.1.21",
+    "2.7.1.22",
+    "2.7.1.23",
+    "2.7.1.24",
+    "2.7.1.25",
+    "2.7.1.26",
+    "2.7.1.27",
+    "2.7.1.28",
+    "2.7.1.29",
+    "2.7.1.30",
+    "2.7.1.31",
+    "2.7.1.32",
+    "2.7.1.33",
+    "2.7.1.34",
+    "2.7.1.35",
+    "2.7.1.36",
+    "2.7.1.39",
+    "2.7.1.40",
+    "2.7.1.41",
+    "2.7.1.42",
+    "2.7.1.43",
+    "2.7.1.44",
+    "2.7.1.45",
+    "2.7.1.46",
+    "2.7.1.47",
+    "2.7.1.48",
+    "2.7.1.49",
+    "2.7.1.50",
+    "2.7.1.51",
+    "2.7.1.52",
+    "2.7.1.53",
+    "2.7.1.54",
+    "2.7.1.55",
+    "2.7.1.56",
+    "2.7.1.58",
+    "2.7.1.59",
+    "2.7.1.60",
+    "2.7.1.61",
+    "2.7.1.62",
+    "2.7.1.63",
+    "2.7.1.64",
+    "2.7.1.65",
+    "2.7.1.66",
+    "2.7.1.67",
+    "2.7.1.68",
+    "2.7.1.69",
+    "2.7.1.71",
+    "2.7.1.72",
+    "2.7.1.73",
+    "2.7.1.74",
+    "2.7.1.76",
+    "2.7.1.77",
+    "2.7.1.78",
+    "2.7.1.79",
+    "2.7.1.80",
+    "2.7.1.81",
+    "2.7.1.82",
+    "2.7.1.83",
+    "2.7.1.84",
+    "2.7.1.85",
+    "2.7.1.86",
+    "2.7.1.87",
+    "2.7.1.88",
+    "2.7.1.89",
+    "2.7.1.90",
+    "2.7.1.91",
+    "2.7.1.92",
+    "2.7.1.93",
+    "2.7.1.94",
+    "2.7.1.95",
+    "2.7.1.100",
+    "2.7.1.101",
+    "2.7.1.102",
+    "2.7.1.103",
+    "2.7.1.105",
+    "2.7.1.106",
+    "2.7.1.107",
+    "2.7.1.108",
+    "2.7.1.113",
+    "2.7.1.114",
+    "2.7.1.118",
+    "2.7.1.119",
+    "2.7.1.121",
+    "2.7.1.122",
+    "2.7.1.127",
+    "2.7.1.130",
+    "2.7.1.134",
+    "2.7.1.136",
+    "2.7.1.137",
+    "2.7.1.138",
+    "2.7.1.140",
+    "2.7.1.142",
+    "2.7.1.143",
+    "2.7.1.144",
+    "2.7.1.145",
+    "2.7.1.146",
+    "2.7.1.147",
+    "2.7.1.148",
+    "2.7.1.149",
+    "2.7.1.150",
+    "2.7.1.151",
+    "2.7.1.153",
+    "2.7.1.154",
+    "2.7.1.156",
+    "2.7.1.157",
+    "2.7.1.158",
+    "2.7.1.159",
+    "2.7.1.160",
+    "2.7.1.161",
+    "2.7.1.162",
+    "2.7.1.163",
+    "2.7.1.164",
+    "2.7.1.165",
+    "2.7.2.1",
+    "2.7.2.2",
+    "2.7.2.3",
+    "2.7.2.4",
+    "2.7.2.6",
+    "2.7.2.7",
+    "2.7.2.8",
+    "2.7.2.10",
+    "2.7.2.11",
+    "2.7.2.12",
+    "2.7.2.13",
+    "2.7.2.14",
+    "2.7.2.15",
+    "2.7.3.1",
+    "2.7.3.2",
+    "2.7.3.3",
+    "2.7.3.4",
+    "2.7.3.5",
+    "2.7.3.6",
+    "2.7.3.7",
+    "2.7.3.8",
+    "2.7.3.9",
+    "2.7.3.10",
+    "2.7.4.1",
+    "2.7.4.2",
+    "2.7.4.3",
+    "2.7.4.4",
+    "2.7.4.6",
+    "2.7.4.7",
+    "2.7.4.8",
+    "2.7.4.9",
+    "2.7.4.10",
+    "2.7.4.11",
+    "2.7.4.12",
+    "2.7.4.13",
+    "2.7.4.14",
+    "2.7.4.15",
+    "2.7.4.16",
+    "2.7.4.17",
+    "2.7.4.18",
+    "2.7.4.19",
+    "2.7.4.20",
+    "2.7.4.21",
+    "2.7.4.22",
+    "2.7.4.23",
+    "2.7.4.24",
+    "2.7.6.1",
+    "2.7.6.2",
+    "2.7.6.3",
+    "2.7.6.4",
+    "2.7.6.5",
+    "2.7.7.1",
+    "2.7.7.2",
+    "2.7.7.3",
+    "2.7.7.4",
+    "2.7.7.5",
+    "2.7.7.6",
+    "2.7.7.7",
+    "2.7.7.8",
+    "2.7.7.9",
+    "2.7.7.10",
+    "2.7.7.11",
+    "2.7.7.12",
+    "2.7.7.13",
+    "2.7.7.14",
+    "2.7.7.15",
+    "2.7.7.18",
+    "2.7.7.19",
+    "2.7.7.21",
+    "2.7.7.22",
+    "2.7.7.23",
+    "2.7.7.24",
+    "2.7.7.25",
+    "2.7.7.27",
+    "2.7.7.28",
+    "2.7.7.30",
+    "2.7.7.31",
+    "2.7.7.32",
+    "2.7.7.33",
+    "2.7.7.34",
+    "2.7.7.35",
+    "2.7.7.36",
+    "2.7.7.37",
+    "2.7.7.38",
+    "2.7.7.39",
+    "2.7.7.40",
+    "2.7.7.41",
+    "2.7.7.42",
+    "2.7.7.43",
+    "2.7.7.44",
+    "2.7.7.45",
+    "2.7.7.46",
+    "2.7.7.47",
+    "2.7.7.48",
+    "2.7.7.49",
+    "2.7.7.50",
+    "2.7.7.51",
+    "2.7.7.52",
+    "2.7.7.53",
+    "2.7.7.54",
+    "2.7.7.55",
+    "2.7.7.56",
+    "2.7.7.57",
+    "2.7.7.58",
+    "2.7.7.59",
+    "2.7.7.60",
+    "2.7.7.61",
+    "2.7.7.62",
+    "2.7.7.63",
+    "2.7.7.64",
+    "2.7.7.65",
+    "2.7.7.66",
+    "2.7.7.67",
+    "2.7.7.68",
+    "2.7.8.1",
+    "2.7.8.2",
+    "2.7.8.3",
+    "2.7.8.4",
+    "2.7.8.5",
+    "2.7.8.6",
+    "2.7.8.7",
+    "2.7.8.8",
+    "2.7.8.9",
+    "2.7.8.10",
+    "2.7.8.11",
+    "2.7.8.12",
+    "2.7.8.13",
+    "2.7.8.14",
+    "2.7.8.15",
+    "2.7.8.17",
+    "2.7.8.18",
+    "2.7.8.19",
+    "2.7.8.20",
+    "2.7.8.21",
+    "2.7.8.22",
+    "2.7.8.23",
+    "2.7.8.24",
+    "2.7.8.25",
+    "2.7.8.26",
+    "2.7.8.27",
+    "2.7.8.28",
+    "2.7.9.1",
+    "2.7.9.2",
+    "2.7.9.3",
+    "2.7.9.4",
+    "2.7.9.5",
+    "2.7.10.1",
+    "2.7.10.2",
+    "2.7.11.1",
+    "2.7.11.2",
+    "2.7.11.3",
+    "2.7.11.4",
+    "2.7.11.5",
+    "2.7.11.6",
+    "2.7.11.7",
+    "2.7.11.8",
+    "2.7.11.9",
+    "2.7.11.10",
+    "2.7.11.11",
+    "2.7.11.12",
+    "2.7.11.13",
+    "2.7.11.14",
+    "2.7.11.15",
+    "2.7.11.16",
+    "2.7.11.17",
+    "2.7.11.18",
+    "2.7.11.19",
+    "2.7.11.20",
+    "2.7.11.21",
+    "2.7.11.22",
+    "2.7.11.23",
+    "2.7.11.24",
+    "2.7.11.25",
+    "2.7.11.26",
+    "2.7.11.27",
+    "2.7.11.28",
+    "2.7.11.29",
+    "2.7.11.30",
+    "2.7.11.31",
+    "2.7.12.1",
+    "2.7.12.2",
+    "2.7.13.1",
+    "2.7.13.2",
+    "2.7.13.3",
+    "2.7.99.1",
+    "2.8.1.1",
+    "2.8.1.2",
+    "2.8.1.3",
+    "2.8.1.4",
+    "2.8.1.5",
+    "2.8.1.6",
+    "2.8.1.7",
+    "2.8.1.8",
+    "2.8.2.1",
+    "2.8.2.2",
+    "2.8.2.3",
+    "2.8.2.4",
+    "2.8.2.5",
+    "2.8.2.6",
+    "2.8.2.7",
+    "2.8.2.8",
+    "2.8.2.9",
+    "2.8.2.10",
+    "2.8.2.11",
+    "2.8.2.13",
+    "2.8.2.14",
+    "2.8.2.15",
+    "2.8.2.16",
+    "2.8.2.17",
+    "2.8.2.18",
+    "2.8.2.19",
+    "2.8.2.20",
+    "2.8.2.21",
+    "2.8.2.22",
+    "2.8.2.23",
+    "2.8.2.24",
+    "2.8.2.25",
+    "2.8.2.26",
+    "2.8.2.27",
+    "2.8.2.28",
+    "2.8.2.29",
+    "2.8.2.30",
+    "2.8.2.31",
+    "2.8.2.32",
+    "2.8.2.33",
+    "2.8.2.34",
+    "2.8.3.1",
+    "2.8.3.2",
+    "2.8.3.3",
+    "2.8.3.5",
+    "2.8.3.6",
+    "2.8.3.7",
+    "2.8.3.8",
+    "2.8.3.9",
+    "2.8.3.10",
+    "2.8.3.11",
+    "2.8.3.12",
+    "2.8.3.13",
+    "2.8.3.14",
+    "2.8.3.15",
+    "2.8.3.16",
+    "2.8.3.17",
+    "2.8.4.1",
+    "2.8.4.2",
+    "2.9.1.1",
+    "2.9.1.2",
+    "3.1.1.1",
+    "3.1.1.2",
+    "3.1.1.3",
+    "3.1.1.4",
+    "3.1.1.5",
+    "3.1.1.6",
+    "3.1.1.7",
+    "3.1.1.8",
+    "3.1.1.10",
+    "3.1.1.11",
+    "3.1.1.13",
+    "3.1.1.14",
+    "3.1.1.15",
+    "3.1.1.17",
+    "3.1.1.19",
+    "3.1.1.20",
+    "3.1.1.21",
+    "3.1.1.22",
+    "3.1.1.23",
+    "3.1.1.24",
+    "3.1.1.25",
+    "3.1.1.26",
+    "3.1.1.27",
+    "3.1.1.28",
+    "3.1.1.29",
+    "3.1.1.30",
+    "3.1.1.31",
+    "3.1.1.32",
+    "3.1.1.33",
+    "3.1.1.34",
+    "3.1.1.35",
+    "3.1.1.36",
+    "3.1.1.37",
+    "3.1.1.38",
+    "3.1.1.39",
+    "3.1.1.40",
+    "3.1.1.41",
+    "3.1.1.42",
+    "3.1.1.43",
+    "3.1.1.44",
+    "3.1.1.45",
+    "3.1.1.46",
+    "3.1.1.47",
+    "3.1.1.48",
+    "3.1.1.49",
+    "3.1.1.50",
+    "3.1.1.51",
+    "3.1.1.52",
+    "3.1.1.53",
+    "3.1.1.54",
+    "3.1.1.55",
+    "3.1.1.56",
+    "3.1.1.57",
+    "3.1.1.58",
+    "3.1.1.59",
+    "3.1.1.60",
+    "3.1.1.61",
+    "3.1.1.63",
+    "3.1.1.64",
+    "3.1.1.65",
+    "3.1.1.66",
+    "3.1.1.67",
+    "3.1.1.68",
+    "3.1.1.70",
+    "3.1.1.71",
+    "3.1.1.72",
+    "3.1.1.73",
+    "3.1.1.74",
+    "3.1.1.75",
+    "3.1.1.76",
+    "3.1.1.77",
+    "3.1.1.78",
+    "3.1.1.79",
+    "3.1.1.80",
+    "3.1.1.81",
+    "3.1.1.82",
+    "3.1.1.83",
+    "3.1.1.84",
+    "3.1.2.1",
+    "3.1.2.2",
+    "3.1.2.3",
+    "3.1.2.4",
+    "3.1.2.5",
+    "3.1.2.6",
+    "3.1.2.7",
+    "3.1.2.10",
+    "3.1.2.11",
+    "3.1.2.12",
+    "3.1.2.13",
+    "3.1.2.14",
+    "3.1.2.15",
+    "3.1.2.16",
+    "3.1.2.17",
+    "3.1.2.18",
+    "3.1.2.19",
+    "3.1.2.20",
+    "3.1.2.21",
+    "3.1.2.22",
+    "3.1.2.23",
+    "3.1.2.25",
+    "3.1.2.26",
+    "3.1.2.27",
+    "3.1.3.1",
+    "3.1.3.2",
+    "3.1.3.3",
+    "3.1.3.4",
+    "3.1.3.5",
+    "3.1.3.6",
+    "3.1.3.7",
+    "3.1.3.8",
+    "3.1.3.9",
+    "3.1.3.10",
+    "3.1.3.11",
+    "3.1.3.12",
+    "3.1.3.13",
+    "3.1.3.14",
+    "3.1.3.15",
+    "3.1.3.16",
+    "3.1.3.17",
+    "3.1.3.18",
+    "3.1.3.19",
+    "3.1.3.20",
+    "3.1.3.21",
+    "3.1.3.22",
+    "3.1.3.23",
+    "3.1.3.24",
+    "3.1.3.25",
+    "3.1.3.26",
+    "3.1.3.27",
+    "3.1.3.28",
+    "3.1.3.29",
+    "3.1.3.31",
+    "3.1.3.32",
+    "3.1.3.33",
+    "3.1.3.34",
+    "3.1.3.35",
+    "3.1.3.36",
+    "3.1.3.37",
+    "3.1.3.38",
+    "3.1.3.39",
+    "3.1.3.40",
+    "3.1.3.41",
+    "3.1.3.42",
+    "3.1.3.43",
+    "3.1.3.44",
+    "3.1.3.45",
+    "3.1.3.46",
+    "3.1.3.47",
+    "3.1.3.48",
+    "3.1.3.49",
+    "3.1.3.50",
+    "3.1.3.51",
+    "3.1.3.52",
+    "3.1.3.53",
+    "3.1.3.54",
+    "3.1.3.55",
+    "3.1.3.56",
+    "3.1.3.57",
+    "3.1.3.58",
+    "3.1.3.59",
+    "3.1.3.60",
+    "3.1.3.62",
+    "3.1.3.63",
+    "3.1.3.64",
+    "3.1.3.66",
+    "3.1.3.67",
+    "3.1.3.68",
+    "3.1.3.69",
+    "3.1.3.70",
+    "3.1.3.71",
+    "3.1.3.72",
+    "3.1.3.73",
+    "3.1.3.74",
+    "3.1.3.75",
+    "3.1.3.76",
+    "3.1.3.77",
+    "3.1.3.78",
+    "3.1.3.79",
+    "3.1.3.80",
+    "3.1.4.1",
+    "3.1.4.2",
+    "3.1.4.3",
+    "3.1.4.4",
+    "3.1.4.11",
+    "3.1.4.12",
+    "3.1.4.13",
+    "3.1.4.14",
+    "3.1.4.15",
+    "3.1.4.16",
+    "3.1.4.17",
+    "3.1.4.35",
+    "3.1.4.37",
+    "3.1.4.38",
+    "3.1.4.39",
+    "3.1.4.40",
+    "3.1.4.41",
+    "3.1.4.42",
+    "3.1.4.43",
+    "3.1.4.44",
+    "3.1.4.45",
+    "3.1.4.46",
+    "3.1.4.48",
+    "3.1.4.49",
+    "3.1.4.50",
+    "3.1.4.51",
+    "3.1.4.52",
+    "3.1.4.53",
+    "3.1.5.1",
+    "3.1.6.1",
+    "3.1.6.2",
+    "3.1.6.3",
+    "3.1.6.4",
+    "3.1.6.6",
+    "3.1.6.7",
+    "3.1.6.8",
+    "3.1.6.9",
+    "3.1.6.10",
+    "3.1.6.11",
+    "3.1.6.12",
+    "3.1.6.13",
+    "3.1.6.14",
+    "3.1.6.15",
+    "3.1.6.16",
+    "3.1.6.17",
+    "3.1.6.18",
+    "3.1.7.1",
+    "3.1.7.2",
+    "3.1.7.3",
+    "3.1.7.4",
+    "3.1.7.5",
+    "3.1.8.1",
+    "3.1.8.2",
+    "3.1.11.1",
+    "3.1.11.2",
+    "3.1.11.3",
+    "3.1.11.4",
+    "3.1.11.5",
+    "3.1.11.6",
+    "3.1.13.1",
+    "3.1.13.2",
+    "3.1.13.3",
+    "3.1.13.4",
+    "3.1.13.5",
+    "3.1.14.1",
+    "3.1.15.1",
+    "3.1.16.1",
+    "3.1.21.1",
+    "3.1.21.2",
+    "3.1.21.3",
+    "3.1.21.4",
+    "3.1.21.5",
+    "3.1.21.6",
+    "3.1.21.7",
+    "3.1.22.1",
+    "3.1.22.2",
+    "3.1.22.4",
+    "3.1.22.5",
+    "3.1.25.1",
+    "3.1.26.1",
+    "3.1.26.2",
+    "3.1.26.3",
+    "3.1.26.4",
+    "3.1.26.5",
+    "3.1.26.6",
+    "3.1.26.7",
+    "3.1.26.8",
+    "3.1.26.9",
+    "3.1.26.10",
+    "3.1.26.11",
+    "3.1.26.12",
+    "3.1.26.13",
+    "3.1.27.1",
+    "3.1.27.2",
+    "3.1.27.3",
+    "3.1.27.4",
+    "3.1.27.5",
+    "3.1.27.6",
+    "3.1.27.7",
+    "3.1.27.8",
+    "3.1.27.9",
+    "3.1.27.10",
+    "3.1.30.1",
+    "3.1.30.2",
+    "3.1.31.1",
+    "3.2.1.1",
+    "3.2.1.2",
+    "3.2.1.3",
+    "3.2.1.4",
+    "3.2.1.6",
+    "3.2.1.7",
+    "3.2.1.8",
+    "3.2.1.10",
+    "3.2.1.11",
+    "3.2.1.14",
+    "3.2.1.15",
+    "3.2.1.17",
+    "3.2.1.18",
+    "3.2.1.20",
+    "3.2.1.21",
+    "3.2.1.22",
+    "3.2.1.23",
+    "3.2.1.24",
+    "3.2.1.25",
+    "3.2.1.26",
+    "3.2.1.28",
+    "3.2.1.31",
+    "3.2.1.32",
+    "3.2.1.33",
+    "3.2.1.35",
+    "3.2.1.36",
+    "3.2.1.37",
+    "3.2.1.38",
+    "3.2.1.39",
+    "3.2.1.40",
+    "3.2.1.41",
+    "3.2.1.42",
+    "3.2.1.43",
+    "3.2.1.44",
+    "3.2.1.45",
+    "3.2.1.46",
+    "3.2.1.47",
+    "3.2.1.48",
+    "3.2.1.49",
+    "3.2.1.50",
+    "3.2.1.51",
+    "3.2.1.52",
+    "3.2.1.53",
+    "3.2.1.54",
+    "3.2.1.55",
+    "3.2.1.56",
+    "3.2.1.57",
+    "3.2.1.58",
+    "3.2.1.59",
+    "3.2.1.60",
+    "3.2.1.61",
+    "3.2.1.62",
+    "3.2.1.63",
+    "3.2.1.64",
+    "3.2.1.65",
+    "3.2.1.66",
+    "3.2.1.67",
+    "3.2.1.68",
+    "3.2.1.70",
+    "3.2.1.71",
+    "3.2.1.72",
+    "3.2.1.73",
+    "3.2.1.74",
+    "3.2.1.75",
+    "3.2.1.76",
+    "3.2.1.77",
+    "3.2.1.78",
+    "3.2.1.80",
+    "3.2.1.81",
+    "3.2.1.82",
+    "3.2.1.83",
+    "3.2.1.84",
+    "3.2.1.85",
+    "3.2.1.86",
+    "3.2.1.87",
+    "3.2.1.88",
+    "3.2.1.89",
+    "3.2.1.91",
+    "3.2.1.92",
+    "3.2.1.93",
+    "3.2.1.94",
+    "3.2.1.95",
+    "3.2.1.96",
+    "3.2.1.97",
+    "3.2.1.98",
+    "3.2.1.99",
+    "3.2.1.100",
+    "3.2.1.101",
+    "3.2.1.102",
+    "3.2.1.103",
+    "3.2.1.104",
+    "3.2.1.105",
+    "3.2.1.106",
+    "3.2.1.107",
+    "3.2.1.108",
+    "3.2.1.109",
+    "3.2.1.111",
+    "3.2.1.112",
+    "3.2.1.113",
+    "3.2.1.114",
+    "3.2.1.115",
+    "3.2.1.116",
+    "3.2.1.117",
+    "3.2.1.118",
+    "3.2.1.119",
+    "3.2.1.120",
+    "3.2.1.121",
+    "3.2.1.122",
+    "3.2.1.123",
+    "3.2.1.124",
+    "3.2.1.125",
+    "3.2.1.126",
+    "3.2.1.127",
+    "3.2.1.128",
+    "3.2.1.129",
+    "3.2.1.130",
+    "3.2.1.131",
+    "3.2.1.132",
+    "3.2.1.133",
+    "3.2.1.134",
+    "3.2.1.135",
+    "3.2.1.136",
+    "3.2.1.137",
+    "3.2.1.139",
+    "3.2.1.140",
+    "3.2.1.141",
+    "3.2.1.142",
+    "3.2.1.143",
+    "3.2.1.144",
+    "3.2.1.145",
+    "3.2.1.146",
+    "3.2.1.147",
+    "3.2.1.149",
+    "3.2.1.150",
+    "3.2.1.151",
+    "3.2.1.152",
+    "3.2.1.153",
+    "3.2.1.154",
+    "3.2.1.155",
+    "3.2.1.156",
+    "3.2.1.157",
+    "3.2.1.158",
+    "3.2.1.159",
+    "3.2.1.161",
+    "3.2.1.162",
+    "3.2.1.163",
+    "3.2.1.164",
+    "3.2.1.165",
+    "3.2.2.1",
+    "3.2.2.2",
+    "3.2.2.3",
+    "3.2.2.4",
+    "3.2.2.5",
+    "3.2.2.6",
+    "3.2.2.7",
+    "3.2.2.8",
+    "3.2.2.9",
+    "3.2.2.10",
+    "3.2.2.11",
+    "3.2.2.12",
+    "3.2.2.13",
+    "3.2.2.14",
+    "3.2.2.15",
+    "3.2.2.16",
+    "3.2.2.17",
+    "3.2.2.19",
+    "3.2.2.20",
+    "3.2.2.21",
+    "3.2.2.22",
+    "3.2.2.23",
+    "3.2.2.24",
+    "3.2.2.25",
+    "3.2.2.26",
+    "3.2.2.27",
+    "3.2.2.28",
+    "3.2.2.29",
+    "3.3.1.1",
+    "3.3.1.2",
+    "3.3.2.1",
+    "3.3.2.2",
+    "3.3.2.4",
+    "3.3.2.5",
+    "3.3.2.6",
+    "3.3.2.7",
+    "3.3.2.8",
+    "3.3.2.9",
+    "3.3.2.10",
+    "3.3.2.11",
+    "3.4.11.1",
+    "3.4.11.2",
+    "3.4.11.3",
+    "3.4.11.4",
+    "3.4.11.5",
+    "3.4.11.6",
+    "3.4.11.7",
+    "3.4.11.9",
+    "3.4.11.10",
+    "3.4.11.13",
+    "3.4.11.14",
+    "3.4.11.15",
+    "3.4.11.16",
+    "3.4.11.17",
+    "3.4.11.18",
+    "3.4.11.19",
+    "3.4.11.20",
+    "3.4.11.21",
+    "3.4.11.22",
+    "3.4.11.23",
+    "3.4.11.24",
+    "3.4.13.3",
+    "3.4.13.4",
+    "3.4.13.5",
+    "3.4.13.7",
+    "3.4.13.9",
+    "3.4.13.12",
+    "3.4.13.17",
+    "3.4.13.18",
+    "3.4.13.19",
+    "3.4.13.20",
+    "3.4.13.21",
+    "3.4.13.22",
+    "3.4.14.1",
+    "3.4.14.2",
+    "3.4.14.4",
+    "3.4.14.5",
+    "3.4.14.6",
+    "3.4.14.9",
+    "3.4.14.10",
+    "3.4.14.11",
+    "3.4.14.12",
+    "3.4.15.1",
+    "3.4.15.4",
+    "3.4.15.5",
+    "3.4.15.6",
+    "3.4.16.2",
+    "3.4.16.4",
+    "3.4.16.5",
+    "3.4.16.6",
+    "3.4.17.1",
+    "3.4.17.2",
+    "3.4.17.3",
+    "3.4.17.4",
+    "3.4.17.6",
+    "3.4.17.8",
+    "3.4.17.10",
+    "3.4.17.11",
+    "3.4.17.12",
+    "3.4.17.13",
+    "3.4.17.14",
+    "3.4.17.15",
+    "3.4.17.16",
+    "3.4.17.17",
+    "3.4.17.18",
+    "3.4.17.19",
+    "3.4.17.20",
+    "3.4.17.21",
+    "3.4.17.22",
+    "3.4.17.23",
+    "3.4.18.1",
+    "3.4.19.1",
+    "3.4.19.2",
+    "3.4.19.3",
+    "3.4.19.5",
+    "3.4.19.6",
+    "3.4.19.7",
+    "3.4.19.9",
+    "3.4.19.11",
+    "3.4.19.12",
+    "3.4.21.1",
+    "3.4.21.2",
+    "3.4.21.3",
+    "3.4.21.4",
+    "3.4.21.5",
+    "3.4.21.6",
+    "3.4.21.7",
+    "3.4.21.9",
+    "3.4.21.10",
+    "3.4.21.12",
+    "3.4.21.19",
+    "3.4.21.20",
+    "3.4.21.21",
+    "3.4.21.22",
+    "3.4.21.25",
+    "3.4.21.26",
+    "3.4.21.27",
+    "3.4.21.32",
+    "3.4.21.34",
+    "3.4.21.35",
+    "3.4.21.36",
+    "3.4.21.37",
+    "3.4.21.38",
+    "3.4.21.39",
+    "3.4.21.41",
+    "3.4.21.42",
+    "3.4.21.43",
+    "3.4.21.45",
+    "3.4.21.46",
+    "3.4.21.47",
+    "3.4.21.48",
+    "3.4.21.49",
+    "3.4.21.50",
+    "3.4.21.53",
+    "3.4.21.54",
+    "3.4.21.55",
+    "3.4.21.57",
+    "3.4.21.59",
+    "3.4.21.60",
+    "3.4.21.61",
+    "3.4.21.62",
+    "3.4.21.63",
+    "3.4.21.64",
+    "3.4.21.65",
+    "3.4.21.66",
+    "3.4.21.67",
+    "3.4.21.68",
+    "3.4.21.69",
+    "3.4.21.70",
+    "3.4.21.71",
+    "3.4.21.72",
+    "3.4.21.73",
+    "3.4.21.74",
+    "3.4.21.75",
+    "3.4.21.76",
+    "3.4.21.77",
+    "3.4.21.78",
+    "3.4.21.79",
+    "3.4.21.80",
+    "3.4.21.81",
+    "3.4.21.82",
+    "3.4.21.83",
+    "3.4.21.84",
+    "3.4.21.85",
+    "3.4.21.86",
+    "3.4.21.88",
+    "3.4.21.89",
+    "3.4.21.90",
+    "3.4.21.91",
+    "3.4.21.92",
+    "3.4.21.93",
+    "3.4.21.94",
+    "3.4.21.95",
+    "3.4.21.96",
+    "3.4.21.97",
+    "3.4.21.98",
+    "3.4.21.99",
+    "3.4.21.100",
+    "3.4.21.101",
+    "3.4.21.102",
+    "3.4.21.103",
+    "3.4.21.104",
+    "3.4.21.105",
+    "3.4.21.106",
+    "3.4.21.107",
+    "3.4.21.108",
+    "3.4.21.109",
+    "3.4.21.110",
+    "3.4.21.111",
+    "3.4.21.112",
+    "3.4.21.113",
+    "3.4.21.114",
+    "3.4.21.115",
+    "3.4.21.116",
+    "3.4.21.117",
+    "3.4.21.118",
+    "3.4.21.119",
+    "3.4.21.120",
+    "3.4.22.1",
+    "3.4.22.2",
+    "3.4.22.3",
+    "3.4.22.6",
+    "3.4.22.7",
+    "3.4.22.8",
+    "3.4.22.10",
+    "3.4.22.14",
+    "3.4.22.15",
+    "3.4.22.16",
+    "3.4.22.24",
+    "3.4.22.25",
+    "3.4.22.26",
+    "3.4.22.27",
+    "3.4.22.28",
+    "3.4.22.29",
+    "3.4.22.30",
+    "3.4.22.31",
+    "3.4.22.32",
+    "3.4.22.33",
+    "3.4.22.34",
+    "3.4.22.35",
+    "3.4.22.36",
+    "3.4.22.37",
+    "3.4.22.38",
+    "3.4.22.39",
+    "3.4.22.40",
+    "3.4.22.41",
+    "3.4.22.42",
+    "3.4.22.43",
+    "3.4.22.44",
+    "3.4.22.45",
+    "3.4.22.46",
+    "3.4.22.47",
+    "3.4.22.48",
+    "3.4.22.49",
+    "3.4.22.50",
+    "3.4.22.51",
+    "3.4.22.52",
+    "3.4.22.53",
+    "3.4.22.54",
+    "3.4.22.55",
+    "3.4.22.56",
+    "3.4.22.57",
+    "3.4.22.58",
+    "3.4.22.59",
+    "3.4.22.60",
+    "3.4.22.61",
+    "3.4.22.62",
+    "3.4.22.63",
+    "3.4.22.64",
+    "3.4.22.65",
+    "3.4.22.66",
+    "3.4.22.67",
+    "3.4.22.68",
+    "3.4.22.69",
+    "3.4.22.70",
+    "3.4.22.71",
+    "3.4.23.1",
+    "3.4.23.2",
+    "3.4.23.3",
+    "3.4.23.4",
+    "3.4.23.5",
+    "3.4.23.12",
+    "3.4.23.15",
+    "3.4.23.16",
+    "3.4.23.17",
+    "3.4.23.18",
+    "3.4.23.19",
+    "3.4.23.20",
+    "3.4.23.21",
+    "3.4.23.22",
+    "3.4.23.23",
+    "3.4.23.24",
+    "3.4.23.25",
+    "3.4.23.26",
+    "3.4.23.28",
+    "3.4.23.29",
+    "3.4.23.30",
+    "3.4.23.31",
+    "3.4.23.32",
+    "3.4.23.34",
+    "3.4.23.35",
+    "3.4.23.36",
+    "3.4.23.38",
+    "3.4.23.39",
+    "3.4.23.40",
+    "3.4.23.41",
+    "3.4.23.42",
+    "3.4.23.43",
+    "3.4.23.44",
+    "3.4.23.45",
+    "3.4.23.46",
+    "3.4.23.47",
+    "3.4.23.48",
+    "3.4.23.49",
+    "3.4.23.50",
+    "3.4.23.51",
+    "3.4.24.1",
+    "3.4.24.3",
+    "3.4.24.6",
+    "3.4.24.7",
+    "3.4.24.11",
+    "3.4.24.12",
+    "3.4.24.13",
+    "3.4.24.14",
+    "3.4.24.15",
+    "3.4.24.16",
+    "3.4.24.17",
+    "3.4.24.18",
+    "3.4.24.19",
+    "3.4.24.20",
+    "3.4.24.21",
+    "3.4.24.22",
+    "3.4.24.23",
+    "3.4.24.24",
+    "3.4.24.25",
+    "3.4.24.26",
+    "3.4.24.27",
+    "3.4.24.28",
+    "3.4.24.29",
+    "3.4.24.30",
+    "3.4.24.31",
+    "3.4.24.32",
+    "3.4.24.33",
+    "3.4.24.34",
+    "3.4.24.35",
+    "3.4.24.36",
+    "3.4.24.37",
+    "3.4.24.38",
+    "3.4.24.39",
+    "3.4.24.40",
+    "3.4.24.41",
+    "3.4.24.42",
+    "3.4.24.43",
+    "3.4.24.44",
+    "3.4.24.45",
+    "3.4.24.46",
+    "3.4.24.47",
+    "3.4.24.48",
+    "3.4.24.49",
+    "3.4.24.50",
+    "3.4.24.51",
+    "3.4.24.52",
+    "3.4.24.53",
+    "3.4.24.54",
+    "3.4.24.55",
+    "3.4.24.56",
+    "3.4.24.57",
+    "3.4.24.58",
+    "3.4.24.59",
+    "3.4.24.60",
+    "3.4.24.61",
+    "3.4.24.62",
+    "3.4.24.63",
+    "3.4.24.64",
+    "3.4.24.65",
+    "3.4.24.66",
+    "3.4.24.67",
+    "3.4.24.68",
+    "3.4.24.69",
+    "3.4.24.70",
+    "3.4.24.71",
+    "3.4.24.72",
+    "3.4.24.73",
+    "3.4.24.74",
+    "3.4.24.75",
+    "3.4.24.76",
+    "3.4.24.77",
+    "3.4.24.78",
+    "3.4.24.79",
+    "3.4.24.80",
+    "3.4.24.81",
+    "3.4.24.82",
+    "3.4.24.83",
+    "3.4.24.84",
+    "3.4.24.85",
+    "3.4.24.86",
+    "3.4.24.87",
+    "3.4.25.1",
+    "3.4.25.2",
+    "3.5.1.1",
+    "3.5.1.2",
+    "3.5.1.3",
+    "3.5.1.4",
+    "3.5.1.5",
+    "3.5.1.6",
+    "3.5.1.7",
+    "3.5.1.8",
+    "3.5.1.9",
+    "3.5.1.10",
+    "3.5.1.11",
+    "3.5.1.12",
+    "3.5.1.13",
+    "3.5.1.14",
+    "3.5.1.15",
+    "3.5.1.16",
+    "3.5.1.17",
+    "3.5.1.18",
+    "3.5.1.19",
+    "3.5.1.20",
+    "3.5.1.21",
+    "3.5.1.22",
+    "3.5.1.23",
+    "3.5.1.24",
+    "3.5.1.25",
+    "3.5.1.26",
+    "3.5.1.27",
+    "3.5.1.28",
+    "3.5.1.29",
+    "3.5.1.30",
+    "3.5.1.31",
+    "3.5.1.32",
+    "3.5.1.33",
+    "3.5.1.35",
+    "3.5.1.36",
+    "3.5.1.38",
+    "3.5.1.39",
+    "3.5.1.40",
+    "3.5.1.41",
+    "3.5.1.42",
+    "3.5.1.43",
+    "3.5.1.44",
+    "3.5.1.46",
+    "3.5.1.47",
+    "3.5.1.48",
+    "3.5.1.49",
+    "3.5.1.50",
+    "3.5.1.51",
+    "3.5.1.52",
+    "3.5.1.53",
+    "3.5.1.54",
+    "3.5.1.55",
+    "3.5.1.56",
+    "3.5.1.57",
+    "3.5.1.58",
+    "3.5.1.59",
+    "3.5.1.60",
+    "3.5.1.61",
+    "3.5.1.62",
+    "3.5.1.63",
+    "3.5.1.64",
+    "3.5.1.65",
+    "3.5.1.66",
+    "3.5.1.67",
+    "3.5.1.68",
+    "3.5.1.69",
+    "3.5.1.70",
+    "3.5.1.71",
+    "3.5.1.72",
+    "3.5.1.73",
+    "3.5.1.74",
+    "3.5.1.75",
+    "3.5.1.76",
+    "3.5.1.77",
+    "3.5.1.78",
+    "3.5.1.79",
+    "3.5.1.81",
+    "3.5.1.82",
+    "3.5.1.83",
+    "3.5.1.84",
+    "3.5.1.85",
+    "3.5.1.86",
+    "3.5.1.87",
+    "3.5.1.88",
+    "3.5.1.89",
+    "3.5.1.90",
+    "3.5.1.91",
+    "3.5.1.92",
+    "3.5.1.93",
+    "3.5.1.94",
+    "3.5.1.95",
+    "3.5.1.96",
+    "3.5.1.97",
+    "3.5.1.98",
+    "3.5.1.99",
+    "3.5.1.100",
+    "3.5.1.101",
+    "3.5.1.102",
+    "3.5.1.103",
+    "3.5.2.1",
+    "3.5.2.2",
+    "3.5.2.3",
+    "3.5.2.4",
+    "3.5.2.5",
+    "3.5.2.6",
+    "3.5.2.7",
+    "3.5.2.9",
+    "3.5.2.10",
+    "3.5.2.11",
+    "3.5.2.12",
+    "3.5.2.13",
+    "3.5.2.14",
+    "3.5.2.15",
+    "3.5.2.16",
+    "3.5.2.17",
+    "3.5.2.18",
+    "3.5.3.1",
+    "3.5.3.2",
+    "3.5.3.3",
+    "3.5.3.4",
+    "3.5.3.5",
+    "3.5.3.6",
+    "3.5.3.7",
+    "3.5.3.8",
+    "3.5.3.9",
+    "3.5.3.10",
+    "3.5.3.11",
+    "3.5.3.12",
+    "3.5.3.13",
+    "3.5.3.14",
+    "3.5.3.15",
+    "3.5.3.16",
+    "3.5.3.17",
+    "3.5.3.18",
+    "3.5.3.19",
+    "3.5.3.20",
+    "3.5.3.21",
+    "3.5.3.22",
+    "3.5.3.23",
+    "3.5.4.1",
+    "3.5.4.2",
+    "3.5.4.3",
+    "3.5.4.4",
+    "3.5.4.5",
+    "3.5.4.6",
+    "3.5.4.7",
+    "3.5.4.8",
+    "3.5.4.9",
+    "3.5.4.10",
+    "3.5.4.11",
+    "3.5.4.12",
+    "3.5.4.13",
+    "3.5.4.14",
+    "3.5.4.15",
+    "3.5.4.16",
+    "3.5.4.17",
+    "3.5.4.18",
+    "3.5.4.19",
+    "3.5.4.20",
+    "3.5.4.21",
+    "3.5.4.22",
+    "3.5.4.23",
+    "3.5.4.24",
+    "3.5.4.25",
+    "3.5.4.26",
+    "3.5.4.27",
+    "3.5.4.28",
+    "3.5.4.29",
+    "3.5.4.30",
+    "3.5.5.1",
+    "3.5.5.2",
+    "3.5.5.4",
+    "3.5.5.5",
+    "3.5.5.6",
+    "3.5.5.7",
+    "3.5.5.8",
+    "3.5.99.1",
+    "3.5.99.2",
+    "3.5.99.3",
+    "3.5.99.4",
+    "3.5.99.5",
+    "3.5.99.6",
+    "3.5.99.7",
+    "3.6.1.1",
+    "3.6.1.2",
+    "3.6.1.3",
+    "3.6.1.5",
+    "3.6.1.6",
+    "3.6.1.7",
+    "3.6.1.8",
+    "3.6.1.9",
+    "3.6.1.10",
+    "3.6.1.11",
+    "3.6.1.12",
+    "3.6.1.13",
+    "3.6.1.14",
+    "3.6.1.15",
+    "3.6.1.16",
+    "3.6.1.17",
+    "3.6.1.18",
+    "3.6.1.19",
+    "3.6.1.20",
+    "3.6.1.21",
+    "3.6.1.22",
+    "3.6.1.23",
+    "3.6.1.24",
+    "3.6.1.25",
+    "3.6.1.26",
+    "3.6.1.27",
+    "3.6.1.28",
+    "3.6.1.29",
+    "3.6.1.30",
+    "3.6.1.31",
+    "3.6.1.39",
+    "3.6.1.40",
+    "3.6.1.41",
+    "3.6.1.42",
+    "3.6.1.43",
+    "3.6.1.44",
+    "3.6.1.45",
+    "3.6.1.52",
+    "3.6.1.53",
+    "3.6.2.1",
+    "3.6.2.2",
+    "3.6.3.1",
+    "3.6.3.2",
+    "3.6.3.3",
+    "3.6.3.4",
+    "3.6.3.5",
+    "3.6.3.6",
+    "3.6.3.7",
+    "3.6.3.8",
+    "3.6.3.9",
+    "3.6.3.10",
+    "3.6.3.11",
+    "3.6.3.12",
+    "3.6.3.14",
+    "3.6.3.15",
+    "3.6.3.16",
+    "3.6.3.17",
+    "3.6.3.18",
+    "3.6.3.19",
+    "3.6.3.20",
+    "3.6.3.21",
+    "3.6.3.22",
+    "3.6.3.23",
+    "3.6.3.24",
+    "3.6.3.25",
+    "3.6.3.26",
+    "3.6.3.27",
+    "3.6.3.28",
+    "3.6.3.29",
+    "3.6.3.30",
+    "3.6.3.31",
+    "3.6.3.32",
+    "3.6.3.33",
+    "3.6.3.34",
+    "3.6.3.35",
+    "3.6.3.36",
+    "3.6.3.37",
+    "3.6.3.38",
+    "3.6.3.39",
+    "3.6.3.40",
+    "3.6.3.41",
+    "3.6.3.42",
+    "3.6.3.43",
+    "3.6.3.44",
+    "3.6.3.46",
+    "3.6.3.47",
+    "3.6.3.48",
+    "3.6.3.49",
+    "3.6.3.50",
+    "3.6.3.51",
+    "3.6.3.52",
+    "3.6.3.53",
+    "3.6.4.1",
+    "3.6.4.2",
+    "3.6.4.3",
+    "3.6.4.4",
+    "3.6.4.5",
+    "3.6.4.6",
+    "3.6.4.7",
+    "3.6.4.8",
+    "3.6.4.9",
+    "3.6.4.10",
+    "3.6.4.11",
+    "3.6.4.12",
+    "3.6.4.13",
+    "3.6.5.1",
+    "3.6.5.2",
+    "3.6.5.3",
+    "3.6.5.4",
+    "3.6.5.5",
+    "3.6.5.6",
+    "3.7.1.1",
+    "3.7.1.2",
+    "3.7.1.3",
+    "3.7.1.4",
+    "3.7.1.5",
+    "3.7.1.6",
+    "3.7.1.7",
+    "3.7.1.8",
+    "3.7.1.9",
+    "3.7.1.10",
+    "3.7.1.11",
+    "3.8.1.1",
+    "3.8.1.2",
+    "3.8.1.3",
+    "3.8.1.5",
+    "3.8.1.6",
+    "3.8.1.7",
+    "3.8.1.8",
+    "3.8.1.9",
+    "3.8.1.10",
+    "3.8.1.11",
+    "3.9.1.1",
+    "3.10.1.1",
+    "3.10.1.2",
+    "3.11.1.1",
+    "3.11.1.2",
+    "3.11.1.3",
+    "3.12.1.1",
+    "3.13.1.1",
+    "3.13.1.3",
+    "4.1.1.1",
+    "4.1.1.2",
+    "4.1.1.3",
+    "4.1.1.4",
+    "4.1.1.5",
+    "4.1.1.6",
+    "4.1.1.7",
+    "4.1.1.8",
+    "4.1.1.9",
+    "4.1.1.11",
+    "4.1.1.12",
+    "4.1.1.14",
+    "4.1.1.15",
+    "4.1.1.16",
+    "4.1.1.17",
+    "4.1.1.18",
+    "4.1.1.19",
+    "4.1.1.20",
+    "4.1.1.21",
+    "4.1.1.22",
+    "4.1.1.23",
+    "4.1.1.24",
+    "4.1.1.25",
+    "4.1.1.28",
+    "4.1.1.29",
+    "4.1.1.30",
+    "4.1.1.31",
+    "4.1.1.32",
+    "4.1.1.33",
+    "4.1.1.34",
+    "4.1.1.35",
+    "4.1.1.36",
+    "4.1.1.37",
+    "4.1.1.38",
+    "4.1.1.39",
+    "4.1.1.40",
+    "4.1.1.41",
+    "4.1.1.42",
+    "4.1.1.43",
+    "4.1.1.44",
+    "4.1.1.45",
+    "4.1.1.46",
+    "4.1.1.47",
+    "4.1.1.48",
+    "4.1.1.49",
+    "4.1.1.50",
+    "4.1.1.51",
+    "4.1.1.52",
+    "4.1.1.53",
+    "4.1.1.54",
+    "4.1.1.55",
+    "4.1.1.56",
+    "4.1.1.57",
+    "4.1.1.58",
+    "4.1.1.59",
+    "4.1.1.60",
+    "4.1.1.61",
+    "4.1.1.62",
+    "4.1.1.63",
+    "4.1.1.64",
+    "4.1.1.65",
+    "4.1.1.66",
+    "4.1.1.67",
+    "4.1.1.68",
+    "4.1.1.69",
+    "4.1.1.70",
+    "4.1.1.71",
+    "4.1.1.72",
+    "4.1.1.73",
+    "4.1.1.74",
+    "4.1.1.75",
+    "4.1.1.76",
+    "4.1.1.77",
+    "4.1.1.78",
+    "4.1.1.79",
+    "4.1.1.80",
+    "4.1.1.81",
+    "4.1.1.82",
+    "4.1.1.83",
+    "4.1.1.84",
+    "4.1.1.85",
+    "4.1.1.86",
+    "4.1.1.87",
+    "4.1.1.88",
+    "4.1.1.89",
+    "4.1.1.90",
+    "4.1.2.2",
+    "4.1.2.4",
+    "4.1.2.5",
+    "4.1.2.8",
+    "4.1.2.9",
+    "4.1.2.10",
+    "4.1.2.11",
+    "4.1.2.12",
+    "4.1.2.13",
+    "4.1.2.14",
+    "4.1.2.17",
+    "4.1.2.18",
+    "4.1.2.19",
+    "4.1.2.20",
+    "4.1.2.21",
+    "4.1.2.22",
+    "4.1.2.23",
+    "4.1.2.24",
+    "4.1.2.25",
+    "4.1.2.26",
+    "4.1.2.27",
+    "4.1.2.28",
+    "4.1.2.29",
+    "4.1.2.30",
+    "4.1.2.32",
+    "4.1.2.33",
+    "4.1.2.34",
+    "4.1.2.35",
+    "4.1.2.36",
+    "4.1.2.37",
+    "4.1.2.38",
+    "4.1.2.40",
+    "4.1.2.41",
+    "4.1.2.42",
+    "4.1.2.43",
+    "4.1.2.44",
+    "4.1.2.45",
+    "4.1.3.1",
+    "4.1.3.3",
+    "4.1.3.4",
+    "4.1.3.6",
+    "4.1.3.13",
+    "4.1.3.14",
+    "4.1.3.16",
+    "4.1.3.17",
+    "4.1.3.22",
+    "4.1.3.24",
+    "4.1.3.25",
+    "4.1.3.26",
+    "4.1.3.27",
+    "4.1.3.30",
+    "4.1.3.32",
+    "4.1.3.34",
+    "4.1.3.35",
+    "4.1.3.36",
+    "4.1.3.38",
+    "4.1.3.39",
+    "4.1.3.40",
+    "4.1.99.1",
+    "4.1.99.2",
+    "4.1.99.3",
+    "4.1.99.5",
+    "4.1.99.11",
+    "4.1.99.12",
+    "4.1.99.13",
+    "4.1.99.14",
+    "4.1.99.15",
+    "4.2.1.1",
+    "4.2.1.2",
+    "4.2.1.3",
+    "4.2.1.4",
+    "4.2.1.5",
+    "4.2.1.6",
+    "4.2.1.7",
+    "4.2.1.8",
+    "4.2.1.9",
+    "4.2.1.10",
+    "4.2.1.11",
+    "4.2.1.12",
+    "4.2.1.17",
+    "4.2.1.18",
+    "4.2.1.19",
+    "4.2.1.20",
+    "4.2.1.22",
+    "4.2.1.24",
+    "4.2.1.25",
+    "4.2.1.27",
+    "4.2.1.28",
+    "4.2.1.30",
+    "4.2.1.31",
+    "4.2.1.32",
+    "4.2.1.33",
+    "4.2.1.34",
+    "4.2.1.35",
+    "4.2.1.36",
+    "4.2.1.39",
+    "4.2.1.40",
+    "4.2.1.41",
+    "4.2.1.42",
+    "4.2.1.43",
+    "4.2.1.44",
+    "4.2.1.45",
+    "4.2.1.46",
+    "4.2.1.47",
+    "4.2.1.48",
+    "4.2.1.49",
+    "4.2.1.50",
+    "4.2.1.51",
+    "4.2.1.52",
+    "4.2.1.53",
+    "4.2.1.54",
+    "4.2.1.55",
+    "4.2.1.56",
+    "4.2.1.57",
+    "4.2.1.58",
+    "4.2.1.59",
+    "4.2.1.60",
+    "4.2.1.61",
+    "4.2.1.62",
+    "4.2.1.65",
+    "4.2.1.66",
+    "4.2.1.67",
+    "4.2.1.68",
+    "4.2.1.69",
+    "4.2.1.70",
+    "4.2.1.73",
+    "4.2.1.74",
+    "4.2.1.75",
+    "4.2.1.76",
+    "4.2.1.77",
+    "4.2.1.78",
+    "4.2.1.79",
+    "4.2.1.80",
+    "4.2.1.81",
+    "4.2.1.82",
+    "4.2.1.83",
+    "4.2.1.84",
+    "4.2.1.85",
+    "4.2.1.87",
+    "4.2.1.88",
+    "4.2.1.89",
+    "4.2.1.90",
+    "4.2.1.91",
+    "4.2.1.92",
+    "4.2.1.93",
+    "4.2.1.94",
+    "4.2.1.95",
+    "4.2.1.96",
+    "4.2.1.97",
+    "4.2.1.98",
+    "4.2.1.99",
+    "4.2.1.100",
+    "4.2.1.101",
+    "4.2.1.103",
+    "4.2.1.104",
+    "4.2.1.105",
+    "4.2.1.106",
+    "4.2.1.107",
+    "4.2.1.108",
+    "4.2.1.109",
+    "4.2.1.110",
+    "4.2.1.111",
+    "4.2.1.112",
+    "4.2.1.113",
+    "4.2.1.114",
+    "4.2.1.115",
+    "4.2.1.116",
+    "4.2.1.117",
+    "4.2.1.118",
+    "4.2.1.119",
+    "4.2.1.120",
+    "4.2.2.1",
+    "4.2.2.2",
+    "4.2.2.3",
+    "4.2.2.5",
+    "4.2.2.6",
+    "4.2.2.7",
+    "4.2.2.8",
+    "4.2.2.9",
+    "4.2.2.10",
+    "4.2.2.11",
+    "4.2.2.12",
+    "4.2.2.13",
+    "4.2.2.14",
+    "4.2.2.15",
+    "4.2.2.16",
+    "4.2.2.17",
+    "4.2.2.18",
+    "4.2.2.19",
+    "4.2.2.20",
+    "4.2.2.21",
+    "4.2.2.22",
+    "4.2.3.1",
+    "4.2.3.2",
+    "4.2.3.3",
+    "4.2.3.4",
+    "4.2.3.5",
+    "4.2.3.6",
+    "4.2.3.7",
+    "4.2.3.8",
+    "4.2.3.9",
+    "4.2.3.10",
+    "4.2.3.11",
+    "4.2.3.12",
+    "4.2.3.13",
+    "4.2.3.14",
+    "4.2.3.15",
+    "4.2.3.16",
+    "4.2.3.17",
+    "4.2.3.18",
+    "4.2.3.19",
+    "4.2.3.20",
+    "4.2.3.21",
+    "4.2.3.22",
+    "4.2.3.23",
+    "4.2.3.24",
+    "4.2.3.25",
+    "4.2.3.26",
+    "4.2.3.27",
+    "4.2.3.28",
+    "4.2.3.29",
+    "4.2.3.30",
+    "4.2.3.31",
+    "4.2.3.32",
+    "4.2.3.33",
+    "4.2.3.34",
+    "4.2.3.35",
+    "4.2.3.36",
+    "4.2.3.37",
+    "4.2.3.38",
+    "4.2.3.39",
+    "4.2.3.40",
+    "4.2.3.41",
+    "4.2.3.42",
+    "4.2.3.43",
+    "4.2.3.44",
+    "4.2.3.45",
+    "4.2.99.12",
+    "4.2.99.18",
+    "4.2.99.20",
+    "4.3.1.1",
+    "4.3.1.2",
+    "4.3.1.3",
+    "4.3.1.4",
+    "4.3.1.6",
+    "4.3.1.7",
+    "4.3.1.9",
+    "4.3.1.10",
+    "4.3.1.12",
+    "4.3.1.13",
+    "4.3.1.14",
+    "4.3.1.15",
+    "4.3.1.16",
+    "4.3.1.17",
+    "4.3.1.18",
+    "4.3.1.19",
+    "4.3.1.20",
+    "4.3.1.22",
+    "4.3.1.23",
+    "4.3.1.24",
+    "4.3.1.25",
+    "4.3.1.26",
+    "4.3.2.1",
+    "4.3.2.2",
+    "4.3.2.3",
+    "4.3.2.4",
+    "4.3.2.5",
+    "4.3.3.1",
+    "4.3.3.2",
+    "4.3.3.3",
+    "4.3.3.4",
+    "4.3.3.5",
+    "4.3.99.2",
+    "4.4.1.1",
+    "4.4.1.2",
+    "4.4.1.3",
+    "4.4.1.4",
+    "4.4.1.5",
+    "4.4.1.6",
+    "4.4.1.8",
+    "4.4.1.9",
+    "4.4.1.10",
+    "4.4.1.11",
+    "4.4.1.13",
+    "4.4.1.14",
+    "4.4.1.15",
+    "4.4.1.16",
+    "4.4.1.17",
+    "4.4.1.19",
+    "4.4.1.20",
+    "4.4.1.21",
+    "4.4.1.22",
+    "4.4.1.23",
+    "4.4.1.24",
+    "4.4.1.25",
+    "4.5.1.1",
+    "4.5.1.2",
+    "4.5.1.3",
+    "4.5.1.4",
+    "4.5.1.5",
+    "4.6.1.1",
+    "4.6.1.2",
+    "4.6.1.6",
+    "4.6.1.12",
+    "4.6.1.13",
+    "4.6.1.14",
+    "4.6.1.15",
+    "4.99.1.1",
+    "4.99.1.2",
+    "4.99.1.3",
+    "4.99.1.4",
+    "4.99.1.5",
+    "4.99.1.6",
+    "4.99.1.7",
+    "4.99.1.8",
+    "5.1.1.1",
+    "5.1.1.2",
+    "5.1.1.3",
+    "5.1.1.4",
+    "5.1.1.5",
+    "5.1.1.6",
+    "5.1.1.7",
+    "5.1.1.8",
+    "5.1.1.9",
+    "5.1.1.10",
+    "5.1.1.11",
+    "5.1.1.12",
+    "5.1.1.13",
+    "5.1.1.14",
+    "5.1.1.15",
+    "5.1.1.16",
+    "5.1.1.17",
+    "5.1.1.18",
+    "5.1.2.1",
+    "5.1.2.2",
+    "5.1.2.3",
+    "5.1.2.4",
+    "5.1.2.5",
+    "5.1.2.6",
+    "5.1.3.1",
+    "5.1.3.2",
+    "5.1.3.3",
+    "5.1.3.4",
+    "5.1.3.5",
+    "5.1.3.6",
+    "5.1.3.7",
+    "5.1.3.8",
+    "5.1.3.9",
+    "5.1.3.10",
+    "5.1.3.11",
+    "5.1.3.12",
+    "5.1.3.13",
+    "5.1.3.14",
+    "5.1.3.15",
+    "5.1.3.16",
+    "5.1.3.17",
+    "5.1.3.18",
+    "5.1.3.19",
+    "5.1.3.20",
+    "5.1.3.21",
+    "5.1.3.22",
+    "5.1.3.23",
+    "5.1.99.1",
+    "5.1.99.2",
+    "5.1.99.3",
+    "5.1.99.4",
+    "5.1.99.5",
+    "5.2.1.1",
+    "5.2.1.2",
+    "5.2.1.3",
+    "5.2.1.4",
+    "5.2.1.5",
+    "5.2.1.6",
+    "5.2.1.7",
+    "5.2.1.8",
+    "5.2.1.9",
+    "5.2.1.10",
+    "5.3.1.1",
+    "5.3.1.3",
+    "5.3.1.4",
+    "5.3.1.5",
+    "5.3.1.6",
+    "5.3.1.7",
+    "5.3.1.8",
+    "5.3.1.9",
+    "5.3.1.12",
+    "5.3.1.13",
+    "5.3.1.14",
+    "5.3.1.15",
+    "5.3.1.16",
+    "5.3.1.17",
+    "5.3.1.20",
+    "5.3.1.21",
+    "5.3.1.22",
+    "5.3.1.23",
+    "5.3.1.24",
+    "5.3.1.25",
+    "5.3.1.26",
+    "5.3.1.27",
+    "5.3.2.1",
+    "5.3.2.2",
+    "5.3.3.1",
+    "5.3.3.2",
+    "5.3.3.3",
+    "5.3.3.4",
+    "5.3.3.5",
+    "5.3.3.6",
+    "5.3.3.7",
+    "5.3.3.8",
+    "5.3.3.9",
+    "5.3.3.10",
+    "5.3.3.11",
+    "5.3.3.12",
+    "5.3.3.13",
+    "5.3.3.14",
+    "5.3.3.15",
+    "5.3.4.1",
+    "5.3.99.2",
+    "5.3.99.3",
+    "5.3.99.4",
+    "5.3.99.5",
+    "5.3.99.6",
+    "5.3.99.7",
+    "5.3.99.8",
+    "5.3.99.9",
+    "5.4.1.1",
+    "5.4.1.2",
+    "5.4.2.1",
+    "5.4.2.2",
+    "5.4.2.3",
+    "5.4.2.4",
+    "5.4.2.5",
+    "5.4.2.6",
+    "5.4.2.7",
+    "5.4.2.8",
+    "5.4.2.9",
+    "5.4.2.10",
+    "5.4.3.2",
+    "5.4.3.3",
+    "5.4.3.4",
+    "5.4.3.5",
+    "5.4.3.6",
+    "5.4.3.7",
+    "5.4.3.8",
+    "5.4.4.1",
+    "5.4.4.2",
+    "5.4.4.3",
+    "5.4.99.1",
+    "5.4.99.2",
+    "5.4.99.3",
+    "5.4.99.4",
+    "5.4.99.5",
+    "5.4.99.7",
+    "5.4.99.8",
+    "5.4.99.9",
+    "5.4.99.11",
+    "5.4.99.12",
+    "5.4.99.13",
+    "5.4.99.14",
+    "5.4.99.15",
+    "5.4.99.16",
+    "5.4.99.17",
+    "5.4.99.18",
+    "5.5.1.1",
+    "5.5.1.2",
+    "5.5.1.3",
+    "5.5.1.4",
+    "5.5.1.5",
+    "5.5.1.6",
+    "5.5.1.7",
+    "5.5.1.8",
+    "5.5.1.9",
+    "5.5.1.10",
+    "5.5.1.11",
+    "5.5.1.12",
+    "5.5.1.13",
+    "5.5.1.14",
+    "5.5.1.15",
+    "5.5.1.16",
+    "5.99.1.1",
+    "5.99.1.2",
+    "5.99.1.3",
+    "5.99.1.4",
+    "6.1.1.1",
+    "6.1.1.2",
+    "6.1.1.3",
+    "6.1.1.4",
+    "6.1.1.5",
+    "6.1.1.6",
+    "6.1.1.7",
+    "6.1.1.9",
+    "6.1.1.10",
+    "6.1.1.11",
+    "6.1.1.12",
+    "6.1.1.13",
+    "6.1.1.14",
+    "6.1.1.15",
+    "6.1.1.16",
+    "6.1.1.17",
+    "6.1.1.18",
+    "6.1.1.19",
+    "6.1.1.20",
+    "6.1.1.21",
+    "6.1.1.22",
+    "6.1.1.23",
+    "6.1.1.24",
+    "6.1.1.25",
+    "6.1.1.26",
+    "6.1.1.27",
+    "6.2.1.1",
+    "6.2.1.2",
+    "6.2.1.3",
+    "6.2.1.4",
+    "6.2.1.5",
+    "6.2.1.6",
+    "6.2.1.7",
+    "6.2.1.8",
+    "6.2.1.9",
+    "6.2.1.10",
+    "6.2.1.11",
+    "6.2.1.12",
+    "6.2.1.13",
+    "6.2.1.14",
+    "6.2.1.15",
+    "6.2.1.16",
+    "6.2.1.17",
+    "6.2.1.18",
+    "6.2.1.19",
+    "6.2.1.20",
+    "6.2.1.22",
+    "6.2.1.23",
+    "6.2.1.24",
+    "6.2.1.25",
+    "6.2.1.26",
+    "6.2.1.27",
+    "6.2.1.28",
+    "6.2.1.30",
+    "6.2.1.31",
+    "6.2.1.32",
+    "6.2.1.33",
+    "6.2.1.34",
+    "6.2.1.35",
+    "6.2.1.36",
+    "6.3.1.1",
+    "6.3.1.2",
+    "6.3.1.4",
+    "6.3.1.5",
+    "6.3.1.6",
+    "6.3.1.7",
+    "6.3.1.8",
+    "6.3.1.9",
+    "6.3.1.10",
+    "6.3.1.11",
+    "6.3.1.12",
+    "6.3.1.13",
+    "6.3.2.1",
+    "6.3.2.2",
+    "6.3.2.3",
+    "6.3.2.4",
+    "6.3.2.5",
+    "6.3.2.6",
+    "6.3.2.7",
+    "6.3.2.8",
+    "6.3.2.9",
+    "6.3.2.10",
+    "6.3.2.11",
+    "6.3.2.12",
+    "6.3.2.13",
+    "6.3.2.14",
+    "6.3.2.16",
+    "6.3.2.17",
+    "6.3.2.18",
+    "6.3.2.19",
+    "6.3.2.20",
+    "6.3.2.21",
+    "6.3.2.22",
+    "6.3.2.23",
+    "6.3.2.24",
+    "6.3.2.25",
+    "6.3.2.26",
+    "6.3.2.27",
+    "6.3.2.28",
+    "6.3.2.29",
+    "6.3.2.30",
+    "6.3.2.31",
+    "6.3.2.32",
+    "6.3.2.33",
+    "6.3.2.34",
+    "6.3.3.1",
+    "6.3.3.2",
+    "6.3.3.3",
+    "6.3.3.4",
+    "6.3.4.1",
+    "6.3.4.2",
+    "6.3.4.3",
+    "6.3.4.4",
+    "6.3.4.5",
+    "6.3.4.6",
+    "6.3.4.7",
+    "6.3.4.8",
+    "6.3.4.9",
+    "6.3.4.10",
+    "6.3.4.11",
+    "6.3.4.12",
+    "6.3.4.13",
+    "6.3.4.14",
+    "6.3.4.15",
+    "6.3.4.16",
+    "6.3.4.17",
+    "6.3.4.18",
+    "6.3.5.1",
+    "6.3.5.2",
+    "6.3.5.3",
+    "6.3.5.4",
+    "6.3.5.5",
+    "6.3.5.6",
+    "6.3.5.7",
+    "6.3.5.9",
+    "6.3.5.10",
+    "6.4.1.1",
+    "6.4.1.2",
+    "6.4.1.3",
+    "6.4.1.4",
+    "6.4.1.5",
+    "6.4.1.6",
+    "6.4.1.7",
+    "6.5.1.1",
+    "6.5.1.2",
+    "6.5.1.3",
+    "6.5.1.4",
+    "6.6.1.1",
+    "6.6.1.2"
+};
diff --git a/api/edutil.c b/api/edutil.c
index bb303b0..c70d35a 100644
--- a/api/edutil.c
+++ b/api/edutil.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 2/4/94
 *
-* $Revision: 6.65 $
+* $Revision: 6.69 $
 *
 * File Description:  Sequence editing utilities
 *
@@ -39,6 +39,22 @@
 * -------  ----------  -----------------------------------------------------
 *
 * $Log: edutil.c,v $
+* Revision 6.69  2010/07/12 14:32:38  kans
+* SeqEntryDelFeat calls SeqEntryDelFeatEx
+*
+* Revision 6.68  2010/07/12 12:21:49  bollin
+* Introduced a version of BioseqDelete that uses idx.deleteme to remove features
+* (instead of freeing them immediately), and fixed bugs in VecScreenTool when
+* entire Bioseqs are deleted.
+*
+* Revision 6.67  2010/06/11 12:03:22  bollin
+* Added iBOL compliance report, which marks items with low trace as failing.
+* Also checking in first draft of functions to reverse Quality Scores, not using
+* until we can verify that they work for float and int graphs.
+*
+* Revision 6.66  2009/10/02 19:46:00  kans
+* address clang static analyzer warnings
+*
 * Revision 6.65  2009/03/04 16:34:15  bollin
 * Added function for removing contigs from scaffolds.
 *
@@ -890,7 +906,7 @@ NLM_EXTERN DeltaSeqPtr LIBCALL SeqLocsToDeltaSeqs (DeltaSeqPtr dsp, SeqLocPtr sl
 *      If do_split, the features across the deleted region are split into
 *        two intervals on either side. If not, the feature is just shortened.
 *****************************************************************************/
-NLM_EXTERN Boolean LIBCALL BioseqDelete (SeqIdPtr target, Int4 from, Int4 to, Boolean do_feat, Boolean do_split)
+NLM_EXTERN Boolean LIBCALL BioseqDeleteEx (SeqIdPtr target, Int4 from, Int4 to, Boolean do_feat, Boolean do_split, Boolean mark_deleted_feat)
 {
 	Boolean retval = FALSE;
 	BioseqPtr bsp;
@@ -904,7 +920,7 @@ NLM_EXTERN Boolean LIBCALL BioseqDelete (SeqIdPtr target, Int4 from, Int4 to, Bo
 	SeqFeatPtr sfpcurr, sfpnext, sfpprev;
 	Int2 dropped;
 	SeqEntryPtr oldscope;
-	DeltaSeqPtr tdsp;
+    DeltaSeqPtr tdsp = NULL;
 
 	bsp = BioseqFind(target);
 	if (bsp == NULL) {
@@ -920,7 +936,7 @@ NLM_EXTERN Boolean LIBCALL BioseqDelete (SeqIdPtr target, Int4 from, Int4 to, Bo
 		(to >= bsp->length) || (from > to)) return retval;
 
 	if (do_feat)
-		SeqEntryDelFeat(NULL, target, from, to, do_split);
+        SeqEntryDelFeatEx(NULL, target, from, to, do_split, mark_deleted_feat);
 
 	len = to - from + 1;
 	           /* if actual sequence present */
@@ -1089,6 +1105,12 @@ NLM_EXTERN Boolean LIBCALL BioseqDelete (SeqIdPtr target, Int4 from, Int4 to, Bo
 }
 
 
+NLM_EXTERN Boolean LIBCALL BioseqDelete (SeqIdPtr target, Int4 from, Int4 to, Boolean do_feat, Boolean do_split)
+{
+  return BioseqDeleteEx (target, from, to, do_feat, do_split, FALSE);
+}
+
+
 /*****************************************************************************
 *
 *   BioseqOverwrite (target, pos, residue, seqcode)
@@ -1155,7 +1177,7 @@ NLM_EXTERN Boolean LIBCALL SeqInsertByLoc (SeqIdPtr target, Int4 offset, SeqLocP
 *   SeqDeleteByLoc (slp, do_feat, do_split)
 *
 *****************************************************************************/
-NLM_EXTERN Boolean LIBCALL SeqDeleteByLoc (SeqLocPtr slp, Boolean do_feat, Boolean do_split)
+NLM_EXTERN Boolean LIBCALL SeqDeleteByLocEx (SeqLocPtr slp, Boolean do_feat, Boolean do_split, Boolean mark_deleted_feat)
 {
 	SeqLocPtr tmp;
 	Boolean retval = FALSE;
@@ -1273,7 +1295,7 @@ NLM_EXTERN Boolean LIBCALL SeqDeleteByLoc (SeqLocPtr slp, Boolean do_feat, Boole
 	{
 		tstart = SeqLocStart(theorder[ctr]);
 		tstop = SeqLocStop(theorder[ctr]);
-		BioseqDelete(SeqLocId(theorder[ctr]), tstart, tstop, do_feat, do_split);
+        BioseqDeleteEx(SeqLocId(theorder[ctr]), tstart, tstop, do_feat, do_split, mark_deleted_feat);
 	}
 
 	MemFree(theorder);
@@ -1282,6 +1304,12 @@ NLM_EXTERN Boolean LIBCALL SeqDeleteByLoc (SeqLocPtr slp, Boolean do_feat, Boole
 }
 
 
+NLM_EXTERN Boolean LIBCALL SeqDeleteByLoc (SeqLocPtr slp, Boolean do_feat, Boolean do_split)
+{
+  return SeqDeleteByLocEx (slp, do_feat, do_split, FALSE);
+}
+
+
 /*****************************************************************************
 *
 *   SeqFeatDelete()
@@ -1860,6 +1888,48 @@ NLM_EXTERN void DelFeat (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 	return;
 }
 
+
+static void MarkDelFeat (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
+{
+    DelStructPtr dsp;
+    BioseqPtr bsp;
+    BioseqSetPtr bssp;
+    SeqAnnotPtr sap;
+    SeqFeatPtr sfp;
+
+    dsp = (DelStructPtr)data;
+    if (IS_Bioseq(sep))
+    {
+        bsp = (BioseqPtr)(sep->data.ptrvalue);
+        sap = bsp->annot;
+    }
+    else
+    {
+        bssp = (BioseqSetPtr)(sep->data.ptrvalue);
+        sap = bssp->annot;
+    }
+
+    while (sap != NULL)
+    {
+        if (sap->type == 1)   /* feature table */
+        {
+            sfp = (SeqFeatPtr) sap->data;
+            while (sfp != NULL)
+            {
+                if (SeqFeatDelete(sfp, dsp->sip, dsp->from, dsp->to, dsp->merge) == 2)
+                {
+                    /* location completely gone */
+                    sfp->idx.deleteme = TRUE;
+                }
+                sfp = sfp->next;
+            }
+        }
+
+        sap = sap->next;
+    }
+}
+
+
 /*****************************************************************************
 *
 *   SeqEntryDelFeat(sep, id, from, to, do_split)
@@ -1874,7 +1944,7 @@ NLM_EXTERN void DelFeat (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 *       for features.
 *   
 *****************************************************************************/
-NLM_EXTERN Boolean	LIBCALL SeqEntryDelFeat (SeqEntryPtr sep, SeqIdPtr sip, Int4 from, Int4 to, Boolean do_split)
+NLM_EXTERN Boolean LIBCALL SeqEntryDelFeatEx (SeqEntryPtr sep, SeqIdPtr sip, Int4 from, Int4 to, Boolean do_split, Boolean mark_deleted_feat)
 {
 
 	DelStruct ds;
@@ -1895,11 +1965,22 @@ NLM_EXTERN Boolean	LIBCALL SeqEntryDelFeat (SeqEntryPtr sep, SeqIdPtr sip, Int4
 	else
 		ds.merge = TRUE;
 
+    if (mark_deleted_feat) {
+      SeqEntryExplore (sep, (Pointer)(&ds), MarkDelFeat);
+    } else {
 	SeqEntryExplore(sep, (Pointer)(&ds), DelFeat);
+    }
 
 	return TRUE;
 }
 
+
+NLM_EXTERN Boolean LIBCALL SeqEntryDelFeat (SeqEntryPtr sep, SeqIdPtr sip, Int4 from, Int4 to, Boolean do_split)
+{
+  return SeqEntryDelFeatEx (sep, sip, from, to, do_split, FALSE);
+}
+
+
 /*****************************************************************************
 *
 *   DescrToFeatures(sep)
@@ -6050,7 +6131,7 @@ static Boolean SeqEdDeleteFromDeltaBsp (BioseqPtr bsp, Int4 from, Int4 to)
 static Boolean SeqEdDeleteFromSegOrDeltaBsp (BioseqPtr bsp, Int4 from, Int4 to)
 {
   SeqLocPtr       tmp, head;
-  DeltaSeqPtr     tdsp;
+  DeltaSeqPtr     tdsp = NULL;
   SeqLocPtr PNTR  newheadptr;
   Int4            totlen, templen, tfrom, tto, diff1, diff2;
   SeqLocPtr       slp, tloc, newhead, prev;
@@ -6594,7 +6675,7 @@ static Boolean DoesIntervalContainUnknownGap (BioseqPtr bsp, Int4 from, Int4 to)
   
   return unknown_gap;
 }
-*
+*/
 
 /* This section of code deals with editing the sequence by inserting and removing characters.
  * Functions are needed to change the indices for the affected features so that they will
@@ -6960,7 +7041,7 @@ NLM_EXTERN SeqEdJournalPtr SeqEdJournalNewFeatEdit
 /* This section of code contains functions used by the new sequence editor for moving feature
  * intervals.
  */
-static Boolean SeqEdAdjustFeatureInterval
+NLM_EXTERN Boolean SeqEdAdjustFeatureInterval
 (SeqLocPtr slp, Int4 change, EMoveType move_type, Int4 interval_offset, BioseqPtr bsp)
 {
   SeqIntPtr sint;
diff --git a/api/edutil.h b/api/edutil.h
index f33e11c..381c76b 100644
--- a/api/edutil.h
+++ b/api/edutil.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 2/2/94
 *
-* $Revision: 6.21 $
+* $Revision: 6.23 $
 *
 * File Description:  Sequence editing utilities
 *
@@ -39,6 +39,16 @@
 * -------  ----------  -----------------------------------------------------
 *
 * $Log: edutil.h,v $
+* Revision 6.23  2010/07/12 12:21:49  bollin
+* Introduced a version of BioseqDelete that uses idx.deleteme to remove features
+* (instead of freeing them immediately), and fixed bugs in VecScreenTool when
+* entire Bioseqs are deleted.
+*
+* Revision 6.22  2010/06/11 12:03:22  bollin
+* Added iBOL compliance report, which marks items with low trace as failing.
+* Also checking in first draft of functions to reverse Quality Scores, not using
+* until we can verify that they work for float and int graphs.
+*
 * Revision 6.21  2009/03/04 16:34:15  bollin
 * Added function for removing contigs from scaffolds.
 *
@@ -211,6 +221,7 @@ extern "C" {
 *
 *****************************************************************************/
 NLM_EXTERN Boolean LIBCALL BioseqDelete (SeqIdPtr target, Int4 from, Int4 to, Boolean do_feat, Boolean do_split);
+NLM_EXTERN Boolean LIBCALL BioseqDeleteEx (SeqIdPtr target, Int4 from, Int4 to, Boolean do_feat, Boolean do_split, Boolean mark_deleted_feat);
 
 
 
@@ -381,6 +392,7 @@ NLM_EXTERN Boolean LIBCALL SeqInsertByLoc (SeqIdPtr target, Int4 offset, SeqLocP
 *
 *****************************************************************************/
 NLM_EXTERN Boolean LIBCALL SeqDeleteByLoc (SeqLocPtr slp, Boolean do_feat, Boolean do_split);
+NLM_EXTERN Boolean LIBCALL SeqDeleteByLocEx (SeqLocPtr slp, Boolean do_feat, Boolean do_split, Boolean mark_deleted_feat);
 
 
 /*****************************************************************************
@@ -496,6 +508,7 @@ NLM_EXTERN Int4 LIBCALL ISADeltaSeqsToSeqLoc (SeqLocPtr slp);
 *   
 *****************************************************************************/
 NLM_EXTERN Boolean	LIBCALL SeqEntryDelFeat PROTO((SeqEntryPtr sep, SeqIdPtr sip, Int4 from, Int4 to, Boolean do_split));
+NLM_EXTERN Boolean	LIBCALL SeqEntryDelFeatEx PROTO((SeqEntryPtr sep, SeqIdPtr sip, Int4 from, Int4 to, Boolean do_split, Boolean mark_deleted_feat));
 
 /*****************************************************************************
 *
@@ -732,6 +745,10 @@ SeqEdGetNextFeature
 /* this enum describes the kind of motion for feature adjusts */
 typedef enum { eLeftEnd=1, eRightEnd, eSlide } EMoveType;
 
+/* this function moves just the location */
+NLM_EXTERN Boolean SeqEdAdjustFeatureInterval
+(SeqLocPtr slp, Int4 change, EMoveType move_type, Int4 interval_offset, BioseqPtr bsp);
+
 /* This function moves a feature location */
 NLM_EXTERN void SeqEdFeatureAdjust
 (SeqFeatPtr sfp,
diff --git a/api/findrepl.c b/api/findrepl.c
index 613de2a..a394d61 100644
--- a/api/findrepl.c
+++ b/api/findrepl.c
@@ -1288,6 +1288,8 @@ static void FindReplFeats (
   RnaRefPtr      rrp;
   Uint1          subtype;
   tRNAPtr        trp;
+  RNAGenPtr      rgp;
+  RNAQualPtr     rq;
 
   if (sfp == NULL) return;
 
@@ -1370,6 +1372,13 @@ static void FindReplFeats (
       } else if (rrp->ext.choice == 2) {
         trp = (tRNAPtr) rrp->ext.value.ptrvalue;
         VisitSeqIdsInSeqLoc (trp->anticodon, userdata, FindReplSeqId);
+      } else if (rrp->ext.choice == 3) {
+        rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+        FindReplString(&(rgp->_class), fsp);
+        FindReplString(&(rgp->product), fsp);
+        for (rq = rgp->quals; rq != NULL; rq = rq->next) {
+          FindReplString(&(rq->val), fsp);
+        }
       }
       break;
     case SEQFEAT_PUB :
@@ -1950,8 +1959,10 @@ NLM_EXTERN void StringActionInEntity (
         break;
       case OBJ_BIOSEQ :
         sep = (SeqEntryPtr) omdp->choice;
+        break;
       case OBJ_BIOSEQSET :
         sep = (SeqEntryPtr) omdp->choice;
+        break;
       default :
         break;
     }
@@ -2275,8 +2286,10 @@ NLM_EXTERN void FindStringsInEntity (
         break;
       case OBJ_BIOSEQ :
         sep = (SeqEntryPtr) omdp->choice;
+        break;
       case OBJ_BIOSEQSET :
         sep = (SeqEntryPtr) omdp->choice;
+        break;
       default :
         break;
     }
diff --git a/api/gather.c b/api/gather.c
index 064bb37..1100f51 100644
--- a/api/gather.c
+++ b/api/gather.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/7/94
 *
-* $Revision: 6.55 $
+* $Revision: 6.56 $
 *
 * File Description: 
 *
@@ -963,7 +963,7 @@ static Boolean NEAR GatherSeqIds(InternalGCCPtr gccp, SeqIdPtr sip,
 {
 	GatherContextPtr gcp;
 	GatherScopePtr gsp;
-	Boolean takeit;
+    Boolean takeit = FALSE;
 	Uint4 LocateItem = 0;
 	Pointer LocateData = NULL;
 	Uint1 thistype;
@@ -1396,7 +1396,7 @@ static Boolean NEAR GatherSeqFeat(InternalGCCPtr gccp, SeqFeatPtr sfp,
 	Boolean takeit=TRUE,
 		takecit, checkseq=FALSE;
 	SeqLocPtr slp, head, tslp, target[2];
-	GatherRangePtr rdp, trdp, lrdp;
+    GatherRangePtr rdp = NULL, trdp, lrdp;
 	Int4 offset, totlen, left_end;
 	Boolean rev, revs[2];
 	Int2 ctr, max_interval, i, numcheck, j;
@@ -1594,10 +1594,12 @@ static Boolean NEAR GatherSeqFeat(InternalGCCPtr gccp, SeqFeatPtr sfp,
 					for (i = 0; i < gccp->segcnt; i++)
 					{
 						totlen = left_end + gccp->seglens[i];
+                        if (rdp != NULL) {
 						if ((rdp->left >= left_end) && (rdp->left < totlen))
 							gccp->found_annot[i] = TRUE;
 						else if ((rdp->right >= left_end) && (rdp->right < totlen))
 							gccp->found_annot[i] = TRUE;
+                        }
 						left_end = totlen;
 					}	
 				}
@@ -1962,7 +1964,7 @@ static void load_trunc_info(SeqLocPtr slp, GatherRangePtr grp)
 	
 	grp->l_trunc = f_trunc;
 	grp->r_trunc = t_trunc;
-	if(grp->strand != sint->strand)
+    if(sint != NULL && grp->strand != sint->strand)
 	{
 		if(grp->strand == Seq_strand_minus || sint->strand == Seq_strand_minus)
 		{
@@ -2186,13 +2188,13 @@ NLM_EXTERN AlignDataPtr gather_align_data(SeqLocPtr m_slp, SeqAlignPtr align,
     DenseSegPtr dsp;
     StdSegPtr ssp;
     DenseDiagPtr ddp;
-    Int2 i, m_order, k, numseg, t_numseg;
+    Int2 i, m_order = 0, k, numseg, t_numseg;
     Int4 s1;
     Uint1 seg_type;
     Boolean is_found = FALSE;
     Int4 start, stop, c_start, c_stop;
     Int4 m_start, m_stop;
-    Int4 master_pos;	/*position of the master sequence*/
+    Int4 master_pos = 0;    /*position of the master sequence*/
     Int4 off_start, off_stop;
     Boolean rev;
     GatherRange gr, t_range;
@@ -2210,7 +2212,7 @@ NLM_EXTERN AlignDataPtr gather_align_data(SeqLocPtr m_slp, SeqAlignPtr align,
     Int4 len;
     Int4 mag_val;	/*the magnification value */
     SeqLocPtr master_loc, m_loc;
-    Boolean inverse;
+    Boolean inverse = FALSE;
     Int4 leftover;
     Int4 left, right;
     Boolean use_stop;
@@ -3015,8 +3017,8 @@ static Boolean NEAR GatherBioseqFunc (InternalGCCPtr gccp, BioseqPtr bsp,
 	Uint1 thistype, segtype;
 	Int2 j, numcheck;
 	Boolean match_target = TRUE, do_seg, is_delta;
-	DeltaSeqPtr dsp;
-	Pointer dataptr;  /* used for OBJ_BIOSEQ_SEG and OBJ_BIOSEQ_DELTA */
+    DeltaSeqPtr dsp = NULL;
+    Pointer dataptr = NULL;  /* used for OBJ_BIOSEQ_SEG and OBJ_BIOSEQ_DELTA */
 
 	if (bsp == NULL)
 		return TRUE;
@@ -3226,7 +3228,9 @@ static Boolean NEAR GatherBioseqFunc (InternalGCCPtr gccp, BioseqPtr bsp,
 			{
 				if ((is_delta) && (segctr))  /* not first one */
 				{
+                    if (dsp != NULL) {
 					dsp = dsp->next;         /* move up dsp */
+                    }
 					if (dsp == NULL)
 						ErrPostEx(SEV_FATAL,0,0,"GatherDeltaSeq: dsp is NULL");
 				}
@@ -3975,7 +3979,7 @@ static Boolean NEAR IGCCBuild (InternalGCCPtr ip, ObjMgrDataPtr omdp, Pointer us
 			oldsep = SeqEntryGetScope();  /* save any current scope */
 			if (omdp->choicetype == OBJ_SEQENTRY) {
 				SeqEntrySetScope(omdp->choice);
-			} else {
+            } else if (scope != NULL) {
 				SeqEntrySetScope(scope->scope);
 			}
 			bsp = BioseqFindCore(sip);
@@ -5416,7 +5420,7 @@ static Boolean NEAR GenericGatherDataForProc (OMProcControlPtr ompcp, Boolean se
 		"AttachDataForProc",
 		"CopyDataForProc",
 		"ReplaceDataForProc" };
-	GatherItemProc gip;
+    GatherItemProc gip = NULL;
 	GDS gds;
 	ObjMgrPtr omp;
 
diff --git a/api/gbftdef.h b/api/gbftdef.h
index 069a018..c91d0d3 100644
--- a/api/gbftdef.h
+++ b/api/gbftdef.h
@@ -117,8 +117,12 @@
 #define GBQUAL_satellite        107
 #define GBQUAL_gene_synonym     108
 #define GBQUAL_UniProtKB_evidence 109
+#define GBQUAL_haplogroup           110
+#define GBQUAL_artificial_location  111
+#define GBQUAL_non_functional       112
+#define GBQUAL_pseudogene           113
 
-#define ParFlat_TOTAL_GBQUAL    110
+#define ParFlat_TOTAL_GBQUAL    114
 #define ParFlat_TOTAL_IntOr       3
 #define ParFlat_TOTAL_LRB         3
 #define ParFlat_TOTAL_Exp         2
diff --git a/api/gbftglob.c b/api/gbftglob.c
index 0bede37..e7863a5 100644
--- a/api/gbftglob.c
+++ b/api/gbftglob.c
@@ -64,7 +64,9 @@ static GbFeatName STATIC__ParFlat_GBQual_names[ParFlat_TOTAL_GBQUAL] = {
  {"bio_material", Class_text}, { "ncRNA_class", Class_text},
  {"tag_peptide", Class_text}, { "mating_type", Class_text},
  {"satellite", Class_text}, { "gene_synonym", Class_text},
- { "UniProtKB_evidence", Class_text}
+ {"UniProtKB_evidence", Class_text}, {"haplogroup", Class_text},
+ {"artificial_location", Class_none}, {"non_functional", Class_none},
+ {"pseudogene", Class_none}
 };
 
 NLM_EXTERN GbFeatNamePtr x_ParFlat_GBQual_names(void) {
@@ -133,7 +135,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"C_region", 0, {-1, -1, -1, -1, -1}, 18,
+   {"C_region", 0, {-1, -1, -1, -1, -1}, 20,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -146,18 +148,20 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1}},
+      -1, -1, -1, -1, -1}},
    {"CAAT_signal", 0, {-1, -1, -1, -1, -1}, 15,
      {
       GBQUAL_allele,
@@ -180,9 +184,10 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"CDS", 0, {-1, -1, -1, -1, -1}, 32,
+   {"CDS", 0, {-1, -1, -1, -1, -1}, 35,
      {
       GBQUAL_allele,
+      GBQUAL_artificial_location,
       GBQUAL_citation,
       GBQUAL_codon_start,
       GBQUAL_codon,
@@ -199,6 +204,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_number,
       GBQUAL_old_locus_tag,
@@ -207,6 +213,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_product,
       GBQUAL_protein_id,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_ribosomal_slippage,
       GBQUAL_standard_name,
       GBQUAL_trans_splicing,
@@ -216,8 +223,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1}},
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
    {"conflict",  1, {
       GBQUAL_citation, -1, -1, -1, -1}, 14,
      {
@@ -263,7 +269,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"D_segment", 0, {-1, -1, -1, -1, -1}, 18,
+   {"D_segment", 0, {-1, -1, -1, -1, -1}, 20,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -276,18 +282,20 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1}},
+      -1, -1, -1, -1, -1}},
    {"enhancer",  0, {-1, -1, -1, -1, -1}, 17,
      {
       GBQUAL_allele,
@@ -312,7 +320,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"exon", 0, {-1, -1, -1, -1, -1}, 21,
+   {"exon", 0, {-1, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -327,19 +335,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_number,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
+      -1, -1}},
    {"gap",  1, {
       GBQUAL_estimated_length, -1, -1, -1, -1}, 5,
      {
@@ -376,7 +386,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"gene", 0, {-1, -1, -1, -1, -1}, 21,
+   {"gene", 0, {-1, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -390,6 +400,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_operon,
@@ -397,13 +408,14 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_phenotype,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_trans_splicing,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
+      -1, -1}},
     {"iDNA", 0, {-1, -1, -1, -1, -1}, 18,
      {
       GBQUAL_allele,
@@ -429,7 +441,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1}},
-   {"intron", 0, {-1, -1, -1, -1, -1}, 20,
+   {"intron", 0, {-1, -1, -1, -1, -1}, 22,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -444,19 +456,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_number,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1}},
-   {"J_segment", 0, {-1, -1, -1, -1, -1}, 18,
+      -1, -1, -1}},
+   {"J_segment", 0, {-1, -1, -1, -1, -1}, 20,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -469,18 +483,20 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1}},
+      -1, -1, -1, -1, -1}},
    {"LTR", 0, {-1, -1, -1, -1, -1}, 16,
      {
       GBQUAL_allele,
@@ -504,7 +520,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"mat_peptide",  0, {-1, -1, -1, -1, -1}, 23,
+   {"mat_peptide",  0, {-1, -1, -1, -1, -1}, 25,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -522,18 +538,19 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1}},
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
    {"misc_binding",  1, {
       GBQUAL_bound_moiety, -1, -1, -1, -1}, 16,
      {
@@ -585,7 +602,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1}},
-   {"misc_feature",  0, {-1, -1, -1, -1, -1}, 21,
+   {"misc_feature",  0, {-1, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -599,6 +616,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_number,
       GBQUAL_old_locus_tag,
@@ -606,13 +624,14 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_phenotype,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
+      -1, -1}},
    {"misc_recomb", 0, {-1, -1, -1, -1, -1}, 16,
      {
       GBQUAL_allele,
@@ -636,7 +655,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"misc_RNA",  0, {-1, -1, -1, -1, -1}, 21,
+   {"misc_RNA",  0, {-1, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -650,12 +669,14 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_operon,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_trans_splicing,
       GBQUAL_usedin,
@@ -663,7 +684,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
+      -1, -1}},
    {"misc_signal",  0, {-1, -1, -1, -1, -1}, 19,
      {
       GBQUAL_allele,
@@ -737,9 +758,10 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"mRNA",  0, {-1, -1, -1, -1, -1}, 22,
+   {"mRNA",  0, {-1, -1, -1, -1, -1}, 25,
      {
       GBQUAL_allele,
+      GBQUAL_artificial_location,
       GBQUAL_citation,
       GBQUAL_db_xref,
       GBQUAL_evidence,
@@ -751,12 +773,14 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_operon,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_trans_splicing,
       GBQUAL_transcript_id,
@@ -764,8 +788,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1}},
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
    {"mutation",  0, {-1, -1, -1, -1, -1}, 18,
      {
       GBQUAL_citation,
@@ -791,7 +814,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1}},
-   {"N_region",  0, {-1, -1, -1, -1, -1}, 16,
+   {"N_region",  0, {-1, -1, -1, -1, -1}, 18,
      {
       GBQUAL_citation,
       GBQUAL_db_xref,
@@ -803,19 +826,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1, -1, -1}},
+      -1, -1, -1, -1, -1, -1, -1}},
    {"ncRNA",  1, {
-      GBQUAL_ncRNA_class, -1, -1, -1, -1}, 21,
+      GBQUAL_ncRNA_class, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -829,12 +854,14 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_operon,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_trans_splicing,
       GBQUAL_usedin,
@@ -842,7 +869,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
+      -1, -1}},
    {"old_sequence",   1, {
       GBQUAL_citation, -1, -1, -1, -1}, 15,
      {
@@ -867,7 +894,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
    {"operon", 1, {
-      GBQUAL_operon, -1, -1, -1, -1}, 14,
+      GBQUAL_operon, -1, -1, -1, -1}, 16,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -878,17 +905,18 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_inference,
       GBQUAL_label,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_partial,
       GBQUAL_phenotype,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1}},
+      -1, -1, -1, -1, -1, -1, -1, -1, -1}},
    {"oriT", 0, {-1, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
@@ -1039,7 +1067,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"promoter",  0, {-1, -1, -1, -1, -1}, 21,
+   {"promoter",  0, {-1, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
       GBQUAL_bound_moiety,
@@ -1054,19 +1082,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_operon,
       GBQUAL_partial,
       GBQUAL_phenotype,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
+      -1, -1}},
    {"protein_bind",  1, {
       GBQUAL_bound_moiety, -1, -1, -1, -1}, 18,
      {
@@ -1200,7 +1230,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"rRNA",  0, {-1, -1, -1, -1, -1}, 20,
+   {"rRNA",  0, {-1, -1, -1, -1, -1}, 22,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1214,20 +1244,22 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_operon,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1}},
-   {"S_region",  0, {-1, -1, -1, -1, -1}, 18,
+      -1, -1, -1}},
+   {"S_region",  0, {-1, -1, -1, -1, -1}, 20,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1240,18 +1272,20 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1}},
+      -1, -1, -1, -1, -1}},
    {"satellite",  0, {-1, -1, -1, -1, -1}, 21,
      {
       GBQUAL_allele,
@@ -1280,7 +1314,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1}},
-   {"scRNA",  0, {-1, -1, -1, -1, -1}, 19,
+   {"scRNA",  0, {-1, -1, -1, -1, -1}, 21,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1294,19 +1328,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1}},
-   {"sig_peptide", 0, {-1, -1, -1, -1, -1}, 19,
+      -1, -1, -1, -1}},
+   {"sig_peptide", 0, {-1, -1, -1, -1, -1}, 21,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1320,19 +1356,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1}},
-   {"snoRNA",  0, {-1, -1, -1, -1, -1}, 19,
+      -1, -1, -1, -1}},
+   {"snoRNA",  0, {-1, -1, -1, -1, -1}, 21,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1346,19 +1384,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1}},
-   {"snRNA",  0, {-1, -1, -1, -1, -1}, 19,
+      -1, -1, -1, -1}},
+   {"snRNA",  0, {-1, -1, -1, -1, -1}, 21,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1372,20 +1412,22 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1}},
+      -1, -1, -1, -1}},
    {"source", 1, {
-      GBQUAL_organism, -1, -1, -1, -1}, 62,
+      GBQUAL_organism, -1, -1, -1, -1}, 63,
      {
       GBQUAL_bio_material,
       GBQUAL_cell_line,
@@ -1449,7 +1491,8 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_usedin,
       GBQUAL_variety,
       GBQUAL_virion,
-      -1, -1, -1}},
+      GBQUAL_haplogroup,
+      -1, -1}},
    {"stem_loop",  0, {-1, -1, -1, -1, -1}, 18,
      {
       GBQUAL_allele,
@@ -1544,7 +1587,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"tmRNA",  0, {-1, -1, -1, -1, -1}, 21,
+   {"tmRNA",  0, {-1, -1, -1, -1, -1}, 23,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1558,12 +1601,14 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_operon,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_tag_peptide,
       GBQUAL_usedin,
@@ -1571,8 +1616,8 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
-   {"transit_peptide",  0, {-1, -1, -1, -1, -1}, 19,
+      -1, -1}},
+   {"transit_peptide",  0, {-1, -1, -1, -1, -1}, 21,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1586,19 +1631,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1}},
-   {"tRNA",  0, {-1, -1, -1, -1, -1}, 21,
+      -1, -1, -1, -1}},
+   {"tRNA",  0, {-1, -1, -1, -1, -1}, 24,
      {
       GBQUAL_allele,
       GBQUAL_anticodon,
@@ -1613,11 +1660,14 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
+      GBQUAL_operon,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_trans_splicing,
       GBQUAL_usedin,
@@ -1625,7 +1675,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1}},
+      -1}},
    {"unsure",  0, {-1, -1, -1, -1, -1}, 15,
      {
       GBQUAL_allele,
@@ -1648,7 +1698,7 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
-   {"V_region",  0, {-1, -1, -1, -1, -1}, 18,
+   {"V_region",  0, {-1, -1, -1, -1, -1}, 20,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1661,19 +1711,21 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1}},
-   {"V_segment",  0, {-1, -1, -1, -1, -1}, 18,
+      -1, -1, -1, -1, -1}},
+   {"V_segment",  0, {-1, -1, -1, -1, -1}, 20,
      {
       GBQUAL_allele,
       GBQUAL_citation,
@@ -1686,18 +1738,20 @@ static SematicFeat STATIC__ParFlat_GBFeat[ParFlat_TOTAL_GBFEAT] = {
       GBQUAL_label,
       GBQUAL_locus_tag,
       GBQUAL_map,
+      GBQUAL_non_functional,
       GBQUAL_note,
       GBQUAL_old_locus_tag,
       GBQUAL_partial,
       GBQUAL_product,
       GBQUAL_pseudo,
+      GBQUAL_pseudogene,
       GBQUAL_standard_name,
       GBQUAL_usedin,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-      -1, -1, -1, -1, -1, -1, -1}},
+      -1, -1, -1, -1, -1}},
    {"variation",  0, {-1, -1, -1, -1, -1}, 21,
      {
       GBQUAL_allele,
diff --git a/api/gbparint.c b/api/gbparint.c
index a84be5c..a54694d 100644
--- a/api/gbparint.c
+++ b/api/gbparint.c
@@ -28,6 +28,9 @@
 * Author:  Karl Sirotkin
 *
 * $Log: gbparint.c,v $
+* Revision 6.9  2009/10/02 19:46:00  kans
+* address clang static analyzer warnings
+*
 * Revision 6.8  2004/07/22 16:08:35  bazhin
 * Changes to parse gaps of unknown lengths (like "gap(unk100)")
 * within location strings.
@@ -1883,7 +1886,7 @@ static int Nlm_gbparse_accprefix(CharPtr acc)
 char Saved_ch;
 
 #define Nlm_lex_error_MACRO(msg)\
-		if (*current_col){\
+        if (current_col != NULL && *current_col){\
 		Saved_ch = *(current_col +1);\
 		*(current_col +1) = '\0';\
 		}else{\
diff --git a/api/macroapi.c b/api/macroapi.c
index a1b92bf..ecae023 100755
--- a/api/macroapi.c
+++ b/api/macroapi.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11/8/2007
 *
-* $Revision: 1.202 $
+* $Revision: 1.262 $
 *
 * File Description: 
 *
@@ -59,11 +59,53 @@
 #include <objmacro.h>
 #include <macroapi.h>
 #include <seqport.h>
+#include <parsegb.h>
+#include <salutil.h>
+
+static Boolean IsAllDigits (CharPtr str)
+{
+  CharPtr cp;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  cp = str;
+  while (*cp != 0 && isdigit (*cp)) {
+    cp++;
+  }
+  if (*cp == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static Boolean IsAllCaps (CharPtr str)
+{
+  CharPtr cp;
+  Boolean at_least_one = FALSE;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  cp = str;
+  while (*cp != 0) {
+    if (isalpha (*cp)) {
+      if (islower (*cp)) {
+        return FALSE;
+      } else {
+        at_least_one = TRUE;
+      }
+    }
+    cp++;
+  }
+  return at_least_one;
+}
 
 
 static Boolean DoesFeatureMatchRnaType (SeqFeatPtr sfp, RnaFeatTypePtr rt);
 static Int4 CompareRnaTypes (RnaFeatTypePtr rt1, RnaFeatTypePtr rt2);
 static int LIBCALLBACK SortVnpByChoiceAndIntvalue (VoidPtr ptr1, VoidPtr ptr2);
+static int LIBCALLBACK SortVnpByChoiceAndPtrvalue (VoidPtr ptr1, VoidPtr ptr2);
 
 /* NOTES */
 /* When adding a new field type, add implementation to the following functions:
@@ -369,7 +411,6 @@ NLM_EXTERN FieldPairTypePtr BuildFieldPairFromFromField (FieldTypePtr field_from
   SourceQualPairPtr sqpp;
   FeatureFieldPairPtr fp;
   FeatureFieldPtr fs;
-  FieldTypePtr f = NULL;
   RnaQualPairPtr   rqp;
   RnaQualPtr       rq;
   CDSGeneProtFieldPairPtr cp;
@@ -1032,10 +1073,10 @@ static FeatTypeFeatDefData feattype_featdef[] = {
  { Feature_type_v_segment , FEATDEF_V_segment , "v_segment" } , 
  { Feature_type_variation , FEATDEF_variation , "variation" } , 
  { Feature_type_virion , FEATDEF_virion , "virion" } , 
- { Feature_type_n3clip , FEATDEF_3clip , "3clip" } , 
- { Feature_type_n3UTR , FEATDEF_3UTR , "3UTR" } , 
- { Feature_type_n5clip , FEATDEF_5clip , "5clip" } , 
- { Feature_type_n5UTR , FEATDEF_5UTR , "5UTR" } , 
+ { Feature_type_n3clip , FEATDEF_3clip , "3'clip" } , 
+ { Feature_type_n3UTR , FEATDEF_3UTR , "3'UTR" } , 
+ { Feature_type_n5clip , FEATDEF_5clip , "5'clip" } , 
+ { Feature_type_n5UTR , FEATDEF_5UTR , "5'UTR" } , 
  { Feature_type_n10_signal , FEATDEF_10_signal , "10_signal" } , 
  { Feature_type_n35_signal , FEATDEF_35_signal , "35_signal" } , 
  { Feature_type_site_ref , FEATDEF_site_ref , "site_ref" } , 
@@ -1290,6 +1331,7 @@ static FeatQualGBQualData featqual_gbqual[] = {
  { Feat_qual_legal_gene , GBQUAL_gene , 0, "locus" } , 
  { Feat_qual_legal_inference , GBQUAL_inference , 0, "inference" } , 
  { Feat_qual_legal_label , GBQUAL_label , 0, "label" } , 
+ { Feat_qual_legal_location , 255 , 0, "location" } , 
  { Feat_qual_legal_locus_tag , GBQUAL_locus_tag , 0, "locus-tag" } , 
  { Feat_qual_legal_map , GBQUAL_map , 0, "map" } , 
  { Feat_qual_legal_mobile_element , GBQUAL_mobile_element , 0, "mobile-element" } , 
@@ -1323,6 +1365,7 @@ static FeatQualGBQualData featqual_gbqual[] = {
  { Feat_qual_legal_segment , GBQUAL_segment , 0, "segment" } , 
  { Feat_qual_legal_sequenced_mol , GBQUAL_sequenced_mol , 0, "sequenced-mol" } , 
  { Feat_qual_legal_standard_name , GBQUAL_standard_name , 0, "standard-name" } , 
+ { Feat_qual_legal_tag_peptide , GBQUAL_tag_peptide , 0, "tag-peptide" } ,
  { Feat_qual_legal_transcript_id , GBQUAL_transcript_id , 0, "transcript-id" } , 
  { Feat_qual_legal_transgenic , GBQUAL_transgenic , 0, "transgenic" } , 
  { Feat_qual_legal_translation , GBQUAL_translation , 0, "translation" } , 
@@ -1447,9 +1490,9 @@ static RnaTypeMapData rnatypemap[] = {
  { RnaFeatType_mRNA , RNA_TYPE_mRNA, Feature_type_mRNA, "mRNA" } ,
  { RnaFeatType_tRNA , RNA_TYPE_tRNA, Feature_type_tRNA, "tRNA" } ,
  { RnaFeatType_rRNA , RNA_TYPE_rRNA, Feature_type_rRNA, "rRNA" } ,
- { RnaFeatType_ncRNA , 255 , Feature_type_ncRNA, "ncRNA" } ,
- { RnaFeatType_tmRNA , 255 , Feature_type_tmRNA, "tmRNA" } ,
- { RnaFeatType_miscRNA , 255 , Feature_type_misc_RNA, "misc_RNA" }
+ { RnaFeatType_ncRNA , RNA_TYPE_ncRNA , Feature_type_ncRNA, "ncRNA" } ,
+ { RnaFeatType_tmRNA , RNA_TYPE_tmRNA , Feature_type_tmRNA, "tmRNA" } ,
+ { RnaFeatType_miscRNA , RNA_TYPE_misc_RNA , Feature_type_misc_RNA, "misc_RNA" }
 };
 
 #define NUM_rnatypemap sizeof (rnatypemap) / sizeof (RnaTypeMapData)
@@ -1523,7 +1566,7 @@ static Boolean DoesFeatureMatchRnaType (SeqFeatPtr sfp, RnaFeatTypePtr rt)
 {
   Boolean rval = FALSE;
   RnaRefPtr rrp;
-  GBQualPtr gbq;
+  RNAGenPtr rgp;
   Int4 rnaval;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) {
@@ -1537,33 +1580,17 @@ static Boolean DoesFeatureMatchRnaType (SeqFeatPtr sfp, RnaFeatTypePtr rt)
   if (rnaval == rrp->type) {
     switch (rt->choice) {
       case RnaFeatType_ncRNA:
-        if (rrp->ext.choice == 1
-            && StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0) {
           if (rt->data.ptrvalue == NULL) {
             rval = TRUE;
-          } else {
-            gbq = sfp->qual;
-            while (gbq != NULL && StringCmp (gbq->qual, "ncRNA_class") != 0) {
-              gbq = gbq->next;
-            }
-            if (gbq != NULL && StringCmp (gbq->val, rt->data.ptrvalue) == 0) {
+        } else if ((rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL && StringCmp (rgp->_class, rt->data.ptrvalue)) {
               rval = TRUE;
             }
-          }
-        }
         break;
       case RnaFeatType_tmRNA:
-        if (rrp->ext.choice == 1
-            && StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0) {
           rval = TRUE;
-        }
         break;
       case RnaFeatType_miscRNA:
-        if (rrp->ext.choice == 1
-            && StringCmp (rrp->ext.value.ptrvalue, "ncRNA") != 0
-            && StringCmp (rrp->ext.value.ptrvalue, "tmRNA") != 0) {
           rval = TRUE;
-        }
         break;
       default:
         rval = TRUE;
@@ -1589,7 +1616,11 @@ static Int4 CompareRnaTypes (RnaFeatTypePtr rt1, RnaFeatTypePtr rt2)
   } else if (rt1->choice > rt2->choice) {
     rval = 1;
   } else if (rt1->choice == RnaFeatType_ncRNA) {
+    if (rt2->data.ptrvalue == NULL) {
+      rval = 0;
+    } else {
     rval = StringCmp (rt1->data.ptrvalue, rt2->data.ptrvalue);
+    }
   } else {
     rval = 0;
   }
@@ -1601,7 +1632,7 @@ static RnaFeatTypePtr RnaFeatTypeFromSeqFeat (SeqFeatPtr sfp)
 {
   RnaRefPtr rrp;
   RnaFeatTypePtr rt = NULL;
-  GBQualPtr gbqual;
+  RNAGenPtr rgp;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || sfp->data.value.ptrvalue == NULL) {
     return NULL;
@@ -1625,26 +1656,24 @@ static RnaFeatTypePtr RnaFeatTypeFromSeqFeat (SeqFeatPtr sfp)
       rt = ValNodeNew (NULL);
       rt->choice = RnaFeatType_rRNA;
       break;
-    case 255:
-      if (rrp->ext.choice == 1) {
-        if (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0) {
+    case RNA_TYPE_ncRNA:
           rt = ValNodeNew (NULL);
           rt->choice = RnaFeatType_ncRNA;
-          gbqual = sfp->qual;
-          while (gbqual != NULL && StringCmp (gbqual->qual, "ncRNA_class") != 0) {
-            gbqual = gbqual->next;
+      if (rrp->ext.choice == 3) {
+        rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+        if (rgp != NULL && !StringHasNoText (rgp->_class)) {
+          rt->data.ptrvalue = StringSave (rgp->_class);
           }
-          if (gbqual != NULL) {
-            rt->data.ptrvalue = StringSave (gbqual->val);
           }
-        } else if (StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0) {
+      break;
+    case RNA_TYPE_tmRNA:
           rt = ValNodeNew (NULL);
           rt->choice = RnaFeatType_tmRNA;
-        } else {
+      break;
+    case RNA_TYPE_misc_RNA:
+    case 255:
           rt = ValNodeNew (NULL);
           rt->choice = RnaFeatType_miscRNA;
-        }
-      }
       break;
   }
   return rt;
@@ -1662,6 +1691,7 @@ static RnaFieldNameData rnafieldnames[] = {
  { Rna_field_comment , Feat_qual_legal_note, "comment" } ,
  { Rna_field_codons_recognized , Feat_qual_legal_codons_recognized, "codons recognized" } ,
  { Rna_field_ncrna_class , Feat_qual_legal_ncRNA_class, "ncRNA class" } ,
+ { Rna_field_tag_peptide , Feat_qual_legal_tag_peptide, "tag-peptide" } ,
  { Rna_field_anticodon , Feat_qual_legal_anticodon, "anticodon" } ,
  { Rna_field_transcript_id , Feat_qual_legal_transcript_id, "transcript ID" } ,
  { Rna_field_gene_locus , Feat_qual_legal_gene, "gene locus" } ,
@@ -1909,6 +1939,7 @@ static SrcQualSCQualData srcqual_scqual[] = {
  { Source_qual_culture_collection_INST , ORGMOD_culture_collection , IS_ORGMOD , 1 , "culture-collection-inst" } , 
  { Source_qual_culture_collection_COLL , ORGMOD_culture_collection , IS_ORGMOD , 2 , "culture-collection-coll" } , 
  { Source_qual_culture_collection_SpecID , ORGMOD_culture_collection , IS_ORGMOD , 3 , "culture-collection-specid" } , 
+ { Source_qual_dbxref , 0 , IS_OTHER , 0 , "dbxref" } , 
  { Source_qual_dev_stage , SUBSRC_dev_stage , IS_SUBSRC , 0 , "dev-stage" } , 
  { Source_qual_division , 0 , IS_OTHER, 0 , "division" } ,
  { Source_qual_dosage , ORGMOD_dosage , IS_ORGMOD , 0 , "dosage" } , 
@@ -2012,7 +2043,7 @@ static Int4 GetSubSrcQualFromSrcQual (Int4 srcqual, Int4Ptr subfield)
 }
 
 
-static Int4 GetOrgModQualFromSrcQual (Int4 srcqual, Int4Ptr subfield) 
+NLM_EXTERN Int4 GetOrgModQualFromSrcQual (Int4 srcqual, Int4Ptr subfield) 
 {
   Int4 i;
 
@@ -2109,6 +2140,13 @@ NLM_EXTERN Int4 GetSourceQualTypeByName (CharPtr qualname)
       return srcqual_scqual[i].srcqual;
     }
   }
+  if (StringICmp (qualname, "subsp.") == 0) {
+    return Source_qual_sub_species;
+  } else if (StringICmp (qualname, "var.") == 0) {
+    return Source_qual_variety;
+  } else if (StringICmp (qualname, "str.") == 0) {
+    return Source_qual_strain;
+  }
   return -1;
 }
 
@@ -2222,6 +2260,66 @@ NLM_EXTERN Boolean AllowSourceQualMulti (SourceQualChoicePtr s)
 }
 
 
+static Boolean IsNotForParsing (Int4 srcqual)
+{
+ if (srcqual == Source_qual_all_notes
+     || srcqual == Source_qual_all_quals
+     || srcqual == Source_qual_common
+     || srcqual == Source_qual_acronym
+     || srcqual == Source_qual_dosage
+     || srcqual == Source_qual_nat_host
+     || srcqual == Source_qual_specimen_voucher
+     || srcqual == Source_qual_authority
+     || srcqual == Source_qual_synonym
+     || srcqual == Source_qual_anamorph
+     || srcqual == Source_qual_teleomorph
+     || srcqual == Source_qual_gb_acronym
+     || srcqual == Source_qual_gb_anamorph
+     || srcqual == Source_qual_gb_synonym
+     || srcqual == Source_qual_culture_collection
+     || srcqual == Source_qual_bio_material
+     || srcqual == Source_qual_metagenome_source 
+     || srcqual == Source_qual_old_lineage 
+     || srcqual == Source_qual_old_name) {
+    return TRUE;
+  } else {
+    return FALSE;
+ }
+}
+
+
+NLM_EXTERN TextFsaPtr GetOrgModSearch (void)
+{
+#if 0
+  Int4  i;
+#endif
+  TextFsaPtr tags;
+  
+  tags = TextFsaNew();
+
+#if 0
+  for (i = 0; i < NUM_srcqual_scqual; i++) {
+    if (!IsNotForParsing(srcqual_scqual[i].srcqual)
+        && (srcqual_scqual[i].typeflag & IS_ORGMOD)) {
+      TextFsaAdd (tags, srcqual_scqual[i].qualname);
+    }
+  }
+#else
+  TextFsaAdd (tags, "pathovar");
+  TextFsaAdd (tags, "serovar");
+  TextFsaAdd (tags, "strain");
+  TextFsaAdd (tags, "sub-species");
+  TextFsaAdd (tags, "variety");
+#endif
+
+  TextFsaAdd (tags, "subsp.");
+  TextFsaAdd (tags, "var.");
+  TextFsaAdd (tags, "str.");
+
+  return tags;
+}
+
+
 typedef struct srclocgenome {
   Int4 srcloc;
   Int4 genome;
@@ -4271,6 +4369,14 @@ NLM_EXTERN Boolean IsLocationConstraintEmpty (LocationConstraintPtr lcp)
   {
     rval = FALSE;
   }
+  else if (lcp->location_type != Location_type_constraint_any)
+  {
+    rval = FALSE;
+  }
+  else if (lcp->end5 != NULL || lcp->end3 != NULL)
+  {
+    rval = FALSE;
+  }
   return rval;
 }
 
@@ -4400,6 +4506,206 @@ static Boolean DoesLocationMatchPartialnessConstraint (SeqLocPtr slp, LocationCo
 }
 
 
+static Boolean DoesLocationMatchTypeConstraint (SeqLocPtr slp, LocationConstraintPtr lcp)
+{
+  Boolean rval = FALSE, has_null = FALSE;
+  Int4    num_intervals = 0;
+  SeqLocPtr slp_tmp = NULL;
+
+  if (slp == NULL) 
+  {
+    rval = FALSE;
+  }
+  else if (lcp->location_type == Location_type_constraint_any) 
+  {
+    rval = TRUE;
+  }
+  else 
+  {
+    while ((slp_tmp = SeqLocFindNext (slp, slp_tmp)) != NULL) {
+      if (slp_tmp->choice == SEQLOC_NULL) 
+      {
+        has_null = TRUE;
+      } 
+      else if (slp->choice != SEQLOC_EMPTY)
+      {
+        num_intervals++;
+      }
+    }
+    if (lcp->location_type == Location_type_constraint_single_interval)
+    {
+      if (num_intervals == 1) 
+      {
+        rval = TRUE;
+      }
+    }
+    else if (lcp->location_type == Location_type_constraint_joined)
+    {
+      if (num_intervals > 1 && !has_null)
+      {
+        rval = TRUE;
+      }
+    } 
+    else if (lcp->location_type == Location_type_constraint_ordered)
+    {
+      if (num_intervals > 1 && has_null)
+      {
+        rval = TRUE;
+      }
+    } 
+  }
+
+  return rval;
+}
+
+
+static Boolean DoesLocationMatchDistanceConstraint (SeqLocPtr slp, LocationConstraintPtr lcp)
+{
+  Boolean   rval = TRUE;
+  Uint1     strand;
+  BioseqPtr bsp = NULL;
+  Int4      pos;
+
+  if (slp == NULL)
+  {
+    return FALSE;
+  } 
+  else if (lcp->end5 == NULL && lcp->end3 == NULL) 
+  {
+    return TRUE;
+  }
+
+  strand = SeqLocStrand (slp);
+  if (strand == Seq_strand_minus) 
+  {
+    if (lcp->end5 != NULL)
+    {
+      bsp = BioseqFindFromSeqLoc (slp);
+      if (bsp == NULL) 
+      {
+        rval = FALSE;
+      }
+      else 
+      {
+        pos = SeqLocStop (slp);
+
+        switch (lcp->end5->choice)
+        {
+          case LocationPosConstraint_dist_from_end:
+            if (bsp->length - pos - 1 != lcp->end5->data.intvalue) 
+            {
+              rval = FALSE;
+            }
+            break;
+          case LocationPosConstraint_max_dist_from_end:
+            if (bsp->length - pos - 1 > lcp->end5->data.intvalue) 
+            {
+              rval = FALSE;
+            }
+            break;
+          case LocationPosConstraint_min_dist_from_end:
+            if (bsp->length - pos - 1 < lcp->end5->data.intvalue) 
+            {
+              rval = FALSE;
+            }
+            break;
+        }
+      }
+    }
+    if (lcp->end3 != NULL && rval) 
+    {
+      pos = SeqLocStart (slp);
+
+      switch (lcp->end3->choice)
+      {
+        case LocationPosConstraint_dist_from_end:
+          if (pos != lcp->end3->data.intvalue) 
+          {
+            rval = FALSE;
+          }
+          break;
+        case LocationPosConstraint_max_dist_from_end:
+          if (pos > lcp->end3->data.intvalue) 
+          {
+            rval = FALSE;
+          }
+          break;
+        case LocationPosConstraint_min_dist_from_end:
+          if (pos < lcp->end3->data.intvalue) 
+          {
+            rval = FALSE;
+          }
+          break;
+      }
+    }
+  }
+  else
+  {
+    if (lcp->end5 != NULL) 
+    {
+      pos = SeqLocStart (slp);
+
+      switch (lcp->end5->choice)
+      {
+        case LocationPosConstraint_dist_from_end:
+          if (pos != lcp->end5->data.intvalue) 
+          {
+            rval = FALSE;
+          }
+          break;
+        case LocationPosConstraint_max_dist_from_end:
+          if (pos > lcp->end5->data.intvalue) 
+          {
+            rval = FALSE;
+          }
+          break;
+        case LocationPosConstraint_min_dist_from_end:
+          if (pos < lcp->end5->data.intvalue) 
+          {
+            rval = FALSE;
+          }
+          break;
+      }
+    }
+    if (lcp->end3 != NULL && rval)
+    {
+      bsp = BioseqFindFromSeqLoc (slp);
+      if (bsp == NULL) 
+      {
+        rval = FALSE;
+      }
+      else 
+      {
+        pos = SeqLocStop (slp);
+
+        switch (lcp->end3->choice)
+        {
+          case LocationPosConstraint_dist_from_end:
+            if (bsp->length - pos - 1 != lcp->end3->data.intvalue) 
+            {
+              rval = FALSE;
+            }
+            break;
+          case LocationPosConstraint_max_dist_from_end:
+            if (bsp->length - pos - 1 > lcp->end3->data.intvalue) 
+            {
+              rval = FALSE;
+            }
+            break;
+          case LocationPosConstraint_min_dist_from_end:
+            if (bsp->length - pos - 1 < lcp->end3->data.intvalue) 
+            {
+              rval = FALSE;
+            }
+            break;
+        }
+      }
+    }
+  }
+  return rval;
+}
+
+
 static Boolean DoesLocationMatchConstraint (SeqLocPtr slp, LocationConstraintPtr lcp)
 
 {
@@ -4415,7 +4721,9 @@ static Boolean DoesLocationMatchConstraint (SeqLocPtr slp, LocationConstraintPtr
   }
   else if (DoesStrandMatchConstraint (slp, lcp)
            && DoesSequenceTypeMatchContraint (slp, lcp) 
-           && DoesLocationMatchPartialnessConstraint (slp, lcp))
+           && DoesLocationMatchPartialnessConstraint (slp, lcp)
+           && DoesLocationMatchTypeConstraint(slp, lcp)
+           && DoesLocationMatchDistanceConstraint(slp, lcp))
   {
     rval = TRUE;
   }
@@ -4461,6 +4769,14 @@ static Boolean DoesFeatureMatchLocationConstraint (SeqFeatPtr sfp, LocationConst
   if (!DoesLocationMatchPartialnessConstraint (sfp->location, constraint)) {
     rval = FALSE;
   }
+
+  if (!DoesLocationMatchTypeConstraint (sfp->location, constraint)) {
+    rval = FALSE;
+  }
+
+  if (!DoesLocationMatchDistanceConstraint(sfp->location, constraint)) {
+    rval = FALSE;
+  }
   return rval;
 }
 
@@ -4512,6 +4828,8 @@ static Boolean DoesObjectMatchLocationConstraint (Uint1 choice, Pointer data, Lo
           return FALSE;
         } else if (!DoesStrandMatchConstraint (sfp->location, constraint)) {
           return FALSE;
+        } else if (DoesLocationMatchTypeConstraint (sfp->location, constraint)) {
+          return FALSE;
         } else {
           return TRUE;
         }
@@ -4553,84 +4871,156 @@ static Boolean DoesObjectMatchLocationConstraint (Uint1 choice, Pointer data, Lo
 }
 
 
-/* for parsing and editing */
-NLM_EXTERN CharPtr GetTextPortionFromString (CharPtr str, TextPortionPtr text_portion)
+NLM_EXTERN Boolean IsTextMarkerEmpty (TextMarkerPtr marker)
 {
-  CharPtr portion = NULL;
-  CharPtr found_start, found_end;
-  Int4    found_len;
+  CharPtr cp;
+  Boolean rval = FALSE;
 
-  if (StringHasNoText (str)) {
-    return NULL;
+  if (marker == NULL) {
+    rval = TRUE;
+  } else if (marker->choice == TextMarker_free_text) {
+    cp = (CharPtr) marker->data.ptrvalue;
+    if (cp == NULL || *cp == 0) {
+      rval = TRUE;
   }
-  if (text_portion == NULL) {
-    return StringSave (str);
   }  
+  return rval;
+}
+
+
+NLM_EXTERN TextMarkerPtr MakeTextTextMarker (CharPtr text)
+{
+  TextMarkerPtr text_marker = ValNodeNew (NULL);
+
+  text_marker->choice = TextMarker_free_text;
+  text_marker->data.ptrvalue = StringSave (text);
+  return text_marker;
+}
+
+
   
-  if (text_portion->left_text == NULL || text_portion->left_text [0] == 0)
+static CharPtr FindTextMarker(CharPtr str, Int4Ptr len, TextMarkerPtr marker, Boolean case_sensitive, Boolean whole_word)
+{
+  CharPtr search;
+  CharPtr rval = NULL;
+  Int4    search_len = 0;
+  Int4    tmp;
+  CharPtr digits = "0123456789";
+  CharPtr letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+  if (marker == NULL) 
   {
-    found_start = str;
+    if (len != NULL) 
+    {
+      *len = StringLen (str);
   }
-  else
+    rval = str;
+  } 
+  else if (marker->choice == TextMarker_free_text) 
+  {
+    search = (CharPtr) marker->data.ptrvalue;
+    if (search == NULL || search[0] == 0) 
   {
-    if (text_portion->case_sensitive)
+      if (len != NULL) 
     {
-      found_start = StringSearch (str, text_portion->left_text);
+        *len = StringLen (str);
+      }
+      rval = str;
     }
     else
     {
-      found_start = StringISearch (str, text_portion->left_text);
-    }
-    
-    if (text_portion->whole_word && ! IsWholeWordMatch (str, found_start, StringLen (text_portion->left_text)))
+      if (case_sensitive)
     {
-      found_start = NULL;
-    }
+        rval = StringSearch (str, search);
   }
-  
-  if (found_start == NULL)
+      else
   {
-    return NULL;
+        rval = StringISearch (str, search);
   }
   
-  if (!text_portion->include_left)
+      if (rval != NULL) 
   {
-    found_start += StringLen (text_portion->left_text);
-  }
+        search_len = StringLen (search);
   
-  if (text_portion->right_text == NULL || text_portion->right_text [0] == 0)
+        if (whole_word && ! IsWholeWordMatch (str, rval, search_len))
   {
-    found_len = StringLen (found_start);
+          rval = NULL;
   }
   else
   {
-    if (text_portion->case_sensitive)
+          if (len != NULL) 
     {
-      found_end = StringSearch (found_start, text_portion->right_text);
+            *len = search_len;
     }
-    else
+        }
+      }
+    }
+  } 
+  else if (marker->choice == TextMarker_digits) 
+  {
+    tmp = StringCSpn(str, digits);
+    if (*(str + tmp) != 0) 
+    {
+      rval = str + tmp;
+      if (len != NULL) 
     {
-      found_end = StringISearch (found_start, text_portion->right_text);
+        *len = StringSpn (rval, digits);
     }
-    if (text_portion->whole_word && ! IsWholeWordMatch (str, found_end, StringLen (text_portion->right_text)))
+    }
+  } 
+  else if (marker->choice == TextMarker_letters) 
+  {
+    tmp = StringCSpn(str, letters);
+    if (*(str + tmp) != 0) 
+    {
+      rval = str + tmp;
+      if (len != NULL) 
     {
-      found_end = NULL;
+        *len = StringSpn (rval, letters);
     }    
+    }
+  }
+  return rval;
+}
     
-    if (found_end == NULL)
-    {
-      found_len = 0;
+
+/* for parsing and editing */
+NLM_EXTERN CharPtr GetTextPortionFromString (CharPtr str, TextPortionPtr text_portion)
+{
+  CharPtr portion = NULL;
+  CharPtr found_start, found_end;
+  Int4    left_len = 0, right_len = 0, found_len;
+
+  if (StringHasNoText (str)) {
+    return NULL;
+  }
+  if (text_portion == NULL) {
+    return StringSave (str);
     }
-    else if (text_portion->include_right)
+  
+  found_start = FindTextMarker(str, &left_len, text_portion->left_marker, text_portion->case_sensitive, text_portion->whole_word);
+  
+  if (found_start == NULL)
     {
-      found_len = (Int4)(found_end - found_start) + StringLen (text_portion->right_text);
+    return NULL;
     }
-    else
+  
+  if (!text_portion->include_left && !IsTextMarkerEmpty(text_portion->left_marker))
     {
-      found_len = found_end - found_start;
+    found_start += left_len;
+  }
+
+  found_end = FindTextMarker (found_start, &right_len, text_portion->right_marker, text_portion->case_sensitive, text_portion->whole_word);
+  if (found_end == NULL) {
+    return NULL;
     }
+
+  if (text_portion->include_right || IsTextMarkerEmpty(text_portion->right_marker)) {
+    found_end += right_len;
   }
 
+  found_len = found_end - found_start;
+
   if (found_len > 0)
   {
     portion = (CharPtr) MemNew (sizeof (Char) * (found_len + 1));
@@ -4648,45 +5038,38 @@ static CharPtr FindTextPortionLocationInString (CharPtr str, TextPortionPtr text
 
   if (str == NULL || text_portion == NULL) return FALSE;
 
-  if (text_portion->left_text != NULL) {
-    start = StringSearch (str, text_portion->left_text);
-    if (start != NULL) {
-      if (!text_portion->include_left) {
-        start += StringLen (text_portion->left_text);
-      }
-    }
-  } else {
-    start = str;
-  }
-  if (start != NULL) {
-    if (text_portion->right_text != NULL) { 
-      stop = StringSearch (start, text_portion->right_text);
-      if (stop == NULL) {
+  start = FindTextMarker(str, NULL, text_portion->left_marker, text_portion->case_sensitive, text_portion->whole_word);
+  
+  if (start != NULL && !IsTextMarkerEmpty (text_portion->right_marker))
+  {
+    stop = FindTextMarker(start, NULL, text_portion->right_marker, text_portion->case_sensitive, text_portion->whole_word);
+    if (stop == NULL) 
+    {
         start = NULL;
       }
     }
-  }
   return start;
 }
 
 
-static void ReplaceStringForParse(CharPtr src_text, TextPortionPtr text_portion)
+static Boolean ReplaceStringForParse(CharPtr src_text, TextPortionPtr text_portion)
 {
   CharPtr         src, dst;
+  Int4 right_len;
   
   if (src_text == NULL || text_portion == NULL) {
-    return;
+    return FALSE;
   }
 
   dst = FindTextPortionLocationInString (src_text, text_portion);
-  if (dst == NULL) return;
-  if (text_portion->right_text == NULL) {
+  if (dst == NULL) return FALSE;
+  if (IsTextMarkerEmpty (text_portion->right_marker)) {
     *dst = 0;
   } else {
-    src = StringSearch (src_text, text_portion->right_text);
+    src = FindTextMarker(dst, &right_len, text_portion->right_marker, text_portion->case_sensitive, text_portion->whole_word);
     if (src != NULL) {
       if (text_portion->include_right) {
-        src += StringLen (text_portion->right_text);
+        src += right_len;
       }
       while (*src != 0) {
         *dst = *src;
@@ -4696,6 +5079,53 @@ static void ReplaceStringForParse(CharPtr src_text, TextPortionPtr text_portion)
       *dst = 0;
     }
   }
+  return TRUE;
+}
+
+
+NLM_EXTERN Boolean RemoveTextPortionFromString (CharPtr str, TextPortionPtr text_portion)
+{
+  CharPtr before = NULL, after = NULL, src, dst;
+  Boolean rval = FALSE;
+  Int4    left_len, right_len;
+
+  if (str == NULL || text_portion == NULL) {
+    return FALSE;
+  }
+
+  if (text_portion->inside) {
+    rval = ReplaceStringForParse (str, text_portion);
+  } else {
+    if ((before = FindTextMarker (str, &left_len, text_portion->left_marker, 
+                                  text_portion->case_sensitive, text_portion->whole_word)) != NULL
+        && (after = FindTextMarker (before, &right_len, text_portion->right_marker, 
+                                  text_portion->case_sensitive, text_portion->whole_word)) != NULL) {
+      if (!IsTextMarkerEmpty (text_portion->right_marker)) {
+        if (text_portion->include_right) {
+          *after = 0;
+        } else {
+          *(after + right_len) = 0;
+        }
+        rval = TRUE;
+      }
+      if (!IsTextMarkerEmpty (text_portion->left_marker)) {
+        dst = str;
+        if (text_portion->include_left) {
+          src = before + left_len;
+        } else {
+          src = before;
+        }
+        while (*src != 0) {
+          *dst = *src;
+          ++dst;
+          ++src;
+        }
+        *dst = 0;
+        rval = TRUE;
+      }
+    }
+  }
+  return rval;
 }
 
 
@@ -5121,7 +5551,16 @@ SetStringsInValNodeStringList
         rval = TRUE;
       }
   } else if (existing_text == ExistingTextOption_replace_old) {
-    if (DoesStringListMatchConstraint (*list, scp)) {
+    found = FALSE;
+    for (vnp = *list; vnp != NULL; vnp = vnp->next) {
+      cp = (CharPtr) vnp->data.ptrvalue;
+      if (DoesStringMatchConstraint (vnp->data.ptrvalue, scp)) {
+        rval |= SetStringValue (&cp, new_val, existing_text);
+        vnp->data.ptrvalue = cp;
+        found = TRUE;
+      }
+    }
+    if (!found && DoesStringListMatchConstraint (*list, scp)) {
       *list = ValNodeFreeData (*list);
       vnp = ValNodeNew (NULL);
       vnp->data.ptrvalue = StringSave (new_val);
@@ -5213,21 +5652,89 @@ static Boolean SetStringInGBQualList (GBQualPtr PNTR list, ValNodePtr field, Str
 }
 
 
-static Boolean IsAllDigits (CharPtr str)
+static Boolean SetStringInRNAQualList (RNAQualPtr PNTR list, CharPtr qual_name, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text)
 {
-  CharPtr cp;
+  Boolean rval = FALSE;
+  RNAQualPtr rq, last_rq = NULL;
 
-  if (StringHasNoText (str)) return FALSE;
+  if (StringHasNoText (qual_name)) {
+    return FALSE;
+  }
 
-  cp = str;
-  while (*cp != 0 && isdigit (*cp)) {
-    cp++;
+  if (existing_text == ExistingTextOption_add_qual) {
+    rq = RNAQualNew ();
+    rq->qual = StringSave (qual_name);
+    rq->val = StringSave (new_val);
+    if (last_rq == NULL) {
+      *list = rq;
+    } else {
+      last_rq->next = rq;
   }
-  if (*cp == 0) {
-    return TRUE;
+    rval = TRUE;
   } else {
-    return FALSE;
+    for (rq = *list; rq != NULL; rq = rq->next) {
+      if (StringCmp (rq->qual, qual_name) == 0 && DoesStringMatchConstraint (rq->val, scp)) {
+        rval |= SetStringValue (&(rq->val), new_val, existing_text);
+      }
+      last_rq = rq;
+    }
+    if (!rval && (scp == NULL || scp->match_text == NULL)) {
+      rq = RNAQualNew ();
+      rq->qual = StringSave (qual_name);
+      rq->val = StringSave (new_val);
+      if (last_rq == NULL) {
+        *list = rq;
+      } else {
+        last_rq->next = rq;
+      }
+      rval = TRUE;
+    }
   }
+
+  return rval;
+}
+
+
+static CharPtr GetFirstRNAQualMatchName (RNAQualPtr qual, CharPtr qual_name, StringConstraintPtr scp)
+{
+  CharPtr str = NULL;
+  while (qual != NULL && str == NULL) {
+    if (StringCmp (qual->qual, qual_name) == 0
+        && !StringHasNoText (qual->val)
+        && DoesStringMatchConstraint (qual->val, scp)) {
+      str = StringSave (qual->val);
+    } 
+    qual = qual->next;
+  }
+  return str;
+}
+
+
+static Boolean RemoveRNAQualMatch (RNAQualPtr PNTR list, CharPtr qual_name, StringConstraintPtr scp)
+{
+  RNAQualPtr qual_prev = NULL, qual_next, qual;
+  Boolean   rval = FALSE;
+
+  if (list == NULL) return FALSE;
+
+  qual = *list;
+  while (qual != NULL) {
+    qual_next = qual->next;
+    if (StringICmp (qual->qual, qual_name) == 0 && DoesStringMatchConstraint (qual->val, scp)) {
+      if (qual_prev == NULL) {
+        *list = qual->next;
+      } else {
+        qual_prev->next = qual->next;
+      }
+      qual->next = NULL;
+      qual = RNAQualFree (qual);
+      rval = TRUE;
+    } else {
+      qual_prev = qual;
+    }
+    qual = qual_next;
+  }
+  return rval;
 }
 
 
@@ -5264,7 +5771,7 @@ static CharPtr GetInt2ValueFromString (Int2 val, StringConstraintPtr scp)
 }
 
 
-static Boolean SetObjectIdString (ObjectIdPtr oip, CharPtr value, Uint2 existing_text)
+NLM_EXTERN Boolean SetObjectIdString (ObjectIdPtr oip, CharPtr value, Uint2 existing_text)
 {
   Boolean rval = FALSE;
   Char    num[15];
@@ -5296,7 +5803,7 @@ static Boolean SetObjectIdString (ObjectIdPtr oip, CharPtr value, Uint2 existing
 }
 
 
-static CharPtr GetObjectIdString (ObjectIdPtr oip)
+NLM_EXTERN CharPtr GetObjectIdString (ObjectIdPtr oip)
 {
   CharPtr rval = NULL;
   Char    num[15];
@@ -5662,12 +6169,28 @@ static CharPtr GetDbxrefString (ValNodePtr list, StringConstraintPtr scp)
   }
   if (StringLen (str) >1) {
     /* remove final semicolon */
-    str [StringLen (str) - 2] = 0;
+    str [StringLen (str) - 1] = 0;
   }
   return str;
 }
 
 
+static ValNodePtr GetMultipleDbxrefStrings (ValNodePtr list, StringConstraintPtr scp)
+{
+  ValNodePtr vnp, val_list = NULL;
+  CharPtr    cp;
+    
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    cp = GetDbtagString (vnp->data.ptrvalue);
+    if (cp != NULL && DoesStringMatchConstraint(cp, scp)) {
+      ValNodeAddPointer (&val_list, 0, cp);
+    }
+  }
+  
+  return val_list;
+}
+
+
 static Boolean RemoveDbxrefString (ValNodePtr PNTR list, StringConstraintPtr scp)
 {
   ValNodePtr vnp, vnp_prev = NULL, vnp_next;
@@ -5700,9 +6223,131 @@ static Boolean RemoveDbxrefString (ValNodePtr PNTR list, StringConstraintPtr scp
 }
 
 
+static CharPtr trnaList [] = {
+  "tRNA-Gap",
+  "tRNA-Ala",
+  "tRNA-Asx",
+  "tRNA-Cys",
+  "tRNA-Asp",
+  "tRNA-Glu",
+  "tRNA-Phe",
+  "tRNA-Gly",
+  "tRNA-His",
+  "tRNA-Ile",
+  "tRNA-Xle",
+  "tRNA-Lys",
+  "tRNA-Leu",
+  "tRNA-Met",
+  "tRNA-Asn",
+  "tRNA-Pyl",
+  "tRNA-Pro",
+  "tRNA-Gln",
+  "tRNA-Arg",
+  "tRNA-Ser",
+  "tRNA-Thr",
+  "tRNA-Sec",
+  "tRNA-Val",
+  "tRNA-Trp",
+  "tRNA-OTHER",
+  "tRNA-Tyr",
+  "tRNA-Glx",
+  "tRNA-TERM",
+  NULL
+};
+
+
+static CharPtr GetTrnaProductString (tRNAPtr trna)
+{
+  Uint1              aa;
+  Uint1              from;
+  SeqMapTablePtr     smtp;
+  Uint2              idx;
+  CharPtr            str = NULL;
+
+  if (trna == NULL) {
+    return NULL;
+  }
+  aa = 0;
+  if (trna->aatype == 2) {
+    aa = trna->aa;
+  } else {
+    from = 0;
+    switch (trna->aatype) {
+      case 0 :
+        from = 0;
+        break;
+      case 1 :
+        from = Seq_code_iupacaa;
+        break;
+      case 2 :
+        from = Seq_code_ncbieaa;
+        break;
+      case 3 :
+        from = Seq_code_ncbi8aa;
+        break;
+      case 4 :
+        from = Seq_code_ncbistdaa;
+        break;
+      default:
+        break;
+    }
+    smtp = SeqMapTableFind (Seq_code_ncbieaa, from);
+    if (smtp != NULL) {
+      aa = SeqMapTableConvert (smtp, trna->aa);
+      if (aa == 255 && from == Seq_code_iupacaa) {
+        if (trna->aa == 'U') {
+          aa = 'U';
+        } else if (trna->aa == 'O') {
+          aa = 'O';
+        }
+      }
+    }
+  }
+  if (aa > 0 && aa != 255) {
+    if (aa != '*') {
+      idx = aa - (64 /* + shift */);
+    } else {
+      idx = 25;
+    }
+    if (idx > 0 && idx < 28) {
+      str = trnaList [idx];
+    }
+  }
+  return str;
+}
+
+
+NLM_EXTERN CharPtr GetRNARefProductString (RnaRefPtr rrp, StringConstraintPtr scp)
+{
+  CharPtr    str = NULL;
+  RNAGenPtr  rgp;
+
+  if (rrp == NULL || rrp->ext.choice == 0) {
+    return NULL;
+  }
+
+  if (rrp->ext.choice == 1) {
+    str = StringSave (rrp->ext.value.ptrvalue);
+  } else if (rrp->ext.choice == 2) {
+    str = GetTrnaProductString (rrp->ext.value.ptrvalue);
+  } else if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL) {
+    if (!StringHasNoText (rgp->product)) {
+      str = StringSave (rgp->product);
+    }
+  }
+  if (!DoesStringMatchConstraint(str, scp)) {
+    str = MemFree (str);
+  }
+
+  return str;
+
+}
+
+
 NLM_EXTERN CharPtr GetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp)
 {
   RnaRefPtr  rrp;
+  RNAGenPtr  rgp;
   SeqMgrFeatContext context;
   CharPtr    str = NULL;
 
@@ -5720,6 +6365,7 @@ NLM_EXTERN CharPtr GetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp)
     str = GetFirstGBQualMatch (sfp->qual, "product", 0, scp);
   }
 
+
   if (str == NULL) {
     if (rrp->ext.choice == 1 && !StringHasNoText (rrp->ext.value.ptrvalue)
         && StringCmp (rrp->ext.value.ptrvalue, "ncRNA") != 0
@@ -5733,6 +6379,10 @@ NLM_EXTERN CharPtr GetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp)
         str = (CharPtr) MemNew (sizeof (Char) + (StringLen (context.label) + 6));
         sprintf (str, "tRNA-%s", context.label);
       }
+    } else if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL) {
+      if (!StringHasNoText (rgp->product)) {
+        str = StringSave (rgp->product);
+      }
     }
     if (!DoesStringMatchConstraint(str, scp)) {
       str = MemFree (str);
@@ -5767,9 +6417,86 @@ static Boolean IsParseabletRNAName (CharPtr name_string)
 }
 
 
-static Boolean SetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text)
+NLM_EXTERN Boolean SetRNARefProductString (RnaRefPtr rrp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text)
+{
+  Boolean rval = FALSE;
+  RNAGenPtr rgp;
+  CharPtr   cp, tmp;
+  tRNAPtr   trp;
+  Boolean justTrnaText = FALSE;
+  Uint1   codon [6];
+
+  if (rrp == NULL) {
+    return FALSE;
+  }
+  if (rrp->ext.choice == 0) {
+    if (scp == NULL || scp->match_text == NULL) {
+      if (rrp->type == 5 || rrp->type == 6 || rrp->type == 7 || rrp->type == 8 || rrp->type == 9 || rrp->type == 10) {
+        rgp = RNAGenNew ();
+        rgp->product = StringSave (new_val);
+        rrp->ext.choice = 3;
+        rrp->ext.value.ptrvalue = rgp;
+      } else {
+        rrp->ext.choice = 1;
+        rrp->ext.value.ptrvalue = StringSave (new_val);
+      }
+      rval = TRUE;
+    }
+  } else if (rrp->ext.choice == 1) {
+    cp = rrp->ext.value.ptrvalue;
+    rval = SetStringValue (&cp, new_val, existing_text);
+    rrp->ext.value.ptrvalue = cp;
+  } else if (rrp->ext.choice == 3) {
+    rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+    rval = SetStringValue (&(rgp->product), new_val, existing_text);
+  } else if (rrp->ext.choice == 2) {
+    tmp = StringSave (GetTrnaProductString (rrp->ext.value.ptrvalue));
+
+    if (DoesStringMatchConstraint (tmp, scp)
+        && SetStringValue (&tmp, new_val, existing_text)) {
+      trp = (tRNAPtr) rrp->ext.value.ptrvalue;
+      if (trp == NULL) {
+        trp = MemNew (sizeof (tRNA));
+        trp->aatype = 0;
+        MemSet (trp->codon, 255, sizeof (trp->codon));
+        trp->anticodon = NULL;
+        rrp->ext.value.ptrvalue = trp;
+      }
+
+      if (!IsParseabletRNAName(tmp))
+      {
+        if (trp->anticodon == NULL
+            && trp->codon[0] == 255
+            && trp->codon[1] == 255
+            && trp->codon[2] == 255
+            && trp->codon[3] == 255
+            && trp->codon[4] == 255
+            && trp->codon[5] == 255)
+        {
+          trp = MemFree (trp);
+          rrp->ext.choice = 1;
+          rrp->ext.value.ptrvalue = tmp;
+          tmp = NULL;
+          rval = TRUE;
+        }
+      }
+      else
+      {
+        trp->aa = ParseTRnaString (tmp, &justTrnaText, codon, TRUE);
+        trp->aatype = 2;
+        rval = TRUE;
+      }
+      tmp = MemFree (tmp);
+    }
+  }
+  return rval;
+}
+
+
+NLM_EXTERN Boolean SetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text)
 {
   RnaRefPtr  rrp;
+  RNAGenPtr  rgp;
   Boolean rval = FALSE;
   ValNode vn;
   CharPtr cp, tmp;
@@ -5782,7 +6509,8 @@ static Boolean SetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp, Cha
   }
 
   rrp = sfp->data.value.ptrvalue;
-  if (rrp->ext.choice == 0 
+
+  if ((rrp->ext.choice == 0 && rrp->type != 5 && rrp->type != 6 && rrp->type != 7 && rrp->type != 8 && rrp->type != 9 && rrp->type != 10)
       || (rrp->ext.choice == 1 && StringHasNoText (rrp->ext.value.ptrvalue))
       || (rrp->ext.choice == 1 
           && (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0 
@@ -5795,6 +6523,11 @@ static Boolean SetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp, Cha
   }
 
   if (!rval) {
+    if (rrp->ext.choice == 0 
+        && (rrp->type == 5 || rrp->type == 6 || rrp->type == 7 || rrp->type == 8 
+            || rrp->type == 9 || rrp->type == 10)) {
+      rrp->ext.choice = 3;
+    }
     if ((rrp->ext.choice == 0 || (rrp->ext.choice == 1 && StringHasNoText (rrp->ext.value.ptrvalue)))
         && (scp == NULL || scp->match_text == NULL)) {
       rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
@@ -5810,6 +6543,13 @@ static Boolean SetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp, Cha
       rval = SetStringValue (&cp, new_val, existing_text);
       rrp->ext.value.ptrvalue = cp;
       rval = TRUE;
+    } else if (rrp->ext.choice == 3) {
+      rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+      if (rgp == NULL) {
+        rgp = RNAGenNew ();
+        rrp->ext.value.ptrvalue = rgp;
+      }
+      rval = SetStringValue (&(rgp->product), new_val, existing_text);
     } else if (rrp->ext.choice == 2) {
       tmp = GetRNAProductString (sfp, NULL);
       if (DoesStringMatchConstraint (tmp, scp)
@@ -5863,9 +6603,10 @@ static Boolean SetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp, Cha
 }
 
 
-static Boolean RemoveRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp)
+NLM_EXTERN Boolean RemoveRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp)
 {
   RnaRefPtr  rrp;
+  RNAGenPtr  rgp;
   Boolean    rval = FALSE;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || sfp->data.value.ptrvalue == NULL) {
@@ -5882,8 +6623,9 @@ static Boolean RemoveRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp)
     rval = RemoveGBQualMatch (&(sfp->qual), "product", 0, scp);
   }
 
-  if (!rval 
-      && rrp->ext.choice == 1 && !StringHasNoText (rrp->ext.value.ptrvalue)
+  if (!rval) {
+    if (rrp->ext.choice == 1) {
+      if (!StringHasNoText (rrp->ext.value.ptrvalue)
       && StringCmp (rrp->ext.value.ptrvalue, "ncRNA") != 0
       && StringCmp (rrp->ext.value.ptrvalue, "tmRNA") != 0
       && StringCmp (rrp->ext.value.ptrvalue, "misc_RNA") != 0
@@ -5892,10 +6634,21 @@ static Boolean RemoveRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp)
     rrp->ext.choice = 0;
     rval = TRUE;
   }
+    } else if (rrp->ext.choice == 3) {
+      rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+      if (rgp != NULL && !StringHasNoText (rgp->product) 
+          && DoesStringMatchConstraint (rgp->product, scp)) {
+        rgp->product = MemFree (rgp->product);
+        rval = TRUE;
+      }
+    }  
+  }
   return rval;
 }
 
 
+
+
 static Boolean RemovetRNACodons_Recognized (SeqFeatPtr sfp)
 {
   RnaRefPtr rrp;
@@ -6132,6 +6885,127 @@ static CharPtr GettRNACodonsRecognized (SeqFeatPtr sfp, StringConstraintPtr scp)
 }
 
 
+NLM_EXTERN Boolean SettmRNATagPeptide (RnaRefPtr rrp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text)
+{
+  RNAGenPtr rgp;
+  Boolean   rval = FALSE;
+
+  if (rrp == NULL) {
+    return FALSE;
+  }
+  if (rrp->ext.choice == 0) {
+    rrp->ext.choice = 3;
+  }
+
+  if (rrp->ext.choice == 1) {
+    rgp = RNAGenNew ();
+    rgp->product = rrp->ext.value.ptrvalue;
+    rrp->ext.value.ptrvalue = rgp;
+    rrp->ext.choice = 3;
+  }
+  if (rrp->ext.choice == 3) {
+    rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+    if (rgp == NULL) {
+      rgp = RNAGenNew ();
+      rrp->ext.value.ptrvalue = rgp;
+    }
+    rval = SetStringInRNAQualList (&(rgp->quals), "tag_peptide", scp, new_val, existing_text);
+  }
+  return rval;
+}
+
+
+NLM_EXTERN CharPtr GettmRNATagPeptide (RnaRefPtr rrp, StringConstraintPtr scp)
+{
+  RNAGenPtr rgp;
+
+  if (rrp == NULL 
+      || rrp->ext.choice != 3 
+      || (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) == NULL) {
+    return NULL;
+  }
+  return GetFirstRNAQualMatchName (rgp->quals, "tag_peptide", scp);
+}
+
+
+static Boolean RemovetmRNATagPeptide (RnaRefPtr rrp, StringConstraintPtr scp)
+{
+  RNAGenPtr rgp;
+
+  if (rrp == NULL 
+      || rrp->ext.choice != 3 
+      || (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) == NULL) {
+    return FALSE;
+  }
+  return RemoveRNAQualMatch (&(rgp->quals), "tag_peptide", scp);
+}
+
+
+NLM_EXTERN Boolean SetncRNAClass (RnaRefPtr rrp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text)
+{
+  RNAGenPtr rgp;
+  Boolean   rval = FALSE;
+
+  if (rrp == NULL) {
+    return FALSE;
+  }
+  if (rrp->ext.choice == 0) {
+    rrp->ext.choice = 3;
+  }
+
+  if (rrp->ext.choice == 1) {
+    rgp = RNAGenNew ();
+    rgp->product = rrp->ext.value.ptrvalue;
+    rrp->ext.value.ptrvalue = rgp;
+    rrp->ext.choice = 3;
+  }
+  if (rrp->ext.choice == 3) {
+    rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+    if (rgp == NULL) {
+      rgp = RNAGenNew ();
+      rrp->ext.value.ptrvalue = rgp;
+    }
+    rval = SetStringValue (&(rgp->_class), new_val, existing_text);
+  }
+  return rval;
+}
+
+
+NLM_EXTERN CharPtr GetncRNAClass (RnaRefPtr rrp, StringConstraintPtr scp)
+{
+  RNAGenPtr rgp;
+
+  if (rrp == NULL 
+      || rrp->ext.choice != 3 
+      || (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) == NULL) {
+    return NULL;
+  }
+  if (DoesStringMatchConstraint (rgp->_class, scp)) {
+    return StringSave (rgp->_class);
+  } else {
+    return NULL;
+  }
+}
+
+
+static Boolean RemovencRNAClass (RnaRefPtr rrp, StringConstraintPtr scp)
+{
+  RNAGenPtr rgp;
+
+  if (rrp == NULL 
+      || rrp->ext.choice != 3 
+      || (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) == NULL) {
+    return FALSE;
+  }
+  if (!StringHasNoText (rgp->_class) && DoesStringMatchConstraint (rgp->_class, scp)) {
+    rgp->_class = MemFree (rgp->_class);
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
 static SeqLocPtr ParseSimpleInterval (CharPtr str, BioseqPtr bsp, CharPtr PNTR end)
 {
   Boolean partial_left = FALSE, partial_right = FALSE;
@@ -6209,7 +7083,7 @@ static void ComplementSeqLoc (SeqLocPtr slp)
 NLM_EXTERN SeqLocPtr ParseSimpleSeqLoc (CharPtr str, BioseqPtr bsp)
 {
   CharPtr cp, cp_next;
-  SeqLocPtr slp = NULL, slp_first = NULL, slp_last = NULL, slp_tmp;
+  SeqLocPtr slp = NULL, slp_first = NULL, slp_tmp;
   Boolean is_complement = FALSE;
 
   if (StringHasNoText (str) || bsp == NULL) {
@@ -6369,7 +7243,6 @@ static CharPtr GetAnticodonLocString (SeqFeatPtr sfp)
 {
   RnaRefPtr rrp;
   tRNAPtr   trp;
-  Boolean   rval = FALSE;
   SeqLocPtr slp;
   CharPtr   str = NULL, tmp;
   ValNodePtr str_list = NULL, vnp;
@@ -6527,6 +7400,48 @@ static CharPtr GetCitationTextFromFeature (SeqFeatPtr sfp, StringConstraintPtr s
 }
 
 
+static CharPtr GetCodeBreakString (SeqFeatPtr sfp)
+{
+  CdRegionPtr crp;
+  ValNodePtr  list = NULL, vnp;
+  BioseqPtr   bsp;
+  Int4        len = 0;
+  CharPtr     str = NULL;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION
+      || (crp = (CdRegionPtr) sfp->data.value.ptrvalue) == NULL
+      || crp->code_break == NULL) {
+    return NULL;
+  } 
+
+  bsp = BioseqFindFromSeqLoc (sfp->location);
+
+  PrintFTCodeBreak (&list, crp->code_break, bsp);
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    if (StringNCmp (vnp->data.ptrvalue, "\t\t\ttransl_except\t", 17) == 0) {
+      len += StringLen (vnp->data.ptrvalue) - 17;
+    }
+  }
+  if (len > 0) {
+    str = (CharPtr) MemNew (sizeof (Char) * (len + 1));
+    str[0] = 0;
+    for (vnp = list; vnp != NULL; vnp = vnp->next) {
+      if (StringNCmp (vnp->data.ptrvalue, "\t\t\ttransl_except\t", 17) == 0) {
+        StringCat (str, ((CharPtr) vnp->data.ptrvalue) + 17);
+        if (vnp->next == NULL) {
+          str[StringLen(str) - 1] = 0;
+        } else {
+          str[StringLen(str) - 1] = ';';
+        }
+      }
+    }
+  }
+  list = ValNodeFreeData (list);
+  return str;
+}
+
+
 NLM_EXTERN CharPtr GetQualFromFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp, BatchExtraPtr batch_extra)
 {
   CharPtr   str = NULL;
@@ -6535,6 +7450,8 @@ NLM_EXTERN CharPtr GetQualFromFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field,
   Int4      gbqual, subfield;
   SeqFeatPtr gene = NULL;
   CdRegionPtr crp;
+  ValNodePtr  vnp;
+  Char        buf[20];
 
   if (sfp == NULL || field == NULL || field->field == NULL)
   {
@@ -6604,6 +7521,14 @@ NLM_EXTERN CharPtr GetQualFromFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field,
     str = GetCitationTextFromFeature (sfp, scp, batch_extra == NULL ? NULL : batch_extra->cit_list);
   }
 
+  /* location */
+  if (str == NULL
+      && ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_location)
+          || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("location", field->field->data.ptrvalue))))
+  {
+    str = SeqLocPrintUseBestID (sfp->location);
+  }
+
   /* fields common to some features */
   /* product */
   if (str == NULL
@@ -6655,7 +7580,8 @@ NLM_EXTERN CharPtr GetQualFromFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field,
   if (str == NULL 
        && ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_allele)
            || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("allele", field->field->data.ptrvalue)))
-       && grp != NULL)
+       && grp != NULL
+       && sfp->idx.subtype != FEATDEF_variation)
   {
     if (!StringHasNoText (grp->allele) && DoesStringMatchConstraint(grp->allele, scp))
     {
@@ -6721,6 +7647,26 @@ NLM_EXTERN CharPtr GetQualFromFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field,
     str = GetFirstValNodeStringMatch (prp->activity, scp);
   }
   
+  /* coding region fields */
+  /* transl_except */
+  if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_transl_except
+      && sfp->data.choice == SEQFEAT_CDREGION) 
+  {
+    str = GetCodeBreakString (sfp);
+  }
+  /* transl_table */
+  if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_transl_table
+      && sfp->data.choice == SEQFEAT_CDREGION
+      && (crp = (CdRegionPtr) sfp->data.value.ptrvalue) != NULL) 
+  {
+    if (crp->genetic_code != NULL && (vnp = crp->genetic_code->data.ptrvalue) != NULL
+        && vnp->choice == 2) {
+      sprintf (buf, "%d", vnp->data.intvalue);
+      str = StringSave (buf);
+    }
+  }
+
+  /* special RNA qualifiers */
   /* tRNA qualifiers */
   /* codon-recognized */
   if (str == NULL
@@ -6734,6 +7680,18 @@ NLM_EXTERN CharPtr GetQualFromFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field,
            || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("anticodon", field->field->data.ptrvalue)))) {
     str = GetAnticodonLocString (sfp);
   }
+  /* tag-peptide */
+  if (str == NULL
+      && ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_tag_peptide)
+           || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("tag-peptide", field->field->data.ptrvalue)))) {
+    str = GettmRNATagPeptide (sfp->data.value.ptrvalue, scp);
+  }
+  /* ncRNA_class */
+  if (str == NULL
+      && ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_ncRNA_class)
+           || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("ncRNA_class", field->field->data.ptrvalue)))) {
+    str = GetncRNAClass (sfp->data.value.ptrvalue, scp);
+  }
 
   /* codon-start */
   if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_codon_start
@@ -6776,12 +7734,34 @@ NLM_EXTERN CharPtr GetQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, St
 }
 
 
-static Boolean RemoveQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp)
+static Boolean RemoveCodeBreak (CdRegionPtr crp)
+
+{
+  CodeBreakPtr  cbp, nextcbp;
+
+  if (crp == NULL || crp->code_break == NULL) {
+    return FALSE;
+  }
+
+  cbp = crp->code_break;
+  while (cbp != NULL) {
+    nextcbp = cbp->next;
+    cbp->next = NULL;
+    cbp = CodeBreakFree (cbp);
+    cbp = nextcbp;
+  }
+  crp->code_break = NULL;
+  return TRUE;
+}
+
+
+NLM_EXTERN Boolean RemoveQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp)
 {
   Boolean rval = FALSE;
   GeneRefPtr grp = NULL;
   ProtRefPtr prp = NULL;
-  RnaRefPtr  rrp;
+  RnaRefPtr   rrp = NULL;
+  CdRegionPtr crp;
   tRNAPtr trp;
   Int4      gbqual, subfield;
   SeqFeatPtr gene = NULL;
@@ -6868,6 +7848,32 @@ static Boolean RemoveQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, Str
     }
   }
 
+  /* location */
+  if ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_location)
+      || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("location", field->field->data.ptrvalue)))
+  {
+    if (sfp->location != NULL) {
+      sfp->location = SeqLocFree (sfp->location);
+      rval = TRUE;
+    }
+  }
+
+  /* pseudo */
+  if ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_pseudo)
+      || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("pseudo", field->field->data.ptrvalue)))
+  {
+    if (gene != NULL) {
+      if (gene->pseudo) {
+        gene->pseudo = FALSE;
+        rval = TRUE;
+      }
+    } 
+    if (sfp->pseudo) {
+      sfp->pseudo = FALSE;
+      rval = TRUE;
+    }
+    return rval;
+  }
 
   /* fields common to some features */
   /* product */
@@ -6917,7 +7923,8 @@ static Boolean RemoveQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, Str
   /* allele */
   if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_allele)
            || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("allele", field->field->data.ptrvalue)))
-      && grp != NULL)
+      && grp != NULL
+      && sfp->idx.subtype != FEATDEF_variation)
   {
     if (!StringHasNoText (grp->allele) && DoesStringMatchConstraint(grp->allele, scp))
     {
@@ -6984,7 +7991,27 @@ static Boolean RemoveQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, Str
     rval = RemoveValNodeStringMatch (&(prp->activity), scp);
   }
   
-  /* RNA fields */
+  /* special coding region fields */
+  /* transl_except */
+  if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_transl_except
+      && sfp->data.choice == SEQFEAT_CDREGION) 
+  {
+    crp = (CdRegionPtr) sfp->data.value.ptrvalue;
+    rval = RemoveCodeBreak (crp);
+  }
+  /* transl_table */
+  if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_transl_table
+      && sfp->data.choice == SEQFEAT_CDREGION
+      && (crp = (CdRegionPtr) sfp->data.value.ptrvalue) != NULL) 
+  {
+    if (crp->genetic_code != NULL) {
+      crp->genetic_code = GeneticCodeFree (crp->genetic_code);
+      rval = TRUE;
+    }
+  }
+
+
+  /* special RNA fields */
   /* anticodon */
   if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_anticodon)
            || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("anticodon", field->field->data.ptrvalue)))
@@ -7003,6 +8030,19 @@ static Boolean RemoveQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, Str
   {
     rval = RemovetRNACodons_Recognized (sfp);
   }
+  /* tag_peptide */
+  if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_tag_peptide)
+           || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("tag-peptide", field->field->data.ptrvalue)))
+       && rrp != NULL && rrp->ext.choice == 3)
+  {
+    rval = RemovetmRNATagPeptide (rrp, scp);
+  }
+  if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_ncRNA_class)
+           || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("ncRNA_class", field->field->data.ptrvalue)))
+       && rrp != NULL && rrp->ext.choice == 3)
+  {
+    rval = RemovencRNAClass (rrp, scp);
+  }
 
   if (!rval) {
     /* actual GenBank qualifiers */
@@ -7153,9 +8193,83 @@ static Boolean SetCitationTextOnFeature (SeqFeatPtr sfp, StringConstraintPtr scp
 }
 
 
+static Boolean SetFeatureLocation (SeqFeatPtr sfp, CharPtr value, Uint2 existing_text)
+{
+  SeqLocPtr  loc;
+  Boolean    locmap;
+  int        num_errs;
+  Boolean    sitesmap;
+  SeqIdPtr   sip;
+  Boolean    rval = FALSE;
+
+  sip = SeqLocId (sfp->location);
+  loc = Nlm_gbparseint (value, &locmap, &sitesmap, &num_errs, sip);
+  if (loc != NULL) {
+    switch (existing_text) {
+      case ExistingTextOption_replace_old:
+        sfp->location = SeqLocFree (sfp->location);
+        sfp->location = loc;
+        loc = NULL;
+        rval = TRUE;
+        break;
+      case ExistingTextOption_append_semi:
+      case ExistingTextOption_append_space:
+      case ExistingTextOption_append_colon:
+      case ExistingTextOption_append_comma:
+      case ExistingTextOption_append_none:
+        SeqLocAdd (&(sfp->location), loc, FALSE, FALSE);
+        SeqLocPackage (sfp->location);
+        loc = NULL;
+        rval = TRUE;
+        break;
+      case ExistingTextOption_prefix_semi:
+      case ExistingTextOption_prefix_space:
+      case ExistingTextOption_prefix_colon:
+      case ExistingTextOption_prefix_comma:
+      case ExistingTextOption_prefix_none:
+        SeqLocAdd (&loc, sfp->location, FALSE, FALSE);
+        SeqLocPackage (loc);
+        sfp->location = loc;
+        loc = NULL;
+        rval = TRUE;
+        break;
+      case ExistingTextOption_leave_old:
+        if (sfp->location == NULL) {
+          sfp->location = loc;
+          loc = NULL;
+          rval = TRUE;
+        }
+        break;
+    }
+  }
+  loc = SeqLocFree (loc);
+  return rval;
+}
+
+
+static Boolean SetGeneticCode (CdRegionPtr crp, Int4 value)
+{
+  ValNodePtr vnp;
+
+  if (crp == NULL) {
+    return FALSE;
+  }
+  if (crp->genetic_code != NULL) {
+    crp->genetic_code = GeneticCodeFree (crp->genetic_code);
+  }
+  crp->genetic_code = GeneticCodeNew ();
+  vnp = ValNodeNew (NULL);
+  vnp->choice = 2;
+  vnp->data.intvalue = value;
+  crp->genetic_code->data.ptrvalue = vnp;
+  return TRUE;
+}
+
+
 static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp, CharPtr value, Uint2 existing_text, BatchExtraPtr batch_extra)
 {
   Boolean rval = FALSE;
+  Boolean    matched_term = FALSE;
   GeneRefPtr grp = NULL;
   ProtRefPtr prp = NULL;
   CharPtr    tmp;
@@ -7198,6 +8312,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     {
       rval = SetStringValue ( &(sfp->comment), value, existing_text);
     }
+    matched_term = TRUE;
   }
   /* db-xref */
   if ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_db_xref)
@@ -7213,6 +8328,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     {
       rval = SetStringValue ( &(sfp->except_text), value, existing_text);
     }
+    matched_term = TRUE;
   }
   /* evidence */
   if ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_evidence)
@@ -7253,6 +8369,33 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     rval = SetCitationTextOnFeature (sfp, scp, value, existing_text, batch_extra == NULL ? NULL : batch_extra->cit_list);
   }
 
+  /* location */
+  if ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_location)
+          || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("location", field->field->data.ptrvalue)))
+  {
+    rval = SetFeatureLocation (sfp, value, existing_text);
+    return rval;
+  }
+
+  /* pseudo */
+  if ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_pseudo)
+      || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("pseudo", field->field->data.ptrvalue)))
+  {
+    if (gene != NULL) {
+      if (!gene->pseudo) {
+        gene->pseudo = TRUE;
+        rval = TRUE;
+      }
+      return rval;
+    } else {
+      if (!sfp->pseudo) {
+        sfp->pseudo = TRUE;
+        rval = TRUE;
+      }
+      return rval;
+    }
+  }
+
   /* fields common to some features */
   /* product */
   if ((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_product)
@@ -7263,6 +8406,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     } else if (sfp->data.choice == SEQFEAT_RNA) {
       rval = SetRNAProductString (sfp, scp, value, existing_text);
     }
+    matched_term = TRUE;
   }
 
   /* Gene fields */
@@ -7283,6 +8427,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     {
       rval = SetStringValue (&(grp->locus), value, existing_text);
     }
+    matched_term = TRUE;
   }
 
   /* description */
@@ -7294,6 +8439,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     {
       rval = SetStringValue (&(grp->desc), value, existing_text);
     }
+    matched_term = TRUE;
   }
   /* maploc */
   if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_map)
@@ -7304,16 +8450,19 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     {
       rval = SetStringValue (&(grp->maploc), value, existing_text);
     }
+    matched_term = TRUE;
   }
   /* allele */
   if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_allele)
            || (field->field->choice == FeatQualChoice_illegal_qual && DoesStringMatchConstraint ("allele", field->field->data.ptrvalue)))
-       && grp != NULL)
+      && grp != NULL
+      && sfp->idx.subtype != FEATDEF_variation)
   {
     if (DoesStringMatchConstraint(grp->allele, scp))
     {
       rval = SetStringValue (&(grp->allele), value, existing_text);
     }
+    matched_term = TRUE;
   }
   /* locus_tag */
   if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_locus_tag)
@@ -7324,6 +8473,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     {
       rval = SetStringValue (&(grp->locus_tag), value, existing_text);
     }
+    matched_term = TRUE;
   }
   /* synonym */
   if (((field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_synonym)
@@ -7331,12 +8481,14 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
        && grp != NULL)
   {
     rval = SetStringsInValNodeStringList (&(grp->syn), scp, value, existing_text);
+    matched_term = TRUE;
   }
   /* gene comment */
   if (field->field->choice == FeatQualChoice_legal_qual
       && field->field->data.intvalue == Feat_qual_legal_gene_comment
       && gene != NULL) {
     rval = SetStringValue (&(gene->comment), value, existing_text);
+    matched_term = TRUE;
   }
 
   /* protein fields */
@@ -7365,6 +8517,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     rval = SetStringsInValNodeStringList (&(prp->activity), scp, value, existing_text);
   }
  
+  /* special coding region fields */
   /* codon start */
   /* note - if product existed before, it will be retranslated */
   if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_codon_start
@@ -7394,7 +8547,35 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
       AdjustProteinSequenceForReadingFrame (sfp);
     }
   } 
+  /* transl_except */
+  if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_transl_except
+      && sfp->data.choice == SEQFEAT_CDREGION) 
+  {
+    crp = (CdRegionPtr) sfp->data.value.ptrvalue;
+    if (crp->code_break != NULL && existing_text == ExistingTextOption_leave_old) {
+      matched_term = TRUE;
+    } else {
+      if (crp->code_break != NULL && existing_text == ExistingTextOption_replace_old) {
+        RemoveCodeBreak (crp);
+      }
+      rval = ParseCodeBreak (sfp, value, 0);
+    }
+  }
+  /* transl_table */
+  if (field->field->choice == FeatQualChoice_legal_qual && field->field->data.intvalue == Feat_qual_legal_transl_table
+      && sfp->data.choice == SEQFEAT_CDREGION
+      && (crp = (CdRegionPtr) sfp->data.value.ptrvalue) != NULL
+      && IsAllDigits (value)) 
+  {
+    if (crp->genetic_code != NULL && existing_text == ExistingTextOption_leave_old) {
+      matched_term = TRUE;
+    } else {
+      rval = SetGeneticCode (crp, atoi (value));
+    }
+  }
 
+
+  /* special RNA fields
   /* tRNA fields */
   if (sfp->idx.subtype == FEATDEF_tRNA
       && ((field->field->choice == FeatQualChoice_legal_qual
@@ -7414,9 +8595,27 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
     rval = SetAnticodon (sfp, scp, value, existing_text);
   }
 
+  if (sfp->idx.subtype == FEATDEF_tmRNA
+      && ((field->field->choice == FeatQualChoice_legal_qual
+           && field->field->data.intvalue == Feat_qual_legal_tag_peptide)
+          || (field->field->choice == FeatQualChoice_illegal_qual
+           && DoesStringMatchConstraint ("tag-peptide", field->field->data.ptrvalue))))
+  {
+    rval = SettmRNATagPeptide (sfp->data.value.ptrvalue, scp, value, existing_text);
+  }
+
+  if (sfp->idx.subtype == FEATDEF_ncRNA
+      && ((field->field->choice == FeatQualChoice_legal_qual
+           && field->field->data.intvalue == Feat_qual_legal_ncRNA_class)
+          || (field->field->choice == FeatQualChoice_illegal_qual
+           && DoesStringMatchConstraint ("ncRNA_class", field->field->data.ptrvalue))))
+  {
+    rval = SetncRNAClass (sfp->data.value.ptrvalue, scp, value, existing_text);
+    matched_term = TRUE;
+  }
 
   /* actual GenBank qualifiers */
-  if (!rval)
+  if (!rval && !matched_term)
   {
     rval = SetStringInGBQualList (&(sfp->qual), field->field, scp, value, existing_text);
   }
@@ -7424,7 +8623,7 @@ static Boolean SetQualOnFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, String
 }
 
 
-static Boolean SetQualOnFeature (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp, CharPtr value, Uint2 existing_text)
+NLM_EXTERN Boolean SetQualOnFeature (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp, CharPtr value, Uint2 existing_text)
 {
   return SetQualOnFeatureEx (sfp, field, scp, value, existing_text, NULL);
 }
@@ -7697,6 +8896,123 @@ NLM_EXTERN CharPtr GetSourceQualFromBioSource (BioSourcePtr biop, SourceQualChoi
 }
 
 
+NLM_EXTERN ValNodePtr GetMultipleSourceQualsFromBioSource (BioSourcePtr biop, SourceQualChoicePtr scp, StringConstraintPtr constraint)
+{
+  ValNodePtr val_list = NULL;
+  CharPtr str = NULL;
+  SubSourcePtr ssp;
+  OrgModPtr mod;
+  Int4 orgmod_subtype = -1, subsrc_subtype = -1;
+  Int4 subfield;
+  ValNode vn;
+
+  if (biop == NULL || scp == NULL) return NULL;
+
+  if (scp->choice == SourceQualChoice_textqual) {
+    if (scp->data.intvalue == Source_qual_taxname) {
+      if (biop->org != NULL && !StringHasNoText (biop->org->taxname)
+          && DoesStringMatchConstraint (biop->org->taxname, constraint)) {
+        ValNodeAddPointer (&val_list, 0, StringSave (biop->org->taxname));
+      }
+    } else if (scp->data.intvalue == Source_qual_common_name) {
+      if (biop->org != NULL && !StringHasNoText (biop->org->common)
+          && DoesStringMatchConstraint (biop->org->common, constraint)) {
+        ValNodeAddPointer (&val_list, 0, StringSave (biop->org->common));
+      }
+    } else if (scp->data.intvalue == Source_qual_lineage) {
+      if (biop->org != NULL && biop->org->orgname != NULL && !StringHasNoText (biop->org->orgname->lineage)
+          && DoesStringMatchConstraint (biop->org->orgname->lineage, constraint)) {
+        ValNodeAddPointer (&val_list, 0, StringSave (biop->org->orgname->lineage));
+      }
+    } else if (scp->data.intvalue == Source_qual_division) {
+      if (biop->org != NULL && biop->org->orgname != NULL  && !StringHasNoText (biop->org->orgname->div)
+          && DoesStringMatchConstraint (biop->org->orgname->div, constraint)) {
+        ValNodeAddPointer (&val_list, 0, StringSave (biop->org->orgname->div));
+      }
+    } else if (scp->data.intvalue == Source_qual_dbxref) {
+      if (biop->org != NULL) {
+        ValNodeLink (&val_list, GetMultipleDbxrefStrings (biop->org->db, constraint));
+      }
+    } else if (scp->data.intvalue == Source_qual_all_notes) {
+      vn.choice = SourceQualChoice_textqual;
+      vn.data.intvalue = Source_qual_subsource_note;
+      vn.next = NULL;
+      str = GetSourceQualFromBioSource (biop, &vn, constraint);
+      if (str != NULL) {
+        ValNodeAddPointer (&val_list, 0, str);
+      }
+      vn.data.intvalue = Source_qual_orgmod_note;
+      str = GetSourceQualFromBioSource (biop, &vn, constraint);
+      if (str != NULL) {
+        ValNodeAddPointer (&val_list, 0, str);
+      }
+    } else if (scp->data.intvalue == Source_qual_all_quals) {
+      /* will not do */
+    } else {
+      orgmod_subtype = GetOrgModQualFromSrcQual (scp->data.intvalue, &subfield);
+      if (orgmod_subtype == -1) {
+        subsrc_subtype = GetSubSrcQualFromSrcQual (scp->data.intvalue, &subfield);
+        for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
+          if (ssp->subtype == subsrc_subtype) {
+            if (StringHasNoText (ssp->name)) {
+              if (IsNonTextSourceQual (scp->data.intvalue)
+                  && DoesStringMatchConstraint ("TRUE", constraint)) {
+                ValNodeAddPointer (&val_list, 0, StringSave ("TRUE"));
+              }
+            } else {
+              if (subfield == 0) {
+                if (DoesStringMatchConstraint (ssp->name, constraint)) {
+                  ValNodeAddPointer (&val_list, 0, StringSave (ssp->name));
+                }
+              } else {
+                str = GetThreeFieldSubfield (ssp->name, subfield);
+                if (StringHasNoText (str) || !DoesStringMatchConstraint (str, constraint)) {
+                  str = MemFree (str);
+                } else {
+                  ValNodeAddPointer (&val_list, 0, str);
+                }
+              }
+            }
+          }
+        }
+      } else {
+        if (biop->org != NULL && biop->org->orgname != NULL) {
+          for (mod = biop->org->orgname->mod; mod != NULL && str == NULL; mod = mod->next) {
+            if (mod->subtype == orgmod_subtype) {
+              if (StringHasNoText (mod->subname)) {
+                if (IsNonTextSourceQual (scp->data.intvalue)
+                    && DoesStringMatchConstraint ("TRUE", constraint)) {
+                  ValNodeAddPointer (&val_list, 0, StringSave ("TRUE"));
+                }
+              } else {
+                if (subfield == 0) {
+                  if (DoesStringMatchConstraint (mod->subname, constraint)) {
+                    ValNodeAddPointer (&val_list, 0, StringSave (mod->subname));
+                  }
+                } else {
+                  str = GetThreeFieldSubfield (mod->subname, subfield);
+                  if (StringHasNoText (str) || !DoesStringMatchConstraint (str, constraint)) {
+                    str = MemFree (str);
+                  } else {
+                    ValNodeAddPointer (&val_list, 0, str);
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  } else {
+    str = GetSourceQualFromBioSource (biop, scp, constraint);
+    if (str != NULL) {
+      ValNodeAddPointer (&val_list, 0, str);
+    }
+  }
+  return val_list;
+}
+
+
 static Boolean RemoveAllSourceQualsFromBioSource (BioSourcePtr biop, StringConstraintPtr constraint)
 {
   Int4 i;
@@ -8259,7 +9575,6 @@ NLM_EXTERN BioseqPtr GetSequenceForObject (Uint1 choice, Pointer data)
           bsp = BioseqFindFromSeqLoc (sfp->location);
         }
       }
-      break;
       for (vnp = cgp->gene_list; vnp != NULL && bsp == NULL; vnp = vnp->next) {
         sfp = vnp->data.ptrvalue;
         if (sfp != NULL) {
@@ -9754,7 +11069,7 @@ static DatePtr ReadDateFromString (CharPtr date_str)
   CharPtr   str;
   Int4      day_val = 0;
   Uint1     month_num = 0;
-  Int4      val;
+  long      val;
   Int4      year_val = 0;
   DatePtr   dp = NULL;
   Boolean   critical_error = FALSE;
@@ -9782,9 +11097,10 @@ static DatePtr ReadDateFromString (CharPtr date_str)
   }
 
   if (day != NULL) {
-    if (sscanf (day, "%ld", &day_val) != 1 || day_val < 1 || day_val > 31) {
+    if (sscanf (day, "%ld", &val) != 1 || val < 1 || val > 31) {
       critical_error = TRUE;
     }
+    day_val = val;
   }
 
   if (month != NULL) {
@@ -11635,7 +12951,10 @@ static void CaptureRefBlockSerialNumbers
  BlockType blocktype,
  Uint2 entityID,
  Uint2 itemtype,
- Uint4 itemID)
+ Uint4 itemID,
+ Int4 left,
+ Int4 right
+)
 {
   CharPtr          cp;
   Int4             serial_number;
@@ -11929,7 +13248,7 @@ NLM_EXTERN CharPtr GetFieldValueForObjectEx (Uint1 choice, Pointer data, FieldTy
   SeqDescrPtr     sdp;
   GBBlockPtr      gb;
 
-  if (data == NULL || field == NULL || field->data.ptrvalue == NULL) return FALSE;
+  if (data == NULL || field == NULL || field->data.ptrvalue == NULL) return NULL;
 
   switch (field->choice) {
     case FieldType_source_qual :
@@ -12002,7 +13321,27 @@ NLM_EXTERN CharPtr GetFieldValueForObject (Uint1 choice, Pointer data, FieldType
   return GetFieldValueForObjectEx (choice, data, field, scp, NULL);
 }
 
-static Boolean GBBlockIsCompletelyEmpty (GBBlockPtr gb)
+
+NLM_EXTERN ValNodePtr GetMultipleFieldValuesForObject (Uint1 choice, Pointer data, FieldTypePtr field, StringConstraintPtr scp, BatchExtraPtr batch_extra)
+{
+  CharPtr str = NULL;
+  ValNodePtr      val_list = NULL;
+
+  if (data == NULL || field == NULL || field->data.ptrvalue == NULL) return FALSE;
+
+  if (field->choice == FieldType_source_qual) {
+    val_list = GetMultipleSourceQualsFromBioSource (GetBioSourceFromObject (choice, data), (SourceQualChoicePtr) field->data.ptrvalue, scp);
+  } else {
+    str = GetFieldValueForObjectEx (choice, data, field, scp, batch_extra);
+    if (str != NULL) {
+      ValNodeAddPointer (&val_list, 0, str);
+    }
+  }
+  return val_list;
+}
+
+
+NLM_EXTERN Boolean GBBlockIsCompletelyEmpty (GBBlockPtr gb)
 {
   if (gb != NULL
       && gb->extra_accessions == NULL
@@ -12493,6 +13832,7 @@ static Boolean DoesObjectMatchStringConstraint (Uint1 choice, Pointer data, Stri
   ValNodePtr          vnp;
   Boolean             all_match = TRUE, any_match = FALSE, rval;
   BioseqPtr           protbsp;
+  ImpFeatPtr          imp;
 
   if (data == NULL) return FALSE;
   if (scp == NULL) return TRUE;
@@ -12573,6 +13913,10 @@ static Boolean DoesObjectMatchStringConstraint (Uint1 choice, Pointer data, Stri
               search_txt = MemFree (search_txt);
             }
           }
+        } else if (!ohsd.found && sfp != NULL 
+                   && sfp->data.choice == SEQFEAT_IMP 
+                   && (imp = (ImpFeatPtr) sfp->data.value.ptrvalue) != NULL) {
+          ohsd.found = DoesSingleStringMatchConstraint (imp->key, ohsd.scp);
         }
       }
     }
@@ -12908,7 +14252,7 @@ static Boolean DoesCGPSetMatchQualConstraint (CGPSetPtr c, CDSGeneProtQualConstr
       str1 = GetFieldValueFromCGPSet (c, constraint->field1->data.intvalue, constraint->constraint);
       if (str1 == NULL) {
         if (constraint->constraint->not_present) {
-          str1 = GetFieldValueFromCGPSet (c, constraint->field1->data.intvalue, constraint->constraint);
+          str1 = GetFieldValueFromCGPSet (c, constraint->field1->data.intvalue, NULL);
           if (str1 == NULL) {
             rval = TRUE;
           }
@@ -12921,7 +14265,7 @@ static Boolean DoesCGPSetMatchQualConstraint (CGPSetPtr c, CDSGeneProtQualConstr
       str2 = GetFieldValueFromCGPSet (c, constraint->field2->data.intvalue, constraint->constraint);
       if (str2 == NULL) {
         if (constraint->constraint->not_present) {
-          str2 = GetFieldValueFromCGPSet (c, constraint->field2->data.intvalue, constraint->constraint);
+          str2 = GetFieldValueFromCGPSet (c, constraint->field2->data.intvalue, NULL);
           if (str2 == NULL) {
             rval = TRUE;
           }
@@ -13258,11 +14602,49 @@ NLM_EXTERN Boolean IsSequenceConstraintEmpty (SequenceConstraintPtr constraint)
   if (constraint->seqtype != NULL && constraint->seqtype->choice != SequenceConstraintMolTypeConstraint_any) return FALSE;
   if (constraint->feature != Feature_type_any) return FALSE;
   if (!IsStringConstraintEmpty (constraint->id)) return FALSE;
+  if (constraint->num_features != NULL) return FALSE;
   return TRUE;
 }
 
 
-static Boolean DoesSeqIDListMeetStringConstraint (SeqIdPtr sip, StringConstraintPtr string_constraint)
+static Boolean DoesTextMatchBankItId (SeqIdPtr sip, StringConstraintPtr scp)
+{
+  Boolean rval = FALSE;
+  Int4    text_len, offset;
+  CharPtr text, tmp;
+  DbtagPtr dbtag;
+
+  if (scp == NULL || (text = scp->match_text) == NULL || sip == NULL || sip->choice != SEQID_GENERAL 
+      || (dbtag = (DbtagPtr) sip->data.ptrvalue) == NULL
+      || StringCmp (dbtag->db, "BankIt") != 0
+      || dbtag->tag == NULL) {
+    return FALSE;
+  }
+  text_len = StringLen (scp->match_text);
+  if (text_len > 6 && StringNICmp (text, "BankIt", 6) == 0) {
+    text += 6;
+    text += StrSpn (text, ":/ ");
+  }
+
+  text = StringSave (text);
+  tmp = scp->match_text;
+  scp->match_text = text;
+  rval = DoesObjectIdMatchStringConstraint (dbtag->tag, scp);
+  if (!rval) {
+    offset = StringCSpn (text, "/ ");
+    if (text[offset] != 0) {
+      text[offset] = '_';
+      rval = DoesObjectIdMatchStringConstraint (dbtag->tag, scp);
+    }
+  }
+  text = MemFree (text);
+  scp->match_text = tmp;
+
+  return rval;
+}
+
+
+NLM_EXTERN Boolean DoesSeqIDListMeetStringConstraint (SeqIdPtr sip, StringConstraintPtr string_constraint)
 {
   CharPtr    id;
   CharPtr    cp, cp_dst;
@@ -13322,7 +14704,14 @@ static Boolean DoesSeqIDListMeetStringConstraint (SeqIdPtr sip, StringConstraint
         {
           *cp = 0;
           match = DoesSingleStringMatchConstraint (id, string_constraint);
+          *cp = '.';
+        }
         }
+
+      /* Bankit? */
+      if (!match && DoesTextMatchBankItId (sip, string_constraint)) 
+      {
+        match = TRUE;
       }       
     }
     id = MemFree (id);
@@ -13418,6 +14807,7 @@ static Boolean DoesSequenceMatchSequenceConstraint (BioseqPtr bsp, SequenceConst
   SeqDescrPtr sdp;
   SeqMgrDescContext dcontext;
   MolInfoPtr mip;
+  Int4       num_features = 0;
   
   if (bsp == NULL) return FALSE;
   if (IsSequenceConstraintEmpty (constraint)) return TRUE;
@@ -13467,6 +14857,38 @@ static Boolean DoesSequenceMatchSequenceConstraint (BioseqPtr bsp, SequenceConst
   if (!IsStringConstraintEmpty (constraint->id) && !DoesSeqIDListMeetStringConstraint (bsp->id, constraint->id)) {
     return FALSE;
   }
+
+  if (constraint->num_features != NULL) {
+    for (sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
+         sfp != NULL;
+         sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext)) {
+      num_features++;
+      /* note - break out of loop or return as soon as we know constraint
+       * succeeds or passes - no need to iterate through all features
+       */
+      if (constraint->num_features->choice == QuantityConstraint_equals 
+          && num_features > constraint->num_features->data.intvalue) {
+        return FALSE;
+      } else if (constraint->num_features->choice == QuantityConstraint_greater_than
+                 && num_features > constraint->num_features->data.intvalue) {
+        break;
+      } else if (constraint->num_features->choice == QuantityConstraint_less_than
+                 && num_features >= constraint->num_features->data.intvalue) {
+        return FALSE;
+      }
+    }
+    if (constraint->num_features->choice == QuantityConstraint_equals 
+        && num_features != constraint->num_features->data.intvalue) {
+      return FALSE;
+    } else if (constraint->num_features->choice == QuantityConstraint_greater_than
+               && num_features <= constraint->num_features->data.intvalue) {
+      return FALSE;
+    } else if (constraint->num_features->choice == QuantityConstraint_less_than
+               && num_features >= constraint->num_features->data.intvalue) {
+      return FALSE;
+    }
+  }
+
   return TRUE;
 }
 
@@ -13644,7 +15066,9 @@ NLM_EXTERN Boolean IsPublicationConstraintEmpty (PublicationConstraintPtr constr
   if (constraint == NULL
       || (constraint->type == Pub_type_any
           && (constraint->field == NULL 
-              || IsStringConstraintEmpty (constraint->field->constraint)))) {
+              || IsStringConstraintEmpty (constraint->field->constraint))
+          && (constraint->special_field == NULL 
+              || constraint->special_field->constraint == NULL))) {
     rval = TRUE;
   }
   return rval;
@@ -13740,32 +15164,20 @@ NLM_EXTERN Int4 GetPubMLStatus (PubPtr the_pub)
 }
 
 
-static Boolean DoesPubMatchPublicationConstraint (PubdescPtr pdp, PublicationConstraintPtr constraint)
+static Boolean DoesPubFieldMatch (PubdescPtr pdp, PubFieldConstraintPtr field)
 {
-  Boolean type_ok = TRUE, rval = FALSE, match_all = TRUE;
+  Boolean rval = FALSE, match_all = TRUE;
   PubPtr pub;
   CharPtr tmp;
 
   if (pdp == NULL) return FALSE;
-  if (IsPublicationConstraintEmpty (constraint)) return TRUE;
+  if (field == NULL) return TRUE;
 
-  if (constraint->type != Pub_type_any) {
-    type_ok = FALSE;
-    for (pub = pdp->pub; pub != NULL && !type_ok; pub = pub->next) {
-      if (GetPubMLStatus (pub) == constraint->type) {
-        type_ok = TRUE;
-      }
-    }
-  }
-  if (type_ok) {
-    if (constraint->field == NULL) {
-      rval = TRUE;
-    } else {
-      if (constraint->field->constraint->not_present) {
+  if (field->constraint->not_present) {
         match_all = TRUE;
         for (pub = pdp->pub; pub != NULL && match_all; pub = pub->next) {
-          tmp = GetPubFieldFromPub (pub, constraint->field->field, NULL);
-          if (!DoesStringMatchConstraint (tmp, constraint->field->constraint)) {
+      tmp = GetPubFieldFromPub (pub, field->field, NULL);
+      if (!DoesStringMatchConstraint (tmp, field->constraint)) {
             match_all = FALSE;
           }
           tmp = MemFree (tmp);
@@ -13773,14 +15185,79 @@ static Boolean DoesPubMatchPublicationConstraint (PubdescPtr pdp, PublicationCon
         rval = match_all;
       } else {
         for (pub = pdp->pub; pub != NULL && !rval; pub = pub->next) {
-          tmp = GetPubFieldFromPub (pub, constraint->field->field, constraint->field->constraint);
+      tmp = GetPubFieldFromPub (pub, field->field, field->constraint);
           if (tmp != NULL) {
             rval = TRUE;
           }
           tmp = MemFree (tmp);
         }
       }
+  return rval;
+}
+
+
+static Boolean DoesPubFieldSpecialMatch (PubdescPtr pdp, PubFieldSpecialConstraintPtr field)
+{
+  Boolean rval = FALSE, match_all = TRUE;
+  PubPtr pub;
+  CharPtr tmp;
+
+  if (pdp == NULL) return FALSE;
+  if (field == NULL) return TRUE;
+
+  if (field->constraint->choice == PubFieldSpecialConstraintType_is_present) {
+    for (pub = pdp->pub; pub != NULL && !rval; pub = pub->next) {
+      tmp = GetPubFieldFromPub (pub, field->field, NULL);
+      if (!StringHasNoText (tmp)) {
+        /* at least one is present and non-empty */
+        rval = TRUE;
+      }
+      tmp = MemFree (tmp);
+    }    
+  } else if (field->constraint->choice == PubFieldSpecialConstraintType_is_not_present) {
+    rval = TRUE;
+    for (pub = pdp->pub; pub != NULL && rval; pub = pub->next) {
+      tmp = GetPubFieldFromPub (pub, field->field, NULL);
+      if (!StringHasNoText (tmp)) {
+        /* at least one is present and non-empty */
+        rval = FALSE;
+      }
+      tmp = MemFree (tmp);
+    }    
+  } else if (field->constraint->choice == PubFieldSpecialConstraintType_is_all_caps) {
+    rval = TRUE;
+    for (pub = pdp->pub; pub != NULL && rval; pub = pub->next) {
+      tmp = GetPubFieldFromPub (pub, field->field, NULL);
+      if (!IsAllCaps (tmp)) {
+        /* at least one is not all caps */
+        rval = FALSE;
+      }
+      tmp = MemFree (tmp);
+    }    
+  }
+
+  return rval;
+}
+
+
+static Boolean DoesPubMatchPublicationConstraint (PubdescPtr pdp, PublicationConstraintPtr constraint)
+{
+  Boolean type_ok = TRUE, rval = FALSE;
+  PubPtr pub;
+
+  if (pdp == NULL) return FALSE;
+  if (IsPublicationConstraintEmpty (constraint)) return TRUE;
+
+  if (constraint->type != Pub_type_any) {
+    type_ok = FALSE;
+    for (pub = pdp->pub; pub != NULL && !type_ok; pub = pub->next) {
+      if (GetPubMLStatus (pub) == constraint->type) {
+        type_ok = TRUE;
+      }
+    }
     }
+  if (type_ok) {
+    rval = DoesPubFieldMatch (pdp, constraint->field) && DoesPubFieldSpecialMatch (pdp, constraint->special_field);
   }
   return rval;
 }
@@ -14634,7 +16111,6 @@ AdjustCGPObjectListForMatPeptides
  ConstraintChoiceSetPtr constraints)
 {
   ConstraintChoiceSetPtr mat_peptide_constraints = NULL;
-  Boolean found_matpeptide_constraint = FALSE;
   ValNodePtr vnp, vnp_prev, vnp_next;
   ValNodePtr m_vnp, m_vnp_prev, m_vnp_next, mat_peptide_list;
   CGPSetPtr  cdsp;
@@ -15028,6 +16504,7 @@ NLM_EXTERN Int4 DoConvertActionToObjectListEx (ConvertActionPtr action, ValNodeP
         if (action->strip_name) {
           RemoveFieldNameFromString (field_name, str);
         }
+        FixCapitalizationInString(&str, action->capitalization, NULL);
     
         if (SetFieldValueForObjectEx (vnp->choice, vnp->data.ptrvalue, field_to, NULL, str, action->existing_text, batch_extra)
             && (action->keep_original || RemoveFieldValueForObject (vnp->choice, vnp->data.ptrvalue, field_from, &remove_constraint))) {
@@ -15159,8 +16636,8 @@ NLM_EXTERN Int4 DoRemoveActionToObjectList (RemoveActionPtr action, ValNodePtr o
 NLM_EXTERN Int4 DoParseActionToObjectListEx (AECRParseActionPtr action, ValNodePtr object_list, Boolean also_change_mrna, StringConstraintPtr scp, BatchExtraPtr batch_extra)
 {
   ValNodePtr vnp;
-  CharPtr    str1, str2, cp;
-  Int4       len, num_succeed = 0, diff;
+  CharPtr    str1, str2, cp, tmp;
+  Int4       len, num_succeed = 0, diff, left_len, right_len;
   FieldTypePtr field_from, field_to;
 
   if (action == NULL || object_list == NULL) return 0;
@@ -15175,13 +16652,28 @@ NLM_EXTERN Int4 DoParseActionToObjectListEx (AECRParseActionPtr action, ValNodeP
         cp = FindTextPortionLocationInString (str1, action->portion);
         if (cp != NULL) {
           len = StringLen (str2);
-          if (action->remove_left &&action->portion != NULL && action->portion->left_text != NULL && !action->portion->include_left) {
-            diff = StringLen (action->portion->left_text);
-            cp -= diff;
-            len += diff;
-          }
-          if (action->remove_right &&action->portion != NULL && action->portion->right_text != NULL && !action->portion->include_right) {
-            diff = StringLen (action->portion->right_text);
+          tmp = cp;
+          if (action->portion != NULL && !IsTextMarkerEmpty (action->portion->left_marker) 
+              && (tmp = FindTextMarker (str1, &left_len, action->portion->left_marker, 
+                                       action->portion->case_sensitive, action->portion->whole_word)) != NULL) {            
+            if (action->portion->include_left) {
+              /* adjust */
+            } else if (!action->portion->include_left) {
+              /* adjust */
+              if (action->remove_left) {
+                len += left_len;
+              } else {
+                cp += left_len;
+              }
+            }
+          }
+          if (!IsTextMarkerEmpty (action->portion->right_marker)
+              && action->remove_right 
+              && !action->portion->include_right
+              && action->portion != NULL
+              && (tmp = FindTextMarker (tmp, &right_len, action->portion->right_marker, 
+                                        action->portion->case_sensitive, action->portion->whole_word)) != NULL) {
+            diff = right_len;
             len += diff;
           }
           StringCpy (cp, cp + len);
@@ -15661,7 +17153,7 @@ static void GetRnaQualFieldListForAECRSampleCallback (SeqFeatPtr sfp, Pointer us
   RnaFeatTypePtr type;
   RnaRefPtr      rrp;
   RnaQualPtr     rq;
-  GBQualPtr      gbqual;
+  RNAGenPtr      rgp;
   GeneRefPtr     grp = NULL;
   SeqFeatPtr     gene = NULL;
   SeqMgrFeatContext fcontext;
@@ -15685,18 +17177,13 @@ static void GetRnaQualFieldListForAECRSampleCallback (SeqFeatPtr sfp, Pointer us
     rq->type = AsnIoMemCopy (type, (AsnReadFunc) RnaFeatTypeAsnRead, (AsnWriteFunc) RnaFeatTypeAsnWrite);
     rq->field = Rna_field_product;
     ValNodeAddPointer ((ValNodePtr PNTR) userdata, FieldType_rna_field, rq);
-  } else if (type->choice == RnaFeatType_ncRNA || type->choice == RnaFeatType_tmRNA) {
-    gbqual = sfp->qual;
-    while (gbqual != NULL && StringCmp (gbqual->qual, "product") != 0) {
-      gbqual = gbqual->next;
-    }
-    if (gbqual != NULL) {
+  } else if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL
+    && !StringHasNoText (rgp->product)) {
       rq = RnaQualNew ();
       rq->type = AsnIoMemCopy (type, (AsnReadFunc) RnaFeatTypeAsnRead, (AsnWriteFunc) RnaFeatTypeAsnWrite);
       rq->field = Rna_field_product;
       ValNodeAddPointer ((ValNodePtr PNTR) userdata, FieldType_rna_field, rq);
     }
-  }
 
   /* add comment if present */
   if (!StringHasNoText (sfp->comment)) {
@@ -15722,18 +17209,14 @@ static void GetRnaQualFieldListForAECRSampleCallback (SeqFeatPtr sfp, Pointer us
   }
 
   /* add ncRNA class if appropriate and present */
-  if (type->choice == RnaFeatType_ncRNA) {
-    gbqual = sfp->qual;
-    while (gbqual != NULL && StringCmp (gbqual->qual, "ncRNA_class") != 0) {
-      gbqual = gbqual->next;
-    }
-    if (gbqual != NULL) {
+  if (type->choice == RnaFeatType_ncRNA 
+      && rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL
+      && !StringHasNoText (rgp->_class)) {
       rq = RnaQualNew ();
       rq->type = AsnIoMemCopy (type, (AsnReadFunc) RnaFeatTypeAsnRead, (AsnWriteFunc) RnaFeatTypeAsnWrite);
       rq->field = Rna_field_ncrna_class;
       ValNodeAddPointer ((ValNodePtr PNTR) userdata, FieldType_rna_field, rq);
     }
-  }
 
   /* add transcript ID if present */
   if (sfp->product != NULL) {
@@ -16820,6 +18303,56 @@ GetStructuredCommentSourcesForBioseq
 }
 
 
+static void GetFlatFileSourcesForBioseq
+(BioseqPtr       bsp,
+ TextPortionPtr  tp,
+ ValNodePtr PNTR source_list)
+
+{
+  SeqEntryPtr      sep;
+  Asn2gbJobPtr     ajp;
+  Int4             index;
+  ErrSev           level;
+  CharPtr          string, str;
+  ParseSourceInfoPtr psip;
+
+  if (bsp == NULL || source_list == NULL)
+  {
+    return;
+  }
+
+  sep = SeqMgrGetSeqEntryForData (bsp);
+  if (sep == NULL) {
+    return;
+  }
+  
+  level = ErrSetMessageLevel (SEV_MAX);
+
+  ajp = asn2gnbk_setup (bsp, NULL, NULL, (FmtType)GENBANK_FMT, SEQUIN_MODE, NORMAL_STYLE, 0, 0, 0, NULL);
+  if (ajp != NULL) {
+    for (index = 0; index < ajp->numParagraphs; index++) {
+      string = asn2gnbk_format (ajp, (Int4) index);
+      if (string != NULL && *string != '\0') {
+        CompressSpaces (string);
+        str = GetTextPortionFromString (string, tp);
+        if (str != NULL) {
+          psip = ParseSourceInfoNew (bsp, NULL, NULL, NULL, str);
+          if (psip == NULL) {
+            str = MemFree (str);
+          } else {
+            ValNodeAddPointer (source_list, 0, psip);
+          }
+        }
+      } 
+      MemFree (string);
+    }
+    asn2gnbk_cleanup (ajp);
+  }
+
+  ErrSetMessageLevel (level);    
+}
+
+
 const CharPtr nomial_keywords[] = {
 "f. sp. ",
 "var.",
@@ -16979,6 +18512,9 @@ static void FindParseSourceBioseqCallback (BioseqPtr bsp, Pointer userdata)
         GetDeflineSourcesForBioseq (bsp, psp->portion, &(psp->src_list));
       }
       break;
+    case ParseSrc_flatfile:
+      GetFlatFileSourcesForBioseq (bsp, psp->portion, &(psp->src_list));
+      break;
     case ParseSrc_local_id:
       if (! ISA_aa (bsp->mol) && bsp->repr != Seq_repr_seg) {
         GetLocalIDSourcesForBioseq (bsp, psp->portion, &(psp->src_list));
@@ -17033,7 +18569,7 @@ static void SetToUpper (CharPtr cp)
 }
 
 
-static void 
+NLM_EXTERN void 
 FixCapitalizationInString 
 (CharPtr PNTR pTitle,
  Uint2 capitalization,
@@ -17057,6 +18593,11 @@ FixCapitalizationInString
       FixAbbreviationsInElement (pTitle);
       FixOrgNamesInString (*pTitle, org_names);
       break;
+    case Cap_change_firstcaprestnochange:
+      if (*pTitle != NULL && isalpha (**pTitle)) {
+        **pTitle = toupper (**pTitle);
+      }
+      break;
   }
 }
 
@@ -17453,7 +18994,7 @@ static void PropagateSourceOnSegSetForParse (ValNodePtr parse_source_list)
 
 
 
-static CharPtr GetDBxrefFromBioSource (BioSourcePtr biop, CharPtr db_name)
+NLM_EXTERN CharPtr GetDBxrefFromBioSource (BioSourcePtr biop, CharPtr db_name)
 {
   CharPtr    rval = NULL;
   ValNodePtr vnp;
@@ -17462,9 +19003,9 @@ static CharPtr GetDBxrefFromBioSource (BioSourcePtr biop, CharPtr db_name)
   if (biop == NULL || biop->org == NULL || StringHasNoText (db_name)) {
     return NULL;
   }
-  for (vnp = biop->org->db; vnp != NULL && rval != NULL; vnp = vnp->next) {
+  for (vnp = biop->org->db; vnp != NULL && rval == NULL; vnp = vnp->next) {
     dbtag = (DbtagPtr) vnp->data.ptrvalue;
-    if (dbtag != NULL && StringCmp (db_name, dbtag->db)) {
+    if (dbtag != NULL && StringCmp (db_name, dbtag->db) == 0) {
       rval = GetObjectIdString (dbtag->tag);
     }
   }
@@ -17472,7 +19013,7 @@ static CharPtr GetDBxrefFromBioSource (BioSourcePtr biop, CharPtr db_name)
 }
 
 
-static Boolean SetDBxrefForBioSource (BioSourcePtr biop, CharPtr db_name, CharPtr str, Uint2 existing_text)
+NLM_EXTERN Boolean SetDBxrefForBioSource (BioSourcePtr biop, CharPtr db_name, CharPtr str, Uint2 existing_text)
 {
   ValNodePtr    dbx;
   DbtagPtr      dbtag;
@@ -17524,6 +19065,50 @@ static Boolean SetDBxrefForBioSource (BioSourcePtr biop, CharPtr db_name, CharPt
 }
 
 
+NLM_EXTERN Boolean RemoveDBxrefForBioSource (BioSourcePtr biop, CharPtr db_name, StringConstraintPtr scp)
+{
+  ValNodePtr    dbx, prev = NULL, dbx_next;
+  DbtagPtr      dbtag;
+  CharPtr       str;
+  Boolean       found = FALSE;
+
+  if (biop == NULL || StringHasNoText (db_name)) {
+    return FALSE;
+  }
+
+  if (biop->org == NULL)
+  {
+    biop->org = OrgRefNew();
+  }
+  dbx = biop->org->db;
+  for (dbx = biop->org->db; dbx != NULL; dbx = dbx_next) 
+  {
+    dbx_next = dbx->next;
+    dbtag = (DbtagPtr) dbx->data.ptrvalue;
+    str = NULL;
+    if (dbtag != NULL && dbtag->tag != NULL
+      && StringCmp (dbtag->db, db_name) == 0
+      && (scp == NULL || ((str = GetDbtagString(dbtag)) != NULL && DoesStringMatchConstraint (str, scp))))
+    {
+      if (prev == NULL) {
+        biop->org->db = dbx->next;
+      } else {
+        prev->next = dbx->next;
+      }
+      dbx->data.ptrvalue = DbtagFree (dbx->data.ptrvalue);
+      dbx = ValNodeFree (dbx);
+      found = TRUE;
+    }
+    else
+    {
+      prev = dbx;
+    }
+    str = MemFree (str);
+  }
+  return found;
+}
+
+
 static Int4 SetFieldForDestList (ValNodePtr dest_list, ParseDestPtr field, CharPtr str, Uint2 existing_text)
 {
   ValNodePtr vnp;
@@ -17882,7 +19467,7 @@ static void CreateDataForFeature (SeqFeatPtr sfp, Int4 feature_type)
   Int4 featdef, seqfeattype;
   CharPtr    label = NULL;
   RnaRefPtr  rrp;
-  GBQualPtr  gbq;
+  RNAGenPtr  rgp;
   ImpFeatPtr ifp;
 
   featdef = GetFeatdefFromFeatureType (feature_type);
@@ -17914,30 +19499,30 @@ static void CreateDataForFeature (SeqFeatPtr sfp, Int4 feature_type)
           rrp->type = RNA_TYPE_rRNA;
           break;
         case FEATDEF_snRNA:
-          rrp->type = RNA_TYPE_other;
-          rrp->ext.choice = 1;
-          rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-          gbq = GBQualNew ();
-          gbq->qual = StringSave ("ncRNA_class");
-          gbq->val = StringSave ("snRNA");
+          rrp->type = RNA_TYPE_ncRNA;
+          SetncRNAClass (rrp, NULL, "snRNA", ExistingTextOption_replace_old);
           break;
         case FEATDEF_scRNA:
-          rrp->type = RNA_TYPE_other;
-          rrp->ext.choice = 1;
-          rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-          gbq = GBQualNew ();
-          gbq->qual = StringSave ("ncRNA_class");
-          gbq->val = StringSave ("scRNA");
+          rrp->type = RNA_TYPE_ncRNA;
+          SetncRNAClass (rrp, NULL, "scRNA", ExistingTextOption_replace_old);
           break;
         case FEATDEF_tmRNA:
-          rrp->type = RNA_TYPE_other;
-          rrp->ext.choice = 1;
-          rrp->ext.value.ptrvalue = StringSave ("tmRNA");
+          rrp->type = RNA_TYPE_tmRNA;
+          rgp = RNAGenNew ();
+          rrp->ext.choice = 3;
+          rrp->ext.value.ptrvalue = rgp;
           break;
         case FEATDEF_ncRNA:
-          rrp->type = RNA_TYPE_other;
-          rrp->ext.choice = 1;
-          rrp->ext.value.ptrvalue = StringSave ("ncRNA");
+          rrp->type = RNA_TYPE_ncRNA;
+          rgp = RNAGenNew ();
+          rrp->ext.choice = 3;
+          rrp->ext.value.ptrvalue = rgp;
+          break;
+        case FEATDEF_otherRNA:
+          rrp->type = RNA_TYPE_misc_RNA;
+          rgp = RNAGenNew();
+          rrp->ext.choice = 3;
+          rrp->ext.value.ptrvalue = rgp;
           break;
       }
       break;
@@ -17970,10 +19555,14 @@ static SeqLocPtr LocationFromApplyFeatureAction (BioseqPtr bsp, ApplyFeatureActi
       to = MAX (l->from, l->to) - 1;
       slp = SeqLocIntNew (from, to, strand, SeqIdFindWorst (bsp->id));
     }
+    SetSeqLocPartial (slp, action->partial5, action->partial3);
   } else if (action->location->choice == LocationChoice_whole_sequence) {
     slp = SeqLocIntNew (0, bsp->length - 1, strand, SeqIdFindWorst (bsp->id));
-  }
   SetSeqLocPartial (slp, action->partial5, action->partial3);
+  } else if (action->location->choice == LocationChoice_point) {
+    AddSeqLocPoint (&slp, SeqIdStripLocus (SeqIdDup (SeqIdFindBest (bsp->id, 0))),
+                    action->location->data.intvalue, FALSE, TRUE, strand);
+  }
   return slp;
 }
 
@@ -18165,60 +19754,41 @@ static void AdjustProteinSequenceForReadingFrame (SeqFeatPtr cds)
 }
 
 
-static Int4 ApplyApplyFeatureActionToSeqEntry (ApplyFeatureActionPtr action, SeqEntryPtr sep)
+NLM_EXTERN SeqFeatPtr 
+ApplyOneFeatureToBioseq 
+(BioseqPtr bsp, 
+ Uint1 featdef, 
+ SeqLocPtr slp, 
+ ValNodePtr fields, 
+ ValNodePtr src_fields,
+ Boolean    add_mrna)
 {
-  ValNodePtr bsp_list = NULL, vnp, field_vnp;
-  Int4       featdef, seqfeattype;
-  BioseqPtr  bsp;
-  SeqFeatPtr sfp;
-  SeqLocPtr  slp;
+  Int4 seqfeattype;
+  SeqFeatPtr sfp, gene = NULL, mrna = NULL;
   FeatQualLegalValPtr q;
   FeatureField f;
-  SeqIdPtr   sip;
-  SeqFeatPtr gene;
-  Int4       num_created = 0;
-
-  if (sep == NULL || action == NULL) return 0;
-
-  /* first, get list of Bioseqs to apply features to */
-  /* relevant values : seq_list, add_redundant, apply_to_parts, only_seg_num */
-  if (action->seq_list != NULL && action->seq_list->choice == SequenceListChoice_list) {
-    for (vnp = action->seq_list->data.ptrvalue; vnp != NULL; vnp = vnp->next) {
-      sip = CreateSeqIdFromText (vnp->data.ptrvalue, sep);
-      bsp = BioseqFind (sip);
-      if (bsp != NULL) {
-        AddSequenceOrParts (action, bsp, &bsp_list);
-      }
-    }  
-  } else {
-    AddSequenceOrPartsFromSeqEntry (action, sep, &bsp_list);
-  }
+  ValNodePtr field_vnp;
+  Int4       feature_type;
 
-  /* now add feature to each bioseq in list */
-  for (vnp = bsp_list; vnp != NULL; vnp = vnp->next) {
-    bsp = vnp->data.ptrvalue;
-    if (bsp == NULL) continue;
-    featdef = GetFeatdefFromFeatureType (action->type);
     seqfeattype = FindFeatFromFeatDefType (featdef);
-    slp = LocationFromApplyFeatureAction (bsp, action);
     sfp = CreateNewFeatureOnBioseq (bsp, seqfeattype, slp);
-    if (sfp == NULL) continue;
-    CreateDataForFeature (sfp, action->type);
+  if (sfp == NULL) return NULL;
+  feature_type = GetFeatureTypeFromFeatdef(featdef);
+  CreateDataForFeature (sfp, feature_type);
     /* any extra actions */
-    switch (action->type) {
-      case Feature_type_cds :
+  switch (featdef) {
+    case FEATDEF_CDS :
         ExtraCDSCreationActions (sfp, GetBestTopParentForData (bsp->idx.entityID, bsp));
         break;
-      case Feature_type_source :
-        if (action->src_fields != NULL) {
+    case FEATDEF_source :
+      if (src_fields != NULL) {
           sfp->data.value.ptrvalue = ImpFeatFree (sfp->data.value.ptrvalue);
           sfp->data.choice = SEQFEAT_BIOSRC;
-          sfp->data.value.ptrvalue = BioSourceFromSourceQualVals (action->src_fields);
+        sfp->data.value.ptrvalue = BioSourceFromSourceQualVals (src_fields);
         }
         break;
     }
-    gene = NULL;
-    for (field_vnp = action->fields; field_vnp != NULL; field_vnp = field_vnp->next) {
+  for (field_vnp = fields; field_vnp != NULL; field_vnp = field_vnp->next) {
       q = (FeatQualLegalValPtr) field_vnp->data.ptrvalue;
       if (q != NULL) {
         f.field = ValNodeNew(NULL);
@@ -18234,20 +19804,75 @@ static Int4 ApplyApplyFeatureActionToSeqEntry (ApplyFeatureActionPtr action, Seq
           f.type = Feature_type_gene;
           SetQualOnFeature (gene, &f, NULL, q->val, ExistingTextOption_replace_old);
         } else {
-          f.type = action->type;
+        f.type = feature_type;
           SetQualOnFeature (sfp, &f, NULL, q->val, ExistingTextOption_replace_old);
         }
       }
     }
-    if (action->type == Feature_type_cds) {
+  if (featdef == FEATDEF_CDS) {
       /* retranslate, to account for change in reading frame */
       AdjustProteinSequenceForReadingFrame (sfp);
       /* after the feature has been created, then adjust it for gaps */
       /* Note - this step may result in multiple coding regions being created. */
       AdjustCDSLocationsForUnknownGapsCallback (sfp, NULL);
+    if (add_mrna) {
+      slp = SeqLocCopy (slp);
+      mrna = CreateNewFeatureOnBioseq (bsp, SEQFEAT_RNA, slp);
+      CreateDataForFeature (mrna, Feature_type_mRNA);
+      for (field_vnp = fields; field_vnp != NULL; field_vnp = field_vnp->next) {
+        q = (FeatQualLegalValPtr) field_vnp->data.ptrvalue;
+        if (q != NULL && q->qual == Feat_qual_legal_product) {
+          f.field = ValNodeNew(NULL);
+          f.field->next = NULL;
+          f.field->choice = FeatQualChoice_legal_qual;
+          f.field->data.intvalue = q->qual;        
+          f.type = Feature_type_mRNA;
+          SetQualOnFeature (mrna, &f, NULL, q->val, ExistingTextOption_replace_old);
+        }
+      }
+    }
     }
+  return sfp;
+}
+
+
+static Int4 ApplyApplyFeatureActionToSeqEntry (ApplyFeatureActionPtr action, SeqEntryPtr sep)
+{
+  ValNodePtr bsp_list = NULL, vnp;
+  Int4       featdef;
+  BioseqPtr  bsp;
+  SeqFeatPtr sfp;
+  SeqLocPtr  slp;
+  SeqIdPtr   sip;
+  Int4       num_created = 0;
+
+  if (sep == NULL || action == NULL) return 0;
+
+  /* first, get list of Bioseqs to apply features to */
+  /* relevant values : seq_list, add_redundant, apply_to_parts, only_seg_num */
+  if (action->seq_list != NULL && action->seq_list->choice == SequenceListChoice_list) {
+    for (vnp = action->seq_list->data.ptrvalue; vnp != NULL; vnp = vnp->next) {
+      sip = CreateSeqIdFromText (vnp->data.ptrvalue, sep);
+      bsp = BioseqFind (sip);
+      if (bsp != NULL) {
+        AddSequenceOrParts (action, bsp, &bsp_list);
+      }
+    }  
+  } else {
+    AddSequenceOrPartsFromSeqEntry (action, sep, &bsp_list);
+  }
+
+  /* now add feature to each bioseq in list */
+  for (vnp = bsp_list; vnp != NULL; vnp = vnp->next) {
+    bsp = vnp->data.ptrvalue;
+    if (bsp == NULL) continue;
+    featdef = GetFeatdefFromFeatureType (action->type);
+    slp = LocationFromApplyFeatureAction (bsp, action);
+    sfp = ApplyOneFeatureToBioseq (bsp, featdef, slp, action->fields, action->src_fields, action->add_mrna);
+    if (sfp != NULL) {
     num_created++;
   }  
+  }  
   return num_created;
 }
 
@@ -18990,14 +20615,37 @@ NLM_EXTERN Boolean IsConversionSupported (Uint2 type_from, Uint2 type_to)
 }
 
 
+static CharPtr GetFeatureTextForLogging (SeqFeatPtr sfp)
+{
+  ValNode    vn;
+  Int4       len;
+  CharPtr    txt = NULL;
+
+  MemSet (&vn, 0, sizeof (ValNode));
+  vn.choice = OBJ_SEQFEAT;
+  vn.data.ptrvalue = sfp;
+  txt = GetDiscrepancyItemText (&vn);
+  if (txt == NULL) {
+    txt = StringSave ("(null)");
+  } else {
+    len = StringLen (txt);
+    if (len > 0 && txt[len - 1] == '\n') {
+      txt[len - 1] = 0;
+    }
+  }
+  return txt;
+}
+
 
-static Int4 ApplyConvertFeatureActionToSeqEntry (ConvertFeatureActionPtr action, SeqEntryPtr sep)
+static Int4 ApplyConvertFeatureActionToSeqEntry (ConvertFeatureActionPtr action, SeqEntryPtr sep, FILE *log_fp)
 {
   ConvertAndRemoveFeatureCollectionData d;
   ValNodePtr vnp;
   SeqFeatPtr sfp, sfp_copy;
   Int4       num_affected = 0, table_line;
   Uint2      seqfeat_from, featdef_from, seqfeat_to, featdef_to;
+  /* variables for logging */
+  CharPtr    txt_old, txt_new;
 
   if (action == NULL) return 0;
 
@@ -19030,6 +20678,18 @@ static Int4 ApplyConvertFeatureActionToSeqEntry (ConvertFeatureActionPtr action,
         if (!action->leave_original) {
           sfp->idx.deleteme = TRUE;
         }
+        if (log_fp != NULL) {
+          txt_old = GetFeatureTextForLogging (sfp);
+          txt_new = GetFeatureTextForLogging (sfp_copy);
+          if (action->leave_original) {
+            fprintf (log_fp, "Added new feature %s based on %s\n", txt_new, txt_old);
+          } else {
+            fprintf (log_fp, "Replaced feature %s with %s\n", txt_old, txt_new);
+          }
+          txt_old = MemFree (txt_old);
+          txt_new = MemFree (txt_new);
+        }
+        sfp_copy->idx.subtype = 0;
       } else {
         sfp_copy->idx.deleteme = TRUE;
       }
@@ -19526,6 +21186,38 @@ static Boolean ApplyConvertLocationToSeqFeat (Int4 convert_location, SeqFeatPtr
 }
 
 
+static Boolean ExtendSeqFeat5 (SeqFeatPtr sfp)
+{
+  BioseqPtr bsp;
+
+  if (sfp == NULL || (bsp = BioseqFindFromSeqLoc (sfp->location)) == NULL)
+  {
+    return FALSE;
+  }
+  if (ExtendSeqLocToEnd (sfp->location, bsp, TRUE) > 0) 
+  {
+    return TRUE;
+  }
+  else
+  {
+    return FALSE;
+  }
+}
+
+
+static Boolean ExtendSeqFeat3 (SeqFeatPtr sfp)
+{
+  BioseqPtr bsp;
+
+  if (sfp == NULL || (bsp = BioseqFindFromSeqLoc (sfp->location)) == NULL)
+  {
+    return FALSE;
+  }
+  ExtendSeqLocToEnd (sfp->location, bsp, FALSE);
+  return TRUE;
+}
+
+
 static Boolean ApplyLocationEditTypeToSeqFeat (ValNodePtr action, SeqFeatPtr sfp)
 {
   Boolean rval = FALSE;
@@ -19553,17 +21245,25 @@ static Boolean ApplyLocationEditTypeToSeqFeat (ValNodePtr action, SeqFeatPtr sfp
     case LocationEditType_convert:
       rval = ApplyConvertLocationToSeqFeat (action->data.intvalue, sfp);
       break;
+    case LocationEditType_extend_5:
+      rval = ExtendSeqFeat5 (sfp);
+      break;
+    case LocationEditType_extend_3:
+      rval = ExtendSeqFeat3 (sfp);
+      break;
   }
   return rval;
 }
 
 
-static Int4 ApplyEditFeatureLocationActionToSeqEntry (EditFeatureLocationActionPtr action, SeqEntryPtr sep)
+static Int4 ApplyEditFeatureLocationActionToSeqEntry (EditFeatureLocationActionPtr action, SeqEntryPtr sep, FILE *log_fp)
 {
   ConvertAndRemoveFeatureCollectionData d;
   ValNodePtr vnp;
   SeqFeatPtr sfp;
   Int4       num_affected = 0;
+  /* variables for logging */
+  CharPtr    old_loc = NULL, new_loc;
 
   if (action == NULL) return 0;
 
@@ -19574,8 +21274,19 @@ static Int4 ApplyEditFeatureLocationActionToSeqEntry (EditFeatureLocationActionP
   VisitFeaturesInSep (sep, &d, ConvertAndRemoveFeatureCollectionCallback);
   for (vnp = d.feature_list; vnp != NULL; vnp = vnp->next) {
     sfp = vnp->data.ptrvalue;
-    if (sfp != NULL && ApplyLocationEditTypeToSeqFeat (action->action, sfp)) {
+    if (sfp != NULL) {
+      if (log_fp != NULL) {
+        old_loc = SeqLocPrintUseBestID (sfp->location);
+      }
+      if (ApplyLocationEditTypeToSeqFeat (action->action, sfp)) {
       num_affected++;
+        if (log_fp != NULL) {
+          new_loc = SeqLocPrintUseBestID (sfp->location);
+          fprintf (log_fp, "Changed location %s to %s\n", old_loc, new_loc);
+          new_loc = MemFree (new_loc);
+        }
+      }
+      old_loc = MemFree (old_loc);
     }
   }
   return num_affected;
@@ -19848,16 +21559,7 @@ static void ApplyAutodefActionToSeqEntry (AutodefActionPtr action, SeqEntryPtr s
   Uint4                i;
   Int4                 defline_pos;
 
-  od.allow_semicolon_in_modifier = FALSE;
-  od.clone_isolate_HIV_rule_num = clone_isolate_HIV_rule_want_both;
-  od.exclude_aff = FALSE;
-  od.exclude_cf = FALSE;
-  od.exclude_nr = FALSE;
-  od.exclude_sp = TRUE;
-  od.include_country_extra = FALSE;
-  od.keep_paren = TRUE;
-  od.max_mods = -99;
-  od.use_labels = TRUE;
+  InitOrganismDescriptionModifiers (&od, NULL);
   od.use_modifiers = TRUE;
 
   modList = MemNew (NumDefLineModifiers () * sizeof (ModifierItemLocalData));
@@ -19903,46 +21605,340 @@ static void ApplyAutodefActionToSeqEntry (AutodefActionPtr action, SeqEntryPtr s
 }
 
 
-NLM_EXTERN void ApplyMacroToSeqEntry (SeqEntryPtr sep, ValNodePtr macro, Int4Ptr pNumFields, Int4Ptr pNumFeat)
+NLM_EXTERN Boolean IsFixPubCapsActionEmpty (FixPubCapsActionPtr action)
+{
+  if (action == NULL) {
+    return TRUE;
+  }
+  if (action->affiliation || action->authors || action->title) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+typedef struct fixpubcaps {
+  FixPubCapsActionPtr action;
+  ValNodePtr          orgnames;
+  Int4                num_fields;
+  ValNodePtr          object_list;
+} FixPubCapsData, PNTR FixPubCapsPtr;
+
+static void ApplyFixPubCapsCallback (PubdescPtr pdp, Pointer data)
+{
+  FixPubCapsPtr f;
+  CharPtr       orig, tmp;
+  ValNodePtr    pub;
+  AuthListPtr   alp = NULL;
+  ValNodePtr	  names;
+  AuthorPtr     ap, ap_orig;
+  AffilPtr      affil_orig;
+
+  f = (FixPubCapsPtr)data;
+  if (f == NULL || f->action == NULL) {
+    return;
+  }
+
+  if (f->action->title) {
+    for (pub = pdp->pub; pub != NULL; pub = pub->next) {
+      orig = GetPubFieldFromPub (pub, Publication_field_title, NULL);
+      if (orig != NULL) {
+        tmp = StringSave (orig);
+        FixCapitalizationInTitle (&tmp, TRUE, f->orgnames);
+        if (StringCmp (orig, tmp) != 0) {
+          SetPubFieldOnPub (pub, Publication_field_title, NULL, tmp, ExistingTextOption_replace_old);
+          f->num_fields++;
+        }
+        tmp = MemFree (tmp);
+        orig = MemFree (orig);
+      }
+    }
+  }
+
+  if (f->action->authors) {
+    alp = GetAuthListPtr (pdp, NULL);
+    if (alp != NULL) {
+      for (names = alp->names; names != NULL; names = names->next) { 
+        ap = names->data.ptrvalue;
+        ap_orig = AsnIoMemCopy (ap, (AsnReadFunc) AuthorAsnRead, (AsnWriteFunc) AuthorAsnWrite);
+        FixCapitalizationInAuthor (ap);
+        if (!AsnIoMemComp (ap, ap_orig, (AsnWriteFunc) AuthorAsnWrite)) {
+          f->num_fields++;
+        }
+        ap_orig = AuthorFree (ap_orig);
+      }
+    }
+  }
+
+  if (f->action->affiliation) {
+    if (alp == NULL) {
+      alp = GetAuthListPtr (pdp, NULL);
+    }
+    if (alp != NULL && alp->affil != NULL) {
+      affil_orig = AsnIoMemCopy (alp->affil, (AsnReadFunc) AffilAsnRead, (AsnWriteFunc) AffilAsnWrite);
+      FixCapsInPubAffil (alp->affil);
+        if (!AsnIoMemComp (alp->affil, affil_orig, (AsnWriteFunc) AffilAsnWrite)) {
+          f->num_fields++;
+        }
+        affil_orig = AffilFree (affil_orig);
+    }
+  }
+}
+
+
+static void CollectPubObjectsFeatCallback (SeqFeatPtr sfp, Pointer data)
+{
+  FixPubCapsPtr f;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_PUB || (f = (FixPubCapsPtr) data) == NULL) {
+    return;
+  }
+
+  if (DoesObjectMatchConstraintChoiceSet (OBJ_SEQFEAT, sfp, f->action->constraint)) {
+    ValNodeAddPointer (&(f->object_list), OBJ_SEQFEAT, sfp);
+  }
+}
+
+
+static void CollectPubObjectsDescCallback (SeqDescPtr sdp, Pointer data)
+{
+  FixPubCapsPtr f;
+
+  if (sdp == NULL || sdp->choice != Seq_descr_pub || (f = (FixPubCapsPtr) data) == NULL) {
+    return;
+  }
+
+  if (DoesObjectMatchConstraintChoiceSet (OBJ_SEQDESC, sdp, f->action->constraint)) {
+    ValNodeAddPointer (&(f->object_list), OBJ_SEQDESC, sdp);
+  }
+}
+
+
+static Int4 ApplyFixPubCapsToSeqEntry (FixPubCapsActionPtr action, SeqEntryPtr sep)
 {
-  Int4 num_AECR = 0, num_parse = 0, num_feature = 0, num_fields = 0;
+  FixPubCapsData         f;
+  ValNodePtr             vnp;
+  Int4                   num_succeeded = 0;
+  PubdescPtr             pdp;
+  SeqFeatPtr             sfp;
+  SeqDescPtr             sdp;
+
+  if (action == NULL || sep == NULL) return 0;
+
+  MemSet (&f, 0, sizeof (FixPubCapsData));
+  f.action = action;
+
+  /* collect pub objects that match constraint */
+  VisitDescriptorsInSep (sep, &f, CollectPubObjectsDescCallback);
+  VisitFeaturesInSep (sep, &f, CollectPubObjectsFeatCallback);
+
+  if (f.object_list == NULL) {
+    /* nothing to change */
+    return 0;
+  }
+
+  if (action->title) {
+    /* get org names to use in fixes */
+    VisitBioSourcesInSep (sep, &f.orgnames, GetOrgNamesInRecordCallback);
+  }
+
+  for (vnp = f.object_list; vnp != NULL; vnp = vnp->next) {
+    pdp = NULL;
+    if (vnp->choice == OBJ_SEQFEAT) {
+      sfp = vnp->data.ptrvalue;
+      pdp = sfp->data.value.ptrvalue;
+    } else if (vnp->choice == OBJ_SEQDESC) {
+      sdp = vnp->data.ptrvalue;
+      pdp = sdp->data.ptrvalue;
+    }
+    ApplyFixPubCapsCallback (pdp, &f);
+  }
+
+  f.orgnames = ValNodeFree (f.orgnames);
+
+  return f.num_fields;
+}
+
+
+NLM_EXTERN Boolean ApplyMacroToSeqEntryEx (SeqEntryPtr sep, ValNodePtr macro, Int4Ptr pNumFields, Int4Ptr pNumFeat, FILE *log_fp)
+{
+  Int4 num_AECR = 0, num_parse = 0, num_feature = 0, num_fields = 0, num;
+  Uint2 entityID;
+  Boolean needs_update = FALSE;
+  CharPtr summ;
+  Boolean any_change = FALSE;
 
   while (macro != NULL) {
+    needs_update = TRUE;
     switch (macro->choice) {
       case MacroActionChoice_aecr:
-        num_AECR += ApplyAECRActionToSeqEntry ((AECRActionPtr) macro->data.ptrvalue, sep);
+        num = ApplyAECRActionToSeqEntry ((AECRActionPtr) macro->data.ptrvalue, sep);
+        num_AECR += num;
+        if (num > 0) {
+          if (log_fp != NULL) {
+            summ = SummarizeAECRAction ((AECRActionPtr) macro->data.ptrvalue);
+            fprintf (log_fp, "Changed %d fields during %s\n", num, summ);
+            summ = MemFree (summ);
+          }
+          any_change = TRUE;
+        }
         break;
       case MacroActionChoice_parse:
-        num_parse += ApplyParseActionToSeqEntry ((ParseActionPtr) macro->data.ptrvalue, sep);
+        num = ApplyParseActionToSeqEntry ((ParseActionPtr) macro->data.ptrvalue, sep);
+        num_parse += num;
+        if (num > 0) {
+          if (log_fp != NULL) {
+            summ = SummarizeParseAction ((ParseActionPtr) macro->data.ptrvalue);
+            fprintf (log_fp, "Changed %d fields during %s\n", num, summ);
+            summ = MemFree (summ);
+          }
+          any_change = TRUE;
+        }
         break;
       case MacroActionChoice_add_feature:
-        num_feature += ApplyApplyFeatureActionToSeqEntry ((ApplyFeatureActionPtr) macro->data.ptrvalue, sep);
+        num = ApplyApplyFeatureActionToSeqEntry ((ApplyFeatureActionPtr) macro->data.ptrvalue, sep);
+        num_feature += num;
+        if (num > 0) {
+          if (log_fp != NULL) {
+            fprintf (log_fp, "Added %d features\n", num);
+          }
+          any_change = TRUE;
+        }
         SeqMgrIndexFeatures (ObjMgrGetEntityIDForChoice(sep), NULL);
         break;
       case MacroActionChoice_remove_feature:
-        num_feature += ApplyRemoveFeatureActionToSeqEntry ((RemoveFeatureActionPtr) macro->data.ptrvalue, sep);
+        num = ApplyRemoveFeatureActionToSeqEntry ((RemoveFeatureActionPtr) macro->data.ptrvalue, sep);
+        if (num > 0) {
+          if (log_fp != NULL) {
+            fprintf (log_fp, "Removed %d features\n", num);
+          }
+          any_change = TRUE;
+        }
         break;
       case MacroActionChoice_edit_location:
-        num_fields += ApplyEditFeatureLocationActionToSeqEntry ((EditFeatureLocationActionPtr) macro->data.ptrvalue, sep);
+        num = ApplyEditFeatureLocationActionToSeqEntry ((EditFeatureLocationActionPtr) macro->data.ptrvalue, sep, log_fp);
+        if (num > 0) {
+          num_fields += num;
+          any_change = TRUE;
+        }
         break;
       case MacroActionChoice_convert_feature:
-        num_feature += ApplyConvertFeatureActionToSeqEntry ((ConvertFeatureActionPtr) macro->data.ptrvalue, sep);
+        num += ApplyConvertFeatureActionToSeqEntry ((ConvertFeatureActionPtr) macro->data.ptrvalue, sep, log_fp);
+        num_feature += num;
+        entityID = SeqMgrGetEntityIDForSeqEntry (sep);
+        ObjMgrSetDirtyFlag (entityID, TRUE);
+        ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+        needs_update = FALSE;
+        any_change = TRUE;
         break;
       case MacroActionChoice_remove_descriptor:
-        num_feature += ApplyRemoveDescriptorActionToSeqEntry ((RemoveDescriptorActionPtr) macro->data.ptrvalue, sep);
+        num = ApplyRemoveDescriptorActionToSeqEntry ((RemoveDescriptorActionPtr) macro->data.ptrvalue, sep);
+        if (num > 0) {
+          if (log_fp != NULL) {
+            summ = SummarizeRemoveDescriptorAction ((RemoveDescriptorActionPtr) macro->data.ptrvalue);
+            fprintf (log_fp, "Removed %d descriptors during %s\n", num, summ);
+            summ = MemFree (summ);
+          }
+          any_change = TRUE;
+        }
         break;
       case MacroActionChoice_autodef:
         ApplyAutodefActionToSeqEntry ((AutodefActionPtr) macro->data.ptrvalue, sep);
+        if (log_fp != NULL) {
+          summ = SummarizeAutodefAction ((AutodefActionPtr) macro->data.ptrvalue);
+          if (summ != NULL) {
+            fprintf (log_fp, "Performed %s\n", summ);
+          }
+          summ = MemFree (summ);
+        }
+        any_change = TRUE;
+        break;
+      case MacroActionChoice_removesets:
+        if (RemoveDuplicateNestedSetsForEntityID (SeqMgrGetEntityIDForSeqEntry (sep))) {
+          if (log_fp != NULL) {
+            fprintf (log_fp, "Removed duplicate nested sets\n");
+          }
+          any_change = TRUE;
+        }
+        break;
+      case MacroActionChoice_trim_junk_from_primer_seq:
+        any_change |= TrimPrimerSeqJunkInSeqEntry (sep, log_fp);
+        break;
+      case MacroActionChoice_fix_usa_and_states:
+        any_change |= FixUsaAndStateAbbreviations (entityID, log_fp);
+        break;   
+      case MacroActionChoice_trim_stop_from_complete_cds:
+        if (TrimStopsFromCompleteCodingRegions(sep, log_fp)) {
+          entityID = SeqMgrGetEntityIDForSeqEntry (sep);
+          ObjMgrSetDirtyFlag (entityID, TRUE);
+          ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+          needs_update = FALSE;
+          any_change = TRUE;
+        }
+        break;
+      case MacroActionChoice_synchronize_cds_partials:
+        if (ResynchCodingRegionPartialsEx(sep, log_fp)) {
+          entityID = SeqMgrGetEntityIDForSeqEntry (sep);
+          ObjMgrSetDirtyFlag (entityID, TRUE);
+          ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+          needs_update = FALSE;
+          any_change = TRUE;
+        }
+        break;
+      case MacroActionChoice_adjust_for_consensus_splice:
+        if (AdjustSeqEntryForConsensusSpliceEx(sep, log_fp)) {
+          entityID = SeqMgrGetEntityIDForSeqEntry (sep);
+          ObjMgrSetDirtyFlag (entityID, TRUE);
+          ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+          needs_update = FALSE;
+          any_change = TRUE;
+        }
+        break;
+      case MacroActionChoice_fix_pub_caps:
+        num = ApplyFixPubCapsToSeqEntry (macro->data.ptrvalue, sep);
+        if (num > 0) {
+          if (log_fp != NULL) {
+            summ = SummarizeFixPubCapsAction (macro->data.ptrvalue);
+            fprintf (log_fp, "Fixed capitalization in %d publication fields during %s\n", num, summ);
+            summ = MemFree (summ);
+          }
+          any_change = TRUE;
+        }
+        num_fields += num;
+        break;
+      case MacroActionChoice_remove_seg_gaps:
+        num = RemoveSegGapsInSeqEntry (sep);
+        if (num > 0) {
+          if (log_fp != NULL) {
+            fprintf (log_fp, "Removed gaps in %d alignments\n", num);
+          }
+          any_change = TRUE;
+        }
+        num_fields += num;
         break;
     }
     macro = macro->next;
   }
+
+  if (needs_update) {
+    entityID = SeqMgrGetEntityIDForSeqEntry (sep);
+    ObjMgrSetDirtyFlag (entityID, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+  }
   if (pNumFields != NULL) {
     *pNumFields = num_AECR + num_parse + num_fields;
   }
   if (pNumFeat != NULL) {
     *pNumFeat = num_feature;
   }
+  return any_change;
+}
+
+
+NLM_EXTERN void ApplyMacroToSeqEntry (SeqEntryPtr sep, ValNodePtr macro, Int4Ptr pNumFields, Int4Ptr pNumFeat)
+{
+  ApplyMacroToSeqEntryEx (sep, macro, pNumFields, pNumFeat, NULL);
 }
 
 
@@ -20188,6 +22184,1584 @@ NLM_EXTERN FieldTypePtr FieldTypeFromString (CharPtr str)
 }
 
 
+NLM_EXTERN Boolean IsFieldTypeNonText (ValNodePtr field_type)
+{
+  ValNodePtr      vnp;
+  FeatureFieldPtr ffp;
+  Boolean         rval = FALSE;
+
+  if (field_type == NULL) {
+    return FALSE;
+  } 
+  switch (field_type->choice) {
+    case FieldType_source_qual :
+      vnp = (ValNodePtr) field_type->data.ptrvalue;
+      if (vnp != NULL) {
+        if (vnp->choice == SourceQualChoice_location || vnp->choice == SourceQualChoice_origin) {
+          rval = TRUE;
+        } else if (vnp->choice == SourceQualChoice_textqual) {
+          if (IsNonTextSourceQual (vnp->data.intvalue)) {
+            rval = TRUE;
+          }
+        }
+      }
+      break;
+    case FieldType_feature_field :
+      ffp = (FeatureFieldPtr) field_type->data.ptrvalue;
+      if (ffp != NULL && ffp->field != NULL && ffp->field->choice == FeatQualChoice_legal_qual
+          && ffp->field->data.intvalue == Feat_qual_legal_pseudo) {
+        rval = TRUE;
+      }
+      break;
+    case FieldType_molinfo_field :
+      rval = TRUE;
+      break;
+  } 
+  return rval;
+}
+
+
+NLM_EXTERN CharPtr SummarizeExistingText (Uint2 existing_text)
+{
+  CharPtr str = NULL;
+
+  switch (existing_text) {
+    case ExistingTextOption_append_semi :
+      str = "append separated by semicolon";
+      break;
+    case ExistingTextOption_append_space :
+      str = "append separated by space";
+      break;
+    case ExistingTextOption_append_colon :
+      str = "append separated by colon";
+      break;
+    case ExistingTextOption_append_none :
+      str = "append (no separator)";
+      break;
+    case ExistingTextOption_prefix_semi :
+      str = "prefix separated by semicolon";
+      break;
+    case ExistingTextOption_prefix_space :
+      str = "prefix separated by space";
+      break;
+    case ExistingTextOption_prefix_colon :
+      str = "prefix separated by colon";
+      break;
+    case ExistingTextOption_prefix_none :
+      str = "prefix (no separator)";
+      break;
+    case ExistingTextOption_leave_old :
+      str = "ignore new text when existing text is present";
+      break;
+    case ExistingTextOption_replace_old :
+      str = "overwrite existing text";
+      break;
+    case ExistingTextOption_add_qual :
+      str = "add new qual";
+      break;
+    default:
+      str = "invalid existing_text option";
+      break;
+  }
+  return str;    
+}
+
+
+static CharPtr SummarizeTextMarker (TextMarkerPtr text_marker)
+{
+  CharPtr summ = NULL;
+
+  if (IsTextMarkerEmpty (text_marker)) {
+    return NULL;
+  } else if (text_marker->choice == TextMarker_free_text) {
+    summ = StringSave (text_marker->data.ptrvalue);
+  } else if (text_marker->choice == TextMarker_digits) {
+    summ = StringSave ("numbers");
+  } else if (text_marker->choice == TextMarker_letters) {
+    summ = StringSave ("letters");
+  }
+  return summ;
+}
+
+
+NLM_EXTERN CharPtr SummarizeTextPortion (TextPortionPtr text_portion)
+{
+  CharPtr summ = NULL;
+  CharPtr left_fmt = NULL, right_fmt = NULL;
+  CharPtr left_text = NULL, right_text = NULL;
+  Int4 len = 6;
+
+  if (text_portion == NULL 
+      || (IsTextMarkerEmpty (text_portion->left_marker)
+          && IsTextMarkerEmpty (text_portion->right_marker))) {
+    summ = StringSave ("entire text");
+  } else {
+    left_text = SummarizeTextMarker(text_portion->left_marker);
+    right_text = SummarizeTextMarker(text_portion->right_marker);
+
+    if (text_portion->inside) {
+      if (left_text != NULL) {
+        if (text_portion->include_left) {
+          left_fmt = "starting with ";
+        } else {
+          left_fmt = "just after ";
+        }
+        len += StringLen (left_fmt) + StringLen (left_text) + 3;
+      }
+      if (right_text != NULL) {
+        if (text_portion->include_right) {
+          right_fmt = "up to and including ";
+        } else {
+          right_fmt = "up to ";
+        }
+        len += StringLen (right_fmt) + StringLen (right_text) + 3;
+        if (left_fmt != NULL) {
+          len += 2;
+        }
+      }
+      if (left_fmt == NULL && right_fmt == NULL) {
+        summ = StringSave ("entire text");
+      } else {
+        summ = (CharPtr) MemNew (sizeof (Char) * len);
+        StringCat (summ, "text ");
+        if (left_fmt != NULL) {
+          StringCat (summ, left_fmt);
+          StringCat (summ, "'");
+          StringCat (summ, left_text);
+          StringCat (summ, "'");
+          if (right_fmt != NULL) {
+            StringCat (summ, ", ");
+          }
+        }
+        if (right_fmt != NULL) {
+          StringCat (summ, right_fmt);
+          StringCat (summ, "'");
+          StringCat (summ, right_text);
+          StringCat (summ, "'");
+        }
+      }
+    } else {
+      if (right_text != NULL) {
+        if (text_portion->include_right) {
+          right_fmt = "starting with ";
+        } else {
+          right_fmt = "after ";
+        }
+        len += StringLen (right_fmt) + StringLen (right_text) + 3;
+      }
+      if (left_text != NULL) {
+        if (text_portion->include_left) {
+          left_fmt = "up to and including ";
+        } else {
+          left_fmt = "before ";
+        }
+        len += StringLen (left_fmt) + StringLen (left_text) + 3;
+        if (right_fmt != NULL) {
+          len += 5;
+        }
+      }
+
+      if (left_fmt == NULL && right_fmt == NULL) {
+        summ = StringSave ("entire text");
+      } else {
+        summ = (CharPtr) MemNew (sizeof (Char) * len);
+        StringCat (summ, "text ");
+        if (right_fmt != NULL) {
+          StringCat (summ, right_fmt);
+          StringCat (summ, "'");
+          StringCat (summ, right_text);
+          StringCat (summ, "'");
+          if (left_fmt != NULL) {
+            StringCat (summ, " and ");
+          }
+        }
+        if (left_fmt != NULL) {
+          StringCat (summ, left_fmt);
+          StringCat (summ, "'");
+          StringCat (summ, left_text);
+          StringCat (summ, "'");
+        }
+      }          
+    }
+    left_text = MemFree (left_text);
+    right_text = MemFree (right_text);
+  }
+  return summ;
+}
+
+
+const CharPtr kTaxnameAfterBinomialString = "Taxname after binomial";
+
+
+NLM_EXTERN CharPtr SummarizeParseSrc (ValNodePtr src)
+{
+  CharPtr summ = NULL;
+  CharPtr fmt = "structured comment field %s";
+  ParseSrcOrgPtr src_org;
+  Boolean need_to_save = TRUE;
+  
+  if (src != NULL) {
+    switch (src->choice) {
+      case ParseSrc_defline:
+        summ = "defline";
+        break;
+      case ParseSrc_flatfile:
+        summ = "flat file";
+        break;
+      case ParseSrc_local_id:
+        summ = "local ID";
+        break;
+      case ParseSrc_org:
+        src_org = (ParseSrcOrgPtr) src->data.ptrvalue;
+        if (src_org != NULL) {
+          if (src_org->field != NULL) {
+            if (src_org->field->choice == ParseSrcOrgChoice_taxname_after_binomial) {
+              summ = kTaxnameAfterBinomialString;
+            } else if (src_org->field->choice == ParseSrcOrgChoice_source_qual) {
+              summ = GetSourceQualName (src_org->field->data.intvalue);
+            }
+          }
+        }
+        break;
+      case ParseSrc_comment:
+        summ = "comment";
+        break;
+      case ParseSrc_bankit_comment:
+        summ = "BankIT comment";
+        break;
+      case ParseSrc_structured_comment:
+        if (!StringHasNoText (src->data.ptrvalue)) {
+          summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (src->data.ptrvalue) + StringLen (fmt)));
+          sprintf (summ, fmt, src->data.ptrvalue);
+          need_to_save = FALSE;
+        }
+        break;
+      case ParseSrc_file_id:
+        summ = "file ID";
+        break;
+    }
+  }
+  if (summ == NULL) {
+    summ = StringSave ("missing field");
+  } else if (need_to_save) {
+    summ = StringSave (summ);
+  } 
+  return summ;
+}
+
+
+NLM_EXTERN CharPtr SummarizeParseDst (ValNodePtr dst)
+{
+  CharPtr summ = NULL;
+  CharPtr fmt = "%s %s";
+  CharPtr feature, field;
+  ParseDstOrgPtr dst_org;
+  Boolean need_to_save = TRUE;
+  FeatureFieldLegalPtr ffp;
+  
+  if (dst != NULL) {
+    switch (dst->choice) {
+      case ParseDest_defline:
+        summ = "defline";
+        break;
+      case ParseDest_org:
+        dst_org = (ParseDstOrgPtr) dst->data.ptrvalue;
+        if (dst_org != NULL) {
+          if (dst_org->field != NULL) {
+            switch (dst_org->field->choice) {
+              case SourceQualChoice_textqual:
+                summ = GetSourceQualName (dst_org->field->data.intvalue);
+                break;
+              case SourceQualChoice_location:
+                summ = "location";
+                break;
+              case SourceQualChoice_origin:
+                summ = "origin";
+                break;
+            }
+          }
+        }
+        break;
+      case ParseDest_featqual:
+        ffp = (FeatureFieldLegalPtr) dst->data.ptrvalue;
+        if (ffp != NULL) {
+          feature = GetFeatureNameFromFeatureType (ffp->type);
+          field = GetFeatQualName (ffp->field);
+          summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (feature) + StringLen (field)));
+          sprintf (summ, fmt, feature, field);
+          need_to_save = FALSE;
+        }
+        break;
+      case ParseDest_dbxref:
+        summ = "dbxref";
+        break;
+    }
+  }
+  if (summ == NULL) {
+    summ = StringSave ("missing field");
+  } else if (need_to_save) {
+    summ = StringSave (summ);
+  } 
+  return summ;
+}
+
+
+/* summarizing AECR actions */
+static CharPtr SummarizeFieldPairType (ValNodePtr vnp, CharPtr connect_word)
+{
+  FeatureFieldPairPtr ffp;
+  CDSGeneProtFieldPairPtr cgp;
+  SourceQualPairPtr     quals;
+  MolinfoFieldPairPtr   m_fields;
+  RnaQualPairPtr        rna_quals;
+  CharPtr str = NULL;
+  CharPtr from_label = NULL, to_label = NULL;
+  CharPtr label_fmt = "%s %s %s";
+  CharPtr type_label_fmt = "%s %s %s %s";
+  CharPtr    label = NULL;
+
+  if (connect_word == NULL) {
+    connect_word = "to";
+  }
+  if (vnp == NULL) {
+    str = StringSave ("missing field");
+  } else {
+    switch (vnp->choice) {
+      case FieldPairType_source_qual:
+        if (vnp->data.ptrvalue != NULL) {
+          quals = (SourceQualPairPtr) vnp->data.ptrvalue;
+          from_label = GetSourceQualName (quals->field_from);
+          to_label = GetSourceQualName (quals->field_to);
+        }
+        if (from_label != NULL && to_label != NULL) {
+          str = (CharPtr) MemNew (sizeof (Char) *
+                                  (StringLen (from_label) + StringLen (connect_word) + StringLen (to_label)
+                                  + 3));
+          sprintf (str, "%s %s %s", from_label, connect_word, to_label);
+        } else {
+          str = StringSave ("missing field");
+        }
+        break;
+      case FieldPairType_feature_field:
+        ffp = (FeatureFieldPairPtr) vnp->data.ptrvalue;
+        if (ffp == NULL || ffp->field_from == NULL || ffp->field_to == NULL) {
+          str = StringSave ("missing field");
+        } else {
+          label = GetFeatureNameFromFeatureType (ffp->type);
+          from_label = FeatureFieldLabel (label, ffp->field_from);
+          to_label = FeatureFieldLabel (label, ffp->field_to);
+          str = (CharPtr) MemNew (sizeof (Char) * 
+                                  (StringLen (label_fmt) 
+                                   + StringLen (from_label) + StringLen (to_label)
+                                   + StringLen (connect_word)));
+          sprintf (str, label_fmt, from_label, connect_word, to_label);
+          from_label = MemFree (from_label);
+          to_label = MemFree (to_label);
+        }
+        break;
+      case FieldPairType_cds_gene_prot:
+        cgp = (CDSGeneProtFieldPairPtr) vnp->data.ptrvalue;
+        from_label = CDSGeneProtNameFromField (cgp->field_from);
+        to_label = CDSGeneProtNameFromField (cgp->field_to);
+        str = (CharPtr) MemNew (sizeof (Char) *
+                                StringLen (from_label) + StringLen (connect_word) + StringLen (to_label)
+                                + 3);
+        sprintf (str, "%s %s %s", from_label, connect_word, to_label);
+        break;
+      case FieldPairType_molinfo_field:
+        m_fields = (MolinfoFieldPairPtr) vnp->data.ptrvalue;
+        from_label = NULL;
+        to_label = NULL;
+        label = NULL;
+        switch (m_fields->choice) {
+          case MolinfoFieldPair_molecule:
+            from_label = BiomolNameFromBiomol (BiomolFromMoleculeType (((MolinfoMoleculePairPtr) m_fields->data.ptrvalue)->from));
+            to_label = BiomolNameFromBiomol (BiomolFromMoleculeType (((MolinfoMoleculePairPtr) m_fields->data.ptrvalue)->to));
+            label = "molecule";
+            break;
+          case MolinfoFieldPair_technique:
+            from_label = TechNameFromTech (TechFromTechniqueType (((MolinfoTechniquePairPtr) m_fields->data.ptrvalue)->from));
+            to_label = TechNameFromTech (TechFromTechniqueType (((MolinfoTechniquePairPtr) m_fields->data.ptrvalue)->to));
+            label = "technique";
+            break;
+          case MolinfoFieldPair_completedness:
+            from_label = CompletenessNameFromCompleteness (CompletenessFromCompletednessType (((MolinfoCompletednessPairPtr) m_fields->data.ptrvalue)->from));
+            to_label = CompletenessNameFromCompleteness (CompletenessFromCompletednessType (((MolinfoCompletednessPairPtr) m_fields->data.ptrvalue)->to));
+            label = "completeness";
+            break;
+          case MolinfoFieldPair_mol_class:
+            from_label = MolNameFromMol (MolFromMoleculeClassType (((MolinfoMolClassPairPtr) m_fields->data.ptrvalue)->from));
+            to_label = MolNameFromMol (MolFromMoleculeClassType (((MolinfoMolClassPairPtr) m_fields->data.ptrvalue)->to));
+            label = "class";
+            break;
+          case MolinfoFieldPair_topology:
+            from_label = TopologyNameFromTopology (TopologyFromTopologyType (((MolinfoTopologyPairPtr) m_fields->data.ptrvalue)->from));
+            to_label = TopologyNameFromTopology (TopologyFromTopologyType (((MolinfoTopologyPairPtr) m_fields->data.ptrvalue)->to));
+            label = "topology";
+            break;
+          case MolinfoFieldPair_strand:
+            from_label = StrandNameFromStrand (StrandFromStrandType (((MolinfoStrandPairPtr) m_fields->data.ptrvalue)->from));
+            to_label = StrandNameFromStrand (StrandFromStrandType (((MolinfoStrandPairPtr) m_fields->data.ptrvalue)->to));
+            label = "strand";
+            break;
+        }
+        if (from_label == NULL) {
+          from_label = "Unknown value";
+        }
+        if (to_label == NULL) {
+          to_label = "Unknown value";
+        }
+        if (label == NULL) {
+          label = "Unknown molinfo field";
+        }
+        str = (CharPtr) MemNew (sizeof (Char) * (StringLen (type_label_fmt)
+                                                 + StringLen (label)
+                                                 + StringLen (from_label)
+                                                 + StringLen (to_label)
+                                                 + StringLen (connect_word)));
+        sprintf (str, type_label_fmt, label, from_label, connect_word, to_label);
+        break;
+      case FieldPairType_rna_field:
+        if (vnp->data.ptrvalue != NULL) {
+          rna_quals = (RnaQualPairPtr) vnp->data.ptrvalue;
+          label = SummarizeRnaType (rna_quals->type);
+          from_label = GetNameForRnaField (rna_quals->field_from);
+          to_label = GetNameForRnaField (rna_quals->field_to);
+        }
+        if (from_label != NULL && to_label != NULL && label != NULL) {
+          str = (CharPtr) MemNew (sizeof (Char) * (StringLen (type_label_fmt)
+                                  + StringLen (label)
+                                  + StringLen (from_label) + StringLen (connect_word) + StringLen (to_label)));
+          sprintf (str, type_label_fmt, label, from_label, connect_word, to_label);
+        } else {
+          str = StringSave ("missing field");
+        }
+        label = MemFree (label);        
+        break;
+
+      default:
+        str = StringSave ("Invalid field type");
+        break;
+    }
+  }
+  return str;
+}
+
+static CharPtr SummarizeApplyAction (ApplyActionPtr a)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "Apply %s to %s (%s)";
+  CharPtr nontextqual_fmt = "Apply %s (%s)";
+  CharPtr field, existing_text;
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->value == NULL || a->field == NULL) {
+    str = StringSave ("Invalid action");
+  } else {
+    field = SummarizeFieldType (a->field);
+    existing_text = SummarizeExistingText (a->existing_text);
+    if (IsFieldTypeNonText (a->field)) {
+      str = (CharPtr) MemNew (sizeof (Char) * StringLen (nontextqual_fmt) + StringLen (field) + StringLen (existing_text));
+      sprintf (str, nontextqual_fmt, field, existing_text);
+    } else {
+      str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (a->value) + StringLen (field) + StringLen (existing_text)));
+      sprintf (str, fmt, a->value, field, existing_text);
+    }
+    field = MemFree (field);
+  }
+  return str;
+}
+
+
+static CharPtr SummarizeEditAction (EditActionPtr a)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "Edit %s replace '%s' with '%s'";
+  CharPtr field;
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->field == NULL || a->field == NULL || a->edit == NULL || a->edit->find_txt == NULL) {
+    str = StringSave ("Invalid action");
+  } else {
+    field = SummarizeFieldType (a->field);
+    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (field) + StringLen (a->edit->find_txt) + StringLen (a->edit->repl_txt)));
+    sprintf (str, fmt, field, a->edit->find_txt, a->edit->repl_txt == NULL ? "" : a->edit->repl_txt);
+    field = MemFree (field);
+  }
+  return str;
+}
+
+
+static CharPtr SummarizeConvertAction (ConvertActionPtr a)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "Convert %s (%s)";
+  CharPtr fields, existing_text;
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->fields == NULL || a->fields == NULL) {
+    str = StringSave ("Invalid action");
+  } else {
+    fields = SummarizeFieldPairType (a->fields, "to");
+    existing_text = SummarizeExistingText (a->existing_text);
+    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (fields) + StringLen (existing_text)));
+    sprintf (str, fmt, fields, existing_text);
+    fields = MemFree (fields);
+  }
+  return str;
+}
+
+
+static CharPtr SummarizeCopyAction (CopyActionPtr a)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "Copy %s (%s)";
+  CharPtr fields, existing_text;
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->fields == NULL) {
+    str = StringSave ("Invalid action");
+  } else {
+    fields = SummarizeFieldPairType (a->fields, "to");
+    existing_text = SummarizeExistingText (a->existing_text);
+    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (fields) + StringLen (existing_text)));
+    sprintf (str, fmt, fields, existing_text);
+    fields = MemFree (fields);
+  }
+  return str;
+}
+
+
+static CharPtr SummarizeSwapAction (SwapActionPtr a)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "Swap %s";
+  CharPtr fields;
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->fields == NULL) {
+    str = StringSave ("Invalid action");
+  } else {
+    fields = SummarizeFieldPairType (a->fields, "with");
+    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (fields)));
+    sprintf (str, fmt, fields);
+    fields = MemFree (fields);
+  }
+  return str;
+}
+
+
+static CharPtr SummarizeAECRParseAction (AECRParseActionPtr a)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "Parse %s from %s (%s)";
+  CharPtr fields, existing_text, text_portion;
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->fields == NULL) {
+    str = StringSave ("Invalid action");
+  } else {
+    fields = SummarizeFieldPairType (a->fields, "to");
+    existing_text = SummarizeExistingText (a->existing_text);
+    text_portion = SummarizeTextPortion (a->portion);
+    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (text_portion) + StringLen (fields) + StringLen (existing_text)));
+    sprintf (str, fmt, text_portion, fields, existing_text);
+    fields = MemFree (fields);
+    text_portion = MemFree (text_portion);
+  }
+  return str;
+}
+
+
+static CharPtr SummarizeRemoveAction (RemoveActionPtr a)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "Remove %s";
+  CharPtr field;
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->field == NULL || a->field == NULL) {
+    str = StringSave ("Invalid action");
+  } else {
+    field = SummarizeFieldType (a->field);
+    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (field)));
+    sprintf (str, fmt, field);
+    field = MemFree (field);
+  }
+  return str;
+}
+
+
+NLM_EXTERN CharPtr SummarizeAECRAction (AECRActionPtr a)
+{
+  CharPtr str = NULL, act = NULL, constraint = NULL;
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else if (a->action == NULL) {
+    str = StringSave ("Invalid command");
+  } else {
+    switch (a->action->choice) {
+      case ActionChoice_apply:
+        act = SummarizeApplyAction (a->action->data.ptrvalue);
+        break;
+      case ActionChoice_edit:
+        act = SummarizeEditAction (a->action->data.ptrvalue);
+        break;
+      case ActionChoice_convert:
+        act = SummarizeConvertAction (a->action->data.ptrvalue);
+        break;
+      case ActionChoice_copy:
+        act = SummarizeCopyAction (a->action->data.ptrvalue);
+        break;
+      case ActionChoice_swap:
+        act = SummarizeSwapAction (a->action->data.ptrvalue);
+        break;
+      case ActionChoice_remove:
+        act = SummarizeRemoveAction (a->action->data.ptrvalue);
+        break;
+      case ActionChoice_parse:
+        act = SummarizeAECRParseAction (a->action->data.ptrvalue);
+        break;
+    }
+    if (act == NULL) {
+      str = StringSave ("Invalid action");
+    } else {
+      constraint = SummarizeConstraintSet (a->constraint);
+      if (constraint == NULL) {
+        str = act;
+      } else {
+        str = (CharPtr) MemNew (sizeof (Char) * (StringLen(act) + 2 + StringLen (constraint)));
+        sprintf (str, "%s %s", act, constraint);
+        act = MemFree (act);
+        constraint = MemFree (constraint);
+      }
+    }
+  }
+  return str;
+}
+
+
+NLM_EXTERN CharPtr SummarizeParseAction (ParseActionPtr p)
+{
+  CharPtr field_from = NULL, field_to = NULL;
+  CharPtr existing_text = NULL, text_portion = NULL;
+  CharPtr summ = NULL;
+  CharPtr fmt = "Parse %s from %s to %s (%s)";
+
+  if (p == NULL) {
+    summ = StringSave ("No action");
+  } else {
+    field_from = SummarizeParseSrc (p->src);
+    field_to = SummarizeParseDst (p->dest);
+    existing_text = SummarizeExistingText (p->existing_text);
+    text_portion = SummarizeTextPortion (p->portion);
+    summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (text_portion) + StringLen (field_from) + StringLen (field_to) + StringLen (existing_text)));
+    sprintf (summ, fmt, text_portion, field_from, field_to, existing_text);
+    text_portion = MemFree (text_portion);
+    field_from = MemFree (field_from);
+    field_to = MemFree (field_to);
+  }
+  return summ;
+}
+
+
+static CharPtr SummarizeAutodefClauseListType (Uint2 clause_list_type)
+{
+  CharPtr str = "complete sequence";
+
+  switch (clause_list_type) {
+    case Autodef_list_type_feature_list:
+      str = "list features";
+      break;
+    case Autodef_list_type_complete_sequence:
+      str = "complete sequence";
+      break;
+    case Autodef_list_type_complete_genome:
+      str = "complete genome";
+      break;
+  }
+  return str;
+}
+
+
+NLM_EXTERN CharPtr SummarizeAutodefAction (AutodefActionPtr autodef)
+{
+  CharPtr    label = NULL, mod_name;
+  CharPtr    str = NULL;
+  CharPtr    fmt = "Autodef %s";
+  CharPtr    modifiers_fmt = " with modifier";
+  Int4       len;
+  ValNodePtr mod_names = NULL, vnp;
+
+  if (autodef == NULL) {
+    str = StringSave ("No action");
+  } else {
+    label = SummarizeAutodefClauseListType (autodef->clause_list_type);
+    len = StringLen (fmt) + StringLen (label);
+    if (autodef->modifiers != NULL) {
+      len += StringLen (modifiers_fmt) + 2;
+      for (vnp = autodef->modifiers; vnp != NULL; vnp = vnp->next) {
+        mod_name = GetSourceQualName (vnp->data.intvalue);
+        len += StringLen (mod_name) + 3;
+        ValNodeAddPointer (&mod_names, 0, mod_name);
+      }
+    }
+    
+    str = (CharPtr) MemNew (sizeof (Char) * (len + 1));
+    sprintf (str, fmt, label);
+
+    if (autodef->modifiers != NULL) {
+      StringCat (str, modifiers_fmt);
+      if (autodef->modifiers->next != NULL) {
+        StringCat (str, "s");
+      }
+      for (vnp = mod_names; vnp != NULL; vnp = vnp->next) {
+        StringCat (str, " ");
+        StringCat (str, vnp->data.ptrvalue);
+        if (vnp->next != NULL) {
+          StringCat (str, ",");
+        }
+      }
+    }
+
+    mod_names = ValNodeFree (mod_names);
+  }
+
+  return str;
+}
+
+
+NLM_EXTERN CharPtr SummarizeRemoveDescriptorAction (RemoveDescriptorActionPtr a)
+{
+  CharPtr    label = NULL;
+  CharPtr    constraint, str;
+  CharPtr    fmt = "Remove %s";
+  CharPtr    constraint_fmt = "Remove %s descriptors %s";
+
+  if (a == NULL) {
+    str = StringSave ("No action");
+  } else {
+    label = GetDescriptorNameFromDescriptorType (a->type);
+    constraint = SummarizeConstraintSet (a->constraint);
+    if (constraint == NULL) {
+      str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (label)));
+      sprintf (str, fmt, label);
+    } else {
+      str = (CharPtr) MemNew (sizeof (Char) * (StringLen (constraint_fmt) + StringLen (label) + StringLen (constraint)));
+      sprintf (str, constraint_fmt, label, constraint);
+      constraint = MemFree (constraint);
+    }
+  }
+
+  return str;
+}
+
+
+NLM_EXTERN CharPtr SummarizeFixPubCapsAction (FixPubCapsActionPtr a)
+{
+  CharPtr constraint = NULL;
+  Int4    len = 0;
+  CharPtr affil = "affiliation";
+  CharPtr title = "title";
+  CharPtr authors = "authors";
+  Boolean first = TRUE;
+  CharPtr summ = NULL;
+
+  if (a == NULL) {
+    return NULL;
+  }
+
+  if (a->title) {
+    len += 6 + StringLen (title);
+  }
+  if (a->authors) {
+    len += 6 + StringLen (authors);
+  }
+  if (a->affiliation) {
+    len += 6 + StringLen (affil);
+  }
+
+  if (len > 0) {
+    constraint = SummarizeConstraintSet (a->constraint);
+    len += StringLen (constraint) + 14;
+    summ = (CharPtr) MemNew (sizeof (Char) * len);
+    sprintf (summ, "Fix pub ");
+    if (a->title) {
+      StringCat (summ, title);
+      first = FALSE;
+    }
+    if (a->authors) {
+      if (!first) {
+        if (a->affiliation) {
+          StringCat (summ, ", ");
+        } else {
+          StringCat (summ, " and ");
+        }
+      }
+      first = FALSE;
+      StringCat (summ, authors);
+    }
+    if (a->affiliation) {
+      if (!first) {
+        if (a->title && a->authors) {
+          StringCat (summ, ", and ");
+        } else {
+          StringCat (summ, " and ");
+        }
+      }
+      first = FALSE;
+      StringCat (summ, affil);
+    }
+    if (constraint != NULL) {
+      StringCat (summ, " where ");
+      StringCat (summ, constraint);
+    }
+    constraint = MemFree (constraint);
+  }
+
+  return summ;
+}
+
+
+/* summarizing constraints */
+static CharPtr GetStringLocationPhrase (Uint2 match_location, Boolean not_present)
+{
+  CharPtr location_word = NULL;
+
+  switch (match_location) {
+    case String_location_contains :
+      if (not_present) {
+        location_word = "does not contain";
+      } else {
+        location_word = "contains";
+      }
+      break;
+    case String_location_equals :
+      if (not_present) {
+        location_word = "does not equal";
+      } else {
+        location_word = "equals";
+      }
+      break;
+    case String_location_starts :
+      if (not_present) {
+        location_word = "does not start with";
+      } else {
+        location_word = "starts with";
+      }
+      break;
+    case String_location_ends :
+      if (not_present) {
+        location_word = "does not end with";
+      } else {
+        location_word = "ends with";
+      }
+      break;
+    case String_location_inlist :
+      if (not_present) {
+        location_word = "is not one of";
+      } else {
+        location_word = "is one of";
+      }
+      break;
+  }
+  return location_word;
+}
+
+
+static CharPtr SummarizeStringConstraint (StringConstraintPtr constraint)
+{
+  CharPtr location_word = NULL;
+  CharPtr case_sensitive = "case-sensitive";
+  CharPtr whole_word = "whole word";
+  CharPtr str = NULL;
+  Int4 len;
+  CharPtr fmt = "%s '%s'";
+
+  if (constraint == NULL || constraint->match_text == NULL) return NULL;
+
+  location_word = GetStringLocationPhrase (constraint->match_location, constraint->not_present);
+  if (location_word == NULL) return NULL;
+  len = StringLen (location_word) + StringLen (constraint->match_text) + StringLen (fmt);
+  if (constraint->case_sensitive) {
+    len += StringLen (case_sensitive) + 3;
+  }
+  if (constraint->whole_word) {
+    len += StringLen (whole_word) + 3;
+  }
+  str = (CharPtr) MemNew (sizeof (Char) * len);
+  sprintf (str, fmt, location_word, constraint->match_text);
+  if (constraint->case_sensitive || constraint->whole_word) {
+    StringCat (str, " (");
+  }
+  if (constraint->case_sensitive) {
+    StringCat (str, case_sensitive);
+    if (constraint->whole_word) {
+      StringCat (str, ", ");
+    }
+  }
+  if (constraint->whole_word) {
+    StringCat (str, whole_word);
+  }
+  if (constraint->case_sensitive || constraint->whole_word) {
+    StringCat (str, ")");
+  }
+
+  return str;
+}
+
+
+static CharPtr SummarizePartialnessForLocationConstraint (LocationConstraintPtr constraint)
+{
+  if (constraint == NULL 
+      || (constraint->partial5 == Partial_constraint_either
+      && constraint->partial3 == Partial_constraint_either)) {
+    return NULL;
+  }
+  if (constraint->partial5 == Partial_constraint_either) {
+    if (constraint->partial3 == Partial_constraint_partial) {
+      return "that are 3' partial";
+    } else {
+      return "that are 3' complete";
+    }
+  } else if (constraint->partial3 == Partial_constraint_either) {
+    if (constraint->partial5 == Partial_constraint_partial) {
+      return "that are 5' partial";
+    } else {
+      return "that are 5' complete";
+    }
+  } else if (constraint->partial5 == Partial_constraint_partial
+             && constraint->partial3 == Partial_constraint_partial) {
+    return "that are partial on both ends";
+  } else if (constraint->partial5 == Partial_constraint_complete
+             && constraint->partial3 == Partial_constraint_complete) {
+    return "that are complete on both ends";
+  } else if (constraint->partial5 == Partial_constraint_complete
+             && constraint->partial3 == Partial_constraint_partial) {
+    return "that are 5' complete and 3' partial";
+  } else if (constraint->partial5 == Partial_constraint_partial
+             && constraint->partial3 == Partial_constraint_complete) {
+    return "that are 5' partial and 3' complete";
+  } else {
+    return NULL;
+  }
+}
+
+
+static CharPtr SummarizeLocationType (LocationConstraintPtr constraint)
+{
+  if (constraint == NULL 
+      || constraint->location_type == Location_type_constraint_any) {
+    return NULL;
+  } else if (constraint->location_type == Location_type_constraint_single_interval) {
+    return "with single interval";
+  } else if (constraint->location_type == Location_type_constraint_joined) {
+    return "with joined intervals";
+  } else if (constraint->location_type == Location_type_constraint_ordered) {
+    return "with ordered intervals";
+  } else {
+    return NULL;
+  }
+}
+
+
+static CharPtr distance_words[] = { NULL, "exactly", "no more than", "no less than" };
+
+static CharPtr SummarizeEndDistance (ValNodePtr vnp, CharPtr end_name)
+{
+  CharPtr str = NULL;
+  CharPtr fmt = "with %s %s %d from end of sequence";
+
+  if (vnp == NULL || vnp->choice < 1 || vnp->choice > 3) {
+    return NULL;
+  }
+
+  str = (CharPtr) MemNew (sizeof (Char) * (StringLen (distance_words[vnp->choice]) + StringLen (end_name) + StringLen (fmt) + 15));
+  sprintf (str, fmt, end_name, distance_words[vnp->choice], vnp->data.intvalue);
+
+  return str;
+}
+
+
+static CharPtr SummarizeLocationConstraint (LocationConstraintPtr constraint)
+{
+  CharPtr str = NULL;
+  CharPtr strand_word = NULL, seq_word = NULL;
+  CharPtr fmt = "only objects";
+  CharPtr partial;
+  CharPtr location_type;
+  CharPtr dist5 = NULL, dist3 = NULL;
+  Int4    len = 0;
+
+  if (IsLocationConstraintEmpty (constraint)) {
+    return NULL;
+  }
+
+  partial = SummarizePartialnessForLocationConstraint (constraint);
+  location_type = SummarizeLocationType(constraint);
+  dist5 = SummarizeEndDistance (constraint->end5, "5' end");
+  dist3 = SummarizeEndDistance (constraint->end3, "3' end");
+
+  if (constraint->seq_type == Seqtype_constraint_nuc) {
+    seq_word = "nucleotide sequences";
+  } else if (constraint->seq_type == Seqtype_constraint_prot) {
+    seq_word = "protein sequences";
+  }
+
+  if (constraint->strand == Strand_constraint_plus) {
+    strand_word = " on plus strands";
+  } else if (constraint->strand == Strand_constraint_minus) {
+    strand_word = " on minus strands";
+  }
+
+  len = StringLen (fmt) + 1;
+  if (strand_word != NULL) {
+    len += StringLen (strand_word);
+  }
+  if (seq_word != NULL) {
+    len += StringLen (seq_word) + 4;
+  }
+  if (partial != NULL) {
+    len += StringLen (partial) + 2;
+  }
+  if (location_type != NULL) {
+    len += StringLen (location_type) + 2;
+  }
+  if (dist5 != NULL) {
+    len += StringLen (dist5) + 1;
+  }
+  if (dist3 != NULL) {
+    len += StringLen (dist3) + 1;
+  }
+  str = (CharPtr) MemNew (sizeof (Char) * len);
+  sprintf (str, "%s", fmt);
+  if (strand_word == NULL && seq_word != NULL) {
+    StringCat (str, " on ");
+    StringCat (str, seq_word);
+  } else if (strand_word != NULL) {
+    StringCat (str, strand_word);
+    if (seq_word != NULL) {
+      StringCat (str, " of ");
+      StringCat (str, seq_word);
+    }
+  }
+  if (partial != NULL) {
+    StringCat (str, " ");
+    StringCat (str, partial);
+  }
+  if (location_type != NULL) {
+    StringCat (str, " ");
+    StringCat (str, location_type);
+  }
+
+  if (dist5 != NULL) {
+    StringCat (str, " ");
+    StringCat (str, dist5);
+    dist5 = MemFree (dist5);
+  }
+  if (dist3 != NULL) {
+    StringCat (str, " ");
+    StringCat (str, dist3);
+    dist3 = MemFree (dist3);
+  }
+    
+  return str;
+}
+
+
+static CharPtr SummarizeSourceConstraint (SourceConstraintPtr constraint)
+{
+  CharPtr string, intro = NULL, field1, field2;
+  CharPtr match_fmt = "%s %s matches %s";
+  CharPtr present_fmt = "%s %s is present";
+  CharPtr text_fmt = "%s text %s";
+  CharPtr two_match_fmt = "%s %s matches %s and %s %s";
+  CharPtr one_match_fmt = "%s %s %s";
+  CharPtr summ = NULL;
+
+  if (constraint == NULL) return NULL;
+
+  string = SummarizeStringConstraint (constraint->constraint);
+  field1 = SummarizeSourceQual (constraint->field1);
+  field2 = SummarizeSourceQual (constraint->field2);
+
+  if (constraint->field1 == NULL && constraint->field2 == NULL && string == NULL) {
+    if (constraint->type_constraint == Object_type_constraint_feature) {
+      summ = StringSave ("where source is a feature");
+    } else if (constraint->type_constraint == Object_type_constraint_descriptor) {
+      summ = StringSave ("where source is a descriptor");
+    }
+  } else { 
+    if (constraint->type_constraint == Object_type_constraint_any) {
+      intro = "where source";
+    } else if (constraint->type_constraint == Object_type_constraint_feature) {
+      intro = "where source feature";
+    } else if (constraint->type_constraint == Object_type_constraint_descriptor) {
+      intro = "where source descriptor";
+    } else {
+      string = MemFree (string);
+      field1 = MemFree (field1);
+      field2 = MemFree (field2);
+      return NULL;
+    }
+
+    if (string == NULL) {
+      if (field1 == NULL && field2 == NULL) {
+        if (constraint->type_constraint == Object_type_constraint_feature) {
+          summ = StringSave ("where source is a feature");
+        } else if (constraint->type_constraint == Object_type_constraint_descriptor) {
+          summ = StringSave ("where source is a descriptor");
+        }
+      } else if (field1 != NULL && field2 != NULL) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (match_fmt) + StringLen (intro) + StringLen (field1) + StringLen (field2)));
+        sprintf (summ, match_fmt, intro, field1, field2);
+      } else if (field1 != NULL) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (intro) + StringLen (field1)));
+        sprintf (summ, present_fmt, intro, field1);
+      } else if (field2 != NULL) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (intro) + StringLen (field2)));
+        sprintf (summ, present_fmt, intro, field2);
+      }
+    } else {
+      if (field1 == NULL && field2 == NULL) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (text_fmt) + StringLen (intro) + StringLen (string)));
+        sprintf (summ, text_fmt, intro, string);
+      } else if (field1 != NULL && field2 != NULL) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (two_match_fmt) + StringLen (intro) 
+                                                   + 2 * StringLen (field1) + StringLen (field2) + StringLen (string)));
+        sprintf (summ, two_match_fmt, intro, field1, field2, field1, string);
+      } else if (field1 != NULL) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (intro) + StringLen (field1) + StringLen (string)));
+        sprintf (summ, one_match_fmt, intro, field1, string);
+      } else if (field2 != NULL) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (intro) + StringLen (field2) + StringLen (string)));
+        sprintf (summ, one_match_fmt, intro, field2, string);
+      }
+    }
+  }
+  string = MemFree (string);
+  field1 = MemFree (field1);
+  field2 = MemFree (field2);
+  return summ;
+}
+
+
+
+static CharPtr SummarizeCDSGeneProtPseudoConstraint (CDSGeneProtPseudoConstraintPtr constraint)
+{
+  CharPtr summ = NULL, pseudo_feat;
+  CharPtr is_pseudo_fmt = "where %s is pseudo";
+  CharPtr not_pseudo_fmt = "where %s is not pseudo";
+
+  if (constraint != NULL) {
+    pseudo_feat = CDSGeneProtFeatureNameFromFeatureType (constraint->feature);
+    if (pseudo_feat != NULL) {
+      if (constraint->is_pseudo) {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (is_pseudo_fmt) + StringLen (pseudo_feat)));
+        sprintf (summ, is_pseudo_fmt, pseudo_feat);
+      } else {
+        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (not_pseudo_fmt) + StringLen (pseudo_feat)));
+        sprintf (summ, not_pseudo_fmt, pseudo_feat);
+      }
+    }
+  }
+     
+  return summ;
+}
+
+
+static CharPtr SummarizeCDSGeneProtQualConstraint (CDSGeneProtQualConstraintPtr constraint)
+{
+  CharPtr string, field1 = NULL, field2 = NULL;
+  CharPtr match_fmt = "where %s matches %s";
+  CharPtr present_fmt = "where %s is present";
+  CharPtr text_fmt = "where CDS-gene-prot text %s";
+  CharPtr two_match_fmt = "where %s matches %s and %s %s";
+  CharPtr one_match_fmt = "where %s %s";
+  CharPtr summ = NULL;
+
+  if (constraint == NULL) return NULL;
+
+  string = SummarizeStringConstraint (constraint->constraint);
+  if (constraint->field1 != NULL && constraint->field1->choice == CDSGeneProtConstraintField_field) {
+    field1 = CDSGeneProtNameFromField (constraint->field1->data.intvalue);
+  }
+  if (constraint->field2 != NULL && constraint->field2->choice == CDSGeneProtConstraintField_field) {
+    field2 = CDSGeneProtNameFromField (constraint->field2->data.intvalue);
+  }
+
+  if (string == NULL) {
+    if (field1 != NULL && field2 != NULL) {
+      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (match_fmt) + StringLen (field1) + StringLen (field2)));
+      sprintf (summ, match_fmt, field1, field2);
+    } else if (field1 != NULL) {
+      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (field1)));
+      sprintf (summ, present_fmt, field1);
+    } else if (field2 != NULL) {
+      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (field2)));
+      sprintf (summ, present_fmt, field2);
+    }
+  } else {
+    if (field1 == NULL && field2 == NULL) {
+      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (text_fmt) + StringLen (string)));
+      sprintf (summ, text_fmt, string);
+    } else if (field1 != NULL && field2 != NULL) {
+      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (two_match_fmt)  
+                                                  + 2 * StringLen (field1) + StringLen (field2) + StringLen (string)));
+      sprintf (summ, two_match_fmt, field1, field2, field1, string);
+    } else if (field1 != NULL) {
+      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (field1) + StringLen (string)));
+      sprintf (summ, one_match_fmt, field1, string);
+    } else if (field2 != NULL) {
+      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (field2) + StringLen (string)));
+      sprintf (summ, one_match_fmt, field2, string);
+    }
+  }
+  
+  string = MemFree (string);
+  /* note - field1 and field2 aren't allocated, so we don't need to free them */
+
+  return summ;
+}
+
+
+const CharPtr s_QuantityWords [] = { "exactly", "more than", "less than" };
+const Int4 k_NumQuantityWords = sizeof (s_QuantityWords) / sizeof (CharPtr);
+
+static CharPtr SummarizeFeatureQuantity (ValNodePtr v)
+{
+  CharPtr fmt = "sequence has %s %d feature%s";
+  CharPtr summ = NULL;
+
+  if (v == NULL || v->choice < 1 || v->choice > k_NumQuantityWords) {
+    return NULL;
+  }
+  
+  summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (s_QuantityWords[v->choice - 1]) + 15));
+  sprintf (summ, fmt, s_QuantityWords[v->choice - 1], v->data.intvalue, v->data.intvalue == 1 ? "" : "s");
+  return summ;
+}
+
+
+static CharPtr SummarizeSequenceConstraint (SequenceConstraintPtr constraint)
+{
+  CharPtr summ = NULL;
+  CharPtr seq_word = NULL, featpresent = NULL, id = NULL;
+  Int4    len = 0;
+  CharPtr seq_word_intro = "where sequence type is ";
+  CharPtr feat_after = " is present";
+  CharPtr id_intro = "sequence ID ";
+  CharPtr feat_quantity = NULL;
+  
+  if (IsSequenceConstraintEmpty (constraint)) {
+    summ = StringSave ("Missing sequence constraint");
+  } else {
+    if (constraint->seqtype != NULL && constraint->seqtype->choice != SequenceConstraintMolTypeConstraint_any) {
+      switch (constraint->seqtype->choice) {
+        case SequenceConstraintMolTypeConstraint_nucleotide:
+          seq_word = "nucleotide";
+          break;
+        case SequenceConstraintMolTypeConstraint_dna:
+          seq_word = "DNA";
+          break;
+        case SequenceConstraintMolTypeConstraint_rna:
+          if (constraint->seqtype->data.intvalue == Sequence_constraint_rnamol_any) {
+            seq_word = "RNA";
+          } else {
+            seq_word = GetBiomolNameForRnaType (constraint->seqtype->data.intvalue);
+          }
+          break;
+        case SequenceConstraintMolTypeConstraint_protein:
+          seq_word = "protein";
+          break;
+      }
+    }
+
+    if (constraint->feature != Feature_type_any) {
+      featpresent = GetFeatureNameFromFeatureType (constraint->feature);
+    }
+
+    if (!IsStringConstraintEmpty (constraint->id)) {
+      id = SummarizeStringConstraint (constraint->id);
+    }
+ 
+    if (seq_word != NULL) {
+      len += StringLen (seq_word) + StringLen (seq_word_intro);
+    }
+
+    if (featpresent != NULL) {
+      if (len == 0) {
+        len += 6;
+      } else {
+        len += 5;
+      }
+      len += StringLen (featpresent);
+      len += StringLen (feat_after);
+    }
+
+    if (id != NULL) {
+      if (len == 0) {
+        len += 6;
+      } else {
+        len += 5;
+      }
+      len += StringLen (id_intro);
+      len += StringLen (id);
+    }
+
+    feat_quantity = SummarizeFeatureQuantity (constraint->num_features);
+    if (feat_quantity != NULL) {
+      len += StringLen (feat_quantity) + 6;
+    }
+
+    if (len == 0) {
+      summ = StringSave ("missing sequence constraint");
+    } else {
+      len++;
+      summ = (CharPtr) MemNew (sizeof (Char) * len);
+      summ[0] = 0;
+      if (seq_word != NULL) {
+        StringCat (summ, seq_word_intro);
+        StringCat (summ, seq_word);
+      }
+      if (featpresent != NULL) {
+        if (seq_word == NULL) {
+          StringCat (summ, "where ");
+        } else {
+          StringCat (summ, " and ");
+        }
+        StringCat (summ, featpresent);
+        StringCat (summ, feat_after);
+      }
+      if (id != NULL) {
+        if (seq_word == NULL && featpresent == NULL) {
+          StringCat (summ, "where ");
+        } else {
+          StringCat (summ, " and ");
+        }
+        StringCat (summ, id_intro);
+        StringCat (summ, id);
+      }
+      if (feat_quantity != NULL) {
+        if (StringHasNoText (summ)) {
+          StringCat (summ, "where ");
+        } else {
+          StringCat (summ, " and ");
+        }
+        StringCat (summ, feat_quantity);
+      }
+    }
+    id = MemFree (id);
+    feat_quantity = MemFree (feat_quantity);
+  }
+  return summ;
+}
+
+
+const CharPtr s_SpecialPubFieldWords [] = { "is present", "is not present", "is all caps" };
+const Int4 k_NumSpecialPubFieldWords = sizeof (s_SpecialPubFieldWords) / sizeof (CharPtr);
+
+static CharPtr SummarizePubFieldSpecialConstraint (PubFieldSpecialConstraintPtr field)
+{
+  CharPtr fmt = "%s %s";
+  CharPtr label, summ = NULL;
+
+  if (field == NULL || field->constraint == NULL 
+      || field->constraint->choice < 1 
+      || field->constraint->choice > k_NumSpecialPubFieldWords) {
+    return NULL;
+  }
+
+  label = GetPubFieldLabel (field->field);
+
+  summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (label)
+                                            + StringLen (s_SpecialPubFieldWords[field->constraint->choice - 1])));
+  sprintf (summ, fmt, label, s_SpecialPubFieldWords[field->constraint->choice - 1]);
+  return summ;
+}
+
+
+static CharPtr SummarizePubFieldConstraint (PubFieldConstraintPtr field)
+{
+  CharPtr fmt = "%s %s", summ = NULL;
+  CharPtr string, label;
+
+  if (field == NULL || field->constraint == NULL) {
+    return NULL;
+  }
+
+  string = SummarizeStringConstraint (field->constraint);
+  label = GetPubFieldLabel (field->field);
+
+  summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (label) + StringLen (string)));
+  sprintf (summ, fmt, label, string);
+  string = MemFree (string);
+  return summ;
+}
+
+
+static CharPtr SummarizePublicationConstraint (PublicationConstraintPtr constraint)
+{
+  CharPtr type = NULL, field = NULL, special = NULL, summ = NULL;
+  Boolean first = TRUE;
+  Int4 len;
+
+  if (IsPublicationConstraintEmpty (constraint)) return NULL;
+
+  switch (constraint->type) {
+    case Pub_type_published:
+      type = "pub is published";
+      break;
+    case Pub_type_unpublished:
+      type = "pub is unpublished";
+      break;
+    case Pub_type_in_press:
+      type = "pub is in press";
+      break;
+    case Pub_type_submitter_block:
+      type = "pub is submitter block";
+      break;
+  }
+
+  field = SummarizePubFieldConstraint (constraint->field);
+  special = SummarizePubFieldSpecialConstraint (constraint->special_field);
+
+  if (type == NULL && field == NULL && special == NULL) {
+    return NULL;
+  }
+  
+  len = 17 + StringLen (type) + StringLen (field) + StringLen (special);
+  summ = (CharPtr) MemNew (sizeof (Char) * len);
+  sprintf (summ, "where ");
+  if (type != NULL) {
+    StringCat (summ, type);
+    first = FALSE;
+  }
+  if (field != NULL) {
+    if (!first) {
+      StringCat (summ, " and ");
+    }
+    StringCat (summ, field);
+    first = FALSE;
+  }
+
+  if (special != NULL) {
+    if (!first) {
+      StringCat (summ, " and ");
+    }
+    StringCat (summ, special);
+    first = FALSE;
+  }
+
+  field = MemFree (field);
+  special = MemFree (special);
+
+  return summ;
+}
+
+
+static CharPtr SummarizeFieldConstraint (FieldConstraintPtr constraint)
+{
+  CharPtr rval = NULL;
+  CharPtr string = NULL, label = NULL;
+  CharPtr fmt = "where %s %s";
+
+  if (IsFieldConstraintEmpty (constraint)) return NULL;
+
+  string = SummarizeStringConstraint (constraint->string_constraint);
+  label = SummarizeFieldType (constraint->field);
+
+  if (string != NULL && label != NULL) {
+    rval = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (label) + StringLen (string)));
+    sprintf (rval, fmt, label, string);
+  }    
+  string = MemFree (string);
+  label = MemFree (label);
+
+  return rval;
+}
+
+
+NLM_EXTERN CharPtr SummarizeConstraint (ValNodePtr constraint)
+{
+  CharPtr phrase = NULL, tmp;
+  CharPtr fmt = "where object text %s";
+
+  if (constraint == NULL) return NULL;
+  switch (constraint->choice) {
+    case ConstraintChoice_string:
+      tmp = SummarizeStringConstraint (constraint->data.ptrvalue);
+      if (tmp != NULL) {
+        phrase = (CharPtr) MemNew (sizeof (Char) * (StringLen (tmp) + StringLen (fmt)));
+        sprintf (phrase, fmt, tmp);
+        tmp = MemFree (tmp);
+      }
+      break;
+    case ConstraintChoice_location:
+      phrase = SummarizeLocationConstraint (constraint->data.ptrvalue);
+      break;
+    case ConstraintChoice_source:
+      phrase = SummarizeSourceConstraint (constraint->data.ptrvalue);
+      break;
+    case ConstraintChoice_cdsgeneprot_qual:
+      phrase = SummarizeCDSGeneProtQualConstraint (constraint->data.ptrvalue);
+      break;
+    case ConstraintChoice_cdsgeneprot_pseudo:
+      phrase = SummarizeCDSGeneProtPseudoConstraint (constraint->data.ptrvalue);
+      break;
+    case ConstraintChoice_sequence:
+      phrase = SummarizeSequenceConstraint (constraint->data.ptrvalue);
+      break;
+    case ConstraintChoice_pub:
+      phrase = SummarizePublicationConstraint (constraint->data.ptrvalue);
+      break;
+    case ConstraintChoice_field:
+      phrase = SummarizeFieldConstraint (constraint->data.ptrvalue);
+      break;
+  }
+  return phrase;
+}
+
+
+NLM_EXTERN CharPtr SummarizeConstraintSet (ValNodePtr constraint_set)
+{
+  ValNodePtr phrases = NULL, vnp;
+  Int4 len = 0;
+  CharPtr phrase, str = NULL;
+
+  while (constraint_set != NULL) {
+    phrase = SummarizeConstraint (constraint_set);
+    if (phrase != NULL) {
+      ValNodeAddPointer (&phrases, 0, phrase);
+      if (len > 0) {
+        len += 5; /* for " and " */
+      } else {
+        len += 1; /* for terminal NULL */
+      }
+      len += StringLen (phrase);
+    }
+    constraint_set = constraint_set->next;
+  }
+  if (len > 0) {
+    str = (CharPtr) MemNew (sizeof (Char) * len);
+    for (vnp = phrases; vnp != NULL; vnp = vnp->next) {
+      StringCat (str, vnp->data.ptrvalue);
+      if (vnp->next != NULL) {
+        StringCat (str, " and ");
+      }
+    }
+  }
+  return str;
+}
+
+
 /* for table readers that use the macro language functions */
 
 /* MatchType is used to represent how the column should be matched.
@@ -20662,18 +24236,337 @@ static ValNodePtr FindBioseqsByMatchType (SeqEntryPtr sep, Uint1 match_location,
   return d.obj_list;
 }
 
+typedef struct bioseqsearchitem {
+  BioseqPtr bsp;
+  CharPtr   str;
+  Int4      num;
+  Boolean   free_str;
+} BioseqSearchItemData, PNTR BioseqSearchItemPtr;
+
+static BioseqSearchItemPtr BioseqSearchItemNewStr (BioseqPtr bsp, CharPtr str, Boolean need_free)
+{
+  BioseqSearchItemPtr bsi;
+
+  bsi = (BioseqSearchItemPtr) MemNew (sizeof (BioseqSearchItemData));
+  bsi->bsp = bsp;
+  bsi->str = str;
+  bsi->free_str = need_free;
+  if (IsAllDigits (bsi->str)) {
+    bsi->num = atoi (bsi->str);
+  }
+  return bsi;
+}
+
+
+static BioseqSearchItemPtr BioseqSearchItemNewInt (BioseqPtr bsp, Int4 num)
+{
+  BioseqSearchItemPtr bsi;
+
+  bsi = (BioseqSearchItemPtr) MemNew (sizeof (BioseqSearchItemData));
+  bsi->bsp = bsp;
+  bsi->num = num;
+  bsi->free_str = FALSE;
+  return bsi;
+}
+
+
+static BioseqSearchItemPtr BioseqSearchItemFree (BioseqSearchItemPtr bsi)
+{
+  if (bsi != NULL) {
+    if (bsi->free_str) {
+      bsi->str = MemFree (bsi->str);
+    }
+    bsi = MemFree (bsi);
+  }
+  return bsi;
+}
+
+
+static int CompareBioseqSearchItem (BioseqSearchItemPtr b1, BioseqSearchItemPtr b2)
+{
+  if (b1 == NULL && b2 == NULL) {
+    return 0;
+  } else if (b1 == NULL) {
+    return 1;
+  } else if (b2 == NULL) {
+    return -1;
+  } else if (b1->num > 0 && b2->num > 0) {
+    if (b1->num < b2->num) {
+      return -1;
+    } else if (b1->num == b2->num) {
+      return 0;
+    } else {
+      return 1;
+    }
+  } else if (b1->num > 0) {
+    return 1;
+  } else if (b2->num > 0) {
+    return -1;
+  } else {
+    return StringICmp (b1->str, b2->str);
+  }
+}
+
+
+static int LIBCALLBACK SortVnpByBioseqSearchItem (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 == NULL || ptr2 == NULL) return 0;
+  vnp1 = *((ValNodePtr PNTR) ptr1);
+  vnp2 = *((ValNodePtr PNTR) ptr2);
+  if (vnp1 == NULL || vnp2 == NULL) return 0;
+
+  return CompareBioseqSearchItem(vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+}
+
+
+NLM_EXTERN void ValNodeAddPointerToEnd (ValNodeBlockPtr vnbp, Uint1 choice, Pointer data)
+{
+  ValNodePtr vnp_new;
+
+  vnp_new = ValNodeAddPointer (&(vnbp->tail), choice, data);
+  if (vnbp->head == NULL) {
+    vnbp->head = vnp_new;
+  }
+  vnbp->tail = vnp_new;
+}
+
+
+NLM_EXTERN void ValNodeAddPointerToFront (ValNodeBlockPtr vnbp, Uint1 choice, Pointer data)
+{
+  ValNodePtr vnp;
+
+  vnp = ValNodeNew (NULL);
+  vnp->choice = choice;
+  vnp->data.ptrvalue = data;
+  vnp->next = vnbp->head;
+  vnbp->head = vnp;
+}
+
+
+static void BuildIDStringsListCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqIdPtr   sip, sip_next;
+  CharPtr    id, cp;
+  DbtagPtr   dbtag;
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    sip_next = sip->next;
+    sip->next = NULL;
+    id = SeqIdWholeLabel (sip, PRINTID_FASTA_LONG);
+    sip->next = sip_next;
+    if (id != NULL) {
+      /* remove terminating pipe character */
+      if (id[StringLen(id) - 1] == '|') 
+      {
+        id[StringLen(id) - 1] = 0;
+      }
+      ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, id, TRUE));
+
+      /* remove leading pipe identifier */
+      cp = StringChr (id, '|');
+      if (cp != NULL)
+      {
+        cp = cp + 1;
+        ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, cp, FALSE));
+      } else {
+        cp = id;
+      }
+
+
+      /* try ID without version */
+      id = StringSave (cp);
+      cp = StringChr (id, '.');
+      if (cp != NULL) 
+      {
+        *cp = 0;
+        ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, id, TRUE));
+      } else {
+        id = MemFree (id);
+      }
+
+      /* just bankit number */
+      if (sip->choice == SEQID_GENERAL 
+          && (dbtag = (DbtagPtr) sip->data.ptrvalue) != NULL) {
+        if (StringCmp (dbtag->db, "BankIt") == 0) {
+          if (dbtag->tag->id > 0) {
+            id = (CharPtr) MemNew (sizeof (Char) * 22);
+            sprintf (id, "BankIt%d", dbtag->tag->id);
+            ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, id, TRUE));
+            ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewInt (bsp, dbtag->tag->id));
+          } else {
+            id = (CharPtr) MemNew (sizeof (Char) * (8 + StringLen (dbtag->tag->str)));
+            sprintf (id, "BankIt%s", dbtag->tag->str);
+            ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, id, TRUE));
+            ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, dbtag->tag->str, FALSE));
+          }
+        } else if (StringCmp (dbtag->db, "NCBIFILE") == 0 && dbtag->tag != NULL) {
+          ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, dbtag->tag->str, FALSE));
+          if ((cp = StringRChr (dbtag->tag->str, '/')) != NULL) {
+            ValNodeAddPointerToEnd ((ValNodeBlockPtr)data, 0, BioseqSearchItemNewStr (bsp, cp + 1, FALSE));
+          }
+        }
+      }
+    }
+  }
+}
+
+
+/* first are str, second are int */
+typedef struct bioseqsearchindex {
+  Int4 num_str;
+  Int4 num_int;
+  Int4 num_total;
+  BioseqSearchItemPtr PNTR items;
+} BioseqSearchIndexData, PNTR BioseqSearchIndexPtr;
+
+
+static BioseqSearchIndexPtr BioseqSearchIndexFree (BioseqSearchIndexPtr index)
+{
+  Int4 i;
+
+  if (index != NULL) {
+    for (i = 0; i < index->num_total; i++) {
+      index->items[i] = BioseqSearchItemFree(index->items[i]);
+    }
+    index->items = MemFree (index->items);
+    index = MemFree (index);
+  }
+  return index;
+}
+
+
+static BioseqSearchIndexPtr BuildIDStringsList (SeqEntryPtr sep)
+{
+  ValNodeBlock vnb;
+  ValNodePtr list = NULL, vnp;
+  Int4       num_total, i;
+  BioseqSearchIndexPtr index;
+
+  vnb.head = NULL;
+  vnb.tail = NULL;
+
+  VisitBioseqsInSep (sep, &vnb, BuildIDStringsListCallback);
+  list = vnb.head;
+  list = ValNodeSort (list, SortVnpByBioseqSearchItem);
+
+  num_total = ValNodeLen (list);
+
+  index = (BioseqSearchIndexPtr) MemNew (sizeof (BioseqSearchIndexData));
+  index->items = (BioseqSearchItemPtr PNTR) MemNew (sizeof (BioseqSearchItemPtr) * num_total);
+  for (vnp = list, i = 0; vnp != NULL && i < num_total; vnp = vnp->next, i++) {
+    index->items[i] = vnp->data.ptrvalue;
+    vnp->data.ptrvalue = NULL;
+    if (index->items[i]->num > 0) {
+      index->num_int++;
+    } else {
+      index->num_str++;
+    }
+  }
+  index->num_total = index->num_int + index->num_str;
+  list = ValNodeFree (list);
+
+  return index;
+}
+
+
+
+static BioseqPtr FindStringInIdListIndex (CharPtr str, BioseqSearchIndexPtr index)
+{
+  CharPtr    tmp;
+  Int4       match, imax, imin, i, j;
+  Int4       num = -1;
+
+  if (index == NULL) {
+    return NULL;
+  }
+  if (IsAllDigits (str)) {
+    match = atoi (str);
+    imax = index->num_total - 1;
+    imin = index->num_str;
+    while (imax >= imin)
+    {
+        i = (imax + imin)/2;
+        if (index->items[i]->num < match)
+            imax = i - 1;
+        else if (index->items[i]->num > match)
+            imin = i + 1;
+        else
+        {
+            num = i;
+            break;
+        }
+    }
+
+  } else {
+    imax = index->num_str - 1;
+    imin = 0;
+    while (imax >= imin)
+    {
+        i = (imax + imin)/2;
+        tmp = index->items[i]->str;
+        if ((j = StringICmp(tmp, str)) > 0)
+            imax = i - 1;
+        else if (j < 0)
+            imin = i + 1;
+        else
+        {
+            num = i;
+            break;
+        }
+    }
+  }
+
+  if (num > -1) {
+    return index->items[num]->bsp;
+  } else {
+    return NULL;
+  }
+}
+
+
+static ValNodePtr FindListInIdListIndex (Uint1 match_location, CharPtr match_str, BioseqSearchIndexPtr index)
+{
+  Int4 i;
+  ValNodePtr list = NULL;
+  StringConstraintPtr scp;
+
+  if (StringHasNoText (match_str) || index == NULL) {
+    return NULL;
+  }
+  scp = StringConstraintNew ();
+  scp->match_text = StringSave (match_str);
+  scp->match_location = match_location;
+  for (i = 0; i < index->num_str; i++) {
+    if (DoesStringMatchConstraint (index->items[i]->str, scp)) {
+      ValNodeAddPointer (&list, OBJ_BIOSEQ, index->items[i]->bsp);
+    }
+  }
+  scp = StringConstraintFree (scp);
+
+  list = ValNodeSort (list, SortVnpByChoiceAndPtrvalue);
+  ValNodeUnique (&list, SortVnpByChoiceAndPtrvalue, ValNodeFree);
+  return list;
+}
+
 
 static ValNodePtr 
-FindMatchForRow 
+FindMatchForRowEx 
 (MatchTypePtr match_type,
  CharPtr      match_str,
  Uint2        entityID,
- SeqEntryPtr  sep)
+ SeqEntryPtr  sep,
+ BioseqSearchIndexPtr index
+ )
 {
   ValNodePtr match_list = NULL;
   FindGeneLocusTagData fd;
   SeqFeatPtr           sfp;
   SeqMgrFeatContext    fcontext;
+  BioseqPtr            bsp;
 
   if (match_type == NULL || sep == NULL) return NULL;
 
@@ -20692,7 +24585,16 @@ FindMatchForRow
       break;
     case eTableMatchProteinID:
     case eTableMatchNucID:
+      if (match_type->match_location == String_location_equals && index != NULL) {
+        bsp = FindStringInIdListIndex (match_str, index);
+        if (bsp != NULL) {
+          ValNodeAddPointer (&match_list, OBJ_BIOSEQ, bsp);
+        }
+      } else if (index != NULL) {
+        ValNodeLink (&match_list, FindListInIdListIndex (match_type->match_location, match_str, index));
+      } else {
       ValNodeLink (&match_list, FindBioseqsByMatchType (sep, match_type->match_location, match_str));
+      }
       break;
     case eTableMatchDbxref:
       match_list = GetFeaturesByDbxref (sep, match_str, match_type->match_location);
@@ -20708,6 +24610,18 @@ FindMatchForRow
 }
 
 
+static ValNodePtr 
+FindMatchForRow
+(MatchTypePtr match_type,
+ CharPtr      match_str,
+ Uint2        entityID,
+ SeqEntryPtr  sep
+ )
+{
+  return FindMatchForRowEx (match_type, match_str, entityID, sep, NULL);
+}
+
+
 static ValNodePtr GetFeatureListForProteinBioseq (Uint1 featdef, BioseqPtr bsp)
 {
   ValNodePtr feat_list = NULL;
@@ -21307,7 +25221,7 @@ static ValNodePtr GetStructuredCommentListForRowAndColumn (MatchTypePtr match_ty
     if (vnp->choice == OBJ_BIOSEQ) {
       for (sdp = SeqMgrGetNextDescriptor (vnp->data.ptrvalue, NULL, Seq_descr_user, &context);
            sdp != NULL;
-           sdp = sdp->next) {
+           sdp = SeqMgrGetNextDescriptor (vnp->data.ptrvalue, sdp, Seq_descr_user, &context)) {
         if (IsUserObjectStructuredComment (sdp->data.ptrvalue)) {
           ValNodeAddPointer (&target_list, OBJ_SEQDESC, sdp);
         }
@@ -21394,11 +25308,15 @@ static ValNodePtr GetTargetListForRowAndColumn (MatchTypePtr match_type, ValNode
     vnp = vnp_next;
   }
 
+  /* remove targets found twice */
+  target_list = ValNodeSort (target_list, SortVnpByChoiceAndPtrvalue);
+  ValNodeUnique (&target_list, SortVnpByChoiceAndPtrvalue, ValNodeFree);
+
   return target_list;
 }
 
 
-static void ReportMissingTargets (ValNodePtr PNTR perr_list, FieldTypePtr ft, CharPtr match_val, Int4 col_num, Int4 line_num)
+static void ReportMissingTargets (ValNodeBlockPtr err_list, FieldTypePtr ft, CharPtr match_val, Int4 col_num, Int4 line_num)
 {
   CharPtr            feat_name;
   FeatureFieldPtr    field;
@@ -21408,7 +25326,7 @@ static void ReportMissingTargets (ValNodePtr PNTR perr_list, FieldTypePtr ft, Ch
   CharPtr            no_cmt_fmt = "No structured comment for %s (column %d, line %d)";
   CharPtr            err_msg;
 
-  if (perr_list == NULL || ft == NULL || match_val == NULL) return;
+  if (err_list == NULL || ft == NULL || match_val == NULL) return;
 
   switch (ft->choice) {
     case FieldType_source_qual:
@@ -21416,7 +25334,7 @@ static void ReportMissingTargets (ValNodePtr PNTR perr_list, FieldTypePtr ft, Ch
                                                     + StringLen (match_val)
                                                     + 30));
       sprintf (err_msg, no_src_fmt, match_val, col_num, line_num);
-      ValNodeAddPointer (perr_list, 0, err_msg);
+      ValNodeAddPointerToEnd (err_list, 0, err_msg);
       break;
     case FieldType_feature_field:
       field = (FeatureFieldPtr) ft->data.ptrvalue;
@@ -21427,7 +25345,7 @@ static void ReportMissingTargets (ValNodePtr PNTR perr_list, FieldTypePtr ft, Ch
                                                       + StringLen (match_val)
                                                       + 30));
         sprintf (err_msg, no_feat_fmt, feat_name, match_val, col_num, line_num);
-        ValNodeAddPointer (perr_list, 0, err_msg);
+        ValNodeAddPointerToEnd (err_list, 0, err_msg);
       }
       break;
     case FieldType_cds_gene_prot:
@@ -21439,7 +25357,7 @@ static void ReportMissingTargets (ValNodePtr PNTR perr_list, FieldTypePtr ft, Ch
                                                       + StringLen (match_val)
                                                       + 30));
         sprintf (err_msg, no_feat_fmt, feat_name, match_val, col_num, line_num);
-        ValNodeAddPointer (perr_list, 0, err_msg);
+        ValNodeAddPointerToEnd (err_list, 0, err_msg);
       }
       field = FeatureFieldFree (field);
       break;
@@ -21452,34 +25370,34 @@ static void ReportMissingTargets (ValNodePtr PNTR perr_list, FieldTypePtr ft, Ch
                                                       + StringLen (match_val)
                                                       + 30));
         sprintf (err_msg, no_feat_fmt, feat_name, match_val, col_num, line_num);
-        ValNodeAddPointer (perr_list, 0, err_msg);
+        ValNodeAddPointerToEnd (err_list, 0, err_msg);
       }
       field = FeatureFieldFree (field);
       break;
     case FieldType_struc_comment_field:
       err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (no_cmt_fmt) + StringLen (match_val) + 30));
       sprintf (err_msg, no_cmt_fmt, match_val, col_num, line_num);
-      ValNodeAddPointer (perr_list, 0, err_msg);
+      ValNodeAddPointerToEnd (err_list, 0, err_msg);
       break;
     case FieldType_misc:
       err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (no_seq_fmt) 
                                                     + StringLen (match_val)
                                                     + 30));
       sprintf (err_msg, no_seq_fmt, match_val, col_num, line_num);
-      ValNodeAddPointer (perr_list, 0, err_msg);
+      ValNodeAddPointerToEnd (err_list, 0, err_msg);
       break;
   }
 }
 
 
-static void ReportEmptyIDColumn (ValNodePtr PNTR perr_list, Int4 line_num)
+static void ReportEmptyIDColumn (ValNodeBlockPtr vnb, Int4 line_num)
 {
   CharPtr            err_msg;
   CharPtr            missing_id_fmt = "No ID for line %d";
 
   err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (missing_id_fmt) + 15));
   sprintf (err_msg, missing_id_fmt, line_num);
-  ValNodeAddPointer (perr_list, 0, err_msg);
+  ValNodeAddPointerToEnd (vnb, 0, err_msg);
 }
 
 static ValNodePtr FindMatchChoiceInLine (ValNodePtr val_vnp, ValNodePtr col_vnp)
@@ -21764,9 +25682,9 @@ static ValNodePtr ReportTableSummaryLine (Int4 err_lines, Int4 total_lines, Char
 
 NLM_EXTERN ValNodePtr GetObjectTableForTabTable (SeqEntryPtr sep, ValNodePtr table, ValNodePtr columns, ValNodePtr PNTR p_err_list)
 {
-  ValNodePtr err_list = NULL;
+  ValNodeBlock vnb;
   ValNodePtr line_vnp, val_vnp, col_vnp, err_vnp;
-  ValNodePtr obj_table = NULL, obj_row;
+  ValNodePtr obj_table = NULL, obj_row, last_obj = NULL, tmp, last = NULL;
   Int4       line_num = 1, col_num;
   Uint2      entityID;
   ValNodePtr match_list, match_choice, target_list;
@@ -21775,22 +25693,25 @@ NLM_EXTERN ValNodePtr GetObjectTableForTabTable (SeqEntryPtr sep, ValNodePtr tab
   CharPtr            no_match_fmt = "No match for %s, line %d";
   MatchTypePtr       match_type;
   Int4       num_empty = 0, num_missing = 0, num_no_targets = 0;
+  BioseqSearchIndexPtr  index = NULL;
 
+  vnb.head = NULL;
+  vnb.tail = NULL;
 
   if (sep == NULL) {
-    ValNodeAddPointer (&err_list, 0, StringSave ("No SeqEntry"));
+    ValNodeAddPointerToEnd (&vnb, 0, StringSave ("No SeqEntry"));
   }
   if (table == NULL) {
-    ValNodeAddPointer (&err_list, 0, StringSave ("No table"));
+    ValNodeAddPointerToEnd (&vnb, 0, StringSave ("No table"));
   }
   if (columns == NULL) {
-    ValNodeAddPointer (&err_list, 0, StringSave ("No column information"));
+    ValNodeAddPointerToEnd (&vnb, 0, StringSave ("No column information"));
   }
-  if (err_list != NULL) {
+  if (vnb.head != NULL) {
     if (p_err_list == NULL) {
-      err_list = ValNodeFreeData (err_list);
+      vnb.head = ValNodeFreeData (vnb.head);
     } else {
-      *p_err_list = err_list;
+      *p_err_list = vnb.head;
     }
     return NULL;
   }
@@ -21800,18 +25721,21 @@ NLM_EXTERN ValNodePtr GetObjectTableForTabTable (SeqEntryPtr sep, ValNodePtr tab
   match_type = FindMatchTypeInHeader (columns);
   if (match_type == NULL) return NULL;
 
+  index = BuildIDStringsList(sep);
+
+  last = NULL;
   for (line_vnp = table, line_num = 1; line_vnp != NULL; line_vnp = line_vnp->next, line_num++) {
     obj_row = NULL;
     match_choice = FindMatchChoiceInLine (line_vnp->data.ptrvalue, columns);
     if (match_choice == NULL || StringHasNoText (match_choice->data.ptrvalue)) {
-      ReportEmptyIDColumn (&err_list, line_num);
+      ReportEmptyIDColumn (&vnb, line_num);
       num_empty++;
     } else {
-      match_list = FindMatchForRow (match_type, match_choice->data.ptrvalue, entityID, sep);
+      match_list = FindMatchForRowEx (match_type, match_choice->data.ptrvalue, entityID, sep, index);
       if (match_list == NULL) {
         err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (no_match_fmt) + StringLen (match_choice->data.ptrvalue) + 15));
         sprintf (err_msg, no_match_fmt, match_choice->data.ptrvalue, line_num);
-        ValNodeAddPointer (&err_list, 0, err_msg);
+        ValNodeAddPointerToEnd (&vnb, 0, err_msg);
         num_missing ++;
       } else {
         for (val_vnp = line_vnp->data.ptrvalue, col_vnp = columns, col_num = 1;
@@ -21825,7 +25749,7 @@ NLM_EXTERN ValNodePtr GetObjectTableForTabTable (SeqEntryPtr sep, ValNodePtr tab
           } else {         
             target_list = GetTargetListForRowAndColumn (match_type, match_list, t->field, t->constraint);
             if (target_list == NULL) {
-              ReportMissingTargets (&err_list, t->field, match_choice->data.ptrvalue, col_num, line_num); 
+              ReportMissingTargets (&vnb, t->field, match_choice->data.ptrvalue, col_num, line_num); 
               num_no_targets++;
             }
           }
@@ -21836,31 +25760,36 @@ NLM_EXTERN ValNodePtr GetObjectTableForTabTable (SeqEntryPtr sep, ValNodePtr tab
         }
       }
     }
-    ValNodeAddPointer (&obj_table, 0, obj_row);
+    tmp = ValNodeAddPointer (&last_obj, 0, obj_row);
+    if (obj_table == NULL) {
+      obj_table = last_obj;
+    }
+    last_obj = tmp;
   }
 
   match_type = MatchTypeFree (match_type);
+  index = BioseqSearchIndexFree (index);
 
-  if (err_list != NULL) {    
+  if (vnb.head != NULL) {    
     if (num_empty > 0) {
       err_vnp = ReportTableSummaryLine (num_empty, line_num - 1, "%d lines out of %d have no ID value");
-      err_vnp->next = err_list;
-      err_list = err_vnp;
+      err_vnp->next = vnb.head;
+      vnb.head = err_vnp;
     }
     if (num_no_targets > 0) {
       err_vnp = ReportTableSummaryLine (num_no_targets, line_num - 1, "%d lines out of %d have no targets");
-      err_vnp->next = err_list;
-      err_list = err_vnp;
+      err_vnp->next = vnb.head;
+      vnb.head = err_vnp;
     }
     if (num_missing > 0) {
       err_vnp = ReportTableSummaryLine (num_missing, line_num - 1, "%d lines out of %d have no match");
-      err_vnp->next = err_list;
-      err_list = err_vnp;
+      err_vnp->next = vnb.head;
+      vnb.head = err_vnp;
     }
     if (p_err_list == NULL) {
-      err_list = ValNodeFreeData (err_list);
+      vnb.head = ValNodeFreeData (vnb.head);
     } else {
-      *p_err_list = err_list;
+      *p_err_list = vnb.head;
     }
   }  
   return obj_table;
@@ -22172,7 +26101,7 @@ static int LIBCALLBACK SortVnpByChoiceAndPtrvalue (VoidPtr ptr1, VoidPtr ptr2)
         return -1;
       } else if (vnp1->data.ptrvalue > vnp2->data.ptrvalue) {
         return 1;
-      } else if (vnp2->data.ptrvalue < vnp2->data.ptrvalue) {
+      } else if (vnp1->data.ptrvalue < vnp2->data.ptrvalue) {
         return -1;
       } else {
         return 0;
@@ -22238,14 +26167,20 @@ static CharPtr FormatMultipleDestinationErrorMessage (Int4 col_num, ValNodePtr m
 NLM_EXTERN ValNodePtr CheckObjTableForRowsThatApplyToTheSameDestination (ValNodePtr obj_table)
 {
   Int4 col_num;
+  ValNodeBlock vnb, err_list;
   ValNodePtr line_vnp, col_vnp, obj_vnp, vnp;
-  ValNodePtr col_list = NULL, col_obj_list;
+  ValNodePtr col_obj_list;
   Boolean any_column_values_left;
-  ValNodePtr err_list = NULL, match_rows;
+  ValNodePtr match_rows;
+
+  vnb.head = NULL;
+  vnb.tail = NULL;
+  err_list.head = NULL;
+  err_list.tail = NULL;
   
   /* now, for each row, get pointer to first column */
   for (line_vnp = obj_table; line_vnp != NULL; line_vnp = line_vnp->next) {
-    ValNodeAddPointer (&col_list, 0, line_vnp->data.ptrvalue);
+    ValNodeAddPointerToEnd (&vnb, 0, line_vnp->data.ptrvalue);
   }
 
   /* now for each column, make a list of all features in the column, then sort to see if there are duplicates */
@@ -22254,7 +26189,7 @@ NLM_EXTERN ValNodePtr CheckObjTableForRowsThatApplyToTheSameDestination (ValNode
   while (any_column_values_left) {
     any_column_values_left = FALSE;
     col_obj_list = NULL;
-    for (vnp = col_list; vnp != NULL; vnp = vnp->next) {
+    for (vnp = vnb.head; vnp != NULL; vnp = vnp->next) {
       col_vnp = vnp->data.ptrvalue;
       if (col_vnp != NULL) {
         obj_vnp = col_vnp->data.ptrvalue;
@@ -22270,7 +26205,7 @@ NLM_EXTERN ValNodePtr CheckObjTableForRowsThatApplyToTheSameDestination (ValNode
             && vnp->data.ptrvalue == vnp->next->data.ptrvalue) {
           match_rows = FindRowsForObjectInObjectTable (obj_table, col_num - 1, vnp->choice, vnp->data.ptrvalue);
           /* report rows with matches */
-          ValNodeAddPointer (&err_list, col_num, FormatMultipleDestinationErrorMessage (col_num, match_rows));
+          ValNodeAddPointerToEnd (&err_list, col_num, FormatMultipleDestinationErrorMessage (col_num, match_rows));
           match_rows = ValNodeFree (match_rows);
           /* skip over the cluster of matches */
           while (vnp->next != NULL && vnp->choice == vnp->next->choice) {
@@ -22282,8 +26217,8 @@ NLM_EXTERN ValNodePtr CheckObjTableForRowsThatApplyToTheSameDestination (ValNode
     }
     col_num++;
   }
-  col_list = ValNodeFree (col_list);
-  return err_list;
+  vnb.head = ValNodeFree (vnb.head);
+  return err_list.head;
 }
 
 
@@ -22309,7 +26244,7 @@ static CharPtr GetMatchTextForLine (ValNodePtr values, ValNodePtr columns)
 /* Note - when creating error messages, mark summary messages with choice = 1 */
 NLM_EXTERN ValNodePtr CheckObjTableForExistingText (SeqEntryPtr sep, ValNodePtr table, ValNodePtr columns, ValNodePtr obj_table)
 {
-  ValNodePtr err_list = NULL, vnp;
+  ValNodeBlock vnb;
   ValNodePtr val_line_vnp, obj_line_vnp;
   ValNodePtr val_vnp, obj_vnp, col_vnp;
   ValNodePtr col_tot = NULL, col_tot_vnp;
@@ -22326,17 +26261,20 @@ NLM_EXTERN ValNodePtr CheckObjTableForExistingText (SeqEntryPtr sep, ValNodePtr
   CharPtr            match_txt;
   CharPtr            new_val;
 
+  vnb.head = NULL;
+  vnb.tail = NULL;
+
   if (sep == NULL) {
-    ValNodeAddPointer (&err_list, 1, StringSave ("No SeqEntry"));
+    ValNodeAddPointerToEnd (&vnb, 1, StringSave ("No SeqEntry"));
   }
   if (table == NULL) {
-    ValNodeAddPointer (&err_list, 1, StringSave ("No table"));
+    ValNodeAddPointerToEnd (&vnb, 1, StringSave ("No table"));
   }
   if (columns == NULL) {
-    ValNodeAddPointer (&err_list, 1, StringSave ("No column information"));
+    ValNodeAddPointerToEnd (&vnb, 1, StringSave ("No column information"));
   }
-  if (err_list != NULL) {
-    return err_list;
+  if (vnb.head != NULL) {
+    return vnb.head;
   }
 
   entityID = SeqMgrGetEntityIDForSeqEntry (sep);
@@ -22384,7 +26322,7 @@ NLM_EXTERN ValNodePtr CheckObjTableForExistingText (SeqEntryPtr sep, ValNodePtr
                                                            + StringLen (qual_name)
                                                            + 30));
               sprintf (err_msg, already_has_val_fmt, match_txt, str, new_val, col_num, qual_name, line_num); 
-              ValNodeAddPointer (&err_list, 0, err_msg);
+              ValNodeAddPointerToEnd (&vnb, 0, err_msg);
               num_existing_text ++;
               new_val = MemFree (new_val);
               col_tot_vnp->data.intvalue ++;
@@ -22418,42 +26356,34 @@ NLM_EXTERN ValNodePtr CheckObjTableForExistingText (SeqEntryPtr sep, ValNodePtr
       if (col_tot_vnp->data.intvalue > 0) {
         err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (col_tot_fmt) + 45));
         sprintf (err_msg, col_tot_fmt, col_num, col_tot_vnp->data.intvalue, line_num - 1);
-        ValNodeAddPointer (&err_list, 1, err_msg);
+        ValNodeAddPointerToEnd (&vnb, 1, err_msg);
       }
     }
 
     err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (num_existing_text_fmt)
                                                 + 15));
     sprintf (err_msg, num_existing_text_fmt, num_existing_text);
-    vnp = ValNodeNew (NULL);
-    vnp->choice = 0;
-    vnp->data.ptrvalue = err_msg;
-    vnp->next = err_list;
-    err_list = vnp;
+    ValNodeAddPointerToFront (&vnb, 0, err_msg);
   }
   col_tot = ValNodeFree (col_tot);
   if (num_with_mrna > 0 && num_without_mrna > 0) {
     err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (mrna_warn_fmt)
                                                 + 30));
     sprintf (err_msg, mrna_warn_fmt, num_with_mrna, num_without_mrna);
-    vnp = ValNodeNew (NULL);
-    vnp->choice = 1;
-    vnp->data.ptrvalue = err_msg;
-    vnp->next = err_list;
-    err_list = vnp;
+    ValNodeAddPointerToFront (&vnb, 1, err_msg);
   }    
 
-  return err_list;
+  return vnb.head;
 }
 
 
 NLM_EXTERN ValNodePtr ApplyTableToFeatures (SeqEntryPtr sep, ValNodePtr table, ValNodePtr columns)
 {
-  ValNodePtr err_list = NULL;
+  ValNodeBlock vnb;
   ValNodePtr line_vnp, val_vnp, col_vnp;
   Int4       line_num = 1, col_num;
   Uint2      entityID;
-  ValNodePtr match_list, match_choice, target_list, feat_vnp, vnp;
+  ValNodePtr match_list, match_choice, target_list, feat_vnp;
   TabColumnConfigPtr t;
   CharPtr            err_msg;
   CharPtr            no_match_fmt = "No match for %s, line %d";
@@ -22464,17 +26394,20 @@ NLM_EXTERN ValNodePtr ApplyTableToFeatures (SeqEntryPtr sep, ValNodePtr table, V
   Boolean            success;
   MatchTypePtr       match_type;
 
+  vnb.head = NULL;
+  vnb.tail = NULL;
+
   if (sep == NULL) {
-    ValNodeAddPointer (&err_list, 0, StringSave ("No SeqEntry"));
+    ValNodeAddPointerToEnd (&vnb, 0, StringSave ("No SeqEntry"));
   }
   if (table == NULL) {
-    ValNodeAddPointer (&err_list, 0, StringSave ("No table"));
+    ValNodeAddPointerToEnd (&vnb, 0, StringSave ("No table"));
   }
   if (columns == NULL) {
-    ValNodeAddPointer (&err_list, 0, StringSave ("No column information"));
+    ValNodeAddPointerToEnd (&vnb, 0, StringSave ("No column information"));
   }
-  if (err_list != NULL) {
-    return err_list;
+  if (vnb.head != NULL) {
+    return vnb.head;
   }
 
   match_type = FindMatchTypeInHeader (columns);
@@ -22484,13 +26417,13 @@ NLM_EXTERN ValNodePtr ApplyTableToFeatures (SeqEntryPtr sep, ValNodePtr table, V
   for (line_vnp = table, line_num = 1; line_vnp != NULL; line_vnp = line_vnp->next, line_num++) {
     match_choice = FindMatchChoiceInLine (line_vnp->data.ptrvalue, columns);
     if (match_choice == NULL || StringHasNoText (match_choice->data.ptrvalue)) {
-      ReportEmptyIDColumn (&err_list, line_num);
+      ReportEmptyIDColumn (&vnb, line_num);
     } else {
       match_list = FindMatchForRow (match_type, match_choice->data.ptrvalue, entityID, sep);
       if (match_list == NULL) {
         err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (no_match_fmt) + StringLen (match_choice->data.ptrvalue) + 15));
         sprintf (err_msg, no_match_fmt, match_choice->data.ptrvalue, line_num);
-        ValNodeAddPointer (&err_list, 0, err_msg);
+        ValNodeAddPointerToEnd (&vnb, 0, err_msg);
       } else {
         for (val_vnp = line_vnp->data.ptrvalue, col_vnp = columns, col_num = 1;
              col_vnp != NULL;
@@ -22506,7 +26439,7 @@ NLM_EXTERN ValNodePtr ApplyTableToFeatures (SeqEntryPtr sep, ValNodePtr table, V
           
           target_list = GetTargetListForRowAndColumn (match_type, match_list, t->field, t->constraint);
           if (target_list == NULL) {
-            ReportMissingTargets (&err_list, t->field, match_choice->data.ptrvalue, col_num, line_num); 
+            ReportMissingTargets (&vnb, t->field, match_choice->data.ptrvalue, col_num, line_num); 
           } else {
             if (val_vnp == NULL || val_vnp->data.ptrvalue == NULL) {
               val = "";
@@ -22531,7 +26464,7 @@ NLM_EXTERN ValNodePtr ApplyTableToFeatures (SeqEntryPtr sep, ValNodePtr table, V
               } else {
                 err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_col_val_fmt) + 30));
                 sprintf (err_msg, bad_col_val_fmt, col_num, line_num);
-                ValNodeAddPointer (&err_list, 0, err_msg);
+                ValNodeAddPointerToEnd (&vnb, 0, err_msg);
               }
             }
           }
@@ -22547,19 +26480,15 @@ NLM_EXTERN ValNodePtr ApplyTableToFeatures (SeqEntryPtr sep, ValNodePtr table, V
   
   err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (num_affected_fmt) + 15));
   sprintf (err_msg, num_affected_fmt, num_fields_affected);
-  vnp = ValNodeNew (NULL);
-  vnp->data.ptrvalue = err_msg;
-  vnp->next = err_list;
-  err_list = vnp;
+  ValNodeAddPointerToFront (&vnb, 0, err_msg);
   match_type = MatchTypeFree (match_type);
 
-  return err_list;
+  return vnb.head;
 }
 
-
 NLM_EXTERN ValNodePtr CheckTableForExistingText (SeqEntryPtr sep, ValNodePtr table, ValNodePtr columns)
 {
-  ValNodePtr err_list = NULL, vnp;
+  ValNodeBlock vnb;
   ValNodePtr line_vnp, val_vnp, col_vnp;
   Int4       line_num = 1, col_num, num_existing_text = 0;
   Uint2      entityID;
@@ -22572,17 +26501,19 @@ NLM_EXTERN ValNodePtr CheckTableForExistingText (SeqEntryPtr sep, ValNodePtr tab
   ValNodePtr         target_list, feat_vnp;
   MatchTypePtr       match_type;
 
+  vnb.head = NULL;
+  vnb.tail = NULL;
   if (sep == NULL) {
-    ValNodeAddPointer (&err_list, 1, StringSave ("No SeqEntry"));
+    ValNodeAddPointerToEnd (&vnb, 1, StringSave ("No SeqEntry"));
   }
   if (table == NULL) {
-    ValNodeAddPointer (&err_list, 1, StringSave ("No table"));
+    ValNodeAddPointerToEnd (&vnb, 1, StringSave ("No table"));
   }
   if (columns == NULL) {
-    ValNodeAddPointer (&err_list, 1, StringSave ("No column information"));
+    ValNodeAddPointerToEnd (&vnb, 1, StringSave ("No column information"));
   }
-  if (err_list != NULL) {
-    return err_list;
+  if (vnb.head != NULL) {
+    return vnb.head;
   }
 
   match_type = FindMatchTypeInHeader (columns);
@@ -22593,13 +26524,16 @@ NLM_EXTERN ValNodePtr CheckTableForExistingText (SeqEntryPtr sep, ValNodePtr tab
   for (line_vnp = table, line_num = 1; line_vnp != NULL; line_vnp = line_vnp->next, line_num++) {
     match_choice = FindMatchChoiceInLine (line_vnp->data.ptrvalue, columns);
     if (match_choice == NULL || StringHasNoText (match_choice->data.ptrvalue)) {
-      ReportEmptyIDColumn (&err_list, line_num);
+      ReportEmptyIDColumn (&vnb, line_num);
+      if (vnb.head == NULL) {
+        vnb.head = vnb.tail;
+      }
     } else {
       match_list = FindMatchForRow (match_type, match_choice->data.ptrvalue, entityID, sep);
       if (match_list == NULL) {
         err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (no_match_fmt) + StringLen (match_choice->data.ptrvalue) + 15));
         sprintf (err_msg, no_match_fmt, match_choice->data.ptrvalue, line_num);
-        ValNodeAddPointer (&err_list, 0, err_msg);
+        ValNodeAddPointerToEnd (&vnb, 0, err_msg);
       } else {
         for (val_vnp = line_vnp->data.ptrvalue, col_vnp = columns, col_num = 1;
              col_vnp != NULL;
@@ -22614,7 +26548,7 @@ NLM_EXTERN ValNodePtr CheckTableForExistingText (SeqEntryPtr sep, ValNodePtr tab
           }
           target_list = GetTargetListForRowAndColumn (match_type, match_list, t->field, t->constraint);
           if (target_list == NULL) {
-            ReportMissingTargets (&err_list, t->field, match_choice->data.ptrvalue, col_num, line_num); 
+            ReportMissingTargets (&vnb, t->field, match_choice->data.ptrvalue, col_num, line_num); 
           } else {
             if (val_vnp == NULL || val_vnp->data.ptrvalue == NULL) {
               val = "";
@@ -22630,7 +26564,7 @@ NLM_EXTERN ValNodePtr CheckTableForExistingText (SeqEntryPtr sep, ValNodePtr tab
                                                             + StringLen (val)
                                                             + 30));
                 sprintf (err_msg, already_has_val_fmt, qual_name, str, col_num, line_num, val);
-                ValNodeAddPointer (&err_list, col_num, err_msg);
+                ValNodeAddPointerToEnd (&vnb, col_num, err_msg);
                 num_existing_text ++;
               }
               str = MemFree (str);
@@ -22649,14 +26583,10 @@ NLM_EXTERN ValNodePtr CheckTableForExistingText (SeqEntryPtr sep, ValNodePtr tab
     err_msg = (CharPtr) MemNew (sizeof (Char) * (StringLen (num_existing_text_fmt)
                                                 + 15));
     sprintf (err_msg, num_existing_text_fmt, num_existing_text);
-    vnp = ValNodeNew (NULL);
-    vnp->choice = 0;
-    vnp->data.ptrvalue = err_msg;
-    vnp->next = err_list;
-    err_list = vnp;
+    ValNodeAddPointerToFront (&vnb, 0, err_msg);
   }
 
-  return err_list;
+  return vnb.head;
 }
 
 
diff --git a/api/macroapi.h b/api/macroapi.h
index fd3e232..54509a6 100644
--- a/api/macroapi.h
+++ b/api/macroapi.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11/15/2007
 *
-* $Revision: 1.78 $
+* $Revision: 1.93 $
 *
 * File Description: 
 *
@@ -90,9 +90,11 @@ NLM_EXTERN CharPtr SummarizeFeatQual (ValNodePtr qual);
 NLM_EXTERN CharPtr GetSourceQualName (Int4 srcqual);
 NLM_EXTERN Int4 GetSourceQualTypeByName (CharPtr qualname);
 NLM_EXTERN Int4 GetSrcQualFromSubSrcOrOrgMod (Int4 qual, Boolean is_org_mod);
+NLM_EXTERN Int4 GetOrgModQualFromSrcQual (Int4 srcqual, Int4Ptr subfield);
 NLM_EXTERN ValNodePtr GetSourceQualList (Boolean for_remove);
 NLM_EXTERN Boolean IsNonTextSourceQual (Int4 srcqual);
 NLM_EXTERN Boolean IsNonTextFieldType (FieldTypePtr field);
+NLM_EXTERN TextFsaPtr GetOrgModSearch (void);
 NLM_EXTERN Int4 GenomeFromSrcLoc (Int4 srcloc);
 NLM_EXTERN Int4 SrcLocFromGenome (Int4 genome);
 NLM_EXTERN CharPtr LocNameFromGenome (Int4 genome);
@@ -156,15 +158,20 @@ NLM_EXTERN void AddAllRNASubtypesToChoiceList (ValNodePtr PNTR field_list);
 
 /* source qual functions */
 NLM_EXTERN CharPtr GetSourceQualFromBioSource (BioSourcePtr biop, SourceQualChoicePtr scp, StringConstraintPtr constraint);
+NLM_EXTERN ValNodePtr GetMultipleSourceQualsFromBioSource (BioSourcePtr biop, SourceQualChoicePtr scp, StringConstraintPtr constraint);
 NLM_EXTERN CharPtr GetQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp);
 NLM_EXTERN CharPtr GetQualFromFeatureEx (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp, BatchExtraPtr batch_extra);
+NLM_EXTERN Boolean SetQualOnFeature (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp, CharPtr value, Uint2 existing_text);
+NLM_EXTERN Boolean RemoveQualFromFeature (SeqFeatPtr sfp, FeatureFieldPtr field, StringConstraintPtr scp);
 NLM_EXTERN Boolean SetSourceQualInBioSource (BioSourcePtr biop, SourceQualChoicePtr scp, StringConstraintPtr constraint, CharPtr value, Uint2 existing_text);
 NLM_EXTERN Boolean RemoveSourceQualFromBioSource (BioSourcePtr biop, SourceQualChoicePtr scp, StringConstraintPtr constraint);
 NLM_EXTERN Boolean AllowSourceQualMulti (SourceQualChoicePtr s);
 
 NLM_EXTERN ValNodePtr SourceQualValsFromBioSourcePtr (BioSourcePtr biop);
 NLM_EXTERN BioSourcePtr BioSourceFromSourceQualVals (ValNodePtr fields);
-
+NLM_EXTERN CharPtr GetDBxrefFromBioSource (BioSourcePtr biop, CharPtr db_name);
+NLM_EXTERN Boolean SetDBxrefForBioSource (BioSourcePtr biop, CharPtr db_name, CharPtr str, Uint2 existing_text);
+NLM_EXTERN Boolean RemoveDBxrefForBioSource (BioSourcePtr biop, CharPtr db_name, StringConstraintPtr scp);
 
 /* RNA-field functions */
 NLM_EXTERN ValNodePtr GetRNATypeList (void);
@@ -173,7 +180,17 @@ NLM_EXTERN CharPtr GetNameForRnaField (Int4 rnafield);
 NLM_EXTERN CharPtr SummarizeRnaType (RnaFeatTypePtr rt);
 NLM_EXTERN FeatureFieldPtr FeatureFieldFromRnaQual (RnaQualPtr rq);
 NLM_EXTERN RnaQualPtr RnaQualFromFeatureField (FeatureFieldPtr ffp);
+NLM_EXTERN Boolean SetRNARefProductString (RnaRefPtr rrp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text);
+NLM_EXTERN CharPtr GetRNARefProductString (RnaRefPtr rrp, StringConstraintPtr scp);
 NLM_EXTERN CharPtr GetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp);
+NLM_EXTERN Boolean SetRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text);
+NLM_EXTERN Boolean RemoveRNAProductString (SeqFeatPtr sfp, StringConstraintPtr scp);
+NLM_EXTERN Boolean SettmRNATagPeptide (RnaRefPtr rrp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text);
+NLM_EXTERN CharPtr GettmRNATagPeptide (RnaRefPtr rrp, StringConstraintPtr scp);
+NLM_EXTERN Boolean SetncRNAClass (RnaRefPtr rrp, StringConstraintPtr scp, CharPtr new_val, Uint2 existing_text);
+NLM_EXTERN CharPtr GetncRNAClass (RnaRefPtr rrp, StringConstraintPtr scp);
+
+
 
 NLM_EXTERN CharPtr GetPubFieldLabel (Int4 pub_field);
 NLM_EXTERN ValNodePtr GetPubFieldList (void);
@@ -198,6 +215,7 @@ NLM_EXTERN Boolean IsFieldConstraintEmpty (FieldConstraintPtr constraint);
 NLM_EXTERN Boolean IsCDSGeneProtQualConstraintEmpty (CDSGeneProtQualConstraintPtr constraint);
 NLM_EXTERN Boolean IsLocationConstraintEmpty (LocationConstraintPtr lcp);
 NLM_EXTERN Boolean DoesObjectMatchConstraintChoiceSet (Uint1 choice, Pointer data, ConstraintChoiceSetPtr csp);
+NLM_EXTERN Boolean DoesSeqIDListMeetStringConstraint (SeqIdPtr sip, StringConstraintPtr string_constraint);
 NLM_EXTERN ValNodePtr FreeObjectList (ValNodePtr vnp);
 NLM_EXTERN ValNodePtr GetObjectListForAECRAction (SeqEntryPtr sep, AECRActionPtr action);
 NLM_EXTERN ValNodePtr GetObjectListForAECRActionEx (SeqEntryPtr sep, AECRActionPtr action, BatchExtraPtr batch_extra);
@@ -223,6 +241,9 @@ NLM_EXTERN int LIBCALLBACK SortVnpByObject (VoidPtr ptr1, VoidPtr ptr2);
 NLM_EXTERN Boolean IsConversionSupported (Uint2 featdef_from, Uint2 featdef_to);
 
 NLM_EXTERN CharPtr GetTextPortionFromString (CharPtr str, TextPortionPtr text_portion);
+NLM_EXTERN Boolean RemoveTextPortionFromString (CharPtr str, TextPortionPtr text_portion);
+NLM_EXTERN Boolean IsTextMarkerEmpty (TextMarkerPtr marker);
+NLM_EXTERN TextMarkerPtr MakeTextTextMarker (CharPtr text);
 
 NLM_EXTERN Uint2 GetEntityIdFromObject (Uint1 choice, Pointer data);
 
@@ -259,8 +280,12 @@ NLM_EXTERN void ApplyMolinfoBlockToSeqEntry (SeqEntryPtr sep, MolinfoBlockPtr mi
 NLM_EXTERN CharPtr GetDescriptorNameFromDescriptorType (Int4 descriptortype);
 NLM_EXTERN void AddAllDescriptorsToChoiceList (ValNodePtr PNTR descriptor_type_list);
 
+NLM_EXTERN Boolean IsFixPubCapsActionEmpty (FixPubCapsActionPtr action);
 
 NLM_EXTERN void ApplyMacroToSeqEntry (SeqEntryPtr sep, ValNodePtr macro, Int4Ptr pNumFields, Int4Ptr pNumFeat);
+NLM_EXTERN Boolean ApplyMacroToSeqEntryEx (SeqEntryPtr sep, ValNodePtr macro, Int4Ptr pNumFields, Int4Ptr pNumFeat, FILE *log_fp);
+
+NLM_EXTERN SeqFeatPtr ApplyOneFeatureToBioseq (BioseqPtr bsp, Uint1 featdef, SeqLocPtr slp, ValNodePtr fields, ValNodePtr src_fields, Boolean add_mrna);
 
 /* for generating text representations of macro objects */
 NLM_EXTERN CharPtr SummarizeSourceQual (ValNodePtr field);
@@ -268,6 +293,25 @@ NLM_EXTERN CharPtr FeatureFieldLabel (CharPtr feature_name, ValNodePtr field);
 NLM_EXTERN Boolean IsFeatureFieldEmpty (FeatureFieldPtr field);
 NLM_EXTERN Boolean IsFieldTypeEmpty (FieldTypePtr field);
 NLM_EXTERN CharPtr SummarizeFieldType (ValNodePtr vnp);
+NLM_EXTERN Boolean IsFieldTypeNonText (ValNodePtr field_type);
+NLM_EXTERN CharPtr SummarizeExistingText (Uint2 existing_text);
+extern const CharPtr kTaxnameAfterBinomialString;
+NLM_EXTERN CharPtr SummarizeTextPortion (TextPortionPtr text_portion);
+NLM_EXTERN CharPtr SummarizeParseSrc (ValNodePtr src);
+NLM_EXTERN CharPtr SummarizeParseDst (ValNodePtr dst);
+NLM_EXTERN CharPtr SummarizeAECRAction (AECRActionPtr a);
+NLM_EXTERN CharPtr SummarizeParseAction (ParseActionPtr p);
+NLM_EXTERN CharPtr SummarizeAutodefAction (AutodefActionPtr autodef);
+NLM_EXTERN CharPtr SummarizeRemoveDescriptorAction (RemoveDescriptorActionPtr a);
+NLM_EXTERN CharPtr SummarizeFixPubCapsAction (FixPubCapsActionPtr a);
+NLM_EXTERN CharPtr SummarizeConstraintSet (ValNodePtr constraint_set);
+NLM_EXTERN CharPtr SummarizeConstraint (ValNodePtr constraint);
+
+extern const CharPtr s_QuantityWords [];
+extern const Int4 k_NumQuantityWords;
+extern const CharPtr s_SpecialPubFieldWords [];
+extern const Int4 k_NumSpecialPubFieldWords;
+
 NLM_EXTERN Boolean AllowFieldMulti (FieldTypePtr field);
 
 NLM_EXTERN CharPtr GetFieldValueForObject (Uint1 choice, Pointer data, FieldTypePtr field, StringConstraintPtr scp);
@@ -275,6 +319,11 @@ NLM_EXTERN CharPtr GetFieldValueForObjectEx (Uint1 choice, Pointer data, FieldTy
 NLM_EXTERN Boolean SetFieldValueForObject (Uint1 choice, Pointer data, FieldTypePtr field, StringConstraintPtr scp, CharPtr value, Uint2 existing_text);
 NLM_EXTERN Boolean SetFieldValueForObjectEx (Uint1 choice, Pointer data, FieldTypePtr field, StringConstraintPtr scp, CharPtr value, Uint2 existing_text, BatchExtraPtr batch_extra);
 NLM_EXTERN BioseqPtr GetSequenceForObject (Uint1 choice, Pointer data);
+NLM_EXTERN ValNodePtr GetMultipleFieldValuesForObject (Uint1 choice, Pointer data, FieldTypePtr field, StringConstraintPtr scp, BatchExtraPtr batch_extra);
+
+NLM_EXTERN void ValNodeAddPointerToEnd (ValNodeBlockPtr vnbp, Uint1 choice, Pointer data);
+NLM_EXTERN void ValNodeAddPointerToFront (ValNodeBlockPtr vnbp, Uint1 choice, Pointer data);
+
 
 typedef enum {
   eTableMatchFeatureID = 1,
@@ -337,6 +386,13 @@ NLM_EXTERN BioseqPtr GetRepresentativeBioseqFromBioseqSet (BioseqSetPtr bssp);
 NLM_EXTERN ValNodePtr ValNodeCopyPtr (ValNodePtr orig);
 NLM_EXTERN SeqLocPtr ParseSimpleSeqLoc (CharPtr str, BioseqPtr bsp);
 
+NLM_EXTERN void FixCapitalizationInString (CharPtr PNTR pTitle, Uint2 capitalization, ValNodePtr   org_names);
+
+NLM_EXTERN Boolean GBBlockIsCompletelyEmpty (GBBlockPtr gb);
+
+NLM_EXTERN CharPtr GetObjectIdString (ObjectIdPtr oip);
+NLM_EXTERN Boolean SetObjectIdString (ObjectIdPtr oip, CharPtr value, Uint2 existing_text);
+
 #ifdef __cplusplus 
 } 
 #endif
diff --git a/api/objmgr.c b/api/objmgr.c
index b53135d..cfa33f9 100644
--- a/api/objmgr.c
+++ b/api/objmgr.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 9/94
 *
-* $Revision: 6.83 $
+* $Revision: 6.86 $
 *
 * File Description:  Manager for Bioseqs and BioseqSets
 *
@@ -1383,7 +1383,7 @@ static Boolean NEAR ObjMgrFreeUserDataFunc (ObjMgrPtr omp, Uint2 entityID,
 								Uint2 procid, Uint2 proctype, Uint2 userkey)
 {
 	OMUserDataPtr omudp=NULL, prev, next;
-	ObjMgrDataPtr omdp;
+    ObjMgrDataPtr omdp = NULL;
 	Boolean got_one = FALSE, view_left;
 	ObjMgrTypePtr omtp = NULL;
 	Uint2 type, options;
@@ -4434,6 +4434,57 @@ NLM_EXTERN Boolean LIBCALL ObjMgrSendMsg(Uint2 msg, Uint2 entityID, Uint4 itemID
 	return retval;
 }
 
+
+NLM_EXTERN Boolean LIBCALL ObjMgrSendMsgOnlyFeatLabelChange (Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype)
+{
+    ObjMgrPtr omp;
+    ObjMgrDataPtr omdp;
+    Boolean retval = FALSE;
+
+    if (msg == OM_MSG_UPDATE) {
+        SeqMgrRedoFeatByLabelIndexes (entityID, NULL);
+    } else if (msg == OM_MSG_DEL) {
+        SeqMgrRedoFeatByLabelIndexes (entityID, NULL);
+      ObjMgrDeSelect (entityID, itemID, itemtype, 0, NULL);
+    }
+    omp = ObjMgrReadLock();
+    omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
+    if (omdp != NULL)
+    {
+        ObjMgrSendMsgFunc(omp, omdp, msg, entityID, itemID, itemtype, 0, 0, 0, NULL);
+        retval = TRUE;
+    }
+    ObjMgrUnlock();
+    return retval;
+}
+
+
+
+NLM_EXTERN Boolean LIBCALL ObjMgrSendMsgNoFeatureChange(Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype)
+{
+    ObjMgrPtr omp;
+    ObjMgrDataPtr omdp;
+    Boolean retval = FALSE;
+
+    if (msg == OM_MSG_UPDATE) {
+      SeqMgrRedoDescriptorIndexes (entityID, NULL);
+    } else if (msg == OM_MSG_DEL) {
+      SeqMgrRedoDescriptorIndexes (entityID, NULL);
+      ObjMgrDeSelect (entityID, itemID, itemtype, 0, NULL);
+    }
+
+    omp = ObjMgrReadLock();
+    omdp = ObjMgrFindByEntityID(omp, entityID, NULL);
+    if (omdp != NULL)
+    {
+        ObjMgrSendMsgFunc(omp, omdp, msg, entityID, itemID, itemtype, 0, 0, 0, NULL);
+        retval = TRUE;
+    }
+    ObjMgrUnlock();
+    return retval;
+}
+
+
 NLM_EXTERN Boolean LIBCALL ObjMgrSendProcMsg(Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype,
                                              Uint2 fromProcID, Uint2 toProcID, Pointer procmsgdata)
 {
diff --git a/api/objmgr.h b/api/objmgr.h
index baaa692..16105b9 100644
--- a/api/objmgr.h
+++ b/api/objmgr.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 9/94
 *
-* $Revision: 6.41 $
+* $Revision: 6.43 $
 *
 * File Description:  Manager for Bioseqs and BioseqSets
 *
@@ -39,183 +39,6 @@
 * -------  ----------  -----------------------------------------------------
 *
 *
-* $Log: objmgr.h,v $
-* Revision 6.41  2006/08/08 20:20:19  kans
-* added ObjMgrReportProc, internals of ObjMgrReportFunc that takes file pointer
-*
-* Revision 6.40  2006/08/03 20:18:14  bollin
-* will remove desktop views if only desktop views remain
-*
-* Revision 6.39  2006/07/13 17:06:38  bollin
-* use Uint4 instead of Uint2 for itemID values
-* removed unused variables
-* resolved compiler warnings
-*
-* Revision 6.38  2005/04/08 21:23:08  kans
-* added ObjMgrStatusString function for debugging
-*
-* Revision 6.37  2004/04/01 13:43:05  lavr
-* Spell "occurred", "occurrence", and "occurring"
-*
-* Revision 6.36  2002/07/30 14:41:45  kans
-* removed omdp->rearranged
-*
-* Revision 6.35  2002/07/29 21:30:17  kans
-* added rearranged flag to omdp
-*
-* Revision 6.34  2002/07/01 14:29:03  kans
-* changed totobj, currobj to Uint4
-*
-* Revision 6.33  2002/05/31 21:53:27  yaschenk
-* changing lookup by EntityID to array[][]
-*
-* Revision 6.32  2001/12/26 20:54:14  kans
-* added defines for OM_OPT_RECORD_SUPPRESSED and OM_OPT_RECORD_DEAD
-*
-* Revision 6.31  2001/11/19 15:26:19  kans
-* added ObjMgrDeleteAllInRecord, still need to bail in ObjMgrDelete if bulkIndexFree, then call from BioseqFree and BioseqSetFree
-*
-* Revision 6.30  2001/11/15 18:15:48  kans
-* set bsp->omdp at creation, SeqMgrDeleteIndexesInRecord sets omdp->bulkIndexFree
-*
-* Revision 6.29  2001/05/31 22:58:25  kans
-* added ObjMgrReapOne, DEFAULT_MAXOBJ, autoclean reaps and frees one entity at a time, as needed
-*
-* Revision 6.28  2001/05/31 22:33:03  kans
-* added autoclean and maxobj to ObjMgr structure, ObjMgrAddFunc optionally calls ObjMgrReap and ObjMgrFreeCache to completely clear out least recently accessed objects if currobj >= maxobj
-*
-* Revision 6.27  2001/02/16 21:34:49  ostell
-* changed GetSecs() to ObjMgrTouchCnt() to reduce system calls
-*
-* Revision 6.26  2000/11/28 22:59:02  kans
-* omdp->lockcnt now a Uint2 to avoid overflow when locking accessions repeatedly referenced by genomic contig
-*
-* Revision 6.25  2000/11/28 21:43:55  kans
-* added ObjMgrReportFunc for debugging
-*
-* Revision 6.24  2000/10/30 21:26:09  shavirin
-* Changes and fixes for some MT-safety related problems.
-*
-* Revision 6.23  2000/04/07 15:01:24  durand
-* added UPDATE_TYPE_NEWSEQ define
-*
-* Revision 6.22  2000/03/02 21:11:05  lewisg
-* use bandalign for import sequence, make standalone ddv use viewmgr, make dialogs modal, send color update
-*
-* Revision 6.21  2000/02/10 17:05:52  kans
-* added UPDATE_TYPE_CN3D
-*
-* Revision 6.20  2000/02/10 16:53:55  kans
-* added UPDATE_TYPE_VIEWMGR define (presumably in the right place)
-*
-* Revision 6.19  1999/12/06 22:38:52  durand
-* add UPDATE_TYPE_CARETPOS to be used by DDV
-*
-* Revision 6.18  1999/12/03 23:17:23  lewisg
-* Patrick's new global update msg, argument passing when launching ddv, experimental editing
-*
-* Revision 6.17  1999/11/18 00:21:42  lewisg
-* draw speedups and selection on mouseup
-*
-* Revision 6.16  1999/10/29 18:53:08  durand
-* add DDVUpdateMSG typedef
-*
-* Revision 6.15  1999/10/15 20:56:40  lewisg
-* append DDV_ColorGlobal as userdata.  free memory when cn3d terminates.
-*
-* Revision 6.14  1999/09/27 20:03:15  kans
-* added rowID to OMMsgStruct, new ObjMgrSendRowMsg function
-*
-* Revision 6.13  1999/08/11 15:17:54  kans
-* added ObjMgrFreeByEntityID
-*
-* Revision 6.12  1999/07/06 17:17:28  ywang
-* add message OM_MSG_FLUSH
-*
- * Revision 6.11  1998/09/28  19:54:12  kans
- * made ObjMgrDump debugging function public, no longer conditionally compiled
- *
-* Revision 6.10  1998/07/01 19:11:51  kans
-* added fromProcID, toProcID, OM_MSG_PROCESS, ObjMgrSendProcMsg, time of indexing, ObjMgrGetProcID, moved protFeat and cdsOrRnaFeat to seqmgr structure
-*
-* Revision 6.9  1998/06/30 21:40:52  kans
-* added seqmgr feature indexed time stamp to omdp
-*
-* Revision 6.8  1998/06/29 20:35:53  kans
-* added reap and reload extra functions
-*
-* Revision 6.7  1998/06/29 00:23:54  kans
-* several changes to new indexing functions
-*
-* Revision 6.6  1998/06/27 22:23:44  kans
-* improvements and further implementation of new indexing, exploration functions
-*
-* Revision 6.5  1998/06/26 22:36:19  kans
-* initial work on tracking sorted features, and cds and prot links, for rapid collection
-*
-* Revision 6.4  1998/05/29 20:34:11  chappey
-* New objmgr messages OM_MSG_HIDE, OM_MSG_SHOW
-*
-* Revision 6.3  1998/03/24 23:55:33  kans
-* added OBJ_PROJECT define
-*
-* Revision 6.2  1997/11/19 22:14:39  ostell
-* added support for multithreaded programs
-*
-* Revision 6.1  1997/09/11 15:55:49  ostell
-* Added support for SetColor messages
-*
-* Revision 6.0  1997/08/25 18:06:49  madden
-* Revision changed to 6.0
-*
-* Revision 5.2  1997/06/19 18:38:31  vakatov
-* [WIN32,MSVC++]  Adopted for the "NCBIOBJ.LIB" DLL'ization
-*
-* Revision 5.1  1997/06/02 17:04:14  kans
-* added ObjMgrProcLoadEx
-*
-* Revision 5.0  1996/05/28 13:23:23  ostell
-* Set to revision 5.0
-*
- * Revision 4.10  1996/02/28  04:53:06  ostell
- * added ObjMgrHold suport
- *
- * Revision 4.8  1996/01/05  14:39:12  ostell
- * fix for control chars in comment
- *
- * Revision 4.6  1995/12/27  18:39:17  ostell
- * added OBJ_BIOSEQ_DELTA
- *
- * Revision 4.5  1995/12/22  14:45:45  ostell
- * added do_not_reload_from_cache to OmProcControl so that DataGet
- * functions from gather can control this behvior
- * added protection from recursion in ObjMgrDelete
- *
- * Revision 4.4  1995/12/06  14:58:12  ostell
- * added OBJ_SEQHIST_ALIGN
- *
- * Revision 4.3  1995/10/03  15:50:37  ostell
- * added support for selection by region.. now fully implemented
- *
- * Revision 4.2  1995/09/30  03:38:31  ostell
- * Changed ObjMgrMessage functions to pass a structure
- * Added support for selecting regions
- * Added ability to remove entity when no more views on it
- *
- * Revision 4.1  1995/09/25  18:06:41  ostell
- * added ObjMgrGenericAsnTextRead
- *
- * Revision 4.0  1995/07/26  13:49:01  ostell
- * force revision to 4.0
- *
- * Revision 1.18  1995/07/08  15:21:01  ostell
- * Added ObjMgrSetOptions() and related functions
- * Added support for delete of entity when no more user data on it
- * Added support for DirtyFlag
- *
- * Revision 1.17  1995/05/15  21:46:05  ostell
- * added Log line
- *
 *
 *
 * ==========================================================================
@@ -445,6 +268,8 @@ typedef struct ddvupdatemsg{
 *
 *****************************************************************************/
 NLM_EXTERN Boolean LIBCALL ObjMgrSendMsg PROTO((Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype));
+NLM_EXTERN Boolean LIBCALL ObjMgrSendMsgNoFeatureChange PROTO((Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype));
+NLM_EXTERN Boolean LIBCALL ObjMgrSendMsgOnlyFeatLabelChange PROTO((Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype));
 
 NLM_EXTERN Boolean LIBCALL ObjMgrSendProcMsg PROTO((Uint2 msg, Uint2 entityID, Uint4 itemID, Uint2 itemtype,
                                                     Uint2 fromProcID, Uint2 toProcID, Pointer procmsgdata));
diff --git a/api/salstruc.c b/api/salstruc.c
index 69d507d..6a62827 100644
--- a/api/salstruc.c
+++ b/api/salstruc.c
@@ -28,358 +28,6 @@
 *
 * Version Creation Date:   1/27/96
 *
-* $Log: salstruc.c,v $
-* Revision 6.18  2009/01/15 21:24:38  kans
-* removed unused variables
-*
-* Revision 6.17  2008/08/13 14:25:32  bollin
-* Fixed bug in method for adjusting alignments affected by trimming sequences.
-*
-* Revision 6.16  2006/07/13 17:06:39  bollin
-* use Uint4 instead of Uint2 for itemID values
-* removed unused variables
-* resolved compiler warnings
-*
-* Revision 6.15  2005/11/22 21:56:23  bollin
-* made function for deleting locations from alignments extern
-*
-* Revision 6.14  2005/09/16 17:12:13  bollin
-* if adjusting an alignment by removing portions, need to reindex the alignment.
-*
-* Revision 6.13  2005/06/10 20:37:26  kans
-* hydrogenosome uses mitochondrial genetic code
-*
-* Revision 6.12  2003/03/24 19:44:13  kans
-* showfastagap_fromalign does not put space between > and Seq-id
-*
-* Revision 6.11  2002/07/31 17:01:07  kans
-* do not call get_tot_line if not showing features (VL)
-*
-* Revision 6.10  2001/11/30 16:57:11  wheelan
-* removed line numbers from FASTA+GAP dumping
-*
-* Revision 6.9  1999/11/24 21:24:29  vakatov
-* Fixed for the C++ and/or MSVC DLL compilation
-*
-* Revision 6.8  1999/10/07 21:51:02  chappey
-* fixes compilation warnings
-*
-* Revision 6.7  1999/10/07 06:17:43  chappey
-* move multseqalign_from_pairseqalign from salstruc.c to salsap.c
-*
-* Revision 6.6  1999/09/30 19:00:15  chappey
-* remove unused parameter in SeqAlignTranslate
-*
-* Revision 6.5  1999/09/07 00:18:35  chappey
-* Setting right scope when collecting (gather) features for Bioseq
-*
-* Revision 6.4  1999/09/02 20:49:58  chappey
-* free valnodes in PairSeqAlignTo..
-*
-* Revision 6.3  1999/09/02 19:07:53  chappey
-* PairSeqAlign2.. returns NULL if no multiple sequence alignment was produced
-*
-* Revision 6.2  1999/09/01 18:28:23  chappey
-* PairSeqAlign2MultiSeqAlign does not free original SeqAlign
-*
-* Revision 6.1  1999/08/25 17:42:55  kans
-* moved from tools directory
-*
-* Revision 6.68  1999/08/20 19:22:49  chappey
-* move Propagate functions to salprop.[ch]
-*
-* Revision 6.67  1999/08/18 19:19:20  chappey
-* number_GBFeat+first_GBFeat
-*
-* Revision 6.66  1999/08/17 12:03:26  chappey
-* is_newfeat tests the subtype of the feature
-*
-* Revision 6.65  1999/08/11 16:44:55  chappey
-* more fix in ApplyBioFeat
-*
-* Revision 6.64  1999/08/11 16:20:08  chappey
-* ApplyBioFeatToSeqEntry now propagates correctly the CDS which extend to the end of the sequence
-*
-* Revision 6.63  1999/08/10 23:50:18  chappey
-* rewrite of the Propagate function
-*
-* Revision 6.62  1999/07/30 18:40:55  chappey
-* Alignment of amino acid sequences are UPPER cases only in Cn3D where they are in LOWER cases
-*
-* Revision 6.61  1999/07/19 22:03:07  ywang
-* force alignment strings to be displayed in lower case letters initially regardless of the existance of block--in data_collect_arrange
-*
-* Revision 6.60  1999/07/14 21:06:17  chappey
-* after debugging using lint and CC
-*
-* Revision 6.59  1999/06/29 13:56:27  chappey
-* more test in multseqalign_from_pairseqalign
-*
-* Revision 6.58  1999/06/28 21:36:45  chappey
-* bug in on_draw with features after scrolling
-*
-* Revision 6.57  1999/06/18 19:33:56  chappey
-* change SeqAlignFree to SeqAlignSetFree
-*
-* Revision 6.56  1999/05/03 22:15:37  chappey
-* cs_option.slabel_format = PRINTID_FASTA_LONG
-*
-* Revision 6.55  1999/01/25 17:21:49  durand
-* .
-*
-* Revision 6.54  1999/01/24 19:32:41  chappey
-* MergeFunc
-*
-* Revision 6.53  1999/01/23 22:14:26  chappey
-* bug in MergeFunc and related functions
-*
-* Revision 6.52  1999/01/19 03:26:18  chappey
-* Merge function allows to specify the intervalle to merge
-*
-* Revision 6.51  1999/01/18 22:47:55  chappey
-* merge update functions Merge3Func and Merge5Func
-*
-* Revision 6.50  1998/12/26 20:09:10  chappey
-* .
-*
-* Revision 6.49  1998/12/02 07:00:38  chappey
-* Copy Feature copies now all the names from the SeqFeat of the protein Bioseq
-*
-* Revision 6.48  1998/11/09 05:13:57  chappey
-* renamed SeqAlign functions
-*
-* Revision 6.47  1998/10/29 19:07:06  chappey
-* Feature propagation now extend CDS until the 1st stop codon
-*
-* Revision 6.46  1998/09/29 03:00:57  chappey
-* Propagation of SEQFEAT_BOND, SEQFEAT_SITE
-*
-* Revision 6.45  1998/09/18 11:48:23  chappey
-* SeqAlignGapCount and fix in BioseqTrimN
-*
-* Revision 6.44  1998/08/24 22:53:32  chappey
-* .
-*
-* Revision 6.43  1998/07/29 01:16:20  chappey
-* .
-*
-* Revision 6.42  1998/07/23 00:15:12  chappey
-* bug in showfastagap_fromalign
-*
-* Revision 6.41  1998/07/22 23:51:03  chappey
-* bug in export PHYLIP format
-*
-* Revision 6.40  1998/07/22 22:54:02  chappey
-* .
-*
-* Revision 6.39  1998/07/17 19:07:57  chappey
-* .
-*
-* Revision 6.38  1998/07/15 20:54:24  chappey
-* seq_info
-*
-* Revision 6.37  1998/07/14 16:49:08  chappey
-* .
-*
-* Revision 6.36  1998/06/12 03:08:34  chappey
-* PropagateFeatureByApply only propagates new features
-*
-* Revision 6.35  1998/06/09 15:11:36  chappey
-* .
-*
-* Revision 6.34  1998/06/02 05:16:49  chappey
-* bug in multseqalign_from_pairseqalign
-*
-* Revision 6.33  1998/06/01 01:09:29  chappey
-* Message -> ErrPostEx
-*
-* Revision 6.32  1998/05/23 04:27:40  chappey
-* Blocks are visible only on sequences in list of Ids
-*
-* Revision 6.31  1998/05/21 17:38:23  chappey
-* changed SEQFEAT to FEATDEF in PropagateFeatureBySeqLock
-*
-* Revision 6.30  1998/05/20 19:02:08  chappey
-* fixes in PairSeqAlign2MultiSeqAlign
-*
-* Revision 6.29  1998/05/19 22:46:10  chappey
-* fixes in data_collect_arrange for LOWER/UPPER cases
-*
-* Revision 6.28  1998/05/19 16:08:21  chappey
-* Fixes in BioseqTrimN
-*
-* Revision 6.27  1998/05/19 02:36:03  chappey
-* minor fixes
-*
-* Revision 6.26  1998/05/18 19:39:48  chappey
-* fixes
-*
-* Revision 6.25  1998/05/12 21:23:30  chappey
-* minor fixes
-*
-* Revision 6.24  1998/05/07 15:25:54  chappey
-* ADD_REGION in ApplyBioFeatToSeqEntry
-*
-* Revision 6.23  1998/05/05 23:37:11  chappey
-* Comments for CopySeqLocFromSeqAlign
-*
-* Revision 6.22  1998/05/05 04:30:42  chappey
-* Changes in ApplyBioFeatToSeqEntry: do not re-translate the CDS because can not find the right Genetic code. Keep the 1rst translation (prot)
-*
-* Revision 6.21  1998/05/04 18:46:53  chappey
-* Allows 1 base long feature
-*
-* Revision 6.20  1998/04/28 17:55:33  chappey
-* BioseqTrimN new function to truncate nnn.s at sequence end
-*
-* Revision 6.19  1998/04/15 19:17:55  chappey
-* not_aligned segments are written in LOWER cases in arrange_buffer
-*
-* Revision 6.18  1998/04/06 23:28:26  chappey
-* minor change
-*
-* Revision 6.16  1998/04/02 23:42:58  chappey
-* minor changes
-*
-* Revision 6.15  1998/04/01 18:26:09  chappey
-* minor changes
-*
-* Revision 6.14  1998/03/23 22:36:36  chappey
-* printf removed from showfastagap_fromalign
-*
-* Revision 6.13  1998/03/22 21:56:33  chappey
-* new function for display alignment as fasta+gap showfastagap_fromalign
-*
-* Revision 6.12  1998/01/03 19:53:03  chappey
-* bugs fixed in ShowAlignmentText
-*
-* Revision 6.11  1997/12/05 18:37:44  chappey
-* casting variables
-*
-* Revision 6.10  1997/12/03 22:31:01  chappey
-* no global variable
-*
-* Revision 6.9  1997/11/06 02:48:05  chappey
-* Bugs fixed
-*
-* Revision 6.8  1997/10/21 23:02:47  chappey
-* bugs fixed
-*
-* Revision 6.7  1997/10/21 22:49:01  chappey
-* bugs fixed
-*
-* Revision 6.6  1997/10/02 05:58:07  chappey
-* Bug fixes
-*
-* Revision 6.5  1997/09/18 14:36:43  kans
-* final fixes to update sequence, removed vibrant dependencies (CC)
-*
-* Revision 6.4  1997/09/16 19:30:42  kans
-* many fixes to speed up sequence merge/replace/copy features (CC)
-*
-* Revision 6.3  1997/09/05 15:04:09  kans
-* ReplaceBioseq, Merge5Func, Merge3Func, and CpyFeatFunc (CC)
-*
-* Revision 6.2  1997/09/04 14:13:56  chappey
-* bug fixes
-*
-* Revision 6.1  1997/08/26 21:00:32  kans
-* various changes (CC)
-*
-* Revision 6.0  1997/08/25 18:54:13  madden
-* Revision changed to 6.0
-*
-* Revision 5.67  1997/08/08 17:25:51  chappey
-* bug fixes
-*
-* Revision 5.66  1997/07/14 12:38:25  kans
-* needed to call MyGetTopSeqEntryForEntityID
-*
-* Revision 5.65  1997/07/14 04:30:14  chappey
-* function FindSeqEntryForSeqId is now Callback fct in SeqEntryExplore
-*
-* Revision 5.64  1997/07/11 17:11:59  kans
-* copied CheckSeqLocForPartial and SetSeqLocPartial temporarily
-*
-* Revision 5.63  1997/07/11 16:13:41  chappey
-* move CopySeqLocFromSeqAlign from salfiles.c
-*
-* Revision 5.62  1997/07/08 05:46:33  chappey
-* bug fixes
-*
-* Revision 5.61  1997/07/01 06:28:40  chappey
-* fixes in FindSeqEntryFromId
-*
-* Revision 5.60  1997/06/26 20:22:47  chappey
-* bug fixed in SeqAlignTranslate
-*
-* Revision 5.59  1997/06/24 01:13:49  chappey
-* bugs fixed
-*
-* Revision 5.58  1997/06/02 19:20:41  kans
-* remove vibrant dependency and unused variables
-*
-* Revision 5.57  1997/06/02 19:08:36  kans
-* another round of changes
-*
-* Revision 5.56  1997/05/22 17:41:07  kans
-* various fixes, supports paup format
-*
-* Revision 5.54  1997/05/12 17:47:43  kans
-* various improvements
-*
- * Revision 5.53  1997/05/04  21:39:40  kans
- * numerous fixes (CC)
- *
- * Revision 5.49  1997/04/03  06:32:18  chappey
- * *** empty log message ***
- *
- * Revision 5.48  1997/03/18  23:53:27  kans
- * *** empty log message ***
- *
- * Revision 5.47  1997/03/13  17:38:24  kans
- * *** empty log message ***
- *
- * Revision 5.35  1997/01/04  00:05:51  kans
- * *** empty log message ***
- *
- * Revision 5.26  1996/11/04  04:23:07  kans
- * in collect feature now gets interval on proper part
- *
- * Revision 5.23  1996/10/27  01:14:23  kans
- * *** empty log message ***
- *
- * Revision 5.22  1996/10/22  23:22:39  chappey
- * *** empty log message ***
- *
- * Revision 5.21  1996/10/04  19:13:20  kans
- * *** empty log message ***
- *
- * Revision 5.18  1996/09/12  02:38:07  chappey
- * New PropagateFeature function to propagate the features from one SeqEntry
- * change the SeqLocs of the features using given SeqAlign
- *
- * Revision 5.8  1996/07/15  15:20:19  kans
- * support propagation (preliminary)
- *
- * Revision 5.1  1996/05/30  17:29:01  kans
- * integrate single and multiple alignment code
- *
- * Revision 1.24  1996/05/14  16:46:15  kans
- * added calls to ExtractBioSourceAndPubs and ReplaceBioSourceAndPubs
- *
- * Revision 1.23  1996/05/06  19:16:36  kans
- * *** empty log message ***
- *
- * Revision 1.22  1996/05/02  21:33:07  kans
- * *** empty log message ***
- *
- * Revision 1.21  1996/04/29  21:59:57  vakatov
- * Sequince of length 1 now treated properly (infinitive loop eliminated)
- *
- * Revision 1.20  1996/04/25  18:59:21  vakatov
- * *** empty log message ***
- *
 * ==========================================================================
 */
 #include <salstruc.h>
@@ -1856,7 +1504,7 @@ static void print_line (FILE *fout, CharPtr label, CharPtr txt, Int2 leftmargin,
   if (strlens > 0) {
      if (strlens > leftmargin)  
         label[leftmargin] = '\0';
-     fprintf (fout, label);       
+     fprintf (fout, "%s", label);       
      if (html_option && gi_sip != NULL) 
         fprintf (fout, "</A>");
      for (j = strlens; j < leftmargin; j++)
diff --git a/api/salutil.c b/api/salutil.c
index 1ae329d..0ddbb3f 100644
--- a/api/salutil.c
+++ b/api/salutil.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/27/96
 *
-* $Revision: 6.13 $
+* $Revision: 6.17 $
 *
 * File Description: 
 *
@@ -487,6 +487,10 @@ NLM_EXTERN CharPtr complement_string (CharPtr str)
          else if (*strp == 't') *strp = 'a';
          else if (*strp == 'c') *strp = 'g';
          else if (*strp == 'g') *strp = 'c';
+         else if (*strp == 'A') *strp = 'T';
+         else if (*strp == 'T') *strp = 'A';
+         else if (*strp == 'C') *strp = 'G';
+         else if (*strp == 'G') *strp = 'C';
   }
   *strp = '\0';
   return str;
@@ -1090,16 +1094,65 @@ typedef struct ccid {
   BioseqPtr   bsp;
 } CcId, PNTR CcIdPtr;
 
+
+NLM_EXTERN void ReplaceSeqIdWithSeqIdInFeat (SeqIdPtr old_id, SeqIdPtr new_id, SeqFeatPtr sfp)
+{
+  SeqIdPtr      current_sip;
+  RnaRefPtr     rrp;
+  tRNAPtr       trp;
+  CodeBreakPtr  cbp;
+  CdRegionPtr   crp;  
+  
+  if (sfp == NULL || old_id == NULL || new_id == NULL)
+  {
+    return;
+  }
+
+  current_sip = SeqLocId (sfp->location);
+  if (SeqIdIn (current_sip, old_id))
+  {
+    sfp->location = SeqLocReplaceID (sfp->location, new_id);
+  }
+  current_sip = SeqLocId (sfp->product);
+  if (SeqIdIn (current_sip, old_id))
+  {
+    sfp->product = SeqLocReplaceID (sfp->product, new_id);
+  }
+  if (sfp->data.choice == SEQFEAT_RNA 
+      && (rrp = (RnaRefPtr) sfp->data.value.ptrvalue) != NULL
+      && rrp->ext.choice == 2
+      && (trp = (tRNAPtr) rrp->ext.value.ptrvalue) != NULL
+      && trp->anticodon != NULL) 
+  {
+    current_sip = SeqLocId (trp->anticodon);
+    if (SeqIdIn (current_sip, old_id))
+    {
+      trp->anticodon = SeqLocReplaceID (trp->anticodon, new_id);
+    }
+  }
+  else if (sfp->data.choice == SEQFEAT_CDREGION
+           && (crp = (CdRegionPtr) sfp->data.value.ptrvalue) != NULL) 
+  {
+    for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
+      current_sip = SeqLocId (cbp->loc);
+      if (SeqIdIn (current_sip, old_id))
+      {
+        cbp->loc = SeqLocReplaceID (cbp->loc, new_id);
+      }
+    }
+  }
+}
+
+
 typedef struct replaceseqid
 {
   SeqIdPtr old_id;
   SeqIdPtr new_id;  
 } ReplaceSeqIdData, PNTR ReplaceSeqIdPtr;
 
-static void ReplaceSeqIdCallback (SeqFeatPtr sfp, Pointer userdata)
+static void ReplaceSeqIdFeatCallback (SeqFeatPtr sfp, Pointer userdata)
 {
   ReplaceSeqIdPtr rsip;
-  SeqIdPtr        current_sip;
   
   if (sfp == NULL || userdata == NULL)
   {
@@ -1110,13 +1163,32 @@ static void ReplaceSeqIdCallback (SeqFeatPtr sfp, Pointer userdata)
   {
     return;
   }
-  current_sip = SeqLocId (sfp->location);
+  ReplaceSeqIdWithSeqIdInFeat (rsip->old_id, rsip->new_id, sfp);
+}
+
+
+static void ReplaceSeqIdInGraphCallback (SeqGraphPtr sgp, Pointer userdata)
+{
+  ReplaceSeqIdPtr rsip;
+  SeqIdPtr        current_sip;
+  
+  if (sgp == NULL || sgp->loc == NULL || userdata == NULL)
+  {
+    return;
+  }
+  rsip = (ReplaceSeqIdPtr) userdata;
+  if (rsip->old_id == NULL || rsip->new_id == NULL)
+  {
+    return;
+  }
+  current_sip = SeqLocId (sgp->loc);
   if (SeqIdIn (current_sip, rsip->old_id))
   {
-    sfp->location = SeqLocReplaceID (sfp->location, rsip->new_id);
+    sgp->loc = SeqLocReplaceID (sgp->loc, rsip->new_id);
   }
 }
 
+
 static void SeqAnnotReplaceID (SeqAnnotPtr sap, SeqIdPtr newsip)
 {
   SeqFeatPtr  sfp;
@@ -1150,7 +1222,7 @@ NLM_EXTERN BioseqPtr BioseqReplaceID (BioseqPtr bsp, SeqIdPtr newsip)
   rsid.old_id = bsp->id;
   rsid.new_id = newsip;
   
-  VisitFeaturesInSep (sep, &rsid, ReplaceSeqIdCallback);
+  VisitFeaturesInSep (sep, &rsid, ReplaceSeqIdFeatCallback);
   SeqIdFree (bsp->id);
   bsp->id = SeqIdDup (newsip);
   SeqMgrReplaceInBioseqIndex (bsp);
@@ -1176,10 +1248,11 @@ NLM_EXTERN void ReplaceSeqIdWithSeqId (SeqIdPtr sip_old, SeqIdPtr sip_new, SeqEn
 
   bsp = BioseqFind (sip_old);
   
-  VisitFeaturesInSep (sep, &rsid, ReplaceSeqIdCallback);
+  VisitFeaturesInSep (sep, &rsid, ReplaceSeqIdFeatCallback);
+  VisitGraphsInSep (sep, &rsid, ReplaceSeqIdInGraphCallback);
   if (bsp != NULL) {
     sip = bsp->id;
-    while (!SeqIdComp (sip, sip_old)) {
+    while (SeqIdComp (sip, sip_old) != SIC_YES) {
       prev = sip;
       sip = sip->next;
     }
@@ -3496,18 +3569,18 @@ static Uint2 GetEntityIDForBioseqSet (void)
 */
 
 
-NLM_EXTERN void CleanUpSegGap (SeqAlignPtr sap)
+NLM_EXTERN Boolean CleanUpSegGap (SeqAlignPtr sap)
 {
    DenseSegPtr  dsp;
    DenseSegPtr  dsp_new;
-   Boolean      found;
+   Boolean      found, any_found = FALSE;
    Int4         i;
    Int4         j;
    Int4         k;
    Int4         numgap;
 
    if (sap == NULL || sap->segtype != SAS_DENSEG)
-      return;
+      return FALSE;
    dsp = (DenseSegPtr)(sap->segs);
    numgap = 0;
    for (i=0; i<dsp->numseg; i++)
@@ -3522,7 +3595,7 @@ NLM_EXTERN void CleanUpSegGap (SeqAlignPtr sap)
          numgap++;
    }
    if (numgap == 0)
-      return;
+      return FALSE;
    dsp_new = DenseSegNew();
    dsp_new->dim = dsp->dim;
    dsp_new->ids = dsp->ids;
@@ -3549,11 +3622,48 @@ NLM_EXTERN void CleanUpSegGap (SeqAlignPtr sap)
          }
          dsp_new->lens[k] = dsp->lens[i];
          k++;
+         any_found = TRUE;
       }
    }
    DenseSegFree(dsp);
    sap->segs = (Pointer)(dsp_new);
-   return;
+   return any_found;
+}
+
+
+static void NoMoreSegGapForOneAlignment (SeqAlignPtr sap, Pointer userdata)
+{
+  SeqAlignPtr       salp;
+  Int4Ptr           p_i;
+
+  salp = sap;
+  while (salp != NULL)
+  {
+    if (salp->saip != NULL)
+    {
+       SeqAlignIndexFree(salp->saip);
+       salp->saip = NULL;
+    } else {
+       AlnMgr2IndexSingleChildSeqAlign(salp); /* make sure it's dense-seg */
+       SeqAlignIndexFree(salp->saip);
+       salp->saip = NULL;
+    }
+    if (CleanUpSegGap(salp)) {
+      if ((p_i = (Int4Ptr) userdata) != NULL) {
+        (*p_i)++;
+      }
+    }
+    AlnMgr2IndexSingleChildSeqAlign(salp);
+    salp = salp->next;
+  }
 }
 
 
+NLM_EXTERN Int4 RemoveSegGapsInSeqEntry (SeqEntryPtr sep)
+{
+  Int4 num_affected = 0;
+
+  VisitAlignmentsInSep (sep, &num_affected, NoMoreSegGapForOneAlignment);
+
+  return num_affected;
+}
diff --git a/api/salutil.h b/api/salutil.h
index 4766fdb..5c93e20 100644
--- a/api/salutil.h
+++ b/api/salutil.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/27/96
 *
-* $Revision: 6.6 $
+* $Revision: 6.8 $
 *
 * File Description: 
 *
@@ -122,6 +122,7 @@ NLM_EXTERN CharPtr PNTR SeqIdListToCharArray (SeqIdPtr id_list, Int2 n);
 NLM_EXTERN SeqIdPtr     SeqIdReplaceID (SeqIdPtr head, SeqIdPtr pre, SeqIdPtr sip, SeqIdPtr next);
 NLM_EXTERN BioseqPtr    BioseqReplaceID (BioseqPtr bsp, SeqIdPtr newsip);
 NLM_EXTERN void         ReplaceSeqIdWithSeqId (SeqIdPtr sip_old, SeqIdPtr sip_new, SeqEntryPtr sep);
+NLM_EXTERN void         ReplaceSeqIdWithSeqIdInFeat (SeqIdPtr old_id, SeqIdPtr new_id, SeqFeatPtr sfp);
 NLM_EXTERN SeqEntryPtr  SeqEntryReplaceSeqID (SeqEntryPtr source_sep, SeqIdPtr sip);
 /*********************************************************
 ***
@@ -264,7 +265,8 @@ NLM_EXTERN Boolean insertchar_atcaret (CharPtr str, EditAlignDataPtr adp);
 
 NLM_EXTERN SeqEntryPtr getfirst_sep(SeqEntryPtr sep, Uint1 bsp_mol);
 
-NLM_EXTERN void CleanUpSegGap (SeqAlignPtr sap);
+NLM_EXTERN Boolean CleanUpSegGap (SeqAlignPtr sap);
+NLM_EXTERN Int4 RemoveSegGapsInSeqEntry (SeqEntryPtr sep);
 
 #endif
 
diff --git a/api/seqmgr.c b/api/seqmgr.c
index d125074..55bb0d8 100644
--- a/api/seqmgr.c
+++ b/api/seqmgr.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 9/94
 *
-* $Revision: 6.302 $
+* $Revision: 6.308 $
 *
 * File Description:  Manager for Bioseqs and BioseqSets
 *
@@ -3761,6 +3761,7 @@ static SeqEntryPtr SeqMgrGetTopSeqEntryForEntity (Uint2 entityID)
   return NULL;
 }
 
+
 static Boolean SeqMgrClearBioseqExtraData (ObjMgrDataPtr omdp)
 
 {
@@ -4221,7 +4222,7 @@ NLM_EXTERN BioseqPtr LIBCALL SeqMgrGetParentOfPart (BioseqPtr bsp,
   SMSeqIdxPtr       segpartptr;
   SeqIdPtr          sip;
   SeqLocPtr         slp;
-  Int2              L, R, mid;
+  Int4              L, R, mid;
 
   if (context != NULL) {
     MemSet ((Pointer) context, 0, sizeof (SeqMgrSegmentContext));
@@ -4436,6 +4437,7 @@ static void GetLeftAndRightOffsetsInNearBioseq (SeqLocPtr loc, BioseqPtr in, Int
   SeqIdPtr   sip;
   Uint1      strand;
   Int4       val_left = -1, val_right = -1;
+  Boolean    left_flip = FALSE, right_flip = FALSE;
 
   if (left != NULL) {
     *left = -1;
@@ -4454,7 +4456,7 @@ static void GetLeftAndRightOffsetsInNearBioseq (SeqLocPtr loc, BioseqPtr in, Int
   }
   if (bsp != NULL) {
 #if 1
-    GetLeftAndRightOffsetsInBioseq (loc, in, &val_left, &val_right, bsp->topology == TOPOLOGY_CIRCULAR);
+    GetLeftAndRightOffsetsInBioseq (loc, in, &val_left, &val_right, bsp->topology == TOPOLOGY_CIRCULAR, &left_flip, &right_flip);
 #else
     val_left = GetOffsetInBioseqEx (loc, in, SEQLOC_LEFT_END, bsp->topology == TOPOLOGY_CIRCULAR);
     val_right = GetOffsetInBioseqEx (loc, in, SEQLOC_RIGHT_END, bsp->topology == TOPOLOGY_CIRCULAR);
@@ -6519,7 +6521,7 @@ static int LIBCALLBACK SortFeatItemListByPos (VoidPtr vp1, VoidPtr vp2)
   if (numivals > 0 && sp1->ivals != NULL && sp2->ivals != NULL) {
     for (i = 0, j = 0; i < numivals; i++) {
 
-      /* check left interval */
+      /* check biological start position */
 
       if (sp1->ivals [j] > sp2->ivals [j]) {
         return 1;
@@ -6528,7 +6530,7 @@ static int LIBCALLBACK SortFeatItemListByPos (VoidPtr vp1, VoidPtr vp2)
       }
       j++;
 
-      /* check right interval */
+      /* check biological stop position */
 
       if (sp1->ivals [j] > sp2->ivals [j]) {
         return -1; /* was 1 */
@@ -6699,7 +6701,7 @@ static int LIBCALLBACK SortFeatItemListByRev (VoidPtr vp1, VoidPtr vp2)
   if (numivals > 0 && sp1->ivals != NULL && sp2->ivals != NULL) {
     for (i = 0, j = sp1->numivals * 2, k = sp2->numivals * 2; i < numivals; i++) {
 
-      /* check right interval */
+      /* check biological stop position */
 
       k--;
       j--;
@@ -6709,7 +6711,7 @@ static int LIBCALLBACK SortFeatItemListByRev (VoidPtr vp1, VoidPtr vp2)
         return -1;
       }
 
-      /* check left interval */
+      /* check biological start position */
 
       k--;
       j--;
@@ -7881,7 +7883,7 @@ static Uint2 LIBCALL s_DoSeqMgrIndexFeatures (
       if (sap->type != 1) continue;
       for (sfp = (SeqFeatPtr) sap->data; sfp != NULL; sfp = sfp->next) {
         publist = NULL;
-        CleanUpSeqFeat (sfp, FALSE, FALSE, TRUE, &publist);
+        CleanUpSeqFeat (sfp, FALSE, FALSE, TRUE, TRUE, &publist);
         ValNodeFreeData (publist);
       }
     }
@@ -9381,7 +9383,12 @@ NLM_EXTERN ValNodePtr LIBCALL SeqMgrGetNextDescriptor (BioseqPtr bsp, ValNodePtr
   } else {
     entityID = ObjMgrGetEntityIDForPointer (omdp->dataptr);
   }
+
+  if (bsp != NULL && bsp->seqentry != NULL) {
+    sep = bsp->seqentry;
+  } else {  
   sep = ObjMgrGetChoiceForData (omdp->dataptr);
+  }
 
   /* now look for next appropriate descriptor after curr in current chain */
 
@@ -9426,7 +9433,13 @@ NLM_EXTERN ValNodePtr LIBCALL SeqMgrGetNextDescriptor (BioseqPtr bsp, ValNodePtr
         break;
     }
 
+    if (omdp->datatype == OBJ_BIOSEQ && bsp != NULL && bsp->seqentry != NULL) {
+      sep = bsp->seqentry;
+    } else if (omdp->datatype == OBJ_BIOSEQSET && bssp != NULL && bssp->seqentry != NULL) {
+      sep = bssp->seqentry;
+    } else {
     sep = ObjMgrGetChoiceForData (omdp->dataptr);
+    }
     
     (context->level)++;
 
@@ -10224,7 +10237,7 @@ static SMSeqIdxPtr BinarySearchPartToSegmentMap (BioseqPtr in, Int4 pos, BioseqP
   SMSeqIdxPtr PNTR  partsBySeqId;
   SMSeqIdxPtr       segpartptr;
   CharPtr           seqIdOfPart;
-  Int2              L, R, mid;
+  Int4              L, R, mid;
 
   if (in == NULL) return NULL;
   omdp = SeqMgrGetOmdpForBioseq (in);
@@ -10302,7 +10315,7 @@ NLM_EXTERN SMSeqIdxPtr GenomePartToSegmentMap (BioseqPtr in, BioseqPtr bsp, Int4
   return BinarySearchPartToSegmentMap (in, 0, bsp, NULL, TRUE, from, to);
 }
 
-NLM_EXTERN Int4 LIBCALL SeqMgrMapPartToSegmentedBioseq (BioseqPtr in, Int4 pos, BioseqPtr bsp, SeqIdPtr sip)
+NLM_EXTERN Int4 LIBCALL SeqMgrMapPartToSegmentedBioseq (BioseqPtr in, Int4 pos, BioseqPtr bsp, SeqIdPtr sip, BoolPtr flip_strand)
 
 {
   BioseqExtraPtr  bspextra;
@@ -10312,6 +10325,9 @@ NLM_EXTERN Int4 LIBCALL SeqMgrMapPartToSegmentedBioseq (BioseqPtr in, Int4 pos,
   SMSeqIdxPtr     segpartptr;
 
   if (in == NULL) return -1;
+  if (flip_strand != NULL) {
+    *flip_strand = FALSE;
+  }
 
   /* first check to see if part has been loaded and single map up block installed */
 
@@ -10330,6 +10346,9 @@ NLM_EXTERN Int4 LIBCALL SeqMgrMapPartToSegmentedBioseq (BioseqPtr in, Int4 pos,
               /* success, immediate return with mapped up value */
 
               if (segpartptr->strand == Seq_strand_minus) {
+                if (flip_strand != NULL) {
+                  *flip_strand = FALSE;
+                }
                 return segpartptr->cumOffset + (segpartptr->to - pos);
               } else {
                 return segpartptr->cumOffset + (pos - segpartptr->from);
@@ -10398,6 +10417,9 @@ NLM_EXTERN Int4 LIBCALL SeqMgrMapPartToSegmentedBioseq (BioseqPtr in, Int4 pos,
     /* now return offset result */
 
     if (segpartptr->strand == Seq_strand_minus) {
+      if (flip_strand != NULL) {
+        *flip_strand = TRUE;
+      }
       return segpartptr->cumOffset + (segpartptr->to - pos);
     } else {
       return segpartptr->cumOffset + (pos - segpartptr->from);
@@ -10438,7 +10460,7 @@ NLM_EXTERN SeqLocPtr TrimLocInSegment (
   SeqIntPtr         sint;
   SeqLocPtr         slp;
   Uint1             strand;
-  Int2              L, R, mid;
+  Int4              L, R, mid;
   Int4              start, stop, swap;
 
   if (master == NULL || location == NULL) return NULL;
@@ -12011,3 +12033,154 @@ NLM_EXTERN SeqFeatPtr FindNthGeneOnBspByLabelOrLocusTag
 }
 
 
+static Boolean SeqMgrClearBioseqExtraDataDescriptors (ObjMgrDataPtr omdp)
+{
+  BioseqExtraPtr  bspextra;
+
+  if (omdp == NULL) return FALSE;
+  bspextra = (BioseqExtraPtr) omdp->extradata;
+  if (bspextra == NULL) return FALSE;
+
+  /* free sorted arrays of pointers into data blocks */
+
+  bspextra->descrsByID = MemFree (bspextra->descrsByID);
+  bspextra->descrsBySdp = MemFree (bspextra->descrsBySdp);
+  bspextra->descrsByIndex = MemFree (bspextra->descrsByIndex);
+
+  /* free list of descriptor information */
+
+  bspextra->desclisthead = ValNodeFreeData (bspextra->desclisthead);
+
+  return TRUE;
+}
+
+
+static void SeqMgrClearDescriptorIndexesProc (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+  BioseqPtr      bsp;
+  BioseqSetPtr   bssp;
+  ObjMgrDataPtr  omdp = NULL;
+  BoolPtr        rsult;
+
+  if (sep == NULL || (! IS_Bioseq (sep))) return;
+  if (IS_Bioseq (sep)) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    if (bsp == NULL) return;
+    omdp = SeqMgrGetOmdpForBioseq (bsp);
+  } else if (IS_Bioseq_set (sep)) {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    if (bssp == NULL) return;
+    omdp = SeqMgrGetOmdpForPointer (bssp);
+  } else return;
+  if (omdp != NULL && SeqMgrClearBioseqExtraDataDescriptors (omdp)) {
+    rsult = (BoolPtr) mydata;
+    *rsult = TRUE;
+  }
+}
+
+
+/* NOTE - this function does NOT do basic seqentry cleanup;
+ * it assumes that cleanup has been done already, probably
+ * on just the descriptor that was changed.
+ */
+NLM_EXTERN void SeqMgrRedoDescriptorIndexes (Uint2 entityID, Pointer ptr)
+
+{
+  Boolean        rsult = FALSE;
+  SeqEntryPtr    sep;
+
+  if (entityID == 0) {
+    entityID = ObjMgrGetEntityIDForPointer (ptr);
+  }
+  if (entityID == 0) return;
+  sep = SeqMgrGetTopSeqEntryForEntity (entityID);
+  if (sep == NULL) return;
+  SeqEntryExplore (sep, (Pointer) (&rsult), SeqMgrClearDescriptorIndexesProc);
+
+  /* finish indexing list of descriptors on each indexed bioseq */
+
+  VisitBioseqsInSep (sep, NULL, RecordDescriptorsInBioseqs);
+
+  if (IS_Bioseq_set (sep)) {
+    RecordDescriptorsOnTopSet (sep);
+  }
+
+  SeqEntryExplore (sep, NULL, IndexRecordedDescriptors);
+}
+
+
+static void SeqMgrRedoFeatByLabel (ObjMgrDataPtr omdp)
+{
+  BioseqExtraPtr      bspextra;
+  SeqFeatPtr          sfp;
+  Int4                i;
+  Char                buf [129];
+  CharPtr             ptr;
+
+  if (omdp == NULL) return;
+  bspextra = (BioseqExtraPtr) omdp->extradata;
+  if (bspextra == NULL || bspextra->featsByLabel == NULL) return;
+
+  for (i = 0; i < bspextra->numfeats; i++) {
+    sfp = bspextra->featsByLabel[i]->sfp;
+
+    FeatDefLabel (sfp, buf, sizeof (buf) - 1, OM_LABEL_CONTENT);
+    ptr = buf;
+    if (sfp->data.choice == SEQFEAT_RNA) {
+      ptr = StringStr (buf, "RNA-");
+      if (ptr != NULL) {
+        ptr += 4;
+      } else {
+        ptr = buf;
+      }
+    }
+    bspextra->featsByLabel[i]->label = MemFree (bspextra->featsByLabel[i]->label);
+    bspextra->featsByLabel[i]->label = StringSaveNoNull (ptr);
+  }
+
+  HeapSort ((VoidPtr) bspextra->featsByLabel, (size_t) bspextra->numfeats, sizeof (SMFeatItemPtr), SortFeatItemListByLabel);
+}
+
+static void SeqMgrRedoFeatByLabelProc (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+  BioseqPtr      bsp;
+  BioseqSetPtr   bssp;
+  ObjMgrDataPtr  omdp = NULL;
+
+  if (sep == NULL || (! IS_Bioseq (sep))) return;
+  if (IS_Bioseq (sep)) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    if (bsp == NULL) return;
+    omdp = SeqMgrGetOmdpForBioseq (bsp);
+  } else if (IS_Bioseq_set (sep)) {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    if (bssp == NULL) return;
+    omdp = SeqMgrGetOmdpForPointer (bssp);
+  } else return;
+  SeqMgrRedoFeatByLabel (omdp);
+}
+
+
+NLM_EXTERN void SeqMgrRedoFeatByLabelIndexes (Uint2 entityID, Pointer ptr)
+{
+  Int4    ret;
+  SeqEntryPtr sep;
+
+  ret = NlmMutexLockEx (&smp_feat_index_mutex);
+  if (ret) {
+    ErrPostEx (SEV_FATAL, 0, 0, "SeqMgrIndexFeatures mutex failed [%ld]", (long) ret);
+    return;
+  }
+  if (entityID == 0) {
+    entityID = ObjMgrGetEntityIDForPointer (ptr);
+  }
+  if (entityID != 0) {
+    sep = GetTopSeqEntryForEntityID (entityID);
+    SeqEntryExplore (sep, NULL, SeqMgrRedoFeatByLabelProc);
+  }
+
+  NlmMutexUnlock (smp_feat_index_mutex);
+}
+
diff --git a/api/seqmgr.h b/api/seqmgr.h
index 77476a5..b1e1201 100644
--- a/api/seqmgr.h
+++ b/api/seqmgr.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 9/94
 *
-* $Revision: 6.69 $
+* $Revision: 6.72 $
 *
 * File Description:  Manager for Bioseqs and BioseqSets
 *
@@ -845,7 +845,7 @@ NLM_EXTERN ValNodePtr LIBCALL SeqMgrGetSfpProductList (BioseqPtr bsp);
 *
 *****************************************************************************/
 
-NLM_EXTERN Int4 LIBCALL SeqMgrMapPartToSegmentedBioseq PROTO((BioseqPtr in, Int4 pos, BioseqPtr bsp, SeqIdPtr sip));
+NLM_EXTERN Int4 LIBCALL SeqMgrMapPartToSegmentedBioseq PROTO((BioseqPtr in, Int4 pos, BioseqPtr bsp, SeqIdPtr sip, BoolPtr flip_strand));
 
 /*****************************************************************************
 *
@@ -982,6 +982,9 @@ NLM_EXTERN ObjMgrDataPtr SeqMgrGetOmdpForBioseq (BioseqPtr bsp);
 
 NLM_EXTERN Pointer SeqMgrGetExtraDataForOmdp (ObjMgrDataPtr omdp);
 
+NLM_EXTERN void SeqMgrRedoDescriptorIndexes (Uint2 entityID, Pointer ptr);
+NLM_EXTERN void SeqMgrRedoFeatByLabelIndexes (Uint2 entityID, Pointer ptr);
+
 
 #ifdef __cplusplus
 }
diff --git a/api/seqport.c b/api/seqport.c
index 06f10c0..6330111 100644
--- a/api/seqport.c
+++ b/api/seqport.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 7/13/91
 *
-* $Revision: 6.177 $
+* $Revision: 6.184 $
 *
 * File Description:  Ports onto Bioseqs
 *
@@ -2470,6 +2470,8 @@ static Int4 SeqPortStreamSeqLoc (
 
   if (slp == NULL || sdp == NULL) return 0;
 
+  if (start < 0 || stop < 0) return 0;
+
   sip = SeqLocId (slp);
   if (sip == NULL) return 0;
 
@@ -2922,7 +2924,12 @@ static Int4 SeqPortStreamWork (
     stop = bsp->length - 1;
   }
 
-  if (start >= bsp->length || stop >= bsp->length) return 0;
+  /* if start or stop are beyond sequence length, set failed flag */
+
+  if (start >= bsp->length || stop >= bsp->length) {
+    sdp->failed = TRUE;
+    return 0;
+  }
 
   if (start > stop) return 0;
 
@@ -3071,6 +3078,11 @@ static Int4 SeqPortStreamSetup (
       to = SeqLocStop (slp);
       strand = SeqLocStrand (slp);
 
+      if (from < 0 || to < 0) {
+        sd.failed = TRUE;
+        return -1;
+      }
+
       count += SeqPortStreamSeqLoc (slp, from, to, strand, &sd, NULL);
 
       slp = SeqLocFindNext (loc, slp);
@@ -3165,6 +3177,7 @@ static Boolean StreamCacheRefreshBuffer (
 
 {
   Bioseq         bsq;
+  Int4           count;
   StreamFlgType  flags;
   SeqLocPtr      loc;
   SeqLoc         sl;
@@ -3196,8 +3209,11 @@ static Boolean StreamCacheRefreshBuffer (
 
     if (scp->bsp != NULL) {
 
-      SeqPortStreamInt (scp->bsp, scp->offset, stop - 1, Seq_strand_plus,
+      count = SeqPortStreamInt (scp->bsp, scp->offset, stop - 1, Seq_strand_plus,
                         flags, (Pointer) &(scp->buf), NULL);
+      if (count < 0) {
+        scp->failed = TRUE;
+      }
 
     } else if (scp->slp != NULL) {
 
@@ -4004,7 +4020,7 @@ static Boolean add_fuzziness_to_loc (SeqLocPtr slp, Boolean less)
 
 	if(spnt != NULL)
 		spnt->fuzz = ifp;
-	else
+    else if (sint != NULL)
 	{
 		if(less)
 			sint->if_from = ifp;
@@ -4244,7 +4260,7 @@ NLM_EXTERN SeqLocPtr LIBCALL aaFeatLoc_to_dnaFeatLoc(SeqFeatPtr sfp,
 					tmp2 = tmp;
 				}
 			
-				if ((tmp1->choice == SEQLOC_INT) &&
+                if (tmp1 != NULL && tmp2 != NULL && (tmp1->choice == SEQLOC_INT) &&
 					(tmp2->choice == SEQLOC_INT))
 				{
 					sp1 = (SeqIntPtr)(tmp1->data.ptrvalue);
@@ -4274,14 +4290,14 @@ NucLocFromProtInterval
  Boolean n_partial)
 {
   CdRegionPtr crp;
-  Int4        nt_before = 0, aa_before = 0, nt_this, prev_nt = 0, part_codon;
+  Int4        aa_before = 0, nt_this, prev_nt = 0, part_codon;
   SeqLocPtr   result = NULL;
   SeqLocPtr   slp = NULL; /* used for iterating through locations in the coding region */
   SeqLocPtr   loc; /* used for creating interval on NT sequence */
   Boolean     first_loc = TRUE;
   Int4        cds_int_start, cds_int_stop, cds_int_len;
   Int4        frame_start = 0;
-  Int4        aa_int_start, aa_int_stop, aa_len, this_aa, aa_needed, aa_unneeded, aa_accumulated = 0;
+  Int4        aa_int_start = 0, aa_int_stop = 0, aa_len, this_aa, aa_needed, aa_unneeded, aa_accumulated = 0;
   Int4        aa_from_this_interval;
   Uint1       strand;
 
@@ -4614,8 +4630,10 @@ merge, Int4Ptr frame, Boolean allowTerminator)
       if (a_right > (bsp->length) * 3 - 1 && !allowTerminator) {
         CheckSeqLocForPartial (slp, &partial5, &partial3);
         strand = SeqLocStrand (slp);
-        if ((partial5 && strand != Seq_strand_minus) || (partial3 && strand == Seq_strand_minus)) {
-				  a_right = bsp->length - 1;
+        if (partial3 && a_right == bsp->length * 3) {
+          /* it's ok, leave it alone */
+        } else if ((partial5 && strand != Seq_strand_minus) || (partial3 && strand == Seq_strand_minus)) {
+                  a_right = (bsp->length * 3) - 1;
         } else {
           a_right -= 3;
         }
@@ -5313,6 +5331,7 @@ NLM_EXTERN Boolean LIBCALL ContigRevComp (BioseqPtr bsp)
 {
   if (bsp == NULL) {
     ErrPostEx (SEV_ERROR, 0, 0, "ContigRevComp: empty BioseqPtr");
+    return FALSE;
   }
 
   if (bsp->repr == Seq_repr_seg && bsp->seq_ext_type == 1 && bsp->seq_ext != NULL) {
@@ -8720,6 +8739,7 @@ NLM_EXTERN void ConvertNsToGaps (
   bsp->repr = Seq_repr_delta;
   bsp->seq_ext_type = 4;
   bsp->seq_ext = seq_ext;
+  bsp->length = len;
 
   BioseqPack (bsp);
 }
@@ -8731,19 +8751,19 @@ NLM_EXTERN void ConvertNsToGaps (
    B is really D or N, but they are close so is treated as D
    Z is really E or Q, but they are close so is treated as E
    X is hard to guess, so the calculation fails on X
-   J and O are unassigned, so fails on those
    - and * are skipped
+   water molecule is removed for in-peptide atom counts
 
   A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
 */
 Uint1 C_atoms[26] =
-{ 3, 4, 3, 4, 5, 9, 2, 6, 6, 0, 6, 6, 5, 4, 0, 5, 5, 6, 3, 4, 3, 5,11, 0, 9, 5};
+{ 3, 4, 3, 4, 5, 9, 2, 6,  6,  6,  6,  6, 5, 4, 12, 5, 5,  6, 3, 4, 3, 5, 11, 0, 9, 5};
 Uint1 H_atoms[26] =
-{ 5, 5, 5, 5, 7, 9, 3, 7,11, 0,12,11, 9, 6, 0, 7, 8,12, 5, 7, 5, 9,10, 0, 9, 7};
+{ 5, 5, 5, 5, 7, 9, 3, 7, 11, 11, 12, 11, 9, 6, 19, 7, 8, 12, 5, 7, 5, 9, 10, 0, 9, 7};
 Uint1 N_atoms[26] =
-{ 1, 1, 1, 1, 1, 1, 1, 3, 1, 0, 2, 1, 1, 2, 0, 1, 2, 4, 1, 1, 1, 1, 2, 0, 1, 1};
+{ 1, 1, 1, 1, 1, 1, 1, 3,  1,  1,  2,  1, 1, 2,  3, 1, 2,  4, 1, 1, 1, 1,  2, 0, 1, 1};
 Uint1 O_atoms[26] =
-{ 1, 3, 1, 3, 3, 1, 1, 1, 1, 0, 1, 1, 1, 2, 0, 1, 2, 1, 2, 2, 1, 1, 1, 0, 2, 3};
+{ 1, 3, 1, 3, 3, 1, 1, 1,  1,  1,  1,  1, 1, 2,  2, 1, 2,  1, 2, 2, 1, 1,  1, 0, 2, 3};
 Uint1 S_atoms[26] =
 { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 Uint1 Se_atoms[26] =
diff --git a/api/seqport.h b/api/seqport.h
index 22cddc3..820f844 100644
--- a/api/seqport.h
+++ b/api/seqport.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 7/13/91
 *
-* $Revision: 6.60 $
+* $Revision: 6.62 $
 *
 * File Description:  Ports onto Bioseqs
 *
@@ -196,6 +196,8 @@ typedef unsigned long StreamFlgType;
 
 #define STREAM_ALLOW_NEG_GIS  128 /* for internal use only by NCBI ID group */
 
+#define STREAM_HTML_SPANS     256 /* show span tags at begining of each line */
+
 NLM_EXTERN Int4 SeqPortStream (
   BioseqPtr bsp,
   StreamFlgType flags,
@@ -238,6 +240,7 @@ typedef struct streamcache {
   Int4          offset;
   Int4          length;
   StreamFlgType flags;
+  Boolean       failed;
 } StreamCache, PNTR StreamCachePtr;
 
 NLM_EXTERN Boolean StreamCacheSetup (
diff --git a/api/sequtil.c b/api/sequtil.c
index b4f067c..1b39894 100644
--- a/api/sequtil.c
+++ b/api/sequtil.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 4/1/91
 *
-* $Revision: 6.285 $
+* $Revision: 6.304 $
 *
 * File Description:  Sequence Utilities for objseq and objsset
 *
@@ -4946,7 +4946,7 @@ NLM_EXTERN Int4 SeqLocLen (SeqLocPtr anp)   /* seqloc */
                 num++;
                 slp = slp->next;
             }
-            if (average) {
+            if (average && num != 0) {
                 len /= num;
             }
             break;
@@ -5067,66 +5067,97 @@ NLM_EXTERN Uint1 StrandCmp (Uint1 strand)
     return strand;
 }
 
-/*****************************************************************************
-*
-*   SeqLocCompare(a, b)
-*       returns
-*       0 = no overlap
-*       1 = a is completely contained in b
-*       2 = b is completely contained in a
-*       3 = a == b
-*       4 = a and b overlap, but neither completely contained in the other
-*   
-*
-*****************************************************************************/
-NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
 
+static Boolean DoStrandsMatch(Uint1 strand1, Uint2 strand2)
 {
-    BioseqPtr bsp;
-    Int4 len = -1L, i, j, num, num2, point, hits;
+  if (strand1 == Seq_strand_minus && strand2 == Seq_strand_minus) {
+    return TRUE;
+  } else if (strand1 != Seq_strand_minus && strand2 != Seq_strand_minus) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static SeqLocPtr SeqLocMixFromPackedSeqPnt (PackSeqPntPtr pspp)
+{
+    SeqPntPtr pnt;
+    SeqLocPtr list = NULL, slp = NULL;
+    Uint1     i;
+
+    if (pspp == NULL) 
+    {
+        return NULL;
+    }
+
+    while (pspp != NULL) 
+    {
+        for (i = 0; i < pspp->used; i++) 
+        {
+            pnt = SeqPntNew();
+            pnt->id = SeqIdDup (pspp->id);
+            pnt->strand = pspp->strand;
+            pnt->point = pspp->pnts[i];
+            ValNodeAddPointer (&list, SEQLOC_PNT, pnt);
+        }
+        pspp = pspp->next;
+    }
+    slp = ValNodeNew (NULL);
+    slp->choice = SEQLOC_MIX;
+    slp->data.ptrvalue = list;
+    return slp;
+}
+
+
+static SeqLocPtr SeqLocMixFromSeqBond (SeqBondPtr sbp)
+{
+  SeqPntPtr pnt;
+  SeqLocPtr list = NULL, slp = NULL;
+
+  if (sbp == NULL || (sbp->a == NULL && sbp->b == NULL)) {
+    return NULL;
+  }
+  if (sbp->a != NULL) {
+    pnt = AsnIoMemCopy (sbp->a, (AsnReadFunc) SeqPntAsnRead, (AsnWriteFunc) SeqPntAsnWrite);
+    ValNodeAddPointer (&list, SEQLOC_PNT, pnt);
+  }
+  if (sbp->b != NULL) {
+    pnt = AsnIoMemCopy (sbp->b, (AsnReadFunc) SeqPntAsnRead, (AsnWriteFunc) SeqPntAsnWrite);
+    ValNodeAddPointer (&list, SEQLOC_PNT, pnt);
+  }
+  slp = ValNodeNew (NULL);
+  slp->choice = SEQLOC_MIX;
+  slp->data.ptrvalue = list;
+  return slp;
+}
+
+
+static Int2 CompareMultiPartLocToMultiPartLoc (SeqLocPtr a, SeqLocPtr b, Boolean compare_strand)
+{
+  Boolean got_one = FALSE;   /* for any overlap */
     SeqLocPtr slp, slp2;
-    ValNode tmp;
-    SeqBondPtr sbp;
-    SeqIntPtr sip, sip2;
-    SeqIdPtr sidp;
-    PackSeqPntPtr pspp, pspp2;
-    Boolean got_one, missed_one, locked = FALSE;
     Int2 retval = SLC_NO_MATCH,
          retval2 = SLC_NO_MATCH;
-    static Uint1 rettable [5][5] = {      /* for developing return values */
-        { 0,4,2,2,4 } ,                      /* when a is longer than b */
-        { 4,1,4,1,4 } ,
-        { 2,4,2,2,4 } ,
-        { 2,1,2,3,4 } ,
-        { 4,4,4,4,4 }};
-    static Uint1 rettable2 [5][5] = {      /* for developing return values */
-        { 0,1,4,1,4 } ,                      /* when b is longer than a */
-        { 1,1,4,1,1 } ,
-        { 4,4,2,2,4 } ,
-        { 1,1,4,3,4 } ,
-        { 4,1,4,4,4 }};
 
-    if ((a == NULL) || (b == NULL))
-        return retval;
+  if (a == NULL || b == NULL) {
+    return SLC_NO_MATCH;
+  }
+  if (a->choice != SEQLOC_MIX && a->choice != SEQLOC_EQUIV && a->choice != SEQLOC_PACKED_INT) {
+    return SLC_NO_MATCH;
+  }
+  if (b->choice != SEQLOC_MIX && b->choice != SEQLOC_EQUIV && b->choice != SEQLOC_PACKED_INT) {
+    return SLC_NO_MATCH;
+  }
 
-    switch (a->choice)
-    {
-        case SEQLOC_MIX:    /* mix -- more than one seq */
-        case SEQLOC_EQUIV:    /* equiv -- ditto */
-        case SEQLOC_PACKED_INT:    /* packed int */
-            if ((b->choice == SEQLOC_MIX) ||  /* check for identity */
-                (b->choice == SEQLOC_EQUIV) ||
-                (b->choice == SEQLOC_PACKED_INT))
-            {
-                got_one = FALSE;   /* for any overlap */
                 slp = (SeqLocPtr)a->data.ptrvalue;  /* check for identity */
                 slp2 = (SeqLocPtr)b->data.ptrvalue;
-                retval = SeqLocCompare(slp, slp2);
+  retval = SeqLocCompareEx(slp, slp2, compare_strand);
                 slp = slp->next;
                 slp2 = slp2->next;
                 while ((slp != NULL) && (slp2 != NULL) && (retval == SLC_A_EQ_B))
                 {
-                    retval = SeqLocCompare(slp, slp2);
+      retval = SeqLocCompareEx(slp, slp2, compare_strand);
                     slp = slp->next;
                     slp2 = slp2->next;
                 }
@@ -5137,7 +5168,7 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                 slp2 = (SeqLocPtr)b->data.ptrvalue;
                 while ((slp != NULL) && (slp2 != NULL))
                 {
-                    retval2 = SeqLocCompare(slp, slp2);
+      retval2 = SeqLocCompareEx(slp, slp2, compare_strand);
                     if (retval2 > SLC_NO_MATCH)
                         got_one = TRUE;
                     switch (retval2)
@@ -5165,7 +5196,7 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                 slp = (SeqLocPtr)b->data.ptrvalue;
                 while ((slp != NULL) && (slp2 != NULL))
                 {
-                    retval2 = SeqLocCompare(slp, slp2);
+      retval2 = SeqLocCompareEx(slp, slp2, compare_strand);
                     if (retval2 > SLC_NO_MATCH)
                         got_one = TRUE;
                     switch (retval2)
@@ -5191,18 +5222,108 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
 
                 if (got_one)
                     return SLC_A_OVERLAP_B;
+
+  return retval;
+}
+
+
+/*****************************************************************************
+*
+*   SeqLocCompare(a, b)
+*       returns
+*       0 = no overlap
+*       1 = a is completely contained in b
+*       2 = b is completely contained in a
+*       3 = a == b
+*       4 = a and b overlap, but neither completely contained in the other
+*   
+*
+*****************************************************************************/
+NLM_EXTERN Int2 SeqLocCompareEx (SeqLocPtr a, SeqLocPtr b, Boolean compare_strand)   /* seqloc */
+
+{
+    BioseqPtr bsp;
+    Int4 len = -1L, i, j, num, num2, point, hits;
+    Uint1 strand;
+    SeqLocPtr slp, tmp_a = NULL, tmp_b = NULL;
+    ValNode tmp;
+    SeqBondPtr sbp;
+    SeqIntPtr sip, sip2;
+    SeqIdPtr sidp;
+    PackSeqPntPtr pspp, pspp2;
+    Boolean got_one, missed_one, locked = FALSE;
+    Int2 retval = SLC_NO_MATCH,
+         retval2 = SLC_NO_MATCH;
+    static Uint1 rettable [5][5] = {      /* for developing return values */
+        { 0,4,2,2,4 } ,                      /* when a is longer than b */
+        { 4,1,4,1,4 } ,
+        { 2,4,2,2,4 } ,
+        { 2,1,2,3,4 } ,
+        { 4,4,4,4,4 }};
+    static Uint1 rettable2 [5][5] = {      /* for developing return values */
+        { 0,1,4,1,4 } ,                      /* when b is longer than a */
+        { 1,1,4,1,1 } ,
+        { 4,4,2,2,4 } ,
+        { 1,1,4,3,4 } ,
+        { 4,1,4,4,4 }};
+
+    if ((a == NULL) || (b == NULL))
+        return retval;
+
+    switch (a->choice)
+    {
+        case SEQLOC_MIX:    /* mix -- more than one seq */
+        case SEQLOC_EQUIV:    /* equiv -- ditto */
+        case SEQLOC_PACKED_INT:    /* packed int */ 
+        case SEQLOC_PACKED_PNT: /* packed points (need to convert to SEQLOC_MIX) */
+        case SEQLOC_BOND: /* bond (need to convert to SEQLOC_MIX) */
+            if (a->choice == SEQLOC_PACKED_PNT) 
+            {
+                tmp_a = SeqLocMixFromPackedSeqPnt ((PackSeqPntPtr)a->data.ptrvalue);
+                a = tmp_a;
+            } 
+            else if (a->choice == SEQLOC_BOND) 
+            {
+                tmp_a = SeqLocMixFromSeqBond ((SeqBondPtr)a->data.ptrvalue);
+                a = tmp_a;
+            }
+            if ((b->choice == SEQLOC_MIX) ||  /* check for identity */
+                (b->choice == SEQLOC_EQUIV) ||
+                (b->choice == SEQLOC_PACKED_INT) ||
+                (b->choice == SEQLOC_PACKED_PNT) ||
+                (b->choice == SEQLOC_BOND))
+            {
+                if (b->choice == SEQLOC_PACKED_PNT) 
+                {
+                    tmp_b = SeqLocMixFromPackedSeqPnt ((PackSeqPntPtr)b->data.ptrvalue);
+                    b = tmp_b;
+                }
+                else if (b->choice == SEQLOC_BOND)
+                {
+                    tmp_b = SeqLocMixFromSeqBond ((SeqBondPtr)b->data.ptrvalue);
+                    b = tmp_b;
+                }
+                retval = CompareMultiPartLocToMultiPartLoc (a, b, compare_strand);
+                if (retval != SLC_NO_MATCH) {
+                  tmp_a = SeqLocFree (tmp_a);
+                  tmp_b = SeqLocFree (tmp_b);
+                  return retval;
+                }
             }
 
             slp = (SeqLocPtr)a->data.ptrvalue; /* check for any overlap */
-            retval = SeqLocCompare(slp, b);
+            retval = SeqLocCompareEx(slp, b, compare_strand);
             slp = slp->next;
             while (slp != NULL)
             {
-                retval2 = SeqLocCompare(slp, b);
+                retval2 = SeqLocCompareEx(slp, b, compare_strand);
                 retval = (Int2) rettable[retval][retval2];
                 slp = slp->next;
             }
+            tmp_a = SeqLocFree (tmp_a);
+            tmp_b = SeqLocFree (tmp_b);
             return retval;
+            break;
         default:
             break;
     }
@@ -5212,15 +5333,16 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
         case SEQLOC_EQUIV:    /* equiv -- ditto */
         case SEQLOC_PACKED_INT:    /* packed int */
             slp = (SeqLocPtr)b->data.ptrvalue;
-            retval = SeqLocCompare(a, slp);
+            retval = SeqLocCompareEx(a, slp, compare_strand);
             slp = slp->next;
             while (slp != NULL)
             {
-                retval2 = SeqLocCompare(a, slp);
+                retval2 = SeqLocCompareEx(a, slp, compare_strand);
                 retval = (Int2)rettable2[retval][retval2];
                 slp = slp->next;
             }
             return retval;
+            break;
         default:
             break;
     }
@@ -5245,11 +5367,11 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
             sbp = (SeqBondPtr)a->data.ptrvalue;
             tmp.choice = SEQLOC_PNT;    /* check the points */
             tmp.data.ptrvalue = (Pointer)sbp->a;
-            retval = SeqLocCompare(&tmp, b);
+            retval = SeqLocCompareEx(&tmp, b, compare_strand);
             if (sbp->b != NULL)
             {
                 tmp.data.ptrvalue = (Pointer)sbp->b;
-                retval2 = SeqLocCompare(&tmp, b);
+                retval2 = SeqLocCompareEx(&tmp, b, compare_strand);
                 retval = (Int2) rettable[retval][retval2];
             }
             break;
@@ -5265,7 +5387,7 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     {
                         if (SeqIdForSameBioseq(sbp->b->id, sidp))
                             retval2 = SLC_B_IN_A;
-                        retval = (Int2) rettable[retval][retval2];
+                        retval = (Int2) rettable2[retval][retval2];
                     }
                     break;
                 case SEQLOC_WHOLE:    /* whole */
@@ -5299,8 +5421,32 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                         retval = SLC_B_IN_A;
                     break;
                 case SEQLOC_PACKED_PNT:    /* packed pnt */
-                    if (SeqIdForSameBioseq(sidp, ((PackSeqPntPtr)b->data.ptrvalue)->id))
+                    got_one = FALSE;
+                    missed_one = FALSE;
+                    for (pspp = (PackSeqPntPtr)b->data.ptrvalue;
+                         pspp != NULL;
+                         pspp = pspp->next) 
+                    {
+                        if (SeqIdForSameBioseq(sidp, pspp->id))
+                        {
+                            got_one = TRUE;
+                        } 
+                        else
+                        {
+                            missed_one = TRUE;
+                        }
+                    }
+                    if (got_one) 
+                    {
+                        if (missed_one) 
+                        {   
+                            retval = SLC_A_OVERLAP_B;
+                        } 
+                        else
+                        {
                         retval = SLC_B_IN_A;
+                        }
+                    }
                     break;
                 default:
                     break;
@@ -5316,18 +5462,24 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     if (SeqIdForSameBioseq(sbp->a->id, sidp))
                     {
                         if ((sip->from <= sbp->a->point) &&
-                            (sip->to >= sbp->a->point))
+                            (sip->to >= sbp->a->point) &&
+                            (!compare_strand || DoStrandsMatch(sip->strand, sbp->a->strand))) 
+                        {
                             retval = SLC_B_IN_A;
                     }
+                    }
                     if (sbp->b != NULL)
                     {
                         if (SeqIdForSameBioseq(sbp->b->id, sidp))
                         {
                             if ((sip->from <= sbp->b->point) &&
-                                (sip->to >= sbp->b->point))
-                                retval = SLC_B_IN_A;
+                                (sip->to >= sbp->b->point) &&
+                                (!compare_strand || DoStrandsMatch(sip->strand, sbp->b->strand)))
+                            {
+                                  retval2 = SLC_B_IN_A;
                         }
-                        retval = (Int2) rettable[retval][retval2];
+                        }
+                        retval = (Int2) rettable2[retval][retval2];
                     }
                     break;
                 case SEQLOC_WHOLE:    /* whole */
@@ -5353,7 +5505,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     break;
                 case SEQLOC_INT:    /* int */
                     sip2 = (SeqIntPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sidp, sip2->id))
+                    if (SeqIdForSameBioseq(sidp, sip2->id) 
+                        && (!compare_strand || DoStrandsMatch (sip->strand, sip2->strand)))
                     {
                         if ((sip->from == sip2->from) && (sip->to == sip2->to))
                             retval = SLC_A_EQ_B;
@@ -5368,7 +5521,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     }
                     break;
                 case SEQLOC_PNT:    /* pnt */
-                    if (SeqIdForSameBioseq(sidp, ((SeqPntPtr)b->data.ptrvalue)->id))
+                    if (SeqIdForSameBioseq(sidp, ((SeqPntPtr)b->data.ptrvalue)->id)
+                        && (!compare_strand || DoStrandsMatch (sip->strand, ((SeqPntPtr)b->data.ptrvalue)->strand)))
                     {
                         point = ((SeqPntPtr)b->data.ptrvalue)->point;
                         if ((point >= sip->from) && (point <= sip->to))
@@ -5377,27 +5531,29 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     break;
                 case SEQLOC_PACKED_PNT:    /* packed pnt */
                     pspp = (PackSeqPntPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sidp, pspp->id))
-                    {
                         got_one = FALSE;
                         missed_one = FALSE;
-                        num = PackSeqPntNum(pspp);
+                    while (pspp != NULL)
+                    {
+                        if (SeqIdForSameBioseq(sidp, pspp->id)
+                            && (!compare_strand || DoStrandsMatch (sip->strand, pspp->strand)))
+                        {
+                            num = pspp->used;
                         for (i = 0; i < num; i++)
                         {
-                            point = PackSeqPntGet(pspp, i);
+                                point = pspp->pnts[i];
                             if ((point < sip->from) || (point > sip->to))
                             {
                                 missed_one = TRUE;
-                                if (got_one)
-                                    i = num;
                             }
                             else
                             {
                                 got_one = TRUE;
-                                if (missed_one)
-                                    i = num;
                             }
                         }
+                        }
+                        pspp = pspp->next;
+                    }
                         if (got_one)
                         {
                             if (missed_one)
@@ -5405,7 +5561,6 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                             else
                                 retval = SLC_B_IN_A;
                         }
-                    }
                     break;
                 default:
                     break;
@@ -5414,23 +5569,26 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
         case SEQLOC_PNT:    /* pnt */
             sidp = ((SeqPntPtr)a->data.ptrvalue)->id;
             point = ((SeqPntPtr)a->data.ptrvalue)->point;
+            strand = ((SeqPntPtr)a->data.ptrvalue)->strand;
             switch (b->choice)
             {
                 case SEQLOC_BOND:   /* bond -- 2 seqs */
                     sbp = (SeqBondPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sbp->a->id, sidp))
+                    if (SeqIdForSameBioseq(sbp->a->id, sidp)
+                        && (!compare_strand || DoStrandsMatch (sbp->a->strand, strand)))
                     {
                         if (point == sbp->a->point)
                             retval = SLC_A_EQ_B;
                     }
                     if (sbp->b != NULL)
                     {
-                        if (SeqIdForSameBioseq(sbp->b->id, sidp))
+                        if (SeqIdForSameBioseq(sbp->b->id, sidp)
+                            && (!compare_strand || DoStrandsMatch (sbp->b->strand, strand)))
                         {
                             if (point == sbp->b->point)
-                                retval = SLC_A_EQ_B;
+                                retval2 = SLC_A_EQ_B;
                         }
-                        retval = (Int2) rettable[retval][retval2];
+                        retval = (Int2) rettable2[retval][retval2];
                     }
                     break;
                 case SEQLOC_WHOLE:    /* whole */
@@ -5439,7 +5597,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     break;
                 case SEQLOC_INT:    /* int */
                     sip2 = (SeqIntPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sidp, sip2->id))
+                    if (SeqIdForSameBioseq(sidp, sip2->id)
+                        && (!compare_strand || DoStrandsMatch (sip2->strand, strand)))
                     {
                         if ((point == sip2->from) && (point == sip2->to))
                             retval = SLC_A_EQ_B;
@@ -5448,7 +5607,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     }
                     break;
                 case SEQLOC_PNT:    /* pnt */
-                    if (SeqIdForSameBioseq(sidp, ((SeqPntPtr)b->data.ptrvalue)->id))
+                    if (SeqIdForSameBioseq(sidp, ((SeqPntPtr)b->data.ptrvalue)->id)
+                        && (!compare_strand || DoStrandsMatch (strand, ((SeqPntPtr)b->data.ptrvalue)->strand)))
                     {
                         if (point == ((SeqPntPtr)b->data.ptrvalue)->point)
                             retval = SLC_A_EQ_B;
@@ -5456,16 +5616,40 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     break;
                 case SEQLOC_PACKED_PNT:    /* packed pnt */
                     pspp = (PackSeqPntPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sidp, pspp->id))
+                    got_one = FALSE;
+                    missed_one = FALSE;
+                    while (pspp != NULL) {
+                        if (SeqIdForSameBioseq(sidp, pspp->id)
+                            && (!compare_strand || DoStrandsMatch (strand, pspp->strand)))
                     {
-                        num = PackSeqPntNum(pspp);
+                            num = pspp->used;
                         for (i = 0; i < num; i++)
                         {
-                            if (point == PackSeqPntGet(pspp, i))
+                                if (point == pspp->pnts[i])
+                                {
+                                    got_one = TRUE;                                    
+                                }
+                                else
+                                {
+                                    missed_one = TRUE;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            missed_one = TRUE;
+                        }
+                        pspp = pspp->next;
+                    }
+                    if (got_one) 
+                    {
+                        if (missed_one) 
                             {
                                 retval = SLC_A_IN_B;
-                                i = num;     /* only check one */
                             }
+                        else
+                        {
+                            retval = SLC_A_EQ_B;
                         }
                     }
                     break;
@@ -5481,7 +5665,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
             {
                 case SEQLOC_BOND:   /* bond -- 2 seqs */
                     sbp = (SeqBondPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sbp->a->id, sidp))
+                    if (SeqIdForSameBioseq(sbp->a->id, sidp)
+                        && (!compare_strand || DoStrandsMatch (pspp->strand, sbp->a->strand)))
                     {
                         point = sbp->a->point;
                         for (i = 0; i < num; i++)
@@ -5495,7 +5680,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     }
                     if (sbp->b != NULL)
                     {
-                        if (SeqIdForSameBioseq(sbp->b->id, sidp))
+                        if (SeqIdForSameBioseq(sbp->b->id, sidp)
+                            && (!compare_strand || DoStrandsMatch(pspp->strand, sbp->b->strand)))
                         {
                             point = sbp->b->point;
                             for (i = 0; i < num; i++)
@@ -5518,7 +5704,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     break;
                 case SEQLOC_INT:    /* int */
                     sip = (SeqIntPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sidp, sip->id))
+                    if (SeqIdForSameBioseq(sidp, sip->id)
+                        && (!compare_strand || DoStrandsMatch(sip->strand, pspp->strand)))
                     {
                         got_one = FALSE;
                         missed_one = FALSE;
@@ -5548,7 +5735,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     }
                     break;
                 case SEQLOC_PNT:    /* pnt */
-                    if (SeqIdForSameBioseq(sidp, ((SeqPntPtr)b->data.ptrvalue)->id))
+                    if (SeqIdForSameBioseq(sidp, ((SeqPntPtr)b->data.ptrvalue)->id)
+                        && (!compare_strand || DoStrandsMatch (pspp->strand, ((SeqPntPtr)b->data.ptrvalue)->strand)))
                     {
                         point = ((SeqPntPtr)b->data.ptrvalue)->point;
                         for (i = 0; i < num; i++)
@@ -5563,7 +5751,8 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
                     break;
                 case SEQLOC_PACKED_PNT:    /* packed pnt */
                     pspp2 = (PackSeqPntPtr)b->data.ptrvalue;
-                    if (SeqIdForSameBioseq(sidp, pspp->id))
+                    if (SeqIdForSameBioseq(sidp, pspp->id)
+                        && (!compare_strand || DoStrandsMatch(pspp->strand, pspp2->strand)))
                     {
                         num2 = PackSeqPntNum(pspp2);
                         if (num == num2)   /* check for identity */
@@ -5606,6 +5795,1047 @@ NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
     return retval;
 }
 
+
+NLM_EXTERN Int2 SeqLocCompare (SeqLocPtr a, SeqLocPtr b)   /* seqloc */
+{
+  return SeqLocCompareEx (a, b, FALSE);
+}
+
+
+static Uint1 ComplementLocCompare (Uint1 val)
+{
+  if (val == SLC_A_IN_B) {
+    val = SLC_B_IN_A;
+  } else if (val == SLC_B_IN_A) {
+    val = SLC_A_IN_B;
+  }
+  return val;
+}
+
+
+static Boolean CheckSeqLocCompResults (SeqLocPtr a, SeqLocPtr b, Uint1 allow_strand, Uint1 check_strand)
+{
+  Boolean rval = TRUE;
+
+  if (SeqLocCompare(a, b) != allow_strand) {
+    rval = FALSE;
+  } else if (SeqLocCompareEx(a, b, TRUE) != check_strand) {
+    rval = FALSE;
+  } else if (SeqLocCompare(b, a) != ComplementLocCompare(allow_strand)) {
+    rval = FALSE;
+  } else if (SeqLocCompareEx(b, a, TRUE) != ComplementLocCompare(check_strand)) {
+    rval = FALSE;
+  }
+  return rval;
+}
+
+
+NLM_EXTERN Boolean UnitTestSeqLocCompare (void)
+{
+  SeqLocPtr a, b;
+  SeqIdPtr sip, sip2 = NULL;
+  SeqIntPtr sint1, sint2, sint3, sint4;
+  TextSeqIdPtr tsip, tsip2 = NULL;
+  ValNodePtr list = NULL, list2 = NULL;
+  SeqPntPtr pnt1, pnt2, pnt3, pnt4;
+  PackSeqPntPtr pspp1, pspp2;
+  SeqBondPtr sbp1, sbp2;
+  Boolean    rval = FALSE;
+
+  a = ValNodeNew (NULL);
+
+  b = ValNodeNew (NULL);
+
+  tsip = TextSeqIdNew ();
+  tsip->accession = StringSave ("AY123456");
+  sip = ValNodeNew (NULL);
+  sip->choice = SEQID_GENBANK;
+  sip->data.ptrvalue = tsip;
+
+  tsip2 = TextSeqIdNew ();
+  tsip2->accession = StringSave ("AY123457");
+  sip2 = ValNodeNew (NULL);
+  sip2->choice = SEQID_GENBANK;
+  sip2->data.ptrvalue = tsip2;
+
+  sint1 = SeqIntNew ();
+  sint1->id = sip;
+  sint1->from = 0;
+  sint1->to = 10;
+
+  sint2 = SeqIntNew ();
+  sint2->id = sip;
+  sint2->from = 15;
+  sint2->to = 25;
+
+  sint3 = SeqIntNew ();
+  sint3->id = sip;
+  sint3->from = 0;
+  sint3->to = 10;
+
+  sint4 = SeqIntNew ();
+  sint4->id = sip;
+  sint4->from = 15;
+  sint4->to = 25;
+
+  pnt1 = SeqPntNew ();
+  pnt1->id = sip;
+  pnt1->point = 5;
+
+  pnt2 = SeqPntNew ();
+  pnt2->id = sip;
+  pnt2->point = 16;
+
+  pnt3 = SeqPntNew ();
+  pnt3->id = sip;
+  pnt3->point = 5;
+
+  pnt4 = SeqPntNew ();
+  pnt4->id = sip;
+  pnt4->point = 16;
+
+  sbp1 = SeqBondNew ();
+  sbp1->a = pnt1;
+  sbp1->b = pnt2;
+
+  sbp2 = SeqBondNew ();
+  sbp2->a = pnt3;
+  sbp2->b = pnt4;
+
+  pspp1 = PackSeqPntNew ();
+  pspp1->id = sip;
+  pspp1->used = 2;
+  pspp1->pnts[0] = 5;
+  pspp1->pnts[1] = 16;
+
+  pspp2 = PackSeqPntNew ();
+  pspp2->id = sip;
+  pspp2->used = 2;
+  pspp2->pnts[0] = 5;
+  pspp2->pnts[1] = 16;
+
+  /* NULL */
+  /* NULL vs NULL */
+  a->choice = SEQLOC_NULL;
+  b->choice = SEQLOC_NULL;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  /* NULL vs EMPTY */
+  b->choice = SEQLOC_EMPTY;
+  b->data.ptrvalue = sip;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* NULL vs WHOLE */
+  b->choice = SEQLOC_WHOLE;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* NULL vs INT */
+  b->choice = SEQLOC_INT;
+  b->data.ptrvalue = sint1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* NULL vs PACKED INT */
+  ValNodeAddPointer (&list, SEQLOC_INT, sint1);
+  ValNodeAddPointer (&list, SEQLOC_INT, sint2);
+  b->choice = SEQLOC_PACKED_INT;
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  list = ValNodeFree (list);
+
+  /* NULL vs point */
+  b->choice = SEQLOC_PNT;
+  b->data.ptrvalue = pnt1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* NULL vs. packed pnt */
+  b->choice = SEQLOC_PACKED_PNT;
+  b->data.ptrvalue = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* NULL vs MIX */
+  list = ValNodeNew (NULL);
+  list->choice = SEQLOC_INT;
+  list->data.ptrvalue = sint1;
+  b->choice = SEQLOC_MIX;
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  list = ValNodeFree (list);
+
+  /* NULL vs BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* EMPTY vs EMPTY */
+  a->choice = SEQLOC_EMPTY;
+  a->data.ptrvalue = sip;
+  b->choice = SEQLOC_EMPTY;
+  b->data.ptrvalue = sip;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  b->data.ptrvalue = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* EMPTY vs WHOLE */
+  b->choice = SEQLOC_WHOLE;
+  b->data.ptrvalue = sip;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* EMPTY vs INT */
+  b->choice = SEQLOC_INT;
+  sint1->id = sip;
+  b->data.ptrvalue = sint1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* EMPTY vs packed-int */
+  list = NULL;
+  ValNodeAddPointer (&list, 0, sint1);
+  ValNodeAddPointer (&list, 0, sint2);
+  b->choice = SEQLOC_PACKED_INT;
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  list = ValNodeFree (list);
+
+  /* EMPTY vs point */
+  b->choice = SEQLOC_PNT;
+  b->data.ptrvalue = pnt1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* EMPTY vs. packed pnt */
+  b->choice = SEQLOC_PACKED_PNT;
+  b->data.ptrvalue = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* EMPTY vs MIX */
+  list = ValNodeNew (NULL);
+  list->choice = SEQLOC_INT;
+  list->data.ptrvalue = sint1;
+  b->choice = SEQLOC_MIX;
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  list = ValNodeFree (list);
+
+  /* EMPTY vs BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  a->choice = SEQLOC_WHOLE;
+  /* WHOLE vs INT */
+  b->choice = SEQLOC_INT;
+  sint1->id = sip;
+  sint1->from = 0;
+  sint1->to = 10;
+  sint1->strand = Seq_strand_plus;
+  b->data.ptrvalue = sint1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->from = 0;
+  sint1->to = 484;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->id = sip;
+  sint1->from = 0;
+  sint1->to = 10;
+  sint1->strand = 0;
+
+  /* WHOLE vs packed int */
+  list = NULL;
+  ValNodeAddPointer (&list, SEQLOC_INT, sint1);
+  ValNodeAddPointer (&list, SEQLOC_INT, sint2);
+  b->choice = SEQLOC_PACKED_INT;
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint2->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  list = ValNodeFree (list);
+  sint1->id = sip;
+  sint2->id = sip;
+
+  /* WHOLE vs pnt */
+  b->choice = SEQLOC_PNT;
+  b->data.ptrvalue = pnt1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = 0;
+  pnt1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->id = sip;
+
+  /* WHOLE vs SEQLOC_PACKED_PNT */
+  b->choice = SEQLOC_PACKED_PNT;
+  b->data.ptrvalue = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = 0;
+  pspp1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = pspp2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    pspp1->next = NULL;
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = NULL;
+  pspp1->id = sip;
+
+  /* WHOLE vs SEQLOC_MIX */
+  list = NULL;
+  ValNodeAddPointer (&list, SEQLOC_INT, sint1);
+  ValNodeAddPointer (&list, SEQLOC_INT, sint2);
+  b->choice = SEQLOC_MIX;
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint2->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->id = sip;
+  sint2->id = sip;
+  list = ValNodeFree (list);
+
+  /* WHOLE vs SEQLOC_BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = 0;
+  sbp1->a->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->id = sip;
+  sbp1->b->id = sip;
+
+  /* INT */
+  a->choice = SEQLOC_INT;
+  a->data.ptrvalue = sint3;
+  /* INT vs SEQLOC_INT */
+  b->choice = SEQLOC_INT;
+  b->data.ptrvalue = sint1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->to = 9;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->to = 11;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->from = 1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->from = 0;
+  sint1->to = 10;
+
+  /* INT vs PACKED_INT */
+  list = NULL;
+  ValNodeAddPointer (&list, SEQLOC_INT, sint1);
+  ValNodeAddPointer (&list, SEQLOC_INT, sint2);
+  b->choice = SEQLOC_PACKED_INT;
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->to = 11;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->from = 1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->from = 11;
+  sint1->to = 24;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->from = 0;
+  sint1->to = 10;
+  list = ValNodeFree (list);
+
+  /* INT vs PNT */
+  b->choice = SEQLOC_PNT;
+  b->data.ptrvalue = pnt1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = 0;
+  pnt1->point = 13;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = 0;
+  pnt1->point = 5;
+  pnt1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->id = sip;
+
+  /* INT vs PACKED_PNT */
+  b->choice = SEQLOC_PACKED_PNT;
+  b->data.ptrvalue = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = 0;
+  pspp1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = pspp2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    pspp1->next = NULL;
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = NULL;
+  pspp1->id = sip;
+  pspp1->pnts[1] = 9;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = 0;
+  pspp1->pnts[1] = 16;
+
+  /* INT vs BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = 0;
+  sbp1->b->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  sbp1->b->strand = 0;
+  sbp1->b->point = 9;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = 0;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = 0;
+
+  sbp1->a->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->id = sip;
+  sbp1->b->id = sip;
+  sbp1->b->point = 16;
+
+  /* PACKED_INT */
+  a->choice = SEQLOC_PACKED_INT;
+  ValNodeAddPointer (&list2, SEQLOC_INT, sint3);
+  ValNodeAddPointer (&list2, SEQLOC_INT, sint4);
+  a->data.ptrvalue = list2;
+
+  /* PACKED_INT vs PACKED_INT */
+  b->choice = SEQLOC_PACKED_INT;
+  ValNodeAddPointer (&list, SEQLOC_INT, sint1);
+  ValNodeAddPointer (&list, SEQLOC_INT, sint2);
+  b->data.ptrvalue = list;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint2->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint2->strand = 0;
+  sint1->from = 1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->strand = 0;
+  sint1->from = 11;
+  sint1->to = 14;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sint1->from = 0;
+  sint1->to = 10;
+
+  /* PACKED_INT vs PNT */
+  b->choice = SEQLOC_PNT;
+  b->data.ptrvalue = pnt1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = 0;
+  pnt1->point = 11;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->point = 16;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+
+  /* PACKED_INT vs SEQLOC_PACKED_PNT */
+  b->choice = SEQLOC_PACKED_PNT;
+  b->data.ptrvalue = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = 0;
+  pspp1->pnts[0] = 11;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = 0;
+  pspp1->pnts[0] = 5;
+  pspp1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = pspp2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    pspp1->next = NULL;
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->id = sip;
+  pspp1->next = NULL;
+
+
+  /* PACKED_INT vs SEQLOC_BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = 0;
+  sbp1->b->strand = 0;
+  sbp1->a->point = 11;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = 0;
+  sbp1->b->point = 13;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->point = 5;
+  sbp1->b->point = 16;
+
+  list2 = ValNodeFree (list2);
+
+  /* PNT */
+  a->choice = SEQLOC_PNT;
+  a->data.ptrvalue = pnt3;
+
+  /* PNT vs PNT */
+  b->choice = SEQLOC_PNT;
+  b->data.ptrvalue = pnt1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->strand = 0;
+  pnt1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->id = sip;
+  pnt1->point = 6;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pnt1->point = 5;
+
+  /* PNT vs PACKED_PNT */
+  b->choice = SEQLOC_PACKED_PNT;
+  b->data.ptrvalue = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = 0;
+  pspp1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = pspp2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    pspp1->next = NULL;
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = NULL;
+  pspp1->id = sip;
+  pspp1->pnts[0] = 6;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->pnts[0] = 4;
+  pspp1->pnts[1] = 5;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->pnts[0] = 5;
+  pspp1->pnts[1] = 16;
+
+  /* PNT vs BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = 0;
+  pnt3->point = 16;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = Seq_strand_minus;  
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = 0;
+  pnt3->point = 5;
+  sbp1->a->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->id = sip;
+
+  /* PACKED_PNT */
+  a->choice = SEQLOC_PACKED_PNT;
+  a->data.ptrvalue = pspp2;
+  /* PACKED_PNT vs PACKED_PNT */
+  b->choice = SEQLOC_PACKED_PNT;
+  b->data.ptrvalue = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->strand = 0;
+  pspp1->pnts[0] = 6;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->pnts[0] = 5;
+  pspp1->pnts[1] = 17;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->pnts[1] = 16;
+  pspp1->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = pspp2;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    pspp1->next = NULL;
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->next = NULL;
+  pspp1->id = sip;
+  pspp1->used = 3;
+  pspp1->pnts[2] = 23;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_IN_B, SLC_A_IN_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp1->used = 2;
+
+  /* PACKED_PNT vs BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp2->used = 3;
+  pspp2->pnts[2] = 23;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp2->used = 2;
+  pspp2->id = sip2;
+  if (!CheckSeqLocCompResults(a, b, SLC_NO_MATCH, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp2->next = pspp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_B_IN_A, SLC_B_IN_A)) {
+    pspp2->next = NULL;
+    goto UnitTestSeqLocCompare_end;
+  }
+  pspp2->next = NULL;
+  pspp2->id = sip;
+  sbp1->a->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = 0;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = 0;
+  sbp1->a->point = 4;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->point = 5;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->point = 5;
+  sbp1->b->point = 16;
+
+  /* BOND */
+  a->choice = SEQLOC_BOND;
+  a->data.ptrvalue = sbp2;
+  /* BOND vs BOND */
+  b->choice = SEQLOC_BOND;
+  b->data.ptrvalue = sbp1;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_EQ_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = Seq_strand_minus;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_NO_MATCH)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->strand = 0;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_EQ_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->strand = 0;
+  sbp1->a->point = 4;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->b->point = 5;
+  if (!CheckSeqLocCompResults(a, b, SLC_A_OVERLAP_B, SLC_A_OVERLAP_B)) {
+    goto UnitTestSeqLocCompare_end;
+  }
+  sbp1->a->point = 5;
+  sbp1->b->point = 16;
+
+  rval = TRUE;
+
+UnitTestSeqLocCompare_end:
+  sint1->id = NULL;
+  sint1 = SeqIntFree (sint1);
+  sint2->id = NULL;
+  sint2 = SeqIntFree (sint2);
+  sint3->id = NULL;
+  sint3 = SeqIntFree (sint3);
+  sint4->id = NULL;
+  sint4 = SeqIntFree (sint4);
+  pnt1->id = NULL;
+  pnt1 = SeqPntFree (pnt1);
+  pnt2->id = NULL;
+  pnt2 = SeqPntFree (pnt2);
+  pspp1->id = NULL;
+  pspp1 = PackSeqPntFree (pspp1);
+  pspp2->id = NULL;
+  pspp2 = PackSeqPntFree (pspp2);
+  sbp1->a = NULL;
+  sbp1->b = NULL;
+  sbp1 = SeqBondFree (sbp1);
+  sbp2->a = NULL;
+  sbp2->b = NULL;
+  sbp2 = SeqBondFree (sbp2);
+
+  sip = SeqIdFree (sip);
+  sip2 = SeqIdFree(sip2);
+  a = ValNodeFree (a);
+  b = ValNodeFree (b);
+  return rval;
+}
+
+/* returns the number of unique nucleotides covered by slp */
+static Int4 SeqLocCoverage (SeqLocPtr slp)
+{
+  Int4Ptr ivals;
+  Int4    numivals = 0;
+  SeqLocPtr tmp;
+  SeqIdPtr sip;
+  SeqIdPtr PNTR id_list;
+  Int4     coverage = 0, i = 0, from, to, j, k;
+  Int4     i_from, i_to, j_from, j_to;
+  Boolean  added_to_prev;
+
+  tmp = NULL;
+  while ((tmp = SeqLocFindNext (slp, tmp)) != NULL) {
+    numivals++;
+  }
+  if (numivals > 0) {
+    ivals = MemNew (sizeof (Int4) * (numivals * 2));
+    id_list = (SeqIdPtr PNTR) MemNew (sizeof (SeqIdPtr) * numivals);
+    tmp = NULL;
+    i = 0;
+    while ((tmp = SeqLocFindNext (slp, tmp)) != NULL) {
+      from = SeqLocStart (tmp);
+      to = SeqLocStop (tmp);
+      sip = SeqLocId (tmp);
+      id_list [i / 2] = sip;
+      ivals [i] = from;
+      i++;
+      ivals [i] = to;
+      i++;
+    }
+    /* now combine overlapping intervals */
+    for (j = 0; j < numivals; j++) {
+      i = j + 1;
+      while (i < numivals) {
+        added_to_prev = FALSE;
+        if (SeqIdComp (sip, id_list[j]) == SIC_YES) {
+          i_from = ivals[2 * i];
+          i_to = ivals[2 * i + 1];
+          j_from = ivals[2 * j];
+          j_to = ivals[2 * j + 1];
+
+          if ((i_from <= j_from && i_to >= j_from) 
+              || (i_from <= j_to && i_to >= j_to)
+              || (i_from >= j_from && i_to <= j_to)) {
+            ivals[2 * j] = MIN (i_from, j_from);
+            ivals[2 * j + 1] = MAX (i_to, j_to);
+            /* delete position i by moving everything above down */
+            for (k = i + 1; k < numivals / 2; k++) {
+              ivals[2 * (k -1)] = ivals[2 * k];
+              ivals[2 * (k - 1) + 1] = ivals[2 * k + 1];
+              id_list[k - 1] = id_list[k];
+            }
+            numivals --;
+            added_to_prev = TRUE;
+          }
+        }
+        if (added_to_prev) {
+          /* do not increment i */
+        } else {
+          i++;
+        }
+      }
+    }
+    /* now add up lengths of intervals */
+    for (j = 0; j < numivals; j++) {
+      coverage += ivals [2 * j + 1] - ivals [2 * j] + 1;
+    }
+    ivals = MemFree (ivals);
+    id_list = MemFree (id_list);
+  }
+  return coverage;
+}
+
+
 /*****************************************************************************
 *
 *   SeqLocAinB(a, b)
@@ -5632,7 +6862,7 @@ NLM_EXTERN Int4 SeqLocAinB (SeqLocPtr a, SeqLocPtr b)
             diff = 0;
             break;
         case SLC_A_IN_B:
-            diff = (SeqLocLen(b) - SeqLocLen(a));
+            diff = (SeqLocCoverage(b) - SeqLocCoverage(a));
             break;
         default:
             break;
@@ -5895,6 +7125,16 @@ NLM_EXTERN Uint2 SeqLocPartialCheckEx (SeqLocPtr head, Boolean farFetch)
                                 }
                             }
                         }
+                    } else if (ifp->choice == 2) /* range */ {
+                        if (sip->strand == Seq_strand_minus) {
+                            if (slp == last) {
+                                retval |= SLP_STOP;
+                            }
+                        } else {
+                            if (slp == first) {
+                                retval |= SLP_START;
+                            }
+                        }
                     }
 
                 }
@@ -5952,6 +7192,16 @@ NLM_EXTERN Uint2 SeqLocPartialCheckEx (SeqLocPtr head, Boolean farFetch)
                                 }
                             }
                         }
+                    } else if (ifp->choice == 2) /* range */ {
+                        if (sip->strand == Seq_strand_minus) {
+                            if (slp == first) {
+                                retval |= SLP_START;
+                            }
+                        } else {
+                            if (slp == last) {
+                                retval |= SLP_STOP;
+                            }
+                        }
                     }
                 }
                 break;
@@ -6144,7 +7394,7 @@ static Boolean GetThePointForOffset(SeqLocPtr of, SeqPntPtr target, Uint1 which_
 Boolean GetThePointForOffsetEx(SeqLocPtr of, SeqPntPtr target, Uint1 which_end, Boolean is_circular);
 Boolean GetPointsForLeftAndRightOffsets(SeqLocPtr of, SeqPntPtr left, SeqPntPtr right, Boolean is_circular);
 static Int4 CheckOffsetInLoc(SeqLocPtr in, Int4 pos, BioseqPtr bsp, SeqIdPtr the_id);
-NLM_EXTERN Int4 CheckPointInBioseq(SeqPntPtr sp, BioseqPtr in);
+NLM_EXTERN Int4 CheckPointInBioseq(SeqPntPtr sp, BioseqPtr in, BoolPtr flip_strand);
 
 /*****************************************************************************
 *
@@ -6201,7 +7451,7 @@ NLM_EXTERN Int4 GetOffsetInBioseq (SeqLocPtr of, BioseqPtr in, Uint1 which_end)
     if (! GetThePointForOffset(of, &sp, which_end))
         return -1L;
 
-    return CheckPointInBioseq(&sp, in);
+    return CheckPointInBioseq(&sp, in, NULL);
 }
 
 
@@ -6215,11 +7465,11 @@ NLM_EXTERN Int4 GetOffsetInBioseqEx (SeqLocPtr of, BioseqPtr in, Uint1 which_end
     if (! GetThePointForOffsetEx(of, &sp, which_end, is_circular))
         return -1L;
 
-    return CheckPointInBioseq(&sp, in);
+    return CheckPointInBioseq(&sp, in, NULL);
 }
 
 
-NLM_EXTERN void GetLeftAndRightOffsetsInBioseq (SeqLocPtr of, BioseqPtr in, Int4Ptr left, Int4Ptr right, Boolean is_circular)
+NLM_EXTERN void GetLeftAndRightOffsetsInBioseq (SeqLocPtr of, BioseqPtr in, Int4Ptr left, Int4Ptr right, Boolean is_circular, BoolPtr left_flip, BoolPtr right_flip)
 {
     SeqPnt l, r;
 
@@ -6236,10 +7486,10 @@ NLM_EXTERN void GetLeftAndRightOffsetsInBioseq (SeqLocPtr of, BioseqPtr in, Int4
         return;
     }
     if (left != NULL) {
-        *left = CheckPointInBioseq (&l, in);
+        *left = CheckPointInBioseq (&l, in, left_flip);
     }
     if (right != NULL) {
-        *right = CheckPointInBioseq (&r, in);
+        *right = CheckPointInBioseq (&r, in, right_flip);
     }
 }
 
@@ -6248,7 +7498,7 @@ NLM_EXTERN void GetLeftAndRightOffsetsInBioseq (SeqLocPtr of, BioseqPtr in, Int4
 *   CheckPointInBioseq(pnt, in)
 *
 *****************************************************************************/
-NLM_EXTERN Int4 CheckPointInBioseq (SeqPntPtr sp, BioseqPtr in)
+NLM_EXTERN Int4 CheckPointInBioseq (SeqPntPtr sp, BioseqPtr in, BoolPtr flip_strand)
 {
     ValNode sl;
     BioseqPtr bsp;
@@ -6294,7 +7544,7 @@ NLM_EXTERN Int4 CheckPointInBioseq (SeqPntPtr sp, BioseqPtr in)
              locked = TRUE;
      }
     if (in->repr == Seq_repr_seg || in->repr == Seq_repr_delta) {
-        retval = SeqMgrMapPartToSegmentedBioseq (in, sp->point, bsp, sp->id);
+        retval = SeqMgrMapPartToSegmentedBioseq (in, sp->point, bsp, sp->id, flip_strand);
     }
     if (retval == -1) {
         retval = CheckOffsetInLoc(slp, sp->point, bsp, sp->id);
@@ -6320,7 +7570,7 @@ NLM_EXTERN Int4 CheckPointInBioseq (SeqPntPtr sp, BioseqPtr in)
                 {
                     case Seq_repr_ref:   /* could have more levels */
                     case Seq_repr_seg:
-                        offset2 = CheckPointInBioseq(sp, bsp);
+                        offset2 = CheckPointInBioseq(sp, bsp, flip_strand);
                         if (offset2 >= 0)   /* got it */
                         {
                             strt = SeqLocStart(curr);
@@ -9258,7 +10508,9 @@ NLM_EXTERN Uint4 LIBCALL WHICH_db_accession (CharPtr s)
           (StringICmp(temp,"GH") == 0) || 
           (StringICmp(temp,"GO") == 0) || 
           (StringICmp(temp,"GR") == 0) || 
-          (StringICmp(temp,"GT") == 0) ) {                /* NCBI EST */
+          (StringICmp(temp,"GT") == 0) || 
+          (StringICmp(temp,"GW") == 0) || 
+          (StringICmp(temp,"HO") == 0) ) {                /* NCBI EST */
               retcode = ACCN_NCBI_EST;
           } else if ((StringICmp(temp,"BV") == 0) ||
                      (StringICmp(temp,"GF") == 0)) {      /* NCBI STS */
@@ -9272,7 +10524,10 @@ NLM_EXTERN Uint4 LIBCALL WHICH_db_accession (CharPtr s)
                      (StringICmp(temp,"EF") == 0) ||
                      (StringICmp(temp,"EU") == 0) ||
                      (StringICmp(temp,"FJ") == 0) ||
-                     (StringICmp(temp,"GQ") == 0)) {      /* NCBI direct submission */
+                     (StringICmp(temp,"GQ") == 0) ||
+                     (StringICmp(temp,"GU") == 0) ||
+                     (StringICmp(temp,"HM") == 0) ||
+                     (StringICmp(temp,"HQ") == 0)) {      /* NCBI direct submission */
               retcode = ACCN_NCBI_DIRSUB;
           } else if ((StringICmp(temp,"AE") == 0) ||
                      (StringICmp(temp,"CP") == 0) ||
@@ -9292,12 +10547,8 @@ NLM_EXTERN Uint4 LIBCALL WHICH_db_accession (CharPtr s)
                      (StringICmp(temp,"GL") == 0)) {      /* NCBI segmented set header Bioseq */
               retcode = ACCN_NCBI_SEGSET;
           } else if ((StringICmp(temp,"AS") == 0) ||
-                     (StringICmp(temp,"GU") == 0) ||
-                     (StringICmp(temp,"GV") == 0) ||
-                     (StringICmp(temp,"GW") == 0) ||
-                     (StringICmp(temp,"GX") == 0) ||
-                     (StringICmp(temp,"GY") == 0) ||
-                     (StringICmp(temp,"GZ") == 0)) {      /* NCBI "other" */
+                     (StringICmp(temp,"HR") == 0) ||
+                     (StringICmp(temp,"HS") == 0)) {      /* NCBI "other" */
               retcode = ACCN_NCBI_OTHER;
           } else if ((StringICmp(temp,"AD") == 0)) {      /* NCBI accessions assigned to GSDB entries */
               retcode = ACCN_NCBI_GSDB;
@@ -9321,13 +10572,21 @@ NLM_EXTERN Uint4 LIBCALL WHICH_db_accession (CharPtr s)
                      (StringICmp(temp,"ET") == 0) ||
                      (StringICmp(temp,"FH") == 0) ||
                      (StringICmp(temp,"FI") == 0) ||
-                     (StringICmp(temp,"GS") == 0) )  {     /* NCBI GSS */
+                     (StringICmp(temp,"GS") == 0) ||
+                     (StringICmp(temp,"HN") == 0) )  {     /* NCBI GSS */
               retcode = ACCN_NCBI_GSS;
           } else if ((StringICmp(temp,"AR") == 0) ||
                      (StringICmp(temp,"DZ") == 0) ||
                      (StringICmp(temp,"EA") == 0) ||
                      (StringICmp(temp,"GC") == 0) ||
-                     (StringICmp(temp,"GP") == 0)) {      /* NCBI patent */
+                     (StringICmp(temp,"GP") == 0) ||
+                     (StringICmp(temp,"GV") == 0) ||
+                     (StringICmp(temp,"GX") == 0) ||
+                     (StringICmp(temp,"GY") == 0) ||
+                     (StringICmp(temp,"GZ") == 0) ||
+                     (StringICmp(temp,"HJ") == 0) ||
+                     (StringICmp(temp,"HK") == 0) ||
+                     (StringICmp(temp,"HL") == 0)) {      /* NCBI patent */
               retcode = ACCN_NCBI_PATENT;
           } else if((StringICmp(temp,"BC")==0)) {         /* NCBI long cDNA project : MGC */
               retcode = ACCN_NCBI_cDNA;
@@ -9338,15 +10597,23 @@ NLM_EXTERN Uint4 LIBCALL WHICH_db_accession (CharPtr s)
                      (StringICmp(temp,"GJ") == 0) ||
                      (StringICmp(temp,"GK") == 0)) {      /* NCBI third-party annotation */
               retcode = ACCN_NCBI_TPA;
-          } else if((StringICmp(temp,"EZ") == 0)) {
-              retcode = ACCN_NCBI_TSA;
           } else if ((StringICmp(temp,"BN") == 0)) {      /* EMBL third-party annotation */
               retcode = ACCN_EMBL_TPA;
           } else if ((StringICmp(temp,"BR") == 0)) {      /* DDBJ third-party annotation */
               retcode = ACCN_DDBJ_TPA;
+          } else if((StringICmp(temp,"EZ") == 0) ||
+                    (StringICmp(temp,"HP") == 0)) {
+              retcode = ACCN_NCBI_TSA;
+          } else if((StringICmp(temp,"FX") == 0)) {
+              retcode = ACCN_DDBJ_TSA;
           } else if ((StringICmp(temp,"AJ") == 0) ||
                      (StringICmp(temp,"AM") == 0) ||
-                     (StringICmp(temp,"FM") == 0)) {     /* EMBL direct submission */
+                     (StringICmp(temp,"FM") == 0) ||
+                     (StringICmp(temp,"HE") == 0) ||
+                     (StringICmp(temp,"HF") == 0) ||
+                     (StringICmp(temp,"HG") == 0) ||
+                     (StringICmp(temp,"HH") == 0) ||
+                     (StringICmp(temp,"HI") == 0)) {     /* EMBL direct submission */
               retcode = ACCN_EMBL_DIRSUB;
           } else if ((StringICmp(temp,"AL") == 0) ||
                      (StringICmp(temp,"BX") == 0)||
@@ -9381,7 +10648,8 @@ NLM_EXTERN Uint4 LIBCALL WHICH_db_accession (CharPtr s)
                      (StringICmp(temp,"DB") == 0) ||
                      (StringICmp(temp,"DC") == 0) ||
                      (StringICmp(temp,"DK") == 0) ||
-                     (StringICmp(temp,"FS") == 0)) {      /* DDBJ EST's */
+                     (StringICmp(temp,"FS") == 0) ||
+                     (StringICmp(temp,"FY") == 0)) {      /* DDBJ EST's */
               retcode = ACCN_DDBJ_EST;
           } else if ((StringICmp(temp,"AB") == 0)) {      /* DDBJ direct submission */
               retcode = ACCN_DDBJ_DIRSUB;
@@ -9401,18 +10669,16 @@ NLM_EXTERN Uint4 LIBCALL WHICH_db_accession (CharPtr s)
                      (StringICmp(temp,"DJ") == 0) || 
                      (StringICmp(temp,"DL") == 0) || 
                      (StringICmp(temp,"DM") == 0) || 
-                     (StringICmp(temp,"FU") == 0)) {      /* DDBJ patent division */
+                     (StringICmp(temp,"FU") == 0) || 
+                     (StringICmp(temp,"FV") == 0) || 
+                     (StringICmp(temp,"FW") == 0) || 
+                     (StringICmp(temp,"FZ") == 0)) {      /* DDBJ patent division */
               retcode = ACCN_DDBJ_PATENT;
           } else if ((StringICmp(temp,"DE") == 0) ||
                      (StringICmp(temp,"DH") == 0) || 
                      (StringICmp(temp,"FT") == 0)) {      /* DDBJ GSS */
               retcode = ACCN_DDBJ_GSS;
-          } else if ((StringICmp(temp,"FV") == 0) || 
-                     (StringICmp(temp,"FW") == 0) || 
-                     (StringICmp(temp,"FX") == 0) || 
-                     (StringICmp(temp,"FY") == 0) || 
-                     (StringICmp(temp,"FZ") == 0) || 
-                     (StringICmp(temp,"GA") == 0) || 
+          } else if ((StringICmp(temp,"GA") == 0) || 
                      (StringICmp(temp,"GB") == 0)) {      /* DDBJ unassigned */
               retcode = ACCN_DDBJ_OTHER;
           } else {
diff --git a/api/sequtil.h b/api/sequtil.h
index b90eaaa..b4eef37 100644
--- a/api/sequtil.h
+++ b/api/sequtil.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 4/1/91
 *
-* $Revision: 6.58 $
+* $Revision: 6.60 $
 *
 * File Description:  Sequence Utilities for objseq and objsset
 *
@@ -608,7 +608,7 @@ NLM_EXTERN Boolean SeqLocRevCmp(SeqLocPtr anp);
 NLM_EXTERN Int4 GetOffsetInLoc(SeqLocPtr of, SeqLocPtr in, Uint1 which_end);
 NLM_EXTERN Int4 GetOffsetInBioseq(SeqLocPtr of, BioseqPtr in, Uint1 which_end);
 NLM_EXTERN Int4 GetOffsetInBioseqEx (SeqLocPtr of, BioseqPtr in, Uint1 which_end, Boolean is_circular);
-NLM_EXTERN void GetLeftAndRightOffsetsInBioseq (SeqLocPtr of, BioseqPtr in, Int4Ptr left, Int4Ptr right, Boolean is_circular);
+NLM_EXTERN void GetLeftAndRightOffsetsInBioseq (SeqLocPtr of, BioseqPtr in, Int4Ptr left, Int4Ptr right, Boolean is_circular, BoolPtr left_flip, BoolPtr right_flip );
 NLM_EXTERN Int2 SeqLocOrder(SeqLocPtr a, SeqLocPtr b, BioseqPtr in);
 
 NLM_EXTERN Int2 SeqLocMol(SeqLocPtr seqloc);
@@ -633,7 +633,9 @@ NLM_EXTERN Int2 SeqLocCompare(SeqLocPtr a, SeqLocPtr b);
 #define SLC_B_IN_A 2
 #define SLC_A_EQ_B 3
 #define SLC_A_OVERLAP_B 4
+NLM_EXTERN Int2 SeqLocCompareEx (SeqLocPtr a, SeqLocPtr b, Boolean compare_strand);
 
+NLM_EXTERN Boolean UnitTestSeqLocCompare (void);
 
 /*****************************************************************************
 *
diff --git a/api/sqnutil1.c b/api/sqnutil1.c
index 44282e9..b67b5d4 100644
--- a/api/sqnutil1.c
+++ b/api/sqnutil1.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   9/2/97
 *
-* $Revision: 6.534 $
+* $Revision: 6.587 $
 *
 * File Description: 
 *
@@ -60,6 +60,10 @@
 #include <subutil.h>
 #include <asn2gnbi.h>
 
+#define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
+#include <macroapi.h>
+
 static int descr_insert_order [] = {
   Seq_descr_title,
   Seq_descr_source,
@@ -98,8 +102,9 @@ static void NormalizeDescriptorProc (
 {
   BioseqPtr         bsp;
   BioseqSetPtr      bssp;
-  SeqDescrPtr       first [SEQDESCR_MAX];
-  SeqDescrPtr       last [SEQDESCR_MAX];
+  /* arrays are SEQDESCR_MAX + 1, last slot stores unexpected descriptor numbers */
+  SeqDescrPtr       first [SEQDESCR_MAX + 1];
+  SeqDescrPtr       last [SEQDESCR_MAX + 1];
   int               i;
   int               idx;
   SeqDescrPtr PNTR  head = NULL;
@@ -132,7 +137,11 @@ static void NormalizeDescriptorProc (
     sdp->next = NULL;
 
     idx = (int) sdp->choice;
-    if (idx > 0 && idx < SEQDESCR_MAX) {
+    /* unexpected descriptor numbers go into last slot */
+    if (idx <= 0 || idx >= SEQDESCR_MAX) {
+      idx = SEQDESCR_MAX;
+    }
+    if (idx > 0 && idx <= SEQDESCR_MAX) {
       if (first [idx] == NULL) {
         first [idx] = sdp;
       }
@@ -198,6 +207,7 @@ NLM_EXTERN DatePtr DateAdvance (DatePtr dp, Uint1 monthsToAdd)
       }
     }
   }
+  if (dp != NULL) {
   switch (dp->data [2]) {
     case 4 :
     case 6 :
@@ -218,6 +228,7 @@ NLM_EXTERN DatePtr DateAdvance (DatePtr dp, Uint1 monthsToAdd)
       }
       break;
   }
+  }
   return dp;
 }
 
@@ -225,6 +236,7 @@ typedef struct orgscan {
   ObjMgrPtr     omp;
   Int2          nuclCode;
   Int2          mitoCode;
+  Int2          pstdCode;
   Boolean       mito;
   Boolean       plastid;
   Char          taxname [196];
@@ -241,6 +253,7 @@ static Boolean OrgScanGatherFunc (GatherContextPtr gcp)
   Boolean        mito = FALSE;
   Int2           mitoCode = 0;
   Int2           nuclCode = 0;
+  Int2           pstdCode = 0;
   ObjMgrTypePtr  omtp;
   OrgNamePtr     onp;
   OrgRefPtr      orp;
@@ -330,6 +343,7 @@ static Boolean OrgScanGatherFunc (GatherContextPtr gcp)
     if (onp != NULL) {
       nuclCode = onp->gcode;
       mitoCode = onp->mgcode;
+      pstdCode = onp->pgcode;
       doCodes = TRUE;
       /* osp->nuclCode = onp->gcode;
       osp->mitoCode = onp->mgcode; */
@@ -347,10 +361,12 @@ static Boolean OrgScanGatherFunc (GatherContextPtr gcp)
                                 biop->genome == GENOME_cyanelle ||
                                 biop->genome == GENOME_apicoplast ||
                                 biop->genome == GENOME_leucoplast ||
-                                biop->genome == GENOME_proplastid);
+                                biop->genome == GENOME_proplastid ||
+                                biop->genome == GENOME_chromatophore);
       if (doCodes) {
         osp->nuclCode = nuclCode;
         osp->mitoCode = mitoCode;
+        osp->pstdCode = pstdCode;
       }
       if (doTaxname) {
         StringNCpy_0 (osp->taxname, taxname, sizeof (osp->taxname));
@@ -379,6 +395,7 @@ static Int2 SeqEntryOrEntityIDToGeneticCode (SeqEntryPtr sep, Uint2 entityID, Bo
   osp.plastid = FALSE;
   osp.nuclCode = 0;
   osp.mitoCode = 0;
+  osp.pstdCode = 0;
   osp.omp = ObjMgrGet ();
   osp.taxname [0] = '\0';
   osp.biop = NULL;
@@ -407,7 +424,11 @@ static Int2 SeqEntryOrEntityIDToGeneticCode (SeqEntryPtr sep, Uint2 entityID, Bo
     *biopp = osp.biop;
   }
   if (osp.plastid) {
+    if (osp.pstdCode > 0) {
+      return osp.pstdCode;
+    } else {
     return 11;
+    }
   } else if (osp.mito) {
     return osp.mitoCode;
   } else {
@@ -451,6 +472,7 @@ NLM_EXTERN Boolean BioseqToGeneticCode (
   Boolean            mito = FALSE;
   Int2               mitoCode = 0;
   Int2               nuclCode = 0;
+  Int2               pstdCode = 0;
   OrgNamePtr         onp;
   OrgRefPtr          orp;
   Boolean            plastid = FALSE;
@@ -483,6 +505,7 @@ NLM_EXTERN Boolean BioseqToGeneticCode (
   if (onp != NULL) {
     nuclCode = onp->gcode;
     mitoCode = onp->mgcode;
+    pstdCode = onp->pgcode;
   }
 
   mito = (Boolean) (biop->genome == GENOME_kinetoplast ||
@@ -495,10 +518,15 @@ NLM_EXTERN Boolean BioseqToGeneticCode (
                        biop->genome == GENOME_cyanelle ||
                        biop->genome == GENOME_apicoplast ||
                        biop->genome == GENOME_leucoplast ||
-                       biop->genome == GENOME_proplastid);
+                       biop->genome == GENOME_proplastid ||
+                       biop->genome == GENOME_chromatophore);
 
   if (plastid) {
+    if (pstdCode > 0) {
+      gencode = pstdCode;
+    } else {
     gencode = 11;
+    }
   } else if (mito) {
     gencode = mitoCode;
   } else {
@@ -1028,6 +1056,195 @@ NLM_EXTERN void RemoveSeqEntryFromSeqEntry (SeqEntryPtr top, SeqEntryPtr del, Bo
   }
 }
 
+
+typedef struct commontitle {
+  BioseqPtr bsp;
+  SeqDescPtr sdp;
+} CommonTitleData, PNTR CommonTitlePtr;
+
+
+static CommonTitlePtr CommonTitleNew (BioseqPtr bsp, SeqDescPtr sdp)
+{
+  CommonTitlePtr c = (CommonTitlePtr) MemNew (sizeof (CommonTitleData));
+  c->bsp = bsp;
+  c->sdp = sdp;
+  return c;
+}
+
+
+static CommonTitlePtr CommonTitleFree (CommonTitlePtr c)
+{
+  if (c != NULL) {
+    c = MemFree (c);
+  }
+  return c;
+}
+
+
+static ValNodePtr CommonTitleListFree (ValNodePtr vnp)
+{
+  ValNodePtr vnp_next;
+
+  while (vnp != NULL) {
+    vnp_next = vnp->next;
+    vnp->next = NULL;
+    vnp->data.ptrvalue = CommonTitleFree (vnp->data.ptrvalue);
+    vnp = ValNodeFree (vnp);
+    vnp = vnp_next;
+  }
+  return vnp;
+}
+
+
+static void RemoveCommonTitles (ValNodePtr vnp, CharPtr common_title)
+{
+  CommonTitlePtr c;
+  ObjValNodePtr  ovp;
+
+  while (vnp != NULL) {
+    c = vnp->data.ptrvalue;
+    if (StringCmp (c->sdp->data.ptrvalue, common_title) == 0 && c->sdp->extended > 0) {
+      ovp = (ObjValNodePtr) c->sdp;
+      ovp->idx.deleteme = TRUE;
+    }
+    vnp = vnp->next;
+  }
+}
+
+
+static int LIBCALLBACK SortCommonTitle (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  CommonTitlePtr c1;
+  CommonTitlePtr c2;
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      c1 = (CommonTitlePtr) vnp1->data.ptrvalue;
+      c2 = (CommonTitlePtr) vnp2->data.ptrvalue;
+      if (c1 != NULL && c2 != NULL && c1->sdp != NULL && c2->sdp != NULL
+          && c1->sdp->data.ptrvalue != NULL && c2->sdp->data.ptrvalue != NULL) {
+        return StringCmp (c1->sdp->data.ptrvalue, c2->sdp->data.ptrvalue);
+      }
+    }
+  }
+  return 0;
+}
+
+
+static void CollectCommonTitle (BioseqPtr bsp, Pointer data)
+{
+  SeqDescPtr sdp;
+
+  if (bsp == NULL || ISA_aa (bsp->mol) || data == NULL) {
+    return;
+  }
+
+  sdp = bsp->descr;
+  while (sdp != NULL) {
+    if (sdp->choice == Seq_descr_title) {
+      ValNodeAddPointer ((ValNodePtr PNTR) data, 0, CommonTitleNew (bsp, sdp));
+    }
+    sdp = sdp->next;
+  }
+}
+
+
+static CharPtr FindCommonTitleFromList (ValNodePtr list)
+{
+  ValNodePtr vnp;
+  CommonTitlePtr c;
+  Int4 num_common = 0, num_total, num_expected;
+  CharPtr common_title;
+
+  if (list == NULL) {
+    return NULL;
+  }
+  num_total = ValNodeLen (list);
+  if (num_total % 2 != 0 || num_total < 4) {
+    return NULL;
+  }
+  num_expected = num_total / 2;
+
+  c = list->data.ptrvalue;
+  common_title = c->sdp->data.ptrvalue;
+  num_common = 1;
+
+  for (vnp = list->next; vnp != NULL; vnp = vnp->next) {
+    c = (CommonTitlePtr) vnp->data.ptrvalue;
+    if (StringCmp (common_title, c->sdp->data.ptrvalue) == 0) {
+      num_common++;
+    } else {
+      num_common = 1;
+      common_title = c->sdp->data.ptrvalue;
+    }
+  }
+  if (num_common == num_expected) {
+    return StringSave (common_title);
+  }
+
+  return NULL;
+}
+
+
+static void PromoteCommonTitlesSetCallback (BioseqSetPtr bssp, Pointer data)
+{
+  ValNodePtr list = NULL;
+  CharPtr common_title = NULL;
+  SeqDescrPtr sdp;
+  Int4        num_member = 0;
+  SeqEntryPtr s;
+  CharPtr     set_title = NULL;
+
+  if (bssp == NULL || !GetsDocsumTitle (bssp->_class)) {
+    return;
+  }
+
+  VisitBioseqsInSet (bssp, &list, CollectCommonTitle);
+  list = ValNodeSort (list, SortCommonTitle);
+
+  common_title = FindCommonTitleFromList (list);
+  if (common_title != NULL) {
+    s = bssp->seq_set;
+    while (s != NULL) {
+      num_member++;
+      s = s->next;
+    }
+    if (ValNodeLen (list) == num_member) {
+      for (sdp = bssp->descr; sdp != NULL && set_title == NULL; sdp = sdp->next) {
+        if (sdp->choice == Seq_descr_title) {
+          set_title = sdp->data.ptrvalue;
+        }
+      }
+      if (set_title != NULL
+          && StringCmp (set_title, common_title) != 0) {
+        /* don't remove, the seq titles just happen to be identical */
+        common_title = MemFree (common_title);
+      }
+    }
+  }
+  if (common_title != NULL) {
+    sdp = SeqDescrNew (NULL);
+    sdp->choice = Seq_descr_title;
+    sdp->data.ptrvalue = common_title;
+    sdp->next = bssp->descr;
+    bssp->descr = sdp;
+    RemoveCommonTitles (list, common_title);
+  }
+  list = CommonTitleListFree(list);
+}
+
+
+NLM_EXTERN void PromoteCommonTitlesToSet (SeqEntryPtr sep)
+{
+  VisitSetsInSep (sep, NULL, PromoteCommonTitlesSetCallback);
+}
+
+
 NLM_EXTERN void DeleteMultipleTitles (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
 
 {
@@ -1077,7 +1294,7 @@ NLM_EXTERN void RenormalizeNucProtSets (SeqEntryPtr sep, Boolean relink)
   ObjMgrData     omdata;
   Uint2          parenttype;
   Pointer        parentptr;
-  SeqAnnotPtr    sap;
+  SeqAnnotPtr    sap, tmp_sap;
   SeqEntryPtr    seqentry;
 
   if (sep == NULL) return;
@@ -1135,11 +1352,14 @@ NLM_EXTERN void RenormalizeNucProtSets (SeqEntryPtr sep, Boolean relink)
           }
         }
         if (sap != NULL) {
-          while (sap->next != NULL) {
-            sap = sap->next;
+          tmp_sap = sap;
+          while (tmp_sap->next != NULL) {
+            tmp_sap = tmp_sap->next;
           }
-          sap->next = annot;
+          tmp_sap->next = annot;
+          MergeAdjacentAnnotsInList (sap);
         }
+
         DeleteMultipleTitles (sep, NULL, 0, 0);
 
         if (relink) {
@@ -1629,6 +1849,59 @@ NLM_EXTERN void SetSeqLocPartial (SeqLocPtr location, Boolean partial5, Boolean
   }
 }
 
+NLM_EXTERN ValNodePtr GetSeqLocPartialSet (SeqLocPtr location)
+
+{
+  ValNodePtr  head = NULL, last = NULL, vnp;
+  Boolean     noLeft;
+  Boolean     noRight;
+  SeqLocPtr   slp;
+  Int4        val;
+
+  if (location == NULL) return NULL;
+
+  slp = SeqLocFindNext (location, NULL);
+  while (slp != NULL) {
+    CheckSeqLocForPartial (slp, &noLeft, &noRight);
+    val = 0;
+    if (noLeft) {
+      val |= 2;
+    }
+    if (noRight) {
+      val |= 1;
+    }
+    vnp = ValNodeAddInt (&last, 0, val);
+    if (head == NULL) {
+      head = vnp;
+    }
+    last = vnp;
+    slp = SeqLocFindNext (location, slp);
+  }
+
+  return head;
+}
+
+NLM_EXTERN void SetSeqLocPartialSet (SeqLocPtr location, ValNodePtr vnp)
+
+{
+  Boolean     noLeft;
+  Boolean     noRight;
+  SeqLocPtr   slp;
+  Int4        val;
+
+  if (location == NULL || vnp == NULL) return;
+
+  slp = SeqLocFindNext (location, NULL);
+  while (slp != NULL && vnp != NULL) {
+    val = (Int4) vnp->data.intvalue;
+    noLeft = (Boolean) ((val & 2) != 0);
+    noRight = (Boolean) ((val & 1) != 0);
+    SetSeqLocPartial (slp, noLeft, noRight);
+    slp = SeqLocFindNext (location, slp);
+    vnp = vnp->next;
+  }
+}
+
 /* KeyTag section */
 
 NLM_EXTERN int LIBCALLBACK SortVnpByString (VoidPtr ptr1, VoidPtr ptr2)
@@ -2147,6 +2420,7 @@ NLM_EXTERN void PromoteXrefsExEx (
   long int             val;
   ValNodePtr           vnp;
   SeqFeatXrefPtr       xref;
+  Boolean              ok_to_remove;
   /*
   DbtagPtr             dbt;
   SeqFeatPtr           gene;
@@ -2412,7 +2686,7 @@ NLM_EXTERN void PromoteXrefsExEx (
           sfp->data.choice == SEQFEAT_CDREGION &&
           sfp->product == NULL && (! sfp->pseudo)) {
         prp = (ProtRefPtr) xref->data.value.ptrvalue;
-        xref->data.value.ptrvalue = NULL;
+        ok_to_remove = TRUE;
         if (prp != NULL) {
           crp = (CdRegionPtr) sfp->data.value.ptrvalue;
           if (crp != NULL) {
@@ -2486,7 +2760,9 @@ NLM_EXTERN void PromoteXrefsExEx (
                     }
                     gbq = nextqual;
                   }
-                  if (! StringHasNoText (id)) {
+                  if (StringHasNoText (id)) {
+                    Message (MSG_POSTERR, "No transcript_id on CDS - unable to create nuc-prot set");
+                  } else {
                     if (StringChr (id, '|') != NULL) {
                       sip = SeqIdParse (id);
                     } else if (force_local_id) {
@@ -2522,6 +2798,11 @@ NLM_EXTERN void PromoteXrefsExEx (
                 } else {
                   sep = GetBestTopParentForData (entityID, bsp);
                 }
+                if (sep == NULL) {
+                  Message (MSG_POSTERR, "No location for nuc-prot set for CDS - unable to create nuc-prot set");
+                  pbsp = BioseqFree (pbsp);
+                  ok_to_remove = FALSE;
+                } else {
                 old = SeqEntrySetScope (sep);
                 gbq = sfp->qual;
                 prevqual = (GBQualPtr PNTR) &(sfp->qual);
@@ -2629,6 +2910,9 @@ NLM_EXTERN void PromoteXrefsExEx (
             }
           }
         }
+        }
+        if (ok_to_remove) {
+          xref->data.value.ptrvalue = NULL;
         *(prev) = next;
         xref->next = NULL;
         xref->data.choice = 0;
@@ -2636,6 +2920,9 @@ NLM_EXTERN void PromoteXrefsExEx (
       } else {
         prev = &(xref->next);
       }
+      } else {
+        prev = &(xref->next);
+      }
       xref = next;
     }
     sfp = sfp->next;
@@ -3941,6 +4228,7 @@ static Boolean HandledGBQualOnRNA (SeqFeatPtr sfp, GBQualPtr gbq, Boolean isEmbl
   Uint1      aa;
   BioseqPtr  bsp;
   Uint1      codon [6];
+  Boolean    emptyRNA;
   Int4       from;
   Boolean    is_fMet = FALSE;
   Boolean    is_std_name = FALSE;
@@ -3967,6 +4255,30 @@ static Boolean HandledGBQualOnRNA (SeqFeatPtr sfp, GBQualPtr gbq, Boolean isEmbl
       rrp->type = 255;
     }
     if (rrp->type == 255 && is_std_name) return FALSE;
+    if (rrp->ext.choice == 1) {
+      name = (CharPtr) rrp->ext.value.ptrvalue;
+      if (StringHasNoText (name)) {
+        rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+        rrp->ext.choice = 0;
+      }
+    }
+    if (rrp->ext.choice == 2) {
+      trp = (tRNAPtr) rrp->ext.value.ptrvalue;
+      if (trp != NULL) {
+        if (trp->aatype == 0 && trp->aa == 0 && trp->anticodon == NULL) {
+          emptyRNA = TRUE;
+          for (j = 0; j < 6; j++) {
+            if (trp->codon [j] != 255) {
+              emptyRNA = FALSE;
+            }
+          }
+          if (emptyRNA) {
+            rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+            rrp->ext.choice = 0;
+          }
+        }
+      }
+    }
     if (rrp->type == 3 && rrp->ext.choice == 1) {
       name = (CharPtr) rrp->ext.value.ptrvalue;
       aa = ParseTRnaString (name, &justTrnaText, codon, FALSE);
@@ -4334,13 +4646,6 @@ static void CleanupRptUnitSeq (GBQualPtr gbq)
 
   if (gbq == NULL) return;
   if (StringHasNoText (gbq->val)) return;
-  ptr = gbq->val;
-  ch = *ptr;
-  while (ch != '\0') {
-    if (StringChr ("ACGTUNacgtun0123456789()", ch) == NULL) return;
-    ptr++;
-    ch = *ptr;
-  }
   /* lower case, and convert U to T */
   ptr = gbq->val;
   ch = *ptr;
@@ -5643,6 +5948,8 @@ static Uint1 LocationForPlastidText (CharPtr plastid_name)
     return GENOME_leucoplast;
   } else if (StringICmp (plastid_name, "proplastid") == 0) {
     return GENOME_proplastid;
+  } else if (StringICmp (plastid_name, "chromatophore") == 0) {
+    return GENOME_chromatophore;
   } else {
     return 0;
   }
@@ -6069,9 +6376,9 @@ static CharPtr StringHasPrefix (CharPtr str, CharPtr pref, Boolean novalneeded,
     return NULL;
   }
   ch = *(str + len);
-  if (ch != '=' && ch != ' ' && ch != '\0') return NULL;
+  if (ch != '=' && ch != ' ' && ch != ':' && ch != '\0') return NULL;
   ch = *val;
-  while (ch == '=' || ch == ' ') {
+  while (ch == '=' || ch == ' ' || ch == ':') {
     val++;
     ch = *val;
   }
@@ -6549,6 +6856,159 @@ static void GbqualToOrpMod (GBQualPtr PNTR prevgbq, ValNodePtr PNTR vnpp)
   }
 }
 
+#define IS_WHITESP(c) (((c) == ' ') || ((c) == '\n') || ((c) == '\r') || ((c) == '\t'))
+
+static Boolean IsStringSingleToken (CharPtr str)
+
+{
+  Char  ch;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  ch = *str;
+  while (ch != '\0') {
+    if (IS_WHITESP (ch)) return FALSE;
+    str++;
+    ch = *str;
+  }
+
+  return TRUE;
+}
+
+static CharPtr FindAnOrgMod (OrgNamePtr onp, Uint1 subtype)
+
+{
+  OrgModPtr  omp;
+
+  if (onp == NULL || subtype == 0) return NULL;
+
+  for (omp = onp->mod; omp != NULL; omp = omp->next) {
+    if (omp->subtype != subtype) continue;
+    if (StringHasNoText (omp->subname)) continue;
+    return omp->subname;
+  }
+
+  return NULL;
+}
+
+static CharPtr FindASubSource (BioSourcePtr biop, Uint1 subtype)
+
+{
+  SubSourcePtr  ssp;
+
+  if (biop == NULL || subtype == 0) return NULL;
+
+  for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
+    if (ssp->subtype != subtype) continue;
+    if (StringHasNoText (ssp->name)) continue;
+    return ssp->name;
+  }
+
+  return NULL;
+}
+
+static void CleanupOrgModOther (BioSourcePtr biop, OrgNamePtr onp)
+
+{
+  OrgModPtr       next;
+  OrgModPtr       omp;
+  OrgModPtr PNTR  prev;
+  CharPtr         str;
+  Uint1           subtype_val;
+  CharPtr         tmp;
+  Boolean         unlink;
+  CharPtr         val;
+
+  if (biop == NULL || onp == NULL) return;
+
+  prev = &(onp->mod);
+  omp = onp->mod;
+  while (omp != NULL) {
+    next = omp->next;
+    unlink= FALSE;
+    if (omp->subtype == ORGMOD_other) {
+      str = omp->subname;
+      val = NULL;
+      subtype_val = 0;
+      StringHasOrgModPrefix (str, &val, &subtype_val, TRUE);
+      if (val != NULL) {
+        tmp = FindAnOrgMod (onp, subtype_val);
+        if (tmp != NULL && StringICmp (tmp, val) == 0) {
+          unlink = TRUE;
+        }
+      } else {
+        subtype_val = 0;
+        StringHasSubSourcePrefix (str, &val, &subtype_val, TRUE);
+        if (val != NULL) {
+          tmp = FindASubSource (biop, subtype_val);
+          if (tmp != NULL && StringICmp (tmp, val) == 0) {
+            unlink = TRUE;
+          }
+        }
+      }
+    }
+    if (unlink) {
+      *prev = omp->next;
+      omp->next = NULL;
+      OrgModFree (omp);
+    } else {
+      prev = &(omp->next);
+    }
+    omp = next;
+  }
+}
+
+static void CleanupSubSourceOther (BioSourcePtr biop, OrgNamePtr onp)
+
+{
+  SubSourcePtr       next;
+  SubSourcePtr PNTR  prev;
+  SubSourcePtr       ssp;
+  CharPtr            str;
+  Uint1              subtype_val;
+  CharPtr            tmp;
+  Boolean            unlink;
+  CharPtr            val;
+
+  if (biop == NULL || onp == NULL) return;
+
+  prev = &(biop->subtype);
+  ssp = biop->subtype;
+  while (ssp != NULL) {
+    next = ssp->next;
+    unlink = FALSE;
+    if (ssp->subtype == SUBSRC_other) {
+      str = ssp->name;
+      val = NULL;
+      subtype_val = 0;
+      StringHasOrgModPrefix (str, &val, &subtype_val, TRUE);
+      if (val != NULL) {
+        tmp = FindAnOrgMod (onp, subtype_val);
+        if (tmp != NULL && StringICmp (tmp, val) == 0) {
+          unlink = TRUE;
+        }
+      } else {
+        subtype_val = 0;
+        StringHasSubSourcePrefix (str, &val, &subtype_val, TRUE);
+        if (val != NULL) {
+          tmp = FindASubSource (biop, subtype_val);
+          if (tmp != NULL && StringICmp (tmp, val) == 0) {
+            unlink = TRUE;
+          }
+        }
+      }
+    }
+    if (unlink) {
+      *prev = ssp->next;
+      ssp->next = NULL;
+      SubSourceFree (ssp);
+    } else {
+      prev = &(ssp->next);
+    }
+    ssp = next;
+  }
+}
+
 static int LIBCALLBACK SortDbxref (VoidPtr ptr1, VoidPtr ptr2)
 
 {
@@ -6587,6 +7047,10 @@ static int LIBCALLBACK SortDbxref (VoidPtr ptr1, VoidPtr ptr2)
     } else if (oip1->id < oip2->id) {
       return -1;
     }
+  } else if (str1 != NULL) {
+    return 1;
+  } else if (str2 != NULL) {
+    return -1;
   }
   return 0;
 }
@@ -6685,6 +7149,12 @@ static void FixOldDbxrefs (ValNodePtr vnp)
       } else if (StringCmp (dbt->db, "GENEDB") == 0) {
         dbt->db = MemFree (dbt->db);
         dbt->db = StringSave ("GeneDB");
+      } else if (StringCmp (dbt->db, "GreengenesID") == 0) {
+        dbt->db = MemFree (dbt->db);
+        dbt->db = StringSave ("Greengenes");
+      } else if (StringCmp (dbt->db, "HMPID") == 0) {
+        dbt->db = MemFree (dbt->db);
+        dbt->db = StringSave ("HMP");
       }
       if (StringICmp (dbt->db, "HPRD") == 0) {
         oip = dbt->tag;
@@ -6753,9 +7223,10 @@ static void FixOldDbxrefs (ValNodePtr vnp)
       } else if (StringICmp (dbt->db, "IFO") == 0) {
         dbt->db = MemFree (dbt->db);
         dbt->db = StringSave ("NBRC");
-      } else if (StringICmp (dbt->db, "BHB") == 0) {
+      } else if (StringICmp (dbt->db, "BHB") == 0 ||
+          StringICmp (dbt->db, "BioHealthBase") == 0) {
         dbt->db = MemFree (dbt->db);
-        dbt->db = StringSave ("BioHealthBase");
+        dbt->db = StringSave ("IRD");
       }
 
       /* expand db_xrefs with colons inside tags */
@@ -7582,6 +8053,30 @@ static void NormalizeAuthors (AuthListPtr alp, Boolean fixInitials)
   }
 }
 
+static void StrStripSpaces (
+  CharPtr str
+)
+
+{
+  CharPtr  new_str;
+
+  if (str == NULL) return;
+
+  new_str = str;
+  while (*str != '\0') {
+    *new_str++ = *str;
+    if (*str == ' ' || *str == '\t' || *str == '(') {
+      for (str++; *str == ' ' || *str == '\t'; str++) continue;
+      if (*str == ')' || *str == ',') {
+        new_str--;
+      }
+    } else {
+      str++;
+    }
+  }
+  *new_str = '\0';
+}
+
 /* from utilpub.c */
 static Boolean empty_citgen(CitGenPtr  cit)
 {
@@ -7612,6 +8107,58 @@ static Boolean empty_citgen(CitGenPtr  cit)
     return TRUE;
 }
 
+static void NormalizePubAuthors (ValNodePtr vnp, Boolean stripSerial, Boolean fixInitials)
+
+{
+  CitArtPtr    cap;
+  CitBookPtr   cbp;
+  CitGenPtr    cgp;
+  CitPatPtr    cpp;
+  CitSubPtr    csp;
+
+  if (vnp == NULL) return;
+  if (vnp->choice == PUB_PMid || vnp->choice == PUB_Muid) return;
+  if (vnp->data.ptrvalue == NULL) return;
+  switch (vnp->choice) {
+    case PUB_Gen :
+      cgp = (CitGenPtr) vnp->data.ptrvalue;
+      NormalizeAuthors (cgp->authors, fixInitials);
+      break;
+    case PUB_Sub :
+      csp = (CitSubPtr) vnp->data.ptrvalue;
+      NormalizeAuthors (csp->authors, fixInitials);
+      break;
+    case PUB_Article :
+      cap = (CitArtPtr) vnp->data.ptrvalue;
+      NormalizeAuthors (cap->authors, fixInitials);
+      if (cap->from == 2 || cap->from == 3) {
+        cbp = (CitBookPtr) cap->fromptr;
+        if (cbp != NULL) {
+          NormalizeAuthors (cbp->authors, fixInitials);
+        }
+      }
+      break;
+    case PUB_Book :
+      cbp = (CitBookPtr) vnp->data.ptrvalue;
+      NormalizeAuthors (cbp->authors, fixInitials);
+      break;
+    case PUB_Man :
+      cbp = (CitBookPtr) vnp->data.ptrvalue;
+      if (cbp->othertype == 2 && cbp->let_type == 3) {
+        NormalizeAuthors (cbp->authors, fixInitials);
+      }
+      break;
+    case PUB_Patent :
+      cpp = (CitPatPtr) vnp->data.ptrvalue;
+      NormalizeAuthors (cpp->authors, fixInitials);
+      NormalizeAuthors (cpp->applicants, fixInitials);
+      NormalizeAuthors (cpp->assignees, fixInitials);
+      break;
+    default :
+      break;
+  }
+}
+
 static void NormalizeAPub (ValNodePtr vnp, Boolean stripSerial, Boolean fixInitials)
 
 {
@@ -7620,19 +8167,20 @@ static void NormalizeAPub (ValNodePtr vnp, Boolean stripSerial, Boolean fixIniti
   CitArtPtr    cap;
   CitBookPtr   cbp;
   CitGenPtr    cgp;
-  CitPatPtr    cpp;
+  CitJourPtr   cjp;
   CitSubPtr    csp;
   ImprintPtr   imp;
   CharPtr      str;
   CharPtr      tmp;
+  ValNodePtr   ttl;
 
   if (vnp == NULL) return;
   if (vnp->choice == PUB_PMid || vnp->choice == PUB_Muid) return;
   if (vnp->data.ptrvalue == NULL) return;
+  imp = NULL;
   switch (vnp->choice) {
     case PUB_Gen :
       cgp = (CitGenPtr) vnp->data.ptrvalue;
-      NormalizeAuthors (cgp->authors, fixInitials);
       if (stripSerial) {
         cgp->serial_number = -1; /* but does not remove if empty */
       }
@@ -7646,10 +8194,12 @@ static void NormalizeAPub (ValNodePtr vnp, Boolean stripSerial, Boolean fixIniti
         }
       }
       TrimSpacesAroundString (cgp->cit);
+      if (StringDoesHaveText (cgp->title)) {
+        StrStripSpaces (cgp->title);
+      }
       break;
     case PUB_Sub :
       csp = (CitSubPtr) vnp->data.ptrvalue;
-      NormalizeAuthors (csp->authors, fixInitials);
       alp = csp->authors;
       imp = csp->imp;
       if (alp != NULL && alp->affil == NULL && imp != NULL && imp->pub != NULL) {
@@ -7681,36 +8231,43 @@ static void NormalizeAPub (ValNodePtr vnp, Boolean stripSerial, Boolean fixIniti
         }
         alp->affil = CleanAffil (alp->affil);
       }
+      imp = csp->imp;
       break;
     case PUB_Article :
       cap = (CitArtPtr) vnp->data.ptrvalue;
-      NormalizeAuthors (cap->authors, fixInitials);
-      if (cap->from == 2 || cap->from == 3) {
+      if (cap != NULL) {
+        if (cap->from == 1) {
+          cjp = (CitJourPtr) cap->fromptr;
+          if (cjp != NULL) {
+            imp = cjp->imp;
+          }
+        } else if (cap->from == 2 || cap->from == 3) {
         cbp = (CitBookPtr) cap->fromptr;
         if (cbp != NULL) {
-          NormalizeAuthors (cbp->authors, fixInitials);
+            imp = cbp->imp;
+          }
+        }
+        for (ttl = cap->title; ttl != NULL; ttl = ttl->next) {
+          if (ttl->choice == Cit_title_name) {
+            str = (CharPtr) ttl->data.ptrvalue;
+            if (StringHasNoText (str)) continue;
+            StrStripSpaces (str);
         }
       }
-      break;
-    case PUB_Book :
-      cbp = (CitBookPtr) vnp->data.ptrvalue;
-      NormalizeAuthors (cbp->authors, fixInitials);
-      break;
-    case PUB_Man :
-      cbp = (CitBookPtr) vnp->data.ptrvalue;
-      if (cbp->othertype == 2 && cbp->let_type == 3) {
-        NormalizeAuthors (cbp->authors, fixInitials);
       }
-      break;
-    case PUB_Patent :
-      cpp = (CitPatPtr) vnp->data.ptrvalue;
-      NormalizeAuthors (cpp->authors, fixInitials);
-      NormalizeAuthors (cpp->applicants, fixInitials);
-      NormalizeAuthors (cpp->assignees, fixInitials);
       break;
     default :
       break;
   }
+  if (imp != NULL) {
+    CleanVisString (&(imp->volume));
+    CleanVisString (&(imp->issue));
+    CleanVisString (&(imp->pages));
+    CleanVisString (&(imp->section));
+    CleanVisString (&(imp->part_sup));
+    CleanVisString (&(imp->language));
+    CleanVisString (&(imp->part_supi));
+  }
 }
 
 static Boolean IsOnlinePub (PubdescPtr pdp)
@@ -7732,7 +8289,41 @@ static Boolean IsOnlinePub (PubdescPtr pdp)
   return FALSE;
 }
 
-static void NormalizePubdesc (PubdescPtr pdp, Boolean stripSerial, ValNodePtr PNTR publist)
+NLM_EXTERN void CleanUpPubdescAuthors (PubdescPtr pdp)
+
+{
+  Char             buf1 [121];
+  Boolean          fixInitials = TRUE;
+  Boolean          hasArt = FALSE;
+  Boolean          hasUid = FALSE;
+  ValNodePtr       next;
+  ValNodePtr PNTR  prev;
+  ValNodePtr       vnp;
+
+  if (pdp == NULL) return;
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Muid || vnp->choice == PUB_PMid) {
+      if (vnp->data.intvalue > 0) {
+        hasUid = TRUE;
+      }
+    } else if (vnp->choice == PUB_Article) {
+      hasArt = TRUE;
+    }
+  }
+  if (hasArt && hasUid) {
+    fixInitials = FALSE;
+  }
+  prev = &(pdp->pub);
+  vnp = pdp->pub;
+  while (vnp != NULL) {
+    next = vnp->next;
+    PubLabelUnique (vnp, buf1, sizeof (buf1) - 1, OM_LABEL_CONTENT, TRUE);
+    NormalizePubAuthors (vnp, TRUE, fixInitials);
+    vnp = next;
+  }
+}
+
+static void NormalizePubdesc (PubdescPtr pdp, Boolean stripSerial, Boolean doAuthors, ValNodePtr PNTR publist)
 
 {
   ArticleIdPtr     aip;
@@ -7778,7 +8369,9 @@ static void NormalizePubdesc (PubdescPtr pdp, Boolean stripSerial, ValNodePtr PN
     cgp = (CitGenPtr) vnp->data.ptrvalue;
     buf1 [0] = '\0';
     PubLabelUnique (vnp, buf1, sizeof (buf1) - 1, OM_LABEL_CONTENT, TRUE);
+    if (doAuthors) {
     NormalizeAuthors (cgp->authors, fixInitials);
+    }
     if (stripSerial) {
       cgp->serial_number = -1;
     }
@@ -7792,6 +8385,9 @@ static void NormalizePubdesc (PubdescPtr pdp, Boolean stripSerial, ValNodePtr PN
       }
     }
     TrimSpacesAroundString (cgp->cit);
+    if (StringDoesHaveText (cgp->title)) {
+      StrStripSpaces (cgp->title);
+    }
     buf2 [0] = '\0';
     PubLabelUnique (vnp, buf2, sizeof (buf2) - 1, OM_LABEL_CONTENT, TRUE);
     if (StringCmp (buf1, buf2) != 0) {
@@ -7804,6 +8400,9 @@ static void NormalizePubdesc (PubdescPtr pdp, Boolean stripSerial, ValNodePtr PN
     next = vnp->next;
     buf1 [0] = '\0';
     PubLabelUnique (vnp, buf1, sizeof (buf1) - 1, OM_LABEL_CONTENT, TRUE);
+    if (doAuthors) {
+      NormalizePubAuthors (vnp, stripSerial, fixInitials);
+    }
     NormalizeAPub (vnp, stripSerial, fixInitials);
     if (vnp->choice == PUB_Article) {
       cap = (CitArtPtr) vnp->data.ptrvalue;
@@ -7856,6 +8455,13 @@ static void NormalizePubdesc (PubdescPtr pdp, Boolean stripSerial, ValNodePtr PN
   }
 }
 
+NLM_EXTERN void CleanUpPubdescBody (PubdescPtr pdp, Boolean stripSerial)
+
+{
+  if (pdp == NULL) return;
+  NormalizePubdesc (pdp, stripSerial, FALSE, NULL);
+}
+
 static Boolean KeywordAlreadyInList (ValNodePtr head, CharPtr kwd)
 
 {
@@ -8096,6 +8702,107 @@ static void CleanUserFields (
   VisitUserFieldsInUfp (ufp, userdata, CleanUserStrings);
 }
 
+
+static void CleanStructuredComment (
+UserObjectPtr uop
+)
+
+{
+  UserFieldPtr ufp;
+  Int4         len;
+  CharPtr      str, new_str, cp;
+
+  if (uop == NULL || uop->type == NULL 
+      || StringCmp (uop->type->str, "StructuredComment") != 0) {
+    return;
+  }
+
+  for (ufp = uop->data; ufp != NULL; ufp = ufp->next) {
+    if (ufp->label != NULL 
+        && ufp->choice == 1 
+        && (str = (CharPtr) ufp->data.ptrvalue) != NULL) {
+      if (StringCmp (ufp->label->str, "StructuredCommentPrefix") == 0) {
+        len = StringLen (str);
+        if (StringNCmp (str, "##", 2) == 0 && len > 12 && StringCmp (str + len - 12, "Data-START##") == 0) {
+          /* it's ok, no changes necessary */
+        } else {
+          cp = str + len - 1;
+          /* strip trailing pound signs (if present) */
+          while (cp > str && *cp == '#') {
+            *cp = 0;
+            cp--;
+          }
+          /* remove START (if present) */
+          if (cp - str > 4 && StringICmp (cp - 4, "START") == 0) {
+            cp -= 4;
+            *cp = 0;
+            cp--;
+          }
+          /* remove dash (if present) */
+          if (cp > str && *cp == '-') {
+            *cp = 0;
+            cp--;
+          }
+          /* remove Data (if present) */
+          if (cp - str > 3 && StringICmp (cp - 3, "Data") == 0) {
+            cp -= 3;
+            *cp = 0;
+          }
+
+          /* skip leading pound signs */
+          cp = str;
+          while (*cp == '#') {
+            ++cp;
+          }
+          new_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (cp) + 15));
+          sprintf (new_str, "##%sData-START##", cp);
+          str = MemFree (str);
+          ufp->data.ptrvalue = new_str;
+        }
+      } else if (StringCmp (ufp->label->str, "StructuredCommentSuffix") == 0) {
+        len = StringLen (str);
+        if (StringNCmp (str, "##", 2) == 0 && len > 10 && StringCmp (str + len - 10, "Data-END##") == 0) {
+          /* it's ok, no changes necessary */
+        } else {
+          cp = str + len - 1;
+          /* strip trailing pound signs (if present) */
+          while (cp > str && *cp == '#') {
+            *cp = 0;
+            cp--;
+          }
+          /* remove END (if present) */
+          if (cp - str > 2 && StringICmp (cp - 2, "END") == 0) {
+            cp -= 2;
+            *cp = 0;
+            cp--;
+          }
+          /* remove dash (if present) */
+          if (cp > str && *cp == '-') {
+            *cp = 0;
+            cp--;
+          }
+          /* remove Data (if present) */
+          if (cp - str > 3 && StringICmp (cp - 3, "Data") == 0) {
+            cp -= 3;
+            *cp = 0;
+          }
+
+          /* skip leading pound signs */
+          cp = str;
+          while (*cp == '#') {
+            ++cp;
+          }
+          new_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (cp) + 15));
+          sprintf (new_str, "##%sData-END##", cp);
+          str = MemFree (str);
+          ufp->data.ptrvalue = new_str;
+        }
+      }
+    }
+  }
+}
+
+
 static void CleanUserObject (
   UserObjectPtr uop,
   Pointer userdata
@@ -8111,6 +8818,7 @@ static void CleanUserObject (
     }
   }
   VisitUserFieldsInUop (uop, userdata, CleanUserFields);
+  CleanStructuredComment (uop);
 }
 
 static CharPtr bsecSiteList [] = {
@@ -8124,30 +8832,6 @@ static CharPtr bsecSiteList [] = {
   "nitrosylation", NULL
 };
 
-static void StrStripSpaces (
-  CharPtr str
-)
-
-{
-  CharPtr  new_str;
-
-  if (str == NULL) return;
-
-  new_str = str;
-  while (*str != '\0') {
-    *new_str++ = *str;
-    if (*str == ' ' || *str == '\t' || *str == '(') {
-      for (str++; *str == ' ' || *str == '\t'; str++) continue;
-      if (*str == ')' || *str == ',') {
-        new_str--;
-      }
-    } else {
-      str++;
-    }
-  }
-  *new_str = '\0';
-}
-
 static CharPtr uninfStrings [] = {
   "signal",
   "transit",
@@ -8762,13 +9446,11 @@ static void CleanupFeatureStrings (
   BioSourcePtr  biop;
   Char          ch;
   Uint1         codon [6];
-  GBQualPtr     gbq;
   GeneRefPtr    grp;
   ImpFeatPtr    ifp;
   Boolean       is_fMet = FALSE;
   Int2          j;
   Boolean       justTrnaText;
-  GBQualPtr     last;
   size_t        len;
   CharPtr       name;
   OrgNamePtr    onp;
@@ -8785,6 +9467,8 @@ static void CleanupFeatureStrings (
   tRNAPtr       trp;
   CharPtr       val;
   ValNodePtr    vnp;
+  RNAGenPtr     rgp;
+  RNAQualPtr    rqp;
 
   if (sfp == NULL) return;
   CleanVisString (&(sfp->comment));
@@ -8847,6 +9531,7 @@ static void CleanupFeatureStrings (
   }
   if (sfp->data.value.ptrvalue == NULL) return;
 
+  biop = NULL;
   orp = NULL;
   switch (sfp->data.choice) {
     case SEQFEAT_ORG :
@@ -8864,6 +9549,7 @@ static void CleanupFeatureStrings (
     GbqualToOrpMod (&(sfp->qual), &(orp->mod));
   }
 
+  biop = NULL;
   orp = NULL;
   switch (sfp->data.choice) {
     case SEQFEAT_GENE :
@@ -9034,6 +9720,14 @@ static void CleanupFeatureStrings (
                 rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
                 rrp->ext.value.ptrvalue = (Pointer) str;
               }
+            } else if (StringNICmp (name + len - 5, "_rRNA", 5) == 0) {
+              str = MemNew (len + 10);
+              if (str != NULL) {
+                StringNCpy (str, name, len - 5);
+                StringCat (str, " ribosomal RNA");
+                rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+                rrp->ext.value.ptrvalue = (Pointer) str;
+              }
             }
           }
         } else if (rrp->type == 3) {
@@ -9106,6 +9800,21 @@ static void CleanupFeatureStrings (
           }
         }
       }
+      if (rrp->ext.choice == 3) {
+        rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+        if (rgp != NULL) {
+          CleanVisString (&(rgp->product));
+          CleanDoubleQuote (rgp->product);
+          CleanVisString (&(rgp->_class));
+          CleanDoubleQuote (rgp->_class);
+          for (rqp = rgp->quals; rqp != NULL; rqp = rqp->next) {
+            CleanVisString (&(rqp->qual));
+            CleanDoubleQuote (rqp->qual);
+            CleanVisString (&(rqp->val));
+            CleanDoubleQuote (rqp->val);
+          }
+        }
+      }
       if (rrp->ext.choice == 0 && sfp->comment != NULL && rrp->type == 4) {
         len = StringLen (sfp->comment);
         if (len > 15 && len < 20) {
@@ -9319,59 +10028,22 @@ static void CleanupFeatureStrings (
           }
         }
       }
-      if (rrp->type == 255 && rrp->ext.choice == 1) {
-        name = (CharPtr) rrp->ext.value.ptrvalue;
+      if (rrp->type == 255 || rrp->type == 10) {
+        name = GetRNARefProductString (rrp, NULL);
         if (StringICmp (name, "its1") == 0 || StringICmp (name, "its 1") == 0) {
-          rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-          rrp->ext.value.ptrvalue = StringSave ("internal transcribed spacer 1");
-        } else if (StringICmp (name, "its2") == 0 || StringICmp (name, "its 2") == 0) {
-          rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-          rrp->ext.value.ptrvalue = StringSave ("internal transcribed spacer 2");
-        } else if (StringICmp (name, "its3") == 0 || StringICmp (name, "its 3") == 0) {
-          rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-          rrp->ext.value.ptrvalue = StringSave ("internal transcribed spacer 3");
-        }
-
-        name = (CharPtr) rrp->ext.value.ptrvalue;
-        if (StringNICmp (name, "internal transcribed spacer", 27) == 0) {
-          gbq = GBQualNew ();
-          if (gbq != NULL) {
-            rrp->ext.value.ptrvalue = StringSave ("misc_RNA");
-            gbq->qual = StringSave ("product");
-            gbq->val = name;
-            if (sfp->qual == NULL) {
-              sfp->qual = gbq;
-            } else {
-              last = sfp->qual;
-              while (last->next != NULL) {
-                last = last->next;
-              }
-              last->next = gbq;
-            }
-          }
-        }
-
-        for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
-          if (StringCmp (gbq->qual, "product") != 0) continue;
-          name = gbq->val;
-          if (StringHasNoText (name)) continue;
-          if (StringICmp (name, "its1") == 0 || StringICmp (name, "its 1") == 0) {
-            gbq->val = MemFree (gbq->val);
-            gbq->val = StringSave ("internal transcribed spacer 1");
+          SetRNARefProductString (rrp, NULL, "internal transcribed spacer 1", ExistingTextOption_replace_old);
           } else if (StringICmp (name, "its2") == 0 || StringICmp (name, "its 2") == 0) {
-            gbq->val = MemFree (gbq->val);
-            gbq->val = StringSave ("internal transcribed spacer 2");
+          SetRNARefProductString (rrp, NULL, "internal transcribed spacer 2", ExistingTextOption_replace_old);
           } else if (StringICmp (name, "its3") == 0 || StringICmp (name, "its 3") == 0) {
-            gbq->val = MemFree (gbq->val);
-            gbq->val = StringSave ("internal transcribed spacer 3");
-          }
+          SetRNARefProductString (rrp, NULL, "internal transcribed spacer 3", ExistingTextOption_replace_old);
         }
+        name = MemFree (name);
       }
       break;
     case SEQFEAT_PUB :
       pdp = (PubdescPtr) sfp->data.value.ptrvalue;
       CleanDoubleQuote (pdp->comment);
-      NormalizePubdesc (pdp, stripSerial, publist);
+      NormalizePubdesc (pdp, stripSerial, TRUE, publist);
       break;
     case SEQFEAT_SEQ :
       break;
@@ -9419,6 +10091,11 @@ static void CleanupFeatureStrings (
         if (orp != NULL) {
           CleanVisStringList (&(orp->mod));
           OrpModToSubSource (&(orp->mod), &(biop->subtype));
+          onp = orp->orgname;
+          if (onp != NULL) {
+            CleanupOrgModOther (biop, onp);
+            CleanupSubSourceOther (biop, onp);
+          }
         }
         biop->subtype = SortSubSourceList (biop->subtype);
         CleanSubSourceList (&(biop->subtype), biop->genome);
@@ -9469,6 +10146,8 @@ static void CleanupDescriptorStrings (ValNodePtr sdp, Boolean stripSerial, ValNo
       break;
   }
   if (sdp->data.ptrvalue == NULL) return;
+
+  biop = NULL;
   orp = NULL;
   switch (sdp->choice) {
     case Seq_descr_mol_type :
@@ -9530,7 +10209,7 @@ static void CleanupDescriptorStrings (ValNodePtr sdp, Boolean stripSerial, ValNo
     case Seq_descr_pub :
       pdp = (PubdescPtr) sdp->data.ptrvalue;
       CleanDoubleQuote (pdp->comment);
-      NormalizePubdesc (pdp, stripSerial, publist);
+      NormalizePubdesc (pdp, stripSerial, TRUE, publist);
       break;
     case Seq_descr_region :
       CleanVisString ((CharPtr PNTR) &sdp->data.ptrvalue);
@@ -9571,6 +10250,11 @@ static void CleanupDescriptorStrings (ValNodePtr sdp, Boolean stripSerial, ValNo
         if (orp != NULL) {
           CleanVisStringList (&(orp->mod));
           OrpModToSubSource (&(orp->mod), &(biop->subtype));
+          onp = orp->orgname;
+          if (onp != NULL) {
+            CleanupOrgModOther (biop, onp);
+            CleanupSubSourceOther (biop, onp);
+          }
         }
         biop->subtype = SortSubSourceList (biop->subtype);
         CleanSubSourceList (&(biop->subtype), biop->genome);
@@ -9800,7 +10484,7 @@ static void CheckForJournalScanID (SeqEntryPtr sep, Pointer mydata, Int4 index,
   }
 }
 
-static void CleanupSeqLoc (SeqLocPtr slp)
+NLM_EXTERN void CleanUpSeqLoc (SeqLocPtr slp)
 
 {
   BioseqPtr  bsp;
@@ -10177,6 +10861,7 @@ static Boolean ConvertToNcRNA (SeqFeatPtr sfp)
       AddNonCopiedQual (sfp, "product", rrp->ext.value.ptrvalue);
       rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
       rrp->ext.value.ptrvalue = StringSave ("misc_RNA");
+      was_converted = TRUE;
     }
   }
   if (rrp->type == 255 && rrp->ext.choice == 0) {
@@ -10200,7 +10885,7 @@ static Boolean ConvertToNcRNA (SeqFeatPtr sfp)
   return was_converted;
 }
 
-static void ModernizeFeatureStrings (SeqFeatPtr sfp)
+static void ModernizeFeatureStrings (SeqFeatPtr sfp, Boolean isEmblOrDdbj)
 
 {
   CharPtr      desc;
@@ -10230,6 +10915,10 @@ static void ModernizeFeatureStrings (SeqFeatPtr sfp)
     case SEQFEAT_PROT:
       prp = (ProtRefPtr) sfp->data.value.ptrvalue;
       desc = prp->desc;
+      if (! isEmblOrDdbj) {
+        CleanVisStringList (&(prp->name));
+        break;
+      }
       for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
         str = (CharPtr) vnp->data.ptrvalue;
         if (StringHasNoText (str)) continue;
@@ -10344,6 +11033,8 @@ static Boolean IsFeatureCommentRedundant (SeqFeatPtr sfp)
   CharPtr          name;
   ProtRefPtr       prp;
   Uint1            residue;
+  RNAGenPtr        rgp;
+  RNAQualPtr       rqp;
   RnaRefPtr        rrp;
   SeqCodeTablePtr  sctp;
   Uint1            seqcode;
@@ -10512,6 +11203,15 @@ static Boolean IsFeatureCommentRedundant (SeqFeatPtr sfp)
             if (residue == aa) return TRUE;
           }
         }
+      } else if (rrp->ext.choice == 3) {
+        rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+        if (rgp != NULL) {
+          if (StringCmp (comment, rgp->product) == 0) return TRUE;
+          if (StringCmp (comment, rgp->_class) == 0) return TRUE;
+          for (rqp = rgp->quals; rqp != NULL; rqp = rqp->next) {
+            if (StringCmp (comment, rqp->val) == 0) return TRUE;
+          }
+        }
       }
       break;
     default:
@@ -10525,8 +11225,8 @@ static Boolean IsFeatureCommentRedundant (SeqFeatPtr sfp)
 static CharPtr ExtractSatelliteFromComment (CharPtr comment)
 {
   CharPtr satellite_type = NULL, satellite_start = NULL;
-  CharPtr satellite_qual = NULL, end;
-  Int4    satellite_len, len = 0;
+  CharPtr satellite_qual = NULL;
+  Int4    satellite_len, i;
 
   if (StringHasNoText (comment)) {
     return NULL;
@@ -10542,34 +11242,77 @@ static CharPtr ExtractSatelliteFromComment (CharPtr comment)
     satellite_type = "satellite";
     satellite_start = comment;
   }
-  satellite_len = StringLen (satellite_type);
-  if (satellite_start != NULL && (satellite_start == comment || isspace (*(satellite_start - 1)))
-      && !isalpha(*(satellite_start + satellite_len))) {
-    len = StringCSpn (satellite_start, ";,~");
-    end = satellite_start + len;
-    if (*end == 0) {
-      satellite_qual = StringSave (satellite_start);
-      *satellite_start = 0;
-    } else {
-      len = end - satellite_start + 1;
-      satellite_qual = (CharPtr) MemNew (sizeof (Char) * len);
-      StringNCpy (satellite_qual, satellite_start, len - 1);
-      satellite_qual[len - 1] = 0;
-      StringCpy (satellite_start, end + 1);
+
+  if (satellite_start == NULL) {
+    return NULL;
     }
-    if (*(satellite_qual + satellite_len) == ' ') {
-      *(satellite_qual + satellite_len) = ':';
+
+  satellite_len = StringLen (satellite_type);
+  if (comment[satellite_len] == '\0') {
+    satellite_qual = StringSave (satellite_type);
+    *comment = 0;
+  } else if (comment[satellite_len] == ';') {
+    satellite_qual = StringSave (satellite_type);
+    for (i = 0; i <= satellite_len; i++) {
+      comment [i] = ' ';
     }
+    TrimSpacesAroundString (comment);
   }
+
   return satellite_qual;
 }
 
+static void DoModernizeRNAFields (SeqFeatPtr sfp)
+
+{
+  RNAQualSetPtr       nextrqp;
+  RNAQualSetPtr PNTR  prevrqp;
+  RNAGenPtr           rgp;
+  RNAQualSetPtr       rqp;
+  RnaRefPtr           rrp;
+  Boolean             unlink;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return;
+
+  ModernizeRNAFields (sfp);
+  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
+  if (rrp == NULL || rrp->ext.choice != 3) return;
+
+  rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+  if (rgp == NULL) return;
+
+  rqp = rgp->quals;
+  prevrqp = (RNAQualSetPtr PNTR) &(rgp->quals);
+  while (rqp != NULL) {
+    nextrqp = rqp->next;
+    unlink = FALSE;
+    if (StringHasNoText (rqp->qual) || StringHasNoText (rqp->val)) {
+      unlink = TRUE;
+    }
+    if (unlink) {
+      *(prevrqp) = rqp->next;
+      rqp->next = NULL;
+      RNAQualFree (rqp);
+    } else {
+      prevrqp = (RNAQualSetPtr PNTR) &(rqp->next);
+    }
+    rqp = nextrqp;
+  }
+
+  if (rgp->quals != NULL) return;
+  if (StringDoesHaveText (rgp->_class) || StringDoesHaveText (rgp->product)) return;
+
+  rrp->ext.value.ptrvalue = NULL;
+  rrp->ext.choice = 0;
+  RNAGenFree (rgp);
+}
 
 NLM_EXTERN void CleanUpSeqFeat (
   SeqFeatPtr sfp,
   Boolean isEmblOrDdbj,
   Boolean isJscan,
   Boolean stripSerial,
+  Boolean modernizeFeats,
   ValNodePtr PNTR publist
 )
 
@@ -10578,19 +11321,25 @@ NLM_EXTERN void CleanUpSeqFeat (
   CodeBreakPtr  cbp;
   CdRegionPtr   crp;
   GBQualPtr     gbq;
+  Boolean       emptyRNA;
   GeneRefPtr    grp;
   Boolean       hasNulls;
   SeqIdPtr      id;
   ImpFeatPtr    ifp;
+  Int2          j;
+  CharPtr       name;
   Boolean       partial5;
   Boolean       partial3;
   Uint1         processed;
   ProtRefPtr    prp;
   ValNodePtr    psp;
+  RNAGenPtr     rgp;
+  RNAQualPtr    rqp;
   RnaRefPtr     rrp;
   Uint1         rrptype;
   CharPtr       satellite_type;
   SeqIntPtr     sintp;
+  SeqPntPtr     pntp;
   SeqIdPtr      sip;
   SeqLocPtr     slp;
   CharPtr       str;
@@ -10717,6 +11466,50 @@ NLM_EXTERN void CleanUpSeqFeat (
   if (crp != NULL && crp->frame == 0 && (! sfp->pseudo)) {
     crp->frame = GetFrameFromLoc (sfp->location);
   }
+  if (sfp->data.choice == SEQFEAT_RNA) {
+    rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
+    if (rrp != NULL) {
+      if (rrp->ext.choice == 1) {
+        name = (CharPtr) rrp->ext.value.ptrvalue;
+        if (StringHasNoText (name)) {
+          rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+          rrp->ext.choice = 0;
+        }
+      } else if (rrp->ext.choice == 2) {
+        trp = (tRNAPtr) rrp->ext.value.ptrvalue;
+        if (trp != NULL) {
+          if (trp->aatype == 0 && trp->aa == 0 && trp->anticodon == NULL) {
+            emptyRNA = TRUE;
+            for (j = 0; j < 6; j++) {
+              if (trp->codon [j] != 255) {
+                emptyRNA = FALSE;
+              }
+            }
+            if (emptyRNA) {
+              rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+              rrp->ext.choice = 0;
+            }
+          }
+        }
+      } else if (rrp->ext.choice == 3) {
+        rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+        if (rgp != NULL) {
+          if (StringHasNoText (rgp->_class) && StringHasNoText (rgp->product)) {
+            emptyRNA = TRUE;
+            for (rqp = rgp->quals; rqp != NULL; rqp = rqp->next) {
+              if (StringDoesHaveText (rqp->qual) && StringDoesHaveText (rqp->val)) {
+                emptyRNA = FALSE;
+              }
+            } 
+            if (emptyRNA) {
+              rrp->ext.value.ptrvalue = RNAGenFree (rrp->ext.value.ptrvalue);
+              rrp->ext.choice = 0;
+            }
+          }
+        }
+      }
+    }
+  }
   ModernizeFeatureGBQuals (sfp);
   sfp->qual = SortFeatureGBQuals (sfp->qual);
   CleanupDuplicateGBQuals (&(sfp->qual));
@@ -10733,7 +11526,7 @@ NLM_EXTERN void CleanUpSeqFeat (
     psp->data.ptrvalue = ValNodeSort ((ValNodePtr) psp->data.ptrvalue, SortCits);
     CleanupDuplicateCits ((ValNodePtr PNTR) &(psp->data.ptrvalue));
   }
-  CleanupSeqLoc (sfp->location);
+  CleanUpSeqLoc (sfp->location);
   strand = SeqLocStrand (sfp->location);
   id = SeqLocId (sfp->location);
   if (sfp->data.choice == SEQFEAT_GENE) {
@@ -10750,7 +11543,7 @@ NLM_EXTERN void CleanUpSeqFeat (
       crp->code_break = SortCodeBreaks (sfp, crp->code_break);
       CleanupDuplicatedCodeBreaks (&(crp->code_break));
       for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
-        CleanupSeqLoc (cbp->loc);
+        CleanUpSeqLoc (cbp->loc);
         if (strand == Seq_strand_minus && id != NULL) {
           slp = cbp->loc;
           if (slp != NULL && slp->choice == SEQLOC_INT) {
@@ -10776,7 +11569,7 @@ NLM_EXTERN void CleanUpSeqFeat (
     if (rrp != NULL && rrp->ext.choice == 2) {
       trp = (tRNAPtr) rrp->ext.value.ptrvalue;
       if (trp != NULL && trp->anticodon != NULL) {
-        CleanupSeqLoc (trp->anticodon);
+        CleanUpSeqLoc (trp->anticodon);
         if (strand == Seq_strand_minus && id != NULL) {
           slp = trp->anticodon;
           if (slp != NULL && slp->choice == SEQLOC_INT) {
@@ -10809,13 +11602,30 @@ NLM_EXTERN void CleanUpSeqFeat (
               sintp->strand = Seq_strand_unknown;
             }
           }
+        } else if (slp->choice == SEQLOC_PNT) {
+          pntp = (SeqPntPtr) slp->data.ptrvalue;
+          if (pntp->strand != Seq_strand_unknown) {
+            pntp->strand = Seq_strand_unknown;
+          }
         }
         slp = SeqLocFindNext (sfp->location, slp);
       }
     }
   }
 
-  ModernizeFeatureStrings (sfp);
+  ModernizeFeatureStrings (sfp, isEmblOrDdbj);
+
+  if (sfp->data.choice == SEQFEAT_GENE) {
+    if (modernizeFeats) {
+      ModernizeGeneFields (sfp);
+    }
+  }
+
+  if (sfp->data.choice == SEQFEAT_RNA) {
+    if (modernizeFeats) {
+      DoModernizeRNAFields (sfp);
+    }
+  }
 
   if (IsFeatureCommentRedundant (sfp)) {
     sfp->comment = MemFree (sfp->comment);
@@ -10847,12 +11657,13 @@ NLM_EXTERN void CleanUpSeqFeat (
   }
 }
 
+
 static void CleanUpSeqGraph (SeqGraphPtr sgp)
 
 {
   if (sgp == NULL) return;
   if (sgp->loc != NULL) {
-    CleanupSeqLoc (sgp->loc);
+    CleanUpSeqLoc (sgp->loc);
   }
 }
 
@@ -11073,7 +11884,7 @@ static void BasicSeqEntryCleanupInternal (
     if (sap->type == 1) {
       sfp = (SeqFeatPtr) sap->data;
       while (sfp != NULL) {
-        CleanUpSeqFeat (sfp, isEmblOrDdbj, isJscan, stripSerial, publist);
+        CleanUpSeqFeat (sfp, isEmblOrDdbj, isJscan, stripSerial, TRUE, publist);
         sfp = sfp->next;
       }
     } else if (sap->type == 3) {
@@ -11453,6 +12264,31 @@ static void UpdateShortFeatCits (SeqFeatPtr sfp, Pointer userdata)
   }
 }
 
+NLM_EXTERN void BasicSeqAnnotCleanup (SeqAnnotPtr sap)
+
+{
+  SeqFeatPtr   sfp;
+  SeqGraphPtr  sgp;
+
+  if (sap == NULL) return;
+
+  VisitSeqIdsInSeqAnnot (sap, NULL, CleanUpSeqId);
+
+  if (sap->type == 1) {
+    sfp = (SeqFeatPtr) sap->data;
+    while (sfp != NULL) {
+      CleanUpSeqFeat (sfp, FALSE, FALSE, TRUE, TRUE, NULL);
+      sfp = sfp->next;
+    }
+  } else if (sap->type == 3) {
+    sgp = (SeqGraphPtr) sap->data;
+    while (sgp != NULL) {
+      CleanUpSeqGraph (sgp);
+      sgp = sgp->next;
+    }
+  }
+}
+
 NLM_EXTERN void BasicSeqEntryCleanup (SeqEntryPtr sep)
 
 {
@@ -11551,6 +12387,70 @@ NLM_EXTERN void BasicSeqEntryCleanup (SeqEntryPtr sep)
   }
 }
 
+static void SortSeqFeatFields (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  CdRegionPtr  crp;
+  ValNodePtr   psp;
+
+  if (sfp == NULL) return;
+
+  sfp->qual = SortFeatureGBQuals (sfp->qual);
+
+  sfp->qual = SortIllegalGBQuals (sfp->qual);
+
+  sfp->dbxref = ValNodeSort (sfp->dbxref, SortDbxref);
+
+  psp = sfp->cit;
+  if (psp != NULL && psp->data.ptrvalue) {
+    psp->data.ptrvalue = ValNodeSort ((ValNodePtr) psp->data.ptrvalue, SortCits);
+  }
+
+  if (sfp->data.choice == SEQFEAT_CDREGION) {
+    crp = (CdRegionPtr) sfp->data.value.ptrvalue;
+    if (crp != NULL) {
+      crp->code_break = SortCodeBreaks (sfp, crp->code_break);
+    }
+  }
+}
+
+static void SortBioSourceFields (
+  BioSourcePtr biop,
+  Pointer userdata
+)
+
+{
+  OrgNamePtr  onp;
+  OrgRefPtr   orp;
+
+  if (biop == NULL) return;
+
+  orp = biop->org;
+  if (orp != NULL) {
+    orp->db = ValNodeSort (orp->db, SortDbxref);
+
+    for (onp = orp->orgname; onp != NULL; onp = onp->next) {
+      onp->mod = SortOrgModList (onp->mod);
+    }
+  }
+
+  biop->subtype = SortSubSourceList (biop->subtype);
+}
+
+NLM_EXTERN void SortSeqEntryQualifiers (
+  SeqEntryPtr sep
+)
+
+{
+  if (sep == NULL) return;
+
+  VisitFeaturesInSep (sep, NULL, SortSeqFeatFields);
+  VisitBioSourcesInSep (sep, NULL, SortBioSourceFields);
+}
+
 /* end BasicSeqEntryCleanup section */
 
 NLM_EXTERN void ResynchCDSPartials (SeqFeatPtr sfp, Pointer userdata)
@@ -11565,6 +12465,10 @@ NLM_EXTERN void ResynchCDSPartials (SeqFeatPtr sfp, Pointer userdata)
   SeqIdPtr     sip;
   SeqLocPtr    slp;
   ValNodePtr   vnp;
+  /* variables for logging */
+  LogInfoPtr    lip;
+  CharPtr orig_loc = NULL, new_loc;
+  Char    id_buf[100];
 
   if (sfp->data.choice != SEQFEAT_CDREGION) return;
   CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
@@ -11574,19 +12478,37 @@ NLM_EXTERN void ResynchCDSPartials (SeqFeatPtr sfp, Pointer userdata)
   sip = SeqLocId (sfp->product);
   if (sip == NULL) return;
   bsp = BioseqFind (sip);
-  if (bsp != NULL && ISA_aa (bsp->mol) && bsp->repr == Seq_repr_raw) {
+  if (bsp == NULL || !ISA_aa (bsp->mol) || bsp->repr != Seq_repr_raw) return;
+
     bestprot = SeqMgrGetBestProteinFeature (bsp, NULL);
     if (bestprot == NULL) {
       bestprot = GetBestProteinFeatureUnindexed (sfp->product);
     }
-    if (bestprot != NULL) {
+  if (bestprot == NULL) return;
+
       sep = SeqMgrGetSeqEntryForData (bsp);
       if (sep == NULL) return;
+
+  if ((lip = (LogInfoPtr)userdata) != NULL) {
+    orig_loc = SeqLocPrintUseBestID (bestprot->location);
+  }
       bestprot->location = SeqLocFree (bestprot->location);
       bestprot->location = CreateWholeInterval (sep);
       SetSeqLocPartial (bestprot->location, partial5, partial3);
       bestprot->partial = (partial5 || partial3);
+  if (lip != NULL) {
+    new_loc = SeqLocPrintUseBestID (bestprot->location);
+    if (StringCmp (orig_loc, new_loc) != 0) {
+      lip->data_in_log = TRUE;
+      if (lip->fp != NULL) {
+        fprintf (lip->fp, "Adjusted protein feature location from %s to %s\n", orig_loc, new_loc);
+      }
+    }
+    new_loc = MemFree (new_loc);
+  }
+  orig_loc = MemFree (orig_loc);
       vnp = SeqEntryGetSeqDescr (sep, Seq_descr_molinfo, NULL);
+  id_buf[0] = 0;
       if (vnp == NULL) {
         vnp = CreateNewDescriptor (sep, Seq_descr_molinfo);
         if (vnp != NULL) {
@@ -11595,6 +12517,13 @@ NLM_EXTERN void ResynchCDSPartials (SeqFeatPtr sfp, Pointer userdata)
           if (mip != NULL) {
             mip->biomol = 8; /* peptide */
             mip->tech = 13; /* concept-trans-author */
+        if (lip != NULL) {
+          if (lip->fp != NULL) {
+            SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_buf, PRINTID_FASTA_SHORT, sizeof (id_buf) - 1);
+            fprintf (lip->fp, "Added MolInfo descriptor for %s\n", id_buf);
+          }
+          lip->data_in_log = TRUE;
+        }
           }
         }
       }
@@ -11602,17 +12531,55 @@ NLM_EXTERN void ResynchCDSPartials (SeqFeatPtr sfp, Pointer userdata)
         mip = (MolInfoPtr) vnp->data.ptrvalue;
         if (mip != NULL) {
           if (partial5 && partial3) {
+        if (mip->completeness != 5) {
             mip->completeness = 5;
+          if (lip != NULL) {
+            if (lip->fp != NULL) {
+              if (id_buf[0] == 0) {
+                SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_buf, PRINTID_FASTA_SHORT, sizeof (id_buf) - 1);
+              }
+              fprintf (lip->fp, "Adjusted completeness for MolInfo descriptor on %s\n", id_buf);
+              lip->data_in_log = TRUE;
+            }
+          }
+        }
           } else if (partial5) {
+        if (mip->completeness != 3) {
             mip->completeness = 3;
+          if (lip != NULL) {
+            if (lip->fp != NULL) {
+              if (id_buf[0] == 0) {
+                SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_buf, PRINTID_FASTA_SHORT, sizeof (id_buf) - 1);
+              }
+              fprintf (lip->fp, "Adjusted completeness for MolInfo descriptor on %s\n", id_buf);
+            }
+            lip->data_in_log = TRUE;
+          }
+        }
           } else if (partial3) {
+        if (mip->completeness != 4) {
             mip->completeness = 4;
-          /*
-          } else if (partial) {
-            mip->completeness = 2;
-          */
+          if (lip != NULL) {
+            if (lip->fp != NULL) {
+              if (id_buf[0] == 0) {
+                SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_buf, PRINTID_FASTA_SHORT, sizeof (id_buf) - 1);
+              }
+              fprintf (lip->fp, "Adjusted completeness for MolInfo descriptor on %s\n", id_buf);
+            }
+            lip->data_in_log = TRUE;
+          }
+        }
           } else {
+        if (mip->completeness != 0) {
             mip->completeness = 0;
+          if (lip != NULL) {
+            if (lip->fp != NULL) {
+              if (id_buf[0] == 0) {
+                SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_buf, PRINTID_FASTA_SHORT, sizeof (id_buf) - 1);
+              }
+              fprintf (lip->fp, "Adjusted completeness for MolInfo descriptor on %s\n", id_buf);
+            }
+            lip->data_in_log = TRUE;
           }
         }
       }
@@ -11620,12 +12587,24 @@ NLM_EXTERN void ResynchCDSPartials (SeqFeatPtr sfp, Pointer userdata)
   }
 }
 
+
+NLM_EXTERN Boolean ResynchCodingRegionPartialsEx (SeqEntryPtr sep, FILE *log_fp)
+
+{
+  LogInfoData lid;
+  MemSet (&lid, 0, sizeof (LogInfoData));
+  lid.fp = log_fp;
+  VisitFeaturesInSep (sep, &lid, ResynchCDSPartials);
+  return lid.data_in_log;
+}
+
 NLM_EXTERN void ResynchCodingRegionPartials (SeqEntryPtr sep)
 
 {
-  VisitFeaturesInSep (sep, NULL, ResynchCDSPartials);
+  ResynchCodingRegionPartialsEx (sep, NULL);
 }
 
+
 NLM_EXTERN void ResynchMRNAPartials (SeqFeatPtr sfp, Pointer userdata)
 
 {
@@ -14541,6 +15520,14 @@ NLM_EXTERN int LIBCALL OrgNameCompare (OrgNamePtr onp1, OrgNamePtr onp2)
     {
       rval = 1;
     }
+    else if (onp1->pgcode < onp2->pgcode)
+    {
+      rval = -1;
+    } 
+    else if (onp1->pgcode > onp2->pgcode)
+    {
+      rval = 1;
+    }
     onp1 = onp1->next;
     onp2 = onp2->next;
   }
@@ -14802,6 +15789,8 @@ static Boolean DoLocationsMatch (SeqLocPtr slp1, SeqLocPtr slp2, Boolean allow_d
         return FALSE;
       }
     }
+  } else if (SeqLocCompare (slp1, slp2) != SLC_A_EQ_B) {
+    return FALSE;
   }
   return TRUE;
 }
@@ -14855,3 +15844,275 @@ NLM_EXTERN Boolean DoFeaturesMatch (SeqFeatPtr sfp1, SeqFeatPtr sfp2, Boolean al
 }
 
 
+NLM_EXTERN void CleanupStringsForOneDescriptor (SeqDescPtr sdp, SeqEntryPtr sep)
+{
+  Boolean stripSerial = FALSE;
+  Boolean isEmblOrDdbj = FALSE;
+
+  if (sdp == NULL) {
+    return;
+  }
+  SeqEntryExplore (sep, (Pointer) &stripSerial, CheckForSwissProtID);
+  SeqEntryExplore (sep, (Pointer) &isEmblOrDdbj, CheckForEmblDdbjID);
+
+  if (sdp->choice == Seq_descr_pub) {
+    FlattenPubdesc (sdp->data.ptrvalue, NULL);
+  }
+
+  CleanupDescriptorStrings (sdp, stripSerial, NULL, isEmblOrDdbj);
+}
+
+
+
+NLM_EXTERN void CleanupOneSeqFeat (SeqFeatPtr sfp)
+{
+  Boolean           isEmblOrDdbj = FALSE;
+  Boolean           isJscan = FALSE;
+  Boolean           stripSerial = TRUE;
+  ValNodePtr        publist = NULL;
+  SeqEntryPtr       sep;
+
+  if (sfp->idx.entityID == 0) {
+    return;
+  }
+  sep = GetTopSeqEntryForEntityID (sfp->idx.entityID);
+
+  SeqEntryExplore (sep, (Pointer) &stripSerial, CheckForSwissProtID);
+  SeqEntryExplore (sep, (Pointer) &isEmblOrDdbj, CheckForEmblDdbjID);
+  SeqEntryExplore (sep, (Pointer) &isJscan, CheckForJournalScanID);
+  FlattenSfpCit (sfp, NULL);
+  CleanUpSeqFeat (sfp, isEmblOrDdbj, isJscan, stripSerial, TRUE, &publist);
+
+  if (publist != NULL) {
+   ChangeCitsOnFeats (sfp, publist);
+  }
+  ValNodeFreeData (publist);
+}
+
+/* special cases for chloroplast genetic code until implemented in taxonomy database */
+
+typedef struct pgorg {
+  CharPtr  organism;
+  Uint1    pgcode;
+} PgOrg;
+
+static PgOrg pgOrgList [] = {
+  { "Chromera velia", 4 } ,
+  { NULL, 0 }
+};
+
+typedef struct pglin {
+  CharPtr  lineage;
+  Uint1    pgcode;
+} PgLin;
+
+static PgLin pgLinList [] = {
+  { "Eukaryota; Alveolata; Apicomplexa; Coccidia; ", 4 } ,
+  { NULL, 0 }
+};
+
+NLM_EXTERN Uint1 GetSpecialPlastidGenCode (
+  CharPtr taxname,
+  CharPtr lineage
+)
+
+{
+  Int2    i;
+  size_t  max;
+  Uint1   pgcode = 0;
+
+  if (StringDoesHaveText (taxname)) {
+    for (i = 0; pgOrgList [i].organism != NULL; i++) {
+      if (StringICmp (taxname, pgOrgList [i].organism) != 0) continue;
+      pgcode = pgOrgList [i].pgcode;
+    }
+  }
+
+  if (StringDoesHaveText (lineage)) {
+    for (i = 0; pgLinList [i].lineage != NULL; i++) {
+      max = StringLen (pgLinList [i].lineage);
+      if (StringNICmp (lineage, pgLinList [i].lineage, max) != 0) continue;
+      pgcode = pgLinList [i].pgcode;
+    }
+  }
+
+  if (pgcode == 11) {
+    pgcode = 0;
+  }
+
+  return pgcode;
+}
+
+
+static void TrimStopsFromCompleteCodingRegionsCallback (SeqFeatPtr sfp, Pointer data)
+{
+  Boolean p5, p3;
+  BioseqPtr protbsp;
+  CharPtr   prot_str;
+  Int4      len;
+  /* variables for shortening protein features */
+  SeqFeatPtr        prot_sfp;
+  SeqMgrFeatContext fcontext;
+  SeqIntPtr         sintp;
+  /* variables for logging */
+  LogInfoPtr lip;
+  Char      id_buf[100];
+  
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION || sfp->product == NULL) {
+    return;
+  }
+
+  CheckSeqLocForPartial (sfp->location, &p5, &p3);
+  if (p3) {
+    return;
+  }
+
+  protbsp = BioseqFindFromSeqLoc (sfp->product);
+  if (protbsp == NULL) {
+    return;
+  }
+
+  prot_str = GetSequenceByBsp (protbsp);
+  if (prot_str == NULL || (len = StringLen (prot_str)) == 0
+      || prot_str[len - 1] != '*') {
+    prot_str = MemFree (prot_str);
+    return;
+  }
+
+  BSSeek ((ByteStorePtr) protbsp->seq_data, -1, SEEK_END);
+  BSDelete ((ByteStorePtr) protbsp->seq_data, 1);
+  protbsp->length -= 1;
+  prot_str = MemFree (prot_str);
+
+  for (prot_sfp = SeqMgrGetNextFeature (protbsp, NULL, 0, 0, &fcontext);
+       prot_sfp != NULL;
+       prot_sfp = SeqMgrGetNextFeature (protbsp, prot_sfp, 0, 0, &fcontext)) {
+    if (prot_sfp->location != NULL
+        && prot_sfp->location->choice == SEQLOC_INT 
+        && (sintp = (SeqIntPtr)prot_sfp->location->data.ptrvalue) != NULL) {
+      if (sintp->to > protbsp->length - 1) {
+        sintp->to = protbsp->length - 1;
+      }
+    }
+  }
+
+  lip = (LogInfoPtr) data;
+  if (lip != NULL) {
+    if (lip->fp != NULL) {
+      SeqIdWrite (SeqIdFindBest (protbsp->id, SEQID_GENBANK), id_buf, PRINTID_FASTA_SHORT, sizeof (id_buf) - 1);
+      fprintf (lip->fp, "Trimmed trailing * from %s\n", id_buf);
+    }
+    lip->data_in_log = TRUE;
+  }
+}
+
+
+NLM_EXTERN Boolean TrimStopsFromCompleteCodingRegions (SeqEntryPtr sep, FILE *log_fp)
+{
+  LogInfoData lid;
+  MemSet (&lid, 0, sizeof (LogInfoData));
+  lid.fp = log_fp;
+  VisitFeaturesInSep (sep, &lid, TrimStopsFromCompleteCodingRegionsCallback);
+  return lid.data_in_log;
+}
+
+
+NLM_EXTERN void 
+FixCapitalizationInTitle 
+(CharPtr PNTR pTitle,
+ Boolean      first_is_upper,
+ ValNodePtr   org_names)
+{
+  if (pTitle == NULL) return;
+  ResetCapitalization (first_is_upper, *pTitle);
+  FixAbbreviationsInElement (pTitle);
+  FixOrgNamesInString (*pTitle, org_names);
+}
+
+
+typedef struct structuredcommentconversion {
+  Int4 num_converted;
+  Int4 num_unable_to_convert;
+} StructuredCommentConversionData, PNTR StructuredCommentConversionPtr;
+
+static void CommentWithSpacesToStructuredCommentCallback (SeqDescPtr sdp, Pointer userdata)
+{
+  UserObjectPtr uop;
+  CharPtr       str, start, stop;
+  Int4          len;
+  UserFieldPtr  ufp = NULL, prev_ufp = NULL;
+  StructuredCommentConversionPtr sd;
+
+  if (sdp == NULL || sdp->choice != Seq_descr_comment || StringHasNoText (sdp->data.ptrvalue)) {
+    return;
+  }
+
+  uop = UserObjectNew ();
+  uop->type = ObjectIdNew ();
+  uop->type->str = StringSave ("StructuredComment");
+
+  start = sdp->data.ptrvalue;
+  while (*start != 0) {
+    stop = start + StringCSpn (start, " ~");
+    while (*stop != 0 && *stop != '~' && !isspace (*(stop + 1)) && *(stop + 1) != 0) {
+      stop = stop + 1 + StringCSpn (stop + 1, " ~");
+    }
+    len = 1 + stop - start;
+    str = (CharPtr) MemNew (sizeof (Char) * len);
+    StringNCpy (str, start, len - 1);
+    str[len - 1] = 0;
+    if (ufp == NULL) {
+      /* add new field */
+      ufp = UserFieldNew ();
+      if (prev_ufp == NULL) {
+        uop->data = ufp;
+      } else {
+        prev_ufp->next = ufp;
+      }
+      ufp->label = ObjectIdNew ();
+      ufp->label->str = str;
+    } else {
+      /* add value to last field */
+      ufp->choice = 1;
+      ufp->data.ptrvalue = str;
+      prev_ufp = ufp;
+      ufp = NULL;
+    }
+    if (*stop == 0) {
+      start = stop;
+    } else {
+      start = stop + 1 + StringSpn (stop + 1, " ");
+    }
+  }
+
+  if (prev_ufp == NULL) {
+    uop = UserObjectFree (uop);
+    return;
+  }
+  sd = (StructuredCommentConversionPtr) userdata;
+  if (ufp == NULL) {
+    sdp->data.ptrvalue = MemFree (sdp->data.ptrvalue);
+    sdp->data.ptrvalue = uop;
+    sdp->choice = Seq_descr_user;
+    if (sd != NULL) {
+      sd->num_converted++;
+    }
+  } else {
+    uop = UserObjectFree (uop);
+    if (sd != NULL) {
+      sd->num_unable_to_convert++;
+    }
+  }
+}
+
+
+NLM_EXTERN Int4 ConvertCommentsWithSpacesToStructuredCommentsForSeqEntry (SeqEntryPtr sep)
+{
+  StructuredCommentConversionData sd;
+  
+  MemSet (&sd, 0, sizeof (StructuredCommentConversionData));
+  VisitDescriptorsInSep (sep, &sd, CommentWithSpacesToStructuredCommentCallback);
+
+  return sd.num_unable_to_convert;
+}
+
diff --git a/api/sqnutil2.c b/api/sqnutil2.c
index f768aed..1f966f3 100644
--- a/api/sqnutil2.c
+++ b/api/sqnutil2.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   9/2/97
 *
-* $Revision: 6.392 $
+* $Revision: 6.439 $
 *
 * File Description: 
 *
@@ -57,6 +57,13 @@
 #include <findrepl.h>
 #include <alignmgr2.h>
 #include <alignval.h>
+#include <objvalid.h>
+#include <valapi.h>
+#define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
+#include <macroapi.h>
+
+#include <utilpub.h>
 
 static CharPtr SqnTrimSpacesAroundString (CharPtr str)
 
@@ -463,6 +470,7 @@ static SeqLocRangePtr CollectRanges (BioseqPtr target, SeqLocPtr slp)
   SeqLocRangePtr  slrp;
   Uint1           strand;
   Boolean         is_circular;
+  Boolean         left_flip = FALSE, right_flip = FALSE;
 
   if (target == NULL) return NULL;
   head = NULL;
@@ -472,14 +480,14 @@ static SeqLocRangePtr CollectRanges (BioseqPtr target, SeqLocPtr slp)
     if (curr->choice != SEQLOC_NULL) {
       is_circular = IsLocationOnCircularBioseq (curr);
 #if 1
-      GetLeftAndRightOffsetsInBioseq (curr, target, &left, &right, is_circular);
+      GetLeftAndRightOffsetsInBioseq (curr, target, &left, &right, is_circular, &left_flip, &right_flip);
 #else
       left = GetOffsetInBioseqEx (curr, target, SEQLOC_LEFT_END, is_circular);
       right = GetOffsetInBioseqEx (curr, target, SEQLOC_RIGHT_END, is_circular);
 #endif
       strand = SeqLocStrand (curr);
       /* left > right if within a minus strand delta seq component, flip strand here */
-      if (left > right) {
+      if (left > right || left_flip || right_flip) {
         if (strand == Seq_strand_minus) {
           strand = Seq_strand_plus;
         } else {
@@ -510,7 +518,7 @@ static SeqLocRangePtr CollectRanges (BioseqPtr target, SeqLocPtr slp)
   }
   if (head == NULL || target->topology != TOPOLOGY_CIRCULAR) return head;
 #if 1
-  GetLeftAndRightOffsetsInBioseq (slp, target, &left, &right, target->topology == TOPOLOGY_CIRCULAR);
+  GetLeftAndRightOffsetsInBioseq (slp, target, &left, &right, target->topology == TOPOLOGY_CIRCULAR, &left_flip, &right_flip);
 #else
   left = GetOffsetInBioseqEx (slp, target, SEQLOC_LEFT_END, target->topology == TOPOLOGY_CIRCULAR);
   right = GetOffsetInBioseqEx (slp, target, SEQLOC_RIGHT_END, target->topology == TOPOLOGY_CIRCULAR);
@@ -1735,6 +1743,23 @@ NLM_EXTERN CharPtr SqnTagFind (SqnTagPtr stp, CharPtr tag)
 }
 
 
+NLM_EXTERN ValNodePtr SqnTagFindMultiple (SqnTagPtr stp, CharPtr tag)
+
+{
+  Int2  i;
+  ValNodePtr list = NULL;
+
+  if (stp == NULL || StringHasNoText (tag)) return NULL;
+  for (i = 0; i < stp->num_tags; i++) {
+    if (stp->tag [i] != NULL && StringsAreEquivalent (stp->tag [i], tag)) {
+      stp->used [i] = TRUE;
+      ValNodeAddPointer (&list, 0, stp->val[i]);
+    }
+  }
+  return list;
+}
+
+
 NLM_EXTERN CharPtr SqnTagFindUnused (SqnTagPtr stp, CharPtr tag)
 
 {
@@ -1867,7 +1892,8 @@ NLM_EXTERN BioSourcePtr ParseTitleIntoBioSource (
   SubSourcePtr  ssp;
   CharPtr       str;
   int           val;
-  ValNodePtr    vnp;
+  ValNodePtr    vnp, list, list_vnp;
+
 
   if ((stp == NULL || stp->num_tags == 0) && StringHasNoText (organism)) return biop;
 
@@ -1942,14 +1968,9 @@ NLM_EXTERN BioSourcePtr ParseTitleIntoBioSource (
 
   SqnTagFindSubSourceQuals (stp, biop);
 
-  str = SqnTagFind (stp, "db_xref");
-  if (str == NULL) {
-    str = SqnTagFind (stp, "db-xref");
-  }
-  if (str == NULL) {
-    str = SqnTagFind (stp, "dbxref");
-  }
-  if (str != NULL) {
+  list = SqnTagFindMultiple (stp, "db_xref");
+  for (list_vnp = list; list_vnp != NULL; list_vnp = list_vnp->next) {
+    str = list_vnp->data.ptrvalue;
     vnp = ValNodeNew (NULL);
     db = DbtagNew ();
     vnp->data.ptrvalue = db;
@@ -1970,6 +1991,7 @@ NLM_EXTERN BioSourcePtr ParseTitleIntoBioSource (
     vnp->next = orp->db;
     orp->db = vnp;
   }
+  list = ValNodeFree (list);
 
   str = SqnTagFind (stp, "division");
   if (str == NULL) {
@@ -1996,6 +2018,11 @@ NLM_EXTERN BioSourcePtr ParseTitleIntoBioSource (
     onp->mgcode = (Uint1) val; /* mitochondrial */
   }
 
+  str = SqnTagFind (stp, "pgcode");
+  if (str != NULL && sscanf (str, "%d", &val) == 1) {
+    onp->pgcode = (Uint1) val; /* plastid */
+  }
+
   str = SqnTagFind (stp, "note");
   if (str == NULL) {
     str = SqnTagFind (stp, "notes");
@@ -2608,6 +2635,42 @@ NLM_EXTERN SeqHistPtr ParseTitleIntoSeqHist (
   return shp;
 }
 
+NLM_EXTERN void ParseTitleIntoSubmitBlock (
+  SqnTagPtr stp,
+  SubmitBlockPtr sbp
+)
+
+{
+  DatePtr  dp;
+  CharPtr  str;
+
+  if (stp == NULL || sbp == NULL) return;
+
+  str = SqnTagFind (stp, "hup");
+  if (str != NULL) {
+    sbp->hup = FALSE;
+    sbp->reldate = DateFree (sbp->reldate);
+    if (StringDoesHaveText (str)) {
+      if (StringICmp (str, "y") == 0) {
+        sbp->hup = TRUE;
+        dp = DateCurr ();
+        sbp->reldate = dp;
+        if (dp != NULL) {
+          if (dp->data [0] == 1) {
+            (dp->data [1])++;
+          }
+        }
+      } else {
+        dp = DateParse (str);
+        if (dp != NULL) {
+          sbp->hup = TRUE;
+          sbp->reldate = dp;
+        }
+      }
+    }
+  }
+}
+
 NLM_EXTERN UserObjectPtr ParseTitleIntoTpaAssembly (
   SqnTagPtr stp,
   UserObjectPtr uop
@@ -5113,11 +5176,10 @@ static Uint1 ParseCodon (CharPtr str)
 }
 */
 
-extern Boolean ParseCodeBreak (SeqFeatPtr sfp, CharPtr val, Int4 offset);
 extern Boolean ParseAnticodon (SeqFeatPtr sfp, CharPtr val, Int4 offset);
 
 static CharPtr orgRefList [] = {
-  "", "organism", "mitochondrion", "div", "lineage", "gcode", "mgcode", NULL
+  "", "organism", "mitochondrion", "div", "lineage", "gcode", "mgcode", "pgcode", NULL
 };
 
 static OrgNamePtr GetOrMakeOnp (OrgRefPtr orp)
@@ -5191,6 +5253,13 @@ static Boolean ParseQualIntoBioSource (SeqFeatPtr sfp, CharPtr qual, CharPtr val
           onp->mgcode = (Uint1) num;
         }
         break;
+      case 7 :
+        onp = GetOrMakeOnp (orp);
+        if (onp == NULL) return FALSE;
+        if (sscanf (val, "%d", &num) == 1) {
+          onp->pgcode = (Uint1) num;
+        }
+        break;
       default :
         break;
     }
@@ -7345,7 +7414,9 @@ static SeqAnnotPtr ReadRestrictionSiteTable (FileCachePtr fcp, CharPtr seqid, Ch
             }
           }
 
+          if (sfp != NULL) {
           sfp->location = AddPointToLocation (sfp->location, sip, pt);
+          }
 
         }
 
@@ -7521,6 +7592,2247 @@ static ByteStorePtr ReadUidList (FileCachePtr fcp, Boolean nucdb, Boolean lastRe
   return bs;
 }
 
+
+static Boolean DoesBioseqAccessionMatchList (BioseqPtr bsp, ValNodePtr accn_list)
+{
+  ValNodePtr vnp, vnp_m;
+  ValNodePtr match_list = NULL;
+  SeqIdPtr   sip, sip_next;
+  CharPtr    id, cp;
+  Boolean    found_match = FALSE;
+  DbtagPtr   dbtag;
+
+  if (bsp == NULL) {
+    return FALSE;
+  }
+
+  /* note - in match_list, 1 indicates that memory needs to be freed, 0 not */
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    sip_next = sip->next;
+    sip->next = NULL;
+    id = SeqIdWholeLabel (sip, PRINTID_FASTA_LONG);
+    sip->next = sip_next;
+    if (id != NULL) {
+      /* remove terminating pipe character */
+      if (id[StringLen(id) - 1] == '|') 
+      {
+        id[StringLen(id) - 1] = 0;
+      }
+      ValNodeAddPointer(&match_list, 1, id);
+
+      /* remove leading pipe identifier */
+      cp = StringChr (id, '|');
+      if (cp != NULL)
+      {
+        cp = cp + 1;
+        ValNodeAddPointer (&match_list, 0, cp);
+      } else {
+        cp = id;
+      }
+
+      /* try ID without version */
+      id = StringSave (cp);
+      cp = StringChr (id, '.');
+      if (cp != NULL) 
+      {
+        *cp = 0;
+        ValNodeAddPointer (&match_list, 1, id);
+      } else {
+        id = MemFree (id);
+      }
+
+      /* just bankit number */
+      if (sip->choice == SEQID_GENERAL 
+          && (dbtag = (DbtagPtr) sip->data.ptrvalue) != NULL) {
+        if (StringCmp (dbtag->db, "BankIt") == 0) {
+          if (dbtag->tag->str != NULL) {
+            ValNodeAddPointer (&match_list, 0, dbtag->tag->str);
+          }
+        } else if (StringCmp (dbtag->db, "NCBIFILE") == 0 && dbtag->tag != NULL) {
+          ValNodeAddPointer (&match_list, 0, dbtag->tag->str);
+          if ((cp = StringRChr (dbtag->tag->str, '/')) != NULL) {
+            ValNodeAddPointer (&match_list, 0, cp + 1);
+          }
+        }
+      }
+    }
+  }
+
+  for (vnp = accn_list; vnp != NULL && !found_match; vnp = vnp->next) {
+    for (vnp_m = match_list; vnp_m != NULL && !found_match; vnp_m = vnp_m->next) {
+      if (StringICmp (vnp->data.ptrvalue, vnp_m->data.ptrvalue) == 0) {
+        found_match = TRUE;
+      }
+    }
+  }
+
+  /* special free for match_list */
+  vnp = ValNodeExtractList (&match_list, 1);
+  vnp = ValNodeFreeData (vnp);
+  match_list = ValNodeFree (match_list);
+
+  return found_match;
+}
+
+
+static Boolean DoesBioseqSetAccessionMatchList (BioseqSetPtr bssp, ValNodePtr accn_list)
+{
+  BioseqPtr bsp;
+  Boolean   rval = FALSE;
+
+  if (bssp != NULL && bssp->_class == BioseqseqSet_class_nuc_prot
+    && bssp->seq_set != NULL && IS_Bioseq (bssp->seq_set)) {
+    bsp = bssp->seq_set->data.ptrvalue;
+    rval = DoesBioseqAccessionMatchList(bsp, accn_list);
+  }
+  return rval;
+}
+
+
+static Boolean DoesSeqEntryAccessionMatchList (SeqEntryPtr sep, ValNodePtr accn_list)
+{
+  BioseqPtr    bsp;
+  BioseqSetPtr bssp;
+  Boolean      rval = FALSE;
+
+  if (sep == NULL) {
+    return FALSE;
+  }
+
+  if (IS_Bioseq (sep)) {
+    bsp = sep->data.ptrvalue;
+    rval = DoesBioseqAccessionMatchList (bsp, accn_list);
+  } else {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    rval = DoesBioseqSetAccessionMatchList (bssp, accn_list);
+  }
+
+  return rval;
+}
+
+
+static Boolean s_IsDelimiter (Char ch)
+{
+  if (isspace (ch) || ch == ',' || ch == ';') {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static ValNodePtr ListFromString (CharPtr accn_list)
+{
+  CharPtr start, stop, id;
+  ValNodePtr list = NULL;
+  Int4 len;
+
+  start = accn_list;
+  while (*start != 0) {
+    while (*start != 0 && s_IsDelimiter(*start)) {
+      start++;
+    }
+    if (*start != 0) {
+      stop = start + 1;
+      while (*stop != 0 && !s_IsDelimiter (*stop)) {
+        stop++;
+      }
+      len = stop - start;
+      id = (CharPtr) MemNew (sizeof (Char) * (len + 1));
+      StringNCpy (id, start, len);
+      id[len] = 0;
+      ValNodeAddPointer (&list, 0, id);
+      start = stop;
+    }
+  }
+
+  return list;
+}
+
+typedef struct setatp {
+  AsnModulePtr amp;
+  AsnTypePtr atp_class;
+  AsnTypePtr atp_seqset;
+  AsnTypePtr atp_se;
+  AsnTypePtr atp_desc;
+  AsnTypePtr atp_annot;
+  AsnTypePtr atp_annot_e;
+  AsnTypePtr atp_id;
+  AsnTypePtr atp_coll;
+  AsnTypePtr atp_date;
+  AsnTypePtr atp_level;
+  AsnTypePtr atp_release;
+  AsnTypePtr atp_bss;
+  AsnTypePtr atp_seqentry;
+  AsnTypePtr atp_seq;
+  AsnTypePtr atp_set;
+  AsnTypePtr atp_seqsubmit;
+  AsnTypePtr atp_sub;
+  AsnTypePtr atp_seqsubmit_data;
+  AsnTypePtr atp_seqsubmit_data_entries_E;
+  AsnTypePtr atp_seqsubmit_data_entries;
+  AsnTypePtr atp_seqsubmit_data_entries_set;
+} SetAtpData, PNTR SetAtpPtr;
+
+
+static SetAtpPtr GetSetAtp (void)
+{
+  AsnModulePtr amp;
+  AsnTypePtr atp_class;
+  AsnTypePtr atp_seqset;
+  AsnTypePtr atp_se;
+  AsnTypePtr atp_desc;
+  AsnTypePtr atp_annot;
+  AsnTypePtr atp_annot_e;
+  AsnTypePtr atp_id;
+  AsnTypePtr atp_coll;
+  AsnTypePtr atp_date;
+  AsnTypePtr atp_level;
+  AsnTypePtr atp_release;
+  AsnTypePtr atp_bss;
+  AsnTypePtr atp_seqentry;
+  AsnTypePtr atp_seq;
+  AsnTypePtr atp_set;
+  AsnTypePtr atp_seqsubmit;
+  AsnTypePtr atp_sub;
+  AsnTypePtr atp_seqsubmit_data;
+  AsnTypePtr atp_seqsubmit_data_entries_E;
+  AsnTypePtr atp_seqsubmit_data_entries;
+  AsnTypePtr atp_seqsubmit_data_entries_set;
+  SetAtpPtr  sp;
+
+  amp = AsnAllModPtr ();
+  if (amp == NULL) {
+    Message (MSG_POSTERR, "Unable to load AsnAllModPtr");
+    return NULL;
+  }
+
+  atp_seqset = AsnFind ("Bioseq-set.seq-set");
+  if (atp_seqset == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.seq-set");
+    return NULL;
+  }
+
+  atp_se = AsnFind ("Bioseq-set.seq-set.E");
+  if (atp_se == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.seq-set.E");
+    return NULL;
+  }
+
+  atp_bss = AsnFind ("Bioseq-set");
+  if (atp_bss == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set");
+    return NULL;
+  }
+
+  atp_class = AsnFind ("Bioseq-set.class");
+  if (atp_class == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.class");
+    return NULL;
+  }
+
+  atp_desc = AsnFind ("Bioseq-set.descr");
+  if (atp_desc == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.descr");
+    return NULL;
+  }
+
+  atp_annot = AsnFind ("Bioseq-set.annot");
+  if (atp_annot == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.annot");
+    return NULL;
+  }
+
+  atp_annot_e = AsnFind ("Bioseq-set.annot.E");
+  if (atp_annot_e == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.annot.E");
+    return NULL;
+  }
+
+  atp_id = AsnFind ("Bioseq-set.id");
+  if (atp_id == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.id");
+    return NULL;
+  }
+
+  atp_coll = AsnFind ("Bioseq-set.coll");
+  if (atp_coll == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.coll");
+    return NULL;
+  }
+  atp_date = AsnFind ("Bioseq-set.date");
+  if (atp_date == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.date");
+    return NULL;
+  }
+  atp_level = AsnFind ("Bioseq-set.level");
+  if (atp_level == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.level");
+    return NULL;
+  }
+  atp_release = AsnFind ("Bioseq-set.release");
+  if (atp_release == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.release");
+    return NULL;
+  }
+
+  atp_seqentry = AsnFind ("Seq-entry");
+  if (atp_seqentry == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-entry");
+    return NULL;
+  }
+
+  atp_seq = AsnFind ("Seq-entry.seq");
+  if (atp_seq == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-entry.seq");
+    return NULL;
+  }
+
+  atp_set = AsnFind ("Seq-entry.set");
+  if (atp_set == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-entry.set");
+    return NULL;
+  }
+
+  atp_seqsubmit = AsnFind ("Seq-submit");
+  if (atp_seqsubmit == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit");
+    return NULL;
+  }
+
+  atp_sub = AsnFind ("Seq-submit.sub");
+  if (atp_sub == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit");
+    return NULL;
+  }
+
+  atp_seqsubmit_data = AsnFind ("Seq-submit.data");
+  if (atp_seqsubmit_data == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit.data");
+    return NULL;
+  }
+
+  atp_seqsubmit_data_entries_E = AsnFind ("Seq-submit.data.entrys.E");
+  if (atp_seqsubmit_data_entries_E == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit.data.entrys.E");
+    return NULL;
+  }
+
+  atp_seqsubmit_data_entries = AsnFind ("Seq-submit.data.entrys");
+  if (atp_seqsubmit_data_entries == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit.data.entrys");
+    return NULL;
+  }
+
+  atp_seqsubmit_data_entries_set = AsnFind ("Seq-submit.data.entrys.E.set");
+  if (atp_seqsubmit_data_entries == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit.data.entrys.E.set");
+    return NULL;
+  }
+
+
+  sp = (SetAtpPtr) MemNew (sizeof(SetAtpData));
+  sp->amp = amp;
+  sp->atp_class = atp_class;
+  sp->atp_seqset = atp_seqset;
+  sp->atp_se = atp_se;
+  sp->atp_desc = atp_desc;
+  sp->atp_annot = atp_annot;
+  sp->atp_annot_e = atp_annot_e;
+  sp->atp_id = atp_id;
+  sp->atp_coll = atp_coll;
+  sp->atp_date = atp_date;
+  sp->atp_level = atp_level;
+  sp->atp_release = atp_release;
+  sp->atp_bss = atp_bss;
+  sp->atp_seqentry = atp_seqentry;
+  sp->atp_seq = atp_seq;
+  sp->atp_set = atp_set;
+  sp->atp_seqsubmit = atp_seqsubmit;
+  sp->atp_sub = atp_sub;
+  sp->atp_seqsubmit_data = atp_seqsubmit_data;
+  sp->atp_seqsubmit_data_entries_E = atp_seqsubmit_data_entries_E;
+  sp->atp_seqsubmit_data_entries = atp_seqsubmit_data_entries;
+  sp->atp_seqsubmit_data_entries_set = atp_seqsubmit_data_entries_set;
+
+  return sp;
+}
+
+
+static BioseqSetPtr BioseqSetPartialRead (AsnIoPtr aip, AsnTypePtr PNTR orig, SetAtpPtr sp)
+{
+  DataVal av;
+  AsnTypePtr atp, oldatp;
+  BioseqSetPtr bsp=NULL;
+  SeqEntryPtr curr, next, hold = NULL;
+
+
+	if (aip == NULL)
+		return bsp;
+
+	if (orig == NULL || *orig == NULL)           /* BioseqSet ::= (self contained) */
+		atp = AsnReadId(aip, sp->amp, sp->atp_bss);
+	else
+		atp = AsnLinkType(*orig, sp->atp_bss);    /* link in local tree */
+
+  oldatp = atp;
+  if (atp == NULL) {
+    if (orig != NULL) {
+      *orig = atp;
+    }
+    return bsp;
+  }
+
+	bsp = BioseqSetNew();
+	if (bsp == NULL) goto erret;
+
+	if (AsnReadVal(aip, atp, &av) <= 0) goto erret;    /* read the start struct */
+    curr = NULL;
+
+    while ((atp = AsnReadId(aip, sp->amp, atp)) != oldatp)
+    {
+		  if (atp == NULL) goto erret;
+      if (atp == sp->atp_id)
+		  {
+        bsp->id = ObjectIdAsnRead(aip, atp);
+			  if (bsp->id == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_coll)
+		  {
+        bsp->coll = DbtagAsnRead(aip, atp);
+			  if (bsp->coll == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_date)
+		  {
+        bsp->date = DateAsnRead(aip, atp);
+			  if (bsp->date == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_desc)
+		  {
+        bsp->descr = SeqDescrAsnRead(aip, atp);
+			  if (bsp->descr == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_se)
+      {
+		  	if ((next = SeqEntryAsnRead(aip, atp)) != NULL)
+			  {
+				  if (IS_Bioseq(next))
+					  SeqMgrConnect(SM_BIOSEQ, next->data.ptrvalue,
+						              SM_BIOSEQSET, (Pointer) bsp);
+				  else
+					  SeqMgrConnect(SM_BIOSEQSET, next->data.ptrvalue,
+						              SM_BIOSEQSET, (Pointer) bsp);
+
+
+          if (curr == NULL)
+  			    bsp->seq_set = next;
+      		else
+           curr->next = next;
+          curr = next;
+			  }
+      }
+      else if (atp == sp->atp_annot)
+      {
+        bsp->annot = SeqAnnotSetAsnRead(aip, atp, sp->atp_annot_e);
+				if (bsp->annot == NULL) goto erret;
+      }
+      else
+      {
+        if (AsnReadVal(aip, atp, &av) <= 0) goto erret;    /* takes care of everything else */
+        if (atp == sp->atp_level)
+          bsp->level = (Int2)av.intvalue;
+        else if (atp == sp->atp_class)
+			  {
+          bsp->_class = (Uint1)av.intvalue;
+          if (bsp->_class != BioseqseqSet_class_nuc_prot) {
+            if (orig != NULL) {
+              *orig = atp;
+            }
+            bsp->descr = NULL;
+            bsp = BioseqSetFree (bsp);
+            return NULL;
+          }
+
+			  }
+        else if (atp == sp->atp_release)
+          bsp->release = (CharPtr)av.ptrvalue;
+      }
+    }
+  if (AsnReadVal(aip, atp, &av) <= 0) goto erret;   /* end BioseqSet */
+
+
+
+ret:
+  AsnUnlinkType(*orig);     /*  unlink local tree */
+  return bsp;
+erret:
+  aip->io_failure = TRUE;
+  bsp = BioseqSetFree(bsp);
+  goto ret;
+}
+
+
+NLM_EXTERN SeqEntryPtr ReadFilteredAsn (FILE *fp, Boolean is_binary, CharPtr accn_list, Uint2Ptr entityIDptr)
+{
+  AsnIoPtr       aip;
+  SetAtpPtr      sp;
+  AsnTypePtr     atp, atp_ssp;
+  SeqEntryPtr    sep = NULL, inner_sep, last_sep = NULL;
+  BioseqSetPtr   bssp = NULL;
+  BioseqSetPtr   nuc_set;
+  BioseqPtr      bsp;
+  ValNodePtr     id_match_list;
+  SeqDescrPtr    sdp = NULL;
+  Uint1          holding_set_class = BioseqseqSet_class_genbank;
+
+  if (fp == NULL) return NULL;
+
+  sp = GetSetAtp ();
+  if (sp == NULL) {
+    return NULL;
+  }
+
+  atp_ssp = AsnFind ("Seq-submit");
+  if (atp_ssp == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit");
+    sp = MemFree (sp);
+    return NULL;
+  }
+
+  aip = AsnIoNew (is_binary ? ASNIO_BIN_IN : ASNIO_TEXT_IN, fp, NULL, NULL, NULL);
+  if (aip == NULL) {
+    Message (MSG_POSTERR, "AsnIoNew failed for input file");
+    sp = MemFree (sp);
+    return NULL;
+  }
+
+  if ((atp = AsnReadId (aip, sp->amp, atp_ssp)) != NULL) {
+    AsnReadVal (aip, atp, NULL);
+    atp = AsnReadId (aip, sp->amp, atp);
+  } else {
+    AsnIoFree (aip, FALSE);
+    rewind (fp);
+    aip = AsnIoNew (is_binary ? ASNIO_BIN_IN : ASNIO_TEXT_IN, fp, NULL, NULL, NULL);
+    atp = AsnReadId (aip, sp->amp, sp->atp_seqentry);
+    if (atp == NULL) {
+      AsnIoFree (aip, FALSE);
+      rewind (fp);
+      aip = AsnIoNew (is_binary ? ASNIO_BIN_IN : ASNIO_TEXT_IN, fp, NULL, NULL, NULL);
+      atp = AsnReadId (aip, sp->amp, sp->atp_bss);
+    } else {
+      AsnReadVal (aip, atp, NULL);
+      atp = AsnReadId(aip, sp->amp, atp);
+    }
+  }
+  if (atp == NULL) {
+    AsnIoFree (aip, FALSE);
+    sp = MemFree (sp);
+    return NULL;
+  }
+
+  id_match_list = ListFromString (accn_list);
+
+  bssp = BioseqSetNew ();
+  bssp->_class = holding_set_class;
+  sep = SeqEntryNew ();
+  sep->choice = 2;
+  sep->data.ptrvalue = bssp;
+
+  SeqMgrSeqEntry (SM_BIOSEQSET, (Pointer) bssp, sep);
+
+
+  while (! aip->io_failure && atp != NULL) {
+    if (atp == sp->atp_set) {
+      nuc_set = BioseqSetPartialRead (aip, &atp, sp);
+      if (nuc_set != NULL) {
+        if (DoesBioseqSetAccessionMatchList (nuc_set, id_match_list)) {
+          inner_sep = SeqEntryNew();
+          inner_sep->choice = 2;
+          inner_sep->data.ptrvalue = nuc_set;
+          SeqMgrSeqEntry (SM_BIOSEQSET, (Pointer) nuc_set, inner_sep);
+
+          if (last_sep == NULL) {
+            bssp->seq_set = inner_sep;
+          } else {
+            last_sep->next = inner_sep;
+          }
+          last_sep = inner_sep;
+          SeqMgrLinkSeqEntry (inner_sep, OBJ_BIOSEQ, bssp);
+        } else {
+          nuc_set = BioseqSetFree (nuc_set);
+        }
+      }
+    } else if (atp == sp->atp_seq) {
+      bsp = BioseqAsnRead (aip, atp);
+      if (DoesBioseqAccessionMatchList (bsp, id_match_list)) {
+        inner_sep = SeqEntryNew();
+        inner_sep->choice = 1;
+        inner_sep->data.ptrvalue = bsp;
+        SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, inner_sep);
+
+        if (last_sep == NULL) {
+          bssp->seq_set = inner_sep;
+        } else {
+          last_sep->next = inner_sep;
+        }
+        last_sep = inner_sep;
+        SeqMgrLinkSeqEntry (inner_sep, OBJ_BIOSEQ, bssp);
+      } else {
+        bsp = BioseqFree (bsp);
+      }
+    } else if (atp == sp->atp_desc) {
+      sdp = SeqDescrAsnRead (aip, atp);      
+      ValNodeLink (&(bssp->descr), ValNodeExtractList (&sdp, Seq_descr_pub));
+      sdp = SeqDescrFree (sdp);
+    } else {
+      AsnReadVal (aip, atp, NULL);
+    }
+    atp = AsnReadId (aip, sp->amp, atp);
+  }
+
+  id_match_list = ValNodeFreeData (id_match_list);
+
+  AsnIoFree (aip, FALSE);
+  if (bssp != NULL) {
+    *entityIDptr = ObjMgrRegister (OBJ_SEQENTRY, sep);
+  }
+  sp = MemFree (sp);
+  return sep;
+}
+
+
+static Boolean IdListsCoincide (SeqIdPtr list1, SeqIdPtr list2)
+{
+  SeqIdPtr sip1, sip2;
+  Boolean  found_match = FALSE;
+  Boolean  found_mismatch = FALSE;
+  Uint1    comp;
+
+  for (sip1 = list1; sip1 != NULL && !found_mismatch; sip1 = sip1->next) {
+    for (sip2 = list2; sip2 != NULL && !found_mismatch; sip2 = sip2->next) {
+      comp = SeqIdComp (sip1, sip2);
+      if (comp == SIC_YES) {
+        found_match = TRUE;
+      } else if (comp == SIC_NO) {
+        found_mismatch = TRUE;
+      }
+    }
+  }
+  if (found_match && !found_mismatch) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static Boolean DoesSeqReplaceSeq (BioseqPtr seq1, BioseqPtr seq2)
+{
+  if (seq1 == NULL || seq2 == NULL) {
+    return FALSE;
+  }
+  return IdListsCoincide (seq1->id, seq2->id);
+}
+
+
+static Boolean DoesSetReplaceSeq (BioseqSetPtr set, BioseqPtr seq)
+{
+  BioseqPtr nuc;
+  if (set == NULL || seq == NULL || set->_class != BioseqseqSet_class_nuc_prot
+      || set->seq_set == NULL || !IS_Bioseq (set->seq_set)
+      || (nuc = (BioseqPtr) set->seq_set->data.ptrvalue) == NULL) {
+    return FALSE;
+  }
+  return DoesSeqReplaceSeq (nuc, seq);
+}
+
+
+static Boolean DoesSetReplaceSet (BioseqSetPtr set1, BioseqSetPtr set2)
+{
+  if (set1 == NULL || set2 == NULL
+      || set1->_class != BioseqseqSet_class_nuc_prot
+      || set2->_class != BioseqseqSet_class_nuc_prot
+      || set1->seq_set == NULL
+      || set2->seq_set == NULL
+      || !IS_Bioseq (set1->seq_set)
+      || !IS_Bioseq (set2->seq_set)) {
+    return FALSE;
+  } else {
+    return DoesSeqReplaceSeq (set1->seq_set->data.ptrvalue, set2->seq_set->data.ptrvalue);
+  }
+}
+
+
+static SeqEntryPtr FindReplacementSeqEntry (SeqEntryPtr edited, SeqEntryPtr orig)
+{
+  BioseqPtr bsp_e, bsp_o;
+  BioseqSetPtr bssp;
+  SeqEntryPtr  sep_replace = NULL, tmp;
+
+  if (edited == NULL || orig == NULL) {
+    return NULL;
+  }
+
+  if (IS_Bioseq (edited)) {
+    bsp_e = (BioseqPtr) edited->data.ptrvalue;
+    if (IS_Bioseq (orig)) {
+      bsp_o = (BioseqPtr) orig->data.ptrvalue;
+      if (IdListsCoincide(bsp_e->id, bsp_o->id)) {
+        sep_replace = edited;
+      }
+    } else {
+      if (DoesSetReplaceSeq (orig->data.ptrvalue, bsp_e)) {
+        sep_replace = edited;
+      }
+    }
+  } else if (IS_Bioseq_set (edited)) {
+    bssp = (BioseqSetPtr) edited->data.ptrvalue;
+    if (bssp->_class == BioseqseqSet_class_nuc_prot) {
+      if (IS_Bioseq (orig)) {
+        if (DoesSetReplaceSeq (bssp, orig->data.ptrvalue)) {
+          sep_replace = edited;
+        }
+      } else {
+        if (DoesSetReplaceSet (bssp, orig->data.ptrvalue)) {
+          sep_replace = edited;
+        }
+      }
+    } else {
+      for (tmp = bssp->seq_set; tmp != NULL && sep_replace == NULL; tmp = tmp->next) {
+        sep_replace = FindReplacementSeqEntry (tmp, orig);
+      }
+    }
+  }
+
+  return sep_replace;
+}
+
+
+static Boolean BioseqSetWriteBefore (BioseqSetPtr bsp, AsnIoPtr aip, AsnTypePtr orig, SetAtpPtr sp)
+{
+	DataVal av;
+	AsnTypePtr atp;
+	Boolean retval = FALSE;
+
+	if (aip == NULL)
+		return FALSE;
+
+  /* first write Seq-entry lead-in */
+  if (!AsnWriteChoice(aip, sp->atp_se, (Int2)2, &av)) goto erret;
+
+	atp = AsnLinkType(orig, sp->atp_bss);   /* link local tree */
+	if (atp == NULL) return FALSE;
+
+	if (bsp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+	if (! AsnOpenStruct(aip, atp, (Pointer)bsp)) goto erret;
+    
+  if (bsp->id != NULL)
+	{
+        if (! ObjectIdAsnWrite(bsp->id, aip, sp->atp_id)) goto erret;
+	}
+  if (bsp->coll != NULL)
+	{
+        if (! DbtagAsnWrite(bsp->coll, aip, sp->atp_coll)) goto erret;
+	}
+  if (bsp->level != INT2_MIN)
+  {
+    av.intvalue = bsp->level;
+    if (! AsnWrite(aip, sp->atp_level, &av)) goto erret;
+  }
+  if (bsp->_class != 0)
+  {
+    av.intvalue = bsp->_class;
+    if (! AsnWrite(aip, sp->atp_class, &av)) goto erret;
+  }
+  if (bsp->release != NULL)
+  {
+    av.ptrvalue = bsp->release;
+    if (! AsnWrite(aip, sp->atp_release, &av)) goto erret;
+  }
+  if (bsp->date != NULL)
+	{
+      if (! DateAsnWrite(bsp->date, aip, sp->atp_date)) goto erret;
+	}
+  if (bsp->descr != NULL)              /* Seq-descr optional */
+	{
+    if (! SeqDescrAsnWrite(bsp->descr, aip, sp->atp_desc)) goto erret;
+	}
+
+  if (! AsnOpenStruct(aip, sp->atp_seqset, (Pointer)bsp->seq_set)) goto erret;
+
+	retval = TRUE;
+erret:
+	return retval;
+
+}
+
+
+static Boolean BioseqSetWriteAfter (BioseqSetPtr bsp, AsnIoPtr aip, AsnTypePtr orig, SetAtpPtr sp)
+{
+	Boolean retval = FALSE;
+
+	if (aip == NULL)
+		return FALSE;
+
+  if (! AsnCloseStruct(aip, sp->atp_seqset, (Pointer)bsp->seq_set)) goto erret;
+    if (bsp->annot != NULL)              /* annotation optional */
+	{
+        if (! SeqAnnotSetAsnWrite(bsp->annot, aip, sp->atp_annot, sp->atp_annot_e)) goto erret;
+	}
+
+    if (! AsnCloseStruct(aip, orig, (Pointer)bsp)) goto erret;
+	retval = TRUE;
+erret:
+
+  return retval;
+}
+
+
+static void SeqEntryCopyReplace (AsnIoPtr aip_in, AsnIoPtr aip_out, SeqEntryPtr edited, AsnTypePtr orig, SetAtpPtr sp);
+
+static SeqEntryPtr BioseqSetCopyReplace (AsnIoPtr aip_in, AsnIoPtr aip_out, SeqEntryPtr edited,
+                                          AsnTypePtr PNTR orig, SetAtpPtr sp)
+{
+  DataVal      av;
+  AsnTypePtr   atp, oldatp;
+  BioseqSetPtr bsp=NULL, edited_set;
+  SeqEntryPtr  curr, next, hold = NULL;
+  Boolean      wrote_front = FALSE;
+  SeqDescrPtr  tmp;
+  SeqEntryPtr  tmp_sep, replace;
+  SeqEntryPtr  sep_return = NULL;
+
+	if (aip_in == NULL)
+		return NULL;
+
+	if (orig == NULL || *orig == NULL)           /* BioseqSet ::= (self contained) */
+		atp = AsnReadId(aip_in, sp->amp, sp->atp_bss);
+	else
+		atp = AsnLinkType(*orig, sp->atp_bss);    /* link in local tree */
+
+  oldatp = atp;
+  if (atp == NULL) {
+    if (orig != NULL) {
+      *orig = atp;
+    }
+    return NULL;
+  }
+
+	bsp = BioseqSetNew();
+	if (bsp == NULL) goto erret;
+
+  edited_set = (BioseqSetPtr) edited->data.ptrvalue;
+
+	if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;    /* read the start struct */
+    curr = NULL;
+
+    while ((atp = AsnReadId(aip_in, sp->amp, atp)) != oldatp)
+    {
+		  if (atp == NULL) goto erret;
+      if (atp == sp->atp_id)
+		  {
+        bsp->id = ObjectIdAsnRead(aip_in, atp);
+			  if (bsp->id == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_coll)
+		  {
+        bsp->coll = DbtagAsnRead(aip_in, atp);
+			  if (bsp->coll == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_date)
+		  {
+        bsp->date = DateAsnRead(aip_in, atp);
+			  if (bsp->date == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_desc)
+		  {
+        bsp->descr = SeqDescrAsnRead(aip_in, atp);
+			  if (bsp->descr == NULL) goto erret;
+		  }
+      else if (atp == sp->atp_se)
+      {
+        /* if this is a nuc prot set, read in the entries so we can see if this is
+         * a candidate for replacement.
+         * otherwise, write out the first part of the bioseq set here,
+         * then write/replace the individual seq-entries.
+         */
+
+        if (bsp->_class == BioseqseqSet_class_nuc_prot) {
+		  	  if ((next = SeqEntryAsnRead(aip_in, atp)) != NULL)
+			    {
+				    if (IS_Bioseq(next))
+					    SeqMgrConnect(SM_BIOSEQ, next->data.ptrvalue,
+						                SM_BIOSEQSET, (Pointer) bsp);
+				    else
+					    SeqMgrConnect(SM_BIOSEQSET, next->data.ptrvalue,
+						                SM_BIOSEQSET, (Pointer) bsp);
+
+
+            if (curr == NULL)
+  			      bsp->seq_set = next;
+      		  else
+             curr->next = next;
+            curr = next;
+			    }
+        } else {
+          /* write front, loop through lower items */
+          if (!wrote_front) {
+            /* remove old pubs */
+            tmp = ValNodeExtract (&(bsp->descr), Seq_descr_pub);
+            tmp = SeqDescrFree (tmp);
+            ValNodeLink (&(bsp->descr), edited_set->descr);
+            edited_set->descr = NULL;
+            BioseqSetWriteBefore (bsp, aip_out, *orig, sp);
+            wrote_front = TRUE;
+          }
+          SeqEntryCopyReplace (aip_in, aip_out, edited, atp, sp);
+        }
+      }
+      else if (atp == sp->atp_annot)
+      {
+        bsp->annot = SeqAnnotSetAsnRead(aip_in, atp, sp->atp_annot_e);
+				if (bsp->annot == NULL) goto erret;
+      }
+      else
+      {
+        if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;    /* takes care of everything else */
+        if (atp == sp->atp_level)
+          bsp->level = (Int2)av.intvalue;
+        else if (atp == sp->atp_class)
+			  {
+          bsp->_class = (Uint1)av.intvalue;
+			  }
+        else if (atp == sp->atp_release)
+          bsp->release = (CharPtr)av.ptrvalue;
+      }
+    }
+  if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;   /* end BioseqSet */
+
+  if (bsp->_class == BioseqseqSet_class_nuc_prot) {
+    tmp_sep = SeqEntryNew ();
+    tmp_sep->choice = 2;
+    tmp_sep->data.ptrvalue = bsp;
+    replace = FindReplacementSeqEntry (edited, tmp_sep);
+    if (replace != NULL) {
+      sep_return = AsnIoMemCopy (replace, (AsnReadFunc) SeqEntryAsnRead, (AsnWriteFunc) SeqEntryAsnWrite);
+    } else {
+      sep_return = SeqEntryNew();
+      sep_return->choice = 2;
+      sep_return->data.ptrvalue = bsp;
+    }
+  } else {
+    BioseqSetWriteAfter (bsp, aip_out, atp, sp);
+    bsp = BioseqSetFree (bsp);
+  }
+  
+ret:
+  AsnUnlinkType(*orig);     /*  unlink local tree */
+  return sep_return;
+erret:
+  aip_in->io_failure = TRUE;
+  aip_out->io_failure = TRUE;
+  bsp = BioseqSetFree(bsp);
+  goto ret;
+}
+
+static void SeqEntryCopyReplace (AsnIoPtr aip_in, AsnIoPtr aip_out, SeqEntryPtr edited, AsnTypePtr orig, SetAtpPtr sp)
+{
+	DataVal av;
+	AsnTypePtr atp;
+  SeqEntryPtr sep=NULL, tmp_sep;
+  SeqEntryPtr replacement_sep;
+	Uint1 type = 0;
+  BioseqSetPtr bssp;
+
+	if (aip_in == NULL || aip_out == NULL || sp == NULL)
+		return;
+
+	if (orig == NULL)           /* SeqEntry ::= (self contained) */
+		atp = AsnReadId(aip_in, sp->amp, sp->atp_seqentry);
+	else
+		atp = AsnLinkType(orig, sp->atp_seqentry);    /* link in local tree */
+	if (atp == NULL) return;
+
+	sep = SeqEntryNew();
+	if (sep == NULL) goto erret;
+
+	if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;    /* read the CHOICE */
+
+  atp = AsnReadId(aip_in, sp->amp, atp); 
+  if (atp == NULL) goto erret;   /* which choice? */
+  if (atp == sp->atp_seq)
+  {
+    sep->choice = 1;
+    sep->data.ptrvalue = (Pointer) BioseqAsnRead(aip_in, atp);
+    type = (Uint1)SM_BIOSEQ;
+    replacement_sep = FindReplacementSeqEntry (edited, sep);
+    if (replacement_sep != NULL) {
+      sep = SeqEntryFree (sep);
+      sep = replacement_sep;
+    }
+    av.ptrvalue = (Pointer)sep;
+    if (!AsnWriteChoice(aip_out, orig, (Int2)sep->choice, &av)) goto erret;
+    if (sep->choice == 1)
+    {
+      if (! BioseqAsnWrite((BioseqPtr)sep->data.ptrvalue, aip_out, sp->atp_seq))
+		    goto erret;
+    }
+    else if (sep->choice == 2)
+    {
+      if (! BioseqSetAsnWrite((BioseqSetPtr)sep->data.ptrvalue, aip_out, sp->atp_set))
+		      goto erret;
+    }
+    /* need to do this so that we don't free part of the edited set before we're done with it. */
+    if (replacement_sep != NULL) {
+      sep = NULL;
+    }
+
+  }
+  else if (atp == sp->atp_set)
+  {
+    /* HERE, we need to read in the first part of the set, determine if it's a nuc-prot set.
+     * if nuc-prot, read the whole set and look for the replacement seq-entry, then write
+     * otherwise, write the front part, then loop through the seq-set recursively
+     */
+
+    tmp_sep = BioseqSetCopyReplace (aip_in, aip_out, edited, &atp, sp);
+
+    if (tmp_sep != NULL) {
+      av.ptrvalue = (Pointer)tmp_sep;
+      AsnIoFlush (aip_out);
+      if (!AsnWriteChoice(aip_out, sp->atp_se, (Int2)sep->choice, &av)) goto erret;
+      if (tmp_sep->choice == 1)
+      {
+        if (! BioseqAsnWrite((BioseqPtr)tmp_sep->data.ptrvalue, aip_out, sp->atp_seq))
+		      goto erret;
+      }
+      else if (tmp_sep->choice == 2)
+      {
+        if (! BioseqSetAsnWrite((BioseqSetPtr)tmp_sep->data.ptrvalue, aip_out, sp->atp_set))
+		        goto erret;
+      }
+      tmp_sep = SeqEntryFree (tmp_sep);
+    }
+  }
+  else if (atp == sp->atp_desc) 
+  {
+    /* write out descriptors from holding set instead */
+    bssp = edited->data.ptrvalue;
+    SeqDescrAsnWrite (bssp->descr, aip_out, sp->atp_desc);
+  }
+
+  sep = SeqEntryFree (sep);
+
+ret:
+  AsnUnlinkType(orig);      /*  unlink local tree */
+	return;
+erret:
+  aip_in->io_failure = TRUE;
+  aip_out->io_failure = TRUE;
+	sep = SeqEntryFree(sep);
+	goto ret;
+}
+
+
+NLM_EXTERN void ReintegrateFilteredAsn (SeqEntryPtr sep, FILE *orig_file, FILE *output, Boolean is_binary)
+{
+  AsnIoPtr       aip_in, aip_out;
+  SetAtpPtr      sp;
+  AsnTypePtr     atp, atp_ssp;
+  DataVal        dv;
+
+  if (orig_file == NULL || output == NULL) {
+    return;
+  }
+
+  sp = GetSetAtp ();
+  if (sp == NULL) {
+    return;
+  }
+
+  atp_ssp = AsnFind ("Seq-submit");
+  if (atp_ssp == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit");
+    sp = MemFree (sp);
+    return;
+  }
+
+  aip_in = AsnIoNew (is_binary? ASNIO_BIN_IN : ASNIO_TEXT_IN, orig_file, NULL, NULL, NULL);
+  if (aip_in == NULL) {
+    Message (MSG_POSTERR, "AsnIoNew failed for input file");
+    sp = MemFree (sp);
+    return;
+  }
+
+  aip_out = AsnIoNew (is_binary ? ASNIO_BIN_OUT : ASNIO_TEXT_OUT, output, NULL, NULL, NULL);
+
+  if ((atp = AsnReadId (aip_in, sp->amp, atp_ssp)) != NULL) {
+    AsnReadVal (aip_in, atp, &dv);
+    AsnWrite (aip_out, atp, &dv);
+    atp = AsnReadId (aip_in, sp->amp, atp);
+  } else {
+    AsnIoFree (aip_in, FALSE);
+    rewind (orig_file);
+    aip_in = AsnIoNew (is_binary ? ASNIO_BIN_IN : ASNIO_TEXT_IN, orig_file, NULL, NULL, NULL);
+    atp = AsnReadId (aip_in, sp->amp, sp->atp_seqentry);
+    if (atp == NULL) {
+      AsnIoFree (aip_in, FALSE);
+      rewind (orig_file);
+      aip_in = AsnIoNew (is_binary ? ASNIO_BIN_IN : ASNIO_TEXT_IN, orig_file, NULL, NULL, NULL);
+      atp = AsnReadId (aip_in, sp->amp, sp->atp_bss);
+    } else {
+      AsnReadVal (aip_in, atp, NULL);
+      AsnWrite (aip_out, atp, &dv);
+      atp = AsnReadId(aip_in, sp->amp, atp);
+    }
+  }
+  if (atp == NULL) {
+    AsnIoFree (aip_in, FALSE);
+    AsnIoFree (aip_out, FALSE);
+    sp = MemFree (sp);
+    return;
+  }
+
+  while (! aip_in->io_failure && atp != NULL) {
+    if (atp == sp->atp_se) {
+      SeqEntryCopyReplace (aip_in, aip_out, sep, atp, sp);
+    } else {
+      AsnReadVal (aip_in, atp, &dv);
+      AsnWrite (aip_out, atp, &dv);
+    }
+    atp = AsnReadId (aip_in, sp->amp, atp);
+  }
+
+  AsnIoFree (aip_in, FALSE);
+  AsnIoFree (aip_out, FALSE);
+  sp = MemFree (sp);
+}
+
+
+static CharPtr MakePubLabelString (PubdescPtr pdp)
+
+{
+  Char        buf [521];
+  CitGenPtr   cgp;
+  ValNodePtr  vnp;
+
+  if (pdp == NULL) return NULL;
+
+  vnp = pdp->pub;
+
+  /* skip over just serial number */
+
+  if (vnp != NULL && vnp->choice == PUB_Gen && vnp->next != NULL) {
+    cgp = (CitGenPtr) vnp->data.ptrvalue;
+    if (cgp != NULL) {
+      if (StringNICmp ("BackBone id_pub", cgp->cit, 15) != 0) {
+        if (cgp->cit == NULL && cgp->journal == NULL && cgp->date == NULL && cgp->serial_number) {
+          vnp = vnp->next;
+        }
+      }
+    }
+  }
+
+  if (PubLabelUnique (vnp, buf, sizeof (buf) - 1, OM_LABEL_CONTENT, TRUE) > 0) {
+    return StringSaveNoNull (buf);
+  }
+
+  return NULL;
+}
+
+
+static CharPtr GetDescriptorLabel (SeqDescrPtr sdp)
+{
+  if (sdp == NULL) {
+    return NULL;
+  } else if (sdp->choice == Seq_descr_pub) {
+    return MakePubLabelString (sdp->data.ptrvalue);
+  } else {
+    return NULL;
+  }
+}
+
+
+NLM_EXTERN DescStreamPtr DescStreamNew (SeqDescPtr sdp, BioseqPtr parent)
+{
+  DescStreamPtr ds;
+
+
+  ds = (DescStreamPtr) MemNew (sizeof (DescStreamData));
+  if (sdp != NULL) {
+    ds->orig = AsnIoMemCopy (sdp, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite);
+    ds->replace = AsnIoMemCopy (sdp, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite);
+    ds->text = GetDescriptorLabel(ds->orig);
+  }
+  if (parent != NULL) {
+    ds->owners = SeqIdDup (SeqIdFindBest (parent->id, SEQID_GENBANK));
+    if (ds->owners != NULL && ds->owners->next != NULL) {
+      ds->owners->next = SeqIdSetFree (ds->owners->next);
+    }
+  }
+
+
+  return ds;
+}
+
+
+NLM_EXTERN DescStreamPtr DescStreamFree (DescStreamPtr ds)
+{
+  if (ds != NULL) {
+    ds->orig = SeqDescFree (ds->orig);
+    ds->replace = SeqDescFree (ds->replace);
+    ds->owners = SeqIdSetFree (ds->owners);
+    ds = MemFree (ds);
+  }
+  return ds;
+}
+
+
+NLM_EXTERN ValNodePtr DescStreamListFree (ValNodePtr vnp)
+{
+  ValNodePtr vnp_next;
+
+  while (vnp != NULL) {
+    vnp_next = vnp->next;
+    vnp->data.ptrvalue = DescStreamFree (vnp->data.ptrvalue);
+    vnp->next = NULL;
+    vnp = ValNodeFree (vnp);
+    vnp = vnp_next;
+  }
+  return vnp;
+}
+
+
+static int DescStreamCompare (DescStreamPtr ds1, DescStreamPtr ds2)
+{
+  if (ds1 == NULL && ds2 == NULL) {
+    return 0;
+  } else if (ds1 == NULL) {
+    return -1;
+  } else if (ds2 == NULL) {
+    return 1;
+  } else if (ds1->text == NULL) {
+    return -1;
+  } else if (ds2->text == NULL) {
+    return 1;
+  } else {
+    return StringCmp (ds1->text, ds2->text);
+  }
+}
+
+
+static int LIBCALLBACK SortVnpByDescStream (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 == NULL || ptr2 == NULL) return 0;
+  vnp1 = *((ValNodePtr PNTR) ptr1);
+  vnp2 = *((ValNodePtr PNTR) ptr2);
+  if (vnp1 == NULL || vnp2 == NULL) return 0;
+
+  return DescStreamCompare(vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+}
+
+
+static void RecombineDescStreamList (ValNodePtr PNTR p_list)
+{
+  ValNodePtr vnp, cmp, tmp;
+  DescStreamPtr d1, d2;
+
+  if (p_list == NULL || *p_list == NULL) {
+    return;
+  }
+
+  *p_list = ValNodeSort (*p_list, SortVnpByDescStream);
+
+  for (vnp = *p_list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == 0) {
+      d1 = (DescStreamPtr) vnp->data.ptrvalue;
+      for (cmp = vnp->next; 
+           cmp != NULL && (d2 = (DescStreamPtr) cmp->data.ptrvalue) != NULL && StringCmp (d1->text, d2->text) == 0;
+           cmp = cmp->next) {
+        if (cmp->choice == 0 && AsnIoMemComp (d1->orig, d2->orig, (AsnWriteFunc) SeqDescAsnWrite)) {
+          ValNodeLink (&d1->owners, d2->owners);
+          d2->owners = NULL;
+          /* add dependencies */
+          d1->num_dependent += d2->num_dependent;
+          /* mark choice for later extraction and deletion */
+          cmp->choice = 1;
+        }
+      }
+    }
+  }
+
+  tmp = ValNodeExtractList (p_list, 1);
+  tmp = DescStreamListFree (tmp);
+}
+  
+
+static void AddPubCitationsFromAnnot (SeqAnnotPtr annot, ValNodePtr desc_stream_list)
+{
+  SeqFeatPtr sfp;
+  ValNodePtr repl_v;
+  DescStreamPtr d;
+  PubdescPtr    pdp;
+  ValNodePtr    vnp;
+  ValNode       vn_p, vn_c;
+  Boolean       found;
+
+  if (annot == NULL || annot->type != 1) 
+  {
+    return;
+  }
+  MemSet (&vn_p, 0, sizeof (ValNode));
+  MemSet (&vn_c, 0, sizeof (ValNode));
+  for (sfp = annot->data; sfp != NULL; sfp = sfp->next) 
+  {
+    if (sfp->cit == NULL || sfp->cit->choice != 1 || sfp->cit->data.ptrvalue == NULL) 
+    {
+      continue;
+    }
+    /* note - there could be multiple identical copies of a pub in the list,
+     * we only need to count the match once - we will combine the totals
+     * in RecombineDescStreamList.
+     */
+    found = FALSE;
+    for (repl_v = desc_stream_list; repl_v != NULL && !found; repl_v = repl_v->next) 
+    {
+      d = (DescStreamPtr) repl_v->data.ptrvalue;
+      if (d->orig != NULL 
+          && d->orig->choice == Seq_descr_pub
+          && (pdp = (PubdescPtr) d->orig->data.ptrvalue) != NULL)
+      {
+        for (vnp = sfp->cit->data.ptrvalue; vnp != NULL; vnp = vnp->next) {
+          /* each vnp is a pub */
+          vn_p.choice = PUB_Equiv;
+          vn_p.data.ptrvalue = pdp->pub;
+          vn_c.choice = PUB_Equiv;
+          vn_c.data.ptrvalue = vnp;
+
+          if (PubLabelMatch (&vn_p, &vn_c) == 0) 
+          {
+            d->num_dependent ++;
+            found = TRUE;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+static void AddPubCitationsFromAnnotSet (SeqAnnotPtr annot, ValNodePtr desc_stream_list)
+{
+  while (annot != NULL)
+  {
+    AddPubCitationsFromAnnot (annot, desc_stream_list);
+    annot = annot->next;
+  }
+}
+
+
+static void AddPubCitationsFromSet (BioseqSetPtr bssp, ValNodePtr desc_stream_list)
+{
+  BioseqPtr    bsp;
+  SeqEntryPtr  sep;
+
+  if (bssp == NULL || desc_stream_list == NULL) 
+  {
+    return;
+  }
+
+  AddPubCitationsFromAnnotSet (bssp->annot, desc_stream_list);
+  for (sep = bssp->seq_set; sep != NULL; sep = sep->next) 
+  {
+    if (IS_Bioseq (sep) && (bsp = (BioseqPtr) sep->data.ptrvalue) != NULL) 
+    {
+      AddPubCitationsFromAnnotSet (bsp->annot, desc_stream_list);
+    }
+    else if (IS_Bioseq_set (sep))
+    {
+      AddPubCitationsFromSet (sep->data.ptrvalue, desc_stream_list);
+    }
+  }
+}
+
+
+static void FixCitationsInAnnot (SeqAnnotPtr annot, ValNodePtr desc_stream_list)
+{
+  SeqFeatPtr sfp;
+  ValNodePtr repl_v;
+  DescStreamPtr d;
+  PubdescPtr    pdp, pdp_r;
+  ValNodePtr    ppr, vnp, vnp_prev, vnp_next;
+  ValNode       vn, vn_p, vn_c, vn_tmp;
+
+  if (annot == NULL || annot->type != 1) 
+  {
+    return;
+  }
+  MemSet (&vn_p, 0, sizeof (ValNode));
+  MemSet (&vn_c, 0, sizeof (ValNode));
+  for (sfp = annot->data; sfp != NULL; sfp = sfp->next) 
+  {
+    if (sfp->cit == NULL || sfp->cit->choice != 1 || sfp->cit->data.ptrvalue == NULL) 
+    {
+      continue;
+    }
+    for (repl_v = desc_stream_list; repl_v != NULL; repl_v = repl_v->next) 
+    {
+      d = (DescStreamPtr) repl_v->data.ptrvalue;
+      if (d->orig != NULL 
+          && d->orig->choice == Seq_descr_pub
+          && (pdp = (PubdescPtr) d->orig->data.ptrvalue) != NULL)
+      {
+        vnp_prev = NULL;
+        for (vnp = sfp->cit->data.ptrvalue; vnp != NULL; vnp = vnp_next) {
+          vnp_next = vnp->next;
+          /* each vnp is a pub */
+          vn_p.choice = PUB_Equiv;
+          vn_p.data.ptrvalue = pdp->pub;
+          vn_c.choice = PUB_Equiv;
+          vn_c.data.ptrvalue = vnp;
+
+          if (PubLabelMatch (&vn_p, &vn_c) == 0) 
+          {
+            if (d->replace != NULL
+                && d->replace->choice == Seq_descr_pub
+                && (pdp_r = (PubdescPtr) d->replace->data.ptrvalue) != NULL) 
+            {
+              /* update Seq-feat cit */
+              MemSet ((Pointer) &vn, 0, sizeof (ValNode));
+              MemCopy (&vn, sfp->cit, sizeof (ValNode));
+              vn_p.choice = PUB_Equiv;
+              vn_p.data.ptrvalue = pdp_r->pub;
+              ppr = MinimizePub (&vn_p);
+              
+              vn_tmp.choice = vnp->choice;
+              vn_tmp.data.ptrvalue = vnp->data.ptrvalue;
+              vnp->choice = ppr->choice;
+              vnp->data.ptrvalue = ppr->data.ptrvalue;
+              ppr->choice = vn_tmp.choice;
+              ppr->data.ptrvalue = vn_tmp.data.ptrvalue;
+              ppr = PubFree (ppr);
+              vnp_prev = vnp;
+            } 
+            else
+            {
+              /* remove Seq-feat Cit */
+              if (vnp_prev == NULL) 
+              {
+                sfp->cit->data.ptrvalue = vnp->next;
+              }
+              else
+              {
+                vnp_prev->next = vnp->next;
+              }
+              vnp->next = NULL;
+              vnp = PubFree (vnp);
+            }
+          }
+          else
+          {
+            vnp_prev = vnp;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+static void FixCitationsInAnnotSet (SeqAnnotPtr sap, ValNodePtr desc_stream_list)
+{
+  while (sap != NULL) 
+  {
+    FixCitationsInAnnot (sap, desc_stream_list);
+    sap = sap->next;
+  }
+}
+
+
+static void FixCitationsInSet (BioseqSetPtr bssp, ValNodePtr desc_stream_list)
+{
+  BioseqPtr    bsp;
+  SeqEntryPtr  sep;
+
+  if (bssp == NULL || desc_stream_list == NULL) 
+  {
+    return;
+  }
+
+  FixCitationsInAnnotSet (bssp->annot, desc_stream_list);
+  for (sep = bssp->seq_set; sep != NULL; sep = sep->next) 
+  {
+    if (IS_Bioseq (sep) && (bsp = (BioseqPtr) sep->data.ptrvalue) != NULL) 
+    {
+      FixCitationsInAnnotSet (bsp->annot, desc_stream_list);
+    }
+    else if (IS_Bioseq_set (sep))
+    {
+      FixCitationsInSet (sep->data.ptrvalue, desc_stream_list);
+    }
+  }
+}
+
+
+typedef struct streamreader {
+  ValNodePtr  desc_stream_list;
+  SeqDescrPtr parent_list;
+  SeqIdPtr PNTR sip_list;
+} StreamReaderData, PNTR StreamReaderPtr;
+
+
+static void StreamingReadAny (AsnIoPtr aip, AsnTypePtr atp, SetAtpPtr sp, StreamReaderPtr sr);
+
+static AsnTypePtr StreamingReadBioseqSet (AsnIoPtr aip, AsnTypePtr orig, SetAtpPtr sp, StreamReaderPtr sr)
+{
+  DataVal      av;
+  AsnTypePtr   atp, oldatp;
+  BioseqSetPtr bsp=NULL;
+  SeqEntryPtr  curr, next, hold = NULL;
+  BioseqPtr    nuc_bsp;
+  SeqDescPtr   sdp = NULL;
+  SeqAnnotPtr  annot;
+  SeqDescPtr   last_parent, first_parent;
+
+	if (aip == NULL || sp == NULL || sr == NULL)
+		return orig;
+
+	if (orig == NULL)           /* BioseqSet ::= (self contained) */
+		atp = AsnReadId(aip, sp->amp, sp->atp_bss);
+	else
+		atp = AsnLinkType(orig, sp->atp_bss);    /* link in local tree */
+
+  oldatp = atp;
+  if (atp == NULL) {
+    return atp;
+  }
+
+	bsp = BioseqSetNew();
+	if (bsp == NULL) goto erret;
+
+	if (AsnReadVal(aip, atp, &av) <= 0) goto erret;    /* read the start struct */
+
+  curr = NULL;
+
+  while ((atp = AsnReadId(aip, sp->amp, atp)) != oldatp)
+  {
+	  if (atp == NULL) goto erret;
+    if (atp == sp->atp_id)
+	  {
+      bsp->id = ObjectIdAsnRead(aip, atp);
+		  if (bsp->id == NULL) goto erret;
+	  }
+    else if (atp == sp->atp_coll)
+	  {
+      bsp->coll = DbtagAsnRead(aip, atp);
+		  if (bsp->coll == NULL) goto erret;
+	  }
+    else if (atp == sp->atp_date)
+	  {
+      bsp->date = DateAsnRead(aip, atp);
+		  if (bsp->date == NULL) goto erret;
+	  }
+    else if (atp == sp->atp_desc)
+	  {
+      bsp->descr = SeqDescrAsnRead(aip, atp);
+		  if (bsp->descr == NULL) goto erret;
+	  }
+    else if (atp == sp->atp_seqset && bsp->_class != BioseqseqSet_class_nuc_prot) 
+    {
+      first_parent = bsp->descr;
+      bsp->descr = NULL;
+      last_parent = sr->parent_list;
+      if (last_parent == NULL) {
+        sr->parent_list = first_parent;
+      } else {
+        while (last_parent->next != NULL) {
+          last_parent = last_parent->next;
+        }
+        last_parent->next = first_parent;
+      }
+      /* reading members of set that is not nuc-prot */
+      StreamingReadAny (aip, atp, sp, sr);
+      if (last_parent == NULL) {
+        sr->parent_list = NULL;
+      } else {
+        last_parent->next = NULL;
+      }
+      first_parent = SeqDescrFree (first_parent);
+    }
+    else if (atp == sp->atp_se)
+    {
+      /* reading members of set that is nuc-prot */
+  	  if ((next = SeqEntryAsnRead(aip, atp)) != NULL)
+	    {
+		    if (IS_Bioseq(next))
+			    SeqMgrConnect(SM_BIOSEQ, next->data.ptrvalue,
+				                SM_BIOSEQSET, (Pointer) bsp);
+		    else
+			    SeqMgrConnect(SM_BIOSEQSET, next->data.ptrvalue,
+				                SM_BIOSEQSET, (Pointer) bsp);
+
+
+        if (curr == NULL)
+		      bsp->seq_set = next;
+  		  else
+         curr->next = next;
+        curr = next;
+	    }
+    }
+    else if (atp == sp->atp_annot)
+    {
+      annot = SeqAnnotSetAsnRead(aip, atp, sp->atp_annot_e);
+			if (annot == NULL) goto erret;
+      if (bsp != NULL) {
+        bsp->annot = annot;
+      }
+    }
+    else
+    {
+      if (AsnReadVal(aip, atp, &av) <= 0) goto erret;    /* takes care of everything else */
+      if (atp == sp->atp_level)
+        bsp->level = (Int2)av.intvalue;
+      else if (atp == sp->atp_class)
+		  {
+        bsp->_class = (Uint1)av.intvalue;
+		  }
+      else if (atp == sp->atp_release)
+      {
+        bsp->release = (CharPtr)av.ptrvalue;
+      }
+    }
+  }
+  if (AsnReadVal(aip, atp, &av) <= 0) goto erret;   /* end BioseqSet */
+
+
+
+ret:
+  AsnUnlinkType(orig);     /*  unlink local tree */
+
+  /* if this was a nuc-prot set, add it to the list now */
+  if (bsp->_class == BioseqseqSet_class_nuc_prot) {
+    if (bsp->seq_set != NULL && IS_Bioseq (bsp->seq_set)) {
+      nuc_bsp = bsp->seq_set->data.ptrvalue;
+      if (sr->sip_list != NULL && nuc_bsp != NULL) {
+        ValNodeLink (sr->sip_list, SeqIdDup (SeqIdFindBest (nuc_bsp->id, SEQID_GENBANK)));
+      }
+      for (sdp = bsp->descr; sdp != NULL; sdp = sdp->next) {
+        if (sdp->choice == Seq_descr_pub) {
+          ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+        }
+      }
+      for (sdp = sr->parent_list; sdp != NULL; sdp = sdp->next) {
+        if (sdp->choice == Seq_descr_pub) {
+          ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+        }
+      }
+    }
+    /* count feature citations */
+    AddPubCitationsFromSet (bsp, sr->desc_stream_list);
+  }
+
+  bsp = BioseqSetFree (bsp);
+
+  return atp;
+erret:
+  aip->io_failure = TRUE;
+  bsp = BioseqSetFree(bsp);
+  goto ret;
+}
+
+
+static void StreamingReadAny (AsnIoPtr aip, AsnTypePtr atp, SetAtpPtr sp, StreamReaderPtr sr)
+{
+  BioseqPtr      nuc_bsp;
+  SeqDescrPtr    sdp = NULL;
+  AsnTypePtr     atp_orig;
+  Boolean        first = TRUE;
+
+  if (aip == NULL || sp == NULL || sr == NULL) {
+    return;
+  }
+  atp_orig = atp;
+
+  while (! aip->io_failure && atp != NULL && (first || atp != atp_orig)) {
+    first = FALSE;
+    if (atp == sp->atp_set) {
+      atp = StreamingReadBioseqSet (aip, atp, sp, sr);
+    } else {
+      if (atp == sp->atp_seq) {
+        nuc_bsp = BioseqAsnRead (aip, atp);
+        if (sr->sip_list != NULL && nuc_bsp != NULL) {
+          ValNodeLink (sr->sip_list, SeqIdDup (SeqIdFindBest (nuc_bsp->id, SEQID_GENBANK)));
+        }
+        for (sdp = nuc_bsp->descr; sdp != NULL; sdp = sdp->next) {
+          if (sdp->choice == Seq_descr_pub) {
+            ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+          }
+        }
+        for (sdp = sr->parent_list; sdp != NULL; sdp = sdp->next) {
+          if (sdp->choice == Seq_descr_pub) {
+            ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+          }
+        }
+        AddPubCitationsFromAnnotSet(nuc_bsp->annot, sr->desc_stream_list);
+        nuc_bsp = BioseqFree (nuc_bsp);
+      } else if (atp == sp->atp_desc) {
+        ValNodeLink (&(sr->parent_list), SeqDescrAsnRead (aip, atp));
+      } else {
+        AsnReadVal (aip, atp, NULL);
+      }
+    }
+    atp = AsnReadId (aip, sp->amp, atp);
+  }
+  if (atp == atp_orig) {
+    AsnReadVal (aip, atp, NULL);
+  }
+}
+
+static Boolean StreamingReadSeqEntry (AsnIoPtr aip, SetAtpPtr sp, StreamReaderPtr sr)
+{
+  AsnTypePtr atp;
+  BioseqPtr  nuc_bsp;
+  SeqDescPtr sdp;
+
+  atp = AsnReadId (aip, sp->amp, sp->atp_seqentry);
+  if (atp == NULL) {
+    return FALSE;
+  }
+
+  AsnReadVal (aip, atp, NULL);
+  atp = AsnReadId(aip, sp->amp, atp);
+
+  if (atp == sp->atp_set) {
+    atp = StreamingReadBioseqSet (aip, atp, sp, sr);
+  } else {
+    if (atp == sp->atp_seq) {
+      nuc_bsp = BioseqAsnRead (aip, atp);
+      if (sr->sip_list != NULL && nuc_bsp != NULL) {
+        ValNodeLink (sr->sip_list, SeqIdDup (SeqIdFindBest (nuc_bsp->id, SEQID_GENBANK)));
+      }
+      for (sdp = nuc_bsp->descr; sdp != NULL; sdp = sdp->next) {
+        if (sdp->choice == Seq_descr_pub) {
+          ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+        }
+      }
+      for (sdp = sr->parent_list; sdp != NULL; sdp = sdp->next) {
+        if (sdp->choice == Seq_descr_pub) {
+          ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+        }
+      }
+      nuc_bsp = BioseqFree (nuc_bsp);
+    } else {
+      AsnReadVal (aip, atp, NULL);
+    }
+  }
+  return TRUE;
+}
+
+
+static Boolean StreamingReadSeqSubmit (AsnIoPtr aip, SetAtpPtr sp, StreamReaderPtr sr)
+{
+  AsnTypePtr atp;
+  BioseqPtr  nuc_bsp;
+  SeqDescPtr sdp;
+  SubmitBlockPtr sbp;
+
+  atp = AsnReadId (aip, sp->amp, sp->atp_seqsubmit);
+  if (atp == NULL) {
+    return FALSE;
+  }
+
+  AsnReadVal (aip, atp, NULL);
+  atp = AsnReadId(aip, sp->amp, atp);
+  
+  if (atp == sp->atp_sub) {
+    sbp = SubmitBlockAsnRead (aip, atp);
+    sbp = SubmitBlockFree (sbp);
+    atp = AsnReadId (aip, sp->amp, atp);
+  }
+
+  while (atp != NULL) {
+    if (atp == sp->atp_set) {
+      atp = StreamingReadBioseqSet (aip, atp, sp, sr);
+    } else {
+      if (atp == sp->atp_seq) {
+        nuc_bsp = BioseqAsnRead (aip, atp);
+        if (sr->sip_list != NULL && nuc_bsp != NULL) {
+          ValNodeLink (sr->sip_list, SeqIdDup (SeqIdFindBest (nuc_bsp->id, SEQID_GENBANK)));
+        }
+        for (sdp = nuc_bsp->descr; sdp != NULL; sdp = sdp->next) {
+          if (sdp->choice == Seq_descr_pub) {
+            ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+          }
+        }
+        for (sdp = sr->parent_list; sdp != NULL; sdp = sdp->next) {
+          if (sdp->choice == Seq_descr_pub) {
+            ValNodeAddPointer (&(sr->desc_stream_list), 0, DescStreamNew (sdp, nuc_bsp));
+          }
+        }
+        nuc_bsp = BioseqFree (nuc_bsp);
+      } else {
+        AsnReadVal (aip, atp, NULL);
+      }
+    }
+    atp = AsnReadId (aip, sp->amp, atp);
+  }
+  return TRUE;
+}
+
+
+/* note - for now, we're just doing pubs.  later I'll find a way to create a text label
+ * for other descriptors so that we can sort them also.
+ * note - we also need to update seqfeatcits when we write out.
+ */
+NLM_EXTERN ValNodePtr StreamAsnForDescriptors (FILE *fp, Boolean is_binary, Boolean is_batch, Boolean is_submit, SeqIdPtr PNTR sip_list)
+{
+  AsnIoPtr       aip;
+  SetAtpPtr      sp;
+  AsnTypePtr     atp = NULL;
+  SeqEntryPtr    sep = NULL, last_sep = NULL;
+  BioseqSetPtr   bssp = NULL;
+  StreamReaderData sr;
+  Boolean          rval;
+
+  if (fp == NULL) return NULL;
+
+  sp = GetSetAtp ();
+  if (sp == NULL) {
+    return NULL;
+  }
+
+  aip = AsnIoNew (is_binary ? ASNIO_BIN_IN : ASNIO_TEXT_IN, fp, NULL, NULL, NULL);
+  if (aip == NULL) {
+    Message (MSG_POSTERR, "AsnIoNew failed for input file");
+    sp = MemFree (sp);
+    return NULL;
+  }
+
+  MemSet (&sr, 0, sizeof (StreamReaderData));
+  sr.sip_list = sip_list;
+
+  if (is_submit) {
+    StreamingReadSeqSubmit (aip, sp, &sr);
+  } else if (is_batch) {
+    while (rval = StreamingReadSeqEntry (aip, sp, &sr)) {
+    }
+  } else {
+    StreamingReadSeqEntry (aip, sp, &sr);
+  }
+
+  AsnIoFree (aip, FALSE);
+  sp = MemFree (sp);
+  sr.parent_list = SeqDescrFree (sr.parent_list);
+
+  /* combine list items */
+  RecombineDescStreamList(&(sr.desc_stream_list));
+
+  return sr.desc_stream_list;
+}
+
+
+static SeqDescrPtr GetDescriptorsForBioseq (BioseqPtr bsp, ValNodePtr desc_stream_list)
+{
+  ValNodePtr vnp;
+  DescStreamPtr d;
+  SeqIdPtr      sip;
+  Boolean       found;
+  SeqDescrPtr   sdp = NULL;
+
+  if (bsp == NULL || desc_stream_list == NULL) {
+    return NULL;
+  }
+
+  for (vnp = desc_stream_list; vnp != NULL; vnp = vnp->next) {
+    d = (DescStreamPtr) vnp->data.ptrvalue;
+    if (d->replace != NULL) {
+      found = FALSE;
+      for (sip = d->owners; sip != NULL && !found; sip = sip->next) {
+        found = SeqIdIn (sip, bsp->id);
+      }
+      if (found) {
+        ValNodeLink (&sdp, AsnIoMemCopy (d->replace, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite));
+      }
+    }
+  }
+  return sdp;
+}
+
+
+static SeqDescrPtr GetDescriptorsForBioseqSet (BioseqSetPtr bssp, ValNodePtr desc_stream_list)
+{
+  if (bssp == NULL || bssp->_class != BioseqseqSet_class_nuc_prot 
+      || bssp->seq_set == NULL
+      || desc_stream_list == NULL) 
+  {
+    return NULL;
+  }
+
+  if (IS_Bioseq(bssp->seq_set)) 
+  {
+    return GetDescriptorsForBioseq (bssp->seq_set->data.ptrvalue, desc_stream_list);
+  } 
+  else 
+  {
+    /* this had better be a segset */
+    bssp = bssp->seq_set->data.ptrvalue;
+    if (bssp != NULL && bssp->_class == BioseqseqSet_class_segset 
+        && bssp->seq_set != NULL
+        && IS_Bioseq (bssp->seq_set))
+    {
+      return GetDescriptorsForBioseq (bssp->seq_set->data.ptrvalue, desc_stream_list);
+    }
+  }
+  return NULL;
+}
+
+
+static void StreamingReadWriteAny (AsnIoPtr aip_in, AsnIoPtr aip_out, AsnTypePtr atp, SetAtpPtr sp, ValNodePtr desc_stream_list);
+
+static AsnTypePtr 
+StreamingReadWriteBioseqSet 
+(AsnIoPtr   aip_in, 
+ AsnIoPtr   aip_out, 
+ ValNodePtr desc_stream_list, 
+ AsnTypePtr orig, 
+ AsnTypePtr set_top,
+ SetAtpPtr  sp)
+{
+  DataVal      av;
+  AsnTypePtr   atp, oldatp;
+  BioseqSetPtr bsp=NULL;
+  SeqEntryPtr  curr, next, hold = NULL;
+  SeqDescPtr   sdp = NULL;
+  SeqDescrPtr  tmp;
+  SeqAnnotPtr  annot;
+
+	if (aip_in == NULL || aip_out == NULL || sp == NULL)
+		return orig;
+
+	if (orig == NULL)           /* BioseqSet ::= (self contained) */
+		atp = AsnReadId(aip_in, sp->amp, sp->atp_bss);
+	else
+		atp = AsnLinkType(orig, sp->atp_bss);    /* link in local tree */
+
+  oldatp = atp;
+  if (atp == NULL) {
+    return atp;
+  }
+
+	bsp = BioseqSetNew();
+	if (bsp == NULL) goto erret;
+
+	if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;    /* read the start struct */
+
+  curr = NULL;
+
+  while ((atp = AsnReadId(aip_in, sp->amp, atp)) != oldatp)
+  {
+	  if (atp == NULL) goto erret;
+    if (atp == sp->atp_id)
+	  {
+      bsp->id = ObjectIdAsnRead(aip_in, atp);
+		  if (bsp->id == NULL) goto erret;
+	  }
+    else if (atp == sp->atp_coll)
+	  {
+      bsp->coll = DbtagAsnRead(aip_in, atp);
+		  if (bsp->coll == NULL) goto erret;
+	  }
+    else if (atp == sp->atp_date)
+	  {
+      bsp->date = DateAsnRead(aip_in, atp);
+		  if (bsp->date == NULL) goto erret;
+	  }
+    else if (atp == sp->atp_desc)
+	  {
+      bsp->descr = SeqDescrAsnRead(aip_in, atp);
+		  if (bsp->descr == NULL) goto erret;
+      /* remove descriptors that are being streamed and edited.
+       * for now, this is just pubs.
+       */
+      tmp = ValNodeExtractList (&(bsp->descr), Seq_descr_pub);
+      tmp = SeqDescrFree (tmp);
+	  }
+    else if (atp == sp->atp_seqset && bsp->_class != BioseqseqSet_class_nuc_prot) 
+    {
+      /* reading members of set that is not nuc-prot */
+      StreamingReadWriteAny (aip_in, aip_out, atp, sp, desc_stream_list);
+    }
+    else if (atp == sp->atp_se)
+    {
+      if (bsp == NULL) 
+      {
+      } 
+      else 
+      {
+        /* reading members of set that is nuc-prot */
+	  	  if ((next = SeqEntryAsnRead(aip_in, atp)) != NULL)
+		    {
+			    if (IS_Bioseq(next))
+				    SeqMgrConnect(SM_BIOSEQ, next->data.ptrvalue,
+					                SM_BIOSEQSET, (Pointer) bsp);
+			    else
+				    SeqMgrConnect(SM_BIOSEQSET, next->data.ptrvalue,
+					                SM_BIOSEQSET, (Pointer) bsp);
+
+
+          if (curr == NULL)
+			      bsp->seq_set = next;
+    		  else
+           curr->next = next;
+          curr = next;
+		    }
+      }
+    }
+    else if (atp == sp->atp_annot)
+    {
+      annot = SeqAnnotSetAsnRead(aip_in, atp, sp->atp_annot_e);
+			if (annot == NULL) goto erret;
+      bsp->annot = annot;
+    }
+    else
+    {
+      if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;    /* takes care of everything else */
+      if (atp == sp->atp_level)
+        bsp->level = (Int2)av.intvalue;
+      else if (atp == sp->atp_class)
+		  {
+        bsp->_class = (Uint1)av.intvalue;
+        if (bsp->_class != BioseqseqSet_class_nuc_prot) {
+          /* remove descriptors that are being streamed and replaced */
+          tmp = ValNodeExtract (&(bsp->descr), Seq_descr_pub);
+          tmp = SeqDescrFree (tmp);
+          BioseqSetWriteBefore (bsp, aip_out, orig, sp);
+        }
+		  }
+      else if (atp == sp->atp_release)
+      {
+        if (bsp != NULL) {
+          bsp->release = (CharPtr)av.ptrvalue;
+        }
+      }
+    }
+  }
+  if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;   /* end BioseqSet */
+
+
+
+ret:
+
+  AsnUnlinkType(orig);     /*  unlink local tree */
+
+  FixCitationsInSet (bsp, desc_stream_list);
+  /* if this was a nuc-prot set, change descriptors and write out now */
+  if (bsp->_class == BioseqseqSet_class_nuc_prot) {
+    ValNodeLink (&(bsp->descr), GetDescriptorsForBioseqSet(bsp, desc_stream_list));
+    AsnWriteChoice(aip_out, set_top, 2, &av);
+    BioseqSetAsnWrite(bsp, aip_out, atp);  
+  } else {
+    BioseqSetWriteAfter (bsp, aip_out, atp, sp);
+  }
+
+  bsp = BioseqSetFree (bsp);
+
+  return atp;
+erret:
+  aip_in->io_failure = TRUE;
+  bsp = BioseqSetFree(bsp);
+  goto ret;
+}
+
+
+static void StreamingReadWriteBioseq (AsnIoPtr aip_in, AsnIoPtr aip_out, AsnTypePtr atp, ValNodePtr desc_stream_list)
+{
+  BioseqPtr   nuc_bsp;
+  SeqDescrPtr tmp;
+
+  nuc_bsp = BioseqAsnRead (aip_in, atp);
+  tmp = ValNodeExtract (&(nuc_bsp->descr), Seq_descr_pub);
+  tmp = SeqDescrFree (tmp);
+  ValNodeLink (&(nuc_bsp->descr), GetDescriptorsForBioseq (nuc_bsp, desc_stream_list));
+  FixCitationsInAnnotSet (nuc_bsp->annot, desc_stream_list);
+  BioseqAsnWrite (nuc_bsp, aip_out, atp);
+  nuc_bsp = BioseqFree (nuc_bsp);
+}
+
+
+static void StreamingReadWriteAny (AsnIoPtr aip_in, AsnIoPtr aip_out, AsnTypePtr atp, SetAtpPtr sp, ValNodePtr desc_stream_list)
+{
+  AsnTypePtr     atp_orig;
+  Boolean        first = TRUE;
+  DataVal       av;
+
+  if (aip_in == NULL || aip_out == NULL || sp == NULL) {
+    return;
+  }
+  atp_orig = atp;
+
+  while (! aip_in->io_failure && atp != NULL && (first || atp != atp_orig)) {
+    first = FALSE;
+    if (atp == sp->atp_set) {
+      atp = StreamingReadWriteBioseqSet (aip_in, aip_out, desc_stream_list, atp, sp->atp_se, sp);
+    } else {
+      if (atp == sp->atp_seq) {
+        AsnWriteChoice(aip_out, sp->atp_se, (Int2)1, &av);
+        StreamingReadWriteBioseq (aip_in, aip_out, atp, desc_stream_list);
+      } else {
+        AsnReadVal (aip_in, atp, NULL);
+      }
+    }
+    atp = AsnReadId (aip_in, sp->amp, atp);
+  }
+  if (atp == atp_orig) {
+    AsnReadVal (aip_in, atp, NULL);
+  }
+}
+
+
+static Boolean StreamingReadWriteSeqEntry (ValNodePtr desc_stream_list, AsnIoPtr aip_in, AsnIoPtr aip_out, SetAtpPtr sp)
+{
+  AsnTypePtr atp;
+  DataVal av;
+
+  atp = AsnReadId (aip_in, sp->amp, sp->atp_seqentry);
+  if (atp == NULL) {
+    return FALSE;
+  }
+
+  AsnReadVal (aip_in, atp, NULL);
+  atp = AsnReadId(aip_in, sp->amp, atp);
+
+  if (atp == sp->atp_set) {
+    atp = StreamingReadWriteBioseqSet (aip_in, aip_out, desc_stream_list, atp, sp->atp_se, sp);
+  } else if (atp == sp->atp_seq) {
+    /* first write Seq-entry lead-in */
+    AsnWriteChoice(aip_out, sp->atp_se, (Int2)1, &av);
+    StreamingReadWriteBioseq (aip_in, aip_out, atp, desc_stream_list);
+  } else {
+    AsnReadVal (aip_in, atp, NULL);
+  }
+  return TRUE;
+}
+
+
+static Boolean StreamingReadWriteSeqSubmit (ValNodePtr desc_stream_list, AsnIoPtr aip_in, AsnIoPtr aip_out, SetAtpPtr sp)
+{
+  AsnTypePtr atp, oldatp;
+  DataVal av;
+  SeqSubmitPtr ssp;
+  SubmitBlockPtr sbp;
+
+  atp = AsnReadId (aip_in, sp->amp, sp->atp_seqsubmit);
+  if (atp == NULL) {
+    return FALSE;
+  }
+
+  AsnReadVal (aip_in, atp, NULL);
+
+  ssp = SeqSubmitNew ();
+  if (! AsnOpenStruct(aip_out, atp, (Pointer)ssp)) {
+    ssp = SeqSubmitFree (ssp);
+    return FALSE;
+  }
+
+  atp = AsnReadId(aip_in, sp->amp, atp);
+  
+  if (atp == sp->atp_sub) 
+  {
+    sbp = SubmitBlockAsnRead (aip_in, atp);
+    SubmitBlockAsnWrite (sbp, aip_out, atp);
+    sbp = SubmitBlockFree (sbp);
+    atp = AsnReadId (aip_in, sp->amp, atp);
+  }
+
+  if (atp == NULL) goto erret;
+  if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;
+
+  atp = AsnReadId(aip_in, sp->amp, atp);  /* read the data */
+  if (atp == NULL) goto erret;
+	oldatp = atp;     /* the SET OF */
+  if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;
+
+  while ((atp = AsnReadId(aip_in, sp->amp, atp)) != oldatp && atp != NULL)
+  {
+	  if (atp == sp->atp_seqsubmit_data_entries_E)
+	  {
+      if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;
+      if (! AsnWriteChoice(aip_out, sp->atp_seqsubmit_data, (Int2)1, &av)) goto erret;
+      if (! AsnOpenStruct(aip_out, sp->atp_seqsubmit_data_entries, ssp->data)) goto erret; 
+    } else if (atp == sp->atp_set) {
+      atp = StreamingReadWriteBioseqSet (aip_in, aip_out, desc_stream_list, atp, sp->atp_seqsubmit_data_entries_E, sp);
+    } else if (atp == sp->atp_seq) {
+      /* first write Seq-entry lead-in */
+      AsnWriteChoice(aip_out, sp->atp_se, (Int2)1, &av);
+      StreamingReadWriteBioseq (aip_in, aip_out, atp, desc_stream_list);
+    }
+  }
+  if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;   /* end set of */
+  if (! AsnCloseStruct(aip_out, atp, (Pointer) ssp)) goto erret;
+
+  atp = AsnReadId(aip_in, sp->amp, atp);
+  if (atp == NULL) goto erret;
+  if (AsnReadVal(aip_in, atp, &av) <= 0) goto erret;  /* end struct */
+  if (! AsnCloseStruct(aip_out, atp, (Pointer)ssp)) goto erret;
+
+ret:
+  ssp = SeqSubmitFree (ssp);
+	return TRUE;
+erret:
+  aip_in->io_failure = TRUE;
+  ssp = SeqSubmitFree(ssp);
+  return FALSE;
+
+}
+
+
+NLM_EXTERN void WriteAsnWithReplacedDescriptors (ValNodePtr desc_stream_list, FILE *orig_file, FILE *output, Boolean is_binary, Boolean is_batch, Boolean is_submit)
+{
+  AsnIoPtr       aip_in, aip_out;
+  SetAtpPtr      sp;
+  Boolean        rval;
+
+  if (orig_file == NULL || output == NULL) {
+    return;
+  }
+
+  sp = GetSetAtp ();
+  if (sp == NULL) {
+    return;
+  }
+
+  aip_in = AsnIoNew (is_binary? ASNIO_BIN_IN : ASNIO_TEXT_IN, orig_file, NULL, NULL, NULL);
+  if (aip_in == NULL) {
+    Message (MSG_POSTERR, "AsnIoNew failed for input file");
+    sp = MemFree (sp);
+    return;
+  }
+
+  aip_out = AsnIoNew (is_binary ? ASNIO_BIN_OUT : ASNIO_TEXT_OUT, output, NULL, NULL, NULL);
+
+  if (is_submit) {
+    StreamingReadWriteSeqSubmit (desc_stream_list, aip_in, aip_out, sp);
+    AsnIoFlush (aip_out);
+  } else if (is_batch) {
+    while (rval = StreamingReadWriteSeqEntry(desc_stream_list, aip_in, aip_out, sp)) {
+      AsnIoReset (aip_out);
+    }
+  } else {
+    rval = StreamingReadWriteSeqEntry(desc_stream_list, aip_in, aip_out, sp);
+    AsnIoFlush (aip_out);
+  }
+  AsnIoClose (aip_in);
+  AsnIoClose (aip_out);
+
+  sp = MemFree (sp);
+}
+
+
 /* ReadAsnFastaOrFlatFileEx reads lines, looking for starts of ASN.1, FASTA, GenBank, EMBL,
 or GenPept files.  It then calls the appropriate read function, which is responsible for
 reading the sequence (or object) and restoring the file pointer to the beginning of the
@@ -8103,10 +10415,12 @@ NLM_EXTERN Pointer ReadAsnFastaOrFlatFileEx (
 
       } else if (StringNCmp (line, "ACCESSION ", 10) == 0) {
 
+        if (StringStr (line + 10, "unknown") == NULL) {
         mayBePlainFasta = FALSE;
         mayBeAccessionList = FALSE;
         /* locus may not be unique, but accession should be, so it overrides locus */
         GetSeqId (seqid, line, sizeof (seqid), TRUE, TRUE);
+        }
 
       } else if (StringNCmp (line, "ORIGIN", 6) == 0 || StringNCmp (line, "SQ ", 3) == 0) {
 
@@ -10089,6 +12403,106 @@ NLM_EXTERN void TrimQualityScores (BioseqPtr bsp, Int4 num_to_trim, Boolean from
 }
 
 
+NLM_EXTERN void ReverseSeqGraph (SeqGraphPtr sgp)
+{
+  FloatHiPtr   flvalues;
+  Int4Ptr      intvalues;
+  ByteStorePtr new_bytevalues = NULL, old_bytevalues;
+  Int4         pos, mid, antipos;
+  FloatHi      fswap;
+  Int4         iswap;
+  Int2         val;
+  Int4         loc_start, loc_stop, diff_left, diff_right;
+  Boolean      changed = FALSE;
+  BioseqPtr    bsp;
+  
+  if (sgp == NULL)
+  {
+    return;
+  }
+    
+  if (sgp->flags[2] == 1)
+  {
+    flvalues = (FloatHiPtr) sgp->values;
+    mid = sgp->numval / 2 - 1;
+    for (pos = 0; mid; pos++) {
+      fswap = flvalues[pos];
+      flvalues[pos] = flvalues[sgp->numval - pos - 1];
+      flvalues[sgp->numval - pos] = fswap;
+    }
+    changed = TRUE;
+  }
+  else if (sgp->flags[2] == 2)
+  {
+    intvalues = (Int4Ptr) sgp->values;
+    mid = sgp->numval / 2 - 1;
+    for (pos = 0; mid; pos++) {
+      iswap = intvalues[pos];
+      intvalues[pos] = intvalues[sgp->numval - pos - 1];
+      intvalues[sgp->numval - pos] = iswap;
+    }
+    changed = TRUE;
+  }
+  else if (sgp->flags[2] == 3)
+  {
+    new_bytevalues = BSNew(sgp->numval + 1);
+    old_bytevalues = (ByteStorePtr) sgp->values;
+    pos = 0;
+    antipos = sgp->numval - 1;
+    while (pos < sgp->numval)
+    {
+      BSSeek (old_bytevalues, antipos, SEEK_SET);
+      BSSeek (new_bytevalues, pos, SEEK_SET);
+      val = (Int2) BSGetByte (old_bytevalues);
+      BSPutByte (new_bytevalues, val);
+      BSSeek (new_bytevalues, pos, SEEK_SET);
+      val = (Int2) BSGetByte (new_bytevalues);
+      pos++;
+      antipos--;
+    }
+    old_bytevalues = BSFree (old_bytevalues);
+    sgp->values = new_bytevalues;
+    changed = TRUE;
+  }
+  if (changed) 
+  {
+    bsp = BioseqLockById (SeqLocId (sgp->loc));
+    if (bsp != NULL) {
+      loc_start = SeqLocStart (sgp->loc);
+      loc_stop = SeqLocStop (sgp->loc);
+      if (loc_start < loc_stop) {
+        diff_left = loc_start;
+        diff_right = bsp->length - loc_stop - 1;
+      } else {
+        diff_left = loc_stop;
+        diff_right = bsp->length - loc_start - 1;
+      }
+      if (diff_right != diff_left) {
+        SeqEdAdjustFeatureInterval (sgp->loc, diff_right - diff_left, eSlide, 0, bsp);
+      }
+      BioseqUnlock (bsp);
+    }
+  }
+}
+
+
+NLM_EXTERN void ReverseQualityScores (BioseqPtr bsp)
+{
+  ValNodePtr    qual_scores, vnp;
+  GphItemPtr    gip;
+
+  if (bsp == NULL) return;
+  qual_scores = GetSeqGraphsOnBioseq (bsp->idx.entityID, bsp);
+  for (vnp = qual_scores; vnp != NULL; vnp = vnp->next)
+  {
+    gip = (GphItemPtr) vnp->data.ptrvalue;
+    if (gip == NULL) continue;
+    ReverseSeqGraph (gip->sgp);
+  }
+  
+}
+
+
 NLM_EXTERN BytePtr GetScoresbySeqId (SeqIdPtr sip, Int4Ptr bsplength)
 
 {
@@ -10759,6 +13173,55 @@ FixCapitalizationInElement
 }
 
 
+NLM_EXTERN void FixCapitalizationInAuthor (AuthorPtr pAuthor)
+{
+  NameStdPtr pNameStandard;
+  CharPtr    cp;
+  
+  if (pAuthor == NULL)
+    return;
+  else if(pAuthor->name->choice != 2)
+    return;
+  pNameStandard = pAuthor->name->data;
+  if (pNameStandard != NULL)
+  {
+    FixCapitalizationInElement (&(pNameStandard->names[0]), FALSE, FALSE, TRUE);
+    FixCapitalizationInElement (&(pNameStandard->names[1]), FALSE, FALSE, FALSE);
+    /* Set initials to all caps */
+    for (cp = pNameStandard->names[4]; cp != NULL && *cp != 0; cp++)
+    {
+      *cp = toupper (*cp);
+    }
+  }
+}
+
+
+NLM_EXTERN void FixCapsInPubAffil (AffilPtr affil)
+{
+  if (affil == NULL) return;
+  FixCapitalizationInElement (&(affil->affil), TRUE, TRUE, FALSE);
+  FixAffiliationShortWordsInElement (&(affil->affil));
+  FixCapitalizationInElement (&(affil->div), TRUE, TRUE, FALSE);
+  FixAffiliationShortWordsInElement (&(affil->div));
+  FixCapitalizationInElement (&(affil->city), FALSE, TRUE, FALSE);
+  FixAffiliationShortWordsInElement (&(affil->city));
+
+  /* special handling for states */
+  if (affil->sub != NULL && StringLen (affil->sub) == 2
+    && isalpha((Int4)(affil->sub[0]))	&& isalpha((Int4)(affil->sub[1])))
+  {
+    affil->sub[0] = toupper(affil->sub[0]);
+    affil->sub[1] = toupper(affil->sub[1]);
+  } else {
+    FixCapitalizationInElement (&(affil->sub), FALSE, TRUE, FALSE);
+    FixAffiliationShortWordsInElement (&(affil->sub));
+  }
+  FixCapitalizationInElement (&(affil->country), TRUE, TRUE, FALSE);
+  FixCapitalizationInElement (&(affil->street), FALSE, TRUE, FALSE);
+  FixAffiliationShortWordsInElement (&(affil->street));
+}
+
+
 ReplaceItemPair AffiliationShortWordList[] = {
  { "Au", "au" } ,
  { "Aux", "aux" } ,
@@ -10951,6 +13414,19 @@ NLM_EXTERN SeqIdPtr CreateSeqIdFromText (CharPtr id_str, SeqEntryPtr sep)
       }
     }
 
+    if (bsp == NULL) {
+      sprintf (tmpstr, "ref|%s", id_str);
+      sip = SeqIdParse (tmpstr);
+      if (sip != NULL) {
+        scope = SeqEntrySetScope (sep);
+        bsp = BioseqFind (sip);
+        SeqEntrySetScope (scope);
+        if (bsp == NULL) {
+          sip = SeqIdFree (sip);
+        }
+      }
+    }
+
     if (bsp == NULL && IsAllDigits (id_str)) {
       sprintf (tmpstr, "gi|%s", id_str);
       sip = SeqIdParse (tmpstr);
@@ -11490,12 +13966,57 @@ NLM_EXTERN Boolean GapInLocation (Int4 seq_offset, Int4 length, SeqLocPtr loc)
 }
 
 
+static Boolean AdjustForThisGap (DeltaSeqPtr dsp, Uint4 options, Int4 seq_offset, SeqLocPtr before)
+{
+  Int4 dsp_len;
+  Int4 range_start, range_stop, tmp;
+
+  dsp_len = GetDeltaSeqLen(dsp);
+  if (!IsDeltaSeqGap(dsp)) {
+    return FALSE;
+  }
+  if (DoesDeltaSeqHaveGapTypeOrLinkage(dsp)) {
+    return FALSE;
+  }
+
+  if (!(options & eAdjustFeatForGap_unknown_gaps) && IsDeltaSeqUnknownGap(dsp)) {
+    return FALSE;
+  }
+
+  if (!(options & eAdjustFeatForGap_known_gaps) && IsDeltaSeqKnownGap (dsp)) {
+    return FALSE;
+  }
+
+  if (options & eAdjustFeatForGap_split_in_intron) {
+    range_start = SeqLocStart (before);
+    range_stop = SeqLocStop (before);
+    if (range_stop < range_start) {
+      tmp = range_stop;
+      range_stop = range_start;
+      range_start = tmp;
+    }
+    if (seq_offset >= range_start && seq_offset <= range_stop) {
+      return TRUE;
+    } else if (seq_offset + dsp_len >= range_start && seq_offset + dsp_len < range_stop) {
+      return TRUE;
+    } else if (seq_offset <= range_start && seq_offset + dsp_len > range_stop) {
+      return TRUE;
+    }
+  }
+
+  if (GapInLocation (seq_offset, dsp_len, before)) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+
 NLM_EXTERN void
 LocationContainsGaps
 (SeqLocPtr slp,
  BioseqPtr bsp,
- Boolean   unknown_gaps,
- Boolean   known_gaps,
+ Uint4     options,
  BoolPtr   terminal_gaps,
  BoolPtr   internal_gaps,
  BoolPtr   entirely_in_gap)
@@ -11533,10 +14054,7 @@ LocationContainsGaps
          dsp = dsp->next)
     {
       dsp_len = GetDeltaSeqLen(dsp);
-      if (IsDeltaSeqGap (dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp)
-          && ((unknown_gaps && IsDeltaSeqUnknownGap (dsp))
-              || (known_gaps && IsDeltaSeqKnownGap (dsp)))
-          && GapInLocation (seq_offset, dsp_len, tmp_slp))
+      if (AdjustForThisGap (dsp, options, seq_offset, tmp_slp))
       {
         if (PointInInterval (seq_offset, dsp_len, start)
             && PointInInterval (seq_offset, dsp_len, stop))
@@ -11636,10 +14154,7 @@ static SeqLocPtr
 RemoveGapsFromDeltaLocation 
 (SeqLocPtr slp,
  BioseqPtr bsp,
- Boolean   unknown_gaps,
- Boolean   known_gaps,
- Boolean   trim_ends,
- Boolean   split_internal,
+ Uint4     options,
  Boolean   set_partial_ends,
  BoolPtr   split)
 {
@@ -11679,10 +14194,7 @@ RemoveGapsFromDeltaLocation
        dsp = dsp->next)
   {
     dsp_len = GetDeltaSeqLen(dsp);
-    if (IsDeltaSeqGap (dsp) && !DoesDeltaSeqHaveGapTypeOrLinkage(dsp)
-        && ((unknown_gaps && IsDeltaSeqUnknownGap (dsp))
-            || (known_gaps && IsDeltaSeqKnownGap (dsp)))
-        && GapInLocation (seq_offset, dsp_len, before))
+    if (AdjustForThisGap (dsp, options, seq_offset, before))
     {
       delete_for_this_gap = TRUE;
       start = SeqLocStart (before);
@@ -11698,7 +14210,7 @@ RemoveGapsFromDeltaLocation
       else if (!PointInInterval (seq_offset, dsp_len, start) 
           && !PointInInterval (seq_offset, dsp_len, stop)) 
       {
-        if (!split_internal) 
+        if (!(options & eAdjustFeatForGap_split_internal)) 
         {
           delete_for_this_gap = FALSE;
         }
@@ -11710,7 +14222,7 @@ RemoveGapsFromDeltaLocation
           }
         }
       }
-      else if (!trim_ends)
+      else if (!(options & eAdjustFeatForGap_trim_ends))
       {
         delete_for_this_gap = FALSE;
       }
@@ -11827,10 +14339,7 @@ RemoveGapsFromDeltaLocation
 static SeqLocPtr 
 RemoveGapsFromLocation 
 (SeqLocPtr slp, 
- Boolean   unknown_gaps,
- Boolean   known_gaps,
- Boolean   trim_ends,
- Boolean   split_internal,
+ Uint4     options,
  Boolean   set_partial_ends,
  BoolPtr   split)
 {
@@ -11855,7 +14364,7 @@ RemoveGapsFromLocation
   }
   else if (bsp->repr == Seq_repr_seg)
   {
-    if (!split_internal) {
+    if (!(options & eAdjustFeatForGap_split_internal)) {
       return slp;
     } else {
       return RemoveGapsFromSegmentedLocation (slp, bsp);
@@ -11865,7 +14374,7 @@ RemoveGapsFromLocation
           && bsp->seq_ext_type == 4
           && bsp->seq_ext != NULL)
   {
-    return RemoveGapsFromDeltaLocation (slp, bsp, unknown_gaps, known_gaps, trim_ends, split_internal, set_partial_ends, split);
+    return RemoveGapsFromDeltaLocation (slp, bsp, options, set_partial_ends, split);
   }
   else
   {
@@ -12201,8 +14710,8 @@ NLM_EXTERN void AdjustFeatureForGapsCallback (SeqFeatPtr sfp, Pointer data)
                                       (AsnReadFunc) SeqLocAsnRead, 
                                       (AsnWriteFunc) SeqLocAsnWrite);                                         
   split = FALSE;
-  set_partial_ends = afgp->make_partial;
-  if (set_partial_ends && ! afgp->partial_for_pseudo) {
+  set_partial_ends = afgp->options & eAdjustFeatForGap_make_partial;
+  if (set_partial_ends && ! (afgp->options & eAdjustFeatForGap_partial_for_pseudo)) {
     if (sfp->pseudo) {
       set_partial_ends = FALSE;
     } else {
@@ -12216,19 +14725,19 @@ NLM_EXTERN void AdjustFeatureForGapsCallback (SeqFeatPtr sfp, Pointer data)
   /* handle overlapping features if coding region */
   if (sfp->data.choice == SEQFEAT_CDREGION) 
   {    
-    split_internal = afgp->split_internal;
-    afgp->split_internal = FALSE;
+    split_internal = afgp->options & eAdjustFeatForGap_split_internal;
+    afgp->options &= ~eAdjustFeatForGap_split_internal;
     tmp_list = afgp->feature_list;
     afgp->feature_list = NULL;
     gene = GetGeneForFeature (sfp);
     AdjustFeatureForGapsCallback (gene, afgp);
     mrna = SeqMgrGetOverlappingmRNA (sfp->location, &fcontext);
-    afgp->split_internal = split_internal;
+    afgp->options |= split_internal;
     AdjustFeatureForGapsCallback (mrna, afgp);
     afgp->feature_list = tmp_list;
   }
 
-  slp_new = RemoveGapsFromLocation (slp_new, afgp->unknown_gaps, afgp->known_gaps, afgp->trim_ends, afgp->split_internal, set_partial_ends, &split);
+  slp_new = RemoveGapsFromLocation (slp_new, afgp->options, set_partial_ends, &split);
   if (slp_new == NULL) {
     ValNodeAddPointer (&(afgp->features_in_gap), OBJ_SEQFEAT, sfp);
     return;
@@ -12349,12 +14858,9 @@ NLM_EXTERN void AdjustCDSLocationsForUnknownGapsCallback (SeqFeatPtr sfp, Pointe
 
   agd.feature_list = NULL;
 
-  agd.unknown_gaps = TRUE;
-  agd.known_gaps = FALSE;
-  agd.make_partial = TRUE;
-  agd.partial_for_pseudo = FALSE;
-  agd.split_internal = TRUE;
-  agd.trim_ends = TRUE;
+  agd.options = eAdjustFeatForGap_unknown_gaps | eAdjustFeatForGap_make_partial
+                | eAdjustFeatForGap_split_internal | eAdjustFeatForGap_trim_ends;
+
   agd.align_func = data;
 
   agd.features_in_gap = NULL;
@@ -12644,7 +15150,12 @@ NLM_EXTERN ValNodePtr ReportCoverageForBioseqSeqHist (BioseqPtr bsp)
       } else {
         prim_len = primary_from - primary_to + 1;
       }
-      if (prim_len <= .9 * assem_len || assem_len <= .9 * prim_len) {
+      if (ABS(assem_len - prim_len) >= .1 * assem_len || ABS(assem_len - prim_len) >= .1 * prim_len) {
+        SeqIdWrite (AlnMgr2GetNthSeqIdPtr (salp, 2), id_buf2, PRINTID_REPORT, sizeof (id_buf2) - 1);
+        range = (CharPtr) MemNew (sizeof (Char) * (StringLen (gaps_fmt) + StringLen (id_buf) + StringLen (id_buf2)));
+        sprintf (range, gaps_fmt, id_buf, id_buf2);
+        ValNodeAddPointer (&range_list, 0, range);
+      } else if (ABS(assem_len - prim_len) > 50) {
         SeqIdWrite (AlnMgr2GetNthSeqIdPtr (salp, 2), id_buf2, PRINTID_REPORT, sizeof (id_buf2) - 1);
         range = (CharPtr) MemNew (sizeof (Char) * (StringLen (gaps_fmt) + StringLen (id_buf) + StringLen (id_buf2)));
         sprintf (range, gaps_fmt, id_buf, id_buf2);
@@ -12829,7 +15340,7 @@ NLM_EXTERN ValNodePtr ReportConsensusMatchForBioseqSeqHist (BioseqPtr bsp)
 {
   ValNodePtr   err_list = NULL;
   SeqAlignPtr  salp;
-  Int4         assembly_from, assembly_to;
+  Int4         assembly_from = 0, assembly_to = 0;
   Int4         aln_pos, i, read_pos, pct;
   Int4Ptr      coverage;
   Int4Ptr      match;
@@ -13663,30 +16174,81 @@ NLM_EXTERN void ParseGoTermsFromFields (SeqEntryPtr sep)
 }
 
 
-static ValNodePtr ReadOneColumnList (CharPtr line)
+typedef  Int4  (*Nlm_LenToToken) PROTO ((CharPtr));
+typedef  Int4  (*Nlm_TokenLen) PROTO ((CharPtr));
+typedef  Boolean (*Nlm_IsToken) PROTO ((CharPtr));
+
+static Int4 LenToTabToken (CharPtr cp) 
 {
-  CharPtr p_start, p_end;
-  Int4    plen;
+  if (cp == NULL) {
+    return 0;
+  } else {
+    return StringCSpn (cp, "\t\n");
+  }
+}
+
+
+static Int4 LenTabToken (CharPtr cp)
+{
+  if (cp == NULL) {
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+
+static Boolean IsTab (CharPtr cp)
+{
+  if (cp == NULL) {
+    return FALSE;
+  } else if (*cp == '\t') {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static ValNodePtr 
+ReadOneColumnListEx 
+(CharPtr line, Nlm_LenToToken len_to_token_func, Nlm_TokenLen token_len_func, Nlm_IsToken is_token_func)
+{
+  CharPtr p_start, p_end, p_quote, zap;
+  Char    tmp_end;
+  Int4    plen, quote_len;
   Boolean found_end;
   ValNodePtr col_list = NULL;
+  Char       term[2];
+  ValNodeBlock col_block;
 
-  if (StringHasNoText (line)) return NULL;
+  if (StringHasNoText (line) || len_to_token_func == NULL || token_len_func == NULL || is_token_func == NULL) return NULL;
+  term[1] = 0;
   p_start = line;
   found_end = FALSE;
+  col_block.head = NULL;
+  col_block.tail = NULL;
   while (*p_start != 0 && !found_end)
   {
-    plen = StringCSpn (p_start, "\t\n");
+    quote_len = StringCSpn (p_start, "\"");
+    plen = len_to_token_func (p_start);
+    if (quote_len < plen) {
+      p_quote = p_start + quote_len;
+      term[0] = *p_quote;
+      plen = quote_len + StringCSpn (p_start + quote_len + 1, term);
+      plen += len_to_token_func (p_start + plen);
+    }
     if (plen == 0)
     {
-      if (*p_start == '\t')
+      if (is_token_func(p_start))
       {
-        ValNodeAddStr (&col_list, 0, StringSave (""));
+        ValNodeAddPointerToEnd (&col_block, 0, StringSave (""));
       }
-      p_start++;
+      p_start+=token_len_func(p_start);
       if (*p_start == 0) {
         if (col_list != NULL)
         {
-          ValNodeAddStr (&col_list, 0, StringSave (""));
+          ValNodeAddPointerToEnd (&col_block, 0, StringSave (""));
         }
       }
       continue;
@@ -13698,16 +16260,32 @@ static ValNodePtr ReadOneColumnList (CharPtr line)
     else
     {
       p_end = p_start + plen;
+      tmp_end = *p_end;
       *p_end = 0;
     }
-    TrimSpacesAroundString (p_start);
-    ValNodeAddStr (&col_list, 0, StringSave (p_start));
+    while (*p_start == ' ') {
+      ++p_start;
+    }
+    zap = p_end - 1;
+    while (zap > p_start && *zap == ' ') {
+      *zap = 0;
+      zap--;
+    }
+    
+    ValNodeAddPointerToEnd (&col_block, 0, StringSave (p_start));
     if (!found_end)
     {
-      p_start = p_end + 1;
+      *p_end = tmp_end;
+      p_start = p_end + token_len_func(p_end);
     }
   }
-  return col_list;  
+  return col_block.head; 
+}
+
+
+NLM_EXTERN ValNodePtr ReadOneColumnList (CharPtr line)
+{
+  return ReadOneColumnListEx (line, LenToTabToken, LenTabToken, IsTab);
 }
 
 
@@ -13818,10 +16396,10 @@ static void RemoveEmptyColumnsFromTabTable (ValNodePtr PNTR line_list)
 
 NLM_EXTERN ValNodePtr ReadTabTableFromFile (FILE *fp)
 {
-  Int4          max_columns, num_cols;
+  Int4          max_columns, num_cols, num_discarded = 0;
   ValNodePtr    header_line;
   ValNodePtr    line_list, column_list;
-  ValNodePtr    vnp;
+  ValNodePtr    vnp, last_line = NULL;
   ReadBufferData rbd;
   CharPtr        line;
 
@@ -13838,7 +16416,11 @@ NLM_EXTERN ValNodePtr ReadTabTableFromFile (FILE *fp)
     column_list = ReadOneColumnList (line);
     if (column_list != NULL)
     {
-      vnp = ValNodeAddPointer (&line_list, 0, column_list);
+      vnp = ValNodeAddPointer (&last_line, 0, column_list);
+      if (line_list == NULL) {
+        line_list = last_line;
+      }
+      last_line = vnp;
       num_cols = ValNodeLen (column_list);
       if (num_cols > max_columns)
       {
@@ -13852,14 +16434,19 @@ NLM_EXTERN ValNodePtr ReadTabTableFromFile (FILE *fp)
   /* throw out all lines before header line */
   if (header_line != line_list)
   {
+    num_discarded = 1;
     vnp = line_list;
     while (vnp != NULL && vnp->next != header_line)
     {
+      num_discarded++;
       vnp = vnp->next;
     }
+    if (vnp != NULL) {
     vnp->next = NULL;
+    }
     ValNodeFreeData (line_list);
     line_list = NULL;
+    Message (MSG_OKC, "Warning - the first row of the table did not have enough columns for headers for the following rows - %d rows were discarded before a row with enough columns to provide headers was found.", num_discarded);
   }
 
   RemoveEmptyColumnsFromTabTable (&header_line);
@@ -13913,6 +16500,18 @@ NLM_EXTERN ValNodePtr FreeTabTable (ValNodePtr row_list)
 }
 
 
+NLM_EXTERN void WriteTabTableToFile (ValNodePtr table, FILE *fp)
+{
+  ValNodePtr line, vnp;
+
+  for (line = table; line != NULL; line = line->next) {
+    for (vnp = line->data.ptrvalue; vnp != NULL; vnp = vnp->next) {
+      fprintf (fp, "%s%s", (CharPtr) vnp->data.ptrvalue, vnp->next == NULL ? "\n" : "\t");
+    }
+  }
+}
+
+
 NLM_EXTERN ValNodePtr CountTabTableBlanks (ValNodePtr row_list)
 {
   ValNodePtr   line_vnp, col_vnp, blank_vnp;
@@ -13971,6 +16570,189 @@ NLM_EXTERN void RemoveQuotesFromTabTable (ValNodePtr row_list)
 }
 
 
+NLM_EXTERN void ReparseTabTableConvertFirstSpaceToTab (ValNodePtr row_list)
+{
+  ValNodePtr line_vnp, col_vnp, new_vnp;
+  CharPtr    first_text, second_text, first_space;
+
+  for (line_vnp = row_list; line_vnp != NULL; line_vnp = line_vnp->next) 
+  {
+    col_vnp = line_vnp->data.ptrvalue;
+    first_text = col_vnp->data.ptrvalue;
+    if ((first_space = StringChr (first_text, ' ')) != NULL) {
+      second_text = first_space + StringSpn (first_space, " ");
+      if (*second_text != 0) {
+        /* terminate first text at first space */
+        *first_space = 0;
+        /* create new column with text after first space */
+        second_text = StringSave (second_text);
+        new_vnp = ValNodeNew (NULL);
+        new_vnp->data.ptrvalue = second_text;
+        /* insert new column */
+        new_vnp->next = col_vnp->next;
+        col_vnp->next = new_vnp;
+      }
+    }
+  }
+}
+
+
+static Int4 LenToNextTabOrMultispace (CharPtr cp)
+{
+  Int4 len = 0;
+  Boolean found = FALSE;
+
+  if (StringHasNoText (cp)) {
+    return 0;
+  }
+
+  while (!found && *cp != 0) {
+    if (*cp == '\t' || *cp == '\n' || (*cp == ' ' && *(cp + 1) == ' ')) {
+      found = TRUE;
+    } else {
+      ++len;
+      ++cp;
+    }
+  }
+  return len;
+}
+
+
+static Int4 LenTabOrMultispace (CharPtr cp)
+{
+  Int4 len = 0;
+  Boolean found = FALSE;
+
+  if (StringHasNoText (cp)) {
+    len = 0;
+  } else if (*cp == '\t' || *cp == '\n') {
+    len = 1;
+  } else {
+    len = StringSpn (cp, " ");
+  }
+  return len;
+}
+
+
+static Boolean IsTabOrMultiSpace (CharPtr cp)
+{
+  if (cp == NULL || *cp == 0) {
+    return FALSE;
+  } else if (*cp == '\t' || *cp == '\n') {
+    return TRUE;
+  } else if (*cp == ' ' && *(cp + 1) == ' ') {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+NLM_EXTERN void ReparseTabTableConvertMultiSpaceToTab (ValNodePtr row_list)
+{
+  ValNodePtr line_vnp, col_vnp, new_cols, col_prev, col_next, last_vnp;
+
+  for (line_vnp = row_list; line_vnp != NULL; line_vnp = line_vnp->next) 
+  {
+    col_prev = NULL;
+    for (col_vnp = line_vnp->data.ptrvalue; col_vnp != NULL; col_vnp = col_next) 
+    {
+      col_next = col_vnp->next;
+      new_cols = ReadOneColumnListEx (col_vnp->data.ptrvalue, LenToNextTabOrMultispace, LenTabOrMultispace, IsTabOrMultiSpace);
+      if (new_cols != NULL) {
+        /* insert new columns */
+        last_vnp = new_cols;
+        while (last_vnp->next != NULL) {
+          last_vnp = last_vnp->next;
+        }
+        last_vnp->next = col_vnp->next;
+        col_vnp->next = NULL;
+        col_vnp = ValNodeFreeData (col_vnp);
+        if (col_prev == NULL) {
+          line_vnp->data.ptrvalue = new_cols;
+        } else {
+          col_prev->next = new_cols;
+        }
+        col_prev = last_vnp;
+      } else {
+        col_prev = col_vnp;
+      }
+    }
+  }
+}
+
+
+/* first intended use is to create file ID columns from first two columns of table.
+ * second intended use is to combine columns to make ID list.
+ * Note that column_pos needs to be a sorted list of integers giving a zero-based column offset.
+ */
+NLM_EXTERN void CombineTabTableColumns (ValNodePtr row_list, ValNodePtr column_pos, CharPtr delimiter)
+{
+  ValNodePtr line_vnp, col_vnp, col_prev, col_next, offset_vnp, add_vnp;
+  Int4       col_num, len;
+  CharPtr    tmp;
+
+  if (row_list == NULL || column_pos == NULL || column_pos->next == NULL) {
+    return;
+  }
+
+
+  for (line_vnp = row_list; line_vnp != NULL; line_vnp = line_vnp->next) 
+  {
+    col_prev = NULL;
+    add_vnp = NULL;
+    offset_vnp = column_pos;
+    for (col_vnp = line_vnp->data.ptrvalue, col_num = 0; col_vnp != NULL && offset_vnp != NULL; col_vnp = col_next, col_num++) 
+    {
+      col_next = col_vnp->next;
+      if (col_num == offset_vnp->data.intvalue) {
+        if (add_vnp == NULL) {
+          add_vnp = col_vnp;
+          col_prev = col_vnp;
+        } else {
+          len = StringLen (add_vnp->data.ptrvalue) + StringLen (delimiter) + StringLen (col_vnp->data.ptrvalue) + 1;
+          tmp = (CharPtr) MemNew (sizeof (Char) * len);
+          sprintf (tmp, "%s%s%s", add_vnp->data.ptrvalue, delimiter == NULL ? "" : delimiter, col_vnp->data.ptrvalue);
+          add_vnp->data.ptrvalue = MemFree (add_vnp->data.ptrvalue);
+          add_vnp->data.ptrvalue = tmp;
+          col_prev->next = col_vnp->next;
+          col_vnp->next = NULL;
+          col_vnp = ValNodeFreeData (col_vnp);
+        }
+        offset_vnp = offset_vnp->next;
+      } else {
+        col_prev = col_vnp;
+      }
+    }
+  }
+}
+
+
+NLM_EXTERN void AddTextToTabTableColumn (ValNodePtr row_list, Int4 col, CharPtr text, Uint2 existing_text)
+{
+  ValNodePtr row_vnp, col_vnp;
+  Int4       i;
+  CharPtr    str;
+
+  if (text == NULL) {
+    return;
+  }
+
+  for (row_vnp = row_list; row_vnp != NULL; row_vnp = row_vnp->next) {
+    for (col_vnp = row_vnp->data.ptrvalue, i = 0;
+         col_vnp != NULL;
+         col_vnp = col_vnp->next, i++) {
+      if (i == col) {
+        str = col_vnp->data.ptrvalue;
+        SetStringValue (&str, text, existing_text);
+        col_vnp->data.ptrvalue = str;
+        break;
+      }
+    }
+  }
+}
+
+
 static void AddToContextList (Char ch, CharPtr PNTR strp, ValNodePtr PNTR search_list)
 {
   ValNodePtr vnp, vnp_last = NULL, vnp2, clist;
@@ -14549,70 +17331,6 @@ static void AddStructuredCommentCallback (BioseqPtr bsp, Pointer data)
 }
 
 
-static Boolean HasNormalStructuredCommentPrefixFormat (CharPtr str)
-{
-  Int4 len;
-
-  if (StringHasNoText (str)) {
-    return FALSE;
-  } else if ((len = StringLen (str)) < 11) {
-    return FALSE;
-  } else if (StringNCmp (str, "##", 2) != 0) {
-    return FALSE;
-  } else if (StringCmp (str + len - 8, "-START##") != 0) {
-    return FALSE;
-  } else {
-    return TRUE;
-  }
-}
-
-
-static Boolean HasNormalStructuredCommentSuffixFormat (CharPtr str)
-{
-  Int4 len;
-
-  if (StringHasNoText (str)) {
-    return FALSE;
-  } else if ((len = StringLen (str)) < 9) {
-    return FALSE;
-  } else if (StringNCmp (str, "##", 2) != 0) {
-    return FALSE;
-  } else if (StringCmp (str + len - 6, "-END##") != 0) {
-    return FALSE;
-  } else {
-    return TRUE;
-  }
-}
-
-
-static Boolean RowHasNormalStructuredCommentPrefixAndSuffix (ValNodePtr header, ValNodePtr values)
-{
-  ValNodePtr vnp_h, vnp_v;
-  Boolean has_prefix = FALSE, has_suffix = FALSE;
-
-  for (vnp_h = header, vnp_v = values; 
-       vnp_h != NULL && vnp_v != NULL;
-       vnp_h = vnp_h->next, vnp_v = vnp_v->next) {
-    if (StringICmp (vnp_h->data.ptrvalue, "StructuredCommentPrefix") == 0) {
-      if (has_prefix) {
-        return FALSE;
-      } else if (HasNormalStructuredCommentPrefixFormat (vnp_v->data.ptrvalue)) {
-        has_prefix = TRUE;
-      } else {
-        return FALSE;
-      }
-    } else if (StringICmp (vnp_h->data.ptrvalue, "StructuredCommentSuffix") == 0) {
-      if (HasNormalStructuredCommentSuffixFormat (vnp_v->data.ptrvalue)) {
-        has_suffix = TRUE;
-      } else {
-        return FALSE;
-      }
-    }
-  }
-  return has_prefix && has_suffix;
-}
-
-
 static CharPtr MakeStructuredCommentPrefixFromString (CharPtr orig)
 {
   CharPtr    core, new_prefix;
@@ -14673,12 +17391,11 @@ static CharPtr MakeStructuredCommentSuffixFromString (CharPtr orig)
  * If not apply_to_all, the first column must contain sequence IDs.  The remaining cells in the first
  * line are the names of fields to create in structured comments.
  */
-static ValNodePtr CreateStructuredCommentsFromRow (ValNodePtr header, ValNodePtr values, CharPtr id_str, ValNodePtr PNTR err_list)
+NLM_EXTERN ValNodePtr CreateStructuredCommentsFromRow (ValNodePtr header, ValNodePtr values, CharPtr id_str, ValNodePtr PNTR err_list)
 {
   ValNodePtr comment_list = NULL;
   ValNodePtr vnp_h, vnp_l;
   UserObjectPtr uop = NULL;
-  Boolean       has_normal_fixes;
   CharPtr       suffix = NULL, fix, msg;
   CharPtr       extra_data_fmt = "Too many fields for sequence %s";
 
@@ -14689,20 +17406,9 @@ static ValNodePtr CreateStructuredCommentsFromRow (ValNodePtr header, ValNodePtr
   vnp_h = header;
   vnp_l = values;
 
-  has_normal_fixes = RowHasNormalStructuredCommentPrefixAndSuffix (header, values);
-  if (has_normal_fixes) {
-    uop = CreateStructuredCommentUserObject (NULL, NULL);
-    ValNodeAddPointer (&comment_list, 0, uop);
-  }
-
   while (vnp_h != NULL && vnp_l != NULL) {
     if (!StringHasNoText (vnp_l->data.ptrvalue)) {
       if (StringICmp (vnp_h->data.ptrvalue, "StructuredCommentPrefix") == 0) {
-        if (has_normal_fixes) {
-          fix = MakeStructuredCommentPrefixFromString (vnp_l->data.ptrvalue);
-          AddItemStructuredCommentUserObject (uop, vnp_h->data.ptrvalue, fix);
-          fix = MemFree (fix);
-        } else {
           if (suffix != NULL) {
             fix = MakeStructuredCommentSuffixFromString (suffix);
             AddItemStructuredCommentUserObject (uop, "StructuredCommentSuffix", fix);
@@ -14715,15 +17421,12 @@ static ValNodePtr CreateStructuredCommentsFromRow (ValNodePtr header, ValNodePtr
           fix = MakeStructuredCommentPrefixFromString (suffix);
           AddItemStructuredCommentUserObject (uop, vnp_h->data.ptrvalue, fix);
           fix = MemFree (fix);
-        }
       } else if (StringICmp (vnp_h->data.ptrvalue, "StructuredCommentSuffix") == 0) {
         fix = MakeStructuredCommentSuffixFromString (vnp_l->data.ptrvalue);
         AddItemStructuredCommentUserObject (uop, vnp_h->data.ptrvalue, fix);
         fix = MemFree (fix);
         suffix = MemFree (suffix);
-        if (!has_normal_fixes) {
           uop = NULL;
-        }
       } else {
         if (uop == NULL) {
           uop = CreateStructuredCommentUserObject (NULL, NULL);
@@ -14736,7 +17439,7 @@ static ValNodePtr CreateStructuredCommentsFromRow (ValNodePtr header, ValNodePtr
     vnp_l = vnp_l->next;
   }
   if (uop != NULL && suffix != NULL) {
-    fix = MakeStructuredCommentPrefixFromString (suffix);
+    fix = MakeStructuredCommentSuffixFromString (suffix);
     AddItemStructuredCommentUserObject (uop, "StructuredCommentSuffix", fix);
     fix = MemFree (fix);
   }
@@ -14830,6 +17533,167 @@ NLM_EXTERN ValNodePtr CreateStructuredCommentsFromFile (FILE *fp, SeqEntryPtr se
 }
 
 
+NLM_EXTERN void AddDatabaseNameToStructuredComment (UserObjectPtr uop, CharPtr dbname)
+{
+  UserFieldPtr   curr;
+  Boolean        hasPrefix = FALSE;
+  Boolean        hasSuffix = FALSE;
+  ObjectIdPtr    oip;
+  CharPtr        prefix_fmt = "##%sData-START##";
+  CharPtr        suffix_fmt = "##%sData-END##";
+  CharPtr        prefix, suffix;
+
+  if (uop == NULL) return;
+  oip = uop->type;
+  if (oip == NULL || StringICmp (oip->str, "StructuredComment") != 0) return;
+
+  if (StringHasNoText (dbname)) {
+    dbname = "Meta";
+  } 
+
+  prefix = (CharPtr) MemNew (sizeof (Char) * (StringLen (prefix_fmt) + StringLen(dbname)));
+  sprintf (prefix, prefix_fmt, dbname);
+  suffix = (CharPtr) MemNew (sizeof (Char) * (StringLen (suffix_fmt) + StringLen(dbname)));
+  sprintf (suffix, suffix_fmt, dbname);
+
+  for (curr = uop->data; curr != NULL; curr = curr->next) {
+    oip = curr->label;
+    if (oip != NULL && StringICmp (oip->str, "StructuredCommentPrefix") == 0) {
+      hasPrefix = TRUE;
+      if (curr->choice == 1) {
+        MemFree (curr->data.ptrvalue);
+        curr->data.ptrvalue = (Pointer) StringSave (prefix);
+      }
+    }
+  }
+  if (! hasPrefix) {
+    AddItemStructuredCommentUserObject (uop, "StructuredCommentPrefix", prefix);
+  }
+
+  for (curr = uop->data; curr != NULL; curr = curr->next) {
+    oip = curr->label;
+    if (oip != NULL && StringICmp (oip->str, "StructuredCommentSuffix") == 0) {
+      hasSuffix = TRUE;
+      if (curr->choice == 1) {
+        MemFree (curr->data.ptrvalue);
+        curr->data.ptrvalue = (Pointer) StringSave (suffix);
+      }
+    }
+  }
+  if (! hasSuffix) {
+    AddItemStructuredCommentUserObject (uop, "StructuredCommentSuffix", suffix);
+  }
+  prefix = MemFree (prefix);
+  suffix = MemFree (suffix);
+}
+
+
+static ValNodePtr RowFromStructuredComment (UserObjectPtr uop, ValNodePtr PNTR header)
+{
+  UserFieldPtr   curr;
+  ObjectIdPtr    oip;
+  ValNodePtr     vnp_h, vnp_v;
+  ValNodePtr     values = NULL;
+  CharPtr        label;
+
+  if (uop == NULL || uop->type == NULL 
+      || StringICmp (uop->type->str, "StructuredComment") != 0) {
+    return NULL;
+  }
+
+  for (curr = uop->data; curr != NULL; curr = curr->next) {
+    oip = curr->label;
+    if (oip != NULL) {
+      label = GetObjectIdString(oip);
+      for (vnp_h = *header, vnp_v = values; 
+           vnp_h != NULL && (StringCmp (oip->str, vnp_h->data.ptrvalue) != 0 || (vnp_v != NULL && vnp_v->data.ptrvalue != NULL)); 
+           vnp_h = vnp_h->next, vnp_v = vnp_v->next) {
+        if (vnp_v == NULL) {
+          vnp_v = ValNodeNew (values);
+          if (values == NULL) {
+            values = vnp_v;
+          }
+        }        
+      }
+      if (vnp_h == NULL) {
+        vnp_h = ValNodeNew (*header);
+        if (*header == NULL) {
+          *header = vnp_h;
+        }
+        vnp_h->data.ptrvalue = label;
+        label = NULL;
+      }
+      label = MemFree (label);
+      if (vnp_v == NULL) {
+        vnp_v = ValNodeNew (values);
+        if (values == NULL) {
+          values = vnp_v;
+        }
+      }
+      vnp_v->data.ptrvalue = StringSave (curr->data.ptrvalue);
+    }
+  }
+  return values;
+}
+
+
+static void GetStructuredCommentsForBioseq(BioseqPtr bsp, Pointer data)
+{
+  SeqMgrDescContext context;
+  SeqDescPtr sdp;
+  ValNodePtr header = NULL;
+  ValNodePtr list = NULL;
+  ValNodePtr PNTR table = NULL;
+  ValNodePtr vnp;
+  Char       id_txt[200];
+
+  if (bsp == NULL || ISA_aa (bsp->mol) || data == NULL) {
+    return;
+  }
+
+  table = (ValNodePtr PNTR) data;
+  if (*table != NULL) {
+    header = (*table)->data.ptrvalue;
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &context);
+       sdp != NULL;
+       sdp = sdp->next) {
+    ValNodeLink (&list, RowFromStructuredComment (sdp->data.ptrvalue, &header));
+  }
+
+  if (list != NULL) {
+    if (*table == NULL) {
+      vnp = ValNodeNew (NULL);
+      vnp->data.ptrvalue = StringSave ("SeqId");
+      vnp->next = header;
+      header = vnp;
+      ValNodeAddPointer (table, 0, header);
+      vnp = ValNodeNew (NULL);
+      SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+      vnp->data.ptrvalue = StringSave (id_txt);
+      vnp->next = list;
+      list = vnp;
+    } else {      
+      (*table)->data.ptrvalue = header;
+      /* placeholder for SeqId already exists */
+      SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+      list->data.ptrvalue = StringSave (id_txt);
+    }
+    ValNodeAddPointer (table, 0, list);
+  }
+}
+
+
+NLM_EXTERN ValNodePtr CreateStructuredCommentTableFromSeqEntry (SeqEntryPtr sep)
+{
+  ValNodePtr table = NULL;
+
+  VisitBioseqsInSep (sep, &table, GetStructuredCommentsForBioseq);
+  return table;
+}
+
+
 static SeqPortPtr SeqPortFromAlignmentInterval (Int4 seqstart, Int4 seqstop, Uint1 strand, BioseqPtr bsp)
 {
   SeqIntPtr  sinp;
@@ -15140,7 +18004,7 @@ AlignmentIntervalToString
     }
   }    
 
-  if (alnbuf[alnbuf_len] == 0) {
+  if (alnbuf[alnbuf_len] == 0 && alnbuffer_len != NULL) {
     *alnbuffer_len = StringLen ((CharPtr) alnbuf);
   }
 
@@ -15154,3 +18018,773 @@ AlignmentIntervalToString
     MemFree (target_buf);
   }
 }
+
+
+NLM_EXTERN void SetDescriptorPropagate (BioseqSetPtr bssp)
+{
+  BioseqPtr         bsp;
+  SeqEntryPtr       seqentry;
+  ValNodePtr        sourcedescr;
+
+  if (bssp != NULL) {
+    sourcedescr = bssp->descr;
+    if (sourcedescr != NULL) {
+      bssp->descr = NULL;
+      seqentry = bssp->seq_set;
+      while (seqentry != NULL) {
+        if (seqentry->data.ptrvalue != NULL) {
+          if (seqentry->choice == 1) {
+            bsp = (BioseqPtr) seqentry->data.ptrvalue;
+            ValNodeLink (&(bsp->descr),
+                         AsnIoMemCopy ((Pointer) sourcedescr,
+                                       (AsnReadFunc) SeqDescrAsnRead,
+                                       (AsnWriteFunc) SeqDescrAsnWrite));
+          } else if (seqentry->choice == 2) {
+            bssp = (BioseqSetPtr) seqentry->data.ptrvalue;
+            ValNodeLink (&(bssp->descr),
+                         AsnIoMemCopy ((Pointer) sourcedescr,
+                                       (AsnReadFunc) SeqDescrAsnRead,
+                                       (AsnWriteFunc) SeqDescrAsnWrite));
+          }
+        }
+        seqentry = seqentry->next;
+      }
+      SeqDescrFree (sourcedescr);
+    }
+  }
+}
+
+
+/* This function will look for nested sets of the same type
+ * and remove the inner set.
+ */
+static Boolean RemoveDuplicateNestedSetsInSeqEntry (SeqEntryPtr top_sep)
+{
+  BioseqSetPtr bssp, lower_bssp;
+  SeqEntryPtr  sep, sep_next, sep_tmp, sep_prev = NULL;
+  SeqDescrPtr  last_sdp;
+  SeqAnnotPtr  last_sap;
+  Boolean      rval = FALSE;
+
+  if (top_sep == NULL || !IS_Bioseq_set (top_sep) 
+      || (bssp = (BioseqSetPtr) top_sep->data.ptrvalue) == NULL
+      || bssp->seq_set == NULL) {
+    return FALSE;
+  }
+  
+  sep = bssp->seq_set;
+  while (sep != NULL) {
+    sep_next = sep->next;
+    rval |= RemoveDuplicateNestedSetsInSeqEntry (sep);
+    if (IS_Bioseq_set (sep) 
+        && (lower_bssp = (BioseqSetPtr) sep->data.ptrvalue) != NULL
+        && bssp->_class == lower_bssp->_class) {
+      /* if this is the only set, move the descriptors up, otherwise
+       * propagate the descriptors down.
+       */
+      if (sep->next == NULL && sep == bssp->seq_set) {
+        if (bssp->descr == NULL) {
+          bssp->descr = lower_bssp->descr;
+        } else {
+          last_sdp = bssp->descr;
+          while (last_sdp->next != NULL) {
+            last_sdp = last_sdp->next;
+          }
+          last_sdp->next = lower_bssp->descr;
+        }
+        lower_bssp->descr = NULL;
+      } else {
+        SetDescriptorPropagate (lower_bssp);
+      }
+      /* copy annotations to parent */
+      if (bssp->annot == NULL) {
+        bssp->annot = lower_bssp->annot;
+      } else {
+        last_sap = bssp->annot;
+        while (last_sap->next != NULL) {
+          last_sap = last_sap->next;
+        }
+        last_sap->next = lower_bssp->annot;
+      }
+      lower_bssp->annot = NULL;
+
+      /* insert members of lower set in this position in upper set */
+      if (lower_bssp->seq_set == NULL) {
+        if (sep_prev == NULL) {
+          bssp->seq_set = sep_next;
+        } else {
+          sep_prev->next = sep_next;
+        }
+      } else {
+        if (sep_prev == NULL) {
+          bssp->seq_set = lower_bssp->seq_set;
+        } else {
+          sep_prev->next = lower_bssp->seq_set;
+        }
+        sep_tmp = lower_bssp->seq_set;
+        while (sep_tmp->next != NULL) {
+          sep_tmp = sep_tmp->next;
+        }
+        sep_tmp->next = sep_next;
+        lower_bssp->seq_set = NULL;
+      }
+      sep->next = NULL;
+      sep = SeqEntryFree (sep);
+      rval = TRUE;
+    }
+    sep = sep_next;
+  }
+  return rval;
+}
+
+
+NLM_EXTERN Boolean RemoveDuplicateNestedSetsForEntityID (Uint2 entityID)
+{
+  SeqEntryPtr       top_sep;
+  ObjMgrDataPtr     omdptop;
+  ObjMgrData        omdata;
+  Uint2             top_parenttype;
+  Pointer           top_parentptr;
+  Boolean           rval = FALSE;
+
+  top_sep = GetTopSeqEntryForEntityID (entityID);
+  if (top_sep == NULL) return FALSE;
+
+  SaveSeqEntryObjMgrData (top_sep, &omdptop, &omdata);
+  GetSeqEntryParent (top_sep, &top_parentptr, &top_parenttype);
+
+  rval = RemoveDuplicateNestedSetsInSeqEntry(top_sep);
+
+  SeqMgrLinkSeqEntry (top_sep, top_parenttype, top_parentptr);
+    
+  SeqMgrClearFeatureIndexes (entityID, NULL);
+  SeqMgrIndexFeatures (entityID, NULL);
+
+  RestoreSeqEntryObjMgrData (top_sep, omdptop, &omdata);
+  NormalizeDescriptorOrder (top_sep);
+  
+  SeqMgrClearFeatureIndexes (entityID, NULL);
+  SeqMgrIndexFeatures (entityID, NULL);
+
+  ObjMgrSetDirtyFlag (entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);    
+  return rval;
+}
+
+
+NLM_EXTERN CharPtr KeywordForStructuredCommentName (UserObjectPtr uop)
+{
+  UserFieldPtr ufp;
+  CharPtr prefix = NULL;
+  CharPtr keyword = NULL;
+
+  if (uop == NULL) {
+    return NULL;
+  }
+
+  for (ufp = uop->data; ufp != NULL && prefix == NULL; ufp = ufp->next) {
+    if (ufp->label != NULL 
+        && StringICmp (ufp->label->str, "StructuredCommentPrefix") == 0
+        && ufp->choice == 1) {
+      prefix = ufp->data.ptrvalue;
+    }
+  }
+
+  if (prefix == NULL) {
+    keyword = NULL;
+  } else if (StringCmp (prefix, "##MIGS-Data-START##") == 0) {
+    keyword = StringSave ("GSC:MIGS:2.1");
+  } else if (StringCmp (prefix, "##MIMS-Data-START##") == 0) {
+    keyword = StringSave ("GSC:MIMS:2.1");
+  } else if (StringCmp (prefix, "##MIENS-Data-START##") == 0) {
+    keyword = StringSave ("GSC:MIENS:2.1");
+  }
+
+  return keyword;
+}
+
+
+static Boolean HasKeyword (BioseqPtr bsp, CharPtr keyword)
+{
+  SeqDescPtr sdp;
+  SeqMgrDescContext context;
+  GBBlockPtr gb;
+  Boolean    has_keyword = FALSE;
+  ValNodePtr vnp;
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_genbank, &context);
+       sdp != NULL && !has_keyword;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_genbank, &context)) {
+    if ((gb = (GBBlockPtr) sdp->data.ptrvalue) != NULL) {
+      for (vnp = gb->keywords; vnp != NULL && !has_keyword; vnp = vnp->next) {
+        if (StringCmp (vnp->data.ptrvalue, keyword) == 0) {
+          has_keyword = TRUE;
+        }
+      }
+    }
+  }
+  return has_keyword;
+}
+
+
+static void AddKeywordToBioseq (BioseqPtr bsp, CharPtr keyword)
+{
+  SeqDescPtr sdp;
+  SeqEntryPtr sep;
+  GBBlockPtr gb;
+  ValNodePtr vnp;
+
+  sep = SeqMgrGetSeqEntryForData (bsp);
+  if (sep == NULL) {
+    return;
+  }
+  sdp = GetDescrOnSeqEntry (sep, Seq_descr_genbank);
+  if (sdp == NULL) {
+    sdp = NewDescrOnSeqEntry (sep, Seq_descr_genbank);
+    if (sdp != NULL) {
+      sdp->data.ptrvalue = (Pointer) GBBlockNew ();
+    }
+  }
+  if (sdp == NULL) return;
+  gb = (GBBlockPtr) sdp->data.ptrvalue;
+  if (gb == NULL) {
+    gb = GBBlockNew ();
+    sdp->data.ptrvalue = gb;
+  }
+  if (gb == NULL) return;
+
+  for (vnp = gb->keywords; vnp; vnp = vnp->next) {
+    if (StringCmp((CharPtr)vnp->data.ptrvalue, keyword) == 0) {
+      return;
+    }
+  }
+  ValNodeAddPointer (&(gb->keywords), 0, StringSave (keyword));
+}
+
+
+static void RemoveKeywordFromBioseq (BioseqPtr bsp, CharPtr keyword)
+{
+  SeqDescPtr sdp;
+  SeqMgrDescContext context;
+  GBBlockPtr gb;
+  ValNodePtr vnp, vnp_next, prev;
+  ObjValNodePtr ovn;
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_genbank, &context);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_genbank, &context)) {
+    gb = (GBBlockPtr) sdp->data.ptrvalue;
+    if (gb != NULL) {
+      prev = NULL;
+      for (vnp = gb->keywords; vnp; vnp = vnp_next) {       
+        vnp_next = vnp->next;
+        if (StringCmp((CharPtr)vnp->data.ptrvalue, keyword) == 0) {
+          if (prev == NULL) {
+            gb->keywords = vnp->next;
+          } else {
+            prev->next = vnp->next;
+          }
+          vnp->next = NULL;
+          vnp = ValNodeFreeData (vnp);
+        } else {
+          prev = vnp;
+        }
+      }
+      if (GBBlockIsCompletelyEmpty(gb)) {
+        if (sdp->extended) {
+          ovn = (ObjValNodePtr) sdp;
+          ovn->idx.deleteme = TRUE;
+        }
+      }
+    }
+  }
+}
+
+
+NLM_EXTERN Boolean HasKeywordForStructuredCommentName (BioseqPtr bsp, UserObjectPtr uop)
+{
+  CharPtr keyword = NULL;
+  Boolean    has_keyword = FALSE;
+
+  if (bsp == NULL || uop == NULL || (keyword = KeywordForStructuredCommentName(uop)) == NULL) {
+    return FALSE;
+  }
+
+  has_keyword = HasKeyword(bsp, keyword);
+  
+  keyword = MemFree (keyword);
+  return has_keyword;
+}
+
+
+static void AddStructuredCommentKeywordsCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqDescPtr sdp;
+  SeqMgrDescContext context;
+  UserObjectPtr     uop;
+  CharPtr           keyword;
+
+  if (bsp == NULL) {
+    return;
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &context);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &context)) {
+    uop = (UserObjectPtr) sdp->data.ptrvalue;
+    keyword = KeywordForStructuredCommentName(uop);
+    if (keyword != NULL) {
+      if (IsStructuredCommentValid (uop, NULL, NULL) == eFieldValid_Valid) {
+        AddKeywordToBioseq(bsp, keyword);
+      }
+    }
+    keyword = MemFree (keyword);
+  }
+}
+
+
+NLM_EXTERN void AddStructuredCommentKeywords (Uint2 entityID)
+{
+  SeqEntryPtr sep;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL) {
+    return;
+  }
+
+  VisitBioseqsInSep (sep, NULL, AddStructuredCommentKeywordsCallback);
+
+  ObjMgrSetDirtyFlag (entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);    
+}
+
+
+static void RemoveStructuredCommentKeywordsCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqDescPtr sdp;
+  SeqMgrDescContext context;
+  UserObjectPtr     uop;
+  CharPtr           keyword;
+
+  if (bsp == NULL || ISA_aa (bsp->mol)) {
+    return;
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &context);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &context)) {
+    uop = (UserObjectPtr) sdp->data.ptrvalue;
+    keyword = KeywordForStructuredCommentName(uop);
+    if (keyword != NULL) {
+      if (IsStructuredCommentValid (uop, NULL, NULL) != eFieldValid_Valid) {
+        RemoveKeywordFromBioseq(bsp, keyword);
+      }
+    }
+    keyword = MemFree (keyword);
+  }
+}
+
+
+NLM_EXTERN void RemoveStructuredCommentKeywords (Uint2 entityID)
+{
+  SeqEntryPtr sep;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL) {
+    return;
+  }
+
+  VisitBioseqsInSep (sep, NULL, RemoveStructuredCommentKeywordsCallback);
+  DeleteMarkedObjects (entityID, 0, NULL);
+
+  ObjMgrSetDirtyFlag (entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);    
+}
+
+
+static void TrimPrimerSeqJunkFromString (CharPtr str)
+{
+  Int4 len;
+  CharPtr src, dst;
+  
+  if (StringHasNoText (str)) {
+    return;
+  }
+  len = StringLen (str);
+
+  if (len >= 7 && StringNCmp (str, "5'-", 3) == 0 && StringCmp (str + len - 3, "-3'") == 0) {
+    src = str + 3;
+    dst = str;
+    len -= 6;
+
+    while (len > 0) {
+      *dst = *src;
+      src++;
+      dst++;
+      len--;
+    }
+    *dst = 0;
+  } else if ((len >= 5 && StringNCmp (str, "5-", 2) == 0 && StringCmp (str + len - 2, "-3") == 0)
+             || (len >= 5 && StringNCmp (str, "5'", 2) == 0 && StringCmp (str + len - 2, "3'") == 0)) {
+    src = str + 2;
+    dst = str;
+    len -= 4;
+    while (len > 0) {
+      *dst = *src;
+      src++;
+      dst++;
+      len--;
+    }
+    *dst = 0;
+  }
+
+}
+
+
+static Boolean TrimPrimerSeqJunkOnBioSource (BioSourcePtr biop, FILE *log_fp)
+{
+  SubSourcePtr ssp;
+  CharPtr      orig = NULL;
+  Boolean      rval = FALSE;
+
+  if (biop == NULL) {
+    return FALSE;
+  }
+
+  for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
+    if (ssp->subtype == SUBSRC_fwd_primer_seq
+      || ssp->subtype == SUBSRC_rev_primer_seq) {
+      if (log_fp != NULL) {
+        orig = StringSave (ssp->name);
+      }
+      TrimPrimerSeqJunkFromString (ssp->name);
+      if (log_fp != NULL && StringCmp (orig, ssp->name) != 0) {
+        fprintf (log_fp, "Changed primer seq from %s to %s\n", orig, ssp->name);
+        rval = TRUE;
+      }
+      orig = MemFree (orig);
+    }
+  }
+  return rval;
+}
+
+
+static void TrimPrimerSeqJunkDescrCallback (SeqDescrPtr sdp, Pointer data)
+{
+  LogInfoPtr lip;
+
+
+  if (sdp != NULL && sdp->choice == Seq_descr_source) {
+    lip = (LogInfoPtr) data;
+    if (TrimPrimerSeqJunkOnBioSource (sdp->data.ptrvalue, lip == NULL ? NULL : lip->fp) && lip != NULL) {
+      lip->data_in_log = TRUE;
+    }
+  }
+}
+
+
+static void TrimPrimerSeqJunkFeatCallback (SeqFeatPtr sfp, Pointer data)
+{
+  LogInfoPtr lip;
+
+  if (sfp != NULL && sfp->data.choice == SEQFEAT_BIOSRC) {
+    lip = (LogInfoPtr) data;
+    if (TrimPrimerSeqJunkOnBioSource (sfp->data.value.ptrvalue, lip == NULL ? NULL : lip->fp) && lip != NULL) {
+      lip->data_in_log = TRUE;
+    }
+  }
+}
+
+
+NLM_EXTERN Boolean TrimPrimerSeqJunkInSeqEntry (SeqEntryPtr sep, FILE *log_fp)
+{
+  LogInfoData lid;
+
+  MemSet (&lid, 0, sizeof (LogInfoData));
+  lid.fp = log_fp;
+  VisitDescriptorsInSep (sep, &lid, TrimPrimerSeqJunkDescrCallback);
+  VisitFeaturesInSep (sep, &lid, TrimPrimerSeqJunkFeatCallback);
+  return lid.data_in_log;
+}
+
+
+static Boolean IsUSA (CharPtr country)
+{
+  if (StringICmp (country, "USA") == 0
+      || StringICmp (country, "United States of America") == 0
+      || StringICmp (country, "U.S.A.") == 0
+      || StringICmp (country, "U S A") == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static void AbbreviateCitSubAffilStatesCallback (PubdescPtr pdp, Pointer data)
+{
+  ValNodePtr vnp;
+  CitSubPtr  csp;
+  CharPtr    abbrev;
+  LogInfoPtr lip;
+
+  if (pdp == NULL) return;
+  lip = (LogInfoPtr)data;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Sub) {
+      csp = (CitSubPtr) vnp->data.ptrvalue;     
+      if (csp != NULL && csp->authors != NULL 
+          && csp->authors->affil != NULL
+          && IsUSA(csp->authors->affil->country)) {
+        if (StringCmp (csp->authors->affil->country, "USA") != 0) {
+          if (lip != NULL) {
+            if (lip->fp != NULL) {
+              fprintf (lip->fp, "Changed %s to USA\n", csp->authors->affil->country);
+            }
+            lip->data_in_log = TRUE;
+          }
+          csp->authors->affil->country = MemFree (csp->authors->affil->country);
+          csp->authors->affil->country = StringSave ("USA");
+        }
+        abbrev = GetStateAbbreviation (csp->authors->affil->sub);
+        if (abbrev != NULL) {
+          if (lip != NULL) {
+            if (lip->fp != NULL) {
+              fprintf (lip->fp, "Changed %s to %s\n", csp->authors->affil->sub, abbrev);
+            }
+            lip->data_in_log = TRUE;
+          }
+          csp->authors->affil->sub = MemFree (csp->authors->affil->sub);
+          csp->authors->affil->sub = StringSave (abbrev);
+        }
+      }
+    }
+  }  
+}
+
+
+NLM_EXTERN Boolean FixUsaAndStateAbbreviations (Uint2 entityID, FILE *log_fp)
+{
+  SeqEntryPtr sep;
+  LogInfoData lid;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL)
+    return FALSE;
+
+  MemSet (&lid, 0, sizeof (LogInfoData));
+  lid.fp = log_fp;
+  VisitPubdescsInSep (sep, &lid, AbbreviateCitSubAffilStatesCallback);
+  return lid.data_in_log;
+}
+
+
+static void AdjustForConsensusSpliceCallback (SeqFeatPtr sfp, Pointer data)
+{
+  SeqLocPtr slp, slp_last = NULL;
+  SeqIdPtr  sip;
+  BioseqPtr bsp;
+  Boolean   partial5, partial3, partial5_last, partial3_last, first = TRUE;
+  Uint1     strand = Seq_strand_unknown, this_strand;
+  Int4      prev_pos = -1, this_pos, exon_len, exon_len_last = -1;
+  CharPtr   buf;
+  Int4      len, start, stop, diff;
+  Boolean   match;
+  SeqIntPtr sint;
+  SeqPntPtr spp;
+  /* variables used for logging change */
+  CharPtr orig_loc = NULL, new_loc;
+  Boolean changed = FALSE;
+  LogInfoPtr lip;
+
+  if (sfp == NULL 
+      || (sfp->data.choice != SEQFEAT_CDREGION && sfp->idx.subtype != FEATDEF_mRNA)
+      || sfp->location == NULL 
+      || (sfp->location->choice != SEQLOC_MIX && sfp->location->choice != SEQLOC_PACKED_INT)
+      || (sip = SeqLocId (sfp->location)) == NULL
+      || (bsp = BioseqLockById (sip)) == NULL) {
+    return;
+  }
+
+  /* we're not going to handle mixed-strand exons */
+  for (slp = sfp->location->data.ptrvalue; slp != NULL && strand != Seq_strand_other; slp = slp->next) {
+    this_strand = SeqLocStrand (slp);
+    if (this_strand == Seq_strand_minus) {
+      if (first) {
+        strand = Seq_strand_minus;
+      } else if (strand != Seq_strand_minus) {
+        strand = Seq_strand_other;
+      }
+    } else {
+      if (strand == Seq_strand_minus) {
+        strand = Seq_strand_other;
+      }
+    }
+    first = FALSE;
+  }
+
+  if (strand == Seq_strand_other) {
+    BioseqUnlock (bsp);
+    return;
+  }
+
+  if ((lip = (LogInfoPtr)data) != NULL && lip->fp != NULL) {
+    orig_loc = SeqLocPrintUseBestID (sfp->location);
+  }
+
+  first = TRUE;
+  for (slp = sfp->location->data.ptrvalue; slp != NULL; slp = slp->next) {
+    CheckSeqLocForPartial (slp, &partial5, &partial3);
+    exon_len = SeqLocLen (slp);
+    if (!first && !partial5 && !partial3_last
+        && (slp_last->choice == SEQLOC_INT || slp_last->choice == SEQLOC_PNT)
+        && (slp->choice == SEQLOC_INT || slp->choice == SEQLOC_PNT)) {      
+      /* check for donor and acceptor pair */
+      /* maximum search space is beginning of previous exon to end of current exon */
+      exon_len_last = SeqLocLen (slp_last);
+      if (strand == Seq_strand_minus) {
+        this_pos = SeqLocStart (slp);
+      } else {
+        this_pos = SeqLocStop (slp);
+      }
+      start = MIN (this_pos, prev_pos);
+      stop = MAX (this_pos, prev_pos);
+      len = stop - start + 1;
+      buf = (CharPtr) MemNew (sizeof (Char) * (len + 1));
+      SeqPortStreamInt (bsp, start, stop, strand, EXPAND_GAPS_TO_DASHES, (Pointer) buf, NULL);
+      if (buf[exon_len_last] == 'G' && (buf[exon_len_last + 1] == 'T' || buf[exon_len_last + 1] == 'C')
+          && buf[len - exon_len - 1] == 'G' && buf[len - exon_len - 2] == 'A') {
+        /* already have donor acceptor pair */
+      } else {
+        match = FALSE;
+        /* search forward */
+        if ((slp_last->choice == SEQLOC_INT || slp_last->choice == SEQLOC_PNT)
+            && slp->choice == SEQLOC_INT) {
+          diff = 1;
+          while (diff < exon_len && !match) {
+            if (buf[exon_len_last + diff - 1] != buf[len - exon_len + diff - 1]) {
+              diff = exon_len;
+            } else if (buf[exon_len_last + diff] == 'G' && buf[exon_len_last + 1 + diff] == 'T'
+                && buf[len - exon_len - 1 + diff] == 'G' && buf[len - exon_len - 2 + diff] == 'A') {
+              match = TRUE;
+            } else {
+              diff++;
+            }
+          }
+          if (match) {
+            if (slp_last->choice == SEQLOC_PNT) {
+              spp = (SeqPntPtr) slp_last->data.ptrvalue;
+              sint = SeqIntNew ();
+              sint->id = spp->id;
+              spp->id = NULL;
+              sint->strand = spp->strand;
+              sint->to = spp->point;
+              sint->from = spp->point;
+              spp = SeqPntFree (spp);
+              slp_last->data.ptrvalue = sint;
+            }
+            sint = (SeqIntPtr) slp_last->data.ptrvalue;
+            if (sint->strand == Seq_strand_minus) {
+              sint->from -= diff;
+            } else {
+              sint->to += diff;
+            }
+            sint = (SeqIntPtr) slp->data.ptrvalue;
+            if (sint->strand == Seq_strand_minus) {
+              sint->to -= diff;
+            } else {
+              sint->from += diff;
+            }
+            changed = TRUE;
+          }
+        }
+        /* search backward */
+        if (!match && slp_last->choice == SEQLOC_INT
+            && (slp->choice == SEQLOC_INT || slp->choice == SEQLOC_PNT)) {
+          diff = 1;
+          while (diff < exon_len_last && !match) {
+            if (buf[exon_len_last - diff] != buf[len - exon_len - diff]) {
+              diff = exon_len_last;
+            } else if (buf[exon_len_last - diff] == 'G' && buf[exon_len_last + 1 - diff] == 'T'
+                && buf[len - exon_len - 1 - diff] == 'G' && buf[len - exon_len - 2 - diff] == 'A') {
+              match = TRUE;
+            } else {
+              diff--;
+            }
+          }
+          if (match) {
+            if (slp->choice == SEQLOC_PNT) {
+              spp = (SeqPntPtr) slp->data.ptrvalue;
+              sint = SeqIntNew ();
+              sint->id = spp->id;
+              spp->id = NULL;
+              sint->strand = spp->strand;
+              sint->to = spp->point;
+              sint->from = spp->point;
+              spp = SeqPntFree (spp);
+              slp->data.ptrvalue = sint;
+            }
+            sint = (SeqIntPtr) slp->data.ptrvalue;
+            if (sint->strand == Seq_strand_minus) {
+              sint->to += diff;
+            } else {
+              sint->from -= diff;
+            }
+            sint = (SeqIntPtr) slp_last->data.ptrvalue;
+            if (sint->strand == Seq_strand_minus) {
+              sint->from += diff;
+            } else {
+              sint->to -= diff;
+            }
+            changed = TRUE;
+          }
+        }
+      }
+
+      buf = MemFree (buf);
+    }
+
+    if (strand == Seq_strand_minus) {
+      prev_pos = SeqLocStop (slp);
+    } else {
+      prev_pos = SeqLocStart (slp);
+    }
+
+    partial5_last = partial5;
+    partial3_last = partial3;
+    slp_last = slp;
+    first = FALSE;
+  }  
+  BioseqUnlock (bsp);
+
+  if (changed) {
+    if (lip->fp != NULL) {
+      new_loc = SeqLocPrintUseBestID (sfp->location);
+      fprintf (lip->fp, "Adjusted location for splice consensus: %s became %s\n", orig_loc, new_loc);
+      new_loc = MemFree (new_loc);
+    }
+    lip->data_in_log = TRUE;
+  }
+  orig_loc = MemFree (orig_loc);
+}
+
+
+NLM_EXTERN Boolean AdjustSeqEntryForConsensusSpliceEx (SeqEntryPtr sep, FILE *log_fp)
+{
+  LogInfoData lid;
+
+  if (sep == NULL) {
+    return FALSE;
+  }
+  MemSet (&lid, 0, sizeof (LogInfoData));
+  lid.fp = log_fp;
+
+  VisitFeaturesInSep (sep, &lid, AdjustForConsensusSpliceCallback);
+  return lid.data_in_log;
+}
+
+NLM_EXTERN void AdjustSeqEntryForConsensusSplice (SeqEntryPtr sep)
+{
+  AdjustSeqEntryForConsensusSpliceEx (sep, NULL);
+}
diff --git a/api/sqnutil3.c b/api/sqnutil3.c
index a4bcf72..3708600 100644
--- a/api/sqnutil3.c
+++ b/api/sqnutil3.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   2/7/00
 *
-* $Revision: 6.514 $
+* $Revision: 6.633 $
 *
 * File Description: 
 *
@@ -1151,6 +1151,41 @@ NLM_EXTERN void StripPCRPrimerAsnFilter (
   }
 }
 
+NLM_EXTERN void StripOrgNamePgcodeAsnFilter (
+  AsnIoPtr aip,
+  AsnIoPtr aop
+)
+
+{
+  AsnModulePtr  amp;
+  AsnTypePtr    atp, atp_se, atp_on;
+  DataVal       dv;
+  OrgNamePtr    onp;
+
+  if (aip == NULL || aop == NULL) return;
+
+  amp = AsnAllModPtr ();
+  if (amp == NULL) return;
+  atp_se = AsnFind ("Seq-entry");
+  atp_on = AsnFind ("OrgName");
+  if (atp_se == NULL || atp_on == NULL) return;
+
+  atp = atp_se;
+
+  while ((atp = AsnReadId (aip, amp, atp)) != NULL) {
+    if (atp == atp_on) {
+      onp = OrgNameAsnRead (aip, atp);
+      onp->pgcode = 0;
+      OrgNameAsnWrite (onp, aop, atp);
+      OrgNameFree (onp);
+    } else {
+      AsnReadVal (aip, atp, &dv);
+      AsnWrite (aop, atp, &dv);
+      AsnKillValue (atp, &dv);
+    }
+  }
+}
+
 static void AddGBQualToFeature (
   SeqFeatPtr sfp,
   CharPtr qual,
@@ -1601,23 +1636,12 @@ static void ChangeImpFeatToProt (SeqEntryPtr sep)
   ValNodeFree (cdslist);
 }
 
-static void MergeAdjacentAnnotsCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
 
+NLM_EXTERN void MergeAdjacentAnnotsInList (SeqAnnotPtr sap)
 {
-  BioseqPtr     bsp;
-  BioseqSetPtr  bssp;
   SeqAnnotPtr   nextsap;
-  SeqAnnotPtr   sap;
   SeqFeatPtr    sfp;
 
-  if (sep == NULL || sep->data.ptrvalue == NULL) return;
-  if (IS_Bioseq (sep)) {
-    bsp = (BioseqPtr) sep->data.ptrvalue;
-    sap = bsp->annot;
-  } else if (IS_Bioseq_set (sep)) {
-    bssp = (BioseqSetPtr) sep->data.ptrvalue;
-    sap = bssp->annot;
-  } else return;
   while (sap != NULL) {
     nextsap = sap->next;
     if (sap->type == 1 && nextsap != NULL && nextsap->type == 1) {
@@ -1641,6 +1665,25 @@ static void MergeAdjacentAnnotsCallback (SeqEntryPtr sep, Pointer mydata, Int4 i
   }
 }
 
+
+static void MergeAdjacentAnnotsCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+  BioseqPtr     bsp;
+  BioseqSetPtr  bssp;
+  SeqAnnotPtr   sap;
+
+  if (sep == NULL || sep->data.ptrvalue == NULL) return;
+  if (IS_Bioseq (sep)) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    sap = bsp->annot;
+  } else if (IS_Bioseq_set (sep)) {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    sap = bssp->annot;
+  } else return;
+  MergeAdjacentAnnotsInList (sap);
+}
+
 NLM_EXTERN Boolean PubIsEffectivelyEmpty (PubdescPtr pdp)
 
 {
@@ -2169,6 +2212,7 @@ static FeatdefNameData featdefWithName [] = {
   { FEATDEF_unsure ,             "unsure"             },
   { FEATDEF_USER ,               "User"               },
   { FEATDEF_variation ,          "variation"          },
+  { FEATDEF_VARIATIONREF ,       "VariationRef"       },
   { FEATDEF_virion ,             "virion"             },
   { FEATDEF_V_region ,           "V_region"           },
   { FEATDEF_V_segment ,          "V_segment"          },
@@ -2298,7 +2342,8 @@ static CharPtr featurekeys [] = {
   "oriT",
   "ncRNA",
   "tmRNA",
-  "CloneRef"
+  "CloneRef",
+  "VariationRef"
 };
 
 NLM_EXTERN CharPtr FindKeyFromFeatDefType (Uint1 type, Boolean forGBFF)
@@ -5144,7 +5189,7 @@ static void FindAlignmentsForBioseqCallback (SeqAnnotPtr sap, Pointer userdata)
   {
     if (SeqAlignFindSeqId (salp, sip))
     {
-      salp = SeqAlignListDup(salp);
+      salp = AlnMgr2DupAlnAndIndexes(salp);
       AlnMgr2IndexSeqAlign(salp);
       if (afbp->salp_last == NULL)
       {
@@ -5675,6 +5720,8 @@ NLM_EXTERN Int2 ValidateInferenceQualifier (CharPtr val, Boolean fetchAccn)
       rsult = tmprsult;
     }
   } else if (best == 12) {
+    tmprsult = VALID_INFERENCE;
+    if (StringChr (str, '|') != NULL) {
     ptr = StringRChr (str, ':');
     while (ptr != NULL) {
       *ptr = '\0';
@@ -5690,6 +5737,7 @@ NLM_EXTERN Int2 ValidateInferenceQualifier (CharPtr val, Boolean fetchAccn)
       ptr = nxt;
     }
   }
+  }
 
   MemFree (str);
 
@@ -5946,6 +5994,80 @@ NewClickableItem
 }
 
 
+extern ValNodePtr ClickableItemObjectListFree (ValNodePtr vnp)
+{
+  ValNodePtr vnp_next;
+  ObjValNodePtr ovn;
+
+  while (vnp != NULL) {
+    vnp_next = vnp->next;
+    vnp->next= NULL;
+    if (vnp->extended != 0) {
+      ovn = (ObjValNodePtr) vnp;
+      ovn->idx.scratch = FieldTypeListFree (ovn->idx.scratch);
+    }
+    vnp = ValNodeFree (vnp);
+    vnp = vnp_next;
+  }
+  return vnp;
+}
+
+
+extern ValNodePtr ClickableItemObjectListCopy (ValNodePtr orig)
+{
+  ValNodePtr cpy = NULL, vnp_last = NULL, vnp;
+  ObjValNodePtr ovn, ovn_cpy;
+
+  while (orig != NULL) {
+    if (orig->extended != 0) {
+      ovn = (ObjValNodePtr) orig;
+      ovn_cpy = (ObjValNodePtr) SeqDescrNew (NULL);
+      ovn_cpy->idx.scratch = FieldTypeListCopy (ovn->idx.scratch);
+      ovn_cpy->vn.choice = ovn->vn.choice;
+      ovn_cpy->vn.data.ptrvalue = ovn->vn.data.ptrvalue;
+      if (vnp_last == NULL) {
+        cpy = (ValNodePtr) ovn_cpy;
+      } else {
+        vnp_last->next = (ValNodePtr) ovn_cpy;
+      }
+      vnp_last = (ValNodePtr) ovn_cpy;
+    } else {
+      vnp = ValNodeNew (NULL);
+      vnp->choice = orig->choice;
+      vnp->data.ptrvalue = orig->data.ptrvalue;
+      if (vnp_last == NULL) {
+        cpy = vnp;
+      } else {
+        vnp_last->next = vnp;
+      }
+      vnp_last = vnp;
+    }
+    orig = orig->next;
+  }
+  return cpy;
+}
+
+static ValNodePtr MakeObjectListWithFields (ValNodePtr item_list, ValNodePtr field_list)
+{
+  ValNodePtr vnp, vnp_last = NULL, extended_item_list = NULL;
+  ObjValNodePtr ovn;
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    ovn = (ObjValNodePtr) SeqDescrNew (NULL);
+    ovn->vn.choice = vnp->choice;
+    ovn->vn.data.ptrvalue = vnp->data.ptrvalue;
+    ovn->idx.scratch = FieldTypeListCopy (field_list);
+    if (vnp_last == NULL) {
+      extended_item_list = (ValNodePtr)ovn;
+    } else {
+      vnp_last->next = (ValNodePtr)ovn;
+    }
+    vnp_last = (ValNodePtr)ovn;
+  }
+  return extended_item_list;
+}
+
+
 extern ClickableItemPtr ClickableItemFree (ClickableItemPtr cip)
 {
   if (cip != NULL)
@@ -5955,7 +6077,7 @@ extern ClickableItemPtr ClickableItemFree (ClickableItemPtr cip)
     {
       (cip->datafree_func) (cip->callback_data);
     }
-    cip->item_list = ValNodeFree (cip->item_list);
+    cip->item_list = ClickableItemObjectListFree (cip->item_list);
   
     cip->subcategories = FreeClickableList (cip->subcategories);
     cip = MemFree (cip);
@@ -5979,6 +6101,38 @@ extern ValNodePtr FreeClickableList (ValNodePtr list)
 }
 
 
+extern Boolean AnyDiscrepanciesChosen (ValNodePtr cip_list)
+{
+  ClickableItemPtr cip;
+  Boolean          any_chosen = FALSE;
+
+  while (cip_list != NULL && !any_chosen) {
+    cip = (ClickableItemPtr) cip_list->data.ptrvalue;
+    if (cip != NULL
+        && (cip->chosen 
+            || (cip->expanded && AnyDiscrepanciesChosen (cip->subcategories)))) {
+      any_chosen = TRUE;
+    }
+    cip_list = cip_list->next;
+  }
+  return any_chosen;
+}
+
+
+NLM_EXTERN void ChooseAllDiscrepancies (ValNodePtr cip_list)
+{
+  ClickableItemPtr cip;
+
+  while (cip_list != NULL) {
+    cip = cip_list->data.ptrvalue;
+    if (cip != NULL) {
+      cip->chosen = TRUE;
+    }
+    cip_list = cip_list->next;
+  }
+}
+
+
 NLM_EXTERN int LIBCALLBACK SortVnpByClickableItemChosen (VoidPtr ptr1, VoidPtr ptr2)
 
 {
@@ -6110,7 +6264,7 @@ static ValNodePtr ItemListFromSubcategories (ValNodePtr subcategories)
   for (vnp = subcategories; vnp != NULL; vnp = vnp->next) {
     cip = (ClickableItemPtr) vnp->data.ptrvalue;
     if (cip != NULL) {
-      ValNodeLinkCopy (&item_list, cip->item_list);
+      ValNodeLink (&item_list, ClickableItemObjectListCopy(cip->item_list));
     }
   }
   return item_list;
@@ -6205,6 +6359,7 @@ extern void ConvertGlobalDiscrepancyToText (GlobalDiscrepancyPtr g, Boolean use_
 
   if (g == NULL || g->data_choice == 0) return;
   
+  MemSet (&vn, 0, sizeof (ValNode));
   vn.choice = g->data_choice;
   vn.data.ptrvalue = g->data;
   vn.next = NULL;
@@ -7052,17 +7207,42 @@ extern void AddMissingAndSuperfluousGeneDiscrepancies (ValNodePtr PNTR discrepan
 }
 
 
+static Boolean CommentHasPhrase (CharPtr comment, CharPtr phrase)
+{
+  CharPtr cp;
+  Int4    len;
+
+  if (StringHasNoText (comment) || StringHasNoText (phrase)) {
+    return FALSE;
+  }
+  len = StringLen (phrase);
+  cp = comment;
+  while (cp != NULL) {
+    if (StringNICmp (comment, phrase, len) == 0 && (*(cp + len) == ';' || *(cp + len) == 0)) {
+      return TRUE;
+    } else {
+      cp = StringChr (cp, ';');
+      if (cp != NULL) {
+        cp++;
+        cp += StringSpn (cp, " ");
+      }
+    }
+  }
+  return FALSE;
+}
+
+
 static Boolean IsOkSuperfluousGene (SeqFeatPtr sfp)
 {
   GeneRefPtr grp;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_GENE) {
     return FALSE;
-  } else if (StringICmp (sfp->comment, "coding region not determined") == 0) {
+  } else if (CommentHasPhrase (sfp->comment, "coding region not determined")) {
     return TRUE;
   } else if ((grp = sfp->data.value.ptrvalue) == NULL) {
     return FALSE;
-  } else if (StringICmp (grp->desc, "coding region not determined") == 0) {
+  } else if (CommentHasPhrase (grp->desc, "coding region not determined")) {
     return TRUE;
   } else {
     return FALSE;
@@ -7579,6 +7759,30 @@ NLM_EXTERN ValNodePtr ValNodeDupStringList (ValNodePtr vnp)
 }
       
 
+NLM_EXTERN ValNodePtr ValNodeDupIntList (ValNodePtr vnp)
+{
+  ValNodePtr cpy = NULL, last = NULL, tmp;
+
+  while (vnp != NULL)
+  {
+    tmp = ValNodeNew (NULL);
+    tmp->choice = vnp->choice;
+    tmp->data.intvalue = vnp->data.intvalue;
+    if (last == NULL)
+    {
+      cpy = tmp;
+    }
+    else
+    {
+      last->next = tmp;
+    }
+    last = tmp;
+    vnp = vnp->next;
+  }
+  return cpy;
+}
+      
+
 NLM_EXTERN ValNodePtr FindBadLocusTagsInList (ValNodePtr list)
 {
   ValNodePtr       bad_list = NULL, list_copy;
@@ -8085,12 +8289,63 @@ static void FindInfluenzaStrainCollectionDateMismatches (ValNodePtr PNTR discrep
 }
 
 
+static Boolean PosIsAt3End (Int4 pos, SeqLocPtr slp)
+{
+  BioseqPtr bsp;
+  SeqLocPtr tmp;
+  Int4      seq_end = 0;
+
+  if ((bsp = BioseqFindFromSeqLoc (slp)) == NULL) {
+    return FALSE;
+  } else if (pos == bsp->length - 1) {
+    return TRUE;
+  } else if (bsp->repr != Seq_repr_seg || bsp->seq_ext_type != 1) {
+    return FALSE;
+  } else {
+    for (tmp = (SeqLocPtr)bsp->seq_ext; tmp != NULL; tmp = tmp->next) {
+      seq_end += SeqLocLen (tmp);
+      if (pos == seq_end - 1) {
+        return TRUE;
+      }
+    }
+    bsp = BioseqFind(SeqLocId (slp));
+    if (pos == bsp->length -1) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+    
+
+static Boolean PosIsAt5End (Int4 pos, SeqLocPtr slp)
+{
+  BioseqPtr bsp;
+  Int4      seq_end = 0;
+
+  if (slp == NULL) {
+    return FALSE;
+  } else if (pos == 0) {
+    return TRUE;
+  } else if ((bsp = BioseqFindFromSeqLoc (slp)) == NULL
+             || bsp->repr != Seq_repr_seg || bsp->seq_ext_type != 1) {
+    return FALSE;
+  } else {
+    for (slp = (SeqLocPtr)bsp->seq_ext; slp != NULL; slp = slp->next) {
+      seq_end += SeqLocLen (slp);
+      if (pos == seq_end) {
+        return TRUE;
+      }
+    }
+  }
+  return FALSE;
+}
+
+
 static void FindShortIntronsCallback (SeqFeatPtr sfp, Pointer data)
 {
   SeqLocPtr slp;
   Int4      last_start, last_stop, start, stop;
   Boolean   found_short = FALSE, partial5, partial3;
-  BioseqPtr bsp = NULL;
   Uint1     strand;
 
   if (sfp == NULL || data == NULL) {
@@ -8100,15 +8355,17 @@ static void FindShortIntronsCallback (SeqFeatPtr sfp, Pointer data)
     if (SeqLocLen (sfp->location) < 11) {
       strand = SeqLocStrand (sfp->location);
       CheckSeqLocForPartial (sfp->location, &partial5, &partial3);      
-      if (partial5 && strand != Seq_strand_minus && SeqLocStart (sfp->location) == 0) {
+      if (partial5 && strand != Seq_strand_minus 
+          && PosIsAt5End (SeqLocStart (sfp->location), sfp->location)) {
         /* partial at end of sequence, ok */
-      } else if (partial3 && strand == Seq_strand_minus && SeqLocStart (sfp->location) == 0) {
+      } else if (partial3 && strand == Seq_strand_minus 
+          && PosIsAt5End (SeqLocStop (sfp->location), sfp->location)) {
         /* partial at end of sequence, ok */
-      } else if (partial5 && strand == Seq_strand_minus && (bsp = BioseqFindFromSeqLoc (sfp->location)) != NULL
-                 && SeqLocStop (sfp->location) == bsp->length - 1) {
+      } else if (partial5 && strand == Seq_strand_minus 
+          && PosIsAt3End (SeqLocStart (sfp->location), sfp->location)) {
         /* partial at end of sequence, ok */
-      } else if (partial3 && strand != Seq_strand_minus && (bsp = BioseqFindFromSeqLoc (sfp->location)) != NULL
-                 && SeqLocStop (sfp->location) == bsp->length - 1) {
+      } else if (partial3 && strand != Seq_strand_minus
+          && PosIsAt3End (SeqLocStop (sfp->location), sfp->location)) {
         /* partial at end of sequence, ok */
       } else {
         ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, sfp);
@@ -8170,9 +8427,124 @@ extern void FindShortIntrons (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_l
 }
 
 
+NLM_EXTERN void AddExceptionsToShortIntrons (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+{
+  ValNodePtr vnp;
+  SeqFeatPtr sfp;
+  CharPtr    txt;
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == OBJ_SEQFEAT && (sfp = (SeqFeatPtr) vnp->data.ptrvalue) != NULL
+        && StringStr (sfp->except_text, "low-quality sequence region") == NULL) {
+      SetStringValue (&(sfp->except_text), "low-quality sequence region", ExistingTextOption_append_semi);
+      sfp->excpt = TRUE;
+      if (lip != NULL && lip->fp != NULL) {
+        txt = GetDiscrepancyItemText (vnp);
+        fprintf (lip->fp, "Added low-quality sequence region exception to %s\n", txt);
+        txt = MemFree (txt);
+      }
+    }
+  }
+}
+
+
+
+static Boolean StrandOk (Uint1 strand1, Uint1 strand2)
+{
+  if (strand1 == Seq_strand_minus && strand2 != Seq_strand_minus) {
+    return FALSE;
+  } else if (strand1 != Seq_strand_minus && strand2 == Seq_strand_minus) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+static Boolean IsMixedStrandGeneLocationOk (SeqLocPtr feat_loc, SeqLocPtr gene_loc)
+{
+  SeqLocPtr         gene_subloc, feat_subloc;
+  Uint1             gene_strand, feat_strand;
+  Int4              gene_start, gene_stop;
+  Int4              feat_start, feat_stop;
+
+  gene_subloc = SeqLocFindNext (gene_loc, NULL);
+  feat_subloc = SeqLocFindNext (feat_loc, NULL);
+  while (gene_subloc != NULL && feat_subloc != NULL) {
+
+    gene_strand = SeqLocStrand (gene_subloc);
+    feat_strand = SeqLocStrand (feat_subloc);
+    if (!StrandOk (gene_strand, feat_strand)) {
+      return FALSE;
+    }
+
+    gene_start = SeqLocStart (gene_subloc);
+    gene_stop = SeqLocStop (gene_subloc);
+    feat_start = SeqLocStart (feat_subloc);
+    feat_stop = SeqLocStop (feat_subloc);
+
+    if (gene_strand == Seq_strand_minus) {
+      if (gene_stop != feat_stop) {
+        return FALSE;
+      }
+      while (gene_start != feat_start && feat_subloc != NULL) {
+        while ((feat_subloc = SeqLocFindNext (feat_loc, feat_subloc)) != NULL) {
+          feat_strand = SeqLocStrand (feat_subloc);
+          if (!StrandOk (gene_strand, feat_strand)) {
+            return FALSE;
+          }
+          feat_start = SeqLocStart (feat_subloc);
+          if (feat_start < gene_start) {
+            return FALSE;
+          } else if (feat_start == gene_start) {
+            break;
+          }
+        }
+      }
+
+    } else {
+      if (gene_start != feat_start) {
+        return FALSE;
+      }
+      while (gene_stop != feat_stop && feat_subloc != NULL) {
+        while ((feat_subloc = SeqLocFindNext (feat_loc, feat_subloc)) != NULL) {
+          feat_strand = SeqLocStrand (feat_subloc);
+          if (!StrandOk (gene_strand, feat_strand)) {
+            return FALSE;
+          }
+          feat_stop = SeqLocStop (feat_subloc);
+          if (feat_stop > gene_stop) {
+            return FALSE;
+          } else if (feat_stop == gene_stop) {
+            break;
+          }
+        }
+      }
+    }
+    if (feat_subloc == NULL) {
+      return FALSE;
+    }
+    gene_subloc = SeqLocFindNext (gene_loc, gene_subloc);
+    feat_subloc = SeqLocFindNext (feat_loc, feat_subloc);
+  }
+  
+
+  if (gene_subloc != NULL || feat_subloc != NULL) 
+  {
+    return FALSE;
+  }
+  else
+  {
+    return TRUE;
+  }
+}
+
+
 static Boolean 
 IsGeneLocationOk 
-(SeqMgrFeatContextPtr feat_context, 
+(SeqFeatPtr           feat,
+ SeqMgrFeatContextPtr feat_context, 
+ SeqFeatPtr           gene,
  SeqMgrFeatContextPtr gene_context,
  BioseqPtr            bsp)
 {
@@ -8183,6 +8555,11 @@ IsGeneLocationOk
   {
     return FALSE;
   }  
+  else if (feat_context->mixed_strand || gene_context->mixed_strand) 
+  {
+    /* special handling for trans-spliced */
+    return IsMixedStrandGeneLocationOk (feat->location, gene->location);
+  }
   else if ((feat_context->strand == Seq_strand_minus && gene_context->strand != Seq_strand_minus)
            || (feat_context->strand != Seq_strand_minus && gene_context->strand == Seq_strand_minus))
   {
@@ -8288,7 +8665,7 @@ CheckFeatureTypeForLocationDiscrepancies
     if (grp == NULL)
     {
       gene_sfp = SeqMgrGetOverlappingGene (sfp->location, &gene_context);
-      if (gene_sfp != NULL && !IsGeneLocationOk (&context, &gene_context, bsp) && sfp->idx.subtype != exclude_featdef)
+      if (gene_sfp != NULL && !IsGeneLocationOk (sfp, &context, gene_sfp, &gene_context, bsp) && sfp->idx.subtype != exclude_featdef)
       {
         ValNodeAddPointer (discrepancy_list, 0, GeneLocationDiscrepancy(feature_type, gene_sfp, sfp));
       }
@@ -8302,7 +8679,7 @@ CheckFeatureTypeForLocationDiscrepancies
       {
         if (GeneRefMatch (gene_sfp->data.value.ptrvalue, grp) && gene_context.strand == context.strand)
         {
-          if (IsGeneLocationOk (&context, &gene_context, bsp))
+          if (IsGeneLocationOk (sfp, &context, gene_sfp, &gene_context, bsp))
           {
             found_match = TRUE;
           }
@@ -8797,6 +9174,57 @@ extern void FindPseudoDiscrepancies (ValNodePtr PNTR discrepancy_list, ValNodePt
 }
 
 
+NLM_EXTERN void OncallerToolPseudoDiscrepanciesFix (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+{
+  ValNodePtr vnp, entityIDList = NULL;
+  ValNode    vn;
+  SeqFeatPtr sfp, mrna;
+  CharPtr    feat_txt;
+  SeqMgrFeatContext fcontext;
+
+  MemSet (&vn, 0, sizeof (ValNode));
+  vn.choice = OBJ_SEQFEAT;
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == OBJ_SEQFEAT) {
+      sfp = (SeqFeatPtr) vnp->data.ptrvalue;
+      ValNodeAddInt (&entityIDList, 0, sfp->idx.entityID);
+      if (!sfp->pseudo) {
+        if (lip != NULL && lip->fp != NULL) {
+          feat_txt = GetDiscrepancyItemText (vnp);
+          fprintf (lip->fp, "Added pseudo to %s\n", feat_txt);
+          feat_txt = MemFree (feat_txt);
+          lip->data_in_log = TRUE;
+        }
+        sfp->pseudo = TRUE;
+      }
+      if (sfp->data.choice == SEQFEAT_CDREGION) {
+        mrna = SeqMgrGetOverlappingmRNA (sfp->location, &fcontext);
+        if (mrna != NULL && !mrna->pseudo) {
+          if (lip != NULL && lip->fp != NULL) {
+            vn.data.ptrvalue = mrna;
+            feat_txt = GetDiscrepancyItemText (&vn);
+            fprintf (lip->fp, "Added pseudo to %s\n", feat_txt);
+            feat_txt = MemFree (feat_txt);
+            lip->data_in_log = TRUE;
+          }
+          mrna->pseudo = TRUE;
+        }
+      }
+    }
+  }
+
+  entityIDList = ValNodeSort (entityIDList, SortByIntvalue);
+  ValNodeUnique (&entityIDList, SortByIntvalue, ValNodeFree);
+  
+  for (vnp = entityIDList; vnp != NULL; vnp = vnp->next) {
+    ObjMgrSetDirtyFlag (vnp->data.intvalue, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, vnp->data.intvalue, 0, 0);    
+  }
+
+}
+
+
 static void FindJoinedLocations (BioseqPtr bsp, Pointer userdata)
 {
   ValNodePtr PNTR joined_features;
@@ -9385,13 +9813,19 @@ NLM_EXTERN void MarkOverlappingCDSs (ValNodePtr item_list, Pointer data, LogInfo
 }
 
 
+typedef struct twolists {
+  ValNodePtr first_list;
+  ValNodePtr second_list;
+} TwoListsData, PNTR TwoListsPtr;
+
 static void FindContainedCDSs (BioseqPtr bsp, Pointer userdata)
 {
   SeqFeatPtr         sfp, sfp_compare;
   SeqMgrFeatContext  context;
-  ValNodePtr PNTR    contained_cds = NULL;
+  TwoListsPtr        two_lists;
   ValNodePtr         cds_list = NULL;
-  ValNodePtr         contained_list = NULL, vnp, vnp_next, last;
+  ValNodePtr         contained_list_this_strand = NULL, contained_list_other_strand = NULL, vnp, vnp_next, last;
+  ValNodePtr         last_this_strand = NULL, last_other_strand = NULL;
   Int2               loc_compare;
   Uint1              strand, strand_compare;
   
@@ -9400,7 +9834,7 @@ static void FindContainedCDSs (BioseqPtr bsp, Pointer userdata)
     return;
   }
   
-  contained_cds = (ValNodePtr PNTR) userdata;
+  two_lists = (TwoListsPtr) userdata;
   last = NULL;
   for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, FEATDEF_CDS, &context);
        sfp != NULL;
@@ -9422,28 +9856,42 @@ static void FindContainedCDSs (BioseqPtr bsp, Pointer userdata)
     {
       sfp_compare = vnp_next->data.ptrvalue;
       strand_compare = SeqLocStrand (sfp_compare->location);
-      if ((strand == Seq_strand_minus && strand_compare != Seq_strand_minus)
-          || (strand != Seq_strand_minus && strand_compare == Seq_strand_minus)) 
-      {
-        continue;
-      }
       loc_compare = SeqLocCompare (sfp->location, sfp_compare->location);
       if (loc_compare == SLC_A_IN_B || loc_compare == SLC_B_IN_A || loc_compare == SLC_A_EQ_B)
       {
-        if (!AlreadyInList (contained_list, sfp)) 
+        if (StrandOk (strand, strand_compare)) {
+          if (!AlreadyInList (contained_list_this_strand, sfp)) 
         {
-          ValNodeAddPointer (&last, OBJ_SEQFEAT, sfp);
-          if (contained_list == NULL) 
+            ValNodeAddPointer (&last_this_strand, OBJ_SEQFEAT, sfp);
+            if (contained_list_this_strand == NULL) 
+            {
+              contained_list_this_strand = last_this_strand;
+            }
+          }
+          if (!AlreadyInList (contained_list_this_strand, sfp_compare)) 
+          {
+            ValNodeAddPointer (&last_this_strand, OBJ_SEQFEAT, sfp_compare);
+            if (contained_list_this_strand == NULL) 
+            {
+              contained_list_this_strand = last_this_strand;
+            }
+          }
+        } else {
+          if (!AlreadyInList (contained_list_other_strand, sfp)) 
+          {
+            ValNodeAddPointer (&last_other_strand, OBJ_SEQFEAT, sfp);
+            if (contained_list_other_strand == NULL) 
           {
-            contained_list = last;
+              contained_list_other_strand = last_other_strand;
           }
         }
-        if (!AlreadyInList (contained_list, sfp_compare)) 
+          if (!AlreadyInList (contained_list_other_strand, sfp_compare)) 
         {
-          ValNodeAddPointer (&last, OBJ_SEQFEAT, sfp_compare);
-          if (contained_list == NULL) 
+            ValNodeAddPointer (&last_other_strand, OBJ_SEQFEAT, sfp_compare);
+            if (contained_list_other_strand == NULL) 
           {
-            contained_list = last;
+              contained_list_other_strand = last_other_strand;
+            }
           }
         }
       }
@@ -9451,10 +9899,8 @@ static void FindContainedCDSs (BioseqPtr bsp, Pointer userdata)
   }
   cds_list = ValNodeFree (cds_list);
   
-  if (contained_list != NULL)
-  {
-    ValNodeLink (contained_cds, contained_list);
-  }
+  ValNodeLink (&(two_lists->first_list), contained_list_this_strand);
+  ValNodeLink (&(two_lists->second_list), contained_list_other_strand);
 }
 
 
@@ -9462,25 +9908,34 @@ extern void AddContainedCodingRegionDiscrepancies (ValNodePtr PNTR discrepancy_l
 {
   ClickableItemPtr dip;
   CharPtr            bad_fmt = "%d coding regions are completely contained in another coding region.";
-  ValNodePtr         contained_cds = NULL, vnp;
+  CharPtr          same_strand_fmt = "%d coding regions are completely contained in another coding region on the same strand.";
+  CharPtr          other_strand_fmt = "%d coding regions are completely contained in another coding region, but on the opposite strand.";
+  TwoListsData     two_lists;
+  ValNodePtr       vnp, subcategories = NULL, item_list;
+  
 
   if (discrepancy_list == NULL)
   {
     return;
   }
   
+  MemSet (&two_lists, 0, sizeof (TwoListsData));
+  
   for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    VisitBioseqsInSep (vnp->data.ptrvalue, &contained_cds, FindContainedCDSs);
+    VisitBioseqsInSep (vnp->data.ptrvalue, &two_lists, FindContainedCDSs);
   }
   
-  if (contained_cds != NULL)
-  {
-    dip = NewClickableItem (DISC_CONTAINED_CDS, bad_fmt, contained_cds);
-
-    if (dip != NULL)
-    {
+  if (two_lists.first_list != NULL && two_lists.second_list != NULL) {
+    ValNodeAddPointer (&subcategories, 0, NewClickableItem (DISC_CONTAINED_CDS, same_strand_fmt, two_lists.first_list));
+    ValNodeAddPointer (&subcategories, 0, NewClickableItem (DISC_CONTAINED_CDS, other_strand_fmt, two_lists.second_list));
+    item_list = ItemListFromSubcategories (subcategories);
+    dip = NewClickableItem (DISC_CONTAINED_CDS, bad_fmt, item_list);
+    dip->subcategories = subcategories;
       ValNodeAddPointer (discrepancy_list, 0, dip);
-    }
+  } else if (two_lists.first_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_CONTAINED_CDS, same_strand_fmt, two_lists.first_list));
+  } else if (two_lists.second_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_CONTAINED_CDS, other_strand_fmt, two_lists.second_list));
   }
 }
 
@@ -9752,6 +10207,69 @@ extern void FindShortSequences (ValNodePtr PNTR discrepancy_list, ValNodePtr sep
   }
 }
 
+
+static void FindShortProtSequencesCallback (BioseqPtr bsp, Pointer userdata)
+{
+  ValNodePtr PNTR bioseq_list;
+  BioseqSetPtr    bssp;
+  SeqDescrPtr     sdp;
+  SeqMgrDescContext context;
+  MolInfoPtr        mip;
+  
+  if (bsp == NULL || !ISA_aa (bsp->mol) || userdata == NULL || bsp->length >= 50)
+  {
+    return;
+  }
+  
+  if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
+    bssp = (BioseqSetPtr) bsp->idx.parentptr;
+    if (bssp != NULL && bssp->_class == BioseqseqSet_class_parts) {
+      return;
+    }
+  }
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
+  if (sdp != NULL && (mip = (MolInfoPtr) sdp->data.ptrvalue) != NULL
+      && mip->completeness != 1) {
+    return;
+  }
+  
+  bioseq_list = (ValNodePtr PNTR) userdata;
+  
+  ValNodeAddPointer (bioseq_list, OBJ_BIOSEQ, bsp);
+}
+
+
+static void FindShortProtSequences (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ClickableItemPtr dip;
+  CharPtr            bad_fmt = "%d protein sequences are shorter than 50 aa.";
+  ValNodePtr         bioseq_list = NULL, vnp;
+  
+  if (discrepancy_list == NULL) return;
+  
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitBioseqsInSep (vnp->data.ptrvalue, &bioseq_list, FindShortProtSequencesCallback);
+  }
+  
+  if (bioseq_list != NULL)
+  {
+    dip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+    if (dip != NULL)
+    {
+      dip->clickable_item_type = SHORT_PROT_SEQUENCES;
+      dip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (bad_fmt) + 15));
+      sprintf (dip->description, bad_fmt, ValNodeLen (bioseq_list));
+      dip->callback_func = NULL;
+      dip->datafree_func = NULL;
+      dip->callback_data = NULL;
+      dip->item_list = bioseq_list;
+      ValNodeAddPointer (discrepancy_list, 0, dip);
+    }
+  }
+}
+
+
 typedef struct sdpandbsp {
   SeqDescrPtr sdp;
   BioseqPtr bsp;
@@ -9906,6 +10424,16 @@ extern void FindNonmatchingContigSources (ValNodePtr PNTR discrepancy_list, ValN
 }
 
 
+static Boolean IsWordChar (Char ch)
+{
+  if (isalpha (ch) || isdigit (ch)) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
 static Boolean DoesStringContainPhrase (CharPtr str, CharPtr phrase, Boolean case_sensitive, Boolean whole_word)
 {
   CharPtr cp;
@@ -9926,8 +10454,8 @@ static Boolean DoesStringContainPhrase (CharPtr str, CharPtr phrase, Boolean cas
     if (whole_word) {
       while (cp != NULL && !rval) {
         len = StringLen (phrase);
-        if ((cp == str || !isalpha (*(cp - 1)))
-            && (cp [len] == 0 || !isalpha (cp [len]))) {
+        if ((cp == str || !IsWordChar (*(cp - 1)))
+            && (cp [len] == 0 || !IsWordChar (cp [len]))) {
           rval = TRUE;
         } else {
           if (case_sensitive) {
@@ -9944,364 +10472,1101 @@ static Boolean DoesStringContainPhrase (CharPtr str, CharPtr phrase, Boolean cas
   return rval;
 }
 
+typedef Boolean (*SuspectProductNameSearchFunc) PROTO ((CharPtr, CharPtr));
+
+typedef struct suspectproductname {
+  CharPtr pattern;
+  SuspectProductNameSearchFunc search_func;
+} SuspectProductNameData, PNTR SuspectProductNamePtr;
 
-static CharPtr suspect_product_names[] = 
+
+static Boolean EndsWithPattern (CharPtr pattern, CharPtr search)
 {
-"like", /* "end with" start */
-"repeat",
-"domain",
-"fold",
-"motif", /* "end with" end */
-"containing", /* "start with" start */
-"from", /* "start with" end */
-"N-term", /* term start */
-"N term",
-"C-term",
-"C term", /* term end */
-"may contain a plural", /* plural */
-"Brackets or parenthesis [] ()", /* brackets */
-"ending with period, comma, hyphen, underscore, colon, or forward slash",
-"beginning with period, comma, or hyphen",
-"unknown", /* unknown */
-"COG", /* whole word case sensitive start */
-"EST", /* whole word case sensitive end */
-"Subtilis", /* wholeword start */
-"coli",
-"pseudo",
-"Yersinia",
-"gene",
-"genes",
-"homo", /* whole word end */
-"protein", /* singleword start */
-"putative",
-"probable",
-"protein-containing",
-"protein containing",
-"transposase of", /* singleword end */
-"Similar to",
-"Related to",
-"interrupt",
-"Homolog",
-"Homologue",
-"Fragment",
-"Frameshift",
-"Intein",
-"Chloroplast",
-"Mitochondrial",
-"puatative",
-"putaive",
-"putaitve",
-"putatitve",
-"putataive",
-"putatuve",
-"ortholog",
-"orthologue",
-"paralog",
-"paralogue",
-"bifunctional protein",
-"pseudogene",
-"frame shift",
-"protien",
-"partial",
-"B.subtilis",
-"E.coli",
-"Escherichia",
-"Bacillus",
-"Staphlococcus",
-"aureus",
-"Salmonella",
-"Streptococcus",
-"Staphlococcal",
-"streptococcal",
-"Helicobacter",
-"pylori",
-"Campylobacter",
-"Jejuni",
-"Pestis",
-"Rhodobacter",
-"sphaeroides",
-"or related",
-"authentic point mutation",
-"novel protein",
-"ttg start",
-"domain protein domain protein",
-"deletion",
-"truncat",
-"hypothteical",
-"hypotethical",
-"hypothetcial",
-"consevered",
-"cotaining",
-"gIycerol",
-"haemagglutination",
-"family family",
-"domain domain",
-"putative, putative",
-"putative putative",
-"putative probable",
-"probable putative",
-"similar",
-"characterised",
-"characterisation",
-"uncharacterised",
-"putatvie",
-"putaitve",
-"simmilar",
-"ribosoml",
-"transcirbed",
-"recognised",
-"heam",
-"haem",
-"active site",
-"human",
-"Arabidopsis",
-"domian",
-"facotr",
-"proein",
-"homo sapiens",
-"sapiens",
-"?",
-"#",
-". "
-};
+  Int4 phrase_len, len;
 
-const int num_suspect_product_names = sizeof (suspect_product_names) / sizeof (CharPtr);
+  phrase_len = StringLen (pattern);
+  len = StringLen (search);
 
-const int end_with_start = 0;
-const int end_with_end = 4;
-const int start_with_start = 5;
-const int start_with_end = 6;
+  if (len >= phrase_len && StringICmp (search + len - phrase_len, pattern) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
 
-const int term_start = 7;
-const int term_end = 10;
 
-const int plural_name = 11;
-const int brackets_name = 12;
-const int end_with_punct_name = 13;
-const int begin_with_punct_name = 14;
+static Boolean StartsWithPattern (CharPtr pattern, CharPtr search)
+{
+  Int4 phrase_len, len;
 
-const int unknown_name = 15;
+  phrase_len = StringLen (pattern);
+  len = StringLen (search);
 
-const int wholeword_casesensitive_start = 16;
-const int wholeword_casesensitive_end = 17;
+  if (len >= phrase_len && StringNICmp (search, pattern, phrase_len) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
 
-const int wholeword_start = 18;
-const int wholeword_end = 24;
 
-const int singleword_start = 25;
-const int singleword_end = 30;
+static Boolean ProductContainsTerm (CharPtr pattern, CharPtr search)
+{
+  CharPtr str;
+
+  /* don't bother searching for c-term or n-term if product name contains "domain" */
+  if (StringISearch (search, "domain") != NULL) {
+    return FALSE;
+  }
 
+  str = StringISearch(search, pattern);
+  /* c-term and n-term must be either first word or separated from other word by space, num, or punct */
+  if (str != NULL && (str == search || !isalpha (*(str - 1)))) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
 
-static Boolean MayContainPlural (CharPtr str)
+static Boolean MayContainPlural (CharPtr pattern, CharPtr search)
 {
   CharPtr cp;
+  Char    last_letter, second_to_last_letter, next_letter;
   Int4    word_len = 0;
   Boolean may_contain_plural = FALSE;
+  CharPtr word_skip = " ,";
 
-  if (str == NULL) return FALSE;
-  cp = str;
+  if (search == NULL) return FALSE;
+  cp = search;
   while (*cp != 0 && !may_contain_plural) {
-    if (isalpha (*cp)) {
-      if (word_len > 2 
-        && *cp == 's'
-        && *(cp - 1) != 's'
-        && *(cp - 1) != 'i'
-        && *(cp - 1) != 'u'
-        && (*(cp + 1) == ',' || *(cp + 1) == 0)) {
+    word_len = StringCSpn (cp, word_skip);
+    last_letter = *(cp + word_len - 1);    
+    if (last_letter == 's') {
+      if (word_len >=5 && StringNCmp (cp + word_len - 5, "trans", 5) == 0) {
+        /* not plural */
+        cp = cp + word_len;
+        cp += StringSpn (cp, word_skip);
+      } else if (word_len > 2
+                 && (second_to_last_letter = *(cp + word_len - 2)) != 's'
+                 && second_to_last_letter != 'i'
+                 && second_to_last_letter != 'u'
+                 && ((next_letter = *(cp + word_len)) == ',' || next_letter == 0)) {
         may_contain_plural = TRUE;
       } else {
-        word_len++;
+        cp = cp + word_len;
+        cp += StringSpn (cp, word_skip);
       }
     } else {
-      word_len = 0;
+      cp = cp + word_len;
+      cp += StringSpn (cp, word_skip);
     }
-    cp++;
   }
   return may_contain_plural;
 }
 
-static void FindSuspectProductNamesCallback (SeqFeatPtr sfp, Pointer userdata)
+
+static CharPtr FindFirstOpen (CharPtr cp)
 {
-  ValNodePtr PNTR feature_list;
-  Int4            k, len, phrase_len;
-  ProtRefPtr      prp;
-  ValNodePtr      vnp;
-  CharPtr         str;
-  BioseqPtr       bsp;
-  SeqFeatPtr      cds;
+  CharPtr pa, ba;
+
+  if (cp == NULL) {
+    return NULL;
+  }
+  pa = StringChr (cp, '(');
+  ba = StringChr (cp, '[');
+  if (pa == NULL) {
+    return ba;
+  } else if (ba == NULL || ba > pa) {
+    return pa;
+  } else {
+    return ba;
+  }
+}
+
+
+static Char GetClose (Char ch) 
+{
+  if (ch == '(') {
+    return ')';
+  } else if (ch == '[') {
+    return ']';
+  } else if (ch == '{') {
+    return '}';
+  } else {
+    return ch;
+  }
+}
+
+
+static Boolean SkipBracketOrParen (CharPtr bp, CharPtr start, CharPtr PNTR skip_to)
+{
+  Boolean rval = FALSE;
+  CharPtr ep, ns;
+
+  if (bp - start > 2 && StringNCmp (bp - 3, "NAD(P)", 6) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 6;
+  } else if (StringNCmp (bp, "(NAD(P)H)", 9) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 9;
+  } else if (StringNCmp (bp, "(NAD(P))", 8) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 8;
+  } else if (StringNCmp (bp, "(I)", 3) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 4;
+  } else if (StringNCmp (bp, "(II)", 4) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 5;
+  } else if (StringNCmp (bp, "(III)", 5) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 6;
+  } else if (StringNCmp (bp, "(NADPH)", 7) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 7;
+  } else if (StringNCmp (bp, "(NAD+)", 6) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 6;
+  } else if (StringNCmp (bp, "(NAPPH/NADH)", 12) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 12;
+  } else if (StringNCmp (bp, "(NADP+)", 7) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 7;
+  } else if (StringNCmp (bp, "[acyl-carrier protein]", 22) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 22;
+  } else if (StringNCmp (bp, "[acyl-carrier-protein]", 22) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 22;
+  } else if (StringNCmp (bp, "(acyl carrier protein)", 22) == 0) {
+    rval = TRUE;
+    *skip_to = bp + 22;
+  } else {
+    ns = StringChr (bp + 1, *bp);
+    ep = StringChr (bp + 1, GetClose(*bp));
+    if (ep != NULL && (ns == NULL || ns > ep)) {
+      if (ep - bp < 5) {
+        rval = TRUE;
+        *skip_to = ep + 1;
+      } else if (ep - bp > 3 && StringNCmp (ep - 3, "ing", 3) == 0) {
+        rval = TRUE;
+        *skip_to = ep + 1;
+      }
+    }
+  }
+  return rval;
+}
+
+
+static Boolean ContainsNorMoreSetsOfBracketsOrParentheses (CharPtr search, Int4 n)
+{
+  CharPtr cp, end;
+  Int4    num_found = 0;
+
+  if (search == NULL) {
+    return FALSE;
+  }
+
+  cp = FindFirstOpen(search);
+  while (num_found < n && cp != NULL && *cp != 0) {
+    if (SkipBracketOrParen(cp, search, &cp)) {
+      /* ignore it */
+      cp = FindFirstOpen (cp);
+    } else if ((end = StringChr (cp, GetClose (*cp))) == NULL) {
+      /* skip, doesn't close the bracket */
+      cp = FindFirstOpen (cp + 1);
+    } else {
+      cp = FindFirstOpen (end);
+      num_found ++;
+    }
+  }
+
+  if (num_found >= n) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static Boolean ContainsBracketsOrParentheses (CharPtr pattern, CharPtr search)
+{
+  return ContainsNorMoreSetsOfBracketsOrParentheses (search, 1);
+}
+
+
+static Boolean ContainsTwoSetsOfBracketsOrParentheses (CharPtr pattern, CharPtr search)
+{
+  return ContainsNorMoreSetsOfBracketsOrParentheses (search, 2);
+}
+
+
+static Boolean EndsWithPunct (CharPtr pattern, CharPtr search)
+{
+  Int4 len;
   Char            last_ch;
   
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT || sfp->data.value.ptrvalue == NULL
-      || userdata == NULL)
+  len = StringLen (search);
+  last_ch = search[len - 1];
+  if (last_ch == '.' || last_ch == ',' || last_ch == '-'
+    || last_ch == '_' || last_ch == ':' || last_ch == '/')
   {
-    return;
+    return TRUE;
+  } else {
+    return FALSE;
   }
+}
   
-  prp = (ProtRefPtr) sfp->data.value.ptrvalue;
-  feature_list = (ValNodePtr PNTR) userdata;
 
-  /* add coding region rather than protein */
-  if (sfp->idx.subtype == FEATDEF_PROT) {
-    bsp = BioseqFindFromSeqLoc (sfp->location);
-    if (bsp != NULL) {
-      cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
-      if (cds != NULL) {
-        sfp = cds;
+static Boolean BeginsWithPunct (CharPtr pattern, CharPtr search)
+{
+  if (search == NULL) return FALSE;
+  if (search[0] == '.' || search[0] == ',' || search[0] == '-'
+      || search[0] == '_' || search[0] == ':' || search[0] == '/') {
+    return TRUE;
+  } else {
+    return FALSE;
       }
+}
+
+
+static Boolean ContainsUnknownName (CharPtr pattern, CharPtr search)
+{
+  if (StringISearch(search, pattern) != NULL
+      && StringISearch (search, "protein of unknown function") == NULL
+      && StringISearch (search, "domain of unknown function") == NULL) {
+    return TRUE;
+  } else {
+    return FALSE;
     }
+}
+
+
+static Boolean ContainsWholeWordCaseSensitive (CharPtr pattern, CharPtr search)
+{
+  if (DoesStringContainPhrase (search, pattern, TRUE, TRUE)) {
+    return TRUE;
+  } else {
+    return FALSE;
   }
+}
   
-  for (k = 0; k < num_suspect_product_names; k++)
-  {
-    if (k == plural_name) 
-    {
-      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-      {
-        if (vnp->data.ptrvalue == NULL) continue;
-        if (MayContainPlural(vnp->data.ptrvalue))
-        {
-          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-          break;
+
+static Boolean ContainsWholeWord (CharPtr pattern, CharPtr search)
+{
+  if (DoesStringContainPhrase(search, pattern, FALSE, TRUE)) {
+    return TRUE;
+  } else {
+    return FALSE;
         }
+}
+
+
+static Boolean IsSingleWord (CharPtr pattern, CharPtr search)
+{
+  if (StringICmp (search, pattern) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
       }
+}
+
+
+static CharPtr s_weasels[] = {
+  "hypothetical", 
+  "probable", 
+  "putative",
+  NULL
+};
+
+
+static Boolean IsSingleWordOrWeaselPlusSingleWord (CharPtr pattern, CharPtr search)
+{
+  Int4 i, len;
+
+  if (StringICmp (search, pattern) == 0) {
+    return TRUE;
+  } else {
+    for (i = 0; s_weasels[i] != NULL; i++) {
+      len = StringLen (s_weasels[i]);
+      if (StringNICmp (search, s_weasels[i], len) == 0
+          && StringCmp (search + len + StringSpn (search + len, " "), pattern) == 0) {
+        return TRUE;
     }
-    else if (k == brackets_name)
-    {
-      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-      {
-        if (StringChr (vnp->data.ptrvalue, '[') != NULL
-            || StringChr (vnp->data.ptrvalue, ']') != NULL
-            || StringChr (vnp->data.ptrvalue, '(') != NULL
-            || StringChr (vnp->data.ptrvalue, ')') != NULL)
-        {
-          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-          break;
         }
+    return FALSE;
       }
+}
+
+
+static Boolean NormalSearch (CharPtr pattern, CharPtr search)
+{
+  if (StringISearch(search, pattern) != NULL) {
+    return TRUE;
+  } else {
+    return FALSE;
     }
-    else if (k == end_with_punct_name)
-    {
-      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-      {
-        if (vnp->data.ptrvalue == NULL) continue;
-        len = StringLen (vnp->data.ptrvalue);
-        str = (CharPtr) vnp->data.ptrvalue;
-        last_ch = str[len - 1];
-        if (last_ch == '.' || last_ch == ',' || last_ch == '-'
-          || last_ch == '_' || last_ch == ':' || last_ch == '/')
-        {
-          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-          break;
+}
+
+
+static Boolean FollowedByFamily (CharPtr PNTR str)
+{
+  Int4 word_len;
+
+  if (str == NULL || *str == NULL || **str == 0) {
+    return FALSE;
         }
+
+  word_len = StringCSpn (*str + 1, " ");
+  if (*(*str + word_len + 1) != 0 && StringNCmp (*str + word_len + 2, "family", 6) == 0) {
+    *str = *str + word_len + 7;
+    return TRUE;
+  } else {
+    return FALSE;
       }
+}
+
+
+static Boolean PrecededByPrefix (CharPtr search, CharPtr cp, CharPtr prefix)
+{
+  Int4 len;
+
+  if (search == NULL || cp == NULL || StringHasNoText (prefix)) {
+    return FALSE;
     }
-    else if (k == begin_with_punct_name)
-    {
-      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-      {
-        if (vnp->data.ptrvalue == NULL) continue;
-        str = (CharPtr) vnp->data.ptrvalue;
-        if (str[0] == '.' || str[0] == ',' || str[0] == '-')
-        {
-          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-          break;
+  len = StringLen (prefix);
+  if (cp - search >= len && StringNCmp (cp - len, prefix, len) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
         }
+}
+
+
+static Boolean InWordBeforeCytochromeOrCoenzyme (CharPtr cp, CharPtr start)
+{
+  if (cp == NULL) {
+    return FALSE;
       }
+
+  while (cp > start && !isspace (*cp)) {
+    cp--;
     }
-    else if (k >= end_with_start && k <= end_with_end)
-    {
-      phrase_len = StringLen (suspect_product_names[k]);
-      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-      {
-        if (vnp->data.ptrvalue == NULL) continue;
-        str = (CharPtr) vnp->data.ptrvalue;
-        len = StringLen (str);
-        if (len >= phrase_len && StringICmp (str + len - phrase_len, suspect_product_names[k]) == 0) 
-        {
-          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-          break;
+  if (cp == start) {
+    return FALSE;
         }
+  while (cp > start && isspace (*cp)) {
+    cp--;
       }
+  if (cp - start >= 9 && StringNICmp (cp - 9, "cytochrome", 10) == 0) {
+    return TRUE;
+  } else if (cp - start >= 7 && StringNCmp (cp - 7, "coenzyme", 8) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
     }
-    else if (k >= start_with_start && k <= start_with_end)
-    {
-      phrase_len = StringLen (suspect_product_names[k]);
-      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-      {
-        if (vnp->data.ptrvalue == NULL) continue;
-        str = (CharPtr) vnp->data.ptrvalue;
-        len = StringLen (str);
-        if (len >= phrase_len && StringNICmp (str, suspect_product_names[k], phrase_len) == 0) 
-        {
-          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-          break;
+}
+
+
+static Boolean ThreeOrMoreNumbersTogether (CharPtr pattern, CharPtr search)
+{
+  CharPtr p;
+  Int4 num_digits = 0;
+
+  if (search == NULL) {
+    return FALSE;
         }
+
+  p = search;
+  while (*p != 0) {
+    if (isdigit (*p)) {
+      if (PrecededByPrefix(search, p, "DUF")
+          || PrecededByPrefix(search, p, "UPF")
+          || PrecededByPrefix(search, p, "IS")
+          || PrecededByPrefix(search, p, "TIGR")) {
+        p += StrSpn (p, "0123456789") - 1;
+        num_digits = 0;
+      } else if (InWordBeforeCytochromeOrCoenzyme (p, search)) {
+        p += StrSpn (p, "0123456789") - 1;
+        num_digits = 0;
+      } else {
+        num_digits ++;
+        if (num_digits == 3) {
+          if (FollowedByFamily (&p)) {
+            num_digits = 0;
+          } else {
+            return TRUE;
       }
     }
-    else if (k >= wholeword_casesensitive_start && k <= wholeword_casesensitive_end)
-    {
-      for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-      {
-        if (DoesStringContainPhrase (vnp->data.ptrvalue, suspect_product_names[k], TRUE, TRUE))
-        {
-          ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-          break;
         }
+    } else {
+      num_digits = 0;
       }
+    p++;
     }
-    else
-    {
-      if (k >= term_start && k <= term_end) {
-        for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-        {
-          /* don't bother searching for c-term or n-term if product name contains "domain" */
-          if (StringISearch (vnp->data.ptrvalue, "domain") != NULL) continue;
-          str = StringISearch(vnp->data.ptrvalue, suspect_product_names[k]);
-          /* c-term and n-term must be either first word or separated from other word by space, num, or punct */
-          if (str != NULL && (str == vnp->data.ptrvalue || !isalpha (*(str - 1))))
-          {
-            ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-            break;
+  return FALSE;
+}
+
+static Boolean ContainsUnderscore (CharPtr pattern, CharPtr search)
+{
+  CharPtr cp;
+
+  if (search == NULL) {
+    return FALSE;
           }
+
+  cp = StringChr (search, '_');
+  while (cp != NULL) {
+    if (FollowedByFamily (&cp)) {
+      /* search again */
+      cp = StringChr (cp, '_');
+    } else if (cp - search < 3 || *(cp + 1) == 0) {
+      return TRUE;
+    } else if ((StringNCmp (cp - 3, "MFS", 3) == 0
+                || StringNCmp (cp - 3, "TPR", 3) == 0
+                || StringNCmp (cp - 3, "AAA", 3) == 0)
+                && isdigit (*(cp + 1)) && !isdigit (*(cp + 2))) {
+      cp = StringChr (cp + 1, '_');
+    } else {
+      return TRUE;
         }
       }
-      else if (k >= wholeword_start && k <= wholeword_end)
-      {
-        for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
-        {
-          if (DoesStringContainPhrase(vnp->data.ptrvalue, suspect_product_names[k], FALSE, TRUE))
-          {
-            ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
-            break;
+  return FALSE;
+}
+
+
+static Boolean PrefixPlusNumbersOnly (CharPtr pattern, CharPtr search)
+{
+  Int4 pattern_len, digit_len;
+
+  if (search == NULL) {
+    return FALSE;
           }
+  pattern_len = StringLen (pattern);
+  if (pattern_len > 0 && StringNCmp (search, pattern, pattern_len) != 0) {
+    return FALSE;
         }
+
+  digit_len = StringSpn (search + pattern_len, "1234567890");
+  if (digit_len > 0 && *(search + pattern_len + digit_len) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
       }
-      else if (k >= singleword_start && k <= singleword_end)
-      {
-        for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
+}
+
+
+static Boolean EndsWithFold (CharPtr pattern, CharPtr search)
+{
+  Int4 len;
+
+  if (search == NULL) {
+    return FALSE;
+  }
+  len = StringLen (search);
+  if (len < 4) {
+    return FALSE;
+  }
+  if (StringICmp (search + len - 4, "fold") == 0) {
+    if (StringCmp (search + len - 4, "folD") == 0
+        || StringCmp (search + len - 4, "FolD") == 0) {
+      return FALSE;
+    } else {
+      return TRUE;
+    }
+  } else {
+    return FALSE;
+  }
+}
+
+static Boolean AllCapitalLetters (CharPtr pattern, CharPtr search)
+{
+  CharPtr cp;
+  Boolean any_alpha = FALSE;
+
+  if (search == NULL) {
+    return FALSE;
+  }
+  cp = search;
+  while (*cp != 0) {
+    if (isalpha (*cp)) {
+      any_alpha = TRUE;
+      if (islower (*cp)) {
+        return FALSE;
+      }
+    }
+    ++cp;
+  }
+  return any_alpha;
+}
+
+
+static Boolean ContainsUnbalancedParentheses (CharPtr pattern, CharPtr search)
+{
+  CharPtr buffer, cp_src;
+  Int4    pos = 0;
+  Boolean is_bad = FALSE;
+
+  if (search == NULL) {
+    return FALSE;
+  }
+
+  /* note - don't need space for terminating character */
+  buffer = MemNew (sizeof (Char) * StringLen (search));
+  cp_src = search;
+  while (*cp_src != 0 && !is_bad) {
+    if (*cp_src == '(' || *cp_src == '[') {
+      buffer[pos++] = *cp_src;
+    } else if (*cp_src == ')') {
+      if (pos < 1) {
+        is_bad = TRUE;
+      } else if (buffer[pos - 1] != '(') {
+        is_bad = TRUE;
+      } else {
+        pos --;
+      }
+    } else if (*cp_src == ']') {
+      if (pos < 1) {
+        is_bad = TRUE;
+      } else if (buffer[pos - 1] != '[') {
+        is_bad = TRUE;
+      } else {
+        pos--;
+      }
+    }
+    ++cp_src;
+  }
+
+  if (pos > 0) {
+    is_bad = TRUE;
+  }
+  buffer = MemFree (buffer);
+  return is_bad;
+}
+
+
+static CharPtr s_pseudoweasels[] = {
+  "pseudouridine",
+  "pseudoazurin",
+  "pseudouridylate",
+  NULL};
+
+static Boolean ContainsPseudo (CharPtr pattern, CharPtr search)
+{
+  CharPtr cp;
+  Int4    i, len;
+  Boolean bad_pseudo;
+
+  if (search == NULL) {
+    return FALSE;
+  }
+  cp = StringISearch (search, "pseudo");
+  while (cp != NULL) {
+    bad_pseudo = FALSE;
+    for (i = 0; s_pseudoweasels[i] != NULL && !bad_pseudo; i++) {
+      len = StringLen (s_pseudoweasels[i]);
+      if (StringNCmp (cp, s_pseudoweasels[i], len) == 0) {
+        bad_pseudo = TRUE;
+        cp = StringISearch (cp + len, "pseudo");
+      }
+    }
+    if (!bad_pseudo) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+
+static Boolean ContainsDoubleSpace (CharPtr pattern, CharPtr search)
+{
+  if (search == NULL) {
+    return FALSE;
+  }
+  if (StringSearch (search, "  ") != NULL) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static CharPtr SummarizeSuspectPhraseFunc (SuspectProductNameSearchFunc s)
+{
+  if (s == NULL) {
+    return "NULL function";
+  } else  if (s == EndsWithPattern) {
+    return "occurs at end of text";
+  } else if (s == ContainsWholeWord) {
+    return "contains phrase as whole word";
+  } else if (s == StartsWithPattern) {
+    return "occurs at beginning of text";
+  } else if (s == ContainsWholeWordCaseSensitive) {
+    return "contains phrase as whole word, case sensitive";
+  } else if (s == IsSingleWord) {
+    return "entire text matches (not case sensitive)";
+  } else if (s == IsSingleWordOrWeaselPlusSingleWord) {
+    return "entire text matches (not case sensitive) or text matches after weasel word";
+  } else if (s == NormalSearch) {
+    return "contains phrase anywhere, not case sensitive";
+  } else if (s == ContainsDoubleSpace) {
+    return "contains double space";
+  } else if (s == PrefixPlusNumbersOnly) {
+    return "entire product is prefix followed by numbers";
+  } else {
+    return "special rules";
+  }
+}
+
+
+static SuspectProductNameData suspect_product_terms[] = {
+  { "like", EndsWithPattern },
+  { "repeat", EndsWithPattern },
+  { "domain", EndsWithPattern },
+  { "fold", EndsWithFold },
+  { "motif", EndsWithPattern },
+  { "related", EndsWithPattern },
+  { "binding", EndsWithPattern },
+  { "containing", EndsWithPattern },
+  { "containing", StartsWithPattern },
+  { "from", StartsWithPattern },
+  { "N-term", ProductContainsTerm },
+  { "N term", ProductContainsTerm },
+  { "C-term", ProductContainsTerm },
+  { "C term", ProductContainsTerm },
+  { "may contain a plural", MayContainPlural },
+  { "Brackets or parenthesis [] ()", ContainsBracketsOrParentheses },
+  { "Two or more sets of brackets or parentheseis", ContainsTwoSetsOfBracketsOrParentheses },
+  { "ending with period, comma, hyphen, underscore, colon, or forward slash", EndsWithPunct },
+  { "beginning with period, comma, or hyphen", BeginsWithPunct },
+  { "unknown", ContainsUnknownName },
+  { "COG", ContainsWholeWordCaseSensitive },
+  { "EST", ContainsWholeWordCaseSensitive },
+  { "DUF", ContainsWholeWordCaseSensitive },
+  { "UPF", ContainsWholeWordCaseSensitive },
+  { "DUF", PrefixPlusNumbersOnly },
+  { "UPF", PrefixPlusNumbersOnly },
+  { "IS", PrefixPlusNumbersOnly },
+  { "FOG", ContainsWholeWordCaseSensitive },
+  { "Subtilis", ContainsWholeWord },
+  { "coli", ContainsWholeWord },
+  { "pseudo", ContainsWholeWord },
+  { "gene", ContainsWholeWord },
+  { "genes", ContainsWholeWord },
+  { "homo", ContainsWholeWord },
+  { "argininte", ContainsWholeWord },
+  { "diacyglycerol", ContainsWholeWord },
+  { "glycosy", ContainsWholeWord },
+  { "hypothetica", ContainsWholeWord },
+  { "ncharacterized", ContainsWholeWord },
+  { "obalt", ContainsWholeWord },
+  { "odule", ContainsWholeWord },
+  { "protei", ContainsWholeWord },
+  { "sigm", ContainsWholeWord },
+  { "thiamin/thiamin", ContainsWholeWord },
+  { "threonin", ContainsWholeWord },
+  { "ypothetical", ContainsWholeWord },
+  { "ytochrome", ContainsWholeWord },
+  { "aminotransferasee", ContainsWholeWord },
+  { "bioin", ContainsWholeWord },
+  { "biosythesis", ContainsWholeWord },
+  { "chelatin", ContainsWholeWord },
+  { "componenet", ContainsWholeWord },
+  { "familie", ContainsWholeWord },
+  { "hexpeptide", ContainsWholeWord },
+  { "homocystein", ContainsWholeWord },
+  { "initation", ContainsWholeWord },
+  { "mobilisation", ContainsWholeWord },
+  { "mutatrotase", ContainsWholeWord },
+  { "oxidoreductasee", ContainsWholeWord },
+  { "periplasmc", ContainsWholeWord },
+  { "puter", ContainsWholeWord },
+  { "reductasee", ContainsWholeWord },
+  { "thioderoxin", ContainsWholeWord },
+  { "transferasee", ContainsWholeWord },
+  { "protein", IsSingleWord },
+  { "putative protein", IsSingleWord },
+  { "probable protein", IsSingleWord },
+  { "sodium", IsSingleWord },
+  { "CHC2 zinc finger", IsSingleWord },
+  { "SWIM zinc finger", IsSingleWord },
+  { "putative", IsSingleWordOrWeaselPlusSingleWord },
+  { "probable", IsSingleWordOrWeaselPlusSingleWord },
+  { "protein-containing", IsSingleWordOrWeaselPlusSingleWord },
+  { "protein containing", IsSingleWordOrWeaselPlusSingleWord },
+  { "transposase of", IsSingleWordOrWeaselPlusSingleWord },
+  { "hypothetical", IsSingleWordOrWeaselPlusSingleWord },
+  { "conserved hypothetical", IsSingleWordOrWeaselPlusSingleWord },
+  { "conserved", IsSingleWordOrWeaselPlusSingleWord },
+  { "purine", IsSingleWordOrWeaselPlusSingleWord },
+  { "iron", IsSingleWordOrWeaselPlusSingleWord },
+  { "phage", IsSingleWordOrWeaselPlusSingleWord },
+  { "insertion sequence", IsSingleWordOrWeaselPlusSingleWord },
+  { "transposon", IsSingleWordOrWeaselPlusSingleWord },
+  { "signal peptide", IsSingleWordOrWeaselPlusSingleWord },
+  { "NAD", IsSingleWordOrWeaselPlusSingleWord },
+  { "p-loop", IsSingleWordOrWeaselPlusSingleWord },
+  { "helix-turn-helix", IsSingleWordOrWeaselPlusSingleWord },
+  { "domain family", IsSingleWordOrWeaselPlusSingleWord },
+  { "PASTA", IsSingleWordOrWeaselPlusSingleWord },
+  { "zinc finger", IsSingleWordOrWeaselPlusSingleWord },
+  { "amino acid", IsSingleWordOrWeaselPlusSingleWord },
+  { "peptide", IsSingleWordOrWeaselPlusSingleWord },
+  { "citrate", IsSingleWordOrWeaselPlusSingleWord },
+  { "PTS system", IsSingleWordOrWeaselPlusSingleWord },
+  { "putative protein", IsSingleWordOrWeaselPlusSingleWord },
+  { "Alanine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Arginine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Asparagine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Aspartic acid", IsSingleWordOrWeaselPlusSingleWord },
+  { "Cysteine", IsSingleWordOrWeaselPlusSingleWord },
+  { "DNA", IsSingleWordOrWeaselPlusSingleWord },
+  { "Glutamic acid", IsSingleWordOrWeaselPlusSingleWord },
+  { "Glutamine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Glycine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Histidine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Isoleucine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Leucine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Lysine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Methionine", IsSingleWordOrWeaselPlusSingleWord },
+  { "ORF", IsSingleWordOrWeaselPlusSingleWord },
+  { "Phenylalanine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Proline", IsSingleWordOrWeaselPlusSingleWord },
+  { "RNA", IsSingleWordOrWeaselPlusSingleWord },
+  { "Serine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Threonine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Tryptophan", IsSingleWordOrWeaselPlusSingleWord },
+  { "Tyrosine", IsSingleWordOrWeaselPlusSingleWord },
+  { "Valine", IsSingleWordOrWeaselPlusSingleWord },
+  { "adenine", IsSingleWordOrWeaselPlusSingleWord },
+  { "barrel", IsSingleWordOrWeaselPlusSingleWord },
+  { "carbon", IsSingleWordOrWeaselPlusSingleWord },
+  { "cytosine", IsSingleWordOrWeaselPlusSingleWord },
+  { "domain", IsSingleWordOrWeaselPlusSingleWord },
+  { "domain protein", IsSingleWordOrWeaselPlusSingleWord },
+  { "factor", IsSingleWordOrWeaselPlusSingleWord },
+  { "family protein", IsSingleWordOrWeaselPlusSingleWord },
+  { "finger", IsSingleWordOrWeaselPlusSingleWord },
+  { "ggdef", IsSingleWordOrWeaselPlusSingleWord },
+  { "guanine", IsSingleWordOrWeaselPlusSingleWord },
+  { "helium", IsSingleWordOrWeaselPlusSingleWord },
+  { "helix", IsSingleWordOrWeaselPlusSingleWord },
+  { "hydrogen", IsSingleWordOrWeaselPlusSingleWord },
+  { "hypothetical ORF", IsSingleWordOrWeaselPlusSingleWord },
+  { "mRNA", IsSingleWordOrWeaselPlusSingleWord },
+  { "membrane", IsSingleWordOrWeaselPlusSingleWord },
+  { "ncRNA", IsSingleWordOrWeaselPlusSingleWord },
+  { "nitrogen", IsSingleWordOrWeaselPlusSingleWord },
+  { "oxygen", IsSingleWordOrWeaselPlusSingleWord },
+  { "plasmid", IsSingleWordOrWeaselPlusSingleWord },
+  { "precursor", IsSingleWordOrWeaselPlusSingleWord },
+  { "protein of unknown function", IsSingleWordOrWeaselPlusSingleWord },
+  { "putative conserved hypothetical", IsSingleWordOrWeaselPlusSingleWord },
+  { "putative hypothetical", IsSingleWordOrWeaselPlusSingleWord },
+  { "putative signal peptide", IsSingleWordOrWeaselPlusSingleWord },
+  { "rRNA", IsSingleWordOrWeaselPlusSingleWord },
+  { "repeat", IsSingleWordOrWeaselPlusSingleWord },
+  { "secreted", IsSingleWordOrWeaselPlusSingleWord },
+  { "signal", IsSingleWordOrWeaselPlusSingleWord },
+  { "subunit", IsSingleWordOrWeaselPlusSingleWord },
+  { "tRNA", IsSingleWordOrWeaselPlusSingleWord },
+  { "thymine", IsSingleWordOrWeaselPlusSingleWord },
+  { "uracil", IsSingleWordOrWeaselPlusSingleWord },
+  { "zinc", IsSingleWordOrWeaselPlusSingleWord },
+  { "transport-associated", IsSingleWordOrWeaselPlusSingleWord },
+  { "Similar to", NormalSearch },
+  { "Related to", NormalSearch },
+  { "interrupt", NormalSearch },
+  { "Homolog", NormalSearch },
+  { "Homologue", NormalSearch },
+  { "Fragment", NormalSearch },
+  { "Frameshift", NormalSearch },
+  { "Intein", NormalSearch },
+  { "Chloroplast", NormalSearch },
+  { "Mitochondrial", NormalSearch },
+  { "puatative", NormalSearch },
+  { "putaive", NormalSearch },
+  { "putaitve", NormalSearch },
+  { "putatitve", NormalSearch },
+  { "putataive", NormalSearch },
+  { "putatuve", NormalSearch },
+  { "ortholog", NormalSearch },
+  { "orthologue", NormalSearch },
+  { "paralog", NormalSearch },
+  { "paralogue", NormalSearch },
+  { "bifunctional protein", NormalSearch },
+  { "pseudogene", NormalSearch },
+  { "frame shift", NormalSearch },
+  { "protien", NormalSearch },
+  { "partial", NormalSearch },
+  { "sphaeroides", NormalSearch },
+  { "or related", NormalSearch },
+  { "authentic point mutation", NormalSearch },
+  { "novel protein", NormalSearch },
+  { "ttg start", NormalSearch },
+  { "domain protein domain protein", NormalSearch },
+  { "deletion", NormalSearch },
+  { "truncat", NormalSearch },
+  { "hypothteical", NormalSearch },
+  { "hypotethical", NormalSearch },
+  { "hypothetcial", NormalSearch },
+  { "consevered", NormalSearch },
+  { "cotaining", NormalSearch },
+  { "gIycerol", NormalSearch },
+  { "haemagglutination", NormalSearch },
+  { "family family", NormalSearch },
+  { "domain domain", NormalSearch },
+  { "putative, putative", NormalSearch },
+  { "putative putative", NormalSearch },
+  { "putative probable", NormalSearch },
+  { "probable putative", NormalSearch },
+  { "similar", NormalSearch },
+  { "characterisation", NormalSearch },
+  { "uncharacterised", NormalSearch },
+  { "putatvie", NormalSearch },
+  { "putaitve", NormalSearch },
+  { "simmilar", NormalSearch },
+  { "ribosoml", NormalSearch },
+  { "transcirbed", NormalSearch },
+  { "recognised", NormalSearch },
+  { "heam", NormalSearch },
+  { "haem", NormalSearch },
+  { "golgi", NormalSearch },
+  { "active site", NormalSearch },
+  { "human", NormalSearch },
+  { "domian", NormalSearch },
+  { "facotr", NormalSearch },
+  { "proein", NormalSearch },
+  { "trnasporter", NormalSearch },
+  { "tranporter", NormalSearch },
+  { "proteinn", NormalSearch },
+  { "homo sapiens", NormalSearch },
+  { "sapiens", NormalSearch },
+  { "Transmebrane", NormalSearch },
+  { "Transemembrane", NormalSearch },
+  { "Intiation", NormalSearch },
+  { "Portein", NormalSearch },
+  { "protrein", NormalSearch },
+  { "hypotehtical", NormalSearch },
+  { "K potassium", NormalSearch },
+  { "K+ potassium", NormalSearch },
+  { "outers", NormalSearch },
+  { "weakly conserved", NormalSearch },
+  { "highly conserved", NormalSearch },
+  { "narrowly conserved", NormalSearch },
+  { "No definition line found", NormalSearch },
+  { "ECOLI", NormalSearch },
+  { "alternate protein name", NormalSearch },
+  { "widely conserved", NormalSearch },
+  { "putative orphan protein", NormalSearch },
+  { "orphan protein", NormalSearch },
+  { "Plasmodium", NormalSearch },
+  { "bos taurus", NormalSearch },
+  { "open reading frame", NormalSearch },
+  { "?", NormalSearch },
+  { "#", NormalSearch },
+  { ". ", NormalSearch },
+  { "|", NormalSearch },
+  { "=", NormalSearch },
+  { "\\-PA", NormalSearch },
+  { "_", ContainsUnderscore },
+  { "three or more numbers together, not after 'UPF' or 'DUF' or 'IS' and not followed by the word 'family' and not preceded by either 'cytochrome' or 'coenzyme'", ThreeOrMoreNumbersTogether },
+  { "putaitive", NormalSearch },
+  { "putatve", NormalSearch },
+  { "hypothtical", NormalSearch },
+  { "hypotheical", NormalSearch },
+  { "meausure", NormalSearch },
+  { "flageller", NormalSearch },
+  { "tumour", NormalSearch },
+  { "dimerising", NormalSearch },
+  { "dimerisation", NormalSearch },
+  { "nucelar", NormalSearch },
+  { "nulcear", NormalSearch },
+  { "proteine", NormalSearch },
+  { "unkown", NormalSearch },
+  { "periplsmic", NormalSearch },
+  { "molybopterin", NormalSearch },
+  { "molydopterin", NormalSearch },
+  { "aluminium", NormalSearch },
+  { "aminopetidase", NormalSearch },
+  { "asparate", NormalSearch },
+  { "aparaginase", NormalSearch },
+  { "bifunctionnal", NormalSearch },
+  { "biosyntesis", NormalSearch },
+  { "bnding", NormalSearch },
+  { "carboxilic", NormalSearch },
+  { "cell divisionFtsK/SpoIIIE", NormalSearch },
+  { "coantaining", NormalSearch },
+  { "coenzye", NormalSearch },
+  { "componnent", NormalSearch },
+  { "degration", NormalSearch },
+  { "dependant", NormalSearch },
+  { "disulphide", NormalSearch },
+  { "divison", NormalSearch },
+  { "dyhydrogenase", NormalSearch },
+  { "glcosyl", NormalSearch },
+  { "glucosainyl", NormalSearch },
+  { "glutaminne", NormalSearch },
+  { "hemelysin", NormalSearch },
+  { "hemoglobine", NormalSearch },
+  { "histadine", NormalSearch },
+  { "homeserine", NormalSearch },
+  { "hyphotetical", NormalSearch },
+  { "hypotetical", NormalSearch },
+  { "hypotheitcal", NormalSearch },
+  { "hpothetical", NormalSearch },
+  { "inductible", NormalSearch },
+  { "majour", NormalSearch },
+  { "mambrane", NormalSearch },
+  { "meausure", NormalSearch },
+  { "membranne", NormalSearch },
+  { "methlytransferase", NormalSearch },
+  { "metylase", NormalSearch },
+  { "monoxyde", NormalSearch },
+  { "monoxygenase", NormalSearch },
+  { "mulitdrug", NormalSearch },
+  { "ndoribonuclease", ContainsWholeWord },
+  { "nickle", NormalSearch },
+  { "oxidoreductasse", NormalSearch },
+  { "oxydase", NormalSearch },
+  { "phophate", NormalSearch },
+  { "phopho", NormalSearch },
+  { "phophoserine", NormalSearch },
+  { "phoshate", NormalSearch },
+  { "phosphotase", NormalSearch },
+  { "posible", NormalSearch },
+  { "presursor", NormalSearch },
+  { "prortein", NormalSearch },
+  { "regulatot", NormalSearch },
+  { "resistence", NormalSearch },
+  { "serinr", NormalSearch },
+  { "signalling", NormalSearch },
+  { "spscific", NormalSearch },
+  { "stabilisation", NormalSearch },
+  { "subnit", NormalSearch },
+  { "sulpho", NormalSearch },
+  { "sulphur", NormalSearch },
+  { "sythase", NormalSearch },
+  { "threonin", ContainsWholeWord },
+  { "tranferase", NormalSearch },
+  { "transebrane", NormalSearch },
+  { "transglycolase", NormalSearch },
+  { "transorter", NormalSearch },
+  { "transpoase", NormalSearch },
+  { "transportor", NormalSearch },
+  { "transproter", NormalSearch },
+  { "transulfuration", NormalSearch },
+  { "typr", NormalSearch },
+  { "uncharaterized", NormalSearch },
+  { "undecapaprenyl", NormalSearch },
+  { "utilisation", ContainsWholeWord },
+  { "contain", ContainsWholeWord },
+  { "start codon", ContainsWholeWord },
+  { "Includes:", ContainsWholeWord },
+  { "inactivated derivative", ContainsWholeWord },
+  { "double space", ContainsDoubleSpace },
+  { "all capital letters", AllCapitalLetters },
+  { "unbalanced brackets or parentheses", ContainsUnbalancedParentheses },
+  /* organism names */
+  { "aureus", ContainsWholeWord },
+  { "Arabidopsis", ContainsWholeWord },
+  { "Aspergillus", ContainsWholeWord },
+  { "niger", ContainsWholeWord },
+  { "Bacillus", ContainsWholeWord },
+  { "Bacteroides", ContainsWholeWord },
+  { "B.subtilis", ContainsWholeWord },
+  { "Campylobacter", ContainsWholeWord },
+  { "cerevisiae", ContainsWholeWord },
+  { "Chlamydial", ContainsWholeWord },
+  { "Chlamydomonas", ContainsWholeWord },
+  { "Drosophila", ContainsWholeWord },
+  { "enterica", ContainsWholeWord },
+  { "Escherichia", ContainsWholeWord },
+  { "E.coli", ContainsWholeWord },
+  { "halophilus", ContainsWholeWord },
+  { "Helicobacter", ContainsWholeWord },
+  { "Jejuni", ContainsWholeWord },
+  { "Leishmania", ContainsWholeWord },
+  { "Marinococcus", ContainsWholeWord },
+  { "mouse", ContainsWholeWord },
+  { "Mus musculus", ContainsWholeWord },
+  { "Mycobacterium", ContainsWholeWord },
+  { "Pestis", ContainsWholeWord },
+  { "pseudomonas", ContainsWholeWord },
+  { "pombe", ContainsWholeWord },
+  { "pylori", ContainsWholeWord },
+  { "Tuberculosis", ContainsWholeWord },
+  { "rat", ContainsWholeWord },
+  { "Rhodobacter", ContainsWholeWord },
+  { "Staphylococcus", ContainsWholeWord },
+  { "subsp", ContainsWholeWord },
+  { "serovar", ContainsWholeWord },
+  { "thaliana", ContainsWholeWord },
+  { "Typhimurium", ContainsWholeWord },
+  { "Salmonella", ContainsWholeWord },
+  { "Staphlococcal", ContainsWholeWord },
+  { "Staphlococcus", ContainsWholeWord },
+  { "staphylococcal", ContainsWholeWord },
+  { "sreptomyces", ContainsWholeWord },
+  { "Streptococcus", ContainsWholeWord },
+  { "streptococcal", ContainsWholeWord },
+  { "streptomyces", ContainsWholeWord },
+  { "xenopus", ContainsWholeWord },
+  { "yeast", ContainsWholeWord },
+  { "Yersinia", ContainsWholeWord }
+};
+
+
+const int num_suspect_product_terms = sizeof (suspect_product_terms) / sizeof (SuspectProductNameData);
+
+
+static void FindSuspectProductNamesCallback (SeqFeatPtr sfp, Pointer userdata)
+{
+  ValNodePtr PNTR feature_list;
+  Int4            k;
+  ProtRefPtr      prp;
+  ValNodePtr      vnp;
+  BioseqPtr       bsp;
+  SeqFeatPtr      cds;
+  
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT || sfp->data.value.ptrvalue == NULL
+      || userdata == NULL)
         {
-          if (StringICmp (prp->name->data.ptrvalue, suspect_product_names[k]) == 0) {
-            ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
+    return;
+  }
+  
+  prp = (ProtRefPtr) sfp->data.value.ptrvalue;
+  feature_list = (ValNodePtr PNTR) userdata;
+
+  /* add coding region rather than protein */
+  if (sfp->idx.subtype == FEATDEF_PROT) {
+    bsp = BioseqFindFromSeqLoc (sfp->location);
+    if (bsp != NULL) {
+      cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
+      if (cds != NULL) {
+        sfp = cds;
           }
         }
       }
-      else
+  
+  for (k = 0; k < num_suspect_product_terms; k++)
       {
         for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
         {
-          if (StringISearch(vnp->data.ptrvalue, suspect_product_names[k]) != NULL)
+      if (suspect_product_terms[k].search_func != NULL
+        && (suspect_product_terms[k].search_func) (suspect_product_terms[k].pattern, vnp->data.ptrvalue)) 
           {
-            if (k != unknown_name 
-                || (StringISearch (vnp->data.ptrvalue, "protein of unknown function") == NULL
-                    && StringISearch (vnp->data.ptrvalue, "domain of unknown function") == NULL)) {
               ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
               break;
             }
+      /* only check the first name */
+      if (!StringHasNoText (vnp->data.ptrvalue)) {
+        break;
           }
         }
       }
-    }
-  }
+        
 }
 
 
@@ -10310,7 +11575,7 @@ static ClickableItemPtr SuspectPhrase (Uint4 clickable_item_type, CharPtr phrase
   ClickableItemPtr dip = NULL;
   CharPtr            bad_fmt = "%d %ss contain '%s'";
 
-  if (feature_list == NULL || StringHasNoText (phrase) || StringHasNoText (feat_type))
+  if (feature_list == NULL || phrase == NULL || StringHasNoText (feat_type))
   {
     return NULL;
   }
@@ -10390,11 +11655,11 @@ extern void FindSuspectProductNames (ValNodePtr PNTR discrepancy_list, ValNodePt
   
   if (discrepancy_list == NULL) return;
 
-  feature_list = (ValNodePtr PNTR) MemNew (sizeof (ValNodePtr) * num_suspect_product_names);
+  feature_list = (ValNodePtr PNTR) MemNew (sizeof (ValNodePtr) * num_suspect_product_terms);
   if (feature_list == NULL) return;
   
   /* initialize array for suspicious product names */
-  for (k = 0; k < num_suspect_product_names; k++)
+  for (k = 0; k < num_suspect_product_terms; k++)
   {
     feature_list[k] = NULL;
   }
@@ -10404,21 +11669,21 @@ extern void FindSuspectProductNames (ValNodePtr PNTR discrepancy_list, ValNodePt
     VisitGenProdSetFeatures (vnp->data.ptrvalue, feature_list, FindSuspectProductNamesCallback);
   }
   
-  for (k = 0; k < num_suspect_product_names; k++)
+  for (k = 0; k < num_suspect_product_terms; k++)
   {
     if (feature_list[k] != NULL)
     {
-      if (k >= end_with_start && k <= end_with_end) 
+      if (suspect_product_terms[k].search_func == EndsWithPattern) 
       {
-        dip = SuspectPhraseEnd (DISC_SUSPECT_PRODUCT_NAME, suspect_product_names[k], "product name", feature_list[k]);
+        dip = SuspectPhraseEnd (DISC_SUSPECT_PRODUCT_NAME, suspect_product_terms[k].pattern, "product name", feature_list[k]);
       }
-      else if (k >= start_with_start && k <= start_with_end) 
+      else if (suspect_product_terms[k].search_func == StartsWithPattern) 
       {
-        dip = SuspectPhraseStart (DISC_SUSPECT_PRODUCT_NAME, suspect_product_names[k], "product name", feature_list[k]);
+        dip = SuspectPhraseStart (DISC_SUSPECT_PRODUCT_NAME, suspect_product_terms[k].pattern, "product name", feature_list[k]);
       }
       else 
       {
-        dip = SuspectPhrase (DISC_SUSPECT_PRODUCT_NAME, suspect_product_names[k], "product name", feature_list[k]);
+        dip = SuspectPhrase (DISC_SUSPECT_PRODUCT_NAME, suspect_product_terms[k].pattern, "product name", feature_list[k]);
       }
       if (dip != NULL)
       {
@@ -10442,6 +11707,61 @@ extern void FindSuspectProductNames (ValNodePtr PNTR discrepancy_list, ValNodePt
 }
 
 
+NLM_EXTERN Boolean IsProductNameOk (CharPtr product_name)
+{
+  Int4     k;
+  Boolean  rval = TRUE;
+
+  for (k = 0; k < num_suspect_product_terms && rval; k++)
+  {    
+    if (suspect_product_terms[k].search_func != NULL
+      && (suspect_product_terms[k].search_func) (suspect_product_terms[k].pattern, product_name)) 
+    {
+      rval = FALSE;
+    }
+  }
+  return rval;
+}
+
+
+extern void FindSuspectProductNamesInNameList (FILE *input_file, FILE *output_file)
+{
+  ReadBufferData    rbd;
+  CharPtr           line, func_name;
+  Int4              k;
+  
+  rbd.fp = input_file;
+  rbd.current_data = NULL;
+
+  line = AbstractReadFunction (&rbd);
+  while (line != NULL) 
+  {
+    for (k = 0; k < num_suspect_product_terms; k++)
+    {    
+      if (suspect_product_terms[k].search_func != NULL
+        && (suspect_product_terms[k].search_func) (suspect_product_terms[k].pattern, line)) 
+      {
+        if (suspect_product_terms[k].search_func == EndsWithPattern) {
+          func_name = "Ends with";
+        } else if (suspect_product_terms[k].search_func == StartsWithPattern) {
+          func_name = "Starts with";
+        } else {
+          func_name = "Contains";
+        }
+        if (output_file) {
+          fprintf (output_file, "%s\t%s '%s'\n", line, func_name, suspect_product_terms[k].pattern);
+        } else {
+          printf ("%s\t%s '%s'\n", line, func_name, suspect_product_terms[k].pattern);
+        }
+      }
+    }
+    
+    line = MemFree (line);
+    line = AbstractReadFunction (&rbd);
+  }
+}
+
+
 static CharPtr suspect_phrases[] = 
 {
 "fragment",
@@ -10559,8 +11879,20 @@ static void CheckForStr
 
 static CharPtr suspicious_note_phrases[] = 
 {
-"homolog",
-"homologue"
+ "characterised",
+ "recognised",
+ "characterisation",
+ "localisation",
+ "tumour",
+ "uncharacterised",
+ "oxydase",
+ "colour",
+ "localise",
+ "faecal",
+ "orthologue",
+ "paralogue",
+ "homolog",
+ "homologue"
 };
 
 const int num_suspicious_note_phrases = sizeof (suspicious_note_phrases) / sizeof (CharPtr);
@@ -11861,15 +13193,18 @@ static void LIBCALLBACK CountNProc (CharPtr sequence, Pointer userdata)
 }
 
 
-static FloatLo PercentNInBioseq (BioseqPtr bsp)
+NLM_EXTERN FloatLo PercentNInBioseq (BioseqPtr bsp, Boolean include_gaps)
 {
   Int4 num_n = 0;
+  Int4 flags = 0;
   
   if (bsp->length == 0) return 0;
 
-  /* if delta sequence, ignore Ns from gaps */
+  if (include_gaps) {
+    flags |= STREAM_EXPAND_GAPS;
+  }
 
-  SeqPortStream (bsp, 0, (Pointer) &num_n, CountNProc);
+  SeqPortStream (bsp, flags, (Pointer) &num_n, CountNProc);
 
   return ((FloatLo)num_n * 100) / (FloatLo) bsp->length;
 }
@@ -11901,7 +13236,7 @@ static void PercentNDiscrepancy (BioseqPtr bsp, Pointer userdata)
     return;
   }
 
-  pct = PercentNInBioseq (bsp);
+  pct = PercentNInBioseq (bsp, FALSE);
   if (pct > 10.0) 
   {
     ValNodeAddPointer ((ValNodePtr PNTR)userdata, OBJ_BIOSEQ, bsp);
@@ -12880,6 +14215,7 @@ static void AddDiscrepanciesForSourceQualComboList (ValNodePtr PNTR discrepancy_
   CharPtr          dup_fmt = "%%d sources have '%s' for %s";
   CharPtr          fmt, qual_name;
   Char tmp[30];
+  ErrSev           msev, lsev;
 
   if (combo_list == NULL || *combo_list == NULL || src_list == NULL) {
     return;
@@ -12963,10 +14299,14 @@ static void AddDiscrepanciesForSourceQualComboList (ValNodePtr PNTR discrepancy_
     cip->clickable_item_type = item_type;
     cip->description = StringSave ("Source Qualifier Report");
 
+    msev = ErrSetMessageLevel (SEV_MAX);
+    lsev = ErrSetLogLevel (SEV_MAX);
     if (GetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_SRCQUAL_REPORT", NULL, tmp, sizeof (tmp) - 1)
         && StringICmp (tmp, "TRUE") == 0) {
       cip->expanded = TRUE; /* initially source qualifier report should be open */
     }
+    ErrSetMessageLevel (msev);
+    ErrSetLogLevel (lsev);
     ValNodeAddPointer (discrepancy_list, 0, cip);
   }
 
@@ -13084,6 +14424,24 @@ static ValNodePtr RunBioSourceTest (SeqEntryPtr sep, BioSourceTestFunc func)
 }
 
 
+static Boolean HasAmplifiedWithSpeciesSpecificPrimerNote (BioSourcePtr biop)
+{
+  SubSourcePtr ssp;
+  Boolean      rval = FALSE;
+  
+  if (biop == NULL) {
+    return FALSE;
+  }
+  for (ssp = biop->subtype; ssp != NULL && !rval; ssp = ssp->next) {
+    if (ssp->subtype == SUBSRC_other 
+        && StringCmp (ssp->name, "amplified with species-specific primers") == 0) {
+      rval = TRUE;
+    }
+  }
+  return rval;
+}
+
+
 static Boolean IsMissingRequiredClone (BioSourcePtr biop)
 {
   Boolean needs_clone = FALSE;
@@ -13092,7 +14450,7 @@ static Boolean IsMissingRequiredClone (BioSourcePtr biop)
   SubSourcePtr ssp;
   OrgModPtr    mod;
 
-  if (biop == NULL) {
+  if (biop == NULL || HasAmplifiedWithSpeciesSpecificPrimerNote(biop)) {
     return FALSE;
   }
   
@@ -13142,60 +14500,6 @@ static void FindRequiredClones (ValNodePtr PNTR discrepancy_list, ValNodePtr sep
 }
 
 
-static Boolean IsPlasmodium (BioSourcePtr biop)
-{
-  if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL
-    || StringISearch (biop->org->orgname->lineage, "Plasmodium") == NULL) {
-    return FALSE;
-  } else {
-    return TRUE;
-  }
-}
-
-
-static Boolean BioSourceHasPlasmodiumAndStrain (BioSourcePtr biop)
-{
-  OrgModPtr orgmod;
-  Boolean   has_strain = FALSE;
-
-  if (!IsPlasmodium (biop)) {
-    return FALSE;
-  }
-
-  for (orgmod = biop->org->orgname->mod; orgmod != NULL && !has_strain; orgmod = orgmod->next) {
-    if (orgmod->subtype == ORGMOD_strain) {
-      has_strain = TRUE;
-    }
-  }
-  return has_strain;
-}
-
-
-static void CheckPlasmodiumIsolateNotStrain (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
-{
-  ValNodePtr vnp, item_list = NULL, subcat = NULL;
-  ClickableItemPtr cip;
-
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    ValNodeLink (&item_list, RunBioSourceTest (vnp->data.ptrvalue, BioSourceHasPlasmodiumAndStrain));
-  }
-
-  if (item_list != NULL) {
-    ValNodeAddPointer (&subcat, 0, NewClickableItem (DISC_PLASMODIUM_ISOLATE_NOT_STRAIN, "%d biosources have plasmodium and strain", item_list));
-    item_list = NULL;
-  }
-
-  if (subcat != NULL) {
-    cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
-    MemSet (cip, 0, sizeof (ClickableItemData));
-    cip->clickable_item_type = DISC_PLASMODIUM_ISOLATE_NOT_STRAIN;
-    cip->description = StringSave ("Plasmodium Problem Report");
-    cip->subcategories = subcat;
-    ValNodeAddPointer (discrepancy_list, 0, cip);
-  }
-}
-
-
 static void RetroviridaeDNACallback (BioseqPtr bsp, Pointer data)
 {
   SeqMgrDescContext context;
@@ -13653,6 +14957,7 @@ static void CollectCitSubPubsFeatCallback (SeqFeatPtr sfp, Pointer data)
   ValNode vn;
 
   if (data != NULL) {
+    MemSet (&vn, 0, sizeof (ValNode));
     vn.choice = OBJ_SEQFEAT;
     vn.data.ptrvalue = sfp;
     vn.next = NULL;
@@ -13668,6 +14973,7 @@ static void CollectCitSubPubsDescCallback (SeqDescrPtr sdp, Pointer data)
   ValNode vn;
 
   if (data != NULL) {
+    MemSet (&vn, 0, sizeof (ValNode));
     vn.choice = OBJ_SEQDESC;
     vn.data.ptrvalue = sdp;
     vn.next = NULL;
@@ -13772,12 +15078,13 @@ static HaplotypeSequencePtr HaplotypeSequenceNew (CharPtr haplotype, CharPtr tax
 
 
 
-static int CompareSubSequences (BioseqPtr bsp1, Int4 pos1, BioseqPtr bsp2, Int4 pos2, Int4 cmp_len)
+static int CompareSubSequences (BioseqPtr bsp1, Int4 pos1, BioseqPtr bsp2, Int4 pos2, Int4 cmp_len, Boolean allow_Ndiff)
 {
   int  rval = 0;
   Int4 buf_len = 49;
   Char buf1[50];
   Char buf2[50];
+  CharPtr cp1, cp2;
   Int2 ctr;
 
   if (bsp1 == NULL && bsp2 == NULL) {
@@ -13798,7 +15105,26 @@ static int CompareSubSequences (BioseqPtr bsp1, Int4 pos1, BioseqPtr bsp2, Int4
                         (Pointer) buf2, NULL);
     buf2[ctr] = 0;
 
-    rval = StringCmp (buf1, buf2);
+    cp1 = buf1;
+    cp2 = buf2;
+    while (*cp1 != 0 && *cp2 != 0 && rval == 0) {
+      if (allow_Ndiff && (*cp1 == 'N' || *cp2 == 'N')) {
+        /* ok - can continue */
+      } else if (*cp1 == *cp2) {
+        /* identical, can continue */
+      } else if (*cp1 < *cp2) {
+        rval = -1;
+      } else {
+        rval = 1;
+      }
+      ++cp1;
+      ++cp2;
+    }
+    if (*cp1 == 0 && *cp2 != 0) {
+      rval = -1;
+    } else if (*cp1 != 0 && *cp2 == 0) {
+      rval = 1;
+    }
     pos1 += buf_len;
     pos2 += buf_len;
     cmp_len -= buf_len;
@@ -13807,7 +15133,7 @@ static int CompareSubSequences (BioseqPtr bsp1, Int4 pos1, BioseqPtr bsp2, Int4
 }
 
 
-static int CompareSequences (BioseqPtr bsp1, BioseqPtr bsp2)
+static int CompareSequences (BioseqPtr bsp1, BioseqPtr bsp2, Boolean allow_Ndiff)
 {
   int       rval = 0;
   
@@ -13817,38 +15143,75 @@ static int CompareSequences (BioseqPtr bsp1, BioseqPtr bsp2)
     } else if (bsp1->length > bsp2->length) {
       rval = 1;
     } else {
-      rval = CompareSubSequences (bsp1, 0, bsp2, 0, bsp1->length);
+      rval = CompareSubSequences (bsp1, 0, bsp2, 0, bsp1->length, allow_Ndiff);
     }
   }
   return rval;
 }
 
 
-static Boolean DoSequencesMatchForHaplotype (BioseqPtr bsp1, BioseqPtr bsp2)
+static Boolean SequencesHaveOverlap (BioseqPtr bsp1, BioseqPtr bsp2, Boolean allow_Ndiff)
+{
+  Int4 pct_overlap_required = 50;
+  Int4 overlap_len, min_overlap_len;
+  int  rval = -1;
+  Int4 offset = 0;
+
+  if (bsp1->length > bsp2->length) {
+    min_overlap_len = (pct_overlap_required * bsp2->length) / 100;
+  } else {
+    min_overlap_len = (pct_overlap_required * bsp1->length) / 100;
+  }
+  while (rval != 0 && offset < bsp1->length - min_overlap_len) {
+    overlap_len = MIN (bsp2->length - offset, bsp1->length - offset);
+    rval = CompareSubSequences(bsp1, offset, bsp2, 0, overlap_len, allow_Ndiff);
+    offset++;
+  }
+  offset = 0;
+  while (rval != 0 && offset < bsp2->length - min_overlap_len) {
+    overlap_len = MIN (bsp2->length - offset, bsp1->length - offset);
+    rval = CompareSubSequences(bsp2, offset, bsp1, 0, overlap_len, allow_Ndiff);
+    offset++;
+  }
+  if (rval == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static Boolean DoSequencesMatchForHaplotype (BioseqPtr bsp1, BioseqPtr bsp2, Boolean allow_Ndiff)
 {
   Int4 diff;
   int  rval = -1;
 
+
   if (bsp1 == NULL && bsp2 == NULL) {
     return TRUE;
   } else if (bsp1 == NULL || bsp2 == NULL) {
     return FALSE;
   }
+
   if (bsp1->length == bsp2->length) {
-    rval = CompareSubSequences (bsp1, 0, bsp2, 0, bsp1->length);
+    rval = CompareSubSequences (bsp1, 0, bsp2, 0, bsp1->length, allow_Ndiff);
   } else if (bsp1->length > bsp2->length) {
     diff = bsp1->length - bsp2->length;
     while (rval != 0 && diff >= 0) {
-      rval = CompareSubSequences (bsp1, diff, bsp2, 0, bsp2->length);
+      rval = CompareSubSequences (bsp1, diff, bsp2, 0, bsp2->length, allow_Ndiff);
       diff--;
     }
   } else {
     diff = bsp2->length - bsp1->length;
     while (rval != 0 && diff >= 0) {
-      rval = CompareSubSequences (bsp1, 0, bsp2, diff, bsp1->length);
+      rval = CompareSubSequences (bsp1, 0, bsp2, diff, bsp1->length, allow_Ndiff);
       diff--;
     }
   }
+  if (rval != 0 && SequencesHaveOverlap(bsp1, bsp2, allow_Ndiff)) {
+    rval = 0;
+  }
+
   if (rval == 0) {
     return TRUE;
   } else {
@@ -13857,7 +15220,7 @@ static Boolean DoSequencesMatchForHaplotype (BioseqPtr bsp1, BioseqPtr bsp2)
 }
 
 
-static int CompareHaplotypeThenSequence (HaplotypeSequencePtr a, HaplotypeSequencePtr b)
+static int CompareHaplotypeThenSequence (HaplotypeSequencePtr a, HaplotypeSequencePtr b, Boolean allowNDiff)
 {
   int   rval = 0;
   
@@ -13866,7 +15229,7 @@ static int CompareHaplotypeThenSequence (HaplotypeSequencePtr a, HaplotypeSequen
     if (rval == 0) {
       rval = StringCmp (a->haplotype, b->haplotype);
       if (rval == 0) {
-        rval = CompareSequences (a->bsp, b->bsp);
+        rval = CompareSequences (a->bsp, b->bsp, allowNDiff);
       }
     }
   }
@@ -13884,19 +15247,36 @@ static int LIBCALLBACK SortVnpByHaplotypeThenSequence (VoidPtr ptr1, VoidPtr ptr
   if (ptr1 != NULL && ptr2 != NULL) {
     vnp1 = *((ValNodePtr PNTR) ptr1);
     vnp2 = *((ValNodePtr PNTR) ptr2);
-    rval = CompareHaplotypeThenSequence (vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+    rval = CompareHaplotypeThenSequence (vnp1->data.ptrvalue, vnp2->data.ptrvalue, FALSE);
   }
 
   return rval;
 }
 
 
-static int CompareSequenceThenHaplotype (HaplotypeSequencePtr a, HaplotypeSequencePtr b)
+static int LIBCALLBACK SortVnpByHaplotypeThenSequenceAllowNDiff (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+  int         rval = 0;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    rval = CompareHaplotypeThenSequence (vnp1->data.ptrvalue, vnp2->data.ptrvalue, TRUE);
+  }
+
+  return rval;
+}
+
+
+static int CompareSequenceThenHaplotype (HaplotypeSequencePtr a, HaplotypeSequencePtr b, Boolean allowNDiff)
 {
   int   rval = 0;
   
   if (a != NULL && b != NULL) {
-    rval = CompareSequences (a->bsp, b->bsp);
+    rval = CompareSequences (a->bsp, b->bsp, allowNDiff);
     if (rval == 0) {
       rval = StringCmp (a->taxname, b->taxname);
       if (rval == 0) {
@@ -13918,13 +15298,31 @@ static int LIBCALLBACK SortVnpBySequenceThenHaplotype (VoidPtr ptr1, VoidPtr ptr
   if (ptr1 != NULL && ptr2 != NULL) {
     vnp1 = *((ValNodePtr PNTR) ptr1);
     vnp2 = *((ValNodePtr PNTR) ptr2);
-    rval = CompareSequenceThenHaplotype (vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+    rval = CompareSequenceThenHaplotype (vnp1->data.ptrvalue, vnp2->data.ptrvalue, FALSE);
   }
 
   return rval;
 }
 
 
+static int LIBCALLBACK SortVnpBySequenceThenHaplotypeAllowNDiff (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+  int         rval = 0;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    rval = CompareSequenceThenHaplotype (vnp1->data.ptrvalue, vnp2->data.ptrvalue, TRUE);
+  }
+
+  return rval;
+}
+
+
+
 static void HaplotypeCollectionCallback (BioseqPtr bsp, Pointer data)
 {
   SeqDescrPtr sdp;
@@ -13954,44 +15352,80 @@ static void HaplotypeCollectionCallback (BioseqPtr bsp, Pointer data)
 }
 
 
-static void ReportOneHaplotypeSequenceMismatch (ValNodePtr PNTR discrepancy_list, CharPtr taxname, CharPtr haplotype, ValNodePtr mismatch_list)
-{
-  CharPtr  seq_mismatch_fmt = "%%d sequences have organism %s haplotype %s but the sequences do not match";
+static void 
+ReportOneHaplotypeSequenceMismatch 
+(ValNodePtr PNTR discrepancy_list, 
+ CharPtr taxname, 
+ CharPtr haplotype, 
+ ValNodePtr mismatch_list,
+ Boolean    allowNDiff)
+{
+  CharPtr  seq_mismatch_fmt = "%%d sequences have organism %s haplotype %s but the sequences do not match%s";
+  CharPtr  allow_N_fmt = " (allowing N to match any)";
+  CharPtr  strict_N_fmt = " (strict match)";
+  Int4     fmt_len;
   CharPtr  fmt;
 
-  fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (seq_mismatch_fmt) + StringLen (taxname) + StringLen (haplotype)));
-  sprintf (fmt, seq_mismatch_fmt, taxname, haplotype);
+  fmt_len = StringLen (seq_mismatch_fmt) + StringLen (taxname) + StringLen (haplotype);
+  if (allowNDiff) {
+    fmt_len += StringLen (allow_N_fmt);
+  } else {
+    fmt_len += StringLen (strict_N_fmt);
+  }
+
+  fmt = (CharPtr) MemNew (sizeof (Char) * fmt_len);
+  sprintf (fmt, seq_mismatch_fmt, taxname, haplotype, allowNDiff ? allow_N_fmt : strict_N_fmt);
+
   ValNodeAddPointer (discrepancy_list, 0, 
                      NewClickableItem (DISC_HAPLOTYPE_MISMATCH, fmt, mismatch_list));
   fmt = MemFree (fmt);
 }
 
 
-static void ReportHaplotypeSequenceMismatch (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+static void
+ReportOneSequenceMatchHaplotypeMismatch
+(ValNodePtr PNTR discrepancy_list, 
+ ValNodePtr mismatch_list,
+ Boolean    allowNDiff)
+{
+  CharPtr  hap_mismatch_strict_fmt = "%d sequences are identical (strict match) but have different haplotypes";
+  CharPtr  hap_mismatch_allowN_fmt = "%d sequences are identical (allowing N to match any) but have different haplotypes";
+  ValNodePtr src_qual, field_list, extended_item_list;
+
+  src_qual = ValNodeNew (NULL);
+  src_qual->choice = SourceQualChoice_textqual;
+  src_qual->data.intvalue = Source_qual_haplotype;
+  field_list = ValNodeNew (NULL);
+  field_list->choice = FieldType_source_qual;
+  field_list->data.ptrvalue = src_qual;
+    
+  extended_item_list = MakeObjectListWithFields (mismatch_list, field_list);
+  mismatch_list = ValNodeFree (mismatch_list);
+  field_list = FieldTypeListFree (field_list);
+
+  ValNodeAddPointer (discrepancy_list, 0,
+                     NewClickableItem (DISC_HAPLOTYPE_MISMATCH, 
+                                       allowNDiff ? hap_mismatch_allowN_fmt : hap_mismatch_strict_fmt, extended_item_list));
+}
+
+
+static ValNodePtr ReportHaplotypeSequenceMismatchForList (ValNodePtr PNTR haplotype_sequence_list, Boolean allow_NDiff)
 {
-  ValNodePtr vnp, vnp_h;
-  ValNodePtr haplotype_sequence_list, same_list, subcat = NULL;
+  ValNodePtr vnp_h;
+  ValNodePtr same_list, subcat = NULL;
   HaplotypeSequencePtr h1, h2;
-  CharPtr  hap_mismatch_fmt = "%d sequences are identical but have different haplotypes";
   Boolean  have_mismatch;
-  ClickableItemPtr cip;
 
-  if (discrepancy_list == NULL || sep_list == NULL) {
-    return;
+  if (haplotype_sequence_list == NULL || *haplotype_sequence_list == NULL) {
+    return subcat;
   }
 
-  /* Note - analysis should be performed separately for each SeqEntry, rather than for the list as a whole */
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    haplotype_sequence_list = NULL;
-    VisitBioseqsInSep (vnp->data.ptrvalue, &haplotype_sequence_list, HaplotypeCollectionCallback);
-
-    if (haplotype_sequence_list != NULL) {
       /* first, look for same taxname, same haplotype, different sequence */
-      haplotype_sequence_list = ValNodeSort (haplotype_sequence_list, SortVnpByHaplotypeThenSequence);
+  *haplotype_sequence_list = ValNodeSort (*haplotype_sequence_list, allow_NDiff ? SortVnpByHaplotypeThenSequence : SortVnpByHaplotypeThenSequence);
       have_mismatch = FALSE;
       same_list = NULL;
-      h1 = haplotype_sequence_list->data.ptrvalue;
-      for (vnp_h = haplotype_sequence_list->next; vnp_h != NULL; vnp_h = vnp_h->next) {
+  h1 = (*haplotype_sequence_list)->data.ptrvalue;
+  for (vnp_h = (*haplotype_sequence_list)->next; vnp_h != NULL; vnp_h = vnp_h->next) {
         h2 = vnp_h->data.ptrvalue;
         if (StringCmp (h1->taxname, h2->taxname) == 0 && StringCmp (h1->haplotype, h2->haplotype) == 0) {
           if (same_list == NULL) {
@@ -13999,14 +15433,14 @@ static void ReportHaplotypeSequenceMismatch (ValNodePtr PNTR discrepancy_list, V
             ValNodeAddPointer (&same_list, OBJ_BIOSEQ, h1->bsp);
           }
           ValNodeAddPointer (&same_list, OBJ_BIOSEQ, h2->bsp);
-          if (!DoSequencesMatchForHaplotype (h1->bsp, h2->bsp)) {
+      if (!DoSequencesMatchForHaplotype (h1->bsp, h2->bsp, allow_NDiff)) {
             have_mismatch = TRUE;
           }
         } else {
           if (same_list != NULL) {
             /* add discrepancy report */
             if (have_mismatch) {
-              ReportOneHaplotypeSequenceMismatch (&subcat, h1->taxname, h1->haplotype, same_list);
+          ReportOneHaplotypeSequenceMismatch (&subcat, h1->taxname, h1->haplotype, same_list, allow_NDiff);
             } else {
               same_list = ValNodeFree (same_list);
             }
@@ -14018,20 +15452,20 @@ static void ReportHaplotypeSequenceMismatch (ValNodePtr PNTR discrepancy_list, V
       if (same_list != NULL) {
         if (have_mismatch) {
           /* add discrepancy report */
-          ReportOneHaplotypeSequenceMismatch (&subcat, h1->taxname, h1->haplotype, same_list);
+      ReportOneHaplotypeSequenceMismatch (&subcat, h1->taxname, h1->haplotype, same_list, allow_NDiff);
         } else {
           same_list = ValNodeFree (same_list);
         }
       }
 
       /* now look for sequence that match but have different haplotypes */
-      haplotype_sequence_list = ValNodeSort (haplotype_sequence_list, SortVnpBySequenceThenHaplotype);
+  *haplotype_sequence_list = ValNodeSort (*haplotype_sequence_list, allow_NDiff ? SortVnpBySequenceThenHaplotypeAllowNDiff : SortVnpBySequenceThenHaplotype);
       same_list = NULL;
       have_mismatch = FALSE;
-      h1 = haplotype_sequence_list->data.ptrvalue;
-      for (vnp_h = haplotype_sequence_list->next; vnp_h != NULL; vnp_h = vnp_h->next) {
+  h1 = (*haplotype_sequence_list)->data.ptrvalue;
+  for (vnp_h = (*haplotype_sequence_list)->next; vnp_h != NULL; vnp_h = vnp_h->next) {
         h2 = vnp_h->data.ptrvalue;
-        if (CompareSequences (h1->bsp, h2->bsp) == 0) {
+    if (CompareSequences (h1->bsp, h2->bsp, allow_NDiff) == 0) {
           if (same_list == NULL) {
             ValNodeAddPointer (&same_list, OBJ_BIOSEQ, h1->bsp);
             have_mismatch = FALSE;
@@ -14043,7 +15477,7 @@ static void ReportHaplotypeSequenceMismatch (ValNodePtr PNTR discrepancy_list, V
         } else {
           if (same_list != NULL) {
             if (have_mismatch) {
-              ValNodeAddPointer (&subcat, 0, NewClickableItem (DISC_HAPLOTYPE_MISMATCH, hap_mismatch_fmt, same_list));
+          ReportOneSequenceMatchHaplotypeMismatch (&subcat, same_list, allow_NDiff);
             } else {
               same_list = ValNodeFree (same_list);
             }
@@ -14054,26 +15488,63 @@ static void ReportHaplotypeSequenceMismatch (ValNodePtr PNTR discrepancy_list, V
       }
       if (same_list != NULL) {
         if (have_mismatch) {
-          ValNodeAddPointer (&subcat, 0, NewClickableItem (DISC_HAPLOTYPE_MISMATCH, hap_mismatch_fmt, same_list));
+      ReportOneSequenceMatchHaplotypeMismatch (&subcat, same_list, allow_NDiff);
         } else {
           same_list = ValNodeFree (same_list);
         }
         same_list = NULL;
       }
-    }
 
-    haplotype_sequence_list = ValNodeFreeData (haplotype_sequence_list);
-  }
-  if (subcat != NULL) {
     subcat = ValNodeSort (subcat, SortVnpByDiscrepancyDescription);
     ValNodeReverse (&subcat);
 
-    cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
-    MemSet (cip, 0, sizeof (ClickableItemData));
-    cip->clickable_item_type = DISC_HAPLOTYPE_MISMATCH;
-    cip->description = StringSave ("Haplotype Problem Report");
-    cip->subcategories = subcat;
-    ValNodeAddPointer (discrepancy_list, 0, cip);
+  return subcat;
+}
+
+
+static void ReportHaplotypeSequenceMismatch (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr vnp;
+  ValNodePtr haplotype_sequence_list, strict_match = NULL, nonstrict_match = NULL, subcat = NULL;
+  CharPtr  mismatch_loose_fmt = "There are %d haplotype problems (loose match, allowing Ns to differ)";
+  CharPtr  mismatch_strict_fmt = "There are %d haplotype problems (strict match)";
+  ClickableItemPtr cip_main, cip_loose = NULL, cip_strict = NULL;
+
+  if (discrepancy_list == NULL || sep_list == NULL) {
+    return;
+  }
+
+  /* Note - analysis should be performed separately for each SeqEntry, rather than for the list as a whole */
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    haplotype_sequence_list = NULL;
+    VisitBioseqsInSep (vnp->data.ptrvalue, &haplotype_sequence_list, HaplotypeCollectionCallback);
+
+    nonstrict_match = ReportHaplotypeSequenceMismatchForList (&haplotype_sequence_list, TRUE);
+    if (nonstrict_match != NULL) {
+      cip_loose = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+      cip_loose->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (mismatch_loose_fmt) + 15));
+      sprintf (cip_loose->description, mismatch_loose_fmt, ValNodeLen (nonstrict_match));
+      cip_loose->subcategories = nonstrict_match;
+      ValNodeAddPointer (&subcat, 0, cip_loose);
+    }
+
+    strict_match = ReportHaplotypeSequenceMismatchForList (&haplotype_sequence_list, FALSE);
+    if (strict_match != NULL) {
+      cip_strict = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+      cip_strict->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (mismatch_strict_fmt) + 15));
+      sprintf (cip_strict->description, mismatch_strict_fmt, ValNodeLen (strict_match));
+      cip_strict->subcategories = strict_match;
+      ValNodeAddPointer (&subcat, 0, cip_strict);
+    }
+  }
+
+  if (subcat != NULL) {
+    cip_main = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+    MemSet (cip_main, 0, sizeof (ClickableItemData));
+    cip_main->clickable_item_type = DISC_HAPLOTYPE_MISMATCH;
+    cip_main->description = StringSave ("Haplotype Problem Report");
+    cip_main->subcategories = subcat;
+    ValNodeAddPointer (discrepancy_list, 0, cip_main);
   }
 }
 
@@ -14161,6 +15632,7 @@ static void ChangeMoltypeToGenomicDNA (ValNodePtr item_list, Pointer data, LogIn
           sdp->data.ptrvalue = mip;
         }
         mip->biomol = MOLECULE_TYPE_GENOMIC;
+        bsp->strand = 0;
         if (lip != NULL && lip->fp != NULL) {
           SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
           fprintf (lip->fp, "Changed biomol for %s\n", id_txt);
@@ -14248,7 +15720,11 @@ static void ReportCDSWithoutmRNACallback (BioseqPtr bsp, Pointer data)
     if (IsPseudo (sfp)) {
       continue;
     }
+    mRNA = SeqMgrGetLocationSupersetmRNA (sfp->location, &mcontext);
+    if (mRNA == NULL) {
     mRNA = SeqMgrGetOverlappingmRNA (sfp->location, &mcontext);
+    }
+
     if (mRNA == NULL) {
       ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, sfp);
     } else {
@@ -14657,31 +16133,13 @@ static void ReportmRNAOnNonGenomicEukaryoticSequences (ValNodePtr PNTR discrepan
 /* if an intron starts or stops between the start of one exon and the end of the next exon, it should
  * abut both exons.
  */
-static void CheckIntronAndExonLocationsOnBioseq (BioseqPtr bsp, Pointer data)
+
+static ValNodePtr CompareIntronExonList (ValNodePtr exon_list, ValNodePtr intron_list)
 {
   SeqFeatPtr        exon, next_exon, intron;
-  SeqMgrFeatContext fcontext;
-  ValNodePtr        exon_list = NULL, intron_list = NULL, vnp_e, vnp_i;
+  ValNodePtr        vnp_e, vnp_i;
   Int4              exon_start, exon_stop, intron_start, intron_stop, next_exon_start, next_exon_stop;
   ValNodePtr        problem_list = NULL;
-  Char              id[255];
-  CharPtr           fmt, problems_fmt = "%%d introns and exons have location conflicts on %s";
-
-  if (bsp == NULL || ISA_aa (bsp->mol) || data == NULL) {
-    return;
-  }
-
-  for (exon = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_exon, &fcontext);
-       exon != NULL;
-       exon = SeqMgrGetNextFeature (bsp, exon, 0, FEATDEF_exon, &fcontext)) {
-    ValNodeAddPointer (&exon_list, OBJ_SEQFEAT, exon);
-  }
-
-  for (intron = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_intron, &fcontext);
-       intron != NULL;
-       intron = SeqMgrGetNextFeature (bsp, intron, 0, FEATDEF_intron, &fcontext)) {
-    ValNodeAddPointer (&intron_list, OBJ_SEQFEAT, intron);
-  }
 
   if (exon_list != NULL && intron_list != NULL) {
     exon = exon_list->data.ptrvalue;
@@ -14739,6 +16197,72 @@ static void CheckIntronAndExonLocationsOnBioseq (BioseqPtr bsp, Pointer data)
     }
 
     RemoveDuplicateItems (&problem_list);
+  }
+  return problem_list;
+}
+
+
+static ValNodePtr GetFeatureListForGene (BioseqPtr bsp, SeqFeatPtr gene, Uint1 featdef)
+{
+  SeqFeatPtr        feat, feat_gene;
+  SeqMgrFeatContext fcontext, gcontext;
+  ValNodePtr        feat_list = NULL;
+  GeneRefPtr        grp;
+
+  for (feat = SeqMgrGetNextFeature (bsp, NULL, 0, featdef, &fcontext);
+       feat != NULL;
+       feat = SeqMgrGetNextFeature (bsp, feat, 0, featdef, &fcontext)) {
+    if (gene == NULL) {
+      /* collect all */
+      ValNodeAddPointer (&feat_list, OBJ_SEQFEAT, feat);
+    } else if ((grp = SeqMgrGetGeneXref (feat)) == NULL) {
+      /* find by overlap */
+      feat_gene = SeqMgrGetOverlappingGene(feat->location, &gcontext);
+      if (feat_gene == gene) {
+        ValNodeAddPointer (&feat_list, OBJ_SEQFEAT, feat);
+      }
+    } else if (!SeqMgrGeneIsSuppressed(grp) && GeneRefMatch(grp, gene->data.value.ptrvalue)) {
+      ValNodeAddPointer (&feat_list, OBJ_SEQFEAT, feat);
+    }
+  }
+  return feat_list;
+}
+
+
+static void CheckIntronAndExonLocationsOnBioseq (BioseqPtr bsp, Pointer data)
+{
+  SeqFeatPtr        gene;
+  SeqMgrFeatContext gcontext;
+  ValNodePtr        exon_list = NULL, intron_list = NULL;
+  ValNodePtr        problem_list = NULL;
+  Char              id[255];
+  CharPtr           fmt, problems_fmt = "%%d introns and exons have location conflicts on %s";
+
+  if (bsp == NULL || ISA_aa (bsp->mol) || data == NULL) {
+    return;
+  }
+
+  gene = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_GENE, 0, &gcontext);
+  if (gene == NULL) {
+    /* no genes - just do all exons and introns present */
+    exon_list = GetFeatureListForGene (bsp, NULL, FEATDEF_exon);
+    intron_list = GetFeatureListForGene (bsp, NULL, FEATDEF_intron);
+    problem_list = CompareIntronExonList (exon_list, intron_list);
+    exon_list = ValNodeFree (exon_list);
+    intron_list = ValNodeFree (intron_list);
+  } else {
+    while (gene != NULL) {
+      if (StringICmp (gene->except_text, "trans-splicing") != 0) {
+        exon_list = GetFeatureListForGene (bsp, gene, FEATDEF_exon);
+        intron_list = GetFeatureListForGene (bsp, gene, FEATDEF_intron);
+        ValNodeLink (&problem_list, CompareIntronExonList (exon_list, intron_list));
+        exon_list = ValNodeFree (exon_list);
+        intron_list = ValNodeFree (intron_list);
+      }
+      gene = SeqMgrGetNextFeature (bsp, gene, SEQFEAT_GENE, 0, &gcontext);
+    }
+  }
+
     if (problem_list != NULL) {
       SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id, PRINTID_REPORT, sizeof (id) - 1);
       fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (problems_fmt) + StringLen (id)));
@@ -14746,10 +16270,7 @@ static void CheckIntronAndExonLocationsOnBioseq (BioseqPtr bsp, Pointer data)
       ValNodeAddPointer ((ValNodePtr PNTR) data, 0, NewClickableItem (DISC_EXON_INTRON_CONFLICT, fmt, problem_list));
       fmt = MemFree (fmt);
     }
-  }
 
-  exon_list = ValNodeFree (exon_list);
-  intron_list = ValNodeFree (intron_list);
 }
 
 
@@ -14849,6 +16370,7 @@ static void SaveFeatureCountSequenceIds (ValNodePtr list, CharPtr filename)
   FeatureCountPtr f;
   ValNode vn;
 
+  MemSet (&vn, 0, sizeof (ValNode));
   vn.choice = OBJ_BIOSEQ;
   vn.next = NULL;
   while (list != NULL) {
@@ -15270,20 +16792,20 @@ static void CountFeaturesOnSequences (ValNodePtr PNTR discrepancy_list, ValNodeP
 }
 
 
-typedef struct specvouchertaxname {
-  CharPtr specvoucher;
+typedef struct taxnameconflict {
+  CharPtr qual;
   CharPtr taxname;
   Uint1   obj_type;
   Pointer obj_data;
-} SpecVoucherTaxNameData, PNTR SpecVoucherTaxNamePtr;
+} TaxNameConflictData, PNTR TaxNameConflictPtr;
 
 
-static SpecVoucherTaxNamePtr SpecVoucherTaxNameNew (CharPtr specvoucher, CharPtr taxname, Uint1 obj_type, Pointer obj_data)
+static TaxNameConflictPtr TaxNameConflictNew (CharPtr qual, CharPtr taxname, Uint1 obj_type, Pointer obj_data)
 {
-  SpecVoucherTaxNamePtr h;
+  TaxNameConflictPtr h;
 
-  h = (SpecVoucherTaxNamePtr) MemNew (sizeof (SpecVoucherTaxNameData));
-  h->specvoucher = specvoucher;
+  h = (TaxNameConflictPtr) MemNew (sizeof (TaxNameConflictData));
+  h->qual = qual;
   h->taxname = taxname;
   h->obj_type = obj_type;
   h->obj_data = obj_data;
@@ -15291,12 +16813,12 @@ static SpecVoucherTaxNamePtr SpecVoucherTaxNameNew (CharPtr specvoucher, CharPtr
 }
 
 
-static int LIBCALLBACK SortSpecVoucherTaxname (VoidPtr ptr1, VoidPtr ptr2)
+static int LIBCALLBACK SortTaxNameConflict (VoidPtr ptr1, VoidPtr ptr2)
 
 {
   ValNodePtr  vnp1;
   ValNodePtr  vnp2;
-  SpecVoucherTaxNamePtr s1, s2;
+  TaxNameConflictPtr s1, s2;
   int         rval = 0;
 
   if (ptr1 != NULL && ptr2 != NULL) {
@@ -15305,7 +16827,7 @@ static int LIBCALLBACK SortSpecVoucherTaxname (VoidPtr ptr1, VoidPtr ptr2)
     s1 = vnp1->data.ptrvalue;
     s2 = vnp2->data.ptrvalue;
     if (s1 != NULL && s2 != NULL) {
-      rval = StringICmp (s1->specvoucher, s2->specvoucher);
+      rval = StringICmp (s1->qual, s2->qual);
       if (rval == 0) {
         rval = StringICmp (s1->taxname, s2->taxname);
       }
@@ -15316,6 +16838,83 @@ static int LIBCALLBACK SortSpecVoucherTaxname (VoidPtr ptr1, VoidPtr ptr2)
 }
 
 
+static void CollectTaxnameConflictDiscrepancies 
+(ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list, 
+ VisitFeaturesFunc feat_callback, VisitDescriptorsFunc desc_callback,
+ CharPtr qual_name, Uint4 item_type)
+{
+  ValNodePtr vnp;
+  ValNodePtr st_list = NULL, spec_list = NULL, disc_list = NULL;
+  TaxNameConflictPtr st1, st2 = NULL;
+  Boolean               have_mismatch;
+  CharPtr               spec_fmt = "%%d biosources have %s %s but do not have the same taxnames";
+  CharPtr               top_fmt = "%%d BioSources have %s/taxname conflicts";
+  CharPtr               fmt;
+  ClickableItemPtr      cip;
+
+  if (sep_list == NULL || discrepancy_list == NULL) {
+    return;
+  }
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitDescriptorsInSep (vnp->data.ptrvalue, &st_list, desc_callback);
+    VisitFeaturesInSep (vnp->data.ptrvalue, &st_list, feat_callback);
+  }
+
+  if (st_list != NULL) {
+    st_list = ValNodeSort (st_list, SortTaxNameConflict);
+    st1 = st_list->data.ptrvalue;
+    ValNodeAddPointer (&spec_list, st1->obj_type, st1->obj_data);
+    have_mismatch = FALSE;
+    for (vnp = st_list->next; vnp != NULL; vnp = vnp->next) {
+      st2 = vnp->data.ptrvalue;
+      if (StringICmp (st1->qual, st2->qual) == 0) {
+        ValNodeAddPointer (&spec_list, st2->obj_type, st2->obj_data);
+        if (StringICmp (st1->taxname, st2->taxname) != 0) {
+          have_mismatch = TRUE;
+        }
+      } else {
+        if (have_mismatch) {
+          fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (spec_fmt) + StringLen (qual_name) + StringLen (st1->qual)));
+          sprintf (fmt, spec_fmt, qual_name, st1->qual);
+          ValNodeAddPointer (&disc_list, 0, NewClickableItem (item_type, fmt, spec_list));
+          fmt = MemFree (fmt);
+          spec_list = NULL;
+        } 
+        spec_list = ValNodeFree (spec_list);
+        have_mismatch = FALSE;
+        ValNodeAddPointer (&spec_list, st2->obj_type, st2->obj_data);
+      }
+      st1 = st2;
+    }
+    if (have_mismatch) {
+      fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (spec_fmt) + StringLen (qual_name) + StringLen (st1->qual)));
+      sprintf (fmt, spec_fmt, qual_name, st1->qual);
+      ValNodeAddPointer (&disc_list, 0, NewClickableItem (item_type, fmt, spec_list));
+      fmt = MemFree (fmt);
+      spec_list = NULL;
+    } 
+    spec_list = ValNodeFree (spec_list);
+    have_mismatch = FALSE;
+
+    if (disc_list != NULL) {
+      if (disc_list->next == NULL) {
+        ValNodeLink (discrepancy_list, disc_list);
+      } else {
+        fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (top_fmt) + StringLen (qual_name)));
+        sprintf (fmt, top_fmt, qual_name);
+        cip = NewClickableItem (item_type, fmt, ItemListFromSubcategories (disc_list));
+        fmt = MemFree (fmt);
+        cip->subcategories = disc_list;
+        ValNodeAddPointer (discrepancy_list, 0, cip);
+      }
+    }
+    st_list = ValNodeFreeData (st_list);
+  }
+
+}
+
+
 static Boolean s_StringHasVoucherSN (CharPtr str)
 {
   if (DoesStringContainPhrase (str, "s.n.", TRUE, TRUE)) {
@@ -15341,7 +16940,7 @@ static void CollectSpecVoucherTaxnameCallback (Uint1 obj_type, Pointer obj_data,
     mod = mod->next;
   }
   if (mod != NULL) {
-    ValNodeAddPointer (list, 0, SpecVoucherTaxNameNew (mod->subname, biop->org->taxname, obj_type, obj_data));
+    ValNodeAddPointer (list, 0, TaxNameConflictNew (mod->subname, biop->org->taxname, obj_type, obj_data));
   }
 }
 
@@ -15364,70 +16963,55 @@ static void CollectSpecVoucherTaxnameDesc (SeqDescrPtr sdp, Pointer data)
 
 static void CollectSpecVoucherTaxnameDiscrepancies (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
-  ValNodePtr vnp;
-  ValNodePtr st_list = NULL, spec_list = NULL, disc_list = NULL;
-  SpecVoucherTaxNamePtr st1, st2;
-  Boolean               have_mismatch;
-  CharPtr               spec_fmt = "%%d biosources have specimen voucher %s but do not have the same taxnames";
-  CharPtr               fmt;
-  ClickableItemPtr      cip;
+  CollectTaxnameConflictDiscrepancies (discrepancy_list, sep_list, 
+                                       CollectSpecVoucherTaxnameFeat,
+                                       CollectSpecVoucherTaxnameDesc,
+                                       "specimen voucher",
+                                       DISC_SPECVOUCHER_TAXNAME_MISMATCH);
+}
 
-  if (sep_list == NULL || discrepancy_list == NULL) {
-    return;
-  }
 
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    VisitDescriptorsInSep (vnp->data.ptrvalue, &st_list, CollectSpecVoucherTaxnameDesc);
-    VisitFeaturesInSep (vnp->data.ptrvalue, &st_list, CollectSpecVoucherTaxnameFeat);
-  }
+static void CollectStrainTaxnameCallback (Uint1 obj_type, Pointer obj_data, BioSourcePtr biop, ValNodePtr PNTR list)
+{
+  OrgModPtr mod;
 
-  if (st_list != NULL) {
-    st_list = ValNodeSort (st_list, SortSpecVoucherTaxname);
-    st1 = st_list->data.ptrvalue;
-    ValNodeAddPointer (&spec_list, st1->obj_type, st1->obj_data);
-    have_mismatch = FALSE;
-    for (vnp = st_list->next; vnp != NULL; vnp = vnp->next) {
-      st2 = vnp->data.ptrvalue;
-      if (StringICmp (st1->specvoucher, st2->specvoucher) == 0) {
-        ValNodeAddPointer (&spec_list, st2->obj_type, st2->obj_data);
-        if (StringICmp (st1->taxname, st2->taxname) != 0) {
-          have_mismatch = TRUE;
-        }
-      } else {
-        if (have_mismatch) {
-          fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (spec_fmt) + StringLen (st1->specvoucher)));
-          sprintf (fmt, spec_fmt, st1->specvoucher);
-          ValNodeAddPointer (&disc_list, 0, NewClickableItem (DISC_SPECVOUCHER_TAXNAME_MISMATCH, fmt, spec_list));
-          spec_list = NULL;
-        } 
-        spec_list = ValNodeFree (spec_list);
-        have_mismatch = FALSE;
-        ValNodeAddPointer (&spec_list, st2->obj_type, st2->obj_data);
+  if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL || list == NULL) {
+    return;
       }
-      st1 = st2;
+
+  mod = biop->org->orgname->mod;
+  while (mod != NULL && mod->subtype != ORGMOD_strain) {
+    mod = mod->next;
     }
-    if (have_mismatch) {
-      fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (spec_fmt) + StringLen (st1->specvoucher)));
-      sprintf (fmt, spec_fmt, st1->specvoucher);
-      ValNodeAddPointer (&disc_list, 0, NewClickableItem (DISC_SPECVOUCHER_TAXNAME_MISMATCH, fmt, spec_list));
-      spec_list = NULL;
+  if (mod != NULL) {
+    ValNodeAddPointer (list, 0, TaxNameConflictNew (mod->subname, biop->org->taxname, obj_type, obj_data));
     } 
-    spec_list = ValNodeFree (spec_list);
-    have_mismatch = FALSE;
-    ValNodeAddPointer (&spec_list, st2->obj_type, st2->obj_data);
+}
 
-    if (disc_list != NULL) {
-      if (disc_list->next == NULL) {
-        ValNodeLink (discrepancy_list, disc_list);
-      } else {
-        cip = NewClickableItem (DISC_SPECVOUCHER_TAXNAME_MISMATCH, "%d BioSources have specimen voucher/taxname conflicts", ItemListFromSubcategories (disc_list));
-        cip->subcategories = disc_list;
-        ValNodeAddPointer (discrepancy_list, 0, cip);
-      }
+
+static void CollectStrainTaxnameFeat (SeqFeatPtr sfp, Pointer data)
+{
+  if (sfp != NULL && sfp->data.choice == SEQFEAT_BIOSRC) {
+    CollectStrainTaxnameCallback (OBJ_SEQFEAT, sfp, sfp->data.value.ptrvalue, data);
     }
-    st_list = ValNodeFreeData (st_list);
+}
+
+
+static void CollectStrainTaxnameDesc (SeqDescrPtr sdp, Pointer data)
+{
+  if (sdp != NULL && sdp->choice == Seq_descr_source) {
+    CollectStrainTaxnameCallback (OBJ_SEQDESC, sdp, sdp->data.ptrvalue, data);
   }
+}
+
 
+static void CollectStrainTaxnameDiscrepancies (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  CollectTaxnameConflictDiscrepancies (discrepancy_list, sep_list, 
+                                       CollectStrainTaxnameFeat,
+                                       CollectStrainTaxnameDesc,
+                                       "strain",
+                                       DISC_STRAIN_TAXNAME_MISMATCH);
 }
 
 
@@ -15719,7 +17303,9 @@ static void FlatfileTextFind (
   BlockType blocktype,
   Uint2 entityID,
   Uint2 itemtype,
-  Uint4 itemID
+  Uint4 itemID,
+  Int4 left,
+  Int4 right
 )
 
 {
@@ -15849,12 +17435,10 @@ static CharPtr flatfile_find_list_oncaller[] = {
  "uiniversity",
  "uinversity",
  "univesity",
+ "uviversity",
  "putatvie",
  "putaitve",
  "protien",
- "homologue",
- "orthologue",
- "paralogue",
  "simmilar",
  "Insitiute",
  "Instutite",
@@ -15865,17 +17449,13 @@ static CharPtr flatfile_find_list_oncaller[] = {
  "ribosoml",
  "transcirbed",
  "Agricultutral", 
- "characterised",
- "recognised",
+ "agriculturral",
  "resaerch",
- "characterisation",
  "charaterization",
- "localisation",
  "clonging",
  "anaemia",
  "heam",
  "haem",
- "tumour",
  "technlogy",
  "technolgy",
  "biotechnlogy",
@@ -15889,20 +17469,16 @@ static CharPtr flatfile_find_list_oncaller[] = {
  "putataive",
  "putatuve",
  "cotaining",
- "uncharacterised",
  "hypothteical",
  "hypotethical",
  "hypothetcial",
  "consevered",
  "haemagglutination",
- "oxydase",
- "colour",
  "indepedent",
  "reserch",
  "agricultral",
  "Bacilllus",
  "catalize",
- "localise",
  "subitilus",
  "P.R.Chian",
  "PRChian",
@@ -15915,7 +17491,6 @@ static CharPtr flatfile_find_list_oncaller[] = {
  "scinece",
  "enivronment",
  "structual",
- "faecal",
  "sulfer",
  NULL
 };
@@ -15974,107 +17549,158 @@ static void OncallerToolSpellFix (ValNodePtr item_list, Pointer data, LogInfoPtr
 }
 
 
-static CharPtr cds_product_find[] = {
- "-like",
- "pseudo",
- "fragment", /* wholeword start */
- "similar",
- "frameshift",
- "partial",
- "homolog",
- "paralog",
- "ortholog",
- "gene",
- "genes",
- "related",
- "terminus",
- "N-terminus",
- "C-terminus",
- "frame",
- NULL};
+static SuspectProductNameData cds_product_find[] = {
+  { "-like", EndsWithPattern } ,
+  { "pseudo", ContainsPseudo } ,
+  { "fragment", ContainsWholeWord } ,
+  { "similar", ContainsWholeWord } ,
+  { "frameshift", ContainsWholeWord } ,
+  { "partial", ContainsWholeWord } ,
+  { "homolog", ContainsWholeWord } ,
+  { "homologue", ContainsWholeWord } ,
+  { "paralog", ContainsWholeWord } ,
+  { "paralogue", ContainsWholeWord } ,
+  { "ortholog", ContainsWholeWord } ,
+  { "orthologue", ContainsWholeWord } ,
+  { "gene", ContainsWholeWord } ,
+  { "genes", ContainsWholeWord } ,
+  { "related", ContainsWholeWord } ,
+  { "terminus", ContainsWholeWord } ,
+  { "N-terminus", ContainsWholeWord } ,
+  { "C-terminus", ContainsWholeWord } ,
+  { "characterised", ContainsWholeWord } ,
+  { "recognised", ContainsWholeWord } ,
+  { "characterisation", ContainsWholeWord } ,
+  { "localisation", ContainsWholeWord } ,
+  { "tumour", ContainsWholeWord } ,
+  { "uncharacterised", ContainsWholeWord } ,
+  { "oxydase", ContainsWholeWord } ,
+  { "colour", ContainsWholeWord } ,
+  { "localise", ContainsWholeWord } ,
+  { "faecal", ContainsWholeWord } ,
+  { "frame"}
+};
 
-const int cds_product_find_wholeword_start = 2;
+const int num_cds_product_find = sizeof (cds_product_find) / sizeof (SuspectProductNameData);
 
 static void FindCodingRegions (SeqFeatPtr sfp, Pointer userdata)
 {
-  if (sfp != NULL && sfp->data.choice == SEQFEAT_CDREGION && userdata != NULL) {
-    ValNodeAddPointer ((ValNodePtr PNTR) userdata, OBJ_SEQFEAT, sfp);
+  ValNodePtr PNTR feature_list;
+  Int4            k;
+  ProtRefPtr      prp;
+  ValNodePtr      vnp;
+  BioseqPtr       bsp;
+  SeqFeatPtr      cds;
+  
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT || sfp->data.value.ptrvalue == NULL
+      || userdata == NULL)
+  {
+    return;
+  }
+  
+  prp = (ProtRefPtr) sfp->data.value.ptrvalue;
+  feature_list = (ValNodePtr PNTR) userdata;
+
+  /* add coding region rather than protein */
+  if (sfp->idx.subtype == FEATDEF_PROT) {
+    bsp = BioseqFindFromSeqLoc (sfp->location);
+    if (bsp != NULL) {
+      cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
+      if (cds != NULL) {
+        sfp = cds;
+      }
+    }
+  }
+  
+  for (k = 0; k < num_cds_product_find; k++)
+  {
+    for (vnp = prp->name; vnp != NULL; vnp = vnp->next) 
+    {
+      if (cds_product_find[k].search_func != NULL
+        && (cds_product_find[k].search_func) (cds_product_find[k].pattern, vnp->data.ptrvalue)) 
+      {
+        ValNodeAddPointer (&(feature_list[k]), OBJ_SEQFEAT, sfp);
+        break;
+      }
+    }
   }
 }
 
+
 static void FindTextInCDSProduct (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
-  ValNodePtr feat_list = NULL, vnp;
-  ValNodePtr PNTR string_lists;
-  FieldTypePtr    field = NULL;
-  FeatureFieldPtr ff;
-  Int4 i, num = 0, len;
-  CharPtr str;
-  CharPtr str_fmt = "%%d coding region products contain '%s'", fmt;
+  ValNodePtr PNTR feature_list;
+  ValNodePtr         master_list = NULL, vnp;
+  Int4               k;
+  ClickableItemPtr dip;
+  ValNodePtr         subcategories = NULL;
 
   if (discrepancy_list == NULL || sep_list == NULL) {
     return;
   }
 
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    VisitFeaturesInSep (vnp->data.ptrvalue, &feat_list, FindCodingRegions);
-  }
+  feature_list = (ValNodePtr PNTR) MemNew (sizeof (ValNodePtr) * num_cds_product_find);
+  if (feature_list == NULL) return;
 
-  if (feat_list != NULL) {
-    /* count strings to search for */
-    for (i = 0; cds_product_find[i] != NULL; i++) {}
-    num = i;
-    string_lists = (ValNodePtr PNTR) MemNew (sizeof (ValNodePtr) * num);
-    for (i = 0; i < num; i++) {
-      string_lists[i] = NULL;
+  /* initialize array for suspicious product names */
+  for (k = 0; k < num_cds_product_find; k++)
+  {
+    feature_list[k] = NULL;
     }
 
-    ff = FeatureFieldNew ();
-    ff->type = Feature_type_cds;
-    ValNodeAddInt (&(ff->field), FeatQualChoice_legal_qual, Feat_qual_legal_product);
-    ValNodeAddPointer (&field, FieldType_feature_field, ff);
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitFeaturesInSep (vnp->data.ptrvalue, feature_list, FindCodingRegions);
+  }
 
-    for (vnp = feat_list; vnp != NULL; vnp = vnp->next) {
-      str = GetFieldValueForObject (vnp->choice, vnp->data.ptrvalue, field, NULL);
-      if (str != NULL) {
-        for (i = 0; cds_product_find[i] != NULL; i++) {
-          if (StringICmp (cds_product_find[i], "-like") == 0) {
-            len = StringLen (str);
-            if (len > 4 && StringICmp (str + len - 5, cds_product_find[i]) == 0) {
-              ValNodeAddPointer (&(string_lists[i]), vnp->choice, vnp->data.ptrvalue);
+  for (k = 0; k < num_cds_product_find; k++)
+  {
+    if (feature_list[k] != NULL)
+    {
+      if (cds_product_find[k].search_func == EndsWithPattern) 
+      {
+        dip = SuspectPhraseEnd (DISC_CDS_PRODUCT_FIND, cds_product_find[k].pattern, "coding region product", feature_list[k]);
             }
-          } else if (DoesStringContainPhrase (str, cds_product_find[i], FALSE, i > cds_product_find_wholeword_start)) {
-            ValNodeAddPointer (&(string_lists[i]), vnp->choice, vnp->data.ptrvalue);
+      else if (cds_product_find[k].search_func == StartsWithPattern) 
+      {
+        dip = SuspectPhraseStart (DISC_CDS_PRODUCT_FIND, cds_product_find[k].pattern, "coding region product", feature_list[k]);
           }
+      else 
+      {
+        dip = SuspectPhrase (DISC_CDS_PRODUCT_FIND, cds_product_find[k].pattern, "coding region product", feature_list[k]);
         }
+      if (dip != NULL)
+      {
+        ValNodeAddPointer (&subcategories, 0, dip);
       }
+      ValNodeLinkCopy (&master_list, feature_list[k]);
     }
-    for (i = 0; i < num; i++) {
-      if (string_lists[i] != NULL) {
-        fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str_fmt) + StringLen (cds_product_find[i])));
-        sprintf (fmt, str_fmt, cds_product_find[i]);
-        ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_CDS_PRODUCT_FIND, fmt, string_lists[i]));
-        fmt = MemFree (fmt);
       }
+  
+  if (master_list != NULL)
+  {
+    dip = SuspectPhrase (DISC_CDS_PRODUCT_FIND, "suspect phrase or characters", "coding region product", master_list);
+    if (dip != NULL)
+    {
+      dip->subcategories = subcategories;
+      ValNodeAddPointer (discrepancy_list, 0, dip);
     }
-    string_lists = MemFree (string_lists);
-    feat_list = ValNodeFree (feat_list);
   }
+
+  MemFree (feature_list);
 }
 
 
 static void FindDupDeflineCallback (BioseqPtr bsp, Pointer data)
 {
   SeqDescrPtr sdp;
-  SeqMgrDescContext context;
 
   if (bsp != NULL && data != NULL && !ISA_aa (bsp->mol)) {
-    for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, &context);
-         sdp != NULL;
-         sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_title, &context)) {
+    for (sdp = bsp->descr; sdp != NULL; sdp = sdp->next) {
+      if (sdp->choice == Seq_descr_title) {
       ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQDESC, sdp);
     }
   }
+  }
 }
 
 
@@ -16254,6 +17880,71 @@ static Boolean HasATCCStrainForCultureCollection (OrgModPtr mods, CharPtr str)
 }
 
 
+typedef Boolean (*CollectBioSourceTest) PROTO ((BioSourcePtr));
+
+typedef struct collectbiosource {
+  CollectBioSourceTest test_func;
+  ValNodePtr pass_list;
+  ValNodePtr fail_list;
+} CollectBioSourceData, PNTR CollectBioSourcePtr;
+
+
+static void CollectBioSourceDescCallback (SeqDescrPtr sdp, Pointer data)
+{
+  CollectBioSourcePtr cb;
+
+  if (sdp != NULL && sdp->choice == Seq_descr_source 
+      && (cb = (CollectBioSourcePtr)data) != NULL
+      && cb->test_func != NULL) {
+    if ((cb->test_func) (sdp->data.ptrvalue)) {
+      ValNodeAddPointer (&(cb->pass_list), OBJ_SEQDESC, sdp);
+    } else {
+      ValNodeAddPointer (&(cb->fail_list), OBJ_SEQDESC, sdp);
+    }
+  }
+}
+
+
+static void CollectBioSourceFeatCallback (SeqFeatPtr sfp, Pointer data)
+{
+  CollectBioSourcePtr cb;
+
+  if (sfp != NULL && sfp->data.choice == SEQFEAT_BIOSRC 
+      && (cb = (CollectBioSourcePtr)data) != NULL
+      && cb->test_func != NULL) {
+    if ((cb->test_func)(sfp->data.value.ptrvalue)) {
+      ValNodeAddPointer (&(cb->pass_list), OBJ_SEQFEAT, sfp);
+    } else {
+      ValNodeAddPointer (&(cb->fail_list), OBJ_SEQFEAT, sfp);
+    }
+  }
+}
+
+
+static ValNodePtr CollectBioSources (ValNodePtr sep_list, CollectBioSourceTest test_func, Boolean want_pass)
+{
+  CollectBioSourceData cb;
+  ValNodePtr vnp;
+
+  cb.test_func = test_func;
+  cb.pass_list = NULL;
+  cb.fail_list = NULL;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitDescriptorsInSep (vnp->data.ptrvalue, &cb, CollectBioSourceDescCallback);
+    VisitFeaturesInSep (vnp->data.ptrvalue, &cb, CollectBioSourceFeatCallback);
+  }
+
+  if (want_pass) {
+    cb.fail_list = ValNodeFree (cb.fail_list);
+    return cb.pass_list;
+  } else {
+    cb.pass_list = ValNodeFree (cb.pass_list);
+    return cb.fail_list;
+  }
+}
+
+
 static Boolean IsATCCStrainInCultureCollectionForBioSource (BioSourcePtr biop)
 {
   OrgModPtr mod;
@@ -16275,33 +17966,15 @@ static Boolean IsATCCStrainInCultureCollectionForBioSource (BioSourcePtr biop)
   return TRUE;
 }
 
-static void ATCCStrainCultureCollConflictDescCallback (SeqDescrPtr sdp, Pointer data)
-{
-  if (sdp != NULL && sdp->choice == Seq_descr_source && data != NULL && !IsATCCStrainInCultureCollectionForBioSource (sdp->data.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQDESC, sdp);
-  }
-}
-
-
-static void ATCCStrainCultureCollConflictFeatCallback (SeqFeatPtr sfp, Pointer data)
-{
-  if (sfp != NULL && sfp->data.choice == SEQFEAT_BIOSRC && data != NULL && !IsATCCStrainInCultureCollectionForBioSource (sfp->data.value.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, sfp);
-  }
-}
-
 
 static void CheckATCCStrainCultureCollConflict (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
-  ValNodePtr vnp, src_list = NULL;
+  ValNodePtr src_list = NULL;
 
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    VisitDescriptorsInSep (vnp->data.ptrvalue, &src_list, ATCCStrainCultureCollConflictDescCallback);
-    VisitFeaturesInSep (vnp->data.ptrvalue, &src_list, ATCCStrainCultureCollConflictFeatCallback);
-  }
+  src_list = CollectBioSources (sep_list, IsATCCStrainInCultureCollectionForBioSource, FALSE);
 
   if (src_list != NULL) {
-    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DUP_DISC_ATCC_CULTURE_CONFLICT, "%d biosources have conflicting strain and culture collection values", src_list));
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DUP_DISC_ATCC_CULTURE_CONFLICT, "%d biosources have conflicting ATCC strain and culture collection values", src_list));
   }
 }
 
@@ -16323,9 +17996,10 @@ static void AddATCCStrainToCultureColl (ValNodePtr item_list, Pointer data, LogI
   parse->fields->data.ptrvalue = pair;
 
   parse->portion = TextPortionNew ();
-  parse->portion->left_text = StringSave ("ATCC ");
+  parse->portion->left_marker = ValNodeNew (NULL);
+  parse->portion->left_marker = MakeTextTextMarker ("ATCC ");
   parse->portion->include_left = FALSE;
-  parse->portion->right_text = StringSave ("");
+  parse->portion->right_marker = NULL;
   parse->portion->include_right = FALSE;
   parse->portion->inside = TRUE;
   parse->portion->case_sensitive = FALSE;
@@ -16613,6 +18287,92 @@ static void CheckForLinkerSequence (ValNodePtr PNTR discrepancy_list, ValNodePtr
 }
 
 
+static Boolean IsMrnaSequence (BioseqPtr bsp)
+{
+  SeqDescrPtr sdp;
+  MolInfoPtr  mip;
+  SeqMgrDescContext dcontext;
+  
+  if (bsp == NULL || bsp->mol != Seq_mol_rna) {
+    return FALSE;
+  }
+
+  /* only inspect mRNA sequences */
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &dcontext);
+  if (sdp == NULL || sdp->data.ptrvalue == NULL) {
+    return FALSE;
+  }
+  mip = (MolInfoPtr) sdp->data.ptrvalue;
+  if (mip->biomol != MOLECULE_TYPE_MRNA) {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
+static void FindExonsOnMrnaCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqMgrFeatContext fcontext;
+  SeqFeatPtr        sfp;
+
+  /* only inspect mRNA sequences */
+  if (!IsMrnaSequence(bsp) || data == NULL) {
+    return;
+  }
+
+  sfp = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_exon, &fcontext);
+  if (sfp != NULL) {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_BIOSEQ, bsp);
+  }
+}
+
+
+static void FindExonsOnMrna (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr vnp, item_list = NULL;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitBioseqsInSep (vnp->data.ptrvalue, &item_list, FindExonsOnMrnaCallback);
+  }
+
+  if (item_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (TEST_EXON_ON_MRNA, "%d mRNA bioseqs have exon features", item_list));
+  }
+}
+
+
+NLM_EXTERN void RemoveExonsOnMrna (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+{
+  ValNodePtr entityIDList = NULL, vnp;
+  BioseqPtr  bsp;
+  SeqFeatPtr sfp;
+  SeqMgrFeatContext fcontext;
+
+  if (item_list == NULL) {
+    return;
+  }
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    bsp = (BioseqPtr) vnp->data.ptrvalue;
+    for (sfp = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_exon, &fcontext);
+         sfp != NULL;
+         sfp = SeqMgrGetNextFeature (bsp, sfp, 0, FEATDEF_exon, &fcontext)) {
+      sfp->idx.deleteme = TRUE;
+    }
+    ValNodeAddInt (&entityIDList, 0, bsp->idx.entityID);
+  }
+
+  entityIDList = ValNodeSort (entityIDList, SortByIntvalue);
+  ValNodeUnique (&entityIDList, SortByIntvalue, ValNodeFree);
+  
+  for (vnp = entityIDList; vnp != NULL; vnp = vnp->next) {
+    DeleteMarkedObjects (vnp->data.intvalue, 0, NULL);
+    ObjMgrSetDirtyFlag (vnp->data.intvalue, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, vnp->data.intvalue, 0, 0);    
+  }
+}
+
+
 static int LIBCALLBACK SortObjectListByPubTitleAndAuthors (VoidPtr ptr1, VoidPtr ptr2)
 
 {
@@ -16804,6 +18564,7 @@ static CharPtr ShortAuthorNames[] = {
 "del",
 "de",
 "da",
+"du",
 "dos",
 "la",
 "le",
@@ -16811,6 +18572,7 @@ static CharPtr ShortAuthorNames[] = {
 "von",
 "der",
 "den",
+"di",
 NULL};
 
 
@@ -16819,6 +18581,7 @@ static Boolean IsNameCapitalizationOk (CharPtr str)
   CharPtr cp;
   Int4    i, len;
   Boolean need_cap = TRUE, rval = TRUE, found;
+  Boolean needed_lower = FALSE, found_lower = FALSE;
 
   if (StringHasNoText(str)) {
     return TRUE;
@@ -16827,6 +18590,12 @@ static Boolean IsNameCapitalizationOk (CharPtr str)
   cp = str;
   while (*cp != 0 && rval) {
     if (isalpha (*cp)) {
+      if (!need_cap) {
+        needed_lower = TRUE;
+        if (!isupper(*cp)) {
+          found_lower = TRUE;
+        }
+      }
       if (need_cap && !isupper (*cp)) {
         if (cp == str || *(cp - 1) == ' ') {
           /* check to see if this is a short name */
@@ -16852,6 +18621,9 @@ static Boolean IsNameCapitalizationOk (CharPtr str)
     }
     cp++;
   }
+  if (needed_lower && !found_lower) {
+    rval = FALSE;
+  }
   return rval;
 }
 
@@ -17326,12 +19098,42 @@ static void FindUnpubPubsWithoutTitles (ValNodePtr PNTR discrepancy_list, ValNod
   }
 }
 
+static Boolean AreIntervalStrandsOk (SeqLocPtr gene, SeqLocPtr feat)
+{
+  SeqLocPtr sub_gene, sub_feat;
+  Boolean   found_match;
+  Boolean   found_bad = FALSE;
+  Int2      cmp;
+  Uint1     feat_strand, gene_strand;
+
+  sub_feat = SeqLocFindNext (feat, NULL);
+  while (sub_feat != NULL && !found_bad) {
+    found_match = FALSE;
+    sub_gene = SeqLocFindNext (gene, NULL);
+    while (sub_gene != NULL && !found_match) {
+      cmp = SeqLocCompare (sub_feat, sub_gene);
+      if (cmp == SLC_A_IN_B || cmp == SLC_A_EQ_B) {
+        found_match = TRUE;
+        feat_strand = SeqLocStrand (sub_feat);
+        gene_strand = SeqLocStrand (sub_gene);
+        if (!StrandOk(feat_strand, gene_strand)) {
+          found_bad = TRUE;
+        }
+      }
+      sub_gene = SeqLocFindNext (gene, sub_gene);
+    }
+    sub_feat = SeqLocFindNext (feat, sub_feat);
+  }
+  return !found_bad;
+}
+
 
 static void CheckGeneFeatureStrandConflictsCallback (BioseqPtr bsp, Pointer data)
 {
   SeqFeatPtr gene, sfp;
   SeqMgrFeatContext gene_context, fcontext;
   ClickableItemPtr cip;
+  Boolean          is_error;
 
   if (bsp == NULL || ISA_aa (bsp->mol) || data == NULL) {
     return;
@@ -17346,9 +19148,18 @@ static void CheckGeneFeatureStrandConflictsCallback (BioseqPtr bsp, Pointer data
       if (sfp->data.choice == SEQFEAT_GENE) {
         continue;
       }
-      if ((fcontext.left == gene_context.left || fcontext.right == gene_context.right)
-          && ((fcontext.strand == Seq_strand_minus && gene_context.strand != Seq_strand_minus)
-              || (fcontext.strand != Seq_strand_minus && gene_context.strand == Seq_strand_minus))) {
+      if (sfp->idx.subtype == FEATDEF_primer_bind) {
+        continue;
+      }
+      if (fcontext.left == gene_context.left || fcontext.right == gene_context.right) {
+        is_error = FALSE;
+        if (gene_context.mixed_strand) {
+          /* trans-splicing - compare each interval */
+          is_error = !AreIntervalStrandsOk(gene->location, sfp->location);
+        } else if (!StrandOk (fcontext.strand, gene_context.strand)) {
+          is_error = TRUE;
+        }
+        if (is_error) {
         cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
         MemSet (cip, 0, sizeof (ClickableItemData));
         cip->clickable_item_type = DISC_BAD_GENE_STRAND;
@@ -17359,6 +19170,7 @@ static void CheckGeneFeatureStrandConflictsCallback (BioseqPtr bsp, Pointer data
       }
     }
   }    
+  }    
 }
 
 
@@ -17943,8 +19755,8 @@ NLM_EXTERN Boolean ExtendPartialsToEndOrGap (SeqFeatPtr sfp)
   SeqIdPtr sip;
   SeqLocPtr slp, slp_start = NULL, slp_stop = NULL;
   BioseqPtr bsp;
-  Uint1 strand;
-  Int4  end5, diff;
+  Uint1 strand = Seq_strand_unknown;
+  Int4  end5 = 0, diff = 0;
   CdRegionPtr crp;
   SeqFeatPtr  gene = NULL, mrna = NULL;
   SeqMgrFeatContext mrna_context;
@@ -18048,24 +19860,16 @@ NLM_EXTERN Boolean ExtendPartialsToEndOrGap (SeqFeatPtr sfp)
 
 
 
-static void FindBacterialExtendablePartialsCallback (BioseqPtr bsp, Pointer userdata)
+static void FindExtendablePartialsCallback (BioseqPtr bsp, Pointer userdata)
 {
-  SeqDescrPtr sdp;
   SeqFeatPtr  sfp;
-  SeqMgrDescContext dcontext;
   SeqMgrFeatContext fcontext;
-  BioSourcePtr biop;
   Boolean partialL, partialR, partial5, partial3;
 
   if (bsp == NULL || ISA_aa (bsp->mol) || userdata == NULL) {
     return;
   }
 
-  /* only perform test if associated organism cannot be identified as eukaryote */
-  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
-  if (sdp == NULL || (biop = sdp->data.ptrvalue) == NULL || biop->org == NULL
-      || biop->org->orgname == NULL
-      || StringISearch (biop->org->orgname->lineage, "Eukaryota") == NULL) {
     for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &fcontext);
          sfp != NULL;
          sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &fcontext)) {
@@ -18082,20 +19886,19 @@ static void FindBacterialExtendablePartialsCallback (BioseqPtr bsp, Pointer user
         ValNodeAddPointer ((ValNodePtr PNTR) userdata, OBJ_SEQFEAT, sfp);
       }
     }
-  }
 }
 
 
-extern void FindBacterialExtendablePartials (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+extern void FindExtendablePartials (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
   ValNodePtr item_list = NULL, vnp;
 
   for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    VisitBioseqsInSep (vnp->data.ptrvalue, &item_list, FindBacterialExtendablePartialsCallback);
+    VisitBioseqsInSep (vnp->data.ptrvalue, &item_list, FindExtendablePartialsCallback);
   }
 
   if (item_list != NULL) {
-    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_BACTERIAL_PARTIAL_PROBLEMS, "%d features have partial ends that do not abut the end of the sequence or a gap, but could be extended by 3 or fewer nucleotides to do so", item_list));
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_PARTIAL_PROBLEMS, "%d features have partial ends that do not abut the end of the sequence or a gap, but could be extended by 3 or fewer nucleotides to do so", item_list));
   }
 }
 
@@ -18318,7 +20121,9 @@ NLM_EXTERN void FixBacterialNonExtendablePartials (ValNodePtr item_list, Pointer
         }
       }
       key = MemFree (key);
+      if (lip != NULL) {
       lip->data_in_log = TRUE;
+      }
       orig_location = MemFree (orig_location);
     }
   }
@@ -18328,7 +20133,7 @@ NLM_EXTERN void FixBacterialNonExtendablePartials (ValNodePtr item_list, Pointer
 }
 
 
-NLM_EXTERN void FixBacterialExtendablePartials (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+NLM_EXTERN void FixExtendablePartials (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
 {
   ValNodePtr vnp;
   SeqFeatPtr sfp, gene;
@@ -18381,8 +20186,11 @@ NLM_EXTERN void FixBacterialExtendablePartials (ValNodePtr item_list, Pointer da
 
 static CharPtr suspect_rrna_product_names[] = 
 {
-"domain", /* "end with" start */
-"partial"
+"domain",
+"partial",
+"5s_rRNA",
+"16s_rRNA",
+"23s_rRNA"
 };
 
 const int num_suspect_rrna_product_names = sizeof (suspect_rrna_product_names) / sizeof (CharPtr);
@@ -18502,83 +20310,48 @@ static Boolean HasMissingBacteriaStrain (BioSourcePtr biop)
 }
 
 
-static void FindMissingBacteriaStrainDescCallback (SeqDescrPtr sdp, Pointer data)
+static void FindMissingBacteriaStrain (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
-  if (sdp != NULL && data != NULL && sdp->choice == Seq_descr_source && HasMissingBacteriaStrain(sdp->data.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQDESC, sdp);
-  }
-}
+  ValNodePtr  item_list = NULL;
 
+  item_list = CollectBioSources (sep_list, HasMissingBacteriaStrain, TRUE);
 
-static void FindMissingBacteriaStrainFeatCallback (SeqFeatPtr sfp, Pointer data)
-{
-  if (sfp != NULL && data != NULL && sfp->data.choice == SEQFEAT_BIOSRC && HasMissingBacteriaStrain(sfp->data.value.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, sfp);
+  if (item_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_BACTERIA_MISSING_STRAIN, "%d bacterial biosources have taxname 'Genus sp. strain' but no strain", item_list));
   }
 }
 
 
-static void FindMissingBacteriaStrain (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+static Boolean IsBacterialIsolate (BioSourcePtr biop)
 {
-  ValNodePtr  vnp, item_list = NULL;
-  SeqEntryPtr sep;
+  OrgModPtr mod;
+  Boolean has_bad_isolate = FALSE;
 
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    sep = (SeqEntryPtr) vnp->data.ptrvalue;
-    VisitDescriptorsInSep (sep, &item_list, FindMissingBacteriaStrainDescCallback);
-    VisitFeaturesInSep (sep, &item_list, FindMissingBacteriaStrainFeatCallback);
+  if (biop == NULL 
+      || biop->org == NULL 
+      || biop->org->orgname == NULL 
+      || StringISearch (biop->org->orgname->lineage, "Bacteria") == NULL
+      || biop->org->orgname->mod == NULL
+      || HasAmplifiedWithSpeciesSpecificPrimerNote(biop)) {
+    return FALSE;
   }
 
-  if (item_list != NULL) {
-    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_BACTERIA_MISSING_STRAIN, "%d bacterial biosources have taxname 'Genus sp. strain' but no strain", item_list));
+  for (mod = biop->org->orgname->mod; mod != NULL && !has_bad_isolate; mod = mod->next) {
+    if (mod->subtype == ORGMOD_isolate
+        && StringNICmp (mod->subname, "DGGE gel band", 13) != 0
+        && StringNICmp (mod->subname, "SSCP gel band", 13) != 0) {
+      has_bad_isolate = TRUE;
   }
+  }
+  return has_bad_isolate;
 }
 
 
 static void FindBacteriaIsolate (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
-  ValNodePtr  vnp, item_list = NULL, constraint = NULL, src_list, vnp_s;
-  SeqEntryPtr sep;
-  SourceConstraintPtr src;
-
-  src = SourceConstraintNew ();
-  src->field1 = ValNodeNew (NULL);
-  src->field1->choice = SourceQualChoice_textqual;
-  src->field1->data.intvalue = Source_qual_lineage;
-  src->constraint = StringConstraintNew ();
-  src->constraint->match_text = StringSave ("Bacteria");
-  src->constraint->match_location = String_location_starts;
-  ValNodeAddPointer (&constraint, ConstraintChoice_source, src);
-
-  /* only want it if isolate is present */
-  src = SourceConstraintNew ();
-  src->field1 = ValNodeNew (NULL);
-  src->field1->choice = SourceQualChoice_textqual;
-  src->field1->data.intvalue = Source_qual_isolate;
-  ValNodeAddPointer (&constraint, ConstraintChoice_source, src);
+  ValNodePtr  item_list = NULL;
 
-  /* only want it if isolate does not start with DGGE gel band */
-  src = SourceConstraintNew ();
-  src->field1 = ValNodeNew (NULL);
-  src->field1->choice = SourceQualChoice_textqual;
-  src->field1->data.intvalue = Source_qual_isolate;
-  src->constraint = StringConstraintNew ();
-  src->constraint->match_text = StringSave ("DGGE gel band");
-  src->constraint->match_location = String_location_starts;
-  src->constraint->not_present = TRUE;
-  ValNodeAddPointer (&constraint, ConstraintChoice_source, src);
-
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    sep = (SeqEntryPtr) vnp->data.ptrvalue;
-    src_list = GetObjectListForFieldType (FieldType_source_qual, sep);
-    for (vnp_s = src_list; vnp_s != NULL; vnp_s = vnp_s->next) {
-      if (DoesObjectMatchConstraintChoiceSet (vnp_s->choice, vnp_s->data.ptrvalue, constraint)) {
-        ValNodeAddPointer (&item_list, vnp_s->choice, vnp_s->data.ptrvalue);
-      }
-    }
-    src_list = FreeObjectList (src_list);
-  }
-  constraint = ConstraintChoiceSetFree (constraint);
+  item_list = CollectBioSources (sep_list, IsBacterialIsolate, TRUE);
 
   if (item_list != NULL) {
     ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_BACTERIA_SHOULD_NOT_HAVE_ISOLATE, "%d bacterial biosources have isolate", item_list));
@@ -18858,7 +20631,7 @@ static SrcQualKeywordData srcqual_keywords[] = {
 
 static Boolean IsTrinomialWithoutQualifier (BioSourcePtr biop)
 {
-  Int4 i;
+  Int4 i, len;
   CharPtr cp, val;
   ValNode vn;
   Boolean rval = FALSE;
@@ -18883,7 +20656,8 @@ static Boolean IsTrinomialWithoutQualifier (BioSourcePtr biop)
         vn.choice = SourceQualChoice_textqual;
         vn.data.intvalue = srcqual_keywords[i].srcqual;
         val = GetSourceQualFromBioSource (biop, &vn, NULL);
-        if (StringCmp (cp, val) != 0) {
+        len = StringLen (val);
+        if (StringNCmp (cp, val, len) != 0) {
           rval = TRUE;
         }
       }
@@ -18894,34 +20668,11 @@ static Boolean IsTrinomialWithoutQualifier (BioSourcePtr biop)
 }
 
 
-static void FindTrinomialWithoutQualifierDescCallback (SeqDescrPtr sdp, Pointer data)
-{
-  if (sdp != NULL && sdp->choice == Seq_descr_source && data != NULL
-      && IsTrinomialWithoutQualifier (sdp->data.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQDESC, sdp);
-  }
-}
-
-
-static void FindTrinomialWithoutQualifierFeatCallback (SeqFeatPtr sfp, Pointer data)
-{
-  if (sfp != NULL && sfp->data.choice == SEQFEAT_BIOSRC && data != NULL
-      && IsTrinomialWithoutQualifier (sfp->data.value.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, sfp);
-  }
-}
-
-
 static void FindTrinomialWithoutQualifier (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
-  ValNodePtr  vnp, item_list = NULL;
-  SeqEntryPtr sep;
+  ValNodePtr  item_list = NULL;
 
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    sep = (SeqEntryPtr) vnp->data.ptrvalue;
-    VisitDescriptorsInSep (sep, &item_list, FindTrinomialWithoutQualifierDescCallback);
-    VisitFeaturesInSep (sep, &item_list, FindTrinomialWithoutQualifierFeatCallback);
-  }
+  item_list = CollectBioSources (sep_list, IsTrinomialWithoutQualifier, TRUE);
 
   if (item_list != NULL) {
     ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_TRINOMIAL_SHOULD_HAVE_QUALIFIER, "%d trinomial sources lack corresponding qualifier", item_list));
@@ -18987,7 +20738,7 @@ static Boolean DoAuthorityAndTaxnameConflict (BioSourcePtr biop)
 {
   OrgModPtr mod;
   CharPtr   end;
-  Int4      len;
+  size_t    len;
 
   if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL || StringHasNoText (biop->org->taxname)) {
     return FALSE;
@@ -19019,40 +20770,11 @@ static Boolean DoAuthorityAndTaxnameConflict (BioSourcePtr biop)
 }
 
 
-static void CheckAuthorityTaxnameConflictDescCallback (SeqDescPtr sdp, Pointer data)
-{
-  if (sdp == NULL || sdp->choice != Seq_descr_source || data == NULL) {
-    return;
-  }
-
-  if (DoAuthorityAndTaxnameConflict((BioSourcePtr)sdp->data.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQDESC, sdp);
-  }
-}
-
-
-static void CheckAuthorityTaxnameConflictFeatCallback (SeqFeatPtr sfp, Pointer data)
-{
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_BIOSRC || data == NULL) {
-    return;
-  }
-
-  if (DoAuthorityAndTaxnameConflict((BioSourcePtr)sfp->data.value.ptrvalue)) {
-    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, sfp);
-  }
-}
-
-
 static void CheckAuthorityTaxnameConflict (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
 {
-  ValNodePtr item_list = NULL, vnp;
+  ValNodePtr item_list = NULL;
 
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    VisitDescriptorsInSep (vnp->data.ptrvalue, &item_list, CheckAuthorityTaxnameConflictDescCallback);
-  }
-  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
-    VisitFeaturesInSep (vnp->data.ptrvalue, &item_list, CheckAuthorityTaxnameConflictFeatCallback);
-  }
+  item_list = CollectBioSources (sep_list, DoAuthorityAndTaxnameConflict, TRUE);
 
   if (item_list != NULL) {
     ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (ONCALLER_CHECK_AUTHORITY, "%d biosources have taxname/authority conflict", item_list));
@@ -19116,6 +20838,9 @@ static Boolean AuthListHasConsortium (AuthListPtr auth_list)
   ValNodePtr  names;
   AuthorPtr   ap;
 
+  if (auth_list == NULL || auth_list->choice != 1) {
+    return FALSE;
+  }
   for (names = auth_list->names; names != NULL; names = names->next) {
     ap = names->data.ptrvalue;
     if (AuthorIsConsortium(ap)) {
@@ -19275,7 +21000,6 @@ NLM_EXTERN void RemoveConsortiums (ValNodePtr item_list, Pointer data, LogInfoPt
   ValNodePtr vnp;
   SeqFeatPtr sfp;
   SeqDescPtr sdp;
-  Boolean    has_title = FALSE;
   PubdescPtr pdp;
   SeqSubmitPtr ssp;
 
@@ -19311,6 +21035,1089 @@ NLM_EXTERN void RemoveConsortiums (ValNodePtr item_list, Pointer data, LogInfoPt
 }
 
 
+static Boolean MatchExceptSpaceColon (CharPtr str1, CharPtr str2)
+{
+  if (str1 == NULL && str2 == NULL) {
+    return TRUE;
+  }
+  while ((str1 == NULL || *str1 != 0) && (str2 == NULL || *str2 != 0)) {
+    if (str1 != NULL && (*str1 == ':' || isspace (*str1))) {
+      str1++;
+    } else if (str2 != NULL && (*str2 == ':' || isspace (*str2))) {
+      str2++;
+    } else if (str1 != NULL && str2 != NULL && *str1 != *str2) {
+      return FALSE;
+    } else if (str1 == NULL && *str2 != 0) {
+      return FALSE;
+    } else if (str2 == NULL && *str1 != 0) {
+      return FALSE;
+    } else {
+      if (str1 != NULL && *str1 != 0) {
+        str1++;
+      }
+      if (str2 != NULL && *str2 != 0) {
+        str2++;
+      }
+    } 
+  }
+  if ((str1 != NULL && *str1 != 0) || (str2 != NULL && *str2 != 0)) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+static Boolean BioSourceHasConflictingStrainAndCultureCollectionValues (BioSourcePtr biop)
+{
+  OrgModPtr strain, culture;
+  Boolean   has_conflict = FALSE, has_match = FALSE;
+  if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL || biop->org->orgname->mod == NULL) {
+    return FALSE;
+  }
+
+  for (strain = biop->org->orgname->mod; strain != NULL && !has_match; strain = strain->next) {
+    if (strain->subtype == ORGMOD_strain) {
+      for (culture = biop->org->orgname->mod; culture != NULL && !has_match; culture = culture->next) {
+        if (culture->subtype == ORGMOD_culture_collection) {
+          if (MatchExceptSpaceColon(strain->subname, culture->subname)) {
+            has_match = TRUE;
+          } else {
+            has_conflict = TRUE;
+          }
+        }
+      }
+    }
+  }
+  if (has_conflict && !has_match) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static void FindStrainCultureCollectionMismatch (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr item_list = NULL, extended_item_list = NULL;
+  ValNodePtr field_list = NULL, field, src_qual;
+
+  item_list = CollectBioSources (sep_list, BioSourceHasConflictingStrainAndCultureCollectionValues, TRUE);
+
+  if (item_list != NULL) {
+    src_qual = ValNodeNew (NULL);
+    src_qual->choice = SourceQualChoice_textqual;
+    src_qual->data.intvalue = Source_qual_strain;
+    field = ValNodeNew (NULL);
+    field->choice = FieldType_source_qual;
+    field->data.ptrvalue = src_qual;
+    field_list = field;
+    src_qual = ValNodeNew (NULL);
+    src_qual->choice = SourceQualChoice_textqual;
+    src_qual->data.intvalue = Source_qual_culture_collection;
+    field = ValNodeNew (field_list);
+    field->choice = FieldType_source_qual;
+    field->data.ptrvalue = src_qual;
+    
+    extended_item_list = MakeObjectListWithFields (item_list, field_list);
+    item_list = ValNodeFree (item_list);
+    field_list = FieldTypeListFree (field_list);
+    ValNodeAddPointer (discrepancy_list, 0, 
+                        NewClickableItem (ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH, 
+                        "%d organisms have conflicting strain and culture-collection values", 
+                        extended_item_list));
+  }
+}
+
+
+static Boolean HasMultiSrc (BioSourcePtr biop)
+{
+  OrgModPtr mod;
+
+  if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL) {
+    return FALSE;
+  }
+
+  for (mod = biop->org->orgname->mod; mod != NULL; mod = mod->next) {
+    if ((mod->subtype == ORGMOD_strain || mod->subtype == ORGMOD_isolate)
+      && (StringChr (mod->subname, ',') != NULL || StringChr (mod->subname, ';') != NULL)) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+
+static void FindMultiSrc (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr item_list = NULL;
+
+  item_list = CollectBioSources (sep_list, HasMultiSrc, TRUE);
+
+  if (item_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (ONCALLER_MULTISRC, "%d organisms have comma or semicolon in strain or isolate", item_list));
+  }
+}
+
+static Boolean HasMultipleCultureCollection (BioSourcePtr biop)
+{
+  OrgModPtr mod;
+  Boolean   has_one = FALSE;
+
+  if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL) {
+    return FALSE;
+  }
+
+  for (mod = biop->org->orgname->mod; mod != NULL; mod = mod->next) {
+    if (mod->subtype == ORGMOD_culture_collection) {
+      if (has_one) {
+        return TRUE;
+      } else {
+        has_one = TRUE;
+      }
+    }
+  }
+  return FALSE;
+}
+
+
+static void FindMultipleCultureCollection (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr item_list = NULL, extended_item_list = NULL, src_qual, field_list;
+
+  item_list = CollectBioSources (sep_list, HasMultipleCultureCollection, TRUE);
+
+  if (item_list != NULL) {
+    src_qual = ValNodeNew (NULL);
+    src_qual->choice = SourceQualChoice_textqual;
+    src_qual->data.intvalue = Source_qual_culture_collection;
+    field_list = ValNodeNew (NULL);
+    field_list->choice = FieldType_source_qual;
+    field_list->data.ptrvalue = src_qual;
+    
+    extended_item_list = MakeObjectListWithFields (item_list, field_list);
+    field_list = FieldTypeListFree (field_list);
+    item_list = ValNodeFree (item_list);
+
+    ValNodeAddPointer (discrepancy_list, 0, 
+                       NewClickableItem (ONCALLER_MULTIPLE_CULTURE_COLLECTION, 
+                                         "%d organisms have multiple culture-collection qualifiers", 
+                                         extended_item_list));
+  }
+}
+
+
+static Boolean HasHumanHost(BioSourcePtr biop)
+{
+  OrgModPtr mod;
+
+  if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL) {
+    return FALSE;
+  }
+
+  for (mod = biop->org->orgname->mod; mod != NULL; mod = mod->next) {
+    if (mod->subtype == ORGMOD_nat_host && DoesStringContainPhrase (mod->subname, "human", FALSE, TRUE)) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+
+static void FindHumanHosts (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr item_list = NULL;
+
+  item_list = CollectBioSources (sep_list, HasHumanHost, TRUE);
+
+  if (item_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_HUMAN_HOST, "%d organisms have 'human' host qualifiers", item_list));
+  }
+}
+
+
+NLM_EXTERN void FixHumanHosts (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+{
+  ValNodePtr   vnp, entityIDList = NULL;
+  Uint2        entityID;
+  BioSourcePtr biop;
+  OrgModPtr    mod;
+  Int4         num_changed = 0;
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    biop = GetBioSourceFromObject (vnp->choice, vnp->data.ptrvalue);
+    if (biop != NULL && biop->org != NULL && biop->org->orgname != NULL) {      
+      for (mod = biop->org->orgname->mod; mod != NULL; mod = mod->next) {
+        if (mod->subtype == ORGMOD_nat_host && DoesStringContainPhrase (mod->subname, "human", FALSE, TRUE)) {
+          FindReplaceString (&(mod->subname), "human", "Homo sapiens", FALSE, TRUE);
+          num_changed++;
+          entityID = GetEntityIdFromObject (vnp->choice, vnp->data.ptrvalue);
+          ValNodeAddInt (&entityIDList, 0, entityID);
+        }
+      }
+    }
+  }
+
+  entityIDList = ValNodeSort (entityIDList, SortByIntvalue);
+  ValNodeUnique (&entityIDList, SortByIntvalue, ValNodeFree);
+  
+  for (vnp = entityIDList; vnp != NULL; vnp = vnp->next) {
+    ObjMgrSetDirtyFlag (vnp->data.intvalue, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, vnp->data.intvalue, 0, 0);    
+  }
+
+  if (num_changed > 0 && lip != NULL && lip->fp != NULL) {
+    fprintf (lip->fp, "Changed %d host qualifiers from 'human' to 'Homo sapiens'\n", num_changed);
+    lip->data_in_log = TRUE;
+  }
+}
+
+
+static void FindSegSetsCallback (BioseqSetPtr bssp, Pointer data)
+{
+  if (bssp != NULL && data != NULL && bssp->_class == BioseqseqSet_class_segset) {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_BIOSEQSET, bssp);
+  }
+}
+
+
+static void FindSegSets (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr item_list = NULL, vnp;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitSetsInSep (vnp->data.ptrvalue, &item_list, FindSegSetsCallback);
+  }
+
+  if (item_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_SEGSETS_PRESENT, "%d segsets are present", item_list));
+  }
+}
+
+
+static void FindNonWGSSetsCallback (BioseqSetPtr bssp, Pointer data)
+{
+  if (bssp != NULL && data != NULL
+      && (bssp->_class == BioseqseqSet_class_eco_set
+          || bssp->_class == BioseqseqSet_class_mut_set
+          || bssp->_class == BioseqseqSet_class_phy_set
+          || bssp->_class == BioseqseqSet_class_pop_set)) {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_BIOSEQSET, bssp);
+  }
+}
+
+
+static void FindNonWGSSets (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr item_list = NULL, vnp;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitSetsInSep (vnp->data.ptrvalue, &item_list, FindNonWGSSetsCallback);
+  }
+
+  if (item_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, NewClickableItem (DISC_NONWGS_SETS_PRESENT, "%d sets are of type eco, mut, phy or pop", item_list));
+  }
+}
+
+
+static void ListAllFeatures (SeqFeatPtr sfp, Pointer data)
+{
+  ValNodePtr PNTR feature_list;
+  ValNodePtr vnp, vnp_last = NULL, item_list;
+
+  if (sfp != NULL 
+      && sfp->idx.subtype != FEATDEF_gap
+      && sfp->idx.subtype != FEATDEF_PROT
+      && (feature_list = (ValNodePtr PNTR)data) != NULL) {
+    for (vnp = *feature_list; vnp != NULL && vnp->choice != sfp->idx.subtype; vnp = vnp->next) {
+      vnp_last = vnp;
+    }
+    if (vnp == NULL) {
+      vnp = ValNodeNew (vnp_last);
+      vnp->choice = sfp->idx.subtype;
+      if (vnp_last == NULL) {
+        *feature_list = vnp;
+      }
+    }
+    item_list = vnp->data.ptrvalue;
+    ValNodeAddPointer (&item_list, OBJ_SEQFEAT, sfp);
+    vnp->data.ptrvalue = item_list;
+  }
+}
+
+
+static void GetFeatureList  (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr feature_list = NULL, vnp, item_list;
+  ClickableItemPtr cip;
+  CharPtr fmt_fmt = "%%d %s features";
+  CharPtr fmt;
+  FeatDefPtr  curr;
+  Uint1       key;
+  CharPtr     label = NULL;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitFeaturesInSep (vnp->data.ptrvalue, &feature_list, ListAllFeatures);
+  }
+
+  for (vnp = feature_list; vnp != NULL; vnp = vnp->next) {
+    item_list = vnp->data.ptrvalue;
+    label = NULL;
+    curr = FeatDefFindNext (NULL, &key, &label, FEATDEF_ANY, TRUE);
+    while (curr != NULL && curr->featdef_key != vnp->choice) {
+      curr = FeatDefFindNext (curr, &key, &label, FEATDEF_ANY, TRUE);
+    }
+    if (curr == NULL) {
+      label = "unknown";
+    } else {
+      label = curr->typelabel;
+    }
+    fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt_fmt) + StringLen (label)));
+    sprintf (fmt, fmt_fmt, label);
+    cip = NewClickableItem (DISC_FEATURE_LIST, fmt, item_list);
+    fmt = MemFree (fmt);
+    vnp->choice = 0;
+    vnp->data.ptrvalue = cip;
+  }
+
+  if (feature_list != NULL) {
+    cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+    MemSet (cip, 0, sizeof (ClickableItemData));
+    cip->clickable_item_type = DISC_FEATURE_LIST;
+    cip->description = StringSave ("Feature List");
+    cip->item_list = NULL;
+    cip->subcategories = feature_list;
+
+    ValNodeAddPointer (discrepancy_list, 0, cip);
+  }
+}
+
+static void FindBadBacterialGeneNamesCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqDescrPtr sdp;
+  SeqMgrDescContext dcontext;
+  BioSourcePtr biop;
+  SeqFeatPtr gene;
+  SeqMgrFeatContext fcontext;
+  GeneRefPtr grp;
+
+  if (bsp == NULL || data == NULL) {
+    return;
+  }
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+  if (sdp == NULL || (biop = sdp->data.ptrvalue) == NULL || biop->org == NULL
+      || biop->org->orgname == NULL
+      || StringISearch (biop->org->orgname->lineage, "Bacteria") == NULL) {
+    return;
+  }
+
+  for (gene = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_GENE, 0, &fcontext);
+       gene != NULL;
+       gene = SeqMgrGetNextFeature (bsp, gene, SEQFEAT_GENE, 0, &fcontext)) {
+    grp = (GeneRefPtr) gene->data.value.ptrvalue;
+    if (grp != NULL && grp->locus != NULL && (!isalpha (*(grp->locus)) || !islower (*(grp->locus)))) {
+      ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, gene);
+    }
+  }
+}
+
+
+static void FindBadBacterialGeneNames (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr feature_list = NULL, vnp;
+  CharPtr fmt = "%d genes do not start with lowercase letters";
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitBioseqsInSep (vnp->data.ptrvalue, &feature_list, FindBadBacterialGeneNamesCallback);
+  }
+
+  if (feature_list != NULL) {
+    ValNodeAddPointer ((ValNodePtr PNTR) discrepancy_list, 0, NewClickableItem (DISC_BAD_BACTERIAL_GENE_NAME, fmt, feature_list));
+  }
+}
+
+
+typedef struct bioseqsetclassnameclassval {
+  CharPtr class_name;
+  Uint1   class_val;
+} BioseqSetClassNameClassValData, PNTR BioseqSetClassNameClassValPtr;
+
+static BioseqSetClassNameClassValData bioseqsetclassname_classval[] = {
+  {"  ",                     BioseqseqSet_class_not_set},
+  {"Nuc-prot",               BioseqseqSet_class_nuc_prot},
+  {"Segset",                 BioseqseqSet_class_segset},
+  {"Conset",                 BioseqseqSet_class_conset},
+  {"Parts",                  BioseqseqSet_class_parts},
+  {"Gibb",                   BioseqseqSet_class_gibb},
+  {"GI",                     BioseqseqSet_class_gi},
+  {"Genbank",                BioseqseqSet_class_genbank},
+  {"PIR",                    BioseqseqSet_class_pir},
+  {"Pubset",                 BioseqseqSet_class_pub_set},
+  {"Equiv",                  BioseqseqSet_class_equiv},
+  {"Swissprot",              BioseqseqSet_class_swissprot},
+  {"PDB-entry",              BioseqseqSet_class_pdb_entry},
+  {"Mut-set",                BioseqseqSet_class_mut_set},
+  {"Pop-set",                BioseqseqSet_class_pop_set},
+  {"Phy-set",                BioseqseqSet_class_phy_set},
+  {"Eco-set",                BioseqseqSet_class_eco_set},
+  {"Gen-prod-set",           BioseqseqSet_class_gen_prod_set},
+  {"WGS-set",                BioseqseqSet_class_wgs_set},
+  {"Other",                  BioseqseqSet_class_other}};
+
+#define NUM_bioseqsetclassname_classval sizeof (bioseqsetclassname_classval) / sizeof (BioseqSetClassNameClassValData)
+
+
+NLM_EXTERN CharPtr GetSetClassName (Uint1 class_val)
+{
+  Int4 i;
+
+  for (i = 0; i < NUM_bioseqsetclassname_classval; i++) {
+    if (bioseqsetclassname_classval[i].class_val == class_val) {
+      return bioseqsetclassname_classval[i].class_name;
+    }
+  }
+  return NULL;
+}
+
+
+static void ReorganizeDoubleGenBankSets (BioseqSetPtr parent_bssp) 
+{
+  SeqEntryPtr this_sep;
+  BioseqSetPtr target_bssp;
+  SeqAnnotPtr  sap_last;
+
+  if (parent_bssp == NULL) {
+    return;
+  }
+
+  for (this_sep = parent_bssp->seq_set; this_sep != NULL; this_sep = this_sep->next) {
+    if (IS_Bioseq_set (this_sep)) {
+      target_bssp = this_sep->data.ptrvalue;
+      if (target_bssp == NULL) {
+        continue;
+      }
+      if (parent_bssp->_class == BioseqseqSet_class_genbank 
+          && target_bssp->_class == BioseqseqSet_class_genbank) {
+        ValNodeLink (&(parent_bssp->seq_set), target_bssp->seq_set);
+        target_bssp->seq_set = NULL;
+        ValNodeLink (&(parent_bssp->descr), target_bssp->descr);          
+        target_bssp->descr = NULL;
+        sap_last = parent_bssp->annot;
+        while (sap_last != NULL && sap_last->next != NULL) {
+          sap_last = sap_last->next;
+        }
+        if (sap_last == NULL) {
+          parent_bssp->annot = target_bssp->annot;
+        } else {
+          sap_last->next = target_bssp->annot;
+        }
+        target_bssp->annot = NULL;
+        target_bssp->idx.deleteme = TRUE;
+      } else {
+        ReorganizeDoubleGenBankSets (target_bssp);
+      }
+    }
+  }
+}
+
+
+static void RemoveDoubleGenBankSets (BioseqSetPtr parent_bssp, Uint2 entityID)
+{
+  ObjMgrDataPtr     omdptop;
+  ObjMgrData        omdata;
+  Uint2             top_parenttype;
+  Pointer           top_parentptr;
+  SeqEntryPtr       top_sep;
+
+  if (parent_bssp == NULL) {
+    return;
+  }
+
+  top_sep = GetTopSeqEntryForEntityID (entityID);
+  if (top_sep == NULL) return;
+  SaveSeqEntryObjMgrData (top_sep, &omdptop, &omdata);
+  GetSeqEntryParent (top_sep, &top_parentptr, &top_parenttype);
+
+  ReorganizeDoubleGenBankSets (parent_bssp);
+
+  SeqMgrLinkSeqEntry (top_sep, top_parenttype, top_parentptr);
+    
+  SeqMgrClearFeatureIndexes (entityID, NULL);
+  SeqMgrIndexFeatures (entityID, NULL);
+
+  RestoreSeqEntryObjMgrData (top_sep, omdptop, &omdata);
+  
+  SeqMgrClearFeatureIndexes (entityID, NULL);
+  SeqMgrIndexFeatures (entityID, NULL);
+
+  DeleteMarkedObjects (entityID, 0, NULL);
+  ObjMgrSetDirtyFlag (entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);    
+
+}
+
+
+NLM_EXTERN void FixNonWGSSets (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+{
+  ValNodePtr vnp;
+  BioseqSetPtr  bssp;
+  CharPtr       class_name;
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == OBJ_BIOSEQSET) {
+      bssp = vnp->data.ptrvalue;
+      if (bssp != NULL) {
+        class_name = GetSetClassName (bssp->_class);
+
+        bssp->_class = BioseqseqSet_class_genbank;
+        if (bssp->idx.parenttype == OBJ_BIOSEQSET) {
+          RemoveDoubleGenBankSets (bssp->idx.parentptr, bssp->idx.entityID);
+        }
+        if (lip != NULL && lip->fp != NULL) {
+          fprintf (lip->fp, "Bioseq-set class changed from %s to genbank\n", class_name == NULL ? "unknown" : class_name);
+          lip->data_in_log = TRUE;
+        }
+      }
+    }
+  }
+}
+
+
+static void FindMismatchedCommentsCallback (SeqDescrPtr sdp, Pointer data)
+{
+  if (sdp != NULL && sdp->choice == Seq_descr_comment && data != NULL) {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQDESC, sdp);
+  }
+}
+
+
+NLM_EXTERN void FindMismatchedComments (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr comment_list = NULL, cat_list = NULL, vnp_prev = NULL, vnp;
+  CharPtr    curr_val = NULL;
+  SeqDescrPtr sdp;
+  ClickableItemPtr cip = NULL;
+  CharPtr sub_fmt = "%%d comments contain %s";
+  CharPtr fmt;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitDescriptorsInSep (vnp->data.ptrvalue, &comment_list, FindMismatchedCommentsCallback);
+  }
+
+  if (comment_list == NULL) {
+    return;
+  }
+
+  comment_list = ValNodeSort (comment_list, SortVnpByObject);
+  for (vnp = comment_list; vnp != NULL; vnp = vnp->next) {
+    sdp = (SeqDescrPtr) vnp->data.ptrvalue;
+    if (curr_val != NULL && StringCmp (curr_val, sdp->data.ptrvalue) != 0) {
+      if (vnp_prev != NULL) {
+        vnp_prev->next = NULL;
+      }
+      fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (sub_fmt) + StringLen ((CharPtr) sdp->data.ptrvalue)));
+      sprintf (fmt, sub_fmt, (CharPtr) sdp->data.ptrvalue);
+      cip = NewClickableItem (DISC_MISMATCHED_COMMENTS, fmt, comment_list);
+      ValNodeAddPointer (&cat_list, 0, cip);
+      comment_list = vnp;
+    }
+    curr_val = (CharPtr) sdp->data.ptrvalue;
+    vnp_prev = vnp;
+  }
+  if (cat_list != NULL) {
+    fmt = (CharPtr) MemNew (sizeof (Char) * (StringLen (sub_fmt) + StringLen ((CharPtr) sdp->data.ptrvalue)));
+    sprintf (fmt, sub_fmt, (CharPtr) sdp->data.ptrvalue);
+    cip = NewClickableItem (DISC_MISMATCHED_COMMENTS, fmt, comment_list);
+    ValNodeAddPointer (&cat_list, 0, cip);
+    comment_list = NULL;
+  }
+
+  if (cat_list != NULL && cat_list->next != NULL) {
+    cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+    MemSet (cip, 0, sizeof (ClickableItemData));
+    cip->clickable_item_type = DISC_MISMATCHED_COMMENTS;
+    cip->description = StringSave ("Mismatched comments were found");
+    cip->subcategories = cat_list;
+    cat_list = NULL;
+    cip->item_list = ItemListFromSubcategories (cip->subcategories);
+    ValNodeAddPointer (discrepancy_list, 0, cip);
+  }
+
+  comment_list = ValNodeFree (comment_list);
+  cat_list = FreeClickableList (cat_list);
+}
+
+
+static void FixMismatchedCommentsCallback (SeqDescrPtr sdp, Pointer data)
+{
+  if (sdp != NULL && sdp->choice == Seq_descr_comment && data != NULL) {
+    sdp->data.ptrvalue = MemFree (sdp->data.ptrvalue);
+    sdp->data.ptrvalue = StringSave ((CharPtr) data);
+  }
+}
+
+
+NLM_EXTERN void FixMismatchedComments (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+{
+  ValNodePtr entityIDList = NULL, vnp;
+  SeqDescrPtr sdp;
+  CharPtr     new_val;
+  ObjValNodePtr ovp;
+  SeqEntryPtr   sep;
+
+  if (item_list == NULL) {
+    return;
+  }
+
+  sdp = (SeqDescrPtr) item_list->data.ptrvalue;
+  if (sdp == NULL || sdp->data.ptrvalue == NULL) {
+    return;
+  }
+
+  new_val = StringSave (sdp->data.ptrvalue);
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    sdp = (SeqDescrPtr) vnp->data.ptrvalue;
+    if (sdp->extended) {
+      ovp = (ObjValNodePtr) sdp;
+      ValNodeAddInt (&entityIDList, 0, ovp->idx.entityID);
+    }
+  }
+
+  entityIDList = ValNodeSort (entityIDList, SortByIntvalue);
+  ValNodeUnique (&entityIDList, SortByIntvalue, ValNodeFree);
+  
+  for (vnp = entityIDList; vnp != NULL; vnp = vnp->next) {
+    sep = GetTopSeqEntryForEntityID (vnp->data.intvalue);
+    VisitDescriptorsInSep (sep, new_val, FixMismatchedCommentsCallback);
+    ObjMgrSetDirtyFlag (vnp->data.intvalue, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, vnp->data.intvalue, 0, 0);    
+  }
+  if (lip != NULL && lip->fp != NULL) {
+    fprintf (lip->fp, "Replaced all coments with '%s'\n", new_val);
+    lip->data_in_log = TRUE;
+  }
+  new_val = MemFree (new_val);
+}
+
+
+static void FindOrderedLocationsCallback (SeqFeatPtr sfp, Pointer data)
+{
+  if (sfp != NULL && data != NULL && LocationHasNullsBetween(sfp->location)) {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQFEAT, sfp);
+  }
+}
+
+
+NLM_EXTERN void FindOrderedLocations (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr vnp;
+  ValNodePtr feat_list = NULL;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitFeaturesInSep (vnp->data.ptrvalue, &feat_list, FindOrderedLocationsCallback);
+  }
+
+  if (feat_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, 
+                       NewClickableItem (ONCALLER_ORDERED_LOCATION, "%d features have ordered locations", feat_list));
+  }
+}
+
+
+static void FixOrderedLocationsCallback (SeqFeatPtr sfp, Pointer data)
+{
+  SeqLocPtr slp_prev = NULL, slp, slp_next;
+  Boolean changed_loc = FALSE;
+  CharPtr orig, repl;
+  LogInfoPtr lip;
+
+  if (sfp != NULL && sfp->location != NULL && sfp->location->choice == SEQLOC_MIX) {
+    orig = SeqLocPrint (sfp->location);
+    for (slp = sfp->location->data.ptrvalue; slp != NULL; slp = slp_next) {
+      slp_next = slp->next;
+      if (slp->choice == SEQLOC_NULL) {
+        if (slp_prev == NULL) {
+          sfp->location->data.ptrvalue = slp_next;
+        } else {
+          slp_prev->next = slp_next;
+        }
+        slp->next = NULL;
+        slp = SeqLocFree (slp);
+        changed_loc = TRUE;
+      } else {
+        slp_prev = slp;
+      }
+    }
+    if (changed_loc && (lip = (LogInfoPtr) data) != NULL && lip->fp != NULL) {
+      repl = SeqLocPrint (sfp->location);
+      fprintf (lip->fp, "Changed location from %s to %s", orig, repl);
+      repl = MemFree (repl);
+      lip->data_in_log = TRUE;
+    }
+    orig = MemFree (orig);
+  }
+}
+
+
+NLM_EXTERN void FixOrderedLocations (ValNodePtr item_list, Pointer data, LogInfoPtr lip)
+{
+  ValNodePtr entityIDList = NULL, vnp;
+  SeqFeatPtr sfp;
+
+  if (item_list == NULL) {
+    return;
+  }
+
+  for (vnp = item_list; vnp != NULL; vnp = vnp->next) {
+    sfp = (SeqFeatPtr) vnp->data.ptrvalue;
+    ValNodeAddInt (&entityIDList, 0, sfp->idx.entityID);
+    FixOrderedLocationsCallback (vnp->data.ptrvalue, lip);
+  }
+
+  entityIDList = ValNodeSort (entityIDList, SortByIntvalue);
+  ValNodeUnique (&entityIDList, SortByIntvalue, ValNodeFree);
+  
+  for (vnp = entityIDList; vnp != NULL; vnp = vnp->next) {
+    ObjMgrSetDirtyFlag (vnp->data.intvalue, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, vnp->data.intvalue, 0, 0);    
+  }
+}
+
+
+static void FindCommentDescriptorsCallback(SeqDescrPtr sdp, Pointer data)
+{
+  if (sdp != NULL && sdp->choice == Seq_descr_comment && data != NULL) {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_SEQDESC, sdp);
+  }
+}
+
+
+NLM_EXTERN void FindCommentDescriptors (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr vnp;
+  ValNodePtr desc_list = NULL;
+  Boolean    all_same = TRUE;
+  SeqDescPtr sdp1, sdp2;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitDescriptorsInSep (vnp->data.ptrvalue, &desc_list, FindCommentDescriptorsCallback);
+  }
+
+  if (desc_list != NULL) {
+    sdp1 = desc_list->data.ptrvalue;
+    vnp = desc_list->next;
+    while (vnp != NULL && all_same) {
+      sdp2 = vnp->data.ptrvalue;
+      if (StringCmp (sdp1->data.ptrvalue, sdp2->data.ptrvalue) != 0) {
+        all_same = FALSE;
+      }
+      vnp = vnp->next;
+    }
+    ValNodeAddPointer (discrepancy_list, 0, 
+                       NewClickableItem (ONCALLER_COMMENT_PRESENT, 
+                       all_same ? "%d comment descriptors were found (all same)" : "%d comment descriptors were found (some different)",
+                       desc_list));
+  }
+}
+
+
+static void FindTitlesOnSetsCallback (BioseqSetPtr bssp, Pointer data)
+{
+  SeqDescPtr sdp;
+  ClickableItemPtr cip;
+
+  if (bssp == NULL || data == NULL) {
+    return;
+  }
+  for (sdp = bssp->descr; sdp != NULL; sdp = sdp->next) {
+    if (sdp->choice == Seq_descr_title) {
+      cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+      cip->description = StringSave ((CharPtr) sdp->data.ptrvalue);
+      cip->clickable_item_type = ONCALLER_DEFLINE_ON_SET;
+      ValNodeAddPointer (&(cip->item_list), OBJ_SEQDESC, sdp);
+      ValNodeAddPointer ((ValNodePtr PNTR) data, 0, cip);
+    }
+  }
+}
+
+
+NLM_EXTERN void FindTitlesOnSets (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr vnp;
+  ValNodePtr title_list = NULL, item_list;
+  ClickableItemPtr cip;
+  Char             tmp[30];
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitSetsInSep (vnp->data.ptrvalue, &title_list, FindTitlesOnSetsCallback);
+  }
+
+  if (title_list != NULL) {
+    item_list = ItemListFromSubcategories(title_list);
+    cip = NewClickableItem (ONCALLER_DEFLINE_ON_SET, "%d titles on sets were found", item_list);
+    cip->subcategories = title_list;
+    if (GetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_DEFLINE_ON_SET", NULL, tmp, sizeof (tmp) - 1)
+        && StringICmp (tmp, "TRUE") == 0) {
+      cip->expanded = TRUE;
+    }
+    ValNodeAddPointer (discrepancy_list, 0, cip);
+  }
+}
+
+
+static void FindInconsistentHIVRNACallback (BioseqPtr bsp, Pointer data)
+{
+  SeqDescrPtr bsdp, msdp;
+  SeqMgrDescContext context;
+  BioSourcePtr biop;
+  MolInfoPtr   mip;
+
+  if (bsp == NULL || data == NULL || bsp->mol != Seq_mol_rna) {
+    return;
+  }
+
+  bsdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &context);
+  if (bsdp == NULL 
+      || (biop = (BioSourcePtr) bsdp->data.ptrvalue) == NULL 
+      || biop->genome == GENOME_unknown
+      || biop->org == NULL) {
+    return;
+  }
+  if (StringICmp (biop->org->taxname, "Human immunodeficiency virus") != 0 
+      && StringICmp (biop->org->taxname, "Human immunodeficiency virus 1") != 0
+      && StringICmp (biop->org->taxname, "Human immunodeficiency virus 2") != 0) {
+    return;
+  }
+
+  if (biop->genome == GENOME_genomic) {
+    msdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
+    if (msdp != NULL && (mip = (MolInfoPtr) msdp->data.ptrvalue) != NULL && mip->biomol == MOLECULE_TYPE_GENOMIC) {
+      return;
+    }
+  }
+  ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_BIOSEQ, bsp);
+}
+
+
+static void FindInconsistentHIVRNA (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr vnp;
+  ValNodePtr item_list = NULL;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitBioseqsInSep (vnp->data.ptrvalue, &item_list, FindInconsistentHIVRNACallback);
+  }
+
+  if (item_list != NULL) {
+    ValNodeAddPointer (discrepancy_list, 0, 
+                       NewClickableItem (ONCALLER_HIV_RNA_INCONSISTENT, "%d HIV RNA bioseqs have inconsistent location/moltype", item_list));
+  }
+}
+
+
+typedef struct bspprojectid {
+  Int4 projectID;
+  BioseqPtr bsp;
+} BspProjectIdData, PNTR BspProjectIdPtr;
+
+
+static BspProjectIdPtr BspProjectIdNew (BioseqPtr bsp, Int4 projectID)
+{
+  BspProjectIdPtr b;
+
+  b = (BspProjectIdPtr) MemNew (sizeof (BspProjectIdData));
+  b->projectID = projectID;
+  b->bsp = bsp;
+  return b;
+}
+
+
+static BspProjectIdPtr BspProjectIdFree (BspProjectIdPtr b)
+{
+  if (b != NULL) {
+    b = MemFree (b);
+  }
+  return b;
+}
+
+
+static ValNodePtr BspProjectIdListFree (ValNodePtr vnp)
+{
+  ValNodePtr vnp_next;
+
+  while (vnp != NULL) {
+    vnp_next = vnp->next;
+    vnp->next = NULL;
+    vnp->data.ptrvalue = BspProjectIdFree (vnp->data.ptrvalue);
+    vnp = ValNodeFree (vnp);
+    vnp = vnp_next;
+  }
+  return vnp;
+}
+
+
+static int LIBCALLBACK SortVnpByBspProjectId (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+  BspProjectIdPtr b1, b2;
+  int         rval = 0;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+
+    if (vnp1 != NULL &&& vnp2 != NULL) {
+      b1 = (BspProjectIdPtr) vnp1->data.ptrvalue;
+      b2 = (BspProjectIdPtr) vnp2->data.ptrvalue;
+      if (b1 != NULL && b2 != NULL) {
+        if (b1->projectID < b2->projectID) {
+          rval = -1;
+        } else if (b1->projectID > b2->projectID) {
+          rval = 1;
+        }
+      }
+    }
+  }
+
+  return rval;
+}
+
+
+static void FindProjectIdSequenceCallback (BioseqPtr bsp, Pointer data)
+{
+  Int4 projectID;
+
+  if (bsp == NULL || data == NULL) {
+    return;
+  }
+
+  projectID = GetGenomeProjectID (bsp);
+  if (projectID > 0) {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, bsp->mol, BspProjectIdNew (bsp, projectID));
+  }
+}
+
+
+static Boolean AllProjectIdsInListSame (ValNodePtr list)
+{
+  BspProjectIdPtr bid;
+  Boolean         rval = TRUE;
+  Int4            first_id;
+
+  if (list == NULL || list->next == NULL) {
+    return TRUE;
+  }
+
+  bid = (BspProjectIdPtr) list->data.ptrvalue;
+  first_id = bid->projectID;
+  list = list->next;
+  while (list != NULL && rval) {
+    bid = (BspProjectIdPtr) list->data.ptrvalue;
+    if (first_id != bid->projectID) {
+      rval = FALSE;
+    }
+    list = list->next;
+  }
+  return rval;
+}
+
+
+static void AddProjectIdSequencesFromList (ValNodePtr PNTR discrepancy_list, ValNodePtr list)
+{
+  ValNodePtr       vnp, subcat_items = NULL, item_list = NULL, subcat = NULL;
+  BspProjectIdPtr  b;
+  CharPtr          fmt = "%%d %s sequences have project ID %d";
+  CharPtr          all_fmt = "%%d %s sequences have project IDs (%s)";
+  Char             format[150];
+  Int4             last_project_id = 0;
+  ClickableItemPtr cip;
+  Boolean          all_same;
+
+  if (list == NULL) {
+    return;
+  }
+  all_same = AllProjectIdsInListSame (list);
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    b = (BspProjectIdPtr) vnp->data.ptrvalue;
+    if (b->projectID != last_project_id && last_project_id > 0) {
+        sprintf (format, fmt, ISA_aa (b->bsp->mol) ? "protein" : "nucleotide", last_project_id); 
+      ValNodeAddPointer (&subcat, 0, 
+                         NewClickableItem (TEST_HAS_PROJECT_ID, format, subcat_items));
+      subcat_items = NULL;
+    }
+    ValNodeAddPointer (&subcat_items, OBJ_BIOSEQ, b->bsp);
+    ValNodeAddPointer (&item_list, OBJ_BIOSEQ, b->bsp);
+    last_project_id = b->projectID;
+  }
+  if (last_project_id > 0) {
+    sprintf (format, fmt, ISA_aa (b->bsp->mol) ? "protein" : "nucleotide", last_project_id); 
+    ValNodeAddPointer (&subcat, 0, 
+                       NewClickableItem (TEST_HAS_PROJECT_ID, format, subcat_items));
+    subcat_items = NULL;
+  }
+
+  if (item_list != NULL) {
+      sprintf (format, all_fmt, ISA_aa (b->bsp->mol) ? "protein" : "nucleotide", all_same ? "all same" : "some different");
+    cip = NewClickableItem (TEST_HAS_PROJECT_ID, format, item_list);
+    cip->subcategories = subcat;
+    ValNodeAddPointer (discrepancy_list, 0, cip);
+  }
+}
+
+
+static void FindProjectIdSequences (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list)
+{
+  ValNodePtr vnp;
+  ValNodePtr id_list = NULL, subcat = NULL;
+  ValNodePtr prot_list = NULL;
+  Int4       num_seq = 0;
+  ClickableItemPtr cip;
+  CharPtr          all_fmt_same = "%d sequences have project IDs (all same)";
+  CharPtr          all_fmt_diff = "%d sequences have project IDs (some different)";
+  CharPtr          all_fmt;
+  Boolean          all_same = TRUE;
+
+  for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+    VisitBioseqsInSep (vnp->data.ptrvalue, &id_list, FindProjectIdSequenceCallback);
+  }
+
+  num_seq = ValNodeLen (id_list);
+  all_same = AllProjectIdsInListSame (id_list);
+  id_list = ValNodeSort (id_list, SortVnpByBspProjectId);
+  prot_list = ValNodeExtractList (&id_list, 3);
+
+  AddProjectIdSequencesFromList (&subcat, id_list);
+  AddProjectIdSequencesFromList (&subcat, prot_list);
+
+  if (subcat != NULL) {
+    if (id_list == NULL) {
+      ValNodeLink (discrepancy_list, subcat);
+    } else if (prot_list == NULL) {
+      ValNodeLink (discrepancy_list, subcat);
+    } else {
+      cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+      cip->clickable_item_type = TEST_HAS_PROJECT_ID;
+      cip->subcategories = subcat;
+      cip->expanded = 1;
+      if (all_same) {
+        all_fmt = all_fmt_same;
+      } else {
+        all_fmt = all_fmt_diff;
+      }
+      cip->description = (CharPtr) MemNew (sizeof (CharPtr) * (StringLen (all_fmt) + 15));
+      sprintf (cip->description, all_fmt, num_seq);
+      ValNodeAddPointer (discrepancy_list, 0, cip);
+    }
+  }
+  id_list = BspProjectIdListFree(id_list);
+  prot_list = BspProjectIdListFree(id_list);
+}
+
+
 static void 
 RemoveUnwantedDiscrepancyItems 
 (ValNodePtr PNTR      discrepancy_list,
@@ -19350,7 +22157,7 @@ RemoveUnwantedDiscrepancyItems
 }
 
 
-static void SetDiscrepancyLevels (ValNodePtr discrepancy_list, Int4 level)
+extern void SetDiscrepancyLevels (ValNodePtr discrepancy_list, Int4 level)
 {
   ClickableItemPtr dip;
   
@@ -19394,7 +22201,7 @@ static DiscrepancyInfoData discrepancy_info_list[] =
   { "Gene Product Conflict", "GENE_PRODUCT_CONFLICT", FindCDSGeneProductConflicts, NULL },
   { "Duplicate Gene Locus", "DUPLICATE_GENE_LOCUS", FindDuplicateGeneLocus, NULL },
   { "EC Number Note", "EC_NUMBER_NOTE", AddECNumberNoteDiscrepancies, NULL },
-  { "Pseudo Mismatch", "PSEUDO_MISMATCH", FindPseudoDiscrepancies, NULL },
+  { "Pseudo Mismatch", "PSEUDO_MISMATCH", FindPseudoDiscrepancies, OncallerToolPseudoDiscrepanciesFix },
   { "Joined Features", "JOINED_FEATURES", AddJoinedFeatureDiscrepancies, NULL },
   { "Overlapping Genes", "OVERLAPPING_GENES", AddOverlappingGeneDiscrepancies, NULL },
   { "Overlapping CDS", "OVERLAPPING_CDS", AddOverlappingCodingRegionDiscrepancies, MarkOverlappingCDSs },
@@ -19434,7 +22241,7 @@ static DiscrepancyInfoData discrepancy_info_list[] =
   { "Adjacent PseudoGenes with Identical Text", "ADJACENT_PSEUDOGENES", FindAdjacentPseudoGenes, NULL},
   { "Bioseqs without Annotations", "NO_ANNOTATION", FindBioseqsWithoutAnnotation, NULL},
   { "Influenza Strain/Collection Date Mismatch", "DISC_INFLUENZA_DATE_MISMATCH", FindInfluenzaStrainCollectionDateMismatches, NULL},
-  { "Introns shorter than 10 nt", "DISC_SHORT_INTRON", FindShortIntrons, NULL},
+  { "Introns shorter than 10 nt", "DISC_SHORT_INTRON", FindShortIntrons, AddExceptionsToShortIntrons},
   { "Viruses should specify collection-date, country, and specific-host", "DISC_MISSING_VIRAL_QUALS", FindMissingViralQuals, NULL},
   { "Source Qualifier Report", "DISC_SRC_QUAL_PROBLEM", CheckBioSourceQuals, NULL},
   { "All sources in a record should have the same qualifier set", "DISC_MISSING_SRC_QUAL", CheckBioSourceQuals, NULL},
@@ -19443,7 +22250,7 @@ static DiscrepancyInfoData discrepancy_info_list[] =
   { "Sequences with the same haplotype should match", "DISC_HAPLOTYPE_MISMATCH", ReportHaplotypeSequenceMismatch, NULL},
   { "Sequences with rRNA or misc_RNA features should be genomic DNA", "DISC_FEATURE_MOLTYPE_MISMATCH", ReportFeatureMoltypeMismatch, ChangeMoltypeToGenomicDNA},
   { "Coding regions on eukaryotic genomic DNA should have mRNAs with matching products", "DISC_CDS_WITHOUT_MRNA", ReportCDSWithoutmRNA, AddMissingmRNA},
-  { "Exon and intron locations should abut", "DISC_EXON_INTRON_CONFLICT", CheckIntronAndExonLocations, NULL},
+  { "Exon and intron locations should abut (unless gene is trans-spliced)", "DISC_EXON_INTRON_CONFLICT", CheckIntronAndExonLocations, NULL},
   { "Count features present or missing from sequences", "DISC_FEATURE_COUNT", CountFeaturesOnSequences, NULL},
   { "BioSources with the same specimen voucher should have the same taxname", "DISC_SPECVOUCHER_TAXNAME_MISMATCH", CollectSpecVoucherTaxnameDiscrepancies, NULL},
   { "Feature partialness should agree with gene partialness if endpoints match", "DISC_GENE_PARTIAL_CONFLICT", ReportPartialConflicts, NULL},
@@ -19461,7 +22268,6 @@ static DiscrepancyInfoData discrepancy_info_list[] =
   { "RBS features should have an overlapping gene", "DISC_RBS_WITHOUT_GENE", CheckForRBSWithoutGene, NULL},
   { "All Cit-subs should have identical affiliations", "DISC_CITSUBAFFIL_CONFLICT", FindMismatchedCitSubAffiliations, NULL},
   { "Uncultured or environmental sources should have clone", "DISC_REQUIRED_CLONE", FindRequiredClones, NULL},
-  { "Sources with Plasmodium in lineage should have isolate and not strain", "DISC_PLASMODIUM_ISOLATE_NOT_STRAIN", CheckPlasmodiumIsolateNotStrain, NULL},
   { "Source Qualifier test for Asndisc", "DISC_SOURCE_QUALS_ASNDISC", CheckBioSourceQualsAsnDisc, NULL},
   { "Eukaryotic sequences that are not genomic or macronuclear should not have mRNA features", "DISC_mRNA_ON_WRONG_SEQUENCE_TYPE", ReportmRNAOnNonGenomicEukaryoticSequences, NULL},
   { "When the organism lineage contains 'Retroviridae' and the molecule type is 'DNA', the location should be set as 'proviral'", "DISC_RETROVIRIDAE_DNA", CheckRetroviridaeDNA, MakeLocationProviral},
@@ -19472,7 +22278,7 @@ static DiscrepancyInfoData discrepancy_info_list[] =
   { "Unpublished pubs should have titles", "DISC_UNPUB_PUB_WITHOUT_TITLE", FindUnpubPubsWithoutTitles, NULL},
   { "Check for Quality Scores", "DISC_QUALITY_SCORES", CheckForQualityScores, NULL},
   { "rRNA product names should not contain 'internal', 'transcribed', or 'spacer'", "DISC_INTERNAL_TRANSCRIBED_SPACER_RRNA", InternalTranscribedSpacerrRNA, NULL},
-  { "Find partial feature ends on bacterial sequences that could be extended", "DISC_BACTERIAL_PARTIAL_PROBLEMS", FindBacterialExtendablePartials, FixBacterialExtendablePartials},
+  { "Find partial feature ends on sequences that could be extended", "DISC_PARTIAL_PROBLEMS", FindExtendablePartials, FixExtendablePartials},
   { "Find partial feature ends on bacterial sequences that cannot be extended", "DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_PROBLEMS", FindBacterialNonExtendablePartials, FixBacterialNonExtendablePartials},
   { "Find partial feature ends on bacterial sequences that cannot be extended but have exceptions", "DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_EXCEPTION", FindBacterialNonExtendablePartialsWithExceptions, NULL},
   { "rRNA product names should not contain 'partial' or 'domain'", "DISC_SUSPECT_RRNA_PRODUCTS", FindSuspectrRNAProducts, NULL},
@@ -19490,7 +22296,25 @@ static DiscrepancyInfoData discrepancy_info_list[] =
   { "Superfluous genes", "ONCALLER_SUPERFLUOUS_GENE", OnCallerMissingAndSuperfluousGenes, NULL},
   { "Short rRNA Features", "DISC_SHORT_RRNA", FindShortrRNAs, NULL},
   { "Authority and Taxname should match first two words", "ONCALLER_CHECK_AUTHORITY", CheckAuthorityTaxnameConflict, NULL},
-  { "Submitter blocks and publications have consortiums", "ONCALLER_CONSORTIUM", FindConsortiums, RemoveConsortiums}
+  { "Submitter blocks and publications have consortiums", "ONCALLER_CONSORTIUM", FindConsortiums, RemoveConsortiums},
+  { "Strain and culture-collection values conflict", "ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH", FindStrainCultureCollectionMismatch, NULL},
+  { "Comma or semicolon appears in strain or isolate", "ONCALLER_MULTISRC", FindMultiSrc, NULL} ,
+  { "Multiple culture-collection quals", "ONCALLER_MULTIPLE_CULTURE_COLLECTION", FindMultipleCultureCollection, NULL},
+  { "Segsets present", "DISC_SEGSETS_PRESENT", FindSegSets, NULL},
+  { "Eco, mut, phy or pop sets present", "DISC_NONWGS_SETS_PRESENT", FindNonWGSSets, FixNonWGSSets},
+  { "Feature List", "DISC_FEATURE_LIST", GetFeatureList, NULL},
+  { "Category Header", "DISC_CATEGORY_HEADER", NULL, NULL},
+  { "Mismatched Comments", "DISC_MISMATCHED_COMMENTS", FindMismatchedComments, FixMismatchedComments},
+  { "BioSources with the same strain should have the same taxname", "DISC_STRAIN_TAXNAME_MISMATCH", CollectStrainTaxnameDiscrepancies, NULL},
+  { "'Human' in host should be 'Homo sapiens'", "DISC_HUMAN_HOST", FindHumanHosts, FixHumanHosts},
+  { "Genes on bacterial sequences should start with lowercase letters", "DISC_BAD_BACTERIAL_GENE_NAME", FindBadBacterialGeneNames, NULL},
+  { "Location is ordered (intervals interspersed with gaps)", "ONCALLER_ORDERED_LOCATION", FindOrderedLocations, FixOrderedLocations},
+  { "Comment descriptor present", "ONCALLER_COMMENT_PRESENT", FindCommentDescriptors, NULL },
+  { "Titles on sets", "ONCALLER_DEFLINE_ON_SET", FindTitlesOnSets, NULL },
+  { "HIV RNA location or molecule type inconsistent", "ONCALLER_HIV_RNA_INCONSISTENT", FindInconsistentHIVRNA, NULL },
+  { "Protein sequences should be at least 50 aa, unless they are partial", "SHORT_PROT_SEQUENCES", FindShortProtSequences, NULL },
+  { "mRNA sequences should not have exons", "TEST_EXON_ON_MRNA", FindExonsOnMrna, RemoveExonsOnMrna },
+  { "Sequences with project IDs", "TEST_HAS_PROJECT_ID", FindProjectIdSequences, NULL }
 };
 
 
@@ -19528,7 +22352,6 @@ extern Boolean IsTestTypeAppropriateForReportType (Int4 test_type, EDiscrepancyR
           || test_type == DISC_RBS_WITHOUT_GENE
           || test_type == DISC_CITSUBAFFIL_CONFLICT
           || test_type == DISC_REQUIRED_CLONE
-          || test_type == DISC_PLASMODIUM_ISOLATE_NOT_STRAIN
           || test_type == DISC_SUSPICIOUS_NOTE_TEXT
           || test_type == DISC_mRNA_ON_WRONG_SEQUENCE_TYPE
           || test_type == DISC_RETROVIRIDAE_DNA
@@ -19550,7 +22373,18 @@ extern Boolean IsTestTypeAppropriateForReportType (Int4 test_type, EDiscrepancyR
           || test_type == ONCALLER_GENE_MISSING
           || test_type == ONCALLER_SUPERFLUOUS_GENE
           || test_type == ONCALLER_CHECK_AUTHORITY
-          || test_type == ONCALLER_CONSORTIUM) {
+          || test_type == ONCALLER_CONSORTIUM
+          || test_type == ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH
+          || test_type == ONCALLER_MULTISRC
+          || test_type == ONCALLER_MULTIPLE_CULTURE_COLLECTION
+          || test_type == DISC_STRAIN_TAXNAME_MISMATCH
+          || test_type == DISC_HUMAN_HOST
+          || test_type == ONCALLER_ORDERED_LOCATION
+          || test_type == ONCALLER_COMMENT_PRESENT
+          || test_type == ONCALLER_DEFLINE_ON_SET
+          || test_type == ONCALLER_HIV_RNA_INCONSISTENT
+          || test_type == TEST_EXON_ON_MRNA
+          || test_type == TEST_HAS_PROJECT_ID) {
         rval = FALSE;
       } else {
         rval = TRUE;
@@ -19590,7 +22424,6 @@ extern Boolean IsTestTypeAppropriateForReportType (Int4 test_type, EDiscrepancyR
           || test_type == DISC_RBS_WITHOUT_GENE
           || test_type == DISC_CITSUBAFFIL_CONFLICT
           || test_type == DISC_REQUIRED_CLONE
-          || test_type == DISC_PLASMODIUM_ISOLATE_NOT_STRAIN
           || test_type == DISC_SUSPICIOUS_NOTE_TEXT
           || test_type == DISC_mRNA_ON_WRONG_SEQUENCE_TYPE
           || test_type == DISC_RETROVIRIDAE_DNA
@@ -19612,10 +22445,24 @@ extern Boolean IsTestTypeAppropriateForReportType (Int4 test_type, EDiscrepancyR
           || test_type == ONCALLER_GENE_MISSING
           || test_type == ONCALLER_SUPERFLUOUS_GENE
           || test_type == ONCALLER_CHECK_AUTHORITY
-          || test_type == ONCALLER_CONSORTIUM) {
+          || test_type == ONCALLER_CONSORTIUM
+          || test_type == ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH
+          || test_type == ONCALLER_MULTISRC
+          || test_type == ONCALLER_MULTIPLE_CULTURE_COLLECTION
+          || test_type == DISC_STRAIN_TAXNAME_MISMATCH
+          || test_type == DISC_HUMAN_HOST
+          || test_type == ONCALLER_ORDERED_LOCATION
+          || test_type == ONCALLER_COMMENT_PRESENT
+          || test_type == ONCALLER_DEFLINE_ON_SET
+          || test_type == ONCALLER_HIV_RNA_INCONSISTENT
+          || test_type == TEST_EXON_ON_MRNA
+          || test_type == TEST_HAS_PROJECT_ID) {
         rval = TRUE;
       }
       break;
+    case eReportTypeMegaReport:
+      rval = TRUE;
+      break;
   }
   return rval;
 }
@@ -19647,13 +22494,15 @@ extern void PrintDiscrepancyTestList (FILE *fp)
   }
   fprintf (fp, "\n");
 
-  fprintf (fp, "Terms searched for by DISC_SUSPECT_PRODUCT_NAME:\n");
-  for (i = 0; i < num_suspect_product_names; i++) {
-    fprintf (fp, "%s\n", suspect_product_names[i]);
+  fprintf (fp, "Terms searched for by SUSPECT_PRODUCT_NAMES:\n");
+  for (i = 0; i < num_suspect_product_terms; i++) {
+    fprintf (fp, "'%s':%s\n", 
+             suspect_product_terms[i].pattern, 
+             SummarizeSuspectPhraseFunc(suspect_product_terms[i].search_func));
   }
   fprintf (fp, "\n");
 
-  fprintf (fp, "Terms searched for by DISC_SUSPECT_PHRASES:\n");
+  fprintf (fp, "Terms searched for by SUSPECT_PHRASES:\n");
   for (i = 0; i < num_suspect_phrases; i++) {
     fprintf (fp, "%s\n", suspect_phrases[i]);
   }
@@ -19672,8 +22521,10 @@ extern void PrintDiscrepancyTestList (FILE *fp)
   fprintf (fp, "\n");
 
   fprintf (fp, "Terms searched for by DISC_CDS_PRODUCT_FIND:\n");
-  for (i = 0; cds_product_find[i] != NULL; i++) {
-    fprintf (fp, "%s\n", cds_product_find[i]);
+  for (i = 0; i < num_cds_product_find; i++) {
+    fprintf (fp, "'%s':%s\n",
+             cds_product_find[i].pattern,
+             SummarizeSuspectPhraseFunc(cds_product_find[i].search_func));
   }
   fprintf (fp, "\n");
   
@@ -19738,58 +22589,56 @@ extern void ConfigureForGenomes (DiscrepancyConfigPtr dcp)
   }
 
   for (i = 0; i < MAX_DISC_TYPE; i++) {
-    dcp->conf_list[i] = FALSE;
+    dcp->conf_list[i] = TRUE;
   }
-  dcp->conf_list[DISC_GENE_MISSING] = TRUE;
-  dcp->conf_list[DISC_SUPERFLUOUS_GENE] = TRUE;
-  dcp->conf_list[DISC_GENE_MISSING_LOCUS_TAG] = TRUE;
-  dcp->conf_list[DISC_GENE_DUPLICATE_LOCUS_TAG] = TRUE;
-  dcp->conf_list[DISC_GENE_LOCUS_TAG_BAD_FORMAT] = TRUE;
-  dcp->conf_list[DISC_GENE_LOCUS_TAG_INCONSISTENT_PREFIX] = TRUE;
-  dcp->conf_list[DISC_NON_GENE_LOCUS_TAG] = TRUE;
-  dcp->conf_list[DISC_COUNT_NUCLEOTIDES] = TRUE;
-  dcp->conf_list[DISC_MISSING_PROTEIN_ID] = TRUE;
-  dcp->conf_list[DISC_INCONSISTENT_PROTEIN_ID_PREFIX] = TRUE;
-  dcp->conf_list[DISC_GENE_CDS_mRNA_LOCATION_CONFLICT] = TRUE;
-  dcp->conf_list[DISC_GENE_PRODUCT_CONFLICT] = TRUE;
-  dcp->conf_list[DISC_GENE_DUPLICATE_LOCUS] = TRUE;
-  dcp->conf_list[DISC_EC_NUMBER_NOTE] = TRUE;
-  dcp->conf_list[DISC_PSEUDO_MISMATCH] = TRUE;
-  dcp->conf_list[DISC_JOINED_FEATURES] = TRUE;
-  dcp->conf_list[DISC_OVERLAPPING_CDS] = TRUE;
-  dcp->conf_list[DISC_CONTAINED_CDS] = TRUE;
-  dcp->conf_list[DISC_RNA_CDS_OVERLAP] = TRUE;
-  dcp->conf_list[DISC_SHORT_CONTIG] = TRUE;
-  dcp->conf_list[DISC_INCONSISTENT_BIOSRC] = TRUE;
-  dcp->conf_list[DISC_SUSPECT_PRODUCT_NAME] = TRUE;
-  dcp->conf_list[DISC_PARTIAL_CDS_IN_COMPLETE_SEQUENCE] = TRUE;
-  dcp->conf_list[DISC_EC_NUMBER_ON_HYPOTHETICAL_PROTEIN] = TRUE;
-  dcp->conf_list[DISC_SHORT_SEQUENCE] = TRUE;
-  dcp->conf_list[DISC_SUSPECT_PHRASES] = TRUE;
-  dcp->conf_list[DISC_SUSPICIOUS_NOTE_TEXT] = TRUE;
-  dcp->conf_list[DISC_RNA_NO_PRODUCT] = TRUE;
-  dcp->conf_list[DISC_MISSING_GENPRODSET_PROTEIN] = TRUE;
-  dcp->conf_list[DISC_DUP_GENPRODSET_PROTEIN] = TRUE;
-  dcp->conf_list[DISC_MISSING_GENPRODSET_TRANSCRIPT_ID] = TRUE;
-  dcp->conf_list[DISC_DUP_GENPRODSET_TRANSCRIPT_ID] = TRUE;
-  dcp->conf_list[DISC_PERCENTN] = TRUE;
-  dcp->conf_list[DISC_N_RUNS] = TRUE;
-  dcp->conf_list[DISC_ZERO_BASECOUNT] = TRUE;
-  dcp->conf_list[DISC_ADJACENT_PSEUDOGENE] = TRUE;
-  dcp->conf_list[DISC_NO_ANNOTATION] = TRUE;
-  dcp->conf_list[DISC_SHORT_INTRON] = TRUE;
-  dcp->conf_list[DISC_SOURCE_QUALS_ASNDISC] = TRUE;
-  dcp->conf_list[DISC_CDS_WITHOUT_MRNA] = TRUE;
-  dcp->conf_list[DUP_DISC_ATCC_CULTURE_CONFLICT] = TRUE;
-  dcp->conf_list[DISC_USA_STATE] = TRUE;
-  dcp->conf_list[DISC_RBS_WITHOUT_GENE] = TRUE;
-  dcp->conf_list[DISC_FEATURE_COUNT] = TRUE;
-  dcp->conf_list[DISC_QUALITY_SCORES] = TRUE;
-  dcp->conf_list[DISC_BACTERIAL_PARTIAL_PROBLEMS] = TRUE;
-  dcp->conf_list[DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_PROBLEMS] = TRUE;
-  dcp->conf_list[DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_EXCEPTION] = TRUE;
-  dcp->conf_list[DISC_SUSPECT_RRNA_PRODUCTS] = TRUE;
-  dcp->conf_list[DISC_SUSPECT_MISC_FEATURES] = TRUE;
+  dcp->conf_list[DISC_STRAIN_TAXNAME_MISMATCH] = FALSE;
+  dcp->conf_list[DISC_CITSUBAFFIL_CONFLICT] = FALSE;
+  dcp->conf_list[DISC_OVERLAPPING_GENES] = FALSE;
+  dcp->conf_list[DISC_INCONSISTENT_BIOSRC_DEFLINE] = FALSE;
+  dcp->conf_list[DISC_NO_TAXLOOKUP] = FALSE;
+  dcp->conf_list[DISC_BAD_TAXLOOKUP] = FALSE;
+  dcp->conf_list[DISC_COUNT_TRNA] = FALSE;
+  dcp->conf_list[DISC_BADLEN_TRNA] = FALSE;
+  dcp->conf_list[DISC_STRAND_TRNA] = FALSE;
+  dcp->conf_list[DISC_COUNT_RRNA] = FALSE;
+  dcp->conf_list[DISC_CDS_OVERLAP_TRNA] = FALSE;
+  dcp->conf_list[DISC_FEAT_OVERLAP_SRCFEAT] = FALSE;
+  dcp->conf_list[DISC_INFLUENZA_DATE_MISMATCH] = FALSE;   
+  dcp->conf_list[DISC_MISSING_VIRAL_QUALS] = FALSE;          
+  dcp->conf_list[DISC_SRC_QUAL_PROBLEM] = FALSE;
+  dcp->conf_list[DISC_MISSING_SRC_QUAL] = FALSE;
+  dcp->conf_list[DISC_DUP_SRC_QUAL] = FALSE;
+  dcp->conf_list[DISC_HAPLOTYPE_MISMATCH] = FALSE;
+  dcp->conf_list[DISC_FEATURE_MOLTYPE_MISMATCH] = FALSE;
+  dcp->conf_list[DISC_SPECVOUCHER_TAXNAME_MISMATCH] = FALSE;
+  dcp->conf_list[DISC_FLATFILE_FIND_ONCALLER] = FALSE;
+  dcp->conf_list[DISC_CDS_PRODUCT_FIND] = FALSE;
+  dcp->conf_list[DISC_DUP_DEFLINE] = FALSE;
+  dcp->conf_list[DISC_INCONSISTENT_MOLTYPES] = FALSE;
+  dcp->conf_list[DISC_SUBMITBLOCK_CONFLICT] = FALSE;
+  dcp->conf_list[DISC_POSSIBLE_LINKER] = FALSE;
+  dcp->conf_list[DISC_TITLE_AUTHOR_CONFLICT] = FALSE;
+  dcp->conf_list[DISC_MAP_CHROMOSOME_CONFLICT] = FALSE;
+  dcp->conf_list[DISC_REQUIRED_CLONE] = FALSE;
+  dcp->conf_list[DISC_mRNA_ON_WRONG_SEQUENCE_TYPE] = FALSE;
+  dcp->conf_list[DISC_RETROVIRIDAE_DNA] = FALSE;
+  dcp->conf_list[DISC_MISSING_DEFLINES] = FALSE;
+  dcp->conf_list[ONCALLER_GENE_MISSING] = FALSE;
+  dcp->conf_list[ONCALLER_SUPERFLUOUS_GENE] = FALSE;
+  dcp->conf_list[ONCALLER_CONSORTIUM] = FALSE;
+  dcp->conf_list[DISC_FEATURE_LIST] = FALSE;
+
+  /* mitochondrial tests */
+  dcp->conf_list[DISC_DUP_TRNA] = FALSE;
+  dcp->conf_list[DISC_DUP_RRNA] = FALSE;
+  dcp->conf_list[DISC_TRANSL_NO_NOTE] = FALSE;
+  dcp->conf_list[DISC_NOTE_NO_TRANSL] = FALSE;
+  dcp->conf_list[DISC_TRANSL_TOO_LONG] = FALSE;
+  dcp->conf_list[DISC_COUNT_PROTEINS] = FALSE;
+
+  /* on-caller specific tests */
+  dcp->conf_list[DISC_SRC_QUAL_PROBLEM] = FALSE;
+  dcp->conf_list[DISC_CATEGORY_HEADER] = FALSE;
 }
 
 
@@ -19942,7 +22791,7 @@ extern CharPtr GetBioseqSetLabel (BioseqSetPtr bssp)
 extern CharPtr GetDiscrepancyItemTextEx (ValNodePtr vnp, CharPtr filename)
 {
   CharPtr           row_text = NULL, tmp, fmt = "%s:%s";
-  SeqFeatPtr        sfp, cds;
+  SeqFeatPtr        sfp, cds, sfp_index;
   BioseqPtr         bsp;
   SeqMgrFeatContext context;
   CharPtr           location;
@@ -19955,12 +22804,19 @@ extern CharPtr GetDiscrepancyItemTextEx (ValNodePtr vnp, CharPtr filename)
   SeqSubmitPtr      ssp;
   Boolean           special_flag = FALSE;
   Uint1             data_choice;
+  ValNodePtr        extra_fields = NULL, field, field_strings = NULL, field_values, val_vnp;
+  Int4              field_len = 0, label_len;
   
   if (vnp == NULL)
   {
     return NULL;
   }
 
+  if (vnp->extended > 0) {
+    ovn = (ObjValNodePtr) vnp;
+    extra_fields = ovn->idx.scratch;
+  }
+
   data_choice = vnp->choice;
   if (data_choice > OBJ_MAX) {
     special_flag = TRUE;
@@ -19976,9 +22832,9 @@ extern CharPtr GetDiscrepancyItemTextEx (ValNodePtr vnp, CharPtr filename)
         SeqMgrIndexFeatures (sfp->idx.entityID, NULL);
       }
 
-      sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL, sfp->idx.itemID, 0, sfp, &context);
-      if (sfp != NULL && sfp->idx.subtype == FEATDEF_PROT) {
-        bsp = BioseqFindFromSeqLoc (sfp->location);
+      sfp_index = SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL, sfp->idx.itemID, 0, sfp, &context);
+      if (sfp_index != NULL && sfp_index->idx.subtype == FEATDEF_PROT) {
+        bsp = BioseqFindFromSeqLoc (sfp_index->location);
         if (bsp != NULL) {
           cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
           if (cds != NULL) {
@@ -19997,7 +22853,9 @@ extern CharPtr GetDiscrepancyItemTextEx (ValNodePtr vnp, CharPtr filename)
           label = "Unknown label";
         }
         locus_tag = GetLocusTagForFeature (sfp);
-        if (context.label == NULL) {
+        if (sfp_index == NULL) {
+          context.label = "Unknown context label";
+        } else if (context.label == NULL) {
           context.label = "Unknown context label";
         }
 
@@ -20065,15 +22923,28 @@ extern CharPtr GetDiscrepancyItemTextEx (ValNodePtr vnp, CharPtr filename)
         }
       }
       if (bsp == NULL) {
+        if (sdp->choice == Seq_descr_title || sdp->choice == Seq_descr_comment) {
+          row_text = (CharPtr) MemNew (sizeof (Char) * (StringLen ((CharPtr)(sdp->data.ptrvalue)) + 2));
+          StringCpy (row_text, (CharPtr)(sdp->data.ptrvalue));
+        } else {
         row_text = (CharPtr) MemNew (sizeof (Char) * 61);
         SeqDescLabel (sdp, row_text, 59, TRUE);
+        }
       } else {
-        row_text = (CharPtr) MemNew (sizeof (Char) * (61 + 41));
+        label_len = 61;
+        if (sdp->choice == Seq_descr_title || sdp->choice == Seq_descr_comment) {
+          label_len = StringLen (sdp->data.ptrvalue) + 3;
+        }
+        row_text = (CharPtr) MemNew (sizeof (Char) * (label_len + 41));
         SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), row_text, PRINTID_REPORT, 39);
         row_text[39] = 0;
         StringCat (row_text, ":");
+        if (sdp->choice == Seq_descr_title || sdp->choice == Seq_descr_comment) {
+          StringCat (row_text, (CharPtr)(sdp->data.ptrvalue));
+        } else {
         SeqDescLabel (sdp, row_text + StringLen (row_text), 59, TRUE);
       }
+      }
       StringCat (row_text, "\n");
     }
   } else if (data_choice == OBJ_SEQSUB) {
@@ -20093,6 +22964,45 @@ extern CharPtr GetDiscrepancyItemTextEx (ValNodePtr vnp, CharPtr filename)
     }
   }
 
+  if (extra_fields != NULL) {
+    for (field = extra_fields; field != NULL; field = field->next) {
+      field_values = GetMultipleFieldValuesForObject (vnp->choice, vnp->data.ptrvalue, field, NULL, NULL);
+      if (field_values != NULL) {
+        label = SummarizeFieldType (field);
+        for (val_vnp = field_values; val_vnp != NULL; val_vnp = val_vnp->next) {
+          if (!StringHasNoText (label)) {
+            tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (label) + 6));
+            sprintf (tmp, "    %s:", label);
+            ValNodeAddPointer (&field_strings, 0, tmp);
+            field_len += StringLen (tmp) + 1;
+          }
+          if (label == NULL) {
+            tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (val_vnp->data.ptrvalue) + 6));
+            sprintf (tmp, "    %s\n", (CharPtr) val_vnp->data.ptrvalue);
+          } else {
+            tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (val_vnp->data.ptrvalue) + 2));
+            sprintf (tmp, "%s\n", (CharPtr) val_vnp->data.ptrvalue);
+          }
+          ValNodeAddPointer (&field_strings, 0, tmp);
+          field_len += StringLen (tmp);
+        }
+        label = MemFree (label);
+        field_values = ValNodeFreeData (field_values);
+      }
+    }
+    if (field_strings != NULL) {
+      tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (row_text) + field_len + 3));
+      StringCpy (tmp, row_text);
+      /* replace trailing carriage return with space */
+      for (field = field_strings; field != NULL; field = field->next) {
+        StringCat (tmp, field->data.ptrvalue);
+      }
+      row_text = MemFree (row_text);
+      row_text = tmp;
+      field_strings = ValNodeFreeData (field_strings);
+    }
+  }
+
   if (!StringHasNoText (row_text) && !StringHasNoText (filename)) {
     tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (filename) + StringLen (row_text)));
     sprintf (tmp, fmt, filename, row_text);
@@ -20443,7 +23353,7 @@ static void StandardWriteDiscrepancy (FILE *fp, ClickableItemPtr dip, Boolean us
       }
       if (row_text != NULL)
       {
-        fprintf (fp, row_text);
+        fprintf (fp, "%s", row_text);
         row_text = MemFree (row_text);
       }
       vnp = vnp->next;
@@ -20594,7 +23504,7 @@ extern DiscrepancyConfigPtr ReadDiscrepancyConfig (void)
   return ReadDiscrepancyConfigEx ("DISCREPANCY_REPORT");
 }
 
-extern void SaveDiscrepancyConfig (DiscrepancyConfigPtr dcp)
+extern void SaveDiscrepancyConfigEx (DiscrepancyConfigPtr dcp, CharPtr report_name)
 {
   Int4 i;
   
@@ -20603,28 +23513,38 @@ extern void SaveDiscrepancyConfig (DiscrepancyConfigPtr dcp)
     return;
   }
   
+  if (report_name == NULL) {
+    report_name = "DISCREPANCY_REPORT";
+  }
+  
   for (i = 0; i < MAX_DISC_TYPE; i++)
   {
     if (dcp->conf_list[i])
     {
-      SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", discrepancy_info_list[i].setting_name, "TRUE");
+      SetAppParam ("SEQUINCUSTOM", report_name, discrepancy_info_list[i].setting_name, "TRUE");
     }
     else
     {
-      SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", discrepancy_info_list[i].setting_name, "FALSE");
+      SetAppParam ("SEQUINCUSTOM", report_name, discrepancy_info_list[i].setting_name, "FALSE");
     }
   }
   if (dcp->use_feature_table_format)
   {
-    SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", "USE_FEATURE_TABLE_FORMAT", "TRUE");
+    SetAppParam ("SEQUINCUSTOM", report_name, "USE_FEATURE_TABLE_FORMAT", "TRUE");
   }
   else
   {
-    SetAppParam ("SEQUINCUSTOM", "DISCREPANCY_REPORT", "USE_FEATURE_TABLE_FORMAT", "FALSE");
+    SetAppParam ("SEQUINCUSTOM", report_name, "USE_FEATURE_TABLE_FORMAT", "FALSE");
   }
 }
 
 
+extern void SaveDiscrepancyConfig (DiscrepancyConfigPtr dcp)
+{
+  SaveDiscrepancyConfigEx (dcp, "DISCREPANCY_REPORT");
+}
+
+
 extern CharPtr SetDiscrepancyReportTestsFromString (CharPtr list, Boolean enable, DiscrepancyConfigPtr dcp)
 {
   CharPtr         ptr, tmp, name_start, err_msg;
@@ -21828,7 +24748,11 @@ static CharPtr BarcodeTestNames[] =
   "Missing Primers",
   "Missing Country",
   "Missing Voucher",
-  "Too Many Ns"
+  "Too Many Ns",
+  "Bad Collection Date",
+  "Missing Order Assignment",
+  "Low Trace",
+  "Frame Shift"
 };
 
 
@@ -22009,7 +24933,7 @@ static Boolean RemoveBarcodeKeywordFromBioseq (BioseqPtr bsp)
 
   for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_genbank, &dcontext);
        sdp != NULL && !found;
-       sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_genbank, &dcontext))
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_genbank, &dcontext))
   {
     gb = (GBBlockPtr) sdp->data.ptrvalue;
     if (gb != NULL)
@@ -22102,6 +25026,108 @@ NLM_EXTERN void ApplyBarcodeKeywordToBioseq (BioseqPtr bsp)
 }
 
 
+NLM_EXTERN Boolean BioseqHasBarcodeKeyword (BioseqPtr bsp)
+{
+  SeqDescrPtr sdp;
+  SeqMgrDescContext context;
+  GBBlockPtr gb;
+  ValNodePtr vnp;
+  Boolean rval = FALSE;
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_genbank, &context);
+        sdp != NULL && !rval;
+        sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_genbank, &context)) {
+    gb = (GBBlockPtr) sdp->data.ptrvalue;
+    if (gb != NULL) {
+      for (vnp = gb->keywords; vnp != NULL && !rval; vnp = vnp->next) {
+        if (StringCmp (vnp->data.ptrvalue, "BARCODE") == 0) {
+          rval = TRUE;
+        }
+      }
+    }
+  }
+  return rval;
+}
+
+
+NLM_EXTERN Boolean HasLowTrace (BioseqPtr bsp)
+{
+  SeqDescrPtr sdp;
+  SeqMgrDescContext context;
+  Boolean rval = TRUE;
+  UserObjectPtr uop;
+  UserFieldPtr  ufp;
+  ObjectIdPtr   oip;
+  int           num_trace = 0;
+
+  if (bsp == NULL) {
+    return FALSE;
+  }
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &context);
+        sdp != NULL && rval;
+        sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &context)) {
+    uop = (UserObjectPtr) sdp->data.ptrvalue;
+    if (uop != NULL && uop->type != NULL && StringICmp (uop->type->str, "Submission") == 0) {
+      for (ufp = uop->data; ufp != NULL && rval; ufp = ufp->next) {
+        oip = ufp->label;
+        if (oip != NULL && StringCmp (oip->str, "AdditionalComment") == 0
+            && sscanf (ufp->data.ptrvalue, "Traces: %d", &num_trace) == 1
+            && num_trace > 1) {
+          rval = FALSE;
+        }
+      }
+    }
+  }
+  return rval;
+}
+
+
+static void GetBarcodeLowTraceListCallback (BioseqPtr bsp, Pointer data)
+{
+  if (bsp == NULL || data == NULL 
+      || ISA_aa (bsp->mol) 
+      || !BioseqHasBarcodeKeyword(bsp) 
+      || !HasLowTrace(bsp)) {
+    return;
+  } else {
+    ValNodeAddPointer ((ValNodePtr PNTR) data, OBJ_BIOSEQ, bsp);
+  }
+}
+
+
+NLM_EXTERN ValNodePtr GetBarcodeLowTraceList (SeqEntryPtr sep)
+{
+  ValNodePtr list = NULL;
+
+  VisitBioseqsInSep (sep, &list, GetBarcodeLowTraceListCallback);
+
+  return list;
+}
+
+
+NLM_EXTERN void RemoveBarcodeKeywordsFromObjectList (FILE *fp, ValNodePtr object_list)
+{
+  BioseqPtr  bsp;
+  ValNodePtr vnp;
+  Char       id_txt[100];
+
+  for (vnp = object_list; vnp != NULL; vnp = vnp->next)
+  {
+    if (vnp->choice == OBJ_BIOSEQ && (bsp = (BioseqPtr) vnp->data.ptrvalue) != NULL)
+    {
+      if (RemoveBarcodeKeywordFromBioseq (bsp))
+      {
+        if (fp != NULL)
+        {
+          SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+          fprintf (fp, "%s\n", id_txt);
+        }
+      }
+    }
+  }
+}  
+
+
 /* Used for generating Discrepancy Report style data,
  * where Bioseqs are listed separately for each test they fail.
  */
@@ -22117,15 +25143,182 @@ static void FindShortBarcodeSequencesCallback (BioseqPtr bsp, Pointer userdata)
   if (bsp == NULL || ISA_aa (bsp->mol) 
       || (bsd = (BarcodeSearchPtr) userdata) == NULL
       || bsd->cfg == NULL
-      || (bsd->cfg->require_keyword && !HasBARCODETech(bsp))) return;
+      || (bsd->cfg->require_keyword && !HasBARCODETech(bsp))) 
+  {
+    return;
+  }
 
-  bsd = (BarcodeSearchPtr) userdata;
   if (bsp->length < bsd->cfg->min_length) 
   { 
     ValNodeAddPointer (&(bsd->bioseq_list), OBJ_BIOSEQ, bsp);
   }
 }  
 
+
+NLM_EXTERN Boolean IsIBOL (BioseqPtr bsp)
+{
+  Boolean           is_ibol = FALSE;
+  SeqMgrDescContext context;
+  SeqDescPtr        sdp;
+  UserObjectPtr     uop;
+  UserFieldPtr      curr;
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &context);
+       sdp != NULL && !is_ibol;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &context)) 
+  {
+    if ((uop = (UserObjectPtr) sdp->data.ptrvalue) != NULL
+        && uop->type != NULL
+        && StringICmp (uop->type->str, "StructuredComment") == 0)
+    {
+      for (curr = uop->data; curr != NULL && !is_ibol; curr = curr->next) 
+      {
+        if (curr->label != NULL
+            && curr->choice == 1
+            && StringICmp (curr->label->str, "StructuredCommentPrefix") == 0
+                   && StringICmp (curr->data.ptrvalue, "##International Barcode of Life (iBOL)Data-START##") == 0) 
+        {
+          is_ibol = TRUE;
+        }
+      }
+    }
+  }
+  return is_ibol;
+}
+
+
+static Boolean HasOrderAssignment (BioseqPtr bsp)
+{
+  Boolean           has_order = FALSE, is_ibol = FALSE;
+  SeqMgrDescContext context;
+  SeqDescPtr        sdp;
+  UserObjectPtr     uop;
+  UserFieldPtr      curr;
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &context);
+       sdp != NULL && !has_order;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &context)) 
+  {
+    if ((uop = (UserObjectPtr) sdp->data.ptrvalue) != NULL
+        && uop->type != NULL
+        && StringICmp (uop->type->str, "StructuredComment") == 0)
+    {
+      is_ibol = FALSE;
+      for (curr = uop->data; curr != NULL && (!has_order || !is_ibol); curr = curr->next) 
+      {
+        if (curr->label != NULL
+            && curr->choice == 1) 
+        {
+          if (StringICmp (curr->label->str, "Order Assignment") == 0
+              && !StringHasNoText (curr->data.ptrvalue))
+          {
+            has_order = TRUE;
+          }
+          else if (StringICmp (curr->label->str, "StructuredCommentPrefix") == 0
+                   && StringICmp (curr->data.ptrvalue, "##International Barcode of Life (iBOL)Data-START##") == 0) 
+          {
+            is_ibol = TRUE;
+          }
+        }
+      }
+    }
+  }
+  if (is_ibol && !has_order) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+static void FindMissingOrderAssignment (BioseqPtr bsp, Pointer userdata)
+{
+  BarcodeSearchPtr  bsd;
+
+  if (bsp == NULL || ISA_aa (bsp->mol) 
+      || (bsd = (BarcodeSearchPtr) userdata) == NULL
+      || bsd->cfg == NULL
+      || (bsd->cfg->require_keyword && !HasBARCODETech(bsp))) 
+  {
+    return;
+  }
+
+  if (!HasOrderAssignment (bsp))
+  { 
+    ValNodeAddPointer (&(bsd->bioseq_list), OBJ_BIOSEQ, bsp);
+  }
+}
+
+
+static void FindLowTrace (BioseqPtr bsp, Pointer userdata)
+{
+  BarcodeSearchPtr  bsd;
+
+  if (bsp == NULL || ISA_aa (bsp->mol) 
+      || (bsd = (BarcodeSearchPtr) userdata) == NULL
+      || bsd->cfg == NULL
+      || (bsd->cfg->require_keyword && !HasBARCODETech(bsp))) 
+  {
+    return;
+  }
+
+  if (HasLowTrace (bsp))
+  { 
+    ValNodeAddPointer (&(bsd->bioseq_list), OBJ_BIOSEQ, bsp);
+  }
+}
+
+
+static Boolean HasFrameShift (BioseqPtr bsp)
+{
+  SeqDescrPtr sdp;
+  SeqMgrDescContext context;
+  Boolean rval = FALSE;
+  UserObjectPtr uop;
+  UserFieldPtr  ufp;
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_user, &context);
+       sdp != NULL && !rval;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_user, &context)) 
+  {
+    uop = (UserObjectPtr) sdp->data.ptrvalue;
+    if (uop != NULL && uop->type != NULL && StringICmp (uop->type->str, "multalin") == 0) 
+    {
+      ufp = uop->data;
+      while (ufp != NULL && !rval) {
+        if (ufp->label != NULL 
+            && StringICmp (ufp->label->str, "frameshift-nuc") == 0
+            && ufp->choice == 1
+            && StringICmp (ufp->data.ptrvalue, "fail") == 0) {
+          rval = TRUE;
+        }
+        ufp = ufp->next;
+      }
+    }
+  }
+  return rval;
+}
+
+
+static void FindFrameShift (BioseqPtr bsp, Pointer userdata)
+{
+  BarcodeSearchPtr  bsd;
+
+  if (bsp == NULL || ISA_aa (bsp->mol) 
+      || (bsd = (BarcodeSearchPtr) userdata) == NULL
+      || bsd->cfg == NULL
+      || (bsd->cfg->require_keyword && !HasBARCODETech(bsp))) 
+  {
+    return;
+  }
+
+  if (IsIBOL (bsp) && HasFrameShift (bsp))
+  { 
+    ValNodeAddPointer (&(bsd->bioseq_list), OBJ_BIOSEQ, bsp);
+  }
+}
+
+
 typedef Boolean (*BarcodeBioSourceTestFunc) PROTO ((BioSourcePtr));
 
 static Boolean HasForwardAndReversePrimers (BioSourcePtr biop)
@@ -22192,6 +25385,348 @@ static Boolean HasVoucher (BioSourcePtr biop)
 }
 
 
+static CharPtr GetDash (CharPtr str)
+
+{
+  Char  ch;
+
+  if (str == NULL) return NULL;
+  ch = *str;
+  while (ch != '\0') {
+    if (ch == '-') return str;
+    str++;
+    ch = *str;
+  }
+
+  return NULL;
+}
+
+static CharPtr legalMonths [] = {
+  "Jan",
+  "Feb",
+  "Mar",
+  "Apr",
+  "May",
+  "Jun",
+  "Jul",
+  "Aug",
+  "Sep",
+  "Oct",
+  "Nov",
+  "Dec",
+  NULL
+};
+
+
+NLM_EXTERN Boolean CollectionDateIsValid (CharPtr name)
+
+{
+  Char      ch;
+  Int2      i;
+  CharPtr   ptr1, ptr2, month = NULL, day = NULL, year = NULL;
+  Char      str [256];
+  long int  val;
+
+  if (StringHasNoText (name)) return FALSE;
+
+  StringNCpy_0 (str, name, sizeof (str));
+  ptr1 = GetDash (str);
+  if (ptr1 != NULL) {
+    *ptr1 = '\0';
+    ptr1++;
+    ptr2 = GetDash (ptr1);
+    if (ptr2 != NULL) {
+      *ptr2 = '\0';
+      ptr2++;
+      day = str;
+      month = ptr1;
+      year = ptr2;
+    } else {
+      month = str;
+      year = ptr1;
+    }
+  } else {
+    year = str;
+  }
+
+  if (day != NULL) {
+    if (sscanf (day, "%ld", &val) != 1 || val < 1 || val > 31) return FALSE;
+    if (StringLen (day) != 2 || !isdigit(day[0]) || !isdigit(day[1])) return FALSE;
+  }
+
+  if (month != NULL) {
+    for (i = 0; legalMonths [i] != NULL; i++) {
+      if (StringCmp (month, legalMonths [i]) == 0) {
+        break;
+      }
+    }
+    if (legalMonths [i] == NULL) return FALSE;
+  }
+
+  if (year != NULL) {
+    ptr1 = year;
+    ch = *ptr1;
+    while (ch != '\0') {
+      if (! (IS_DIGIT (ch))) return FALSE;
+      ptr1++;
+      ch = *ptr1;
+    }
+    if (sscanf (year, "%ld", &val) == 1) {
+      if (val >= 1700 && val < 2100) return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+
+/* This mimics a portion of the DatePtr structure,
+ * but allows dates with years before 1900 because
+ * the year value is Int4 instead of Uint1.
+ *   data [0] : Set to 1
+ *        [1] - year (- 1900)
+ *        [2] - month (1-12)  optional
+ *        [3] - day (1-31)     optional
+ * Not bothering with time.
+ */
+
+typedef struct betterdate {
+    Int4 data[8];      /* see box above */
+} BetterDateData, PNTR BetterDatePtr;
+
+static BetterDatePtr BetterDateNew()
+{
+  BetterDatePtr dp;
+
+  dp = (BetterDatePtr) MemNew (sizeof (BetterDateData));
+  return dp;
+}
+
+static BetterDatePtr BetterDateFree (BetterDatePtr dp)
+{
+  if (dp != NULL) {
+    dp = MemFree (dp);
+  }
+  return dp;
+}
+
+
+static BetterDatePtr CollectionDateFromString (CharPtr name)
+{
+  Char      ch;
+  Int2      i;
+  CharPtr   ptr1, ptr2, month = NULL, day = NULL, year = NULL;
+  Char      str [256];
+  long int  day_val = 0;
+  Int2      month_num = 0;
+  long int  val, year_val = 0;
+  BetterDatePtr   dp;
+
+  if (StringHasNoText (name)) return NULL;
+
+  StringNCpy_0 (str, name, sizeof (str));
+  ptr1 = GetDash (str);
+  if (ptr1 != NULL) {
+    *ptr1 = '\0';
+    ptr1++;
+    ptr2 = GetDash (ptr1);
+    if (ptr2 != NULL) {
+      *ptr2 = '\0';
+      ptr2++;
+      day = str;
+      month = ptr1;
+      year = ptr2;
+    } else {
+      month = str;
+      year = ptr1;
+    }
+  } else {
+    year = str;
+  }
+
+  if (day != NULL) {
+    if (sscanf (day, "%ld", &day_val) != 1 || day_val < 1 || day_val > 31) return NULL;
+  }
+
+  if (month != NULL) {
+    for (i = 0; legalMonths [i] != NULL; i++) {
+      if (StringCmp (month, legalMonths [i]) == 0) {
+        month_num = i + 1;
+        break;
+      }
+    }
+    if (legalMonths [i] == NULL) return NULL;
+  }
+
+  if (year != NULL) {
+    ptr1 = year;
+    ch = *ptr1;
+    while (ch != '\0') {
+      if (! (IS_DIGIT (ch))) return NULL;
+      ptr1++;
+      ch = *ptr1;
+    }
+    if (sscanf (year, "%ld", &val) == 1) {
+      if (val < 1700 || val > 2100) return NULL;
+      year_val = val - 1900;
+    }
+    else
+    {
+      return NULL;
+    }
+  }
+
+  dp = BetterDateNew();
+  dp->data[0] = 1;
+  dp->data[1] = year_val;
+  dp->data[2] = month_num;
+  dp->data[3] = day_val;
+  return dp;
+}
+
+
+NLM_EXTERN Boolean CollectionDateIsInTheFuture (CharPtr name)
+
+{
+  DatePtr   dp_now;
+  BetterDatePtr dp_coll_date;
+  Boolean   rval = FALSE;
+
+  dp_coll_date = CollectionDateFromString (name);
+  if (dp_coll_date == NULL) return FALSE;
+
+  if (dp_coll_date->data[1] < 0)
+  {
+    /* year before 1900 */
+    dp_coll_date = BetterDateFree (dp_coll_date);
+    return FALSE;
+  }
+
+  dp_now = DateCurr();
+
+  /* compare years */
+  if (dp_now->data[1] < dp_coll_date->data[1])
+  {
+    rval = TRUE;
+  }
+  else if (dp_now->data[1] > dp_coll_date->data[1])
+  {
+    rval = FALSE;
+  }
+  /* years are equal - compare months */
+  else if (dp_now->data[2] < dp_coll_date->data[2])
+  {
+    rval = TRUE;
+  }
+  else if (dp_now->data[2] > dp_coll_date->data[2])
+  {
+    rval = FALSE;
+  }
+  /* years and months are equal - compare days */
+  else if (dp_now->data[3] < dp_coll_date->data[3])
+  {
+    rval = TRUE;
+  }
+  else
+  {
+    rval = FALSE;
+  }
+
+  dp_now = DateFree (dp_now);
+  dp_coll_date = BetterDateFree (dp_coll_date);
+  return rval;
+}
+
+
+/* collection date is not required, but if present must be valid and in the past */
+static Boolean HasCollectionDate (BioSourcePtr biop)
+{
+  SubSourcePtr ssp;
+  Boolean      rval = TRUE;
+
+  if (biop == NULL) {
+    return FALSE;
+  }
+  ssp = biop->subtype;
+  while (ssp != NULL && rval) {
+    if (ssp->subtype == SUBSRC_collection_date) {
+      if (!CollectionDateIsValid(ssp->name) || CollectionDateIsInTheFuture(ssp->name)) {
+        rval = FALSE;
+      }
+    }
+    ssp = ssp->next;
+  }
+  return rval;
+}
+
+
+static Boolean BarcodeGPSOkay (BioSourcePtr biop)
+{
+  SubSourcePtr ssp;
+  Boolean      rval = TRUE;
+  CharPtr      country = NULL;
+  Boolean      format_ok, lat_in_range, lon_in_range;
+  FloatHi      lat, lon;
+  Char         buf [256];
+  CharPtr      ptr;
+  CharPtr      guess;
+
+  if (biop == NULL) {
+    return FALSE;
+  }
+  ssp = biop->subtype;
+  /* first find country */
+  for (ssp = biop->subtype; ssp != NULL && country == NULL; ssp = ssp->next) 
+  {
+    if (ssp->subtype == SUBSRC_country) 
+    {
+      country = ssp->name;
+    }
+  }
+  if (StringContainsBodyOfWater (country)) 
+  {
+    return TRUE;
+  }
+  if (country != NULL) 
+  {
+    StringNCpy_0 (buf, country, sizeof (buf));
+    ptr = StringChr (buf, ':');
+    if (ptr != NULL) {
+      *ptr = '\0';
+    }
+    country = buf;
+  }
+
+  for (ssp = biop->subtype; ssp != NULL && rval; ssp = ssp->next) 
+  {
+    if (ssp->subtype == SUBSRC_lat_lon) 
+    {
+      IsCorrectLatLonFormat (ssp->name, &format_ok, &lat_in_range, &lon_in_range);
+      if (!format_ok || !lat_in_range || !lon_in_range) 
+      {
+        rval = FALSE;
+      } 
+      else if (!ParseLatLon (ssp->name, &lat, &lon))
+      {
+        rval = FALSE;
+      }
+      else if (country != NULL && IsCountryInLatLonList (country))
+      {
+        if (!(TestLatLonForCountry (country, lat, lon))) 
+        {
+          guess = GuessCountryForLatLon (lat, lon);
+          if (StringHasNoText (guess) || !CountryBoxesOverlap (country, guess)) {
+            rval = FALSE;
+          }
+        }
+      }
+    }
+  }
+
+  return rval;
+}
+
+
 static Boolean BarcodeBioSourceTest (BioseqPtr bsp, BarcodeBioSourceTestFunc test_func, Boolean require_keyword)
 {
   SeqDescrPtr       sdp;
@@ -22253,6 +25788,19 @@ static void FindMissingSpecimenVoucher (BioseqPtr bsp, Pointer userdata)
 }
 
 
+static void FindBadCollectionDate (BioseqPtr bsp, Pointer userdata)
+{  
+  BarcodeBioSourceTestCallback (bsp, userdata, HasCollectionDate);
+}
+
+
+static void FindBadGPS (BioseqPtr bsp, Pointer userdata)
+{
+  BarcodeBioSourceTestCallback (bsp, userdata, BarcodeGPSOkay);
+}
+
+
+
 static void 
 BarcodeTestForSeqEntry 
 (SeqEntryPtr          sep,
@@ -22297,7 +25845,7 @@ static void BarcodePercentNDiscrepancy (BioseqPtr bsp, Pointer userdata)
 
   bs = (BarcodeSearchPtr) userdata;
 
-  pct = PercentNInBioseq (bsp);
+  pct = PercentNInBioseq (bsp, TRUE);
   if (pct > bs->cfg->min_n_percent) 
   {
     ValNodeAddPointer (&(bs->bioseq_list), OBJ_BIOSEQ, bsp);
@@ -22329,7 +25877,7 @@ static void BarcodePercentNDiscrepanciesForSeqEntry (SeqEntryPtr sep, ValNodePtr
     cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
     MemSet (cip, 0, sizeof (ClickableItemData));
     cip->description = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + 5));
-    pct = PercentNInBioseq (vnp->data.ptrvalue);
+    pct = PercentNInBioseq (vnp->data.ptrvalue, TRUE);
     sprintf (cip->description, fmt, pct);
     ValNodeAddPointer (&(cip->item_list), OBJ_BIOSEQ, vnp->data.ptrvalue);
     ValNodeAddPointer (&subcategories, 0, cip);
@@ -22374,6 +25922,22 @@ static void GetBarcodeDiscrepanciesForSeqEntry (SeqEntryPtr sep, ValNodePtr PNTR
   {
     BarcodePercentNDiscrepanciesForSeqEntry (sep, discrepancy_list, cfg);
   }
+  if (cfg->conf_list[eBarcodeTest_CollectionDate])
+  {
+    BarcodeTestForSeqEntry (sep, discrepancy_list, FindBadCollectionDate, "%d sequences have invalid collection date", cfg);
+  }
+  if (cfg->conf_list[eBarcodeTest_OrderAssignment])
+  {
+    BarcodeTestForSeqEntry (sep, discrepancy_list, FindMissingOrderAssignment, "%d sequences are missing order assignment", cfg);
+  }
+  if (cfg->conf_list[eBarcodeTest_LowTrace])
+  {
+    BarcodeTestForSeqEntry (sep, discrepancy_list, FindLowTrace, "%d sequences have low trace", cfg);
+  }
+  if (cfg->conf_list[eBarcodeTest_FrameShift])
+  {
+    BarcodeTestForSeqEntry (sep, discrepancy_list, FindFrameShift, "%d sequences have frameshift", cfg);
+  }
 }
 
 
@@ -22564,7 +26128,7 @@ static CharPtr SummaryTextFromBarcodeTestResults (BarcodeTestResultsPtr res)
       msg_len += StringLen (GetBarcodeTestName (i)) + 2;
       if (i == eBarcodeTest_PercentN)
       {
-        msg_len += 5;
+        msg_len += 6;
       }
       any_failed = TRUE;
     }
@@ -22605,7 +26169,11 @@ extern Boolean PassBarcodeTests (BarcodeTestResultsPtr res)
       || res->failed_tests[eBarcodeTest_Primers]
       || res->failed_tests[eBarcodeTest_Country]
       || res->failed_tests[eBarcodeTest_SpecimenVoucher]
-      || res->failed_tests[eBarcodeTest_PercentN])
+      || res->failed_tests[eBarcodeTest_PercentN]
+      || res->failed_tests[eBarcodeTest_CollectionDate]
+      || res->failed_tests[eBarcodeTest_OrderAssignment]
+      || res->failed_tests[eBarcodeTest_LowTrace]
+      || res->failed_tests[eBarcodeTest_FrameShift])
   {
     return FALSE;
   }
@@ -22616,7 +26184,7 @@ extern Boolean PassBarcodeTests (BarcodeTestResultsPtr res)
 }
 
 
-static BarcodeTestResultsPtr BarcodeTestResultsForBioseq (BioseqPtr bsp, BarcodeTestConfigPtr cfg)
+NLM_EXTERN BarcodeTestResultsPtr BarcodeTestResultsForBioseq (BioseqPtr bsp, BarcodeTestConfigPtr cfg)
 {
   BarcodeTestResultsPtr res = NULL;
 
@@ -22646,10 +26214,26 @@ static BarcodeTestResultsPtr BarcodeTestResultsForBioseq (BioseqPtr bsp, Barcode
   {
     res->failed_tests[eBarcodeTest_SpecimenVoucher] = BarcodeBioSourceTest(bsp, HasVoucher, cfg->require_keyword);
   }
+  if (cfg->conf_list[eBarcodeTest_CollectionDate]) 
+  {
+    res->failed_tests[eBarcodeTest_CollectionDate] = BarcodeBioSourceTest(bsp, HasCollectionDate, cfg->require_keyword);
+  }
+  if (cfg->conf_list[eBarcodeTest_OrderAssignment]) 
+  {
+    res->failed_tests[eBarcodeTest_OrderAssignment] = !HasOrderAssignment (bsp);
+  }
+  if (cfg->conf_list[eBarcodeTest_LowTrace])
+  {
+    res->failed_tests[eBarcodeTest_LowTrace] = HasLowTrace (bsp);
+  }
+  if (cfg->conf_list[eBarcodeTest_FrameShift])
+  {
+    res->failed_tests[eBarcodeTest_FrameShift] = IsIBOL(bsp) && HasFrameShift (bsp);
+  }
 
   if (cfg->conf_list[eBarcodeTest_PercentN])
   {
-    res->n_percent = PercentNInBioseq (bsp);
+    res->n_percent = PercentNInBioseq (bsp, TRUE);
     res->failed_tests[eBarcodeTest_PercentN] = (Boolean)(res->n_percent > cfg->min_n_percent);
   }
  
@@ -22740,11 +26324,12 @@ extern ValNodePtr GetBarcodePassFail (SeqEntryPtr sep, BarcodeTestConfigPtr cfg)
 /* Report lists each Bioseq and whether the Bioseq passed all tests
  * or failed at least one.
  */
-extern void WriteBarcodeTestCompliance (FILE *fp, ValNodePtr results_list)
+extern void WriteBarcodeTestComplianceEx (FILE *fp, ValNodePtr results_list, Boolean low_trace_fail)
 {
   BarcodeTestResultsPtr res;
   ValNodePtr            vnp;
   CharPtr               barcode_id, genbank_id;
+  Boolean               pass;
 
   if (fp == NULL) return;
 
@@ -22753,14 +26338,23 @@ extern void WriteBarcodeTestCompliance (FILE *fp, ValNodePtr results_list)
     res = (BarcodeTestResultsPtr) vnp->data.ptrvalue;
     barcode_id = BarcodeTestBarcodeIdString (res->bsp);
     genbank_id = BarcodeTestGenbankIdString (res->bsp);
-    fprintf (fp, "%s\t%s\t%s\n", barcode_id, genbank_id, 
-                                 PassBarcodeTests (res) ? "PASS" : "FAIL");
+    pass = PassBarcodeTests (res);
+    if (pass && low_trace_fail && HasLowTrace (res->bsp)) {
+      pass = FALSE;
+    }
+    fprintf (fp, "%s\t%s\t%s\n", barcode_id, genbank_id, pass ? "PASS" : "FAIL");
     barcode_id = MemFree (barcode_id);
     genbank_id = MemFree (genbank_id);
   }
 }
 
 
+extern void WriteBarcodeTestCompliance (FILE *fp, ValNodePtr results_list)
+{
+  WriteBarcodeTestComplianceEx (fp, results_list, FALSE);
+}
+
+
 /* Report lists each Bioseq and whether the Bioseq passed all tests
  * or failed at least one.
  */
@@ -22829,6 +26423,66 @@ extern void WriteBarcodeDiscrepancies (FILE *fp, ValNodePtr results_list)
 }
 
 
+static CharPtr FailureTextFromBarcodeTestResults (BarcodeTestResultsPtr res)
+{
+  Int4             i, msg_len = 0;
+  Boolean          any_failed = FALSE;
+  CharPtr          msg, genbank_id, barcode_id;
+
+  if (res == NULL || res->bsp == NULL) return NULL;
+
+  for (i = 0; i < eBarcodeTest_LAST; i++)
+  {
+    if (res->failed_tests[i]) 
+    {
+      msg_len += StringLen (GetBarcodeTestName (i)) + 2;
+      any_failed = TRUE;
+    }
+  }
+  if (!any_failed) return NULL;
+
+  genbank_id = BarcodeTestGenbankIdString (res->bsp);
+  barcode_id = BarcodeTestBarcodeIdString (res->bsp);
+  
+  msg_len += StringLen (genbank_id) + StringLen (barcode_id) + 2;
+ 
+  msg = (CharPtr) MemNew (sizeof (Char) * msg_len);
+  sprintf (msg, "%s\t%s\t", barcode_id, genbank_id);
+  for (i = 0; i < eBarcodeTest_LAST; i++)
+  {
+    if (res->failed_tests[i])
+    {
+      StringCat (msg, GetBarcodeTestName(i));
+      StringCat (msg, ",");
+    }
+  }
+  /* remove trailing comma */
+  msg[StringLen(msg) - 1] = 0;
+          
+  return msg;
+}
+
+
+extern void WriteBarcodeFailureReport (FILE *fp, ValNodePtr results_list)
+{
+  ValNodePtr vnp;
+  BarcodeTestResultsPtr res;
+  CharPtr msg;
+
+  if (fp == NULL) return;
+
+  for (vnp = results_list; vnp != NULL; vnp = vnp->next)
+  {
+    res = (BarcodeTestResultsPtr) vnp->data.ptrvalue;
+    msg = FailureTextFromBarcodeTestResults (res);
+    if (msg != NULL) {
+      fprintf (fp, "%s\n", msg);
+      msg = MemFree (msg);
+    }
+  }
+}
+
+
 static void BarcodeValPrintStr (FILE *fp, CharPtr fmt, CharPtr str)
 {
   if (fp == NULL) {
@@ -23144,8 +26798,10 @@ extern void AbstractReportError (
   {
     for (last = *list; last != NULL && last->next != NULL; last = last->next)
     {}
+    if (last != NULL) {
     last->next = err_ptr;
   }
+  }
 
 }
 
@@ -24613,7 +28269,9 @@ static CharPtr FindStateMatch (CharPtr search, CharPtr PNTR country, Int4Ptr sta
     if (state_matches != NULL) {
       if (state_matches->next == NULL && best_match == NULL) {
         best_match = state_matches->data.ptrvalue;
+        if (country != NULL) {
         *country = country_state_list[i].country_name;
+        }
       } else {
         *pMulti = TRUE;
         return NULL;
@@ -25375,7 +29033,7 @@ extern ValNodePtr ListFeaturesInLocation (BioseqPtr bsp, SeqLocPtr slp, Uint1 se
 }
 
 
-extern ValNodePtr ListFeaturesOverlappingLocation (BioseqPtr bsp, SeqLocPtr slp, Uint1 seqfeatChoice, Uint1 featdefChoice)
+extern ValNodePtr ListFeaturesOverlappingLocationEx (BioseqPtr bsp, SeqLocPtr slp, Uint1 seqfeatChoice, Uint1 featdefChoice, ValNodePtr constraint)
 {
   ValNodePtr        feat_list = NULL;
   SeqMgrFeatContext fcontext;
@@ -25396,6 +29054,9 @@ extern ValNodePtr ListFeaturesOverlappingLocation (BioseqPtr bsp, SeqLocPtr slp,
        sfp != NULL && fcontext.left <= loc_right;
        sfp = SeqMgrGetNextFeature (bsp, sfp, seqfeatChoice, featdefChoice, &fcontext))
   {
+    if (!DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, constraint)) {
+      continue;
+    }
     cmp = SeqLocCompare (sfp->location, slp);
     if (cmp != SLC_NO_MATCH)
     {
@@ -25406,6 +29067,12 @@ extern ValNodePtr ListFeaturesOverlappingLocation (BioseqPtr bsp, SeqLocPtr slp,
 }
 
 
+extern ValNodePtr ListFeaturesOverlappingLocation (BioseqPtr bsp, SeqLocPtr slp, Uint1 seqfeatChoice, Uint1 featdefChoice)
+{
+  return ListFeaturesOverlappingLocationEx (bsp, slp, seqfeatChoice, featdefChoice, NULL);
+}
+
+
 static void CDSInSrcFeatCallback (BioseqPtr bsp, Pointer data)
 {
   SeqMgrFeatContext fcontext;
@@ -25509,5 +29176,103 @@ extern LogInfoPtr FreeLog (LogInfoPtr lip)
 }
 
 
+static void ParseOneFromTaxnameToQuals (OrgRefPtr org, CharPtr qual_name, CharPtr start, Int4 val_len)
+{
+  Int4        q_type, s_type;
+  Boolean     found = FALSE;
+  OrgModPtr   mod;
+
+  if (val_len > 0) {
+    q_type = GetSourceQualTypeByName (qual_name);
+    if (q_type > -1) {
+      s_type = GetOrgModQualFromSrcQual (q_type, NULL);
+      if (s_type > -1) {
+        /* look for existing value */
+        if (org->orgname != NULL) {
+          for (mod = org->orgname->mod; mod != NULL && !found; mod = mod->next) {
+            if (mod->subtype == s_type) {
+              found = TRUE;
+            }
+          }
+        }
+        if (!found) {
+          if (org->orgname == NULL) {
+            org->orgname = OrgNameNew ();
+          }
+          mod = OrgModNew ();
+          mod->subtype = s_type;
+          mod->subname = (CharPtr) MemNew (sizeof (Char) * (val_len));
+          StringNCpy (mod->subname, start + 1, val_len - 1);
+          mod->subname[val_len - 1] = 0;
+          mod->next = org->orgname->mod;
+          org->orgname->mod = mod;
+        }
+      }
+    }
+  }
+}
+
+
+NLM_EXTERN void ParseTaxNameToQuals (OrgRefPtr org, TextFsaPtr tags)
+{
+  Char        ch;
+  CharPtr     ptr;
+  Int4        state;
+  ValNodePtr  matches;
+  CharPtr     last_hit = NULL, last_pos = NULL;
+  Int4        val_len, match_len;
+
+  if (tags == NULL || org == NULL || StringHasNoText (org->taxname)) return;
+  state = 0;
+  ptr = org->taxname;
+  ch = *ptr;
+  while (ch != '\0') {
+    matches = NULL;
+    state = TextFsaNext (tags, state, ch, &matches);
+    if (matches != NULL && isspace (*(ptr + 1)) && (match_len = StringLen (matches->data.ptrvalue)) > 0
+        && (isspace (*(ptr - match_len)) || ispunct (*(ptr - match_len)))) {
+      if (last_pos != NULL) {
+        val_len = ptr - last_pos - 1 - match_len;
+        ParseOneFromTaxnameToQuals (org, last_hit, last_pos + 1, val_len);
+      }
+      last_pos = ptr;
+      last_hit = (CharPtr) matches->data.ptrvalue;
+    }
+    ptr++;
+    ch = *ptr;
+  }
+  if (last_pos != NULL) {
+    val_len = ptr - last_pos;
+    ParseOneFromTaxnameToQuals (org, last_hit, last_pos, val_len);
+  }
+}
+
+
+static void GetLocusTagPrefixListCallback (SeqFeatPtr sfp, Pointer data)
+{
+  GeneRefPtr grp;
+  CharPtr    cp, prefix;
+  Int4       len;
 
+  if (sfp != NULL && sfp->data.choice == SEQFEAT_GENE 
+      && (grp = (GeneRefPtr) sfp->data.value.ptrvalue) != NULL
+      && (cp = StringChr (grp->locus_tag, '_')) != NULL
+      && (len = cp - grp->locus_tag) > 0) {
+    prefix = (CharPtr) MemNew (sizeof (Char) * (len + 1));
+    StringNCpy (prefix, grp->locus_tag, len);
+    prefix[len] = 0;
+    ValNodeAddPointer ((ValNodePtr PNTR) data, 0, prefix);
+  }
+}
+
+
+NLM_EXTERN ValNodePtr GetLocusTagPrefixList (SeqEntryPtr sep)
+{
+    ValNodePtr list = NULL;
+
+    VisitFeaturesInSep (sep, &list, GetLocusTagPrefixListCallback);
+    list = ValNodeSort (list, SortVnpByString);
+    ValNodeUnique (&list, SortVnpByString, ValNodeFreeData);
+    return list;
+}
 
diff --git a/api/sqnutil4.c b/api/sqnutil4.c
index 26d7b9b..6690de0 100755
--- a/api/sqnutil4.c
+++ b/api/sqnutil4.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   12/27/2007
 *
-* $Revision: 1.59 $
+* $Revision: 1.111 $
 *
 * File Description: 
 * This file contains functions for automatically generating definition lines.
@@ -56,6 +56,7 @@
 #define NLM_GENERATED_CODE_PROTO
 #include <objmacro.h>
 #include <macroapi.h>
+#include <tax3api.h>
 
 /* This is a list of the modifiers that are of interest */
 /* Note that if you modify the DefLineModifiers array, */ 
@@ -294,6 +295,7 @@ static ValNodePtr FindStringInStrings (
   return NULL;
 }
 
+#if 0
 /* This function finds the first item in "strings" that is identical to
  * "value".
  */
@@ -311,6 +313,25 @@ extern ValNodePtr FindExactStringInStrings (
   {}
   return string_match;
 }
+#endif
+
+
+NLM_EXTERN ValNodePtr FindExactStringListMatch (
+  ValNodePtr list,
+  CharPtr value
+)
+
+{
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringCmp (str, value) == 0) return vnp;
+  }
+
+  return NULL;
+}
 
 /* This function creates a new linked list of strings with copies of
  * contents of orig.
@@ -626,7 +647,7 @@ static void CountModifiersProc (
           {
             ItemList[i].first_value_seen = mod->subname;
           }
-          if ( FindExactStringInStrings (ItemList[i].values_seen, mod->subname)
+          if ( FindExactStringListMatch (ItemList[i].values_seen, mod->subname)
             == NULL)
           {
             ValNodeAddStr (&ItemList[i].values_seen, 0, mod->subname);
@@ -657,7 +678,7 @@ static void CountModifiersProc (
         {
           ItemList[i].first_value_seen = ssp->name;
         }
-        if ( FindExactStringInStrings (ItemList[i].values_seen, ssp->name)
+        if ( FindExactStringListMatch (ItemList[i].values_seen, ssp->name)
           == NULL)
         {
           ValNodeAddStr (&ItemList[i].values_seen, 0, ssp->name);
@@ -1338,7 +1359,7 @@ static Boolean OkToTryAddingQual (
   ValNodePtr vnp;
 
   /* if feature_index indicates a value we don't use for best combos, skip */
-  if (feature_index == DEFLINE_POS_Map)
+  if (feature_index == DEFLINE_POS_Map || feature_index == DEFLINE_POS_Specific_host)
   {
     return FALSE;
   }
@@ -1930,7 +1951,7 @@ static Boolean HasTypeStrainComment (BioSourcePtr biop)
     return FALSE;
   }
   
-  if (!UseOrgModifier (mod, biop->org->taxname))
+  if (!UseOrgModifier (mod, biop->org->taxname, FALSE))
   {
     return FALSE;
   }
@@ -2096,7 +2117,7 @@ static OrgModAbbrevData orgmod_abbrevs[] = {
 
 
 
-static Boolean FindModifierTextInTaxname (CharPtr search_text, Int2 subtype, CharPtr taxName)
+static Boolean FindModifierTextInTaxname (CharPtr search_text, Int2 subtype, CharPtr taxName, Boolean allow_at_end)
 {
   CharPtr value_found, abbrev_start;
   Int4    value_len, i;
@@ -2126,6 +2147,9 @@ static Boolean FindModifierTextInTaxname (CharPtr search_text, Int2 subtype, Cha
       value_found = StringStr (value_found + 1, search_text);
       continue;
     }
+    if (allow_at_end && value_found != NULL && StringCmp (value_found, search_text) == 0) {
+      return FALSE;
+    }
     other_abbrev_found = FALSE;
     for (i = 0; i < NUM_orgmod_abbrevs; i++)
     {
@@ -2167,7 +2191,8 @@ static Boolean FindModifierTextInTaxname (CharPtr search_text, Int2 subtype, Cha
  */
 NLM_EXTERN Boolean UseOrgModifier (
   OrgModPtr mod,
-  CharPtr   taxName
+  CharPtr   taxName,
+  Boolean   allow_at_end
 )
 {
   Boolean value_found = FALSE;
@@ -2188,12 +2213,12 @@ NLM_EXTERN Boolean UseOrgModifier (
     || mod->subtype == ORGMOD_isolate
     || mod->subtype == ORGMOD_cultivar)
   {
-    if (FindModifierTextInTaxname (mod->subname, mod->subtype, taxName)) {
+    if (FindModifierTextInTaxname (mod->subname, mod->subtype, taxName, allow_at_end)) {
       value_found = TRUE;
     } else if (mod->subtype == ORGMOD_specimen_voucher && (cp = StringChr (mod->subname, ':')) != NULL) {
       search_text = StringSave (mod->subname);
       search_text[cp - mod->subname] = ' ';
-      value_found = FindModifierTextInTaxname (search_text, mod->subtype, taxName);
+      value_found = FindModifierTextInTaxname (search_text, mod->subtype, taxName, allow_at_end);
       search_text = MemFree (search_text);
     }
   }
@@ -2218,6 +2243,41 @@ NLM_EXTERN void SetRequiredModifiers (
   
 }
 
+
+static const Int4 s_auto_def_id_preferred_quals[] = {
+  DEFLINE_POS_Strain,
+  DEFLINE_POS_Clone,
+  DEFLINE_POS_Isolate,
+  DEFLINE_POS_Cultivar,
+  DEFLINE_POS_Specimen_voucher,
+};
+
+static const Int4 k_num_auto_def_id_preferred_quals = sizeof (s_auto_def_id_preferred_quals) / sizeof (Int4);
+
+/* This function generates the modifiers for "AutoDefID" */
+NLM_EXTERN void SetAutoDefIDModifiers (ModifierItemLocalPtr modList)
+{
+  Int4 index;
+  Boolean added_required = FALSE;
+
+  if (modList == NULL) return;
+  /* first look for first modifier in list that is present on all sources */
+  for (index = 0; index < k_num_auto_def_id_preferred_quals && !added_required; index++) {
+    if (modList[s_auto_def_id_preferred_quals[index]].all_present) {
+      modList[s_auto_def_id_preferred_quals[index]].required = TRUE;
+      added_required = TRUE;
+    }
+  }
+  /* if not found, then look for first modifier in list that is present on any sources */
+  for (index = 0; index < k_num_auto_def_id_preferred_quals && !added_required; index++) {
+    if (modList[s_auto_def_id_preferred_quals[index]].any_present) {
+      modList[s_auto_def_id_preferred_quals[index]].required = TRUE;
+      added_required = TRUE;
+    }
+  }
+}
+
+
 /* This function fixes HIV abbreviations, removes items in parentheses,
  * and trims spaces around the taxonomy name.
  */
@@ -2395,6 +2455,109 @@ NLM_EXTERN Int4 GetGenomeProjectID (BioseqPtr bsp)
 }
 
 
+static void AddSpTaxnameToList (SeqDescrPtr sdp, Pointer userdata)
+{
+  BioSourcePtr biop;
+
+  if (sdp == NULL || sdp->choice != Seq_descr_source || userdata == NULL) return;
+
+  biop = (BioSourcePtr) sdp->data.ptrvalue;
+  if (biop == NULL || biop->org == NULL || !IsSpName (biop->org->taxname)) return;
+
+  ValNodeAddPointer ((ValNodePtr PNTR) userdata, 0, biop->org->taxname);
+}
+
+
+NLM_EXTERN Boolean ShouldExcludeSp (SeqEntryPtr sep)
+{
+  ValNodePtr name_list = NULL, vnp1, vnp2;
+  Boolean    all_diff = TRUE;
+
+  if (sep == NULL) return TRUE;
+  VisitDescriptorsInSep (sep, &name_list, AddSpTaxnameToList);
+
+  name_list = ValNodeSort (name_list, SortVnpByString);
+
+  if (name_list != NULL && name_list->next != NULL)
+  {
+    for (vnp1 = name_list; vnp1 != NULL && vnp1->next != NULL && all_diff; vnp1 = vnp1->next)
+    {
+      for (vnp2 = vnp1->next; vnp2 != NULL && all_diff; vnp2 = vnp2->next)
+      {
+        if (StringCmp (vnp1->data.ptrvalue, vnp2->data.ptrvalue) == 0)
+        {
+          all_diff = FALSE;
+        }
+      }
+    }
+  }
+  name_list = ValNodeFree (name_list);
+  return all_diff;
+}
+
+
+/* This function sets the default values for the organism description settings */
+NLM_EXTERN void InitOrganismDescriptionModifiers(OrganismDescriptionModifiersPtr odmp, SeqEntryPtr sep)
+{
+  if (odmp == NULL) {
+    return;
+  }
+  MemSet (odmp, 0, sizeof (OrganismDescriptionModifiers));
+  odmp->use_labels = TRUE;
+  odmp->max_mods = -99;
+  odmp->keep_paren = TRUE;
+  odmp->exclude_sp = ShouldExcludeSp (sep);
+  odmp->exclude_cf = FALSE;
+  odmp->exclude_aff = FALSE;
+  odmp->exclude_nr = FALSE;
+  odmp->include_country_extra = FALSE;
+  odmp->clone_isolate_HIV_rule_num = clone_isolate_HIV_rule_want_both;
+  odmp->use_modifiers = FALSE;
+  odmp->allow_semicolon_in_modifier = FALSE;
+  odmp->allow_mod_at_end_of_taxname = FALSE;
+
+}
+
+
+static ValNodePtr AddPlasmid (SubSourcePtr ssp_list, Boolean use_labels, Boolean allow_semicolon_in_modifier)
+{
+  Char         modifier_text [256];
+  ValNodePtr   strings = NULL;
+  Uint4        no_semicolon_len, label_len;
+
+  while (ssp_list != NULL) {
+    if (ssp_list->name != NULL && ssp_list->name[0] != 0
+        && ssp_list->subtype == SUBSRC_plasmid_name
+        && StringCmp (ssp_list->name, "unnamed") != 0)
+    {
+      AddModifierLabel (use_labels, FALSE, ssp_list->subtype, modifier_text);
+      if (modifier_text[0] != 0)
+      {
+        StringCat (modifier_text, " ");
+      }
+      label_len = StringLen (modifier_text);
+      if (allow_semicolon_in_modifier)
+      {
+        no_semicolon_len = StringLen (ssp_list->name);
+      }
+      else
+      {
+        no_semicolon_len = StringCSpn (ssp_list->name, ";");
+      }
+      if (no_semicolon_len > sizeof (modifier_text) - 1 - label_len)
+      {
+        no_semicolon_len = sizeof (modifier_text) - 1 - label_len;
+      }
+      StringNCat (modifier_text, ssp_list->name, no_semicolon_len);
+      modifier_text [ no_semicolon_len + label_len ] = 0;
+      ValNodeCopyStr( &strings, 0, modifier_text);
+    }
+    ssp_list = ssp_list->next;
+  }
+  return strings;
+}
+
+
 /* This function generates a string describing the organism based on the
  * modifiers selected and other organism description options.
  */
@@ -2407,7 +2570,7 @@ static CharPtr GetOrganismDescription (
 {
   Char         taxName [196];
   Char         modifier_text [256];
-  ValNodePtr   strings;
+  ValNodePtr   strings = NULL;
   BioSourcePtr biop;
   OrgModPtr    mod;
   SubSourcePtr ssp;
@@ -2422,8 +2585,6 @@ static CharPtr GetOrganismDescription (
   SeqIdPtr     sip;
   DbtagPtr     dbtag;
 
-  biop = NULL;
-  strings = NULL;
   taxName [0] = '\0';
 
   biop = GetBiopForBsp (bsp);
@@ -2435,9 +2596,19 @@ static CharPtr GetOrganismDescription (
 
   CleanUpTaxName (taxName, odmp->keep_paren);
 
+  if (biop->origin == ORG_MUT)
+  {
+    ValNodeAddStr (&strings, 0, StringSave ("Mutant"));
+  }
+
+  ValNodeAddStr (&strings, 0, StringSave (taxName));
+
   if (odmp->exclude_sp && IsSpName(taxName))
   {
-    return StringSave (taxName);
+    ValNodeLink (&strings, AddPlasmid (biop->subtype, odmp->use_labels, odmp->allow_semicolon_in_modifier));
+    org_desc = MergeValNodeStrings (strings, FALSE);
+    ValNodeFreeData (strings);
+    return org_desc;
   }
 
   if (odmp->exclude_cf)
@@ -2445,7 +2616,9 @@ static CharPtr GetOrganismDescription (
     cp = StringStr (taxName, " cf.");
     if (cp != NULL)
     {
-      return StringSave (taxName);
+      org_desc = MergeValNodeStrings (strings, FALSE);
+      ValNodeFreeData (strings);
+      return org_desc;
     }
   }
   
@@ -2454,7 +2627,9 @@ static CharPtr GetOrganismDescription (
     cp = StringStr (taxName, " aff.");
     if (cp != NULL)
     {
-      return StringSave (taxName);
+      org_desc = MergeValNodeStrings (strings, FALSE);
+      ValNodeFreeData (strings);
+      return org_desc;
     }
   }
   if (odmp->exclude_nr)
@@ -2462,16 +2637,12 @@ static CharPtr GetOrganismDescription (
     cp = StringStr (taxName, " nr.");
     if (cp != NULL)
     {
-      return StringSave (taxName);
-    }
+      org_desc = MergeValNodeStrings (strings, FALSE);
+      ValNodeFreeData (strings);
+      return org_desc;
   }
-  
-  if (biop->origin == ORG_MUT)
-  {
-    ValNodeAddStr (&strings, 0, StringSave ("Mutant"));
   }
 
-  ValNodeAddStr (&strings, 0, StringSave (taxName));
 
   if (HasTypeStrainComment (biop))
   {
@@ -2505,7 +2676,7 @@ static CharPtr GetOrganismDescription (
       {
         mod = mod->next;
       }
-      if ( UseOrgModifier (mod, taxName))
+      if ( UseOrgModifier (mod, taxName, odmp->allow_mod_at_end_of_taxname))
       {
         if (odmp->allow_semicolon_in_modifier) {
           no_semicolon_len = StringLen (mod->subname);
@@ -2611,6 +2782,7 @@ static CharPtr GetOrganismDescription (
           StringNCat (modifier_text, ssp->name, no_semicolon_len);
           modifier_text [ no_semicolon_len + label_len ] = 0;
         }
+
         ValNodeCopyStr( &strings, 0, modifier_text);
         if (odmp->max_mods != -99)
           odmp->max_mods --;
@@ -3107,6 +3279,31 @@ static Boolean LIBCALLBACK IsCDS (SeqFeatPtr sfp)
   return FALSE;
 }
 
+
+static Boolean LIBCALLBACK IsuORF (SeqFeatPtr sfp)
+{
+  SeqMgrFeatContext context;
+  CharPtr           cp;
+  Int4              len;
+
+  if (sfp == NULL) return FALSE;
+  if (sfp->data.choice == SEQFEAT_CDREGION 
+      && sfp->product != NULL
+      && SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL, sfp->idx.itemID, 0, sfp, &context) == sfp) {
+    cp = StringStr (context.label, "uORF");
+    if (cp != NULL && (cp == context.label || *(cp - 1) == ' ')
+        && (*(cp + 4) == 0 || isspace (*(cp + 4)) || isdigit (*(cp + 4)))) {
+      return TRUE;
+    }
+    if ((len = StringLen (context.label)) >= 14
+        && StringCmp (context.label + len - 14, "leader peptide") == 0) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+
 static Boolean LIBCALLBACK IsrRNA (
   SeqFeatPtr sfp
 )
@@ -3132,26 +3329,14 @@ static Boolean LIBCALLBACK IsncRNA (
   SeqFeatPtr sfp
 )
 {
-  RnaRefPtr rrp;
-
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return FALSE;
   if (sfp->idx.subtype == FEATDEF_scRNA 
       || sfp->idx.subtype == FEATDEF_snRNA 
       || sfp->idx.subtype == FEATDEF_snoRNA
       || sfp->idx.subtype == FEATDEF_ncRNA
-      || sfp->idx.subtype == FEATDEF_tmRNA)
-  {
-    return TRUE;
-  }
-  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-  if (rrp == NULL || rrp->type != 255 || rrp->ext.choice != 1)
-  {
-    return FALSE;
-  }
-  else if (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0
-      || StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0
-      || StringCmp (rrp->ext.value.ptrvalue, "misc_RNA") == 0
-      || IsStringInNcRNAClassList (rrp->ext.value.ptrvalue))
+      || sfp->idx.subtype == FEATDEF_tmRNA
+      || sfp->idx.subtype == FEATDEF_misc_RNA
+      || sfp->idx.subtype == FEATDEF_otherRNA)
   {
     return TRUE;
   }
@@ -3164,10 +3349,11 @@ static Boolean LIBCALLBACK IsncRNA (
 
 static CharPtr GetncRNAProduct (SeqFeatPtr sfp, Boolean use_ncrna_note)
 {
-  GBQualPtr gbq = NULL, q_class = NULL, q_product = NULL;
-  CharPtr product = NULL;
+  GBQualPtr gbq = NULL;
+  CharPtr product = NULL, q_class = NULL, q_product = NULL;
   CharPtr tmp_class = NULL, cp;
   RnaRefPtr rrp;
+  RNAGenPtr rgp;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA)
   {
@@ -3175,20 +3361,28 @@ static CharPtr GetncRNAProduct (SeqFeatPtr sfp, Boolean use_ncrna_note)
   }
   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
   
+  if (rrp->ext.choice == 3) {
+    rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+    if (rgp != NULL) {
+      q_class = rgp->_class;
+      q_product = rgp->product;
+    }
+  } else {  
   gbq = sfp->qual;
   while (gbq != NULL && q_product == NULL) {
     if (StringICmp (gbq->qual, "ncRNA_class") == 0
         && !StringHasNoText (gbq->val)) {
-      q_class = gbq;
+        q_class = gbq->val;
     } else if (StringICmp (gbq->qual, "product") == 0
         && !StringHasNoText (gbq->val)) {
-      q_product = gbq;
+        q_product = gbq->val;
     }
     gbq = gbq->next;
   }
+  }
   
   if (q_class != NULL) {
-    tmp_class = StringSave (q_class->val);
+    tmp_class = StringSave (q_class);
     cp = tmp_class;
     while (*cp != 0) {
       if (*cp == '_') {
@@ -3198,11 +3392,14 @@ static CharPtr GetncRNAProduct (SeqFeatPtr sfp, Boolean use_ncrna_note)
     }
   }
   if (q_product != NULL) {
-    if (tmp_class == NULL || StringStr (q_product->val, tmp_class) != NULL || StringCmp (tmp_class, "other") == 0) {
-      product = StringSave (q_product->val);
+    if (tmp_class == NULL 
+        || StringStr (q_product, tmp_class) != NULL 
+        || StringCmp (tmp_class, "other") == 0
+        || StringCmp (tmp_class, "RNase P RNA") == 0) {
+      product = StringSave (q_product);
     } else {
-      product = (CharPtr) MemNew (sizeof (Char) * (StringLen (q_product->val) + StringLen (tmp_class) + 2));
-      sprintf (product, "%s %s", q_product->val, tmp_class);
+      product = (CharPtr) MemNew (sizeof (Char) * (StringLen (q_product) + StringLen (tmp_class) + 2));
+      sprintf (product, "%s %s", q_product, tmp_class);
     }
   } else if (q_class != NULL) {
     if (use_ncrna_note && !StringHasNoText (sfp->comment)) {
@@ -3213,9 +3410,7 @@ static CharPtr GetncRNAProduct (SeqFeatPtr sfp, Boolean use_ncrna_note)
       product = StringSave (tmp_class);
     }
   } else if ((use_ncrna_note || 
-              (rrp != NULL && rrp->type == 255
-               && rrp->ext.choice == 1
-               && StringCmp (rrp->ext.value.ptrvalue, "misc_RNA") == 0))
+              (rrp != NULL && rrp->type == 10))
              && !StringHasNoText (sfp->comment)) {
     product = StringSave (sfp->comment);
   } else {
@@ -5225,7 +5420,7 @@ static void ExpandAltSplicedExons (
   BioseqPtr  bsp,
   DeflineFeatureRequestListPtr rp)
 {
-  ValNodePtr clause, rest_of_list, featlist, new_clause;
+  ValNodePtr clause, rest_of_list, featlist, new_clause = NULL;
   FeatureClausePtr fcp, new_fcp;
   SeqFeatPtr sfp;
 
@@ -5975,7 +6170,7 @@ static CharPtr GetGeneProtDescription
   else
   {
     if (gene_name != NULL)
-      sprintf (description, gene_name);
+      sprintf (description, "%s", gene_name);
   }
   if (protein_name != NULL) MemFree (protein_name);
   if (StringHasNoText (description)) {
@@ -7122,6 +7317,62 @@ GetFeatureClausesFromMiscRNATokens
 }
 
 
+static Boolean s_ItemNeedsGene (CharPtr item_str)
+{
+  Int4 item_len;
+
+  item_len = StringLen (item_str);
+  if (StringSearch (item_str, "RNA") != NULL 
+      && !((item_len > 4 && StringCmp (item_str + item_len - 4, "gene") == 0)
+      || (item_len > 5 && StringCmp (item_str + item_len - 5, "genes") == 0))) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+static CharPtr GetRegionDescription 
+(ValNodePtr token_list,
+ SeqFeatPtr misc_rna,
+ BioseqPtr bsp,
+ DeflineFeatureRequestListPtr rp)
+{
+  ValNodePtr vnp;
+  CharPtr desc, item_str;
+  Int4    len = 5, item_len;
+
+  if (token_list == NULL) {
+    return NULL;
+  } 
+
+  for (vnp = token_list; vnp != NULL; vnp = vnp->next) {
+    item_str = (CharPtr) vnp->data.ptrvalue;
+    item_len = StringLen (item_str);
+    len += item_len + 2;
+    if (s_ItemNeedsGene(item_str)) {
+      len += 5;
+    }
+  }
+
+  desc = (CharPtr) MemNew (sizeof (Char) * (len));
+  desc[0] = 0;
+  for (vnp = token_list; vnp != NULL; vnp = vnp->next) {
+    StringCat (desc, vnp->data.ptrvalue);
+    if (s_ItemNeedsGene(vnp->data.ptrvalue)) {
+      StringCat (desc, " gene");
+    }
+    if (vnp->next != NULL) {
+      StringCat (desc, ", ");
+      if (vnp->next->next == NULL) {
+        StringCat (desc, "and ");
+      }
+    }
+  }
+
+  return desc;
+}
+
+
 static ValNodePtr GetMiscRNAelements 
 ( SeqFeatPtr misc_rna,
   BioseqPtr  bsp,
@@ -7131,7 +7382,6 @@ static ValNodePtr GetMiscRNAelements
   ValNodePtr token_list, clause_list = NULL;
   FeatureClausePtr fcp;
 
-
   if (misc_rna == NULL) return NULL;
   buffer = GetProductName (misc_rna, bsp, rp);
   if (buffer == NULL) 
@@ -7153,7 +7403,8 @@ static ValNodePtr GetMiscRNAelements
     token_list = TokenListFromMiscRNAString (buffer + 12);
     if (token_list != NULL) {
       fcp = NewFeatureClause ( misc_rna, bsp, rp);
-      fcp->feature_label_data.description = StringSave (buffer + 12);
+      fcp->feature_label_data.description = GetRegionDescription (token_list, misc_rna, bsp, rp);
+      fcp->feature_label_data.typeword = StringSave ("");
       fcp->interval = StringSave ("region");
       ValNodeAddPointer (&clause_list, DEFLINE_CLAUSEPLUS, fcp);
     }
@@ -7314,7 +7565,12 @@ static void RenameMiscFeats (ValNodePtr clause_list, Uint1 biomol)
       fcp->feature_label_data.description [ name_len ] = 0;
       fcp->feature_label_data.typeword =
             MemFree (fcp->feature_label_data.typeword);
-      if (biomol == MOLECULE_TYPE_GENOMIC)
+      if (StringCmp (fcp->feature_label_data.description + name_len - 9, " sequence") == 0) 
+      {
+        fcp->feature_label_data.description[name_len - 9] = 0;
+        fcp->feature_label_data.typeword = StringSave ("sequence");
+      }
+      else if (biomol == MOLECULE_TYPE_GENOMIC)
       {
         fcp->feature_label_data.typeword = StringSave ("genomic sequence");
       }
@@ -7673,6 +7929,8 @@ static CharPtr organelleByGenome [] = {
   "proplastid",
   "",
   "hydrogenosome",
+  "",
+  "chromatophore",
   NULL,
 };
 
@@ -7741,6 +7999,7 @@ AddProductEnding
     case GENOME_leucoplast :
     case GENOME_proplastid :
     case GENOME_hydrogenosome :
+    case GENOME_chromatophore :
       sprintf (orgnelle, "; %s", organelleByGenome [biop->genome]);
       StringCat (str, orgnelle);
       break;
@@ -8345,7 +8604,6 @@ static Boolean SpecialHandlingForSpecialTechniques (
 {
   SeqDescPtr sdp;
   MolInfoPtr mip;
-  ValNodePtr vnp;
 
   if (bsp == NULL) return MOLECULE_TYPE_GENOMIC;
   sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, NULL);
@@ -8366,11 +8624,11 @@ static Boolean SpecialHandlingForSpecialTechniques (
       mip->tech == MI_TECH_sts ||
       mip->tech == MI_TECH_survey ||
       mip->tech == MI_TECH_wgs) {
-    vnp = ValNodeExtract (&(bsp->descr), Seq_descr_title);
-    if (vnp != NULL)
-      vnp = ValNodeFreeData (vnp);
+    sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, NULL);
+    if (sdp != NULL) {
     return TRUE;
   }
+  }
 
   return FALSE;
 }
@@ -8539,6 +8797,25 @@ static Boolean LIBCALLBACK ShouldRemove5UTR (
     return TRUE;
 }
 
+
+static Boolean LIBCALLBACK ShouldRemoveuORF (
+  SeqFeatPtr sfp,
+  FeatureClausePtr parent_fcp,
+  FeatureClausePtr this_fcp,
+  BioseqPtr bsp,
+  Boolean isLonely,
+  Boolean isRequested,
+  Boolean isSegment,
+  DeflineFeatureRequestListPtr rp
+)
+{
+  if (isLonely || isRequested)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+
 static Boolean LIBCALLBACK ShouldRemoveIntron (
   SeqFeatPtr sfp,
   FeatureClausePtr parent_fcp,
@@ -8585,6 +8862,36 @@ static Boolean LIBCALLBACK ShouldRemoveMobileElement
   return (!isLonely && !isRequested);
 }
 
+static Boolean LIBCALLBACK ShouldRemovencRNA
+( SeqFeatPtr sfp,
+  FeatureClausePtr parent_fcp,
+  FeatureClausePtr this_fcp,
+  BioseqPtr bsp,
+  Boolean isLonely,
+  Boolean isRequested,
+  Boolean isSegment,
+  DeflineFeatureRequestListPtr rp)
+{
+  Boolean rval = FALSE;
+  SeqMgrFeatContext context;
+  SeqFeatPtr precursor_rna;
+    Int2 cmpval;
+
+  if (isRequested) {
+    return FALSE;
+  }
+  for (precursor_rna = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_preRNA, &context);
+       precursor_rna != NULL && !rval;
+       precursor_rna = SeqMgrGetNextFeature (bsp, precursor_rna, 0, FEATDEF_preRNA, &context)) {
+    cmpval = SeqLocCompare (sfp->location, precursor_rna->location);
+    if (cmpval != SLC_NO_MATCH) {
+      rval = TRUE;
+    }
+  }
+  return rval;
+}
+
+
 static Boolean LIBCALLBACK ShouldRemoveGeneric 
 ( SeqFeatPtr sfp,
   FeatureClausePtr parent_fcp,
@@ -8670,12 +8977,14 @@ static RemovableItemGlobalData remove_items[] = {
   { IsIntron, ShouldRemoveIntron, "Introns" },
   { Is5UTR, ShouldRemove5UTR, "5' UTRs" },
   { Is3UTR, ShouldRemove3UTR, "3' UTRs" },
+  { IsuORF, ShouldRemoveuORF, "uORFs"},
   { IsCDS,  ShouldRemoveCDS, "CDSs" },
   { IsPromoter, ShouldRemovePromoter, "Promoters:" },
   { IsLTR, ShouldRemoveLTR, "LTRs" },
   { IsNoncodingProductFeat,  ShouldRemoveNoncodingProductFeat, "Misc feats with comments:" },
   { IsRemovableMobileElement, ShouldRemoveMobileElement, "Optional Mobile Element" },
-  { IsPrecursorRNA, ShouldRemovePrecursorRNA, "Precursor RNAs" }
+  { IsPrecursorRNA, ShouldRemovePrecursorRNA, "Precursor RNAs" },
+  { IsncRNA, ShouldRemovencRNA, "ncRNAs that overlap precursor RNAs"}
 };
 
 
@@ -8707,6 +9016,17 @@ NLM_EXTERN void InitFeatureRequests (
   feature_requests->use_ncrna_note = FALSE;
 }
 
+
+NLM_EXTERN DeflineFeatureRequestListPtr FreeDeflineFeatureRequestList (DeflineFeatureRequestListPtr feature_requests)
+{
+  if (feature_requests != NULL) {
+    feature_requests->suppressed_feature_list = ValNodeFree (feature_requests->suppressed_feature_list);
+    feature_requests = MemFree (feature_requests);
+  }
+  return feature_requests;
+}
+
+
 static Boolean RemoveCondition (
   SeqFeatPtr sfp,
   FeatureClausePtr parent_fcp,
@@ -9409,12 +9729,12 @@ static void ConsolidateClauses (
   ValNodePtr       vnp;
   FeatureClausePtr fcp;
   FeatureClausePtr last_cds_fcp;
-  CharPtr          last_desc, new_desc;
+  CharPtr          last_desc = NULL, new_desc;
   Boolean          last_partial, new_partial, partial3, partial5;
+  SeqLocPtr        new_loc;
 
   if (list == NULL || *list == NULL) return;
   last_cds_fcp = NULL;
-  last_desc = NULL;
   for (vnp = *list; vnp != NULL; vnp = vnp->next)
   {
     if (vnp->choice != DEFLINE_CLAUSEPLUS
@@ -9476,8 +9796,10 @@ static void ConsolidateClauses (
         RemoveRedundantGeneFeatureFromConsolidatedClause (last_cds_fcp);
         fcp->featlist = NULL;
         fcp->delete_me = TRUE;
-        last_cds_fcp->slp = SeqLocMerge (bsp, last_cds_fcp->slp, fcp->slp,
+        new_loc = SeqLocMerge (bsp, last_cds_fcp->slp, fcp->slp,
                                          FALSE, TRUE, FALSE);
+        last_cds_fcp->slp = SeqLocFree (last_cds_fcp->slp);
+        last_cds_fcp->slp = new_loc;
         /* if we have two clauses that are really identical instead of
          * just sharing a "prefix", make the description plural
          */
@@ -9505,6 +9827,7 @@ static void ConsolidateClauses (
       }
     }  
   }   
+  last_desc = MemFree (last_desc);
   if (delete_now) 
   {
     DeleteFeatureClauses (list);
@@ -9529,7 +9852,8 @@ static void CountUnknownGenes (
   {
     if (vnp->choice == DEFLINE_CLAUSEPLUS
       && (fcp = vnp->data.ptrvalue) != NULL
-      && ! fcp->is_unknown) 
+      && ! fcp->is_unknown
+      && fcp->grp == NULL) 
     {
       CountUnknownGenes (&(fcp->featlist), bsp, rp);
       gene_name = GetGeneProtDescription (fcp, bsp, rp);
@@ -9557,6 +9881,7 @@ static void CountUnknownGenes (
         num_unknown_genes ++;
         fcp->delete_me = TRUE;
       }
+      gene_name = MemFree (gene_name);
     }
     vnp = vnp->next;
   }
@@ -9571,7 +9896,7 @@ static void CountUnknownGenes (
   }
 }
 
-static void ReplaceDefinitionLine (
+NLM_EXTERN void ReplaceDefinitionLine (
   SeqEntryPtr sep,
   CharPtr defline
 )
@@ -10147,6 +10472,116 @@ static Boolean IsInGenProdSet (BioseqPtr bsp)
   }
 }
 
+
+NLM_EXTERN CharPtr BuildNonFeatureListClause (BioseqPtr bsp, DefLineType feature_list_type)
+{
+  CharPtr      str = NULL;
+  BioSourcePtr biop;
+  SeqDescrPtr  sdp;
+  SeqMgrDescContext context;
+  Char         ending_str [200];
+  CharPtr      mol_name;
+  MolInfoPtr   molinfo;
+
+  if (feature_list_type == DEFLINE_COMPLETE_SEQUENCE)
+  {
+    str = StringSave (", complete sequence.");
+  }
+  else if (feature_list_type == DEFLINE_COMPLETE_GENOME)
+  {
+    ending_str [0] = 0;
+    biop = GetBiopForBsp (bsp);
+    if (biop != NULL)
+    {
+      switch (biop->genome) {
+        case GENOME_macronuclear :
+          sprintf (ending_str, "macronuclear");
+          break;
+        case GENOME_nucleomorph :
+          sprintf (ending_str, "nucleomorph");
+          break;
+        case GENOME_mitochondrion :
+          sprintf (ending_str, "mitochondrion");
+          break;
+        case GENOME_apicoplast :
+        case GENOME_chloroplast :
+        case GENOME_chromoplast :
+        case GENOME_kinetoplast :
+        case GENOME_plastid :
+        case GENOME_cyanelle :
+        case GENOME_leucoplast :
+        case GENOME_proplastid :
+        case GENOME_hydrogenosome :
+        case GENOME_chromatophore :
+          sprintf (ending_str, "%s", organelleByGenome [biop->genome]);
+          break;
+      }
+    }
+    StringCat (ending_str, ", complete genome.");
+    str = StringSave (ending_str);
+  }
+  else if (feature_list_type == DEFLINE_PARTIAL_GENOME)
+  {
+    ending_str [0] = 0;
+    biop = GetBiopForBsp (bsp);
+    if (biop != NULL)
+    {
+      switch (biop->genome) {
+        case GENOME_macronuclear :
+          sprintf (ending_str, "macronuclear");
+          break;
+        case GENOME_nucleomorph :
+          sprintf (ending_str, "nucleomorph");
+          break;
+        case GENOME_mitochondrion :
+          sprintf (ending_str, "mitochondrion");
+          break;
+        case GENOME_apicoplast :
+        case GENOME_chloroplast :
+        case GENOME_chromoplast :
+        case GENOME_kinetoplast :
+        case GENOME_plastid :
+        case GENOME_cyanelle :
+        case GENOME_leucoplast :
+        case GENOME_proplastid :
+        case GENOME_hydrogenosome :
+        case GENOME_chromatophore :
+          sprintf (ending_str, "%s", organelleByGenome [biop->genome]);
+          break;
+      }
+    }
+    StringCat (ending_str, ", partial genome.");
+    str = StringSave (ending_str);
+  }
+  else if (feature_list_type == DEFLINE_SEQUENCE) 
+  {
+    sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
+    if (sdp == NULL || (molinfo = sdp->data.ptrvalue) == NULL) 
+    {
+      mol_name = NULL;
+    } 
+    else 
+    {
+      mol_name = BiomolNameFromBiomol (molinfo->biomol);
+    }
+    if (mol_name == NULL) 
+    {
+      str = StringSave (" sequence");
+    } 
+    else 
+    {
+      str = (CharPtr) MemNew (sizeof (Char) * (StringLen (mol_name) + 10));
+      sprintf (str, "%s sequence", mol_name);
+    }
+  }
+  else
+  {
+    str = StringSave ("");
+  }
+  return str;
+}
+
+
 /* NOTE: under some circumstances this function will create features that
  * are marked for deletion, so DeleteMarkedObjects should always be called
  * at some later point.
@@ -10167,9 +10602,7 @@ static CharPtr BuildFeatureClauses (
   ValNodePtr   strings = NULL;
   ValNodePtr   clause;
   CharPtr      str = NULL;
-  Char         ending_str [200];
   ValNodePtr   tmp_feat_list;
-  BioSourcePtr biop;
 
   if ((feature_requests->feature_list_type == DEFLINE_USE_FEATURES
        || (IsmRNASequence(bsp) && IsInGenProdSet(bsp)))
@@ -10278,46 +10711,8 @@ static CharPtr BuildFeatureClauses (
                        product_flag, alternate_splice_flag);
     str = MergeValNodeStrings (strings, FALSE);
 	  ValNodeFreeData (strings);
-  }
-  else if (feature_requests->feature_list_type == DEFLINE_COMPLETE_SEQUENCE)
-  {
-    str = StringSave (", complete sequence.");
-  }
-  else if (feature_requests->feature_list_type == DEFLINE_COMPLETE_GENOME)
-  {
-    ending_str [0] = 0;
-    biop = GetBiopForBsp (bsp);
-    if (biop != NULL)
-    {
-      switch (biop->genome) {
-        case GENOME_macronuclear :
-          sprintf (ending_str, "macronuclear");
-          break;
-        case GENOME_nucleomorph :
-          sprintf (ending_str, "nucleomorph");
-          break;
-        case GENOME_mitochondrion :
-          sprintf (ending_str, "mitochondrion");
-          break;
-        case GENOME_apicoplast :
-        case GENOME_chloroplast :
-        case GENOME_chromoplast :
-        case GENOME_kinetoplast :
-        case GENOME_plastid :
-        case GENOME_cyanelle :
-        case GENOME_leucoplast :
-        case GENOME_proplastid :
-        case GENOME_hydrogenosome :
-          sprintf (ending_str, "%s", organelleByGenome [biop->genome]);
-          break;
-      }
-    }
-    StringCat (ending_str, ", complete genome.");
-    str = StringSave (ending_str);
-  }
-  else
-  {
-    str = StringSave ("");
+  } else {
+    str = BuildNonFeatureListClause(bsp, feature_requests->feature_list_type);
   }
   
   return str;
@@ -10362,8 +10757,9 @@ static Int2 GetProductFlagFromCDSProductNames (BioseqPtr bsp)
   return product_flag;
 }
 
-NLM_EXTERN void BuildDefLineFeatClauseList (
-  SeqEntryPtr sep,
+
+static void BuildFeatClauseListForSegSet (
+  BioseqPtr bsp,
   Uint2 entityID,
   DeflineFeatureRequestList PNTR feature_requests,
   Int2 product_flag,
@@ -10372,46 +10768,10 @@ NLM_EXTERN void BuildDefLineFeatClauseList (
   ValNodePtr PNTR list
 )
 {
-  BioseqSetPtr    bssp;
-  BioseqPtr    bsp;
-  ValNodePtr    head;
-  Uint1      molecule_type;
-  SeqEntryPtr   nsep;
   SegmentDefLineFeatureClauseData sdld;
   DefLineFeatClausePtr deflist;
   ValNodePtr    vnp;
 
-  if (sep == NULL || list == NULL) return;
-
-  if ( IS_Bioseq_set (sep))
-  {
-    bssp = (BioseqSetPtr) sep->data.ptrvalue;
-    if (bssp == NULL) return;
-    if ( bssp->_class == 7 || IsPopPhyEtcSet (bssp->_class)
-        || bssp->_class == BioseqseqSet_class_gen_prod_set
-        || bssp->_class == BioseqseqSet_class_not_set)
-    {
-      for (sep = bssp->seq_set; sep != NULL; sep = sep->next)
-      {
-        BuildDefLineFeatClauseList (sep, entityID, feature_requests,
-                                    product_flag, alternate_splice_flag,
-                                    gene_cluster_opp_strand, list);
-      }
-      return;
-    }
-  }
-    
-  nsep = FindNucSeqEntry (sep);
-  if (nsep != NULL)
-  {
-    bsp = (BioseqPtr) nsep->data.ptrvalue;
-    if ( SpecialHandlingForSpecialTechniques (bsp)) 
-    {
-      return;
-    }
-    if (bsp != NULL && bsp->repr == Seq_repr_seg &&
-      bsp->seq_ext != NULL && bsp->seq_ext_type == 1) 
-    {
       /* get default product flag if necessary */
 	  if (product_flag == -1 || product_flag == DEFAULT_ORGANELLE_CLAUSE) {
 	    product_flag = GetProductFlagFromCDSProductNames (bsp);
@@ -10448,9 +10808,38 @@ NLM_EXTERN void BuildDefLineFeatClauseList (
       if (*list == NULL) *list = vnp;
       vnp->data.ptrvalue = deflist;
       FreeListElement (sdld.parent_feature_list);
-      DeleteMarkedObjects (entityID, 0, NULL);
+}
+
+static void BuildOneFeatClauseList (
+  SeqEntryPtr sep,
+  Uint2 entityID,
+  DeflineFeatureRequestList PNTR feature_requests,
+  Int2 product_flag,
+  Boolean alternate_splice_flag,
+  Boolean gene_cluster_opp_strand,
+  ValNodePtr PNTR list
+)
+{
+  BioseqPtr    bsp;
+  ValNodePtr    head;
+  Uint1      molecule_type;
+  SeqEntryPtr   nsep;
+  DefLineFeatClausePtr deflist;
+  ValNodePtr    vnp;
+
+  nsep = FindNucSeqEntry (sep);
+  if (nsep != NULL)
+  {
+    bsp = (BioseqPtr) nsep->data.ptrvalue;
+    if ( SpecialHandlingForSpecialTechniques (bsp)) 
+    {
       return;
     }
+    if (bsp != NULL && bsp->repr == Seq_repr_seg &&
+      bsp->seq_ext != NULL && bsp->seq_ext_type == 1) 
+    {
+      BuildFeatClauseListForSegSet (bsp, entityID, feature_requests, product_flag, alternate_splice_flag, gene_cluster_opp_strand, list);
+    }
   }
 
   if (nsep != NULL && nsep != sep)
@@ -10493,6 +10882,53 @@ NLM_EXTERN void BuildDefLineFeatClauseList (
   if (*list == NULL) *list = vnp;
   vnp->data.ptrvalue = deflist;
   FreeListElement (head);
+}
+
+
+static void RecurseForBuildingFeatClauseLists(
+  SeqEntryPtr sep,
+  Uint2 entityID,
+  DeflineFeatureRequestList PNTR feature_requests,
+  Int2 product_flag,
+  Boolean alternate_splice_flag,
+  Boolean gene_cluster_opp_strand,
+  ValNodePtr PNTR list
+)
+{
+  BioseqSetPtr    bssp;
+
+  if ( IS_Bioseq_set (sep))
+  {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    if (bssp == NULL) return;
+    if ( bssp->_class == 7 || IsPopPhyEtcSet (bssp->_class)
+        || bssp->_class == BioseqseqSet_class_gen_prod_set
+        || bssp->_class == BioseqseqSet_class_not_set)
+    {
+      for (sep = bssp->seq_set; sep != NULL; sep = sep->next)
+      {
+        RecurseForBuildingFeatClauseLists (sep, entityID, feature_requests,
+                                    product_flag, alternate_splice_flag,
+                                    gene_cluster_opp_strand, list);
+      }
+      return;
+    }
+  }
+  BuildOneFeatClauseList (sep, entityID, feature_requests, product_flag, alternate_splice_flag, gene_cluster_opp_strand, list);
+}
+
+
+NLM_EXTERN void BuildDefLineFeatClauseList (
+  SeqEntryPtr sep,
+  Uint2 entityID,
+  DeflineFeatureRequestList PNTR feature_requests,
+  Int2 product_flag,
+  Boolean alternate_splice_flag,
+  Boolean gene_cluster_opp_strand,
+  ValNodePtr PNTR list
+)
+{
+  RecurseForBuildingFeatClauseLists (sep, entityID, feature_requests, product_flag, alternate_splice_flag, gene_cluster_opp_strand, list);
   DeleteMarkedObjects (entityID, 0, NULL);
 }
 
@@ -10588,7 +11024,7 @@ NLM_EXTERN Boolean AreFeatureClausesUnique (ValNodePtr list)
 }
 
 
-static CharPtr GetKeywordPrefix (SeqEntryPtr sep)
+NLM_EXTERN CharPtr GetKeywordPrefix (SeqEntryPtr sep)
 {
   ValNodePtr vnp;
   GBBlockPtr gbp;
@@ -10623,48 +11059,1165 @@ static CharPtr GetKeywordPrefix (SeqEntryPtr sep)
 	return "";
 }
 
-NLM_EXTERN void BuildDefinitionLinesFromFeatureClauseLists (
-  ValNodePtr list,
+
+NLM_EXTERN CharPtr 
+BuildOneDefinitionLine 
+(SeqEntryPtr sep, 
+ BioseqPtr   bsp,
+ CharPtr  featclause_list, 
   ModifierItemLocalPtr modList,
   ValNodePtr modifier_indices,
-  OrganismDescriptionModifiersPtr odmp
-)
+  OrganismDescriptionModifiersPtr odmp)
 {
-  ValNodePtr vnp;
-  DefLineFeatClausePtr defline_featclause;
   CharPtr    org_desc, tmp_str, keyword_prefix;
 
-  for (vnp = list; vnp != NULL; vnp = vnp->next)
-  {
-    if (vnp->data.ptrvalue != NULL)
-    {
-      defline_featclause = vnp->data.ptrvalue;
-      
-      keyword_prefix = GetKeywordPrefix (defline_featclause->sep);
+  keyword_prefix = GetKeywordPrefix (sep);
       
-      org_desc = GetOrganismDescription (defline_featclause->bsp,
-                                         modList, modifier_indices, odmp);
+  org_desc = GetOrganismDescription (bsp, modList, modifier_indices, odmp);
       tmp_str = (CharPtr) MemNew (StringLen (keyword_prefix) 
                                   + StringLen (org_desc) 
-                                  + StringLen (defline_featclause->clauselist) + 2);
-      if (tmp_str == NULL) return;
+                              + StringLen (featclause_list) + 2);
+  if (tmp_str == NULL) return NULL;
       tmp_str [0] = 0;
       if (keyword_prefix != NULL)
       {
         StringCat (tmp_str, keyword_prefix);
       }
       StringCat (tmp_str, org_desc);
-      if (defline_featclause->clauselist != NULL
-        && defline_featclause->clauselist [0] != ','
-        && defline_featclause->clauselist [0] != '.'
-        && defline_featclause->clauselist [0] != 0)
+  MemFree (org_desc);
+  if (featclause_list != NULL
+    && featclause_list [0] != ','
+    && featclause_list [0] != '.'
+    && featclause_list [0] != 0)
       {
         StringCat (tmp_str, " ");
       }
-      StringCat (tmp_str, defline_featclause->clauselist);
+  StringCat (tmp_str, featclause_list);
       tmp_str [0] = toupper (tmp_str [0]);
+
+  return tmp_str;
+}
+
+
+typedef struct deflineclauseoptions {
+  DeflineFeatureRequestList feature_requests;
+  Int2 product_flag;
+  Boolean alternate_splice_flag;
+  Boolean gene_cluster_opp_strand;
+} DefLineClauseOptions, PNTR DefLineClauseOptionsPtr;
+
+static DefLineClauseOptionsPtr DefLineClauseOptionsNew (void)
+{
+  DefLineClauseOptionsPtr clause_options;
+
+  clause_options = MemNew (sizeof (DefLineClauseOptions));
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->product_flag = DEFAULT_ORGANELLE_CLAUSE;
+  clause_options->alternate_splice_flag = FALSE;
+  clause_options->gene_cluster_opp_strand = FALSE;
+
+  return clause_options;
+}
+
+
+static DefLineClauseOptionsPtr DefLineClauseOptionsFree (DefLineClauseOptionsPtr clause_options)
+{
+  if (clause_options != NULL) {
+    clause_options = MemFree (clause_options);
+  }
+  return clause_options;
+}
+
+
+typedef void (*Nlm_SetFeatureRequestsProc) PROTO ((DefLineClauseOptionsPtr));
+
+static void DefaultClauseOptions (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->product_flag = DEFAULT_ORGANELLE_CLAUSE;
+  clause_options->alternate_splice_flag = FALSE;
+  clause_options->gene_cluster_opp_strand = FALSE;
+}
+
+
+static void CompleteSequenceClauseOptions (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->feature_requests.feature_list_type = DEFLINE_COMPLETE_SEQUENCE;
+  clause_options->product_flag = DEFAULT_ORGANELLE_CLAUSE;
+  clause_options->alternate_splice_flag = FALSE;
+  clause_options->gene_cluster_opp_strand = FALSE;
+}
+
+
+static void CompleteGenomeClauseOptions (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->feature_requests.feature_list_type = DEFLINE_COMPLETE_GENOME;
+  clause_options->product_flag = DEFAULT_ORGANELLE_CLAUSE;
+  clause_options->alternate_splice_flag = FALSE;
+  clause_options->gene_cluster_opp_strand = FALSE;
+}
+
+
+static void SequenceClauseOptions (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->feature_requests.feature_list_type = DEFLINE_SEQUENCE;
+  clause_options->product_flag = DEFAULT_ORGANELLE_CLAUSE;
+  clause_options->alternate_splice_flag = FALSE;
+  clause_options->gene_cluster_opp_strand = FALSE;
+}
+
+
+static void MiscFeatNonCodingOptions (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  
+  clause_options->feature_requests.keep_items[RemovableNoncodingProductFeat] = TRUE;
+}
+
+
+static void MiscFeatSemicolonOptions (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  
+  clause_options->feature_requests.keep_items[RemovableNoncodingProductFeat] = TRUE;
+  clause_options->feature_requests.misc_feat_parse_rule = 1;
+ 
+}
+
+
+static void MitochondrialProductClauseOptions (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->product_flag = 2;
+  clause_options->alternate_splice_flag = FALSE;
+  clause_options->gene_cluster_opp_strand = FALSE;
+}
+
+
+static void RequestPromoterAndExon (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->feature_requests.keep_items[RemovableExon] = TRUE;
+  clause_options->feature_requests.keep_items[RemovablePromoter] = TRUE;
+}
+
+
+static void RequestIntronAndExon (DefLineClauseOptionsPtr clause_options)
+{
+  InitFeatureRequests (&(clause_options->feature_requests));
+  clause_options->feature_requests.keep_items[RemovableExon] = TRUE;
+  clause_options->feature_requests.keep_items[RemovableIntron] = TRUE;
+}
+
+
+static Nlm_SetFeatureRequestsProc ClauseOptionSetList[] = {
+  DefaultClauseOptions,
+  RequestPromoterAndExon,
+  RequestIntronAndExon,
+  CompleteSequenceClauseOptions,
+  CompleteGenomeClauseOptions,
+  SequenceClauseOptions,
+  MiscFeatNonCodingOptions,
+  MiscFeatSemicolonOptions,
+  MitochondrialProductClauseOptions,
+  NULL };
+
+typedef Boolean (*Nlm_SetOrgModifiersProc) PROTO ((OrganismDescriptionModifiersPtr, ValNodePtr PNTR, ModifierItemLocalPtr));
+
+
+static void DefaultOrgOptions (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list)
+{
+  odmp->use_modifiers = TRUE;
+  odmp->use_labels = TRUE;
+}
+
+
+static Boolean SubstituteMod (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available, Int4 mod1, Int4 mod2) 
+{
+  ValNodePtr vnp;
+  Boolean has_one = FALSE;
+  Boolean has_two = FALSE;
+  Boolean rval = FALSE;
+
+  if (mod_list == NULL || *mod_list == NULL || available == NULL || !available[mod2].any_present) {
+    return FALSE;
+  }
+  DefaultOrgOptions(odmp, mod_list);
+
+  for (vnp = *mod_list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->data.intvalue == mod1) {
+      has_one = TRUE;
+    } else if (vnp->data.intvalue == mod2) {
+      has_two = TRUE;
+    }
+  }
+
+  if (has_one && !has_two) {
+    for (vnp = *mod_list; vnp != NULL; vnp = vnp->next) {
+      if (vnp->data.intvalue == mod1) {
+        vnp->data.intvalue = mod2;
+        rval = TRUE;
+      }
+    }
+  }
+  return rval;
+}
+
+
+static Boolean IsolateInsteadOfClone (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available) 
+{
+  return SubstituteMod (odmp, mod_list, available, DEFLINE_POS_Clone, DEFLINE_POS_Isolate);
+} 
+
+
+static Boolean  HaplotypeInsteadOfVoucher (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available) 
+{
+  return SubstituteMod (odmp, mod_list, available, DEFLINE_POS_Specimen_voucher, DEFLINE_POS_Haplotype);
+} 
+
+
+static Boolean  VoucherInsteadOfIsolate (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available) 
+{
+  return SubstituteMod (odmp, mod_list, available, DEFLINE_POS_Isolate, DEFLINE_POS_Specimen_voucher);
+} 
+
+
+static Boolean UseNone (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available)
+{
+  if (mod_list == NULL || *mod_list == NULL) {
+    return FALSE;
+  }
+
+  DefaultOrgOptions(odmp, mod_list);
+  odmp->use_modifiers = FALSE;
+  return TRUE;
+}
+
+
+static Boolean AddOneAdjustmentMod (ValNodePtr PNTR mod_list, ModifierItemLocalPtr available, Int4 specific)
+{
+  Boolean already_has_sv = FALSE;
+  Boolean rval = FALSE;
+  ValNodePtr vnp, vnp_new;
+
+  if (mod_list == NULL || available == NULL || !available[specific].any_present) {
+    return FALSE;
+  }
+
+  for (vnp = *mod_list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->data.intvalue == specific) {
+      already_has_sv = TRUE;
+    }
+  }
+  if (!already_has_sv) {
+    vnp_new = ValNodeNew (NULL);
+    vnp_new->choice = 0;
+    vnp_new->data.intvalue = specific;
+    vnp_new->next = *mod_list;
+    *mod_list = vnp_new;
+    rval = TRUE;
+  }
+  return rval;
+}
+
+
+static Boolean UseOneSpecific (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available, Int4 specific)
+{
+  DefaultOrgOptions(odmp, mod_list);
+  return AddOneAdjustmentMod (mod_list, available, specific);
+}
+
+
+static Boolean UseStrain (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available)
+{
+  return UseOneSpecific (odmp, mod_list, available, DEFLINE_POS_Strain);
+}
+
+
+static Boolean UseSpecimenVoucher (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available)
+{
+  return UseOneSpecific (odmp, mod_list, available, DEFLINE_POS_Specimen_voucher);
+}
+
+
+static Boolean UseHaplotype (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available)
+{
+  return UseOneSpecific (odmp, mod_list, available, DEFLINE_POS_Haplotype);
+}
+
+
+static Boolean UseAutoDefId (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available)
+{
+  Int4 index;
+  ValNodePtr vnp;
+  Boolean found, changed = FALSE;
+  ModifierItemLocalPtr cpy;
+
+  if (mod_list == NULL) {
+    return FALSE;
+  }
+
+  cpy = MemNew (NumDefLineModifiers () * sizeof (ModifierItemLocalData));
+  if (cpy == NULL) return FALSE;
+  MemCpy (cpy, available, NumDefLineModifiers () * sizeof (ModifierItemLocalData));
+
+  DefaultOrgOptions(odmp, mod_list);
+  SetAutoDefIDModifiers (cpy);
+  for (index = 0; index < NumDefLineModifiers(); index++) {
+    if (cpy[index].required) {
+      found = FALSE;
+      if (*mod_list != NULL) {
+        for (vnp = *mod_list; vnp != NULL && !found; vnp = vnp->next) {
+          if (vnp->data.intvalue == index) {
+            found = TRUE;
+          }
+        }
+      }
+      if (!found) {
+        ValNodeAddInt (mod_list, 0, index);
+        changed = TRUE;
+      }
+    }
+  }
+  cpy = MemFree (cpy);
+  
+  return changed;
+}
+
+
+static Boolean DontExcludeSp (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available)
+{
+  if (odmp == NULL || !odmp->exclude_sp) {
+    return FALSE;
+  }
+  DefaultOrgOptions(odmp, mod_list);
+  odmp->exclude_sp = FALSE;
+  return TRUE;
+}
+
+
+static Boolean UseCountryAndIsolate (OrganismDescriptionModifiersPtr odmp, ValNodePtr PNTR mod_list, ModifierItemLocalPtr available)
+{
+  Boolean add_country, add_isolate;
+  Boolean rval = FALSE;
+
+  DefaultOrgOptions(odmp, mod_list);
+  add_country =  AddOneAdjustmentMod (mod_list, available, DEFLINE_POS_Country);
+  add_isolate = AddOneAdjustmentMod (mod_list, available, DEFLINE_POS_Isolate);
+  if (add_country || add_isolate) {
+    rval = TRUE;
+  }
+  return rval;
+}
+
+
+static Nlm_SetOrgModifiersProc OrgModifiersSetList[] = {
+  IsolateInsteadOfClone,
+  UseNone,
+  UseStrain,
+  UseSpecimenVoucher,
+  UseHaplotype,
+  HaplotypeInsteadOfVoucher,
+  VoucherInsteadOfIsolate,
+  UseAutoDefId,
+  DontExcludeSp,
+  UseCountryAndIsolate,
+  NULL };
+
+
+typedef Boolean (*Nlm_CompareDeflinesProc) PROTO ((CharPtr, CharPtr));
+
+static Boolean MatchExceptOldProduct (CharPtr old_str, CharPtr new_str)
+{
+  Int4 old_len, new_len, pattern_len, new_pattern_len, organelle_len, i;
+  CharPtr pattern_fmt = "%s %s gene%s for %s product%s.";
+  CharPtr other_pattern_fmt = "%s %s gene%s for %s RNA.";
+  CharPtr new_pattern_fmt = "; %s.";
+  CharPtr pattern, new_pattern;
+  Boolean rval = FALSE;
+  CharPtr delimiters[] = {";", ",", NULL};
+  CharPtr plural[] = {"", "s", NULL};
+  Int4 j, k;
+
+  old_len = StringLen (old_str);
+  new_len = StringLen (new_str);
+
+  for (i = 2; organelleByGenome[i] != NULL && !rval; i++) {
+    if (StringHasNoText (organelleByGenome[i])) {
+      continue;
+    }
+    organelle_len = StringLen (organelleByGenome[i]);
+    new_pattern = (CharPtr) MemNew (sizeof (Char) * (StringLen (new_pattern_fmt) + organelle_len));
+    sprintf (new_pattern, new_pattern_fmt, organelleByGenome[i]);
+    new_pattern_len = StringLen (new_pattern);
+
+    if (new_len > new_pattern_len
+        && StringCmp (new_str + new_len - new_pattern_len, new_pattern) == 0) {
+      pattern = (CharPtr) MemNew (sizeof (Char) * (StringLen (pattern_fmt) + (2 * organelle_len)));
+      for (j = 0; delimiters[j] != NULL; j++) {
+        for (k = 0; plural[k] != NULL; k++) {
+          /* first pattern */
+          sprintf (pattern, pattern_fmt, delimiters[j], organelleByGenome[i], plural[k], organelleByGenome[i], plural[k]);
+          pattern_len = StringLen (pattern);     
+          if (old_len > pattern_len && new_len > organelle_len + 2
+              && StringCmp (old_str + old_len - pattern_len, pattern) == 0) {
+            rval = TRUE;
+          }
+          /* other pattern */
+          sprintf (pattern, other_pattern_fmt, delimiters[j], organelleByGenome[i], plural[k], organelleByGenome[i]);
+          pattern_len = StringLen (pattern);     
+          if (old_len > pattern_len && new_len > organelle_len + 2
+              && StringCmp (old_str + old_len - pattern_len, pattern) == 0) {
+            rval = TRUE;
+          }
+        }
+      }
+
+      pattern = MemFree (pattern);
+    }   
+    new_pattern = MemFree (new_pattern);
+  }
+  return rval;
+}
+
+
+static Boolean NoSequenceForIntron (CharPtr old_str, CharPtr new_str)
+{
+  Int4 old_len, new_len;
+
+  old_len = StringLen (old_str);
+  new_len = StringLen (new_str);
+  
+  if (new_len < old_len && StringNCmp (old_str, new_str, new_len - 1) == 0
+      && (StringCmp (old_str + new_len - 7, "intron, partial sequence.") == 0
+          || StringCmp (old_str + new_len - 7, "intron, complete sequence.") == 0)) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+
+}
+
+
+static Boolean SkipPair (CharPtr PNTR a, CharPtr PNTR b, CharPtr a_start, CharPtr b_start, CharPtr val1, CharPtr val2)
+{
+  Int4 len1, len2;
+  Char end1, end2;
+  Boolean rval = FALSE;
+
+  if (a == NULL || *a == NULL
+      || b == NULL || *b == NULL 
+      || a_start == NULL || b_start == NULL
+      || val1 == NULL || val2 == NULL) {
+    return FALSE;
+  }
+  len1 = StringLen (val1);
+  len2 = StringLen (val2);
+
+  end1 = *(val1 + len1 - 1);
+  end2 = *(val2 + len2 - 1);
+
+  if (**a == end1 && **b == end2 && *a - a_start > len1 && *b - b_start > len2
+            && StringNCmp (*a - len1 + 1, val1, len1) == 0
+            && StringNCmp (*b - len2 + 1, val2, len2) == 0) {
+    *a -= len1 - 1;
+    *b -= len2 - 1;
+    rval = TRUE;
+  } else if (**a == end2 && **b == end1 && *a - a_start > len2 && *b - b_start > len2
+              && StringNCmp (*a - len2 + 1, val2, len2) == 0
+              && StringNCmp (*b - len1 + 1, val1, len1) == 0) {
+    *a -= len2 - 1;
+    *b -= len1 - 1;
+    rval = TRUE;
+  }
+  return rval;
+}
+
+
+static Boolean AdjustForSpace (CharPtr PNTR a, CharPtr PNTR b, CharPtr a_start, CharPtr b_start) 
+{
+  Boolean rval = FALSE;
+
+  if (a == NULL || *a == NULL 
+      || b == NULL || *b == NULL) {
+    rval = FALSE;
+  } else if (**a == ' ' && *a > a_start && *((*a) - 1) == **b) {
+    (*a)--;
+    rval = TRUE;
+  } else if (**b == ' ' && *b > b_start && *((*b) - 1) == **a) {
+    (*b)--;
+    rval = TRUE;
+  }
+  return rval;
+}
+
+
+static Boolean AdjustForCharBeforePhrase (CharPtr PNTR a, CharPtr PNTR b, CharPtr phrase, Char ch)
+{
+  Boolean rval = FALSE;
+  Int4    phrase_len = StringLen (phrase);
+
+  if (a == NULL || *a == NULL 
+      || b == NULL || *b == NULL) {
+    rval = FALSE;
+  } else if (**a == ch && StringNCmp ((*a) + 1, phrase, phrase_len) == 0
+             && **b != ch && StringNCmp ((*b) + 1, phrase, phrase_len) == 0) {
+    (*a)--;
+    rval = TRUE;
+  } else if (**b == ch && StringNCmp ((*b) + 1, phrase, phrase_len) == 0
+             && **a != ch && StringNCmp ((*a) + 1, phrase, phrase_len) == 0) {
+    (*b)--;
+    rval = TRUE;
+  }
+  return rval;
+}
+
+
+static Boolean AdjustForCommaBeforePhrase (CharPtr PNTR a, CharPtr PNTR b, CharPtr phrase)
+{
+  return AdjustForCharBeforePhrase (a, b, phrase, ',');
+}
+
+
+static Boolean AdjustForCommaBeforeAnd (CharPtr PNTR a, CharPtr PNTR b)
+{
+  return AdjustForCommaBeforePhrase (a, b, " and ");
+}
+
+
+static Boolean AdjustForSkippableWord (CharPtr PNTR a, CharPtr PNTR b, CharPtr str1, CharPtr str2, CharPtr word)
+{
+  Int4 len;
+  Boolean rval = FALSE;
+
+  if (a == NULL || *a == NULL || b == NULL || *b == NULL) {
+    return FALSE;
+  }
+  len = StringLen (word);
+  if (*a - str1 > len && StringNCmp (*a - len + 1, word, len) == 0) {
+    *a -= len - 1;
+    *b += 1;
+    rval = TRUE;
+  }
+  if (*b - str2 > len && StringNCmp (*b - len + 1, word, len) == 0) {
+    *b -= len - 1;
+    *a += 1;
+    rval = TRUE;
+  }
+  return rval;
+}
+
+
+static Boolean AdjustForKnownDiffs (CharPtr PNTR a, CharPtr PNTR b, CharPtr str1, CharPtr str2)
+{
+  Boolean rval = SkipPair (a, b, str1, str2, " pseudogene, partial sequence", " gene, partial cds")
+                || SkipPair (a, b, str1, str2, " pseudogene, complete sequence", " gene, partial cds")
+                || SkipPair (a, b, str1, str2, " pseudogene, partial sequence", " gene, complete cds")
+                || SkipPair (a, b, str1, str2, " pseudogene, complete sequence", " gene, complete cds")
+                || SkipPair (a, b, str1, str2, " partial", " complete")
+                || SkipPair (a, b, str1, str2, "cds", "sequence")
+                || SkipPair (a, b, str1, str2, "gene, partial sequence;", "gene")
+                || SkipPair (a, b, str1, str2, "gene, complete sequence;", "gene")
+                || SkipPair (a, b, str1, str2, "spacer, partial sequence;", "spacer")
+                || SkipPair (a, b, str1, str2, "spacer, complete sequence;", "spacer")
+                || SkipPair (a, b, str1, str2, "gene", "genes")
+                || AdjustForSkippableWord (a, b, str1, str2, "-like")
+                || AdjustForSkippableWord (a, b, str1, str2, " truncated")
+                || AdjustForSkippableWord (a, b, str1, str2, " nonfunctional")
+                || AdjustForSkippableWord (a, b, str1, str2, " pseudo")
+                || AdjustForSkippableWord (a, b, str1, str2, " and")
+                || AdjustForSkippableWord (a, b, str1, str2, " partial sequence")
+                || AdjustForSkippableWord (a, b, str1, str2, " partial cds")
+                || AdjustForSkippableWord (a, b, str1, str2, " complete sequence")
+                || AdjustForSkippableWord (a, b, str1, str2, " complete cds")
+                || AdjustForSkippableWord (a, b, str1, str2, " gene")
+                || AdjustForSkippableWord (a, b, str1, str2, " genes")
+                || AdjustForSkippableWord (a, b, str1, str2, " pseudogene")
+                || AdjustForSkippableWord (a, b, str1, str2, " pseudogenes")
+                || AdjustForSkippableWord (a, b, str1, str2, ";")
+                || AdjustForSkippableWord (a, b, str1, str2, ",")
+                || AdjustForSpace (a, b, str1, str2);
+  return rval;
+}
+
+
+static Boolean AdjustForCommaBeforeGenomicSequence (CharPtr PNTR a, CharPtr PNTR b)
+{
+  return AdjustForCommaBeforePhrase (a, b, " genomic sequence");
+}
+
+
+static CharPtr defline_skippable_words[] = {
+  " transposon",
+  " mitochondrial",
+  NULL};
+
+static Boolean SkipWord (CharPtr PNTR a, CharPtr a_start, CharPtr PNTR b)
+{
+  Int4 index, len;
+  Boolean rval = FALSE;
+
+  if (a == NULL || *a == NULL || *a <= a_start || b == NULL || *b == NULL) {
+     return FALSE;
+  }
+
+  for (index = 0; defline_skippable_words[index] != NULL && !rval; index++) {
+    len = StringLen (defline_skippable_words[index]);
+    if (*a - a_start >= len && StringNCmp (*a - len + 1, defline_skippable_words[index], len) == 0) {
+      *a -= len - 1;
+      (*b)++;
+      rval = TRUE;
+    }
+  }
+  return rval;
+}
+   
+
+static Boolean MatchWithPhraseExceptions (CharPtr str1, CharPtr str2)
+{
+  Int4 len_curr, len_new;
+  CharPtr a, b;
+  CharPtr mitochondrial = "; mitochondrial";
+  Int4 len_mito = StringLen (mitochondrial);
+
+  len_curr = StringLen (str1);
+  len_new = StringLen (str2);
+  b = str2;
+  if (len_curr > 0) {
+    a = str1 + len_curr - 1;
+    b = str2 + len_new - 1;
+    if (*a == '.') {
+      a--;
+    }
+    if (*b == '.') {
+      b--;
+    }
+    /* skip trailing "mitochondrial" */
+    if (a - str1 > len_mito && StringNCmp (a - len_mito + 1, mitochondrial, len_mito) == 0) {
+      a -= len_mito;
+    }
+    if (b - str2 > len_mito && StringNCmp (b - len_mito + 1, mitochondrial, len_mito) == 0) {
+      b -= len_mito;
+    }
+
+    while (a >= str1 && b >= str2 
+            && (toupper (*a) == toupper(*b)
+                || SkipPair (&a, &b, str1, str2, " gene", " genes")
+                || SkipPair (&a, &b, str1, str2, "; and", ";")
+                || AdjustForCommaBeforeAnd (&a, &b)
+                || AdjustForCommaBeforeGenomicSequence (&a, &b)
+                || AdjustForSpace (&a, &b, str1, str2)
+                || SkipWord (&a, str1, &b)
+                || SkipWord (&b, str2, &a))) {
+      a--;
+      b--;
+    }
+  }
+  if (a + 1 == str1 && b + 1 == str2) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static Nlm_CompareDeflinesProc CompareDeflinesList[] = {
+  MatchExceptOldProduct,
+  NoSequenceForIntron,
+  MatchWithPhraseExceptions,
+  NULL };
+
+
+static Boolean DeflinesMatch (CharPtr old_str, CharPtr new_str)
+{
+  Int4 index;
+  Boolean match = FALSE;
+
+  if (StringCmp (old_str, new_str) == 0) {
+    return TRUE;
+  }
+
+  for (index = 0; CompareDeflinesList[index] != NULL && !match; index++) {
+    match = CompareDeflinesList[index](old_str, new_str);
+  }
+  return match;
+}
+
+
+static void ReplaceOldName (BioseqPtr bsp, CharPtr PNTR old_title)
+{
+  SeqDescPtr                    sdp;
+  SeqMgrDescContext             dcontext;
+  BioSourcePtr                  biop;
+  OrgModPtr                     omp;
+
+  if (old_title == NULL) {
+    return;
+  }
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+  if (sdp != NULL && (biop = (BioSourcePtr)sdp->data.ptrvalue) != NULL && biop->org != NULL && biop->org->orgname != NULL) {
+    omp = biop->org->orgname->mod;
+    while (omp != NULL) {
+      if (omp->subtype == ORGMOD_old_name) {
+        FindReplaceString (old_title, omp->subname, biop->org->taxname, TRUE, TRUE);
+      }
+      omp = omp->next;
+    }
+  }
+}
+
+
+static void AddMissingPeriod (CharPtr PNTR old_title)
+{
+  Int4 len;
+  CharPtr new_title;
+
+  if (old_title == NULL || *old_title == NULL) {
+    return;
+  }
+
+  len = StringLen (*old_title);
+  if ((*old_title)[len - 1] != '.') {
+    new_title = (CharPtr) MemNew (sizeof (Char) * (len + 2));
+    sprintf (new_title, "%s.", *old_title);
+    *old_title = MemFree (*old_title);
+    *old_title = new_title;
+  }
+}
+
+
+static void ChangeExonList (CharPtr PNTR old_title)
+{
+  CharPtr exon_start, first_and, second_and;
+  CharPtr src, dst;
+
+  if (old_title == NULL || StringHasNoText (*old_title) 
+      || (exon_start = StringStr (*old_title, "exons ")) == NULL
+      || (first_and = StringStr (exon_start, " and ")) == NULL
+      || (second_and = StringStr (first_and + 1, " and ")) == NULL) {
+    return;
+  }
+
+  if (StringCmp (second_and, " and partial cds.") != 0 && StringCmp (second_and, " and complete cds.") != 0) {
+    return;
+  }
+
+  *first_and = ',';
+  src = first_and + 4,
+  dst = first_and + 1;
+  while (*src != 0) {
+    *dst = *src;
+    dst++;
+    src++;
+  }
+  *dst = 0;
+}
+
+
+NLM_EXTERN DefLineClauseOptionsPtr MakeFeatureRequestsMatchExpectedTitle (BioseqPtr bsp)
+{
+  SeqEntryPtr                   sep;
+  ValNodePtr                    defline_clauses = NULL;
+  Int4                          index, mod_index;
+  ValNodePtr                    best_modifier_indices, default_modifier_indices, modifier_indices = NULL, tmp_mod_list;
+  ValNodePtr                    vnp;
+  ModifierItemLocalPtr          modList;
+  OrganismDescriptionModifiers  odmp;
+  SeqEntryPtr                   oldscope;
+  CharPtr                       clause_list = NULL, attempt = NULL, old_title;
+  DefLineFeatClausePtr          df;
+  DefLineClauseOptionsPtr       clause_options;
+  SeqDescPtr                    sdp;
+  SeqMgrDescContext             dcontext;
+  Boolean                       found_match = FALSE;
+  Boolean                       default_exclude_sp;
+
+  if (bsp == NULL) {
+    return NULL;
+  }
+  sep = GetTopSeqEntryForEntityID (bsp->idx.entityID);
+  if (sep == NULL) return NULL;
+
+  modList = MemNew (NumDefLineModifiers () * sizeof (ModifierItemLocalData));
+  if (modList == NULL) return NULL;
+
+  sdp = SeqMgrGetNextDescriptor(bsp, NULL, Seq_descr_title, &dcontext);
+  if (sdp == NULL || (old_title = (CharPtr) sdp->data.ptrvalue) == NULL) {
+    return NULL;
+  }
+
+  old_title = StringSave (old_title);
+  /* replacements for old RNA style */
+  FindReplaceString (&old_title, "RNA gene, mitochondrial gene for mitochondrial RNA, partial sequence", "RNA gene, partial sequence; mitochondrial", TRUE, TRUE);
+  FindReplaceString (&old_title, "16S ribosomal RNA, complete sequence", "16S ribosomal RNA gene, complete sequence", TRUE, TRUE);
+  FindReplaceString (&old_title, "16S ribosomal RNA, partial sequence", "16S ribosomal RNA gene, partial sequence", TRUE, TRUE);
+  FindReplaceString (&old_title, "subunit ribosomal RNA, complete sequence", "subunit ribosomal RNA gene, complete sequence", TRUE, TRUE);
+  FindReplaceString (&old_title, "subunit ribosomal RNA, partial sequence", "subunit ribosomal RNA gene, partial sequence", TRUE, TRUE);
+  FindReplaceString (&old_title, "specimen-voucher", "voucher", TRUE, TRUE);
+
+  ReplaceOldName (bsp, &old_title);
+  AddMissingPeriod (&old_title);
+  ChangeExonList (&old_title);
+
+  SetRequiredModifiers (modList);
+  CountModifiers (modList, sep);
+
+  InitOrganismDescriptionModifiers (&odmp, sep);
+  default_exclude_sp = odmp.exclude_sp;
+  odmp.use_modifiers = TRUE;
+
+  oldscope = SeqEntrySetScope (sep);
+
+  clause_options = DefLineClauseOptionsNew();
+
+  best_modifier_indices = FindBestModifiersEx (sep, modList, TRUE);
+  default_modifier_indices = GetModifierIndicesFromModList (modList);
+
+  /* start loop here */
+  for (index = 0;
+       ClauseOptionSetList[index] != NULL && !found_match;
+       index++) {
+    ClauseOptionSetList[index](clause_options);
+    BuildDefLineFeatClauseList (sep, bsp->idx.entityID, 
+                                &(clause_options->feature_requests),
+                                clause_options->product_flag, 
+                                clause_options->alternate_splice_flag, 
+                                clause_options->gene_cluster_opp_strand,
+                                &defline_clauses);
+    if (AreFeatureClausesUnique (defline_clauses)) {
+      modifier_indices = ValNodeDupIntList(default_modifier_indices);
+    } else {
+      modifier_indices = ValNodeDupIntList(best_modifier_indices);
+    }
+    for (vnp = defline_clauses; vnp != NULL; vnp = vnp->next) {
+      df = (DefLineFeatClausePtr) vnp->data.ptrvalue;
+      if (df->bsp == bsp) {
+        clause_list = df->clauselist;
+        break;
+      }
+    }
+
+    attempt = BuildOneDefinitionLine (sep, bsp, clause_list, modList, modifier_indices, &odmp);
+    if (DeflinesMatch(old_title, attempt)) {
+      found_match = TRUE;
+    }
+    attempt = MemFree (attempt);
+
+    if (!found_match) {
+      odmp.use_labels = FALSE;
+      attempt = BuildOneDefinitionLine (sep, bsp, clause_list, modList, modifier_indices, &odmp);
+      if (DeflinesMatch(old_title, attempt)) {
+        found_match = TRUE;
+      }
+      attempt = MemFree (attempt);
+      odmp.use_labels = TRUE; 
+    }
+
+    if (!found_match) {
+      for (mod_index = 0; OrgModifiersSetList[mod_index] != NULL && !found_match; mod_index++) {
+        tmp_mod_list = ValNodeDupIntList (modifier_indices);
+        if (OrgModifiersSetList[mod_index](&odmp, &tmp_mod_list, modList)) {
+          attempt = BuildOneDefinitionLine (sep, bsp, clause_list, modList, tmp_mod_list, &odmp);
+          if (DeflinesMatch(old_title, attempt)) {
+            found_match = TRUE;
+          }
+          attempt = MemFree (attempt);
+          if (!found_match) {
+            odmp.use_labels = FALSE;
+            attempt = BuildOneDefinitionLine (sep, bsp, clause_list, modList, tmp_mod_list, &odmp);
+            if (DeflinesMatch(old_title, attempt)) {
+              found_match = TRUE;
+            }
+            attempt = MemFree (attempt);
+            odmp.use_labels = TRUE; 
+          }
+        }
+        tmp_mod_list = ValNodeFree (tmp_mod_list);
+        odmp.exclude_sp = default_exclude_sp;
+      }
+    }
+
+    DefLineFeatClauseListFree (defline_clauses);
+    defline_clauses = NULL;
+    modifier_indices = ValNodeFree (modifier_indices);
+  }
+  /* end loop here */
+  best_modifier_indices = ValNodeFree (best_modifier_indices);
+  default_modifier_indices = ValNodeFree (default_modifier_indices);
+
+  old_title = MemFree (old_title);
+
+  if (modList != NULL) {
+    for (index = 0; index < NumDefLineModifiers (); index++) {
+      ValNodeFree (modList [index].values_seen);
+    }
+    MemFree (modList);
+  }
+
+  SeqEntrySetScope (oldscope);
+
+  if (!found_match) {
+    clause_options = DefLineClauseOptionsFree (clause_options);
+  }
+
+  return clause_options;
+}
+
+
+static Int4 MatchlenForAutodef (CharPtr str1, CharPtr str2)
+{
+  Int4 len_curr, len_new;
+  CharPtr a, b;
+
+  len_curr = StringLen (str1);
+  len_new = StringLen (str2);
+  b = str2;
+  if (len_curr > 0) {
+    a = str1 + len_curr - 1;
+    b = str2 + len_new - 1;
+    if (*a == '.') {
+      a--;
+    }
+    if (*b == '.') {
+      b--;
+    }
+    if (a - str1 > 13 && StringNCmp (a - 12, "; chloroplast", 13) == 0) {
+      a-= 13;
+    }
+    if (b - str2 > 13 && StringNCmp (b - 12, "; chloroplast", 13) == 0) {
+      b -= 13;
+    }
+    while (a >= str1 && b >= str2 
+            && (*a == *b || AdjustForKnownDiffs(&a, &b, str1, str2))) {
+      a--;
+      b--;
+    }
+  }
+  return len_new - (b - str2 + 1);
+}
+
+
+static void FindCommonTitleCallback (BioseqPtr bsp, Pointer data)
+{
+  Int4 len_curr, len_new;
+  CharPtr new_title;
+  CharPtr PNTR current_title;
+  CharPtr a, b;
+  CharPtr src, dst;
+  SeqMgrDescContext context;
+  SeqDescPtr sdp;
+
+  if (bsp == NULL || ISA_aa (bsp->mol)) {
+    return;
+  }
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, &context);
+
+  if (sdp == NULL || sdp->choice != Seq_descr_title 
+      || (new_title = (CharPtr) sdp->data.ptrvalue) == NULL
+      || (current_title = (CharPtr PNTR) data) == NULL) {
+    return;
+  }
+
+  if (*current_title == NULL) {
+    *current_title = StringSave (new_title);
+  } else {
+    len_curr = StringLen (*current_title);
+    len_new = StringLen (new_title);
+    if (len_curr > 0) {
+      a = (*current_title) + len_curr - 1;
+      b = new_title + len_new - 1;
+      if (*a == '.') {
+        a--;
+      }
+      if (*b == '.') {
+        b--;
+      }
+      if (a - *current_title > 13 && StringNCmp (a - 12, "; chloroplast", 13) == 0) {
+        a-= 13;
+      }
+      if (b - new_title > 13 && StringNCmp (b - 12, "; chloroplast", 13) == 0) {
+        b -= 13;
+      }
+      while (a >= *current_title && b >= new_title 
+            && (*a == *b || AdjustForKnownDiffs(&a, &b, *current_title, new_title))) {
+        a--;
+        b--;
+      }
+      /* don't copy part of a word */
+      while (*(a + 1) != 0 && !isspace (*(a + 1))) {
+        a++;
+      }
+      if (a + 1 > *current_title) {
+        src = a + 1;
+        dst = *current_title;
+        while (*src != 0) {
+          *dst = *src;
+          dst++;
+          src++;
+        }
+        *dst = 0;
+      }
+    }
+  }
+}
+
+
+typedef struct verifycommonfeatureclause {
+  CharPtr common_clause;
+  Boolean is_ok;
+} VerifyCommonFeatureClauseData, PNTR VerifyCommonFeatureClausePtr;
+
+
+static void PrintBioSource (BioSourcePtr biop)
+{
+  OrgModPtr mod;
+  SubSourcePtr ssp;
+
+  printf ("Taxname: %s", biop->org->taxname);
+  for (mod = biop->org->orgname->mod; mod != NULL; mod = mod->next) {
+    printf ("\tOrgMod%d:%s", mod->subtype, mod->subname);
+  }
+  for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
+    printf ("\tSubSource%d:%s", ssp->subtype, ssp->name);
+  }
+  printf ("\n");
+}
+
+
+static void VerifyCommonFeatureClauseCallback (BioseqPtr bsp, Pointer data)
+{
+  VerifyCommonFeatureClausePtr v;
+  SeqMgrDescContext context;
+  SeqDescPtr sdp;
+  CharPtr title;
+  BioSourcePtr biop;
+  Int4 common_clause_len, title_len, last_word_len = 0;
+  SourceConstraint source_constraint;
+  CharPtr last_word, cp;
+  Char id_txt[100];
+
+  if (bsp == NULL || ISA_aa (bsp->mol) 
+      || (v = (VerifyCommonFeatureClausePtr) data) == NULL
+      || !v->is_ok) {
+    return;
+  }
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, &context);
+
+  if (sdp == NULL || sdp->choice != Seq_descr_title || (title = (CharPtr) sdp->data.ptrvalue) == NULL) {
+    return;
+  }
+  title_len = StringLen (title);
+  common_clause_len = MatchlenForAutodef (v->common_clause, title);
+
+  cp = title + title_len - common_clause_len - 1;
+  while (cp > title && !isspace (*cp)) {
+    --cp;
+    last_word_len++;
+  }
+  if (*(cp + last_word_len) == ',') {
+    last_word_len--;
+  }
+
+  /* note - allocate extra space, in case we need to try adding a semicolon */
+  last_word = (CharPtr) MemNew (sizeof (Char) * (last_word_len + 2));
+  StringNCpy (last_word, cp + 1, last_word_len);
+  last_word[last_word_len] = 0;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &context);
+
+  if (sdp == NULL || sdp->choice != Seq_descr_source || (biop = (BioSourcePtr) sdp->data.ptrvalue) == NULL) {
+    return;
+  }
+
+  MemSet (&source_constraint, 0, sizeof (SourceConstraint));
+  source_constraint.constraint = StringConstraintNew ();
+  source_constraint.constraint->match_text = last_word;
+  source_constraint.constraint->match_location = String_location_ends;
+  source_constraint.constraint->case_sensitive = FALSE;
+  source_constraint.constraint->whole_word = TRUE;
+  source_constraint.constraint->not_present = FALSE;
+
+  if (!DoesBiosourceMatchConstraint(biop, &source_constraint)) {
+    StringCat (last_word, ";");
+    source_constraint.constraint->match_location = String_location_contains;
+    if (!DoesBiosourceMatchConstraint(biop, &source_constraint)) {
+      /* try country with colon */
+      last_word[last_word_len] = ':';
+      source_constraint.constraint->match_location = String_location_contains;
+      source_constraint.field1 = ValNodeNew (NULL);
+      source_constraint.field1->choice = SourceQualChoice_textqual;
+      source_constraint.field1->data.intvalue = Source_qual_country;
+      if (!DoesBiosourceMatchConstraint(biop, &source_constraint)) {
+        v->is_ok = FALSE;
+        SeqIdWrite (bsp->id, id_txt, PRINTID_TEXTID_ACC_ONLY, sizeof (id_txt) - 1);
+        printf ("For %s, common title fails, last word is %s\n", id_txt, last_word);
+        PrintBioSource (biop);
+      }
+      source_constraint.field1 = ValNodeFree (source_constraint.field1);
+    }
+  }
+  source_constraint.constraint = StringConstraintFree (source_constraint.constraint);
+}
+
+
+static CharPtr GetCommonFeatureClause (SeqEntryPtr sep)
+{
+  CharPtr common_clause = NULL;
+  VerifyCommonFeatureClauseData v;
+  CharPtr src, dst;
+
+  VisitBioseqsInSep (sep, &common_clause, FindCommonTitleCallback);
+  if (StringHasNoText (common_clause)) {
+    common_clause = MemFree (common_clause);
+  } else {
+    MemSet (&v, 0, sizeof (VerifyCommonFeatureClauseData));
+    v.common_clause = common_clause;
+    v.is_ok = TRUE;
+    VisitBioseqsInSep (sep, &v, VerifyCommonFeatureClauseCallback);
+    if (!v.is_ok) {
+      if (StringNCmp (common_clause, " chloroplast", 12) == 0) {
+        dst = common_clause;
+        for (src = common_clause + 12; *src != 0; src++) {
+          *dst = *src;
+        }
+        *dst = 0;
+        v.is_ok = TRUE;
+        VisitBioseqsInSep (sep, &v, VerifyCommonFeatureClauseCallback);
+      }
+    }
+    if (!v.is_ok) {
+      common_clause = MemFree (common_clause);
+    }
+  }
+  return common_clause;
+}
+
+
+NLM_EXTERN void BuildDefinitionLinesFromFeatureClauseLists (
+  ValNodePtr list,
+  ModifierItemLocalPtr modList,
+  ValNodePtr modifier_indices,
+  OrganismDescriptionModifiersPtr odmp
+)
+{
+  ValNodePtr vnp;
+  DefLineFeatClausePtr defline_featclause;
+  CharPtr    tmp_str;
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next)
+  {
+    if (vnp->data.ptrvalue != NULL)
+    {
+      defline_featclause = vnp->data.ptrvalue;
+      tmp_str = BuildOneDefinitionLine (defline_featclause->sep, defline_featclause->bsp,
+                                        defline_featclause->clauselist,
+                                        modList, modifier_indices, odmp);
       ReplaceDefinitionLine (defline_featclause->sep, tmp_str);
-      MemFree (org_desc);
     }
   }
 }
@@ -10719,6 +12272,218 @@ NLM_EXTERN void RemoveNucProtSetTitles (SeqEntryPtr sep)
 }
 
 
+static void ProtTitleRemoveProc (BioseqPtr bsp, Pointer userdata)
+
+{
+  ObjValNodePtr  ovp;
+  SeqDescrPtr    sdp;
+
+  if (bsp == NULL) return;
+  if (! ISA_aa (bsp->mol)) return;
+
+  for (sdp = bsp->descr; sdp != NULL; sdp = sdp->next) {
+    if (sdp->choice == Seq_descr_title && sdp->extended) {
+      ovp = (ObjValNodePtr) sdp;
+      ovp->idx.deleteme = TRUE;
+    }
+  }
+}
+
+NLM_EXTERN void RemoveProteinTitles (SeqEntryPtr sep)
+
+{
+  Uint2  entityID;
+
+  if (sep == NULL) return;
+  VisitBioseqsInSep (sep, NULL, ProtTitleRemoveProc);
+  entityID = ObjMgrGetEntityIDForChoice (sep);
+  DeleteMarkedObjects (entityID, 0, NULL);
+}
+
+
+typedef struct popsetdefline {
+ DeflineFeatureRequestListPtr feature_requests;
+ Int2 product_flag;
+ Boolean alternate_splice_flag;
+ Boolean gene_cluster_opp_strand;
+} PopsetDeflineData, PNTR PopsetDeflinePtr;
+
+
+
+NLM_EXTERN Boolean GetsDocsumTitle(Uint1 set_class)
+{
+  if (set_class == BioseqseqSet_class_pop_set
+      || set_class == BioseqseqSet_class_phy_set
+      || set_class == BioseqseqSet_class_eco_set
+      || set_class == BioseqseqSet_class_mut_set) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static Boolean HasTitle(SeqDescrPtr descr)
+{
+  while (descr != NULL) {
+    if (descr->choice == Seq_descr_title) {
+      return TRUE;
+    }
+    descr = descr->next;
+  }
+  return FALSE;
+}
+
+
+NLM_EXTERN void AddPopsetDeflineWithClause (BioseqSetPtr bssp, CharPtr clause)
+{
+  SeqEntryPtr set_sep;
+  OrgRefPtr   org;
+  CharPtr     org_desc = NULL, keyword_prefix = NULL, tmp_str = NULL;
+
+  set_sep = SeqMgrGetSeqEntryForData (bssp);
+  org = GetCommonOrgRefForSeqEntry (set_sep);
+  if (org == NULL || StringHasNoText (org->taxname)) {
+    return;
+  }
+  org_desc = StringSave (org->taxname);
+  org = OrgRefFree (org);
+    
+  keyword_prefix = GetKeywordPrefix (set_sep);
+  
+  tmp_str = (CharPtr) MemNew (StringLen (keyword_prefix) 
+                              + StringLen (org_desc) 
+                              + StringLen (clause) + 2);
+  if (tmp_str == NULL) return;
+  tmp_str [0] = 0;
+  if (keyword_prefix != NULL)
+  {
+    StringCat (tmp_str, keyword_prefix);
+  }
+  StringCat (tmp_str, org_desc);
+  if (clause != NULL
+    && clause[0] != ','
+    && clause[0] != '.'
+    && clause[0] != ' '
+    && clause[0] != 0)
+  {
+    StringCat (tmp_str, " ");
+  }
+  StringCat (tmp_str, clause);
+  tmp_str [0] = toupper (tmp_str [0]);
+  ReplaceDefinitionLine (set_sep, tmp_str);
+  MemFree (org_desc);
+}
+
+
+static void AddPopsetCallback (BioseqSetPtr bssp, Pointer data)
+{
+  SeqEntryPtr          set_sep, first_sep;
+  OrgRefPtr            org;
+  ValNodePtr           defline_clauses = NULL;
+  DefLineFeatClausePtr defline_featclause;
+  CharPtr              org_desc = NULL, keyword_prefix = NULL, tmp_str = NULL;
+  PopsetDeflinePtr     pop;
+
+  if (bssp == NULL 
+      || !GetsDocsumTitle(bssp->_class) 
+      || HasTitle(bssp->descr)
+      || (pop = (PopsetDeflinePtr)data) == NULL) {
+    return;
+  }
+
+  set_sep = SeqMgrGetSeqEntryForData (bssp);
+  org = GetCommonOrgRefForSeqEntry (set_sep);
+  if (org == NULL || StringHasNoText (org->taxname)) {
+    return;
+  }
+  org_desc = StringSave (org->taxname);
+  org = OrgRefFree (org);
+
+  /* make title here */
+  first_sep = bssp->seq_set;
+
+  BuildDefLineFeatClauseList (first_sep, bssp->idx.entityID,
+                              pop->feature_requests,
+                              pop->product_flag, pop->alternate_splice_flag, pop->gene_cluster_opp_strand,
+                              &defline_clauses);
+
+  if (defline_clauses != NULL) {
+    defline_featclause = defline_clauses->data.ptrvalue;
+    
+    keyword_prefix = GetKeywordPrefix (defline_featclause->sep);
+    
+    tmp_str = (CharPtr) MemNew (StringLen (keyword_prefix) 
+                                + StringLen (org_desc) 
+                                + StringLen (defline_featclause->clauselist) + 2);
+    if (tmp_str == NULL) return;
+    tmp_str [0] = 0;
+    if (keyword_prefix != NULL)
+    {
+      StringCat (tmp_str, keyword_prefix);
+    }
+    StringCat (tmp_str, org_desc);
+    if (defline_featclause->clauselist != NULL
+      && defline_featclause->clauselist [0] != ','
+      && defline_featclause->clauselist [0] != '.'
+      && defline_featclause->clauselist [0] != 0)
+    {
+      StringCat (tmp_str, " ");
+    }
+    StringCat (tmp_str, defline_featclause->clauselist);
+    tmp_str [0] = toupper (tmp_str [0]);
+    ReplaceDefinitionLine (set_sep, tmp_str);
+  }
+  MemFree (org_desc);
+}
+
+
+NLM_EXTERN void AddPopsetTitles 
+(SeqEntryPtr sep,
+ DeflineFeatureRequestListPtr feature_requests,
+ Int2 product_flag,
+ Boolean alternate_splice_flag,
+ Boolean gene_cluster_opp_strand)
+{
+  PopsetDeflineData pop;
+
+  pop.feature_requests = feature_requests;
+  pop.product_flag = product_flag;
+  pop.alternate_splice_flag = alternate_splice_flag;
+  pop.gene_cluster_opp_strand = gene_cluster_opp_strand;
+
+  VisitSetsInSep (sep, &pop, AddPopsetCallback);
+}
+
+
+static void RemovePopsetTitlesCallback(BioseqSetPtr bssp, Pointer data)
+{
+  SeqDescrPtr   sdp;
+  ObjValNodePtr ovp;
+
+  if (bssp == NULL || !GetsDocsumTitle(bssp->_class)) {
+    return;
+  }
+  for (sdp = bssp->descr; sdp != NULL; sdp = sdp->next) {
+    if (sdp->choice == Seq_descr_title
+        && sdp->extended) {
+      ovp = (ObjValNodePtr) sdp;
+      ovp->idx.deleteme = TRUE;
+    }
+  }
+}
+
+
+NLM_EXTERN void RemovePopsetTitles(SeqEntryPtr sep)
+{
+  Uint2 entityID;
+
+  VisitSetsInSep (sep, NULL, RemovePopsetTitlesCallback);
+  entityID = ObjMgrGetEntityIDForChoice (sep);
+  DeleteMarkedObjects (entityID, 0, NULL);
+}
+
+
 NLM_EXTERN void 
 AutoDefForSeqEntry 
 (SeqEntryPtr sep,
@@ -10752,9 +12517,138 @@ AutoDefForSeqEntry
   DefLineFeatClauseListFree (defline_clauses);
   ClearProteinTitlesInNucProts (entityID, NULL);
   InstantiateProteinTitles (entityID, NULL);
+
+  AddPopsetTitles (sep, feature_requests, product_flag, 
+                   alternate_splice_flag, gene_cluster_opp_strand);
+}
+
+
+/* Retro PopSet Title Functions */
+static SeqDescPtr BioseqHasTitleOrNucProtSetHasTitle (BioseqPtr bsp)
+{
+  SeqDescPtr sdp = NULL;
+  SeqMgrDescContext context;
+  BioseqSetPtr bssp;
+  ObjValNodePtr ovn;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, &context);
+  while (sdp != NULL) {
+    if (sdp->extended) {
+      ovn = (ObjValNodePtr) sdp;
+      if (ovn->idx.parentptr == bsp) {
+        return sdp;
+      } else if (ovn->idx.parenttype == OBJ_BIOSEQSET
+                 && (bssp = (BioseqSetPtr) ovn->idx.parentptr) != NULL
+                 && bssp->_class == BioseqseqSet_class_nuc_prot) {
+        return sdp;
+      }
+    }
+    sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_title, &context);
+  }
+  return NULL;
+}
+
+
+static BioseqPtr FindFirstNucBioseqWithTitle (SeqEntryPtr sep)
+
+{
+  BioseqPtr     bsp;
+  BioseqSetPtr  bssp;
+
+  if (sep == NULL || sep->data.ptrvalue == NULL ||
+      /* sep->choice < 0 || */ sep->choice > 2) return NULL;
+  if (IS_Bioseq (sep) ) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    if (!ISA_aa (bsp->mol) && BioseqHasTitleOrNucProtSetHasTitle(bsp) != NULL) {
+      return bsp;
+    } else {
+      return NULL;
+    }
+  }
+  bssp = (BioseqSetPtr) sep->data.ptrvalue;
+  for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
+    bsp = FindFirstNucBioseqWithTitle (sep);
+    if (bsp != NULL) return bsp;
+  }
+  return NULL;
+}
+
+
+static void RetroPopSetAutoDefCallback (BioseqSetPtr bssp, Pointer data)
+{
+  SeqEntryPtr set_sep;
+  BioseqPtr   first_bsp;
+  DefLineClauseOptionsPtr clause_options = NULL;
+  CharPtr                    common_title = NULL;
+  SeqEntryPtr oldscope, sep;
+  PopSetRetroStatPtr stat = (PopSetRetroStatPtr) data;
+
+  if (bssp == NULL || !GetsDocsumTitle (bssp->_class) || HasTitle (bssp->descr)) {
+    return;
+  }
+
+  set_sep = SeqMgrGetSeqEntryForData (bssp);
+  first_bsp = FindFirstNucBioseqWithTitle (set_sep);
+  if (first_bsp == NULL) {
+    if (stat != NULL) {
+      stat->uncalculatable++;
+    }
+    return;
+  }
+  sep = GetTopSeqEntryForEntityID (bssp->idx.entityID);
+
+  /* infer feature list from first title */
+  clause_options = MakeFeatureRequestsMatchExpectedTitle (first_bsp);
+
+  if (clause_options == NULL) {
+    common_title = GetCommonFeatureClause (set_sep);
+    if (common_title == NULL) {
+      if (stat != NULL) {
+        stat->uncalculatable++;
+      }
+    } else {
+      AddPopsetDeflineWithClause (bssp, common_title);
+      common_title = MemFree (common_title);
+      if (stat != NULL) {
+        stat->common_title++;
+        stat->title_added = TRUE;
+      }
+    }
+  } else {
+    oldscope = SeqEntrySetScope (sep);
+
+    AddPopsetTitles (sep, &(clause_options->feature_requests),
+                     clause_options->product_flag,
+                     clause_options->alternate_splice_flag,
+                     clause_options->gene_cluster_opp_strand);
+
+    SeqEntrySetScope (oldscope);
+    clause_options = DefLineClauseOptionsFree (clause_options);
+    if (stat != NULL) {
+      stat->feature_clause++;
+      stat->title_added = TRUE;
+    }
+  }
+}
+
+
+NLM_EXTERN void PopSetAutoDefRetro (SeqEntryPtr sep, PopSetRetroStatPtr stat)
+
+{
+  SeqEntryPtr oldscope;
+
+  if (sep == NULL) return;
+
+  oldscope = SeqEntrySetScope (sep);
+
+  VisitSetsInSep (sep, stat, RetroPopSetAutoDefCallback);
+
+  SeqEntrySetScope (oldscope);
 }
 
 
+
+
 /* functions for editing seq-locs */
 NLM_EXTERN Int4 ExtendSeqLocToEnd (SeqLocPtr slp, BioseqPtr bsp, Boolean end5)
 {
@@ -10895,16 +12789,23 @@ NLM_EXTERN RnaRefPtr RnaRefFromLabel (Uint2 featdef_to, CharPtr label, BoolPtr a
       rrp->type = 4;
       break;
     case FEATDEF_snRNA :
-      rrp->type = 5;
+      rrp->type = 8;
       break;
     case FEATDEF_scRNA :
-      rrp->type = 6;
+      rrp->type = 8;
       break;
     case FEATDEF_snoRNA :
-      rrp->type = 7;
+      rrp->type = 8;
       break;
     case FEATDEF_ncRNA:
+      rrp->type = 8;
+      break;
     case FEATDEF_tmRNA:
+      rrp->type = 9;
+      break;
+    case FEATDEF_misc_RNA:
+      rrp->type = 10;
+      break;
     case FEATDEF_otherRNA :
       rrp->type = 255;
       break;
@@ -10927,25 +12828,9 @@ NLM_EXTERN RnaRefPtr RnaRefFromLabel (Uint2 featdef_to, CharPtr label, BoolPtr a
       *add_label_to_comment = TRUE;
     }
   } 
-  else if (featdef_to == FEATDEF_ncRNA) 
-  {
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-  }  
-  else if (featdef_to == FEATDEF_tmRNA) 
-  {
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave ("tmRNA");
-  } 
-  else if (featdef_to == FEATDEF_otherRNA) 
-  {
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave ("misc_RNA");
-  } 
-  else if (! StringHasNoText (label))
+  else 
   {
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave (label);
+    SetRNARefProductString (rrp, NULL, label, ExistingTextOption_replace_old);
   }
   return rrp;
 }
@@ -11202,7 +13087,7 @@ static Boolean add_fuzziness_to_loc (SeqLocPtr slp, Boolean less)
 
 	if(spnt != NULL)
 		spnt->fuzz = ifp;
-	else
+    else if (sint != NULL)
 	{
 		if(less)
 			sint->if_from = ifp;
@@ -11381,7 +13266,7 @@ codons */
 
 NLM_EXTERN SeqLocPtr BuildProtLoc (SeqFeatPtr overlapping_cds, SeqLocPtr slp, Int4Ptr frame)
 {
-  SeqLocPtr tmp_loc, aa_loc, prot_loc = NULL, last_loc = NULL, next_loc;
+  SeqLocPtr tmp_loc, aa_loc = NULL, prot_loc = NULL, last_loc = NULL, next_loc;
   Boolean   partial5, partial3;
   BioseqPtr prot_bsp;
   Boolean   is_ordered = FALSE;
@@ -11692,7 +13577,7 @@ NLM_EXTERN Boolean ConvertProtToImpFunc (SeqFeatPtr  sfp, Uint2 featdef_to)
   CharPtr       ec;
   CharPtr       activity;
   ValNodePtr    vnp;
-  GBQualPtr     gbqual;
+  GBQualPtr     gbqual = NULL;
   GBQualPtr     prevGbq;
   GBQualPtr     topOfGbqList;
   DbtagPtr      dbt;
@@ -12752,54 +14637,111 @@ NLM_EXTERN void InstantiateMatPeptideProducts (SeqEntryPtr sep)
 }
 
 
+typedef struct tsa_id_callback {
+  SeqEntryPtr top_sep;
+  CharPtr suffix;
+} TSAIdCallbackData, PNTR TSAIdCallbackPtr;
+
 
-static void ConvertLocalIdsToTSAIdsCallback (BioseqPtr bsp, Pointer data)
+static void MakeTSAIdsCallback (BioseqPtr bsp, Pointer data)
 {
   Int4            gpid = 0;
-  SeqIdPtr        sip_local = NULL;
-  SeqEntryPtr     top_sep;
-  SeqIdPtr        sip_new;
-  DbtagPtr        dbtag;
+  SeqIdPtr        sip, sip_tsa = NULL, sip_local = NULL;
+  TSAIdCallbackPtr t;
+  SeqIdPtr        sip_new = NULL;
+  DbtagPtr        dbtag, dbtag_old = NULL;
   CharPtr         id_fmt = "gpid:%d";
   ObjectIdPtr     oip = NULL;
+  Int4            id_num = 0;
+  CharPtr         id_str = NULL;
+  CharPtr         cp;
 
   if (bsp == NULL || ISA_aa (bsp->mol) || data == NULL || !IsTSA (bsp)) {
     return;
   }
 
-  top_sep = (SeqEntryPtr) data;
+  t = (TSAIdCallbackPtr) data;
 
-  for (sip_local = bsp->id;
-       sip_local != NULL && sip_local->choice != SEQID_LOCAL;
-       sip_local = sip_local->next)
-  {}
-  if (sip_local == NULL) return;
-  oip = sip_local->data.ptrvalue;
-  if (oip == NULL) return;
+  for (sip = bsp->id;
+       sip != NULL;
+       sip = sip->next) 
+  {
+    if (sip->choice == SEQID_LOCAL) 
+    {
+      sip_local = sip;
+    } 
+    else if (sip->choice == SEQID_GENERAL
+               && (dbtag_old = (DbtagPtr) sip->data.ptrvalue) != NULL
+               && StringNCmp (dbtag_old->db, "gpid:", 5) == 0) 
+    {
+      sip_tsa = sip;
+    }
+  }
 
+  if (sip_tsa == NULL && sip_local == NULL) {
+    return;
+  }
   gpid = GetGenomeProjectID (bsp);
+  if (gpid <= 0) {
+    return;
+  }
 
-  if (gpid > 0) {
     dbtag = DbtagNew ();
     dbtag->db = MemNew (sizeof (Char) * (StringLen (id_fmt) + 15));
     sprintf (dbtag->db, id_fmt, gpid);
     dbtag->tag = ObjectIdNew ();
+  
+  if (sip_tsa != NULL && (dbtag_old = (DbtagPtr) sip_tsa->data.ptrvalue) != NULL) {
+    oip = dbtag_old->tag;
+    sip = sip_tsa;
+  } else if (sip_local != NULL) {
+    oip = sip_local->data.ptrvalue;
+    sip = sip_local;
+  }
+
+  if (oip == NULL) {
+    return;
+  }
+
     if (oip->str == NULL) {
-      dbtag->tag->id = oip->id;
+    id_num = oip->id;
     } else {
-      dbtag->tag->str = StringSave (oip->str);
+    id_str = StringSave (oip->str);
+    if (sip == sip_tsa && (cp = StringRChr (id_str, '.')) != NULL) {
+      *cp = 0;
+    }
+  }
+
+  if (t->suffix == NULL) {
+    if (id_str == NULL) {
+      dbtag->tag->id = id_num;
+    } else {
+      dbtag->tag->str = StringSave (id_str);
+    }
+  } else {
+    if (id_str == NULL) {
+      dbtag->tag->str = (CharPtr) MemNew (sizeof (Char) * (16 + StringLen (t->suffix)));
+      sprintf (dbtag->tag->str, "%d.%s", id_num, t->suffix);
+    } else {
+      dbtag->tag->str = (CharPtr) MemNew (sizeof (Char) * (StringLen (oip->str) + StringLen (t->suffix) + 2));
+      sprintf (dbtag->tag->str, "%s.%s", id_str, t->suffix);
+    }
     }
+  id_str = MemFree (id_str);
     sip_new = ValNodeNew (NULL);
     sip_new->choice = SEQID_GENERAL;
     sip_new->data.ptrvalue = dbtag;
-    ReplaceSeqIdWithSeqId (sip_local, sip_new, top_sep);
-  }
+  ReplaceSeqIdWithSeqId (sip, sip_new, t->top_sep);
 }     
           
   
-NLM_EXTERN void ConvertLocalIdsToTSAIds (SeqEntryPtr sep)
+NLM_EXTERN void ConvertLocalIdsToTSAIds (SeqEntryPtr sep, CharPtr suffix)
 {
-  VisitBioseqsInSep (sep, sep, ConvertLocalIdsToTSAIdsCallback);
+  TSAIdCallbackData t;
+
+  t.top_sep = sep;
+  t.suffix = suffix;
+  VisitBioseqsInSep (sep, &t, MakeTSAIdsCallback);
 }
 
 
@@ -12911,6 +14853,8 @@ static Boolean RemoveMatchingFieldType (FieldTypePtr PNTR orig_list, FieldTypePt
       vnp->next = NULL;
       vnp = FieldTypeFree (vnp);
       rval = TRUE;
+    } else {
+      prev = vnp;
     }
   }
   return rval;
@@ -12936,8 +14880,8 @@ static Boolean ListHasMatchingFieldType (FieldTypePtr list, FieldTypePtr match)
 
 static Int4 DefLineFieldTypeSortOrder [] = {
   Source_qual_strain,
-  Source_qual_clone,
   Source_qual_isolate,
+  Source_qual_clone,
   Source_qual_haplotype,
   Source_qual_cultivar,
   Source_qual_specimen_voucher,
@@ -13331,8 +15275,9 @@ static FieldTypePtr GetAllPresentQualsForGroup (UniqBioSrcGrpPtr g)
 
 static FieldTypePtr GetAllQualsForGroup (UniqBioSrcGrpPtr g)
 {
-  ValNodePtr vnp;
-  FieldTypePtr field_list = NULL;
+  ValNodePtr vnp, tmp;
+  FieldTypePtr field_list_head = NULL;
+  FieldTypePtr field_list_tail = NULL;
   UniqBioSourcePtr u;
 
   if (g == NULL || g->num_biop < 2) {
@@ -13342,11 +15287,20 @@ static FieldTypePtr GetAllQualsForGroup (UniqBioSrcGrpPtr g)
   for (vnp = g->biop_list; vnp != NULL; vnp = vnp->next) {
     u = vnp->data.ptrvalue;
     if (u != NULL && u->available_fields != NULL) {
-      ValNodeLink (&field_list, FieldTypeListCopy (u->available_fields));
+      tmp = ValNodeLink (&field_list_tail, FieldTypeListCopy (u->available_fields));
+      if (field_list_head == NULL) {
+        field_list_head = tmp;
+      }
+      if (tmp != NULL) {
+        while (tmp->next != NULL) {
+          tmp = tmp->next;
+        }
+      }
+      field_list_tail = tmp;
     }
   }
-  SortUniqueFieldTypeList (&field_list);
-  return field_list;
+  SortUniqueFieldTypeList (&field_list_head);
+  return field_list_head;
 }
 
 
@@ -13582,6 +15536,26 @@ static QualComboPtr QualComboFree (
 }
 
 
+static void TESTDisplayQualCombo (QualComboPtr q)
+{
+  ValNodePtr vnp_t, vnp_b, vnp_q, vnp_f;
+  UniqBioSrcGrpPtr g;
+  UniqBioSourcePtr bio;
+  Int4             val;
+
+  for (vnp_t = q->group_list; vnp_t != NULL; vnp_t = vnp_t->next) {
+    g = (UniqBioSrcGrpPtr) vnp_t->data.ptrvalue;
+    for (vnp_b = g->biop_list; vnp_b != NULL; vnp_b = vnp_b->next) {
+      bio = (UniqBioSourcePtr) vnp_b->data.ptrvalue;
+      for (vnp_q = bio->available_fields; vnp_q != NULL; vnp_q = vnp_q->next) {
+        vnp_f = (ValNodePtr) vnp_q->data.ptrvalue;
+        val = vnp_f->data.intvalue;
+      }
+    }
+  }
+}
+
+
 static Boolean AddQualToQualCombo (
   QualComboPtr m,
   FieldTypePtr field
@@ -13716,6 +15690,37 @@ static ValNodePtr ExpandOneComboListUsingAllPresentQuals (QualComboPtr q)
 }
 
 
+static void TESTDisplayList (ValNodePtr new_list)
+{
+  QualComboPtr q;
+  ValNodePtr vnp;
+
+  for (vnp = new_list; vnp != NULL; vnp = vnp->next) {
+    q = (QualComboPtr) vnp->data.ptrvalue;
+    TESTDisplayQualCombo (q);
+  }
+
+}
+
+
+static Boolean IsQualOkForDefline (ValNodePtr vnp)
+{
+  ValNodePtr scp;
+  
+  if (vnp == NULL || vnp->choice != FieldType_source_qual
+      || (scp = (SourceQualChoicePtr) vnp->data.ptrvalue) == NULL
+      || scp->choice != SourceQualChoice_textqual) {
+    return FALSE;
+  }
+  if (scp->data.intvalue == Source_qual_map || scp->data.intvalue == Source_qual_nat_host) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+  
+      
+    
 static ValNodePtr ExpandOneComboListUsingAnyPresentQuals (QualComboPtr q)
 {
   ValNodePtr new_list = NULL, vnp, vnp_m;
@@ -13730,6 +15735,9 @@ static ValNodePtr ExpandOneComboListUsingAnyPresentQuals (QualComboPtr q)
     if (g->num_biop == 1) break;
     match_list = GetAllQualsForGroup (g);
     for (vnp_m = match_list; vnp_m != NULL; vnp_m = vnp_m->next) {
+      if (!IsQualOkForDefline(vnp_m)) {
+        RemoveFieldFromUniqBioSrcGrp (g, vnp_m);
+      } else {
       q_new = QualComboCopy (q);
       if (AddQualToQualCombo (q_new, vnp_m) && q_new->num_groups > q->num_groups) {
         ValNodeAddPointer (&new_list, 0, q_new);
@@ -13739,8 +15747,10 @@ static ValNodePtr ExpandOneComboListUsingAnyPresentQuals (QualComboPtr q)
         RemoveFieldFromUniqBioSrcGrp (g, vnp_m);
       }
     }
+    }
     match_list = FieldTypeListFree (match_list);
   }
+
   return new_list;
 }
 
@@ -13787,9 +15797,16 @@ static void BuildUniqBioSrcList (
 )
 {
   UniqBioSourcePtr u;
+  ValNodeBlockPtr  vnbp;
+  ValNodePtr       vnp;
 
   u = UniqBioSourceNew (biop);
-  ValNodeAddPointer ((ValNodePtr PNTR) userdata, 0, u);
+  vnbp = (ValNodeBlockPtr) userdata;
+  vnp = ValNodeAddPointer (&vnbp->tail, 0, u);
+  if (vnbp->head == NULL) {
+    vnbp->head = vnp;
+  }
+  vnbp->tail = vnp;
 }
 
 
@@ -13862,7 +15879,7 @@ static QualComboPtr FindBestQualComboEx(ValNodePtr PNTR biop_list, ModifierItemL
     AddQualToQualCombo (initial_combo, &ft);
   } else {
     for (i = 0; i < numDefLineModifiers; i++) {
-      if (ItemList[i].required) {
+      if (ItemList[i].required && ItemList[i].any_present) {
         qual = GetSrcQualFromSubSrcOrOrgMod (DefLineModifiers[i].subtype, DefLineModifiers[i].isOrgMod);
         if (qual > -1) {
           scd.data.intvalue = qual;
@@ -13898,14 +15915,16 @@ static QualComboPtr FindBestQualComboEx(ValNodePtr PNTR biop_list, ModifierItemL
 static QualComboPtr FindBestQualCombo(SeqEntryPtr sep, ModifierItemLocalPtr ItemList)
 {
   QualComboPtr best_combo;
-  ValNodePtr   biop_list = NULL;
+  ValNodeBlock  vnb;
 
   /* first, get list of organisms */
-  VisitBioSourcesInSep (sep, &biop_list, BuildUniqBioSrcList);
+  vnb.head = NULL;
+  vnb.tail = NULL;
+  VisitBioSourcesInSep (sep, &vnb, BuildUniqBioSrcList);
 
-  best_combo = FindBestQualComboEx (&biop_list, ItemList);
+  best_combo = FindBestQualComboEx (&vnb.head, ItemList);
 
-  biop_list = UniqBioSourceListFree (biop_list);
+  UniqBioSourceListFree (vnb.head);
   return best_combo;
 }
 
@@ -13992,6 +16011,7 @@ NLM_EXTERN ValNodePtr FindBestModifiersEx(
   if (use_new) {
     q = FindBestQualCombo (sep, ItemList);
     m = ModifierCombinationFromQualCombo (q);
+    q = QualComboFree (q);
   } else {
     m = FindBestCombo (sep, ItemList);
   }
@@ -14869,3 +16889,514 @@ NLM_EXTERN Boolean AutoConvertCDSToMiscFeat (SeqFeatPtr cds, Boolean remove_orig
   }
   return rval;
 }
+
+
+NLM_EXTERN SeqEntryPtr GetBestSeqEntryForItem (ValNodePtr vnp)
+{
+  SeqFeatPtr       sfp;
+  SeqDescrPtr      sdp;
+  ObjValNodePtr    ovp;
+  SeqEntryPtr      sep = NULL;
+  BioseqPtr        bsp;
+
+  if (vnp == NULL || vnp->data.ptrvalue == NULL) return NULL;
+
+  if (vnp->choice == OBJ_SEQFEAT) {
+    sfp = vnp->data.ptrvalue;
+    sep = GetBestTopParentForData (sfp->idx.entityID, BioseqFindFromSeqLoc (sfp->location));
+  } else if (vnp->choice == OBJ_SEQDESC) {
+    sdp = vnp->data.ptrvalue;
+    if (sdp->extended != 0) {
+      ovp = (ObjValNodePtr) sdp;
+      if (ovp->idx.parenttype == OBJ_BIOSEQSET) {
+        sep = SeqMgrGetSeqEntryForData (ovp->idx.parentptr);
+      } else if (ovp->idx.parenttype == OBJ_BIOSEQ) {
+        sep = GetBestTopParentForData (ovp->idx.entityID, ovp->idx.parentptr);
+      }
+    }
+  } else if (vnp->choice == OBJ_BIOSEQ) {
+    bsp = (BioseqPtr) vnp->data.ptrvalue;
+    sep = GetBestTopParentForData (bsp->idx.entityID, bsp);
+  } else if (vnp->choice == OBJ_SEQENTRY) {
+    sep = vnp->data.ptrvalue;
+  }
+  return sep;
+}
+
+NLM_EXTERN void AddNewUniqueDescriptors (SeqDescrPtr PNTR new_set, SeqDescrPtr parent_set)
+{
+  SeqDescrPtr sdp, sdp_next, sdp_tmp, sdp_tmp_next;
+  Boolean     found_match;
+
+  if (new_set == NULL || parent_set == NULL) return;
+
+  if (*new_set == NULL) {
+    ValNodeLink (new_set,
+                 AsnIoMemCopy ((Pointer) parent_set,
+                               (AsnReadFunc) SeqDescrAsnRead,
+                               (AsnWriteFunc) SeqDescrAsnWrite));
+  } else {
+    sdp = parent_set;
+    while (sdp != NULL) {
+      sdp_next = sdp->next;
+      sdp->next = NULL;
+      for (sdp_tmp = *new_set, found_match = FALSE;
+           sdp_tmp != NULL && !found_match; 
+           sdp_tmp = sdp_tmp->next) {
+        sdp_tmp_next = sdp_tmp->next;
+        sdp_tmp->next = NULL;
+        if (AsnIoMemComp (sdp, sdp_tmp, (AsnWriteFunc) SeqDescrAsnWrite)) {
+          found_match = TRUE;
+        }
+        sdp_tmp->next = sdp_tmp_next;
+      }
+      if (!found_match) {
+        ValNodeLink (new_set,
+                     AsnIoMemCopy ((Pointer) sdp,
+                                   (AsnReadFunc) SeqDescrAsnRead,
+                                   (AsnWriteFunc) SeqDescrAsnWrite));
+      }
+      sdp->next = sdp_next;
+      sdp = sdp->next;
+    }
+  }
+}
+
+static void AddNewUniqueDescriptorsToSeqEntry (SeqEntryPtr sep, SeqDescrPtr parent_set)
+{
+  BioseqPtr    bsp;
+  BioseqSetPtr bssp;
+
+  if (IS_Bioseq(sep)) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    if (bsp != NULL) {
+      AddNewUniqueDescriptors (&(bsp->descr), parent_set);
+    }
+  } else if (IS_Bioseq_set (sep)) {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    if (bssp != NULL) {
+      AddNewUniqueDescriptors (&(bssp->descr), parent_set);
+    }
+  }
+}
+
+NLM_EXTERN void AddNewUniqueAnnotations (SeqAnnotPtr PNTR new_set, SeqAnnotPtr parent_set)
+{
+  SeqAnnotPtr sap, sap_next, sap_tmp, sap_tmp_next, sap_copy, last_sap;
+  Boolean     found_match;
+
+  if (new_set == NULL || parent_set == NULL) return;
+
+  sap = parent_set;
+  while (sap != NULL) {
+    sap_next = sap->next;
+    sap->next = NULL;
+    last_sap = NULL;
+    for (sap_tmp = *new_set, found_match = FALSE;
+         sap_tmp != NULL && !found_match;
+         sap_tmp = sap_tmp->next) {
+      sap_tmp_next = sap_tmp->next;
+      sap_tmp->next = NULL;
+      if (AsnIoMemComp (sap, sap_tmp, (AsnWriteFunc) SeqAnnotAsnWrite)) {
+        found_match = TRUE;
+      }
+      sap_tmp->next = sap_tmp->next;
+      last_sap = sap_tmp;
+    }
+    if (!found_match) {        
+      sap_copy = (SeqAnnotPtr) AsnIoMemCopy ((Pointer) sap, (AsnReadFunc) SeqAnnotAsnRead, (AsnWriteFunc) SeqAnnotAsnWrite); 
+      if (last_sap == NULL) {
+        *new_set = sap_copy;
+      } else {
+        last_sap->next = sap_copy;
+      }
+    }
+    sap->next = sap_next;
+    sap = sap->next;
+  }
+}
+
+static void AddCategorySeqEntriesToSet (BioseqSetPtr newset, ClickableItemPtr category)
+{
+  ValNodePtr vnp_item;
+  SeqEntryPtr sep, last_sep, prev_sep, remove_sep;
+  BioseqSetPtr bssp, orig_parent;
+  BioseqPtr bsp;
+
+  if (newset == NULL || category == NULL || category->item_list == NULL) return;
+
+  if (category->chosen) {
+    last_sep = newset->seq_set;
+    while (last_sep != NULL && last_sep->next != NULL) {
+      last_sep = last_sep->next;
+    }
+
+    for (vnp_item = category->item_list; vnp_item != NULL; vnp_item = vnp_item->next) {
+      sep = GetBestSeqEntryForItem (vnp_item);
+      if (sep == NULL || sep->data.ptrvalue == NULL) continue;
+      orig_parent = NULL;
+      if (IS_Bioseq (sep)) {
+        bsp = sep->data.ptrvalue;
+        if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
+          orig_parent = bsp->idx.parentptr;
+          bsp->idx.parentptr = NULL;
+        }
+      } else if (IS_Bioseq_set (sep)) {
+        bssp = sep->data.ptrvalue;
+        if (bssp->idx.parenttype == OBJ_BIOSEQSET) {
+          orig_parent = bssp->idx.parentptr;
+          bssp->idx.parentptr = NULL;
+        }
+      } else {
+        continue;
+      }
+         
+      if (orig_parent != NULL) {
+        /* remove this seq-entry from the original parent */
+        prev_sep = NULL;
+        for (remove_sep = orig_parent->seq_set;
+             remove_sep != NULL && remove_sep != sep;
+             remove_sep = remove_sep->next) {
+          prev_sep = remove_sep;
+        }
+        if (remove_sep == sep) {
+          if (prev_sep == NULL) {
+            orig_parent->seq_set = orig_parent->seq_set->next;
+            if (orig_parent->seq_set == NULL) {
+              orig_parent->idx.deleteme = TRUE; 
+            }
+          } else {
+            prev_sep->next = sep->next;
+          }
+        }
+        /* set class type if not already set */
+        if (newset->_class == BioseqseqSet_class_genbank) {
+          newset->_class = orig_parent->_class;
+        }
+      }
+      if (orig_parent != NULL) {
+        /* add descriptors from the orig_parent to the new parent */
+        AddNewUniqueDescriptors (&(newset->descr), orig_parent->descr);
+
+        /* add annotations from the orig_parent to the new parent */
+        AddNewUniqueAnnotations (&(newset->annot), orig_parent->annot);
+      }
+
+      /* add to new parent */
+      sep->next = NULL;
+      if (last_sep == NULL) {
+        newset->seq_set = sep;
+      } else {
+        last_sep->next = sep;
+      }
+      last_sep = sep;
+      SeqMgrLinkSeqEntry (sep, OBJ_BIOSEQSET, newset);
+    }
+  } else {
+    for (vnp_item = category->subcategories; vnp_item != NULL; vnp_item = vnp_item->next) {
+      AddCategorySeqEntriesToSet (newset, vnp_item->data.ptrvalue);
+    }
+  }
+}
+
+static Boolean NeedsNewSet (SeqEntryPtr sep)
+{
+  BioseqSetPtr bssp;
+  while (sep != NULL) {
+    if (IS_Bioseq (sep)) {
+      return TRUE;
+    } else if (IS_Bioseq_set (sep)) {
+      bssp = (BioseqSetPtr) sep->data.ptrvalue;
+      if (bssp != NULL 
+          && (bssp->_class == BioseqseqSet_class_nuc_prot
+          || bssp->_class == BioseqseqSet_class_segset)) {
+        return TRUE;
+      }
+    }
+    sep = sep->next;
+  }
+  return FALSE;
+}
+
+NLM_EXTERN BioseqSetPtr MakeGroupsForUniqueValues
+(BioseqSetPtr bssp, 
+ ValNodePtr   value_lists)
+{
+  ObjMgrDataPtr     omdptop;
+  ObjMgrData        omdata;
+  Uint2             parenttype;
+  Pointer           parentptr;
+  BioseqSetPtr parent_set;
+  SeqEntryPtr  sep, first_new_sep = NULL;
+  SeqEntryPtr  tmp;
+  BioseqSetPtr newset;
+  ValNodePtr   vnp;
+  ClickableItemPtr cip;
+  Uint1        child_class;
+  Uint2        entityID;
+  Boolean      child_became_parent = FALSE;
+
+  if (bssp == NULL) return NULL;
+  entityID = bssp->idx.entityID;
+  
+  sep = SeqMgrGetSeqEntryForData (bssp);
+
+  SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
+  GetSeqEntryParent (sep, &parentptr, &parenttype);
+
+  parent_set = (BioseqSetPtr)(bssp->idx.parentptr);
+
+  if (parent_set == NULL || parent_set->seq_set == NULL) {
+    /* this set has no parent, so make it the parent set, class GenBank,
+     * and create two new sets using the original set class as members of this set
+     */
+    parent_set = bssp;
+    child_class = parent_set->_class;
+    child_became_parent = TRUE;
+  } else {
+    /* we already have a parent set. */
+    child_class = bssp->_class;
+  }
+
+  for (vnp = value_lists; vnp != NULL; vnp = vnp->next) {      
+    cip = (ClickableItemPtr) vnp->data.ptrvalue;
+    if (cip == NULL || (!cip->chosen && ! AnyDiscrepanciesChosen (cip->subcategories))) {
+      continue;
+    }
+
+    newset = BioseqSetNew ();
+    newset->_class = child_class;
+    /* add SeqEntries for this category here */
+    AddCategorySeqEntriesToSet (newset, cip);
+
+    /* check - is any member of the newset also a set? */
+    tmp = newset->seq_set;
+    while (tmp != NULL && IS_Bioseq (tmp)) {
+      tmp = tmp->next;
+    }
+
+    /* add to members for parent_set */
+    tmp = SeqEntryNew ();
+    tmp->choice = 2;
+    tmp->data.ptrvalue = (Pointer) newset;
+
+    tmp->next = parent_set->seq_set;
+    parent_set->seq_set = tmp;
+
+    if (parent_set->idx.deleteme) {
+      parent_set->idx.deleteme = FALSE;
+    }
+    if (first_new_sep == NULL) {
+      first_new_sep = tmp;
+    }
+
+    SeqMgrLinkSeqEntry (tmp, OBJ_BIOSEQSET, parent_set);
+  }
+
+  RestoreSeqEntryObjMgrData (sep, omdptop, &omdata); 
+  DeleteMarkedObjects (entityID, 0, NULL);
+
+  if (child_became_parent) {
+    if (first_new_sep != NULL && NeedsNewSet (first_new_sep->next)) {
+      /* make new set to hold what wasn't moved */
+      newset = BioseqSetNew ();
+      /* contents of set are unmoved sequences */
+      newset->seq_set = first_new_sep->next;
+      /* set class type */
+      newset->_class = parent_set->_class;
+      /* add descriptors from the parent */
+      ValNodeLink (&(newset->descr),
+                   AsnIoMemCopy ((Pointer) parent_set->descr,
+                                 (AsnReadFunc) SeqDescrAsnRead,
+                                 (AsnWriteFunc) SeqDescrAsnWrite));
+
+
+      tmp = SeqEntryNew();
+      tmp->choice = 2;
+      tmp->data.ptrvalue = (Pointer) newset;
+      tmp->next = NULL;
+      first_new_sep->next = tmp;
+      SeqMgrLinkSeqEntry (tmp, OBJ_BIOSEQSET, parent_set);
+    } else {
+      sep = first_new_sep->next;
+      while (sep != NULL) {
+        AddNewUniqueDescriptorsToSeqEntry (sep, parent_set->descr);
+        sep = sep->next;
+      }
+    }
+    /* set parent class to GenBank set */
+    parent_set->_class = BioseqseqSet_class_genbank;
+    /* remove descriptors on parent, they will all have been copied down */
+    parent_set->descr = SeqDescrFree (parent_set->descr);
+  }
+
+  ObjMgrSetDirtyFlag (entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+
+  return parent_set;
+}
+
+
+static void GetBioseqListCallback (BioseqPtr bsp, Pointer userdata)
+{
+  if (bsp != NULL && userdata != NULL && ! ISA_aa (bsp->mol))
+  {
+    ValNodeAddPointer ((ValNodePtr PNTR) userdata, OBJ_BIOSEQ, bsp);
+  }
+}
+
+NLM_EXTERN ValNodePtr PrepareSequenceListForSegregateByNumberOfSets (Int4 num_sets, SeqEntryPtr sep)
+{
+  ValNodePtr cip_list = NULL;
+  ValNodePtr         vnp;
+  CharPtr            fmt = "set contains %d sequences";
+  ValNodePtr         bsp_list = NULL, v_next;
+  Int4               num_bioseqs, num_per_set, num_in_set;
+
+  VisitBioseqsInSep (sep, &bsp_list, GetBioseqListCallback);
+  num_bioseqs = ValNodeLen (bsp_list);
+  num_per_set = num_bioseqs / num_sets;
+  if (num_bioseqs % num_sets > 0) {
+    num_per_set ++;
+  }
+
+  num_in_set = 0;
+  
+  for (vnp = bsp_list; vnp != NULL; vnp = v_next) {
+    v_next = vnp->next;
+    num_in_set ++;
+    if (num_in_set == num_per_set) {
+      vnp->next = NULL;
+      ValNodeAddPointer (&cip_list, 0, NewClickableItem (0, fmt, bsp_list));
+      bsp_list = v_next;
+      num_in_set = 0;
+    }
+  }
+  if (bsp_list != NULL) {
+    ValNodeAddPointer (&cip_list, 0, NewClickableItem (0, fmt, bsp_list));
+    bsp_list = NULL;
+  }
+  return cip_list;
+}
+
+
+NLM_EXTERN ValNodePtr PrepareSequenceListForSegregateByNumberPerSet (Int4 num_per_set, SeqEntryPtr sep)
+{
+  ValNodePtr cip_list = NULL;
+  ValNodePtr         vnp;
+  CharPtr            fmt = "set contains %d sequences";
+  ValNodePtr         bsp_list = NULL, v_next;
+  Int4               num_in_set;
+
+  VisitBioseqsInSep (sep, &bsp_list, GetBioseqListCallback);
+
+  num_in_set = 0;
+  
+  for (vnp = bsp_list; vnp != NULL; vnp = v_next) {
+    v_next = vnp->next;
+    num_in_set ++;
+    if (num_in_set == num_per_set) {
+      vnp->next = NULL;
+      ValNodeAddPointer (&cip_list, 0, NewClickableItem (0, fmt, bsp_list));
+      bsp_list = v_next;
+      num_in_set = 0;
+    }
+  }
+  if (bsp_list != NULL) {
+    ValNodeAddPointer (&cip_list, 0, NewClickableItem (0, fmt, bsp_list));
+    bsp_list = NULL;
+  }
+  return cip_list;
+}
+
+
+NLM_EXTERN void SegregateSetsByNumber (SeqEntryPtr sep, Int4 num_sets)
+{
+  ValNodePtr set_list;
+  BioseqSetPtr bssp;
+
+  if (sep == NULL || !IS_Bioseq_set (sep) || (bssp = (BioseqSetPtr) sep->data.ptrvalue) == NULL) {
+    return;
+  }
+
+  set_list = PrepareSequenceListForSegregateByNumberOfSets (num_sets, sep);
+  ChooseAllDiscrepancies(set_list);
+
+  MakeGroupsForUniqueValues (bssp, set_list);
+
+  FreeClickableList (set_list);
+
+}
+
+
+NLM_EXTERN void SegregateSetsByNumberPerSet (SeqEntryPtr sep, Int4 num_per_set)
+{
+  ValNodePtr set_list;
+  BioseqSetPtr bssp;
+
+  if (sep == NULL || !IS_Bioseq_set (sep) || (bssp = (BioseqSetPtr) sep->data.ptrvalue) == NULL) {
+    return;
+  }
+
+  set_list = PrepareSequenceListForSegregateByNumberPerSet (num_per_set, sep);
+  ChooseAllDiscrepancies(set_list);
+
+  MakeGroupsForUniqueValues (bssp, set_list);
+
+  FreeClickableList (set_list);
+
+}
+
+
+NLM_EXTERN CharPtr CompressSpaces (CharPtr str)
+
+{
+  Char     ch;
+  CharPtr  dst;
+  Char     last;
+  CharPtr  ptr;
+
+  if (str != NULL && str [0] != '\0') {
+    dst = str;
+    ptr = str;
+    ch = *ptr;
+    while (ch != '\0' && ch <= ' ') {
+      ptr++;
+      ch = *ptr;
+    }
+    while (ch != '\0') {
+      *dst = ch;
+      dst++;
+      ptr++;
+      last = ch;
+      ch = *ptr;
+      if (ch != '\0' && ch < ' ') {
+        *ptr = ' ';
+        ch = *ptr;
+      }
+      while (ch != '\0' && last <= ' ' && ch <= ' ') {
+        ptr++;
+        ch = *ptr;
+      }
+    }
+    *dst = '\0';
+    dst = NULL;
+    ptr = str;
+    ch = *ptr;
+    while (ch != '\0') {
+      if (ch != ' ') {
+        dst = NULL;
+      } else if (dst == NULL) {
+        dst = ptr;
+      }
+      ptr++;
+      ch = *ptr;
+    }
+    if (dst != NULL) {
+      *dst = '\0';
+    }
+  }
+  return str;
+}
+
+
diff --git a/api/sqnutils.h b/api/sqnutils.h
index 03a2cb4..d0c01c5 100644
--- a/api/sqnutils.h
+++ b/api/sqnutils.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   9/2/97
 *
-* $Revision: 6.379 $
+* $Revision: 6.483 $
 *
 * File Description: 
 *
@@ -192,6 +192,8 @@ NLM_EXTERN Boolean CheckSeqLocForPartial (SeqLocPtr location, BoolPtr p5ptr, Boo
 NLM_EXTERN void SetSeqLocPartial (SeqLocPtr location, Boolean partial5, Boolean partial3);
 NLM_EXTERN void FreeAllFuzz (SeqLocPtr location);
 NLM_EXTERN Boolean LocationHasNullsBetween (SeqLocPtr location);
+NLM_EXTERN ValNodePtr GetSeqLocPartialSet (SeqLocPtr location);
+NLM_EXTERN void SetSeqLocPartialSet (SeqLocPtr location, ValNodePtr vnp);
 NLM_EXTERN Boolean SeqLocBadSortOrder (BioseqPtr bsp, SeqLocPtr slp);
 NLM_EXTERN Boolean SeqLocMixedStrands (BioseqPtr bsp, SeqLocPtr slp);
 
@@ -216,6 +218,7 @@ NLM_EXTERN SeqFeatPtr LIBCALL GetBestProteinFeatureUnindexed (SeqLocPtr product)
 /* resynchronizes coding regions with product protein bioseq and protein feature */
 
 NLM_EXTERN void ResynchCodingRegionPartials (SeqEntryPtr sep);
+NLM_EXTERN Boolean ResynchCodingRegionPartialsEx (SeqEntryPtr sep, FILE *log_fp);
 
 /* resynchronizes mRNAs with product cDNA bioseq */
 
@@ -254,6 +257,7 @@ NLM_EXTERN void StripFeatIDXrefAsnFilter (AsnIoPtr aip, AsnIoPtr aop);
 NLM_EXTERN void StripSeqDataGapAsnFilter (AsnIoPtr aip, AsnIoPtr aop);
 NLM_EXTERN void StripNewFeatMolInfoFieldsAsnFilter (AsnIoPtr aip, AsnIoPtr aop);
 NLM_EXTERN void StripPCRPrimerAsnFilter (AsnIoPtr aip, AsnIoPtr aop);
+NLM_EXTERN void StripOrgNamePgcodeAsnFilter (AsnIoPtr aip, AsnIoPtr aop);
 NLM_EXTERN void StripGeneRnaPcrAsnFilter (AsnIoPtr aip, AsnIoPtr aop);
     
 
@@ -274,6 +278,7 @@ NLM_EXTERN SqnTagPtr SqnTagParse (CharPtr ttl);
 NLM_EXTERN SqnTagPtr SqnTagFree (SqnTagPtr stp);
 
 NLM_EXTERN CharPtr SqnTagFind (SqnTagPtr stp, CharPtr tag);
+NLM_EXTERN ValNodePtr SqnTagFindMultiple (SqnTagPtr stp, CharPtr tag);
 NLM_EXTERN CharPtr SqnTagFindUnused (SqnTagPtr stp, CharPtr tag);
 
 NLM_EXTERN void ReadTechFromString (CharPtr str, MolInfoPtr mip);
@@ -329,6 +334,11 @@ NLM_EXTERN SeqHistPtr ParseStringIntoSeqHist (
   CharPtr str
 );
 
+NLM_EXTERN void ParseTitleIntoSubmitBlock (
+  SqnTagPtr stp,
+  SubmitBlockPtr sbp
+);
+
 NLM_EXTERN UserObjectPtr ParseTitleIntoTpaAssembly (
   SqnTagPtr stp,
   UserObjectPtr uop
@@ -488,6 +498,10 @@ NLM_EXTERN void PrintQualityScores (BioseqPtr bsp, FILE *fp);
 NLM_EXTERN void TrimSeqGraph (SeqGraphPtr sgp, Int4 num_to_trim, Boolean from_left);
 NLM_EXTERN void TrimQualityScores (BioseqPtr bsp, Int4 num_to_trim, Boolean from_left);
 
+NLM_EXTERN void ReverseSeqGraph (SeqGraphPtr sgp);
+NLM_EXTERN void ReverseQualityScores (BioseqPtr bsp);
+
+
 typedef void (*QualityWriteFunc) (CharPtr buf, Uint4 buflen, Pointer userdata);
 
 NLM_EXTERN void PrintQualityScoresToBuffer (BioseqPtr bsp, Boolean gapIsZero, Pointer userdata, QualityWriteFunc callback);
@@ -597,9 +611,23 @@ require reindexing) */
 
 NLM_EXTERN void BasicSeqEntryCleanup (SeqEntryPtr sep);
 
-/* CleanUpSeqFeat componenet of BasicSeqEntryCleanup, can be called for external features */
+/* cleanup for a single descriptor, after editing */
+NLM_EXTERN void CleanupStringsForOneDescriptor (SeqDescPtr sdp, SeqEntryPtr sep);
+
+/* Selective components of BasicSeqEntryCleanup can be called for QA filtering */
+
+NLM_EXTERN void CleanUpSeqFeat (SeqFeatPtr sfp, Boolean isEmblOrDdbj, Boolean isJscan, Boolean stripSerial, Boolean modernizeFeats, ValNodePtr PNTR publist);
 
-NLM_EXTERN void CleanUpSeqFeat (SeqFeatPtr sfp, Boolean isEmblOrDdbj, Boolean isJscan, Boolean stripSerial, ValNodePtr PNTR publist);
+NLM_EXTERN void CleanUpSeqLoc (SeqLocPtr slp);
+
+NLM_EXTERN void CleanUpPubdescAuthors (PubdescPtr pdp);
+NLM_EXTERN void CleanUpPubdescBody (PubdescPtr pdp, Boolean stripSerial);
+
+NLM_EXTERN void SortSeqEntryQualifiers (SeqEntryPtr sep);
+
+/* BasicSeqAnnotCleanup is for cleaning up contents of separate named Seq-annot objects */
+
+NLM_EXTERN void BasicSeqAnnotCleanup (SeqAnnotPtr sap);
 
 /* CautiousSeqEntryCleanup is a gradual consolidation and replacement of functions in SeriousSeqEntryCleanup,
 which does change the itemID structure, and is intended to be safe for a retrofit of the ID database */
@@ -881,6 +909,8 @@ typedef struct loginfo
 extern LogInfoPtr OpenLog (CharPtr display_title);
 extern LogInfoPtr FreeLog (LogInfoPtr lip);
 
+NLM_EXTERN void FixNonWGSSets (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+
 /* structures and functions for the Discrepancy Report */
 typedef void (*ClickableCallback) (ValNodePtr item_list, Pointer userdata);
 typedef void (*ClickableCallbackDataFree) (Pointer userdata);
@@ -905,8 +935,12 @@ NewClickableItem
  CharPtr         description_fmt,
  ValNodePtr      item_list);
  
+extern ValNodePtr ClickableItemObjectListFree (ValNodePtr vnp);
+extern ValNodePtr ClickableItemObjectListCopy (ValNodePtr orig);
 extern ClickableItemPtr ClickableItemFree (ClickableItemPtr cip);
 extern ValNodePtr FreeClickableList (ValNodePtr list);
+extern Boolean AnyDiscrepanciesChosen (ValNodePtr cip_list);
+NLM_EXTERN void ChooseAllDiscrepancies (ValNodePtr cip_list);
 
 extern int LIBCALLBACK SortVnpByClickableItemDescription (VoidPtr ptr1, VoidPtr ptr2);
 NLM_EXTERN int LIBCALLBACK SortVnpByClickableItemChosen (VoidPtr ptr1, VoidPtr ptr2);
@@ -1006,7 +1040,6 @@ typedef enum {
   DISC_RBS_WITHOUT_GENE,
   DISC_CITSUBAFFIL_CONFLICT,
   DISC_REQUIRED_CLONE,
-  DISC_PLASMODIUM_ISOLATE_NOT_STRAIN,
   DISC_SOURCE_QUALS_ASNDISC,
   DISC_mRNA_ON_WRONG_SEQUENCE_TYPE,
   DISC_RETROVIRIDAE_DNA,
@@ -1017,7 +1050,7 @@ typedef enum {
   DISC_UNPUB_PUB_WITHOUT_TITLE,
   DISC_QUALITY_SCORES,
   DISC_INTERNAL_TRANSCRIBED_SPACER_RRNA,
-  DISC_BACTERIAL_PARTIAL_PROBLEMS,
+  DISC_PARTIAL_PROBLEMS,
   DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_PROBLEMS,
   DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_EXCEPTION,
   DISC_SUSPECT_RRNA_PRODUCTS,
@@ -1036,19 +1069,39 @@ typedef enum {
   DISC_SHORT_RRNA,
   ONCALLER_CHECK_AUTHORITY,
   ONCALLER_CONSORTIUM,
+  ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH,
+  ONCALLER_MULTISRC,
+  ONCALLER_MULTIPLE_CULTURE_COLLECTION,
+  DISC_SEGSETS_PRESENT,
+  DISC_NONWGS_SETS_PRESENT,
+  DISC_FEATURE_LIST,
+  DISC_CATEGORY_HEADER,
+  DISC_MISMATCHED_COMMENTS,
+  DISC_STRAIN_TAXNAME_MISMATCH,
+  DISC_HUMAN_HOST,
+  DISC_BAD_BACTERIAL_GENE_NAME,
+  ONCALLER_ORDERED_LOCATION,
+  ONCALLER_COMMENT_PRESENT,
+  ONCALLER_DEFLINE_ON_SET,
+  ONCALLER_HIV_RNA_INCONSISTENT,
+  SHORT_PROT_SEQUENCES,
+  TEST_EXON_ON_MRNA,
+  TEST_HAS_PROJECT_ID,
   MAX_DISC_TYPE
 } DiscrepancyType;
 
 
 typedef enum {
   eReportTypeDiscrepancy = 1,
-  eReportTypeOnCaller
+  eReportTypeOnCaller,
+  eReportTypeMegaReport
 } EDiscrepancyReportType;
 
 extern Boolean IsTestTypeAppropriateForReportType (Int4 test_type, EDiscrepancyReportType report_type);
 
 extern void PrintDiscrepancyTestList (FILE *fp);
 
+extern void SetDiscrepancyLevels (ValNodePtr discrepancy_list, Int4 level);
 
 extern CharPtr GetDiscrepancyTestConfName (DiscrepancyType dtype);
 extern CharPtr GetDiscrepancyTestSettingName (DiscrepancyType dtype);
@@ -1066,6 +1119,7 @@ extern DiscrepancyConfigPtr DiscrepancyConfigCopy (DiscrepancyConfigPtr dcp);
 extern DiscrepancyConfigPtr ReadDiscrepancyConfig (void);
 extern DiscrepancyConfigPtr ReadDiscrepancyConfigEx (CharPtr report_config_name);
 extern void SaveDiscrepancyConfig (DiscrepancyConfigPtr dcp);
+extern void SaveDiscrepancyConfigEx (DiscrepancyConfigPtr dcp, CharPtr report_name);
 extern void DisableTRNATests (DiscrepancyConfigPtr dcp);
 extern CharPtr SetDiscrepancyReportTestsFromString (CharPtr list, Boolean enable, DiscrepancyConfigPtr dcp);
 extern void ConfigureForBigSequence (DiscrepancyConfigPtr dcp);
@@ -1095,13 +1149,20 @@ extern void AddDiscrepanciesForMissingOrNonUniqueGeneLocusTagsEx (ValNodePtr PNT
 extern void AddDiscrepanciesForMissingOrNonUniqueGeneLocusTags (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
 extern void FindShortIntrons (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
 extern void CheckBioSourceQuals (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
-extern void FindBacterialExtendablePartials (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
+extern void FindExtendablePartials (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
 extern void FindBacterialNonExtendablePartials (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
+NLM_EXTERN void FindMismatchedComments (ValNodePtr PNTR discrepancy_list, ValNodePtr sep_list);
 
 /* autofix functions */
 NLM_EXTERN void MarkOverlappingCDSs (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
 NLM_EXTERN void FixBacterialNonExtendablePartials (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
-NLM_EXTERN void FixBacterialExtendablePartials (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+NLM_EXTERN void FixExtendablePartials (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+NLM_EXTERN void FixMismatchedComments (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+NLM_EXTERN void FixHumanHosts (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+NLM_EXTERN void FixOrderedLocations (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+NLM_EXTERN void OncallerToolPseudoDiscrepanciesFix (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+NLM_EXTERN void OncallerToolFindEcoNoEnvFix (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
+NLM_EXTERN void AddExceptionsToShortIntrons (ValNodePtr item_list, Pointer data, LogInfoPtr lip);
 
 /* structure shared by tbl2asn and discrepancy report functions */
 typedef struct genprodsetdiscrepancylists {
@@ -1172,7 +1233,7 @@ extern CharPtr GetBioseqLabel (BioseqPtr bsp);
 extern CharPtr GetBioseqSetLabel (BioseqSetPtr bssp);
 
 NLM_EXTERN ValNodePtr ValNodeDupStringList (ValNodePtr vnp);
-
+NLM_EXTERN ValNodePtr ValNodeDupIntList (ValNodePtr vnp);
 
 typedef enum {
   eLocusTagErrorBadFormat,
@@ -1218,6 +1279,8 @@ NLM_EXTERN GlobalDiscrepReportPtr GlobalDiscrepReportFree (GlobalDiscrepReportPt
 NLM_EXTERN void AddSeqEntryToGlobalDiscrepReport (SeqEntryPtr sep, GlobalDiscrepReportPtr g, CharPtr filename);
 NLM_EXTERN void WriteGlobalDiscrepancyReport (GlobalDiscrepReportPtr g, FILE *fp);
 
+NLM_EXTERN Boolean CollectionDateIsInTheFuture (CharPtr name);
+NLM_EXTERN Boolean CollectionDateIsValid (CharPtr name);
 
 /* for the Barcode Discrepancy Test */
 typedef enum {
@@ -1226,6 +1289,10 @@ typedef enum {
   eBarcodeTest_Country,
   eBarcodeTest_SpecimenVoucher,
   eBarcodeTest_PercentN,
+  eBarcodeTest_CollectionDate,
+  eBarcodeTest_OrderAssignment,
+  eBarcodeTest_LowTrace,
+  eBarcodeTest_FrameShift,
   eBarcodeTest_LAST
 } EBarcodeTest;
 
@@ -1267,11 +1334,17 @@ extern ValNodePtr GetBarcodeDiscrepancies (ValNodePtr sep_list, BarcodeTestConfi
 extern ValNodePtr GetBarcodeFailedAccessionList (SeqEntryPtr sep, BarcodeTestConfigPtr cfg);
 extern ValNodePtr GetBarcodePassFail (SeqEntryPtr sep, BarcodeTestConfigPtr cfg);
 NLM_EXTERN CharPtr GetBarcodeTestFailureReasons (BarcodeTestResultsPtr res);
+NLM_EXTERN BarcodeTestResultsPtr BarcodeTestResultsForBioseq (BioseqPtr bsp, BarcodeTestConfigPtr cfg);
 /* This one lists passes and failures, with reasons for failures */
 extern void WriteBarcodeTestComprehensive (FILE *fp, ValNodePtr results_list);
 extern void WriteBarcodeDiscrepancies (FILE *fp, ValNodePtr results_list);
+extern void WriteBarcodeFailureReport (FILE *fp, ValNodePtr results_list);
 extern void WriteBarcodeTestCompliance (FILE *fp, ValNodePtr results_list);
+extern void WriteBarcodeTestComplianceEx (FILE *fp, ValNodePtr results_list, Boolean low_trace_fail);
 extern void WriteBarcodeTagTable (FILE *fp, ValNodePtr results_list);
+NLM_EXTERN Boolean HasLowTrace (BioseqPtr bsp);
+NLM_EXTERN Boolean IsIBOL (BioseqPtr bsp);
+
 NLM_EXTERN Boolean 
 BarcodeValidateOneSeqEntry 
 (FILE *ofp,
@@ -1287,6 +1360,9 @@ extern void ApplyBarcodeTech (FILE *fp, ValNodePtr results_list);
 extern Boolean PassBarcodeTests (BarcodeTestResultsPtr res);
 extern Boolean HasBARCODETech (BioseqPtr bsp);
 NLM_EXTERN void ApplyBarcodeKeywordToBioseq (BioseqPtr bsp);
+NLM_EXTERN Boolean BioseqHasBarcodeKeyword (BioseqPtr bsp);
+NLM_EXTERN ValNodePtr GetBarcodeLowTraceList (SeqEntryPtr sep);
+NLM_EXTERN void RemoveBarcodeKeywordsFromObjectList (FILE *fp, ValNodePtr object_list);
 extern Int4 CountPolymorphismsInBioseq (BioseqPtr bsp);
 
 
@@ -1338,6 +1414,7 @@ extern Int4 NcrnaOTHER;
 extern Boolean IsStringInNcRNAClassList (CharPtr str);
 extern ValNodePtr ListFeaturesInLocation (BioseqPtr bsp, SeqLocPtr slp, Uint1 seqfeatChoice, Uint1 featdefChoice);
 extern ValNodePtr ListCodingRegionsContainedInSourceFeatures (SeqEntryPtr sep);
+extern ValNodePtr ListFeaturesOverlappingLocationEx (BioseqPtr bsp, SeqLocPtr slp, Uint1 seqfeatChoice, Uint1 featdefChoice, ValNodePtr constraint);
 extern ValNodePtr ListFeaturesOverlappingLocation (BioseqPtr bsp, SeqLocPtr slp, Uint1 seqfeatChoice, Uint1 featdefChoice);
 
 extern void ConvertSourceFeatDescProc (SeqFeatPtr sfp, Pointer userdata);
@@ -1350,6 +1427,9 @@ FixCapitalizationInElement
  Boolean      bShortWords,
  Boolean      bApostrophes);
 
+NLM_EXTERN void FixCapitalizationInAuthor (AuthorPtr pAuthor);
+NLM_EXTERN void FixCapsInPubAffil (AffilPtr affil);
+
 NLM_EXTERN void FixAffiliationShortWordsInElement (CharPtr PNTR pEl);
 
 NLM_EXTERN void FixAbbreviationsInElement (CharPtr PNTR pEl);
@@ -1362,14 +1442,19 @@ NLM_EXTERN Int4 GetDeltaSeqLen (DeltaSeqPtr dsp);
 
 typedef SeqAlignPtr (*GlobalAlignFunc) PROTO ((BioseqPtr, BioseqPtr, BoolPtr));
 
+typedef enum {
+  eAdjustFeatForGap_unknown_gaps = 0x01,
+  eAdjustFeatForGap_known_gaps = 0x02,
+  eAdjustFeatForGap_make_partial = 0x04,
+  eAdjustFeatForGap_partial_for_pseudo = 0x08,
+  eAdjustFeatForGap_trim_ends = 0x10,
+  eAdjustFeatForGap_split_internal = 0x20,
+  eAdjustFeatForGap_split_in_intron = 0x40
+} EAdjustFeatForGap;
+
 typedef struct adjustfeatforgap {
   ValNodePtr feature_list;
-  Boolean    unknown_gaps;
-  Boolean    known_gaps;
-  Boolean    make_partial;
-  Boolean    partial_for_pseudo;
-  Boolean    trim_ends;
-  Boolean    split_internal;
+  Uint4      options;
   GlobalAlignFunc align_func;
   ValNodePtr features_in_gap;
 } AdjustFeatForGapData, PNTR AdjustFeatForGapPtr;
@@ -1380,8 +1465,7 @@ NLM_EXTERN void
 LocationContainsGaps
 (SeqLocPtr slp,
  BioseqPtr bsp,
- Boolean   unknown_gaps,
- Boolean   known_gaps,
+ Uint4     options,
  BoolPtr   terminal_gaps,
  BoolPtr   internal_gaps,
  BoolPtr   entirely_in_gap);
@@ -1447,7 +1531,7 @@ NLM_EXTERN ValNodePtr ReportConsensusMatchForBioseqSeqHist (BioseqPtr bsp);
 NLM_EXTERN ValNodePtr ReportGapsInSeqHistAlignmentForBioseq (BioseqPtr bsp);
 NLM_EXTERN ValNodePtr ReportGapsInSeqHistAlignmentsForIdsList (ValNodePtr list);
 
-NLM_EXTERN void ConvertLocalIdsToTSAIds (SeqEntryPtr sep);
+NLM_EXTERN void ConvertLocalIdsToTSAIds (SeqEntryPtr sep, CharPtr suffix);
 NLM_EXTERN void ConvertLocalIdsToBarcodeIds (SeqEntryPtr sep);
 
 NLM_EXTERN ValNodePtr MakeTokensFromLine (CharPtr line);
@@ -1464,12 +1548,14 @@ typedef enum {
   RemovableIntron,
   Removable5UTR,
   Removable3UTR,
+  RemovableuORF,
   RemovableCDS,
   RemovablePromoter,
   RemovableLTR,
   RemovableNoncodingProductFeat,
   RemovableMobileElement,
   RemovablePrecursorRNA,
+  RemovablencRNA,
   NumRemovableItems
 } RemovableList;
 NLM_EXTERN CharPtr GetRemovableItemName (Int4 i);
@@ -1477,7 +1563,9 @@ NLM_EXTERN CharPtr GetRemovableItemName (Int4 i);
 typedef enum {
   DEFLINE_USE_FEATURES = 1,
   DEFLINE_COMPLETE_SEQUENCE,
-  DEFLINE_COMPLETE_GENOME
+  DEFLINE_COMPLETE_GENOME,
+  DEFLINE_PARTIAL_GENOME,
+  DEFLINE_SEQUENCE
 } DefLineType;
 
 typedef struct deflinefeaturerequestlist {
@@ -1619,8 +1707,12 @@ typedef struct organismdescriptionmodifiers {
   Int4     clone_isolate_HIV_rule_num;
   Boolean  use_modifiers;
   Boolean  allow_semicolon_in_modifier;
+  Boolean  allow_mod_at_end_of_taxname;
 } OrganismDescriptionModifiers, PNTR OrganismDescriptionModifiersPtr;
 
+NLM_EXTERN Boolean ShouldExcludeSp (SeqEntryPtr sep);
+NLM_EXTERN void InitOrganismDescriptionModifiers(OrganismDescriptionModifiersPtr odmp, SeqEntryPtr sep);
+
 /* These values are used for the clone_isolate_HIV_rule_num value in OrganismDescriptionModifiers */
 typedef enum {
   clone_isolate_HIV_rule_prefer_clone = 1,
@@ -1649,6 +1741,8 @@ extern void TestFindBestQualCombo (FILE *fp);
 
 NLM_EXTERN CharPtr MergeValNodeStrings (ValNodePtr list, Boolean useReturn);
 
+NLM_EXTERN ValNodePtr FindExactStringListMatch (ValNodePtr list, CharPtr value);
+
 NLM_EXTERN void BuildDefLineFeatClauseList 
 ( SeqEntryPtr sep,
   Uint2 entityID,
@@ -1680,13 +1774,31 @@ AutoDefForSeqEntry
  Boolean alternate_splice_flag,
  Boolean gene_cluster_opp_strand);
 
+NLM_EXTERN void AddPopsetTitles 
+(SeqEntryPtr sep,
+ DeflineFeatureRequestListPtr feature_requests,
+ Int2 product_flag,
+ Boolean alternate_splice_flag,
+ Boolean gene_cluster_opp_strand);
+
+NLM_EXTERN void RemovePopsetTitles(SeqEntryPtr sep); 
+
+typedef struct popsetretrostat {
+  Int4 feature_clause;
+  Int4 common_title;
+  Int4 uncalculatable; 
+  Boolean title_added;
+} PopSetRetroStatData, PNTR PopSetRetroStatPtr;
+
+NLM_EXTERN void PopSetAutoDefRetro (SeqEntryPtr sep, PopSetRetroStatPtr stat);
+
 NLM_EXTERN Boolean IsSpName (CharPtr taxName);
 
 #define DEFAULT_ORGANELLE_CLAUSE 10
 NLM_EXTERN BioSourcePtr GetBiopForBsp (BioseqPtr bsp);
 NLM_EXTERN Boolean IsLocAInBonSameStrand (SeqLocPtr slp1, SeqLocPtr slp2);
 NLM_EXTERN void CleanUpTaxName (CharPtr taxName, Boolean keep_in_paren);
-NLM_EXTERN Boolean UseOrgModifier (OrgModPtr mod, CharPtr   taxName);
+NLM_EXTERN Boolean UseOrgModifier (OrgModPtr mod, CharPtr taxName, Boolean allow_at_end);
 NLM_EXTERN void AddModifierLabel 
 ( Boolean use_labels,
   Boolean is_orgmod,
@@ -1694,14 +1806,22 @@ NLM_EXTERN void AddModifierLabel
   CharPtr modifier_text);
 NLM_EXTERN Boolean LIBCALLBACK IsMobileElement (SeqFeatPtr sfp);
 NLM_EXTERN void RemoveNucProtSetTitles (SeqEntryPtr sep);
+NLM_EXTERN void RemoveProteinTitles (SeqEntryPtr sep);
+NLM_EXTERN void SetAutoDefIDModifiers (ModifierItemLocalPtr modList);
 
 
 NLM_EXTERN ValNodePtr ReadTabTableFromFile (FILE *fp);
 NLM_EXTERN ValNodePtr FlipTabTableAxes (ValNodePtr row_list);
 NLM_EXTERN ValNodePtr FreeTabTable (ValNodePtr row_list);
+NLM_EXTERN void WriteTabTableToFile (ValNodePtr table, FILE *fp);
 NLM_EXTERN ValNodePtr CountTabTableBlanks (ValNodePtr row_list);
 NLM_EXTERN ValNodePtr ScanTabTableForSpecialCharacters (ValNodePtr row_list);
 NLM_EXTERN void RemoveQuotesFromTabTable (ValNodePtr row_list);
+NLM_EXTERN void ReparseTabTableConvertFirstSpaceToTab (ValNodePtr row_list);
+NLM_EXTERN void ReparseTabTableConvertMultiSpaceToTab (ValNodePtr row_list);
+NLM_EXTERN void CombineTabTableColumns (ValNodePtr row_list, ValNodePtr column_pos, CharPtr delimiter);
+NLM_EXTERN void AddTextToTabTableColumn (ValNodePtr row_list, Int4 col, CharPtr text, Uint2 existing_text);
+NLM_EXTERN ValNodePtr ReadOneColumnList (CharPtr line);
 
 NLM_EXTERN void SpecialCharFindWithContext (CharPtr PNTR strp, Pointer userdata, BoolPtr did_find, BoolPtr did_change);
 NLM_EXTERN ValNodePtr FreeContextList (ValNodePtr context_list);
@@ -1771,6 +1891,8 @@ NLM_EXTERN CharPtr GetMonthAbbrev (Int4 n);
 NLM_EXTERN Int4 GetDaysInMonth (Int4 n);
 
 NLM_EXTERN ValNodePtr CreateStructuredCommentsFromFile (FILE *fp, SeqEntryPtr sep, Boolean apply_to_all);
+NLM_EXTERN void AddDatabaseNameToStructuredComment (UserObjectPtr uop, CharPtr dbname);
+NLM_EXTERN ValNodePtr CreateStructuredCommentTableFromSeqEntry (SeqEntryPtr sep);
 
 #define ALNMGR_GAP           -2
 #define ALNMGR_ROW_UNDEFINED -1
@@ -1821,6 +1943,82 @@ NLM_EXTERN void RemoveConsortiumFromPub (PubPtr pub);
 NLM_EXTERN Int4 Extend5PartialSeqIntToEndOrGap (SeqIntPtr sint, BioseqPtr bsp, Boolean short_only);
 NLM_EXTERN Int4 Extend3PartialSeqIntToEndOrGap (SeqIntPtr sint, BioseqPtr bsp, Boolean short_only);
 NLM_EXTERN Int4 ExtendSeqLocToEndOrGap (SeqLocPtr slp, BioseqPtr bsp, Boolean end5);
+NLM_EXTERN FloatLo PercentNInBioseq (BioseqPtr bsp, Boolean include_gaps);
+
+NLM_EXTERN SeqEntryPtr GetBestSeqEntryForItem (ValNodePtr vnp);
+NLM_EXTERN void AddNewUniqueDescriptors (SeqDescrPtr PNTR new_set, SeqDescrPtr parent_set);
+NLM_EXTERN void AddNewUniqueAnnotations (SeqAnnotPtr PNTR new_set, SeqAnnotPtr parent_set);
+NLM_EXTERN BioseqSetPtr MakeGroupsForUniqueValues (BioseqSetPtr bssp, ValNodePtr value_lists);
+NLM_EXTERN ValNodePtr PrepareSequenceListForSegregateByNumberOfSets (Int4 num_sets, SeqEntryPtr sep);
+NLM_EXTERN void SegregateSetsByNumber (SeqEntryPtr sep, Int4 num_sets);
+NLM_EXTERN ValNodePtr PrepareSequenceListForSegregateByNumberPerSet (Int4 num_per_set, SeqEntryPtr sep);
+NLM_EXTERN void SegregateSetsByNumberPerSet (SeqEntryPtr sep, Int4 num_per_set);
+
+NLM_EXTERN ValNodePtr CreateStructuredCommentsFromRow (ValNodePtr header, ValNodePtr values, CharPtr id_str, ValNodePtr PNTR err_list);
+
+NLM_EXTERN CharPtr CompressSpaces (CharPtr str);
+
+NLM_EXTERN void MergeAdjacentAnnotsInList (SeqAnnotPtr sap);
+
+NLM_EXTERN Boolean GetsDocsumTitle(Uint1 set_class);
+NLM_EXTERN void PromoteCommonTitlesToSet (SeqEntryPtr sep);
+
+NLM_EXTERN void SetDescriptorPropagate (BioseqSetPtr bssp);
+NLM_EXTERN Boolean RemoveDuplicateNestedSetsForEntityID (Uint2 entityID);
+
+NLM_EXTERN void AddStructuredCommentKeywords (Uint2 entityID);
+NLM_EXTERN CharPtr KeywordForStructuredCommentName (UserObjectPtr uop);
+NLM_EXTERN Boolean HasKeywordForStructuredCommentName (BioseqPtr bsp, UserObjectPtr uop);
+NLM_EXTERN void RemoveStructuredCommentKeywords (Uint2 entityID);
+
+NLM_EXTERN void ParseTaxNameToQuals (OrgRefPtr org, TextFsaPtr tags);
+
+NLM_EXTERN ValNodePtr GetLocusTagPrefixList (SeqEntryPtr sep);
+
+NLM_EXTERN Boolean IsProductNameOk (CharPtr product_name);
+extern void FindSuspectProductNamesInNameList (FILE *input_file, FILE *output_file);
+
+NLM_EXTERN SeqEntryPtr ReadFilteredAsn (FILE *fp, Boolean is_binary, CharPtr accn_list, Uint2Ptr entityIDptr);
+NLM_EXTERN void ReintegrateFilteredAsn (SeqEntryPtr sep, FILE *orig_file, FILE *output, Boolean is_binary);
+
+typedef struct descstream {
+  SeqDescPtr orig;
+  SeqDescPtr replace;
+  SeqIdPtr   owners;
+  CharPtr    text;
+  Int4       num_dependent;
+} DescStreamData, PNTR DescStreamPtr;
+
+NLM_EXTERN DescStreamPtr DescStreamNew (SeqDescPtr sdp, BioseqPtr parent);
+NLM_EXTERN DescStreamPtr DescStreamFree (DescStreamPtr ds);
+NLM_EXTERN ValNodePtr DescStreamListFree (ValNodePtr vnp);
+
+NLM_EXTERN ValNodePtr StreamAsnForDescriptors (FILE *fp, Boolean is_binary, Boolean is_batch, Boolean is_submit, SeqIdPtr PNTR sip_list);
+NLM_EXTERN void WriteAsnWithReplacedDescriptors (ValNodePtr desc_stream_list, FILE *orig_file, FILE *output, Boolean is_binary, Boolean is_batch, Boolean is_submit);
+
+extern Boolean ParseCodeBreak (SeqFeatPtr sfp, CharPtr val, Int4 offset);
+
+NLM_EXTERN void CleanupOneSeqFeat (SeqFeatPtr sfp);
+
+NLM_EXTERN Uint1 GetSpecialPlastidGenCode (
+  CharPtr taxname,
+  CharPtr lineage
+);
+
+
+NLM_EXTERN Boolean TrimPrimerSeqJunkInSeqEntry (SeqEntryPtr sep, FILE *log_fp);
+NLM_EXTERN Boolean FixUsaAndStateAbbreviations (Uint2 entityID, FILE *log_fp);
+NLM_EXTERN Boolean TrimStopsFromCompleteCodingRegions (SeqEntryPtr sep, FILE *log_fp);
+NLM_EXTERN void AdjustSeqEntryForConsensusSplice (SeqEntryPtr sep);
+NLM_EXTERN Boolean AdjustSeqEntryForConsensusSpliceEx (SeqEntryPtr sep, FILE *log_fp);
+
+NLM_EXTERN void 
+FixCapitalizationInTitle 
+(CharPtr PNTR pTitle,
+ Boolean      first_is_upper,
+ ValNodePtr   org_names);
+
+NLM_EXTERN Int4 ConvertCommentsWithSpacesToStructuredCommentsForSeqEntry (SeqEntryPtr sep);
 
 
 #ifdef __cplusplus
diff --git a/api/subutil.c b/api/subutil.c
index f52d0cb..572c23b 100644
--- a/api/subutil.c
+++ b/api/subutil.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 11/3/93
 *
-* $Revision: 6.78 $
+* $Revision: 6.87 $
 *
 * File Description: Utilities for creating ASN.1 submissions
 *
@@ -4394,7 +4394,7 @@ NLM_EXTERN void AddAccessionToRefGeneTrackUserObject (UserObjectPtr uop, CharPtr
   UserFieldPtr  last;
   UserFieldPtr  prev = NULL;
   ObjectIdPtr   oip;
-  UserFieldPtr  ufp;
+  UserFieldPtr  ufp = NULL;
 
   if (uop == NULL || field == NULL) return;
   oip = uop->type;
@@ -5062,6 +5062,55 @@ NLM_EXTERN UserObjectPtr CreateTpaAssemblyUserObject (void)
   return uop;
 }
 
+
+
+NLM_EXTERN UserFieldPtr CreateTPAAssemblyAccessionField (CharPtr accn)
+{
+  UserFieldPtr ufp;
+  ObjectIdPtr  oip;
+
+  ufp = UserFieldNew ();
+  oip = ObjectIdNew ();
+  oip->str = StringSave ("accession");
+  ufp->label = oip;
+  ufp->choice = 1; /* visible string */
+  ufp->data.ptrvalue = (Pointer) StringSave (accn);
+
+  return ufp;
+}
+
+NLM_EXTERN UserFieldPtr CreateTPAAssemblyFromField (Int4 from)
+{
+  UserFieldPtr ufp;
+  ObjectIdPtr  oip;
+
+  ufp = UserFieldNew ();
+  oip = ObjectIdNew ();
+  oip->str = StringSave ("from");
+  ufp->label = oip;
+  ufp->choice = 2; /* int */
+  ufp->data.intvalue = from;
+
+  return ufp;
+}
+
+
+NLM_EXTERN UserFieldPtr CreateTPAAssemblyToField (Int4 to)
+{
+  UserFieldPtr ufp;
+  ObjectIdPtr  oip;
+
+  ufp = UserFieldNew ();
+  oip = ObjectIdNew ();
+  oip->str = StringSave ("to");
+  ufp->label = oip;
+  ufp->choice = 2; /* int */
+  ufp->data.intvalue = to;
+
+  return ufp;
+}
+
+
 NLM_EXTERN void AddAccessionToTpaAssemblyUserObject (UserObjectPtr uop, CharPtr accn, Int4 from, Int4 to)
 
 {
@@ -5094,34 +5143,19 @@ NLM_EXTERN void AddAccessionToTpaAssemblyUserObject (UserObjectPtr uop, CharPtr
 
   if (curr == NULL || curr->choice != 11) return;
 
-  ufp = UserFieldNew ();
-  oip = ObjectIdNew ();
-  oip->str = StringSave ("accession");
-  ufp->label = oip;
-  ufp->choice = 1; /* visible string */
-  ufp->data.ptrvalue = (Pointer) StringSave (accn);
+  ufp = CreateTPAAssemblyAccessionField(accn);
 
   curr->data.ptrvalue = (Pointer) ufp;
   prev = ufp;
 
   if (from == 0 && to == 0) return;
 
-  ufp = UserFieldNew ();
-  oip = ObjectIdNew ();
-  oip->str = StringSave ("from");
-  ufp->label = oip;
-  ufp->choice = 2; /* int */
-  ufp->data.intvalue = from;
+  ufp = CreateTPAAssemblyFromField(from);
 
   prev->next = ufp;
   prev = ufp;
 
-  ufp = UserFieldNew ();
-  oip = ObjectIdNew ();
-  oip->str = StringSave ("to");
-  ufp->label = oip;
-  ufp->choice = 2; /* int */
-  ufp->data.intvalue = to;
+  ufp = CreateTPAAssemblyToField (to);
 
   prev->next = ufp;
 }
@@ -5489,6 +5523,59 @@ NLM_EXTERN void AddProbeDBIDsToDBLinkUserObject (
   curr->data.ptrvalue = (Pointer) cpp;
 }
 
+NLM_EXTERN void AddSeqReadArchiveIDsToDBLinkUserObject (
+  UserObjectPtr uop,
+  Int4 num,
+  CharPtr PNTR values
+)
+
+{
+  CharPtr PNTR   cpp;
+  UserFieldPtr   curr;
+  Int4           i;
+  UserFieldPtr   prev = NULL;
+  ObjectIdPtr    oip;
+
+  if (uop == NULL || values == NULL) return;
+  oip = uop->type;
+  if (oip == NULL || StringICmp (oip->str, "DBLink") != 0) return;
+
+  for (curr = uop->data; curr != NULL; curr = curr->next) {
+    oip = curr->label;
+    if (oip != NULL && StringICmp (oip->str, "Sequence Read Archive") == 0) {
+      break;
+    }
+    prev = curr;
+  }
+
+  if (curr == NULL) {
+    curr = UserFieldNew ();
+    oip = ObjectIdNew ();
+    oip->str = StringSave ("Sequence Read Archive");
+    curr->label = oip;
+    curr->choice = 7; /* sequence of string */
+
+    /* link new set at end of list */
+
+    if (prev != NULL) {
+      prev->next = curr;
+    } else {
+      uop->data = curr;
+    }
+  }
+
+  if (curr == NULL || curr->choice != 7) return;
+
+  cpp = (CharPtr PNTR) MemNew (sizeof (CharPtr) * (num));
+  if (cpp == NULL) return;
+
+  curr->num = num;
+  for (i = 0; i < num; i++) {
+    cpp [i] = StringSaveNoNull (values [i]);
+  }
+  curr->data.ptrvalue = (Pointer) cpp;
+}
+
 NLM_EXTERN UserObjectPtr CreateNcbiCleanupUserObject (
   void
 )
@@ -5575,12 +5662,48 @@ NLM_EXTERN void AddIntegerToNcbiCleanupUserObject (
   }
 }
 
+static void GetNcbiCleanupDescr (
+  SeqDescrPtr sdp,
+  Pointer userdata
+)
+
+{
+  ObjectIdPtr        oip;
+  UserObjectPtr      uop;
+  UserObjectPtr PNTR uopp;
+
+  if (sdp->choice != Seq_descr_user) return;
+  uop = (UserObjectPtr) sdp->data.ptrvalue;
+  if (uop == NULL) return;
+
+  oip = uop->type;
+  if (oip == NULL || StringICmp (oip->str, "NcbiCleanup") != 0) return;
+  uopp = (UserObjectPtr PNTR) userdata;
+  if (uopp == NULL) return;
+  *uopp = uop;
+}
+
+NLM_EXTERN UserObjectPtr FindNcbiCleanupUserObject (
+  SeqEntryPtr sep
+)
+
+{
+  UserObjectPtr  uop = NULL;
+
+  if (sep == NULL) return NULL;
+
+  VisitDescriptorsOnSep (sep, (Pointer) &uop, GetNcbiCleanupDescr);
+
+  return uop;
+}
+
 static void ClearNcbiCleanupDescr (
   SeqDescrPtr sdp,
   Pointer userdata
 )
 
 {
+  BoolPtr        bp;
   ObjectIdPtr    oip;
   ObjValNodePtr  ovp;
   UserObjectPtr  uop;
@@ -5593,7 +5716,20 @@ static void ClearNcbiCleanupDescr (
   if (sdp->extended != 0) {
     ovp = (ObjValNodePtr) sdp;
     ovp->idx.deleteme = TRUE;
+    bp = (BoolPtr) userdata;
+    if (bp != NULL) {
+      *bp = TRUE;
   }
+  }
+}
+
+static void ClearSeqAnnotCleanupObj (
+  SeqAnnotPtr sap,
+  Pointer userdata
+)
+
+{
+  RemoveAllSeqAnnotCleanupUserObjs (sap);
 }
 
 NLM_EXTERN void RemoveAllNcbiCleanupUserObjects (
@@ -5601,9 +5737,77 @@ NLM_EXTERN void RemoveAllNcbiCleanupUserObjects (
 )
 
 {
+  Boolean  do_delete = FALSE;
   if (sep == NULL) return;
 
-  VisitDescriptorsInSep (sep, NULL, ClearNcbiCleanupDescr);
+  VisitDescriptorsInSep (sep, (Pointer) &do_delete, ClearNcbiCleanupDescr);
+  VisitAnnotsInSep (sep, NULL, ClearSeqAnnotCleanupObj);
+  if (do_delete) {
   DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
+  }
+}
+
+static Boolean IsAnnotDescCleanupUserObj (
+  AnnotDescrPtr adp
+)
+
+{
+  ObjectIdPtr    oip;
+  UserObjectPtr  uop;
+
+  if (adp->choice != Annot_descr_user) return FALSE;
+  uop = (UserObjectPtr) adp->data.ptrvalue;
+  if (uop == NULL) return FALSE;
+  oip = uop->type;
+  if (oip == NULL) return FALSE;
+  if (StringICmp (oip->str, "NcbiCleanup") == 0) return TRUE;
+
+  return FALSE;
+}
+
+NLM_EXTERN UserObjectPtr FindSeqAnnotCleanupUserObj (
+  SeqAnnotPtr sap
+)
+
+{
+  AnnotDescrPtr  adp;
+  UserObjectPtr  uop;
+
+  if (sap == NULL) return NULL;
+
+  for (adp = sap->desc; adp != NULL; adp = adp->next) {
+    if (IsAnnotDescCleanupUserObj (adp)) {
+      uop = (UserObjectPtr) adp->data.ptrvalue;
+      return uop;
+    }
+  }
+
+  return NULL;
+}
+
+NLM_EXTERN void RemoveAllSeqAnnotCleanupUserObjs (
+  SeqAnnotPtr sap
+)
+
+{
+  AnnotDescrPtr       adp;
+  AnnotDescrPtr       next;
+  AnnotDescrPtr PNTR  prev;
+
+  if (sap == NULL) return;
+
+  prev = &(sap->desc);
+  adp = sap->desc;
+  while (adp != NULL) {
+    next = adp->next;
+    if (IsAnnotDescCleanupUserObj (adp)) {
+      *prev = adp->next;
+      adp->next = NULL;
+      AnnotDescFree (adp);
+    } else {
+      prev = (AnnotDescrPtr PNTR) &(adp->next);
+    }
+    adp = next;
+  }
 }
 
diff --git a/api/subutil.h b/api/subutil.h
index 30c22e4..7dbad98 100644
--- a/api/subutil.h
+++ b/api/subutil.h
@@ -31,7 +31,7 @@
 *   
 * Version Creation Date: 11/3/93
 *
-* $Revision: 6.73 $
+* $Revision: 6.78 $
 *
 * File Description: Utilities for creating ASN.1 submissions
 *
@@ -1349,6 +1349,10 @@ NLM_EXTERN Boolean MakeRNAFeature (
 #define RNA_TYPE_rRNA   4
 #define RNA_TYPE_snRNA  5
 #define RNA_TYPE_scRNA  6
+#define RNA_TYPE_snoRNA 7
+#define RNA_TYPE_ncRNA  8
+#define RNA_TYPE_tmRNA  9
+#define RNA_TYPE_misc_RNA 10
 #define RNA_TYPE_other  255
            
 /******************************************************************
@@ -1507,6 +1511,10 @@ NLM_EXTERN UserFieldPtr FindModelEvidenceField (
 NLM_EXTERN UserObjectPtr CreateTpaAssemblyUserObject (
   void
 );
+NLM_EXTERN UserFieldPtr CreateTPAAssemblyAccessionField (CharPtr accn);
+NLM_EXTERN UserFieldPtr CreateTPAAssemblyFromField (Int4 from);
+NLM_EXTERN UserFieldPtr CreateTPAAssemblyToField (Int4 to);
+
 NLM_EXTERN void AddAccessionToTpaAssemblyUserObject (
   UserObjectPtr uop,
   CharPtr accn,
@@ -1571,6 +1579,12 @@ NLM_EXTERN void AddProbeDBIDsToDBLinkUserObject (
   CharPtr PNTR values
 );
 
+NLM_EXTERN void AddSeqReadArchiveIDsToDBLinkUserObject (
+  UserObjectPtr uop,
+  Int4 num,
+  CharPtr PNTR values
+);
+
 /* NcbiCleanup user object for SeriousSeqEntryCleanup time/version stamp */
 
 NLM_EXTERN UserObjectPtr CreateNcbiCleanupUserObject (
@@ -1589,10 +1603,26 @@ NLM_EXTERN void AddIntegerToNcbiCleanupUserObject (
   Int4 num
 );
 
+/* FindNcbiCleanupUserObject returns user object on top Seq-entry */
+
+NLM_EXTERN UserObjectPtr FindNcbiCleanupUserObject (
+  SeqEntryPtr sep
+);
+
 NLM_EXTERN void RemoveAllNcbiCleanupUserObjects (
   SeqEntryPtr sep
 );
 
+/* Also can put NcbiCleanupUserObject on Seq-annot Annot-desc */
+
+NLM_EXTERN UserObjectPtr FindSeqAnnotCleanupUserObj (
+  SeqAnnotPtr sap
+);
+
+NLM_EXTERN void RemoveAllSeqAnnotCleanupUserObjs (
+  SeqAnnotPtr sap
+);
+
 
 #ifdef __cplusplus
 }
diff --git a/api/tofasta.c b/api/tofasta.c
index 9e8b7da..58797c4 100644
--- a/api/tofasta.c
+++ b/api/tofasta.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 7/12/91
 *
-* $Revision: 6.203 $
+* $Revision: 6.219 $
 *
 * File Description:  various sequence objects to fasta output
 *
@@ -142,8 +142,8 @@ Int4 GetOrderBySeqId(Int4 choice, Boolean is_prot)
 void SeqEntryFasta (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 {
   FastaPtr tfa;
-  BioseqPtr bsp;
-  BioseqSetPtr bssp;
+  BioseqPtr bsp = NULL;
+  BioseqSetPtr bssp = NULL;
   MyFsaPtr mfp;
   Boolean is_na;
   SeqIdPtr sip;
@@ -742,6 +742,10 @@ typedef struct streamfsa {
   Int2          blocklen;
   Int2          grouplen;
   Int2          skip;
+  Int4          gi;
+  Int4          start;
+  Int4          seqpos;
+  Boolean       seqspans;
 } StreamFsa, PNTR StreamFsaPtr;
 
 static void LIBCALLBACK FsaStreamProc (
@@ -752,12 +756,14 @@ static void LIBCALLBACK FsaStreamProc (
 {
   Char          ch;
   StreamFsaPtr  sfp;
+  Char          spn [64];
 
   if (StringHasNoText (sequence) || userdata == NULL) return;
   sfp = (StreamFsaPtr) userdata;
   ch = *sequence;
   while (ch != '\0' && sfp->skip > 0) {
     (sfp->skip)--;
+    (sfp->seqpos)++;
     sequence++;
     ch = *sequence;
   }
@@ -787,16 +793,32 @@ static void LIBCALLBACK FsaStreamProc (
       }
       /* print actual sequence line here */
       if (sfp->fp != NULL) {
-        fprintf (sfp->fp, "%s\n", sfp->buf);
+        if (sfp->seqspans) {
+          fprintf (sfp->fp, "<span class=\"ff_line\" id=\"gi_%ld_%ld\">", (long) sfp->gi, (long) (sfp->start + 1));
+        }
+        fprintf (sfp->fp, "%s", sfp->buf);
+        if (sfp->seqspans) {
+          fprintf (sfp->fp, "</span>");
+        }
+        fprintf (sfp->fp, "\n");
       } else if (sfp->bs != NULL) {
+        if (sfp->seqspans) {
+          sprintf (spn, "<span class=\"ff_line\" id=\"gi_%ld_%ld\">", (long) sfp->gi, (long) (sfp->start + 1));
+          BSWrite (sfp->bs, spn, StringLen (spn));
+        }
         BSWrite (sfp->bs, sfp->buf, StringLen (sfp->buf));
+        if (sfp->seqspans) {
+          BSWrite (sfp->bs, "</span>", sizeof ("</span>"));
+        }
         BSWrite (sfp->bs, "\n", sizeof ("\n"));
       }
+      sfp->start = sfp->seqpos + 1;
       sfp->idx = 0;
       sfp->lin = 0;
       sfp->blk = 0;
       (sfp->grp)++;
     }
+    (sfp->seqpos)++;
     sequence++;
     ch = *sequence;
   }
@@ -873,7 +895,8 @@ static Int4 BioseqFastaStreamInternal (
   Int4         count = 0;
   Char         id [128];
   StreamFsa    sf;
-  SeqIdPtr     sip;
+  SeqIdPtr     sip = NULL;
+  Char         spn [64];
   CharPtr      tmp;
 
   if (bsp == NULL && slp == NULL && str == NULL) return 0;
@@ -908,11 +931,21 @@ static Int4 BioseqFastaStreamInternal (
   sf.blocklen = blocklen;
   sf.grouplen = grouplen;
   sf.skip = skip;
+  sf.gi = 0;
+  if (bsp != NULL) {
+    for (sip = bsp->id; sip != NULL; sip = sip->next) {
+      if (sip->choice != SEQID_GI) continue;
+      sf.gi = sip->data.intvalue;
+    }
+  }
+  sf.start = 0;
+  sf.seqpos = 0;
+  sf.seqspans = (Boolean) ((flags & STREAM_HTML_SPANS) != 0);
   if (do_defline) {
     id [0] = '\0';
     if (substitute_ids) {
       sip = ChooseFastaID (bsp, sorted_prot);
-    } else {
+    } else if (bsp != NULL) {
       sip = bsp->id;
     }
     SeqIdWrite (sip, id, PRINTID_FASTA_LONG, sizeof (id) - 1);
@@ -966,9 +999,23 @@ static Int4 BioseqFastaStreamInternal (
       }
     }
     if (sf.fp != NULL) {
-      fprintf (fp, "%s\n", sf.buf);
+      if (sf.seqspans) {
+        fprintf (sf.fp, "<span class=\"ff_line\" id=\"gi_%ld_%ld\">", (long) sf.gi, (long) (sf.start + 1));
+      }
+      fprintf (sf.fp, "%s", sf.buf);
+      if (sf.seqspans) {
+        fprintf (sf.fp, "</span>");
+      }
+      fprintf (sf.fp, "\n");
     } else if (sf.bs != NULL) {
+      if (sf.seqspans) {
+        sprintf (spn, "<span class=\"ff_line\" id=\"gi_%ld_%ld\">", (long) sf.gi, (long) (sf.start + 1));
+        BSWrite (sf.bs, spn, StringLen (spn));
+      }
       BSWrite (sf.bs, sf.buf, StringLen (sf.buf));
+      if (sf.seqspans) {
+        BSWrite (sf.bs, "</span>", sizeof ("</span>"));
+      }
       BSWrite (sf.bs, "\n", sizeof ("\n"));
     }
   }
@@ -1035,26 +1082,25 @@ NLM_EXTERN Int4 SeqLocFastaStream (
 )
 
 {
+  if (slp == NULL || fp == NULL) return 0;
+
   return BioseqFastaStreamInternal (NULL, slp, NULL, fp, NULL, flags, 
                                     linelen, blocklen, grouplen,
                                     FALSE, FALSE, FALSE, 0);
 }
 
-NLM_EXTERN Int4 CdRegionFastaStream (
+static void DoSpecialDefline (
   SeqFeatPtr sfp,
   FILE *fp,
-  StreamFlgType flags,
-  Int2 linelen,
-  Int2 blocklen,
-  Int2 grouplen,
-  Boolean do_defline
+  CdRegionPtr crp,
+  CharPtr idSuffix
 )
 
 {
   BioseqPtr          bsp = NULL;
   Char               buf [512];
   SeqMgrFeatContext  cdscontext;
-  CdRegionPtr        crp;
+  Boolean            do_defline = TRUE;
   Uint2              entityID;
   SeqFeatPtr         gene = NULL;
   SeqMgrFeatContext  genecontext;
@@ -1065,14 +1111,10 @@ NLM_EXTERN Int4 CdRegionFastaStream (
   Boolean            partial3;
   BioseqPtr          prod;
   SeqIdPtr           sip;
-  Int2               skip = 0;
   CharPtr            str;
   Char               tmp [64];
 
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return 0;
-  if (fp == NULL) return 0;
-  crp = (CdRegionPtr) sfp->data.value.ptrvalue;
-  if (crp == NULL) return 0;
+  if (sfp == NULL || fp == NULL || crp == NULL) return;
 
   if (do_defline) {
     bsp = BioseqFindFromSeqLoc (sfp->location);
@@ -1080,10 +1122,13 @@ NLM_EXTERN Int4 CdRegionFastaStream (
       do_defline = FALSE;
       StringCpy (buf, "lcl|");
       sip = SeqLocId (sfp->location);
+      if (sip != NULL) {
       SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
       StringCat (buf, tmp);
-      sprintf (tmp, "_cds_%ld", (long) sfp->idx.itemID);
-      StringCat (buf, tmp);
+      }
+      if (StringDoesHaveText (idSuffix) && StringLen (idSuffix) < 200) {
+        StringCat (buf, idSuffix);
+      }
       FastaFileFunc (bsp, FASTA_ID, buf, sizeof (buf), (Pointer) fp);
       StringCpy (buf, "?");
       FastaFileFunc (bsp, FASTA_DEFLINE, buf, sizeof (buf), (Pointer) fp);
@@ -1096,10 +1141,13 @@ NLM_EXTERN Int4 CdRegionFastaStream (
       do_defline = FALSE;
       StringCpy (buf, "lcl|");
       sip = SeqIdFindWorst (bsp->id);
+      if (sip != NULL) {
       SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
       StringCat (buf, tmp);
-      sprintf (tmp, "_cds_%ld", (long) sfp->idx.itemID);
-      StringCat (buf, tmp);
+      }
+      if (StringDoesHaveText (idSuffix) && StringLen (idSuffix) < 200) {
+        StringCat (buf, idSuffix);
+      }
       FastaFileFunc (bsp, FASTA_ID, buf, sizeof (buf), (Pointer) fp);
       StringCpy (buf, "?");
       FastaFileFunc (bsp, FASTA_DEFLINE, buf, sizeof (buf), (Pointer) fp);
@@ -1126,10 +1174,13 @@ NLM_EXTERN Int4 CdRegionFastaStream (
   
     StringCpy (buf, "lcl|");
     sip = SeqIdFindWorst (bsp->id);
+    if (sip != NULL) {
     SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
     StringCat (buf, tmp);
-    sprintf (tmp, "_cds_%ld", (long) sfp->idx.itemID);
-    StringCat (buf, tmp);
+    }
+    if (StringDoesHaveText (idSuffix) && StringLen (idSuffix) < 200) {
+      StringCat (buf, idSuffix);
+    }
   
     FastaFileFunc (bsp, FASTA_ID, buf, sizeof (buf), (Pointer) fp);
   
@@ -1165,6 +1216,7 @@ NLM_EXTERN Int4 CdRegionFastaStream (
           sip = SeqIdFindWorst (prod->id);
           SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
         } else {
+          gi = sip->data.intvalue;
           sip = GetSeqIdForGI (gi);
           SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp));
           SeqIdFree (sip);
@@ -1178,7 +1230,7 @@ NLM_EXTERN Int4 CdRegionFastaStream (
         StringCat (buf, "] ");
       }
     }
-    str = FFFlatLoc (&iaj, bsp, sfp->location, FALSE);
+    str = FFFlatLoc (&iaj, bsp, sfp->location, FALSE, FALSE);
     if (str != NULL && StringLen (str) + StringLen (buf) < sizeof (buf) - 10) {
       StringCat (buf, "[location=");
       StringCat (buf, str);
@@ -1191,6 +1243,31 @@ NLM_EXTERN Int4 CdRegionFastaStream (
   
     fflush (fp);
   }
+}
+
+NLM_EXTERN Int4 CdRegionFastaStream (
+  SeqFeatPtr sfp,
+  FILE *fp,
+  StreamFlgType flags,
+  Int2 linelen,
+  Int2 blocklen,
+  Int2 grouplen,
+  Boolean do_defline,
+  CharPtr idSuffix
+)
+
+{
+  CdRegionPtr  crp;
+  Int2         skip = 0;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return 0;
+  if (fp == NULL) return 0;
+  crp = (CdRegionPtr) sfp->data.value.ptrvalue;
+  if (crp == NULL) return 0;
+
+  if (do_defline) {
+    DoSpecialDefline (sfp, fp, crp, idSuffix);
+  }
 
   if (crp->frame == 2) {
     skip = 1;
@@ -1210,31 +1287,18 @@ NLM_EXTERN Int4 TranslationFastaStream (
   Int2 linelen,
   Int2 blocklen,
   Int2 grouplen,
-  Boolean do_defline
+  Boolean do_defline,
+  CharPtr idSuffix
 )
 
 {
   ByteStorePtr       bs;
-  BioseqPtr          bsp = NULL;
-  Char               buf [512];
-  SeqMgrFeatContext  cdscontext;
   Char               ch;
   Int4               count = 0;
   CdRegionPtr        crp;
-  Uint2              entityID;
-  SeqFeatPtr         gene = NULL;
-  SeqMgrFeatContext  genecontext;
-  Int4               gi;
-  GeneRefPtr         grp;
-  IntAsn2gbJob       iaj;
-  Boolean            partial5;
-  Boolean            partial3;
-  BioseqPtr          prod;
   size_t             prtlen;
   CharPtr            ptr;
-  SeqIdPtr           sip;
   CharPtr            str;
-  Char               tmp [64];
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return 0;
   if (fp == NULL) return 0;
@@ -1242,121 +1306,7 @@ NLM_EXTERN Int4 TranslationFastaStream (
   if (crp == NULL) return 0;
 
   if (do_defline) {
-    bsp = BioseqFindFromSeqLoc (sfp->location);
-    if (bsp == NULL) {
-      do_defline = FALSE;
-      StringCpy (buf, "lcl|");
-      sip = SeqLocId (sfp->location);
-      SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
-      StringCat (buf, tmp);
-      sprintf (tmp, "_prt_%ld", (long) sfp->idx.itemID);
-      StringCat (buf, tmp);
-      FastaFileFunc (bsp, FASTA_ID, buf, sizeof (buf), (Pointer) fp);
-      StringCpy (buf, "?");
-      FastaFileFunc (bsp, FASTA_DEFLINE, buf, sizeof (buf), (Pointer) fp);
-      fflush (fp);
-    }
-  }
-
-  if (do_defline && bsp != NULL) {
-    if (sfp != SeqMgrGetDesiredFeature (0, bsp, 0, 0, sfp, &cdscontext)) {
-      do_defline = FALSE;
-      StringCpy (buf, "lcl|");
-      sip = SeqIdFindWorst (bsp->id);
-      SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
-      StringCat (buf, tmp);
-      sprintf (tmp, "_prt_%ld", (long) sfp->idx.itemID);
-      StringCat (buf, tmp);
-      FastaFileFunc (bsp, FASTA_ID, buf, sizeof (buf), (Pointer) fp);
-      StringCpy (buf, "?");
-      FastaFileFunc (bsp, FASTA_DEFLINE, buf, sizeof (buf), (Pointer) fp);
-      fflush (fp);
-    }
-  }
-
-  if (do_defline) {
-    entityID = ObjMgrGetEntityIDForPointer (bsp);
-    if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, NULL);
-    }
-
-    CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
-  
-    grp = SeqMgrGetGeneXref (sfp);
-    if (grp == NULL || (! SeqMgrGeneIsSuppressed (grp))) {
-      gene = SeqMgrGetOverlappingGene (sfp->location, &genecontext);
-    }
-  
-    MemSet ((Pointer) &iaj, 0, sizeof (IntAsn2gbJob));
-    iaj.flags.iupacaaOnly = FALSE;
-    iaj.relModeError = FALSE;
-  
-    StringCpy (buf, "lcl|");
-    sip = SeqIdFindWorst (bsp->id);
-    SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
-    StringCat (buf, tmp);
-    sprintf (tmp, "_prt_%ld", (long) sfp->idx.itemID);
-    StringCat (buf, tmp);
-  
-    FastaFileFunc (bsp, FASTA_ID, buf, sizeof (buf), (Pointer) fp);
-  
-    buf [0] = '\0';
-    if (StringDoesHaveText (genecontext.label)) {
-      StringCat (buf, "[gene=");
-      StringCat (buf, genecontext.label);
-      StringCat (buf, "] ");
-    }
-    if (StringDoesHaveText (cdscontext.label)) {
-      StringCat (buf, "[protein=");
-      StringCat (buf, cdscontext.label);
-      StringCat (buf, "] ");
-    }
-    if (crp->frame == 2) {
-      StringCat (buf, "[frame=2] ");
-    } else if (crp->frame == 3) {
-      StringCat (buf, "[frame=3] ");
-    }
-    if (partial5 && partial3) {
-      StringCat (buf, "[partial=5',3'] ");
-    } else if (partial5) {
-      StringCat (buf, "[partial=5'] ");
-    } else if (partial3) {
-      StringCat (buf, "[partial=3'] ");
-    }
-    if (sfp->product != NULL) {
-      tmp [0] = '\0';
-      sip = SeqLocId (sfp->product);
-      if (sip != NULL && sip->choice == SEQID_GI) {
-        prod = BioseqFind (sip);
-        if (prod != NULL) {
-          sip = SeqIdFindWorst (prod->id);
-          SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp) - 1);
-        } else {
-          sip = GetSeqIdForGI (gi);
-          SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp));
-          SeqIdFree (sip);
-        }
-      } else if (sip != NULL) {
-        SeqIdWrite (sip, tmp, PRINTID_TEXTID_ACC_VER, sizeof (tmp));
-      }
-      if (StringDoesHaveText (tmp)) {
-        StringCat (buf, "[protein_id=");
-        StringCat (buf, tmp);
-        StringCat (buf, "] ");
-      }
-    }
-    str = FFFlatLoc (&iaj, bsp, sfp->location, FALSE);
-    if (str != NULL && StringLen (str) + StringLen (buf) < sizeof (buf) - 10) {
-      StringCat (buf, "[location=");
-      StringCat (buf, str);
-      StringCat (buf, "] ");
-      MemFree (str);
-    }
-    TrimSpacesAroundString (buf);
-  
-    FastaFileFunc (bsp, FASTA_DEFLINE, buf, sizeof (buf), (Pointer) fp);
-  
-    fflush (fp);
+    DoSpecialDefline (sfp, fp, crp, idSuffix);
   }
 
   str = NULL;
@@ -4906,6 +4856,74 @@ NLM_EXTERN void NC_Cleanup (Uint2 entityID, Pointer ptr)
   objMgrFilt [OBJ_BIOSEQ] = TRUE;
   GatherObjectsInEntity (entityID, 0, NULL, AddNcTitles, NULL, objMgrFilt);
 }
+
+NLM_EXTERN void InstantiateNCTitle (Uint2 entityID, Pointer ptr)
+{
+  Boolean      objMgrFilt [OBJ_MAX];
+
+  if (entityID == 0) {
+    entityID = ObjMgrGetEntityIDForPointer (ptr);
+  }
+  if (entityID == 0) return;
+
+  AssignIDsInEntity (entityID, 0, NULL);
+  MemSet ((Pointer) objMgrFilt, FALSE, sizeof (objMgrFilt));
+  objMgrFilt [OBJ_BIOSEQ] = TRUE;
+  GatherObjectsInEntity (entityID, 0, NULL, AddNcTitles, NULL, objMgrFilt);
+}
+
+static Boolean AddNmTitles (GatherObjectPtr gop)
+{
+  BioseqPtr     bsp;
+  Char          buf [512];
+  Boolean       is_nm;
+  SeqIdPtr      sip;
+  CharPtr       str;
+  TextSeqIdPtr  tsip;
+  if (gop == NULL ||
+      gop->itemtype != OBJ_BIOSEQ) return TRUE;
+  bsp = (BioseqPtr) gop->dataptr;
+  if (bsp == NULL) return TRUE;
+  is_nm = FALSE;
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_OTHER) {
+      tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+      if (tsip != NULL && tsip->accession != NULL) {
+        if (StringNICmp (tsip->accession, "NM_", 3) == 0) {
+          is_nm = TRUE;
+        } else if (StringNICmp (tsip->accession, "XM_", 3) == 0) {
+          is_nm = TRUE;
+        }
+      }
+    }
+  }
+  if (! is_nm) return TRUE;
+  if (NewCreateDefLineBuf (NULL, bsp, buf, sizeof (buf), FALSE, FALSE)) {
+    if (! StringHasNoText (buf)) {
+      str = StringSaveNoNull (buf);
+      if (str != NULL) {
+        SeqDescrAddPointer (&(bsp->descr), Seq_descr_title, (Pointer) str);
+      }
+    }
+  }
+  return TRUE;
+}
+
+NLM_EXTERN void InstantiateNMTitles (Uint2 entityID, Pointer ptr)
+{
+  Boolean      objMgrFilt [OBJ_MAX];
+
+  if (entityID == 0) {
+    entityID = ObjMgrGetEntityIDForPointer (ptr);
+  }
+  if (entityID == 0) return;
+
+  AssignIDsInEntity (entityID, 0, NULL);
+  MemSet ((Pointer) objMgrFilt, FALSE, sizeof (objMgrFilt));
+  objMgrFilt [OBJ_BIOSEQ] = TRUE;
+  GatherObjectsInEntity (entityID, 0, NULL, AddNmTitles, NULL, objMgrFilt);
+}
+
 static void ClearProtTitlesProc (BioseqPtr bsp, Pointer userdata)
 {
   ObjValNodePtr  ovp;
@@ -5181,6 +5199,8 @@ static void x_SetFlags (
               dlp->m_is_nc = TRUE;
             } else if (StringNICmp (tsip->accession, "NM_", 3) == 0) {
               dlp->m_is_nm = TRUE;
+            } else if (StringNICmp (tsip->accession, "XM_", 3) == 0) {
+              dlp->m_is_nm = TRUE;
             } else if (StringNICmp (tsip->accession, "NR_", 3) == 0) {
               dlp->m_is_nr = TRUE;
             }
@@ -5625,7 +5645,7 @@ static Boolean x_EndsWithStrain (
   if (ptr == NULL) return FALSE;
   ptr++;
 
-  ptr = StringISearch (ptr, dlp->m_strain);
+  ptr = StringISearch (dlp->m_taxname, dlp->m_strain);
   if (ptr == NULL) return FALSE;
 
   nxt = StringISearch (ptr + 1, dlp->m_strain);
@@ -6420,8 +6440,14 @@ static CharPtr x_TitleFromProtein (
   if (indexed) {
     sfp = SeqMgrGetBestProteinFeature (bsp, NULL);
   } else {
+    if (dlp->m_is_seg) {
+      SeqMgrIndexFeatures (entityID, NULL);
+      indexed = TRUE;
+      sfp = SeqMgrGetBestProteinFeature (bsp, NULL);
+    } else {
     sfp = x_GetLongestProteinUnindexed (bsp);
   }
+  }
 
   if (sfp != NULL) {
     prp = (ProtRefPtr) sfp->data.value.ptrvalue;
@@ -6458,7 +6484,7 @@ static CharPtr x_TitleFromProtein (
           if (cds != NULL) {
             grp = SeqMgrGetGeneXref (cds);
             if (grp == NULL) {
-              sfp = SeqMgrGetOverlappingGene (cds->location, NULL);
+              sfp = SeqMgrGetOverlappingFeature (cds->location, FEATDEF_GENE, NULL, 0, NULL, LOCATION_SUBSET, NULL);
               if (sfp != NULL) {
                 grp = (GeneRefPtr) sfp->data.value.ptrvalue;
               }
@@ -6503,7 +6529,7 @@ static CharPtr x_TitleFromProtein (
     if (cds != NULL) {
       grp = SeqMgrGetGeneXref (cds);
       if (grp == NULL) {
-        sfp = SeqMgrGetOverlappingGene (cds->location, NULL);
+        sfp = SeqMgrGetOverlappingFeature (cds->location, FEATDEF_GENE, NULL, 0, NULL, LOCATION_SUBSET, NULL);
         if (sfp != NULL) {
           grp = (GeneRefPtr) sfp->data.value.ptrvalue;
         }
diff --git a/api/tofasta.h b/api/tofasta.h
index 1628919..e3e4310 100644
--- a/api/tofasta.h
+++ b/api/tofasta.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 7/12/91
 *
-* $Revision: 6.35 $
+* $Revision: 6.39 $
 *
 * File Description:  various sequence objects to fasta output
 *
@@ -204,7 +204,8 @@ NLM_EXTERN Int4 CdRegionFastaStream (
   Int2 linelen,
   Int2 blocklen,
   Int2 grouplen,
-  Boolean do_defline
+  Boolean do_defline,
+  CharPtr idSuffix
 );
 
 NLM_EXTERN Int4 TranslationFastaStream (
@@ -214,7 +215,8 @@ NLM_EXTERN Int4 TranslationFastaStream (
   Int2 linelen,
   Int2 blocklen,
   Int2 grouplen,
-  Boolean do_defline
+  Boolean do_defline,
+  CharPtr idSuffix
 );
 
 NLM_EXTERN Int4 SeqEntryFastaStream (
@@ -462,6 +464,16 @@ NLM_EXTERN void ClearGenBankKeywords (Uint2 entityID, Pointer ptr);
 
 /*****************************************************************************
 *
+*   InstantiateNCTitle (entityID, ptr) and InstantiateNMTitles (entityID, ptr)
+*     allows NC and NM titles to be kept as Seq_descr_title rather than always
+*     being generated on the fly
+*
+*****************************************************************************/
+NLM_EXTERN void InstantiateNCTitle (Uint2 entityID, Pointer ptr);
+NLM_EXTERN void InstantiateNMTitles (Uint2 entityID, Pointer ptr);
+
+/*****************************************************************************
+*
 *   InstantiateProteinTitles (entityID, ptr) and ClearProteinTitles (entityID, ptr)
 *     allows proteins titles to be kept as Seq_descr_title rather than always
 *     being generated on the fly
diff --git a/api/valapi.c b/api/valapi.c
index 382a766..e7f589a 100755
--- a/api/valapi.c
+++ b/api/valapi.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/7/2009
 *
-* $Revision: 1.1 $
+* $Revision: 1.9 $
 *
 * File Description: 
 *
@@ -67,14 +67,150 @@
 
 static CommentRulePtr CommentRules = NULL;
 
+
 #ifndef WIN16
 static CharPtr commentRulesStr = "Comment-set ::= {\n" \
-"{ prefix \"foo\" , fields { { field-name \"bar\" , match-expression \"^s\" } , { field-name \"baz\" , match-expression \"\\d+\\s+z\" } } } , \n " \
-"{ prefix \"foo2\" , fields { { field-name \"bar\" , match-expression \"b\\W+a\" } , { field-name \"baz\" , match-expression \"z\\s+\\d+\" , required TRUE } } } , \n " \
-"}\n";
+"  { \n" \
+"    prefix \"##Genome-Assembly-Data-START##\" ,\n" \
+"    fields { \n" \
+"      { \n" \
+"        field-name \"Finishing Goal\" ,\n" \
+"        match-expression \"^\\(Standard Draft\\|High Quality Draft\\|Improved High Quality Draft\\|Annotation Directed\\|Non-contiguous Finished\\|Finished\\)$\" ,\n" \
+"        required TRUE } ,\n" \
+"      { \n" \
+"        field-name \"Current Finishing Status\" ,\n" \
+"        match-expression \"^\\(Standard Draft\\|High Quality Draft\\|Improved High Quality Draft\\|Annotation Directed\\|Non-contiguous Finished\\|Finished\\)$\" , \n" \
+"        required TRUE } ,\n" \
+"      {\n" \
+"        field-name \"Assembly Method\" , \n" \
+"        match-expression \".* v\\. [0123456789][0123456789\\.]*$\" ,\n" \
+"        required TRUE } ,\n" \
+"      { \n" \
+"        field-name \"Assembly Name\" } ,\n" \
+"      { \n" \
+"        field-name \"Genome Coverage\" ,\n" \
+"        required TRUE} ,\n" \
+"      { \n" \
+"        field-name \"Sequencing Technology\" ,\n" \
+"        required TRUE} } ,\n" \
+"    dependent-rules {\n" \
+"      { \n" \
+"        match-name \"Finishing Goal\" , \n" \
+"        value-constraint \"^Standard Draft$\" , \n" \
+"        other-fields {\n" \
+"          { \n" \
+"            field-name \"Current Finishing Status\" ,\n" \
+"            match-expression \"^Standard Draft$\" } } } ,\n" \
+"      { \n" \
+"        match-name \"Finishing Goal\" , \n" \
+"        value-constraint \"^High Quality Draft$\" , \n" \
+"        other-fields {\n" \
+"          { \n" \
+"            field-name \"Current Finishing Status\" ,\n" \
+"            match-expression \"^\\(Standard Draft\\|High Quality Draft\\)$\" } } } ,\n" \
+"      { \n" \
+"        match-name \"Finishing Goal\" , \n" \
+"        value-constraint \"^Improved High Quality Draft$\" , \n" \
+"        other-fields {\n" \
+"          { \n" \
+"            field-name \"Current Finishing Status\" ,\n" \
+"            match-expression \"^\\(Standard Draft\\|High Quality Draft\\|Improved High Quality Draft\\)$\" } } } ,\n" \
+"      { \n" \
+"        match-name \"Finishing Goal\" , \n" \
+"        value-constraint \"^Annotation Directed$\" , \n" \
+"        other-fields {\n" \
+"          { \n" \
+"            field-name \"Current Finishing Status\" ,\n" \
+"            match-expression \"^\\(Standard Draft\\|High Quality Draft\\|Improved High Quality Draft\\|Annotation Directed\\)$\" } } } ,\n" \
+"      { \n" \
+"        match-name \"Finishing Goal\" , \n" \
+"        value-constraint \"^Non-contiguous Finished$\" , \n" \
+"        other-fields {\n" \
+"          { \n" \
+"            field-name \"Current Finishing Status\" ,\n" \
+"            match-expression \"^\\(Standard Draft\\|High Quality Draft\\|Improved High Quality Draft\\|Annotation Directed\\|Non-contiguous Finished\\)$\" } } } ,\n" \
+"      { \n" \
+"        match-name \"Finishing Goal\" , \n" \
+"        value-constraint \"^Finished$\" , \n" \
+"        other-fields {\n" \
+"          { \n" \
+"            field-name \"Current Finishing Status\" ,\n" \
+"            match-expression \"^\\(Standard Draft\\|High Quality Draft\\|Improved High Quality Draft\\|Annotation Directed\\|Non-contiguous Finished\\|Finished\\)$\" } } }\n" \
+"} } }\n";
 #endif
 
 
+static int CompareFieldRules (FieldRulePtr r1, FieldRulePtr r2)
+{
+  int rval = 0;
+
+  if (r1 == NULL && r2 == NULL) {
+    rval = 0;
+  } else if (r1 == NULL) {
+    rval = -1;
+  } else if (r2 == NULL) {
+    rval = 1;
+  } else {
+    rval = StringCmp (r1->field_name, r2->field_name);
+  }
+  return rval;
+}
+
+
+NLM_EXTERN int LIBCALLBACK SortVnpByFieldRule (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      return CompareFieldRules(vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+    }
+  }
+  return 0;
+}
+
+
+static void SortFieldsInCommentRule (CommentRulePtr cr)
+{
+  FieldRulePtr r, prev = NULL;
+  ValNodePtr list = NULL, vnp;
+
+  if (cr == NULL || cr->fields == NULL) {
+    return;
+  }
+
+  for (r = cr->fields; r != NULL; r = r->next) {
+    ValNodeAddPointer (&list, 0, r);
+  }
+
+  list = ValNodeSort (list, SortVnpByFieldRule);
+
+  prev = list->data.ptrvalue;
+  cr->fields = prev;
+  for (vnp = list->next; vnp != NULL; vnp = vnp->next) {
+    prev->next = vnp->data.ptrvalue;
+    prev = prev->next;
+  }
+  prev->next = NULL;
+  list = ValNodeFree (list);
+}
+
+
+static void SortCommentRuleFields (CommentSetPtr cr_set)
+{
+  while (cr_set != NULL) {
+    if (!cr_set->require_order) {
+      SortFieldsInCommentRule(cr_set);
+    }
+    cr_set = cr_set->next;
+  }
+}
+
+
 static Boolean LoadCommentRulesFromLocalString (void)
 
 {
@@ -85,6 +221,7 @@ static Boolean LoadCommentRulesFromLocalString (void)
   if (aimp == NULL || aimp->aip == NULL) return FALSE;
 
   CommentRules = CommentSetAsnRead (aimp->aip, NULL);
+  SortCommentRuleFields(CommentRules);
   AsnIoMemClose (aimp);
 #endif
   return (Boolean) (CommentRules != NULL);
@@ -99,14 +236,6 @@ NLM_EXTERN CommentRulePtr LoadCommentRuleSet (void)
     if (CommentRules != NULL)
         return CommentRules;
 
-#ifdef OS_UNIX
-    if (getenv ("USE_VALIDRULES_FILE") == NULL) {
-          if (LoadCommentRulesFromLocalString ()) {
-              return CommentRules;
-          }
-    }
-#endif
-
     if (! FindPath("ncbi", "ncbi", "data", buf, sizeof (buf)))
     {
 
@@ -118,8 +247,8 @@ NLM_EXTERN CommentRulePtr LoadCommentRuleSet (void)
         return CommentRules;
     }
 
-    StringCat(buf, "validrules.val");
-    if ((aip = AsnIoOpen(buf, "rb")) == NULL)
+    StringCat(buf, "validrules.prt");
+    if ((aip = AsnIoOpen(buf, "r")) == NULL)
     {
 
         if (LoadCommentRulesFromLocalString ()) {
@@ -130,9 +259,9 @@ NLM_EXTERN CommentRulePtr LoadCommentRuleSet (void)
         return CommentRules;
     }
 
-    CommentSetAsnRead(aip, NULL);
-
+    CommentRules = CommentSetAsnRead(aip, NULL);
     AsnIoClose(aip);
+    SortCommentRuleFields (CommentRules);
     return CommentRules;
 }
 
@@ -158,6 +287,31 @@ NLM_EXTERN CommentRulePtr GetCommentRuleFromRuleSet (CharPtr prefix)
   return cr;
 }
 
+
+static Boolean DoesFieldNameMatchRuleName (UserFieldPtr ufp, CharPtr rule_field_name)
+{
+  Char buf[15];
+  Boolean rval = FALSE;
+
+  if (ufp == NULL) {
+    return FALSE;
+  }
+
+  /* Does this match the rule field name? */
+  if (ufp->label == NULL) {
+    rval = FALSE;
+  } else if (ufp->label->id > 0) {
+    sprintf (buf, "%d", ufp->label->id);
+    if (StringCmp (rule_field_name, buf) == 0) {
+      rval = TRUE;
+    }
+  } else if (StringCmp (rule_field_name, ufp->label->str) == 0) {
+    rval = TRUE;
+  }
+  return rval;
+}
+
+
 static Boolean DoesStringMatchExpression (CharPtr str, CharPtr expression)
 {
   Boolean rval;
@@ -179,61 +333,42 @@ static Boolean DoesStringMatchExpression (CharPtr str, CharPtr expression)
 }
 
 
-static EFieldValid IsStructuredCommentFieldValid (UserFieldPtr ufp, FieldRulePtr rule)
+static Boolean DoesFieldValueMatchExpression (UserFieldPtr ufp, CharPtr match_expression)
 {
   Char buf[15];
-  EFieldValid rval = eFieldValid_Invalid;
-
-  if (rule == NULL) {
-    return eFieldValid_Valid;
-  }
-  if (ufp == NULL) {
-    if (rule->required) {
-      return eFieldValid_MissingRequiredField;
-    } else {
-      return eFieldValid_OptionalFieldSkipped;
-    }
-  }
-
-  /* Does this match the rule field name? */
-  if (ufp->label == NULL) {
-    return eFieldValid_Invalid;
-  } else if (ufp->label->id > 0) {
-    sprintf (buf, "%d", ufp->label->id);
-    if (StringCmp (rule->field_name, buf) != 0) {
-      if (rule->required) {
-        return eFieldValid_MissingRequiredField;
-      } else {
-        return eFieldValid_OptionalFieldSkipped;
-      }
-    }
-  } else if (StringCmp (rule->field_name, ufp->label->str) != 0) {
-    if (rule->required) {
-      return eFieldValid_MissingRequiredField;
-    } else {
-      return eFieldValid_OptionalFieldSkipped;
-    }
-  }
-
-  /* now validate field value */
-  if (rule->match_expression == NULL) {
-    return eFieldValid_Valid;
-  }
+  Boolean rval = FALSE;
 
   if (ufp->choice == 1) {
     /* compare string value */
-    if (DoesStringMatchExpression(ufp->data.ptrvalue, rule->match_expression)) {
-      rval = eFieldValid_Valid;
+    if (DoesStringMatchExpression(ufp->data.ptrvalue, match_expression)) {
+      rval = TRUE;
     }
   } else if (ufp->choice == 2) {
     /* compare int value */
     sprintf (buf, "%d", ufp->data.intvalue);
-    if (DoesStringMatchExpression(buf, rule->match_expression)) {
-      rval = eFieldValid_Valid;
+    if (DoesStringMatchExpression(buf, match_expression)) {
+      rval = TRUE;
     }
   } else {
     /* for now, only allowing matches for int or string fields */
-    rval = eFieldValid_Invalid;
+    rval = FALSE;
+  }
+  return rval;
+}
+
+
+static Boolean DoesFieldValueMatchRule (UserFieldPtr ufp, FieldRulePtr rule)
+{
+  Boolean rval = FALSE;
+
+  if (ufp == NULL || rule == NULL) {
+    return FALSE;
+  }
+  /* now validate field value */
+  if (rule->match_expression == NULL) {
+    rval = TRUE;
+  } else {
+    rval = DoesFieldValueMatchExpression (ufp, rule->match_expression);
   }
   return rval;
 }
@@ -266,11 +401,129 @@ static Boolean DoesStructuredCommentHavePrefix (UserObjectPtr uop, CharPtr prefi
 }
 
 
-NLM_EXTERN EFieldValid IsStructuredCommentValidForRule (UserObjectPtr uop, CommentRulePtr comment_rule)
+static FieldRulePtr FindRuleForFieldName (UserFieldPtr ufp, FieldRulePtr field_rule)
 {
-  UserFieldPtr ufp;
-  FieldRulePtr field_rule;
-  EFieldValid  valid;
+  if (ufp == NULL) {
+    return NULL;
+  }
+
+  while (field_rule != NULL && ! DoesFieldNameMatchRuleName(ufp, field_rule->field_name)) {
+    field_rule = field_rule->next;
+  }
+  return field_rule;
+}
+
+
+static UserFieldPtr FindFieldForRuleName (UserFieldPtr ufp, CharPtr field_rule)
+{
+  if (StringHasNoText (field_rule)) {
+    return NULL;
+  }
+
+  while (ufp != NULL && !DoesFieldNameMatchRuleName(ufp, field_rule)) {
+    ufp = ufp->next;
+  }
+  return ufp;
+}
+
+
+static int CompareUserFields (UserFieldPtr ufp1, UserFieldPtr ufp2)
+{
+  int rval = 0;
+  CharPtr cp1, cp2;
+  Char buf1[15];
+  Char buf2[15];
+
+  if (ufp1 == NULL && ufp2 == NULL) {
+    rval = 0;
+  } else if (ufp1 == NULL) {
+    rval = -1;
+  } else if (ufp2 == NULL) {
+    rval = 1;
+  } else if (ufp1->label == NULL) {
+    rval = -1;
+  } else if (ufp2->label == NULL) {
+    rval = 1;
+  } else if (ufp1->label->id > 0 && ufp2->label->id > 0) {
+    if (ufp1->label->id > ufp2->label->id) {
+      rval = 1;
+    } else if (ufp1->label->id < ufp2->label->id) {
+      rval = -1;
+    } else {
+      rval = 0;
+    }
+  } else {
+    if (ufp1->label->id > 0) {
+      sprintf (buf1, "%d", ufp1->label->id);
+      cp1 = buf1;
+    } else {
+      cp1 = ufp1->label->str;
+    }
+    if (ufp2->label->id > 0) {
+      sprintf (buf2, "%d", ufp2->label->id);
+      cp2 = buf2;
+    } else {
+      cp2 = ufp2->label->str;
+    }
+    rval = StringCmp (cp1, cp2);
+  }
+  return rval;
+}
+
+
+NLM_EXTERN int LIBCALLBACK SortVnpByUserField (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      return CompareUserFields(vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+    }
+  }
+  return 0;
+}
+
+
+static void SortFieldsInUserObject (UserObjectPtr uop)
+{
+  UserFieldPtr ufp, prev = NULL;
+  ValNodePtr list = NULL, vnp;
+
+  if (uop == NULL || uop->data == NULL) {
+    return;
+  }
+
+  for (ufp = uop->data; ufp != NULL; ufp = ufp->next) {
+    ValNodeAddPointer (&list, 0, ufp);
+  }
+
+  list = ValNodeSort (list, SortVnpByUserField);
+
+  prev = list->data.ptrvalue;
+  uop->data = prev;
+  for (vnp = list->next; vnp != NULL; vnp = vnp->next) {
+    prev->next = vnp->data.ptrvalue;
+    prev = prev->next;
+  }
+  prev->next = NULL;
+  list = ValNodeFree (list);
+}
+
+
+NLM_EXTERN EFieldValid 
+IsStructuredCommentValidForRule 
+(UserObjectPtr uop,
+ CommentRulePtr comment_rule,
+ StructuredCommentCallback s_callback,
+ Pointer s_callback_data)
+{
+  UserFieldPtr ufp, ufp_tmp, depend_ufp;
+  FieldRulePtr field_rule, rule_tmp;
+  DependentFieldRulePtr depend_rule;
   EFieldValid  rval = eFieldValid_Valid;
 
   if (uop == NULL || uop->type == NULL || StringICmp (uop->type->str, "StructuredComment") != 0) {
@@ -283,42 +536,190 @@ NLM_EXTERN EFieldValid IsStructuredCommentValidForRule (UserObjectPtr uop, Comme
   if (!DoesStructuredCommentHavePrefix (uop, comment_rule->prefix)) {
     return eFieldValid_Invalid;
   }
-  /* now check fields in order */
+
+  if (!comment_rule->require_order) {
+    uop = (UserObjectPtr) AsnIoMemCopy (uop, (AsnReadFunc) UserObjectAsnRead, (AsnWriteFunc) UserObjectAsnWrite);
+    SortFieldsInUserObject(uop);
+  }
+
+  /* now check individual fields */
   ufp = uop->data;
   field_rule = comment_rule->fields;
 
-  while (field_rule != NULL && ufp != NULL && rval == eFieldValid_Valid) {
+  while (field_rule != NULL && ufp != NULL) {
     if (ufp->label != NULL 
         && (StringICmp (ufp->label->str, "StructuredCommentPrefix") == 0
             || StringICmp (ufp->label->str, "StructuredCommentSuffix") == 0)) {
       /* skip suffix and prefix */
       ufp = ufp->next;
+    } else if (DoesFieldNameMatchRuleName (ufp, field_rule->field_name)) {
+      if (DoesFieldValueMatchRule (ufp, field_rule)) {
+        /* all good */
     } else {
-      valid = IsStructuredCommentFieldValid (ufp, field_rule);
-      if (valid == eFieldValid_OptionalFieldSkipped) {
-        field_rule = field_rule->next;
-      } else if (valid == eFieldValid_Valid) {
+        if (s_callback == NULL) {
+          rval = eFieldValid_Invalid;
+          goto IsStructuredCommentValidForRule_exit;
+        } else {
+          if (rval == eFieldValid_Valid) {
+            rval = eFieldValid_Invalid;
+          }
+          s_callback (eFieldValid_Invalid, field_rule, ufp, NULL, s_callback_data);
+        }
+      }
+      ufp = ufp->next;
         field_rule = field_rule->next;
+    } else if ((rule_tmp = FindRuleForFieldName(ufp, comment_rule->fields)) == NULL) {
+      if (!comment_rule->allow_unlisted) {
+        if (s_callback == NULL) {
+          rval = eFieldValid_Invalid;
+          goto IsStructuredCommentValidForRule_exit;
+        } else {
+          if (rval == eFieldValid_Valid) {
+            rval = eFieldValid_Invalid;
+          }
+          s_callback (eFieldValid_Invalid, NULL, ufp, NULL, s_callback_data);
+        }
+      }
         ufp = ufp->next;
       } else {
-        rval = valid;
+      ufp_tmp = FindFieldForRuleName (ufp, field_rule->field_name);
+      if (ufp_tmp == NULL) {
+        if (field_rule->required) {
+          if (s_callback == NULL) {
+            rval = eFieldValid_MissingRequiredField;
+            goto IsStructuredCommentValidForRule_exit;
+          } else {
+            if (rval == eFieldValid_Valid) {
+              rval = eFieldValid_MissingRequiredField;
+            }
+            s_callback (eFieldValid_MissingRequiredField, field_rule, NULL, NULL, s_callback_data);
+          }
+        } else {
+          /* field wasn't required, it's ok */
+        }
+      } else {
+        /* field is out of order */
+        if (s_callback == NULL) {
+          rval = eFieldValid_FieldOutOfOrder;
+          goto IsStructuredCommentValidForRule_exit;
+        } else {
+          if (rval == eFieldValid_Valid) {
+            rval = eFieldValid_FieldOutOfOrder;
+          }
+          s_callback (eFieldValid_FieldOutOfOrder, field_rule, ufp_tmp, NULL, s_callback_data);
+          if (!DoesFieldValueMatchRule (ufp_tmp, field_rule)) {
+            s_callback (eFieldValid_Invalid, field_rule, ufp_tmp, NULL, s_callback_data);
       }
     }
   }
-  if (valid == eFieldValid_Valid) {
-    while (field_rule != NULL && !field_rule->required) {
       field_rule = field_rule->next;
     }
-    if (field_rule != NULL) {
+  }
+
+  /* validate remaining rules */
+  while (field_rule != NULL) {
+    if (field_rule->required) {
+      if (s_callback == NULL) {
       rval = eFieldValid_MissingRequiredField;
+        goto IsStructuredCommentValidForRule_exit;
+      } else {
+        if (rval == eFieldValid_Valid) {
+          rval = eFieldValid_MissingRequiredField;
+        }
+        s_callback (eFieldValid_MissingRequiredField, field_rule, NULL, NULL, s_callback_data);
+      }
+    }
+    field_rule = field_rule->next;
+  }
+
+  while (ufp != NULL) {
+    if (ufp->label != NULL 
+      && (StringICmp (ufp->label->str, "StructuredCommentPrefix") == 0
+          || StringICmp (ufp->label->str, "StructuredCommentSuffix") == 0)) {
+      /* skip suffix and prefix */
+      ufp = ufp->next;
+      continue;
+    }
+    field_rule = FindRuleForFieldName (ufp, comment_rule->fields);
+    if (field_rule == NULL && !comment_rule->allow_unlisted) {
+      if (s_callback == NULL) {
+        rval = eFieldValid_Invalid;
+        goto IsStructuredCommentValidForRule_exit;
+      } else {
+        if (rval == eFieldValid_Valid) {
+          rval = eFieldValid_Invalid;
+        }
+        s_callback (eFieldValid_Invalid, NULL, ufp, NULL, s_callback_data);
     }
+    } else if (field_rule != NULL && FindFieldForRuleName(uop->data, field_rule->field_name) != ufp) {
+      if (s_callback == NULL) {
+        rval = eFieldValid_DuplicateField;
+        goto IsStructuredCommentValidForRule_exit;
+      } else {
+        if (rval == eFieldValid_Valid) {
+          rval = eFieldValid_DuplicateField;
+        }
+        s_callback (eFieldValid_DuplicateField, field_rule, ufp, NULL, s_callback_data);
+      }
+    }
+    ufp = ufp->next;
+  }
+
+  /* now look at fields in context of other fields */
+  for (depend_rule = comment_rule->dependent_rules; depend_rule != NULL; depend_rule = depend_rule->next) {
+    depend_ufp = FindFieldForRuleName(uop->data, depend_rule->match_name);
+    if (depend_ufp != NULL && DoesFieldValueMatchExpression(depend_ufp, depend_rule->value_constraint)) {
+      for (field_rule = depend_rule->other_fields; field_rule != NULL; field_rule = field_rule->next) {
+        ufp = FindFieldForRuleName (uop->data, field_rule->field_name);
+        if (ufp == NULL) {
+          if (s_callback == NULL) {
+            rval = eFieldValid_MissingRequiredField;
+            goto IsStructuredCommentValidForRule_exit;
+          } else {
+            if (rval == eFieldValid_Valid) {
+              rval = eFieldValid_MissingRequiredField;
+            }
+            s_callback (eFieldValid_MissingRequiredField, field_rule, ufp, depend_ufp, s_callback_data);
+          }
+        } else if (!DoesFieldValueMatchRule (ufp, field_rule)) {
+          if (s_callback == NULL) {
+            rval = eFieldValid_Invalid;
+            goto IsStructuredCommentValidForRule_exit;
+          } else {
+            if (rval == eFieldValid_Valid) {
+              rval = eFieldValid_MissingRequiredField;
+            }
+            s_callback (eFieldValid_Invalid, field_rule, ufp, depend_ufp, s_callback_data);
+          }
+        }
+      }
+      for (field_rule = depend_rule->disallowed_fields; field_rule != NULL; field_rule = field_rule->next) {
+        ufp = FindFieldForRuleName (uop->data, field_rule->field_name);
+        if (ufp != NULL && DoesFieldValueMatchRule (ufp, field_rule)) {
+          if (s_callback == NULL) {
+            rval = eFieldValid_Disallowed;
+            goto IsStructuredCommentValidForRule_exit;
+          } else {
+            if (rval == eFieldValid_Valid) {
+              rval = eFieldValid_Disallowed;
+            }
+            s_callback (eFieldValid_Disallowed, field_rule, ufp, depend_ufp, s_callback_data);
+          }
+        }
+      }
+    }
+  }
+
+IsStructuredCommentValidForRule_exit:
+  if (!comment_rule->require_order) {
+    uop = UserObjectFree (uop);
   }
 
   return rval;
 }
 
 
-NLM_EXTERN EFieldValid IsStructuredCommentValid (UserObjectPtr uop)
+NLM_EXTERN EFieldValid IsStructuredCommentValid (UserObjectPtr uop, StructuredCommentCallback s_callback, Pointer s_callback_data)
 {
   CommentRulePtr cr;
   UserFieldPtr ufp;
@@ -336,7 +737,7 @@ NLM_EXTERN EFieldValid IsStructuredCommentValid (UserObjectPtr uop)
     return TRUE;
   }
   cr = GetCommentRuleFromRuleSet (prefix);
-  return IsStructuredCommentValidForRule (uop, cr);
+  return IsStructuredCommentValidForRule (uop, cr, s_callback, s_callback_data);
 }
 
 
diff --git a/api/valapi.h b/api/valapi.h
index 7a50c05..63aca82 100755
--- a/api/valapi.h
+++ b/api/valapi.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/8/2009
 *
-* $Revision: 1.1 $
+* $Revision: 1.3 $
 *
 * File Description: 
 *
@@ -56,14 +56,24 @@ NLM_EXTERN CommentRulePtr GetCommentRuleFromRuleSet (CharPtr prefix);
 typedef enum {
   eFieldValid_Valid = 0 ,
   eFieldValid_Invalid,
-  eFieldValid_OptionalFieldSkipped,
-  eFieldValid_MissingRequiredField
+  eFieldValid_MissingRequiredField,
+  eFieldValid_FieldOutOfOrder,
+  eFieldValid_DuplicateField,
+  eFieldValid_Disallowed
 } EFieldValid;
 
 
-NLM_EXTERN EFieldValid IsStructuredCommentValidForRule (UserObjectPtr uop, CommentRulePtr comment_rule);
+/* error code, field rule violated, value of offending field (if any), extra data provided by user */
+typedef void (*StructuredCommentCallback) PROTO ((EFieldValid, FieldRulePtr, UserFieldPtr, UserFieldPtr, Pointer));
 
-NLM_EXTERN EFieldValid IsStructuredCommentValid (UserObjectPtr uop);
+NLM_EXTERN EFieldValid 
+IsStructuredCommentValidForRule 
+(UserObjectPtr uop,
+ CommentRulePtr comment_rule,
+ StructuredCommentCallback s_callback,
+ Pointer s_callback_data);
+
+NLM_EXTERN EFieldValid IsStructuredCommentValid (UserObjectPtr uop, StructuredCommentCallback s_callback, Pointer s_callback_data);
 
 
 
diff --git a/api/valid.c b/api/valid.c
index ecb4005..c526bbf 100644
--- a/api/valid.c
+++ b/api/valid.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 1/1/94
 *
-* $Revision: 6.1247 $
+* $Revision: 6.1388 $
 *
 * File Description:  Sequence editing utilities
 *
@@ -61,14 +61,15 @@ static char    *this_file = __FILE__;
 #include <objsub.h>
 #include <asn2gnbi.h>
 #include <explore.h>
+#include <gather.h>
 #include <subutil.h>
 #include <tofasta.h>
 #include <findrepl.h>
-#ifdef TEST_VALIDAPI
 #define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
+#include <macroapi.h>
 #include <objvalid.h>
 #include <valapi.h>
-#endif
 
 /*****************************************************************************
 *
@@ -118,6 +119,7 @@ static TextFsaPtr GetReplacedECNumberFSA (void);
 static Boolean ECnumberNotInList (CharPtr str);
 static Boolean ECnumberWasDeleted (CharPtr str);
 static Boolean ECnumberWasReplaced (CharPtr str);
+static void ValidateCitSub (ValidStructPtr vsp, CitSubPtr csp);
 
 /* alignment validator */
 NLM_EXTERN Boolean ValidateSeqAlignWithinValidator (ValidStructPtr vsp, SeqEntryPtr sep, Boolean find_remote_bsp, Boolean do_hist_assembly);
@@ -169,11 +171,14 @@ NLM_EXTERN void ValidStructClear (ValidStructPtr vsp)
   Boolean         is_htg_in_sep;
   Boolean         is_barcode_sep;
   Boolean         is_refseq_in_sep;
+  Boolean         is_gpipe_in_sep;
   Boolean         is_gps_in_sep;
   Boolean         is_embl_ddbj_in_sep;
+  Boolean         other_sets_in_sep;
   Boolean         is_insd_in_sep;
   Boolean         only_lcl_gnl_in_sep;
   Boolean         has_gnl_prot_sep;
+  Boolean         bsp_genomic_in_sep;
   Boolean         is_smupd_in_sep;
   Boolean         feat_loc_has_gi;
   Boolean         feat_prod_has_gi;
@@ -219,11 +224,14 @@ NLM_EXTERN void ValidStructClear (ValidStructPtr vsp)
   is_htg_in_sep = vsp->is_htg_in_sep;
   is_barcode_sep = vsp->is_barcode_sep;
   is_refseq_in_sep = vsp->is_refseq_in_sep;
+  is_gpipe_in_sep = vsp->is_gpipe_in_sep;
   is_gps_in_sep = vsp->is_gps_in_sep;
+  other_sets_in_sep = vsp->other_sets_in_sep;
   is_embl_ddbj_in_sep = vsp->is_embl_ddbj_in_sep;
   is_insd_in_sep = vsp->is_insd_in_sep;
   only_lcl_gnl_in_sep = vsp->only_lcl_gnl_in_sep;
   has_gnl_prot_sep = vsp->has_gnl_prot_sep;
+  bsp_genomic_in_sep = vsp->bsp_genomic_in_sep;
   is_smupd_in_sep = vsp->is_smupd_in_sep;
   feat_loc_has_gi = vsp->feat_loc_has_gi;
   feat_prod_has_gi = vsp->feat_prod_has_gi;
@@ -266,11 +274,14 @@ NLM_EXTERN void ValidStructClear (ValidStructPtr vsp)
   vsp->is_htg_in_sep = is_htg_in_sep;
   vsp->is_barcode_sep = is_barcode_sep;
   vsp->is_refseq_in_sep = is_refseq_in_sep;
+  vsp->is_gpipe_in_sep = is_gpipe_in_sep;
   vsp->is_gps_in_sep = is_gps_in_sep;
+  vsp->other_sets_in_sep = other_sets_in_sep;
   vsp->is_embl_ddbj_in_sep = is_embl_ddbj_in_sep;
   vsp->is_insd_in_sep = is_insd_in_sep;
   vsp->only_lcl_gnl_in_sep = only_lcl_gnl_in_sep;
   vsp->has_gnl_prot_sep = has_gnl_prot_sep;
+  vsp->bsp_genomic_in_sep = bsp_genomic_in_sep;
   vsp->is_smupd_in_sep = is_smupd_in_sep;
   vsp->feat_loc_has_gi = feat_loc_has_gi;
   vsp->feat_prod_has_gi = feat_prod_has_gi;
@@ -558,7 +569,9 @@ static CharPtr err1Label [] = {
   "ProteinsHaveGeneralID",
   "HighNContent",
   "SeqLitDataLength0",
-  "DSmRNA"
+  "DSmRNA",
+  "HighNContentStretch",
+  "HighNContentPercent"
 };
 
 static CharPtr err2Label [] = {
@@ -627,7 +640,18 @@ static CharPtr err2Label [] = {
   "WrongVoucherType",
   "UserObjectProblem",
   "TitleHasPMID",
-  "BadKeyword"
+  "BadKeyword",
+  "NoOrganismInTitle",
+  "MissingChromosome",
+  "LatLonAdjacent",
+  "BadStrucCommInvalidFieldName",
+  "BadStrucCommInvalidFieldValue",
+  "BadStrucCommMissingField",
+  "BadStrucCommFieldOutOfOrder",
+  "BadStrucCommMultipleFields",
+  "BioSourceNeedsChromosome",
+  "MolInfoConflictsWithBioSource",
+  "MissingKeyword"
 };
 
 static CharPtr err3Label [] = {
@@ -644,7 +668,9 @@ static CharPtr err3Label [] = {
   "CollidingSerialNumbers",
   "EmbeddedScript",
   "PublicationInconsistency",
-  "SgmlPresentInText"
+  "SgmlPresentInText",
+  "UnexpectedPubStatusComment",
+  "PastReleaseDate"
 };
 
 static CharPtr err4Label [] = {
@@ -670,7 +696,12 @@ static CharPtr err4Label [] = {
   "INSDRefSeqPackaging",
   "GPSnonGPSPackaging",
   "RefSeqPopSet",
-  "BioseqSetClassNotSet"
+  "BioseqSetClassNotSet",
+  "OrphanedProtein",
+  "MissingSetTitle",
+  "NucProtSetHasTitle",
+  "ComponentMissingTitle",
+  "SingleItemSet"
 };
 
 static CharPtr err5Label [] = {
@@ -849,7 +880,8 @@ static CharPtr err5Label [] = {
   "ReplicatedGeneSequence",
   "ShortIntron",
   "GeneXrefStrandProblem",
-  "CDSmRNAXrefLocationProblem"
+  "CDSmRNAXrefLocationProblem",
+  "LocusCollidesWithLocusTag"
 };
 
 static CharPtr err6Label [] = {
@@ -968,7 +1000,7 @@ static void CustValErr (ValidStructPtr vsp, ErrSev severity, int errcode, int su
   ObjValNodePtr     ovp;
   SeqDescrPtr       sdp;
   SeqEntryPtr       sep;
-  SeqFeatPtr        sfp;
+  SeqFeatPtr        sfp = NULL;
   SeqIdPtr          sip;
   SeqLocPtr         slp;
 
@@ -1067,8 +1099,9 @@ static void CustValErr (ValidStructPtr vsp, ErrSev severity, int errcode, int su
   }
 
   if (vsp->sfp != NULL) {
+    sfp = vsp->sfp;
     label = tmp;
-    diff = FeatDefLabel (vsp->sfp, tmp, wrklen, OM_LABEL_BOTH);
+    diff = FeatDefLabel (sfp, tmp, wrklen, OM_LABEL_BOTH);
     buflen -= diff;
     tmp += diff;
     *tmp = '\0';
@@ -1502,6 +1535,124 @@ NLM_EXTERN void CDECL ValidErr (ValidStructPtr vsp, int severity, int code1, int
   vsp->errbuf[0] = '\0';
 }
 
+
+static CharPtr GetUserFieldLabelString (UserFieldPtr ufp)
+{
+  Char buf[15];
+
+  if (ufp == NULL || ufp->label == NULL) {
+    return StringSave ("Unlabeled field");
+  } else if (ufp->label->id > 0) {
+    sprintf (buf, "%d", ufp->label->id);
+    return StringSave (buf);
+  } else {
+    return StringSave (ufp->label->str);
+  }
+}
+
+
+static CharPtr GetUserFieldValueString (UserFieldPtr ufp)
+{
+  Char buf[15];
+
+  if (ufp == NULL) {
+    return StringSave ("Value is missing");
+  } else if (ufp->choice == 1) {
+    return StringSave (ufp->data.ptrvalue);
+  } else if (ufp->choice == 2) {
+    sprintf (buf, "%d", ufp->data.intvalue);
+    return StringSave (buf);
+  } else {
+    return StringSave ("Bad format for value");
+  }
+}
+
+
+static ErrSev ErrorLevelFromFieldRuleSev (Uint2 severity)
+{
+  ErrSev sev = SEV_ERROR;
+  switch (severity) {
+    case Severity_level_none:
+      sev = SEV_NONE;
+      break;
+    case Severity_level_info:
+      sev = SEV_INFO;
+      break;
+    case Severity_level_warning:
+      sev = SEV_WARNING;
+      break;
+    case Severity_level_error:
+      sev = SEV_ERROR;
+      break;
+    case Severity_level_reject:
+      sev = SEV_REJECT;
+      break;
+    case Severity_level_fatal:
+      sev = SEV_FATAL;
+      break;
+  }
+  return sev;
+}
+
+static void StructuredCommentError (EFieldValid err_code, FieldRulePtr field_rule, UserFieldPtr ufp, UserFieldPtr depend_ufp, Pointer data)
+{
+  ValidStructPtr     vsp;
+  CharPtr            label, val;
+  CharPtr            depend_label, depend_val, depend_str = NULL;
+  CharPtr            depend_fmt = " when %s has value '%s'";
+  ErrSev             sev = SEV_ERROR;
+
+  if ((vsp = (ValidStructPtr) data) == NULL) {
+    return;
+  }
+
+  if (field_rule != NULL) {
+    sev = ErrorLevelFromFieldRuleSev(field_rule->severity);
+  }
+
+  if (depend_ufp != NULL) {
+    depend_label = GetUserFieldLabelString  (depend_ufp);
+    depend_val = GetUserFieldValueString (depend_ufp);
+    depend_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (depend_fmt) + StringLen (depend_label) + StringLen (depend_val)));
+    sprintf (depend_str, depend_fmt, depend_label, depend_val);
+    depend_val = MemFree (depend_val);
+    depend_label = MemFree (depend_label);
+  }
+
+  switch (err_code) {
+    case eFieldValid_Invalid:
+      label = GetUserFieldLabelString  (ufp);
+      if (field_rule == NULL) {
+        ValidErr (vsp, sev, ERR_SEQ_DESCR_BadStrucCommInvalidFieldName, "%s is not a valid field name%s", label, depend_str == NULL ? "" : depend_str);
+      } else {
+        val = GetUserFieldValueString (ufp);
+        ValidErr (vsp, sev, ERR_SEQ_DESCR_BadStrucCommInvalidFieldValue, "%s is not a valid value for %s%s", val, label, depend_str == NULL ? "" : depend_str);
+        val = MemFree (val);
+      }
+      label = MemFree (label);
+      break;
+    case eFieldValid_MissingRequiredField:
+      ValidErr (vsp, sev, ERR_SEQ_DESCR_BadStrucCommMissingField, "Required field %s is missing%s", field_rule->field_name, depend_str == NULL ? "" : depend_str);
+      break;
+    case eFieldValid_FieldOutOfOrder:
+      ValidErr (vsp, sev, ERR_SEQ_DESCR_BadStrucCommFieldOutOfOrder, "%s field is out of order%s", field_rule->field_name, depend_str == NULL ? "" : depend_str);
+      break;
+    case eFieldValid_DuplicateField:
+      ValidErr (vsp, sev, ERR_SEQ_DESCR_BadStrucCommMultipleFields, "Multiple values for %s field%s", field_rule->field_name, depend_str == NULL ? "" : depend_str);
+      break;
+    case eFieldValid_Disallowed:
+      label = GetUserFieldLabelString  (ufp);
+      ValidErr (vsp, sev, ERR_SEQ_DESCR_BadStrucCommInvalidFieldName, "%s is not a valid field name%s", label, depend_str == NULL ? "" : depend_str);
+      label = MemFree (label);
+      break;
+    default:
+      /* do nothing */
+      break;
+  }
+  depend_str = MemFree (depend_str);
+}
+
+
 /*****************************************************************************
 *
 *   Valid1GatherProc(gcp)
@@ -1512,25 +1663,28 @@ NLM_EXTERN void CDECL ValidErr (ValidStructPtr vsp, int severity, int code1, int
 static Boolean Valid1GatherProc (GatherContextPtr gcp)
 {
   ValidStructPtr     vsp;
+  UserFieldPtr       curr;
   AnnotDescrPtr      desc;
+  CharPtr            field;
   SeqAnnotPtr        sap;
-  ObjectIdPtr        oip;
   Boolean            is_blast_align;
   Int2               limit;
   SeqFeatPtr         sfp;
   ValNodePtr         sdp;
   SeqGraphPtr        sgp;
   BioSourcePtr       biop;
+  ObjectIdPtr        oip;
   PubdescPtr         pdp;
+  CharPtr            ptr;
   BioseqPtr          bsp;
   SeqIdPtr           sip;
+  CharPtr            str;
   Char               buf [64];
   Char               tmp [64];
+  ValNodePtr         vnp2;
   SeqMgrFeatContext  context;
-#ifdef TEST_VALIDAPI
   UserObjectPtr uop;
   EFieldValid   sc_valid;
-#endif
 
   vsp = (ValidStructPtr) (gcp->userdata);
   vsp->gcp = gcp;               /* needed for ValidErr */
@@ -1688,14 +1842,44 @@ static Boolean Valid1GatherProc (GatherContextPtr gcp)
           ValidatePubdesc (vsp, gcp, pdp);
           LookForMultiplePubs (vsp, gcp, sdp);
         }
-#ifdef TEST_VALIDAPI
         if (sdp->choice == Seq_descr_user) {
           uop = sdp->data.ptrvalue;
           if (uop != NULL && uop->type != NULL && StringICmp (uop->type->str, "StructuredComment") == 0) {
-            sc_valid = IsStructuredCommentValid (uop);
+            sc_valid = IsStructuredCommentValid (uop, StructuredCommentError, vsp);
+            /* report ? */
+            for (curr = uop->data; curr != NULL; curr = curr->next) {
+              if (curr->choice != 1) continue;
+              oip = curr->label;
+              if (oip == NULL) continue;
+              field = oip->str;
+              if (StringStr (field, "::") != NULL) {
+                ValidErr (vsp, SEV_REJECT, ERR_SEQ_DESCR_BadStrucCommInvalidFieldName, "Structured comment field '%s' contains double colons", field);
+              }
+              str = (CharPtr) curr->data.ptrvalue;
+              if (StringStr (str, "::") != NULL) {
+                ValidErr (vsp, SEV_REJECT, ERR_SEQ_DESCR_BadStrucCommInvalidFieldValue, "Structured comment value '%s' contains double colons", str);
+              }
+            }
+          }
+        }
+        if (sdp->choice == Seq_descr_comment) {
+          str = (CharPtr) sdp->data.ptrvalue;
+          if (StringHasNoText (str)) {
+            ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_MissingText, "Comment descriptor needs text");
+          }
+          if (SerialNumberInString (str)) {
+            ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_SerialInComment,
+                      "Comment may refer to reference by serial number - attach reference specific comments to the reference REMARK instead.");
+          }
+          for (vnp2 = sdp->next; vnp2 != NULL; vnp2 = vnp2->next) {
+            if (vnp2->choice == Seq_descr_comment) {
+              ptr = (CharPtr) vnp2->data.ptrvalue;
+              if (StringDoesHaveText (ptr) && StringICmp (str, ptr) == 0) {
+                ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_MultipleComments, "Undesired multiple comment descriptors, identical text");
+              }
+            }
           }
         }
-#endif
         if (sdp->choice == Seq_descr_mol_type) {
           ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_InvalidForType, "MolType descriptor is obsolete");
         }
@@ -2615,213 +2799,147 @@ static void ValidateSeqIdCase (SeqEntryPtr sep, ValidStructPtr vsp)
   ValNodeFreeData (vd.headid);
 }
 
-static void LookForNC (BioseqPtr bsp, Pointer userdata)
+static void LookForBioseqFields (BioseqPtr bsp, Pointer userdata)
 
 {
-  BoolPtr       is_ncp;
-  SeqIdPtr      sip;
-  TextSeqIdPtr  tsip;
-
-  if (bsp == NULL || userdata == NULL) return;
-  is_ncp = (BoolPtr) userdata;
-  for (sip = bsp->id; sip != NULL; sip = sip->next) {
-    if (sip->choice == SEQID_OTHER) {
-      tsip = (TextSeqIdPtr) sip->data.ptrvalue;
-      if (tsip != NULL && tsip->accession != NULL) {
-        /*
-        if (StringNICmp (tsip->accession, "NC_", 3) == 0) {
-          *is_ncp = TRUE;
-        }
-        */
-        *is_ncp = TRUE; /* any refseq now drops pubdesc message severity */
-      }
-    }
-  }
-}
-
-static void LookForGPS (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
-
-{
-  BioseqSetPtr  bssp;
-  BoolPtr       is_gpsp;
-
-  if (sep == NULL || data == NULL) return;
-  is_gpsp = (BoolPtr) data;
-
-  if (IS_Bioseq_set (sep)) {
-    bssp = (BioseqSetPtr) sep->data.ptrvalue;
-    if (bssp != NULL && bssp->_class == BioseqseqSet_class_gen_prod_set) {
-      *is_gpsp = TRUE;
-    }
-  }
-}
-
-static void LookForNonGPS (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
-
-{
-  BioseqSetPtr  bssp;
-  BoolPtr       is_ngpsp;
-
-  if (sep == NULL || data == NULL) return;
-  is_ngpsp = (BoolPtr) data;
-
-  if (IS_Bioseq_set (sep)) {
-    bssp = (BioseqSetPtr) sep->data.ptrvalue;
-    if (bssp == NULL) return;
-    if (bssp->_class == BioseqseqSet_class_mut_set ||
-        bssp->_class == BioseqseqSet_class_pop_set ||
-        bssp->_class == BioseqseqSet_class_phy_set ||
-        bssp->_class == BioseqseqSet_class_eco_set ||
-        bssp->_class == BioseqseqSet_class_wgs_set) {
-      *is_ngpsp = TRUE;
-    }
-  }
-}
-
-static void LookForEmblDdbj (BioseqPtr bsp, Pointer userdata)
-
-{
-  BoolPtr   is_ed;
+  DbtagPtr        dbt;
+  Boolean         has_lcl_gnl = FALSE;
+  Boolean         has_others = FALSE;
   SeqIdPtr  sip;
+  ValidStructPtr  vsp;
 
   if (bsp == NULL || userdata == NULL) return;
-  is_ed = (BoolPtr) userdata;
-  for (sip = bsp->id; sip != NULL; sip = sip->next) {
-    if (sip->choice == SEQID_EMBL || sip->choice == SEQID_DDBJ) {
-      *is_ed = TRUE;
-    }
-  }
-}
+  vsp = (ValidStructPtr) userdata;
 
-static void LookForGEDseqID (BioseqPtr bsp, Pointer userdata)
-{
-  BoolPtr         isGEDPtr;
-  SeqIdPtr        sip;
-
-  isGEDPtr = (BoolPtr) userdata;
   for (sip = bsp->id; sip != NULL; sip = sip->next) {
     switch (sip->choice) {
-    case SEQID_GENBANK:
     case SEQID_EMBL:
     case SEQID_DDBJ:
+      vsp->is_embl_ddbj_in_sep = TRUE;
+      /* and fall through */
+    case SEQID_GENBANK:
     case SEQID_TPG:
     case SEQID_TPE:
     case SEQID_TPD:
-      *isGEDPtr = TRUE;
-      return;
-    default:
+      vsp->is_insd_in_sep = TRUE;
+      break;
+    case SEQID_OTHER:
+      vsp->is_refseq_in_sep = TRUE;
       break;
+    case SEQID_GPIPE:
+      vsp->is_gpipe_in_sep = TRUE;
+      break;
+    case SEQID_GENERAL:
+      if (ISA_aa (bsp->mol)) {
+        dbt = (DbtagPtr) sip->data.ptrvalue;
+        if (dbt == NULL) break;
+        if (IsSkippableDbtag (dbt)) break;
+        vsp->has_gnl_prot_sep = TRUE;
     }
+      break;
+    default:
+      break;
   }
-}
-
-static void LookForLclGnl (BioseqPtr bsp, Pointer userdata)
-
-{
-  Boolean   has_lcl_gnl = FALSE;
-  Boolean   has_others = FALSE;
-  BoolPtr   is_lcl_gnl_P;
-  SeqIdPtr  sip;
-
-  if (bsp == NULL || userdata == NULL) return;
-  is_lcl_gnl_P = (BoolPtr) userdata;
-  for (sip = bsp->id; sip != NULL; sip = sip->next) {
     if (sip->choice == SEQID_LOCAL || sip->choice == SEQID_GENERAL) {
       has_lcl_gnl = TRUE;
     } else {
       has_others = TRUE;
     }
   }
-  if (has_others) {
-    *is_lcl_gnl_P = FALSE;
-    return;
-  }
-  if (has_lcl_gnl) {
-    *is_lcl_gnl_P = TRUE;
-  }
-}
-
-static void LookForProteinGnl (BioseqPtr bsp, Pointer userdata)
-
-{
-  DbtagPtr  dbt;
-  Boolean   has_gnl_prot = FALSE;
-  BoolPtr   is_gnl_prot_P;
-  SeqIdPtr  sip;
-
-  if (bsp == NULL || userdata == NULL) return;
-  if (! ISA_aa (bsp->mol)) return;
-  is_gnl_prot_P = (BoolPtr) userdata;
-  for (sip = bsp->id; sip != NULL; sip = sip->next) {
-    if (sip->choice == SEQID_GENERAL) {
-      dbt = (DbtagPtr) sip->data.ptrvalue;
-      if (dbt == NULL) continue;
-      if (IsSkippableDbtag (dbt)) continue;
-      has_gnl_prot = TRUE;
-    }
-  }
-  if (has_gnl_prot) {
-    *is_gnl_prot_P = TRUE;
+  if (has_lcl_gnl && ! has_others) {
+    vsp->only_lcl_gnl_in_sep = TRUE;
   }
 }
 
-static void LookForHTG (SeqDescrPtr sdp, Pointer userdata)
+static void LookForBioseqSetFields (BioseqSetPtr bssp, Pointer userdata)
 
 {
-  BoolPtr     is_htgp;
-  MolInfoPtr  mip;
-
-  if (sdp == NULL || userdata == NULL) return;
-  if (sdp->choice != Seq_descr_molinfo) return;
-
-  mip = (MolInfoPtr) sdp->data.ptrvalue;
-  if (mip == NULL) return;
+  ValidStructPtr  vsp;
 
-  if (mip->tech == MI_TECH_htgs_1 ||
-      mip->tech == MI_TECH_htgs_2 ||
-      mip->tech == MI_TECH_htgs_3 ||
-      mip->tech == MI_TECH_htgs_0) {
+  if (bssp == NULL || userdata == NULL) return;
+  vsp = (ValidStructPtr) userdata;
 
-    is_htgp = (BoolPtr) userdata;
-    *is_htgp = TRUE; /* any htg now drops citsub missing affil message severity */
+  /* the switch statement is erroneously reporting gen_prod_set for a pop_set under Xcode */
+  /*
+  switch (bssp->_class) {
+  case BioseqseqSet_class_gen_prod_set:
+    vsp->is_gps_in_sep = TRUE;
+    break;
+  case BioseqseqSet_class_mut_set:
+  case BioseqseqSet_class_pop_set:
+  case BioseqseqSet_class_phy_set:
+  case BioseqseqSet_class_eco_set:
+  case BioseqseqSet_class_wgs_set:
+    break;
+    vsp->other_sets_in_sep = TRUE;
+  default:
+    break;
   }
-}
-
-static void LookForBarcode (SeqDescrPtr sdp, Pointer userdata)
-
-{
-  BoolPtr     is_barcode;
-  MolInfoPtr  mip;
-
-  if (sdp == NULL || userdata == NULL) return;
-  if (sdp->choice != Seq_descr_molinfo) return;
-
-  mip = (MolInfoPtr) sdp->data.ptrvalue;
-  if (mip == NULL) return;
-
-  if (mip->tech == MI_TECH_barcode) {
+  */
 
-    is_barcode = (BoolPtr) userdata;
-    *is_barcode = TRUE; /* any barcode now drops bad country code message severity */
+  if (bssp->_class == BioseqseqSet_class_gen_prod_set) {
+    vsp->is_gps_in_sep = TRUE;
+  } else if (bssp->_class == BioseqseqSet_class_mut_set ||
+             bssp->_class == BioseqseqSet_class_pop_set ||
+             bssp->_class == BioseqseqSet_class_phy_set ||
+             bssp->_class == BioseqseqSet_class_eco_set ||
+             bssp->_class == BioseqseqSet_class_wgs_set) {
+    vsp->other_sets_in_sep = TRUE;
   }
 }
 
-static void LookForSMUPD (SeqDescrPtr sdp, Pointer userdata)
+static void LookForSeqDescrFields (SeqDescrPtr sdp, Pointer userdata)
 
 {
-  BoolPtr        is_smupdp;
+  BioSourcePtr    biop;
+  MolInfoPtr      mip;
+  ObjectIdPtr     oip;
   UserObjectPtr  uop;
+  ValidStructPtr  vsp;
 
   if (sdp == NULL || userdata == NULL) return;
-  if (sdp->choice != Seq_descr_user) return;
+  vsp = (ValidStructPtr) userdata;
 
+  switch (sdp->choice) {
+  case Seq_descr_user:
   uop = (UserObjectPtr) sdp->data.ptrvalue;
-  if (uop == NULL) return;
-
+    if (uop == NULL) break;
   if (StringICmp (uop->_class, "SMART_V1.0") == 0) {
-
-    is_smupdp = (BoolPtr) userdata;
-    *is_smupdp = TRUE;
+      vsp->is_smupd_in_sep = TRUE;
+    }
+    oip = uop->type;
+    if (oip != NULL) {
+      if (StringICmp (oip->str, "GenomeBuild") == 0) {
+        vsp->is_gpipe_in_sep = TRUE;
+      }
+    }
+    break;
+  case Seq_descr_source:
+    biop = (BioSourcePtr) sdp->data.ptrvalue;
+    if (biop == NULL) break;
+    if (biop->genome == GENOME_genomic) {
+      vsp->bsp_genomic_in_sep = TRUE;
+    }
+    break;
+  case Seq_descr_molinfo:
+    mip = (MolInfoPtr) sdp->data.ptrvalue;
+    if (mip == NULL) break;
+    switch (mip->tech) {
+    case MI_TECH_htgs_1:
+    case MI_TECH_htgs_2:
+    case MI_TECH_htgs_3:
+    case MI_TECH_htgs_0:
+      vsp->is_htg_in_sep = TRUE;
+      break;
+    case MI_TECH_barcode:
+      vsp->is_barcode_sep = TRUE;
+      break;
+    default:
+      break;
+    }
+    break;
+  default:
+    break;
   }
 }
 
@@ -3188,11 +3306,175 @@ static void TestDeletedOrReplacedECnumbers (ValidStructPtr vsp)
   }
 }
 
+
+typedef struct collisioninfo {
+  CharPtr str;
+  SeqIdPtr sip;
+  BioseqPtr bsp;
+} CollisionInfoData, PNTR CollisionInfoPtr;
+
+
+static CollisionInfoPtr CollisionInfoNew (SeqIdPtr sip, BioseqPtr bsp)
+{
+  CollisionInfoPtr cip = (CollisionInfoPtr) MemNew (sizeof (CollisionInfoData));
+  cip->sip = sip;
+  cip->bsp = bsp;
+  cip->str = SeqIdWholeLabel (sip, PRINTID_FASTA_SHORT);
+  return cip;
+}
+
+
+static CollisionInfoPtr CollisionInfoFree (CollisionInfoPtr cip)
+{
+  if (cip != NULL) {
+    cip->str = MemFree (cip->str);
+    cip = MemFree (cip);
+  }
+  return cip;
+}
+
+
+static Boolean IsNcbiFileId(SeqIdPtr sip)
+{
+  DbtagPtr dbtag;
+
+  if (sip == NULL || sip->choice != SEQID_GENERAL || (dbtag = sip->data.ptrvalue) == NULL) {
+    return FALSE;
+  }
+  if (StringCmp (dbtag->db, "NCBIFILE") == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static void LongCollisionCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqIdPtr sip;
+
+  if (bsp == NULL || data == NULL) {
+    return;
+  }
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (!IsNcbiFileId(sip)) {
+      ValNodeAddPointer ((ValNodePtr PNTR) data, 0, CollisionInfoNew (sip, bsp));
+    }
+  }
+}
+
+
+static int LIBCALLBACK SortVnpByCollisionInfo (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  CollisionInfoPtr  cip1, cip2;
+  ValNodePtr    vnp1, vnp2;
+
+  if (ptr1 == NULL || ptr2 == NULL) return 0;
+  vnp1 = *((ValNodePtr PNTR) ptr1);
+  vnp2 = *((ValNodePtr PNTR) ptr2);
+  if (vnp1 == NULL || vnp2 == NULL) return 0;
+  cip1 = (CollisionInfoPtr) vnp1->data.ptrvalue;
+  cip2 = (CollisionInfoPtr) vnp2->data.ptrvalue;
+
+  if (cip1 == NULL || cip2 == NULL) return 0;
+  return StringCmp (cip1->str, cip2->str);
+}
+
+
+static void FindLongIdsThatCollideWhenTruncated (SeqEntryPtr sep, ValidStructPtr vsp, Int4 trunc_len)
+{
+  ValNodePtr id_list = NULL, vnp, vnp_c;
+  CollisionInfoPtr  cip1, cip2;
+  BioseqPtr         oldbsp;
+
+  VisitBioseqsInSep (sep, &id_list, LongCollisionCallback);
+  id_list = ValNodeSort (id_list, SortVnpByCollisionInfo);
+  oldbsp = vsp->bsp;
+
+  for (vnp = id_list; vnp != NULL; vnp = vnp->next) {
+    cip1 = (CollisionInfoPtr) vnp->data.ptrvalue;
+    vnp_c = vnp->next;
+    while (vnp_c != NULL && (cip2 = (CollisionInfoPtr) vnp_c->data.ptrvalue) != NULL
+          && StringNCmp (cip1->str, cip2->str, trunc_len) == 0) {
+      vsp->bsp = cip2->bsp;
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_BadSeqIdFormat,
+                "First %d characters of %s and %s are identical", trunc_len, cip1->str, cip2->str);
+      vnp = vnp_c;
+      vnp_c = vnp_c->next;
+    }
+  }
+
+  vsp->bsp = oldbsp;
+  vnp = id_list;
+  while (vnp != NULL) {
+    vnp_c = vnp->next;
+    vnp->data.ptrvalue = CollisionInfoFree (vnp->data.ptrvalue);
+    vnp->next = NULL;
+    vnp = ValNodeFree (vnp);
+    vnp = vnp_c;
+  }
+}
+
+
+static void ValLookForBigFarSeqs (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  Int4         count = 0;
+  DeltaSeqPtr  dsp;
+  Boolean      is_ddbj = FALSE;
+  SeqIdPtr     sip;
+  BoolPtr      toomanyfarP;
+
+  if (bsp == NULL || userdata == NULL) return;
+
+  if (bsp->repr != Seq_repr_delta) return;
+  if (bsp->seq_ext_type != 4) return;
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_DDBJ) {
+      is_ddbj = TRUE;
+    }
+  }
+
+  if (! is_ddbj) return;
+
+  for (dsp = (DeltaSeqPtr) bsp->seq_ext; dsp != NULL; dsp = dsp->next) {
+    if (dsp->choice == 1) {
+      count++;
+    }
+  }
+
+  if (count > 10000) {
+    toomanyfarP = (BoolPtr) userdata;
+    *toomanyfarP = TRUE;
+  }
+}
+
+static Boolean ValTooManyFarComponents (
+  SeqEntryPtr sep
+)
+
+{
+  Boolean  toomanyfar = FALSE;
+
+  if (sep == NULL) return FALSE;
+
+  VisitBioseqsInSep (sep, (Pointer) &toomanyfar, ValLookForBigFarSeqs);
+
+  return toomanyfar;
+}
+
 NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
 
 {
   AuthListPtr     alp;
   AuthorPtr       ap;
+  DatePtr         cd, dp;
   ContactInfoPtr  cip;
   CitSubPtr       csp;
   Uint2           entityID = 0;
@@ -3207,7 +3489,6 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
   Int2            i;
   Boolean         suppress_no_pubs = TRUE;
   Boolean         suppress_no_biosrc = TRUE;
-  Boolean         other_sets_in_sep = FALSE;
   FeatProb        featprob;
   GatherContextPtr gcp = NULL;
   GatherContext   gc;
@@ -3308,6 +3589,24 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
   }
 
   vsp->is_htg_in_sep = FALSE;
+  vsp->is_barcode_sep = FALSE;
+  vsp->is_refseq_in_sep = FALSE;
+  vsp->is_gpipe_in_sep = FALSE;
+  vsp->is_gps_in_sep = FALSE;
+  vsp->other_sets_in_sep = FALSE;
+  vsp->is_embl_ddbj_in_sep = FALSE;
+  vsp->is_insd_in_sep = FALSE;
+  vsp->only_lcl_gnl_in_sep = FALSE;
+  vsp->has_gnl_prot_sep = FALSE;
+  vsp->bsp_genomic_in_sep = FALSE;
+  vsp->is_smupd_in_sep = FALSE;
+
+  VisitBioseqsInSep (sep, (Pointer) vsp, LookForBioseqFields);
+  VisitSetsInSep (sep, (Pointer) vsp, LookForBioseqSetFields);
+  VisitDescriptorsInSep (sep, (Pointer) vsp, LookForSeqDescrFields);
+
+  /*
+  vsp->is_htg_in_sep = FALSE;
   VisitDescriptorsInSep (sep, (Pointer) &(vsp->is_htg_in_sep), LookForHTG);
   vsp->is_barcode_sep = FALSE;
   VisitDescriptorsInSep (sep, (Pointer) &(vsp->is_barcode_sep), LookForBarcode);
@@ -3315,8 +3614,8 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
   VisitDescriptorsInSep (sep, (Pointer) &(vsp->is_smupd_in_sep), LookForSMUPD);
   vsp->is_gps_in_sep = FALSE;
   SeqEntryExplore (sep, (Pointer) &(vsp->is_gps_in_sep), LookForGPS);
-  other_sets_in_sep = FALSE;
-  SeqEntryExplore (sep, (Pointer) &(other_sets_in_sep), LookForNonGPS);
+  vsp->other_sets_in_sep = FALSE;
+  SeqEntryExplore (sep, (Pointer) &(vsp->other_sets_in_sep), LookForNonGPS);
   vsp->is_refseq_in_sep = FALSE;
   VisitBioseqsInSep (sep, (Pointer) &(vsp->is_refseq_in_sep), LookForNC);
   vsp->is_embl_ddbj_in_sep = FALSE;
@@ -3327,6 +3626,7 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
   VisitBioseqsInSep (sep, (Pointer) &(vsp->only_lcl_gnl_in_sep), LookForLclGnl);
   vsp->has_gnl_prot_sep = FALSE;
   VisitBioseqsInSep (sep, (Pointer) &(vsp->has_gnl_prot_sep), LookForProteinGnl);
+  */
 
   vsp->feat_loc_has_gi = featprob.loc_has_gi;
   vsp->feat_prod_has_gi = featprob.prod_has_gi;
@@ -3363,7 +3663,7 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
                 "INSD and RefSeq records should not be present in the same set");
     }
 
-    if (vsp->is_gps_in_sep && other_sets_in_sep) {
+    if (vsp->is_gps_in_sep && vsp->other_sets_in_sep) {
       ValidErr (vsp, SEV_ERROR, ERR_SEQ_PKG_GPSnonGPSPackaging,
                 "Genomic product set and mut/pop/phy/eco set records should not be present in the same set");
     }
@@ -3383,6 +3683,7 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
       /* lock all remote genome components, locations, and products in advance */
 
       limit = vsp->validationLimit;
+      if (! ValTooManyFarComponents (sep)) {
       if (limit == VALIDATE_ALL || limit == VALIDATE_INST || limit == VALIDATE_HIST) {
         farFetchProd = (Boolean) (vsp->farFetchCDSproducts || vsp->farFetchMRNAproducts);
         oldsev = ErrSetMessageLevel (SEV_WARNING);
@@ -3390,6 +3691,7 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
         ErrSetMessageLevel (oldsev);
       }
     }
+    }
 
     fsep = FindNthBioseq (sep, 1);
     fbsp = NULL;
@@ -3483,6 +3785,10 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
       topsep = GetTopSeqEntryForEntityID (gc.entityID);
       oldsep = SeqEntrySetScope (topsep);
   
+      /* disabled for now
+      FindLongIdsThatCollideWhenTruncated (topsep, vsp, 30);
+      */
+
       /* do validator tests using Discrepancy Report */
       ValidateGeneLocusTags (topsep, vsp);
       ValidateShortIntrons (topsep, vsp);
@@ -3509,6 +3815,7 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
               if (alp != NULL) {
                 ValidateAffil (vsp, alp->affil);
               }
+              ValidateCitSub (vsp, csp);
             }
             cip = sbp->contact;
             if (cip != NULL) {
@@ -3517,6 +3824,17 @@ NLM_EXTERN Boolean ValidateSeqEntry (SeqEntryPtr sep, ValidStructPtr vsp)
                 ValidateAffil (vsp, ap->affil);
               }
             }
+            if (sbp->hup) {
+              dp = sbp->reldate;
+              cd = DateCurr ();
+              if (dp != NULL && cd != NULL) {
+                if (DateMatch (dp, cd, FALSE) == -1) {
+                  ValidErr (vsp, SEV_WARNING, ERR_GENERIC_PastReleaseDate,
+                            "Record release date has already passed");
+                }
+              }
+              DateFree (cd);
+            }
           }
         }
       }
@@ -3789,6 +4107,9 @@ static void ValidateNucProtSet (BioseqSetPtr bssp, ValidStructPtr vsp)
         orp = biop->org;
         if (orp != NULL && StringDoesHaveText (orp->taxname)) return;
       }
+    } else if (sdp->choice == Seq_descr_title) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_PKG_NucProtSetHasTitle,
+                "Nuc-prot set should not have title descriptor");
     }
   }
 
@@ -3992,11 +4313,6 @@ static Boolean CheckForInconsistentBiosources (SeqEntryPtr sep, ValidStructPtr v
     return FALSE;
   }
 
-  if (StringNICmp (orp->taxname, "Influenza virus ", 16) == 0 &&
-      StringNICmp (firstorp->taxname, "Influenza virus ", 16) == 0 && StringNICmp (orp->taxname, firstorp->taxname, 17) == 0) {
-    return FALSE;
-  }
-
   if (StringICmp (orp->taxname, firstorp->taxname) == 0)
     return FALSE;
 
@@ -4165,6 +4481,68 @@ static void ValidatePopSet (BioseqSetPtr bssp, ValidStructPtr vsp)
   }
 }
 
+typedef struct mutsetsrcdata {
+  CharPtr  taxname;
+  Int2     num_not_mut_origin;
+  Boolean  failed;
+} MutSetSrcData, PNTR MutSetSrcPtr;
+
+static void CheckMutSetSources (BioSourcePtr biop, Pointer userdata)
+
+{
+  MutSetSrcPtr  mssp;
+  OrgRefPtr     orp;
+
+  if (biop == NULL || userdata == NULL) return;
+  mssp = (MutSetSrcPtr) userdata;
+
+  orp = biop->org;
+  if (orp == NULL || StringHasNoText (orp->taxname)) return;
+  if (mssp->taxname == NULL) {
+    mssp->taxname = orp->taxname;
+  } else if (StringCmp (mssp->taxname, orp->taxname) != 0) {
+    mssp->failed = TRUE;
+  }
+  if (biop->origin != ORG_MUT) {
+    (mssp->num_not_mut_origin)++;
+  }
+}
+
+static void ValidateMutSet (BioseqSetPtr bssp, ValidStructPtr vsp)
+
+{
+  BioseqSetPtr   bssp1;
+/*  MutSetSrcData  mssd; */
+  SeqEntryPtr    sep;
+
+  if (bssp->_class != BioseqseqSet_class_mut_set)
+    return;
+
+  for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
+    if (!IS_Bioseq_set (sep)) continue;
+    bssp1 = sep->data.ptrvalue;
+    if (bssp1 == NULL) continue;
+
+    if (bssp1->_class == BioseqseqSet_class_genbank) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_PKG_InternalGenBankSet,
+                "Bioseq-set contains internal GenBank Bioseq-set");
+    }
+  }
+
+  LookForMolInfoInconsistency (bssp, vsp);
+
+  /* error is currently suppressed
+  MemSet ((Pointer) &mssd, 0, sizeof (MutSetSrcData));
+  VisitBioSourcesInSet (bssp, (Pointer) &mssd, CheckMutSetSources);
+  if (mssd.failed) {
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_InconsistentBioSources, "Mutation set contains inconsistent organisms.");
+  }
+  if (mssd.num_not_mut_origin > 1) {
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_InconsistentBioSources, "Mutation set contains more than one non-mutant organism.");
+  }
+  */
+}
+
 static void ValidateGenbankSet (BioseqSetPtr bssp, ValidStructPtr vsp)
 
 {
@@ -4183,7 +4561,7 @@ static void ValidateGenbankSet (BioseqSetPtr bssp, ValidStructPtr vsp)
   }
 }
 
-static void ValidatePhyMutEcoWgsSet (BioseqSetPtr bssp, ValidStructPtr vsp)
+static void ValidatePhyEcoWgsSet (BioseqSetPtr bssp, ValidStructPtr vsp)
 
 {
   BioseqSetPtr  bssp1;
@@ -4269,6 +4647,9 @@ static void ValidateBioseqSet (GatherContextPtr gcp)
   BioseqSetPtr    bssp;
   ValidStructPtr  vsp;
   SeqEntryPtr     sep;
+  SeqDescrPtr     sdp;
+  CharPtr         str;
+  Boolean         has_title = FALSE;
 
   vsp = (ValidStructPtr) (gcp->userdata);
   bssp = (BioseqSetPtr) (gcp->thisitem);
@@ -4327,10 +4708,12 @@ static void ValidateBioseqSet (GatherContextPtr gcp)
     ValidatePopSet (bssp, vsp);
     break;
   case BioseqseqSet_class_mut_set:
+    ValidateMutSet (bssp, vsp);
+    break;
   case BioseqseqSet_class_phy_set:
   case BioseqseqSet_class_eco_set:
   case BioseqseqSet_class_wgs_set:
-    ValidatePhyMutEcoWgsSet (bssp, vsp);
+    ValidatePhyEcoWgsSet (bssp, vsp);
     break;
   case BioseqseqSet_class_gen_prod_set:
     ValidateGenProdSet (bssp, vsp);
@@ -4346,7 +4729,33 @@ static void ValidateBioseqSet (GatherContextPtr gcp)
     }
     break;
   }
-  return;
+
+  switch (bssp->_class) {
+  case BioseqseqSet_class_pop_set:
+  case BioseqseqSet_class_mut_set:
+  case BioseqseqSet_class_phy_set:
+  case BioseqseqSet_class_eco_set:
+    for (sdp = bssp->descr; sdp != NULL; sdp = sdp->next) {
+      if (sdp->choice != Seq_descr_title) continue;
+      str = (CharPtr) sdp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      has_title = TRUE;
+    }
+    if (! has_title && (vsp->is_insd_in_sep || vsp->is_refseq_in_sep)) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_PKG_MissingSetTitle, "Pop/Phy/Mut/Eco set does not have title");
+    }
+    sep = bssp->seq_set;
+    if (sep == NULL) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_PKG_EmptySet, "Pop/Phy/Mut/Eco set has no components");
+    } else if (sep->next == NULL) {
+      if (VisitAlignmentsInSep (sep, NULL, NULL) == 0) {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_PKG_SingleItemSet, "Pop/Phy/Mut/Eco set has only one component and no alignments");
+      }
+    }
+    break;
+  default:
+    break;
+  }
 }
 
 static Boolean SuppressTrailingXMessage (BioseqPtr bsp)
@@ -4961,6 +5370,25 @@ static CharPtr legal_refgene_status_strings [] = {
 };
 
 
+static void ReportLongSeqId (SeqIdPtr sip, ValidStructPtr vsp, Int4 max_len)
+{
+  Int4 id_len = 0;
+  CharPtr id_txt;
+
+  if (sip == NULL || vsp == NULL || IsNcbiFileId(sip)) {
+    return;
+  }
+
+  id_len = SeqIdLabelLen(sip, PRINTID_FASTA_SHORT);
+  if (id_len > max_len) {
+    id_txt = SeqIdWholeLabel (sip, PRINTID_FASTA_SHORT);
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_BadSeqIdFormat, "Sequence ID is unusually long (%d): %s", id_len, id_txt);
+    id_txt = MemFree (id_txt);
+  }
+
+}
+
+
 static void ValidateBioseqInst (GatherContextPtr gcp)
 {
   Boolean         retval = TRUE;
@@ -5012,10 +5440,15 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
   IntFuzzPtr      ifp;
   Boolean         in_gap;
   Boolean         in_N;
+  Boolean         in_nps;
   Boolean         isActiveFin = FALSE;
+  Boolean         isDDBJ = FALSE;
   Boolean         isDraft = FALSE;
+  Boolean         isEMBL = FALSE;
   Boolean         isFullTop = FALSE;
   Boolean         isGB = FALSE;
+  Boolean         isGIBBMT = FALSE;
+  Boolean         isGIBBSQ = FALSE;
   Boolean         isPatent = FALSE;
   Boolean         isPDB = FALSE;
   Boolean         isPreFin = FALSE;
@@ -5072,6 +5505,10 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
   Int4            dnalen;
   Int4            total;
   Boolean         has_barcode_keyword = FALSE;
+  CharPtr         keyword;
+  Int4            count;
+  Boolean         doNotSkip;
+  SeqMgrPtr       smp;
 
   /* set up data structures */
 
@@ -5113,8 +5550,16 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
       hasGi = TRUE;
     } else if (sip1->choice == SEQID_GENBANK) {
       isGB = TRUE;
+    } else if (sip1->choice == SEQID_EMBL) {
+      isEMBL = TRUE;
+    } else if (sip1->choice == SEQID_DDBJ) {
+      isDDBJ = TRUE;
     } else if (sip1->choice == SEQID_SWISSPROT) {
       isSwissProt = TRUE;
+    } else if (sip1->choice == SEQID_GIBBSQ) {
+      isGIBBSQ = TRUE;
+    } else if (sip1->choice == SEQID_GIBBMT) {
+      isGIBBMT = TRUE;
     }
 
     for (sip2 = sip1->next; sip2 != NULL; sip2 = sip2->next) {
@@ -5127,6 +5572,9 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
   }
 
   for (sip1 = bsp->id; sip1 != NULL; sip1 = sip1->next) {
+    /* disabled for now
+    ReportLongSeqId (sip1, vsp, 40);
+    */
     switch (sip1->choice) {
     case SEQID_TPG:
     case SEQID_TPE:
@@ -5196,9 +5644,11 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
         } else if (numletters == 3 && numdigits == 5 && ISA_aa (bsp->mol)) {
         } else if (numletters == 2 && numdigits == 6 && ISA_aa (bsp->mol) && bsp->repr == Seq_repr_seg) {
         } else if (numletters == 4 && numdigits == 8 && ISA_na (bsp->mol) &&
-                   (sip1->choice == SEQID_GENBANK || sip1->choice == SEQID_EMBL || sip1->choice == SEQID_DDBJ)) {
+                   (sip1->choice == SEQID_GENBANK || sip1->choice == SEQID_EMBL || sip1->choice == SEQID_DDBJ ||
+                    sip1->choice == SEQID_TPG || sip1->choice == SEQID_TPE || sip1->choice == SEQID_TPD)) {
         } else if (numletters == 4 && numdigits == 9 && ISA_na (bsp->mol) &&
-                   (sip1->choice == SEQID_GENBANK || sip1->choice == SEQID_EMBL || sip1->choice == SEQID_DDBJ)) {
+                   (sip1->choice == SEQID_GENBANK || sip1->choice == SEQID_EMBL || sip1->choice == SEQID_DDBJ ||
+                    sip1->choice == SEQID_TPG || sip1->choice == SEQID_TPE || sip1->choice == SEQID_TPD)) {
         } else if (numletters == 5 && numdigits == 7 && ISA_na (bsp->mol) &&
                    (sip1->choice == SEQID_GENBANK || sip1->choice == SEQID_EMBL || sip1->choice == SEQID_DDBJ)) {
         } else {
@@ -5413,7 +5863,9 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
                 olditemtype = gcp->thistype;
                 gcp->itemID = context.itemID;
                 gcp->thistype = OBJ_SEQDESC;
+                vsp->descr = vnp;
                 ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_RefGeneTrackingIllegalStatus, "RefGeneTracking object has illegal Status '%s'", str);
+                vsp->descr = NULL;
                 gcp->itemID = olditemid;
                 gcp->thistype = olditemtype;
               }
@@ -5424,21 +5876,36 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
             olditemtype = gcp->thistype;
             gcp->itemID = context.itemID;
             gcp->thistype = OBJ_SEQDESC;
+            vsp->descr = vnp;
             ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_RefGeneTrackingWithoutStatus, "RefGeneTracking object needs to have Status set");
+            vsp->descr = NULL;
             gcp->itemID = olditemid;
             gcp->thistype = olditemtype;
           }
-          if (! isRefSeq) {
-            if (! IsWgsIntermediate (vsp->sep)) {
+          if (! isRefSeq && ! vsp->is_refseq_in_sep) {
               olditemid = gcp->itemID;
               olditemtype = gcp->thistype;
               gcp->itemID = context.itemID;
               gcp->thistype = OBJ_SEQDESC;
+            vsp->descr = vnp;
               ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_RefGeneTrackingOnNonRefSeq, "RefGeneTracking object should only be in RefSeq record");
+            vsp->descr = NULL;
               gcp->itemID = olditemid;
               gcp->thistype = olditemtype;
             }
           }
+        if ((keyword = KeywordForStructuredCommentName (uop)) != NULL) {
+          if (IsStructuredCommentValid(uop, NULL, NULL) == eFieldValid_Valid) {
+            if (HasKeywordForStructuredCommentName(bsp, uop)) {
+              /* as it should be */
+            } else {
+              ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_MissingKeyword, "Structured Comment compliant, keyword should be added");
+            }
+          } else {
+            if (HasKeywordForStructuredCommentName(bsp, uop)) {
+              ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_BadKeyword, "Structured Comment is non-compliant, keyword should be removed");
+            }
+          }
         }
       }
       vnp = SeqMgrGetNextDescriptor (bsp, vnp, Seq_descr_user, &context);
@@ -5718,11 +6185,15 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
             gapatstart = TRUE;
           }
         } else if (residue == 'X') {
+          if (ISA_na (bsp->mol)) {
+            ValidErr (vsp, SEV_REJECT, ERR_SEQ_INST_InvalidResidue, "Invalid nucleotide residue '%c' at position [%ld]", (char) residue, (long) (len + 1));
+          } else {
           trailingX++;
           if (isFirst) {
             leadingX = TRUE;
           }
-        } else if (ISA_na (bsp->mol) && StringChr ("EFIJLPQZ", (Char) residue) != NULL) {
+          }
+        } else if (ISA_na (bsp->mol) && StringChr ("EFIJLOPQZ", (Char) residue) != NULL) {
           ValidErr (vsp, SEV_REJECT, ERR_SEQ_INST_InvalidResidue, "Invalid nucleotide residue '%c' at position [%ld]", (char) residue, (long) (len + 1));
         } else if (! IS_ALPHA ((Char) residue)) {
           ValidErr (vsp, SEV_REJECT, ERR_SEQ_INST_InvalidResidue, "Invalid residue '%c' at position [%ld]", (char) residue, (long) (len + 1));
@@ -5898,7 +6369,7 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
             ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_DuplicateSegmentReferences, "Segmented sequence has multiple references to %s", str);
           } else {
             ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_DuplicateSegmentReferences,
-                      "Segmented sequence has multiple references to %s that are not SEQLOC_WHOLE\n", str);
+                      "Segmented sequence has multiple references to %s that are not SEQLOC_WHOLE", str);
           }
         } else {
           last = (CharPtr) vnp->data.ptrvalue;
@@ -5910,26 +6381,28 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
     }
 
     vsp->bsp_partial_val = SeqLocPartialCheck ((SeqLocPtr) (&head));
-    if ((vsp->bsp_partial_val) && (ISA_aa (bsp->mol))) {
-      bcp = NULL;
+    if (ISA_aa (bsp->mol)) {
       got_partial = FALSE;
       if (mip != NULL) {
           switch (mip->completeness) {
           case 2:             /* partial */
             got_partial = TRUE;
+            if (!vsp->bsp_partial_val) {
+              ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_PartialInconsistent, "Complete segmented sequence with MolInfo partial");
+            }
             break;
           case 3:             /* no-left */
-            if (!(vsp->bsp_partial_val & SLP_START))
+            if (!(vsp->bsp_partial_val & SLP_START) || (vsp->bsp_partial_val && SLP_STOP))
               ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_PartialInconsistent, "No-left inconsistent with segmented SeqLoc");
             got_partial = TRUE;
             break;
           case 4:             /* no-right */
-            if (!(vsp->bsp_partial_val & SLP_STOP))
+            if (!(vsp->bsp_partial_val & SLP_STOP) || (vsp->bsp_partial_val && SLP_START))
               ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_PartialInconsistent, "No-right inconsistent with segmented SeqLoc");
             got_partial = TRUE;
             break;
           case 5:             /* no-ends */
-            if ((!(vsp->bsp_partial_val & SLP_STOP)) && (!(vsp->bsp_partial_val & SLP_START)))
+            if ((!(vsp->bsp_partial_val & SLP_STOP)) || (!(vsp->bsp_partial_val & SLP_START)))
               ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_PartialInconsistent, "No-ends inconsistent with segmented SeqLoc");
             got_partial = TRUE;
             break;
@@ -5937,13 +6410,11 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
             break;
           }
       }
-      if (!vsp->useSeqMgrIndexes) {
-        BioseqContextFree (bcp);
-      }
-      if (!got_partial)
+      if (!got_partial && vsp->bsp_partial_val) {
         ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_PartialInconsistent, "Partial segmented sequence without MolInfo partial");
     }
   }
+  }
 
   if (bsp->repr == Seq_repr_delta || bsp->repr == Seq_repr_raw) {
 
@@ -5994,6 +6465,22 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
 
   if (bsp->repr == Seq_repr_delta) {
     len = 0;
+    count = 0;
+    doNotSkip = TRUE;
+    for (vnp = (ValNodePtr) (bsp->seq_ext); vnp != NULL; vnp = vnp->next) {
+      if (vnp->choice == 1) {
+        count++;
+      }
+    }
+    if (count > 10000) {
+      smp = SeqMgrGet ();
+      if (smp != NULL) {
+        if (smp->seq_len_lookup_func == NULL) {
+          doNotSkip = FALSE;
+        }
+      }
+    }
+    if (doNotSkip) {
     for (vnp = (ValNodePtr) (bsp->seq_ext), segnum = 1; vnp != NULL; vnp = vnp->next, segnum++) {
       if (vnp->data.ptrvalue == NULL)
         ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_SeqDataLenWrong, "NULL pointer in delta seq_ext valnode");
@@ -6040,7 +6527,7 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
               if (len3 != -1) {
                 if (sintp->to >= len3) {
                   SeqIdWrite (sip3, buf1, PRINTID_FASTA_SHORT, 40);
-                  ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_SeqDataLenWrong,
+                    ValidErr (vsp, SEV_REJECT, ERR_SEQ_INST_SeqDataLenWrong,
                             "Seq-loc extent (%ld) greater than length of %s (%ld)",
                             (long) (sintp->to + 1), buf1, (long) len3);
                 }
@@ -6101,22 +6588,22 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
               if (mip->tech == MI_TECH_htgs_1 || mip->tech == MI_TECH_htgs_2) {
                 runsofn = CountAdjacentNsInInterval (gcp, bsp, len, len + slitp->length - 1);
                 if (runsofn > 80) {
-                  ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %ld that starts at base %ld", (long) runsofn, (int) segnum, (long) (len + 1));
+                    ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %d that starts at base %ld", (long) runsofn, segnum, (long) (len + 1));
                 }
               } else if (mip->tech == MI_TECH_wgs) {
                 runsofn = CountAdjacentNsInInterval (gcp, bsp, len, len + slitp->length - 1);
                 if (runsofn >= 20) {
-                  ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %ld that starts at base %ld", (long) runsofn, (int) segnum, (long) (len + 1));
+                    ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %d that starts at base %ld", (long) runsofn, segnum, (long) (len + 1));
                 }
               } else if (mip->tech == MI_TECH_composite_wgs_htgs) {
                 runsofn = CountAdjacentNsInInterval (gcp, bsp, len, len + slitp->length - 1);
                 if (runsofn > 80) {
-                  ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %ld that starts at base %ld", (long) runsofn, (int) segnum, (long) (len + 1));
+                    ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %d that starts at base %ld", (long) runsofn, segnum, (long) (len + 1));
                 }
               } else {
                 runsofn = CountAdjacentNsInInterval (gcp, bsp, len, len + slitp->length - 1);
                 if (runsofn > 100) {
-                  ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %ld that starts at base %ld", (long) runsofn, (int) segnum, (long) (len + 1));
+                    ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_InternalNsInSeqLit, "Run of %ld Ns in delta component %d that starts at base %ld", (long) runsofn, segnum, (long) (len + 1));
                 }
               }
             }
@@ -6146,6 +6633,48 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
     } else if (bsp->length < len) {
       ValidErr (vsp, SEV_REJECT, ERR_SEQ_INST_SeqDataLenWrong, "Bioseq.seq_data is larger [%ld] than given length [%ld]", (long) (len), (long) bsp->length);
     }
+
+    } else {
+
+      for (vnp = (ValNodePtr) (bsp->seq_ext); vnp != NULL; vnp = vnp->next) {
+        if (vnp->data.ptrvalue == NULL) {
+          ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_SeqDataLenWrong, "NULL pointer in delta seq_ext valnode");
+          continue;
+        }
+        switch (vnp->choice) {
+          case 1 :
+            slp = (SeqLocPtr) vnp->data.ptrvalue;
+            if (slp->choice == SEQLOC_WHOLE) {
+              ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_WholeComponent, "Delta seq component should not be of type whole");
+              break;
+            }
+            if (slp->choice == SEQLOC_INT) {
+              sintp = (SeqIntPtr) slp->data.ptrvalue;
+              if (sintp != NULL) {
+                len2 = sintp->to - sintp->from + 1;
+                if (len2 < 0) {
+                  ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_SeqDataLenWrong, "-1 length on seq-loc of delta seq_ext");
+                } else {
+                  len += len2;
+                }
+              }
+            }
+            break;
+          case 2 :
+            slitp = (SeqLitPtr) vnp->data.ptrvalue;
+            len += slitp->length;
+            break;
+          default :
+            ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_ExtNotAllowed, "Illegal choice [%d] in delta chain", (int) (vnp->choice));
+            break;
+        }
+      }
+      if (bsp->length > len) {
+        ValidErr (vsp, SEV_REJECT, ERR_SEQ_INST_SeqDataLenWrong, "Bioseq.seq_data too short [%ld] for given length [%ld]", (long) (len), (long) bsp->length);
+      } else if (bsp->length < len) {
+        ValidErr (vsp, SEV_REJECT, ERR_SEQ_INST_SeqDataLenWrong, "Bioseq.seq_data is larger [%ld] than given length [%ld]", (long) (len), (long) bsp->length);
+      }
+    }
     if (mip != NULL) {
       is_gps = FALSE;
       sep = vsp->sep;
@@ -6257,11 +6786,6 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
         ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_MissingGaps, "HTGS delta seq should have gaps between all sequence runs");
       }
     }
-    if (num_adjacent_gaps > 1) {
-      ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_BadDeltaSeq, "There are %d adjacent gaps in delta seq", (int) num_adjacent_gaps);
-    } else if (num_adjacent_gaps > 0) {
-      ValidErr (vsp, SEV_ERROR, ERR_SEQ_INST_BadDeltaSeq, "There is %d adjacent gap in delta seq", (int) num_adjacent_gaps);
-    }
     if (vnp != NULL && vnp->choice == 2) {
       slitp = (SeqLitPtr) vnp->data.ptrvalue;
       if (slitp != NULL && (slitp->seq_data == NULL || slitp->seq_data_type == Seq_code_gap)) {
@@ -6277,6 +6801,15 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
         }
       }
     }
+    sev = SEV_ERROR;
+    if (isRefSeq) {
+      sev = SEV_WARNING;
+    }
+    if (num_adjacent_gaps > 1) {
+      ValidErr (vsp, sev, ERR_SEQ_INST_BadDeltaSeq, "There are %d adjacent gaps in delta seq", (int) num_adjacent_gaps);
+    } else if (num_adjacent_gaps > 0) {
+      ValidErr (vsp, sev, ERR_SEQ_INST_BadDeltaSeq, "There is %d adjacent gap in delta seq", (int) num_adjacent_gaps);
+    }
   }
 
   if (bsp->repr == Seq_repr_raw) {
@@ -6425,6 +6958,11 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
           }
         }
       }
+    } else {
+      if (ISA_na (bsp->mol) && vsp->other_sets_in_sep && vsp->indexerVersion) {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_PKG_ComponentMissingTitle,
+                  "Nucleotide component of pop/phy/mut/eco/wgs set is missing its title");
+      }
     }
   }
 
@@ -6487,6 +7025,36 @@ static void ValidateBioseqInst (GatherContextPtr gcp)
     }
   }
 
+  if (ISA_aa (bsp->mol) && vsp->useSeqMgrIndexes) {
+    in_nps = FALSE;
+    if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
+      bssp = (BioseqSetPtr) bsp->idx.parentptr;
+      while (bssp != NULL && bssp->_class != BioseqseqSet_class_nuc_prot) {
+        if (bssp->idx.parenttype == OBJ_BIOSEQSET) {
+          bssp = (BioseqSetPtr) bssp->idx.parentptr;
+        } else {
+          bssp = NULL;
+        }
+      }
+      if (bssp != NULL && bssp->_class == BioseqseqSet_class_nuc_prot) {
+        in_nps = TRUE;
+      }
+    }
+    if (! in_nps) {
+      if (isGB || isEMBL || isDDBJ || isRefSeq) {
+        if (! isGIBBMT && ! isGIBBSQ) {
+          olditemid = gcp->itemID;
+          olditemtype = gcp->thistype;
+          gcp->itemID = bsp->idx.itemID;
+          gcp->thistype = OBJ_BIOSEQ;
+          ValidErr (vsp, SEV_ERROR, ERR_SEQ_PKG_OrphanedProtein, "Orphaned stand-alone protein");
+          gcp->itemID = olditemid;
+          gcp->thistype = olditemtype;
+        }
+      }
+    }
+  }
+
   vnp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
   if (vnp != NULL) {
     mip = (MolInfoPtr) vnp->data.ptrvalue;
@@ -7085,7 +7653,7 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
   ImprintPtr      imp;
   Boolean         last_name_bad;
   Int4            muid = 0;
-  Boolean         noVol, noPages;
+  Boolean         noVol = FALSE, noPages = FALSE;
   ValNodePtr      name;
   PersonIdPtr     pid;
   Int4            pmid = 0;
@@ -7095,13 +7663,19 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
   Int4            stop;
   CharPtr         str;
   Char            temp [64];
+  Int4            thepmid = 0;
   ValNodePtr      title;
   Int4            uid = 0;
   long int        val;
   ValNodePtr      vnp;
 
-  if (vsp == NULL || pdp == NULL)
-    return;
+  if (vsp == NULL || pdp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_PMid) {
+      thepmid = vnp->data.intvalue;
+    }
+  }
   for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
     switch (vnp->choice) {
     case PUB_Gen:
@@ -7127,7 +7701,7 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
           }
         }
         /* skip if just serial number */
-        if (cgp->cit == NULL && cgp->journal == NULL && cgp->date == NULL && cgp->serial_number) break;
+        if (cgp->cit == NULL && cgp->journal == NULL && cgp->date == NULL && cgp->serial_number > -1) break;
         dp = cgp->date;
         if (dp == NULL) {
           if (! unpub) {
@@ -7167,7 +7741,7 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
         }
       }
       break;
-    case PUB_Muid:
+    case PUB_PMid:
       if (pmid == 0) {
         pmid = vnp->data.intvalue;
       } else if (pmid != vnp->data.intvalue) {
@@ -7179,7 +7753,7 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
         uid = vnp->data.intvalue;
       }
       break;
-    case PUB_PMid:
+    case PUB_Muid:
       if (muid == 0) {
         muid = vnp->data.intvalue;
       } else if (muid != vnp->data.intvalue) {
@@ -7234,6 +7808,7 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
         }
       }
 
+      if (cap != NULL) {
       switch (cap->from) {
       case 1:
         cjp = (CitJourPtr) cap->fromptr;
@@ -7270,6 +7845,9 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
               if (vsp->is_refseq_in_sep) {
                 sev = SEV_WARNING;
               }
+                if (imp->pubstatus == PUBSTATUS_epublish) {
+                  sev = SEV_WARNING;
+                }
               if (noVol && noPages) {
                 ValidErr (vsp, sev, ERR_GENERIC_MissingPubInfo, "Journal volume and pages missing");
               } else if (noVol) {
@@ -7329,12 +7907,22 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
             if (imp->pubstatus == PUBSTATUS_epublish && imp->prepub == 2) {
               ValidErr (vsp, SEV_WARNING, ERR_GENERIC_PublicationInconsistency, "Electronic-only publication should not also be in-press");
             }
+              if (imp->pubstatus == PUBSTATUS_epublish || imp->pubstatus == PUBSTATUS_ppublish || imp->pubstatus == PUBSTATUS_aheadofprint) {
+                if (StringDoesHaveText (pdp->comment)) {
+                  if (StringStr (pdp->comment, "Publication Status") != NULL ||
+                      StringStr (pdp->comment, "Publication-Status") != NULL ||
+                      StringStr (pdp->comment, "Publication_Status") != NULL) {
+                    ValidErr (vsp, SEV_ERROR, ERR_GENERIC_UnexpectedPubStatusComment, "Publication status is in comment for pmid %ld", (long) thepmid);
+                  }
+                }
+              }
           }
         }
         break;
       default:
         break;
       }
+      }
       break;
     case PUB_Equiv:
       ValidErr (vsp, SEV_WARNING, ERR_GENERIC_UnnecessaryPubEquiv, "Publication has unexpected internal Pub-equiv");
@@ -7378,7 +7966,7 @@ static void ValidatePubdesc (ValidStructPtr vsp, GatherContextPtr gcp, PubdescPt
             badauthor = "?";
           }
           if (last_name_bad) {
-            ValidErr (vsp, sev, ERR_SEQ_FEAT_BadCharInAuthorLastName, "Bad characters in author %s", badauthor);
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadCharInAuthorLastName, "Bad characters in author %s", badauthor);
           } else {
             ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadCharInAuthorName, "Bad characters in author %s", badauthor);
           }
@@ -7440,7 +8028,8 @@ typedef struct bioseqvalid
   Boolean         is_aa;         /* bioseq is protein? */
   Boolean         is_mrna;       /* molinfo is mrna? */
   Boolean         is_prerna;     /* molinfo is precursor rna? */
-  Boolean         is_artificial; /* biosource origin is artificial, synthetic, mutant? */
+  Boolean         is_artificial; /* biosource origin is artificial */
+  Boolean         is_synthetic;  /* biosource origin synthetic */
   Boolean         is_syn_constr; /* is organism name synthetic construct, plasmid, vector, or SYN division? */
   Boolean         got_a_pub;
   int             last_na_mol, last_na_mod, last_organelle, last_partialness, last_left_right,
@@ -7508,7 +8097,9 @@ static Boolean IsLocationOrganelle (Uint1 genome)
       || genome == GENOME_apicoplast 
       || genome == GENOME_leucoplast 
       || genome == GENOME_proplastid 
-      || genome == GENOME_hydrogenosome) {
+      || genome == GENOME_hydrogenosome
+      || genome == GENOME_plastid
+      || genome == GENOME_chromatophore) {
     return TRUE;
   } else {
     return FALSE;
@@ -7545,6 +8136,7 @@ ValidateIntronEndsAtSpliceSiteOrGap
   Char               id_buf[150];
   SeqFeatPtr         rna;
   SeqMgrFeatContext  rcontext;
+  ErrSev             sev = SEV_WARNING;
 
   if (vsp == NULL || slp == NULL) return;
   CheckSeqLocForPartial (slp, &partial5, &partial3);
@@ -7586,6 +8178,10 @@ ValidateIntronEndsAtSpliceSiteOrGap
 
   strand = SeqLocStrand (slp);
 
+  if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+    sev = SEV_INFO;
+  }
+
   if (!partial5) {
     if (strand == Seq_strand_minus) {
       SeqPortStreamInt (bsp, stop - 1, stop, Seq_strand_minus, EXPAND_GAPS_TO_DASHES, (Pointer) buf, NULL);
@@ -7602,7 +8198,7 @@ ValidateIntronEndsAtSpliceSiteOrGap
       ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_NotSpliceConsensusDonor,
                 "Splice donor consensus (GT) not found at start of terminal intron, position %ld of %s", (long) (pos + 1), id_buf);
     } else {
-      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_NotSpliceConsensusDonor,
+      ValidErr (vsp, sev, ERR_SEQ_FEAT_NotSpliceConsensusDonor,
                 "Splice donor consensus (GT) not found at start of intron, position %ld of %s", (long) (pos + 1), id_buf);
     }
   }
@@ -7621,7 +8217,7 @@ ValidateIntronEndsAtSpliceSiteOrGap
       ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_NotSpliceConsensusAcceptor,
                 "Splice acceptor consensus (AG) not found at end of terminal intron, position %ld of %s, but at end of sequence", (long) (pos + 1), id_buf);
     } else {
-      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_NotSpliceConsensusAcceptor,
+      ValidErr (vsp, sev, ERR_SEQ_FEAT_NotSpliceConsensusAcceptor,
                 "Splice acceptor consensus (AG) not found at end of intron, position %ld of %s", (long) (pos + 1), id_buf);
     }
   }
@@ -8033,6 +8629,7 @@ static CharPtr  Nlm_valid_country_codes [] = {
   "Bermuda",
   "Bhutan",
   "Bolivia",
+  "Borneo",
   "Bosnia and Herzegovina",
   "Botswana",
   "Bouvet Island",
@@ -8158,6 +8755,7 @@ static CharPtr  Nlm_valid_country_codes [] = {
   "Mauritania",
   "Mauritius",
   "Mayotte",
+  "Mediterranean Sea",
   "Mexico",
   "Micronesia",
   "Midway Islands",
@@ -8205,6 +8803,7 @@ static CharPtr  Nlm_valid_country_codes [] = {
   "Republic of the Congo",
   "Reunion",
   "Romania",
+  "Ross Sea",
   "Russia",
   "Rwanda",
   "Saint Helena",
@@ -8228,6 +8827,7 @@ static CharPtr  Nlm_valid_country_codes [] = {
   "South Africa",
   "South Georgia and the South Sandwich Islands",
   "South Korea",
+  "Southern Ocean",
   "Spain",
   "Spratly Islands",
   "Sri Lanka",
@@ -8241,6 +8841,7 @@ static CharPtr  Nlm_valid_country_codes [] = {
   "Taiwan",
   "Tajikistan",
   "Tanzania",
+  "Tasman Sea",
   "Thailand",
   "Togo",
   "Tokelau",
@@ -8278,6 +8879,7 @@ static CharPtr  Nlm_formerly_valid_country_codes [] = {
   "British Guiana",
   "Burma",
   "Czechoslovakia",
+  "Korea",
   "Serbia and Montenegro",
   "Siam",
   "USSR",
@@ -8430,6 +9032,7 @@ static CharPtr ctry_lat_lon [] = {
   "Bermuda\tBD\t-64.9\t32.2\t-64.7\t32.4",
   "Bhutan\tBT\t88.7\t26.7\t92.1\t28.3",
   "Bolivia\tBL\t-69.7\t-22.9\t-57.5\t-9.7",
+  "Borneo\tXX\t108.6\t-4.2\t119.3\t7.4",
   "Bosnia and Herzegovina\tBK\t15.7\t42.5\t19.7\t45.3",
   "Botswana\tBC\t19.9\t-27.0\t29.4\t-17.8",
   "Bouvet Island\tBV\t3.3\t-54.5\t3.5\t-54.4",
@@ -8571,6 +9174,7 @@ static CharPtr ctry_lat_lon [] = {
   "Mauritania\tMR\t-17.1\t14.7\t-4.8\t27.3",
   "Mauritius\tMP\t57.3\t-20.6\t57.8\t-20.0\t59.5\t-16.9\t59.6\t-16.7",
   "Mayotte\tMF\t45.0\t-13.1\t45.3\t-12.6",
+  "Mediterranean Sea\tXX\t",
   "Mexico\tMX\t-118.5\t28.8\t-118.3\t29.2\t-117.3\t14.5\t-86.7\t32.7",
   "Micronesia\tFM\t138.0\t9.4\t138.2\t9.6\t139.6\t9.8\t139.8\t10.0\t140.5\t9.7\t140.5\t9.8\t147.0\t7.3\t147.0\t7.4\t149.3\t6.6\t149.3\t6.7\t151.5\t7.1\t152.0\t7.5\t153.5\t5.2\t153.8\t5.6\t157.1\t5.7\t160.7\t7.1\t162.9\t5.2\t163.0\t5.4",
   "Midway Islands\tMQ\t-178.4\t28.3\t-178.3\t28.4\t-177.4\t28.1\t-177.3\t28.2\t-174.0\t26.0\t-174.0\t26.1\t-171.8\t25.7\t-171.7\t25.8",
@@ -8620,6 +9224,7 @@ static CharPtr ctry_lat_lon [] = {
   "Republic of the Congo\tCF\t11.2\t-5.1\t18.6\t3.7",
   "Reunion\tRE\t55.2\t-21.4\t55.8\t-20.9",
   "Romania\tRO\t20.2\t43.6\t29.7\t48.3",
+  "Ross Sea\tXX\t",
   "Russia\tRS\t-180.0\t64.2\t-169.0\t71.6\t19.7\t54.3\t22.9\t55.3\t26.9\t41.1\t180.0\t81.3",
   "Rwanda\tRW\t28.8\t-2.9\t30.9\t-1.1",
   "Saint Helena\tSH\t-5.8\t-16.1\t-5.6\t-15.9",
@@ -8643,6 +9248,7 @@ static CharPtr ctry_lat_lon [] = {
   "South Africa\tSF\t16.4\t-34.9\t32.9\t-22.1",
   "South Georgia and the South Sandwich Islands\tSX\t-38.3\t-54.9\t-35.7\t-53.9",
   "South Korea\tKS\t125.0\t33.1\t129.6\t38.6",
+  "Southern Ocean\tXX\t",
   "Spain\tSP\t-9.3\t35.1\t4.3\t43.8\t-18.2\t27.6\t-13.4\t29.5",
   "Spain: Canary Islands\tXX\t-18.2\t27.6\t-13.4\t29.5",
   "Spratly Islands\tPG\t114.0\t9.6\t115.8\t11.1",
@@ -8657,6 +9263,7 @@ static CharPtr ctry_lat_lon [] = {
   "Taiwan\tTW\t119.3\t21.9\t122.0\t25.3",
   "Tajikistan\tTI\t67.3\t36.6\t75.1\t41.0",
   "Tanzania\tTZ\t29.3\t-11.8\t40.4\t-1.0",
+  "Tasman Sea\tXX\t",
   "Thailand\tTH\t97.3\t5.6\t105.6\t20.5",
   "Togo\tTO\t-0.2\t6.1\t1.8\t11.1",
   "Tokelau\tTL\t-172.6\t-9.5\t-171.1\t-8.5",
@@ -9173,6 +9780,90 @@ NLM_EXTERN Boolean IsCountryInLatLonList (
   return FALSE;
 }
 
+static Int2 GetCountryBlockIndex (
+  CharPtr country
+)
+
+{
+  CtBlockPtr       cbp;
+  CtBlockPtr PNTR  bkarray;
+  CtSetPtr         csp;
+  Int2             L, R, mid;
+
+  if (StringHasNoText (country)) return -1;
+
+  csp = GetCtSetLatLonData ();
+  if (csp == NULL) return -1;
+
+  bkarray = csp->bkarray;
+  if (bkarray == NULL) return -1;
+
+  L = 0;
+  R = csp->num_blocks - 1;
+
+  while (L < R) {
+    mid = (L + R) / 2;
+    cbp = bkarray [mid];
+    if (cbp != NULL && StringICmp (cbp->country, country) < 0) {
+      L = mid + 1;
+    } else {
+      R = mid;
+    }
+  }
+
+  if (R < csp->num_blocks) {
+    cbp = bkarray [R];
+    if (cbp == NULL) return -1;
+    if (StringICmp (cbp->country, country) != 0) return -1;
+    return R;
+  }
+
+  return -1;
+}
+
+NLM_EXTERN Boolean CountryBoxesOverlap (
+  CharPtr country1,
+  CharPtr country2
+)
+
+{
+  CtBlockPtr       cbp1, cbp2;
+  CtBlockPtr PNTR  bkarray;
+  CtSetPtr         csp;
+  Int4             num_blocks;
+  Int2             R1, R2, x1, x2;
+
+  R1 = GetCountryBlockIndex (country1);
+  R2 = GetCountryBlockIndex (country2);
+
+  if (R1 < 0 || R2 < 0) return FALSE;
+
+  csp = GetCtSetLatLonData ();
+  if (csp == NULL) return FALSE;
+  num_blocks = csp->num_blocks;
+
+  bkarray = csp->bkarray;
+  if (bkarray == NULL) return FALSE;
+
+  for (x1 = R1; x1 < num_blocks; x1++) {
+    cbp1 = bkarray [x1];
+    if (cbp1 == NULL) return FALSE;
+    if (StringICmp (cbp1->country, country1) != 0) break;
+
+    for (x2 = R2; x2 < num_blocks; x2++) {
+      cbp2 = bkarray [x2];
+      if (cbp2 == NULL) return FALSE;
+      if (StringICmp (cbp2->country, country2) != 0) break;
+
+      if (cbp1->maxx >= cbp2->minx && cbp1->minx <= cbp2->maxx) {
+        if (cbp1->maxy >= cbp2->miny && cbp1->miny <= cbp2->maxy) return TRUE;
+      }
+    }
+  }
+
+  return FALSE;
+}
+
 NLM_EXTERN Boolean TestLatLonForCountry (
   CharPtr country,
   FloatHi lat,
@@ -9286,6 +9977,7 @@ static CharPtr bodiesOfWater [] = {
   "Lake",
   "Narrows",
   "Ocean",
+  "Offshore",
   "Passage",
   "River",
   "Sea",
@@ -9355,258 +10047,6 @@ NLM_EXTERN Boolean StringContainsBodyOfWater (CharPtr str)
 
 
 
-static CharPtr GetDash (CharPtr str)
-
-{
-  Char  ch;
-
-  if (str == NULL) return NULL;
-  ch = *str;
-  while (ch != '\0') {
-    if (ch == '-') return str;
-    str++;
-    ch = *str;
-  }
-
-  return NULL;
-}
-
-static CharPtr legalMonths [] = {
-  "Jan",
-  "Feb",
-  "Mar",
-  "Apr",
-  "May",
-  "Jun",
-  "Jul",
-  "Aug",
-  "Sep",
-  "Oct",
-  "Nov",
-  "Dec",
-  NULL
-};
-
-
-static Boolean CollectionDateIsValid (CharPtr name)
-
-{
-  Char      ch;
-  Int2      i;
-  CharPtr   ptr1, ptr2, month = NULL, day = NULL, year = NULL;
-  Char      str [256];
-  long int  val;
-
-  if (StringHasNoText (name)) return FALSE;
-
-  StringNCpy_0 (str, name, sizeof (str));
-  ptr1 = GetDash (str);
-  if (ptr1 != NULL) {
-    *ptr1 = '\0';
-    ptr1++;
-    ptr2 = GetDash (ptr1);
-    if (ptr2 != NULL) {
-      *ptr2 = '\0';
-      ptr2++;
-      day = str;
-      month = ptr1;
-      year = ptr2;
-    } else {
-      month = str;
-      year = ptr1;
-    }
-  } else {
-    year = str;
-  }
-
-  if (day != NULL) {
-    if (sscanf (day, "%ld", &val) != 1 || val < 1 || val > 31) return FALSE;
-    if (StringLen (day) != 2 || !isdigit(day[0]) || !isdigit(day[1])) return FALSE;
-  }
-
-  if (month != NULL) {
-    for (i = 0; legalMonths [i] != NULL; i++) {
-      if (StringCmp (month, legalMonths [i]) == 0) {
-        break;
-      }
-    }
-    if (legalMonths [i] == NULL) return FALSE;
-  }
-
-  if (year != NULL) {
-    ptr1 = year;
-    ch = *ptr1;
-    while (ch != '\0') {
-      if (! (IS_DIGIT (ch))) return FALSE;
-      ptr1++;
-      ch = *ptr1;
-    }
-    if (sscanf (year, "%ld", &val) == 1) {
-      if (val >= 1700 && val < 2100) return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-/* This mimics a portion of the DatePtr structure,
- * but allows dates with years before 1900 because
- * the year value is Int4 instead of Uint1.
- *   data [0] : Set to 1
- *        [1] - year (- 1900)
- *        [2] - month (1-12)  optional
- *        [3] - day (1-31)     optional
- * Not bothering with time.
- */
-
-typedef struct betterdate {
-    Int4 data[8];      /* see box above */
-} BetterDateData, PNTR BetterDatePtr;
-
-static BetterDatePtr BetterDateNew()
-{
-  BetterDatePtr dp;
-
-  dp = (BetterDatePtr) MemNew (sizeof (BetterDateData));
-  return dp;
-}
-
-static BetterDatePtr BetterDateFree (BetterDatePtr dp)
-{
-  if (dp != NULL) {
-    dp = MemFree (dp);
-  }
-  return dp;
-}
-
-
-static BetterDatePtr CollectionDateFromString (CharPtr name)
-{
-  Char      ch;
-  Int2      i;
-  CharPtr   ptr1, ptr2, month = NULL, day = NULL, year = NULL;
-  Char      str [256];
-  long int  day_val = 0;
-  Int2      month_num = 0;
-  long int  val, year_val = 0;
-  BetterDatePtr   dp;
-
-  if (StringHasNoText (name)) return NULL;
-
-  StringNCpy_0 (str, name, sizeof (str));
-  ptr1 = GetDash (str);
-  if (ptr1 != NULL) {
-    *ptr1 = '\0';
-    ptr1++;
-    ptr2 = GetDash (ptr1);
-    if (ptr2 != NULL) {
-      *ptr2 = '\0';
-      ptr2++;
-      day = str;
-      month = ptr1;
-      year = ptr2;
-    } else {
-      month = str;
-      year = ptr1;
-    }
-  } else {
-    year = str;
-  }
-
-  if (day != NULL) {
-    if (sscanf (day, "%ld", &day_val) != 1 || day_val < 1 || day_val > 31) return NULL;
-  }
-
-  if (month != NULL) {
-    for (i = 0; legalMonths [i] != NULL; i++) {
-      if (StringCmp (month, legalMonths [i]) == 0) {
-        month_num = i + 1;
-        break;
-      }
-    }
-    if (legalMonths [i] == NULL) return NULL;
-  }
-
-  if (year != NULL) {
-    ptr1 = year;
-    ch = *ptr1;
-    while (ch != '\0') {
-      if (! (IS_DIGIT (ch))) return NULL;
-      ptr1++;
-      ch = *ptr1;
-    }
-    if (sscanf (year, "%ld", &val) == 1) {
-      if (val < 1700 || val > 2100) return NULL;
-      year_val = val - 1900;
-    }
-    else
-    {
-      return NULL;
-    }
-  }
-
-  dp = BetterDateNew();
-  dp->data[0] = 1;
-  dp->data[1] = year_val;
-  dp->data[2] = month_num;
-  dp->data[3] = day_val;
-  return dp;
-}
-
-
-static Boolean CollectionDateIsInTheFuture (CharPtr name)
-
-{
-  DatePtr   dp_now;
-  BetterDatePtr dp_coll_date;
-  Boolean   rval = FALSE;
-
-  dp_coll_date = CollectionDateFromString (name);
-  if (dp_coll_date == NULL) return FALSE;
-
-  if (dp_coll_date->data[1] < 0)
-  {
-    /* year before 1900 */
-    dp_coll_date = BetterDateFree (dp_coll_date);
-    return FALSE;
-  }
-
-  dp_now = DateCurr();
-
-  /* compare years */
-  if (dp_now->data[1] < dp_coll_date->data[1])
-  {
-    rval = TRUE;
-  }
-  else if (dp_now->data[1] > dp_coll_date->data[1])
-  {
-    rval = FALSE;
-  }
-  /* years are equal - compare months */
-  else if (dp_now->data[2] < dp_coll_date->data[2])
-  {
-    rval = TRUE;
-  }
-  else if (dp_now->data[2] > dp_coll_date->data[2])
-  {
-    rval = FALSE;
-  }
-  /* years and months are equal - compare days */
-  else if (dp_now->data[3] < dp_coll_date->data[3])
-  {
-    rval = TRUE;
-  }
-  else
-  {
-    rval = FALSE;
-  }
-
-  dp_now = DateFree (dp_now);
-  dp_coll_date = BetterDateFree (dp_coll_date);
-  return rval;
-}
-
-
 static Boolean StringListIsUnique (ValNodePtr list)
 
 {
@@ -9947,14 +10387,14 @@ static CharPtr source_qual_prefixes [] = {
   "genotype:",
   "germline:",
   "group:",
-  "haplogrop:",
+  "haplogroup:",
   "haplotype:",
   "identified_by:",
   "insertion_seq_name:",
   "isolate:",
   "isolation_source:",
   "lab_host:",
-  "lat_lon:"
+  "lat_lon:",
   "left_primer:",
   "linkage_group:",
   "map:",
@@ -10126,10 +10566,13 @@ static CharPtr PNTR  ic_code_data = NULL;
 static Uint1 PNTR    ic_code_type = NULL;
 static Int4          ic_code_len = 0;
 
+#define BIO_MATERIAL_TYPE       1
+#define CULTURE_COLLECTION_TYPE 2
+#define SPECIMEN_VOUCHER_TYPE   4
+
 static void SetupInstCollTable (void)
 
 {
-  Char        ch;
   FileCache   fc;
   CharPtr     file = "institution_codes.txt";
   FILE        *fp = NULL;
@@ -10141,6 +10584,7 @@ static void SetupInstCollTable (void)
   ErrSev      sev;
   CharPtr     str;
   CharPtr     tmp;
+  Uint1       type;
   ValNodePtr  vnp;
 
   if (ic_code_data != NULL) return;
@@ -10163,7 +10607,7 @@ static void SetupInstCollTable (void)
   str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
   while (str != NULL) {
     if (StringDoesHaveText (str)) {
-      ch = '\0';
+      type = 0;
       ptr = StringChr (str, '\t');
       if (ptr != NULL) {
         *ptr = '\0';
@@ -10171,13 +10615,19 @@ static void SetupInstCollTable (void)
         tmp = StringChr (ptr, '\t');
         if (tmp != NULL) {
           *tmp = '\0';
-          if (ptr [1] == '\0') {
-            ch = *ptr;
+          if (StringChr (ptr, 'b') != NULL) {
+            type |= BIO_MATERIAL_TYPE;
+          }
+          if (StringChr (ptr, 'c') != NULL) {
+            type |= CULTURE_COLLECTION_TYPE;
+          }
+          if (StringChr (ptr, 's') != NULL) {
+            type |= SPECIMEN_VOUCHER_TYPE;
           }
         }
       }
       TrimSpacesAroundString (str);
-      vnp = ValNodeCopyStr (&last, (Uint1) ch, str);
+      vnp = ValNodeCopyStr (&last, type, str);
       if (ic_code_list == NULL) {
         ic_code_list = vnp;
       }
@@ -10257,7 +10707,7 @@ static void ValidateOrgModVoucher (ValidStructPtr vsp, OrgModPtr mod)
     }
     return;
   }
-  if (! ParseStructuredVoucher (buf, &inst, &id)) {
+  if (! ParseStructuredVoucher (buf, &inst, &id) || inst == NULL || inst[0] == ':') {
     if (StringHasNoText (inst) || inst [0] == ':') {
       ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BadInstitutionCode, "Voucher is missing institution code");
     }
@@ -10270,14 +10720,14 @@ static void ValidateOrgModVoucher (ValidStructPtr vsp, OrgModPtr mod)
   
   str = CheckInstCollName (inst, &type);
   if (StringCmp (str, inst) == 0) {
-    if ((mod->subtype == ORGMOD_bio_material && type != 'b') ||
-        (mod->subtype == ORGMOD_culture_collection && type != 'c') ||
-        (mod->subtype == ORGMOD_specimen_voucher && type != 's')) {
-      if (type == 'b') {
+    if ((mod->subtype == ORGMOD_bio_material && (type & BIO_MATERIAL_TYPE) == 0) ||
+        (mod->subtype == ORGMOD_culture_collection && (type & CULTURE_COLLECTION_TYPE) == 0) ||
+        (mod->subtype == ORGMOD_specimen_voucher && (type & SPECIMEN_VOUCHER_TYPE) == 0)) {
+      if ((type & BIO_MATERIAL_TYPE) != 0) {
         ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_WrongVoucherType, "Institution code %s should be bio_material", inst);
-      } else if (type == 'c') {
+      } else if ((type & CULTURE_COLLECTION_TYPE) != 0) {
         ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_WrongVoucherType, "Institution code %s should be culture_collection", inst);
-      } else if (type == 's') {
+      } else if ((type & SPECIMEN_VOUCHER_TYPE) != 0) {
         ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_WrongVoucherType, "Institution code %s should be specimen_voucher", inst);
       }
     }
@@ -10285,7 +10735,7 @@ static void ValidateOrgModVoucher (ValidStructPtr vsp, OrgModPtr mod)
   }
 
   if (StringICmp (str, inst) == 0) {
-    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BadCollectionCode,
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BadInstitutionCode,
               "Institution code %s exists, but correct capitalization is %s", inst, str);
     return;
   }
@@ -10315,7 +10765,7 @@ static void ValidateOrgModVoucher (ValidStructPtr vsp, OrgModPtr mod)
   if (StringCmp (str, inst) == 0) {
     if (StringCmp (coll, "DNA") == 0) {
       /* DNA is a valid collection for any institution (using bio_material) */
-      if (type != 'b') {
+      if (mod->subtype != ORGMOD_bio_material) {
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_WrongVoucherType, "DNA should be bio_material");
       }
     } else {
@@ -10431,7 +10881,6 @@ static void ValidateLocationForHIV (ValidStructPtr vsp, BioSourcePtr biop, Biose
 {
   SeqDescrPtr sdp;
   SeqMgrDescContext context;
-  Boolean location_ok = FALSE;
   MolInfoPtr mip;
 
   if (vsp == NULL || biop == NULL) {
@@ -10444,18 +10893,11 @@ static void ValidateLocationForHIV (ValidStructPtr vsp, BioSourcePtr biop, Biose
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "HIV with moltype DNA should be proviral");
       }
     } else if (bsp->mol == Seq_mol_rna) {
-      if (biop->genome == GENOME_unknown) {
-        location_ok = TRUE;
-      } else if (biop->genome == GENOME_genomic) {
         sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
         if (sdp != NULL 
             && (mip = (MolInfoPtr) sdp->data.ptrvalue) != NULL
-            && mip->biomol == MOLECULE_TYPE_GENOMIC) {
-          location_ok = TRUE;
-            }
-      }
-      if (!location_ok) {
-        ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "HIV with moltype RNA should have source location unset or set to genomic (on genomic RNA sequence)");
+          && mip->biomol == MOLECULE_TYPE_MRNA) {
+        ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_BioSourceInconsistency, "HIV with mRNA molecule type is rare");
       }
     }
   }
@@ -10486,6 +10928,8 @@ static Boolean UnbalancedParentheses (CharPtr str)
     } else if (ch == ']') {
       rev_bkt++;
     }
+    if (fwd_par < rev_par) return TRUE;
+    if (fwd_bkt < rev_bkt) return TRUE;
     str++;
     ch = *str;
   }
@@ -10512,10 +10956,10 @@ static CharPtr sgml_strings [] = {
   "&Egr;",
   "&zgr;",
   "&Zgr;",
-  "&eegr"
-  "&EEgr"
-  "&thgr"
-  "&THgr"
+  "&eegr;",
+  "&EEgr;",
+  "&thgr;",
+  "&THgr;",
   "&igr;",
   "&Igr;",
   "&kgr;",
@@ -10536,7 +10980,7 @@ static CharPtr sgml_strings [] = {
   "&Rgr;",
   "&sgr;",
   "&Sgr;",
-  "&sfgr"
+  "&sfgr;",
   "&tgr;",
   "&Tgr;",
   "&ugr;",
@@ -10699,6 +11143,7 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
   Int2            num_rev_primer_seq = 0;
   Int2            num_fwd_primer_name = 0;
   Int2            num_rev_primer_name = 0;
+  ObjectIdPtr     oip;
   Boolean         old_country = FALSE;
   OrgNamePtr      onp;
   OrgModPtr       omp, nxtomp;
@@ -10838,7 +11283,9 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
       str = ssp->name;
       if (isAnimal || isPlant) {
         /* always use /sex, do not check values at this time */
-      } else if (isViral || isBacteria || isArchaea || isFungal) {
+      } else if (isViral) {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Virus has unexpected sex qualifier");
+      } else if (isBacteria || isArchaea || isFungal) {
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Unexpected use of /sex qualifier");
       } else if (IsValidSexValue (str)) {
         /* otherwise expect male or female, or a few others */
@@ -10887,6 +11334,10 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
         if (biop->genome != GENOME_proplastid) {
           ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Plastid name subsource proplastid but not proplastid location");
         }
+      } else if (StringCmp (ssp->name, "chromatophore") == 0) {
+        if (biop->genome != GENOME_chromatophore) {
+          ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Plastid name subsource chromatophore but not chromatophore location");
+        }
       } else {
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Plastid name subsource contains unrecognized value");
       }  
@@ -10990,8 +11441,6 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
           ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "bad frequency qualifier value %s", ssp->name);
         }
       }
-    } else if (ssp->subtype == SUBSRC_sex && isViral) {
-      ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Virus has unexpected sex qualifier");
     } else if (ssp->subtype == SUBSRC_cell_line && isViral) {
       ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Virus has unexpected cell_line qualifier");
     } else if (ssp->subtype == SUBSRC_cell_type && isViral) {
@@ -11060,8 +11509,19 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
                   /* passed unqualified but failed qualified country name, report at info level for now */
                   guess = GuessCountryForLatLon (lat, lon);
                   if (StringDoesHaveText (guess)) {
+                    if (CountryBoxesOverlap (buf, guess)) {
+                      if (vsp->indexerVersion) {
+                        ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonAdjacent,
+                                  "Lat_lon '%s' MIGHT be in '%s' instead of adjacent '%s' - SHIFT DOUBLE CLICK TO LAUNCH GOOGLE EARTH -",
+                                  lat_lon, guess, buf);
+                      } else {
+                        ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonState,
+                                  "Lat_lon '%s' MIGHT be in '%s' instead of '%s'", lat_lon, guess, buf);
+                      }
+                    } else {
                     ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonState,
                               "Lat_lon '%s' does not map to subregion '%s', but may be in '%s'", lat_lon, buf, guess);
+                    }
                   } else {
                     ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonState,
                               "Lat_lon '%s' does not map to subregion '%s'", lat_lon, buf);
@@ -11096,8 +11556,19 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
           if (vsp->strictLatLonCountry || (! StringContainsBodyOfWater (countryname))) {
             guess = GuessCountryForLatLon (lat, lon);
             if (guess != NULL) {
+              if (CountryBoxesOverlap (buf, guess)) {
+                if (vsp->indexerVersion) {
+                  ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonAdjacent,
+                            "Lat_lon '%s' MIGHT be in '%s' instead of adjacent '%s' - SHIFT DOUBLE CLICK TO LAUNCH GOOGLE EARTH -",
+                            lat_lon, guess, buf);
+                } else {
+                  ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonCountry,
+                            "Lat_lon '%s' MIGHT be in '%s' instead of '%s'", lat_lon, guess, buf);
+                }
+              } else {
               ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonCountry,
                         "Lat_lon '%s' does not map to '%s', but may be in '%s'", lat_lon, buf, guess);
+              }
             } else {
               ValidErr (vsp, SEV_INFO, ERR_SEQ_DESCR_LatLonCountry,
                         "Lat_lon '%s' does not map to '%s'", lat_lon, buf);
@@ -11197,6 +11668,16 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Uncultured should also have /environmental_sample");
       }
     }
+    str = orp->taxname;
+    if (StringDoesHaveText (str)) {
+      if (UnbalancedParentheses (str)) {
+          ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_UnbalancedParentheses,
+                    "Unbalanced parentheses in taxname '%s'", str);
+      }
+      if (StringHasSgml (vsp, str)) {
+        ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "taxname %s has SGML", str);
+      }
+    }
   }
 
   for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
@@ -11208,8 +11689,8 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
     str = ssp->name;
     if (StringHasNoText (str)) continue;
     if (UnbalancedParentheses (str)) {
-        ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_UnbalancedParentheses,
-                  "Unbalanced parentheses in '%s'", str);
+        ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_UnbalancedParentheses,
+                  "Unbalanced parentheses in subsource '%s'", str);
     }
     if (StringHasSgml (vsp, str)) {
       ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "subsource %s has SGML", str);
@@ -11227,7 +11708,7 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
   }
   onp = orp->orgname;
   if (onp == NULL || StringHasNoText (onp->lineage)) {
-    if (! vsp->seqSubmitParent) { /* suppress when validator run from tbl2asn */
+    if (! vsp->seqSubmitParent && vsp->indexerVersion) { /* suppress when validator run from tbl2asn or when not indexer version */
       sev = SEV_ERROR;
       if (vsp->is_refseq_in_sep) {
         for (db = orp->db; db != NULL; db = db->next) {
@@ -11259,7 +11740,8 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
     if (StringCmp (onp->div, "BCT") == 0 
         && biop->genome != GENOME_unknown 
         && biop->genome != GENOME_genomic
-        && biop->genome != GENOME_plasmid) {
+        && biop->genome != GENOME_plasmid
+        && biop->genome != GENOME_chromosome) {
       ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Bacterial source should not have organelle location");
     }
 
@@ -11364,6 +11846,7 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
         coll2++;
       }
       if (StringICmp (inst1, inst2) != 0) continue;
+      if (omp->subtype != nxtomp->subtype) continue;
       if (StringCmp (coll1, "DNA") == 0 || StringCmp (coll2, "DNA") == 0) continue;
       if (coll1 != NULL && coll2 != NULL && StringICmp (coll1, coll2) == 0) {
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_MultipleSourceVouchers, "Multiple vouchers with same institution:collection");
@@ -11379,8 +11862,8 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
       if (StringHasNoText (str)) continue;
       if (UnbalancedParentheses (str)) {
         if (omp->subtype == ORGMOD_old_name) continue;
-        ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_UnbalancedParentheses,
-                  "Unbalanced parentheses in '%s'", str);
+        ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_UnbalancedParentheses,
+                  "Unbalanced parentheses in orgmod '%s'", str);
       }
       if (StringHasSgml (vsp, str)) {
         ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "orgmod %s has SGML", str);
@@ -11449,6 +11932,19 @@ static void ValidateBioSource (ValidStructPtr vsp, GatherContextPtr gcp, BioSour
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_IllegalDbXref, "Illegal db_xref type %s", dbt->db);
       }
 
+      if (StringDoesHaveText (dbt->db)) {
+        if (StringHasSgml (vsp, dbt->db)) {
+          ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "dbxref database %s has SGML", dbt->db);
+        }
+      }
+
+      oip = dbt->tag;
+      if (oip != NULL && StringDoesHaveText (oip->str)) {
+        if (StringHasSgml (vsp, oip->str)) {
+          ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "dbxref value %s has SGML", oip->str);
+        }
+      }
+
       /*
       dbxerr = NULL;
       dbvalid = IsDbxrefValid (dbt->db, NULL, orp, FALSE, &dbxerr);
@@ -11711,6 +12207,7 @@ static Boolean ValidateSeqDescrCommon (ValNodePtr sdp, BioseqValidStrPtr bvsp, V
       ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_InvalidForType, "Nucleic acid with protein sequence method");
     }
     break;
+  /*
   case Seq_descr_comment:
     str = (CharPtr) vnp->data.ptrvalue;
     if (StringHasNoText (str)) {
@@ -11729,6 +12226,7 @@ static Boolean ValidateSeqDescrCommon (ValNodePtr sdp, BioseqValidStrPtr bvsp, V
       }
     }
     break;
+  */
   case Seq_descr_genbank:
     if (bvsp->last_gb != NULL)
       ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_Inconsistent, "Multiple GenBank blocks");
@@ -11831,12 +12329,14 @@ static Boolean ValidateSeqDescrCommon (ValNodePtr sdp, BioseqValidStrPtr bvsp, V
     }
     if (biop != NULL && biop->origin == 5) {
       bsp = bvsp->bsp;
-      if (! IsOtherDNA (bsp)) {
+      if (! IsOtherDNA (bsp) && !ISA_aa (bsp->mol)) {
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_InvalidForType, "Molinfo-biomol other should be used if Biosource-location is synthetic");
       }
     }
     /* ValidateBioSource (vsp, gcp, biop, NULL, vnp); */
+    if (biop != NULL) {
     this_org = biop->org;
+    }
     /* fall into Seq_descr_org */
   case Seq_descr_org:
     if (this_org == NULL)
@@ -11875,6 +12375,7 @@ static Boolean ValidateSeqDescrCommon (ValNodePtr sdp, BioseqValidStrPtr bvsp, V
     for (vnp2 = vnp->next; vnp2 != NULL; vnp2 = vnp2->next) {
       if (vnp2->choice == Seq_descr_title) {
         ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_MultipleTitles, "Undesired multiple title descriptors");
+        break;
       }
     }
     len = StringLen (str);
@@ -11911,6 +12412,7 @@ static Boolean ValidateSeqDescrCommon (ValNodePtr sdp, BioseqValidStrPtr bvsp, V
         }
       }
     }
+    break;
   case Seq_descr_region:
     str = (CharPtr) vnp->data.ptrvalue;
     if (StringHasNoText (str)) {
@@ -13302,17 +13804,15 @@ static Boolean HaveUniqueFeatIDXrefs (SeqFeatXrefPtr xref1, SeqFeatXrefPtr xref2
 static Int2 WhichRNA (SeqFeatPtr sfp)
 
 {
-  GBQualPtr  gbq;
   RnaRefPtr  rrp;
   CharPtr    str;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return 0;
   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
   if (rrp == NULL) return 0;
-  if (rrp->ext.choice != 1) return 0;
-  str = (CharPtr) rrp->ext.value.ptrvalue;
+  str = GetRNARefProductString (rrp, NULL);
   if (StringHasNoText (str)) return 0;
-  if (rrp->type == 4) {
+  if (rrp->type == RNA_TYPE_rRNA) {
     if (StringNICmp (str, "small ", 6) == 0) return LEFT_RIBOSOMAL_SUBUNIT;
     if (StringNICmp (str, "18S ", 4) == 0) return LEFT_RIBOSOMAL_SUBUNIT;
     if (StringNICmp (str, "16S ", 4) == 0) return LEFT_RIBOSOMAL_SUBUNIT;
@@ -13329,14 +13829,7 @@ static Int2 WhichRNA (SeqFeatPtr sfp)
     if (StringNICmp (str, "28 ", 3) == 0) return RIGHT_RIBOSOMAL_SUBUNIT;
     if (StringNICmp (str, "23 ", 3) == 0) return RIGHT_RIBOSOMAL_SUBUNIT;
   }
-  if (rrp->type == 255) {
-    if (StringICmp (str, "misc_RNA") == 0) {
-      for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
-        if (StringICmp (gbq->qual, "product") != 0) continue;
-        if (StringHasNoText (gbq->val)) continue;
-        str = gbq->val;
-      }
-    }
+  if (rrp->type == RNA_TYPE_misc_RNA) {
     if (StringICmp (str, "internal transcribed spacer 1") == 0) return INTERNAL_SPACER_1;
     if (StringICmp (str, "internal transcribed spacer 2") == 0) return INTERNAL_SPACER_2;
     /* variant spellings */
@@ -13658,11 +14151,205 @@ static Boolean GeneXrefsDifferent (SeqFeatPtr sfp, SeqFeatPtr lastsfp)
   return FALSE;
 }
 
+
+static void CheckForGenesInconsistent (BioseqPtr bsp, ValidStructPtr vsp)
+{
+  SeqMgrFeatContext  fcontext;
+  SeqFeatPtr mrna, genomic_gene = NULL, mrna_gene = NULL;
+  GeneRefPtr genomicgrp, grp, found_grp;
+  BioseqPtr  genomic_bsp;
+  Boolean    is_error = FALSE;
+
+  mrna = SeqMgrGetRNAgivenProduct (bsp, &fcontext);
+  if (mrna != NULL) {
+    genomicgrp = SeqMgrGetGeneXref (mrna);
+    if (genomicgrp == NULL) {
+      genomic_gene = SeqMgrGetOverlappingGene (mrna->location, NULL);
+      if (genomic_gene != NULL) {
+        genomicgrp = (GeneRefPtr) genomic_gene->data.value.ptrvalue;
+      }
+    }
+    if (genomicgrp != NULL
+        && (mrna_gene = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_GENE, 0, &fcontext)) != NULL
+        && (grp = (GeneRefPtr) mrna_gene->data.value.ptrvalue) != NULL) {
+      if (StringCmp (grp->locus, genomicgrp->locus) != 0 ||
+          StringCmp (grp->allele, genomicgrp->allele) != 0 ||
+          StringCmp (grp->desc, genomicgrp->desc) != 0 ||
+          StringCmp (grp->locus_tag, genomicgrp->locus_tag) != 0) {
+        is_error = TRUE;
+        if (genomic_gene == NULL
+            && ((StringHasNoText (genomicgrp->desc) && StringDoesHaveText(grp->desc))
+                || (StringHasNoText (genomicgrp->allele) && StringDoesHaveText(grp->allele)))) {
+          genomic_bsp = BioseqFindFromSeqLoc (mrna->location);
+          if (StringDoesHaveText (genomicgrp->locus_tag)) {
+            genomic_gene = SeqMgrGetGeneByLocusTag (genomic_bsp, genomicgrp->locus_tag, &fcontext);
+            if (genomic_gene != NULL && (found_grp = (GeneRefPtr)genomic_gene->data.value.ptrvalue)
+              && StringCmp (found_grp->locus, genomicgrp->locus) != 0) {
+              genomic_gene = NULL;
+            }
+          } else if (StringDoesHaveText (genomicgrp->locus)) {
+            genomic_gene = SeqMgrGetFeatureByLabel (genomic_bsp, genomicgrp->locus, SEQFEAT_GENE, 0, &fcontext);
+            if (genomic_gene != NULL
+                && (found_grp = (GeneRefPtr)genomic_gene->data.value.ptrvalue) != NULL
+                && StringDoesHaveText (found_grp->locus_tag)) {
+              genomic_gene = NULL;
+            }
+          }
+          if (genomic_gene != NULL && (genomicgrp = (GeneRefPtr) genomic_gene->data.value.ptrvalue) != NULL
+              && StringCmp (grp->locus, genomicgrp->locus) == 0
+              && StringCmp (grp->allele, genomicgrp->allele) == 0
+              && StringCmp (grp->desc, genomicgrp->desc) == 0
+              && StringCmp (grp->locus_tag, genomicgrp->locus_tag) == 0) {
+            is_error = FALSE;
+          }
+        }
+        if (is_error) {
+          vsp->descr = NULL;
+          vsp->sfp = mrna_gene;
+          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_GenesInconsistent, "Gene on mRNA bioseq does not match gene on genomic bioseq");
+        }
+      }
+    }
+  }
+}
+
+static void CheckForNonViralComplete (BioseqPtr bsp, ValidStructPtr vsp, GatherContextPtr gcp)
+
+{
+  BioSourcePtr       biop = NULL;
+  SeqMgrDescContext  dcontext;
+  MolInfoPtr         mip = NULL;
+  Uint2              olditemtype = 0;
+  Uint4              olditemid = 0;
+  OrgNamePtr         onp;
+  OrgRefPtr          orp;
+  ObjValNodePtr      ovp;
+  SeqDescrPtr        sdp;
+  CharPtr            title = NULL;
+
+  if (bsp == NULL || vsp == NULL) return;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &dcontext);
+  if (sdp != NULL) {
+    mip = (MolInfoPtr) sdp->data.ptrvalue;
+  }
+  if (mip == NULL) return;
+  if (mip->biomol != MOLECULE_TYPE_GENOMIC || mip->completeness != 1) return;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, &dcontext);
+  if (sdp != NULL) {
+    title = (CharPtr) sdp->data.ptrvalue;
+  }
+  if (title == NULL) return;
+  if (StringStr (title, "complete genome") == NULL) return;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+  if (sdp != NULL) {
+    biop = (BioSourcePtr) sdp->data.ptrvalue;
+  }
+  if (biop == NULL) return;
+  if (biop->genome != GENOME_genomic && biop->genome != GENOME_unknown) return;
+
+  orp = biop->org;
+  if (orp == NULL) return;
+  onp = orp->orgname;
+  if (onp == NULL) return;
+  if (StringNICmp (onp->lineage, "Viruses; ", 9) == 0) return;
+  if (StringNICmp (onp->lineage, "Viroids; ", 9) == 0) return;
+  if (StringICmp (onp->lineage, "Viruses") == 0 && StringICmp (onp->div, "PHG") == 0) return;
+
+  if (gcp != NULL) {
+    olditemid = gcp->itemID;
+    olditemtype = gcp->thistype;
+  }
+
+  if (sdp != NULL && sdp->extended != 0) {
+    ovp = (ObjValNodePtr) sdp;
+    if (ovp != NULL && gcp != NULL) {
+      gcp->itemID = ovp->idx.itemID;
+      gcp->thistype = ovp->idx.itemtype;
+    }
+  }
+
+  ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceNeedsChromosome, "Non-viral complete genome not labeled as chromosome");
+
+  if (gcp != NULL) {
+    gcp->itemID = olditemid;
+    gcp->thistype = olditemtype;
+  }
+}
+
+
+static void LookForViralMolInfoInLineage (BioseqPtr bsp, ValidStructPtr vsp, GatherContextPtr gcp)
+{
+  SeqDescPtr        sdp;
+  SeqMgrDescContext context;
+  BioSourcePtr      biop;
+  CharPtr           lineage;
+  ObjValNodePtr     ovp;
+  Uint2             olditemtype = 0;
+  Uint4             olditemid = 0;
+
+  if (bsp == NULL || ISA_aa (bsp->mol) || vsp == NULL) return;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &context);
+  if (sdp == NULL || (biop = (BioSourcePtr) sdp->data.ptrvalue) == NULL
+      || biop->org == NULL || biop->org->orgname == NULL
+      || (lineage = biop->org->orgname->lineage) == NULL
+      || StringNICmp (biop->org->orgname->lineage, "Viruses; ", 9) != 0) {
+    return;
+  }
+
+  if (gcp != NULL) {
+    olditemid = gcp->itemID;
+    olditemtype = gcp->thistype;
+  }
+
+  if (sdp != NULL && sdp->extended != 0) {
+    ovp = (ObjValNodePtr) sdp;
+    if (ovp != NULL && gcp != NULL) {
+      gcp->itemID = ovp->idx.itemID;
+      gcp->thistype = ovp->idx.itemtype;
+    }
+  }
+
+  vsp->bsp = bsp;
+  vsp->descr = sdp;
+
+  if ((StringSearch (lineage, " ssRNA viruses; ") != NULL
+       || StringSearch (lineage, " ssRNA negative-strand viruses; ") != NULL
+       || StringSearch (lineage, " ssRNA positive-strand viruses, no DNA stage; ") != NULL
+       || StringSearch (lineage, " unassigned ssRNA viruses; ") != NULL)
+      && (bsp->mol != Seq_mol_rna)) {
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_MolInfoConflictsWithBioSource, "Taxonomy indicates single-stranded RNA, sequence does not agree.");
+  }
+
+  if (StringSearch (lineage, " dsRNA viruses; ") != NULL
+      && (bsp->mol != Seq_mol_rna)) {
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_MolInfoConflictsWithBioSource, "Taxonomy indicates double-stranded RNA, sequence does not agree.");
+  }
+
+  if (StringSearch (lineage, " ssDNA viruses; ") != NULL
+      && (bsp->mol != Seq_mol_dna)) {
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_MolInfoConflictsWithBioSource, "Taxonomy indicates single-stranded DNA, sequence does not agree.");
+  }
+
+  if (StringSearch (lineage, " dsDNA viruses; ") != NULL
+      && (bsp->mol != Seq_mol_dna)) {
+    ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_MolInfoConflictsWithBioSource, "Taxonomy indicates double-stranded DNA, sequence does not agree.");
+  }
+
+  if (gcp != NULL) {
+    gcp->itemID = olditemid;
+    gcp->thistype = olditemtype;
+  }
+}
+
+
 static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bvsp)
 
 {
   ValidStructPtr     vsp;
-  CitSubPtr          csp;
   ObjMgrDataPtr      omdp;
   SeqSubmitPtr       ssp;
   SubmitBlockPtr     sbp;
@@ -13671,7 +14358,7 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
   SeqMgrFeatContext  fcontext;
   Uint2              featdeftype = 0;
   Boolean            firstCDS;
-  GeneRefPtr         grp, genomicgrp, lastgrp;
+  GeneRefPtr         grp, lastgrp;
   SeqFeatPtr         last = NULL;
   Boolean            leave;
   CharPtr            label = NULL;
@@ -13709,7 +14396,7 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
   Int4               cdsRight;
   Int4               threeUTRright;
   Int4               cdscount, genecount, utr5count, utr3count;
-  SeqFeatPtr         mrna, gene, cdsgene, utr5gene, utr3gene;
+  SeqFeatPtr         gene, cdsgene, utr5gene, utr3gene;
   PubdescPtr         pdp = NULL, lastpdp;
   SeqDescrPtr        sdp;
   SeqMgrDescContext  dcontext;
@@ -13739,6 +14426,8 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
   MolInfoPtr         mip = NULL;
   SeqFeatPtr         cds;
   BioseqPtr          nbsp;
+  Boolean            last_reported;
+  Boolean            found_overlapping_peptide;
 
   gcp = bvsp->gcp;
   vsp = bvsp->vsp;
@@ -13955,12 +14644,14 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
   }
 
   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
+  last_reported = FALSE;
   while (sfp != NULL) {
     leave = TRUE;
     if (last != NULL) {
       ivalssame = FALSE;
       if (fcontext.left == left && fcontext.right == right && fcontext.featdeftype == featdeftype) {
-        if (fcontext.strand == strand || strand == Seq_strand_unknown || fcontext.strand == Seq_strand_unknown) {
+        if ((fcontext.strand == Seq_strand_minus && strand == Seq_strand_minus)
+            || (fcontext.strand != Seq_strand_minus && strand != Seq_strand_minus)) {
           ivalssame = TRUE;
           if (fcontext.numivals != numivals || fcontext.ivals == NULL || ivals == NULL) {
             ivalssame = FALSE;
@@ -14138,6 +14829,7 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
           }
         }
       }
+      found_overlapping_peptide = FALSE;
       if (fcontext.featdeftype == FEATDEF_mat_peptide_aa ||
           fcontext.featdeftype == FEATDEF_sig_peptide_aa || fcontext.featdeftype == FEATDEF_transit_peptide_aa) {
         if (featdeftype == FEATDEF_mat_peptide_aa || featdeftype == FEATDEF_sig_peptide_aa || featdeftype == FEATDEF_transit_peptide_aa) {
@@ -14155,13 +14847,24 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
               }
             }
             vsp->descr = NULL;
-            vsp->sfp = sfp;
             if (StringDoesHaveText (buf)) {
+              if (!last_reported) {
+                vsp->sfp = last;
+                ValidErr (vsp, overlapPepSev, ERR_SEQ_FEAT_OverlappingPeptideFeat,
+                          "Signal, Transit, or Mature peptide features overlap (parent CDS is on %s)", buf);
+              }
+              vsp->sfp = sfp;
               ValidErr (vsp, overlapPepSev, ERR_SEQ_FEAT_OverlappingPeptideFeat,
                         "Signal, Transit, or Mature peptide features overlap (parent CDS is on %s)", buf);
             } else {
+              if (!last_reported) {
+                vsp->sfp = last;
+                ValidErr (vsp, overlapPepSev, ERR_SEQ_FEAT_OverlappingPeptideFeat, "Signal, Transit, or Mature peptide features overlap");
+              }
+              vsp->sfp = sfp;
               ValidErr (vsp, overlapPepSev, ERR_SEQ_FEAT_OverlappingPeptideFeat, "Signal, Transit, or Mature peptide features overlap");
             }
+            found_overlapping_peptide = TRUE;
             vsp->sfp = NULL;
             if (gcp != NULL) {
               gcp->itemID = olditemid;
@@ -14170,6 +14873,7 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
           }
         }
       }
+      last_reported = found_overlapping_peptide;
     }
     if (leave) {
       last = sfp;
@@ -14538,40 +15242,7 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
     gcp->thistype = olditemtype;
   }
 
-  mrna = SeqMgrGetRNAgivenProduct (bsp, &fcontext);
-  if (mrna != NULL) {
-    genomicgrp = SeqMgrGetGeneXref (mrna);
-    if (genomicgrp == NULL) {
-      gene = SeqMgrGetOverlappingGene (mrna->location, NULL);
-      if (gene != NULL) {
-        genomicgrp = (GeneRefPtr) gene->data.value.ptrvalue;
-      }
-    }
-    if (genomicgrp != NULL) {
-      gene = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_GENE, 0, &fcontext);
-      if (gene != NULL) {
-        grp = (GeneRefPtr) gene->data.value.ptrvalue;
-        if (grp != NULL) {
-          if (StringCmp (grp->locus, genomicgrp->locus) != 0 ||
-              StringCmp (grp->allele, genomicgrp->allele) != 0 ||
-              StringCmp (grp->desc, genomicgrp->desc) != 0 ||
-              StringCmp (grp->locus_tag, genomicgrp->locus_tag) != 0) {
-            if (gcp != NULL) {
-              gcp->itemID = fcontext.itemID;
-              gcp->thistype = OBJ_SEQFEAT;
-            }
-            vsp->descr = NULL;
-            vsp->sfp = gene;
-            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_GenesInconsistent, "Gene on mRNA bioseq does not match gene on genomic bioseq");
-            if (gcp != NULL) {
-              gcp->itemID = olditemid;
-              gcp->thistype = olditemtype;
-            }
-          }
-        }
-      }
-    }
-  }
+  CheckForGenesInconsistent(bsp, vsp);
 
   if (ISA_na (bsp->mol)) {
     sfp = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_gap, &fcontext);
@@ -14719,7 +15390,7 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
       if (lastsfp != NULL) {
         if (StringDoesHaveText (lastsfp->comment) && StringDoesHaveText (sfp->comment) && StringICmp (lastsfp->comment, sfp->comment) != 0) {
           /* different comments, so ignore */
-        } else if (IsIdenticalBioSource (biop, lastbiop) && (! bvsp->is_artificial)) {
+        } else if (IsIdenticalBioSource (biop, lastbiop) && (! bvsp->is_synthetic) && (!bvsp->is_artificial)) {
           if (gcp != NULL) {
             gcp->itemID = fcontext.itemID;
             gcp->thistype = OBJ_SEQFEAT;
@@ -14795,20 +15466,6 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
       sbp = ssp->sub;
       if (sbp != NULL) {
         bvsp->got_a_pub = TRUE;
-        csp = sbp->cit;
-        /* csp = (CitSubPtr) gcp->thisitem; */
-        if (gcp != NULL) {
-          gcp->itemID = 1;
-          gcp->thistype = OBJ_SEQSUB_CIT;
-        }
-        vsp->descr = NULL;
-        vsp->sfp = NULL;
-        vsp->bssp = NULL;
-        ValidateCitSub (vsp, csp);
-        if (gcp != NULL) {
-          gcp->itemID = olditemid;
-          gcp->thistype = olditemtype;
-        }
       }
     }
   }
@@ -14827,6 +15484,10 @@ static Boolean ValidateBioseqContextIndexed (BioseqPtr bsp, BioseqValidStrPtr bv
     CheckBioseqForFeatsInGap (bsp, vsp);
   }
 
+  CheckForNonViralComplete (bsp, vsp, gcp);
+
+  LookForViralMolInfoInLineage (bsp, vsp, gcp);
+
   return TRUE;
 }
 
@@ -15037,14 +15698,17 @@ static void FindMultiGeneOverlaps (BioseqPtr bsp, ValidStructPtr vsp)
 
 }
 
-
 static void ValidateTSASequenceForNs (BioseqPtr bsp, ValidStructPtr vsp)
 {
   Int4 total = 0, max_stretch = 0;
   GatherContextPtr  gcp;
   Uint2           oldEntityID, oldItemtype;
   Uint4           oldItemID;
-  Int4            percent_N;
+  Int4            percent_N, allowed_percentN = 10;
+  SeqFeat         sf;
+  SeqInt          si;
+  CharPtr         str;
+  ValNode         vn;
 
   gcp = vsp->gcp;
 
@@ -15055,7 +15719,7 @@ static void ValidateTSASequenceForNs (BioseqPtr bsp, ValidStructPtr vsp)
   if (IsTSA (bsp)) {
     CountNsInSequence (bsp, &total, &max_stretch, FALSE);
     percent_N = (total * 100) / bsp->length;
-    if (percent_N > 5) {
+    if (percent_N > allowed_percentN) {
       vsp->bsp = bsp;
       vsp->descr = NULL;
       vsp->sfp = NULL;
@@ -15063,9 +15727,9 @@ static void ValidateTSASequenceForNs (BioseqPtr bsp, ValidStructPtr vsp)
       gcp->itemID = bsp->idx.itemID;
       gcp->thistype = OBJ_BIOSEQ;
 
-      ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_HighNContent, "Sequence contains %d percent Ns", percent_N);
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_HighNContentPercent, "Sequence contains %d percent Ns", percent_N);
     }
-    if (max_stretch > 5) {
+    if (max_stretch > 15) {
       vsp->bsp = bsp;
       vsp->descr = NULL;
       vsp->sfp = NULL;
@@ -15073,7 +15737,36 @@ static void ValidateTSASequenceForNs (BioseqPtr bsp, ValidStructPtr vsp)
       gcp->itemID = bsp->idx.itemID;
       gcp->thistype = OBJ_BIOSEQ;
 
-      ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_HighNContent, "Sequence has a stretch of %d Ns", max_stretch);
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_HighNContentStretch, "Sequence has a stretch of %d Ns", max_stretch);
+    } else if (bsp->length > 20) {
+      vsp->bsp = bsp;
+      vsp->descr = NULL;
+      vsp->sfp = NULL;
+      gcp->entityID = bsp->idx.entityID;
+      gcp->itemID = bsp->idx.itemID;
+      gcp->thistype = OBJ_BIOSEQ;
+
+      MemSet ((Pointer) &sf, 0, sizeof (SeqFeat));
+      MemSet ((Pointer) &si, 0, sizeof (SeqInt));
+      MemSet ((Pointer) &vn, 0, sizeof (ValNode));
+      sf.location = &vn;
+      vn.choice = SEQLOC_INT;
+      vn.data.ptrvalue = (Pointer) &si;
+      si.id = bsp->id;
+      si.from = 0;
+      si.to = 19;
+      str = GetSequenceByFeature (&sf);
+      if (StringStr (str, "NNNNN") != NULL) {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_HighNContentStretch, "Sequence has a stretch of at least 5 Ns within the first 20 bases");
+      }
+      MemFree (str);
+      si.from = bsp->length - 20;
+      si.to = bsp->length - 1;
+      str = GetSequenceByFeature (&sf);
+      if (StringStr (str, "NNNNN") != NULL) {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_HighNContentStretch, "Sequence has a stretch of at least 5 Ns within the last 20 bases");
+      }
+      MemFree (str);
     }
   }
   gcp->entityID = oldEntityID;
@@ -15082,6 +15775,65 @@ static void ValidateTSASequenceForNs (BioseqPtr bsp, ValidStructPtr vsp)
 }
 
 
+static void ValidateRefSeqTitle (BioseqPtr bsp, ValidStructPtr vsp, Boolean is_virus)
+{
+  SeqDescrPtr       sdp;
+  SeqMgrDescContext dcontext;
+  SeqMgrFeatContext fcontext;
+  CharPtr           taxname = NULL, title;
+  BioSourcePtr      biop;
+  SeqFeatPtr        cds, src_feat;
+  size_t            len, tlen;
+
+  if (bsp == NULL || vsp == NULL) {
+    return;
+  }
+
+  if (is_virus) return;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+  if (sdp != NULL
+      && (biop = (BioSourcePtr) sdp->data.ptrvalue) != NULL
+      && biop->org != NULL) {
+    taxname = biop->org->taxname;
+  }
+  if (ISA_aa(bsp->mol)) {
+    cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
+    if (cds != NULL) {
+      src_feat = SeqMgrGetOverlappingSource (cds->location, &fcontext);
+      if (src_feat != NULL
+          && (biop = (BioSourcePtr) src_feat->data.value.ptrvalue) != NULL
+          && biop->org != NULL) {
+        taxname = biop->org->taxname;
+      }
+    }
+  }
+
+  if (StringDoesHaveText (taxname)) {
+    sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, &dcontext);
+    if (sdp != NULL) {
+      title = (CharPtr) sdp->data.ptrvalue;
+      if (StringDoesHaveText (title)) {
+        len = StringLen (taxname);
+        tlen = StringLen (title);
+        if (ISA_na (bsp->mol)) {
+          if (tlen < len || StringNICmp (title, taxname, len) != 0) {
+            ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_NoOrganismInTitle, "RefSeq nucleotide title does not start with organism name");
+          }
+        } else if (ISA_aa (bsp->mol)) {
+          if (tlen < len + 3 ||
+              StringNICmp (title + tlen - len - 1, taxname, len) != 0 ||
+              title [tlen - len - 2] != '[' ||
+              title [tlen - 1] != ']') {
+            ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_NoOrganismInTitle, "RefSeq protein title does not end with organism name");
+          }
+        }
+      }
+    }
+  }
+}
+
+
 /*****************************************************************************
 *
 *   ValidateBioseqContext(gcp)
@@ -15116,18 +15868,26 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
   Boolean         isPDB = FALSE;
   Boolean         is_wgs = FALSE;
   Boolean         is_gb = FALSE;
+  Boolean         is_ac = FALSE;
   Boolean         is_ch_or_cm = FALSE;
   Boolean         is_nc = FALSE;
   Boolean         is_local = FALSE;
   Boolean         is_local_only = TRUE;
+  Boolean         is_organelle = FALSE;
+  Boolean         is_plasmid = FALSE;
+  Boolean         is_prokaryote = FALSE;
+  Boolean         is_refseq = FALSE;
   Boolean         is_neg_strand_virus = FALSE;
   Boolean         is_ambisense_virus = FALSE;
   Boolean         is_synthetic = FALSE;
   Boolean         is_transgenic = FALSE;
+  Boolean         is_virus = FALSE;
   Boolean         has_cds = FALSE;
+  Boolean         has_chromosome = FALSE;
   ErrSev          sev;
   SubSourcePtr    ssp;
   CharPtr         str;
+  CharPtr         taxname = NULL;
   TextSeqIdPtr    tsip;
   BioSourcePtr    biop;
   OrgRefPtr       orp;
@@ -15184,12 +15944,14 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
     if (vnp != NULL) {
       mip = (MolInfoPtr) vnp->data.ptrvalue;
     }
+
     vnp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
     if (vnp != NULL) {
       biop = (BioSourcePtr) vnp->data.ptrvalue;
       if (biop != NULL) {
         orp = biop->org;
         if (orp != NULL) {
+          taxname = orp->taxname;
           if (StringICmp (orp->taxname, "Human immunodeficiency virus") == 0 ||
               StringICmp (orp->taxname, "Human immunodeficiency virus 1") == 0 ||
               StringICmp (orp->taxname, "Human immunodeficiency virus 2") == 0) {
@@ -15212,11 +15974,24 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
               is_neg_strand_virus = TRUE;
             }
             if (StringISearch (onp->lineage, "Arenavirus") != NULL ||
+                StringISearch (onp->lineage, "Arenaviridae") != NULL ||
                 StringISearch (onp->lineage, "Phlebovirus") != NULL ||
                 StringISearch (onp->lineage, "Tospovirus") != NULL ||
                 StringISearch (onp->lineage, "Tenuivirus") != NULL) {
               is_ambisense_virus = TRUE;
             }
+            if (StringNICmp (onp->lineage, "Viruses; ", 9) == 0 ||
+                StringNICmp (onp->lineage, "Bacteria; ", 10) == 0 ||
+                StringNICmp (onp->lineage, "Archaea; ", 9) == 0 ||
+                StringCmp (onp->div, "BCT") == 0 ||
+                StringCmp (onp->div, "VRL") == 0) {
+              is_prokaryote = TRUE;
+            }
+            if (StringNICmp (onp->lineage, "Viruses; ", 9) == 0) {
+              is_virus = TRUE;
+            }
+            is_organelle = IsLocationOrganelle (biop->genome);
+            is_plasmid = (Boolean) (biop->genome == GENOME_plasmid);
             for (omp = onp->mod; omp != NULL; omp = omp->next) {
               if (omp->subtype == ORGMOD_other) {
                 if (mip != NULL && (StringICmp (omp->subname, "cRNA") == 0)) {
@@ -15247,8 +16022,10 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
             }
           }
         }
-        if (biop->origin == ORG_ARTIFICIAL || biop->origin == ORG_SYNTHETIC) {
+        if (biop->origin == ORG_ARTIFICIAL) {
           bvs.is_artificial = TRUE;
+        } else if (biop->origin == ORG_SYNTHETIC) {
+          bvs.is_synthetic = TRUE;
         }
         if (biop->origin == ORG_MUT || biop->origin == ORG_ARTIFICIAL || biop->origin == ORG_SYNTHETIC) {
           is_synthetic = TRUE;
@@ -15256,6 +16033,10 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
         for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
           if (ssp->subtype == SUBSRC_transgenic) {
             is_transgenic = TRUE;
+          } else if (ssp->subtype == SUBSRC_chromosome) {
+            if (StringDoesHaveText (ssp->name)) {
+              has_chromosome = TRUE;
+            }
           } else if (ssp->subtype == SUBSRC_other) {
             if (mip != NULL && (StringICmp (ssp->name, "cRNA") == 0)) {
               oldEntityID = gcp->entityID;
@@ -15285,6 +16066,22 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
         }
       }
     }
+
+    if (mip != NULL && mip->tech == MI_TECH_tsa && bsp->mol == MOLECULE_CLASS_DNA) {
+      oldEntityID = gcp->entityID;
+      oldItemID = gcp->itemID;
+      oldItemtype = gcp->thistype;
+
+      gcp->entityID = mipEntityID;
+      gcp->itemID = mipItemID;
+      gcp->thistype = mipItemtype;
+
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_INST_ConflictingBiomolTech, "TSA sequence should not be DNA");
+
+      gcp->entityID = oldEntityID;
+      gcp->itemID = oldItemID;
+      gcp->thistype = oldItemtype;
+    }
   }
 
   if (is_neg_strand_virus && mip != NULL) {
@@ -15316,7 +16113,7 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
         if (StringISearch (sfp->comment, "nonfunctional") != NULL) {
           if (SeqLocStrand (sfp->location) == Seq_strand_minus) {
             if (mip->biomol != MOLECULE_TYPE_GENOMIC) {
-              ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Negative-strand virus with nonfunctional minus strand misc_feature should be mRNA or cRNA");
+              ValidErr (vsp, SEV_WARNING, ERR_SEQ_DESCR_BioSourceInconsistency, "Negative-strand virus with nonfunctional minus strand misc_feature should be genomic");
             }
           } else {
             if (mip->biomol != MOLECULE_TYPE_MRNA && mip->biomol != MOLECULE_TYPE_CRNA && (! is_ambisense_virus)) {
@@ -15396,7 +16193,8 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
         mip->tech == MI_TECH_survey ||
         mip->tech == MI_TECH_wgs ||
         mip->tech == MI_TECH_htgs_0 || mip->tech == MI_TECH_htgs_1 ||
-        mip->tech == MI_TECH_htgs_2 || mip->tech == MI_TECH_htgs_3) {
+        mip->tech == MI_TECH_htgs_2 || mip->tech == MI_TECH_htgs_3 ||
+        mip->tech == MI_TECH_composite_wgs_htgs) {
       if (mip->tech == MI_TECH_sts && bsp->mol == Seq_mol_rna && mip->biomol == MOLECULE_TYPE_MRNA) {
         /* there are some STS sequences derived from cDNAs, so do not report these */
       } else if (mip->biomol != MOLECULE_TYPE_GENOMIC) {
@@ -15486,10 +16284,15 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
           is_ch_or_cm = TRUE;
         */
         } else if (WHICH_db_accession (tsip->accession) == ACCN_NCBI_SEGSET) {
+          /* NOTE '==' is appropriate here, rather than '|', because we
+           * really do only want to suppress if the type is exactly ACCN_NCBI_SEGSET
+           * and NOT if the type is ACCN_NCBI_SEGSET | ACCN_AMBIGOUS_MOL (prefix is AH)
+           */
           is_ch_or_cm = TRUE;
         }
       }
     } else if (sip->choice == SEQID_OTHER) {
+      is_refseq = TRUE;
       tsip = (TextSeqIdPtr) sip->data.ptrvalue;
       if (tsip != NULL && tsip->accession != NULL) {
         if (StringNCmp (tsip->accession, "NM_", 3) == 0 ||
@@ -15499,10 +16302,17 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
           is_gb = TRUE;
         } else if (StringNCmp (tsip->accession, "NC_", 3) == 0) {
           is_nc = TRUE;
+        } else if (StringNCmp (tsip->accession, "AC_", 3) == 0) {
+          is_ac = TRUE;
         }
       }
     }
   }
+  if (is_nc || is_ac) {
+    if (! is_prokaryote && ! is_organelle && ! has_chromosome && ! is_plasmid) {
+      ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_MissingChromosome, "Missing chromosome qualifier on NC or AC RefSeq record");
+    }
+  }
   if (! is_local) {
     is_local_only = FALSE;
   }
@@ -15525,6 +16335,10 @@ static void ValidateBioseqContext (GatherContextPtr gcp)
     }
   }
 
+  if (bsp != NULL && is_refseq) {
+    ValidateRefSeqTitle (bsp, vsp, is_virus);
+  }
+
   if ((!bvs.last_org) && (!vsp->suppress_no_biosrc))
     ValidErr (vsp, SEV_ERROR, ERR_SEQ_DESCR_NoOrgFound, "No organism name has been applied to this Bioseq.  Other qualifiers may exist.");
 
@@ -15644,7 +16458,9 @@ static void CheckPeptideOnCodonBoundary (ValidStructPtr vsp, GatherContextPtr gc
     mod2 = 2;
   }
 
-  if (mod1 != 0 && mod2 != 2) {
+  if (pos1 < 0 && pos2 < 0 && StringICmp (key, "sig_peptide") == 0) {
+    /* ignore special case of sig_peptide completely before codon_start of CDS */
+  } else if (mod1 != 0 && mod2 != 2) {
     ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PeptideFeatOutOfFrame, "Start and stop of %s are out of frame with CDS codons", key);
   } else if (mod1 != 0) {
     ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PeptideFeatOutOfFrame, "Start of %s is out of frame with CDS codons", key);
@@ -15685,142 +16501,132 @@ static CharPtr legal_mobile_element_strings [] = {
 };
 
 static CharPtr ecnum_ambig [] = {
-  "1.-.-.-", "1.-.-.n", "1.-.n.n", "1.n.n.n", "1.1.-.-", "1.1.-.n",
-  "1.1.n.n", "1.1.1.-", "1.1.1.n", "1.1.2.-", "1.1.2.n", "1.1.3.-",
-  "1.1.3.n", "1.1.4.-", "1.1.4.n", "1.1.5.-", "1.1.5.n", "1.1.99.-",
-  "1.1.99.n", "1.2.-.-", "1.2.-.n", "1.2.n.n", "1.2.1.-", "1.2.1.n",
-  "1.2.2.-", "1.2.2.n", "1.2.3.-", "1.2.3.n", "1.2.4.-", "1.2.4.n",
-  "1.2.7.-", "1.2.7.n", "1.2.99.-", "1.2.99.n", "1.3.-.-", "1.3.-.n",
-  "1.3.n.n", "1.3.1.-", "1.3.1.n", "1.3.2.-", "1.3.2.n", "1.3.3.-",
-  "1.3.3.n", "1.3.5.-", "1.3.5.n", "1.3.7.-", "1.3.7.n", "1.3.99.-",
-  "1.3.99.n", "1.4.-.-", "1.4.-.n", "1.4.n.n", "1.4.1.-", "1.4.1.n",
-  "1.4.2.-", "1.4.2.n", "1.4.3.-", "1.4.3.n", "1.4.4.-", "1.4.4.n",
-  "1.4.7.-", "1.4.7.n", "1.4.99.-", "1.4.99.n", "1.5.-.-", "1.5.-.n",
-  "1.5.n.n", "1.5.1.-", "1.5.1.n", "1.5.3.-", "1.5.3.n", "1.5.4.-",
-  "1.5.4.n", "1.5.5.-", "1.5.5.n", "1.5.7.-", "1.5.7.n", "1.5.8.-",
-  "1.5.8.n", "1.5.99.-", "1.5.99.n", "1.6.-.-", "1.6.-.n", "1.6.n.n",
-  "1.6.1.-", "1.6.1.n", "1.6.2.-", "1.6.2.n", "1.6.3.-", "1.6.3.n",
-  "1.6.4.-", "1.6.4.n", "1.6.5.-", "1.6.5.n", "1.6.6.-", "1.6.6.n",
-  "1.6.7.-", "1.6.7.n", "1.6.8.-", "1.6.8.n", "1.6.99.-", "1.6.99.n",
-  "1.7.-.-", "1.7.-.n", "1.7.n.n", "1.7.1.-", "1.7.1.n", "1.7.2.-",
-  "1.7.2.n", "1.7.3.-", "1.7.3.n", "1.7.7.-", "1.7.7.n", "1.7.99.-",
-  "1.7.99.n", "1.8.-.-", "1.8.-.n", "1.8.n.n", "1.8.1.-", "1.8.1.n",
-  "1.8.2.-", "1.8.2.n", "1.8.3.-", "1.8.3.n", "1.8.4.-", "1.8.4.n",
-  "1.8.5.-", "1.8.5.n", "1.8.6.-", "1.8.6.n", "1.8.7.-", "1.8.7.n",
-  "1.8.98.-", "1.8.98.n", "1.8.99.-", "1.8.99.n", "1.9.-.-", "1.9.-.n",
-  "1.9.n.n", "1.9.3.-", "1.9.3.n", "1.9.6.-", "1.9.6.n", "1.9.99.-",
-  "1.9.99.n", "1.10.-.-", "1.10.-.n", "1.10.n.n", "1.10.1.-",
+  "1.-.-.-", "1.1.-.-", "1.1.1.-", "1.1.1.n", "1.1.2.-", "1.1.2.n",
+  "1.1.3.-", "1.1.3.n", "1.1.4.-", "1.1.4.n", "1.1.5.-", "1.1.5.n",
+  "1.1.98.-", "1.1.98.n", "1.1.99.-", "1.1.99.n", "1.1.n.n",
+  "1.2.-.-", "1.2.1.-", "1.2.1.n", "1.2.2.-", "1.2.2.n", "1.2.3.-",
+  "1.2.3.n", "1.2.4.-", "1.2.4.n", "1.2.7.-", "1.2.7.n", "1.2.99.-",
+  "1.2.99.n", "1.2.n.n", "1.3.-.-", "1.3.1.-", "1.3.1.n", "1.3.2.-",
+  "1.3.2.n", "1.3.3.-", "1.3.3.n", "1.3.5.-", "1.3.5.n", "1.3.7.-",
+  "1.3.7.n", "1.3.99.-", "1.3.99.n", "1.3.n.n", "1.4.-.-", "1.4.1.-",
+  "1.4.1.n", "1.4.2.-", "1.4.2.n", "1.4.3.-", "1.4.3.n", "1.4.4.-",
+  "1.4.4.n", "1.4.5.-", "1.4.5.n", "1.4.7.-", "1.4.7.n", "1.4.99.-",
+  "1.4.99.n", "1.4.n.n", "1.5.-.-", "1.5.1.-", "1.5.1.n", "1.5.3.-",
+  "1.5.3.n", "1.5.4.-", "1.5.4.n", "1.5.5.-", "1.5.5.n", "1.5.7.-",
+  "1.5.7.n", "1.5.8.-", "1.5.8.n", "1.5.99.-", "1.5.99.n", "1.5.n.n",
+  "1.6.-.-", "1.6.1.-", "1.6.1.n", "1.6.2.-", "1.6.2.n", "1.6.3.-",
+  "1.6.3.n", "1.6.4.-", "1.6.4.n", "1.6.5.-", "1.6.5.n", "1.6.6.-",
+  "1.6.6.n", "1.6.7.-", "1.6.7.n", "1.6.8.-", "1.6.8.n", "1.6.99.-",
+  "1.6.99.n", "1.6.n.n", "1.7.-.-", "1.7.1.-", "1.7.1.n", "1.7.2.-",
+  "1.7.2.n", "1.7.3.-", "1.7.3.n", "1.7.5.-", "1.7.5.n", "1.7.7.-",
+  "1.7.7.n", "1.7.99.-", "1.7.99.n", "1.7.n.n", "1.8.-.-", "1.8.1.-",
+  "1.8.1.n", "1.8.2.-", "1.8.2.n", "1.8.3.-", "1.8.3.n", "1.8.4.-",
+  "1.8.4.n", "1.8.5.-", "1.8.5.n", "1.8.6.-", "1.8.6.n", "1.8.7.-",
+  "1.8.7.n", "1.8.98.-", "1.8.98.n", "1.8.99.-", "1.8.99.n",
+  "1.8.n.n", "1.9.-.-", "1.9.3.-", "1.9.3.n", "1.9.6.-", "1.9.6.n",
+  "1.9.99.-", "1.9.99.n", "1.9.n.n", "1.10.-.-", "1.10.1.-",
   "1.10.1.n", "1.10.2.-", "1.10.2.n", "1.10.3.-", "1.10.3.n",
-  "1.10.99.-", "1.10.99.n", "1.11.-.-", "1.11.-.n", "1.11.n.n",
-  "1.11.1.-", "1.11.1.n", "1.12.-.-", "1.12.-.n", "1.12.n.n",
-  "1.12.1.-", "1.12.1.n", "1.12.2.-", "1.12.2.n", "1.12.5.-",
-  "1.12.5.n", "1.12.7.-", "1.12.7.n", "1.12.98.-", "1.12.98.n",
-  "1.12.99.-", "1.12.99.n", "1.13.-.-", "1.13.-.n", "1.13.n.n",
-  "1.13.1.-", "1.13.1.n", "1.13.11.-", "1.13.11.n", "1.13.12.-",
-  "1.13.12.n", "1.13.99.-", "1.13.99.n", "1.14.-.-", "1.14.-.n",
-  "1.14.n.n", "1.14.1.-", "1.14.1.n", "1.14.2.-", "1.14.2.n",
-  "1.14.3.-", "1.14.3.n", "1.14.11.-", "1.14.11.n", "1.14.12.-",
-  "1.14.12.n", "1.14.13.-", "1.14.13.n", "1.14.14.-", "1.14.14.n",
-  "1.14.15.-", "1.14.15.n", "1.14.16.-", "1.14.16.n", "1.14.17.-",
-  "1.14.17.n", "1.14.18.-", "1.14.18.n", "1.14.19.-", "1.14.19.n",
-  "1.14.20.-", "1.14.20.n", "1.14.21.-", "1.14.21.n", "1.14.99.-",
-  "1.14.99.n", "1.15.-.-", "1.15.-.n", "1.15.n.n", "1.15.1.-",
-  "1.15.1.n", "1.16.-.-", "1.16.-.n", "1.16.n.n", "1.16.1.-",
-  "1.16.1.n", "1.16.3.-", "1.16.3.n", "1.16.8.-", "1.16.8.n",
-  "1.17.-.-", "1.17.-.n", "1.17.n.n", "1.17.1.-", "1.17.1.n",
-  "1.17.3.-", "1.17.3.n", "1.17.4.-", "1.17.4.n", "1.17.5.-",
-  "1.17.5.n", "1.17.7.-", "1.17.7.n", "1.17.99.-", "1.17.99.n",
-  "1.18.-.-", "1.18.-.n", "1.18.n.n", "1.18.1.-", "1.18.1.n",
-  "1.18.2.-", "1.18.2.n", "1.18.3.-", "1.18.3.n", "1.18.6.-",
-  "1.18.6.n", "1.18.96.-", "1.18.96.n", "1.18.99.-", "1.18.99.n",
-  "1.19.-.-", "1.19.-.n", "1.19.n.n", "1.19.6.-", "1.19.6.n",
-  "1.20.-.-", "1.20.-.n", "1.20.n.n", "1.20.1.-", "1.20.1.n",
+  "1.10.99.-", "1.10.99.n", "1.10.n.n", "1.11.-.-", "1.11.1.-",
+  "1.11.1.n", "1.11.n.n", "1.12.-.-", "1.12.1.-", "1.12.1.n",
+  "1.12.2.-", "1.12.2.n", "1.12.5.-", "1.12.5.n", "1.12.7.-",
+  "1.12.7.n", "1.12.98.-", "1.12.98.n", "1.12.99.-", "1.12.99.n",
+  "1.12.n.n", "1.13.-.-", "1.13.1.-", "1.13.1.n", "1.13.11.-",
+  "1.13.11.n", "1.13.12.-", "1.13.12.n", "1.13.99.-", "1.13.99.n",
+  "1.13.n.n", "1.14.-.-", "1.14.1.-", "1.14.1.n", "1.14.2.-",
+  "1.14.2.n", "1.14.3.-", "1.14.3.n", "1.14.11.-", "1.14.11.n",
+  "1.14.12.-", "1.14.12.n", "1.14.13.-", "1.14.13.n", "1.14.14.-",
+  "1.14.14.n", "1.14.15.-", "1.14.15.n", "1.14.16.-", "1.14.16.n",
+  "1.14.17.-", "1.14.17.n", "1.14.18.-", "1.14.18.n", "1.14.19.-",
+  "1.14.19.n", "1.14.20.-", "1.14.20.n", "1.14.21.-", "1.14.21.n",
+  "1.14.99.-", "1.14.99.n", "1.14.n.n", "1.15.-.-", "1.15.1.-",
+  "1.15.1.n", "1.15.n.n", "1.16.-.-", "1.16.1.-", "1.16.1.n",
+  "1.16.3.-", "1.16.3.n", "1.16.8.-", "1.16.8.n", "1.16.n.n",
+  "1.17.-.-", "1.17.1.-", "1.17.1.n", "1.17.3.-", "1.17.3.n",
+  "1.17.4.-", "1.17.4.n", "1.17.5.-", "1.17.5.n", "1.17.7.-",
+  "1.17.7.n", "1.17.99.-", "1.17.99.n", "1.17.n.n", "1.18.-.-",
+  "1.18.1.-", "1.18.1.n", "1.18.2.-", "1.18.2.n", "1.18.3.-",
+  "1.18.3.n", "1.18.6.-", "1.18.6.n", "1.18.96.-", "1.18.96.n",
+  "1.18.99.-", "1.18.99.n", "1.18.n.n", "1.19.-.-", "1.19.6.-",
+  "1.19.6.n", "1.19.n.n", "1.20.-.-", "1.20.1.-", "1.20.1.n",
   "1.20.4.-", "1.20.4.n", "1.20.98.-", "1.20.98.n", "1.20.99.-",
-  "1.20.99.n", "1.21.-.-", "1.21.-.n", "1.21.n.n", "1.21.3.-",
-  "1.21.3.n", "1.21.4.-", "1.21.4.n", "1.21.99.-", "1.21.99.n",
-  "1.97.-.-", "1.97.-.n", "1.97.n.n", "1.97.1.-", "1.97.1.n",
-  "1.98.-.-", "1.98.-.n", "1.98.n.n", "1.98.1.-", "1.98.1.n",
-  "1.99.-.-", "1.99.-.n", "1.99.n.n", "1.99.1.-", "1.99.1.n",
-  "1.99.2.-", "1.99.2.n", "2.-.-.-", "2.-.-.n", "2.-.n.n", "2.n.n.n",
-  "2.1.-.-", "2.1.-.n", "2.1.n.n", "2.1.1.-", "2.1.1.n", "2.1.2.-",
-  "2.1.2.n", "2.1.3.-", "2.1.3.n", "2.1.4.-", "2.1.4.n", "2.2.-.-",
-  "2.2.-.n", "2.2.n.n", "2.2.1.-", "2.2.1.n", "2.3.-.-", "2.3.-.n",
-  "2.3.n.n", "2.3.1.-", "2.3.1.n", "2.3.2.-", "2.3.2.n", "2.3.3.-",
-  "2.3.3.n", "2.4.-.-", "2.4.-.n", "2.4.n.n", "2.4.1.-", "2.4.1.n",
-  "2.4.2.-", "2.4.2.n", "2.4.99.-", "2.4.99.n", "2.5.-.-", "2.5.-.n",
-  "2.5.n.n", "2.5.1.-", "2.5.1.n", "2.6.-.-", "2.6.-.n", "2.6.n.n",
-  "2.6.1.-", "2.6.1.n", "2.6.2.-", "2.6.2.n", "2.6.3.-", "2.6.3.n",
-  "2.6.99.-", "2.6.99.n", "2.7.-.-", "2.7.-.n", "2.7.n.n", "2.7.1.-",
-  "2.7.1.n", "2.7.2.-", "2.7.2.n", "2.7.3.-", "2.7.3.n", "2.7.4.-",
-  "2.7.4.n", "2.7.5.-", "2.7.5.n", "2.7.6.-", "2.7.6.n", "2.7.7.-",
-  "2.7.7.n", "2.7.8.-", "2.7.8.n", "2.7.9.-", "2.7.9.n", "2.7.10.-",
-  "2.7.10.n", "2.7.11.-", "2.7.11.n", "2.7.12.-", "2.7.12.n",
-  "2.7.13.-", "2.7.13.n", "2.7.99.-", "2.7.99.n", "2.8.-.-", "2.8.-.n",
-  "2.8.n.n", "2.8.1.-", "2.8.1.n", "2.8.2.-", "2.8.2.n", "2.8.3.-",
-  "2.8.3.n", "2.8.4.-", "2.8.4.n", "2.9.-.-", "2.9.-.n", "2.9.n.n",
-  "2.9.1.-", "2.9.1.n", "3.-.-.-", "3.-.-.n", "3.-.n.n", "3.n.n.n",
-  "3.1.-.-", "3.1.-.n", "3.1.n.n", "3.1.1.-", "3.1.1.n", "3.1.2.-",
-  "3.1.2.n", "3.1.3.-", "3.1.3.n", "3.1.4.-", "3.1.4.n", "3.1.5.-",
-  "3.1.5.n", "3.1.6.-", "3.1.6.n", "3.1.7.-", "3.1.7.n", "3.1.8.-",
-  "3.1.8.n", "3.1.11.-", "3.1.11.n", "3.1.13.-", "3.1.13.n", "3.1.14.-",
+  "1.20.99.n", "1.20.n.n", "1.21.-.-", "1.21.3.-", "1.21.3.n",
+  "1.21.4.-", "1.21.4.n", "1.21.99.-", "1.21.99.n", "1.21.n.n",
+  "1.22.-.-", "1.22.1.-", "1.22.1.n", "1.22.n.n", "1.97.-.-",
+  "1.97.1.-", "1.97.1.n", "1.97.n.n", "1.98.-.-", "1.98.1.-",
+  "1.98.1.n", "1.98.n.n", "1.99.-.-", "1.99.1.-", "1.99.1.n",
+  "1.99.2.-", "1.99.2.n", "1.99.n.n", "1.n.n.n", "2.-.-.-", "2.1.-.-",
+  "2.1.1.-", "2.1.1.n", "2.1.2.-", "2.1.2.n", "2.1.3.-", "2.1.3.n",
+  "2.1.4.-", "2.1.4.n", "2.1.n.n", "2.2.-.-", "2.2.1.-", "2.2.1.n",
+  "2.2.n.n", "2.3.-.-", "2.3.1.-", "2.3.1.n", "2.3.2.-", "2.3.2.n",
+  "2.3.3.-", "2.3.3.n", "2.3.n.n", "2.4.-.-", "2.4.1.-", "2.4.1.n",
+  "2.4.2.-", "2.4.2.n", "2.4.99.-", "2.4.99.n", "2.4.n.n", "2.5.-.-",
+  "2.5.1.-", "2.5.1.n", "2.5.n.n", "2.6.-.-", "2.6.1.-", "2.6.1.n",
+  "2.6.2.-", "2.6.2.n", "2.6.3.-", "2.6.3.n", "2.6.99.-", "2.6.99.n",
+  "2.6.n.n", "2.7.-.-", "2.7.1.-", "2.7.1.n", "2.7.2.-", "2.7.2.n",
+  "2.7.3.-", "2.7.3.n", "2.7.4.-", "2.7.4.n", "2.7.5.-", "2.7.5.n",
+  "2.7.6.-", "2.7.6.n", "2.7.7.-", "2.7.7.n", "2.7.8.-", "2.7.8.n",
+  "2.7.9.-", "2.7.9.n", "2.7.10.-", "2.7.10.n", "2.7.11.-",
+  "2.7.11.n", "2.7.12.-", "2.7.12.n", "2.7.13.-", "2.7.13.n",
+  "2.7.99.-", "2.7.99.n", "2.7.n.n", "2.8.-.-", "2.8.1.-", "2.8.1.n",
+  "2.8.2.-", "2.8.2.n", "2.8.3.-", "2.8.3.n", "2.8.4.-", "2.8.4.n",
+  "2.8.n.n", "2.9.-.-", "2.9.1.-", "2.9.1.n", "2.9.n.n", "2.n.n.n",
+  "3.-.-.-", "3.1.-.-", "3.1.1.-", "3.1.1.n", "3.1.2.-", "3.1.2.n",
+  "3.1.3.-", "3.1.3.n", "3.1.4.-", "3.1.4.n", "3.1.5.-", "3.1.5.n",
+  "3.1.6.-", "3.1.6.n", "3.1.7.-", "3.1.7.n", "3.1.8.-", "3.1.8.n",
+  "3.1.11.-", "3.1.11.n", "3.1.13.-", "3.1.13.n", "3.1.14.-",
   "3.1.14.n", "3.1.15.-", "3.1.15.n", "3.1.16.-", "3.1.16.n",
   "3.1.21.-", "3.1.21.n", "3.1.22.-", "3.1.22.n", "3.1.23.-",
   "3.1.23.n", "3.1.24.-", "3.1.24.n", "3.1.25.-", "3.1.25.n",
   "3.1.26.-", "3.1.26.n", "3.1.27.-", "3.1.27.n", "3.1.30.-",
-  "3.1.30.n", "3.1.31.-", "3.1.31.n", "3.2.-.-", "3.2.-.n", "3.2.n.n",
-  "3.2.1.-", "3.2.1.n", "3.2.2.-", "3.2.2.n", "3.2.3.-", "3.2.3.n",
-  "3.3.-.-", "3.3.-.n", "3.3.n.n", "3.3.1.-", "3.3.1.n", "3.3.2.-",
-  "3.3.2.n", "3.4.-.-", "3.4.-.n", "3.4.n.n", "3.4.1.-", "3.4.1.n",
-  "3.4.2.-", "3.4.2.n", "3.4.3.-", "3.4.3.n", "3.4.4.-", "3.4.4.n",
-  "3.4.11.-", "3.4.11.n", "3.4.12.-", "3.4.12.n", "3.4.13.-",
-  "3.4.13.n", "3.4.14.-", "3.4.14.n", "3.4.15.-", "3.4.15.n",
-  "3.4.16.-", "3.4.16.n", "3.4.17.-", "3.4.17.n", "3.4.18.-",
-  "3.4.18.n", "3.4.19.-", "3.4.19.n", "3.4.21.-", "3.4.21.n",
-  "3.4.22.-", "3.4.22.n", "3.4.23.-", "3.4.23.n", "3.4.24.-",
-  "3.4.24.n", "3.4.25.-", "3.4.25.n", "3.4.99.-", "3.4.99.n", "3.5.-.-",
-  "3.5.-.n", "3.5.n.n", "3.5.1.-", "3.5.1.n", "3.5.2.-", "3.5.2.n",
-  "3.5.3.-", "3.5.3.n", "3.5.4.-", "3.5.4.n", "3.5.5.-", "3.5.5.n",
-  "3.5.99.-", "3.5.99.n", "3.6.-.-", "3.6.-.n", "3.6.n.n", "3.6.1.-",
-  "3.6.1.n", "3.6.2.-", "3.6.2.n", "3.6.3.-", "3.6.3.n", "3.6.4.-",
-  "3.6.4.n", "3.6.5.-", "3.6.5.n", "3.7.-.-", "3.7.-.n", "3.7.n.n",
-  "3.7.1.-", "3.7.1.n", "3.8.-.-", "3.8.-.n", "3.8.n.n", "3.8.1.-",
-  "3.8.1.n", "3.8.2.-", "3.8.2.n", "3.9.-.-", "3.9.-.n", "3.9.n.n",
-  "3.9.1.-", "3.9.1.n", "3.10.-.-", "3.10.-.n", "3.10.n.n", "3.10.1.-",
-  "3.10.1.n", "3.11.-.-", "3.11.-.n", "3.11.n.n", "3.11.1.-",
-  "3.11.1.n", "3.12.-.-", "3.12.-.n", "3.12.n.n", "3.12.1.-",
-  "3.12.1.n", "3.13.-.-", "3.13.-.n", "3.13.n.n", "3.13.1.-",
-  "3.13.1.n", "4.-.-.-", "4.-.-.n", "4.-.n.n", "4.n.n.n", "4.1.-.-",
-  "4.1.-.n", "4.1.n.n", "4.1.1.-", "4.1.1.n", "4.1.2.-", "4.1.2.n",
-  "4.1.3.-", "4.1.3.n", "4.1.99.-", "4.1.99.n", "4.2.-.-", "4.2.-.n",
-  "4.2.n.n", "4.2.1.-", "4.2.1.n", "4.2.2.-", "4.2.2.n", "4.2.3.-",
-  "4.2.3.n", "4.2.99.-", "4.2.99.n", "4.3.-.-", "4.3.-.n", "4.3.n.n",
-  "4.3.1.-", "4.3.1.n", "4.3.2.-", "4.3.2.n", "4.3.3.-", "4.3.3.n",
-  "4.3.99.-", "4.3.99.n", "4.4.-.-", "4.4.-.n", "4.4.n.n", "4.4.1.-",
-  "4.4.1.n", "4.5.-.-", "4.5.-.n", "4.5.n.n", "4.5.1.-", "4.5.1.n",
-  "4.6.-.-", "4.6.-.n", "4.6.n.n", "4.6.1.-", "4.6.1.n", "4.99.-.-",
-  "4.99.-.n", "4.99.n.n", "4.99.1.-", "4.99.1.n", "5.-.-.-", "5.-.-.n",
-  "5.-.n.n", "5.n.n.n", "5.1.-.-", "5.1.-.n", "5.1.n.n", "5.1.1.-",
+  "3.1.30.n", "3.1.31.-", "3.1.31.n", "3.1.n.n", "3.2.-.-", "3.2.1.-",
+  "3.2.1.n", "3.2.2.-", "3.2.2.n", "3.2.3.-", "3.2.3.n", "3.2.n.n",
+  "3.3.-.-", "3.3.1.-", "3.3.1.n", "3.3.2.-", "3.3.2.n", "3.3.n.n",
+  "3.4.-.-", "3.4.1.-", "3.4.1.n", "3.4.2.-", "3.4.2.n", "3.4.3.-",
+  "3.4.3.n", "3.4.4.-", "3.4.4.n", "3.4.11.-", "3.4.11.n", "3.4.12.-",
+  "3.4.12.n", "3.4.13.-", "3.4.13.n", "3.4.14.-", "3.4.14.n",
+  "3.4.15.-", "3.4.15.n", "3.4.16.-", "3.4.16.n", "3.4.17.-",
+  "3.4.17.n", "3.4.18.-", "3.4.18.n", "3.4.19.-", "3.4.19.n",
+  "3.4.21.-", "3.4.21.n", "3.4.22.-", "3.4.22.n", "3.4.23.-",
+  "3.4.23.n", "3.4.24.-", "3.4.24.n", "3.4.25.-", "3.4.25.n",
+  "3.4.99.-", "3.4.99.n", "3.4.n.n", "3.5.-.-", "3.5.1.-", "3.5.1.n",
+  "3.5.2.-", "3.5.2.n", "3.5.3.-", "3.5.3.n", "3.5.4.-", "3.5.4.n",
+  "3.5.5.-", "3.5.5.n", "3.5.99.-", "3.5.99.n", "3.5.n.n", "3.6.-.-",
+  "3.6.1.-", "3.6.1.n", "3.6.2.-", "3.6.2.n", "3.6.3.-", "3.6.3.n",
+  "3.6.4.-", "3.6.4.n", "3.6.5.-", "3.6.5.n", "3.6.n.n", "3.7.-.-",
+  "3.7.1.-", "3.7.1.n", "3.7.n.n", "3.8.-.-", "3.8.1.-", "3.8.1.n",
+  "3.8.2.-", "3.8.2.n", "3.8.n.n", "3.9.-.-", "3.9.1.-", "3.9.1.n",
+  "3.9.n.n", "3.10.-.-", "3.10.1.-", "3.10.1.n", "3.10.n.n",
+  "3.11.-.-", "3.11.1.-", "3.11.1.n", "3.11.n.n", "3.12.-.-",
+  "3.12.1.-", "3.12.1.n", "3.12.n.n", "3.13.-.-", "3.13.1.-",
+  "3.13.1.n", "3.13.n.n", "3.n.n.n", "4.-.-.-", "4.1.-.-", "4.1.1.-",
+  "4.1.1.n", "4.1.2.-", "4.1.2.n", "4.1.3.-", "4.1.3.n", "4.1.99.-",
+  "4.1.99.n", "4.1.n.n", "4.2.-.-", "4.2.1.-", "4.2.1.n", "4.2.2.-",
+  "4.2.2.n", "4.2.3.-", "4.2.3.n", "4.2.99.-", "4.2.99.n", "4.2.n.n",
+  "4.3.-.-", "4.3.1.-", "4.3.1.n", "4.3.2.-", "4.3.2.n", "4.3.3.-",
+  "4.3.3.n", "4.3.99.-", "4.3.99.n", "4.3.n.n", "4.4.-.-", "4.4.1.-",
+  "4.4.1.n", "4.4.n.n", "4.5.-.-", "4.5.1.-", "4.5.1.n", "4.5.n.n",
+  "4.6.-.-", "4.6.1.-", "4.6.1.n", "4.6.n.n", "4.99.-.-", "4.99.1.-",
+  "4.99.1.n", "4.99.n.n", "4.n.n.n", "5.-.-.-", "5.1.-.-", "5.1.1.-",
   "5.1.1.n", "5.1.2.-", "5.1.2.n", "5.1.3.-", "5.1.3.n", "5.1.99.-",
-  "5.1.99.n", "5.2.-.-", "5.2.-.n", "5.2.n.n", "5.2.1.-", "5.2.1.n",
-  "5.3.-.-", "5.3.-.n", "5.3.n.n", "5.3.1.-", "5.3.1.n", "5.3.2.-",
-  "5.3.2.n", "5.3.3.-", "5.3.3.n", "5.3.4.-", "5.3.4.n", "5.3.99.-",
-  "5.3.99.n", "5.4.-.-", "5.4.-.n", "5.4.n.n", "5.4.1.-", "5.4.1.n",
-  "5.4.2.-", "5.4.2.n", "5.4.3.-", "5.4.3.n", "5.4.4.-", "5.4.4.n",
-  "5.4.99.-", "5.4.99.n", "5.5.-.-", "5.5.-.n", "5.5.n.n", "5.5.1.-",
-  "5.5.1.n", "5.99.-.-", "5.99.-.n", "5.99.n.n", "5.99.1.-", "5.99.1.n",
-  "6.-.-.-", "6.-.-.n", "6.-.n.n", "6.n.n.n", "6.1.-.-", "6.1.-.n",
-  "6.1.n.n", "6.1.1.-", "6.1.1.n", "6.2.-.-", "6.2.-.n", "6.2.n.n",
-  "6.2.1.-", "6.2.1.n", "6.3.-.-", "6.3.-.n", "6.3.n.n", "6.3.1.-",
-  "6.3.1.n", "6.3.2.-", "6.3.2.n", "6.3.3.-", "6.3.3.n", "6.3.4.-",
-  "6.3.4.n", "6.3.5.-", "6.3.5.n", "6.4.-.-", "6.4.-.n", "6.4.n.n",
-  "6.4.1.-", "6.4.1.n", "6.5.-.-", "6.5.-.n", "6.5.n.n", "6.5.1.-",
-  "6.5.1.n", "6.6.-.-", "6.6.-.n", "6.6.n.n", "6.6.1.-", "6.6.1.n",
+  "5.1.99.n", "5.1.n.n", "5.2.-.-", "5.2.1.-", "5.2.1.n", "5.2.n.n",
+  "5.3.-.-", "5.3.1.-", "5.3.1.n", "5.3.2.-", "5.3.2.n", "5.3.3.-",
+  "5.3.3.n", "5.3.4.-", "5.3.4.n", "5.3.99.-", "5.3.99.n", "5.3.n.n",
+  "5.4.-.-", "5.4.1.-", "5.4.1.n", "5.4.2.-", "5.4.2.n", "5.4.3.-",
+  "5.4.3.n", "5.4.4.-", "5.4.4.n", "5.4.99.-", "5.4.99.n", "5.4.n.n",
+  "5.5.-.-", "5.5.1.-", "5.5.1.n", "5.5.n.n", "5.99.-.-", "5.99.1.-",
+  "5.99.1.n", "5.99.n.n", "5.n.n.n", "6.-.-.-", "6.1.-.-", "6.1.1.-",
+  "6.1.1.n", "6.1.n.n", "6.2.-.-", "6.2.1.-", "6.2.1.n", "6.2.n.n",
+  "6.3.-.-", "6.3.1.-", "6.3.1.n", "6.3.2.-", "6.3.2.n", "6.3.3.-",
+  "6.3.3.n", "6.3.4.-", "6.3.4.n", "6.3.5.-", "6.3.5.n", "6.3.n.n",
+  "6.4.-.-", "6.4.1.-", "6.4.1.n", "6.4.n.n", "6.5.-.-", "6.5.1.-",
+  "6.5.1.n", "6.5.n.n", "6.6.-.-", "6.6.1.-", "6.6.1.n", "6.6.n.n",
+  "6.n.n.n",
   NULL
 };
 
 static CharPtr ecnum_specif [] = {
-  "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4", "1.1.1.5", "1.1.1.6",
-  "1.1.1.7", "1.1.1.8", "1.1.1.9", "1.1.1.10", "1.1.1.11", "1.1.1.12",
+  "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4", "1.1.1.6", "1.1.1.7",
+  "1.1.1.8", "1.1.1.9", "1.1.1.10", "1.1.1.11", "1.1.1.12",
   "1.1.1.13", "1.1.1.14", "1.1.1.15", "1.1.1.16", "1.1.1.17",
   "1.1.1.18", "1.1.1.19", "1.1.1.20", "1.1.1.21", "1.1.1.22",
   "1.1.1.23", "1.1.1.24", "1.1.1.25", "1.1.1.26", "1.1.1.27",
@@ -15875,485 +16681,516 @@ static CharPtr ecnum_specif [] = {
   "1.1.1.282", "1.1.1.283", "1.1.1.284", "1.1.1.285", "1.1.1.286",
   "1.1.1.287", "1.1.1.288", "1.1.1.289", "1.1.1.290", "1.1.1.291",
   "1.1.1.292", "1.1.1.294", "1.1.1.295", "1.1.1.296", "1.1.1.297",
-  "1.1.2.2", "1.1.2.3", "1.1.2.4", "1.1.2.5", "1.1.3.3", "1.1.3.4",
-  "1.1.3.5", "1.1.3.6", "1.1.3.7", "1.1.3.8", "1.1.3.9", "1.1.3.10",
-  "1.1.3.11", "1.1.3.12", "1.1.3.13", "1.1.3.14", "1.1.3.15",
-  "1.1.3.16", "1.1.3.17", "1.1.3.18", "1.1.3.19", "1.1.3.20",
-  "1.1.3.21", "1.1.3.23", "1.1.3.27", "1.1.3.28", "1.1.3.29",
-  "1.1.3.30", "1.1.3.37", "1.1.3.38", "1.1.3.39", "1.1.3.40",
-  "1.1.3.41", "1.1.4.1", "1.1.4.2", "1.1.5.2", "1.1.5.3", "1.1.99.1",
-  "1.1.99.2", "1.1.99.3", "1.1.99.4", "1.1.99.6", "1.1.99.7",
-  "1.1.99.8", "1.1.99.9", "1.1.99.10", "1.1.99.11", "1.1.99.12",
-  "1.1.99.13", "1.1.99.14", "1.1.99.16", "1.1.99.18", "1.1.99.20",
-  "1.1.99.21", "1.1.99.22", "1.1.99.23", "1.1.99.24", "1.1.99.25",
-  "1.1.99.26", "1.1.99.27", "1.1.99.28", "1.1.99.29", "1.1.99.30",
-  "1.1.99.31", "1.1.99.32", "1.2.1.2", "1.2.1.3", "1.2.1.4", "1.2.1.5",
-  "1.2.1.7", "1.2.1.8", "1.2.1.9", "1.2.1.10", "1.2.1.11", "1.2.1.12",
-  "1.2.1.13", "1.2.1.15", "1.2.1.16", "1.2.1.17", "1.2.1.18",
-  "1.2.1.19", "1.2.1.20", "1.2.1.21", "1.2.1.22", "1.2.1.23",
-  "1.2.1.24", "1.2.1.25", "1.2.1.26", "1.2.1.27", "1.2.1.28",
-  "1.2.1.29", "1.2.1.30", "1.2.1.31", "1.2.1.32", "1.2.1.33",
-  "1.2.1.36", "1.2.1.38", "1.2.1.39", "1.2.1.40", "1.2.1.41",
-  "1.2.1.42", "1.2.1.43", "1.2.1.44", "1.2.1.45", "1.2.1.46",
-  "1.2.1.47", "1.2.1.48", "1.2.1.49", "1.2.1.50", "1.2.1.51",
-  "1.2.1.52", "1.2.1.53", "1.2.1.54", "1.2.1.57", "1.2.1.58",
-  "1.2.1.59", "1.2.1.60", "1.2.1.61", "1.2.1.62", "1.2.1.63",
-  "1.2.1.64", "1.2.1.65", "1.2.1.66", "1.2.1.67", "1.2.1.68",
-  "1.2.1.69", "1.2.1.70", "1.2.1.71", "1.2.1.72", "1.2.1.73", "1.2.2.1",
-  "1.2.2.2", "1.2.2.3", "1.2.2.4", "1.2.3.1", "1.2.3.3", "1.2.3.4",
-  "1.2.3.5", "1.2.3.6", "1.2.3.7", "1.2.3.8", "1.2.3.9", "1.2.3.11",
-  "1.2.3.13", "1.2.3.14", "1.2.4.1", "1.2.4.2", "1.2.4.4", "1.2.7.1",
-  "1.2.7.2", "1.2.7.3", "1.2.7.4", "1.2.7.5", "1.2.7.6", "1.2.7.7",
-  "1.2.7.8", "1.2.99.2", "1.2.99.3", "1.2.99.4", "1.2.99.5", "1.2.99.6",
-  "1.2.99.7", "1.3.1.1", "1.3.1.2", "1.3.1.3", "1.3.1.4", "1.3.1.5",
-  "1.3.1.6", "1.3.1.7", "1.3.1.8", "1.3.1.9", "1.3.1.10", "1.3.1.11",
-  "1.3.1.12", "1.3.1.13", "1.3.1.14", "1.3.1.15", "1.3.1.16",
-  "1.3.1.17", "1.3.1.18", "1.3.1.19", "1.3.1.20", "1.3.1.21",
-  "1.3.1.22", "1.3.1.24", "1.3.1.25", "1.3.1.26", "1.3.1.27",
-  "1.3.1.28", "1.3.1.29", "1.3.1.30", "1.3.1.31", "1.3.1.32",
-  "1.3.1.33", "1.3.1.34", "1.3.1.35", "1.3.1.36", "1.3.1.37",
-  "1.3.1.38", "1.3.1.39", "1.3.1.40", "1.3.1.41", "1.3.1.42",
-  "1.3.1.43", "1.3.1.44", "1.3.1.45", "1.3.1.46", "1.3.1.47",
-  "1.3.1.48", "1.3.1.49", "1.3.1.51", "1.3.1.52", "1.3.1.53",
-  "1.3.1.54", "1.3.1.56", "1.3.1.57", "1.3.1.58", "1.3.1.60",
-  "1.3.1.62", "1.3.1.63", "1.3.1.64", "1.3.1.65", "1.3.1.66",
-  "1.3.1.67", "1.3.1.68", "1.3.1.69", "1.3.1.70", "1.3.1.71",
-  "1.3.1.72", "1.3.1.73", "1.3.1.74", "1.3.1.75", "1.3.1.76",
-  "1.3.1.77", "1.3.1.78", "1.3.1.79", "1.3.1.80", "1.3.1.81",
-  "1.3.1.82", "1.3.2.3", "1.3.3.1", "1.3.3.3", "1.3.3.4", "1.3.3.5",
-  "1.3.3.6", "1.3.3.7", "1.3.3.8", "1.3.3.9", "1.3.3.10", "1.3.3.11",
-  "1.3.3.12", "1.3.5.1", "1.3.5.2", "1.3.7.1", "1.3.7.2", "1.3.7.3",
-  "1.3.7.4", "1.3.7.5", "1.3.7.6", "1.3.99.1", "1.3.99.2", "1.3.99.3",
-  "1.3.99.4", "1.3.99.5", "1.3.99.6", "1.3.99.7", "1.3.99.8",
-  "1.3.99.10", "1.3.99.12", "1.3.99.13", "1.3.99.14", "1.3.99.15",
-  "1.3.99.16", "1.3.99.17", "1.3.99.18", "1.3.99.19", "1.3.99.20",
-  "1.3.99.21", "1.3.99.22", "1.3.99.23", "1.3.99.24", "1.3.99.25",
-  "1.4.1.1", "1.4.1.2", "1.4.1.3", "1.4.1.4", "1.4.1.5", "1.4.1.7",
-  "1.4.1.8", "1.4.1.9", "1.4.1.10", "1.4.1.11", "1.4.1.12", "1.4.1.13",
-  "1.4.1.14", "1.4.1.15", "1.4.1.16", "1.4.1.17", "1.4.1.18",
-  "1.4.1.19", "1.4.1.20", "1.4.1.21", "1.4.2.1", "1.4.3.1", "1.4.3.2",
-  "1.4.3.3", "1.4.3.4", "1.4.3.5", "1.4.3.7", "1.4.3.8", "1.4.3.10",
-  "1.4.3.11", "1.4.3.12", "1.4.3.13", "1.4.3.14", "1.4.3.15",
-  "1.4.3.16", "1.4.3.19", "1.4.3.20", "1.4.3.21", "1.4.3.22", "1.4.4.2",
-  "1.4.7.1", "1.4.99.1", "1.4.99.2", "1.4.99.3", "1.4.99.4", "1.4.99.5",
+  "1.1.1.298", "1.1.1.299", "1.1.1.300", "1.1.1.301", "1.1.1.302",
+  "1.1.1.303", "1.1.1.304", "1.1.2.2", "1.1.2.3", "1.1.2.4",
+  "1.1.2.5", "1.1.3.3", "1.1.3.4", "1.1.3.5", "1.1.3.6", "1.1.3.7",
+  "1.1.3.8", "1.1.3.9", "1.1.3.10", "1.1.3.11", "1.1.3.12",
+  "1.1.3.13", "1.1.3.14", "1.1.3.15", "1.1.3.16", "1.1.3.17",
+  "1.1.3.18", "1.1.3.19", "1.1.3.20", "1.1.3.21", "1.1.3.23",
+  "1.1.3.27", "1.1.3.28", "1.1.3.29", "1.1.3.30", "1.1.3.37",
+  "1.1.3.38", "1.1.3.39", "1.1.3.40", "1.1.3.41", "1.1.4.1",
+  "1.1.4.2", "1.1.5.2", "1.1.5.3", "1.1.5.4", "1.1.5.5", "1.1.5.6",
+  "1.1.5.7", "1.1.99.1", "1.1.99.2", "1.1.99.3", "1.1.99.4",
+  "1.1.99.6", "1.1.99.7", "1.1.99.8", "1.1.99.9", "1.1.99.10",
+  "1.1.99.11", "1.1.99.12", "1.1.99.13", "1.1.99.14", "1.1.99.18",
+  "1.1.99.20", "1.1.99.21", "1.1.99.22", "1.1.99.23", "1.1.99.24",
+  "1.1.99.25", "1.1.99.26", "1.1.99.27", "1.1.99.28", "1.1.99.29",
+  "1.1.99.30", "1.1.99.31", "1.1.99.32", "1.1.99.33", "1.2.1.2",
+  "1.2.1.3", "1.2.1.4", "1.2.1.5", "1.2.1.7", "1.2.1.8", "1.2.1.9",
+  "1.2.1.10", "1.2.1.11", "1.2.1.12", "1.2.1.13", "1.2.1.15",
+  "1.2.1.16", "1.2.1.17", "1.2.1.18", "1.2.1.19", "1.2.1.20",
+  "1.2.1.21", "1.2.1.22", "1.2.1.23", "1.2.1.24", "1.2.1.25",
+  "1.2.1.26", "1.2.1.27", "1.2.1.28", "1.2.1.29", "1.2.1.30",
+  "1.2.1.31", "1.2.1.32", "1.2.1.33", "1.2.1.36", "1.2.1.38",
+  "1.2.1.39", "1.2.1.40", "1.2.1.41", "1.2.1.42", "1.2.1.43",
+  "1.2.1.44", "1.2.1.45", "1.2.1.46", "1.2.1.47", "1.2.1.48",
+  "1.2.1.49", "1.2.1.50", "1.2.1.51", "1.2.1.52", "1.2.1.53",
+  "1.2.1.54", "1.2.1.57", "1.2.1.58", "1.2.1.59", "1.2.1.60",
+  "1.2.1.61", "1.2.1.62", "1.2.1.63", "1.2.1.64", "1.2.1.65",
+  "1.2.1.66", "1.2.1.67", "1.2.1.68", "1.2.1.69", "1.2.1.70",
+  "1.2.1.71", "1.2.1.72", "1.2.1.73", "1.2.1.74", "1.2.1.75",
+  "1.2.1.76", "1.2.1.77", "1.2.1.78", "1.2.2.1", "1.2.2.2", "1.2.2.3",
+  "1.2.2.4", "1.2.3.1", "1.2.3.3", "1.2.3.4", "1.2.3.5", "1.2.3.6",
+  "1.2.3.7", "1.2.3.8", "1.2.3.9", "1.2.3.11", "1.2.3.13", "1.2.3.14",
+  "1.2.4.1", "1.2.4.2", "1.2.4.4", "1.2.7.1", "1.2.7.2", "1.2.7.3",
+  "1.2.7.4", "1.2.7.5", "1.2.7.6", "1.2.7.7", "1.2.7.8", "1.2.99.2",
+  "1.2.99.3", "1.2.99.4", "1.2.99.5", "1.2.99.6", "1.2.99.7",
+  "1.3.1.1", "1.3.1.2", "1.3.1.3", "1.3.1.4", "1.3.1.5", "1.3.1.6",
+  "1.3.1.7", "1.3.1.8", "1.3.1.9", "1.3.1.10", "1.3.1.11", "1.3.1.12",
+  "1.3.1.13", "1.3.1.14", "1.3.1.15", "1.3.1.16", "1.3.1.17",
+  "1.3.1.18", "1.3.1.19", "1.3.1.20", "1.3.1.21", "1.3.1.22",
+  "1.3.1.24", "1.3.1.25", "1.3.1.26", "1.3.1.27", "1.3.1.28",
+  "1.3.1.29", "1.3.1.30", "1.3.1.31", "1.3.1.32", "1.3.1.33",
+  "1.3.1.34", "1.3.1.35", "1.3.1.36", "1.3.1.37", "1.3.1.38",
+  "1.3.1.39", "1.3.1.40", "1.3.1.41", "1.3.1.42", "1.3.1.43",
+  "1.3.1.44", "1.3.1.45", "1.3.1.46", "1.3.1.47", "1.3.1.48",
+  "1.3.1.49", "1.3.1.51", "1.3.1.52", "1.3.1.53", "1.3.1.54",
+  "1.3.1.56", "1.3.1.57", "1.3.1.58", "1.3.1.60", "1.3.1.62",
+  "1.3.1.63", "1.3.1.64", "1.3.1.65", "1.3.1.66", "1.3.1.67",
+  "1.3.1.68", "1.3.1.69", "1.3.1.70", "1.3.1.71", "1.3.1.72",
+  "1.3.1.73", "1.3.1.74", "1.3.1.75", "1.3.1.76", "1.3.1.77",
+  "1.3.1.78", "1.3.1.79", "1.3.1.80", "1.3.1.81", "1.3.1.82",
+  "1.3.1.83", "1.3.1.84", "1.3.2.3", "1.3.3.1", "1.3.3.3", "1.3.3.4",
+  "1.3.3.5", "1.3.3.6", "1.3.3.7", "1.3.3.8", "1.3.3.9", "1.3.3.10",
+  "1.3.3.11", "1.3.3.12", "1.3.5.1", "1.3.5.2", "1.3.7.1", "1.3.7.2",
+  "1.3.7.3", "1.3.7.4", "1.3.7.5", "1.3.7.6", "1.3.99.1", "1.3.99.2",
+  "1.3.99.3", "1.3.99.4", "1.3.99.5", "1.3.99.6", "1.3.99.7",
+  "1.3.99.8", "1.3.99.10", "1.3.99.12", "1.3.99.13", "1.3.99.14",
+  "1.3.99.15", "1.3.99.16", "1.3.99.17", "1.3.99.18", "1.3.99.19",
+  "1.3.99.20", "1.3.99.21", "1.3.99.22", "1.3.99.23", "1.3.99.24",
+  "1.3.99.25", "1.4.1.1", "1.4.1.2", "1.4.1.3", "1.4.1.4", "1.4.1.5",
+  "1.4.1.7", "1.4.1.8", "1.4.1.9", "1.4.1.10", "1.4.1.11", "1.4.1.12",
+  "1.4.1.13", "1.4.1.14", "1.4.1.15", "1.4.1.16", "1.4.1.17",
+  "1.4.1.18", "1.4.1.19", "1.4.1.20", "1.4.1.21", "1.4.2.1",
+  "1.4.3.1", "1.4.3.2", "1.4.3.3", "1.4.3.4", "1.4.3.5", "1.4.3.7",
+  "1.4.3.8", "1.4.3.10", "1.4.3.11", "1.4.3.12", "1.4.3.13",
+  "1.4.3.14", "1.4.3.15", "1.4.3.16", "1.4.3.19", "1.4.3.20",
+  "1.4.3.21", "1.4.3.22", "1.4.3.23", "1.4.4.2", "1.4.5.1", "1.4.7.1",
+  "1.4.99.1", "1.4.99.2", "1.4.99.3", "1.4.99.4", "1.4.99.5",
   "1.5.1.1", "1.5.1.2", "1.5.1.3", "1.5.1.5", "1.5.1.6", "1.5.1.7",
-  "1.5.1.8", "1.5.1.9", "1.5.1.10", "1.5.1.11", "1.5.1.12", "1.5.1.15",
-  "1.5.1.16", "1.5.1.17", "1.5.1.18", "1.5.1.19", "1.5.1.20",
-  "1.5.1.21", "1.5.1.22", "1.5.1.23", "1.5.1.24", "1.5.1.25",
-  "1.5.1.26", "1.5.1.27", "1.5.1.28", "1.5.1.29", "1.5.1.30",
-  "1.5.1.31", "1.5.1.32", "1.5.1.33", "1.5.1.34", "1.5.3.1", "1.5.3.2",
-  "1.5.3.4", "1.5.3.5", "1.5.3.6", "1.5.3.7", "1.5.3.10", "1.5.3.11",
-  "1.5.3.12", "1.5.4.1", "1.5.5.1", "1.5.7.1", "1.5.8.1", "1.5.8.2",
-  "1.5.99.1", "1.5.99.2", "1.5.99.3", "1.5.99.4", "1.5.99.5",
-  "1.5.99.6", "1.5.99.8", "1.5.99.9", "1.5.99.11", "1.5.99.12",
-  "1.6.1.1", "1.6.1.2", "1.6.2.2", "1.6.2.4", "1.6.2.5", "1.6.2.6",
-  "1.6.3.1", "1.6.5.2", "1.6.5.3", "1.6.5.4", "1.6.5.5", "1.6.5.6",
-  "1.6.5.7", "1.6.6.9", "1.6.99.1", "1.6.99.3", "1.6.99.5", "1.6.99.6",
-  "1.7.1.1", "1.7.1.2", "1.7.1.3", "1.7.1.4", "1.7.1.5", "1.7.1.6",
-  "1.7.1.7", "1.7.1.9", "1.7.1.10", "1.7.1.11", "1.7.1.12", "1.7.1.13",
+  "1.5.1.8", "1.5.1.9", "1.5.1.10", "1.5.1.11", "1.5.1.12",
+  "1.5.1.15", "1.5.1.16", "1.5.1.17", "1.5.1.18", "1.5.1.19",
+  "1.5.1.20", "1.5.1.21", "1.5.1.22", "1.5.1.23", "1.5.1.24",
+  "1.5.1.25", "1.5.1.26", "1.5.1.27", "1.5.1.28", "1.5.1.29",
+  "1.5.1.30", "1.5.1.31", "1.5.1.32", "1.5.1.33", "1.5.1.34",
+  "1.5.3.1", "1.5.3.2", "1.5.3.4", "1.5.3.5", "1.5.3.6", "1.5.3.7",
+  "1.5.3.10", "1.5.3.11", "1.5.3.12", "1.5.3.13", "1.5.3.14",
+  "1.5.3.15", "1.5.3.16", "1.5.3.17", "1.5.4.1", "1.5.5.1", "1.5.7.1",
+  "1.5.8.1", "1.5.8.2", "1.5.99.1", "1.5.99.2", "1.5.99.3",
+  "1.5.99.4", "1.5.99.5", "1.5.99.6", "1.5.99.8", "1.5.99.9",
+  "1.5.99.11", "1.5.99.12", "1.5.99.13", "1.6.1.1", "1.6.1.2",
+  "1.6.2.2", "1.6.2.4", "1.6.2.5", "1.6.2.6", "1.6.3.1", "1.6.5.2",
+  "1.6.5.3", "1.6.5.4", "1.6.5.5", "1.6.5.6", "1.6.5.7", "1.6.6.9",
+  "1.6.99.1", "1.6.99.3", "1.6.99.5", "1.6.99.6", "1.7.1.1",
+  "1.7.1.2", "1.7.1.3", "1.7.1.4", "1.7.1.5", "1.7.1.6", "1.7.1.7",
+  "1.7.1.9", "1.7.1.10", "1.7.1.11", "1.7.1.12", "1.7.1.13",
   "1.7.2.1", "1.7.2.2", "1.7.2.3", "1.7.3.1", "1.7.3.2", "1.7.3.3",
-  "1.7.3.4", "1.7.3.5", "1.7.7.1", "1.7.7.2", "1.7.99.1", "1.7.99.4",
-  "1.7.99.6", "1.7.99.7", "1.7.99.8", "1.8.1.2", "1.8.1.3", "1.8.1.4",
-  "1.8.1.5", "1.8.1.6", "1.8.1.7", "1.8.1.8", "1.8.1.9", "1.8.1.10",
-  "1.8.1.11", "1.8.1.12", "1.8.1.13", "1.8.1.14", "1.8.1.15", "1.8.2.1",
-  "1.8.2.2", "1.8.3.1", "1.8.3.2", "1.8.3.3", "1.8.3.4", "1.8.3.5",
-  "1.8.4.1", "1.8.4.2", "1.8.4.3", "1.8.4.4", "1.8.4.7", "1.8.4.8",
-  "1.8.4.9", "1.8.4.10", "1.8.4.11", "1.8.4.12", "1.8.4.13", "1.8.4.14",
-  "1.8.5.1", "1.8.5.2", "1.8.7.1", "1.8.98.1", "1.8.98.2", "1.8.99.1",
-  "1.8.99.2", "1.8.99.3", "1.9.3.1", "1.9.6.1", "1.9.99.1", "1.10.1.1",
-  "1.10.2.1", "1.10.2.2", "1.10.3.1", "1.10.3.2", "1.10.3.3",
-  "1.10.3.4", "1.10.3.5", "1.10.3.6", "1.10.99.1", "1.10.99.2",
-  "1.10.99.3", "1.11.1.1", "1.11.1.2", "1.11.1.3", "1.11.1.5",
-  "1.11.1.6", "1.11.1.7", "1.11.1.8", "1.11.1.9", "1.11.1.10",
-  "1.11.1.11", "1.11.1.12", "1.11.1.13", "1.11.1.14", "1.11.1.15",
-  "1.11.1.16", "1.12.1.2", "1.12.1.3", "1.12.2.1", "1.12.5.1",
-  "1.12.7.2", "1.12.98.1", "1.12.98.2", "1.12.98.3", "1.12.99.6",
-  "1.13.11.1", "1.13.11.2", "1.13.11.3", "1.13.11.4", "1.13.11.5",
-  "1.13.11.6", "1.13.11.8", "1.13.11.9", "1.13.11.10", "1.13.11.11",
-  "1.13.11.12", "1.13.11.13", "1.13.11.14", "1.13.11.15", "1.13.11.16",
-  "1.13.11.17", "1.13.11.18", "1.13.11.19", "1.13.11.20", "1.13.11.22",
-  "1.13.11.23", "1.13.11.24", "1.13.11.25", "1.13.11.26", "1.13.11.27",
-  "1.13.11.28", "1.13.11.29", "1.13.11.30", "1.13.11.31", "1.13.11.32",
-  "1.13.11.33", "1.13.11.34", "1.13.11.35", "1.13.11.36", "1.13.11.37",
-  "1.13.11.38", "1.13.11.39", "1.13.11.40", "1.13.11.41", "1.13.11.43",
-  "1.13.11.44", "1.13.11.45", "1.13.11.46", "1.13.11.47", "1.13.11.48",
-  "1.13.11.49", "1.13.11.50", "1.13.11.51", "1.13.11.52", "1.13.11.53",
-  "1.13.11.54", "1.13.11.55", "1.13.12.1", "1.13.12.2", "1.13.12.3",
-  "1.13.12.4", "1.13.12.5", "1.13.12.6", "1.13.12.7", "1.13.12.8",
-  "1.13.12.9", "1.13.12.12", "1.13.12.13", "1.13.12.14", "1.13.12.15",
-  "1.13.99.1", "1.13.99.3", "1.14.11.1", "1.14.11.2", "1.14.11.3",
-  "1.14.11.4", "1.14.11.6", "1.14.11.7", "1.14.11.8", "1.14.11.9",
-  "1.14.11.10", "1.14.11.11", "1.14.11.12", "1.14.11.13", "1.14.11.14",
-  "1.14.11.15", "1.14.11.16", "1.14.11.17", "1.14.11.18", "1.14.11.19",
-  "1.14.11.20", "1.14.11.21", "1.14.11.22", "1.14.11.23", "1.14.11.24",
-  "1.14.11.25", "1.14.11.26", "1.14.11.27", "1.14.11.28", "1.14.12.1",
-  "1.14.12.3", "1.14.12.4", "1.14.12.5", "1.14.12.7", "1.14.12.8",
-  "1.14.12.9", "1.14.12.10", "1.14.12.11", "1.14.12.12", "1.14.12.13",
-  "1.14.12.14", "1.14.12.15", "1.14.12.16", "1.14.12.17", "1.14.12.18",
-  "1.14.12.19", "1.14.12.20", "1.14.13.1", "1.14.13.2", "1.14.13.3",
-  "1.14.13.4", "1.14.13.5", "1.14.13.6", "1.14.13.7", "1.14.13.8",
-  "1.14.13.9", "1.14.13.10", "1.14.13.11", "1.14.13.12", "1.14.13.13",
-  "1.14.13.14", "1.14.13.15", "1.14.13.16", "1.14.13.17", "1.14.13.18",
-  "1.14.13.19", "1.14.13.20", "1.14.13.21", "1.14.13.22", "1.14.13.23",
-  "1.14.13.24", "1.14.13.25", "1.14.13.26", "1.14.13.27", "1.14.13.28",
-  "1.14.13.29", "1.14.13.30", "1.14.13.31", "1.14.13.32", "1.14.13.33",
-  "1.14.13.34", "1.14.13.35", "1.14.13.36", "1.14.13.37", "1.14.13.38",
-  "1.14.13.39", "1.14.13.40", "1.14.13.41", "1.14.13.42", "1.14.13.43",
-  "1.14.13.44", "1.14.13.46", "1.14.13.47", "1.14.13.48", "1.14.13.49",
-  "1.14.13.50", "1.14.13.51", "1.14.13.52", "1.14.13.53", "1.14.13.54",
-  "1.14.13.55", "1.14.13.56", "1.14.13.57", "1.14.13.58", "1.14.13.59",
-  "1.14.13.60", "1.14.13.61", "1.14.13.62", "1.14.13.63", "1.14.13.64",
-  "1.14.13.66", "1.14.13.67", "1.14.13.68", "1.14.13.69", "1.14.13.70",
-  "1.14.13.71", "1.14.13.72", "1.14.13.73", "1.14.13.74", "1.14.13.75",
-  "1.14.13.76", "1.14.13.77", "1.14.13.78", "1.14.13.79", "1.14.13.80",
-  "1.14.13.81", "1.14.13.82", "1.14.13.83", "1.14.13.84", "1.14.13.85",
-  "1.14.13.86", "1.14.13.87", "1.14.13.88", "1.14.13.89", "1.14.13.90",
-  "1.14.13.91", "1.14.13.92", "1.14.13.93", "1.14.13.94", "1.14.13.95",
-  "1.14.13.96", "1.14.13.97", "1.14.13.98", "1.14.13.99", "1.14.13.100",
-  "1.14.13.101", "1.14.13.102", "1.14.13.103", "1.14.13.104",
-  "1.14.13.105", "1.14.13.106", "1.14.13.107", "1.14.14.1", "1.14.14.3",
-  "1.14.14.5", "1.14.14.6", "1.14.15.1", "1.14.15.2", "1.14.15.3",
-  "1.14.15.4", "1.14.15.5", "1.14.15.6", "1.14.15.7", "1.14.16.1",
-  "1.14.16.2", "1.14.16.3", "1.14.16.4", "1.14.16.5", "1.14.16.6",
-  "1.14.17.1", "1.14.17.3", "1.14.17.4", "1.14.18.1", "1.14.18.2",
-  "1.14.19.1", "1.14.19.2", "1.14.19.3", "1.14.19.4", "1.14.19.5",
-  "1.14.19.6", "1.14.20.1", "1.14.21.1", "1.14.21.2", "1.14.21.3",
-  "1.14.21.4", "1.14.21.5", "1.14.21.6", "1.14.21.7", "1.14.99.1",
-  "1.14.99.2", "1.14.99.3", "1.14.99.4", "1.14.99.7", "1.14.99.9",
-  "1.14.99.10", "1.14.99.11", "1.14.99.12", "1.14.99.14", "1.14.99.15",
-  "1.14.99.19", "1.14.99.20", "1.14.99.21", "1.14.99.22", "1.14.99.23",
-  "1.14.99.24", "1.14.99.26", "1.14.99.27", "1.14.99.28", "1.14.99.29",
-  "1.14.99.30", "1.14.99.31", "1.14.99.32", "1.14.99.33", "1.14.99.34",
-  "1.14.99.35", "1.14.99.36", "1.14.99.37", "1.14.99.38", "1.15.1.1",
-  "1.15.1.2", "1.16.1.1", "1.16.1.2", "1.16.1.3", "1.16.1.4",
-  "1.16.1.5", "1.16.1.6", "1.16.1.7", "1.16.1.8", "1.16.3.1",
-  "1.16.8.1", "1.17.1.1", "1.17.1.2", "1.17.1.3", "1.17.1.4",
-  "1.17.1.5", "1.17.3.1", "1.17.3.2", "1.17.3.3", "1.17.4.1",
-  "1.17.4.2", "1.17.5.1", "1.17.7.1", "1.17.99.1", "1.17.99.2",
-  "1.17.99.3", "1.17.99.4", "1.17.99.5", "1.18.1.1", "1.18.1.2",
-  "1.18.1.3", "1.18.1.4", "1.18.6.1", "1.19.6.1", "1.20.1.1",
-  "1.20.4.1", "1.20.4.2", "1.20.98.1", "1.20.99.1", "1.21.3.1",
+  "1.7.3.4", "1.7.3.5", "1.7.5.1", "1.7.7.1", "1.7.7.2", "1.7.99.1",
+  "1.7.99.4", "1.7.99.6", "1.7.99.7", "1.7.99.8", "1.8.1.2",
+  "1.8.1.3", "1.8.1.4", "1.8.1.5", "1.8.1.6", "1.8.1.7", "1.8.1.8",
+  "1.8.1.9", "1.8.1.10", "1.8.1.11", "1.8.1.12", "1.8.1.13",
+  "1.8.1.14", "1.8.1.15", "1.8.1.16", "1.8.2.1", "1.8.2.2", "1.8.3.1",
+  "1.8.3.2", "1.8.3.3", "1.8.3.4", "1.8.3.5", "1.8.4.1", "1.8.4.2",
+  "1.8.4.3", "1.8.4.4", "1.8.4.7", "1.8.4.8", "1.8.4.9", "1.8.4.10",
+  "1.8.4.11", "1.8.4.12", "1.8.4.13", "1.8.4.14", "1.8.5.1",
+  "1.8.5.2", "1.8.7.1", "1.8.98.1", "1.8.98.2", "1.8.99.1",
+  "1.8.99.2", "1.8.99.3", "1.9.3.1", "1.9.6.1", "1.9.99.1",
+  "1.10.1.1", "1.10.2.1", "1.10.2.2", "1.10.3.1", "1.10.3.2",
+  "1.10.3.3", "1.10.3.4", "1.10.3.5", "1.10.3.6", "1.10.99.1",
+  "1.10.99.2", "1.10.99.3", "1.11.1.1", "1.11.1.2", "1.11.1.3",
+  "1.11.1.5", "1.11.1.6", "1.11.1.7", "1.11.1.8", "1.11.1.9",
+  "1.11.1.10", "1.11.1.11", "1.11.1.12", "1.11.1.13", "1.11.1.14",
+  "1.11.1.15", "1.11.1.16", "1.11.1.17", "1.12.1.2", "1.12.1.3",
+  "1.12.2.1", "1.12.5.1", "1.12.7.2", "1.12.98.1", "1.12.98.2",
+  "1.12.98.3", "1.12.99.6", "1.13.11.1", "1.13.11.2", "1.13.11.3",
+  "1.13.11.4", "1.13.11.5", "1.13.11.6", "1.13.11.8", "1.13.11.9",
+  "1.13.11.10", "1.13.11.11", "1.13.11.12", "1.13.11.13",
+  "1.13.11.14", "1.13.11.15", "1.13.11.16", "1.13.11.17",
+  "1.13.11.18", "1.13.11.19", "1.13.11.20", "1.13.11.22",
+  "1.13.11.23", "1.13.11.24", "1.13.11.25", "1.13.11.26",
+  "1.13.11.27", "1.13.11.28", "1.13.11.29", "1.13.11.30",
+  "1.13.11.31", "1.13.11.33", "1.13.11.34", "1.13.11.35",
+  "1.13.11.36", "1.13.11.37", "1.13.11.38", "1.13.11.39",
+  "1.13.11.40", "1.13.11.41", "1.13.11.43", "1.13.11.44",
+  "1.13.11.45", "1.13.11.46", "1.13.11.47", "1.13.11.48",
+  "1.13.11.49", "1.13.11.50", "1.13.11.51", "1.13.11.52",
+  "1.13.11.53", "1.13.11.54", "1.13.11.55", "1.13.11.56", "1.13.12.1",
+  "1.13.12.2", "1.13.12.3", "1.13.12.4", "1.13.12.5", "1.13.12.6",
+  "1.13.12.7", "1.13.12.8", "1.13.12.9", "1.13.12.12", "1.13.12.13",
+  "1.13.12.14", "1.13.12.15", "1.13.12.16", "1.13.12.17", "1.13.99.1",
+  "1.13.99.3", "1.14.11.1", "1.14.11.2", "1.14.11.3", "1.14.11.4",
+  "1.14.11.6", "1.14.11.7", "1.14.11.8", "1.14.11.9", "1.14.11.10",
+  "1.14.11.11", "1.14.11.12", "1.14.11.13", "1.14.11.14",
+  "1.14.11.15", "1.14.11.16", "1.14.11.17", "1.14.11.18",
+  "1.14.11.19", "1.14.11.20", "1.14.11.21", "1.14.11.22",
+  "1.14.11.23", "1.14.11.24", "1.14.11.25", "1.14.11.26",
+  "1.14.11.27", "1.14.11.28", "1.14.12.1", "1.14.12.3", "1.14.12.4",
+  "1.14.12.5", "1.14.12.7", "1.14.12.8", "1.14.12.9", "1.14.12.10",
+  "1.14.12.11", "1.14.12.12", "1.14.12.13", "1.14.12.14",
+  "1.14.12.15", "1.14.12.16", "1.14.12.17", "1.14.12.18",
+  "1.14.12.19", "1.14.12.20", "1.14.12.21", "1.14.13.1", "1.14.13.2",
+  "1.14.13.3", "1.14.13.4", "1.14.13.5", "1.14.13.6", "1.14.13.7",
+  "1.14.13.8", "1.14.13.9", "1.14.13.10", "1.14.13.11", "1.14.13.12",
+  "1.14.13.13", "1.14.13.14", "1.14.13.15", "1.14.13.16",
+  "1.14.13.17", "1.14.13.18", "1.14.13.19", "1.14.13.20",
+  "1.14.13.21", "1.14.13.22", "1.14.13.23", "1.14.13.24",
+  "1.14.13.25", "1.14.13.26", "1.14.13.27", "1.14.13.28",
+  "1.14.13.29", "1.14.13.30", "1.14.13.31", "1.14.13.32",
+  "1.14.13.33", "1.14.13.34", "1.14.13.35", "1.14.13.36",
+  "1.14.13.37", "1.14.13.38", "1.14.13.39", "1.14.13.40",
+  "1.14.13.41", "1.14.13.42", "1.14.13.43", "1.14.13.44",
+  "1.14.13.46", "1.14.13.47", "1.14.13.48", "1.14.13.49",
+  "1.14.13.50", "1.14.13.51", "1.14.13.52", "1.14.13.53",
+  "1.14.13.54", "1.14.13.55", "1.14.13.56", "1.14.13.57",
+  "1.14.13.58", "1.14.13.59", "1.14.13.60", "1.14.13.61",
+  "1.14.13.62", "1.14.13.63", "1.14.13.64", "1.14.13.66",
+  "1.14.13.67", "1.14.13.68", "1.14.13.69", "1.14.13.70",
+  "1.14.13.71", "1.14.13.72", "1.14.13.73", "1.14.13.74",
+  "1.14.13.75", "1.14.13.76", "1.14.13.77", "1.14.13.78",
+  "1.14.13.79", "1.14.13.80", "1.14.13.81", "1.14.13.82",
+  "1.14.13.83", "1.14.13.84", "1.14.13.85", "1.14.13.86",
+  "1.14.13.87", "1.14.13.88", "1.14.13.89", "1.14.13.90",
+  "1.14.13.91", "1.14.13.92", "1.14.13.93", "1.14.13.94",
+  "1.14.13.95", "1.14.13.96", "1.14.13.97", "1.14.13.98",
+  "1.14.13.99", "1.14.13.100", "1.14.13.101", "1.14.13.102",
+  "1.14.13.103", "1.14.13.104", "1.14.13.105", "1.14.13.106",
+  "1.14.13.107", "1.14.13.108", "1.14.13.109", "1.14.13.110",
+  "1.14.13.111", "1.14.13.112", "1.14.13.113", "1.14.14.1",
+  "1.14.14.3", "1.14.14.5", "1.14.14.7", "1.14.15.1", "1.14.15.2",
+  "1.14.15.3", "1.14.15.4", "1.14.15.5", "1.14.15.6", "1.14.15.7",
+  "1.14.15.8", "1.14.16.1", "1.14.16.2", "1.14.16.3", "1.14.16.4",
+  "1.14.16.5", "1.14.16.6", "1.14.17.1", "1.14.17.3", "1.14.17.4",
+  "1.14.18.1", "1.14.18.2", "1.14.19.1", "1.14.19.2", "1.14.19.3",
+  "1.14.19.4", "1.14.19.5", "1.14.19.6", "1.14.20.1", "1.14.21.1",
+  "1.14.21.2", "1.14.21.3", "1.14.21.4", "1.14.21.5", "1.14.21.6",
+  "1.14.21.7", "1.14.99.1", "1.14.99.2", "1.14.99.3", "1.14.99.4",
+  "1.14.99.7", "1.14.99.9", "1.14.99.10", "1.14.99.11", "1.14.99.12",
+  "1.14.99.14", "1.14.99.15", "1.14.99.19", "1.14.99.20",
+  "1.14.99.21", "1.14.99.22", "1.14.99.23", "1.14.99.24",
+  "1.14.99.26", "1.14.99.27", "1.14.99.28", "1.14.99.29",
+  "1.14.99.30", "1.14.99.31", "1.14.99.32", "1.14.99.33",
+  "1.14.99.34", "1.14.99.35", "1.14.99.36", "1.14.99.37",
+  "1.14.99.38", "1.14.99.39", "1.14.99.40", "1.15.1.1", "1.15.1.2",
+  "1.16.1.1", "1.16.1.2", "1.16.1.3", "1.16.1.4", "1.16.1.5",
+  "1.16.1.6", "1.16.1.7", "1.16.1.8", "1.16.3.1", "1.16.8.1",
+  "1.17.1.1", "1.17.1.2", "1.17.1.3", "1.17.1.4", "1.17.1.5",
+  "1.17.3.1", "1.17.3.2", "1.17.3.3", "1.17.4.1", "1.17.4.2",
+  "1.17.5.1", "1.17.7.1", "1.17.99.1", "1.17.99.2", "1.17.99.3",
+  "1.17.99.4", "1.17.99.5", "1.18.1.1", "1.18.1.2", "1.18.1.3",
+  "1.18.1.4", "1.18.6.1", "1.19.6.1", "1.20.1.1", "1.20.4.1",
+  "1.20.4.2", "1.20.4.3", "1.20.98.1", "1.20.99.1", "1.21.3.1",
   "1.21.3.2", "1.21.3.3", "1.21.3.4", "1.21.3.5", "1.21.3.6",
   "1.21.4.1", "1.21.4.2", "1.21.4.3", "1.21.4.4", "1.21.99.1",
-  "1.97.1.1", "1.97.1.2", "1.97.1.3", "1.97.1.4", "1.97.1.8",
-  "1.97.1.9", "1.97.1.10", "1.97.1.11", "2.1.1.1", "2.1.1.2", "2.1.1.3",
-  "2.1.1.4", "2.1.1.5", "2.1.1.6", "2.1.1.7", "2.1.1.8", "2.1.1.9",
-  "2.1.1.10", "2.1.1.11", "2.1.1.12", "2.1.1.13", "2.1.1.14",
-  "2.1.1.15", "2.1.1.16", "2.1.1.17", "2.1.1.18", "2.1.1.19",
-  "2.1.1.20", "2.1.1.21", "2.1.1.22", "2.1.1.25", "2.1.1.26",
-  "2.1.1.27", "2.1.1.28", "2.1.1.29", "2.1.1.31", "2.1.1.32",
-  "2.1.1.33", "2.1.1.34", "2.1.1.35", "2.1.1.36", "2.1.1.37",
-  "2.1.1.38", "2.1.1.39", "2.1.1.40", "2.1.1.41", "2.1.1.42",
-  "2.1.1.43", "2.1.1.44", "2.1.1.45", "2.1.1.46", "2.1.1.47",
-  "2.1.1.48", "2.1.1.49", "2.1.1.50", "2.1.1.51", "2.1.1.52",
-  "2.1.1.53", "2.1.1.54", "2.1.1.55", "2.1.1.56", "2.1.1.57",
-  "2.1.1.59", "2.1.1.60", "2.1.1.61", "2.1.1.62", "2.1.1.63",
-  "2.1.1.64", "2.1.1.65", "2.1.1.66", "2.1.1.67", "2.1.1.68",
-  "2.1.1.69", "2.1.1.70", "2.1.1.71", "2.1.1.72", "2.1.1.74",
-  "2.1.1.75", "2.1.1.76", "2.1.1.77", "2.1.1.78", "2.1.1.79",
-  "2.1.1.80", "2.1.1.82", "2.1.1.83", "2.1.1.84", "2.1.1.85",
-  "2.1.1.86", "2.1.1.87", "2.1.1.88", "2.1.1.89", "2.1.1.90",
-  "2.1.1.91", "2.1.1.94", "2.1.1.95", "2.1.1.96", "2.1.1.97",
-  "2.1.1.98", "2.1.1.99", "2.1.1.100", "2.1.1.101", "2.1.1.102",
-  "2.1.1.103", "2.1.1.104", "2.1.1.105", "2.1.1.106", "2.1.1.107",
-  "2.1.1.108", "2.1.1.109", "2.1.1.110", "2.1.1.111", "2.1.1.112",
-  "2.1.1.113", "2.1.1.114", "2.1.1.115", "2.1.1.116", "2.1.1.117",
-  "2.1.1.118", "2.1.1.119", "2.1.1.120", "2.1.1.121", "2.1.1.122",
-  "2.1.1.123", "2.1.1.124", "2.1.1.125", "2.1.1.126", "2.1.1.127",
-  "2.1.1.128", "2.1.1.129", "2.1.1.130", "2.1.1.131", "2.1.1.132",
-  "2.1.1.133", "2.1.1.136", "2.1.1.137", "2.1.1.139", "2.1.1.140",
-  "2.1.1.141", "2.1.1.142", "2.1.1.143", "2.1.1.144", "2.1.1.145",
-  "2.1.1.146", "2.1.1.147", "2.1.1.148", "2.1.1.149", "2.1.1.150",
-  "2.1.1.151", "2.1.1.152", "2.1.1.153", "2.1.1.154", "2.1.1.155",
-  "2.1.1.156", "2.1.1.157", "2.1.1.158", "2.1.1.159", "2.1.1.160",
-  "2.1.1.161", "2.1.1.162", "2.1.2.1", "2.1.2.2", "2.1.2.3", "2.1.2.4",
-  "2.1.2.5", "2.1.2.7", "2.1.2.8", "2.1.2.9", "2.1.2.10", "2.1.2.11",
-  "2.1.3.1", "2.1.3.2", "2.1.3.3", "2.1.3.5", "2.1.3.6", "2.1.3.7",
-  "2.1.3.8", "2.1.3.9", "2.1.3.10", "2.1.3.11", "2.1.4.1", "2.1.4.2",
-  "2.2.1.1", "2.2.1.2", "2.2.1.3", "2.2.1.4", "2.2.1.5", "2.2.1.6",
-  "2.2.1.7", "2.2.1.8", "2.2.1.9", "2.3.1.1", "2.3.1.2", "2.3.1.3",
-  "2.3.1.4", "2.3.1.5", "2.3.1.6", "2.3.1.7", "2.3.1.8", "2.3.1.9",
-  "2.3.1.10", "2.3.1.11", "2.3.1.12", "2.3.1.13", "2.3.1.14",
-  "2.3.1.15", "2.3.1.16", "2.3.1.17", "2.3.1.18", "2.3.1.19",
-  "2.3.1.20", "2.3.1.21", "2.3.1.22", "2.3.1.23", "2.3.1.24",
-  "2.3.1.25", "2.3.1.26", "2.3.1.27", "2.3.1.28", "2.3.1.29",
-  "2.3.1.30", "2.3.1.31", "2.3.1.32", "2.3.1.33", "2.3.1.34",
-  "2.3.1.35", "2.3.1.36", "2.3.1.37", "2.3.1.38", "2.3.1.39",
-  "2.3.1.40", "2.3.1.41", "2.3.1.42", "2.3.1.43", "2.3.1.44",
-  "2.3.1.45", "2.3.1.46", "2.3.1.47", "2.3.1.48", "2.3.1.49",
-  "2.3.1.50", "2.3.1.51", "2.3.1.52", "2.3.1.53", "2.3.1.54",
-  "2.3.1.56", "2.3.1.57", "2.3.1.58", "2.3.1.59", "2.3.1.60",
-  "2.3.1.61", "2.3.1.62", "2.3.1.63", "2.3.1.64", "2.3.1.65",
-  "2.3.1.66", "2.3.1.67", "2.3.1.68", "2.3.1.69", "2.3.1.71",
-  "2.3.1.72", "2.3.1.73", "2.3.1.74", "2.3.1.75", "2.3.1.76",
-  "2.3.1.77", "2.3.1.78", "2.3.1.79", "2.3.1.80", "2.3.1.81",
-  "2.3.1.82", "2.3.1.83", "2.3.1.84", "2.3.1.85", "2.3.1.86",
-  "2.3.1.87", "2.3.1.88", "2.3.1.89", "2.3.1.90", "2.3.1.91",
-  "2.3.1.92", "2.3.1.93", "2.3.1.94", "2.3.1.95", "2.3.1.96",
-  "2.3.1.97", "2.3.1.98", "2.3.1.99", "2.3.1.100", "2.3.1.101",
-  "2.3.1.102", "2.3.1.103", "2.3.1.104", "2.3.1.105", "2.3.1.106",
-  "2.3.1.107", "2.3.1.108", "2.3.1.109", "2.3.1.110", "2.3.1.111",
-  "2.3.1.112", "2.3.1.113", "2.3.1.114", "2.3.1.115", "2.3.1.116",
-  "2.3.1.117", "2.3.1.118", "2.3.1.119", "2.3.1.121", "2.3.1.122",
-  "2.3.1.123", "2.3.1.125", "2.3.1.126", "2.3.1.127", "2.3.1.128",
-  "2.3.1.129", "2.3.1.130", "2.3.1.131", "2.3.1.132", "2.3.1.133",
-  "2.3.1.134", "2.3.1.135", "2.3.1.136", "2.3.1.137", "2.3.1.138",
-  "2.3.1.139", "2.3.1.140", "2.3.1.141", "2.3.1.142", "2.3.1.143",
-  "2.3.1.144", "2.3.1.145", "2.3.1.146", "2.3.1.147", "2.3.1.148",
-  "2.3.1.149", "2.3.1.150", "2.3.1.151", "2.3.1.152", "2.3.1.153",
-  "2.3.1.154", "2.3.1.155", "2.3.1.156", "2.3.1.157", "2.3.1.158",
-  "2.3.1.159", "2.3.1.160", "2.3.1.161", "2.3.1.162", "2.3.1.163",
-  "2.3.1.164", "2.3.1.165", "2.3.1.166", "2.3.1.167", "2.3.1.168",
-  "2.3.1.169", "2.3.1.170", "2.3.1.171", "2.3.1.172", "2.3.1.173",
-  "2.3.1.174", "2.3.1.175", "2.3.1.176", "2.3.1.177", "2.3.1.178",
-  "2.3.1.179", "2.3.1.180", "2.3.1.181", "2.3.1.182", "2.3.1.183",
-  "2.3.1.184", "2.3.1.185", "2.3.1.186", "2.3.1.187", "2.3.2.1",
-  "2.3.2.2", "2.3.2.3", "2.3.2.4", "2.3.2.5", "2.3.2.6", "2.3.2.7",
-  "2.3.2.8", "2.3.2.9", "2.3.2.10", "2.3.2.11", "2.3.2.12", "2.3.2.13",
+  "1.22.1.1", "1.97.1.1", "1.97.1.2", "1.97.1.3", "1.97.1.4",
+  "1.97.1.8", "1.97.1.9", "1.97.1.10", "1.97.1.11", "2.1.1.1",
+  "2.1.1.2", "2.1.1.3", "2.1.1.4", "2.1.1.5", "2.1.1.6", "2.1.1.7",
+  "2.1.1.8", "2.1.1.9", "2.1.1.10", "2.1.1.11", "2.1.1.12",
+  "2.1.1.13", "2.1.1.14", "2.1.1.15", "2.1.1.16", "2.1.1.17",
+  "2.1.1.18", "2.1.1.19", "2.1.1.20", "2.1.1.21", "2.1.1.22",
+  "2.1.1.25", "2.1.1.26", "2.1.1.27", "2.1.1.28", "2.1.1.29",
+  "2.1.1.31", "2.1.1.32", "2.1.1.33", "2.1.1.34", "2.1.1.35",
+  "2.1.1.36", "2.1.1.37", "2.1.1.38", "2.1.1.39", "2.1.1.40",
+  "2.1.1.41", "2.1.1.42", "2.1.1.43", "2.1.1.44", "2.1.1.45",
+  "2.1.1.46", "2.1.1.47", "2.1.1.48", "2.1.1.49", "2.1.1.50",
+  "2.1.1.51", "2.1.1.52", "2.1.1.53", "2.1.1.54", "2.1.1.55",
+  "2.1.1.56", "2.1.1.57", "2.1.1.59", "2.1.1.60", "2.1.1.61",
+  "2.1.1.62", "2.1.1.63", "2.1.1.64", "2.1.1.65", "2.1.1.66",
+  "2.1.1.67", "2.1.1.68", "2.1.1.69", "2.1.1.70", "2.1.1.71",
+  "2.1.1.72", "2.1.1.74", "2.1.1.75", "2.1.1.76", "2.1.1.77",
+  "2.1.1.78", "2.1.1.79", "2.1.1.80", "2.1.1.82", "2.1.1.83",
+  "2.1.1.84", "2.1.1.85", "2.1.1.86", "2.1.1.87", "2.1.1.88",
+  "2.1.1.89", "2.1.1.90", "2.1.1.91", "2.1.1.94", "2.1.1.95",
+  "2.1.1.96", "2.1.1.97", "2.1.1.98", "2.1.1.99", "2.1.1.100",
+  "2.1.1.101", "2.1.1.102", "2.1.1.103", "2.1.1.104", "2.1.1.105",
+  "2.1.1.106", "2.1.1.107", "2.1.1.108", "2.1.1.109", "2.1.1.110",
+  "2.1.1.111", "2.1.1.112", "2.1.1.113", "2.1.1.114", "2.1.1.115",
+  "2.1.1.116", "2.1.1.117", "2.1.1.118", "2.1.1.119", "2.1.1.120",
+  "2.1.1.121", "2.1.1.122", "2.1.1.123", "2.1.1.124", "2.1.1.125",
+  "2.1.1.126", "2.1.1.127", "2.1.1.128", "2.1.1.129", "2.1.1.130",
+  "2.1.1.131", "2.1.1.132", "2.1.1.133", "2.1.1.136", "2.1.1.137",
+  "2.1.1.139", "2.1.1.140", "2.1.1.141", "2.1.1.142", "2.1.1.143",
+  "2.1.1.144", "2.1.1.145", "2.1.1.146", "2.1.1.147", "2.1.1.148",
+  "2.1.1.149", "2.1.1.150", "2.1.1.151", "2.1.1.152", "2.1.1.153",
+  "2.1.1.154", "2.1.1.155", "2.1.1.156", "2.1.1.157", "2.1.1.158",
+  "2.1.1.159", "2.1.1.160", "2.1.1.161", "2.1.1.162", "2.1.1.163",
+  "2.1.1.164", "2.1.1.165", "2.1.2.1", "2.1.2.2", "2.1.2.3",
+  "2.1.2.4", "2.1.2.5", "2.1.2.7", "2.1.2.8", "2.1.2.9", "2.1.2.10",
+  "2.1.2.11", "2.1.3.1", "2.1.3.2", "2.1.3.3", "2.1.3.5", "2.1.3.6",
+  "2.1.3.7", "2.1.3.8", "2.1.3.9", "2.1.3.10", "2.1.3.11", "2.1.4.1",
+  "2.1.4.2", "2.2.1.1", "2.2.1.2", "2.2.1.3", "2.2.1.4", "2.2.1.5",
+  "2.2.1.6", "2.2.1.7", "2.2.1.8", "2.2.1.9", "2.3.1.1", "2.3.1.2",
+  "2.3.1.3", "2.3.1.4", "2.3.1.5", "2.3.1.6", "2.3.1.7", "2.3.1.8",
+  "2.3.1.9", "2.3.1.10", "2.3.1.11", "2.3.1.12", "2.3.1.13",
+  "2.3.1.14", "2.3.1.15", "2.3.1.16", "2.3.1.17", "2.3.1.18",
+  "2.3.1.19", "2.3.1.20", "2.3.1.21", "2.3.1.22", "2.3.1.23",
+  "2.3.1.24", "2.3.1.25", "2.3.1.26", "2.3.1.27", "2.3.1.28",
+  "2.3.1.29", "2.3.1.30", "2.3.1.31", "2.3.1.32", "2.3.1.33",
+  "2.3.1.34", "2.3.1.35", "2.3.1.36", "2.3.1.37", "2.3.1.38",
+  "2.3.1.39", "2.3.1.40", "2.3.1.41", "2.3.1.42", "2.3.1.43",
+  "2.3.1.44", "2.3.1.45", "2.3.1.46", "2.3.1.47", "2.3.1.48",
+  "2.3.1.49", "2.3.1.50", "2.3.1.51", "2.3.1.52", "2.3.1.53",
+  "2.3.1.54", "2.3.1.56", "2.3.1.57", "2.3.1.58", "2.3.1.59",
+  "2.3.1.60", "2.3.1.61", "2.3.1.62", "2.3.1.63", "2.3.1.64",
+  "2.3.1.65", "2.3.1.66", "2.3.1.67", "2.3.1.68", "2.3.1.69",
+  "2.3.1.71", "2.3.1.72", "2.3.1.73", "2.3.1.74", "2.3.1.75",
+  "2.3.1.76", "2.3.1.77", "2.3.1.78", "2.3.1.79", "2.3.1.80",
+  "2.3.1.81", "2.3.1.82", "2.3.1.83", "2.3.1.84", "2.3.1.85",
+  "2.3.1.86", "2.3.1.87", "2.3.1.88", "2.3.1.89", "2.3.1.90",
+  "2.3.1.91", "2.3.1.92", "2.3.1.93", "2.3.1.94", "2.3.1.95",
+  "2.3.1.96", "2.3.1.97", "2.3.1.98", "2.3.1.99", "2.3.1.100",
+  "2.3.1.101", "2.3.1.102", "2.3.1.103", "2.3.1.104", "2.3.1.105",
+  "2.3.1.106", "2.3.1.107", "2.3.1.108", "2.3.1.109", "2.3.1.110",
+  "2.3.1.111", "2.3.1.112", "2.3.1.113", "2.3.1.114", "2.3.1.115",
+  "2.3.1.116", "2.3.1.117", "2.3.1.118", "2.3.1.119", "2.3.1.121",
+  "2.3.1.122", "2.3.1.123", "2.3.1.125", "2.3.1.126", "2.3.1.127",
+  "2.3.1.128", "2.3.1.129", "2.3.1.130", "2.3.1.131", "2.3.1.132",
+  "2.3.1.133", "2.3.1.134", "2.3.1.135", "2.3.1.136", "2.3.1.137",
+  "2.3.1.138", "2.3.1.139", "2.3.1.140", "2.3.1.141", "2.3.1.142",
+  "2.3.1.143", "2.3.1.144", "2.3.1.145", "2.3.1.146", "2.3.1.147",
+  "2.3.1.148", "2.3.1.149", "2.3.1.150", "2.3.1.151", "2.3.1.152",
+  "2.3.1.153", "2.3.1.154", "2.3.1.155", "2.3.1.156", "2.3.1.157",
+  "2.3.1.158", "2.3.1.159", "2.3.1.160", "2.3.1.161", "2.3.1.162",
+  "2.3.1.163", "2.3.1.164", "2.3.1.165", "2.3.1.166", "2.3.1.167",
+  "2.3.1.168", "2.3.1.169", "2.3.1.170", "2.3.1.171", "2.3.1.172",
+  "2.3.1.173", "2.3.1.174", "2.3.1.175", "2.3.1.176", "2.3.1.177",
+  "2.3.1.178", "2.3.1.179", "2.3.1.180", "2.3.1.181", "2.3.1.182",
+  "2.3.1.183", "2.3.1.184", "2.3.1.185", "2.3.1.186", "2.3.1.187",
+  "2.3.1.188", "2.3.1.189", "2.3.1.190", "2.3.2.1", "2.3.2.2",
+  "2.3.2.3", "2.3.2.4", "2.3.2.5", "2.3.2.6", "2.3.2.7", "2.3.2.8",
+  "2.3.2.9", "2.3.2.10", "2.3.2.11", "2.3.2.12", "2.3.2.13",
   "2.3.2.14", "2.3.2.15", "2.3.3.1", "2.3.3.2", "2.3.3.3", "2.3.3.4",
   "2.3.3.5", "2.3.3.6", "2.3.3.7", "2.3.3.8", "2.3.3.9", "2.3.3.10",
-  "2.3.3.11", "2.3.3.12", "2.3.3.13", "2.3.3.14", "2.3.3.15", "2.4.1.1",
-  "2.4.1.2", "2.4.1.4", "2.4.1.5", "2.4.1.7", "2.4.1.8", "2.4.1.9",
-  "2.4.1.10", "2.4.1.11", "2.4.1.12", "2.4.1.13", "2.4.1.14",
-  "2.4.1.15", "2.4.1.16", "2.4.1.17", "2.4.1.18", "2.4.1.19",
-  "2.4.1.20", "2.4.1.21", "2.4.1.22", "2.4.1.23", "2.4.1.24",
-  "2.4.1.25", "2.4.1.26", "2.4.1.27", "2.4.1.28", "2.4.1.29",
-  "2.4.1.30", "2.4.1.31", "2.4.1.32", "2.4.1.33", "2.4.1.34",
-  "2.4.1.35", "2.4.1.36", "2.4.1.37", "2.4.1.38", "2.4.1.39",
-  "2.4.1.40", "2.4.1.41", "2.4.1.43", "2.4.1.44", "2.4.1.45",
-  "2.4.1.46", "2.4.1.47", "2.4.1.48", "2.4.1.49", "2.4.1.50",
-  "2.4.1.52", "2.4.1.53", "2.4.1.54", "2.4.1.56", "2.4.1.57",
-  "2.4.1.58", "2.4.1.60", "2.4.1.62", "2.4.1.63", "2.4.1.64",
-  "2.4.1.65", "2.4.1.66", "2.4.1.67", "2.4.1.68", "2.4.1.69",
-  "2.4.1.70", "2.4.1.71", "2.4.1.73", "2.4.1.74", "2.4.1.78",
-  "2.4.1.79", "2.4.1.80", "2.4.1.81", "2.4.1.82", "2.4.1.83",
-  "2.4.1.85", "2.4.1.86", "2.4.1.87", "2.4.1.88", "2.4.1.90",
-  "2.4.1.91", "2.4.1.92", "2.4.1.94", "2.4.1.95", "2.4.1.96",
-  "2.4.1.97", "2.4.1.99", "2.4.1.100", "2.4.1.101", "2.4.1.102",
-  "2.4.1.103", "2.4.1.104", "2.4.1.105", "2.4.1.106", "2.4.1.109",
-  "2.4.1.110", "2.4.1.111", "2.4.1.113", "2.4.1.114", "2.4.1.115",
-  "2.4.1.116", "2.4.1.117", "2.4.1.118", "2.4.1.119", "2.4.1.120",
-  "2.4.1.121", "2.4.1.122", "2.4.1.123", "2.4.1.125", "2.4.1.126",
-  "2.4.1.127", "2.4.1.128", "2.4.1.129", "2.4.1.130", "2.4.1.131",
-  "2.4.1.132", "2.4.1.133", "2.4.1.134", "2.4.1.135", "2.4.1.136",
-  "2.4.1.137", "2.4.1.138", "2.4.1.139", "2.4.1.140", "2.4.1.141",
-  "2.4.1.142", "2.4.1.143", "2.4.1.144", "2.4.1.145", "2.4.1.146",
-  "2.4.1.147", "2.4.1.148", "2.4.1.149", "2.4.1.150", "2.4.1.152",
-  "2.4.1.153", "2.4.1.155", "2.4.1.156", "2.4.1.157", "2.4.1.158",
-  "2.4.1.159", "2.4.1.160", "2.4.1.161", "2.4.1.162", "2.4.1.163",
-  "2.4.1.164", "2.4.1.165", "2.4.1.166", "2.4.1.167", "2.4.1.168",
-  "2.4.1.170", "2.4.1.171", "2.4.1.172", "2.4.1.173", "2.4.1.174",
-  "2.4.1.175", "2.4.1.176", "2.4.1.177", "2.4.1.178", "2.4.1.179",
-  "2.4.1.180", "2.4.1.181", "2.4.1.182", "2.4.1.183", "2.4.1.184",
-  "2.4.1.185", "2.4.1.186", "2.4.1.187", "2.4.1.188", "2.4.1.189",
-  "2.4.1.190", "2.4.1.191", "2.4.1.192", "2.4.1.193", "2.4.1.194",
-  "2.4.1.195", "2.4.1.196", "2.4.1.197", "2.4.1.198", "2.4.1.199",
-  "2.4.1.201", "2.4.1.202", "2.4.1.203", "2.4.1.205", "2.4.1.206",
-  "2.4.1.207", "2.4.1.208", "2.4.1.209", "2.4.1.210", "2.4.1.211",
-  "2.4.1.212", "2.4.1.213", "2.4.1.214", "2.4.1.215", "2.4.1.216",
-  "2.4.1.217", "2.4.1.218", "2.4.1.219", "2.4.1.220", "2.4.1.221",
-  "2.4.1.222", "2.4.1.223", "2.4.1.224", "2.4.1.225", "2.4.1.226",
-  "2.4.1.227", "2.4.1.228", "2.4.1.229", "2.4.1.230", "2.4.1.231",
-  "2.4.1.232", "2.4.1.234", "2.4.1.236", "2.4.1.237", "2.4.1.238",
-  "2.4.1.239", "2.4.1.240", "2.4.1.241", "2.4.1.242", "2.4.1.243",
-  "2.4.1.244", "2.4.1.245", "2.4.1.246", "2.4.2.1", "2.4.2.2",
+  "2.3.3.11", "2.3.3.12", "2.3.3.13", "2.3.3.14", "2.3.3.15",
+  "2.4.1.1", "2.4.1.2", "2.4.1.4", "2.4.1.5", "2.4.1.7", "2.4.1.8",
+  "2.4.1.9", "2.4.1.10", "2.4.1.11", "2.4.1.12", "2.4.1.13",
+  "2.4.1.14", "2.4.1.15", "2.4.1.16", "2.4.1.17", "2.4.1.18",
+  "2.4.1.19", "2.4.1.20", "2.4.1.21", "2.4.1.22", "2.4.1.23",
+  "2.4.1.24", "2.4.1.25", "2.4.1.26", "2.4.1.27", "2.4.1.28",
+  "2.4.1.29", "2.4.1.30", "2.4.1.31", "2.4.1.32", "2.4.1.33",
+  "2.4.1.34", "2.4.1.35", "2.4.1.36", "2.4.1.37", "2.4.1.38",
+  "2.4.1.39", "2.4.1.40", "2.4.1.41", "2.4.1.43", "2.4.1.44",
+  "2.4.1.45", "2.4.1.46", "2.4.1.47", "2.4.1.48", "2.4.1.49",
+  "2.4.1.50", "2.4.1.52", "2.4.1.53", "2.4.1.54", "2.4.1.56",
+  "2.4.1.57", "2.4.1.58", "2.4.1.60", "2.4.1.62", "2.4.1.63",
+  "2.4.1.64", "2.4.1.65", "2.4.1.66", "2.4.1.67", "2.4.1.68",
+  "2.4.1.69", "2.4.1.70", "2.4.1.71", "2.4.1.73", "2.4.1.74",
+  "2.4.1.78", "2.4.1.79", "2.4.1.80", "2.4.1.81", "2.4.1.82",
+  "2.4.1.83", "2.4.1.85", "2.4.1.86", "2.4.1.87", "2.4.1.88",
+  "2.4.1.90", "2.4.1.91", "2.4.1.92", "2.4.1.94", "2.4.1.95",
+  "2.4.1.96", "2.4.1.97", "2.4.1.99", "2.4.1.100", "2.4.1.101",
+  "2.4.1.102", "2.4.1.103", "2.4.1.104", "2.4.1.105", "2.4.1.106",
+  "2.4.1.109", "2.4.1.110", "2.4.1.111", "2.4.1.113", "2.4.1.114",
+  "2.4.1.115", "2.4.1.116", "2.4.1.117", "2.4.1.118", "2.4.1.119",
+  "2.4.1.120", "2.4.1.121", "2.4.1.122", "2.4.1.123", "2.4.1.125",
+  "2.4.1.126", "2.4.1.127", "2.4.1.128", "2.4.1.129", "2.4.1.130",
+  "2.4.1.131", "2.4.1.132", "2.4.1.133", "2.4.1.134", "2.4.1.135",
+  "2.4.1.136", "2.4.1.137", "2.4.1.138", "2.4.1.139", "2.4.1.140",
+  "2.4.1.141", "2.4.1.142", "2.4.1.143", "2.4.1.144", "2.4.1.145",
+  "2.4.1.146", "2.4.1.147", "2.4.1.148", "2.4.1.149", "2.4.1.150",
+  "2.4.1.152", "2.4.1.153", "2.4.1.155", "2.4.1.156", "2.4.1.157",
+  "2.4.1.158", "2.4.1.159", "2.4.1.160", "2.4.1.161", "2.4.1.162",
+  "2.4.1.163", "2.4.1.164", "2.4.1.165", "2.4.1.166", "2.4.1.167",
+  "2.4.1.168", "2.4.1.170", "2.4.1.171", "2.4.1.172", "2.4.1.173",
+  "2.4.1.174", "2.4.1.175", "2.4.1.176", "2.4.1.177", "2.4.1.178",
+  "2.4.1.179", "2.4.1.180", "2.4.1.181", "2.4.1.182", "2.4.1.183",
+  "2.4.1.184", "2.4.1.185", "2.4.1.186", "2.4.1.187", "2.4.1.188",
+  "2.4.1.189", "2.4.1.190", "2.4.1.191", "2.4.1.192", "2.4.1.193",
+  "2.4.1.194", "2.4.1.195", "2.4.1.196", "2.4.1.197", "2.4.1.198",
+  "2.4.1.199", "2.4.1.201", "2.4.1.202", "2.4.1.203", "2.4.1.205",
+  "2.4.1.206", "2.4.1.207", "2.4.1.208", "2.4.1.209", "2.4.1.210",
+  "2.4.1.211", "2.4.1.212", "2.4.1.213", "2.4.1.214", "2.4.1.215",
+  "2.4.1.216", "2.4.1.217", "2.4.1.218", "2.4.1.219", "2.4.1.220",
+  "2.4.1.221", "2.4.1.222", "2.4.1.223", "2.4.1.224", "2.4.1.225",
+  "2.4.1.226", "2.4.1.227", "2.4.1.228", "2.4.1.229", "2.4.1.230",
+  "2.4.1.231", "2.4.1.232", "2.4.1.234", "2.4.1.236", "2.4.1.237",
+  "2.4.1.238", "2.4.1.239", "2.4.1.240", "2.4.1.241", "2.4.1.242",
+  "2.4.1.243", "2.4.1.244", "2.4.1.245", "2.4.1.246", "2.4.1.247",
+  "2.4.1.248", "2.4.1.249", "2.4.1.250", "2.4.2.1", "2.4.2.2",
   "2.4.2.3", "2.4.2.4", "2.4.2.5", "2.4.2.6", "2.4.2.7", "2.4.2.8",
-  "2.4.2.9", "2.4.2.10", "2.4.2.11", "2.4.2.12", "2.4.2.14", "2.4.2.15",
-  "2.4.2.16", "2.4.2.17", "2.4.2.18", "2.4.2.19", "2.4.2.20",
-  "2.4.2.21", "2.4.2.22", "2.4.2.23", "2.4.2.24", "2.4.2.25",
-  "2.4.2.26", "2.4.2.27", "2.4.2.28", "2.4.2.29", "2.4.2.30",
-  "2.4.2.31", "2.4.2.32", "2.4.2.33", "2.4.2.34", "2.4.2.35",
-  "2.4.2.36", "2.4.2.37", "2.4.2.38", "2.4.2.39", "2.4.2.40",
-  "2.4.99.1", "2.4.99.2", "2.4.99.3", "2.4.99.4", "2.4.99.5",
-  "2.4.99.6", "2.4.99.7", "2.4.99.8", "2.4.99.9", "2.4.99.10",
-  "2.4.99.11", "2.5.1.1", "2.5.1.2", "2.5.1.3", "2.5.1.4", "2.5.1.5",
-  "2.5.1.6", "2.5.1.7", "2.5.1.8", "2.5.1.9", "2.5.1.10", "2.5.1.11",
-  "2.5.1.15", "2.5.1.16", "2.5.1.17", "2.5.1.18", "2.5.1.19",
-  "2.5.1.20", "2.5.1.21", "2.5.1.22", "2.5.1.23", "2.5.1.24",
-  "2.5.1.25", "2.5.1.26", "2.5.1.27", "2.5.1.28", "2.5.1.29",
-  "2.5.1.30", "2.5.1.31", "2.5.1.32", "2.5.1.33", "2.5.1.34",
-  "2.5.1.35", "2.5.1.36", "2.5.1.38", "2.5.1.39", "2.5.1.41",
-  "2.5.1.42", "2.5.1.43", "2.5.1.44", "2.5.1.45", "2.5.1.46",
-  "2.5.1.47", "2.5.1.48", "2.5.1.49", "2.5.1.50", "2.5.1.51",
-  "2.5.1.52", "2.5.1.53", "2.5.1.54", "2.5.1.55", "2.5.1.56",
-  "2.5.1.57", "2.5.1.58", "2.5.1.59", "2.5.1.60", "2.5.1.61",
-  "2.5.1.62", "2.5.1.63", "2.5.1.65", "2.5.1.66", "2.5.1.67",
-  "2.5.1.68", "2.5.1.69", "2.5.1.70", "2.5.1.71", "2.5.1.72", "2.6.1.1",
-  "2.6.1.2", "2.6.1.3", "2.6.1.4", "2.6.1.5", "2.6.1.6", "2.6.1.7",
-  "2.6.1.8", "2.6.1.9", "2.6.1.11", "2.6.1.12", "2.6.1.13", "2.6.1.14",
-  "2.6.1.15", "2.6.1.16", "2.6.1.17", "2.6.1.18", "2.6.1.19",
-  "2.6.1.21", "2.6.1.22", "2.6.1.23", "2.6.1.24", "2.6.1.26",
-  "2.6.1.27", "2.6.1.28", "2.6.1.29", "2.6.1.30", "2.6.1.31",
-  "2.6.1.32", "2.6.1.33", "2.6.1.34", "2.6.1.35", "2.6.1.36",
-  "2.6.1.37", "2.6.1.38", "2.6.1.39", "2.6.1.40", "2.6.1.41",
-  "2.6.1.42", "2.6.1.43", "2.6.1.44", "2.6.1.45", "2.6.1.46",
-  "2.6.1.47", "2.6.1.48", "2.6.1.49", "2.6.1.50", "2.6.1.51",
-  "2.6.1.52", "2.6.1.54", "2.6.1.55", "2.6.1.56", "2.6.1.57",
-  "2.6.1.58", "2.6.1.59", "2.6.1.60", "2.6.1.62", "2.6.1.63",
-  "2.6.1.64", "2.6.1.65", "2.6.1.66", "2.6.1.67", "2.6.1.68",
-  "2.6.1.70", "2.6.1.71", "2.6.1.72", "2.6.1.73", "2.6.1.74",
-  "2.6.1.75", "2.6.1.76", "2.6.1.77", "2.6.1.78", "2.6.1.79",
-  "2.6.1.80", "2.6.1.81", "2.6.1.82", "2.6.1.83", "2.6.1.84",
-  "2.6.1.85", "2.6.1.86", "2.6.3.1", "2.6.99.1", "2.6.99.2", "2.7.1.1",
-  "2.7.1.2", "2.7.1.3", "2.7.1.4", "2.7.1.5", "2.7.1.6", "2.7.1.7",
-  "2.7.1.8", "2.7.1.10", "2.7.1.11", "2.7.1.12", "2.7.1.13", "2.7.1.14",
-  "2.7.1.15", "2.7.1.16", "2.7.1.17", "2.7.1.18", "2.7.1.19",
-  "2.7.1.20", "2.7.1.21", "2.7.1.22", "2.7.1.23", "2.7.1.24",
-  "2.7.1.25", "2.7.1.26", "2.7.1.27", "2.7.1.28", "2.7.1.29",
-  "2.7.1.30", "2.7.1.31", "2.7.1.32", "2.7.1.33", "2.7.1.34",
-  "2.7.1.35", "2.7.1.36", "2.7.1.39", "2.7.1.40", "2.7.1.41",
-  "2.7.1.42", "2.7.1.43", "2.7.1.44", "2.7.1.45", "2.7.1.46",
-  "2.7.1.47", "2.7.1.48", "2.7.1.49", "2.7.1.50", "2.7.1.51",
-  "2.7.1.52", "2.7.1.53", "2.7.1.54", "2.7.1.55", "2.7.1.56",
-  "2.7.1.58", "2.7.1.59", "2.7.1.60", "2.7.1.61", "2.7.1.62",
-  "2.7.1.63", "2.7.1.64", "2.7.1.65", "2.7.1.66", "2.7.1.67",
-  "2.7.1.68", "2.7.1.69", "2.7.1.71", "2.7.1.72", "2.7.1.73",
-  "2.7.1.74", "2.7.1.76", "2.7.1.77", "2.7.1.78", "2.7.1.79",
-  "2.7.1.80", "2.7.1.81", "2.7.1.82", "2.7.1.83", "2.7.1.84",
-  "2.7.1.85", "2.7.1.86", "2.7.1.87", "2.7.1.88", "2.7.1.89",
-  "2.7.1.90", "2.7.1.91", "2.7.1.92", "2.7.1.93", "2.7.1.94",
-  "2.7.1.95", "2.7.1.100", "2.7.1.101", "2.7.1.102", "2.7.1.103",
-  "2.7.1.105", "2.7.1.106", "2.7.1.107", "2.7.1.108", "2.7.1.113",
-  "2.7.1.114", "2.7.1.118", "2.7.1.119", "2.7.1.121", "2.7.1.122",
-  "2.7.1.127", "2.7.1.130", "2.7.1.134", "2.7.1.136", "2.7.1.137",
-  "2.7.1.138", "2.7.1.140", "2.7.1.142", "2.7.1.143", "2.7.1.144",
-  "2.7.1.145", "2.7.1.146", "2.7.1.147", "2.7.1.148", "2.7.1.149",
-  "2.7.1.150", "2.7.1.151", "2.7.1.153", "2.7.1.154", "2.7.1.156",
-  "2.7.1.157", "2.7.1.158", "2.7.1.159", "2.7.1.160", "2.7.1.161",
-  "2.7.1.162", "2.7.2.1", "2.7.2.2", "2.7.2.3", "2.7.2.4", "2.7.2.6",
-  "2.7.2.7", "2.7.2.8", "2.7.2.10", "2.7.2.11", "2.7.2.12", "2.7.2.13",
-  "2.7.2.14", "2.7.2.15", "2.7.3.1", "2.7.3.2", "2.7.3.3", "2.7.3.4",
-  "2.7.3.5", "2.7.3.6", "2.7.3.7", "2.7.3.8", "2.7.3.9", "2.7.3.10",
-  "2.7.4.1", "2.7.4.2", "2.7.4.3", "2.7.4.4", "2.7.4.6", "2.7.4.7",
-  "2.7.4.8", "2.7.4.9", "2.7.4.10", "2.7.4.11", "2.7.4.12", "2.7.4.13",
-  "2.7.4.14", "2.7.4.15", "2.7.4.16", "2.7.4.17", "2.7.4.18",
-  "2.7.4.19", "2.7.4.20", "2.7.4.21", "2.7.4.22", "2.7.4.23",
-  "2.7.4.24", "2.7.6.1", "2.7.6.2", "2.7.6.3", "2.7.6.4", "2.7.6.5",
-  "2.7.7.1", "2.7.7.2", "2.7.7.3", "2.7.7.4", "2.7.7.5", "2.7.7.6",
-  "2.7.7.7", "2.7.7.8", "2.7.7.9", "2.7.7.10", "2.7.7.11", "2.7.7.12",
-  "2.7.7.13", "2.7.7.14", "2.7.7.15", "2.7.7.18", "2.7.7.19",
-  "2.7.7.21", "2.7.7.22", "2.7.7.23", "2.7.7.24", "2.7.7.25",
-  "2.7.7.27", "2.7.7.28", "2.7.7.30", "2.7.7.31", "2.7.7.32",
-  "2.7.7.33", "2.7.7.34", "2.7.7.35", "2.7.7.36", "2.7.7.37",
-  "2.7.7.38", "2.7.7.39", "2.7.7.40", "2.7.7.41", "2.7.7.42",
-  "2.7.7.43", "2.7.7.44", "2.7.7.45", "2.7.7.46", "2.7.7.47",
-  "2.7.7.48", "2.7.7.49", "2.7.7.50", "2.7.7.51", "2.7.7.52",
-  "2.7.7.53", "2.7.7.54", "2.7.7.55", "2.7.7.56", "2.7.7.57",
-  "2.7.7.58", "2.7.7.59", "2.7.7.60", "2.7.7.61", "2.7.7.62",
-  "2.7.7.63", "2.7.7.64", "2.7.7.65", "2.7.7.66", "2.7.7.67", "2.7.8.1",
-  "2.7.8.2", "2.7.8.3", "2.7.8.4", "2.7.8.5", "2.7.8.6", "2.7.8.7",
-  "2.7.8.8", "2.7.8.9", "2.7.8.10", "2.7.8.11", "2.7.8.12", "2.7.8.13",
-  "2.7.8.14", "2.7.8.15", "2.7.8.17", "2.7.8.18", "2.7.8.19",
-  "2.7.8.20", "2.7.8.21", "2.7.8.22", "2.7.8.23", "2.7.8.24",
-  "2.7.8.25", "2.7.8.26", "2.7.8.27", "2.7.9.1", "2.7.9.2", "2.7.9.3",
-  "2.7.9.4", "2.7.9.5", "2.7.10.1", "2.7.10.2", "2.7.11.1", "2.7.11.2",
-  "2.7.11.3", "2.7.11.4", "2.7.11.5", "2.7.11.6", "2.7.11.7",
-  "2.7.11.8", "2.7.11.9", "2.7.11.10", "2.7.11.11", "2.7.11.12",
-  "2.7.11.13", "2.7.11.14", "2.7.11.15", "2.7.11.16", "2.7.11.17",
-  "2.7.11.18", "2.7.11.19", "2.7.11.20", "2.7.11.21", "2.7.11.22",
-  "2.7.11.23", "2.7.11.24", "2.7.11.25", "2.7.11.26", "2.7.11.27",
-  "2.7.11.28", "2.7.11.29", "2.7.11.30", "2.7.11.31", "2.7.12.1",
-  "2.7.12.2", "2.7.13.1", "2.7.13.2", "2.7.13.3", "2.7.99.1", "2.8.1.1",
-  "2.8.1.2", "2.8.1.3", "2.8.1.4", "2.8.1.5", "2.8.1.6", "2.8.1.7",
-  "2.8.1.8", "2.8.2.1", "2.8.2.2", "2.8.2.3", "2.8.2.4", "2.8.2.5",
-  "2.8.2.6", "2.8.2.7", "2.8.2.8", "2.8.2.9", "2.8.2.10", "2.8.2.11",
-  "2.8.2.13", "2.8.2.14", "2.8.2.15", "2.8.2.16", "2.8.2.17",
-  "2.8.2.18", "2.8.2.19", "2.8.2.20", "2.8.2.21", "2.8.2.22",
-  "2.8.2.23", "2.8.2.24", "2.8.2.25", "2.8.2.26", "2.8.2.27",
-  "2.8.2.28", "2.8.2.29", "2.8.2.30", "2.8.2.31", "2.8.2.32",
-  "2.8.2.33", "2.8.2.34", "2.8.3.1", "2.8.3.2", "2.8.3.3", "2.8.3.5",
-  "2.8.3.6", "2.8.3.7", "2.8.3.8", "2.8.3.9", "2.8.3.10", "2.8.3.11",
-  "2.8.3.12", "2.8.3.13", "2.8.3.14", "2.8.3.15", "2.8.3.16",
-  "2.8.3.17", "2.8.4.1", "2.9.1.1", "3.1.1.1", "3.1.1.2", "3.1.1.3",
-  "3.1.1.4", "3.1.1.5", "3.1.1.6", "3.1.1.7", "3.1.1.8", "3.1.1.10",
-  "3.1.1.11", "3.1.1.13", "3.1.1.14", "3.1.1.15", "3.1.1.17",
-  "3.1.1.19", "3.1.1.20", "3.1.1.21", "3.1.1.22", "3.1.1.23",
-  "3.1.1.24", "3.1.1.25", "3.1.1.26", "3.1.1.27", "3.1.1.28",
-  "3.1.1.29", "3.1.1.30", "3.1.1.31", "3.1.1.32", "3.1.1.33",
-  "3.1.1.34", "3.1.1.35", "3.1.1.36", "3.1.1.37", "3.1.1.38",
-  "3.1.1.39", "3.1.1.40", "3.1.1.41", "3.1.1.42", "3.1.1.43",
-  "3.1.1.44", "3.1.1.45", "3.1.1.46", "3.1.1.47", "3.1.1.48",
-  "3.1.1.49", "3.1.1.50", "3.1.1.51", "3.1.1.52", "3.1.1.53",
-  "3.1.1.54", "3.1.1.55", "3.1.1.56", "3.1.1.57", "3.1.1.58",
-  "3.1.1.59", "3.1.1.60", "3.1.1.61", "3.1.1.63", "3.1.1.64",
-  "3.1.1.65", "3.1.1.66", "3.1.1.67", "3.1.1.68", "3.1.1.70",
-  "3.1.1.71", "3.1.1.72", "3.1.1.73", "3.1.1.74", "3.1.1.75",
-  "3.1.1.76", "3.1.1.77", "3.1.1.78", "3.1.1.79", "3.1.1.80",
-  "3.1.1.81", "3.1.1.82", "3.1.1.83", "3.1.2.1", "3.1.2.2", "3.1.2.3",
-  "3.1.2.4", "3.1.2.5", "3.1.2.6", "3.1.2.7", "3.1.2.10", "3.1.2.11",
-  "3.1.2.12", "3.1.2.13", "3.1.2.14", "3.1.2.15", "3.1.2.16",
-  "3.1.2.17", "3.1.2.18", "3.1.2.19", "3.1.2.20", "3.1.2.21",
-  "3.1.2.22", "3.1.2.23", "3.1.2.25", "3.1.2.26", "3.1.2.27", "3.1.3.1",
-  "3.1.3.2", "3.1.3.3", "3.1.3.4", "3.1.3.5", "3.1.3.6", "3.1.3.7",
-  "3.1.3.8", "3.1.3.9", "3.1.3.10", "3.1.3.11", "3.1.3.12", "3.1.3.13",
-  "3.1.3.14", "3.1.3.15", "3.1.3.16", "3.1.3.17", "3.1.3.18",
-  "3.1.3.19", "3.1.3.20", "3.1.3.21", "3.1.3.22", "3.1.3.23",
-  "3.1.3.24", "3.1.3.25", "3.1.3.26", "3.1.3.27", "3.1.3.28",
-  "3.1.3.29", "3.1.3.31", "3.1.3.32", "3.1.3.33", "3.1.3.34",
-  "3.1.3.35", "3.1.3.36", "3.1.3.37", "3.1.3.38", "3.1.3.39",
-  "3.1.3.40", "3.1.3.41", "3.1.3.42", "3.1.3.43", "3.1.3.44",
-  "3.1.3.45", "3.1.3.46", "3.1.3.47", "3.1.3.48", "3.1.3.49",
-  "3.1.3.50", "3.1.3.51", "3.1.3.52", "3.1.3.53", "3.1.3.54",
-  "3.1.3.55", "3.1.3.56", "3.1.3.57", "3.1.3.58", "3.1.3.59",
-  "3.1.3.60", "3.1.3.62", "3.1.3.63", "3.1.3.64", "3.1.3.66",
-  "3.1.3.67", "3.1.3.68", "3.1.3.69", "3.1.3.70", "3.1.3.71",
-  "3.1.3.72", "3.1.3.73", "3.1.3.74", "3.1.3.75", "3.1.3.76",
-  "3.1.3.77", "3.1.3.78", "3.1.3.79", "3.1.4.1", "3.1.4.2", "3.1.4.3",
-  "3.1.4.4", "3.1.4.11", "3.1.4.12", "3.1.4.13", "3.1.4.14", "3.1.4.15",
-  "3.1.4.16", "3.1.4.17", "3.1.4.35", "3.1.4.37", "3.1.4.38",
-  "3.1.4.39", "3.1.4.40", "3.1.4.41", "3.1.4.42", "3.1.4.43",
-  "3.1.4.44", "3.1.4.45", "3.1.4.46", "3.1.4.48", "3.1.4.49",
-  "3.1.4.50", "3.1.4.51", "3.1.4.52", "3.1.4.53", "3.1.5.1", "3.1.6.1",
-  "3.1.6.2", "3.1.6.3", "3.1.6.4", "3.1.6.6", "3.1.6.7", "3.1.6.8",
-  "3.1.6.9", "3.1.6.10", "3.1.6.11", "3.1.6.12", "3.1.6.13", "3.1.6.14",
-  "3.1.6.15", "3.1.6.16", "3.1.6.17", "3.1.6.18", "3.1.7.1", "3.1.7.2",
-  "3.1.7.3", "3.1.7.4", "3.1.8.1", "3.1.8.2", "3.1.11.1", "3.1.11.2",
-  "3.1.11.3", "3.1.11.4", "3.1.11.5", "3.1.11.6", "3.1.13.1",
-  "3.1.13.2", "3.1.13.3", "3.1.13.4", "3.1.13.5", "3.1.14.1",
-  "3.1.15.1", "3.1.16.1", "3.1.21.1", "3.1.21.2", "3.1.21.3",
-  "3.1.21.4", "3.1.21.5", "3.1.21.6", "3.1.21.7", "3.1.22.1",
-  "3.1.22.2", "3.1.22.4", "3.1.22.5", "3.1.25.1", "3.1.26.1",
-  "3.1.26.2", "3.1.26.3", "3.1.26.4", "3.1.26.5", "3.1.26.6",
-  "3.1.26.7", "3.1.26.8", "3.1.26.9", "3.1.26.10", "3.1.26.11",
-  "3.1.26.12", "3.1.27.1", "3.1.27.2", "3.1.27.3", "3.1.27.4",
+  "2.4.2.9", "2.4.2.10", "2.4.2.11", "2.4.2.12", "2.4.2.14",
+  "2.4.2.15", "2.4.2.16", "2.4.2.17", "2.4.2.18", "2.4.2.19",
+  "2.4.2.20", "2.4.2.21", "2.4.2.22", "2.4.2.23", "2.4.2.24",
+  "2.4.2.25", "2.4.2.26", "2.4.2.27", "2.4.2.28", "2.4.2.29",
+  "2.4.2.30", "2.4.2.31", "2.4.2.32", "2.4.2.33", "2.4.2.34",
+  "2.4.2.35", "2.4.2.36", "2.4.2.37", "2.4.2.38", "2.4.2.39",
+  "2.4.2.40", "2.4.2.41", "2.4.2.42", "2.4.99.1", "2.4.99.2",
+  "2.4.99.3", "2.4.99.4", "2.4.99.5", "2.4.99.6", "2.4.99.7",
+  "2.4.99.8", "2.4.99.9", "2.4.99.10", "2.4.99.11", "2.5.1.1",
+  "2.5.1.2", "2.5.1.3", "2.5.1.4", "2.5.1.5", "2.5.1.6", "2.5.1.7",
+  "2.5.1.9", "2.5.1.10", "2.5.1.11", "2.5.1.15", "2.5.1.16",
+  "2.5.1.17", "2.5.1.18", "2.5.1.19", "2.5.1.20", "2.5.1.21",
+  "2.5.1.22", "2.5.1.23", "2.5.1.24", "2.5.1.25", "2.5.1.26",
+  "2.5.1.27", "2.5.1.28", "2.5.1.29", "2.5.1.30", "2.5.1.31",
+  "2.5.1.32", "2.5.1.33", "2.5.1.34", "2.5.1.35", "2.5.1.36",
+  "2.5.1.38", "2.5.1.39", "2.5.1.41", "2.5.1.42", "2.5.1.43",
+  "2.5.1.44", "2.5.1.45", "2.5.1.46", "2.5.1.47", "2.5.1.48",
+  "2.5.1.49", "2.5.1.50", "2.5.1.51", "2.5.1.52", "2.5.1.53",
+  "2.5.1.54", "2.5.1.55", "2.5.1.56", "2.5.1.57", "2.5.1.58",
+  "2.5.1.59", "2.5.1.60", "2.5.1.61", "2.5.1.62", "2.5.1.63",
+  "2.5.1.65", "2.5.1.66", "2.5.1.67", "2.5.1.68", "2.5.1.69",
+  "2.5.1.70", "2.5.1.71", "2.5.1.72", "2.5.1.73", "2.5.1.74",
+  "2.5.1.75", "2.5.1.76", "2.5.1.77", "2.5.1.78", "2.5.1.79",
+  "2.5.1.80", "2.6.1.1", "2.6.1.2", "2.6.1.3", "2.6.1.4", "2.6.1.5",
+  "2.6.1.6", "2.6.1.7", "2.6.1.8", "2.6.1.9", "2.6.1.11", "2.6.1.12",
+  "2.6.1.13", "2.6.1.14", "2.6.1.15", "2.6.1.16", "2.6.1.17",
+  "2.6.1.18", "2.6.1.19", "2.6.1.21", "2.6.1.22", "2.6.1.23",
+  "2.6.1.24", "2.6.1.26", "2.6.1.27", "2.6.1.28", "2.6.1.29",
+  "2.6.1.30", "2.6.1.31", "2.6.1.32", "2.6.1.33", "2.6.1.34",
+  "2.6.1.35", "2.6.1.36", "2.6.1.37", "2.6.1.38", "2.6.1.39",
+  "2.6.1.40", "2.6.1.41", "2.6.1.42", "2.6.1.43", "2.6.1.44",
+  "2.6.1.45", "2.6.1.46", "2.6.1.47", "2.6.1.48", "2.6.1.49",
+  "2.6.1.50", "2.6.1.51", "2.6.1.52", "2.6.1.54", "2.6.1.55",
+  "2.6.1.56", "2.6.1.57", "2.6.1.58", "2.6.1.59", "2.6.1.60",
+  "2.6.1.62", "2.6.1.63", "2.6.1.64", "2.6.1.65", "2.6.1.66",
+  "2.6.1.67", "2.6.1.68", "2.6.1.70", "2.6.1.71", "2.6.1.72",
+  "2.6.1.73", "2.6.1.74", "2.6.1.75", "2.6.1.76", "2.6.1.77",
+  "2.6.1.78", "2.6.1.79", "2.6.1.80", "2.6.1.81", "2.6.1.82",
+  "2.6.1.83", "2.6.1.84", "2.6.1.85", "2.6.1.86", "2.6.3.1",
+  "2.6.99.1", "2.6.99.2", "2.7.1.1", "2.7.1.2", "2.7.1.3", "2.7.1.4",
+  "2.7.1.5", "2.7.1.6", "2.7.1.7", "2.7.1.8", "2.7.1.10", "2.7.1.11",
+  "2.7.1.12", "2.7.1.13", "2.7.1.14", "2.7.1.15", "2.7.1.16",
+  "2.7.1.17", "2.7.1.18", "2.7.1.19", "2.7.1.20", "2.7.1.21",
+  "2.7.1.22", "2.7.1.23", "2.7.1.24", "2.7.1.25", "2.7.1.26",
+  "2.7.1.27", "2.7.1.28", "2.7.1.29", "2.7.1.30", "2.7.1.31",
+  "2.7.1.32", "2.7.1.33", "2.7.1.34", "2.7.1.35", "2.7.1.36",
+  "2.7.1.39", "2.7.1.40", "2.7.1.41", "2.7.1.42", "2.7.1.43",
+  "2.7.1.44", "2.7.1.45", "2.7.1.46", "2.7.1.47", "2.7.1.48",
+  "2.7.1.49", "2.7.1.50", "2.7.1.51", "2.7.1.52", "2.7.1.53",
+  "2.7.1.54", "2.7.1.55", "2.7.1.56", "2.7.1.58", "2.7.1.59",
+  "2.7.1.60", "2.7.1.61", "2.7.1.62", "2.7.1.63", "2.7.1.64",
+  "2.7.1.65", "2.7.1.66", "2.7.1.67", "2.7.1.68", "2.7.1.69",
+  "2.7.1.71", "2.7.1.72", "2.7.1.73", "2.7.1.74", "2.7.1.76",
+  "2.7.1.77", "2.7.1.78", "2.7.1.79", "2.7.1.80", "2.7.1.81",
+  "2.7.1.82", "2.7.1.83", "2.7.1.84", "2.7.1.85", "2.7.1.86",
+  "2.7.1.87", "2.7.1.88", "2.7.1.89", "2.7.1.90", "2.7.1.91",
+  "2.7.1.92", "2.7.1.93", "2.7.1.94", "2.7.1.95", "2.7.1.100",
+  "2.7.1.101", "2.7.1.102", "2.7.1.103", "2.7.1.105", "2.7.1.106",
+  "2.7.1.107", "2.7.1.108", "2.7.1.113", "2.7.1.114", "2.7.1.118",
+  "2.7.1.119", "2.7.1.121", "2.7.1.122", "2.7.1.127", "2.7.1.130",
+  "2.7.1.134", "2.7.1.136", "2.7.1.137", "2.7.1.138", "2.7.1.140",
+  "2.7.1.142", "2.7.1.143", "2.7.1.144", "2.7.1.145", "2.7.1.146",
+  "2.7.1.147", "2.7.1.148", "2.7.1.149", "2.7.1.150", "2.7.1.151",
+  "2.7.1.153", "2.7.1.154", "2.7.1.156", "2.7.1.157", "2.7.1.158",
+  "2.7.1.159", "2.7.1.160", "2.7.1.161", "2.7.1.162", "2.7.1.163",
+  "2.7.1.164", "2.7.1.165", "2.7.2.1", "2.7.2.2", "2.7.2.3",
+  "2.7.2.4", "2.7.2.6", "2.7.2.7", "2.7.2.8", "2.7.2.10", "2.7.2.11",
+  "2.7.2.12", "2.7.2.13", "2.7.2.14", "2.7.2.15", "2.7.3.1",
+  "2.7.3.2", "2.7.3.3", "2.7.3.4", "2.7.3.5", "2.7.3.6", "2.7.3.7",
+  "2.7.3.8", "2.7.3.9", "2.7.3.10", "2.7.4.1", "2.7.4.2", "2.7.4.3",
+  "2.7.4.4", "2.7.4.6", "2.7.4.7", "2.7.4.8", "2.7.4.9", "2.7.4.10",
+  "2.7.4.11", "2.7.4.12", "2.7.4.13", "2.7.4.14", "2.7.4.15",
+  "2.7.4.16", "2.7.4.17", "2.7.4.18", "2.7.4.19", "2.7.4.20",
+  "2.7.4.21", "2.7.4.22", "2.7.4.23", "2.7.4.24", "2.7.6.1",
+  "2.7.6.2", "2.7.6.3", "2.7.6.4", "2.7.6.5", "2.7.7.1", "2.7.7.2",
+  "2.7.7.3", "2.7.7.4", "2.7.7.5", "2.7.7.6", "2.7.7.7", "2.7.7.8",
+  "2.7.7.9", "2.7.7.10", "2.7.7.11", "2.7.7.12", "2.7.7.13",
+  "2.7.7.14", "2.7.7.15", "2.7.7.18", "2.7.7.19", "2.7.7.21",
+  "2.7.7.22", "2.7.7.23", "2.7.7.24", "2.7.7.25", "2.7.7.27",
+  "2.7.7.28", "2.7.7.30", "2.7.7.31", "2.7.7.32", "2.7.7.33",
+  "2.7.7.34", "2.7.7.35", "2.7.7.36", "2.7.7.37", "2.7.7.38",
+  "2.7.7.39", "2.7.7.40", "2.7.7.41", "2.7.7.42", "2.7.7.43",
+  "2.7.7.44", "2.7.7.45", "2.7.7.46", "2.7.7.47", "2.7.7.48",
+  "2.7.7.49", "2.7.7.50", "2.7.7.51", "2.7.7.52", "2.7.7.53",
+  "2.7.7.54", "2.7.7.55", "2.7.7.56", "2.7.7.57", "2.7.7.58",
+  "2.7.7.59", "2.7.7.60", "2.7.7.61", "2.7.7.62", "2.7.7.63",
+  "2.7.7.64", "2.7.7.65", "2.7.7.66", "2.7.7.67", "2.7.7.68",
+  "2.7.8.1", "2.7.8.2", "2.7.8.3", "2.7.8.4", "2.7.8.5", "2.7.8.6",
+  "2.7.8.7", "2.7.8.8", "2.7.8.9", "2.7.8.10", "2.7.8.11", "2.7.8.12",
+  "2.7.8.13", "2.7.8.14", "2.7.8.15", "2.7.8.17", "2.7.8.18",
+  "2.7.8.19", "2.7.8.20", "2.7.8.21", "2.7.8.22", "2.7.8.23",
+  "2.7.8.24", "2.7.8.25", "2.7.8.26", "2.7.8.27", "2.7.8.28",
+  "2.7.9.1", "2.7.9.2", "2.7.9.3", "2.7.9.4", "2.7.9.5", "2.7.10.1",
+  "2.7.10.2", "2.7.11.1", "2.7.11.2", "2.7.11.3", "2.7.11.4",
+  "2.7.11.5", "2.7.11.6", "2.7.11.7", "2.7.11.8", "2.7.11.9",
+  "2.7.11.10", "2.7.11.11", "2.7.11.12", "2.7.11.13", "2.7.11.14",
+  "2.7.11.15", "2.7.11.16", "2.7.11.17", "2.7.11.18", "2.7.11.19",
+  "2.7.11.20", "2.7.11.21", "2.7.11.22", "2.7.11.23", "2.7.11.24",
+  "2.7.11.25", "2.7.11.26", "2.7.11.27", "2.7.11.28", "2.7.11.29",
+  "2.7.11.30", "2.7.11.31", "2.7.12.1", "2.7.12.2", "2.7.13.1",
+  "2.7.13.2", "2.7.13.3", "2.7.99.1", "2.8.1.1", "2.8.1.2", "2.8.1.3",
+  "2.8.1.4", "2.8.1.5", "2.8.1.6", "2.8.1.7", "2.8.1.8", "2.8.2.1",
+  "2.8.2.2", "2.8.2.3", "2.8.2.4", "2.8.2.5", "2.8.2.6", "2.8.2.7",
+  "2.8.2.8", "2.8.2.9", "2.8.2.10", "2.8.2.11", "2.8.2.13",
+  "2.8.2.14", "2.8.2.15", "2.8.2.16", "2.8.2.17", "2.8.2.18",
+  "2.8.2.19", "2.8.2.20", "2.8.2.21", "2.8.2.22", "2.8.2.23",
+  "2.8.2.24", "2.8.2.25", "2.8.2.26", "2.8.2.27", "2.8.2.28",
+  "2.8.2.29", "2.8.2.30", "2.8.2.31", "2.8.2.32", "2.8.2.33",
+  "2.8.2.34", "2.8.3.1", "2.8.3.2", "2.8.3.3", "2.8.3.5", "2.8.3.6",
+  "2.8.3.7", "2.8.3.8", "2.8.3.9", "2.8.3.10", "2.8.3.11", "2.8.3.12",
+  "2.8.3.13", "2.8.3.14", "2.8.3.15", "2.8.3.16", "2.8.3.17",
+  "2.8.4.1", "2.8.4.2", "2.9.1.1", "2.9.1.2", "3.1.1.1", "3.1.1.2",
+  "3.1.1.3", "3.1.1.4", "3.1.1.5", "3.1.1.6", "3.1.1.7", "3.1.1.8",
+  "3.1.1.10", "3.1.1.11", "3.1.1.13", "3.1.1.14", "3.1.1.15",
+  "3.1.1.17", "3.1.1.19", "3.1.1.20", "3.1.1.21", "3.1.1.22",
+  "3.1.1.23", "3.1.1.24", "3.1.1.25", "3.1.1.26", "3.1.1.27",
+  "3.1.1.28", "3.1.1.29", "3.1.1.30", "3.1.1.31", "3.1.1.32",
+  "3.1.1.33", "3.1.1.34", "3.1.1.35", "3.1.1.36", "3.1.1.37",
+  "3.1.1.38", "3.1.1.39", "3.1.1.40", "3.1.1.41", "3.1.1.42",
+  "3.1.1.43", "3.1.1.44", "3.1.1.45", "3.1.1.46", "3.1.1.47",
+  "3.1.1.48", "3.1.1.49", "3.1.1.50", "3.1.1.51", "3.1.1.52",
+  "3.1.1.53", "3.1.1.54", "3.1.1.55", "3.1.1.56", "3.1.1.57",
+  "3.1.1.58", "3.1.1.59", "3.1.1.60", "3.1.1.61", "3.1.1.63",
+  "3.1.1.64", "3.1.1.65", "3.1.1.66", "3.1.1.67", "3.1.1.68",
+  "3.1.1.70", "3.1.1.71", "3.1.1.72", "3.1.1.73", "3.1.1.74",
+  "3.1.1.75", "3.1.1.76", "3.1.1.77", "3.1.1.78", "3.1.1.79",
+  "3.1.1.80", "3.1.1.81", "3.1.1.82", "3.1.1.83", "3.1.1.84",
+  "3.1.2.1", "3.1.2.2", "3.1.2.3", "3.1.2.4", "3.1.2.5", "3.1.2.6",
+  "3.1.2.7", "3.1.2.10", "3.1.2.11", "3.1.2.12", "3.1.2.13",
+  "3.1.2.14", "3.1.2.15", "3.1.2.16", "3.1.2.17", "3.1.2.18",
+  "3.1.2.19", "3.1.2.20", "3.1.2.21", "3.1.2.22", "3.1.2.23",
+  "3.1.2.25", "3.1.2.26", "3.1.2.27", "3.1.3.1", "3.1.3.2", "3.1.3.3",
+  "3.1.3.4", "3.1.3.5", "3.1.3.6", "3.1.3.7", "3.1.3.8", "3.1.3.9",
+  "3.1.3.10", "3.1.3.11", "3.1.3.12", "3.1.3.13", "3.1.3.14",
+  "3.1.3.15", "3.1.3.16", "3.1.3.17", "3.1.3.18", "3.1.3.19",
+  "3.1.3.20", "3.1.3.21", "3.1.3.22", "3.1.3.23", "3.1.3.24",
+  "3.1.3.25", "3.1.3.26", "3.1.3.27", "3.1.3.28", "3.1.3.29",
+  "3.1.3.31", "3.1.3.32", "3.1.3.33", "3.1.3.34", "3.1.3.35",
+  "3.1.3.36", "3.1.3.37", "3.1.3.38", "3.1.3.39", "3.1.3.40",
+  "3.1.3.41", "3.1.3.42", "3.1.3.43", "3.1.3.44", "3.1.3.45",
+  "3.1.3.46", "3.1.3.47", "3.1.3.48", "3.1.3.49", "3.1.3.50",
+  "3.1.3.51", "3.1.3.52", "3.1.3.53", "3.1.3.54", "3.1.3.55",
+  "3.1.3.56", "3.1.3.57", "3.1.3.58", "3.1.3.59", "3.1.3.60",
+  "3.1.3.62", "3.1.3.63", "3.1.3.64", "3.1.3.66", "3.1.3.67",
+  "3.1.3.68", "3.1.3.69", "3.1.3.70", "3.1.3.71", "3.1.3.72",
+  "3.1.3.73", "3.1.3.74", "3.1.3.75", "3.1.3.76", "3.1.3.77",
+  "3.1.3.78", "3.1.3.79", "3.1.3.80", "3.1.4.1", "3.1.4.2", "3.1.4.3",
+  "3.1.4.4", "3.1.4.11", "3.1.4.12", "3.1.4.13", "3.1.4.14",
+  "3.1.4.15", "3.1.4.16", "3.1.4.17", "3.1.4.35", "3.1.4.37",
+  "3.1.4.38", "3.1.4.39", "3.1.4.40", "3.1.4.41", "3.1.4.42",
+  "3.1.4.43", "3.1.4.44", "3.1.4.45", "3.1.4.46", "3.1.4.48",
+  "3.1.4.49", "3.1.4.50", "3.1.4.51", "3.1.4.52", "3.1.4.53",
+  "3.1.5.1", "3.1.6.1", "3.1.6.2", "3.1.6.3", "3.1.6.4", "3.1.6.6",
+  "3.1.6.7", "3.1.6.8", "3.1.6.9", "3.1.6.10", "3.1.6.11", "3.1.6.12",
+  "3.1.6.13", "3.1.6.14", "3.1.6.15", "3.1.6.16", "3.1.6.17",
+  "3.1.6.18", "3.1.7.1", "3.1.7.2", "3.1.7.3", "3.1.7.4", "3.1.7.5",
+  "3.1.8.1", "3.1.8.2", "3.1.11.1", "3.1.11.2", "3.1.11.3",
+  "3.1.11.4", "3.1.11.5", "3.1.11.6", "3.1.13.1", "3.1.13.2",
+  "3.1.13.3", "3.1.13.4", "3.1.13.5", "3.1.14.1", "3.1.15.1",
+  "3.1.16.1", "3.1.21.1", "3.1.21.2", "3.1.21.3", "3.1.21.4",
+  "3.1.21.5", "3.1.21.6", "3.1.21.7", "3.1.22.1", "3.1.22.2",
+  "3.1.22.4", "3.1.22.5", "3.1.25.1", "3.1.26.1", "3.1.26.2",
+  "3.1.26.3", "3.1.26.4", "3.1.26.5", "3.1.26.6", "3.1.26.7",
+  "3.1.26.8", "3.1.26.9", "3.1.26.10", "3.1.26.11", "3.1.26.12",
+  "3.1.26.13", "3.1.27.1", "3.1.27.2", "3.1.27.3", "3.1.27.4",
   "3.1.27.5", "3.1.27.6", "3.1.27.7", "3.1.27.8", "3.1.27.9",
-  "3.1.27.10", "3.1.30.1", "3.1.30.2", "3.1.31.1", "3.2.1.1", "3.2.1.2",
-  "3.2.1.3", "3.2.1.4", "3.2.1.6", "3.2.1.7", "3.2.1.8", "3.2.1.10",
-  "3.2.1.11", "3.2.1.14", "3.2.1.15", "3.2.1.17", "3.2.1.18",
-  "3.2.1.20", "3.2.1.21", "3.2.1.22", "3.2.1.23", "3.2.1.24",
-  "3.2.1.25", "3.2.1.26", "3.2.1.28", "3.2.1.31", "3.2.1.32",
-  "3.2.1.33", "3.2.1.35", "3.2.1.36", "3.2.1.37", "3.2.1.38",
-  "3.2.1.39", "3.2.1.40", "3.2.1.41", "3.2.1.42", "3.2.1.43",
-  "3.2.1.44", "3.2.1.45", "3.2.1.46", "3.2.1.47", "3.2.1.48",
-  "3.2.1.49", "3.2.1.50", "3.2.1.51", "3.2.1.52", "3.2.1.53",
-  "3.2.1.54", "3.2.1.55", "3.2.1.56", "3.2.1.57", "3.2.1.58",
-  "3.2.1.59", "3.2.1.60", "3.2.1.61", "3.2.1.62", "3.2.1.63",
-  "3.2.1.64", "3.2.1.65", "3.2.1.66", "3.2.1.67", "3.2.1.68",
-  "3.2.1.70", "3.2.1.71", "3.2.1.72", "3.2.1.73", "3.2.1.74",
-  "3.2.1.75", "3.2.1.76", "3.2.1.77", "3.2.1.78", "3.2.1.80",
-  "3.2.1.81", "3.2.1.82", "3.2.1.83", "3.2.1.84", "3.2.1.85",
-  "3.2.1.86", "3.2.1.87", "3.2.1.88", "3.2.1.89", "3.2.1.91",
-  "3.2.1.92", "3.2.1.93", "3.2.1.94", "3.2.1.95", "3.2.1.96",
-  "3.2.1.97", "3.2.1.98", "3.2.1.99", "3.2.1.100", "3.2.1.101",
-  "3.2.1.102", "3.2.1.103", "3.2.1.104", "3.2.1.105", "3.2.1.106",
-  "3.2.1.107", "3.2.1.108", "3.2.1.109", "3.2.1.111", "3.2.1.112",
-  "3.2.1.113", "3.2.1.114", "3.2.1.115", "3.2.1.116", "3.2.1.117",
-  "3.2.1.118", "3.2.1.119", "3.2.1.120", "3.2.1.121", "3.2.1.122",
-  "3.2.1.123", "3.2.1.124", "3.2.1.125", "3.2.1.126", "3.2.1.127",
-  "3.2.1.128", "3.2.1.129", "3.2.1.130", "3.2.1.131", "3.2.1.132",
-  "3.2.1.133", "3.2.1.134", "3.2.1.135", "3.2.1.136", "3.2.1.137",
-  "3.2.1.139", "3.2.1.140", "3.2.1.141", "3.2.1.142", "3.2.1.143",
-  "3.2.1.144", "3.2.1.145", "3.2.1.146", "3.2.1.147", "3.2.1.149",
-  "3.2.1.150", "3.2.1.151", "3.2.1.152", "3.2.1.153", "3.2.1.154",
-  "3.2.1.155", "3.2.1.156", "3.2.1.157", "3.2.1.158", "3.2.1.159",
-  "3.2.1.161", "3.2.1.162", "3.2.1.163", "3.2.1.164", "3.2.1.165",
-  "3.2.2.1", "3.2.2.2", "3.2.2.3", "3.2.2.4", "3.2.2.5", "3.2.2.6",
-  "3.2.2.7", "3.2.2.8", "3.2.2.9", "3.2.2.10", "3.2.2.11", "3.2.2.12",
-  "3.2.2.13", "3.2.2.14", "3.2.2.15", "3.2.2.16", "3.2.2.17",
-  "3.2.2.19", "3.2.2.20", "3.2.2.21", "3.2.2.22", "3.2.2.23",
-  "3.2.2.24", "3.2.2.25", "3.2.2.26", "3.3.1.1", "3.3.1.2", "3.3.2.1",
-  "3.3.2.2", "3.3.2.4", "3.3.2.5", "3.3.2.6", "3.3.2.7", "3.3.2.8",
-  "3.3.2.9", "3.3.2.10", "3.3.2.11", "3.4.11.1", "3.4.11.2", "3.4.11.3",
+  "3.1.27.10", "3.1.30.1", "3.1.30.2", "3.1.31.1", "3.2.1.1",
+  "3.2.1.2", "3.2.1.3", "3.2.1.4", "3.2.1.6", "3.2.1.7", "3.2.1.8",
+  "3.2.1.10", "3.2.1.11", "3.2.1.14", "3.2.1.15", "3.2.1.17",
+  "3.2.1.18", "3.2.1.20", "3.2.1.21", "3.2.1.22", "3.2.1.23",
+  "3.2.1.24", "3.2.1.25", "3.2.1.26", "3.2.1.28", "3.2.1.31",
+  "3.2.1.32", "3.2.1.33", "3.2.1.35", "3.2.1.36", "3.2.1.37",
+  "3.2.1.38", "3.2.1.39", "3.2.1.40", "3.2.1.41", "3.2.1.42",
+  "3.2.1.43", "3.2.1.44", "3.2.1.45", "3.2.1.46", "3.2.1.47",
+  "3.2.1.48", "3.2.1.49", "3.2.1.50", "3.2.1.51", "3.2.1.52",
+  "3.2.1.53", "3.2.1.54", "3.2.1.55", "3.2.1.56", "3.2.1.57",
+  "3.2.1.58", "3.2.1.59", "3.2.1.60", "3.2.1.61", "3.2.1.62",
+  "3.2.1.63", "3.2.1.64", "3.2.1.65", "3.2.1.66", "3.2.1.67",
+  "3.2.1.68", "3.2.1.70", "3.2.1.71", "3.2.1.72", "3.2.1.73",
+  "3.2.1.74", "3.2.1.75", "3.2.1.76", "3.2.1.77", "3.2.1.78",
+  "3.2.1.80", "3.2.1.81", "3.2.1.82", "3.2.1.83", "3.2.1.84",
+  "3.2.1.85", "3.2.1.86", "3.2.1.87", "3.2.1.88", "3.2.1.89",
+  "3.2.1.91", "3.2.1.92", "3.2.1.93", "3.2.1.94", "3.2.1.95",
+  "3.2.1.96", "3.2.1.97", "3.2.1.98", "3.2.1.99", "3.2.1.100",
+  "3.2.1.101", "3.2.1.102", "3.2.1.103", "3.2.1.104", "3.2.1.105",
+  "3.2.1.106", "3.2.1.107", "3.2.1.108", "3.2.1.109", "3.2.1.111",
+  "3.2.1.112", "3.2.1.113", "3.2.1.114", "3.2.1.115", "3.2.1.116",
+  "3.2.1.117", "3.2.1.118", "3.2.1.119", "3.2.1.120", "3.2.1.121",
+  "3.2.1.122", "3.2.1.123", "3.2.1.124", "3.2.1.125", "3.2.1.126",
+  "3.2.1.127", "3.2.1.128", "3.2.1.129", "3.2.1.130", "3.2.1.131",
+  "3.2.1.132", "3.2.1.133", "3.2.1.134", "3.2.1.135", "3.2.1.136",
+  "3.2.1.137", "3.2.1.139", "3.2.1.140", "3.2.1.141", "3.2.1.142",
+  "3.2.1.143", "3.2.1.144", "3.2.1.145", "3.2.1.146", "3.2.1.147",
+  "3.2.1.149", "3.2.1.150", "3.2.1.151", "3.2.1.152", "3.2.1.153",
+  "3.2.1.154", "3.2.1.155", "3.2.1.156", "3.2.1.157", "3.2.1.158",
+  "3.2.1.159", "3.2.1.161", "3.2.1.162", "3.2.1.163", "3.2.1.164",
+  "3.2.1.165", "3.2.2.1", "3.2.2.2", "3.2.2.3", "3.2.2.4", "3.2.2.5",
+  "3.2.2.6", "3.2.2.7", "3.2.2.8", "3.2.2.9", "3.2.2.10", "3.2.2.11",
+  "3.2.2.12", "3.2.2.13", "3.2.2.14", "3.2.2.15", "3.2.2.16",
+  "3.2.2.17", "3.2.2.19", "3.2.2.20", "3.2.2.21", "3.2.2.22",
+  "3.2.2.23", "3.2.2.24", "3.2.2.25", "3.2.2.26", "3.2.2.27",
+  "3.2.2.28", "3.2.2.29", "3.3.1.1", "3.3.1.2", "3.3.2.1", "3.3.2.2",
+  "3.3.2.4", "3.3.2.5", "3.3.2.6", "3.3.2.7", "3.3.2.8", "3.3.2.9",
+  "3.3.2.10", "3.3.2.11", "3.4.11.1", "3.4.11.2", "3.4.11.3",
   "3.4.11.4", "3.4.11.5", "3.4.11.6", "3.4.11.7", "3.4.11.9",
   "3.4.11.10", "3.4.11.13", "3.4.11.14", "3.4.11.15", "3.4.11.16",
   "3.4.11.17", "3.4.11.18", "3.4.11.19", "3.4.11.20", "3.4.11.21",
@@ -16367,27 +17204,28 @@ static CharPtr ecnum_specif [] = {
   "3.4.17.4", "3.4.17.6", "3.4.17.8", "3.4.17.10", "3.4.17.11",
   "3.4.17.12", "3.4.17.13", "3.4.17.14", "3.4.17.15", "3.4.17.16",
   "3.4.17.17", "3.4.17.18", "3.4.17.19", "3.4.17.20", "3.4.17.21",
-  "3.4.17.22", "3.4.18.1", "3.4.19.1", "3.4.19.2", "3.4.19.3",
-  "3.4.19.5", "3.4.19.6", "3.4.19.7", "3.4.19.9", "3.4.19.11",
-  "3.4.19.12", "3.4.21.1", "3.4.21.2", "3.4.21.3", "3.4.21.4",
-  "3.4.21.5", "3.4.21.6", "3.4.21.7", "3.4.21.9", "3.4.21.10",
-  "3.4.21.12", "3.4.21.19", "3.4.21.20", "3.4.21.21", "3.4.21.22",
-  "3.4.21.25", "3.4.21.26", "3.4.21.27", "3.4.21.32", "3.4.21.34",
-  "3.4.21.35", "3.4.21.36", "3.4.21.37", "3.4.21.38", "3.4.21.39",
-  "3.4.21.41", "3.4.21.42", "3.4.21.43", "3.4.21.45", "3.4.21.46",
-  "3.4.21.47", "3.4.21.48", "3.4.21.49", "3.4.21.50", "3.4.21.53",
-  "3.4.21.54", "3.4.21.55", "3.4.21.57", "3.4.21.59", "3.4.21.60",
-  "3.4.21.61", "3.4.21.62", "3.4.21.63", "3.4.21.64", "3.4.21.65",
-  "3.4.21.66", "3.4.21.67", "3.4.21.68", "3.4.21.69", "3.4.21.70",
-  "3.4.21.71", "3.4.21.72", "3.4.21.73", "3.4.21.74", "3.4.21.75",
-  "3.4.21.76", "3.4.21.77", "3.4.21.78", "3.4.21.79", "3.4.21.80",
-  "3.4.21.81", "3.4.21.82", "3.4.21.83", "3.4.21.84", "3.4.21.85",
-  "3.4.21.86", "3.4.21.88", "3.4.21.89", "3.4.21.90", "3.4.21.91",
-  "3.4.21.92", "3.4.21.93", "3.4.21.94", "3.4.21.95", "3.4.21.96",
-  "3.4.21.97", "3.4.21.98", "3.4.21.99", "3.4.21.100", "3.4.21.101",
-  "3.4.21.102", "3.4.21.103", "3.4.21.104", "3.4.21.105", "3.4.21.106",
-  "3.4.21.107", "3.4.21.108", "3.4.21.109", "3.4.21.110", "3.4.21.111",
-  "3.4.21.112", "3.4.21.113", "3.4.21.114", "3.4.21.115", "3.4.21.116",
+  "3.4.17.22", "3.4.17.23", "3.4.18.1", "3.4.19.1", "3.4.19.2",
+  "3.4.19.3", "3.4.19.5", "3.4.19.6", "3.4.19.7", "3.4.19.9",
+  "3.4.19.11", "3.4.19.12", "3.4.21.1", "3.4.21.2", "3.4.21.3",
+  "3.4.21.4", "3.4.21.5", "3.4.21.6", "3.4.21.7", "3.4.21.9",
+  "3.4.21.10", "3.4.21.12", "3.4.21.19", "3.4.21.20", "3.4.21.21",
+  "3.4.21.22", "3.4.21.25", "3.4.21.26", "3.4.21.27", "3.4.21.32",
+  "3.4.21.34", "3.4.21.35", "3.4.21.36", "3.4.21.37", "3.4.21.38",
+  "3.4.21.39", "3.4.21.41", "3.4.21.42", "3.4.21.43", "3.4.21.45",
+  "3.4.21.46", "3.4.21.47", "3.4.21.48", "3.4.21.49", "3.4.21.50",
+  "3.4.21.53", "3.4.21.54", "3.4.21.55", "3.4.21.57", "3.4.21.59",
+  "3.4.21.60", "3.4.21.61", "3.4.21.62", "3.4.21.63", "3.4.21.64",
+  "3.4.21.65", "3.4.21.66", "3.4.21.67", "3.4.21.68", "3.4.21.69",
+  "3.4.21.70", "3.4.21.71", "3.4.21.72", "3.4.21.73", "3.4.21.74",
+  "3.4.21.75", "3.4.21.76", "3.4.21.77", "3.4.21.78", "3.4.21.79",
+  "3.4.21.80", "3.4.21.81", "3.4.21.82", "3.4.21.83", "3.4.21.84",
+  "3.4.21.85", "3.4.21.86", "3.4.21.88", "3.4.21.89", "3.4.21.90",
+  "3.4.21.91", "3.4.21.92", "3.4.21.93", "3.4.21.94", "3.4.21.95",
+  "3.4.21.96", "3.4.21.97", "3.4.21.98", "3.4.21.99", "3.4.21.100",
+  "3.4.21.101", "3.4.21.102", "3.4.21.103", "3.4.21.104",
+  "3.4.21.105", "3.4.21.106", "3.4.21.107", "3.4.21.108",
+  "3.4.21.109", "3.4.21.110", "3.4.21.111", "3.4.21.112",
+  "3.4.21.113", "3.4.21.114", "3.4.21.115", "3.4.21.116",
   "3.4.21.117", "3.4.21.118", "3.4.21.119", "3.4.21.120", "3.4.22.1",
   "3.4.22.2", "3.4.22.3", "3.4.22.6", "3.4.22.7", "3.4.22.8",
   "3.4.22.10", "3.4.22.14", "3.4.22.15", "3.4.22.16", "3.4.22.24",
@@ -16399,15 +17237,16 @@ static CharPtr ecnum_specif [] = {
   "3.4.22.50", "3.4.22.51", "3.4.22.52", "3.4.22.53", "3.4.22.54",
   "3.4.22.55", "3.4.22.56", "3.4.22.57", "3.4.22.58", "3.4.22.59",
   "3.4.22.60", "3.4.22.61", "3.4.22.62", "3.4.22.63", "3.4.22.64",
-  "3.4.22.65", "3.4.22.66", "3.4.22.67", "3.4.22.68", "3.4.23.1",
-  "3.4.23.2", "3.4.23.3", "3.4.23.4", "3.4.23.5", "3.4.23.12",
-  "3.4.23.15", "3.4.23.16", "3.4.23.17", "3.4.23.18", "3.4.23.19",
-  "3.4.23.20", "3.4.23.21", "3.4.23.22", "3.4.23.23", "3.4.23.24",
-  "3.4.23.25", "3.4.23.26", "3.4.23.28", "3.4.23.29", "3.4.23.30",
-  "3.4.23.31", "3.4.23.32", "3.4.23.34", "3.4.23.35", "3.4.23.36",
-  "3.4.23.38", "3.4.23.39", "3.4.23.40", "3.4.23.41", "3.4.23.42",
-  "3.4.23.43", "3.4.23.44", "3.4.23.45", "3.4.23.46", "3.4.23.47",
-  "3.4.23.48", "3.4.23.49", "3.4.24.1", "3.4.24.3", "3.4.24.6",
+  "3.4.22.65", "3.4.22.66", "3.4.22.67", "3.4.22.68", "3.4.22.69",
+  "3.4.22.70", "3.4.22.71", "3.4.23.1", "3.4.23.2", "3.4.23.3",
+  "3.4.23.4", "3.4.23.5", "3.4.23.12", "3.4.23.15", "3.4.23.16",
+  "3.4.23.17", "3.4.23.18", "3.4.23.19", "3.4.23.20", "3.4.23.21",
+  "3.4.23.22", "3.4.23.23", "3.4.23.24", "3.4.23.25", "3.4.23.26",
+  "3.4.23.28", "3.4.23.29", "3.4.23.30", "3.4.23.31", "3.4.23.32",
+  "3.4.23.34", "3.4.23.35", "3.4.23.36", "3.4.23.38", "3.4.23.39",
+  "3.4.23.40", "3.4.23.41", "3.4.23.42", "3.4.23.43", "3.4.23.44",
+  "3.4.23.45", "3.4.23.46", "3.4.23.47", "3.4.23.48", "3.4.23.49",
+  "3.4.23.50", "3.4.23.51", "3.4.24.1", "3.4.24.3", "3.4.24.6",
   "3.4.24.7", "3.4.24.11", "3.4.24.12", "3.4.24.13", "3.4.24.14",
   "3.4.24.15", "3.4.24.16", "3.4.24.17", "3.4.24.18", "3.4.24.19",
   "3.4.24.20", "3.4.24.21", "3.4.24.22", "3.4.24.23", "3.4.24.24",
@@ -16423,193 +17262,204 @@ static CharPtr ecnum_specif [] = {
   "3.4.24.70", "3.4.24.71", "3.4.24.72", "3.4.24.73", "3.4.24.74",
   "3.4.24.75", "3.4.24.76", "3.4.24.77", "3.4.24.78", "3.4.24.79",
   "3.4.24.80", "3.4.24.81", "3.4.24.82", "3.4.24.83", "3.4.24.84",
-  "3.4.24.85", "3.4.24.86", "3.4.25.1", "3.5.1.1", "3.5.1.2", "3.5.1.3",
-  "3.5.1.4", "3.5.1.5", "3.5.1.6", "3.5.1.7", "3.5.1.8", "3.5.1.9",
-  "3.5.1.10", "3.5.1.11", "3.5.1.12", "3.5.1.13", "3.5.1.14",
-  "3.5.1.15", "3.5.1.16", "3.5.1.17", "3.5.1.18", "3.5.1.19",
-  "3.5.1.20", "3.5.1.21", "3.5.1.22", "3.5.1.23", "3.5.1.24",
-  "3.5.1.25", "3.5.1.26", "3.5.1.27", "3.5.1.28", "3.5.1.29",
-  "3.5.1.30", "3.5.1.31", "3.5.1.32", "3.5.1.33", "3.5.1.35",
-  "3.5.1.36", "3.5.1.38", "3.5.1.39", "3.5.1.40", "3.5.1.41",
-  "3.5.1.42", "3.5.1.43", "3.5.1.44", "3.5.1.46", "3.5.1.47",
-  "3.5.1.48", "3.5.1.49", "3.5.1.50", "3.5.1.51", "3.5.1.52",
-  "3.5.1.53", "3.5.1.54", "3.5.1.55", "3.5.1.56", "3.5.1.57",
-  "3.5.1.58", "3.5.1.59", "3.5.1.60", "3.5.1.61", "3.5.1.62",
-  "3.5.1.63", "3.5.1.64", "3.5.1.65", "3.5.1.66", "3.5.1.67",
-  "3.5.1.68", "3.5.1.69", "3.5.1.70", "3.5.1.71", "3.5.1.72",
-  "3.5.1.73", "3.5.1.74", "3.5.1.75", "3.5.1.76", "3.5.1.77",
-  "3.5.1.78", "3.5.1.79", "3.5.1.81", "3.5.1.82", "3.5.1.83",
-  "3.5.1.84", "3.5.1.85", "3.5.1.86", "3.5.1.87", "3.5.1.88",
-  "3.5.1.89", "3.5.1.90", "3.5.1.91", "3.5.1.92", "3.5.1.93",
-  "3.5.1.94", "3.5.1.95", "3.5.1.96", "3.5.1.97", "3.5.1.98", "3.5.2.1",
-  "3.5.2.2", "3.5.2.3", "3.5.2.4", "3.5.2.5", "3.5.2.6", "3.5.2.7",
-  "3.5.2.9", "3.5.2.10", "3.5.2.11", "3.5.2.12", "3.5.2.13", "3.5.2.14",
-  "3.5.2.15", "3.5.2.16", "3.5.2.17", "3.5.2.18", "3.5.3.1", "3.5.3.2",
-  "3.5.3.3", "3.5.3.4", "3.5.3.5", "3.5.3.6", "3.5.3.7", "3.5.3.8",
-  "3.5.3.9", "3.5.3.10", "3.5.3.11", "3.5.3.12", "3.5.3.13", "3.5.3.14",
+  "3.4.24.85", "3.4.24.86", "3.4.24.87", "3.4.25.1", "3.4.25.2",
+  "3.5.1.1", "3.5.1.2", "3.5.1.3", "3.5.1.4", "3.5.1.5", "3.5.1.6",
+  "3.5.1.7", "3.5.1.8", "3.5.1.9", "3.5.1.10", "3.5.1.11", "3.5.1.12",
+  "3.5.1.13", "3.5.1.14", "3.5.1.15", "3.5.1.16", "3.5.1.17",
+  "3.5.1.18", "3.5.1.19", "3.5.1.20", "3.5.1.21", "3.5.1.22",
+  "3.5.1.23", "3.5.1.24", "3.5.1.25", "3.5.1.26", "3.5.1.27",
+  "3.5.1.28", "3.5.1.29", "3.5.1.30", "3.5.1.31", "3.5.1.32",
+  "3.5.1.33", "3.5.1.35", "3.5.1.36", "3.5.1.38", "3.5.1.39",
+  "3.5.1.40", "3.5.1.41", "3.5.1.42", "3.5.1.43", "3.5.1.44",
+  "3.5.1.46", "3.5.1.47", "3.5.1.48", "3.5.1.49", "3.5.1.50",
+  "3.5.1.51", "3.5.1.52", "3.5.1.53", "3.5.1.54", "3.5.1.55",
+  "3.5.1.56", "3.5.1.57", "3.5.1.58", "3.5.1.59", "3.5.1.60",
+  "3.5.1.61", "3.5.1.62", "3.5.1.63", "3.5.1.64", "3.5.1.65",
+  "3.5.1.66", "3.5.1.67", "3.5.1.68", "3.5.1.69", "3.5.1.70",
+  "3.5.1.71", "3.5.1.72", "3.5.1.73", "3.5.1.74", "3.5.1.75",
+  "3.5.1.76", "3.5.1.77", "3.5.1.78", "3.5.1.79", "3.5.1.81",
+  "3.5.1.82", "3.5.1.83", "3.5.1.84", "3.5.1.85", "3.5.1.86",
+  "3.5.1.87", "3.5.1.88", "3.5.1.89", "3.5.1.90", "3.5.1.91",
+  "3.5.1.92", "3.5.1.93", "3.5.1.94", "3.5.1.95", "3.5.1.96",
+  "3.5.1.97", "3.5.1.98", "3.5.1.99", "3.5.1.100", "3.5.1.101",
+  "3.5.1.102", "3.5.1.103", "3.5.2.1", "3.5.2.2", "3.5.2.3",
+  "3.5.2.4", "3.5.2.5", "3.5.2.6", "3.5.2.7", "3.5.2.9", "3.5.2.10",
+  "3.5.2.11", "3.5.2.12", "3.5.2.13", "3.5.2.14", "3.5.2.15",
+  "3.5.2.16", "3.5.2.17", "3.5.2.18", "3.5.3.1", "3.5.3.2", "3.5.3.3",
+  "3.5.3.4", "3.5.3.5", "3.5.3.6", "3.5.3.7", "3.5.3.8", "3.5.3.9",
+  "3.5.3.10", "3.5.3.11", "3.5.3.12", "3.5.3.13", "3.5.3.14",
   "3.5.3.15", "3.5.3.16", "3.5.3.17", "3.5.3.18", "3.5.3.19",
-  "3.5.3.20", "3.5.3.21", "3.5.3.22", "3.5.3.23", "3.5.4.1", "3.5.4.2",
-  "3.5.4.3", "3.5.4.4", "3.5.4.5", "3.5.4.6", "3.5.4.7", "3.5.4.8",
-  "3.5.4.9", "3.5.4.10", "3.5.4.11", "3.5.4.12", "3.5.4.13", "3.5.4.14",
-  "3.5.4.15", "3.5.4.16", "3.5.4.17", "3.5.4.18", "3.5.4.19",
-  "3.5.4.20", "3.5.4.21", "3.5.4.22", "3.5.4.23", "3.5.4.24",
-  "3.5.4.25", "3.5.4.26", "3.5.4.27", "3.5.4.28", "3.5.4.29",
-  "3.5.4.30", "3.5.5.1", "3.5.5.2", "3.5.5.4", "3.5.5.5", "3.5.5.6",
-  "3.5.5.7", "3.5.5.8", "3.5.99.1", "3.5.99.2", "3.5.99.3", "3.5.99.4",
-  "3.5.99.5", "3.5.99.6", "3.5.99.7", "3.6.1.1", "3.6.1.2", "3.6.1.3",
-  "3.6.1.5", "3.6.1.6", "3.6.1.7", "3.6.1.8", "3.6.1.9", "3.6.1.10",
-  "3.6.1.11", "3.6.1.12", "3.6.1.13", "3.6.1.14", "3.6.1.15",
-  "3.6.1.16", "3.6.1.17", "3.6.1.18", "3.6.1.19", "3.6.1.20",
-  "3.6.1.21", "3.6.1.22", "3.6.1.23", "3.6.1.24", "3.6.1.25",
-  "3.6.1.26", "3.6.1.27", "3.6.1.28", "3.6.1.29", "3.6.1.30",
-  "3.6.1.31", "3.6.1.39", "3.6.1.40", "3.6.1.41", "3.6.1.42",
-  "3.6.1.43", "3.6.1.44", "3.6.1.45", "3.6.1.52", "3.6.1.53", "3.6.2.1",
-  "3.6.2.2", "3.6.3.1", "3.6.3.2", "3.6.3.3", "3.6.3.4", "3.6.3.5",
-  "3.6.3.6", "3.6.3.7", "3.6.3.8", "3.6.3.9", "3.6.3.10", "3.6.3.11",
-  "3.6.3.12", "3.6.3.14", "3.6.3.15", "3.6.3.16", "3.6.3.17",
-  "3.6.3.18", "3.6.3.19", "3.6.3.20", "3.6.3.21", "3.6.3.22",
-  "3.6.3.23", "3.6.3.24", "3.6.3.25", "3.6.3.26", "3.6.3.27",
-  "3.6.3.28", "3.6.3.29", "3.6.3.30", "3.6.3.31", "3.6.3.32",
-  "3.6.3.33", "3.6.3.34", "3.6.3.35", "3.6.3.36", "3.6.3.37",
-  "3.6.3.38", "3.6.3.39", "3.6.3.40", "3.6.3.41", "3.6.3.42",
-  "3.6.3.43", "3.6.3.44", "3.6.3.46", "3.6.3.47", "3.6.3.48",
-  "3.6.3.49", "3.6.3.50", "3.6.3.51", "3.6.3.52", "3.6.3.53", "3.6.4.1",
+  "3.5.3.20", "3.5.3.21", "3.5.3.22", "3.5.3.23", "3.5.4.1",
+  "3.5.4.2", "3.5.4.3", "3.5.4.4", "3.5.4.5", "3.5.4.6", "3.5.4.7",
+  "3.5.4.8", "3.5.4.9", "3.5.4.10", "3.5.4.11", "3.5.4.12",
+  "3.5.4.13", "3.5.4.14", "3.5.4.15", "3.5.4.16", "3.5.4.17",
+  "3.5.4.18", "3.5.4.19", "3.5.4.20", "3.5.4.21", "3.5.4.22",
+  "3.5.4.23", "3.5.4.24", "3.5.4.25", "3.5.4.26", "3.5.4.27",
+  "3.5.4.28", "3.5.4.29", "3.5.4.30", "3.5.5.1", "3.5.5.2", "3.5.5.4",
+  "3.5.5.5", "3.5.5.6", "3.5.5.7", "3.5.5.8", "3.5.99.1", "3.5.99.2",
+  "3.5.99.3", "3.5.99.4", "3.5.99.5", "3.5.99.6", "3.5.99.7",
+  "3.6.1.1", "3.6.1.2", "3.6.1.3", "3.6.1.5", "3.6.1.6", "3.6.1.7",
+  "3.6.1.8", "3.6.1.9", "3.6.1.10", "3.6.1.11", "3.6.1.12",
+  "3.6.1.13", "3.6.1.14", "3.6.1.15", "3.6.1.16", "3.6.1.17",
+  "3.6.1.18", "3.6.1.19", "3.6.1.20", "3.6.1.21", "3.6.1.22",
+  "3.6.1.23", "3.6.1.24", "3.6.1.25", "3.6.1.26", "3.6.1.27",
+  "3.6.1.28", "3.6.1.29", "3.6.1.30", "3.6.1.31", "3.6.1.39",
+  "3.6.1.40", "3.6.1.41", "3.6.1.42", "3.6.1.43", "3.6.1.44",
+  "3.6.1.45", "3.6.1.52", "3.6.1.53", "3.6.2.1", "3.6.2.2", "3.6.3.1",
+  "3.6.3.2", "3.6.3.3", "3.6.3.4", "3.6.3.5", "3.6.3.6", "3.6.3.7",
+  "3.6.3.8", "3.6.3.9", "3.6.3.10", "3.6.3.11", "3.6.3.12",
+  "3.6.3.14", "3.6.3.15", "3.6.3.16", "3.6.3.17", "3.6.3.18",
+  "3.6.3.19", "3.6.3.20", "3.6.3.21", "3.6.3.22", "3.6.3.23",
+  "3.6.3.24", "3.6.3.25", "3.6.3.26", "3.6.3.27", "3.6.3.28",
+  "3.6.3.29", "3.6.3.30", "3.6.3.31", "3.6.3.32", "3.6.3.33",
+  "3.6.3.34", "3.6.3.35", "3.6.3.36", "3.6.3.37", "3.6.3.38",
+  "3.6.3.39", "3.6.3.40", "3.6.3.41", "3.6.3.42", "3.6.3.43",
+  "3.6.3.44", "3.6.3.46", "3.6.3.47", "3.6.3.48", "3.6.3.49",
+  "3.6.3.50", "3.6.3.51", "3.6.3.52", "3.6.3.53", "3.6.4.1",
   "3.6.4.2", "3.6.4.3", "3.6.4.4", "3.6.4.5", "3.6.4.6", "3.6.4.7",
-  "3.6.4.8", "3.6.4.9", "3.6.4.10", "3.6.4.11", "3.6.5.1", "3.6.5.2",
-  "3.6.5.3", "3.6.5.4", "3.6.5.5", "3.6.5.6", "3.7.1.1", "3.7.1.2",
-  "3.7.1.3", "3.7.1.4", "3.7.1.5", "3.7.1.6", "3.7.1.7", "3.7.1.8",
-  "3.7.1.9", "3.7.1.10", "3.8.1.1", "3.8.1.2", "3.8.1.3", "3.8.1.5",
-  "3.8.1.6", "3.8.1.7", "3.8.1.8", "3.8.1.9", "3.8.1.10", "3.8.1.11",
-  "3.9.1.1", "3.10.1.1", "3.10.1.2", "3.11.1.1", "3.11.1.2", "3.11.1.3",
-  "3.12.1.1", "3.13.1.1", "3.13.1.3", "4.1.1.1", "4.1.1.2", "4.1.1.3",
-  "4.1.1.4", "4.1.1.5", "4.1.1.6", "4.1.1.7", "4.1.1.8", "4.1.1.9",
-  "4.1.1.11", "4.1.1.12", "4.1.1.14", "4.1.1.15", "4.1.1.16",
-  "4.1.1.17", "4.1.1.18", "4.1.1.19", "4.1.1.20", "4.1.1.21",
-  "4.1.1.22", "4.1.1.23", "4.1.1.24", "4.1.1.25", "4.1.1.28",
-  "4.1.1.29", "4.1.1.30", "4.1.1.31", "4.1.1.32", "4.1.1.33",
-  "4.1.1.34", "4.1.1.35", "4.1.1.36", "4.1.1.37", "4.1.1.38",
-  "4.1.1.39", "4.1.1.40", "4.1.1.41", "4.1.1.42", "4.1.1.43",
-  "4.1.1.44", "4.1.1.45", "4.1.1.46", "4.1.1.47", "4.1.1.48",
-  "4.1.1.49", "4.1.1.50", "4.1.1.51", "4.1.1.52", "4.1.1.53",
-  "4.1.1.54", "4.1.1.55", "4.1.1.56", "4.1.1.57", "4.1.1.58",
-  "4.1.1.59", "4.1.1.60", "4.1.1.61", "4.1.1.62", "4.1.1.63",
-  "4.1.1.64", "4.1.1.65", "4.1.1.66", "4.1.1.67", "4.1.1.68",
-  "4.1.1.69", "4.1.1.70", "4.1.1.71", "4.1.1.72", "4.1.1.73",
-  "4.1.1.74", "4.1.1.75", "4.1.1.76", "4.1.1.77", "4.1.1.78",
-  "4.1.1.79", "4.1.1.80", "4.1.1.81", "4.1.1.82", "4.1.1.83",
-  "4.1.1.84", "4.1.1.85", "4.1.1.86", "4.1.1.87", "4.1.1.88",
-  "4.1.1.89", "4.1.2.2", "4.1.2.4", "4.1.2.5", "4.1.2.8", "4.1.2.9",
+  "3.6.4.8", "3.6.4.9", "3.6.4.10", "3.6.4.11", "3.6.4.12",
+  "3.6.4.13", "3.6.5.1", "3.6.5.2", "3.6.5.3", "3.6.5.4", "3.6.5.5",
+  "3.6.5.6", "3.7.1.1", "3.7.1.2", "3.7.1.3", "3.7.1.4", "3.7.1.5",
+  "3.7.1.6", "3.7.1.7", "3.7.1.8", "3.7.1.9", "3.7.1.10", "3.7.1.11",
+  "3.8.1.1", "3.8.1.2", "3.8.1.3", "3.8.1.5", "3.8.1.6", "3.8.1.7",
+  "3.8.1.8", "3.8.1.9", "3.8.1.10", "3.8.1.11", "3.9.1.1", "3.10.1.1",
+  "3.10.1.2", "3.11.1.1", "3.11.1.2", "3.11.1.3", "3.12.1.1",
+  "3.13.1.1", "3.13.1.3", "4.1.1.1", "4.1.1.2", "4.1.1.3", "4.1.1.4",
+  "4.1.1.5", "4.1.1.6", "4.1.1.7", "4.1.1.8", "4.1.1.9", "4.1.1.11",
+  "4.1.1.12", "4.1.1.14", "4.1.1.15", "4.1.1.16", "4.1.1.17",
+  "4.1.1.18", "4.1.1.19", "4.1.1.20", "4.1.1.21", "4.1.1.22",
+  "4.1.1.23", "4.1.1.24", "4.1.1.25", "4.1.1.28", "4.1.1.29",
+  "4.1.1.30", "4.1.1.31", "4.1.1.32", "4.1.1.33", "4.1.1.34",
+  "4.1.1.35", "4.1.1.36", "4.1.1.37", "4.1.1.38", "4.1.1.39",
+  "4.1.1.40", "4.1.1.41", "4.1.1.42", "4.1.1.43", "4.1.1.44",
+  "4.1.1.45", "4.1.1.46", "4.1.1.47", "4.1.1.48", "4.1.1.49",
+  "4.1.1.50", "4.1.1.51", "4.1.1.52", "4.1.1.53", "4.1.1.54",
+  "4.1.1.55", "4.1.1.56", "4.1.1.57", "4.1.1.58", "4.1.1.59",
+  "4.1.1.60", "4.1.1.61", "4.1.1.62", "4.1.1.63", "4.1.1.64",
+  "4.1.1.65", "4.1.1.66", "4.1.1.67", "4.1.1.68", "4.1.1.69",
+  "4.1.1.70", "4.1.1.71", "4.1.1.72", "4.1.1.73", "4.1.1.74",
+  "4.1.1.75", "4.1.1.76", "4.1.1.77", "4.1.1.78", "4.1.1.79",
+  "4.1.1.80", "4.1.1.81", "4.1.1.82", "4.1.1.83", "4.1.1.84",
+  "4.1.1.85", "4.1.1.86", "4.1.1.87", "4.1.1.88", "4.1.1.89",
+  "4.1.1.90", "4.1.2.2", "4.1.2.4", "4.1.2.5", "4.1.2.8", "4.1.2.9",
   "4.1.2.10", "4.1.2.11", "4.1.2.12", "4.1.2.13", "4.1.2.14",
   "4.1.2.17", "4.1.2.18", "4.1.2.19", "4.1.2.20", "4.1.2.21",
   "4.1.2.22", "4.1.2.23", "4.1.2.24", "4.1.2.25", "4.1.2.26",
   "4.1.2.27", "4.1.2.28", "4.1.2.29", "4.1.2.30", "4.1.2.32",
   "4.1.2.33", "4.1.2.34", "4.1.2.35", "4.1.2.36", "4.1.2.37",
-  "4.1.2.38", "4.1.2.40", "4.1.2.41", "4.1.2.42", "4.1.2.43", "4.1.3.1",
-  "4.1.3.3", "4.1.3.4", "4.1.3.6", "4.1.3.13", "4.1.3.14", "4.1.3.16",
-  "4.1.3.17", "4.1.3.22", "4.1.3.24", "4.1.3.25", "4.1.3.26",
-  "4.1.3.27", "4.1.3.30", "4.1.3.32", "4.1.3.34", "4.1.3.35",
-  "4.1.3.36", "4.1.3.38", "4.1.3.39", "4.1.3.40", "4.1.99.1",
-  "4.1.99.2", "4.1.99.3", "4.1.99.5", "4.1.99.11", "4.1.99.12",
-  "4.2.1.1", "4.2.1.2", "4.2.1.3", "4.2.1.4", "4.2.1.5", "4.2.1.6",
-  "4.2.1.7", "4.2.1.8", "4.2.1.9", "4.2.1.10", "4.2.1.11", "4.2.1.12",
-  "4.2.1.17", "4.2.1.18", "4.2.1.19", "4.2.1.20", "4.2.1.22",
-  "4.2.1.24", "4.2.1.25", "4.2.1.27", "4.2.1.28", "4.2.1.30",
-  "4.2.1.31", "4.2.1.32", "4.2.1.33", "4.2.1.34", "4.2.1.35",
-  "4.2.1.36", "4.2.1.39", "4.2.1.40", "4.2.1.41", "4.2.1.42",
-  "4.2.1.43", "4.2.1.44", "4.2.1.45", "4.2.1.46", "4.2.1.47",
-  "4.2.1.48", "4.2.1.49", "4.2.1.50", "4.2.1.51", "4.2.1.52",
-  "4.2.1.53", "4.2.1.54", "4.2.1.55", "4.2.1.56", "4.2.1.57",
-  "4.2.1.58", "4.2.1.59", "4.2.1.60", "4.2.1.61", "4.2.1.62",
-  "4.2.1.65", "4.2.1.66", "4.2.1.67", "4.2.1.68", "4.2.1.69",
-  "4.2.1.70", "4.2.1.73", "4.2.1.74", "4.2.1.75", "4.2.1.76",
-  "4.2.1.77", "4.2.1.78", "4.2.1.79", "4.2.1.80", "4.2.1.81",
-  "4.2.1.82", "4.2.1.83", "4.2.1.84", "4.2.1.85", "4.2.1.87",
-  "4.2.1.88", "4.2.1.89", "4.2.1.90", "4.2.1.91", "4.2.1.92",
-  "4.2.1.93", "4.2.1.94", "4.2.1.95", "4.2.1.96", "4.2.1.97",
-  "4.2.1.98", "4.2.1.99", "4.2.1.100", "4.2.1.101", "4.2.1.103",
-  "4.2.1.104", "4.2.1.105", "4.2.1.106", "4.2.1.107", "4.2.1.108",
-  "4.2.1.109", "4.2.1.110", "4.2.1.111", "4.2.1.112", "4.2.1.113",
-  "4.2.1.114", "4.2.1.115", "4.2.2.1", "4.2.2.2", "4.2.2.3", "4.2.2.5",
-  "4.2.2.6", "4.2.2.7", "4.2.2.8", "4.2.2.9", "4.2.2.10", "4.2.2.11",
-  "4.2.2.12", "4.2.2.13", "4.2.2.14", "4.2.2.15", "4.2.2.16",
-  "4.2.2.17", "4.2.2.18", "4.2.2.19", "4.2.2.20", "4.2.2.21",
-  "4.2.2.22", "4.2.3.1", "4.2.3.2", "4.2.3.3", "4.2.3.4", "4.2.3.5",
-  "4.2.3.6", "4.2.3.7", "4.2.3.8", "4.2.3.9", "4.2.3.10", "4.2.3.11",
-  "4.2.3.12", "4.2.3.13", "4.2.3.14", "4.2.3.15", "4.2.3.16",
-  "4.2.3.17", "4.2.3.18", "4.2.3.19", "4.2.3.20", "4.2.3.21",
-  "4.2.3.22", "4.2.3.23", "4.2.3.24", "4.2.3.25", "4.2.3.26",
-  "4.2.3.27", "4.2.3.28", "4.2.3.29", "4.2.3.30", "4.2.3.31",
-  "4.2.3.32", "4.2.3.33", "4.2.3.34", "4.2.3.35", "4.2.3.36",
-  "4.2.3.37", "4.2.3.38", "4.2.3.39", "4.2.3.40", "4.2.99.12",
-  "4.2.99.18", "4.2.99.20", "4.3.1.1", "4.3.1.2", "4.3.1.3", "4.3.1.4",
-  "4.3.1.6", "4.3.1.7", "4.3.1.9", "4.3.1.10", "4.3.1.12", "4.3.1.13",
-  "4.3.1.14", "4.3.1.15", "4.3.1.16", "4.3.1.17", "4.3.1.18",
-  "4.3.1.19", "4.3.1.20", "4.3.1.22", "4.3.1.23", "4.3.1.24",
-  "4.3.1.25", "4.3.2.1", "4.3.2.2", "4.3.2.3", "4.3.2.4", "4.3.2.5",
-  "4.3.3.1", "4.3.3.2", "4.3.3.3", "4.3.3.4", "4.3.99.2", "4.4.1.1",
+  "4.1.2.38", "4.1.2.40", "4.1.2.41", "4.1.2.42", "4.1.2.43",
+  "4.1.2.44", "4.1.2.45", "4.1.3.1", "4.1.3.3", "4.1.3.4", "4.1.3.6",
+  "4.1.3.13", "4.1.3.14", "4.1.3.16", "4.1.3.17", "4.1.3.22",
+  "4.1.3.24", "4.1.3.25", "4.1.3.26", "4.1.3.27", "4.1.3.30",
+  "4.1.3.32", "4.1.3.34", "4.1.3.35", "4.1.3.36", "4.1.3.38",
+  "4.1.3.39", "4.1.3.40", "4.1.99.1", "4.1.99.2", "4.1.99.3",
+  "4.1.99.5", "4.1.99.11", "4.1.99.12", "4.1.99.13", "4.1.99.14",
+  "4.1.99.15", "4.2.1.1", "4.2.1.2", "4.2.1.3", "4.2.1.4", "4.2.1.5",
+  "4.2.1.6", "4.2.1.7", "4.2.1.8", "4.2.1.9", "4.2.1.10", "4.2.1.11",
+  "4.2.1.12", "4.2.1.17", "4.2.1.18", "4.2.1.19", "4.2.1.20",
+  "4.2.1.22", "4.2.1.24", "4.2.1.25", "4.2.1.27", "4.2.1.28",
+  "4.2.1.30", "4.2.1.31", "4.2.1.32", "4.2.1.33", "4.2.1.34",
+  "4.2.1.35", "4.2.1.36", "4.2.1.39", "4.2.1.40", "4.2.1.41",
+  "4.2.1.42", "4.2.1.43", "4.2.1.44", "4.2.1.45", "4.2.1.46",
+  "4.2.1.47", "4.2.1.48", "4.2.1.49", "4.2.1.50", "4.2.1.51",
+  "4.2.1.52", "4.2.1.53", "4.2.1.54", "4.2.1.55", "4.2.1.56",
+  "4.2.1.57", "4.2.1.58", "4.2.1.59", "4.2.1.60", "4.2.1.61",
+  "4.2.1.62", "4.2.1.65", "4.2.1.66", "4.2.1.67", "4.2.1.68",
+  "4.2.1.69", "4.2.1.70", "4.2.1.73", "4.2.1.74", "4.2.1.75",
+  "4.2.1.76", "4.2.1.77", "4.2.1.78", "4.2.1.79", "4.2.1.80",
+  "4.2.1.81", "4.2.1.82", "4.2.1.83", "4.2.1.84", "4.2.1.85",
+  "4.2.1.87", "4.2.1.88", "4.2.1.89", "4.2.1.90", "4.2.1.91",
+  "4.2.1.92", "4.2.1.93", "4.2.1.94", "4.2.1.95", "4.2.1.96",
+  "4.2.1.97", "4.2.1.98", "4.2.1.99", "4.2.1.100", "4.2.1.101",
+  "4.2.1.103", "4.2.1.104", "4.2.1.105", "4.2.1.106", "4.2.1.107",
+  "4.2.1.108", "4.2.1.109", "4.2.1.110", "4.2.1.111", "4.2.1.112",
+  "4.2.1.113", "4.2.1.114", "4.2.1.115", "4.2.1.116", "4.2.1.117",
+  "4.2.1.118", "4.2.1.119", "4.2.1.120", "4.2.2.1", "4.2.2.2",
+  "4.2.2.3", "4.2.2.5", "4.2.2.6", "4.2.2.7", "4.2.2.8", "4.2.2.9",
+  "4.2.2.10", "4.2.2.11", "4.2.2.12", "4.2.2.13", "4.2.2.14",
+  "4.2.2.15", "4.2.2.16", "4.2.2.17", "4.2.2.18", "4.2.2.19",
+  "4.2.2.20", "4.2.2.21", "4.2.2.22", "4.2.3.1", "4.2.3.2", "4.2.3.3",
+  "4.2.3.4", "4.2.3.5", "4.2.3.6", "4.2.3.7", "4.2.3.8", "4.2.3.9",
+  "4.2.3.10", "4.2.3.11", "4.2.3.12", "4.2.3.13", "4.2.3.14",
+  "4.2.3.15", "4.2.3.16", "4.2.3.17", "4.2.3.18", "4.2.3.19",
+  "4.2.3.20", "4.2.3.21", "4.2.3.22", "4.2.3.23", "4.2.3.24",
+  "4.2.3.25", "4.2.3.26", "4.2.3.27", "4.2.3.28", "4.2.3.29",
+  "4.2.3.30", "4.2.3.31", "4.2.3.32", "4.2.3.33", "4.2.3.34",
+  "4.2.3.35", "4.2.3.36", "4.2.3.37", "4.2.3.38", "4.2.3.39",
+  "4.2.3.40", "4.2.3.41", "4.2.3.42", "4.2.3.43", "4.2.3.44",
+  "4.2.3.45", "4.2.99.12", "4.2.99.18", "4.2.99.20", "4.3.1.1",
+  "4.3.1.2", "4.3.1.3", "4.3.1.4", "4.3.1.6", "4.3.1.7", "4.3.1.9",
+  "4.3.1.10", "4.3.1.12", "4.3.1.13", "4.3.1.14", "4.3.1.15",
+  "4.3.1.16", "4.3.1.17", "4.3.1.18", "4.3.1.19", "4.3.1.20",
+  "4.3.1.22", "4.3.1.23", "4.3.1.24", "4.3.1.25", "4.3.1.26",
+  "4.3.2.1", "4.3.2.2", "4.3.2.3", "4.3.2.4", "4.3.2.5", "4.3.3.1",
+  "4.3.3.2", "4.3.3.3", "4.3.3.4", "4.3.3.5", "4.3.99.2", "4.4.1.1",
   "4.4.1.2", "4.4.1.3", "4.4.1.4", "4.4.1.5", "4.4.1.6", "4.4.1.8",
-  "4.4.1.9", "4.4.1.10", "4.4.1.11", "4.4.1.13", "4.4.1.14", "4.4.1.15",
-  "4.4.1.16", "4.4.1.17", "4.4.1.19", "4.4.1.20", "4.4.1.21",
-  "4.4.1.22", "4.4.1.23", "4.4.1.24", "4.4.1.25", "4.5.1.1", "4.5.1.2",
-  "4.5.1.3", "4.5.1.4", "4.5.1.5", "4.6.1.1", "4.6.1.2", "4.6.1.6",
-  "4.6.1.12", "4.6.1.13", "4.6.1.14", "4.6.1.15", "4.99.1.1",
-  "4.99.1.2", "4.99.1.3", "4.99.1.4", "4.99.1.5", "4.99.1.6",
-  "4.99.1.7", "5.1.1.1", "5.1.1.2", "5.1.1.3", "5.1.1.4", "5.1.1.5",
-  "5.1.1.6", "5.1.1.7", "5.1.1.8", "5.1.1.9", "5.1.1.10", "5.1.1.11",
-  "5.1.1.12", "5.1.1.13", "5.1.1.14", "5.1.1.15", "5.1.1.16",
-  "5.1.1.17", "5.1.1.18", "5.1.2.1", "5.1.2.2", "5.1.2.3", "5.1.2.4",
-  "5.1.2.5", "5.1.2.6", "5.1.3.1", "5.1.3.2", "5.1.3.3", "5.1.3.4",
-  "5.1.3.5", "5.1.3.6", "5.1.3.7", "5.1.3.8", "5.1.3.9", "5.1.3.10",
-  "5.1.3.11", "5.1.3.12", "5.1.3.13", "5.1.3.14", "5.1.3.15",
-  "5.1.3.16", "5.1.3.17", "5.1.3.18", "5.1.3.19", "5.1.3.20",
-  "5.1.3.21", "5.1.3.22", "5.1.3.23", "5.1.99.1", "5.1.99.2",
-  "5.1.99.3", "5.1.99.4", "5.1.99.5", "5.2.1.1", "5.2.1.2", "5.2.1.3",
-  "5.2.1.4", "5.2.1.5", "5.2.1.6", "5.2.1.7", "5.2.1.8", "5.2.1.9",
-  "5.2.1.10", "5.3.1.1", "5.3.1.3", "5.3.1.4", "5.3.1.5", "5.3.1.6",
-  "5.3.1.7", "5.3.1.8", "5.3.1.9", "5.3.1.12", "5.3.1.13", "5.3.1.14",
+  "4.4.1.9", "4.4.1.10", "4.4.1.11", "4.4.1.13", "4.4.1.14",
+  "4.4.1.15", "4.4.1.16", "4.4.1.17", "4.4.1.19", "4.4.1.20",
+  "4.4.1.21", "4.4.1.22", "4.4.1.23", "4.4.1.24", "4.4.1.25",
+  "4.5.1.1", "4.5.1.2", "4.5.1.3", "4.5.1.4", "4.5.1.5", "4.6.1.1",
+  "4.6.1.2", "4.6.1.6", "4.6.1.12", "4.6.1.13", "4.6.1.14",
+  "4.6.1.15", "4.99.1.1", "4.99.1.2", "4.99.1.3", "4.99.1.4",
+  "4.99.1.5", "4.99.1.6", "4.99.1.7", "4.99.1.8", "5.1.1.1",
+  "5.1.1.2", "5.1.1.3", "5.1.1.4", "5.1.1.5", "5.1.1.6", "5.1.1.7",
+  "5.1.1.8", "5.1.1.9", "5.1.1.10", "5.1.1.11", "5.1.1.12",
+  "5.1.1.13", "5.1.1.14", "5.1.1.15", "5.1.1.16", "5.1.1.17",
+  "5.1.1.18", "5.1.2.1", "5.1.2.2", "5.1.2.3", "5.1.2.4", "5.1.2.5",
+  "5.1.2.6", "5.1.3.1", "5.1.3.2", "5.1.3.3", "5.1.3.4", "5.1.3.5",
+  "5.1.3.6", "5.1.3.7", "5.1.3.8", "5.1.3.9", "5.1.3.10", "5.1.3.11",
+  "5.1.3.12", "5.1.3.13", "5.1.3.14", "5.1.3.15", "5.1.3.16",
+  "5.1.3.17", "5.1.3.18", "5.1.3.19", "5.1.3.20", "5.1.3.21",
+  "5.1.3.22", "5.1.3.23", "5.1.99.1", "5.1.99.2", "5.1.99.3",
+  "5.1.99.4", "5.1.99.5", "5.2.1.1", "5.2.1.2", "5.2.1.3", "5.2.1.4",
+  "5.2.1.5", "5.2.1.6", "5.2.1.7", "5.2.1.8", "5.2.1.9", "5.2.1.10",
+  "5.3.1.1", "5.3.1.3", "5.3.1.4", "5.3.1.5", "5.3.1.6", "5.3.1.7",
+  "5.3.1.8", "5.3.1.9", "5.3.1.12", "5.3.1.13", "5.3.1.14",
   "5.3.1.15", "5.3.1.16", "5.3.1.17", "5.3.1.20", "5.3.1.21",
   "5.3.1.22", "5.3.1.23", "5.3.1.24", "5.3.1.25", "5.3.1.26",
   "5.3.1.27", "5.3.2.1", "5.3.2.2", "5.3.3.1", "5.3.3.2", "5.3.3.3",
   "5.3.3.4", "5.3.3.5", "5.3.3.6", "5.3.3.7", "5.3.3.8", "5.3.3.9",
   "5.3.3.10", "5.3.3.11", "5.3.3.12", "5.3.3.13", "5.3.3.14",
-  "5.3.3.15", "5.3.4.1", "5.3.99.2", "5.3.99.3", "5.3.99.4", "5.3.99.5",
-  "5.3.99.6", "5.3.99.7", "5.3.99.8", "5.3.99.9", "5.4.1.1", "5.4.1.2",
-  "5.4.2.1", "5.4.2.2", "5.4.2.3", "5.4.2.4", "5.4.2.5", "5.4.2.6",
-  "5.4.2.7", "5.4.2.8", "5.4.2.9", "5.4.2.10", "5.4.3.2", "5.4.3.3",
-  "5.4.3.4", "5.4.3.5", "5.4.3.6", "5.4.3.7", "5.4.3.8", "5.4.4.1",
-  "5.4.4.2", "5.4.4.3", "5.4.99.1", "5.4.99.2", "5.4.99.3", "5.4.99.4",
-  "5.4.99.5", "5.4.99.7", "5.4.99.8", "5.4.99.9", "5.4.99.11",
-  "5.4.99.12", "5.4.99.13", "5.4.99.14", "5.4.99.15", "5.4.99.16",
-  "5.4.99.17", "5.4.99.18", "5.5.1.1", "5.5.1.2", "5.5.1.3", "5.5.1.4",
-  "5.5.1.5", "5.5.1.6", "5.5.1.7", "5.5.1.8", "5.5.1.9", "5.5.1.10",
-  "5.5.1.11", "5.5.1.12", "5.5.1.13", "5.5.1.14", "5.5.1.15",
-  "5.5.1.16", "5.99.1.1", "5.99.1.2", "5.99.1.3", "6.1.1.1", "6.1.1.2",
-  "6.1.1.3", "6.1.1.4", "6.1.1.5", "6.1.1.6", "6.1.1.7", "6.1.1.9",
-  "6.1.1.10", "6.1.1.11", "6.1.1.12", "6.1.1.13", "6.1.1.14",
-  "6.1.1.15", "6.1.1.16", "6.1.1.17", "6.1.1.18", "6.1.1.19",
-  "6.1.1.20", "6.1.1.21", "6.1.1.22", "6.1.1.23", "6.1.1.24",
-  "6.1.1.25", "6.1.1.26", "6.2.1.1", "6.2.1.2", "6.2.1.3", "6.2.1.4",
+  "5.3.3.15", "5.3.4.1", "5.3.99.2", "5.3.99.3", "5.3.99.4",
+  "5.3.99.5", "5.3.99.6", "5.3.99.7", "5.3.99.8", "5.3.99.9",
+  "5.4.1.1", "5.4.1.2", "5.4.2.1", "5.4.2.2", "5.4.2.3", "5.4.2.4",
+  "5.4.2.5", "5.4.2.6", "5.4.2.7", "5.4.2.8", "5.4.2.9", "5.4.2.10",
+  "5.4.3.2", "5.4.3.3", "5.4.3.4", "5.4.3.5", "5.4.3.6", "5.4.3.7",
+  "5.4.3.8", "5.4.4.1", "5.4.4.2", "5.4.4.3", "5.4.99.1", "5.4.99.2",
+  "5.4.99.3", "5.4.99.4", "5.4.99.5", "5.4.99.7", "5.4.99.8",
+  "5.4.99.9", "5.4.99.11", "5.4.99.12", "5.4.99.13", "5.4.99.14",
+  "5.4.99.15", "5.4.99.16", "5.4.99.17", "5.4.99.18", "5.5.1.1",
+  "5.5.1.2", "5.5.1.3", "5.5.1.4", "5.5.1.5", "5.5.1.6", "5.5.1.7",
+  "5.5.1.8", "5.5.1.9", "5.5.1.10", "5.5.1.11", "5.5.1.12",
+  "5.5.1.13", "5.5.1.14", "5.5.1.15", "5.5.1.16", "5.99.1.1",
+  "5.99.1.2", "5.99.1.3", "5.99.1.4", "6.1.1.1", "6.1.1.2", "6.1.1.3",
+  "6.1.1.4", "6.1.1.5", "6.1.1.6", "6.1.1.7", "6.1.1.9", "6.1.1.10",
+  "6.1.1.11", "6.1.1.12", "6.1.1.13", "6.1.1.14", "6.1.1.15",
+  "6.1.1.16", "6.1.1.17", "6.1.1.18", "6.1.1.19", "6.1.1.20",
+  "6.1.1.21", "6.1.1.22", "6.1.1.23", "6.1.1.24", "6.1.1.25",
+  "6.1.1.26", "6.1.1.27", "6.2.1.1", "6.2.1.2", "6.2.1.3", "6.2.1.4",
   "6.2.1.5", "6.2.1.6", "6.2.1.7", "6.2.1.8", "6.2.1.9", "6.2.1.10",
   "6.2.1.11", "6.2.1.12", "6.2.1.13", "6.2.1.14", "6.2.1.15",
   "6.2.1.16", "6.2.1.17", "6.2.1.18", "6.2.1.19", "6.2.1.20",
   "6.2.1.22", "6.2.1.23", "6.2.1.24", "6.2.1.25", "6.2.1.26",
   "6.2.1.27", "6.2.1.28", "6.2.1.30", "6.2.1.31", "6.2.1.32",
-  "6.2.1.33", "6.2.1.34", "6.2.1.35", "6.3.1.1", "6.3.1.2", "6.3.1.4",
-  "6.3.1.5", "6.3.1.6", "6.3.1.7", "6.3.1.8", "6.3.1.9", "6.3.1.10",
-  "6.3.1.11", "6.3.1.12", "6.3.2.1", "6.3.2.2", "6.3.2.3", "6.3.2.4",
-  "6.3.2.5", "6.3.2.6", "6.3.2.7", "6.3.2.8", "6.3.2.9", "6.3.2.10",
-  "6.3.2.11", "6.3.2.12", "6.3.2.13", "6.3.2.14", "6.3.2.16",
-  "6.3.2.17", "6.3.2.18", "6.3.2.19", "6.3.2.20", "6.3.2.21",
-  "6.3.2.22", "6.3.2.23", "6.3.2.24", "6.3.2.25", "6.3.2.26",
-  "6.3.2.27", "6.3.2.28", "6.3.2.29", "6.3.2.30", "6.3.3.1", "6.3.3.2",
-  "6.3.3.3", "6.3.3.4", "6.3.4.1", "6.3.4.2", "6.3.4.3", "6.3.4.4",
-  "6.3.4.5", "6.3.4.6", "6.3.4.7", "6.3.4.8", "6.3.4.9", "6.3.4.10",
-  "6.3.4.11", "6.3.4.12", "6.3.4.13", "6.3.4.14", "6.3.4.15",
-  "6.3.4.16", "6.3.4.17", "6.3.4.18", "6.3.5.1", "6.3.5.2", "6.3.5.3",
-  "6.3.5.4", "6.3.5.5", "6.3.5.6", "6.3.5.7", "6.3.5.9", "6.3.5.10",
-  "6.4.1.1", "6.4.1.2", "6.4.1.3", "6.4.1.4", "6.4.1.5", "6.4.1.6",
-  "6.4.1.7", "6.5.1.1", "6.5.1.2", "6.5.1.3", "6.5.1.4", "6.6.1.1",
-  "6.6.1.2",
+  "6.2.1.33", "6.2.1.34", "6.2.1.35", "6.2.1.36", "6.3.1.1",
+  "6.3.1.2", "6.3.1.4", "6.3.1.5", "6.3.1.6", "6.3.1.7", "6.3.1.8",
+  "6.3.1.9", "6.3.1.10", "6.3.1.11", "6.3.1.12", "6.3.1.13",
+  "6.3.2.1", "6.3.2.2", "6.3.2.3", "6.3.2.4", "6.3.2.5", "6.3.2.6",
+  "6.3.2.7", "6.3.2.8", "6.3.2.9", "6.3.2.10", "6.3.2.11", "6.3.2.12",
+  "6.3.2.13", "6.3.2.14", "6.3.2.16", "6.3.2.17", "6.3.2.18",
+  "6.3.2.19", "6.3.2.20", "6.3.2.21", "6.3.2.22", "6.3.2.23",
+  "6.3.2.24", "6.3.2.25", "6.3.2.26", "6.3.2.27", "6.3.2.28",
+  "6.3.2.29", "6.3.2.30", "6.3.2.31", "6.3.2.32", "6.3.2.33",
+  "6.3.2.34", "6.3.3.1", "6.3.3.2", "6.3.3.3", "6.3.3.4", "6.3.4.1",
+  "6.3.4.2", "6.3.4.3", "6.3.4.4", "6.3.4.5", "6.3.4.6", "6.3.4.7",
+  "6.3.4.8", "6.3.4.9", "6.3.4.10", "6.3.4.11", "6.3.4.12",
+  "6.3.4.13", "6.3.4.14", "6.3.4.15", "6.3.4.16", "6.3.4.17",
+  "6.3.4.18", "6.3.5.1", "6.3.5.2", "6.3.5.3", "6.3.5.4", "6.3.5.5",
+  "6.3.5.6", "6.3.5.7", "6.3.5.9", "6.3.5.10", "6.4.1.1", "6.4.1.2",
+  "6.4.1.3", "6.4.1.4", "6.4.1.5", "6.4.1.6", "6.4.1.7", "6.5.1.1",
+  "6.5.1.2", "6.5.1.3", "6.5.1.4", "6.6.1.1", "6.6.1.2",
   NULL
 };
 
@@ -16731,8 +17581,12 @@ static Boolean ValidateECnumber (CharPtr str)
       ptr++;
       ch = *ptr;
     } else if (ch == 'n') {
+      if (numperiods == 3 && numdigits == 0 && IS_DIGIT(*(ptr + 1))) {
+        /* allow/ignore n in first position of fourth number to not mean ambiguous, if followed by digit */
+      } else {
       numdashes++;
       is_ambig = TRUE;
+      }
       ptr++;
       ch = *ptr;
     } else if (ch == '.') {
@@ -17042,7 +17896,7 @@ static void ValidateRptUnit (ValidStructPtr vsp, GatherContextPtr gcp, SeqFeatPt
   if (StringICmp (key,"repeat_region") == 0 && qual == GBQUAL_rpt_unit_seq && ! multi_rpt_unit) {
     if (StringLen (gbqual->val) <= SeqLocLen (sfp->location)) {
       just_nuc_letters = TRUE;
-      for (ptr = gbqual->val, ch = *ptr; ch != '\0'; ptr++, ch = *ptr) {
+      for (ptr = gbqual->val, ch = *ptr; ch != '\0' && just_nuc_letters; ptr++, ch = *ptr) {
         if (StringChr ("ACGTNacgtn", ch) == NULL) {
           just_nuc_letters = FALSE;
         }
@@ -17896,7 +18750,7 @@ static Boolean PartialAtSpliceSiteOrGap (ValidStructPtr vsp, SeqLocPtr head, Uin
         *isgapP = TRUE;
       }
       rsult = TRUE;
-    } else if (IS_residue (residue1) && IS_residue (residue2)) {
+    } else if (IS_residue (residue1) && IS_residue (residue2) && IS_ALPHA ((Char) residue1) && IS_ALPHA ((Char) residue2)) {
       if ((residue1 == 'A') && (residue2 == 'G')) {
         rsult = TRUE;
       }
@@ -18470,7 +19324,7 @@ static BioseqSetPtr GetParentNPS (BioseqPtr bsp)
   while (bssp != NULL && bssp->_class != BioseqseqSet_class_nuc_prot && bssp->idx.parenttype == OBJ_BIOSEQSET) {
     bssp = (BioseqSetPtr) bssp->idx.parentptr;
   }
-  if (bssp->_class == BioseqseqSet_class_nuc_prot)
+  if (bssp != NULL && bssp->_class == BioseqseqSet_class_nuc_prot)
     return bssp;
   return NULL;
 }
@@ -19009,7 +19863,7 @@ static Boolean OverlappingGeneIsPseudo (SeqFeatPtr sfp)
   return FALSE;
 }
 
-static void CheckForIllegalDbxref (ValidStructPtr vsp, GatherContextPtr gcp, SeqFeatPtr sfp, ValNodePtr dbxref)
+static void CheckForIllegalDbxref (ValidStructPtr vsp, GatherContextPtr gcp, ValNodePtr dbxref)
 
 {
   DbtagPtr     db;
@@ -19125,6 +19979,7 @@ static CharPtr legal_exception_strings [] = {
   "heterogeneous population sequenced",
   "low-quality sequence region",
   "unextendable partial coding region",
+  "artificial location",
   NULL
 };
 
@@ -19140,13 +19995,17 @@ static CharPtr refseq_exception_strings [] = {
 static void ValidateExceptText (ValidStructPtr vsp, GatherContextPtr gcp, SeqFeatPtr sfp)
 
 {
+  Boolean    art_loc_except = FALSE;
   Boolean  found;
+  GBQualPtr  gbq;
   Int2     i;
+  Boolean    has_inference = FALSE;
   CharPtr  ptr;
   Boolean  reasons_given_except = FALSE;
   Boolean  redundant_with_comment = FALSE;
   Boolean  refseq_except = FALSE;
   ErrSev   sev = SEV_ERROR;
+  Boolean    trans_prot_except = FALSE;
   CharPtr  str;
   CharPtr  tmp;
 
@@ -19166,6 +20025,10 @@ static void ValidateExceptText (ValidStructPtr vsp, GatherContextPtr gcp, SeqFea
         found = TRUE;
         if (StringICmp (tmp, "reasons given in citation") == 0) {
           reasons_given_except = TRUE;
+        } else if (StringICmp (tmp, "annotated by transcript or proteomic data") == 0) {
+          trans_prot_except = TRUE;
+        } else if (StringICmp (tmp, "artificial location") == 0) {
+          art_loc_except = TRUE;
         }
         break;
       }
@@ -19188,7 +20051,9 @@ static void ValidateExceptText (ValidStructPtr vsp, GatherContextPtr gcp, SeqFea
       }
     }
     if (sfp->comment != NULL && StringISearch (sfp->comment, tmp) != NULL) {
-      if (StringICmp (tmp, "ribosomal slippage") != 0 && StringICmp (tmp, "trans-splicing") != 0) {
+      if (StringICmp (tmp, "ribosomal slippage") != 0 &&
+          StringICmp (tmp, "trans-splicing") != 0 &&
+          StringICmp (tmp, "artificial location") != 0) {
         redundant_with_comment = TRUE;
       } else if (StringICmp (sfp->comment, tmp) == 0) {
         redundant_with_comment = TRUE;
@@ -19210,12 +20075,31 @@ static void ValidateExceptText (ValidStructPtr vsp, GatherContextPtr gcp, SeqFea
       }
     }
     if (! found) {
+      if (! vsp->is_gpipe_in_sep) {
       ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_ExceptionProblem, "Genome processing exception should not be combined with other explanations");
     }
   }
+  }
   if (reasons_given_except && sfp->cit == NULL) {
     ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_ExceptionProblem, "Reasons given in citation exception does not have the required citation");
   }
+  if (trans_prot_except) {
+    for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+      if (StringICmp (gbq->qual, "inference") == 0) {
+        has_inference = TRUE;
+      }
+    }
+    if (! has_inference) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_ExceptionProblem,
+                "Annotated by transcript or proteomic data exception does not have the required inference qualifier");
+    }
+  }
+  if (art_loc_except) {
+    if (! vsp->is_embl_ddbj_in_sep) {
+      ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_ExceptionProblem,
+                "Artificial location should only be used directly by EMBL or DDBJ records");
+    }
+  }
 }
 
 typedef struct samecds {
@@ -19697,6 +20581,7 @@ static void ValidateAnticodon (ValidStructPtr vsp, SeqLocPtr slp)
       id2 = sip->id;
       from2 = sip->from;
       to2 = sip->to;
+      tmpval = SeqIntCheck (sip);
       break;
     case SEQLOC_PNT:
       spp = (SeqPntPtr) (tmp->data.ptrvalue);
@@ -19705,6 +20590,7 @@ static void ValidateAnticodon (ValidStructPtr vsp, SeqLocPtr slp)
       id2 = spp->id;
       from2 = spp->point;
       to2 = spp->point;
+      tmpval = SeqPntCheck (spp);
       break;
     case SEQLOC_NULL:
       continue;
@@ -19875,7 +20761,7 @@ static Boolean LIBCALLBACK DummySMFEProc (
   DummySmfePtr  dsp;
   GeneRefPtr    grp, grpx;
   Int4          len;
-  Boolean       redundantgenexref;
+  Boolean       redundantgenexref = FALSE;
   CharPtr       syn1, syn2;
 
   if (sfp == NULL || context == NULL) return TRUE;
@@ -20494,6 +21380,7 @@ static CharPtr badProtName [] = {
   "uncharacterized protein",
   "uncharacterized protein conserved in archaea",
   "uncharacterized protein conserved in bacteria",
+  "uniprot",
   "unique hypothetical",
   "unique hypothetical protein",
   "unknown",
@@ -20643,10 +21530,254 @@ static Boolean LocationStrandsIncompatible (
   if (slp1 == NULL || slp2 == NULL) return FALSE;
   strand1 = SeqLocStrand (slp1);
   strand2 = SeqLocStrand (slp2);
-  if (strand1 != strand2) return TRUE;
+  if (strand1 != strand2) {
+    /* if strands are mixed, need to check if interval is contained */
+    if (strand1 == Seq_strand_other) {
+      if (SeqLocCompareEx (slp1, slp2, TRUE) == SLC_B_IN_A) {
   return FALSE;
+      }
+    } else if (strand2 == Seq_strand_other) {
+      if (SeqLocCompareEx (slp1, slp2, TRUE) == SLC_A_IN_B) {
+        return FALSE;
+      }
+    }
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
+static CharPtr GetGeneXrefLabel (GeneRefPtr grp)
+{
+  SeqFeat sf;
+  Char    buf[255];
+
+  MemSet (&sf, 0, sizeof (SeqFeat));
+  sf.data.choice = SEQFEAT_GENE;
+  sf.data.value.ptrvalue = grp;
+
+  FeatDefLabel (&sf, buf, sizeof (buf) - 1, OM_LABEL_CONTENT);
+  return StringSave (buf);
+}
+
+
+static void TestForBracketsInProductName (CharPtr str, ValidStructPtr vsp)
+{
+  size_t  len;
+  Boolean report_error = FALSE;
+  CharPtr cp;
+
+  if (StringHasNoText (str)) {
+    return;
+  }
+
+  len = StringLen (str);
+  if (len > 1) {
+    if (str [len - 1] != ']') {
+      /* doesn't end with bracket */
+    } else if (len < 5) {
+      /* too short to contain special text */
+      report_error = TRUE;
+    } else if ((cp = StringRChr (str, '[')) == NULL) {
+      /* doesn't contain matched brackets */
+      report_error = TRUE;
+    } else if (StringNCmp (cp, "[NAD", 4) == 0) {
+      /* contains special text */
+    } else {
+      report_error = TRUE;
+    }
+    if (report_error) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_ProteinNameEndsInBracket, "Protein name ends with bracket and may contain organism name");
+    }
+  }
 }
 
+
+static void ValidateRna (SeqFeatPtr sfp, ValidStructPtr vsp, GatherContextPtr gcp)
+{
+  RnaRefPtr rrp;
+  Boolean   pseudo, ovgenepseudo = FALSE;
+  Boolean   protidqual = FALSE, transidqual = FALSE;
+  GBQualPtr gbq;
+  tRNAPtr   trp;
+  Boolean   badanticodon, anticodonqual, productqual;
+  Int4      anticodonlen;
+  SeqLocPtr slp;
+  RNAGenPtr rgp;
+  Int2      i;
+  CharPtr   str;
+
+    rrp = (RnaRefPtr) (sfp->data.value.ptrvalue);
+
+    pseudo = sfp->pseudo;
+    ovgenepseudo = FALSE;
+    if (OverlappingGeneIsPseudo (sfp)) {
+      pseudo = TRUE;
+      ovgenepseudo = TRUE;
+    }
+
+    if (rrp->type == 2) {       /* mRNA */
+      if (!pseudo) {
+        MrnaTransCheck (vsp, sfp);      /* transcription check */
+        SpliceCheck (vsp, sfp);
+      }
+      /* CheckForBothStrands (vsp, sfp); */
+      CheckForBadGeneOverlap (vsp, sfp);
+      CheckForCommonMRNAProduct (vsp, sfp);
+      protidqual = FALSE;
+      transidqual = FALSE;
+      gbq = sfp->qual;
+      while (gbq != NULL) {
+        if (StringICmp (gbq->qual, "protein_id") == 0) {
+          protidqual = TRUE;
+        }
+        if (StringICmp (gbq->qual, "transcript_id") == 0) {
+          transidqual = TRUE;
+        }
+        gbq = gbq->next;
+      }
+      if (protidqual) {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_WrongQualOnFeature, "protein_id should not be a gbqual on an mRNA feature");
+      }
+      if (transidqual) {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_WrongQualOnFeature, "transcript_id should not be a gbqual on an mRNA feature");
+      }
+    }
+    if (rrp->ext.choice == 2) { /* tRNA */
+      trp = (tRNAPtr) (rrp->ext.value.ptrvalue);
+      if (trp->anticodon != NULL) {
+        badanticodon = FALSE;
+        anticodonlen = 0;
+        slp = SeqLocFindNext (trp->anticodon, NULL);
+        while (slp != NULL) {
+          anticodonlen += SeqLocLen (slp);
+          i = SeqLocCompare (slp, sfp->location);
+          if ((i != SLC_A_IN_B) && (i != SLC_A_EQ_B)) {
+            badanticodon = TRUE;
+          }
+          slp = SeqLocFindNext (trp->anticodon, slp);
+        }
+        if (badanticodon) {
+          ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_Range, "Anticodon location not in tRNA");
+        }
+        if (anticodonlen != 3) {
+          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_Range, "Anticodon is not 3 bases in length");
+        }
+        ValidateAnticodon (vsp, trp->anticodon);
+      }
+      CheckTrnaCodons (vsp, gcp, sfp, trp);
+    }
+    if (rrp->type == 3) {       /* tRNA */
+      anticodonqual = FALSE;
+      productqual = FALSE;
+      gbq = sfp->qual;
+      while (gbq != NULL) {
+        if (StringICmp (gbq->qual, "anticodon") == 0) {
+          anticodonqual = TRUE;
+        } else if (StringICmp (gbq->qual, "product") == 0) {
+          productqual = TRUE;
+        }
+        gbq = gbq->next;
+      }
+      if (anticodonqual) {
+        ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_InvalidQualifierValue, "Unparsed anticodon qualifier in tRNA");
+      }
+      if (productqual) {
+        ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_InvalidQualifierValue, "Unparsed product qualifier in tRNA");
+      }
+    }
+    if (rrp->type == 3 && rrp->ext.choice == 1) { /* tRNA with string extension */
+      ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_InvalidQualifierValue, "Unparsed product qualifier in tRNA");
+    }
+    if (rrp->type == 3 && rrp->ext.choice == 0) { /* tRNA with no extension */
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_MissingTrnaAA, "Missing encoded amino acid qualifier in tRNA");
+    }
+    if (rrp->type == 0) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_RNAtype0, "RNA type 0 (unknown) not supported");
+    }
+    if (rrp->type == 4 || rrp->type == 5 || rrp->type == 6 || rrp->type == 7) { /* rRNA, snRNA, scRNA, snoRNA */
+      if (rrp->ext.choice != 1 || StringHasNoText ((CharPtr) rrp->ext.value.ptrvalue)) {
+        if (! pseudo) {
+          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_InvalidQualifierValue, "%s has no name", rnaNameByType [(int) rrp->type]);
+        }
+      }
+    }
+    /*
+    if (rrp->type == 255 && rrp->ext.choice == 1) {
+      str = (CharPtr) rrp->ext.value.ptrvalue;
+      if (StringICmp (str, "ncRNA") == 0) {
+        for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+          if (StringICmp (gbq->qual, "ncRNA_class") != 0) continue;
+          if (StringHasNoText (gbq->val)) continue;
+          if (IsStringInNcRNAClassList (gbq->val)) continue;
+          ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_InvalidQualifierValue, "Illegal ncRNA_class value '%s'", gbq->val);
+        }
+      }
+    }
+    */
+    if (rrp->type == 2) {
+      if (rrp->ext.choice == 1) {
+        str = (CharPtr) rrp->ext.value.ptrvalue;
+        if (StringDoesHaveText (str)) {
+          if (HasBadCharacter (str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadInternalCharacter, "mRNA name contains undesired character");
+          }
+          if (EndsWithBadCharacter (str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingCharacter, "mRNA name ends with undesired character");
+          }
+          if (EndsWithHyphen (str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingHyphen, "mRNA name ends with hyphen");
+          }
+          if (StringHasSgml (vsp, str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "mRNA name %s has SGML", str);
+          }
+        }
+      }
+    }
+    if (rrp->type == 4) {
+      if (rrp->ext.choice == 1) {
+        str = (CharPtr) rrp->ext.value.ptrvalue;
+        if (StringDoesHaveText (str)) {
+          if (HasBadCharacter (str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadInternalCharacter, "rRNA name contains undesired character");
+          }
+          if (EndsWithBadCharacter (str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingCharacter, "rRNA name ends with undesired character");
+          }
+          if (EndsWithHyphen (str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingHyphen, "rRNA name ends with hyphen");
+          }
+          if (StringHasSgml (vsp, str)) {
+            ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "rRNA name %s has SGML", str);
+          }
+        }
+      }
+    }
+    if (sfp->product != NULL) {
+      CheckRnaProductType (vsp, gcp, sfp, rrp);
+    }
+
+    if (pseudo && sfp->product != NULL && StringISearch (sfp->except_text, "transcribed pseudogene") == NULL) {
+      if (ovgenepseudo) {
+        if (sfp->pseudo) {
+          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PseudoRnaHasProduct, "A pseudo RNA should not have a product");
+        } else {
+          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PseudoRnaViaGeneHasProduct, "An RNA overlapped by a pseudogene should not have a product");
+        }
+      } else {
+        ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PseudoRnaHasProduct, "A pseudo RNA should not have a product");
+      }
+    }
+
+    if (rrp->ext.choice == 3
+        && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL
+        && !StringHasNoText (rgp->_class)
+        && rrp->type != 8) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_WrongQualOnFeature, "Only ncRNA should have ncRNA-class");
+    }
+}
+
+
 NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
 {
   Int2            type, i, j;
@@ -20666,11 +21797,9 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
   CdRegionPtr     crp;
   CodeBreakPtr    cbp, prevcbp;
   CharPtr         ctmp;
-  RnaRefPtr       rrp;
-  tRNAPtr         trp;
   GBQualPtr       gbq;
   Boolean         pseudo, excpt, conflict, codonqual,
-                  anticodonqual, productqual, protidqual,
+                  protidqual,
                   transidqual, ovgenepseudo;
   ImpFeatPtr      ifp;
   GeneRefPtr      grp;
@@ -20698,7 +21827,7 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
   SeqFeatPtr      operon;
   Boolean         redundantgenexref;
   SeqMgrFeatContext fcontext;
-  CharPtr         syn1, syn2, label = NULL;
+  CharPtr         syn1, syn2, label = NULL, genexref_label;
   Uint2           oldEntityID;
   Uint4           oldItemID;
   SeqIdPtr        sip;
@@ -20708,13 +21837,10 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
   Boolean         multitoken;
   Char            ch;
   CharPtr         ptr;
-  Int4            anticodonlen;
-  Boolean         badanticodon;
   SeqLocPtr       slp;
   Int2            count;
   DummySmfeData   dsd;
   CharPtr         str;
-  size_t          len;
   Boolean         isgap;
   Boolean         badseq;
   Boolean         is_seqloc_bond;
@@ -20737,6 +21863,7 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
   Boolean         skip;
   Boolean         is_nc = FALSE;
   Boolean         no_nonconsensus_except = TRUE;
+  VariationRefPtr  vrfp;
 
 
   vsp = (ValidStructPtr) (gcp->userdata);
@@ -20778,7 +21905,8 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
   if (sfp->excpt) {
     if (StringISearch (sfp->except_text, "nonconsensus splice site") != NULL ||
         StringISearch (sfp->except_text, "heterogeneous population sequenced") != NULL ||
-        StringISearch (sfp->except_text, "low-quality sequence region") != NULL) {
+        StringISearch (sfp->except_text, "low-quality sequence region") != NULL ||
+        StringISearch (sfp->except_text, "artificial location") != NULL) {
       no_nonconsensus_except = FALSE;
     }
   }
@@ -20791,8 +21919,12 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
     /* a partial feature, with complete location, but partial product */
     else if ((sfp->partial) && (sfp->product != NULL) && (partials[1] == SLP_COMPLETE) && (sfp->product->choice == SEQLOC_WHOLE)
              && (partials[0] != SLP_COMPLETE)) {
+      if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+        /* skip in gpipe genomic */
+      } else {
       ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PartialProblem, "When SeqFeat.product is a partial Bioseq, SeqFeat.location should also be partial");
     }
+    }
     /* gene on segmented set is now 'order', should also be partial */
     else if (type == SEQFEAT_GENE && sfp->product == NULL && partials[1] == SLP_INTERNAL) {
       if (!sfp->partial) {
@@ -20827,6 +21959,8 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
         tmp = StringMove (tmp, "FALSE");
       if (bsp == NULL && LocationIsFar (sfp->product) && NoFetchFunctions ()) {
         vsp->far_fetch_failure = TRUE;
+      } else if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+        /* ignore inconsistent partial warnings in genomic gpipe sequence */
       } else {
         ValidErr (vsp, sev, ERR_SEQ_FEAT_PartialsInconsistent, buf);
       }
@@ -20850,8 +21984,12 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
         tmp = StringMove (tmp, "TRUE");
       else
         tmp = StringMove (tmp, "FALSE");
+      if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+        /* ignore inconsistent partial warnings in genomic gpipe sequence */
+      } else {
       ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PartialsInconsistent, buf);
     }
+    }
     /* 5' or 3' partial location giving unclassified partial product */
     else if (((partials [1] & SLP_START) != 0 || ((partials [1] & SLP_STOP) != 0)) && ((partials [0] & SLP_OTHER) != 0) && sfp->partial) {
       ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PartialProblem, "5' or 3' partial location should not have unclassified partial in product molinfo descriptor");
@@ -20885,9 +22023,13 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
           } else if (i == 1 && j < 2 && PartialAtSpliceSiteOrGap (vsp, sfp->location, errtype, &isgap, &badseq)) {
             if (! isgap) {
               if (sfp->idx.subtype != FEATDEF_CDS || SplicingNotExpected (sfp)) {
+                if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep && i == 1 && (j == 0 || j == 1 || j == 2)) {
+                  /* ignore in genomic gpipe sequence */
+                } else {
                 ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_PartialProblem,
                           "%s: %s (but is at consensus splice site)",
                           parterr[i], parterrs[j]);
+                }
               } else if (sfp->idx.subtype == FEATDEF_CDS) {
                 bsp = BioseqFindFromSeqLoc (sfp->location);
                 if (bsp != NULL) {
@@ -20905,25 +22047,34 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
                 }
               }
             }
-            if (badseq) {
+          } else if (i == 1 && j < 2 && badseq) {
               ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_PartialProblem,
                 "%s: %s (and is at bad sequence)",
                 parterr[i], parterrs[j]);
-            }
           } else if (sfp->data.choice == SEQFEAT_CDREGION && sfp->excpt &&
                      StringStr (sfp->except_text, "rearrangement required for product") != NULL) {
           } else if (sfp->data.choice == SEQFEAT_CDREGION && j == 0) {
             if (no_nonconsensus_except) {
+              if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+                /* skip in gpipe genomic */
+              } else {
               ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PartialProblem,
                 "%s: %s", parterr[i], "5' partial is not at start AND"
                 " is not at consensus splice site");
             }
+            }
           } else if (sfp->data.choice == SEQFEAT_CDREGION && j == 1) {
             if (no_nonconsensus_except) {
+              if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+                /* skip in gpipe genomic */
+              } else {
               ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PartialProblem,
                 "%s: %s", parterr[i], "3' partial is not at stop AND"
                 " is not at consensus splice site");
             }
+            }
+          } else if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep && i == 1 && (j == 0 || j == 1 || j == 2)) {
+            /* ignore start/stop not at end in genomic gpipe sequence */
           } else {
             ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PartialProblem,
               "%s: %s", parterr[i], parterrs[j]);
@@ -20935,7 +22086,7 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
 
   }
 
-  CheckForIllegalDbxref (vsp, gcp, sfp, sfp->dbxref);
+  CheckForIllegalDbxref (vsp, gcp, sfp->dbxref);
   /*
   for (vnp = sfp->dbxref; vnp != NULL; vnp = vnp->next) {
     id = -1;
@@ -20984,7 +22135,7 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
           ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_LocusTagProblem, "Gene locus and locus_tag '%s' match", grp->locus);
         }
       }
-      CheckForIllegalDbxref (vsp, gcp, sfp, grp->db);
+      CheckForIllegalDbxref (vsp, gcp, grp->db);
       if (StringDoesHaveText (grp->allele)) {
         for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
           if (StringCmp (gbq->qual, "allele") == 0 && StringDoesHaveText (gbq->val)) {
@@ -21096,6 +22247,22 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
           ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "gene synonym %s has SGML", str);
         }
       }
+      if (StringDoesHaveText (grp->locus)) {
+        bsp = BioseqFindFromSeqLoc (sfp->location);
+        sfpx = SeqMgrGetGeneByLocusTag (bsp, grp->locus, &fcontext);
+        if (sfpx != NULL) {
+          grpx = (GeneRefPtr) sfpx->data.value.ptrvalue;
+          if (grpx != NULL) {
+            if (grp == grpx) {
+              /*
+              ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_LocusCollidesWithLocusTag, "locus collides with locus_tag in same gene");
+              */
+            } else {
+              ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_LocusCollidesWithLocusTag, "locus collides with locus_tag in another gene");
+            }
+          }
+        }
+      }
     }
     break;
   case 2:                      /* Org-ref */
@@ -21228,8 +22395,13 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
                        biop->genome == GENOME_cyanelle ||
                        biop->genome == GENOME_apicoplast ||
                        biop->genome == GENOME_leucoplast ||
-                       biop->genome == GENOME_proplastid) {
+                       biop->genome == GENOME_proplastid ||
+                       biop->genome == GENOME_chromatophore) {
+              if (onp->pgcode > 0) {
+                biopgencode = onp->pgcode;
+              } else {
               biopgencode = 11;
+              }
               plastid = TRUE;
             } else {
               biopgencode = onp->gcode;
@@ -21303,12 +22475,7 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
         if (vnp != NULL) {
           str = (CharPtr) vnp->data.ptrvalue;
           if (StringDoesHaveText (str)) {
-            len = StringLen (str);
-            if (len > 1) {
-              if (str [len - 1] == ']') {
-                ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_ProteinNameEndsInBracket, "Protein name ends with bracket and may contain organism name");
-              }
-            }
+            TestForBracketsInProductName (str, vsp);
             if (StringNICmp (str, "hypothetical protein XP_", 24) == 0) {
               bsp = GetBioseqGivenSeqLoc (sfp->location, gcp->entityID);
               if (bsp != NULL) {
@@ -21359,7 +22526,7 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
           }
         }
       }
-      CheckForIllegalDbxref (vsp, gcp, sfp, prp->db);
+      CheckForIllegalDbxref (vsp, gcp, prp->db);
       /*
       for (vnp = prp->db; vnp != NULL; vnp = vnp->next) {
         id = -1;
@@ -21404,24 +22571,42 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
             } else if (ECnumberWasReplaced (str)) {
               ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadEcNumberValue, "EC_number %s was transferred and is no longer valid", str);
             } else {
+              StringNCpy_0 (buf, str, sizeof (buf));
+              ptr = StringChr (buf, 'n');
+              if (ptr != NULL) {
+                ch = ptr [1];
+                if (IS_DIGIT (ch)) {
+                  ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_BadEcNumberValue, "%s is not a legal preliminary value for qualifier EC_number", str);
+                } else {
+                  ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadEcNumberValue, "%s is not a legal value for qualifier EC_number", str);
+                }
+              } else {
               ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadEcNumberValue, "%s is not a legal value for qualifier EC_number", str);
             }
           }
+          }
         } else {
           ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_EcNumberProblem, "EC number should not be empty");
         }
       }
     }
-    if (prp->name != NULL && (vsp->is_refseq_in_sep /* || vsp->seqSubmitParent */)) {
+    if (prp != NULL && prp->name != NULL && (vsp->is_refseq_in_sep /* || vsp->seqSubmitParent */)) {
       for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
         str = (CharPtr) vnp->data.ptrvalue;
         if (StringHasNoText (str)) continue;
           if (NameInList (str, badProtName, sizeof (badProtName) / sizeof (badProtName [0]))) {
             ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_UndesiredProteinName, "Uninformative protein name '%s'", str);
+          } else if (StringStr (str, "=") != NULL ||
+                     StringStr (str, "~") != NULL ||
+                     StringISearch (str, "uniprot") != NULL ||
+                     StringISearch (str, "uniprotkb") != NULL ||
+                     StringISearch (str, "pmid") != NULL ||
+                     StringISearch (str, "dbxref") != NULL) {
+            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_UndesiredProteinName, "Uninformative protein name '%s'", str);
           }
         }
       }
-      if (prp->name != NULL) {
+      if (prp != NULL && prp->name != NULL) {
         for (vnp = prp->name; vnp != NULL; vnp = vnp->next) {
           str = (CharPtr) vnp->data.ptrvalue;
           if (StringHasNoText (str)) continue;
@@ -21447,167 +22632,8 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
       }
     break;
   case 5:                      /* RNA-ref */
-    rrp = (RnaRefPtr) (sfp->data.value.ptrvalue);
-
-    pseudo = sfp->pseudo;
-    ovgenepseudo = FALSE;
-    if (OverlappingGeneIsPseudo (sfp)) {
-      pseudo = TRUE;
-      ovgenepseudo = TRUE;
-    }
-
-    if (rrp->type == 2) {       /* mRNA */
-      if (!pseudo) {
-        MrnaTransCheck (vsp, sfp);      /* transcription check */
-        SpliceCheck (vsp, sfp);
-      }
-      /* CheckForBothStrands (vsp, sfp); */
-      CheckForBadGeneOverlap (vsp, sfp);
-      CheckForCommonMRNAProduct (vsp, sfp);
-      protidqual = FALSE;
-      transidqual = FALSE;
-      gbq = sfp->qual;
-      while (gbq != NULL) {
-        if (StringICmp (gbq->qual, "protein_id") == 0) {
-          protidqual = TRUE;
-        }
-        if (StringICmp (gbq->qual, "transcript_id") == 0) {
-          transidqual = TRUE;
-        }
-        gbq = gbq->next;
-      }
-      if (protidqual) {
-        ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_WrongQualOnFeature, "protein_id should not be a gbqual on an mRNA feature");
-      }
-      if (transidqual) {
-        ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_WrongQualOnFeature, "transcript_id should not be a gbqual on an mRNA feature");
-      }
-    }
-    if (rrp->ext.choice == 2) { /* tRNA */
-      trp = (tRNAPtr) (rrp->ext.value.ptrvalue);
-      if (trp->anticodon != NULL) {
-        badanticodon = FALSE;
-        anticodonlen = 0;
-        slp = SeqLocFindNext (trp->anticodon, NULL);
-        while (slp != NULL) {
-          anticodonlen += SeqLocLen (slp);
-          i = SeqLocCompare (slp, sfp->location);
-          if ((i != SLC_A_IN_B) && (i != SLC_A_EQ_B)) {
-            badanticodon = TRUE;
-          }
-          slp = SeqLocFindNext (trp->anticodon, slp);
-        }
-        if (badanticodon) {
-          ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_Range, "Anticodon location not in tRNA");
-        }
-        if (anticodonlen != 3) {
-          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_Range, "Anticodon is not 3 bases in length");
-        }
-        ValidateAnticodon (vsp, trp->anticodon);
-      }
-      CheckTrnaCodons (vsp, gcp, sfp, trp);
-    }
-    if (rrp->type == 3) {       /* tRNA */
-      anticodonqual = FALSE;
-      productqual = FALSE;
-      gbq = sfp->qual;
-      while (gbq != NULL) {
-        if (StringICmp (gbq->qual, "anticodon") == 0) {
-          anticodonqual = TRUE;
-        } else if (StringICmp (gbq->qual, "product") == 0) {
-          productqual = TRUE;
-        }
-        gbq = gbq->next;
-      }
-      if (anticodonqual) {
-        ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_InvalidQualifierValue, "Unparsed anticodon qualifier in tRNA");
-      }
-      if (productqual) {
-        ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_InvalidQualifierValue, "Unparsed product qualifier in tRNA");
-      }
-    }
-    if (rrp->type == 3 && rrp->ext.choice == 1) { /* tRNA with string extension */
-      ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_InvalidQualifierValue, "Unparsed product qualifier in tRNA");
-    }
-    if (rrp->type == 3 && rrp->ext.choice == 0) { /* tRNA with no extension */
-      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_MissingTrnaAA, "Missing encoded amino acid qualifier in tRNA");
-    }
-    if (rrp->type == 0) {
-      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_RNAtype0, "RNA type 0 (unknown) not supported");
-    }
-    if (rrp->type == 4 || rrp->type == 5 || rrp->type == 6 || rrp->type == 7) { /* rRNA, snRNA, scRNA, snoRNA */
-      if (rrp->ext.choice != 1 || StringHasNoText ((CharPtr) rrp->ext.value.ptrvalue)) {
-        if (! pseudo) {
-          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_InvalidQualifierValue, "%s has no name", rnaNameByType [(int) rrp->type]);
-        }
-      }
-    }
-    /*
-    if (rrp->type == 255 && rrp->ext.choice == 1) {
-      str = (CharPtr) rrp->ext.value.ptrvalue;
-      if (StringICmp (str, "ncRNA") == 0) {
-        for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
-          if (StringICmp (gbq->qual, "ncRNA_class") != 0) continue;
-          if (StringHasNoText (gbq->val)) continue;
-          if (IsStringInNcRNAClassList (gbq->val)) continue;
-          ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_InvalidQualifierValue, "Illegal ncRNA_class value '%s'", gbq->val);
-        }
-      }
-    }
-    */
-    if (rrp->type == 2) {
-      if (rrp->ext.choice == 1) {
-        str = (CharPtr) rrp->ext.value.ptrvalue;
-        if (StringDoesHaveText (str)) {
-          if (HasBadCharacter (str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadInternalCharacter, "mRNA name contains undesired character");
-          }
-          if (EndsWithBadCharacter (str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingCharacter, "mRNA name ends with undesired character");
-          }
-          if (EndsWithHyphen (str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingHyphen, "mRNA name ends with hyphen");
-          }
-          if (StringHasSgml (vsp, str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "mRNA name %s has SGML", str);
-          }
-        }
-      }
-    }
-    if (rrp->type == 4) {
-      if (rrp->ext.choice == 1) {
-        str = (CharPtr) rrp->ext.value.ptrvalue;
-        if (StringDoesHaveText (str)) {
-          if (HasBadCharacter (str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadInternalCharacter, "rRNA name contains undesired character");
-          }
-          if (EndsWithBadCharacter (str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingCharacter, "rRNA name ends with undesired character");
-          }
-          if (EndsWithHyphen (str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_BadTrailingHyphen, "rRNA name ends with hyphen");
-          }
-          if (StringHasSgml (vsp, str)) {
-            ValidErr (vsp, SEV_WARNING, ERR_GENERIC_SgmlPresentInText, "rRNA name %s has SGML", str);
-          }
-        }
-      }
-    }
-    if (sfp->product != NULL) {
-      CheckRnaProductType (vsp, gcp, sfp, rrp);
-    }
+    ValidateRna(sfp, vsp, gcp);
 
-    if (pseudo && sfp->product != NULL && StringISearch (sfp->except_text, "transcribed pseudogene") == NULL) {
-      if (ovgenepseudo) {
-        if (sfp->pseudo) {
-          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PseudoRnaHasProduct, "A pseudo RNA should not have a product");
-        } else {
-          ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PseudoRnaViaGeneHasProduct, "An RNA overlapped by a pseudogene should not have a product");
-        }
-      } else {
-        ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_PseudoRnaHasProduct, "A pseudo RNA should not have a product");
-      }
-    }
     break;
   case 6:                      /* Pub */
     pdp = (PubdescPtr) sfp->data.value.ptrvalue;
@@ -21709,6 +22735,11 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
     if (clrp != NULL) {
     }
     break;
+  case 22:                     /* VariationRef */
+    vrfp = (VariationRefPtr) sfp->data.value.ptrvalue;
+    if (vrfp != NULL) {
+    }
+    break;
   default:
     ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_InvalidType, "Invalid SeqFeat type [%d]", (int) (type));
     break;
@@ -22095,7 +23126,9 @@ NLM_EXTERN void ValidateSeqFeat (GatherContextPtr gcp)
                   ValStrandsMatch (SeqLocStrand (sfp->location), SeqLocStrand (sfpy->location))) {
                 /* cross-reference needed to disambiguate between multiple overlapping genes, ignore */
               } else {
-                ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_SuspiciousGeneXref, "Curated Drosophila record should not have gene cross-reference %s", label);
+                genexref_label = GetGeneXrefLabel (grp);
+                ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_SuspiciousGeneXref, "Curated Drosophila record should not have gene cross-reference %s", genexref_label);
+                genexref_label = MemFree (genexref_label);
               }
             }
           }
@@ -22168,6 +23201,7 @@ NLM_EXTERN void MrnaTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
   SeqDescrPtr     sdp;
   MolInfoPtr      mip;
   TextSeqIdPtr    tsip;
+  Boolean         rna_editing = FALSE;
 
   if (sfp == NULL)
     return;
@@ -22182,6 +23216,9 @@ NLM_EXTERN void MrnaTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
         report_errors = FALSE;  /* biological exception */
       }
     }
+    if (StringISearch (sfp->except_text, "RNA editing") != NULL) {
+      rna_editing = TRUE;
+    }
     if (StringStr (sfp->except_text, "unclassified transcription discrepancy") != NULL) {
       unclassified_except = TRUE;
     }
@@ -22311,29 +23348,37 @@ NLM_EXTERN void MrnaTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
         if (counta < 19 * countnona) {
           has_errors = TRUE;
           other_than_mismatch = TRUE;
-          if (report_errors) {
+          if (report_errors || rna_editing) {
             ValidErr (vsp, sev, ERR_SEQ_FEAT_TranscriptLen, "Transcript length [%ld] less than %sproduct length [%ld], and tail < 95%s polyA", (long) mlen, farstr, (long) plen, "%");
           }
           plen = mlen; /* even if it fails polyA test, allow base-by-base comparison on common length */
         } else if (counta > 0 && countnona == 0) {
           has_errors = TRUE;
           other_than_mismatch = TRUE;
-          if (report_errors) {
+          if (report_errors || rna_editing) {
+            if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+              /* suppress if gpipe genomic */
+            } else {
             ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_PolyATail, "Transcript length [%ld] less than %sproduct length [%ld], but tail is 100%s polyA", (long) mlen, farstr, (long) plen, "%");
           }
+          }
           plen = mlen; /* if it passes polyA test, allow base-by-base comparison on common length */
         } else {
           has_errors = TRUE;
           other_than_mismatch = TRUE;
-          if (report_errors) {
+          if (report_errors || rna_editing) {
+            if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+              /* suppress if gpipe genomic */
+            } else {
             ValidErr (vsp, SEV_INFO, ERR_SEQ_FEAT_PolyATail, "Transcript length [%ld] less than %sproduct length [%ld], but tail >= 95%s polyA", (long) mlen, farstr, (long) plen, "%");
           }
+          }
           plen = mlen; /* if it passes polyA test, allow base-by-base comparison on common length */
         }
       } else {
         has_errors = TRUE;
         other_than_mismatch = TRUE;
-        if (report_errors) {
+        if (report_errors || rna_editing) {
           ValidErr (vsp, sev, ERR_SEQ_FEAT_TranscriptLen, "Transcript length [%ld] greater than %sproduct length [%ld]", (long) mlen, farstr, (long) plen);
         }
       }
@@ -22505,6 +23550,7 @@ static CharPtr bypass_cds_trans_check [] = {
   "annotated by transcript or proteomic data",
   "heterogeneous population sequenced",
   "low-quality sequence region",
+  "artificial location",
   NULL
 };
 
@@ -22565,8 +23611,10 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
   ByteStorePtr    newprot = NULL;
   CharPtr         protseq = NULL;
   BioseqPtr       prot1seq = NULL, prot2seq = NULL;
-  Int4            prot1len = 0, prot2len, i, len = 0, x_count = 0,
+  Int4            i, len = 0, x_count = 0,
                   nonx_count = 0, xcount1 = 0, xcount2 = 0;
+  Int4            prot1len = 0; /* length of protein product sequence */
+  Int4            prot2len = 0; /* length of translation of coding region */
   CdRegionPtr     crp;
   SeqIdPtr        protid = NULL;
   Int2            residue1, residue2, stop_count = 0, mismatch = 0, ragged = 0;
@@ -22576,16 +23624,20 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
   */
   Uint2           part_loc = 0, part_prod = 0;
   Boolean         no_end = FALSE, no_beg = FALSE, show_stop = FALSE,
-                  got_dash = FALSE, alt_start = FALSE, done;
+                  got_dash = FALSE, alt_start = FALSE, got_x = FALSE, done;
   GBQualPtr       gb;
-  ValNodePtr      vnp, code, codebreakhead = NULL;
+  ValNodePtr      vnp, vnp2, code, codebreakhead = NULL;
   int             gccode = 0;
   Boolean         transl_except = FALSE, prot_ok = TRUE, is_nc = FALSE,
                   has_errors = FALSE, report_errors = TRUE,
                   unclassified_except = FALSE, mismatch_except = FALSE,
                   frameshift_except = FALSE, rearrange_except = FALSE,
                   other_than_mismatch = FALSE, product_replaced = FALSE,
-                  mixed_population = FALSE, low_quality = FALSE;
+                  mixed_population = FALSE, low_quality = FALSE,
+                  artificial_location = FALSE;
+  Boolean         partial5 = FALSE;
+  Boolean         partial3 = FALSE;
+  Boolean         rna_editing = FALSE;
   CharPtr         nuclocstr, farstr = "";
   CodeBreakPtr    cbp;
   Int4            pos1, pos2, pos;
@@ -22606,9 +23658,12 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
   SeqDescrPtr     sdp;
   MolInfoPtr      mip;
   TextSeqIdPtr    tsip;
+  Boolean         annotated_by_transcript_or_proteomic = FALSE;
 
-  if (sfp == NULL)
-    return;
+  if (sfp == NULL) return;
+
+  crp = (CdRegionPtr) (sfp->data.value.ptrvalue);
+  if (crp == NULL) return;
 
   for (gb = sfp->qual; gb != NULL; gb = gb->next) {     /* pseuogene */
     if (!StringICmp ("pseudo", gb->qual))
@@ -22620,6 +23675,8 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
     return;
   }
 
+  CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
+
   if (sfp->excpt && (! vsp->ignoreExceptions) && (! StringHasNoText (sfp->except_text))) {
     for (i = 0; bypass_cds_trans_check [i] != NULL; i++) {
       if (StringISearch (sfp->except_text,  bypass_cds_trans_check [i]) != NULL) {
@@ -22649,9 +23706,17 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
     if (StringICmp (sfp->except_text, "low-quality sequence region") == 0) {
       low_quality = TRUE;
     }
+    if (StringICmp (sfp->except_text, "artificial location") == 0) {
+      artificial_location = TRUE;
+    }
+    if (StringISearch (sfp->except_text, "RNA editing") != NULL) {
+      rna_editing = TRUE;
+    }
+  }
+  if (StringISearch (sfp->except_text, "annotated by transcript or proteomic data") != NULL) {
+    annotated_by_transcript_or_proteomic = TRUE;
   }
 
-  crp = (CdRegionPtr) (sfp->data.value.ptrvalue);
   if (crp->code_break == NULL) {        /* check for unparsed transl_except */
     for (gb = sfp->qual; gb != NULL; gb = gb->next) {
       if (StringCmp (gb->qual, "transl_except") == 0) {
@@ -22671,9 +23736,9 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
       case 1:                  /* name */
         code = GeneticCodeFind (0, (CharPtr) (vnp->data.ptrvalue));
         if (code != NULL) {
-          for (vnp = code->data.ptrvalue; ((vnp != NULL) && (!gccode)); vnp = vnp->next) {
-            if (vnp->choice == 2)       /* id */
-              gccode = (int) (vnp->data.intvalue);
+          for (vnp2 = code->data.ptrvalue; ((vnp2 != NULL) && (!gccode)); vnp2 = vnp2->next) {
+            if (vnp2->choice == 2)       /* id */
+              gccode = (int) (vnp2->data.intvalue);
           }
         }
         break;
@@ -22703,11 +23768,52 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
     ValidateTranslExcept (vsp, sfp, codebreakhead, farFetchProd, crp->frame, crp->genetic_code);
   }
 
+  protid = SeqLocId (sfp->product);
+  if (protid != NULL) {
+    prot1seq = BioseqFind (protid);
+    if (prot1seq == NULL && vsp->farFetchCDSproducts) {
+      if (protid != NULL && (protid->choice != SEQID_GI || protid->data.intvalue > 0)) {
+        prot1seq = BioseqLockById (protid);
+      }
+      if (prot1seq != NULL) {
+        unlockProd = TRUE;
+        farstr = "(far) ";
+        if (sfp->partial) {
+          sdp = GetNextDescriptorUnindexed (prot1seq, Seq_descr_molinfo, NULL);
+          if (sdp != NULL && sdp->choice == Seq_descr_molinfo) {
+            mip = (MolInfoPtr) sdp->data.ptrvalue;
+            if (mip != NULL) {
+              if (mip->completeness < 2 || mip->completeness > 5) {
+                for (sip3 = prot1seq->id; sip3 != NULL; sip3 = sip3->next) {
+                  if (sip3->choice != SEQID_OTHER) continue;
+                  tsip = (TextSeqIdPtr) sip3->data.ptrvalue;
+                  if (tsip == NULL) continue;
+                  if (StringNCmp (tsip->accession, "NP_", 3) == 0) {
+                    /* if far NP_ record, return to lower severity */
+                    trans_len_sev = SEV_WARNING;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    if (prot1seq != NULL)
+      prot1len = prot1seq->length;
+  }
+
+  if (annotated_by_transcript_or_proteomic) {
+    if (1.2 * prot2len < prot1len) {
+      ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_TransLen, "Protein product length [%ld] is more than 120%% of the %stranslation length [%ld]", prot1len, farstr, prot2len);
+    }
+  }
+
   if (alt_start && gccode == 1) {
     /* sev = SEV_WARNING; */
     sev = SEV_NONE; /* only enable for RefSeq, leave old code in for now */
     if (Loc_is_RefSeq (sfp->location)) {
-      sev = SEV_ERROR;
+      sev = /* SEV_ERROR */ SEV_NONE; /* now also disable for RefSeq */
     } else if (Loc_is_GEDL (sfp->location)) {
       sev = SEV_NONE;
     }
@@ -22840,8 +23946,12 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
     len = prot2len;
     for (i = 0; i < len; i++) {
       residue1 = protseq [i];
-      if ((i == 0) && (residue1 == '-'))
+      if (i == 0 && residue1 == '-') {
         got_dash = TRUE;
+      }
+      if (i == 0 && residue1 == 'X') {
+        got_x = TRUE;
+      }
       if (residue1 == '*') {
         if (i == (len - 1))
           got_stop = TRUE;
@@ -22885,10 +23995,34 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
         sev = SEV_WARNING;
       }
       if (report_errors || unclassified_except) {
+        if (! unclassified_except) {
         ValidErr (vsp, sev, ERR_SEQ_FEAT_StartCodon,
                   "Illegal start codon (and %ld internal stops). Probably wrong genetic code [%d]", (long) stop_count, gccode);
+        }
+        if (unclassified_except && vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+          /* suppress if gpipe genomic */
+        } else {
         ValidErr (vsp, sev, ERR_SEQ_FEAT_InternalStop, "%ld internal stops (and illegal start codon). Genetic code [%d]", (long) stop_count, gccode);
       }
+      }
+    } else if (got_x) {
+      has_errors = TRUE;
+      other_than_mismatch = TRUE;
+      sev = SEV_ERROR;
+      if (unclassified_except) {
+        sev = SEV_WARNING;
+      }
+      if (report_errors || unclassified_except) {
+        if (! unclassified_except) {
+          ValidErr (vsp, sev, ERR_SEQ_FEAT_StartCodon,
+                    "Ambiguous start codon (and %ld internal stops). Possibly wrong genetic code [%d]", (long) stop_count, gccode);
+        }
+        if (unclassified_except && vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+          /* suppress if gpipe genomic */
+        } else {
+          ValidErr (vsp, sev, ERR_SEQ_FEAT_InternalStop, "%ld internal stops (and ambiguous start codon). Genetic code [%d]", (long) stop_count, gccode);
+        }
+      }
     } else {
       has_errors = TRUE;
       other_than_mismatch = TRUE;
@@ -22923,53 +24057,33 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
             sev = SEV_REJECT;
           }
         }
+        if (unclassified_except && vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+          /* suppress if gpipe genomic */
+        } else {
         ValidErr (vsp, sev, ERR_SEQ_FEAT_InternalStop, "%ld internal stops. Genetic code [%d]", (long) stop_count, gccode);
       }
     }
+    }
     prot_ok = FALSE;
     if (stop_count > 5)
       goto erret;
   } else if (got_dash) {
     has_errors = TRUE;
     other_than_mismatch = TRUE;
-    if (report_errors) {
+    if (report_errors && ! unclassified_except) {
       ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_StartCodon, "Illegal start codon used. Wrong genetic code [%d] or protein should be partial", gccode);
     }
+  } else if (got_x && (! partial5)) {
+    has_errors = TRUE;
+    other_than_mismatch = TRUE;
+    if (report_errors && ! unclassified_except) {
+      ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_StartCodon, "Ambiguous start codon used. Wrong genetic code [%d] or protein should be partial", gccode);
+    }
   }
 
   show_stop = TRUE;
 
-  protid = SeqLocId (sfp->product);
   if (protid != NULL) {
-    prot1seq = BioseqFind (protid);
-    if (prot1seq == NULL && vsp->farFetchCDSproducts) {
-      if (protid != NULL && (protid->choice != SEQID_GI || protid->data.intvalue > 0)) {
-        prot1seq = BioseqLockById (protid);
-      }
-      if (prot1seq != NULL) {
-        unlockProd = TRUE;
-        farstr = "(far) ";
-        if (sfp->partial) {
-          sdp = GetNextDescriptorUnindexed (prot1seq, Seq_descr_molinfo, NULL);
-          if (sdp != NULL && sdp->choice == Seq_descr_molinfo) {
-            mip = (MolInfoPtr) sdp->data.ptrvalue;
-            if (mip != NULL) {
-              if (mip->completeness < 2 || mip->completeness > 5) {
-                for (sip3 = prot1seq->id; sip3 != NULL; sip3 = sip3->next) {
-                  if (sip3->choice != SEQID_OTHER) continue;
-                  tsip = (TextSeqIdPtr) sip3->data.ptrvalue;
-                  if (tsip == NULL) continue;
-                  if (StringNCmp (tsip->accession, "NP_", 3) == 0) {
-                    /* if far NP_ record, return to lower severity */
-                    trans_len_sev = SEV_WARNING;
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    }
     if (prot1seq == NULL && (! vsp->farFetchCDSproducts)) {
       goto erret;
     }
@@ -23108,9 +24222,21 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
             other_than_mismatch = TRUE;
             if (report_errors) {
               if (! got_dash) {
+                if (! unclassified_except){
                 ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_StartCodon, "Illegal start codon used. Wrong genetic code [%d] or protein should be partial", gccode);
               }
             }
+            }
+          } else if (residue1 == 'X') {
+            has_errors = TRUE;
+            other_than_mismatch = TRUE;
+            if (report_errors) {
+              if (! got_x) {
+                if (! unclassified_except){
+                  ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_StartCodon, "Ambiguous start codon used. Wrong genetic code [%d] or protein should be partial", gccode);
+                }
+              }
+            }
           } else {
             nuclocstr = MapToNTCoords (sfp, protid, i);
             if (nuclocstr != NULL) {
@@ -23154,8 +24280,8 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
   } else {
     has_errors = TRUE;
     other_than_mismatch = TRUE;
-    if (report_errors) {
-      ValidErr (vsp, trans_len_sev, ERR_SEQ_FEAT_TransLen, "Given protein length [%ld] does not match %stranslation length [%ld]", prot1len, farstr, len);
+    if (report_errors || (rna_editing && (prot1len < len - 1 || prot1len > len))) {
+      ValidErr (vsp, rna_editing ? SEV_WARNING : trans_len_sev, ERR_SEQ_FEAT_TransLen, "Given protein length [%ld] does not match %stranslation length [%ld]", prot1len, farstr, len);
     }
   }
 
@@ -23165,25 +24291,34 @@ NLM_EXTERN void CdTransCheck (ValidStructPtr vsp, SeqFeatPtr sfp)
         has_errors = TRUE;
         other_than_mismatch = TRUE;
         if (report_errors) {
+          if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+            /* suppress if gpipe genomic */
+          } else {
           ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_PartialProblem, "End of location should probably be partial");
         }
+        }
       } else {
         has_errors = TRUE;
         other_than_mismatch = TRUE;
         if (report_errors) {
+          if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+            /* suppress if gpipe genomic */
+          } else {
           ValidErr (vsp, SEV_ERROR, ERR_SEQ_FEAT_PartialProblem, "This SeqFeat should not be partial");
         }
       }
+      }
       show_stop = FALSE;
     }
   }
 
+
+
+erret:
   if (unlockProd) {
     BioseqUnlock (prot1seq);
   }
 
-
-erret:
   if (show_stop) {
     if ((!got_stop) && (!no_end)) {
       has_errors = TRUE;
@@ -23240,7 +24375,7 @@ erret:
 
   if (! report_errors) {
     if (! has_errors) {
-      if ((! frameshift_except) && (! rearrange_except) && (! mixed_population) && (! low_quality)) {
+      if ((! frameshift_except) && (! rearrange_except) && (! mixed_population) && (! low_quality) && (! artificial_location)) {
         ValidErr (vsp, SEV_WARNING, ERR_SEQ_FEAT_UnnecessaryException, "CDS has exception but passes translation test");
       }
     } else if (unclassified_except && (! other_than_mismatch)) {
@@ -23313,7 +24448,8 @@ static void SpliceCheckEx (ValidStructPtr vsp, SeqFeatPtr sfp, Boolean checkAll)
         StringISearch (sfp->except_text, "nonconsensus splice site") != NULL ||
         StringISearch (sfp->except_text, "adjusted for low-quality genome") != NULL ||
         StringISearch (sfp->except_text, "heterogeneous population sequenced") != NULL ||
-        StringISearch (sfp->except_text, "low-quality sequence region") != NULL) {
+        StringISearch (sfp->except_text, "low-quality sequence region") != NULL ||
+        StringISearch (sfp->except_text, "artificial location") != NULL) {
       report_errors = FALSE;
     }
   }
@@ -23536,7 +24672,9 @@ static void SpliceCheckEx (ValidStructPtr vsp, SeqFeatPtr sfp, Boolean checkAll)
               }
             }
           } else {
-            if (gpsOrRefSeq) {
+            if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+              severity = SEV_INFO;
+            } else if (gpsOrRefSeq) {
               severity = SEV_WARNING;
             } else if (checkExonDonor) {
               severity = SEV_WARNING;
@@ -23584,7 +24722,9 @@ static void SpliceCheckEx (ValidStructPtr vsp, SeqFeatPtr sfp, Boolean checkAll)
         has_errors = TRUE;
       } else if (IS_residue (residue1) && IS_residue (residue2)) {
         if (residue1 != 'A' || residue2 != 'G') {
-          if (gpsOrRefSeq) {
+          if (vsp->is_gpipe_in_sep && vsp->bsp_genomic_in_sep) {
+            severity = SEV_INFO;
+          } else if (gpsOrRefSeq) {
             severity = SEV_WARNING;
           } else if (checkExonAcceptor) {
             severity = SEV_WARNING;
@@ -23730,10 +24870,11 @@ NLM_EXTERN void ValidateSeqLoc (ValidStructPtr vsp, SeqLocPtr slp, CharPtr prefi
 {
   SeqLocPtr       tmp, prev;
   Boolean         retval = TRUE, tmpval, mixed_strand = FALSE, unmarked_strand = FALSE,
-                  ordered = TRUE, adjacent = FALSE, circular = FALSE, exception = FALSE;
+                  ordered = TRUE, adjacent = FALSE, circular = FALSE, exception = FALSE,
+                  bad = FALSE;
   CharPtr         ctmp;
   Uint1           strand2 = 0, strand1;
-  ErrSev          sev;
+  ErrSev          sev, oldsev;
   SeqIntPtr       sip1, sip2, prevsip;
   SeqPntPtr       spp;
   PackSeqPntPtr   pspp;
@@ -23964,7 +25105,10 @@ NLM_EXTERN void ValidateSeqLoc (ValidStructPtr vsp, SeqLocPtr slp, CharPtr prefi
 
   if (bsp == NULL || bsp->repr != Seq_repr_seg) return;
 
-  if (SeqLocBadSortOrder (bsp, slp)) {
+  oldsev = ErrSetMessageLevel (SEV_ERROR);
+  bad = SeqLocBadSortOrder (bsp, slp);
+  ErrSetMessageLevel (oldsev);
+  if (bad) {
     ctmp = SeqLocPrint (slp);
     if (ctmp != NULL && StringLen (ctmp) > 800) {
       StringCpy (ctmp + 797, "...");
@@ -23975,7 +25119,10 @@ NLM_EXTERN void ValidateSeqLoc (ValidStructPtr vsp, SeqLocPtr slp, CharPtr prefi
 
   /* newer check for mixed strand on segmented bioseq */
 
-  if (SeqLocMixedStrands (bsp, slp)) {
+  oldsev = ErrSetMessageLevel (SEV_ERROR);
+  bad = SeqLocMixedStrands (bsp, slp);
+  ErrSetMessageLevel (oldsev);
+  if (bad) {
     ctmp = SeqLocPrint (slp);
     if (ctmp != NULL && StringLen (ctmp) > 800) {
       StringCpy (ctmp + 797, "...");
diff --git a/api/valid.h b/api/valid.h
index b867f72..edd532c 100644
--- a/api/valid.h
+++ b/api/valid.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 1/1/94
 *
-* $Revision: 6.54 $
+* $Revision: 6.56 $
 *
 * File Description:  Sequence editing utilities
 *
@@ -165,11 +165,14 @@ typedef struct validstruct {
     Boolean is_htg_in_sep;         /* record has technique of htgs 0 through htgs 3 */
     Boolean is_barcode_sep;        /* record has technique barcode */
     Boolean is_refseq_in_sep;      /* record has seqid of type other (refseq) */
+    Boolean is_gpipe_in_sep;       /* record has seqid of type gpipe */
     Boolean is_gps_in_sep;         /* record has genomic product set */
+    Boolean other_sets_in_sep;     /* record has pop/phy/mut/eco/wgs set */
     Boolean is_embl_ddbj_in_sep;   /* record has embl or ddbj seqid */
     Boolean is_insd_in_sep;        /* record has genbank/embl/ddbj or tpg/tpe/tpd seqid */
     Boolean only_lcl_gnl_in_sep;   /* record has seqid of only local or general */
     Boolean has_gnl_prot_sep;      /* protein Bioseq has general seqid */
+    Boolean bsp_genomic_in_sep;    /* biosource.genome == genomic */
     Boolean is_smupd_in_sep;       /* record in INSD internal processing */
     Boolean feat_loc_has_gi;       /* at least one feature has a gi location reference */
     Boolean feat_prod_has_gi;      /* at least one feature has a gi product reference */
@@ -209,6 +212,8 @@ NLM_EXTERN void ECNumberFSAFreeAll (void);
 
 NLM_EXTERN Boolean HasTpaUserObject (BioseqPtr bsp);
 
+NLM_EXTERN Boolean CountryBoxesOverlap (CharPtr country1, CharPtr country2);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/api/valid.msg b/api/valid.msg
index 844d0c1..d8669dc 100644
--- a/api/valid.msg
+++ b/api/valid.msg
@@ -237,6 +237,11 @@ A SeqLit component of a delta Bioseq must not have 0 length.
 $^   DSmRNA, 67
 This mRNA Bioseq is not single stranded.
 
+$^   HighNContentStretch, 68
+This sequence contains long stretches of Ns.
+
+$^   HighNContentPercent, 69
+This sequence contains a high percentage of Ns.
 
 $$ SEQ_DESCR, 2
 
@@ -471,6 +476,40 @@ The title has (PMID #####) embedded in it.
 $^   BadKeyword, 65
 The keyword is not appropriate in this record.
 
+$^   NoOrganismInTitle, 66
+A RefSeq record should have the organism name at the beginning of a nucleotide
+title and bracketed at the end of a protein title.
+
+$^   MissingChromosome, 67
+An NC or AC RefSeq record should have a chromosome annotated.
+
+$^   LatLonAdjacent, 68
+The lat_lon coordinate may be in an adjacent country or in surrounding waters.
+
+$^   BadStrucCommInvalidFieldName, 69
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommInvalidFieldValue, 70
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommMissingField, 71
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommFieldOutOfOrder, 72
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommMultipleFields, 73
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BioSourceNeedsChromosome, 74
+Chromosome should be set on a BioSource descriptor in non-viral complete genomes.
+
+$^   MolInfoConflictsWithBioSource, 75
+Viral lineage information conflicts with MolInfo.
+
+$^   MissingKeyword, 76
+Expected keyword was not found.
+
 
 $$ GENERIC, 3
 
@@ -520,6 +559,14 @@ Some fields in the publication should not be present with other fields.
 $^ SgmlPresentInText, 13
 SGML markup is embedded in text.
 
+$^ UnexpectedPubStatusComment, 14
+An unexpected publication status exists for a print, online-only,
+or ahead-of-print article : Content-Of-Pubdesc.comment-String.
+
+$^ PastReleaseDate, 15
+The record has is marked as hold-until-published, but the release
+anyway date has already passed.
+
 $$ SEQ_PKG, 4
 
 $^   NoCdRegionPtr, 1
@@ -593,6 +640,22 @@ RefSeq records should not be packaged in a popset.
 $^   BioseqSetClassNotSet, 22
 The BioseqSet class field is not set.
 
+$^   OrphanedProtein, 23
+The Bioseq is an INSD or RefSeq protein erroneously not in a nuc-prot set.
+
+$^   MissingSetTitle, 24
+No title was found on a pop/phy/mut/eco set.
+
+$^   NucProtSetHasTitle, 25
+A title descriptor was found on a nuc-prot set.
+
+$^   ComponentMissingTitle, 26
+A title descriptor should be present on the components of a
+pop/phy/mut/eco set.
+
+$^   SingleItemSet, 27
+Only a single Bioseq was found in this BioseqSet. Is that what was intended?
+
 
 $$ SEQ_FEAT, 5
 
@@ -1268,6 +1331,9 @@ This feature has a gene xref that points to a gene on the wrong strand.
 $^ CDSmRNAXrefLocationProblem, 175
 The CDS is not contained within the cross-referenced mRNA.
 
+$^ LocusCollidesWithLocusTag, 176
+A gene locus is identical with a gene locus_tag.
+
 $$ SEQ_ALIGN, 6
 
 $^   SeqIdProblem, 1
diff --git a/api/validerr.h b/api/validerr.h
index 6b8aeac..515f59b 100644
--- a/api/validerr.h
+++ b/api/validerr.h
@@ -69,6 +69,8 @@
 #define ERR_SEQ_INST_HighNContent  1,65
 #define ERR_SEQ_INST_SeqLitDataLength0  1,66
 #define ERR_SEQ_INST_DSmRNA  1,67
+#define ERR_SEQ_INST_HighNContentStretch  1,68
+#define ERR_SEQ_INST_HighNContentPercent  1,69
 #define ERR_SEQ_DESCR  2,0
 #define ERR_SEQ_DESCR_BioSourceMissing  2,1
 #define ERR_SEQ_DESCR_InvalidForType  2,2
@@ -135,6 +137,17 @@
 #define ERR_SEQ_DESCR_UserObjectProblem  2,63
 #define ERR_SEQ_DESCR_TitleHasPMID  2,64
 #define ERR_SEQ_DESCR_BadKeyword  2,65
+#define ERR_SEQ_DESCR_NoOrganismInTitle  2,66
+#define ERR_SEQ_DESCR_MissingChromosome  2,67
+#define ERR_SEQ_DESCR_LatLonAdjacent  2,68
+#define ERR_SEQ_DESCR_BadStrucCommInvalidFieldName  2,69
+#define ERR_SEQ_DESCR_BadStrucCommInvalidFieldValue  2,70
+#define ERR_SEQ_DESCR_BadStrucCommMissingField  2,71
+#define ERR_SEQ_DESCR_BadStrucCommFieldOutOfOrder  2,72
+#define ERR_SEQ_DESCR_BadStrucCommMultipleFields  2,73
+#define ERR_SEQ_DESCR_BioSourceNeedsChromosome  2,74
+#define ERR_SEQ_DESCR_MolInfoConflictsWithBioSource  2,75
+#define ERR_SEQ_DESCR_MissingKeyword  2,76
 #define ERR_GENERIC  3,0
 #define ERR_GENERIC_NonAsciiAsn  3,1
 #define ERR_GENERIC_Spell  3,2
@@ -149,6 +162,8 @@
 #define ERR_GENERIC_EmbeddedScript  3,11
 #define ERR_GENERIC_PublicationInconsistency  3,12
 #define ERR_GENERIC_SgmlPresentInText  3,13
+#define ERR_GENERIC_UnexpectedPubStatusComment  3,14
+#define ERR_GENERIC_PastReleaseDate  3,15
 #define ERR_SEQ_PKG  4,0
 #define ERR_SEQ_PKG_NoCdRegionPtr  4,1
 #define ERR_SEQ_PKG_NucProtProblem  4,2
@@ -172,6 +187,11 @@
 #define ERR_SEQ_PKG_GPSnonGPSPackaging  4,20
 #define ERR_SEQ_PKG_RefSeqPopSet  4,21
 #define ERR_SEQ_PKG_BioseqSetClassNotSet  4,22
+#define ERR_SEQ_PKG_OrphanedProtein  4,23
+#define ERR_SEQ_PKG_MissingSetTitle  4,24
+#define ERR_SEQ_PKG_NucProtSetHasTitle  4,25
+#define ERR_SEQ_PKG_ComponentMissingTitle  4,26
+#define ERR_SEQ_PKG_SingleItemSet  4,27
 #define ERR_SEQ_FEAT  5,0
 #define ERR_SEQ_FEAT_InvalidForType  5,1
 #define ERR_SEQ_FEAT_PartialProblem  5,2
@@ -348,6 +368,7 @@
 #define ERR_SEQ_FEAT_ShortIntron  5,173
 #define ERR_SEQ_FEAT_GeneXrefStrandProblem  5,174
 #define ERR_SEQ_FEAT_CDSmRNAXrefLocationProblem  5,175
+#define ERR_SEQ_FEAT_LocusCollidesWithLocusTag  5,176
 #define ERR_SEQ_ALIGN  6,0
 #define ERR_SEQ_ALIGN_SeqIdProblem  6,1
 #define ERR_SEQ_ALIGN_StrandRev  6,2
diff --git a/asn/asn.all b/asn/asn.all
index 2d4743b..c4723f8 100644
--- a/asn/asn.all
+++ b/asn/asn.all
@@ -614,7 +614,7 @@ Pub-set ::= CHOICE {
 
 END
 
---$Revision: 6.4 $
+--$Revision: 6.5 $
 --**********************************************************************
 --
 --  NCBI Sequence location and identifier elements
@@ -660,6 +660,8 @@ Seq-id ::= CHOICE {
     named-annot-track Textseq-id -- Internal named annotation tracking ID
 }
 
+Seq-id-set ::= SET OF Seq-id
+
 
 Patent-seq-id ::= SEQUENCE {
     seqid INTEGER ,         -- number of sequence in patent
@@ -741,7 +743,7 @@ Seq-loc-equiv ::= SET OF Seq-loc      -- for a set of equivalent locations
 END
     
 
---$Revision: 6.20 $
+--$Revision: 6.21 $
 --**********************************************************************
 --
 --  NCBI Sequence elements
@@ -755,7 +757,7 @@ BEGIN
 
 EXPORTS Annotdesc, Annot-descr, Bioseq, GIBB-mol, Heterogen, MolInfo,
         Numbering, Pubdesc, Seq-annot, Seq-data, Seqdesc, Seq-descr, Seq-ext,
-        Seq-hist, Seq-inst, Seq-literal, Seqdesc, Delta-ext;
+        Seq-hist, Seq-inst, Seq-literal, Seqdesc, Delta-ext, Seq-gap;
 
 IMPORTS Date, Int-fuzz, Dbtag, Object-id, User-object FROM NCBI-General
         Seq-align FROM NCBI-Seqalign
@@ -1561,7 +1563,7 @@ PDB-replace ::= SEQUENCE {
 
 END
 
---$Revision: 6.27 $
+--$Revision: 6.35 $
 --**********************************************************************
 --
 --  NCBI Sequence Feature elements
@@ -1578,6 +1580,7 @@ EXPORTS Seq-feat, Feat-id, Genetic-code;
 IMPORTS Gene-ref FROM NCBI-Gene
         Prot-ref FROM NCBI-Protein
         Org-ref FROM NCBI-Organism
+        Variation-ref FROM NCBI-Variation
         BioSource FROM NCBI-BioSource
         RNA-ref FROM NCBI-RNA
         Seq-loc, Giimport-id FROM NCBI-Seqloc
@@ -1677,7 +1680,8 @@ SeqFeatData ::= CHOICE {
     non-std-residue VisibleString ,  -- non-standard residue here in seq
     het Heterogen ,         -- cofactor, prosthetic grp, etc, bound to seq
     biosrc BioSource,
-    clone Clone-ref
+    clone Clone-ref,
+    variation Variation-ref
 }
 
 SeqFeatXref ::= SEQUENCE {       -- both optional because can have one or both
@@ -1796,9 +1800,460 @@ Clone-seq ::= SEQUENCE {
     align-id Dbtag OPTIONAL
 }
 
+END
+
+
+--*** Variation-ref ***********************************************
+--*
+--*  Specification of variation features
+--*
+
+NCBI-Variation DEFINITIONS ::=
+BEGIN
+
+EXPORTS Variation-ref, Variation-inst;
+
+IMPORTS Int-fuzz, User-object, Object-id, Dbtag FROM NCBI-General
+        Seq-literal FROM NCBI-Sequence
+        Seq-loc FROM NCBI-Seqloc
+        Pub FROM NCBI-Pub;
+
+-- --------------------------------------------------------------------------
+-- Historically, the dbSNP definitions document data structures used in the
+-- processing and annotation of variations by the dbSNP group.  The intention
+-- is to provide information to clients that reflect internal information
+-- produced during the mapping of SNPs
+-- --------------------------------------------------------------------------
+
+VariantProperties ::= SEQUENCE {
+    version INTEGER,
+
+    -- NOTE:
+    -- The format for each of these values is as an integer
+    -- Unless otherwise noted, these integers represent a bitwise OR of the
+    -- possible values, and as such, these values represent the specific bit
+    -- flags that may be set for each of the possible attributes here.
+
+    resource-link INTEGER {
+        preserved        (1), -- Clinical, Pubmed, Cited, (0x01)
+        provisional      (2), -- Provisional Third Party Annotations (0x02)
+        has3D            (4), -- Has 3D strcture SNP3D table (0x04)
+        submitterLinkout (8), -- SNP->SubSNP->Batch link_out (0x08)
+        clinical        (16), -- Clinical if LSDB, OMIM, TPA, Diagnostic (0x10)
+        genotypeKit     (32)  -- Marker exists on high density genotyping kit
+                              -- (0x20)
+    } OPTIONAL,
+
+    gene-location INTEGER {
+        in-gene         (1), -- Sequence intervals covered by a gene ID but not
+                             -- having an aligned transcript (0x01)
+        near-gene-5     (2), -- Within 2kb of the 5' end of a gene feature
+        near-gene-3     (4), -- Within 0.5kb of the 3' end of a gene feature
+        intron          (8), -- In Intron (0x08)
+        donor          (16), -- In donor splice-site (0x10)
+        acceptor       (32), -- In acceptor splice-site (0x20)
+        utr-5          (64), -- In 5' UTR (0x40)
+        utr-3         (128), -- In 3' UTR (0x80)
+        in-start-codon(256), -- the variant is observed in a start codon
+                             -- (0x100)
+        in-stop-codon (512), -- the variant is observed in a stop codon
+                             -- (0x200)
+        intergenic   (1024), -- variant located between genes (0x400)
+        conserved-noncoding(2048) -- variant is located in a conserved
+                                  -- non-coding region (0x800)
+    } OPTIONAL,
+
+    effect INTEGER {
+        no-change      (0), -- known to cause no functional changes
+                            -- since 0 does not combine with any other bit
+                            -- value, 'no-change' specifically implies that
+                            -- there are no consequences
+        synonymous     (1), -- one allele in the set does not change the encoded
+                            -- amino acid (0x1)
+        nonsense       (2), -- one allele in the set changes to STOP codon
+                            -- (TER).  (0x2)
+        missense       (4), -- one allele in the set changes protein peptide
+                            -- (0x4)
+        frameshift     (8), -- one allele in the set changes all downstream
+                            -- amino acids (0x8)
+
+        up-regulator  (16), -- the variant causes increased transcription
+                            -- (0x10)
+        down-regulator(32), -- the variant causes decreased transcription
+                            -- (0x20)
+        methylation(64)
+    } OPTIONAL,
+
+    mapping INTEGER {
+        has-other-snp         (1), -- Another SNP has the same mapped positions
+                                   -- on reference assembly (0x01)
+        has-assembly-conflict (2), -- Weight 1 or 2 SNPs that map to different
+                                   -- chromosomes on different assemblies (0x02)
+        is-assembly-specific  (4)  -- Only maps to 1 assembly (0x04)
+    } OPTIONAL,
+
+    -- This is *NOT* a bitfield
+    map-weight INTEGER {
+        is-uniquely-placed(1),
+        placed-twice-on-same-chrom(2),
+        placed-twice-on-diff-chrom(3),
+        many-placements(10)
+    } OPTIONAL,
+
+    frequency-based-validation INTEGER {
+        is-mutation       (1), -- low frequency variation that is cited in
+                               -- journal or other reputable sources (0x01)
+        above-5pct-all    (2), -- >5% minor allele freq in each and all
+                               -- populations (0x02)
+        above-5pct-1plus  (4), -- >5% minor allele freq in 1+ populations (0x04)
+        validated         (8), -- Bit is set if the variant has 2+ minor allele
+                               -- count based on freq or genotype data
+        above-1pct-all   (16), -- >1% minor allele freq in each and all
+                               -- populations (0x10)
+        above-1pct-1plus (32)  -- >1% minor allele freq in 1+ populations (0x20)
+    } OPTIONAL,
+
+    genotype INTEGER {
+        in-haplotype-set (1), -- Exists in a haplotype tagging set (0x01)
+        has-genotypes    (2)  -- SNP has individual genotype (0x02)
+    } OPTIONAL,
+
+    project-data SET OF SEQUENCE {
+        -- project IDs are IDs from BioProjects
+        -- in order to report information about project relationships, we
+        -- require projects to be registered
+        -- This field in many ways duplicates dbxrefs; however, the
+        -- intention of this field is to more adequately reflects
+        -- ownership and data source
+        project-ids SET OF INTEGER
+    } OPTIONAL,
+
+    quality-check INTEGER {
+        contig-allele-missing   (1), -- Reference sequence allele at the mapped
+                                     -- position is not present in the SNP
+                                     -- allele list, adjusted for orientation
+                                     -- (0x01)
+        withdrawn-by-submitter  (2), -- One member SS is withdrawn by submitter
+                                     -- (0x02)
+        non-overlapping-alleles (4), -- RS set has 2+ alleles from different
+                                     -- submissions and these sets share no
+                                     -- alleles in common (0x04)
+        strain-specific         (8), -- Straing specific fixed difference (0x08)
+        genotype-conflict      (16)  -- Has Genotype Conflict (0x10)
+    } OPTIONAL,
+
+    confidence INTEGER {
+        unknown         (0),
+        likely-artifact (1),
+        other           (255)
+    } OPTIONAL
+}
+
+Phenotype ::= SEQUENCE {
+    source VisibleString OPTIONAL,
+    term VisibleString OPTIONAL,
+    xref SET OF Dbtag OPTIONAL,
+
+    -- does this variant have known clinical significance?
+    clinical-significance INTEGER {
+        unknown                 (0),
+        untested                (1),
+        non-pathogenic          (2),
+        probable-non-pathogenic (3),
+        probable-pathogenic     (4),
+        pathogenic              (5),
+        other                   (255)
+    } OPTIONAL
+}
+
+Population-data ::= SEQUENCE {
+    -- assayed population (e.g. HAPMAP-CEU)
+    population VisibleString,
+    genotype-frequency REAL OPTIONAL,
+    chromosomes-tested INTEGER OPTIONAL,
+    sample-ids SET OF Object-id OPTIONAL
+}
+
+Ext-loc ::= SEQUENCE {
+    id Object-id,
+    location Seq-loc
+}
+
+Variation-ref ::= SEQUENCE {
+    -- ids (i.e., SNP rsid / ssid, dbVar nsv/nssv)
+    -- expected values include 'dbSNP|rs12334', 'dbSNP|ss12345', 'dbVar|nsv1'
+    --
+    -- we relate three kinds of IDs here:
+    --  - our current object's id
+    --  - the id of this object's parent, if it exists
+    --  - the sample ID that this item originates from
+    id        Dbtag OPTIONAL,
+    parent-id Dbtag OPTIONAL,
+    sample-id Object-id OPTIONAL,
+    other-ids SET OF Dbtag OPTIONAL,
+
+    -- names and synonyms
+    -- some variants have well-known canonical names and possible accepted
+    -- synonyms
+    name VisibleString OPTIONAL,
+    synonyms SET OF VisibleString OPTIONAL,
+
+    -- tag for comment and descriptions
+    description VisibleString OPTIONAL,
+
+    -- phenotype
+    phenotype SET OF Phenotype OPTIONAL,
+
+    -- sequencing / acuisition method
+    method SET OF INTEGER {
+        unknown             (0),
+        bac-acgh            (1),
+        computational       (2),
+        curated             (3),
+        digital-array       (4),
+        expression-array    (5),
+        fish                (6),
+        flanking-sequence   (7),
+        maph                (8),
+        mcd-analysis        (9),
+        mlpa                (10),
+        oea-assembly        (11),
+        oligo-acgh          (12),
+        paired-end          (13),
+        pcr                 (14),
+        qpcr                (15),
+        read-depth          (16),
+        roma                (17),
+        rt-pcr              (18),
+        sage                (19),
+        sequence-alignment  (20),
+        sequencing          (21),
+        snp-array           (22),
+        snp-genoytyping     (23),
+        southern            (24),
+        western             (25),
+        optical-mapping     (26),
+
+        other               (255)
+    } OPTIONAL,
+
+    -- Note about SNP representation and pretinent fields: allele-frequency,
+    -- population, quality-codes:
+    -- The case of multiple alleles for a SNP would be described by
+    -- parent-feature of type Variation-set.diff-alleles, where the child
+    -- features of type Variation-inst, all at the same location, would
+    -- describe individual alleles.
+
+    -- population data
+    population-data SET OF Population-data OPTIONAL,
+
+    -- variant properties bit fields
+    variant-prop VariantProperties OPTIONAL,
+
+    -- has this variant been validated?
+    validated BOOLEAN OPTIONAL,
+
+    -- link-outs to GeneTests database
+    clinical-test SET OF Dbtag OPTIONAL,
+
+    -- origin of this allele, if known
+    allele-origin INTEGER {
+        unknown         (0),
+        germline        (1),
+        somatic         (2),
+        inherited       (3),
+        paternal        (4),
+        maternal        (5),
+        de-novo         (6),
+        biparental      (7),
+        uniparental     (8),
+        not-tested      (9),
+        tested-inconclusive (10),
+
+        other           (255)
+    } OPTIONAL,
+
+    -- observed allele state, if known
+    allele-state INTEGER {
+        unknown         (0),
+        homozygous      (1),
+        heterozygous    (2),
+        hemizygous      (3),
+        nullizygous     (4),
+        other           (255)
+    } OPTIONAL,
+
+    allele-frequency REAL OPTIONAL,
+
+    -- is this variant the ancestral allele?
+    is-ancestral-allele BOOLEAN OPTIONAL,
+
+    -- publication support.
+    -- Note: made this pub instead of pub-equiv, since
+    -- Pub can be pub-equiv and pub-equiv is a set of pubs, but it looks like
+    -- Pub is more often used as top-level container
+    pub Pub OPTIONAL,
+
+    data CHOICE {
+        unknown NULL,
+        note    VisibleString, --free-form
+        uniparental-disomy NULL,
+
+        -- actual sequence-edit at feat.location
+        instance        Variation-inst,
+
+        -- Set of related Variations.
+        -- Location of the set equals to the union of member locations
+        set SEQUENCE {
+            type INTEGER {
+                unknown     (0),
+                compound    (1), -- complex change at the same location on the
+                                 -- same molecule
+                products    (2), -- different products arising from the same
+                                 -- variation in a precursor, e.g. r.[13g>a,
+                                 -- 13_88del]
+                haplotype   (3), -- changes on the same allele, e.g
+                                 -- r.[13g>a;15u>c]
+                genotype    (4), -- changes on different alleles in the same
+                                 -- genotype, e.g. g.[476C>T]+[476C>T]
+                mosaic      (5), -- different genotypes in the same individual
+                individual  (6), -- same organism; allele relationship unknown,
+                                 -- e.g. g.[476C>T(+)183G>C]
+                population  (7), -- population
+                alleles     (8), -- set represents a set of observed alleles
+                other       (255)
+            },
+            variations SET OF Variation-ref,
+            name  VisibleString OPTIONAL
+        }
+    },
+
+    consequence SET OF CHOICE {
+        unknown     NULL,
+        splicing    NULL, --some effect on splicing
+        note        VisibleString,  --freeform
+
+        -- Describe resulting variation in the product, e.g. missense,
+        -- nonsense, silent, neutral, etc in a protein, that arises from
+        -- THIS variation.
+        variation   Variation-ref,
+
+        -- see http://www.hgvs.org/mutnomen/recs-prot.html
+        frameshift SEQUENCE {
+            phase INTEGER OPTIONAL,
+            x-length INTEGER OPTIONAL
+        },
+
+        loss-of-heterozygosity SEQUENCE {
+            -- In germline comparison, it will be reference genome assembly
+            -- (default) or reference/normal population. In somatic mutation,
+            -- it will be a name of the normal tissue.
+            reference VisibleString OPTIONAL,
+
+            -- Name of the testing subject type or the testing tissue.
+            test VisibleString OPTIONAL
+        }
+    } OPTIONAL,
+
+    -- Observed location, if different from the parent set or feature.location.
+    location        Seq-loc OPTIONAL,
+
+    -- reference other locs, e.g. mapped source
+    ext-locs SET OF Ext-loc OPTIONAL,
+
+    ext             User-object OPTIONAL
+
+}
+
+Delta-item ::= SEQUENCE {
+    seq CHOICE {
+        literal Seq-literal,
+        loc Seq-loc,
+        this NULL --same location as variation-ref itself
+    } OPTIONAL,
+
+    -- Multiplier allows representing a tandem, e.g.  ATATAT as AT*3
+    -- This allows describing CNV/SSR where delta=self  with a
+    -- multiplier which specifies the count of the repeat unit.
+
+    multiplier          INTEGER OPTIONAL, --assumed 1 if not specified.
+    multiplier-fuzz     Int-fuzz OPTIONAL,
+
+    action INTEGER {
+
+        -- replace len(seq) positions starting with location.start with seq
+        morph      (0),
+
+        -- go downstream by distance specified by multiplier (upstream if < 0),
+        -- in genomic context.
+        offset     (1),
+
+        -- excise sequence at location
+        -- if multiplier is specified, delete len(location)*multiplier
+        -- positions downstream
+        del-at     (2),
+
+        -- insert seq before the location.start
+        ins-before (3)
+
+    } DEFAULT morph
+}
+
+
+-- Variation instance
+Variation-inst ::= SEQUENCE {
+    type INTEGER {
+        unknown         (0),    -- delta=[]
+        identity        (1),    -- delta=[]
+        inv             (2),    -- delta=[del, ins.seq=
+                                -- RevComp(variation-location)]
+        snv             (3),    -- delta=[morph of length 1]
+                                -- NOTE: this is snV not snP; the latter
+                                -- requires frequency-based validation to be
+                                -- established in VariantProperties
+                                -- the strict definition of SNP is an SNV with
+                                -- an established population frequency of at
+                                -- least 1% in at least 1 popuplation
+        mnp             (4),    -- delta=[morph of length >1]
+        delins          (5),    -- delta=[del, ins]
+        del             (6),    -- delta=[del]
+        ins             (7),    -- delta=[ins]
+        microsatellite  (8),    -- delta=[del, ins.seq= repeat-unit with fuzzy
+                                -- multiplier]
+                                -- variation-location is the microsat expansion
+                                -- on the sequence
+        transposon      (9),    -- delta=[del, ins.seq= known donor or 'this']
+                                -- variation-location is equiv of transposon
+                                -- locs.
+        cnv             (10),   -- delta=[del, ins= 'this' with fuzzy
+                                -- multiplier]
+        direct-copy     (11),   -- delta=[ins.seq= upstream location on the
+                                -- same strand]
+        rev-direct-copy (12),   -- delta=[ins.seq= downstream location on the
+                                -- same strand]
+        inverted-copy   (13),   -- delta=[ins.seq= upstream location on the
+                                -- opposite strand]
+        everted-copy    (14),   -- delta=[ins.seq= downstream location on the
+                                -- opposite strand]
+        translocation   (15),   -- delta=like delins
+        prot-missense   (16),   -- delta=[morph of length 1]
+        prot-nonsense   (17),   -- delta=[del]; variation-location is the tail
+                                -- of the protein being truncated
+        prot-neutral    (18),   -- delta=[morph of length 1]
+        prot-silent     (19),   -- delta=[morph of length 1, same AA as at
+                                -- variation-location]
+        prot-other      (20),   -- delta=any
+
+        other           (255)   -- delta=any
+    },
+
+    -- Sequence that replaces the location, in biological order.
+    delta SEQUENCE OF Delta-item
+}
 
 END 
 
+
 --**********************************************************************
 --
 --  NCBI Restriction Sites
@@ -1974,7 +2429,8 @@ OrgName ::= SEQUENCE {
     lineage VisibleString OPTIONAL ,       -- lineage with semicolon separators
     gcode INTEGER OPTIONAL ,               -- genetic code (see CdRegion)
     mgcode INTEGER OPTIONAL ,              -- mitochondrial genetic code
-    div VisibleString OPTIONAL }           -- GenBank division code
+    div VisibleString OPTIONAL ,           -- GenBank division code
+    pgcode INTEGER OPTIONAL }              -- plastid genetic code
     
 
 OrgMod ::= SEQUENCE {
@@ -2201,8 +2657,6 @@ Prot-ref ::= SEQUENCE {
        signal-peptide (3) ,
        transit-peptide (4) } DEFAULT not-set }
 
-
-
 END 
 --********************************************************************
 --
@@ -2282,7 +2736,6 @@ Tx-evidence ::= SEQUENCE {
     --          product (blocked  by  RNA  5'end)  by  comparison with
     --          homologous sequence ladder (J. Mol. Biol. 199, 587)
 
-    
 END
 
 --$Revision: 1.5 $
@@ -3461,12 +3914,12 @@ PrintFormText ::= SEQUENCE {
     
 END
 
---$Revision: 6.7 $
+--$Revision: 6.10 $
 --*********************************************************
 --
 -- ASN.1 and XML for the components of a GenBank format sequence
 -- J.Ostell 2002
--- Updated 15 January 2009
+-- Updated 25 May 2010
 --
 --*********************************************************
 
@@ -3574,22 +4027,23 @@ GBSeq ::= SEQUENCE {
     taxonomy VisibleString OPTIONAL ,
     references SEQUENCE OF GBReference OPTIONAL ,
     comment VisibleString OPTIONAL ,
-    tagset GBTagset OPTIONAL ,
+    comment-set SEQUENCE OF GBComment OPTIONAL ,
+    struc-comments SEQUENCE OF GBStrucComment OPTIONAL ,
     primary VisibleString OPTIONAL ,
     source-db VisibleString OPTIONAL ,
     database-reference VisibleString OPTIONAL ,
     feature-table SEQUENCE OF GBFeature OPTIONAL ,
-    sequence VisibleString OPTIONAL ,  -- Optional for other dump forms
-    contig VisibleString OPTIONAL
+    feature-set SEQUENCE OF GBFeatureSet OPTIONAL ,
+    sequence VisibleString OPTIONAL ,  -- Optional for contig, wgs, etc.
+    contig VisibleString OPTIONAL ,
+    alt-seq SEQUENCE OF GBAltSeqData OPTIONAL
 }
 
-GBSecondary-accn ::= VisibleString
-
 GBSeqid ::= VisibleString
 
-GBKeyword ::= VisibleString
+GBSecondary-accn ::= VisibleString
 
-GBAuthor ::= VisibleString
+GBKeyword ::= VisibleString
 
 GBReference ::= SEQUENCE {
     reference VisibleString ,
@@ -3598,29 +4052,46 @@ GBReference ::= SEQUENCE {
     consortium VisibleString OPTIONAL ,
     title VisibleString OPTIONAL ,
     journal VisibleString ,
-    xref SET OF GBXref OPTIONAL ,
+    xref SEQUENCE OF GBXref OPTIONAL ,
     pubmed INTEGER OPTIONAL ,
     remark VisibleString OPTIONAL
 }
 
+GBAuthor ::= VisibleString
+
 GBXref ::= SEQUENCE {
     dbname VisibleString ,
     id VisibleString
 }
 
-GBTagset ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    url VisibleString OPTIONAL ,
-    tags GBTags OPTIONAL
+GBComment ::= SEQUENCE {
+    type VisibleString OPTIONAL ,
+    paragraphs SEQUENCE OF GBCommentParagraph
+}
+
+GBCommentParagraph ::= SEQUENCE {
+    items SEQUENCE OF GBCommentItem
 }
 
-GBTags ::= SEQUENCE OF GBTag
+GBCommentItem ::= SEQUENCE {
+    value VisibleString OPTIONAL ,
+    url VisibleString OPTIONAL
+}
 
-GBTag ::= SEQUENCE {
+GBStrucComment ::= SEQUENCE {
     name VisibleString OPTIONAL ,
+    items SEQUENCE OF GBStrucCommentItem
+}
+
+GBStrucCommentItem ::= SEQUENCE {
+    tag VisibleString OPTIONAL ,
     value VisibleString OPTIONAL ,
-    unit VisibleString OPTIONAL
+    url VisibleString OPTIONAL
+}
+
+GBFeatureSet ::= SEQUENCE {
+    annot-source VisibleString OPTIONAL ,
+    features SEQUENCE OF GBFeature
 }
 
 GBFeature ::= SEQUENCE {
@@ -3630,7 +4101,8 @@ GBFeature ::= SEQUENCE {
     operator VisibleString OPTIONAL ,
     partial5 BOOLEAN OPTIONAL ,
     partial3 BOOLEAN OPTIONAL ,
-    quals SEQUENCE OF GBQualifier OPTIONAL
+    quals SEQUENCE OF GBQualifier OPTIONAL ,
+    xrefs SEQUENCE OF GBXref OPTIONAL
 }
 
 GBInterval ::= SEQUENCE {
@@ -3647,27 +4119,31 @@ GBQualifier ::= SEQUENCE {
     value VisibleString OPTIONAL
 }
 
-GBTagsetRules ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    mandatorytags GBTagNames OPTIONAL ,
-    optionaltags GBTagNames OPTIONAL ,
-    uniquetags GBTagNames OPTIONAL ,
-    extensible BOOLEAN OPTIONAL
+GBAltSeqData ::= SEQUENCE {
+    name VisibleString ,  -- e.g., contig, wgs, scaffold, cage, genome
+    items SEQUENCE OF GBAltSeqItem OPTIONAL
 }
 
-GBTagNames ::= SEQUENCE OF VisibleString
-
-GBTagsetRuleSet ::= SEQUENCE OF GBTagsetRules
+GBAltSeqItem ::= SEQUENCE {
+    interval GBInterval OPTIONAL ,
+    isgap BOOLEAN OPTIONAL ,
+    gap-length INTEGER OPTIONAL ,
+    gap-type VisibleString OPTIONAL ,
+    gap-linkage VisibleString OPTIONAL ,
+    gap-comment VisibleString OPTIONAL ,
+    first-accn VisibleString OPTIONAL ,
+    last-accn VisibleString OPTIONAL ,
+    value VisibleString OPTIONAL
+}
 
 END
 
---$Revision: 1.7 $
+--$Revision: 1.8 $
 --************************************************************************
 --
 -- ASN.1 and XML for the components of a GenBank/EMBL/DDBJ sequence record
 -- The International Nucleotide Sequence Database (INSD) collaboration
--- Version 1.5, 15 January 2009
+-- Version 1.6, 25 May 2010
 --
 --************************************************************************
 
@@ -3779,13 +4255,16 @@ INSDSeq ::= SEQUENCE {
     taxonomy VisibleString OPTIONAL ,
     references SEQUENCE OF INSDReference OPTIONAL ,
     comment VisibleString OPTIONAL ,
-    tagset INSDTagset OPTIONAL ,
+    comment-set SEQUENCE OF INSDComment OPTIONAL ,
+    struc-comments SEQUENCE OF INSDStrucComment OPTIONAL ,
     primary VisibleString OPTIONAL ,
     source-db VisibleString OPTIONAL ,
     database-reference VisibleString OPTIONAL ,
     feature-table SEQUENCE OF INSDFeature OPTIONAL ,
-    sequence VisibleString OPTIONAL ,  -- Optional for other dump forms
-    contig VisibleString OPTIONAL
+    feature-set SEQUENCE OF INSDFeatureSet OPTIONAL ,
+    sequence VisibleString OPTIONAL ,  -- Optional for contig, wgs, etc.
+    contig VisibleString OPTIONAL ,
+    alt-seq SEQUENCE OF INSDAltSeqData OPTIONAL
 }
 
 INSDSeqid ::= VisibleString
@@ -3815,8 +4294,6 @@ INSDKeyword ::= VisibleString
 --   References that lack an INSDReference_position element apply
 --   to the entire sequence.
 
-INSDAuthor ::= VisibleString
-
 INSDReference ::= SEQUENCE {
     reference VisibleString ,
     position VisibleString OPTIONAL ,
@@ -3824,11 +4301,13 @@ INSDReference ::= SEQUENCE {
     consortium VisibleString OPTIONAL ,
     title VisibleString OPTIONAL ,
     journal VisibleString ,
-    xref SET OF INSDXref OPTIONAL ,
+    xref SEQUENCE OF INSDXref OPTIONAL ,
     pubmed INTEGER OPTIONAL ,
     remark VisibleString OPTIONAL
 }
 
+INSDAuthor ::= VisibleString
+
 -- INSDXref provides a method for referring to records in
 -- other databases. INSDXref_dbname is a string value that
 -- provides the name of the database, and INSDXref_dbname
@@ -3840,22 +4319,29 @@ INSDXref ::= SEQUENCE {
     id VisibleString
 }
 
--- INSDTagset is used for community-specific data elements
--- in a tag/value format.
+INSDComment ::= SEQUENCE {
+    type VisibleString OPTIONAL ,
+    paragraphs SEQUENCE OF INSDCommentParagraph
+}
 
-INSDTagset ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    url VisibleString OPTIONAL ,
-    tags INSDTags OPTIONAL
+INSDCommentParagraph ::= SEQUENCE {
+    items SEQUENCE OF INSDCommentItem
 }
 
-INSDTags ::= SEQUENCE OF INSDTag
+INSDCommentItem ::= SEQUENCE {
+    value VisibleString OPTIONAL ,
+    url VisibleString OPTIONAL
+}
 
-INSDTag ::= SEQUENCE {
+INSDStrucComment ::= SEQUENCE {
     name VisibleString OPTIONAL ,
+    items SEQUENCE OF INSDStrucCommentItem
+}
+
+INSDStrucCommentItem ::= SEQUENCE {
+    tag VisibleString OPTIONAL ,
     value VisibleString OPTIONAL ,
-    unit VisibleString OPTIONAL
+    url VisibleString OPTIONAL
 }
 
 -- INSDFeature_operator contains a string value describing
@@ -3873,6 +4359,11 @@ INSDTag ::= SEQUENCE {
 --   Either 'join' or 'order' is required if INSDFeature_intervals
 --   is comprised of more than one INSDInterval .
 
+INSDFeatureSet ::= SEQUENCE {
+    annot-source VisibleString OPTIONAL ,
+    features SEQUENCE OF INSDFeature
+}
+
 INSDFeature ::= SEQUENCE {
     key VisibleString ,
     location VisibleString ,
@@ -3880,7 +4371,8 @@ INSDFeature ::= SEQUENCE {
     operator VisibleString OPTIONAL ,
     partial5 BOOLEAN OPTIONAL ,
     partial3 BOOLEAN OPTIONAL ,
-    quals SEQUENCE OF INSDQualifier OPTIONAL
+    quals SEQUENCE OF INSDQualifier OPTIONAL ,
+    xrefs SEQUENCE OF INSDXref OPTIONAL
 }
 
 -- INSDInterval_iscomp is a boolean indicating whether
@@ -3911,25 +4403,23 @@ INSDQualifier ::= SEQUENCE {
     value VisibleString OPTIONAL
 }
 
--- INSDTagsetRules defines mandatory, optional, and unique tags
--- for a given community's INSDTagset. If the tagset is extensible,
--- then additional tags which are not included in the list of
--- mandatory or optional tags may be present. The uniquetags
--- element provides a list of the tags that may occur only once
--- in a given tagset.
-
-INSDTagsetRules ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    mandatorytags INSDTagNames OPTIONAL ,
-    optionaltags INSDTagNames OPTIONAL ,
-    uniquetags INSDTagNames OPTIONAL ,
-    extensible BOOLEAN OPTIONAL
+INSDAltSeqData ::= SEQUENCE {
+    name VisibleString ,  -- e.g., CON-division-join, WGS-contig-range,
+                          -- WGS-scaffold-range, MGA/CAGE-range, genome
+    items SEQUENCE OF INSDAltSeqItem OPTIONAL
 }
 
-INSDTagNames ::= SEQUENCE OF VisibleString
-
-INSDTagsetRuleSet ::= SEQUENCE OF INSDTagsetRules
+INSDAltSeqItem ::= SEQUENCE {
+    interval INSDInterval OPTIONAL ,
+    isgap BOOLEAN OPTIONAL ,
+    gap-length INTEGER OPTIONAL ,
+    gap-type VisibleString OPTIONAL ,
+    gap-linkage VisibleString OPTIONAL ,
+    gap-comment VisibleString OPTIONAL ,
+    first-accn VisibleString OPTIONAL ,
+    last-accn VisibleString OPTIONAL ,
+    value VisibleString OPTIONAL
+}
 
 END
 
@@ -4290,7 +4780,7 @@ PssmWithParameters ::= SEQUENCE {
 }
 
 END
---$Revision: 1.54 $
+--$Revision: 1.68 $
 --**********************************************************************
 --
 --  NCBI ASN.1 macro editing language specifications
@@ -4335,11 +4825,25 @@ Partial-constraint ::= ENUMERATED {
     partial (1) ,
     complete (2) }
 
+Location-type-constraint ::= ENUMERATED {
+    any (0) ,
+    single-interval (1) ,
+    joined (2) ,
+    ordered (3) }
+
+Location-pos-constraint ::= CHOICE {
+    dist-from-end INTEGER ,
+    max-dist-from-end INTEGER ,
+    min-dist-from-end INTEGER }
+
 Location-constraint ::= SEQUENCE {
     strand Strand-constraint DEFAULT any ,
     seq-type Seqtype-constraint DEFAULT any ,
     partial5 Partial-constraint DEFAULT either ,
-    partial3 Partial-constraint DEFAULT either }
+    partial3 Partial-constraint DEFAULT either ,
+    location-type Location-type-constraint DEFAULT any ,
+    end5 Location-pos-constraint OPTIONAL ,
+    end3 Location-pos-constraint OPTIONAL }
 
 Object-type-constraint ::= ENUMERATED {
     any (0) ,
@@ -4512,7 +5016,9 @@ Feat-qual-legal ::= ENUMERATED {
     gene-comment (64) ,
     satellite (65) ,
     satellite-type (66) ,
-    satellite-name (67) }
+    satellite-name (67) ,
+    location (68) ,
+    tag-peptide (69) }
 
 Feat-qual-legal-val ::= SEQUENCE {
     qual Feat-qual-legal ,
@@ -4561,7 +5067,8 @@ Rna-field ::= ENUMERATED {
     gene-maploc (9) ,
     gene-locus-tag (10) ,
     gene-synonym (11) ,
-    gene-comment (12) }
+    gene-comment (12) ,
+    tag-peptide (13) }
     
 
 Rna-qual ::= SEQUENCE {
@@ -4937,9 +5444,19 @@ Pub-field-constraint ::= SEQUENCE {
   field Publication-field ,
   constraint String-constraint }
   
+Pub-field-special-constraint-type ::= CHOICE {
+  is-present NULL ,
+  is-not-present NULL ,
+  is-all-caps NULL }
+
+Pub-field-special-constraint ::= SEQUENCE {
+  field Publication-field ,
+  constraint Pub-field-special-constraint-type }
+  
 Publication-constraint ::= SEQUENCE {
   type Pub-type ,
-  field Pub-field-constraint OPTIONAL }
+  field Pub-field-constraint OPTIONAL ,
+  special-field Pub-field-special-constraint OPTIONAL }
 
 Source-constraint ::= SEQUENCE {
   field1 Source-qual-choice OPTIONAL ,
@@ -4991,10 +5508,16 @@ Sequence-constraint-mol-type-constraint ::= CHOICE {
   rna Sequence-constraint-rnamol ,
   protein NULL }
 
+Quantity-constraint ::= CHOICE {
+  equals INTEGER ,
+  greater-than INTEGER ,
+  less-than INTEGER }
+
 Sequence-constraint ::= SEQUENCE {
     seqtype Sequence-constraint-mol-type-constraint OPTIONAL ,
     id String-constraint OPTIONAL ,
-    feature Feature-type }
+    feature Feature-type ,
+    num-features Quantity-constraint OPTIONAL }
 
 Constraint-choice ::= CHOICE {
     string String-constraint ,
@@ -5008,10 +5531,15 @@ Constraint-choice ::= CHOICE {
 
 Constraint-choice-set ::= SET OF Constraint-choice
 
+Text-marker ::= CHOICE {
+    free-text VisibleString ,
+    digits NULL ,
+    letters NULL }
+
 Text-portion ::= SEQUENCE {
-    left-text VisibleString OPTIONAL ,
+    left-marker Text-marker  OPTIONAL ,
     include-left BOOLEAN ,
-    right-text VisibleString OPTIONAL ,
+    right-marker Text-marker  OPTIONAL ,
     include-right BOOLEAN ,
     inside BOOLEAN ,
     case-sensitive BOOLEAN DEFAULT FALSE ,
@@ -5070,10 +5598,18 @@ Edit-action ::= SEQUENCE {
     edit Field-edit ,
     field Field-type }
 
+Cap-change ::= ENUMERATED {
+    none (0) ,
+    tolower (1) ,
+    toupper (2) ,
+    firstcap (3) ,
+    firstcaprestnochange (4) }
+
 Convert-action ::= SEQUENCE {
     fields Field-pair-type ,
     strip-name BOOLEAN DEFAULT FALSE ,
     keep-original BOOLEAN DEFAULT FALSE ,
+    capitalization Cap-change DEFAULT none ,
     existing-text ExistingTextOption }
 
 Copy-action ::= SEQUENCE {
@@ -5109,12 +5645,6 @@ AECR-action ::= SEQUENCE {
     also-change-mrna BOOLEAN DEFAULT FALSE ,
     constraint Constraint-choice-set OPTIONAL }
 
-Cap-change ::= ENUMERATED {
-    none (0) ,
-    tolower (1) ,
-    toupper (2) ,
-    firstcap (3) }
-
 Parse-src-org-choice ::= CHOICE {
     source-qual Source-qual ,
     taxname-after-binomial NULL }
@@ -5159,7 +5689,8 @@ Location-interval ::= SEQUENCE {
 
 Location-choice ::= CHOICE {
     interval Location-interval ,
-    whole-sequence NULL }
+    whole-sequence NULL ,
+    point INTEGER }
 
 Sequence-list ::= SET OF VisibleString
 Sequence-list-choice ::= CHOICE {
@@ -5309,7 +5840,9 @@ Location-edit-type ::= CHOICE {
   clear-5-partial Partial-5-clear-constraint ,
   set-3-partial Partial-3-set-action ,
   clear-3-partial Partial-3-clear-constraint ,
-  convert Convert-location-type }
+  convert Convert-location-type ,
+  extend-5 NULL ,
+  extend-3 NULL }
 
 Edit-feature-location-action ::= SEQUENCE {
   type Feature-type ,
@@ -5348,6 +5881,12 @@ Autodef-action ::= SEQUENCE {
   modifiers SET OF Source-qual OPTIONAL ,
   clause-list-type Autodef-list-type }
 
+Fix-pub-caps-action ::= SEQUENCE {
+  title BOOLEAN OPTIONAL ,
+  authors BOOLEAN OPTIONAL ,
+  affiliation BOOLEAN OPTIONAL ,
+  constraint Constraint-choice-set OPTIONAL }
+
 Macro-action-choice ::= CHOICE {
   aecr AECR-action ,
   parse Parse-action ,
@@ -5356,7 +5895,15 @@ Macro-action-choice ::= CHOICE {
   convert-feature Convert-feature-action ,
   edit-location Edit-feature-location-action ,
   remove-descriptor Remove-descriptor-action ,
-  autodef Autodef-action }
+  autodef Autodef-action ,
+  removesets NULL ,
+  trim-junk-from-primer-seq NULL ,
+  trim-stop-from-complete-cds NULL ,
+  fix-usa-and-states NULL ,
+  synchronize-cds-partials NULL ,
+  adjust-for-consensus-splice NULL ,
+  fix-pub-caps Fix-pub-caps-action ,
+  remove-seg-gaps NULL }
 
 
 Macro-action-list ::= SET OF Macro-action-choice
diff --git a/asn/gbseq.asn b/asn/gbseq.asn
index a03a6f2..cd02232 100644
--- a/asn/gbseq.asn
+++ b/asn/gbseq.asn
@@ -1,9 +1,9 @@
---$Revision: 6.7 $
+--$Revision: 6.10 $
 --*********************************************************
 --
 -- ASN.1 and XML for the components of a GenBank format sequence
 -- J.Ostell 2002
--- Updated 15 January 2009
+-- Updated 25 May 2010
 --
 --*********************************************************
 
@@ -111,22 +111,23 @@ GBSeq ::= SEQUENCE {
     taxonomy VisibleString OPTIONAL ,
     references SEQUENCE OF GBReference OPTIONAL ,
     comment VisibleString OPTIONAL ,
-    tagset GBTagset OPTIONAL ,
+    comment-set SEQUENCE OF GBComment OPTIONAL ,
+    struc-comments SEQUENCE OF GBStrucComment OPTIONAL ,
     primary VisibleString OPTIONAL ,
     source-db VisibleString OPTIONAL ,
     database-reference VisibleString OPTIONAL ,
     feature-table SEQUENCE OF GBFeature OPTIONAL ,
-    sequence VisibleString OPTIONAL ,  -- Optional for other dump forms
-    contig VisibleString OPTIONAL
+    feature-set SEQUENCE OF GBFeatureSet OPTIONAL ,
+    sequence VisibleString OPTIONAL ,  -- Optional for contig, wgs, etc.
+    contig VisibleString OPTIONAL ,
+    alt-seq SEQUENCE OF GBAltSeqData OPTIONAL
 }
 
-GBSecondary-accn ::= VisibleString
-
 GBSeqid ::= VisibleString
 
-GBKeyword ::= VisibleString
+GBSecondary-accn ::= VisibleString
 
-GBAuthor ::= VisibleString
+GBKeyword ::= VisibleString
 
 GBReference ::= SEQUENCE {
     reference VisibleString ,
@@ -135,29 +136,46 @@ GBReference ::= SEQUENCE {
     consortium VisibleString OPTIONAL ,
     title VisibleString OPTIONAL ,
     journal VisibleString ,
-    xref SET OF GBXref OPTIONAL ,
+    xref SEQUENCE OF GBXref OPTIONAL ,
     pubmed INTEGER OPTIONAL ,
     remark VisibleString OPTIONAL
 }
 
+GBAuthor ::= VisibleString
+
 GBXref ::= SEQUENCE {
     dbname VisibleString ,
     id VisibleString
 }
 
-GBTagset ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    url VisibleString OPTIONAL ,
-    tags GBTags OPTIONAL
+GBComment ::= SEQUENCE {
+    type VisibleString OPTIONAL ,
+    paragraphs SEQUENCE OF GBCommentParagraph
 }
 
-GBTags ::= SEQUENCE OF GBTag
+GBCommentParagraph ::= SEQUENCE {
+    items SEQUENCE OF GBCommentItem
+}
 
-GBTag ::= SEQUENCE {
+GBCommentItem ::= SEQUENCE {
+    value VisibleString OPTIONAL ,
+    url VisibleString OPTIONAL
+}
+
+GBStrucComment ::= SEQUENCE {
     name VisibleString OPTIONAL ,
+    items SEQUENCE OF GBStrucCommentItem
+}
+
+GBStrucCommentItem ::= SEQUENCE {
+    tag VisibleString OPTIONAL ,
     value VisibleString OPTIONAL ,
-    unit VisibleString OPTIONAL
+    url VisibleString OPTIONAL
+}
+
+GBFeatureSet ::= SEQUENCE {
+    annot-source VisibleString OPTIONAL ,
+    features SEQUENCE OF GBFeature
 }
 
 GBFeature ::= SEQUENCE {
@@ -167,7 +185,8 @@ GBFeature ::= SEQUENCE {
     operator VisibleString OPTIONAL ,
     partial5 BOOLEAN OPTIONAL ,
     partial3 BOOLEAN OPTIONAL ,
-    quals SEQUENCE OF GBQualifier OPTIONAL
+    quals SEQUENCE OF GBQualifier OPTIONAL ,
+    xrefs SEQUENCE OF GBXref OPTIONAL
 }
 
 GBInterval ::= SEQUENCE {
@@ -184,18 +203,22 @@ GBQualifier ::= SEQUENCE {
     value VisibleString OPTIONAL
 }
 
-GBTagsetRules ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    mandatorytags GBTagNames OPTIONAL ,
-    optionaltags GBTagNames OPTIONAL ,
-    uniquetags GBTagNames OPTIONAL ,
-    extensible BOOLEAN OPTIONAL
+GBAltSeqData ::= SEQUENCE {
+    name VisibleString ,  -- e.g., contig, wgs, scaffold, cage, genome
+    items SEQUENCE OF GBAltSeqItem OPTIONAL
 }
 
-GBTagNames ::= SEQUENCE OF VisibleString
-
-GBTagsetRuleSet ::= SEQUENCE OF GBTagsetRules
+GBAltSeqItem ::= SEQUENCE {
+    interval GBInterval OPTIONAL ,
+    isgap BOOLEAN OPTIONAL ,
+    gap-length INTEGER OPTIONAL ,
+    gap-type VisibleString OPTIONAL ,
+    gap-linkage VisibleString OPTIONAL ,
+    gap-comment VisibleString OPTIONAL ,
+    first-accn VisibleString OPTIONAL ,
+    last-accn VisibleString OPTIONAL ,
+    value VisibleString OPTIONAL
+}
 
 END
 
diff --git a/asn/insdseq.asn b/asn/insdseq.asn
index 0ff2274..8e7346a 100644
--- a/asn/insdseq.asn
+++ b/asn/insdseq.asn
@@ -1,9 +1,9 @@
---$Revision: 1.7 $
+--$Revision: 1.8 $
 --************************************************************************
 --
 -- ASN.1 and XML for the components of a GenBank/EMBL/DDBJ sequence record
 -- The International Nucleotide Sequence Database (INSD) collaboration
--- Version 1.5, 15 January 2009
+-- Version 1.6, 25 May 2010
 --
 --************************************************************************
 
@@ -115,13 +115,16 @@ INSDSeq ::= SEQUENCE {
     taxonomy VisibleString OPTIONAL ,
     references SEQUENCE OF INSDReference OPTIONAL ,
     comment VisibleString OPTIONAL ,
-    tagset INSDTagset OPTIONAL ,
+    comment-set SEQUENCE OF INSDComment OPTIONAL ,
+    struc-comments SEQUENCE OF INSDStrucComment OPTIONAL ,
     primary VisibleString OPTIONAL ,
     source-db VisibleString OPTIONAL ,
     database-reference VisibleString OPTIONAL ,
     feature-table SEQUENCE OF INSDFeature OPTIONAL ,
-    sequence VisibleString OPTIONAL ,  -- Optional for other dump forms
-    contig VisibleString OPTIONAL
+    feature-set SEQUENCE OF INSDFeatureSet OPTIONAL ,
+    sequence VisibleString OPTIONAL ,  -- Optional for contig, wgs, etc.
+    contig VisibleString OPTIONAL ,
+    alt-seq SEQUENCE OF INSDAltSeqData OPTIONAL
 }
 
 INSDSeqid ::= VisibleString
@@ -151,8 +154,6 @@ INSDKeyword ::= VisibleString
 --   References that lack an INSDReference_position element apply
 --   to the entire sequence.
 
-INSDAuthor ::= VisibleString
-
 INSDReference ::= SEQUENCE {
     reference VisibleString ,
     position VisibleString OPTIONAL ,
@@ -160,11 +161,13 @@ INSDReference ::= SEQUENCE {
     consortium VisibleString OPTIONAL ,
     title VisibleString OPTIONAL ,
     journal VisibleString ,
-    xref SET OF INSDXref OPTIONAL ,
+    xref SEQUENCE OF INSDXref OPTIONAL ,
     pubmed INTEGER OPTIONAL ,
     remark VisibleString OPTIONAL
 }
 
+INSDAuthor ::= VisibleString
+
 -- INSDXref provides a method for referring to records in
 -- other databases. INSDXref_dbname is a string value that
 -- provides the name of the database, and INSDXref_dbname
@@ -176,22 +179,29 @@ INSDXref ::= SEQUENCE {
     id VisibleString
 }
 
--- INSDTagset is used for community-specific data elements
--- in a tag/value format.
+INSDComment ::= SEQUENCE {
+    type VisibleString OPTIONAL ,
+    paragraphs SEQUENCE OF INSDCommentParagraph
+}
 
-INSDTagset ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    url VisibleString OPTIONAL ,
-    tags INSDTags OPTIONAL
+INSDCommentParagraph ::= SEQUENCE {
+    items SEQUENCE OF INSDCommentItem
 }
 
-INSDTags ::= SEQUENCE OF INSDTag
+INSDCommentItem ::= SEQUENCE {
+    value VisibleString OPTIONAL ,
+    url VisibleString OPTIONAL
+}
 
-INSDTag ::= SEQUENCE {
+INSDStrucComment ::= SEQUENCE {
     name VisibleString OPTIONAL ,
+    items SEQUENCE OF INSDStrucCommentItem
+}
+
+INSDStrucCommentItem ::= SEQUENCE {
+    tag VisibleString OPTIONAL ,
     value VisibleString OPTIONAL ,
-    unit VisibleString OPTIONAL
+    url VisibleString OPTIONAL
 }
 
 -- INSDFeature_operator contains a string value describing
@@ -209,6 +219,11 @@ INSDTag ::= SEQUENCE {
 --   Either 'join' or 'order' is required if INSDFeature_intervals
 --   is comprised of more than one INSDInterval .
 
+INSDFeatureSet ::= SEQUENCE {
+    annot-source VisibleString OPTIONAL ,
+    features SEQUENCE OF INSDFeature
+}
+
 INSDFeature ::= SEQUENCE {
     key VisibleString ,
     location VisibleString ,
@@ -216,7 +231,8 @@ INSDFeature ::= SEQUENCE {
     operator VisibleString OPTIONAL ,
     partial5 BOOLEAN OPTIONAL ,
     partial3 BOOLEAN OPTIONAL ,
-    quals SEQUENCE OF INSDQualifier OPTIONAL
+    quals SEQUENCE OF INSDQualifier OPTIONAL ,
+    xrefs SEQUENCE OF INSDXref OPTIONAL
 }
 
 -- INSDInterval_iscomp is a boolean indicating whether
@@ -247,25 +263,23 @@ INSDQualifier ::= SEQUENCE {
     value VisibleString OPTIONAL
 }
 
--- INSDTagsetRules defines mandatory, optional, and unique tags
--- for a given community's INSDTagset. If the tagset is extensible,
--- then additional tags which are not included in the list of
--- mandatory or optional tags may be present. The uniquetags
--- element provides a list of the tags that may occur only once
--- in a given tagset.
-
-INSDTagsetRules ::= SEQUENCE {
-    authority VisibleString OPTIONAL ,
-    version VisibleString OPTIONAL ,
-    mandatorytags INSDTagNames OPTIONAL ,
-    optionaltags INSDTagNames OPTIONAL ,
-    uniquetags INSDTagNames OPTIONAL ,
-    extensible BOOLEAN OPTIONAL
+INSDAltSeqData ::= SEQUENCE {
+    name VisibleString ,  -- e.g., CON-division-join, WGS-contig-range,
+                          -- WGS-scaffold-range, MGA/CAGE-range, genome
+    items SEQUENCE OF INSDAltSeqItem OPTIONAL
 }
 
-INSDTagNames ::= SEQUENCE OF VisibleString
-
-INSDTagsetRuleSet ::= SEQUENCE OF INSDTagsetRules
+INSDAltSeqItem ::= SEQUENCE {
+    interval INSDInterval OPTIONAL ,
+    isgap BOOLEAN OPTIONAL ,
+    gap-length INTEGER OPTIONAL ,
+    gap-type VisibleString OPTIONAL ,
+    gap-linkage VisibleString OPTIONAL ,
+    gap-comment VisibleString OPTIONAL ,
+    first-accn VisibleString OPTIONAL ,
+    last-accn VisibleString OPTIONAL ,
+    value VisibleString OPTIONAL
+}
 
 END
 
diff --git a/asn/seq.asn b/asn/seq.asn
index 0f38fca..cef1de0 100644
--- a/asn/seq.asn
+++ b/asn/seq.asn
@@ -1,4 +1,4 @@
---$Revision: 6.20 $
+--$Revision: 6.21 $
 --**********************************************************************
 --
 --  NCBI Sequence elements
@@ -12,7 +12,7 @@ BEGIN
 
 EXPORTS Annotdesc, Annot-descr, Bioseq, GIBB-mol, Heterogen, MolInfo,
         Numbering, Pubdesc, Seq-annot, Seq-data, Seqdesc, Seq-descr, Seq-ext,
-        Seq-hist, Seq-inst, Seq-literal, Seqdesc, Delta-ext;
+        Seq-hist, Seq-inst, Seq-literal, Seqdesc, Delta-ext, Seq-gap;
 
 IMPORTS Date, Int-fuzz, Dbtag, Object-id, User-object FROM NCBI-General
         Seq-align FROM NCBI-Seqalign
diff --git a/asn/seqfeat.asn b/asn/seqfeat.asn
index eb5cd77..d545c3e 100644
--- a/asn/seqfeat.asn
+++ b/asn/seqfeat.asn
@@ -1,4 +1,4 @@
---$Revision: 6.27 $
+--$Revision: 6.35 $
 --**********************************************************************
 --
 --  NCBI Sequence Feature elements
@@ -15,6 +15,7 @@ EXPORTS Seq-feat, Feat-id, Genetic-code;
 IMPORTS Gene-ref FROM NCBI-Gene
         Prot-ref FROM NCBI-Protein
         Org-ref FROM NCBI-Organism
+        Variation-ref FROM NCBI-Variation
         BioSource FROM NCBI-BioSource
         RNA-ref FROM NCBI-RNA
         Seq-loc, Giimport-id FROM NCBI-Seqloc
@@ -114,7 +115,8 @@ SeqFeatData ::= CHOICE {
     non-std-residue VisibleString ,  -- non-standard residue here in seq
     het Heterogen ,         -- cofactor, prosthetic grp, etc, bound to seq
     biosrc BioSource,
-    clone Clone-ref
+    clone Clone-ref,
+    variation Variation-ref
 }
 
 SeqFeatXref ::= SEQUENCE {       -- both optional because can have one or both
@@ -233,9 +235,460 @@ Clone-seq ::= SEQUENCE {
     align-id Dbtag OPTIONAL
 }
 
+END
+
+
+--*** Variation-ref ***********************************************
+--*
+--*  Specification of variation features
+--*
+
+NCBI-Variation DEFINITIONS ::=
+BEGIN
+
+EXPORTS Variation-ref, Variation-inst;
+
+IMPORTS Int-fuzz, User-object, Object-id, Dbtag FROM NCBI-General
+        Seq-literal FROM NCBI-Sequence
+        Seq-loc FROM NCBI-Seqloc
+        Pub FROM NCBI-Pub;
+
+-- --------------------------------------------------------------------------
+-- Historically, the dbSNP definitions document data structures used in the
+-- processing and annotation of variations by the dbSNP group.  The intention
+-- is to provide information to clients that reflect internal information
+-- produced during the mapping of SNPs
+-- --------------------------------------------------------------------------
+
+VariantProperties ::= SEQUENCE {
+    version INTEGER,
+
+    -- NOTE:
+    -- The format for each of these values is as an integer
+    -- Unless otherwise noted, these integers represent a bitwise OR of the
+    -- possible values, and as such, these values represent the specific bit
+    -- flags that may be set for each of the possible attributes here.
+
+    resource-link INTEGER {
+        preserved        (1), -- Clinical, Pubmed, Cited, (0x01)
+        provisional      (2), -- Provisional Third Party Annotations (0x02)
+        has3D            (4), -- Has 3D strcture SNP3D table (0x04)
+        submitterLinkout (8), -- SNP->SubSNP->Batch link_out (0x08)
+        clinical        (16), -- Clinical if LSDB, OMIM, TPA, Diagnostic (0x10)
+        genotypeKit     (32)  -- Marker exists on high density genotyping kit
+                              -- (0x20)
+    } OPTIONAL,
+
+    gene-location INTEGER {
+        in-gene         (1), -- Sequence intervals covered by a gene ID but not
+                             -- having an aligned transcript (0x01)
+        near-gene-5     (2), -- Within 2kb of the 5' end of a gene feature
+        near-gene-3     (4), -- Within 0.5kb of the 3' end of a gene feature
+        intron          (8), -- In Intron (0x08)
+        donor          (16), -- In donor splice-site (0x10)
+        acceptor       (32), -- In acceptor splice-site (0x20)
+        utr-5          (64), -- In 5' UTR (0x40)
+        utr-3         (128), -- In 3' UTR (0x80)
+        in-start-codon(256), -- the variant is observed in a start codon
+                             -- (0x100)
+        in-stop-codon (512), -- the variant is observed in a stop codon
+                             -- (0x200)
+        intergenic   (1024), -- variant located between genes (0x400)
+        conserved-noncoding(2048) -- variant is located in a conserved
+                                  -- non-coding region (0x800)
+    } OPTIONAL,
+
+    effect INTEGER {
+        no-change      (0), -- known to cause no functional changes
+                            -- since 0 does not combine with any other bit
+                            -- value, 'no-change' specifically implies that
+                            -- there are no consequences
+        synonymous     (1), -- one allele in the set does not change the encoded
+                            -- amino acid (0x1)
+        nonsense       (2), -- one allele in the set changes to STOP codon
+                            -- (TER).  (0x2)
+        missense       (4), -- one allele in the set changes protein peptide
+                            -- (0x4)
+        frameshift     (8), -- one allele in the set changes all downstream
+                            -- amino acids (0x8)
+
+        up-regulator  (16), -- the variant causes increased transcription
+                            -- (0x10)
+        down-regulator(32), -- the variant causes decreased transcription
+                            -- (0x20)
+        methylation(64)
+    } OPTIONAL,
+
+    mapping INTEGER {
+        has-other-snp         (1), -- Another SNP has the same mapped positions
+                                   -- on reference assembly (0x01)
+        has-assembly-conflict (2), -- Weight 1 or 2 SNPs that map to different
+                                   -- chromosomes on different assemblies (0x02)
+        is-assembly-specific  (4)  -- Only maps to 1 assembly (0x04)
+    } OPTIONAL,
+
+    -- This is *NOT* a bitfield
+    map-weight INTEGER {
+        is-uniquely-placed(1),
+        placed-twice-on-same-chrom(2),
+        placed-twice-on-diff-chrom(3),
+        many-placements(10)
+    } OPTIONAL,
+
+    frequency-based-validation INTEGER {
+        is-mutation       (1), -- low frequency variation that is cited in
+                               -- journal or other reputable sources (0x01)
+        above-5pct-all    (2), -- >5% minor allele freq in each and all
+                               -- populations (0x02)
+        above-5pct-1plus  (4), -- >5% minor allele freq in 1+ populations (0x04)
+        validated         (8), -- Bit is set if the variant has 2+ minor allele
+                               -- count based on freq or genotype data
+        above-1pct-all   (16), -- >1% minor allele freq in each and all
+                               -- populations (0x10)
+        above-1pct-1plus (32)  -- >1% minor allele freq in 1+ populations (0x20)
+    } OPTIONAL,
+
+    genotype INTEGER {
+        in-haplotype-set (1), -- Exists in a haplotype tagging set (0x01)
+        has-genotypes    (2)  -- SNP has individual genotype (0x02)
+    } OPTIONAL,
+
+    project-data SET OF SEQUENCE {
+        -- project IDs are IDs from BioProjects
+        -- in order to report information about project relationships, we
+        -- require projects to be registered
+        -- This field in many ways duplicates dbxrefs; however, the
+        -- intention of this field is to more adequately reflects
+        -- ownership and data source
+        project-ids SET OF INTEGER
+    } OPTIONAL,
+
+    quality-check INTEGER {
+        contig-allele-missing   (1), -- Reference sequence allele at the mapped
+                                     -- position is not present in the SNP
+                                     -- allele list, adjusted for orientation
+                                     -- (0x01)
+        withdrawn-by-submitter  (2), -- One member SS is withdrawn by submitter
+                                     -- (0x02)
+        non-overlapping-alleles (4), -- RS set has 2+ alleles from different
+                                     -- submissions and these sets share no
+                                     -- alleles in common (0x04)
+        strain-specific         (8), -- Straing specific fixed difference (0x08)
+        genotype-conflict      (16)  -- Has Genotype Conflict (0x10)
+    } OPTIONAL,
+
+    confidence INTEGER {
+        unknown         (0),
+        likely-artifact (1),
+        other           (255)
+    } OPTIONAL
+}
+
+Phenotype ::= SEQUENCE {
+    source VisibleString OPTIONAL,
+    term VisibleString OPTIONAL,
+    xref SET OF Dbtag OPTIONAL,
+
+    -- does this variant have known clinical significance?
+    clinical-significance INTEGER {
+        unknown                 (0),
+        untested                (1),
+        non-pathogenic          (2),
+        probable-non-pathogenic (3),
+        probable-pathogenic     (4),
+        pathogenic              (5),
+        other                   (255)
+    } OPTIONAL
+}
+
+Population-data ::= SEQUENCE {
+    -- assayed population (e.g. HAPMAP-CEU)
+    population VisibleString,
+    genotype-frequency REAL OPTIONAL,
+    chromosomes-tested INTEGER OPTIONAL,
+    sample-ids SET OF Object-id OPTIONAL
+}
+
+Ext-loc ::= SEQUENCE {
+    id Object-id,
+    location Seq-loc
+}
+
+Variation-ref ::= SEQUENCE {
+    -- ids (i.e., SNP rsid / ssid, dbVar nsv/nssv)
+    -- expected values include 'dbSNP|rs12334', 'dbSNP|ss12345', 'dbVar|nsv1'
+    --
+    -- we relate three kinds of IDs here:
+    --  - our current object's id
+    --  - the id of this object's parent, if it exists
+    --  - the sample ID that this item originates from
+    id        Dbtag OPTIONAL,
+    parent-id Dbtag OPTIONAL,
+    sample-id Object-id OPTIONAL,
+    other-ids SET OF Dbtag OPTIONAL,
+
+    -- names and synonyms
+    -- some variants have well-known canonical names and possible accepted
+    -- synonyms
+    name VisibleString OPTIONAL,
+    synonyms SET OF VisibleString OPTIONAL,
+
+    -- tag for comment and descriptions
+    description VisibleString OPTIONAL,
+
+    -- phenotype
+    phenotype SET OF Phenotype OPTIONAL,
+
+    -- sequencing / acuisition method
+    method SET OF INTEGER {
+        unknown             (0),
+        bac-acgh            (1),
+        computational       (2),
+        curated             (3),
+        digital-array       (4),
+        expression-array    (5),
+        fish                (6),
+        flanking-sequence   (7),
+        maph                (8),
+        mcd-analysis        (9),
+        mlpa                (10),
+        oea-assembly        (11),
+        oligo-acgh          (12),
+        paired-end          (13),
+        pcr                 (14),
+        qpcr                (15),
+        read-depth          (16),
+        roma                (17),
+        rt-pcr              (18),
+        sage                (19),
+        sequence-alignment  (20),
+        sequencing          (21),
+        snp-array           (22),
+        snp-genoytyping     (23),
+        southern            (24),
+        western             (25),
+        optical-mapping     (26),
+
+        other               (255)
+    } OPTIONAL,
+
+    -- Note about SNP representation and pretinent fields: allele-frequency,
+    -- population, quality-codes:
+    -- The case of multiple alleles for a SNP would be described by
+    -- parent-feature of type Variation-set.diff-alleles, where the child
+    -- features of type Variation-inst, all at the same location, would
+    -- describe individual alleles.
+
+    -- population data
+    population-data SET OF Population-data OPTIONAL,
+
+    -- variant properties bit fields
+    variant-prop VariantProperties OPTIONAL,
+
+    -- has this variant been validated?
+    validated BOOLEAN OPTIONAL,
+
+    -- link-outs to GeneTests database
+    clinical-test SET OF Dbtag OPTIONAL,
+
+    -- origin of this allele, if known
+    allele-origin INTEGER {
+        unknown         (0),
+        germline        (1),
+        somatic         (2),
+        inherited       (3),
+        paternal        (4),
+        maternal        (5),
+        de-novo         (6),
+        biparental      (7),
+        uniparental     (8),
+        not-tested      (9),
+        tested-inconclusive (10),
+
+        other           (255)
+    } OPTIONAL,
+
+    -- observed allele state, if known
+    allele-state INTEGER {
+        unknown         (0),
+        homozygous      (1),
+        heterozygous    (2),
+        hemizygous      (3),
+        nullizygous     (4),
+        other           (255)
+    } OPTIONAL,
+
+    allele-frequency REAL OPTIONAL,
+
+    -- is this variant the ancestral allele?
+    is-ancestral-allele BOOLEAN OPTIONAL,
+
+    -- publication support.
+    -- Note: made this pub instead of pub-equiv, since
+    -- Pub can be pub-equiv and pub-equiv is a set of pubs, but it looks like
+    -- Pub is more often used as top-level container
+    pub Pub OPTIONAL,
+
+    data CHOICE {
+        unknown NULL,
+        note    VisibleString, --free-form
+        uniparental-disomy NULL,
+
+        -- actual sequence-edit at feat.location
+        instance        Variation-inst,
+
+        -- Set of related Variations.
+        -- Location of the set equals to the union of member locations
+        set SEQUENCE {
+            type INTEGER {
+                unknown     (0),
+                compound    (1), -- complex change at the same location on the
+                                 -- same molecule
+                products    (2), -- different products arising from the same
+                                 -- variation in a precursor, e.g. r.[13g>a,
+                                 -- 13_88del]
+                haplotype   (3), -- changes on the same allele, e.g
+                                 -- r.[13g>a;15u>c]
+                genotype    (4), -- changes on different alleles in the same
+                                 -- genotype, e.g. g.[476C>T]+[476C>T]
+                mosaic      (5), -- different genotypes in the same individual
+                individual  (6), -- same organism; allele relationship unknown,
+                                 -- e.g. g.[476C>T(+)183G>C]
+                population  (7), -- population
+                alleles     (8), -- set represents a set of observed alleles
+                other       (255)
+            },
+            variations SET OF Variation-ref,
+            name  VisibleString OPTIONAL
+        }
+    },
+
+    consequence SET OF CHOICE {
+        unknown     NULL,
+        splicing    NULL, --some effect on splicing
+        note        VisibleString,  --freeform
+
+        -- Describe resulting variation in the product, e.g. missense,
+        -- nonsense, silent, neutral, etc in a protein, that arises from
+        -- THIS variation.
+        variation   Variation-ref,
+
+        -- see http://www.hgvs.org/mutnomen/recs-prot.html
+        frameshift SEQUENCE {
+            phase INTEGER OPTIONAL,
+            x-length INTEGER OPTIONAL
+        },
+
+        loss-of-heterozygosity SEQUENCE {
+            -- In germline comparison, it will be reference genome assembly
+            -- (default) or reference/normal population. In somatic mutation,
+            -- it will be a name of the normal tissue.
+            reference VisibleString OPTIONAL,
+
+            -- Name of the testing subject type or the testing tissue.
+            test VisibleString OPTIONAL
+        }
+    } OPTIONAL,
+
+    -- Observed location, if different from the parent set or feature.location.
+    location        Seq-loc OPTIONAL,
+
+    -- reference other locs, e.g. mapped source
+    ext-locs SET OF Ext-loc OPTIONAL,
+
+    ext             User-object OPTIONAL
+
+}
+
+Delta-item ::= SEQUENCE {
+    seq CHOICE {
+        literal Seq-literal,
+        loc Seq-loc,
+        this NULL --same location as variation-ref itself
+    } OPTIONAL,
+
+    -- Multiplier allows representing a tandem, e.g.  ATATAT as AT*3
+    -- This allows describing CNV/SSR where delta=self  with a
+    -- multiplier which specifies the count of the repeat unit.
+
+    multiplier          INTEGER OPTIONAL, --assumed 1 if not specified.
+    multiplier-fuzz     Int-fuzz OPTIONAL,
+
+    action INTEGER {
+
+        -- replace len(seq) positions starting with location.start with seq
+        morph      (0),
+
+        -- go downstream by distance specified by multiplier (upstream if < 0),
+        -- in genomic context.
+        offset     (1),
+
+        -- excise sequence at location
+        -- if multiplier is specified, delete len(location)*multiplier
+        -- positions downstream
+        del-at     (2),
+
+        -- insert seq before the location.start
+        ins-before (3)
+
+    } DEFAULT morph
+}
+
+
+-- Variation instance
+Variation-inst ::= SEQUENCE {
+    type INTEGER {
+        unknown         (0),    -- delta=[]
+        identity        (1),    -- delta=[]
+        inv             (2),    -- delta=[del, ins.seq=
+                                -- RevComp(variation-location)]
+        snv             (3),    -- delta=[morph of length 1]
+                                -- NOTE: this is snV not snP; the latter
+                                -- requires frequency-based validation to be
+                                -- established in VariantProperties
+                                -- the strict definition of SNP is an SNV with
+                                -- an established population frequency of at
+                                -- least 1% in at least 1 popuplation
+        mnp             (4),    -- delta=[morph of length >1]
+        delins          (5),    -- delta=[del, ins]
+        del             (6),    -- delta=[del]
+        ins             (7),    -- delta=[ins]
+        microsatellite  (8),    -- delta=[del, ins.seq= repeat-unit with fuzzy
+                                -- multiplier]
+                                -- variation-location is the microsat expansion
+                                -- on the sequence
+        transposon      (9),    -- delta=[del, ins.seq= known donor or 'this']
+                                -- variation-location is equiv of transposon
+                                -- locs.
+        cnv             (10),   -- delta=[del, ins= 'this' with fuzzy
+                                -- multiplier]
+        direct-copy     (11),   -- delta=[ins.seq= upstream location on the
+                                -- same strand]
+        rev-direct-copy (12),   -- delta=[ins.seq= downstream location on the
+                                -- same strand]
+        inverted-copy   (13),   -- delta=[ins.seq= upstream location on the
+                                -- opposite strand]
+        everted-copy    (14),   -- delta=[ins.seq= downstream location on the
+                                -- opposite strand]
+        translocation   (15),   -- delta=like delins
+        prot-missense   (16),   -- delta=[morph of length 1]
+        prot-nonsense   (17),   -- delta=[del]; variation-location is the tail
+                                -- of the protein being truncated
+        prot-neutral    (18),   -- delta=[morph of length 1]
+        prot-silent     (19),   -- delta=[morph of length 1, same AA as at
+                                -- variation-location]
+        prot-other      (20),   -- delta=any
+
+        other           (255)   -- delta=any
+    },
+
+    -- Sequence that replaces the location, in biological order.
+    delta SEQUENCE OF Delta-item
+}
 
 END 
 
+
 --**********************************************************************
 --
 --  NCBI Restriction Sites
@@ -411,7 +864,8 @@ OrgName ::= SEQUENCE {
     lineage VisibleString OPTIONAL ,       -- lineage with semicolon separators
     gcode INTEGER OPTIONAL ,               -- genetic code (see CdRegion)
     mgcode INTEGER OPTIONAL ,              -- mitochondrial genetic code
-    div VisibleString OPTIONAL }           -- GenBank division code
+    div VisibleString OPTIONAL ,           -- GenBank division code
+    pgcode INTEGER OPTIONAL }              -- plastid genetic code
     
 
 OrgMod ::= SEQUENCE {
@@ -638,8 +1092,6 @@ Prot-ref ::= SEQUENCE {
        signal-peptide (3) ,
        transit-peptide (4) } DEFAULT not-set }
 
-
-
 END 
 --********************************************************************
 --
@@ -719,6 +1171,5 @@ Tx-evidence ::= SEQUENCE {
     --          product (blocked  by  RNA  5'end)  by  comparison with
     --          homologous sequence ladder (J. Mol. Biol. 199, 587)
 
-    
 END
 
diff --git a/asn/seqloc.asn b/asn/seqloc.asn
index 87c2300..9054f65 100644
--- a/asn/seqloc.asn
+++ b/asn/seqloc.asn
@@ -1,4 +1,4 @@
---$Revision: 6.4 $
+--$Revision: 6.5 $
 --**********************************************************************
 --
 --  NCBI Sequence location and identifier elements
@@ -44,6 +44,8 @@ Seq-id ::= CHOICE {
     named-annot-track Textseq-id -- Internal named annotation tracking ID
 }
 
+Seq-id-set ::= SET OF Seq-id
+
 
 Patent-seq-id ::= SEQUENCE {
     seqid INTEGER ,         -- number of sequence in patent
diff --git a/asn/valid.asn b/asn/valid.asn
index 414c875..bbc136a 100644
--- a/asn/valid.asn
+++ b/asn/valid.asn
@@ -1,4 +1,4 @@
---$Revision: 1.1 $
+--$Revision: 1.3 $
 --**********************************************************************
 --
 --  NCBI ASN.1 structured comment validation rule specifications
@@ -10,20 +10,42 @@
 NCBI-Structured-comment-validation DEFINITIONS ::=
 BEGIN
 
-EXPORTS Field-rule, Field-set, Comment-rule, Comment-set;
+EXPORTS Severity-level, Field-rule, Field-set, Dependent-field-rule , Dependent-field-set ,Comment-rule, Comment-set;
+
+Severity-level ::= ENUMERATED {
+    none (0) ,
+    info (1) ,
+    warning (2) ,
+    error (3) ,
+    reject (4) ,
+    fatal (5)
+}
 
 Field-rule ::= SEQUENCE {
     field-name VisibleString ,
     match-expression VisibleString OPTIONAL ,
-    required BOOLEAN DEFAULT FALSE
+    required BOOLEAN DEFAULT FALSE ,
+    severity Severity-level DEFAULT warning
 }
 
 Field-set ::= SET OF Field-rule
 
+Dependent-field-rule ::= SEQUENCE {
+    match-name VisibleString ,
+    value-constraint VisibleString OPTIONAL ,
+    other-fields Field-set OPTIONAL ,
+    disallowed-fields Field-set OPTIONAL
+}
+
+Dependent-field-set ::= SET OF Dependent-field-rule    
+
 Comment-rule ::= SEQUENCE {
     prefix VisibleString ,
     updated BOOLEAN DEFAULT FALSE ,
-    fields Field-set
+    fields Field-set ,
+    require-order BOOLEAN DEFAULT TRUE ,
+    allow-unlisted BOOLEAN DEFAULT FALSE ,
+    dependent-rules Dependent-field-set OPTIONAL
 }
 
 Comment-set ::= SET OF Comment-rule
diff --git a/asnlib/asn.h b/asnlib/asn.h
index 1f3179a..7064f97 100644
--- a/asnlib/asn.h
+++ b/asnlib/asn.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 1/1/91
 *
-* $Revision: 6.11 $
+* $Revision: 6.15 $
 *
 * File Description:
 *   This header the interface to all the routines in the ASN.1 libraries
@@ -42,83 +42,6 @@
 * --------------------------------------------------------------------------
 * Date     Name        Description of modification
 * -------  ----------  -----------------------------------------------------
-* 04-20-93 Schuler     LIBCALL calling convention
-* 05-13-93 Schuler     Changed definitions of AsnReadFunc and AsnWriteFunc to
-*                      use the LIBCALL calling convention.
-* 02-24-94 Schuler     AsnTypeStringToHex moved here (from asntypes.h)
-*
-* $Log: asn.h,v $
-* Revision 6.11  2003/12/03 19:31:09  gouriano
-* Corrected DTD generation (a different approach)
-*
-* Revision 6.10  2003/09/15 16:16:32  kans
-* added AsnWriteEx, AsnTxtWriteEx, and AsnPrintStream
-*
-* Revision 6.9  2002/05/20 23:13:39  ivanov
-* Fixed overburn memory AsnIo buf in the AsnPrint*() -- increased
-* buffers reserved room
-*
-* Revision 6.8  2001/10/11 14:39:08  ostell
-* added support for XMLModulePrefix
-*
-* Revision 6.7  2000/12/12 15:56:08  ostell
-* added support BigInt
-*
-* Revision 6.6  2000/07/25 20:30:59  ostell
-* added support for printing multiple ASN.1 modules as multiple XML DTD and .mod files
-*
-* Revision 6.5  2000/05/12 20:44:01  ostell
-* make changes to collect comments from spec and print in DTD
-*
-* Revision 6.4  2000/05/10 03:12:36  ostell
-* added support for XML DTD and XML data output
-*
-* Revision 6.3  1998/02/27 17:22:18  vakatov
-* [WIN32 DLL]  Declared some functions as NLM_EXTERN(DLL-exportable)
-*
-* Revision 6.2  1998/01/09 15:54:08  shavirin
-* Added definition of hash calculating function
-*
-* Revision 6.1  1997/10/28 15:13:23  epstein
-* add AsnFindNthPieceOfObject
-*
-* Revision 6.0  1997/08/25 18:09:34  madden
-* Revision changed to 6.0
-*
-* Revision 5.3  1997/04/24 12:47:49  ostell
-* in AsnTypeStringToHex, allowed argument "left" to be NULL
-*
- * Revision 5.2  1997/04/23  21:23:03  ostell
- * changed BitHex reading routine to strip internal spaces and allow for linewraps at
- * any spacing.
- *
- * Revision 5.1  1996/12/03  21:43:48  vakatov
- * Adopted for 32-bit MS-Windows DLLs
- *
- * Revision 5.0  1996/05/28  14:00:29  ostell
- * Set to revision 5.0
- *
- * Revision 4.2  1996/02/18  16:45:36  ostell
- * changed fix_non_print behavior and added option 3
- *
- * Revision 4.1  1995/12/21  14:00:51  ostell
- * added AsnIoFree()
- *
- * Revision 4.0  1995/07/26  13:47:38  ostell
- * force revision to 4.0
- *
- * Revision 2.27  1995/06/29  15:58:51  epstein
- * add OP_NCBIOBJSTR for complex handling when reading biostrucs
- *
- * Revision 2.26  95/05/24  19:08:49  ostell
- * added spec_version to AsnIoPtr. This is used to set a non-zero asn.1
- * spec version number on a particular stream. The object loaders check this
- * number and remove new asn1 elements on either read or write. This allows
- * filtering of data that conforms to a not yet public spec.
- *
- * Revision 2.25  1995/05/15  18:38:28  ostell
- * added Log line
- *
 *
 * ==========================================================================
 */
@@ -229,7 +152,7 @@ typedef struct asnmodule {
 #define ASNIO_CARRIER   32         /* is a pure iterator */
 #define ASNIO_XML       64
 
-#define ASNIO_TEXT_IN	21         /* AsnIo.type */
+#define ASNIO_TEXT_IN	21         /* AsnIo.type for files */
 #define ASNIO_TEXT_OUT	25
 #define ASNIO_BIN_IN	22
 #define ASNIO_BIN_OUT	26
@@ -310,6 +233,9 @@ typedef struct asnio {
 	Int2 spec_version;      /* used for filtering between asn.1 spec versions */
 	Boolean no_newline;     /* to suppress internal newlines in long XML strings */
 	Boolean XMLModuleWritten; /* to put header on first XML DTD only */
+    /* the following fields are used for easier ASN.1 comparisons, not normal operations */
+	Boolean asn_no_newline;  /* to suppress internal newlines in long ASN.1 strings */
+	Boolean asn_alt_struct;  /* structure ending braces on separate lines */
 } AsnIo, PNTR AsnIoPtr;
 
 
@@ -506,6 +432,26 @@ NLM_EXTERN Pointer LIBCALL AsnGenericChoiceSeqOfAsnRead PROTO ((AsnIoPtr aip, As
 NLM_EXTERN Boolean LIBCALL AsnGenericChoiceSeqOfAsnWrite PROTO ((Pointer ptr, AsnWriteFunc writefunc, AsnIoPtr aip, AsnTypePtr bag_atp, AsnTypePtr element_atp));
 NLM_EXTERN Boolean LIBCALL AsnGenericChoiceSeqOfFree PROTO ((Pointer ptr, AsnOptFreeFunc freefunc));
 
+NLM_EXTERN ValNodePtr LIBCALL AsnGenericValNodeSetAsnRead (
+  AsnIoPtr aip,
+  AsnModulePtr amp,
+  AsnTypePtr orig,
+  BoolPtr isError,
+  AsnReadFunc readfunc,
+  AsnOptFreeFunc freefunc
+);
+NLM_EXTERN Boolean LIBCALL AsnGenericValNodeSetAsnWrite (
+  ValNodePtr ptr,
+  AsnWriteFunc writefunc,
+  AsnIoPtr aip,
+  AsnTypePtr bag_atp,
+  AsnTypePtr element_atp
+);
+NLM_EXTERN ValNodePtr LIBCALL AsnGenericValNodeSetFree (
+  ValNodePtr ptr,
+  AsnOptFreeFunc freefunc
+);
+
 /*** asnbufo.c ***/
 NLM_EXTERN Boolean LIBCALL AsnBufWrite PROTO ((AsnIoPtr aip, AsnTypePtr atp, CharPtr buf, size_t buflen));
 NLM_EXTERN Boolean LIBCALL AsnBinBufWrite PROTO ((AsnIoPtr aip, AsnTypePtr atp, CharPtr buf, size_t buflen));
diff --git a/asnlib/asncode.c b/asnlib/asncode.c
index ac3a838..9b9f7f9 100644
--- a/asnlib/asncode.c
+++ b/asnlib/asncode.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 7/8/93
 *
-* $Revision: 6.16 $
+* $Revision: 6.17 $
 *
 * File Description:
 *   Automatically generate C code from ASN.1 specifications
@@ -47,6 +47,9 @@
 * -------  ----------  -----------------------------------------------------
 *
 * $Log: asncode.c,v $
+* Revision 6.17  2009/11/05 16:54:12  gouriano
+* Added option to use quoted syntax form to include headers. JIRA: CXX-1402
+*
 * Revision 6.16  2005/01/24 17:12:11  kans
 * added force_choice_struct (-V) to force struct plus object instead of ValNode for choices - for compatibility with old hand-coded object loaders
 *
@@ -144,7 +147,7 @@
 
 static Boolean AsnCodeIsEnumType PROTO ((AsnTypePtr atp));
 
-static char     RCS_Rev [] = "$Revision: 6.16 $";
+static char     RCS_Rev [] = "$Revision: 6.17 $";
 
 /*******************
  * Interator structure
@@ -4400,6 +4403,8 @@ AsnCode (AsnCodeInfoPtr acip)
    AsnModulePtr last_amp = acip -> last_amp;
 
    CharPtr         use_load = StringSave (loadname);
+   Char include_open = acip->use_quoted_include ? '\"' : '<';
+   Char include_close = acip->use_quoted_include ? '\"' : '>';
 
    iter -> acip = acip;
    iter -> do_opt_bits = do_bit_twiddle;
@@ -4594,10 +4599,10 @@ AsnCode (AsnCodeInfoPtr acip)
    AsnIterTakeBuf (iter);
    if (include_filename) {
       sprintf (iter->buf,
-	       "#include <%s>\n", include_filename);
+	       "#include %c%s%c\n", include_open, include_filename, include_close);
       AsnIterTakeBuf (iter);
    }
-   sprintf (iter->buf, "#include <%s>\n", include_name);
+   sprintf (iter->buf, "#include %c%s%c\n", include_open, include_name, include_close);
    AsnIterTakeBuf (iter);
    sprintf (iter->buf, "\nstatic Boolean loaded = FALSE;\n\n");
    AsnIterTakeBuf (iter);
@@ -4613,7 +4618,7 @@ AsnCode (AsnCodeInfoPtr acip)
    hold_buf = StringSave (buf);
    StringCat (buf, ".h");
    include_name = StringSave (buf);
-   sprintf (iter->buf, "#include <%s>\n\n", include_name);
+   sprintf (iter->buf, "#include %c%s%c\n\n", include_open, include_name, include_close);
    AsnIterTakeBuf (iter);
    if (object_manager_entry != NULL) {
      if (objlabel == NULL) {
diff --git a/asnlib/asngenob.c b/asnlib/asngenob.c
index d914922..7c88012 100644
--- a/asnlib/asngenob.c
+++ b/asnlib/asngenob.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 4/21/94
 *
-* $Revision: 6.2 $
+* $Revision: 6.3 $
 *
 * File Description:
 *   Generic routines shared by object loaders which are automatically
@@ -41,6 +41,9 @@
 * -------  ----------  -----------------------------------------------------
 *
 * $Log: asngenob.c,v $
+* Revision 6.3  2010/04/29 22:01:17  kans
+* added AsnGenericValNodeSet functions to aid in manual object loader tweaking
+*
 * Revision 6.2  2000/12/12 15:56:12  ostell
 * added support BigInt
 *
@@ -396,3 +399,109 @@ NLM_EXTERN Boolean LIBCALL AsnGenericChoiceSeqOfFree (Pointer ptr, AsnOptFreeFun
 
    return retval;
 }
+
+
+NLM_EXTERN ValNodePtr LIBCALL AsnGenericValNodeSetAsnRead (
+  AsnIoPtr aip,
+  AsnModulePtr amp,
+  AsnTypePtr orig,
+  BoolPtr isError,
+  AsnReadFunc readfunc,
+  AsnOptFreeFunc freefunc
+)
+
+{
+  AsnTypePtr  atp = orig, start_atp;
+  DataVal     av;
+  Pointer     val;
+  ValNodePtr  vnp, head = NULL, last = NULL;
+
+  if (isError != NULL) {
+    *isError = FALSE;
+  }
+  if (aip == NULL || readfunc == NULL || freefunc == NULL) return NULL;
+
+  if (AsnReadVal (aip, atp, &av) <= 0) goto erret; /* read START STRUCT */
+
+  start_atp = orig;
+  atp = start_atp;
+
+  while ((atp = AsnReadId (aip, amp, atp)) != start_atp) {
+    val = (Pointer) readfunc (aip, atp);
+    if (val == NULL) goto erret;
+    vnp = ValNodeAddPointer (&last, 0, val);
+    if (head == NULL) {
+      head = vnp;
+    }
+    last = vnp;
+  }
+
+  if (AsnReadVal (aip, atp, &av) <= 0) goto erret; /* read END STRUCT */
+
+ret:
+  return (Pointer) head;
+
+erret:
+  head = AsnGenericValNodeSetFree (head, freefunc);
+
+  if (isError != NULL) {
+    *isError = TRUE;
+  }
+
+  goto ret;
+}
+
+NLM_EXTERN Boolean LIBCALL AsnGenericValNodeSetAsnWrite (
+  ValNodePtr ptr,
+  AsnWriteFunc writefunc,
+  AsnIoPtr aip,
+  AsnTypePtr bag_atp,
+  AsnTypePtr element_atp
+)
+
+{
+  Boolean     retval = FALSE;
+  Pointer     val;
+  ValNodePtr  vnp;
+
+  if (aip == NULL || writefunc == NULL) return FALSE;
+  if (ptr == NULL && bag_atp != NULL && bag_atp->optional) return TRUE;
+
+  if (! AsnOpenStruct (aip, bag_atp, ptr)) goto ret; /* write START STRUCT */
+
+  for (vnp = ptr; vnp != NULL; vnp = vnp->next) {
+    val = (Pointer) vnp->data.ptrvalue;
+    if (val == NULL) goto ret;
+    if (! writefunc (val, aip, element_atp)) goto ret;
+  }
+
+  if (! AsnCloseStruct (aip, bag_atp, ptr)) goto ret; /* write END STRUCT */
+
+  retval = TRUE;
+
+ret:
+   return retval;
+}
+
+NLM_EXTERN ValNodePtr LIBCALL AsnGenericValNodeSetFree (
+  ValNodePtr ptr,
+  AsnOptFreeFunc freefunc
+)
+
+{
+  ValNodePtr  vnp, next;
+
+  if (ptr == NULL || freefunc == NULL) return NULL;
+
+  for (vnp = ptr; vnp != NULL; vnp = next) {
+    next = vnp->next;
+    vnp->next = NULL;
+    if (vnp->data.ptrvalue != NULL) {
+      freefunc (vnp->data.ptrvalue);
+    }
+    ValNodeFree (vnp);
+  }
+
+  return NULL;
+}
+
diff --git a/asnlib/asnout.c b/asnlib/asnout.c
index 774c5fc..bbf51fc 100644
--- a/asnlib/asnout.c
+++ b/asnlib/asnout.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 3/4/91
 *
-* $Revision: 6.2 $
+* $Revision: 6.3 $
 *
 * File Description:
 *   Routines for outputing ASN.1 parse trees from asntool
@@ -41,6 +41,9 @@
 * 3/4/91   Kans        Stricter typecasting for GNU C and C++
 *
 * $Log: asnout.c,v $
+* Revision 6.3  2009/10/02 19:28:19  kans
+* address clang static analyzer warnings
+*
 * Revision 6.2  2001/01/10 17:42:47  beloslyu
 * fix to resolve the problem with buggy optimizer of Forte compiler on Solaris/Intel
 *
@@ -157,7 +160,7 @@ NLM_EXTERN void AsnOutput (CharPtr filename, AsnModulePtr amp, Boolean loader, I
         ld = NULL;
 
 	for (i = 0; i < 12; i++)
-		fprintf(fp, headerlines[i]);
+		fprintf(fp, "%s", headerlines[i]);
 	fprintf(fp, "static char * asnfilename = \"%s\";\n", buf);
 
 	curr_mod = amp;
diff --git a/asnlib/asnprint.c b/asnlib/asnprint.c
index 73721d2..81c463a 100644
--- a/asnlib/asnprint.c
+++ b/asnlib/asnprint.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 3/4/91
 *
-* $Revision: 6.24 $
+* $Revision: 6.27 $
 *
 * File Description:
 *   Routines for printing ASN.1 value notation (text) messages and
@@ -39,105 +39,6 @@
 * --------------------------------------------------------------------------
 * Date     Name        Description of modification
 * -------  ----------  -----------------------------------------------------
-* 3/4/91   Kans        Stricter typecasting for GNU C and C++
-*
-* $Log: asnprint.c,v $
-* Revision 6.24  2008/05/28 15:07:41  gouriano
-* Corrected alignment of output in AsnPrintString. Jira CXX-119
-*
-* Revision 6.23  2007/12/03 18:15:31  gouriano
-* Corrected line length in AsnPrintString
-*
-* Revision 6.22  2004/12/08 04:39:38  beloslyu
-* c++ comment changed to c-style one. Anrdrei, please be careful
-*
-* Revision 6.21  2004/08/17 19:34:42  kans
-* AsnPrintOctets uses BSRead instead of BSGetByte for significant speed increase
-*
-* Revision 6.20  2003/12/03 19:31:09  gouriano
-* Corrected DTD generation (a different approach)
-*
-* Revision 6.19  2003/12/02 19:52:48  gouriano
-* Corrected DTD generation
-*
-* Revision 6.18  2003/09/15 16:16:32  kans
-* added AsnWriteEx, AsnTxtWriteEx, and AsnPrintStream
-*
-* Revision 6.17  2002/06/10 15:19:16  kans
-* AsnPrintString checks for NULL input string, reports error and returns FALSE
-*
-* Revision 6.16  2002/03/08 20:13:10  ivanov
-* Fixed AsnPrintNewLine(), AsnPrintString() -- accurate print XML
-*
-* Revision 6.15  2001/10/11 14:39:08  ostell
-* added support for XMLModulePrefix
-*
-* Revision 6.14  2001/03/28 01:25:38  juran
-* Removed unused variable.
-*
-* Revision 6.13  2000/12/12 15:56:14  ostell
-* added support BigInt
-*
-* Revision 6.12  2000/07/27 12:28:04  ostell
-* fixed PUBLIC identifier for DTDs in XML
-*
-* Revision 6.11  2000/07/25 20:30:58  ostell
-* added support for printing multiple ASN.1 modules as multiple XML DTD and .mod files
-*
-* Revision 6.10  2000/06/29 20:15:15  ostell
-* minor typos fixed
-*
-* Revision 6.9  2000/05/26 14:55:31  ostell
-* remove apostrophes and H from OCTETS for XML
-*
-* Revision 6.8  2000/05/22 15:01:06  ostell
-* added check to AsnXMLTag for ENUM in SETOF/SEQOF
-*
-* Revision 6.7  2000/05/12 20:44:01  ostell
-* make changes to collect comments from spec and print in DTD
-*
-* Revision 6.6  2000/05/11 21:35:44  ostell
-* made elements and ennumerated prettier in DTD
-*
-* Revision 6.5  2000/05/10 15:30:01  ostell
-* fixed CHOICE poping multiple levels deep for XML
-*
-* Revision 6.4  2000/05/10 04:34:12  ostell
-* couple more xml fixes
-*
-* Revision 6.3  2000/05/10 03:12:37  ostell
-* added support for XML DTD and XML data output
-*
-* Revision 6.2  1999/07/15 18:52:52  shavirin
-* Fixed mantissa overflow in the function AsnPrintReal().
-*
-* Revision 6.1  1998/06/12 19:27:53  kans
-* fixed unix compiler warnings
-*
-* Revision 6.0  1997/08/25 18:10:18  madden
-* Revision changed to 6.0
-*
-* Revision 5.1  1996/12/03 21:43:48  vakatov
-* Adopted for 32-bit MS-Windows DLLs
-*
- * Revision 5.0  1996/05/28  14:00:29  ostell
- * Set to revision 5.0
- *
- * Revision 4.1  1996/02/18  16:45:36  ostell
- * changed fix_non_print behavior and added option 3
- *
- * Revision 4.0  1995/07/26  13:47:38  ostell
- * force revision to 4.0
- *
- * Revision 2.17  1995/07/13  14:28:37  madden
- * Changed tbuf in AsnPrintInteger from 11 to 20.
- *
- * Revision 2.16  1995/07/13  14:19:06  madden
- * Changed tbuf in AsnPrintInteger from 10 to 11 bytes.
- *
- * Revision 2.15  1995/05/15  18:38:28  ostell
- * added Log line
- *
 *
 * ==========================================================================
 */
@@ -1207,7 +1108,7 @@ NLM_EXTERN void AsnPrintIndent (Boolean increase, AsnIoPtr aip)
 *       indent to the proper level on the next line
 *
 *****************************************************************************/
-NLM_EXTERN void AsnPrintNewLine (AsnIoPtr aip)
+static void AsnPrintNewLineInt (AsnIoPtr aip, Boolean addAsnComma)
 
 {
 	Int1    tpos, indent;
@@ -1256,7 +1157,7 @@ NLM_EXTERN void AsnPrintNewLine (AsnIoPtr aip)
             /* not first line of struct */
             if (aip->first[aip->indent_level] == FALSE)
             {
-                if (!(aip->type & ASNIO_XML))   /* add commas */
+                if (!(aip->type & ASNIO_XML) && addAsnComma)   /* add commas */
                 {
                     *tmp = ' '; tmp++;
                     *tmp = ','; tmp++;
@@ -1300,6 +1201,12 @@ NLM_EXTERN void AsnPrintNewLine (AsnIoPtr aip)
 	return;
 }
 
+NLM_EXTERN void AsnPrintNewLine (AsnIoPtr aip)
+
+{
+  AsnPrintNewLineInt (aip, TRUE);
+}
+
 
 /*  XML transliteration table
  */
@@ -1677,7 +1584,7 @@ NLM_EXTERN Boolean AsnPrintString (CharPtr the_string, AsnIoPtr aip)
             /* Print new line */
 
             aip->first[aip->indent_level] = TRUE;   /* no commas */
-            if ( isXML )                /* don't split XML lines */
+            if ( isXML || aip->asn_no_newline )                /* don't split XML lines */
                 aip->no_newline = TRUE;
             AsnPrintNewLine(aip);       
             aip->offset = aip->offset - aip->linepos + cnt_save;
@@ -1856,6 +1763,11 @@ NLM_EXTERN void AsnPrintCloseStruct (AsnIoPtr aip, AsnTypePtr atp)
             AsnXMLTerm(aip, atp2);
             
 		}
+    } else if (aip->asn_alt_struct) {
+		AsnPrintNewLineInt (aip, FALSE);
+	    AsnPrintIndent (FALSE, aip);
+	    AsnTypeSetIndent (FALSE, aip, atp);
+	    AsnPrintChar ('}', aip);
     } else {
 	    AsnPrintChar(' ', aip);
 	    AsnPrintChar('}', aip);
diff --git a/asnlib/asntool.c b/asnlib/asntool.c
index 1769426..8aacc47 100644
--- a/asnlib/asntool.c
+++ b/asnlib/asntool.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 1/1/91
 *
-* $Revision: 6.16 $
+* $Revision: 6.17 $
 *
 * File Description:
 *   Main routine for asntool.  Uses the ASN.1 library routines to perform
@@ -43,6 +43,9 @@
 *
 *
 * $Log: asntool.c,v $
+* Revision 6.17  2009/11/05 16:54:12  gouriano
+* Added option to use quoted syntax form to include headers. JIRA: CXX-1402
+*
 * Revision 6.16  2005/01/24 17:12:11  kans
 * added force_choice_struct (-V) to force struct plus object instead of ValNode for choices - for compatibility with old hand-coded object loaders
 *
@@ -138,7 +141,7 @@ extern void AsnTxtReadValFile PROTO((AsnModulePtr amp, AsnIoPtr aip, AsnIoPtr ai
 extern void AsnBinReadValFile PROTO((AsnTypePtr atp, AsnIoPtr aip, AsnIoPtr aipout,
 				     AsnIoPtr encode, AsnIoPtr xaipout));
 
-#define NUMARGS 26
+#define NUMARGS 27
 
 Args asnargs[NUMARGS] = {
 	{"ASN.1 Module File",NULL,NULL,NULL,FALSE,'m',ARG_FILE_IN,0.0,0,NULL},
@@ -172,6 +175,8 @@ Args asnargs[NUMARGS] = {
    {"Force choice to use structure instead of ValNodePtr","F",NULL,NULL,TRUE,'V',ARG_BOOLEAN,0.0,0,NULL},
    /*-- not used now {"Asnload directory [for parsetrees]", NULL, NULL, NULL, TRUE, 'd', ARG_FILE_IN, 0.0, 0, NULL}, -----------*/
 
+   {"Use quoted syntax form for generated include files","F",NULL,NULL,TRUE,'Q',ARG_BOOLEAN,0.0,0,NULL},
+
 };
 
 Int2 Main (void)
@@ -190,7 +195,7 @@ Int2 Main (void)
 	, S_argDebugFileName = 18, I_argExtraIncludeName = 19
 	, Z_argBitTwiddle = 20, K_argLoadName = 21
 	, J_objMgrEntry = 22, L_objMgrLabel = 23, P_argXMLmodulePrefix = 24
-	, V_argChoiceStruct = 25;
+	, V_argChoiceStruct = 25, Q_argQuoted = 26;
 
 	AsnIoPtr aip = NULL,
 		aipout = NULL,
@@ -517,6 +522,7 @@ Int2 Main (void)
 	    } else {
 		(acip -> bug_fp) = FileOpen ("stderr", "w");
 	    }
+	    acip -> use_quoted_include = asnargs[Q_argQuoted ].intvalue != 0;
 	    AsnCode(acip);
 	}
 	
diff --git a/asnlib/asntool.h b/asnlib/asntool.h
index 5b8cc14..af83ec2 100644
--- a/asnlib/asntool.h
+++ b/asnlib/asntool.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date: 12/3/97
 *
-* $Revision: 6.3 $
+* $Revision: 6.4 $
 *
 * File Description:
 *   Includes for building asntool and libraries
@@ -40,6 +40,9 @@
 * -------  ----------  -----------------------------------------------------
 *
 * $Log: asntool.h,v $
+* Revision 6.4  2009/11/05 16:54:12  gouriano
+* Added option to use quoted syntax form to include headers. JIRA: CXX-1402
+*
 * Revision 6.3  2005/01/24 17:12:11  kans
 * added force_choice_struct (-V) to force struct plus object instead of ValNode for choices - for compatibility with old hand-coded object loaders
 *
@@ -73,6 +76,7 @@ typedef struct struct_AsnCodeInfo {
    CharPtr object_label; /* label (defaults to object_manager_entry) */
    AsnModulePtr amp;         /* standard ncbi usage, all modules */
    AsnModulePtr last_amp;    /* stop generating code when get to this module */
+   Boolean use_quoted_include;
 } AsnCodeInfo, PNTR AsnCodeInfoPtr;
 
 void AsnCode    PROTO ((AsnCodeInfoPtr acip));
diff --git a/biostruc/cdd/cdd.asn b/biostruc/cdd/cdd.asn
index 41b14f8..6b49014 100644
--- a/biostruc/cdd/cdd.asn
+++ b/biostruc/cdd/cdd.asn
@@ -1,4 +1,4 @@
---$Revision: 1.27 $
+--$Revision: 1.28 $
 --**********************************************************************
 --
 --  Definitions for CDD's 
@@ -280,7 +280,19 @@ Align-annot ::= SEQUENCE {
                                         -- be used for labels in visualization
   evidence      SEQUENCE OF Feature-evidence OPTIONAL,  -- evidence we can
                                                         -- compute with
-  type          INTEGER OPTIONAL        -- for typing annotated features
+  type          INTEGER OPTIONAL,       -- for typing annotated features
+                                        -- 0 .. no type assigned
+                                        -- 1 .. active site
+                                        -- 2 .. polypeptide binding site
+                                        -- 3 .. nucleic acid binding site
+                                        -- 4 .. ion binding site
+                                        -- 5 .. chemical binding site
+                                        -- 6 .. posttranslational modification site
+  aliases       SEQUENCE OF VisibleString OPTIONAL, -- adding more names for indexing
+  motif         VisibleString OPTIONAL, -- to validate mapping of sites
+  motifuse      INTEGER OPTIONAL        -- 0 for validation,
+                                        -- 1 for motif somewhere in seqloc
+                                        -- 2 for multiple motifs in seqloc
 }
 
 Align-annot-set ::= SEQUENCE OF Align-annot
@@ -480,7 +492,12 @@ Cdd-Project ::= SEQUENCE {
   cdcolor       SEQUENCE OF INTEGER,      -- colors  
   viewers       SEQUENCE OF Cdd-Viewer,   -- Sequence viewers
   log           VisibleString,            -- log
-  scripts       SEQUENCE OF Cdd-Script OPTIONAL    -- command scripts
+  scripts       SEQUENCE OF Cdd-Script OPTIONAL,    -- command scripts
+  id            Cdd-id-set  OPTIONAL,               -- to assign unique project id
+  rids          SEQUENCE OF VisibleString OPTIONAL, -- to store request IDs for batch CD-Searches
+  create-date   Date OPTIONAL,
+  update-date   Date OPTIONAL,
+  project-id    INTEGER OPTIONAL          -- for temporary tracking in the database
 }
 
 END
diff --git a/checkout.date b/checkout.date
index 0204f58..f6098ec 100644
--- a/checkout.date
+++ b/checkout.date
@@ -1 +1 @@
-Sun Aug 9 10:12:32 EDT 2009
+Sun Aug 8 10:12:32 EDT 2010
diff --git a/connect/ncbi_ansi_ext.h b/connect/ncbi_ansi_ext.h
index 1dbbb21..7e18d3d 100644
--- a/connect/ncbi_ansi_ext.h
+++ b/connect/ncbi_ansi_ext.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_ANSI_EXT__H
 #define CONNECT___NCBI_ANSI_EXT__H
 
-/*  $Id: ncbi_ansi_ext.h,v 6.17 2008/05/01 16:25:34 kazimird Exp $
+/* $Id: ncbi_ansi_ext.h,v 6.19 2010/05/22 14:59:43 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -32,12 +32,10 @@
  *   Non-ANSI, yet widely used functions
  *
  */
+
 #include <connect/connect_export.h>
 #include "ncbi_config.h"
 #include <stddef.h>
-#if !defined(NCBI_CXX_TOOLKIT)  &&  !defined(_GNU_SOURCE)
-#  define _GNU_SOURCE
-#endif /*!NCBI_CXX_TOOLKIT && !_GNU_SOURCE*/
 #include <string.h>
 
 
@@ -57,7 +55,8 @@ extern "C" {
  * Return an identical malloc'ed string, which must be explicitly freed 
  * by free() when no longer needed.
  */
-extern NCBI_XCONNECT_EXPORT char* strdup(const char* str);
+extern NCBI_XCONNECT_EXPORT
+char* strdup(const char* str);
 
 #endif /*HAVE_STRDUP*/
 
@@ -73,7 +72,8 @@ extern NCBI_XCONNECT_EXPORT char* strdup(const char* str);
  * Return a malloc'ed and '\0'-terminated string, which must be
  * explicitly freed by free() when no longer needed.
  */
-extern NCBI_XCONNECT_EXPORT char* strndup(const char* str, size_t n);
+extern NCBI_XCONNECT_EXPORT
+char* strndup(const char* str, size_t n);
 
 #endif /*HAVE_STRNDUP*/
 
@@ -91,13 +91,15 @@ extern NCBI_XCONNECT_EXPORT char* strndup(const char* str, size_t n);
  * Return less than, equal to or greater than zero if
  * "s1" is lexicographically less than, equal to or greater than "s2".
  */
-extern NCBI_XCONNECT_EXPORT int strcasecmp(const char* s1, const char* s2);
+extern NCBI_XCONNECT_EXPORT
+int strcasecmp(const char* s1, const char* s2);
 
 /* Compare not more than "n" characters of "s1" and "s2", ignoring case.
  * Return less than, equal to or greater than zero if
  * "s1" is lexicographically less than, equal to or greater than "s2".
  */
-extern NCBI_XCONNECT_EXPORT int strncasecmp(const char* s1, const char* s2, size_t n);
+extern NCBI_XCONNECT_EXPORT
+int strncasecmp(const char* s1, const char* s2, size_t n);
 
 #endif/*HAVE_STRCASECMP*/
 
@@ -113,13 +115,15 @@ extern NCBI_XCONNECT_EXPORT int strncasecmp(const char* s1, const char* s2, size
  * the altered string. Because the conversion is made in place, the
  * returned pointer is the same as the passed one.
  */
-extern NCBI_XCONNECT_EXPORT char* strupr(char* s);
+extern NCBI_XCONNECT_EXPORT
+char* strupr(char* s);
 
 /* Convert a string to lowercase, then return pointer to
  * the altered string. Because the conversion is made in place, the
  * returned pointer is the same as the passed one.
  */
-extern NCBI_XCONNECT_EXPORT char* strlwr(char* s);
+extern NCBI_XCONNECT_EXPORT
+char* strlwr(char* s);
 
 
 /* Copy not more than "n" characters from string "s2" into "s1"
@@ -128,7 +132,8 @@ extern NCBI_XCONNECT_EXPORT char* strlwr(char* s);
  * that the result is always null-terminated and that the function does not
  * pad "s1" with null bytes should "s2" be shorter than "n" characters.
  */
-extern NCBI_XCONNECT_EXPORT char* strncpy0(char* s1, const char* s2, size_t n);
+extern NCBI_XCONNECT_EXPORT
+char* strncpy0(char* s1, const char* s2, size_t n);
 
 
 #ifdef __cplusplus
diff --git a/connect/ncbi_base64.c b/connect/ncbi_base64.c
new file mode 100644
index 0000000..13cbf9a
--- /dev/null
+++ b/connect/ncbi_base64.c
@@ -0,0 +1,204 @@
+/* $Id: ncbi_base64.c,v 1.1 2010/06/08 15:24:52 lavr Exp $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Anton Lavrentiev
+ *
+ * File Description:
+ *   BASE-64 Encoding/Decoding
+ *
+ */
+
+#include "ncbi_base64.h"
+
+
+extern void BASE64_Encode
+(const void* src_buf,
+ size_t      src_size,
+ size_t*     src_read,
+ void*       dst_buf,
+ size_t      dst_size,
+ size_t*     dst_written,
+ size_t*     line_len)
+{
+    static const char syms[] =
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /*26*/
+        "abcdefghijklmnopqrstuvwxyz" /*52*/
+        "0123456789+/";              /*64*/
+    const size_t max_len = line_len ? *line_len : 76;
+    const size_t max_src =
+        ((dst_size - (max_len ? dst_size/(max_len + 1) : 0)) >> 2) * 3;
+    unsigned char* src = (unsigned char*) src_buf;
+    unsigned char* dst = (unsigned char*) dst_buf;
+    size_t len = 0, i = 0, j = 0;
+    unsigned char temp = 0, c;
+    unsigned char shift = 2;
+    if (!max_src  ||  !src_size) {
+        *src_read    = 0;
+        *dst_written = 0;
+        if (dst_size > 0) {
+            *dst = '\0';
+        }
+        return;
+    }
+    if (src_size > max_src) {
+        src_size = max_src;
+    }
+    c = src[0];
+    for (;;) {
+        unsigned char bits = (c >> shift) & 0x3F;
+        if (max_len  &&  len >= max_len) {
+            dst[j++] = '\n';
+            len = 0;
+        }
+        _ASSERT((size_t)(temp | bits) < sizeof(syms) - 1);
+        dst[j++] = syms[temp | bits];
+        len++;
+        if (i >= src_size) {
+            break;
+        }
+        shift += 2;
+        shift &= 7;
+        temp = (c << (8 - shift)) & 0x3F;
+        if (shift) {
+            c = ++i < src_size ? src[i] : 0;
+        } else if (i + 1 == src_size) {
+            i++;
+        }
+    }
+    _ASSERT(j <= dst_size);
+    *src_read = i;
+    for (i = 0; i < (3 - src_size % 3) % 3; i++) {
+        if (max_len  &&  len >= max_len) {
+            dst[j++] = '\n';
+            len = 0;
+        }
+        dst[j++] = '=';
+        len++;
+    }
+    _ASSERT(j <= dst_size);
+    *dst_written = j;
+    if (j < dst_size) {
+        dst[j] = '\0';
+    }
+}
+
+
+extern int/*bool*/ BASE64_Decode
+(const void* src_buf,
+ size_t      src_size,
+ size_t*     src_read,
+ void*       dst_buf,
+ size_t      dst_size,
+ size_t*     dst_written)
+{
+    unsigned char* src = (unsigned char*) src_buf;
+    unsigned char* dst = (unsigned char*) dst_buf;
+    size_t i = 0, j = 0, k = 0, l;
+    unsigned int temp = 0;
+    if (src_size < 4  ||  dst_size < 3) {
+        *src_read    = 0;
+        *dst_written = 0;
+        return 0/*false*/;
+    }
+    for (;;) {
+        int/*bool*/  ok = i < src_size ? 1/*true*/ : 0/*false*/;
+        unsigned char c = ok ? src[i++] : '=';
+        if (c == '=') {
+            c  = 64; /*end*/
+        } else if (c >= 'A'  &&  c <= 'Z') {
+            c -= 'A';
+        } else if (c >= 'a'  &&  c <= 'z') {
+            c -= 'a' - 26;
+        } else if (c >= '0'  &&  c <= '9') {
+            c -= '0' - 52;
+        } else if (c == '+') {
+            c  = 62;
+        } else if (c == '/') {
+            c  = 63;
+        } else {
+            continue;
+        }
+        temp <<= 6;
+        temp  |= c & 0x3F;
+        if (!(++k & 3)  ||  c == 64) {
+            if (c == 64) {
+                if (k < 2) {
+                    if (ok) {
+                        /* pushback leading '=' */
+                        --i;
+                    }
+                    break;
+                }
+                switch (k) {
+                case 2:
+                    temp >>= 4;
+                    break;
+                case 3:
+                    temp >>= 10;
+                    break;
+                case 4:
+                    temp >>= 8;
+                    break;
+                default:
+                    _ASSERT(0);
+                    break;
+                }
+                l = 4 - k;
+                while (l > 0) {
+                    /* eat up '='-padding */
+                    if (i >= src_size)
+                        break;
+                    if (src[i] == '=')
+                        l--;
+                    else if (src[i] != '\r'  &&  src[i] != '\n')
+                        break;
+                    i++;
+                }
+            } else {
+                k = 0;
+            }
+            switch (k) {
+            case 0:
+                dst[j++] = (temp & 0xFF0000) >> 16;
+                /*FALLTHRU*/;
+            case 4:
+                dst[j++] = (temp & 0xFF00) >> 8;
+                /*FALLTHRU*/
+            case 3:
+                dst[j++] = (temp & 0xFF);
+                break;
+            default:
+                break;
+            }
+            if (j + 3 >= dst_size  ||  c == 64) {
+                break;
+            }
+            temp = 0;
+        }
+    }
+    *src_read    = i;
+    *dst_written = j;
+    return i  &&  j ? 1/*true*/ : 0/*false*/;
+}
diff --git a/connect/ncbi_base64.h b/connect/ncbi_base64.h
new file mode 100644
index 0000000..f72a5b8
--- /dev/null
+++ b/connect/ncbi_base64.h
@@ -0,0 +1,99 @@
+#ifndef CONNECT___NCBI_BASE64__H
+#define CONNECT___NCBI_BASE64__H
+
+/* $Id: ncbi_base64.h,v 1.7 2010/06/08 16:19:54 lavr Exp $
+ * ===========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *               National Center for Biotechnology Information
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government have not placed any restriction on its use or reproduction.
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ *  Please cite the author in any work or product based on this material.
+ *
+ * ===========================================================================
+ *
+ * Author:  Anton Lavrentiev
+ *
+ * File Description:
+ *   BASE-64 Encoding/Decoding (C Toolkit CONNECT version)
+ *
+ */
+
+#include <connect/connect_export.h>
+#include <assert.h>
+#include <stddef.h>
+
+
+#define BASE64_Encode CONNECT_BASE64_Encode
+#define BASE64_Decode CONNECT_BASE64_Decode
+
+#define _ASSERT assert
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+
+/** BASE64-encode up to "src_size" symbols(bytes) from buffer "src_buf".
+ *  Write the encoded data to buffer "dst_buf", but no more than "dst_size"
+ *  bytes.
+ *  Assign "*src_read" with the # of bytes successfully encoded from "src_buf".
+ *  Assign "*dst_written" with the # of bytes written to buffer "dst_buf".
+ *  Resulting lines will not exceed "*line_len" (or the standard default
+ *  if "line_len" is NULL) bytes;  *line_len == 0 disables the line breaks.
+ *  To estimate required destination buffer size, you can take into account
+ *  that BASE64 encoding converts every 3 bytes of source into 4 bytes of
+ *  encoded output, not including the additional line breaks ('\n').
+ */
+extern NCBI_XCONNECT_EXPORT void        BASE64_Encode
+(const void* src_buf,     /* [in]     non-NULL */
+ size_t      src_size,    /* [in]              */
+ size_t*     src_read,    /* [out]    non-NULL */
+ void*       dst_buf,     /* [in/out] non-NULL */
+ size_t      dst_size,    /* [in]              */
+ size_t*     dst_written, /* [out]    non-NULL */
+ size_t*     line_len     /* [in]  may be NULL */
+ );
+
+
+/** BASE64-decode up to "src_size" symbols(bytes) from buffer "src_buf".
+ *  Write the decoded data to buffer "dst_buf", but no more than "dst_size"
+ *  bytes.
+ *  Assign "*src_read" with the # of bytes successfully decoded from "src_buf".
+ *  Assign "*dst_written" with the # of bytes written to buffer "dst_buf".
+ *  Return FALSE (0) only if this call cannot decode anything at all.
+ *  The destination buffer size, as a worst case, equal to the source size
+ *  will accomodate the entire output.  As a rule, each 4 bytes of source
+ *  (line breaks ignored) get converted into 3 bytes of decoded output.
+ */
+extern NCBI_XCONNECT_EXPORT int/*bool*/ BASE64_Decode
+(const void* src_buf,     /* [in]     non-NULL */
+ size_t      src_size,    /* [in]              */
+ size_t*     src_read,    /* [out]    non-NULL */
+ void*       dst_buf,     /* [in/out] non-NULL */
+ size_t      dst_size,    /* [in]              */
+ size_t*     dst_written  /* [out]    non-NULL */
+ );
+
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+
+
+#endif  /* CONNECT___NCBI_BASE64__H */
diff --git a/connect/ncbi_buffer.c b/connect/ncbi_buffer.c
index 6f964e8..c631bc0 100644
--- a/connect/ncbi_buffer.c
+++ b/connect/ncbi_buffer.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_buffer.c,v 6.18 2009/07/06 18:49:30 kazimird Exp $
+/* $Id: ncbi_buffer.c,v 6.19 2009/12/30 19:34:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -104,12 +104,13 @@ extern size_t BUF_Size(BUF buf)
 
 
 /* Create a new chunk.
- * Allocate at least "chunk_size" bytes, but no less than "size" bytes.
- * Special case: "size" == 0 results in no data storage allocation.
+ * Allocate at least "chunk_size" bytes, but no less than "data_size" bytes.
+ * Special case: "data_size" == 0 results in no data storage allocation.
  */
-static SBufChunk* s_AllocChunk(size_t size, size_t chunk_size)
+static SBufChunk* s_AllocChunk(size_t data_size, size_t chunk_size)
 {
-    size_t alloc_size = ((size + chunk_size - 1) / chunk_size) * chunk_size;
+    size_t alloc_size = ((data_size + chunk_size - 1)
+                         / chunk_size) * chunk_size;
     SBufChunk* pChunk = (SBufChunk*) malloc(sizeof(*pChunk) + alloc_size);
     if ( !pChunk )
         return 0;
@@ -123,7 +124,8 @@ static SBufChunk* s_AllocChunk(size_t size, size_t chunk_size)
 }
 
 
-extern int/*bool*/ BUF_Append(BUF* pBuf, const void* data, size_t size)
+extern int/*bool*/ BUF_AppendEx(BUF* pBuf, void* data,
+                                size_t size, size_t alloc_size)
 {
     SBufChunk* pChunk;
     if ( !size )
@@ -137,8 +139,8 @@ extern int/*bool*/ BUF_Append(BUF* pBuf, const void* data, size_t size)
         return 0/*false*/;
 
     assert( !pChunk->data );
-    pChunk->alloc_size = size;
     pChunk->size       = size;
+    pChunk->alloc_size = alloc_size;
     pChunk->data       = (char*) data;
     pChunk->next       = 0;
 
@@ -152,7 +154,14 @@ extern int/*bool*/ BUF_Append(BUF* pBuf, const void* data, size_t size)
 }
 
 
-extern int/*bool*/ BUF_Prepend(BUF* pBuf, const void* data, size_t size)
+extern int/*bool*/ BUF_Append(BUF* pBuf, const void* data, size_t size)
+{
+    return BUF_AppendEx(pBuf, (void*) data, size, 0);
+}
+
+
+extern int/*bool*/ BUF_PrependEx(BUF* pBuf, void* data,
+                                 size_t size, size_t alloc_size)
 {
     SBufChunk* pChunk;
     if ( !size )
@@ -166,8 +175,8 @@ extern int/*bool*/ BUF_Prepend(BUF* pBuf, const void* data, size_t size)
         return 0/*false*/;
 
     assert( !pChunk->data );
-    pChunk->alloc_size = size;
     pChunk->size       = size;
+    pChunk->alloc_size = alloc_size;
     pChunk->data       = (char*) data;
     pChunk->next       = (*pBuf)->list;
 
@@ -177,6 +186,12 @@ extern int/*bool*/ BUF_Prepend(BUF* pBuf, const void* data, size_t size)
 }
 
 
+extern int/*bool*/ BUF_Prepend(BUF* pBuf, const void* data, size_t size)
+{
+    return BUF_PrependEx(pBuf, (void*) data, size, 0);
+}
+
+
 extern int/*bool*/ BUF_Write(BUF* pBuf, const void* data, size_t size)
 {
     SBufChunk* pChunk, *pTail;
diff --git a/connect/ncbi_comm.h b/connect/ncbi_comm.h
index e275022..9f29727 100644
--- a/connect/ncbi_comm.h
+++ b/connect/ncbi_comm.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_COMM__H
 #define CONNECT___NCBI_COMM__H
 
-/*  $Id: ncbi_comm.h,v 6.15 2006/12/13 21:15:51 lavr Exp $
+/* $Id: ncbi_comm.h,v 6.16 2010/04/01 14:09:34 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,7 +34,6 @@
  *
  */
 
-
 #define NCBID_WEBPATH           "/Service/ncbid.cgi"
 #define HTTP_CONNECTION_INFO    "Connection-Info:"
 #define HTTP_DISP_FAILURES      "Dispatcher-Failures:"
@@ -46,7 +45,8 @@
 #define DISPATCHER_CFGFILE      "servrc.cfg"
 #define DISP_PROTOCOL_VERSION   "1.1"
 #define DISPD_MESSAGE_FILE      ".dispd.msg"
-
+#define CONN_FWD_PORT_MIN      5860
+#define CONN_FWD_PORT_MAX      5870
 
 #ifdef __cplusplus
 extern "C" {
@@ -60,56 +60,4 @@ typedef unsigned int ticket_t;
 } /* extern "C" */
 #endif
 
-
-/*
- * --------------------------------------------------------------------------
- * $Log: ncbi_comm.h,v $
- * Revision 6.15  2006/12/13 21:15:51  lavr
- * Fix comments
- *
- * Revision 6.14  2006/09/07 17:50:02  lavr
- * DISPATCHER_CFGPATH to define as "/etc/lbsmd"
- *
- * Revision 6.13  2006/04/05 14:59:04  lavr
- * +LBSM_DEFAULTs
- *
- * Revision 6.12  2006/01/17 20:19:01  lavr
- * HTTP_DISP_FAILURES split into FAILURES and MESSAGES (new macro)
- *
- * Revision 6.11  2005/12/23 18:09:01  lavr
- * Bump minor version number in DISP_PROTOCOL_VERSION
- *
- * Revision 6.10  2005/04/20 18:13:10  lavr
- * extern "C" limited to code only (not preprocessor macros)
- *
- * Revision 6.9  2004/08/02 16:52:42  lavr
- * +DISPD_MESSAGE_FILE
- *
- * Revision 6.8  2003/08/11 19:06:23  lavr
- * +HTTP_DISP_MESSAGE
- *
- * Revision 6.7  2002/12/10 22:11:14  lavr
- * Add DISP_PROTOCOL_VERSION
- *
- * Revision 6.6  2002/10/11 19:44:51  lavr
- * NCBID_NAME changed into NCBID_WEBAPTH; DISPATCHER_CFGPATH added
- *
- * Revision 6.5  2002/09/19 18:07:57  lavr
- * Header file guard macro changed; log moved to end
- *
- * Revision 6.4  2001/08/20 21:59:05  lavr
- * New macro: DISPATCHER_CFGFILE
- *
- * Revision 6.3  2001/05/11 15:28:46  lavr
- * Protocol change: REQUEST_FAILED -> DISP_FAILURES
- *
- * Revision 6.2  2001/01/08 22:34:45  lavr
- * Request-Failed added to protocol
- *
- * Revision 6.1  2000/12/29 18:20:26  lavr
- * Initial revision
- *
- * ==========================================================================
- */
-
 #endif /* CONNECT___NCBI_COMM__H */
diff --git a/connect/ncbi_config.h b/connect/ncbi_config.h
index 1854450..a2228c6 100644
--- a/connect/ncbi_config.h
+++ b/connect/ncbi_config.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_CONFIG__H
 #define CONNECT___NCBI_CONFIG__H
 
-/* $Id: ncbi_config.h,v 6.15 2008/10/16 19:12:55 lavr Exp $
+/* $Id: ncbi_config.h,v 6.17 2010/05/21 16:40:19 lavr Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -51,9 +51,7 @@
 #    else
 #      define NCBI_PLATFORM_BITS 32
 #    endif
-#    define HAVE_STRDUP 1
 #    define HAVE_STRNDUP 1
-#    define HAVE_STRCASECMP 1
 #    define HAVE_GETPAGESIZE 1
 #    if !defined(HAVE_GETHOSTBYNAME_R)
 #      define HAVE_GETHOSTBYNAME_R 6
@@ -76,6 +74,8 @@
 #    endif
 #  elif defined(OS_UNIX_BEOS)
 #    define NCBI_OS_BEOS 1
+#  elif defined(OS_UNIX_FREEBSD)  ||  defined(OS_UNIX_NETBSD)
+#    define NCBI_OS_BSD 1
 #  elif defined(OS_UNIX_DARWIN)
 #    define NCBI_OS_DARWIN 1
 #    define HAVE_GETPAGESIZE 1
diff --git a/connect/ncbi_connection.c b/connect/ncbi_connection.c
index dda0c39..0e6d38d 100644
--- a/connect/ncbi_connection.c
+++ b/connect/ncbi_connection.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_connection.c,v 6.60 2009/07/28 13:04:32 kazimird Exp $
+/* $Id: ncbi_connection.c,v 6.65 2010/07/13 16:04:35 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -39,6 +39,8 @@
 
 #define NCBI_USE_ERRCODE_X   Connect_Connection
 
+#define CONNECTION_MAGIC     0xEFCDAB09
+
 
 /***********************************************************************
  *  INTERNAL
@@ -47,8 +49,14 @@
 /* Standard logging message
  */
 #define CONN_LOG_EX(subcode, func_name, level, message, status)            \
-  {                                                                        \
+  do {                                                                     \
       const char* ststr = status ? IO_StatusStr((EIO_Status) status) : ""; \
+      const char* ctype = (conn->meta.get_type                             \
+                           ? conn->meta.get_type(conn->meta.c_get_type)    \
+                           : 0);                                           \
+      char* descr = (conn->meta.descr                                      \
+                     ? conn->meta.descr(conn->meta.c_descr)                \
+                     : 0);                                                 \
       char stbuf[80];                                                      \
       if ((EIO_Status) status == eIO_Timeout  &&  timeout) {               \
           sprintf(stbuf, "%s[%u.%06u]", ststr,                             \
@@ -58,13 +66,15 @@
           ststr = stbuf;                                                   \
       }                                                                    \
       CORE_LOGF_X(subcode, level,                                          \
-                  ("[CONN_" #func_name "(%s)]  %s%s%s",                    \
-                   conn->meta.get_type                                     \
-                   ? conn->meta.get_type(conn->meta.c_get_type)            \
-                   : "Unknown", message,                                   \
+                  ("[CONN_" #func_name "(%s%s%s)]  %s%s%s",                \
+                   ctype  &&  *ctype ? ctype : "UNKNOWN",                  \
+                   descr  &&  *descr ? "; "  : "", descr ? descr : "",     \
+                   message,                                                \
                    ststr  &&  *ststr ? ": "  : "",                         \
                    ststr             ? ststr : ""));                       \
-  }
+      if (descr)                                                           \
+          free(descr);                                                     \
+  } while (0)
 
 #define CONN_LOG(s_c, f_n, lvl, msg)  CONN_LOG_EX(s_c, f_n, lvl, msg, status)
 
@@ -72,13 +82,20 @@
  * NB: "retval" must be either a valid EIO_Status or 0 (no status logged)
  */
 #define CONN_NOT_NULL_EX(subcode, func_name, retval)                    \
+  do {                                                                  \
   if (!conn) {                                                          \
       const STimeout* timeout = 0/*dummy*/;                             \
       CONN_LOG_EX(subcode, func_name, eLOG_Error,                       \
                   "NULL connection handle", retval);                    \
       assert(conn);                                                     \
       return retval;                                                    \
-  }
+      }                                                                 \
+      if (conn->magic != CONNECTION_MAGIC) {                            \
+          const STimeout* timeout = 0/*dummy*/;                         \
+          CONN_LOG_EX(subcode, func_name, eLOG_Critical,                \
+                      "Data corruption detected", 0);                   \
+      }                                                                 \
+  } while (0)
 
 #define CONN_NOT_NULL(s_c, f_n)  CONN_NOT_NULL_EX(s_c, f_n, eIO_InvalidArg)
 
@@ -92,9 +109,10 @@
 /* Connection state
  */
 typedef enum ECONN_StateTag {
-    eCONN_Unusable = -1,               /* this should be iff !conn->meta.list*/
+    eCONN_Unusable = -1,               /* iff !conn->meta.list               */
     eCONN_Closed   =  0,
-    eCONN_Open     =  1
+    eCONN_Open     =  1,
+    eCONN_Bad      =  2
 } ECONN_State;
 
 
@@ -104,16 +122,13 @@ typedef struct SConnectionTag {
     SMetaConnector         meta;       /* VTable of operations and list      */
 
     BUF                    buf;        /* storage for the Peek'd data        */
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    SConnectorAsyncHandler async_data; /* info of curr. async event handler  */
-#endif
     ECONN_State            state;      /* connection state                   */
 
     /* "[c|r|w|l]_timeout" is either 0 (kInfiniteTimeout), kDefaultTimeout
        (to use connector-specific one), or points to "[cc|rr|ww|ll]_timeout" */
     const STimeout*        o_timeout;  /* timeout on open                    */
-    const STimeout*        r_timeout;  /* timeout on reading                 */
-    const STimeout*        w_timeout;  /* timeout on writing                 */
+    const STimeout*        r_timeout;  /* timeout on read                    */
+    const STimeout*        w_timeout;  /* timeout on write                   */
     const STimeout*        c_timeout;  /* timeout on close                   */
     STimeout               oo_timeout; /* storage for "o_timeout"            */
     STimeout               rr_timeout; /* storage for "r_timeout"            */
@@ -121,89 +136,33 @@ typedef struct SConnectionTag {
     STimeout               cc_timeout; /* storage for "c_timeout"            */
 
     SCONN_Callback         cbs[CONN_N_CALLBACKS];
-} SConnection;
-
-
-
-/***********************************************************************
- *  EXTERNAL
- ***********************************************************************/
-
-extern EIO_Status CONN_Create
-(CONNECTOR connector,
- CONN*     connection)
-{
-    CONN conn = (SConnection*) calloc(1, sizeof(SConnection));
-    EIO_Status status = eIO_Unknown;
-
-    if (conn) {
-        conn->state     = eCONN_Unusable;
-        conn->o_timeout = kDefaultTimeout;
-        conn->r_timeout = kDefaultTimeout;
-        conn->w_timeout = kDefaultTimeout;
-        conn->c_timeout = kDefaultTimeout;
-        if ((status = CONN_ReInit(conn, connector)) != eIO_Success) {
-            free(conn);
-            conn = 0;
-        }
-    }
 
-    *connection = conn;
-    return status;
-}
+    unsigned int           magic;      /* magic number for integrity checks  */
+} SConnection;
 
 
-extern EIO_Status CONN_ReInit
+static EIO_Status x_ReInit
 (CONN      conn,
  CONNECTOR connector)
 {
-    const STimeout* timeout = 0/*dummy*/;
-    CONNECTOR  x_conn = 0;
+    CONNECTOR       x_conn;
     EIO_Status status;
+    const STimeout* timeout = 0/*dummy*/;
 
-    CONN_NOT_NULL(1, ReInit);
-
-    /* check arg */
-    if (!connector  &&  !conn->meta.list) {
-        assert(conn->state == eCONN_Unusable);
-        status = eIO_InvalidArg;
-        CONN_LOG(2, ReInit, eLOG_Error,
-                 "Cannot re-init empty connection with NULL");
-        return status;
-    }
+    assert(conn->meta.list  ||  conn->state == eCONN_Unusable);
 
     /* reset and close current connector(s), if any */
     if (conn->meta.list) {
-#ifdef IMPLEMENTED__CONN_WaitAsync
-        /* cancel async. i/o event handler */
-        CONN_WaitAsync(conn, eIO_ReadWrite, 0, 0, 0);
-#endif
-        {{ /* erase unread data */
-            size_t buf_size = BUF_Size(conn->buf);
-            verify(BUF_Read(conn->buf, 0, buf_size) == buf_size);
-        }}
-        /* call current connector's "FLUSH" and "CLOSE" methods */
         if (conn->state == eCONN_Open) {
+            /* call current connector's "FLUSH" method */
             if (conn->meta.flush) {
                 conn->meta.flush(conn->meta.c_flush,
                                  conn->c_timeout == kDefaultTimeout
                                  ? conn->meta.default_timeout
                                  : conn->c_timeout);
             }
-            if (conn->meta.close) {
-                status = conn->meta.close(conn->meta.c_close,
-                                          conn->c_timeout == kDefaultTimeout
-                                          ? conn->meta.default_timeout
-                                          : conn->c_timeout);
-                if (status != eIO_Success) {
-                    CONN_LOG(3, ReInit, connector ? eLOG_Error : eLOG_Warning,
-                             "Cannot close current connection");
-                    if (connector)
-                        return status;
                 }
             }
-            conn->state = eCONN_Closed;
-        }
 
         for (x_conn = conn->meta.list;  x_conn;  x_conn = x_conn->next) {
             if (x_conn == connector) {
@@ -217,23 +176,66 @@ extern EIO_Status CONN_ReInit
         }
 
         if (!x_conn) {
+        FConnCallback func;
+        void*         data;
+        /* NB: Re-initing with same connector does not cause the callback;   */
+        /* NB: Newly created connection can't have a callback set just as yet*/
+        if (conn->state != eCONN_Unusable) {
+            func = conn->cbs[eCONN_OnClose].func;
+            data = conn->cbs[eCONN_OnClose].data;
+        } else {
+            func = 0;
+            data = 0;
+        }
+        /* allow close CB only once */
+        memset(&conn->cbs[eCONN_OnClose], 0, sizeof(conn->cbs[eCONN_OnClose]));
+        /* call it! */
+        if (func)
+            func(conn, eCONN_OnClose, data);
+    }
+
+    if (conn->meta.list) {
+        /* erase unread data */
+        BUF_Erase(conn->buf);
+
+        if (conn->state == eCONN_Open) {
+            /* call current connector's "CLOSE" method */
+            if (conn->meta.close) {
+                status = conn->meta.close(conn->meta.c_close,
+                                          conn->c_timeout == kDefaultTimeout
+                                          ? conn->meta.default_timeout
+                                          : conn->c_timeout);
+                if (status != eIO_Success  &&  status != eIO_Closed) {
+                    CONN_LOG(3, ReInit, connector ? eLOG_Error : eLOG_Warning,
+                             "Error closing connection");
+                    if (connector) {
+                        conn->state = eCONN_Bad;
+                        return status;
+                    }
+                }
+            }
+            conn->state = eCONN_Closed;
+        }
+
+        if (!x_conn) {
             /* Entirely new connector - remove the old connector stack first */
             METACONN_Remove(&conn->meta, 0);
-            assert(conn->meta.list == 0);
+            assert(!conn->meta.list);
             memset(&conn->meta, 0, sizeof(conn->meta));
             conn->state = eCONN_Unusable;
         }
     }
 
-    if (connector  &&  !x_conn) {
+    if (!x_conn  &&  connector) {
         assert(conn->state == eCONN_Unusable);
         /* Setup the new connector */
         if (METACONN_Add(&conn->meta, connector) != eIO_Success)
             return eIO_Unknown;
+        assert(conn->meta.list);
         conn->state = eCONN_Closed;
     }
 
-    assert(conn->state != eCONN_Open);
+    assert(conn->state != eCONN_Open  &&  conn->state != eCONN_Bad);
     return eIO_Success;
 }
 
@@ -244,7 +246,10 @@ static EIO_Status s_Open
     const STimeout* timeout;
     EIO_Status status;
 
-    assert(conn->state == eCONN_Closed  &&  conn->meta.list != 0);
+    if (conn->state == eCONN_Bad)
+        return eIO_Closed;
+
+    assert(conn->state == eCONN_Closed  &&  conn->meta.list);
 
     /* call current connector's "OPEN" method */
     if (conn->meta.open) {
@@ -259,12 +264,67 @@ static EIO_Status s_Open
 
     if (status != eIO_Success) {
         CONN_LOG(5, Open, eLOG_Error, "Failed to open connection");
+        conn->state = eCONN_Bad;
+    } else
+        conn->state = eCONN_Open;
         return status;
+}
+
+
+/***********************************************************************
+ *  EXTERNAL
+ ***********************************************************************/
+
+extern EIO_Status CONN_Create
+(CONNECTOR connector,
+ CONN*     connection)
+{
+    EIO_Status status;
+    CONN       conn;
+
+    if (!connector)
+        return eIO_InvalidArg;
+
+    conn = (SConnection*) calloc(1, sizeof(SConnection));
+
+    if (conn) {
+        conn->state     = eCONN_Unusable;
+        conn->o_timeout = kDefaultTimeout;
+        conn->r_timeout = kDefaultTimeout;
+        conn->w_timeout = kDefaultTimeout;
+        conn->c_timeout = kDefaultTimeout;
+        conn->magic     = CONNECTION_MAGIC;
+        if ((status = x_ReInit(conn, connector)) != eIO_Success) {
+            free(conn);
+            conn = 0;
     }
+    } else
+        status = eIO_Unknown;
 
-    /* success */
-    conn->state = eCONN_Open;
+    *connection = conn;
+    return status;
+}
+
+
+extern EIO_Status CONN_ReInit
+(CONN      conn,
+ CONNECTOR connector)
+{
+    const STimeout* timeout = 0/*dummy*/;
+    EIO_Status status;
+
+    CONN_NOT_NULL(1, ReInit);
+
+    /* check arg */
+    if (!connector  &&  !conn->meta.list) {
+        assert(conn->state == eCONN_Unusable);
+        status = eIO_InvalidArg;
+        CONN_LOG(2, ReInit, eLOG_Error,
+                 "Cannot re-init empty connection with NULL");
     return status;
+    }
+
+    return x_ReInit(conn, connector);
 }
 
 
@@ -304,14 +364,6 @@ extern EIO_Status CONN_SetTimeout
         } else
             conn->o_timeout  = timeout;
         break;
-    case eIO_Close:
-        if (timeout  &&  timeout != kDefaultTimeout) {
-            if (&conn->cc_timeout != timeout)
-                conn->cc_timeout = *timeout;
-            conn->c_timeout  = &conn->cc_timeout;
-        } else
-            conn->c_timeout  = timeout;
-        break;
     case eIO_Read:
     case eIO_ReadWrite:
         if (timeout  &&  timeout != kDefaultTimeout) {
@@ -331,6 +383,14 @@ extern EIO_Status CONN_SetTimeout
         } else
             conn->w_timeout  = timeout;
         break;
+    case eIO_Close:
+        if (timeout  &&  timeout != kDefaultTimeout) {
+            if (&conn->cc_timeout != timeout)
+                conn->cc_timeout = *timeout;
+            conn->c_timeout  = &conn->cc_timeout;
+        } else
+            conn->c_timeout  = timeout;
+        break;
     default:
         sprintf(errbuf, "Unknown event #%d to set timeout for", (int) event);
         CONN_LOG_EX(9, SetTimeout, eLOG_Error, errbuf, eIO_InvalidArg);
@@ -369,7 +429,7 @@ extern const STimeout* CONN_GetTimeout
         timeout = conn->c_timeout;
         break;
     default:
-        timeout = 0;
+        timeout = 0/*dummy*/;
         sprintf(errbuf, "Unknown event #%d to get timeout for", (int) event);
         CONN_LOG_EX(12, GetTimeout, eLOG_Error, errbuf, 0);
         assert(0);
@@ -397,7 +457,7 @@ extern EIO_Status CONN_Wait
     /* perform open, if not opened yet */
     if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
         return status;
-    assert(conn->state == eCONN_Open  &&  conn->meta.list != 0);
+    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
     /* check if there is a PEEK'ed data in the input */
     if (event == eIO_Read  &&  BUF_Size(conn->buf))
@@ -526,7 +586,7 @@ extern EIO_Status CONN_Write
     /* open connection, if not yet opened */
     if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
         return status;
-    assert(conn->state == eCONN_Open  &&  conn->meta.list != 0);
+    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
     switch (how) {
     case eIO_WritePlain:
@@ -547,6 +607,9 @@ extern EIO_Status CONN_PushBack
 {
     CONN_NOT_NULL(19, PushBack);
 
+    if (conn->state == eCONN_Unusable)
+        return eIO_InvalidArg;
+
     if (conn->state != eCONN_Open)
         return eIO_Closed;
 
@@ -568,7 +631,7 @@ extern EIO_Status CONN_Flush
     /* perform open, if not opened yet */
     if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
         return status;
-    assert(conn->state == eCONN_Open  &&  conn->meta.list != 0);
+    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
     /* call current connector's "FLUSH" method */
     if (!conn->meta.flush)
@@ -628,10 +691,8 @@ static EIO_Status s_CONN_Read
         *n_read += x_read;
 
         /* save data in the internal peek buffer */
-        if (peek  &&  !BUF_Write(&conn->buf, buf, x_read)) {
-            CONN_LOG_EX(32, Read, eLOG_Error,
-                        "Cannot save peek data", 0);
-        }
+        if (peek  &&  !BUF_Write(&conn->buf, buf, x_read))
+            CONN_LOG_EX(32, Read, eLOG_Error, "Cannot save peek data", 0);
     }}
 
     if (status != eIO_Success) {
@@ -708,7 +769,7 @@ extern EIO_Status CONN_Read
     /* perform open, if not opened yet */
     if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
         return status;
-    assert(conn->state == eCONN_Open  &&  conn->meta.list != 0);
+    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
     /* flush the unwritten output data (if any) */
     if (conn->meta.flush) {
@@ -740,24 +801,29 @@ extern EIO_Status CONN_ReadLine
  size_t* n_read
  )
 {
-    EIO_Status  status = eIO_Success;
-    int/*bool*/ done = 0/*false*/;
+    EIO_Status  status;
+    int/*bool*/ done;
     size_t      len;
 
     if (!n_read)
         return eIO_InvalidArg;
     *n_read = 0;
-    if (size  &&  !line)
+    if (size) {
+        if (!line)
         return eIO_InvalidArg;
+        *line = '\0';
+    }
 
     CONN_NOT_NULL(25, ReadLine);
 
+    if (conn->state == eCONN_Unusable)
+        return eIO_InvalidArg;
+
     /* perform open, if not opened yet */
-    if (conn->state != eCONN_Open)
-        status = s_Open(conn);
+    if (conn->state != eCONN_Open  &&  (status = s_Open(conn)) != eIO_Success)
+        return status;
+    assert(conn->state == eCONN_Open  &&  conn->meta.list);
 
-    if (status == eIO_Success) {
-        assert(conn->state == eCONN_Open  &&  conn->meta.list != 0);
         /* flush the unwritten output data (if any) */
         if (conn->meta.flush) {
             conn->meta.flush(conn->meta.c_flush,
@@ -765,10 +831,10 @@ extern EIO_Status CONN_ReadLine
                              ? conn->meta.default_timeout
                              : conn->r_timeout);
         }
-    }
 
     len = 0;
-    while (status == eIO_Success) {
+    done = 0/*false*/;
+    do {
         size_t i;
         char   w[1024];
         size_t x_read = 0;
@@ -788,14 +854,18 @@ extern EIO_Status CONN_ReadLine
                 line[len] = c;
             len++;
         }
-        if (i < x_read  &&  !BUF_PushBack(&conn->buf, x_buf + i, x_read - i)) {
-            const STimeout* timeout = 0;
+        if (i < x_read) {
+            assert(done  ||  len >= size);
+            if (!BUF_PushBack(&conn->buf, x_buf + i, x_read - i)) {
+                const STimeout* timeout = 0/*dummy*/;
             CONN_LOG_EX(15, ReadLine, eLOG_Error,
                         "Cannot pushback extra data", 0);
-        }
-        if (done  ||  len >= size)
+                status = eIO_Unknown;
+            } else
+                status = eIO_Success;
             break;
     }
+    } while (!done  &&  len < size  &&  status == eIO_Success);
     if (len < size)
         line[len] = '\0';
     *n_read = len;
@@ -808,13 +878,13 @@ extern EIO_Status CONN_Status(CONN conn, EIO_Event dir)
 {
     CONN_NOT_NULL(26, Status);
 
-    if (conn->state == eCONN_Unusable  ||  !conn->meta.list)
-        return eIO_Unknown;
+    if (conn->state == eCONN_Unusable)
+        return eIO_InvalidArg;
 
     if (dir != eIO_Read  &&  dir != eIO_Write)
         return eIO_InvalidArg;
 
-    if (conn->state == eCONN_Closed)
+    if (conn->state != eCONN_Open)
         return eIO_Closed;
 
     if (!conn->meta.status)
@@ -826,27 +896,16 @@ extern EIO_Status CONN_Status(CONN conn, EIO_Event dir)
 
 extern EIO_Status CONN_Close(CONN conn)
 {
-    FConnCallback func = 0;
-    void*         data = 0;
+    EIO_Status status;
 
     CONN_NOT_NULL(27, Close);
 
-    if (conn->state != eCONN_Unusable) {
-        func = conn->cbs[eCONN_OnClose].func;
-        data = conn->cbs[eCONN_OnClose].data;
-    }
-    /* allow close CB only once */
-    memset(&conn->cbs[eCONN_OnClose], 0, sizeof(conn->cbs[eCONN_OnClose]));
-    /* call it! */
-    if (func)
-        func(conn, eCONN_OnClose, data);
-    /* now close the connection - this also makes it "eCONN_Unusable" */
-    if (conn->meta.list)
-        CONN_ReInit(conn, 0);
+    status = x_ReInit(conn, 0);
     BUF_Destroy(conn->buf);
+    conn->magic = 0;
     conn->buf = 0;
     free(conn);
-    return eIO_Success;
+    return status == eIO_Closed ? eIO_Success : status;
 }
 
 
@@ -868,71 +927,3 @@ extern EIO_Status CONN_SetCallback
         conn->cbs[i] = *new_cb;
     return eIO_Success;
 }
-
-
-#ifdef IMPLEMENTED__CONN_WaitAsync
-/* Internal handler(wrapper for the user-provided handler) for CONN_WaitAsync()
- */
-static void s_ConnectorAsyncHandler
-(SConnectorAsyncHandler* data,
- EIO_Event               event,
- EIO_Status              status)
-{
-    /* handle the async. event */
-    data->handler(data->conn, event, status, data->data);
-
-    /* reset */
-    verify(CONN_WaitAsync(data->conn, eIO_ReadWrite, 0, 0, 0) == eIO_Success);
-}
-
-
-extern EIO_Status CONN_WaitAsync
-(CONN              conn,
- EIO_Event         event,
- FConnAsyncHandler handler,
- void*             data,
- FConnAsyncCleanup cleanup)
-{
-    EIO_Status status;
-    const STimeout* timeout = 0/*dummy*/;
-    CONNECTOR  x_connector = conn->connector;
-    SConnectorAsyncHandler* x_data = &conn->async_data;
-
-    CONN_NOT_NULL(29, WaitAsync);
-
-    /* perform connect, if not connected yet */
-    if (!conn->connected  &&  (status = s_Open(conn)) != eIO_Success)
-        return status;
-
-    /* reset previous handler, cleanup its data */
-    /* (call current connector's "WAIT_ASYNC" method with NULLs) */
-    status = (x_connector->vtable.wait_async
-              ? x_connector->vtable.wait_async(x_connector->handle, 0, 0)
-              : eIO_NotSupported);
-    if (status != eIO_Success) {
-        CONN_LOG(30, WaitAsync, eLOG_Error, "Cannot reset handler");
-        return status;
-    }
-    if (x_data->cleanup)
-        x_data->cleanup(x_data->data);
-    memset(x_data, '\0', sizeof(*x_data));
-
-    /* set new handler, if specified */
-    /* (call current connector's "WAIT_ASYNC" method with new handler/data) */
-    if (!handler)
-        return eIO_Success;
-
-    x_data->conn       = conn;
-    x_data->wait_event = event;
-    x_data->handler    = handler;
-    x_data->data       = data;
-    x_data->cleanup    = cleanup;
-
-    status = x_connector->vtable.wait_async(x_connector->handle,
-                                            s_ConnectorAsyncHandler,
-                                            x_data);
-    if (status != eIO_Success)
-        CONN_LOG(31, WaitAsync, eLOG_Error, "Cannot set new handler");
-    return status;
-}
-#endif /* IMPLEMENTED__CONN_WaitAsync */
diff --git a/connect/ncbi_connection.h b/connect/ncbi_connection.h
index 1881bcc..27fa3ef 100644
--- a/connect/ncbi_connection.h
+++ b/connect/ncbi_connection.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_CONNECTION__H
 #define CONNECT___NCBI_CONNECTION__H
 
-/*  $Id: ncbi_connection.h,v 6.21 2004/10/26 14:47:42 lavr Exp $
+/* $Id: ncbi_connection.h,v 6.22 2010/02/01 13:54:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -68,7 +68,7 @@ typedef struct SConnectionTag* CONN;      /* connection handle */
  * sets conn to 0, and leaves connector intact (can be used again).
  * NOTE1:  The real connection will not be established right away. Instead,
  *         it will be established at the moment of the first call to one of
- *         "Flush", "Wait", "WaitAsync", "Write", or "Read" methods.
+ *         "Flush", "Wait", "Write", or "Read" methods.
  * NOTE2:  "Connection establishment" at this level of abstraction may differ
  *         from actual link establishment at the underlying connector's level.
  * NOTE3:  Initial timeout values are set to CONN_DEFAULT_TIMEOUT, meaning
@@ -286,35 +286,6 @@ extern NCBI_XCONNECT_EXPORT EIO_Status CONN_SetCallback
 );
 
 
-#ifdef IMPLEMENTED__CONN_WaitAsync
-/* Wait for an asynchronous I/O event, then call the specified handler.
- * In the "handler" function:
- *   "event"  -- is the I/O direction where the async. event happened
- *   "status" -- must be "eIO_Success" if it is ready for I/O
- *   "data"   -- callback data (passed as "data" in CONN_WaitAsync())
- * If "handler" is NULL then discard the current handler, if any.
- * The "cleanup" function to be called right after the call to "handler" or
- * by CONN_Close(), or if the handler is reset by calling CONN_WaitAsync()
- * again -- whichever happens first.
- */
-typedef void (*FConnAsyncHandler)
-(CONN       conn,
- EIO_Event  event,
- EIO_Status status,
- void*      data
-);
-typedef void (*FConnAsyncCleanup)(void* data);
-
-extern EIO_Status CONN_WaitAsync
-(CONN              conn,      /* [in] connection handle */
- EIO_Event         event,     /* [in] I/O direction     */
- FConnAsyncHandler handler,   /* [in] callback function */
- void*             data,      /* [in] callback data     */
- FConnAsyncCleanup cleanup    /* [in] cleanup procedure */
- );
-#endif /* IMPLEMENTED__CONN_WaitAsync */
-
-
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
@@ -322,77 +293,4 @@ extern EIO_Status CONN_WaitAsync
 
 /* @} */
 
-
-/*
- * ---------------------------------------------------------------------------
- * $Log: ncbi_connection.h,v $
- * Revision 6.21  2004/10/26 14:47:42  lavr
- * Slight formatting
- *
- * Revision 6.20  2004/06/09 14:03:06  jcherry
- * Moved #define out of enum body (SWIG was choking on this)
- *
- * Revision 6.19  2004/05/24 19:58:29  lavr
- * +NCBI_XCONNECT_EXPORT for CONN_ReadLine()
- *
- * Revision 6.18  2004/05/24 19:53:30  lavr
- * +CONN_ReadLine()
- *
- * Revision 6.17  2004/02/23 15:23:36  lavr
- * New (last) parameter "how" added in CONN_Write() API call
- *
- * Revision 6.16  2003/05/14 03:47:12  lavr
- * +CONN_Description()
- *
- * Revision 6.15  2003/04/09 17:58:43  siyan
- * Added doxygen support
- *
- * Revision 6.14  2003/01/15 19:50:17  lavr
- * +CONN_PushBack()
- *
- * Revision 6.13  2003/01/08 01:59:32  lavr
- * DLL-ize CONNECT library for MSVC (add NCBI_XCONNECT_EXPORT)
- *
- * Revision 6.12  2002/09/19 18:00:04  lavr
- * Header file guard macro changed
- *
- * Revision 6.11  2002/09/06 15:40:32  lavr
- * More comments and notes to the API
- *
- * Revision 6.10  2002/08/07 16:27:33  lavr
- * EIO_ReadMethod enums changed accordingly; log moved to the bottom
- *
- * Revision 6.9  2001/08/20 20:00:22  vakatov
- * CONN_SetTimeout() to return "EIO_Status".
- *
- * Revision 6.8  2001/06/28 22:00:31  lavr
- * Added function: CONN_SetCallback
- * Added callback: eCONN_OnClose
- *
- * Revision 6.7  2001/04/24 21:19:29  lavr
- * Introduced CONN_DEFAULT_TIMEOUT for use as a CONNECTOR-specific timeout
- *
- * Revision 6.6  2001/03/02 20:07:33  lavr
- * Typo fixed
- *
- * Revision 6.5  2001/02/09 17:33:38  lavr
- * CONN_GetType added
- *
- * Revision 6.4  2001/01/03 22:29:22  lavr
- * Changed IOStatus -> Status
- *
- * Revision 6.3  2000/12/29 17:43:42  lavr
- * Pretty printed;
- * Reconnect renamed to ReInit with ability to close current connector
- *
- * Revision 6.2  2000/04/07 19:59:47  vakatov
- * Moved forward-declaration of CONNECTOR from "ncbi_connection.h"
- * to "ncbi_connector.h"
- *
- * Revision 6.1  2000/03/24 22:52:20  vakatov
- * Initial revision
- *
- * ===========================================================================
- */
-
 #endif /* CONNECT___NCBI_CONNECTION__H */
diff --git a/connect/ncbi_connector.h b/connect/ncbi_connector.h
index 7f1a344..e027d12 100644
--- a/connect/ncbi_connector.h
+++ b/connect/ncbi_connector.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_CONNECTOR__H
 #define CONNECT___NCBI_CONNECTOR__H
 
-/*  $Id: ncbi_connector.h,v 6.17 2007/09/04 20:25:30 kazimird Exp $
+/* $Id: ncbi_connector.h,v 6.18 2010/02/01 13:54:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -83,6 +83,9 @@ typedef char* (*FConnectorDescr)
 
 /* Open connection. Used to setup all related data structures,
  * but not necessarily has to actually open the data channel.
+ * NOTE: Regardless of the returned status, the connection is
+ *       considered open (so this call does not get repeated)
+ *       when the call completes.
  */
 typedef EIO_Status (*FConnectorOpen)
 (CONNECTOR       connector,
@@ -176,9 +179,6 @@ typedef struct {
     FConnectorDescr     descr;       CONNECTOR c_descr;
     FConnectorOpen      open;        CONNECTOR c_open;
     FConnectorWait      wait;        CONNECTOR c_wait;
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    FConnectorWaitAsync wait_async;  CONNECTOR c_wait_async;
-#endif
     FConnectorWrite     write;       CONNECTOR c_write;
     FConnectorFlush     flush;       CONNECTOR c_flush;
     FConnectorRead      read;        CONNECTOR c_read;
@@ -196,17 +196,17 @@ typedef struct {
     do {                                                   \
         meta->method = function;                           \
         meta->CONN_TWO2ONE(c_,method) = connector;         \
-    } while (0);
+    } while (0)
 
 
 #define CONN_SET_DEFAULT_TIMEOUT(meta, timeout)            \
     do {                                                   \
         if (timeout) {                                     \
-            meta->default_timeout = &meta->default_tmo;    \
             meta->default_tmo     = *timeout;              \
+            meta->default_timeout = &meta->default_tmo;    \
         } else                                             \
-            meta->default_timeout = 0;                     \
-    } while (0);
+            meta->default_timeout = kInfiniteTimeout/*0*/; \
+    } while (0)
 
 
 /* Insert a connector in the beginning of the connection's list of connectors.
@@ -255,29 +255,6 @@ typedef struct SConnectorTag {
 } SConnector;
 
 
-#ifdef IMPLEMENTED__CONN_WaitAsync
-typedef struct {
-  CONN                   conn;
-  EIO_Event              event;
-  FConnAsyncHandler      handler;
-  void*                  data;
-  FConnAsyncCleanup      cleanup;
-} SConnectorAsyncHandler;
-
-typedef void (*FConnectorAsyncHandler)
-(SConnectorAsyncHandler* data,
- EIO_Event               event,
- EIO_Status              status
- );
-
-typedef EIO_Status (*FConnectorWaitAsync)
-(CONNECTOR               connector,
- FConnectorAsyncHandler  func,
- SConnectorAsyncHandler* data
- );
-#endif /* IMPLEMENTED__CONN_WaitAsync */
-
-
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
diff --git a/connect/ncbi_connutil.c b/connect/ncbi_connutil.c
index 1445481..771508c 100644
--- a/connect/ncbi_connutil.c
+++ b/connect/ncbi_connutil.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_connutil.c,v 6.133 2009/06/23 16:04:40 kazimird Exp $
+/* $Id: ncbi_connutil.c,v 6.149 2010/06/10 18:36:29 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -41,6 +41,43 @@
 #define NCBI_USE_ERRCODE_X   Connect_Util
 
 
+static const char kHostTag[] = "Host: ";
+
+
+static char* x_StrcatCRLF(char* dst, const char* src)
+{
+    size_t dstlen = dst  &&  *dst ? strlen(dst) : 0;
+    size_t srclen = src  &&  *src ? strlen(src) : 0;
+    if (dstlen  ||  srclen) {
+        size_t len;
+        char*  temp;
+        if (dstlen  &&  dst[dstlen - 1] == '\n') {
+            if (--dstlen  &&  dst[dstlen - 1] == '\r')
+                --dstlen;
+        }
+        if (srclen  &&  src[srclen - 1] == '\n') {
+            if (--srclen  &&  src[srclen - 1] == '\r')
+                --srclen;
+        }
+        len = (dstlen ? dstlen + 2 : 0) + (srclen ? srclen + 2 : 0) + 1;
+        if (!(temp = (char*)(dst ? realloc(dst, len) : malloc (len))))
+            return 0;
+        dst = temp;
+        if (dstlen) {
+            temp += dstlen;
+            memcpy(temp, "\r\n", 3);
+            temp += 2;
+        }
+        if (srclen) {
+            memcpy(temp, src, srclen);
+            temp += srclen;
+            memcpy(temp, "\r\n", 3);
+        }
+    }
+    return dst;
+}
+
+
 extern const char* ConnNetInfo_GetValue(const char* service, const char* param,
                                         char* value, size_t value_size,
                                         const char* def_value)
@@ -58,9 +95,11 @@ extern const char* ConnNetInfo_GetValue(const char* service, const char* param,
 
     if (service  &&  *service) {
         /* Service-specific inquiry */
+        char   temp[sizeof(buf)];
         size_t slen = strlen(service);
         size_t plen = strlen(param) + 1;
-        if (slen + 1 + sizeof(DEF_CONN_REG_SECTION) + plen > sizeof(buf))
+        size_t len  = slen + 1 + sizeof(DEF_CONN_REG_SECTION) + plen;
+        if (len > sizeof(buf))
             return 0;
 
         /* First, environment search for 'service_CONN_param' */
@@ -70,8 +109,10 @@ extern const char* ConnNetInfo_GetValue(const char* service, const char* param,
         s += sizeof(DEF_CONN_REG_SECTION) - 1;
         *s++ = '_';
         memcpy(s, param, plen);
-        if ((val = getenv(buf)) != 0  ||  (val = getenv(strupr(buf))) != 0)
+        if ((val = getenv(strupr((char*) memcpy(temp, buf, len)))) != 0
+            ||  (memcmp(temp, buf, len) != 0  &&  (val = getenv(buf)) != 0)) {
             return strncpy0(value, val, value_size - 1);
+        }
 
         /* Next, search for 'CONN_param' in '[service]' registry section */
         buf[slen++] = '\0';
@@ -103,6 +144,15 @@ extern const char* ConnNetInfo_GetValue(const char* service, const char* param,
 }
 
 
+int/*bool*/ ConnNetInfo_Boolean(const char* str)
+{
+    return str  &&  *str  &&  (strcmp    (str, "1")    == 0  ||
+                               strcasecmp(str, "on")   == 0  ||
+                               strcasecmp(str, "yes")  == 0  ||
+                               strcasecmp(str, "true") == 0);
+}
+
+
 static EURLScheme s_ParseScheme(const char* str, size_t len)
 {
     if (len == 5  &&  strncasecmp(str, "https", len) == 0)
@@ -117,6 +167,24 @@ static EURLScheme s_ParseScheme(const char* str, size_t len)
 }
 
 
+static const char* s_Scheme(EURLScheme scheme)
+{
+    switch (scheme) {
+    case eURL_Unspec:
+        break;
+    case eURL_Https:
+        return "https";
+    case eURL_Http:
+        return "http";
+    case eURL_File:
+        return "file";
+    case eURL_Ftp:
+        return "ftp";
+    }
+    return 0;
+}
+
+
 /****************************************************************************
  * ConnNetInfo API
  */
@@ -127,12 +195,12 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
 #define REG_VALUE(name, value, def_value) \
     ConnNetInfo_GetValue(service, name, value, sizeof(value), def_value)
 
-    SConnNetInfo* info = (SConnNetInfo*) malloc(sizeof(*info) +
-                                                (service  &&  *service
-                                                 ? strlen(service) + 1 : 0));
-    size_t len;
-    /* aux. storage for the string-to-int conversions, etc. */
+    SConnNetInfo* info =
+        (SConnNetInfo*) malloc(sizeof(*info)
+                               + (service ? strlen(service) + 1 : 0));
+    /* aux. storage */
     char   str[1024];
+    size_t len;
     int    val;
     double dbl;
     char*  e;
@@ -191,7 +259,7 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
             dbl = DEF_CONN_TIMEOUT;
         info->timeout->sec  = (unsigned int) dbl;
         info->timeout->usec = (unsigned int)
-            ((dbl - info->timeout->sec) * 1000000);
+            ((dbl - info->timeout->sec) * 1000000.0);
     }
 
     /* max. # of attempts to establish connection */
@@ -211,59 +279,47 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
             info->http_proxy_port = val;
         } else
             info->http_proxy_port = 0/*default*/;
-    } else
+        /* HTTP proxy username */
+        REG_VALUE(REG_CONN_HTTP_PROXY_USER, info->http_proxy_user,
+                  DEF_CONN_HTTP_PROXY_USER);
+        /* HTTP proxy password */
+        REG_VALUE(REG_CONN_HTTP_PROXY_PASS, info->http_proxy_pass,
+                  DEF_CONN_HTTP_PROXY_PASS);
+    } else {
         info->http_proxy_port = 0;
+        info->http_proxy_user[0] = '\0';
+        info->http_proxy_pass[0] = '\0';
+    }
 
     /* non-transparent CERN-like firewall proxy server? */
     REG_VALUE(REG_CONN_PROXY_HOST, info->proxy_host, DEF_CONN_PROXY_HOST);
 
     /* turn on debug printout? */
     REG_VALUE(REG_CONN_DEBUG_PRINTOUT, str, DEF_CONN_DEBUG_PRINTOUT);
-    if (*str  &&  (strcmp    (str, "1")    == 0  ||
-                   strcasecmp(str, "true") == 0  ||
-                   strcasecmp(str, "yes" ) == 0  ||
-                   strcasecmp(str, "on"  ) == 0  ||
-                   strcasecmp(str, "some") == 0)) {
+    if (ConnNetInfo_Boolean(str)
+        ||    (*str  &&   strcasecmp(str, "some") == 0)) {
         info->debug_printout = eDebugPrintout_Some;
-    } else if (*str  &&  (strcasecmp(str, "data") == 0  ||
-                          strcasecmp(str, "all" ) == 0)) {
+    } else if (*str  &&  (strcasecmp(str, "all")  == 0  ||
+                          strcasecmp(str, "data") == 0)) {
         info->debug_printout = eDebugPrintout_Data;
     } else
         info->debug_printout = eDebugPrintout_None;
 
     /* stateless client? */
     REG_VALUE(REG_CONN_STATELESS, str, DEF_CONN_STATELESS);
-    info->stateless = (*str  &&  (strcmp    (str, "1")    == 0  ||
-                                  strcasecmp(str, "true") == 0  ||
-                                  strcasecmp(str, "yes" ) == 0  ||
-                                  strcasecmp(str, "on"  ) == 0));
+    info->stateless = ConnNetInfo_Boolean(str);
 
     /* firewall mode? */
     REG_VALUE(REG_CONN_FIREWALL, str, DEF_CONN_FIREWALL);
-    info->firewall = (*str  &&  (strcmp    (str, "1")    == 0  ||
-                                 strcasecmp(str, "true") == 0  ||
-                                 strcasecmp(str, "yes" ) == 0  ||
-                                 strcasecmp(str, "on"  ) == 0));
+    info->firewall = ConnNetInfo_Boolean(str);
 
     /* prohibit the use of local load balancer? */
     REG_VALUE(REG_CONN_LB_DISABLE, str, DEF_CONN_LB_DISABLE);
-    info->lb_disable = (*str  &&  (strcmp    (str, "1")    == 0  ||
-                                   strcasecmp(str, "true") == 0  ||
-                                   strcasecmp(str, "yes" ) == 0  ||
-                                   strcasecmp(str, "on"  ) == 0));
+    info->lb_disable = ConnNetInfo_Boolean(str);
 
-    /* user header (with optional '\r\n' added automagically) */
+    /* user header */
     REG_VALUE(REG_CONN_HTTP_USER_HEADER, str, DEF_CONN_HTTP_USER_HEADER);
-    if (*str) {
-        size_t len = strlen(str);
-        if (str[len - 1] != '\n'  &&  len < sizeof(str) - 2) {
-            str[len++] = '\r';
-            str[len++] = '\n';
-            str[len]   = '\0';
-        }
-        info->http_user_header = strdup(str);
-    } else
-        info->http_user_header = 0;
+    info->http_user_header = *str ? x_StrcatCRLF(NULL, str) : 0;
 
     /* default referer */
     ConnNetInfo_GetValue(0, REG_CONN_HTTP_REFERER, str, sizeof(str),
@@ -272,10 +328,9 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
 
     /* not adjusted yet... */
     info->http_proxy_adjusted = 0/*false*/;
+
     /* store the service name for which this structure has been created */
-    info->service = (service  &&  *service
-                     ? strcpy((char*) info + sizeof(*info), service)
-                     : 0);
+    info->service = service ? strcpy((char*)info + sizeof(*info), service) : 0;
 
     /* done */
     return info;
@@ -285,49 +340,95 @@ extern SConnNetInfo* ConnNetInfo_Create(const char* service)
 
 extern int/*bool*/ ConnNetInfo_AdjustForHttpProxy(SConnNetInfo* info)
 {
+    int/*bool*/ add_host;
+    char   port[10];
+    size_t hostlen;
+    size_t portlen;
+    size_t pathlen;
+    const char* s;
+    size_t len;
+
     if (!info)
-        return 0/*false*/;
+        return 0/*failed*/;
 
     if (!*info->http_proxy_host  ||  info->http_proxy_adjusted)
-        return 1/*true*/;
-
-    if (info->scheme != eURL_Unspec  &&  info->scheme != eURL_Http)
-        return 0/*false*/;
+        return 1/*succeeded*/;
 
-    if (strlen(info->host) + 16 + strlen(info->path) >= sizeof(info->path)) {
-        CORE_LOG_X(1, eLOG_Error,
-                   "[ConnNetInfo_AdjustForHttpProxy]  Adjusted path too long");
+    if (info->scheme != eURL_Unspec  &&  info->scheme != eURL_Http) {
+        /* Would require to use HTTP's CONNECT method -- not implemented */
+        CORE_LOGF_X(13, eLOG_Error,
+                    ("[ConnNetInfo_AdjustForHttpProxy] "
+                     " Cannot adjust for scheme \"%s\"",
+                     s_Scheme(info->scheme)));
         assert(0);
-        return 0/*false*/;
+        return 0/*failed*/;
     }
 
-    {{
-        char x_path[sizeof(info->host) + 16 + sizeof(info->path)];
-        int n = sprintf(x_path, "http://%s", info->host);
-        if (info->port)
-            n += sprintf(x_path + n, ":%hu", info->port);
+    hostlen = strlen(info->host);
+    portlen = info->port ? (size_t) sprintf(port, ":%hu", info->port) : 0; 
         if (*info->path != '/')
-            x_path[n++]  = '/';
-        strcpy(x_path + n, info->path);
-        assert(strlen(x_path) < sizeof(x_path));
-        strncpy0(info->path, x_path, sizeof(info->path) - 1);
-    }}
+        port[portlen++] = '/';
+    pathlen = strlen(info->path);
+
+    len = 7/*http://*/ + hostlen + portlen;
+
+    if (len + pathlen + 1 > sizeof(info->path)) {
+        CORE_LOGF_X(14, eLOG_Error,
+                    ("[ConnNetInfo_AdjustForHttpProxy] "
+                     "  Adjusted path too long (%lu vs max=%lu)",
+                     (unsigned long)(len + pathlen + 1),
+                     (unsigned long) sizeof(info->path)));
+        assert(0);
+        return 0/*failed*/;
+    }
+
+    add_host = 1/*true*/;
+    for (s = info->http_user_header;  s  &&  *s;  s = strchr(s, '\n')) {
+        if (s != info->http_user_header)
+            s++;
+        if (strncasecmp(s, kHostTag, sizeof(kHostTag) - 2) == 0) {
+            add_host = 0/*false*/;
+            break;
+        }
+    }
+
+    memmove(info->path + len,               info->path, pathlen + 1);
+    memcpy (info->path + len - portlen,     port,       portlen);
+    memcpy (info->path + 7,                 info->host, hostlen);
+    assert(info->path[len] == '/');
+    if (add_host) {
+        int failed;
+        info->path[len] = '\0';
+        assert(sizeof(kHostTag) == 7);
+        memcpy(info->path + 1, kHostTag, sizeof(kHostTag) - 1);
+        failed = !ConnNetInfo_OverrideUserHeader(info, info->path + 1);
+        info->path[len] = '/';
+        if (failed) {
+            /* restore path */
+            memmove(info->path, info->path + len, strlen(info->path + len)+1);
+            return 0/*failed*/;
+        }
+    }
+    memcpy (info->path, "http://", 7);
 
     assert(sizeof(info->host) >= sizeof(info->http_proxy_host));
     strncpy0(info->host, info->http_proxy_host, sizeof(info->host) - 1);
     info->port = info->http_proxy_port;
+    info->scheme = eURL_Http;
+
     info->http_proxy_adjusted = 1/*true*/;
-    return 1/*true*/;
+    return 1/*succeeded*/;
 }
 
 
 extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url)
 {
+    int/*bool*/ was_http_proxy_adjusted = info->http_proxy_adjusted;
     const char *s, *a;
     size_t len;
     char* p;
 
-    if (info->http_proxy_adjusted) {
+    if (was_http_proxy_adjusted) {
         /* undo proxy adjustment */
         SConnNetInfo* temp = ConnNetInfo_Create(info->service);
         if (!ConnNetInfo_ParseURL(temp, info->path)) {
@@ -343,19 +444,18 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url)
 
     /* "user:pass@host:port" first [any optional] */
     if ((s = strstr(url, "://")) != 0) {
-        const char* h = s + 3; /* host starts here */
+        const char* h = s + 3; /*host starts here*/
 
         len = (size_t)(s - url);
         if ((info->scheme = s_ParseScheme(url, len)) == eURL_Unspec)
             return 0/*failure*/;
 
-        /* find end of host spec */
-        if (!(s = strchr(h, '/')))
-            s = h + strlen(h);
-        len = (size_t)(s - h);
+        /* find the end of host spec */
+        len = strcspn(h, "/?#");
+        s = h + len;
 
         /* username:password */
-        if (!(a = memchr(h, '@', len))) {
+        if (!(a = (const char*) memchr(h, '@', len))) {
             info->user[0] = '\0';
             info->pass[0] = '\0';
         } else {
@@ -370,11 +470,12 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url)
                 memcpy(info->user, h, sizeof(info->user) - 1);
                 info->user[sizeof(info->user) - 1] = '\0';
             }
-            if (t  &&  ulen) { /* take pass only if user non-empty */
-                len = (size_t)(a - ++t);
-                if (len < sizeof(info->pass)) {
-                    memcpy(info->pass, t, len);
-                    info->pass[len] = '\0';
+            if (t  &&  ulen) {
+                /* take pass only if user non-empty */
+                ulen = (size_t)(a - ++t);
+                if (ulen < sizeof(info->pass)) {
+                    memcpy(info->pass, t, ulen);
+                    info->pass[ulen] = '\0';
                 } else {
                     memcpy(info->pass, t, sizeof(info->pass) - 1);
                     info->pass[sizeof(info->pass) - 1] = '\0';
@@ -405,21 +506,19 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url)
             memcpy(info->host, h, sizeof(info->host) - 1);
             info->host[sizeof(info->host) - 1] = '\0';
         }
+        if (len  &&  was_http_proxy_adjusted)
+            ConnNetInfo_DeleteUserHeader(info, kHostTag);
     } else
         s = url;
 
-    /* arguments */
-    if ((a = strchr(s, '?')) != 0) {
-        strncpy0(info->args, a + 1, sizeof(info->args) - 1);
+    a = s + strcspn(s, "?#");
         len = (size_t)(a - s);
-    } else
-        len = strlen(s);
 
-    /* path (NB: can be relative); "len" holds the path len */
+    /* path (NB: can be relative); "len" holds the path length */
     if (s != url  ||  *s == '/'  ||  !(p = strrchr(info->path, '/'))) {
         /* absolute path */
         p = info->path;
-        if (!*s) {
+        if (!len) {
             s = "/";   /* in case of an empty path we take the root '/' */
             len = 1;
         }
@@ -433,6 +532,49 @@ extern int/*bool*/ ConnNetInfo_ParseURL(SConnNetInfo* info, const char* url)
         info->path[sizeof(info->path) - 1] = '\0';
     }
 
+    /* arguments and fragment */
+    if (*a) {
+        if (*a == '#') {
+            len = 0/*unused*/;
+            s = a;
+        } else if (!(s = strchr(++a/*NB: *a=='?'*/, '#'))) {
+            len = strlen(a);
+            s = a + len;
+        } else
+            len = (size_t)(s - a);
+        /* "len" holds the length of new args("a", w/o the leading "?") */
+        assert(!*s  ||  *s == '#');
+        assert(*a != '?');
+
+        if (*s) {
+            /* if there is a new fragment, the entire args get overridden */
+            if (!s[1]) {
+                /* don't store the empty fragment # */
+                len = (size_t)(s - a);
+                if (len > sizeof(info->args) - 1)
+                    len = sizeof(info->args) - 1;
+            } else
+                len = sizeof(info->args) - 1;
+            strncpy0(info->args, a, len);
+        } else if (!(p = strchr(info->args, '#'))
+                   ||  len >= sizeof(info->args) - 1) {
+            /* there is no new fragment and: either there is no old fragment,
+             * or the old one will not fit -- in both cases, replace */
+            strncpy0(info->args, a, sizeof(info->args) - 1);
+        } else {
+            /* there is no new fragment, but there was an old one -- keep it */
+            size_t move = strlen(p);
+            if (move > sizeof(info->args) - 1 - len)
+                move = sizeof(info->args) - 1 - len;
+            memmove(info->args + len, p, move);
+            memcpy (info->args,       a, len);
+            info->args[len + move] = '\0';
+        }
+    } else if ((p = strchr(info->args, '#')) != 0) {
+        /* keep the old fragment, if any, but drop all args */
+        memmove(info->args, p, strlen(p) + 1);
+    }
+
     return 1/*success*/;
 }
 
@@ -442,11 +584,10 @@ extern int/*bool*/ ConnNetInfo_SetUserHeader(SConnNetInfo* info,
 {
     if (info->http_user_header)
         free((void*) info->http_user_header);
-    if (user_header && *user_header) {
-        info->http_user_header = strdup(user_header);
-        return info->http_user_header ? 1/*success*/ : 0/*failure*/;
-    } else
+    if (!user_header  ||  !*user_header)
         info->http_user_header = 0;
+    else if (!(info->http_user_header = x_StrcatCRLF(NULL, user_header)))
+        return 0/*failure*/;
     return 1/*success*/;
 }
 
@@ -454,21 +595,15 @@ extern int/*bool*/ ConnNetInfo_SetUserHeader(SConnNetInfo* info,
 extern int/*bool*/ ConnNetInfo_AppendUserHeader(SConnNetInfo* info,
                                                 const char*   user_header)
 {
-    size_t oldlen, newlen;
     char* new_header;
 
-    if (!info->http_user_header || !(oldlen = strlen(info->http_user_header)))
+    if (!info->http_user_header  ||  !*info->http_user_header)
         return ConnNetInfo_SetUserHeader(info, user_header);
 
-    if (!user_header || !(newlen = strlen(user_header)))
-        return 1/*success*/;
-
-    new_header = (char*)
-        realloc((void*) info->http_user_header, oldlen + newlen + 1);
-    if (!new_header)
+    new_header = (char*) info->http_user_header;
+    if (!(new_header = x_StrcatCRLF(new_header, user_header)))
         return 0/*failure*/;
 
-    memcpy(&new_header[oldlen], user_header, newlen + 1);
     info->http_user_header = new_header;
     return 1/*success*/;
 }
@@ -526,8 +661,9 @@ static int/*bool*/ s_ModifyUserHeader(SConnNetInfo* info,
         newlinelen = (size_t)
             (eol ? eol - newline + 1 : new_header + newhdrlen - newline);
         if (!eot || eot >= newline + newlinelen ||
-            !(newtaglen = (size_t)(eot - newline)))
+            !(newtaglen = (size_t)(eot - newline))) {
             continue;
+        }
 
         newtagval = newline + newtaglen + 1;
         while (newtagval < newline + newlinelen) {
@@ -568,6 +704,12 @@ static int/*bool*/ s_ModifyUserHeader(SConnNetInfo* info,
                 continue;
 
             if (op == eUserHeaderOp_Extend) {
+                if (linelen - taglen >= len
+                    &&  strncasecmp(line + linelen - len, newtagval, len) == 0
+                    &&  (linelen - taglen == len  ||
+                         isspace((unsigned char) line[linelen - len - 1]))) {
+                    len = 0;
+                }
                 l = linelen + len;
                 if (len && linelen > 1 && line[linelen - 2] == '\r')
                     --l;
@@ -598,7 +740,8 @@ static int/*bool*/ s_ModifyUserHeader(SConnNetInfo* info,
                     memcpy(line, newline, len);
                 linelen = l;
                 used = 1;
-            }
+            } else if (op == eUserHeaderOp_Extend)
+                used = 1;
         }
 
         if (op == eUserHeaderOp_Delete)
@@ -824,10 +967,6 @@ extern int/*bool*/ ConnNetInfo_SetupStandardArgs(SConnNetInfo* info,
 
     if (!info)
         return 0/*failed*/;
-    if (!service  ||  !*service) {
-        assert(0);
-        return 0/*failed*/;
-    }
     /* Dispatcher CGI args (may sacrifice some if they don't fit altogether) */
     if (!(arch = CORE_GetPlatform())  ||  !*arch)
         ConnNetInfo_DeleteArg(info, kPlatform);
@@ -844,6 +983,7 @@ extern int/*bool*/ ConnNetInfo_SetupStandardArgs(SConnNetInfo* info,
         ConnNetInfo_PreOverrideArg(info, kAddress, addr);
     if (addr != info->client_host)
         free((void*) addr);
+    if (service  &&  *service) {
     if (!ConnNetInfo_PreOverrideArg(info, kService, service)) {
         ConnNetInfo_DeleteArg(info, kPlatform);
         if (!ConnNetInfo_PreOverrideArg(info, kService, service)) {
@@ -852,6 +992,7 @@ extern int/*bool*/ ConnNetInfo_SetupStandardArgs(SConnNetInfo* info,
                 return 0/*failed*/;
         }
     }
+    }
     return 1/*succeeded*/;
 }
 
@@ -859,25 +1000,37 @@ extern int/*bool*/ ConnNetInfo_SetupStandardArgs(SConnNetInfo* info,
 extern SConnNetInfo* ConnNetInfo_Clone(const SConnNetInfo* info)
 {
     SConnNetInfo* x_info;
+    const char* service;
+
     if (!info)
         return 0;
 
-    x_info = (SConnNetInfo*) malloc(sizeof(SConnNetInfo) +
-                                    (info->service
-                                     ? strlen(info->service) + 1 : 0));
-    *x_info = *info;
+    service = info->service;
+    x_info = (SConnNetInfo*) malloc(sizeof(*x_info)
+                                    + (service ? strlen(service) + 1 : 0));
+    if (!x_info)
+        return 0;
+
+    memcpy(x_info, info, sizeof(*x_info));
+    x_info->http_user_header = 0;
+    x_info->http_referer = 0;
+
     if (info->timeout  &&  info->timeout != kDefaultTimeout) {
         x_info->tmo     = *info->timeout;
         x_info->timeout = &x_info->tmo;
     }
-    if (info->service) {
-        char* s = (char*) x_info + sizeof(*x_info);
-        strcpy(s, info->service);
-        x_info->service = s;
+    if (info->http_user_header
+        &&  !(x_info->http_user_header = strdup(info->http_user_header))) {
+        ConnNetInfo_Destroy(x_info);
+        return 0;
     }
-    x_info->http_user_header = 0;
-    ConnNetInfo_SetUserHeader(x_info, info->http_user_header);
-    x_info->http_referer = info->http_referer ? strdup(info->http_referer) : 0;
+    if (x_info->http_referer
+        &&  !(x_info->http_referer = strdup(info->http_referer))) {
+        ConnNetInfo_Destroy(x_info);
+        return 0;
+    }
+    x_info->service
+        = service ? strcpy((char*) x_info + sizeof(*x_info), service) : 0;
     return x_info;
 }
 
@@ -908,7 +1061,7 @@ static const char* s_PortStr(unsigned short port, char buf[])
         sprintf(buf, "%hu", port);
         return buf;
     }
-    return "<default>";
+    return "(default)";
 }
 
 static void s_SaveStringQuot(char* s, const char* name,
@@ -952,31 +1105,36 @@ static void s_SaveUserHeader(char* s, const char* name,
         memcpy(s, "NULL\n", 6);
 }
 
-extern void ConnNetInfo_Log(const SConnNetInfo* info, LOG lg)
+extern void ConnNetInfo_LogEx(const SConnNetInfo* info, ELOG_Level sev, LOG lg)
 {
     char   scheme[32];
     char   port[16];
     size_t uhlen;
+    size_t len;
     char*  s;
 
-    if (!lg)
+    if (!lg) {
+        if (sev == eLOG_Fatal)
+            abort();
         return;
+    }
 
     if (!info) {
-        LOG_Write(lg, NCBI_C_ERRCODE_X, 10, eLOG_Trace, 0, 0, 0,
+        LOG_Write(lg, NCBI_C_ERRCODE_X, 10, sev, 0, 0, 0,
                   "ConnNetInfo_Log: NULL info", 0, 0);
         return;
     }
 
     uhlen = info->http_user_header ? strlen(info->http_user_header) : 0;
        
-    if (!(s = (char*) malloc(sizeof(*info) + 1024/*slack for all labels*/ +
-                             (info->service ? strlen(info->service) : 0) +
-                             UTIL_PrintableStringSize(info->http_user_header,
-                                                      uhlen) +
-                             (info->http_referer
-                              ? strlen(info->http_referer) : 0)))) {
-        LOG_WRITE(lg, NCBI_C_ERRCODE_X, 11, eLOG_Error,
+    len = sizeof(*info) + 1024/*slack for all labels*/
+        + UTIL_PrintableStringSize(info->http_user_header, uhlen)
+        + (info->http_referer ? strlen(info->http_referer) : 0)
+        + (info->service ? strlen(info->service) : 0);
+
+    if (!(s = (char*) malloc(len))) {
+        LOG_WRITE(lg, NCBI_C_ERRCODE_X, 11,
+                  sev == eLOG_Fatal ? eLOG_Fatal : eLOG_Error,
                   "ConnNetInfo_Log: Cannot allocate temporary buffer");
         return;
     }
@@ -987,10 +1145,13 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, LOG lg)
     if (*info->client_host)
         s_SaveString(s, "client_host",     info->client_host);
     else
-        s_SaveKeyval(s, "client_host",     "<default>");
+        s_SaveKeyval(s, "client_host",     "(default)");
     s_SaveString    (s, "scheme",          s_SchemeStr(info->scheme, scheme));
     s_SaveString    (s, "user",            info->user);
-    s_SaveString    (s, "pass",            info->pass);
+    if (*info->pass)
+        s_SaveKeyval(s, "pass",           *info->user ? "(set)" : "(ignored)");
+    else
+        s_SaveString(s, "pass",            info->pass);
     s_SaveString    (s, "host",            info->host);
     s_SaveKeyval    (s, "port",            s_PortStr(info->port, port));
     s_SaveString    (s, "path",            info->path);
@@ -1002,7 +1163,7 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, LOG lg)
                                               ? "GET"
                                               : (info->req_method
                                                  == eReqMethod_Post
-                                                 ? "POST" : "<unknown>"))));
+                                                 ? "POST" : "(unknown)"))));
     if (info->timeout) {
         s_SaveULong (s, "timeout(sec)",    info->timeout->sec);
         s_SaveULong (s, "timeout(usec)",   info->timeout->usec);
@@ -1012,6 +1173,11 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, LOG lg)
     s_SaveString    (s, "http_proxy_host", info->http_proxy_host);
     s_SaveKeyval    (s, "http_proxy_port", s_PortStr(info->http_proxy_port,
                                                      port));
+    s_SaveString    (s, "http_proxy_user", info->http_proxy_user);
+    if (*info->http_proxy_pass)
+        s_SaveKeyval(s, "http_proxy_pass", "(set)");
+    else
+        s_SaveString(s, "http_proxy_pass", info->http_proxy_pass);
     s_SaveString    (s, "proxy_host",      info->proxy_host);
     s_SaveKeyval    (s, "debug_printout", (info->debug_printout
                                            == eDebugPrintout_None
@@ -1021,20 +1187,56 @@ extern void ConnNetInfo_Log(const SConnNetInfo* info, LOG lg)
                                               ? "SOME"
                                               : (info->debug_printout
                                                  == eDebugPrintout_Data
-                                                 ? "DATA" : "<unknown>"))));
+                                                 ? "DATA" : "(unknown)"))));
     s_SaveBool      (s, "stateless",       info->stateless);
     s_SaveBool      (s, "firewall",        info->firewall);
     s_SaveBool      (s, "lb_disable",      info->lb_disable);
     s_SaveUserHeader(s, "http_user_header",info->http_user_header, uhlen);
     s_SaveString    (s, "http_referer",    info->http_referer);
-    s_SaveBool      (s, "proxy_adjusted",  info->http_proxy_adjusted);
+    s_SaveBool      (s, "[http_proxy_adj]",info->http_proxy_adjusted);
     strcat(s, "#################### [END] SConnNetInfo\n");
 
-    LOG_Write(lg, NCBI_C_ERRCODE_X, 12, eLOG_Trace, 0, 0, 0, s, 0, 0);
+    assert(strlen(s) < len);
+    LOG_Write(lg, NCBI_C_ERRCODE_X, 12, sev, 0, 0, 0, s, 0, 0);
     free(s);
 }
 
 
+extern char* ConnNetInfo_URL(const SConnNetInfo* info)
+{
+    const char* scheme;
+    size_t      len;
+    char*       url;
+
+    if (!info  ||  info->scheme == eURL_Unspec
+        ||  !(scheme = s_Scheme(info->scheme))) {
+        return 0;
+    }
+
+    len = strlen(scheme) + 3/*"://"*/ + strlen(info->host)
+        + (*info->user ? strlen(info->user) + strlen(info->pass) + 2 : 0)
+        + (info->port ? 6/*:port*/ : 0)
+        + (info->http_proxy_adjusted ? 2 : 0)
+        + strlen(info->path)
+        + (*info->args ? strlen(info->args) + 3 : 2);
+    url = (char*) malloc(len);
+
+    if (url) {
+        len = (size_t) sprintf(url, "%s://%s", scheme,
+                               *info->user ? info->user : info->host);
+        if (*info->user)
+            len += sprintf(url + len, ":%s@%s", info->pass, info->host);
+        if (info->port)
+            len += sprintf(url + len, ":%hu", info->port);
+        sprintf(url + len, "%s%s%s%s%s", info->http_proxy_adjusted
+                ? "(" : *info->path != '/' ? "/" : "", info->path,
+                &"?"[!*info->args  ||  *info->args == '#'], info->args,
+                ")" + !info->http_proxy_adjusted);
+    }
+    return url;
+}
+
+
 extern void ConnNetInfo_Destroy(SConnNetInfo* info)
 {
     if (!info)
@@ -1061,7 +1263,7 @@ extern EIO_Status URL_ConnectEx
  const char*     args,
  EReqMethod      req_method,
  size_t          content_length,
- const STimeout* c_timeout,
+ const STimeout* o_timeout,
  const STimeout* rw_timeout,
  const char*     user_hdr,
  int/*bool*/     encode_args,
@@ -1070,18 +1272,19 @@ extern EIO_Status URL_ConnectEx
 {
     static const char X_REQ_Q[] = "?";
     static const char X_REQ_E[] = " HTTP/1.0\r\n";
-    static const char X_HOST[]  = "Host: ";
 
-    EIO_Status  st;
     BUF         buf;
-    char*       header;
-    size_t      hdrsize;
-    char        strbuf[80];
-    const char* x_args = 0;
+    char*       hdr;
+    const char* temp;
+    EIO_Status  status;
+    size_t      hdr_len;
+    char        hdr_buf[80];
+    int         add_hdr = 1;
+    size_t      args_len = args  &&  *args ? strcspn(args, "#") : 0;
     size_t      user_hdr_len = user_hdr  &&  *user_hdr ? strlen(user_hdr) : 0;
-    const char* x_req_r; /* "POST "/"GET " */
+    const char* x_req_method; /* "POST "/"GET " */
 
-    /* check the args */
+    /* sanity check first */
     if (!sock  ||  !host  ||  !*host  ||
         (user_hdr  &&  *user_hdr  &&  user_hdr[user_hdr_len - 1] != '\n')) {
         CORE_LOG_X(2, eLOG_Error, "[URL_Connect]  Bad arguments");
@@ -1099,10 +1302,10 @@ extern EIO_Status URL_ConnectEx
     }
     switch (req_method) {
     case eReqMethod_Post:
-        x_req_r = "POST ";
+        x_req_method = "POST ";
         break;
     case eReqMethod_Get:
-        x_req_r = "GET ";
+        x_req_method = "GET ";
         break;
     default:
         CORE_LOGF_X(4, eLOG_Error,
@@ -1112,98 +1315,117 @@ extern EIO_Status URL_ConnectEx
         return eIO_InvalidArg;
     }
 
+    for (temp = user_hdr;  temp  &&  *temp;  temp = strchr(temp, '\n')) {
+        if (temp != user_hdr)
+            temp++;
+        if (strncasecmp(temp, kHostTag, sizeof(kHostTag) - 2) == 0) {
+            add_hdr = 0;
+            break;
+        }
+    }
+
     /* URL-encode "args", if any specified */
-    if (args  &&  *args) {
-        size_t src_size = strlen(args);
-        if ( encode_args ) {
-            size_t dst_size = 3 * src_size;
-            size_t src_read, dst_written;
-            char* xx_args = (char*) malloc(dst_size + 1);
-            if (!xx_args) {
+    if (args_len) {
+        if (encode_args) {
+            size_t rd_len, wr_len;
+            size_t size = 3 * args_len;
+            char* x_args = (char*) malloc(size);
+            if (!x_args) {
                 CORE_LOGF_ERRNO_X(8, eLOG_Error, errno,
                                   ("[URL_Connect]  Out of memory (%lu)",
-                                   (unsigned long)(dst_size + 1)));
+                                   (unsigned long) size));
                 return eIO_Unknown;
             }
-            URL_Encode(args,    src_size, &src_read,
-                       xx_args, dst_size, &dst_written);
-            xx_args[dst_written] = '\0';
-            assert(src_read == src_size);
-            x_args = xx_args;
+            URL_Encode(args, args_len, &rd_len, x_args, size, &wr_len);
+            assert(args_len == rd_len);
+            args_len = wr_len;
+            temp = x_args;
         } else
-            x_args = args;
-    }
+            temp = args;
+    } else
+        temp = 0;
 
-    buf = 0;
-    errno = 0;
     if (!port) {
-        *strbuf = '\0';
+        hdr_len = 0;
         port = flags & fSOCK_Secure ? 443 : 80;
     } else
-        sprintf(strbuf, ":%hu", port);
+        hdr_len = (size_t)(add_hdr ? sprintf(hdr_buf, ":%hu", port) : 0);
 
+    buf = 0;
+    errno = 0;
     /* compose HTTP header */
     if (/* {POST|GET} <path>?<args> HTTP/1.0\r\n */
-        !BUF_Write(&buf, x_req_r, strlen(x_req_r))            ||
+        !BUF_Write(&buf, x_req_method,   strlen(x_req_method))  ||
         !BUF_Write(&buf, path,    strlen(path))               ||
-        (x_args  &&  *x_args
+        (args_len
          &&  (!BUF_Write(&buf, X_REQ_Q, sizeof(X_REQ_Q) - 1)  ||
-              !BUF_Write(&buf, x_args,  strlen(x_args))))     ||
-        !BUF_Write(&buf,       X_REQ_E, sizeof(X_REQ_E) - 1)  ||
+              !BUF_Write(&buf, temp,     args_len)))            ||
+        !BUF_Write      (&buf, X_REQ_E,  sizeof(X_REQ_E) - 1)   ||
 
+        (add_hdr
         /* Host: host[:port]\r\n */
-        !BUF_Write(&buf, X_HOST, sizeof(X_HOST) - 1)          ||
+         &&  (!BUF_Write(&buf, kHostTag, sizeof(kHostTag) - 1)  ||
         !BUF_Write(&buf, host,   strlen(host))                ||
-        !BUF_Write(&buf, strbuf, strlen(strbuf))              ||
-        !BUF_Write(&buf, "\r\n", 2)                           ||
+              !BUF_Write(&buf, hdr_buf,  hdr_len)               ||
+              !BUF_Write(&buf, "\r\n",   2)))                   ||
+
+        /* Content-Length: <content_length>\r\n */
+        (req_method != eReqMethod_Get
+         &&  ((add_hdr =
+               sprintf(hdr_buf, "Content-Length: %lu\r\n",
+                       (unsigned long) content_length)) < 0     ||
+              !BUF_Write(&buf, hdr_buf,  (size_t) add_hdr)))    ||
 
         /* <user_header> */
-        (user_hdr  &&  *user_hdr
+        (user_hdr_len
          &&  !BUF_Write(&buf, user_hdr, user_hdr_len))        ||
 
-        /* Content-Length: <content_length>\r\n\r\n */
-        (req_method != eReqMethod_Get
-         &&  (sprintf(strbuf, "Content-Length: %lu\r\n",
-                      (unsigned long) content_length) <= 0    ||
-              !BUF_Write(&buf, strbuf, strlen(strbuf))))      ||
-
+        /* header separator */
         !BUF_Write(&buf, "\r\n", 2)) {
         int x_errno = errno;
         CORE_LOGF_ERRNO_X(5, eLOG_Error, x_errno,
                           ("[URL_Connect]  Error building HTTP header for"
                            " %s:%hu", host, port));
         BUF_Destroy(buf);
-        if (x_args  &&  x_args != args)
-            free((void*) x_args);
+        if (temp  &&  temp != args)
+            free((void*) temp);
         return eIO_Unknown;
     }
-    if (x_args  &&  x_args != args)
-        free((void*) x_args);
+    if (temp  &&  temp != args)
+        free((void*) temp);
 
-    if (!(header = (char*) malloc(hdrsize = BUF_Size(buf)))
-        ||  BUF_Read(buf, header, hdrsize) != hdrsize) {
+    if (!(hdr = (char*) malloc(hdr_len = BUF_Size(buf)))
+        ||  BUF_Read(buf, hdr, hdr_len) != hdr_len) {
         int x_errno = errno;
         CORE_LOGF_ERRNO_X(6, eLOG_Error, x_errno,
                           ("[URL_Connect]  Error storing HTTP header for"
                            " %s:%hu", host, port));
-        if (header)
-            free(header);
+        if (hdr)
+            free(hdr);
         BUF_Destroy(buf);
         return eIO_Unknown;
     }
     BUF_Destroy(buf);
 
     /* connect to HTTPD */
-    st = SOCK_CreateEx(host, port, c_timeout, sock, header, hdrsize, flags);
-    free(header);
-    if (st != eIO_Success) {
+    status = SOCK_CreateEx(host, port, o_timeout, sock, hdr, hdr_len, flags);
+    free(hdr);
+
+    if (status != eIO_Success) {
+        char temp[80];
         assert(!*sock);
+        if (status == eIO_Timeout  &&  o_timeout) {
+            sprintf(temp, "[%u.%06u]",
+                    (unsigned int)(o_timeout->sec + o_timeout->usec/1000000),
+                    (unsigned int)                 (o_timeout->usec%1000000));
+        } else
+            *temp = '\0';
         CORE_LOGF_X(7, eLOG_Error,
-                    ("[URL_Connect]  Socket connect to %s:%hu failed: %s",
-                     host, port, IO_StatusStr(st)));
+                    ("[URL_Connect]  Socket connect to %s:%hu failed: %s%s",
+                     host, port, IO_StatusStr(status), temp));
     } else
         verify(SOCK_SetTimeout(*sock, eIO_ReadWrite, rw_timeout)==eIO_Success);
-    return st;
+    return status;
 }
 
 
@@ -1508,6 +1730,8 @@ extern int/*bool*/ URL_DecodeEx
     *dst_written = 0;
     if (!src_size  ||  !dst_size)
         return 1/*true*/;
+    if (!src  ||  !dst)
+        return 0/*false*/;
 
     for ( ;  *src_read != src_size  &&  *dst_written != dst_size;
           (*src_read)++, (*dst_written)++, src++, dst++) {
@@ -1573,7 +1797,7 @@ extern void URL_Encode
 
     *src_read    = 0;
     *dst_written = 0;
-    if (!src_size  ||  !dst_size)
+    if (!src_size  ||  !dst_size  ||  !dst  ||  !src)
         return;
 
     for ( ;  *src_read != src_size  &&  *dst_written != dst_size;
diff --git a/connect/ncbi_connutil.h b/connect/ncbi_connutil.h
index a269fdb..e599aa0 100644
--- a/connect/ncbi_connutil.h
+++ b/connect/ncbi_connutil.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_CONNUTIL__H
 #define CONNECT___NCBI_CONNUTIL__H
 
-/* $Id: ncbi_connutil.h,v 6.68 2009/06/23 16:04:40 kazimird Exp $
+/* $Id: ncbi_connutil.h,v 6.72 2010/06/08 15:14:44 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -31,6 +31,8 @@
  * File Description:
  *   Auxiliary API to:
  *    1.Retrieve connection related info from the registry:
+ *       ConnNetInfo_GetValue
+ *       ConnNetInfo_Boolean
  *       SConnNetInfo
  *       ConnNetInfo_Create()
  *       ConnNetInfo_AdjustForHttpProxy()
@@ -118,13 +120,18 @@ typedef enum {
  * ATTENTION:  Do NOT fill out this structure (SConnNetInfo) "from scratch"!
  *             Instead, use ConnNetInfo_Create() described below to create
  *             it, and then fix (hard-code) some fields, if really necessary.
- * NOTE:       "scheme", "user", and "pass" are reserved (unused) fields.
+ * NOTE1:      Not every field may be fully utilized throughout the library.
+ * NOTE2:      HTTP passwords can be either clear text or Base64 encoded values
+ *             enclosed in square brackets [] (which are not Base-64 charset).
+ *             For encoding / decoding, one can use command line open ssl:
+ *             echo "password|base64value" | openssl enc {-e|-d} -base64
+ *             or an online tool (search the Web for "base64 online").
  */
 typedef struct {
     char           client_host[256]; /* effective client hostname ('\0'=def) */
     EURLScheme     scheme;           /* only pre-defined types (limited)     */
-    char           user[128];        /* username (if specified)              */
-    char           pass[128];        /* password (if any, clear text!!!)     */
+    char           user[64];         /* username (if specified)              */
+    char           pass[64];         /* password (if any)                    */
     char           host[256];        /* host to connect to                   */
     unsigned short port;             /* port to connect to, host byte order  */
     char           path[1024];       /* service: path(e.g. to  a CGI script) */
@@ -134,6 +141,8 @@ typedef struct {
     unsigned short max_try;          /* max. # of attempts to connect (>= 1) */
     char           http_proxy_host[256]; /* hostname of HTTP proxy server    */
     unsigned short http_proxy_port;      /* port #   of HTTP proxy server    */
+    char           http_proxy_user[64];  /* http proxy username              */
+    char           http_proxy_pass[64];  /* http proxy password              */
     char           proxy_host[256];  /* CERN-like (non-transp) f/w proxy srv */
     EDebugPrintout debug_printout;   /* printout some debug info             */
     int/*bool*/    stateless;        /* to connect in HTTP-like fashion only */
@@ -189,6 +198,12 @@ typedef struct {
 #define REG_CONN_HTTP_PROXY_PORT  "HTTP_PROXY_PORT"
 #define DEF_CONN_HTTP_PROXY_PORT  ""
 
+#define REG_CONN_HTTP_PROXY_USER  "HTTP_PROXY_USER"
+#define DEF_CONN_HTTP_PROXY_USER  ""
+
+#define REG_CONN_HTTP_PROXY_PASS  "HTTP_PROXY_PASS"
+#define DEF_CONN_HTTP_PROXY_PASS  ""
+
 #define REG_CONN_PROXY_HOST       "PROXY_HOST"
 #define DEF_CONN_PROXY_HOST       ""
 
@@ -230,6 +245,14 @@ extern NCBI_XCONNECT_EXPORT const char* ConnNetInfo_GetValue
  );
 
 
+/* Return non-zero if "str" (when non-NULL, non-empty) represents a
+ * true boolean value;  return 0 otherwise.
+ */
+extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_Boolean
+(const char* str
+ );
+
+
 /* This function to fill out the "*info" structure using
  * registry entries named (see above) in macros REG_CONN_<NAME>:
  *
@@ -348,7 +371,7 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_SetUserHeader
 
 
 /* Append user header (same as ConnNetInfo_SetUserHeader() if no previous
- * header was set, or if "header" == NULL).
+ * header was set); do nothing if the provided "header" is NULL or empty.
  * Return non-zero if successful, otherwise return 0 to indicate an error.
  */
 extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_AppendUserHeader
@@ -360,7 +383,7 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_AppendUserHeader
 /* Override user header.
  * Tags replaced (case-insensitively), and tags with empty values effectively
  * delete existing tags from the old user header, e.g. "My-Tag:\r\n" deletes
- * any appearence (if any) of "My-Tag: [<value>]" from the user header.
+ * a first appearence (if any) of "My-Tag: [<value>]" from the user header.
  * Unmatched tags with non-empty values are simply added to the existing user
  * header (as with "Append" above).
  * Return non-zero if successful, otherwise return 0 to indicate an error.
@@ -372,11 +395,13 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_OverrideUserHeader
 
 
 /* Extend user header.
- * Existings tags matching (case-insensitively) those from "header" are
- * appended with new value (separated by a comma and a space) if the added
- * value is non-empty, otherwise, the tags are left untouched. All new
- * unmatched tags from "header" with non-empty values get added to the end
- * of the user header.
+ * Existing tags matching (case-insensitively) first appearances of those
+ * from "header" get appended with new value (separated by a space) if the
+ * added value is non-empty, otherwise, the tags are left untouched.  If new
+ * tag value matches (case-insensitively) last tag value already in the
+ * header, the new value does not get added (to avoid repetitive duplicates).
+ * All new unmatched tags from "header" with non-empty values get added
+ * to the end of the user header (as with "Append" above).
  * Return non-zero if successful, otherwise return 0 to indicate an error.
  */
 extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_ExtendUserHeader
@@ -394,7 +419,10 @@ extern NCBI_XCONNECT_EXPORT void ConnNetInfo_DeleteUserHeader
  );
 
 
-/* Parse URL into "*info", using (service-specific, if any) defaults.
+/* Parse URL into "*info", using defaults provided via "*info".
+ * In case of a relative URL, only those URL elements provided in it,
+ * will get replaced in the resultant "*info".
+ * Return non-zero if successful, otherwise return 0 to indicate an error.
  */
 extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_ParseURL
 (SConnNetInfo* info,
@@ -411,13 +439,26 @@ extern NCBI_XCONNECT_EXPORT int/*bool*/ ConnNetInfo_SetupStandardArgs
  );
 
 
-/* Log the contents of "*info".
+/* Log the contents of "*info" into log "log" with severity "sev".
  */
-extern NCBI_XCONNECT_EXPORT void ConnNetInfo_Log
+extern NCBI_XCONNECT_EXPORT void ConnNetInfo_LogEx
 (const SConnNetInfo* info,
+ ELOG_Level          sev,
  LOG                 log
  );
 
+#define ConnNetInfo_Log(i, l) ConnNetInfo_LogEx((i), eLOG_Trace, (l))
+
+
+/* Reconstruct text URL out of SConnNetInfo components
+ * (username:password excluded for security reasons).
+ * Returned string must be free()'d when no longer necessary.
+ * Return NULL on error.
+ */
+extern NCBI_XCONNECT_EXPORT char* ConnNetInfo_URL
+(const SConnNetInfo* info
+ );
+
 
 /* Destroy and deallocate "info" (if not NULL).
  */
diff --git a/connect/ncbi_file_connector.c b/connect/ncbi_file_connector.c
index f9efc00..858721d 100644
--- a/connect/ncbi_file_connector.c
+++ b/connect/ncbi_file_connector.c
@@ -1,4 +1,4 @@
-/*  $Id: ncbi_file_connector.c,v 6.14 2006/01/11 20:21:22 lavr Exp $
+/* $Id: ncbi_file_connector.c,v 6.15 2010/02/01 13:54:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -47,8 +47,8 @@
 /* All internal data necessary to perform the (re)connect and i/o
  */
 typedef struct {
-    char*         inp_file_name;
-    char*         out_file_name;
+    const char*   inp_file_name;
+    const char*   out_file_name;
     FILE*         finp;
     FILE*         fout;
     SFileConnAttr attr;
@@ -87,11 +87,6 @@ extern "C" {
     static void        s_Setup      (SMetaConnector* meta,
                                      CONNECTOR       connector);
     static void        s_Destroy    (CONNECTOR       connector);
-#  ifdef IMPLEMENTED__CONN_WaitAsync
-    static EIO_Status s_VT_WaitAsync(void*                   connector,
-                                     FConnectorAsyncHandler  func,
-                                     SConnectorAsyncHandler* data);
-#  endif
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
@@ -111,29 +106,32 @@ static EIO_Status s_VT_Open
  const STimeout* timeout)
 {
     SFileConnector* xxx = (SFileConnector*) connector->handle;
-    const char*     mode = 0;
+    const char*     mode;
 
-    /* if connected already, and trying to reconnect */
-    if (xxx->finp  &&  xxx->fout)
-        return eIO_Success;
+    assert(!xxx->finp  &&  !xxx->fout);
 
     /* open file for output */
     switch ( xxx->attr.w_mode ) {
     case eFCM_Truncate:
-        mode = "wb";  break;
-    case eFCM_Seek: /* mode = "rb+"; break; */
+        mode = "wb";
+        break;
+    case eFCM_Seek:
+        /* mode = "rb+"; break; */
     case eFCM_Append:
-        mode = "ab";  break;
+        mode = "ab";
+        break;
+    default:
+        return eIO_InvalidArg;
     }
 
-    if (!xxx->out_file_name  ||
-        !(xxx->fout = fopen(xxx->out_file_name, mode))) {
+    if (!xxx->out_file_name
+        ||  !(xxx->fout = fopen(xxx->out_file_name, mode))) {
         return eIO_Unknown;
     }
 
     /* open file for input */
-    if (!xxx->inp_file_name  ||
-        !(xxx->finp = fopen(xxx->inp_file_name, "rb"))) {
+    if (!xxx->inp_file_name
+        ||  !(xxx->finp = fopen(xxx->inp_file_name, "rb"))) {
         fclose(xxx->fout);
         xxx->fout = 0;
         return eIO_Unknown;
@@ -147,74 +145,67 @@ static EIO_Status s_VT_Open
 
 
 /*ARGSUSED*/
-static EIO_Status s_VT_Write
+static EIO_Status s_VT_Wait
 (CONNECTOR       connector,
- const void*     buf,
- size_t          size,
- size_t*         n_written,
+ EIO_Event       event,
  const STimeout* timeout)
 {
-    SFileConnector* xxx = (SFileConnector*) connector->handle;
-
-    if ( !size ) {
-        *n_written = 0;
-        return eIO_Success;
-    }
-
-    *n_written = fwrite(buf, 1, size, xxx->fout);
-    if ( !*n_written ) {
-        return eIO_Unknown;
-    }
-
     return eIO_Success;
 }
 
 
 /*ARGSUSED*/
-static EIO_Status s_VT_Read
+static EIO_Status s_VT_Write
 (CONNECTOR       connector,
- void*           buf,
+ const void*     buf,
  size_t          size,
- size_t*         n_read,
+ size_t*         n_written,
  const STimeout* timeout)
 {
     SFileConnector* xxx = (SFileConnector*) connector->handle;
 
-    if ( !size ) {
-        *n_read = 0;
+    assert(xxx->fout  &&  *n_written == 0);
+
+    if (!size)
         return eIO_Success;
-    }
 
-    *n_read = fread(buf, 1, size, xxx->finp);
-    if ( !*n_read ) {
-        return feof(xxx->finp) ? eIO_Closed : eIO_Unknown;
-    }
+    *n_written = fwrite(buf, 1, size, xxx->fout);
 
-    return eIO_Success;
+    return *n_written ? eIO_Success : eIO_Unknown;
 }
 
 
 /*ARGSUSED*/
-static EIO_Status s_VT_Wait
+static EIO_Status s_VT_Flush
 (CONNECTOR       connector,
- EIO_Event       event,
  const STimeout* timeout)
 {
-    return eIO_Success;
+    SFileConnector* xxx = (SFileConnector*) connector->handle;
+
+    assert(xxx->fout);
+
+    return fflush(xxx->fout) != 0 ? eIO_Unknown : eIO_Success;
 }
 
 
 /*ARGSUSED*/
-static EIO_Status s_VT_Flush
+static EIO_Status s_VT_Read
 (CONNECTOR       connector,
+ void*           buf,
+ size_t          size,
+ size_t*         n_read,
  const STimeout* timeout)
 {
     SFileConnector* xxx = (SFileConnector*) connector->handle;
 
-    if (fflush(xxx->fout) != 0)
-        return eIO_Unknown;
+    assert(xxx->finp  &&  *n_read == 0);
 
+    if (!size)
     return eIO_Success;
+
+    *n_read = fread(buf, 1, size, xxx->finp);
+
+    return *n_read ? eIO_Success : feof(xxx->finp) ? eIO_Closed : eIO_Unknown;
 }
 
 
@@ -223,12 +214,20 @@ static EIO_Status s_VT_Status
  EIO_Event dir)
 {
     SFileConnector* xxx = (SFileConnector*) connector->handle;
-    assert(dir == eIO_Read || dir == eIO_Write);
-    if (dir == eIO_Read)
-        return feof(xxx->finp) ? eIO_Closed :
-        (ferror(xxx->finp) ? eIO_Unknown : eIO_Success);
-    else
+
+    switch (dir) {
+    case eIO_Read:
+        assert(xxx->finp);
+        return feof(xxx->finp) ? eIO_Closed
+            : ferror(xxx->finp) ? eIO_Unknown : eIO_Success;
+    case eIO_Write:
+        assert(xxx->fout);
         return ferror(xxx->fout) ?  eIO_Unknown : eIO_Success;
+    default:
+        assert(0);
+        break;
+    }
+    return eIO_InvalidArg;
 }
 
 
@@ -238,10 +237,15 @@ static EIO_Status s_VT_Close
  const STimeout* timeout)
 {
     SFileConnector* xxx = (SFileConnector*) connector->handle;
+    EIO_Status status;
 
-    fclose(xxx->finp);
+    assert(xxx->finp  &&  xxx->fout);
+
+    if (fclose(xxx->finp) != 0)
+        status = eIO_Unknown;
     xxx->finp = 0;
-    fclose(xxx->fout);
+    if (fclose(xxx->fout) != 0)
+        status = eIO_Unknown;
     xxx->fout = 0;
     return eIO_Success;
 }
@@ -260,10 +264,7 @@ static void s_Setup
     CONN_SET_METHOD(meta, read,       s_VT_Read,      connector);
     CONN_SET_METHOD(meta, status,     s_VT_Status,    connector);
     CONN_SET_METHOD(meta, close,      s_VT_Close,     connector);
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
-#endif
-    meta->default_timeout = 0/*infinite*/;
+    meta->default_timeout = kInfiniteTimeout;
 }
 
 
@@ -271,11 +272,17 @@ static void s_Destroy
 (CONNECTOR connector)
 {
     SFileConnector* xxx = (SFileConnector*) connector->handle;
+    connector->handle = 0;
     
-    free(xxx->inp_file_name);
-    free(xxx->out_file_name);
+    if (xxx->inp_file_name) {
+        free((void*) xxx->inp_file_name);
+        xxx->inp_file_name = 0;
+    }
+    if (xxx->out_file_name) {
+        free((void*) xxx->out_file_name);
+        xxx->out_file_name = 0;
+    }
     free(xxx);
-    connector->handle = 0;
     free(connector);
 }
 
@@ -308,7 +315,7 @@ extern CONNECTOR FILE_CreateConnectorEx
     xxx->finp          = 0;
     xxx->fout          = 0;
 
-    memcpy(&xxx->attr, attr, sizeof(SFileConnAttr));
+    memcpy(&xxx->attr, attr, sizeof(xxx->attr));
 
     /* initialize connector data */
     ccc->handle  = xxx;
@@ -319,53 +326,3 @@ extern CONNECTOR FILE_CreateConnectorEx
 
     return ccc;
 }
-
-
-/*
- * --------------------------------------------------------------------------
- * $Log: ncbi_file_connector.c,v $
- * Revision 6.14  2006/01/11 20:21:22  lavr
- * Uniform creation/fill-up of connector structures
- *
- * Revision 6.13  2005/04/20 18:15:59  lavr
- * +<assert.h>
- *
- * Revision 6.12  2003/05/31 05:14:56  lavr
- * Add ARGSUSED where args are meant to be unused
- *
- * Revision 6.11  2003/05/14 03:55:53  lavr
- * Slight VT table reformatting
- *
- * Revision 6.10  2002/10/28 15:46:20  lavr
- * Use "ncbi_ansi_ext.h" privately
- *
- * Revision 6.9  2002/10/22 15:11:24  lavr
- * Zero connector's handle to crash if revisited
- *
- * Revision 6.8  2002/09/24 15:06:00  lavr
- * Log moved to end
- *
- * Revision 6.7  2002/04/26 16:32:36  lavr
- * Added setting of default timeout in meta-connector's setup routine
- *
- * Revision 6.6  2001/12/04 15:56:35  lavr
- * Use strdup() instead of explicit strcpy(malloc(...), ...)
- *
- * Revision 6.5  2001/01/25 17:04:43  lavr
- * Reversed:: DESTROY method calls free() to delete connector structure
- *
- * Revision 6.4  2001/01/23 23:11:20  lavr
- * Status virtual method implemented
- *
- * Revision 6.3  2001/01/11 16:38:16  lavr
- * free(connector) removed from s_Destroy function
- * (now always called from outside, in METACONN_Remove)
- *
- * Revision 6.2  2000/12/29 17:55:53  lavr
- * Adapted for use of new connector structure.
- *
- * Revision 6.1  2000/04/12 15:18:13  vakatov
- * Initial revision
- *
- * ==========================================================================
- */
diff --git a/connect/ncbi_ftp_connector.c b/connect/ncbi_ftp_connector.c
index d4f1bc3..06f9280 100644
--- a/connect/ncbi_ftp_connector.c
+++ b/connect/ncbi_ftp_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_ftp_connector.c,v 1.25 2009/05/11 03:14:30 kazimird Exp $
+/* $Id: ncbi_ftp_connector.c,v 1.44 2010/06/04 14:59:37 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -27,8 +27,10 @@
  *
  * File Description:
  *   FTP CONNECTOR
- *   See also:  RFCs 959 (STD 9), 1634 (FYI 24),
- *   and IETF 9-2002 "Extensions to FTP".
+ *   See also:  RFCs 959 (STD 9), 1123 (4.1), 1635 (FYI 24), 2428,
+ *   3659 ("Extensions to FTP"), 5797 (FTP Command Registry).
+ *
+ *   Minimum FTP implementation: RFC 1123 (4.1.2.13)
  *
  *   See <connect/ncbi_connector.h> for the detailed specification of
  *   the connector's methods and structures.
@@ -36,13 +38,17 @@
  */
 
 #include "ncbi_ansi_ext.h"
-#include "ncbi_assert.h"
 #include "ncbi_priv.h"
 #include <connect/ncbi_ftp_connector.h>
 #include <connect/ncbi_socket.h>
 #include <ctype.h>
-#include <stdio.h>
 #include <stdlib.h>
+#include <time.h>
+
+#if !defined(NCBI_OS_MSWIN)  &&  !defined(__CYGWIN__)
+#  define _timezone timezone
+#  define _daylight daylight
+#endif /*!NCBI_OS_MSWIN && !__CYGWIN__*/
 
 #define NCBI_USE_ERRCODE_X   Connect_FTP
 
@@ -52,88 +58,134 @@
  ***********************************************************************/
 
 typedef enum {
-    fFtpFeature_MDTM = 1,
-    fFtpFeature_SIZE = 2
+    fFtpFeature_NOOP = 0x01, /* all implementations MUST support */
+    fFtpFeature_SYST = 0x02,
+    fFtpFeature_SITE = 0x04,
+    fFtpFeature_FEAT = 0x08,
+    fFtpFeature_MDTM = 0x10,
+    fFtpFeature_REST = 0x20,
+    fFtpFeature_SIZE = 0x40,
+    fFtpFeature_EPSV = 0x80,
+    fFtpFeature_APSV = 0x100 /* EPSV ALL -- a la "APSV" from RFC 1579 */
 } EFTP_Feature;
-typedef unsigned int TFTP_Features; /* bitwise OR of individual EFtpFeature's */
+typedef unsigned int TFTP_Features; /* bitwise OR of EFtpFeature's */
 
 
-/* All internal data necessary to perform the (re)connect and i/o
+/* All internal data necessary to perform I/O
  */
 typedef struct {
     const char*    host;
-    unsigned short port;
     const char*    user;
     const char*    pass;
     const char*    path;
-    const char*    name;
-    TFTP_Features  feat;
-    TFCDC_Flags    flag;
+    unsigned short        port;
+    unsigned char/*bool*/ send;  /* true when in send mode (STOR/APPE)     */
+    unsigned char/*bool*/ sync;  /* true when last cmd acked (cntl synced) */
+    TFTP_Features         feat;  /* FTP server features as discovered      */
+    TFCDC_Flags           flag;  /* connector flags per constructor        */
     SOCK           cntl;  /* control connection */
     SOCK           data;  /* data    connection */
+    BUF                   rbuf;  /* read  buffer       */
     BUF            wbuf;  /* write buffer       */
+    size_t                size;  /* uploaded data size */
     EIO_Status     r_status;
     EIO_Status     w_status;
 } SFTPConnector;
 
 
-static const STimeout kFTPFailsafeTimeout = {10, 0};
+static const STimeout kFailsafe = {10, 0};
+static const char     kDigits[] = "0123456789";
+
+
+typedef EIO_Status (*FParseFTPReply)(void* data, int code,
+                                     size_t lineno, const char* line);
 
 
 static EIO_Status s_ReadReply(SOCK sock, int* code,
-                              char* line, size_t maxlinelen)
+                              char* line, size_t maxlinelen,
+                              FParseFTPReply parser, void* data)
 {
-    int/*bool*/ first = 1/*true*/;
+    EIO_Status status = eIO_Success;
+    size_t lineno = 0;
     for (;;) {
         int c, m;
         size_t n;
         char buf[1024];
-        EIO_Status status = SOCK_ReadLine(sock, buf, sizeof(buf), &n);
+        const char* msg;
+        EIO_Status rdstatus = SOCK_ReadLine(sock, buf, sizeof(buf), &n);
         /* All FTP replies are at least '\n'-terminated, no ending with EOF */
-        if (status != eIO_Success)
-            return status;
+        if (rdstatus != eIO_Success)
+            return rdstatus;
         if (n == sizeof(buf))
             return eIO_Unknown/*line too long*/;
-        if (first  ||  isdigit((unsigned char) *buf)) {
-            if (sscanf(buf, "%d%n", &c, &m) < 1)
-                return eIO_Unknown;
-        } else
-            c = 0;
-        if (first) {
-            if (m != 3  ||  code == 0)
+        msg = buf;
+        if (!lineno  ||  isdigit((unsigned char)(*buf))) {
+            if (sscanf(buf, "%d%n", &c, &m) < 1  ||  m != 3  ||  !c
+                ||  (buf[m]  &&  buf[m] != ' '  &&  buf[m] != '-')
+                ||  (lineno  &&  c != *code)) {
                 return eIO_Unknown;
+            }
+            msg += m + 1;
+            if (buf[m] == '-')
+                m = 0;
+        } else {
+            c = *code;
+            m = 0;
+        }
+        msg += strspn(msg, " \t");
+        if (status == eIO_Success  &&  parser)
+            status = parser(data, lineno  &&  m ? 0 : c, lineno, msg);
+        if (!lineno++) {
             if (line)
-                strncpy0(line, &buf[m + 1], maxlinelen);
+                strncpy0(line, msg, maxlinelen);
             *code = c;
-            if (buf[m] != '-') {
-                if (buf[m] == ' ')
-                    break;
-                return eIO_Unknown;
             }
-            first = 0/*false*/;
-        } else if (c == *code  &&  m == 3  &&  buf[m] == ' ')
+        if (m)
             break;
     }
-    return eIO_Success;
+    return status;
+}
+
+
+static EIO_Status s_FTPCloseData(SFTPConnector* xxx, int/*bool*/ abort)
+{
+    static const STimeout kInstant = {0, 0};
+    EIO_Status status;
+    assert(xxx->data);
+    if (xxx->flag & fFCDC_LogControl)
+        SOCK_SetDataLogging(xxx->data, eOn);
+    if (!abort) {
+        SOCK_SetTimeout(xxx->data, eIO_Close, &kInstant);
+        status = SOCK_Close(xxx->data);
+    } else {
+        status = SOCK_Abort(xxx->data);
+        SOCK_Close(xxx->data);
+    }
+    xxx->data = 0;
+    return status;
 }
 
 
 static EIO_Status s_FTPReply(SFTPConnector* xxx, int* code,
-                             char* line, size_t maxlinelen)
+                             char* line, size_t maxlinelen,
+                             FParseFTPReply parser)
 {
     int c = 0;
     EIO_Status status = eIO_Closed;
     if (xxx->cntl) {
-        status = s_ReadReply(xxx->cntl, &c, line, maxlinelen);
+        xxx->sync = 0/*false*/;
+        status = s_ReadReply(xxx->cntl, &c, line, maxlinelen, parser, xxx);
+        if (status != eIO_Timeout)
+            xxx->sync = 1/*true*/;
         if (status == eIO_Success  &&  c == 421)
             status =  eIO_Closed;
         if (status == eIO_Closed  ||  (status == eIO_Success  &&  c == 221)) {
-            SOCK_Close(xxx->cntl);
-            xxx->cntl = 0;
             if (xxx->data) {
-                SOCK_Close(xxx->data);
-                xxx->data = 0;
+                s_FTPCloseData(xxx,
+                               status == eIO_Closed ? 1/*abort*/ : 0/*close*/);
             }
+            SOCK_Close(xxx->cntl);
+            xxx->cntl = 0;
         }
     }
     if (code)
@@ -144,25 +196,34 @@ static EIO_Status s_FTPReply(SFTPConnector* xxx, int* code,
 
 static EIO_Status s_FTPDrainReply(SFTPConnector* xxx, int* code, int cXX)
 {
-    EIO_Status status;
     int        c;
-    while ((status = s_FTPReply(xxx, &c, 0, 0)) == eIO_Success  &&
-           (!cXX  ||  c/100 != cXX)) {
+    EIO_Status status;
+    int        quit = *code;
+    while ((status = s_FTPReply(xxx, &c, 0, 0, 0)) == eIO_Success) {
         *code = c;
+        if ((quit  &&  quit == c)  ||  (cXX  &&  c / 100 == cXX))
+            break;
     }
     return status;
 }
 
 
-static EIO_Status s_WriteCommand(SOCK sock,
-                                 const char* cmd, const char* arg)
+#define s_FTPCommand(x, c, a)  s_FTPCommandEx(x, c, a, 0/*false*/)
+
+static EIO_Status s_FTPCommandEx(SFTPConnector* xxx,
+                                 const char*    cmd,
+                                 const char*    arg,
+                                 int/*bool*/    off)
 {
     size_t cmdlen = strlen(cmd);
     size_t arglen = arg ? strlen(arg) : 0;
     size_t linelen = cmdlen + (arglen ? 1/* */ + arglen : 0) + 2/*\r\n*/;
     char* line = (char*) malloc(linelen + 1/*\0*/);
-    EIO_Status status = eIO_Unknown;
+    EIO_Status status;
+
+    assert(xxx->cntl);
     if (line) {
+        ESwitch log = eDefault;
         memcpy(line, cmd, cmdlen);
         if (arglen) {
             line[cmdlen++] = ' ';
@@ -172,59 +233,239 @@ static EIO_Status s_WriteCommand(SOCK sock,
         line[cmdlen++] = '\r';
         line[cmdlen++] = '\n';
         line[cmdlen]   = '\0';
-        status = SOCK_Write(sock, line, linelen, 0, eIO_WritePersist);
+        log = off ? SOCK_SetDataLogging(xxx->cntl, eOff) : eOff;
+        status = SOCK_Write(xxx->cntl, line, linelen, 0, eIO_WritePersist);
+        if (off  &&  log != eOff) {
+            SOCK_SetDataLogging(xxx->cntl, log);
+            if (log == eOn  ||  SOCK_SetDataLoggingAPI(eDefault) == eOn)
+                CORE_LOGF_X(4, eLOG_Trace,
+                            ("%.*s command sent (%s)",
+                             (int) strcspn(line, " \t"), line,
+                             IO_StatusStr(status)));
+        }
         free(line);
+    } else
+        status = eIO_Unknown;
+    return status;
+}
+
+
+static const char* x_4Word(const char* line, const char word[4+1])
+{
+    const char* s = strstr(line, word);
+    if (!s)
+        return 0;
+    return (s == line  ||  isspace((unsigned char) s[-1]))
+        &&  !isalpha((unsigned char) s[4]) ? s : 0;
+}
+
+
+static EIO_Status x_FTPHelpParse(void* data, int code,
+                                 size_t lineno, const char* line)
+{
+    if (!lineno)
+        return code == 211  ||  code == 214 ? eIO_Success : eIO_NotSupported;
+    if (code) {
+        const char* s;
+        SFTPConnector* xxx = (SFTPConnector*) data;
+        if ((s = x_4Word(line, "NOOP")) != 0) {  /* RFC 959 */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_NOOP;
+            else
+                xxx->feat &= ~fFtpFeature_NOOP;
+        }
+        if ((s = x_4Word(line, "SYST")) != 0) {  /* RFC 959 */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_SYST;
+            else
+                xxx->feat &= ~fFtpFeature_SYST;
+        }
+        if ((s = x_4Word(line, "SITE")) != 0) {  /* RFC 959, 1123 */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_SITE;
+            else
+                xxx->feat &= ~fFtpFeature_SITE;
+        }
+        if ((s = x_4Word(line, "FEAT")) != 0) {  /* RFC 3659 */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_FEAT;
+            else
+                xxx->feat &= ~fFtpFeature_FEAT;
     }
+        if ((s = x_4Word(line, "MDTM")) != 0) {  /* RFC 3659 */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_MDTM;
+            else
+                xxx->feat &= ~fFtpFeature_MDTM;
+        }
+        if ((s = x_4Word(line, "REST")) != 0) {  /* RFC 3659 */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_REST;
+            else
+                xxx->feat &= ~fFtpFeature_REST;
+        }
+        if ((s = x_4Word(line, "SIZE")) != 0) {  /* RFC 3659 */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_SIZE;
+            else
+                xxx->feat &= ~fFtpFeature_SIZE;
+        }
+        if ((s = x_4Word(line, "EPSV")) != 0) {  /* RFC 2428 (cf 1579) */
+            if (s[4 + strspn(s + 4, " \t")] != '*')
+                xxx->feat |=  fFtpFeature_EPSV;
+            else
+                xxx->feat &= ~fFtpFeature_EPSV;
+        }
+    }
+    return eIO_Success;
+}
+
+
+static EIO_Status s_FTPHelp(SFTPConnector* xxx)
+{
+    int code;
+    TFTP_Features feat;
+    EIO_Status status = s_FTPCommand(xxx, "HELP", 0);
+    if (status != eIO_Success)
     return status;
+    feat = xxx->feat;
+    status = s_FTPReply(xxx, &code, 0, 0, x_FTPHelpParse);
+    if (status != eIO_Success  ||  (code != 211  &&  code != 214)) {
+        xxx->feat = feat;
+        return status != eIO_Success ? status : eIO_NotSupported;
+    }
+    return eIO_Success;
 }
 
 
-static EIO_Status s_FTPCommand(SFTPConnector* xxx,
-                               const char* cmd, const char* arg)
+static EIO_Status x_FTPFeatParse(void* data, int code,
+                                 size_t lineno, const char* line)
 {
-    return xxx->cntl ? s_WriteCommand(xxx->cntl, cmd, arg) : eIO_Closed;
+    if (!lineno)
+        return code == 211 ? eIO_Success : eIO_NotSupported;
+    if (code  &&  strlen(line) >= 4  &&  isspace((unsigned char) line[4])) {
+        SFTPConnector* xxx = (SFTPConnector*) data;
+        assert(code == 211);
+        if      (strncasecmp(line, "MDTM", 4) == 0)
+            xxx->feat |= fFtpFeature_MDTM;
+        else if (strncasecmp(line, "REST", 4) == 0)
+            xxx->feat |= fFtpFeature_REST;
+        else if (strncasecmp(line, "SIZE", 4) == 0)
+            xxx->feat |= fFtpFeature_SIZE;
+        else if (strncasecmp(line, "EPSV", 4) == 0)
+            xxx->feat |= fFtpFeature_EPSV;
+    }
+    return eIO_Success;
 }
 
 
-static EIO_Status s_FTPLogin(SFTPConnector* xxx, const STimeout* timeout)
+static EIO_Status s_FTPFeat(SFTPConnector* xxx)
 {
-    EIO_Status status;
     int code;
+    EIO_Status status;
+    TFTP_Features feat;
+    if (xxx->feat  &&  !(xxx->feat & fFtpFeature_FEAT))
+        return eIO_NotSupported;
+    status = s_FTPCommand(xxx, "FEAT", 0);
+    if (status != eIO_Success)
+        return status;
+    feat = xxx->feat;
+    status = s_FTPReply(xxx, &code, 0, 0, x_FTPFeatParse);
+    if (status != eIO_Success  ||  code != 211) {
+        xxx->feat = feat;
+        return status != eIO_Success ? status : eIO_NotSupported;
+    }
+    return eIO_Success;
+}
+
 
-    assert(xxx->cntl  &&  xxx->user  &&  xxx->pass);
-    status = SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
+static EIO_Status s_FTPNoop(SFTPConnector* xxx)
+{
+    int code;
+    EIO_Status status = s_FTPCommand(xxx, "NOOP", 0);
     if (status != eIO_Success)
         return status;
-    status = s_FTPReply(xxx, &code, 0, 0);
+    status = s_FTPReply(xxx, &code, 0, 0, 0);
     if (status != eIO_Success)
         return status;
-    if (code != 220  ||  !*xxx->user)
+    if (code != 200  &&  (code / 100 != 5  ||  (xxx->feat & fFtpFeature_NOOP)))
+        return eIO_Unknown;
+    return eIO_Success;
+}
+
+
+static EIO_Status s_FTPFeatures(SFTPConnector* xxx)
+{
+    if (xxx->flag & fFCDC_UseFeatures) {
+        /* try to setup features */
+        if (s_FTPHelp(xxx) == eIO_Closed)
+            return eIO_Closed;
+        if (s_FTPFeat(xxx) == eIO_Closed)
+            return eIO_Closed;
+        /* make sure the connection is still good */
+        return s_FTPNoop(xxx);
+    }
+    return eIO_Success;
+}
+
+
+static EIO_Status s_FTPLogin(SFTPConnector* xxx)
+{
+    int code;
+    EIO_Status status;
+
+    xxx->feat = 0;
+    status = s_FTPReply(xxx, &code, 0, 0, 0);
+    if (status != eIO_Success)
+        return status;
+    if (code != 220  ||  !xxx->user  ||  !*xxx->user)
         return eIO_Unknown;
     status = s_FTPCommand(xxx, "USER", xxx->user);
     if (status != eIO_Success)
         return status;
-    status = s_FTPReply(xxx, &code, 0, 0);
+    status = s_FTPReply(xxx, &code, 0, 0, 0);
     if (status != eIO_Success)
         return status;
     if (code == 230)
         return eIO_Success;
-    if (code != 331  ||  !*xxx->pass)
+    if (code != 331  ||  !xxx->pass)
         return eIO_Unknown;
-    status = s_FTPCommand(xxx, "PASS", xxx->pass);
+    status = s_FTPCommandEx(xxx, "PASS", *xxx->pass ? xxx->pass : " ", 1);
     if (status != eIO_Success)
         return status;
-    status = s_FTPReply(xxx, &code, 0, 0);
+    status = s_FTPReply(xxx, &code, 0, 0, 0);
     if (status != eIO_Success)
         return status;
-    if (code == 230)
-        return eIO_Success;
-    else
+    if (code != 230)
         return eIO_Unknown;
+    status = s_FTPFeatures(xxx);
+    if (status != eIO_Success)
+        return status;
+    if (xxx->flag & fFCDC_LogControl) {
+        CORE_LOGF_X(3, eLOG_Trace,
+                    ("FTP server %s:%hu ready, features = 0x%02X",
+                     xxx->host, xxx->port, (unsigned int) xxx->feat));
+    }
+    if (xxx->feat &  fFtpFeature_EPSV)
+        xxx->feat |= fFtpFeature_APSV;
+    return eIO_Success;
+}
+
+
+static EIO_Status s_FTPRename(SFTPConnector* xxx,
+                              const char*    cmd)
+{
+    return eIO_NotSupported; /*yet*/
 }
 
 
-static EIO_Status s_FTPChdir(SFTPConnector* xxx, const char* cmd)
+static EIO_Status s_FTPDir(SFTPConnector* xxx,
+                           const char*    cmd)
 {
+    if (cmd  &&  (*cmd == 'P'/*PWD*/  ||
+                  *cmd == 'M'/*MKD*/)) {
+        return eIO_NotSupported; /*yet*/
+    }
     if (cmd  ||  xxx->path) {
         int code;
         EIO_Status status = s_FTPCommand(xxx,
@@ -232,11 +473,20 @@ static EIO_Status s_FTPChdir(SFTPConnector* xxx, const char* cmd)
                                          cmd ? 0   : xxx->path);
         if (status != eIO_Success)
             return status;
-        status = s_FTPReply(xxx, &code, 0, 0);
+        status = s_FTPReply(xxx, &code, 0, 0, 0);
         if (status != eIO_Success)
             return status;
+        if (!cmd  ||  *cmd == 'C') { /* CWD, CDUP */
+            if (code != 200  &&  code != 250)
+                return eIO_Unknown;
+        } else if (*cmd == 'R') { /* RMD */
         if (code != 250)
             return eIO_Unknown;
+        } else {
+            /* 257 is a success code: 257<SP>"directory"<SP>comment
+             * For MKD there is 521 for "directory exits, no action taken" */
+            return eIO_NotSupported; /*yet*/
+        }
     }
     return eIO_Success;
 }
@@ -245,98 +495,211 @@ static EIO_Status s_FTPChdir(SFTPConnector* xxx, const char* cmd)
 static EIO_Status s_FTPBinary(SFTPConnector* xxx)
 {
     int code;
+    /* all implementations MUST support TYPE */
     EIO_Status status = s_FTPCommand(xxx, "TYPE", "I");
     if (status != eIO_Success)
         return status;
-    status = s_FTPReply(xxx, &code, 0, 0);
+    status = s_FTPReply(xxx, &code, 0, 0, 0);
     if (status != eIO_Success)
         return status;
-    if (code == 200)
-        return eIO_Success;
-    else
-        return eIO_Unknown;
+    return code == 200 ? eIO_Success : eIO_Unknown;
 }
 
 
-static EIO_Status s_FTPAbort(SFTPConnector*  xxx,
-                             const STimeout* timeout,
-                             int/*bool*/     quit)
+#if 0 /*unused*/
+static EIO_Status s_FTPSyst(SFTPConnector* xxx, char* buf, size_t bufsize)
 {
-    EIO_Status status = eIO_Success;
     int        code;
-    size_t     n;
+    EIO_Status status = s_FTPCommand(xxx, "SYST", 0);
+    if (status != eIO_Success)
+        return status;
+    status = s_FTPReply(xxx, &code, buf, bufsize - 1, 0);
+    if (status != eIO_Success)
+        return status;
+    return code == 215 ? eIO_Succes : eIO_Unknown;
+}
+#endif
 
-    if (!xxx->data)
+
+static EIO_Status s_FTPRest(SFTPConnector* xxx,
+                            const char*    cmd)
+{
+    int code;
+    EIO_Status status = s_FTPCommand(xxx, cmd, 0);
+    if (status != eIO_Success)
         return status;
-    if (quit  ||  !xxx->cntl) {
-        status = SOCK_Abort(xxx->data);
-        xxx->data = 0;
+    status = s_FTPReply(xxx, &code, 0, 0, 0);
+    if (status != eIO_Success)
         return status;
+    return code == 350 ? eIO_Success : eIO_Unknown;
+}
+
+
+static EIO_Status s_FTPDele(SFTPConnector* xxx,
+                            const char*    cmd)
+{
+    int code;
+    EIO_Status status = s_FTPCommand(xxx, cmd, 0);
+    if (status != eIO_Success)
+        return status;
+    status = s_FTPReply(xxx, &code, 0, 0, 0);
+    if (status != eIO_Success)
+        return status;
+    return code == 250 ? eIO_Success : eIO_Unknown;
+}
+
+
+static EIO_Status x_FTPMdtmParse(SFTPConnector* xxx, const char* timestamp)
+{
+    static const int kDay[12] = {31,  0, 31, 30, 31, 30,
+                                 31, 31, 30, 31, 30, 31};
+    int field[6], n;
+    struct tm tm;
+    char buf[40];
+    time_t t;
+
+    for (n = 0;  n < 6;  n++) {
+        size_t len = n ? 2 : 4/*year*/;
+        if (len != strlen(strncpy0(buf, timestamp, len))  ||
+            len != strspn(buf, kDigits)) {
+            return eIO_Unknown;
     }
-    if (!timeout)
-        timeout = &kFTPFailsafeTimeout;
-    if (SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout) != eIO_Success  ||
-        SOCK_SetTimeout(xxx->data, eIO_ReadWrite, timeout) != eIO_Success  ||
-        /* Send TELNET IP (Interrupt Process) command */
-        (status = SOCK_Write(xxx->cntl, "\377\364", 2, &n, eIO_WritePersist))
-        != eIO_Success  ||  n != 2                                         ||
-        /* Send TELNET DM (Data Mark) command to complete SYNCH, RFC 854 */
-        (status = SOCK_Write(xxx->cntl, "\377\362", 2, &n, eIO_WriteOutOfBand))
-        != eIO_Success  ||  n != 2                                         ||
-        (status = s_FTPCommand(xxx, "ABOR", 0)) != eIO_Success) {
-        SOCK_Abort(xxx->data);
-        xxx->data = 0;
-        return status == eIO_Success ? eIO_Unknown : status;
+        field[n] = atoi(buf);
+        timestamp += len;
     }
-    while (SOCK_Read(xxx->data, 0, 1024*1024/*drain up*/, 0, eIO_ReadPlain)
-           == eIO_Success) {
-        continue;
+    if (*timestamp) {
+        if (*timestamp++ != '.'
+            ||  strlen(timestamp) != strspn(timestamp, kDigits)) {
+            return eIO_Unknown;
     }
-    if (SOCK_Status(xxx->data, eIO_Read) == eIO_Closed) {
-        SOCK_Close(xxx->data);
-        xxx->data = 0;
     }
-    if ((status = s_FTPDrainReply(xxx, &code, 2/*2xx*/)) == eIO_Success
-        /* Microsoft FTP is known to return 225 (instead of 226) */
-        &&  code != 225  &&  code != 226) {
-        status = eIO_Unknown;
+    memset(&tm, 0, sizeof(tm));
+    if (field[0] < 1970)
+        return eIO_Unknown;
+    tm.tm_year  = field[0] - 1900;
+    if (field[1] < 1  ||  field[1] > 12)
+        return eIO_Unknown;
+    tm.tm_mon   = field[1] - 1;
+    if (field[2] < 1  ||  field[2] > (field[1] != 2
+                                      ? kDay[tm.tm_mon]
+                                      : 28 +
+                                      (!(field[0] % 4)  &&
+                                       (field[0] % 100
+                                        ||  !(field[0] % 400))))) {
+        return eIO_Unknown;
     }
-    if (xxx->data) {
-        if (status == eIO_Success)
-            status = SOCK_Close(xxx->data);
-        else {
-            if (status == eIO_Timeout) {
-                CORE_LOG_X(1, eLOG_Warning,
-                           "[FTP]  Timed out on data connection abort");
+    tm.tm_mday  = field[2];
+    if (field[3] < 1  ||  field[3] > 23)
+        return eIO_Unknown;
+    tm.tm_hour  = field[3];
+    if (field[4] < 1  ||  field[4] > 59)
+        return eIO_Unknown;
+    tm.tm_min   = field[4];
+    if (field[5] < 1  ||  field[5] > 60) /* allow one leap second */
+        return eIO_Unknown;
+    tm.tm_sec   = field[5];
+    tm.tm_isdst = 0;
+    if ((t = mktime(&tm)) == (time_t)(-1))
+        return eIO_Unknown;
+#if !defined(NCBI_OS_DARWIN)  &&  !defined(NCBI_OS_BSD)
+    /* NB: timezone information is unavailable on Darwin or BSD :-/ */
+    if (t >= _timezone)
+        t -= _timezone;
+    if (t >= _daylight  &&  tm.tm_isdst > 0)
+        t -= _daylight;
+#endif /*!NCBI_OS_DARWIN && !NCBI_OS_BSD*/
+    n = sprintf(buf, "%lu%s%s", (unsigned long) t,
+                *timestamp ? "." : "", timestamp);
+    if (n <= 0  ||  !BUF_Write(&xxx->rbuf, buf, (size_t) n))
+        return eIO_Unknown;
+    return eIO_Success;
+}
+
+
+static EIO_Status s_FTPMdtm(SFTPConnector* xxx,
+                            const char*    cmd)
+{
+    int code;
+    char buf[128];
+    EIO_Status status = s_FTPCommand(xxx, cmd, 0);
+    if (status != eIO_Success)
+        return status;
+    status = s_FTPReply(xxx, &code, buf, sizeof(buf)-1, 0);
+    if (status == eIO_Success) {
+        switch (code) {
+        case 213:
+            status = x_FTPMdtmParse(xxx, buf);
+            break;
+        case 550:
+            /* file not plain or does not exist */
+            break;
+        default:
+            status =
+                xxx->feat & fFtpFeature_MDTM ? eIO_Unknown : eIO_NotSupported;
+            break;
             }
-            SOCK_Abort(xxx->data);
         }
-        xxx->data = 0;
+    return status;
+}
+
+
+static EIO_Status x_FTPSizeParse(SFTPConnector* xxx,
+                                 const char*    line)
+{
+    size_t n = strspn(line, kDigits);
+    return n  &&  n == strlen(line)  &&  BUF_Write(&xxx->rbuf, line, n)
+        ? eIO_Success : eIO_Unknown;
+}
+
+
+static EIO_Status s_FTPSize(SFTPConnector* xxx,
+                            const char*    cmd)
+{
+    int code;
+    char buf[128];
+    EIO_Status status = s_FTPCommand(xxx, cmd, 0);
+    if (status != eIO_Success)
+        return status;
+    status = s_FTPReply(xxx, &code, buf, sizeof(buf)-1, 0);
+    if (status == eIO_Success) {
+        switch (code) {
+        case 213:
+            status = x_FTPSizeParse(xxx, buf);
+            break;
+        case 550:
+            /* file not plain or does not exist */
+            break;
+        default:
+            status =
+                xxx->feat & fFtpFeature_SIZE ? eIO_Unknown : eIO_NotSupported;
+            break;
+        }
     }
     return status;
 }
 
 
-static EIO_Status s_FTPPasv(SFTPConnector* xxx)
+static EIO_Status s_FTPPasv(SFTPConnector*  xxx,
+                            unsigned int*   host,
+                            unsigned short* port)
 {
-    static const STimeout instant = {0, 0};
-    unsigned int   host, i;
-    unsigned short port;
     EIO_Status status;
     int  code, o[6];
+    unsigned int i;
     char buf[128];
 
+    /* all implementations MUST support */
     status = s_FTPCommand(xxx, "PASV", 0);
     if (status != eIO_Success)
         return status;
-    status = s_FTPReply(xxx, &code, buf, sizeof(buf) - 1);
+    status = s_FTPReply(xxx, &code, buf, sizeof(buf) - 1, 0);
     if (status != eIO_Success  ||  code != 227)
         return eIO_Unknown;
     buf[sizeof(buf) - 1] = '\0';
     for (;;) {
         char* c;
-        /* RFC 1123 4.1.2.6 says that ()'s in PASV reply must not be assumed */
-        for (c = buf; *c; c++) {
+        /* RFC 1123 4.1.2.6 says that ()'s in PASV reply MUST NOT be assumed */
+        for (c = buf;  *c;  ++c) {
             if (isdigit((unsigned char)(*c)))
                 break;
         }
@@ -352,54 +715,206 @@ static EIO_Status s_FTPPasv(SFTPConnector* xxx)
         if (o[i] < 0  ||  o[i] > 255)
             return eIO_Unknown;
     }
-    i = (((((o[0] << 8) | o[1]) << 8) | o[2]) << 8) | o[3];
-    host = SOCK_HostToNetLong(i);
-    i = (o[4] << 8) | o[5];
-    port = (unsigned short) i;
-    if (SOCK_ntoa(host, buf, sizeof(buf)) != 0)
+    if (!(i = (((((o[0] << 8) | o[1]) << 8) | o[2]) << 8) | o[3]))
+        return eIO_Unknown;
+    *host = SOCK_HostToNetLong(i);
+    if (!(i = (o[4] << 8) | o[5]))
+        return eIO_Unknown;
+    *port = (unsigned short) i;
+    return eIO_Success;
+}
+
+
+static EIO_Status s_FTPEpsv(SFTPConnector*  xxx,
+                            unsigned int*   host,
+                            unsigned short* port)
+{
+    EIO_Status status;
+    char buf[128], d;
+    unsigned int p;
+    const char* s;
+    int n;
+
+    assert(xxx->feat & (fFtpFeature_EPSV | fFtpFeature_APSV));
+    status = s_FTPCommand(xxx, "EPSV", port ? 0 : "ALL");
+    if (status != eIO_Success)
+        return status;
+    status = s_FTPReply(xxx, &n, buf, sizeof(buf) - 1, 0);
+    if (status != eIO_Success)
+        return status;
+    if (!port  &&  n == 200)
+        return eIO_Success;
+    if (!port  ||  n != 229)
+        return xxx->feat & ~fFtpFeature_EPSV ? eIO_Unknown : eIO_NotSupported;
+    buf[sizeof(buf) - 1] = '\0';
+    if (!(s = strchr(buf, '('))  ||  !(d = *++s)  ||  *++s != d  ||  *++s != d
+        ||  sscanf(++s, "%u%c%n", &p, buf, &n) < 2  ||  p > 0xFFFF
+        ||  *buf != d  ||  s[n] != ')'  ||  s[++n]) {
+        return eIO_Unknown;
+    }
+    *host = 0;
+    *port = (unsigned short) p;
+    return eIO_Success;
+}
+
+
+static EIO_Status s_FTPAbort(SFTPConnector*  xxx,
+                             const STimeout* timeout,
+                             int/*bool*/     quit)
+{
+    EIO_Status status;
+    int        code;
+    size_t     n;
+
+    if (!xxx->data)
+        return eIO_Success;
+    if (quit  ||  !xxx->cntl)
+        return s_FTPCloseData(xxx, 1/*abort*/);
+    if (!timeout)
+        timeout = &kFailsafe;
+    SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
+    SOCK_SetTimeout(xxx->data, eIO_ReadWrite, timeout);
+    if (/* Send TELNET IP (Interrupt Process) command */
+        (status = SOCK_Write(xxx->cntl, "\377\364", 2, &n, eIO_WritePersist))
+        != eIO_Success  ||  n != 2  ||
+        /* Send TELNET DM (Data Mark) command to complete SYNCH, RFC 854 */
+        (status = SOCK_Write(xxx->cntl, "\377\362", 2, &n, eIO_WriteOutOfBand))
+        != eIO_Success  ||  n != 2  ||
+        (status = s_FTPCommand(xxx, "ABOR", 0)) != eIO_Success) {
+        s_FTPCloseData(xxx, 1/*abort*/);
+        return status != eIO_Success ? status : eIO_Unknown;
+    }
+    while (SOCK_Read(xxx->data, 0, 1024*1024/*drain up*/, 0, eIO_ReadPlain)
+           == eIO_Success) {
+        continue;
+    }
+    n = status == eIO_Timeout ? 1 : 0; /*just a bool here*/
+    s_FTPCloseData(xxx, SOCK_Status(xxx->data, eIO_Read) == eIO_Closed
+                   ? 0/*close*/ : 1/*abort*/);
+    code = 426;
+    if ((status = s_FTPDrainReply(xxx, &code, 2/*2xx*/)) == eIO_Success
+        /* Microsoft FTP is known to return 225 (instead of 226) */
+        &&  code != 225  &&  code != 226  &&  code != 426) {
+        status = eIO_Unknown;
+    }
+    if (n  ||  status == eIO_Timeout) {
+        CORE_LOG_X(1, eLOG_Warning,
+                   "[FTP]  Timed out in data connection abort");
+    }
+    return status;
+}
+
+
+static EIO_Status s_FTPPassive(SFTPConnector*  xxx,
+                               const STimeout* timeout)
+{
+    unsigned int   host;
+    unsigned short port;
+    EIO_Status     status;
+    char           buf[40];
+
+    if (xxx->feat & (fFtpFeature_EPSV | fFtpFeature_APSV)) {
+        if ((xxx->feat & fFtpFeature_EPSV) && (xxx->feat & fFtpFeature_APSV)) {
+            /* first time here, try to set EPSV ALL */
+            if (s_FTPEpsv(xxx, 0, 0) == eIO_Success)
+                xxx->feat &= ~fFtpFeature_EPSV; /* APSV mode */
+            else
+                xxx->feat &= ~fFtpFeature_APSV; /* EPSV mode */
+        }
+        status = s_FTPEpsv(xxx, &host, &port);
+        switch (status) {
+        case eIO_NotSupported:
+            /* wild guess did not work */
+            xxx->feat &= ~fFtpFeature_EPSV;
+            port = 0;
+            break;
+        case eIO_Success:
+            assert(port);
+            break;
+        default:
+            return status;
+        }
+    } else
+        port = 0;
+    if (!port  &&  (status = s_FTPPasv(xxx, &host, &port)) != eIO_Success)
+        return status;
+    assert(port);
+    if (( host  &&
+          SOCK_ntoa(host, buf, sizeof(buf)) != 0)  ||
+        (!host  &&
+         !SOCK_GetPeerAddressStringEx(xxx->cntl, buf, sizeof(buf), eSAF_IP))) {
         return eIO_Unknown;
-    if ((status = SOCK_CreateEx(buf, port, &instant, &xxx->data, 0, 0,
-                                xxx->flag & fFCDC_LogData
-                                ? fSOCK_LogOn
-                                : fSOCK_LogDefault)) != eIO_Success) {
+    }
+    status = SOCK_CreateEx(buf, port, timeout, &xxx->data, 0, 0,
+                           xxx->flag & fFCDC_LogControl
+                           ? fSOCK_LogOn : fSOCK_LogDefault);
+    if (status != eIO_Success) {
         CORE_LOGF_X(2, eLOG_Error,
                     ("[FTP]  Cannot open data connection to %s:%hu: %s",
                      buf, port, IO_StatusStr(status)));
-        s_FTPAbort(xxx, 0, 0/*!quit*/);
+        s_FTPAbort(xxx, timeout, 0/*!quit*/);
+        assert(!xxx->data);
         return eIO_Unknown;
     }
+    assert(xxx->data);
+    if (!(xxx->flag & fFCDC_LogData))
+        SOCK_SetDataLogging(xxx->data, eDefault);
     return eIO_Success;
 }
 
 
+/* all implementations MUST support RETR */
 static EIO_Status s_FTPRetrieve(SFTPConnector* xxx,
-                                const char*    cmd)
+                                const char*     cmd,
+                                const STimeout* timeout)
 {
     int code;
-    EIO_Status status = s_FTPPasv(xxx);
+    EIO_Status status = s_FTPPassive(xxx, timeout);
     if (status != eIO_Success)
         return status;
     status = s_FTPCommand(xxx, cmd, 0);
-    if (status != eIO_Success)
+    if (status == eIO_Success) {
+        status  = s_FTPReply(xxx, &code, 0, 0, 0);
+        if (status == eIO_Success) {
+            assert(xxx->data);
+            if (code == 125  ||  code == 150)
+                return eIO_Success;
+            /* w/o data connection open, user gets eIO_Closed on read */
+            if (code == 450  &&  (*cmd != 'N'/*NLST*/ || *cmd != 'L'/*LIST*/))
+                s_FTPCloseData(xxx, 1/*abort*/);
+            status = eIO_Unknown;
+        }
+    }
+    s_FTPAbort(xxx, timeout, 0/*!quit*/);
+    assert(!xxx->data);
         return status;
-    status = s_FTPReply(xxx, &code, 0, 0);
+}
+
+
+/* all implementations MUST support STOR */
+static EIO_Status s_FTPStore(SFTPConnector*  xxx,
+                             const char*     cmd,
+                             const STimeout* timeout)
+{
+    int code;
+    EIO_Status status = s_FTPPassive(xxx, timeout);
     if (status != eIO_Success)
         return status;
-    if (code == 150)
+    status = s_FTPCommand(xxx, cmd, 0);
+    if (status == eIO_Success) {
+        status  = s_FTPReply(xxx, &code, 0, 0, 0);
+        if (status == eIO_Success) {
+            if (code == 125  ||  code == 150) {
+                xxx->send = 1/*true*/;
+                xxx->size = 0;
         return eIO_Success;
-    if (code == 450  &&  (strncasecmp(cmd, "NLST", 4) == 0  ||
-                          strncasecmp(cmd, "LIST", 4) == 0)) {
-        /* server usually drops data connection on 450: no files ...*/
-        if (xxx->data) {
-            /* ... so do we :-/ */
-            SOCK_Abort(xxx->data);
-            xxx->data = 0;
         }
-        /* with no data connection open, user gets eIO_Closed on read */
-        return eIO_Success;
+            status = eIO_Unknown;
     }
-    s_FTPAbort(xxx, 0, 0/*!quit*/);
-    return eIO_Unknown;
+    }
+    s_FTPAbort(xxx, timeout, 0/*!quit*/);
+    assert(!xxx->data);
+    return status;
 }
 
 
@@ -409,43 +924,69 @@ static EIO_Status s_FTPExecute(SFTPConnector* xxx, const STimeout* timeout)
     size_t     size;
     char*      s;
 
-    if ((status = s_FTPAbort(xxx, timeout, 0/*!quit*/)) != eIO_Success)
-        return status;
-    verify((size = BUF_Size(xxx->wbuf)) != 0);
-    if (!(s = (char*) malloc(size + 1)))
-        return eIO_Unknown;
-    if (BUF_Read(xxx->wbuf, s, size) == size  &&
-        SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout) == eIO_Success) {
-        char* c;
-        if ((c = (char*) memchr(s, '\n', size)) != 0) {
-            if (c != s  &&  c[-1] == '\r')
-                c--;
-            *c = '\0';
-        } else
+    BUF_Erase(xxx->rbuf);
+    status = s_FTPAbort(xxx, timeout, 0/*!quit*/);
+    assert(!xxx->data);
+    if (status != eIO_Success)
+        goto out;
+    if (!xxx->sync) {
+        int dummy;
+        status = s_ReadReply(xxx->cntl, &dummy, 0, 0, 0, 0);
+        if (status != eIO_Success)
+            goto out;
+        assert(xxx->sync);
+    }
+    assert(xxx->cntl);
+    verify(size = BUF_Size(xxx->wbuf));
+    if ((s = (char*) malloc(size + 1)) != 0
+        &&  BUF_Read(xxx->wbuf, s, size) == size) {
+        const char* c;
+        assert(!memchr(s, '\n', size));
+        if (s[size - 1] == '\r')
+            --size;
             s[size] = '\0';
-        if (!(c = strchr(s, ' ')))
-            c = s + strlen(s);
-        if (!(size = (size_t)(c - s))  ||  size < 3  ||  size > 4) {
-            status = eIO_Unknown;
-        } else if (size == 3  &&  strncasecmp(s, "CWD",  3) == 0) {
-            status = s_FTPChdir(xxx, s);
+        if (!(c = (const char*) memchr(s, ' ', size)))
+            c = s + size;
+        else
+            size = (size_t)(c - s);
+        if (size == 3  ||  size == 4) {
+            /* FIXME: todo X<dir> commands (should be supported per RFC1123) */
+            SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
+            if        (size == 3  &&   strncasecmp(s, "REN",  3) == 0) {
+                /* special-cased non-standard command */
+                status = s_FTPRename(xxx, c);
+            } else if (size == 3  &&  (strncasecmp(s, "CWD",  3) == 0  ||
+                                       strncasecmp(s, "PWD",  3) == 0  ||
+                                       strncasecmp(s, "MKD",  3) == 0  ||
+                                       strncasecmp(s, "RMD",  3) == 0)) {
+                status = s_FTPDir (xxx, s);
+            } else if (size == 4  &&   strncasecmp(s, "CDUP", 4) == 0) {
+                status = s_FTPDir (xxx, s);
+            } else if (size == 4  &&   strncasecmp(s, "DELE", 4) == 0) {
+                status = s_FTPDele(xxx, s);
         } else if (size == 4  && (strncasecmp(s, "LIST", 4) == 0  ||
                                   strncasecmp(s, "NLST", 4) == 0  ||
                                   strncasecmp(s, "RETR", 4) == 0)) {
-            status = s_FTPRetrieve(xxx, s);
+                status = s_FTPRetrieve(xxx, s, timeout);
+            } else if (size == 4  &&   strncasecmp(s, "MDTM", 4) == 0) {
+                status = s_FTPMdtm(xxx, s);
         } else if (size == 4  &&  strncasecmp(s, "REST", 4) == 0) {
-            status = s_FTPCommand(xxx, s, 0);
-            if (status == eIO_Success) {
-                int code;
-                status = s_FTPReply(xxx, &code, 0, 0);
-                if (status == eIO_Success  &&  code != 350)
-                    status = eIO_Unknown;
-            }
+                status = s_FTPRest(xxx, s);
+            } else if (size == 4  &&   strncasecmp(s, "SIZE", 4) == 0) {
+                status = s_FTPSize(xxx, s);
+            } else if (size == 4  &&  (strncasecmp(s, "STOR", 4) == 0  ||
+                                       strncasecmp(s, "APPE", 4) == 0)) {
+                status = s_FTPStore(xxx, s, timeout);
         } else
-            status = eIO_Unknown;
+                status = eIO_NotSupported;
+        } else
+            status = eIO_NotSupported;
     } else
         status = eIO_Unknown;
+    if (s)
     free(s);
+ out:
+    BUF_Erase(xxx->wbuf);
     return status;
 }
 
@@ -482,11 +1023,6 @@ extern "C" {
     static void        s_Setup      (SMetaConnector* meta,
                                      CONNECTOR       connector);
     static void        s_Destroy    (CONNECTOR       connector);
-#  ifdef IMPLEMENTED__CONN_WaitAsync
-    static EIO_Status s_VT_WaitAsync(void*                   connector,
-                                     FConnectorAsyncHandler  func,
-                                     SConnectorAsyncHandler* data);
-#  endif
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
@@ -508,117 +1044,168 @@ static EIO_Status s_VT_Open
     EIO_Status status;
 
     assert(!xxx->data  &&  !xxx->cntl);
+
     status = SOCK_CreateEx(xxx->host, xxx->port, timeout, &xxx->cntl, 0, 0,
                            xxx->flag & fFCDC_LogControl
                            ? fSOCK_LogOn : fSOCK_LogDefault);
+    if (status == eIO_Success) {
+        SOCK_DisableOSSendDelay(xxx->cntl, 1/*yes,disable*/);
+        SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
+        status  = s_FTPLogin(xxx);
+    }
     if (status == eIO_Success)
-        status = s_FTPLogin(xxx, timeout);
-    if (status == eIO_Success)
-        status = s_FTPChdir(xxx, 0);
+        status  = s_FTPDir(xxx, 0);
     if (status == eIO_Success)
         status = s_FTPBinary(xxx);
-    if (status != eIO_Success) {
-        if (xxx->cntl) {
+    if (status == eIO_Success)
+        xxx->send = 0/*false*/;
+    else if (xxx->cntl) {
+        SOCK_Abort(xxx->cntl);
             SOCK_Close(xxx->cntl);
             xxx->cntl = 0;
         }
-    }
     xxx->r_status = status;
     xxx->w_status = status;
     return status;
 }
 
 
-static EIO_Status s_VT_Write
+static EIO_Status s_VT_Wait
 (CONNECTOR       connector,
- const void*     buf,
- size_t          size,
- size_t*         n_written,
+ EIO_Event       event,
  const STimeout* timeout)
 {
     SFTPConnector* xxx = (SFTPConnector*) connector->handle;
-    EIO_Status status;
-    const char* c;
+    assert(event == eIO_Read  ||  event == eIO_Write);
 
     if (!xxx->cntl)
         return eIO_Closed;
-    if (!size)
-        return eIO_Success;
 
-    if ((c = (const char*) memchr((const char*) buf, '\n', size)) != 0  &&
-        c < (const char*) buf + size - 1) {
-        return eIO_Unknown;
-    }
-    status = BUF_Write(&xxx->wbuf, buf, size) ? eIO_Success : eIO_Unknown;
-    if (status == eIO_Success  &&  c) {
-        xxx->w_status = s_FTPExecute(xxx, timeout);
-        status = xxx->w_status;
+    if (xxx->send  &&  xxx->data) {
+        if (event & eIO_Read)
+            return eIO_Closed;
+        return SOCK_Wait(xxx->data, eIO_Write, timeout);
     }
-    *n_written = size;
+    if (event & eIO_Write)
+        return xxx->send ? eIO_Closed : eIO_Success;
+    if (!xxx->data) {
+        EIO_Status status;
+        if (BUF_Size(xxx->rbuf))
+            return eIO_Success;
+        if (!BUF_Size(xxx->wbuf))
+            return eIO_Closed;
+        if ((status = s_FTPExecute(xxx, timeout)) != eIO_Success)
     return status;
+        if (BUF_Size(xxx->rbuf))
+            return eIO_Success;
+    }
+    return xxx->data ? SOCK_Wait(xxx->data, eIO_Read, timeout) : eIO_Closed;
 }
 
 
-static EIO_Status s_VT_Read
+static EIO_Status s_VT_Write
 (CONNECTOR       connector,
- void*           buf,
+ const void*     buf,
  size_t          size,
- size_t*         n_read,
+ size_t*         n_written,
  const STimeout* timeout)
 {
     SFTPConnector* xxx = (SFTPConnector*) connector->handle;
-    EIO_Status status = eIO_Closed;
-    if (xxx->cntl  &&  xxx->data) {
-        status = SOCK_SetTimeout(xxx->data, eIO_Read, timeout);
-        if (status == eIO_Success) {
-            xxx->r_status = SOCK_Read(xxx->data,
-                                      buf, size, n_read, eIO_ReadPlain);
-            if (xxx->r_status == eIO_Closed) {
-                int code;
-                SOCK_Close(xxx->data);
-                xxx->data = 0;
-                SOCK_SetTimeout(xxx->cntl, eIO_Read, timeout);
-                if (s_FTPReply(xxx, &code, 0, 0) != eIO_Success  ||
-                    (code != 225  &&  code != 226)) {
-                    xxx->r_status = eIO_Unknown;
-                }
-            }
-            status = xxx->r_status;
-        }
+    EIO_Status status;
+    const char* c;
+
+    if (!xxx->cntl)
+        return eIO_Closed;
+
+    if (xxx->send) {
+        if (!xxx->data)
+            return eIO_Closed;
+        SOCK_SetTimeout(xxx->data, eIO_Write, timeout);
+        status = SOCK_Write(xxx->data, buf, size, n_written, eIO_WritePlain);
+        xxx->size += *n_written;
+        if (status == eIO_Closed)
+            s_FTPCloseData(xxx, 1/*abort*/);
+    } else if (!size) {
+        return eIO_Success;
+    } else if (((c = (const char*) memchr((const char*) buf, '\n', size)) != 0
+                &&  c < (const char*) buf + size - 1)
+               ||  !BUF_Write(&xxx->wbuf, buf, size - (c ? 1 : 0))) {
+        return eIO_Unknown;
+    } else {
+        status = c ? s_FTPExecute(xxx, timeout) : eIO_Success;
+        *n_written = size;
     }
+    if (status != eIO_Timeout)
+        xxx->w_status = status;
     return status;
 }
 
 
-static EIO_Status s_VT_Wait
+static EIO_Status s_VT_Flush
 (CONNECTOR       connector,
- EIO_Event       event,
  const STimeout* timeout)
 {
     SFTPConnector* xxx = (SFTPConnector*) connector->handle;
     if (!xxx->cntl)
         return eIO_Closed;
-    if (event & eIO_Write)
+
+    if (xxx->send  ||  !BUF_Size(xxx->wbuf))
         return eIO_Success;
-    if (!xxx->data) {
-        EIO_Status status;
-        if (!BUF_Size(xxx->wbuf))
-            return eIO_Closed;
-        if ((status = s_FTPExecute(xxx, timeout)) != eIO_Success)
-            return status;
-        if (!xxx->data)
-            return eIO_Closed;
-    }
-    return SOCK_Wait(xxx->data, eIO_Read, timeout);
+    return s_FTPExecute(xxx, timeout);
 }
 
 
-static EIO_Status s_VT_Flush
+static EIO_Status s_VT_Read
 (CONNECTOR       connector,
+ void*           buf,
+ size_t          size,
+ size_t*         n_read,
  const STimeout* timeout)
 {
     SFTPConnector* xxx = (SFTPConnector*) connector->handle;
-    return BUF_Size(xxx->wbuf) ? s_FTPExecute(xxx, timeout) : eIO_Success;
+    EIO_Status status;
+    int code;
+
+    if (!xxx->cntl)
+        return eIO_Closed;
+
+    if (xxx->send) {
+        if (xxx->data)
+            s_FTPCloseData(xxx, 0/*close*/);
+        SOCK_SetTimeout(xxx->cntl, eIO_Read, timeout);
+        status = s_FTPReply(xxx, &code, 0, 0, 0);
+        if (status == eIO_Timeout)
+            return status;
+        xxx->send = 0/*false*/;
+        if (status != eIO_Success  ||  code != 226)
+            status  = eIO_Unknown;
+        if (status == eIO_Success) {
+            char buf[40];
+            int n = sprintf(buf, "%lu", (unsigned long) xxx->size);
+            if (!BUF_Write(&xxx->rbuf, buf, (size_t) n))
+                status = eIO_Unknown;
+        }
+        xxx->w_status = status;
+        assert(!xxx->data);
+    } else
+        status = eIO_Success;
+    if (xxx->data) {
+        assert(!xxx->send  &&  !BUF_Size(xxx->rbuf));
+        SOCK_SetTimeout(xxx->data, eIO_Read, timeout);
+        status = SOCK_Read(xxx->data, buf, size, n_read, eIO_ReadPlain);
+        if (status == eIO_Closed) {
+            s_FTPCloseData(xxx, 0/*close*/);
+            SOCK_SetTimeout(xxx->cntl, eIO_Read, timeout);
+            if (s_FTPReply(xxx, &code, 0, 0, 0) != eIO_Success
+                ||  (code != 225  &&  code != 226)) {
+                status = eIO_Unknown;
+            }
+        }
+        if (status != eIO_Timeout)
+            xxx->r_status = status;
+    } else if (size  &&  !(*n_read = BUF_Read(xxx->rbuf, buf, size)))
+        status = eIO_Closed;
+    return status;
 }
 
 
@@ -630,13 +1217,14 @@ static EIO_Status s_VT_Status
 
     switch (dir) {
     case eIO_Read:
-        return xxx->r_status;
+        return xxx->cntl ? xxx->r_status : eIO_Closed;
     case eIO_Write:
-        return xxx->w_status;
+        return xxx->cntl ? xxx->w_status : eIO_Closed;
     default:
         assert(0); /* should never happen as checked by connection */
-        return eIO_InvalidArg;
+        break;
     }
+    return eIO_InvalidArg;
 }
 
 
@@ -647,28 +1235,28 @@ static EIO_Status s_VT_Close
     SFTPConnector* xxx = (SFTPConnector*) connector->handle;
     EIO_Status status;
 
-    if ((status = s_FTPAbort(xxx, timeout, 1/*quit*/)) == eIO_Success) {
-        if (xxx->cntl) {
-            int code;
+    status = s_FTPAbort(xxx, timeout, 1/*quit*/);
+    assert(!xxx->data);
+    if (xxx->cntl  &&  status == eIO_Success) {
+        int code = 0/*any*/;
             if (!timeout)
-                timeout = &kFTPFailsafeTimeout;
+            timeout = &kFailsafe;
             SOCK_SetTimeout(xxx->cntl, eIO_ReadWrite, timeout);
+        /* all implementations MUST support QUIT */
             status = s_FTPCommand(xxx, "QUIT", 0);
             if (status == eIO_Success)
-                status = s_FTPDrainReply(xxx, &code, 0);
+            status  = s_FTPDrainReply(xxx, &code, 0/*any*/);
             if (status != eIO_Closed  ||  code != 221)
                 status = eIO_Unknown;
         }
-    }
     if (xxx->cntl) {
         assert(status != eIO_Success);
         if (status == eIO_Timeout)
             SOCK_Abort(xxx->cntl);
-        else
-            SOCK_Close(xxx->cntl);
+        status = SOCK_Close(xxx->cntl);
         xxx->cntl = 0;
     }
-    return status != eIO_Closed ? status : eIO_Success;
+    return status;
 }
 
 
@@ -685,10 +1273,7 @@ static void s_Setup
     CONN_SET_METHOD(meta, read,       s_VT_Read,      connector);
     CONN_SET_METHOD(meta, status,     s_VT_Status,    connector);
     CONN_SET_METHOD(meta, close,      s_VT_Close,     connector);
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
-#endif
-    meta->default_timeout = 0/*infinite*/;
+    meta->default_timeout = kInfiniteTimeout;
 }
 
 
@@ -696,16 +1281,29 @@ static void s_Destroy
 (CONNECTOR connector)
 {
     SFTPConnector* xxx = (SFTPConnector*) connector->handle;
+    connector->handle = 0;
+
+    if (xxx->host) {
     free((void*) xxx->host);
+        xxx->host = 0;
+    }
+    if (xxx->user) {
     free((void*) xxx->user);
+        xxx->user = 0;
+    }
+    if (xxx->pass) {
     free((void*) xxx->pass);
-    if (xxx->path)
+        xxx->pass = 0;
+    }
+    if (xxx->path) {
         free((void*) xxx->path);
-    if (xxx->name)
-        free((void*) xxx->name);
+        xxx->path = 0;
+    }
+    BUF_Destroy(xxx->rbuf);
+    xxx->rbuf = 0;
     BUF_Destroy(xxx->wbuf);
+    xxx->wbuf = 0;
     free(xxx);
-    connector->handle = 0;
     free(connector);
 }
 
@@ -714,7 +1312,7 @@ static void s_Destroy
  *  EXTERNAL -- the connector's "constructors"
  ***********************************************************************/
 
-extern CONNECTOR FTP_CreateDownloadConnector(const char*    host,
+extern CONNECTOR FTP_CreateConnector(const char*    host,
                                              unsigned short port,
                                              const char*    user,
                                              const char*    pass,
@@ -724,17 +1322,15 @@ extern CONNECTOR FTP_CreateDownloadConnector(const char*    host,
     CONNECTOR      ccc = (SConnector*)    malloc(sizeof(SConnector));
     SFTPConnector* xxx = (SFTPConnector*) malloc(sizeof(*xxx));
 
-    assert(!(flag & ~fFCDC_LogAll));
-
     xxx->data    = 0;
     xxx->cntl    = 0;
+    xxx->rbuf     = 0;
     xxx->wbuf    = 0;
     xxx->host    = strdup(host);
     xxx->port    = port ? port : 21;
     xxx->user    = strdup(user ? user : "ftp");
     xxx->pass    = strdup(pass ? pass : "-none");
     xxx->path    = path  &&  *path ? strdup(path) : 0;
-    xxx->name    = 0;
     xxx->flag    = flag;
 
     /* initialize connector data */
@@ -746,3 +1342,15 @@ extern CONNECTOR FTP_CreateDownloadConnector(const char*    host,
 
     return ccc;
 }
+
+
+/*DEPRECATED*/
+extern CONNECTOR FTP_CreateDownloadConnector(const char*    host,
+                                             unsigned short port,
+                                             const char*    user,
+                                             const char*    pass,
+                                             const char*    path,
+                                             TFCDC_Flags    flag)
+{
+    return FTP_CreateConnector(host, port, user, pass, path, flag);
+}
diff --git a/connect/ncbi_ftp_connector.h b/connect/ncbi_ftp_connector.h
index 86d42c7..4174278 100644
--- a/connect/ncbi_ftp_connector.h
+++ b/connect/ncbi_ftp_connector.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_FTP_CONNECTOR__H
 #define CONNECT___NCBI_FTP_CONNECTOR__H
 
-/* $Id: ncbi_ftp_connector.h,v 1.3 2008/10/16 18:55:44 kazimird Exp $
+/* $Id: ncbi_ftp_connector.h,v 1.5 2010/05/21 12:34:38 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -54,21 +54,23 @@ extern "C" {
 typedef enum {
     fFCDC_LogControl = 1,
     fFCDC_LogData    = 2,
-    fFCDC_LogAll     = fFCDC_LogControl | fFCDC_LogData
+    fFCDC_LogAll      = fFCDC_LogControl | fFCDC_LogData,
+    fFCDC_UseFeatures = 8
 } EFCDC_Flags;
 typedef unsigned int TFCDC_Flags;
 
-typedef enum { /* DEPRECATED -- DON'T USE */
+typedef enum { /* DEPRECATED -- DON'T USE! */
     eFCDC_LogControl = fFCDC_LogControl,
     eFCDC_LogData    = fFCDC_LogData,
     eFCDC_LogAll     = fFCDC_LogAll
 } EFCDC_OldFlags;
 
 
-/* Create new CONNECTOR structure to handle ftp download transfer.
+/* Create new CONNECTOR structure to handle ftp transfers,
+ * both download and upload.
  * Return NULL on error.
  */
-extern NCBI_XCONNECT_EXPORT CONNECTOR FTP_CreateDownloadConnector
+extern NCBI_XCONNECT_EXPORT CONNECTOR FTP_CreateConnector
 (const char*    host,     /* hostname, required                             */
  unsigned short port,     /* port #, 21 [standard] if 0 passed here         */
  const char*    user,     /* username, "ftp" [==anonymous] by default       */
@@ -78,6 +80,19 @@ extern NCBI_XCONNECT_EXPORT CONNECTOR FTP_CreateDownloadConnector
 );
 
 
+#ifndef NCBI_DEPRECATED
+#  define NCBI_FTP_CONNECTOR_DEPRECATED
+#else
+#  define NCBI_FTP_CONNECTOR_DEPRECATED NCBI_DEPRECATED
+#endif
+
+/* Same as above:  do not use for the obsolete naming */
+NCBI_FTP_CONNECTOR_DEPRECATED
+extern NCBI_XCONNECT_EXPORT CONNECTOR FTP_CreateDownloadConnector
+(const char* host, unsigned short port, const char* user,
+ const char* pass, const char*    path, TFCDC_Flags flag);
+
+
 #ifdef __cplusplus
 }  /* extern "C" */
 #endif
diff --git a/connect/ncbi_host_info.h b/connect/ncbi_host_info.h
index ed9984f..e77b8f0 100644
--- a/connect/ncbi_host_info.h
+++ b/connect/ncbi_host_info.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_HOST_INFO__H
 #define CONNECT___NCBI_HOST_INFO__H
 
-/* $Id: ncbi_host_info.h,v 6.10 2009/02/03 16:39:35 kazimird Exp $
+/* $Id: ncbi_host_info.h,v 6.11 2009/09/30 20:24:38 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -58,6 +58,12 @@ struct SHostInfoTag;  /*forward declaration of an opaque private structure*/
 typedef struct SHostInfoTag* HOST_INFO; /*handle for the user code use*/
 
 
+/* Return official host address or 0 if unknown.
+ */
+extern NCBI_XCONNECT_EXPORT
+unsigned int HINFO_HostAddr(const HOST_INFO host_info);
+
+
 /* Return CPU count or -1 if an error occurred.
  */
 extern NCBI_XCONNECT_EXPORT
diff --git a/connect/ncbi_http_connector.c b/connect/ncbi_http_connector.c
index e345524..b81a285 100644
--- a/connect/ncbi_http_connector.c
+++ b/connect/ncbi_http_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_http_connector.c,v 6.96 2009/07/06 18:49:30 kazimird Exp $
+/* $Id: ncbi_http_connector.c,v 6.107 2010/06/08 15:14:44 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -36,6 +36,7 @@
 #include "ncbi_ansi_ext.h"
 #include "ncbi_comm.h"
 #include "ncbi_priv.h"
+#include <connect/ncbi_base64.h>
 #include <connect/ncbi_http_connector.h>
 #include <ctype.h>
 #include <errno.h>
@@ -65,13 +66,6 @@ typedef enum {
     eRM_WaitCalled = 2
 } EReadMode;
 
-typedef enum {
-    eRetry_None = 0,
-    eRetry_Redirect,
-    eRetry_Authenticate,
-    eRetry_ProxyAuthenticate
-} ERetry;
-
 
 /* All internal data necessary to perform the (re)connect and I/O
  *
@@ -94,10 +88,12 @@ typedef struct {
     unsigned             error_header:1;  /* only err.HTTP header on SOME dbg*/
     EBCanConnect         can_connect:2;   /* whether more conns permitted    */
     unsigned             read_header:1;   /* whether reading header          */
-    unsigned             auth_sent:1;     /* authenticate sent               */
     unsigned             shut_down:1;     /* whether shut down for write     */
-    unsigned             reserved:10;     /* MBZ                             */
-    unsigned short       failure_count;   /* incr each failure since open    */
+    unsigned             auth_done:1;     /* website authorization sent      */
+    unsigned       proxy_auth_done:1;     /* proxy authorization sent        */
+    unsigned             reserved:6;      /* MBZ                             */
+    unsigned             minor_fault:3;   /* incr each min failure since maj */
+    unsigned short       major_fault;     /* incr each maj failure since open*/
     unsigned short       code;            /* last response code              */
 
     SOCK                 sock;         /* socket;  NULL if not in "READ" mode*/
@@ -121,37 +117,115 @@ static int                   s_MessageIssued = 0;
 static FHTTP_NcbiMessageHook s_MessageHook   = 0;
 
 
+typedef enum {
+    eRetry_None = 0,
+    eRetry_Redirect,
+    eRetry_Authenticate,
+    eRetry_ProxyAuthenticate
+} ERetry;
+
+
+typedef struct {
+    ERetry      mode;
+    const char* data;
+} SRetry;
+
+
+static int/*bool tri-state inverted*/ x_Authorize(SHttpConnector* uuu,
+                                                  const SRetry*   retry)
+{
+    static const char kProxyAuthorization[] = "Proxy-Authorization: Basic ";
+    static const char kAuthorization[]      = "Authorization: Basic ";
+    char buf[80+sizeof(uuu->net_info->user)*4], *s;
+    size_t taglen, userlen, passlen, len, n;
+    const char *tag, *user, *pass;
+
+    assert(retry  &&  retry->data);
+    assert(strncasecmp(retry->data, "basic", strcspn(retry->data," \t")) == 0);
+    switch (retry->mode) {
+    case eRetry_Authenticate:
+        if (uuu->auth_done)
+            return  1/*failed*/;
+        uuu->auth_done = 1/*true*/;
+        if (uuu->net_info->scheme != eURL_Https
+            &&  !(uuu->flags & fHCC_InsecureRedirect)) {
+            return -1/*prohibited*/;
+        }
+        tag    = kAuthorization;
+        taglen = sizeof(kAuthorization) - 1;
+        user   = uuu->net_info->user;
+        pass   = uuu->net_info->pass;
+        break;
+    case eRetry_ProxyAuthenticate:
+        if (uuu->proxy_auth_done)
+            return 1/*failed*/;
+        uuu->proxy_auth_done = 1/*true*/;
+        tag    = kProxyAuthorization;
+        taglen = sizeof(kProxyAuthorization) - 1;
+        user   = uuu->net_info->http_proxy_user;
+        pass   = uuu->net_info->http_proxy_pass;
+        break;
+    default:
+        assert(0);
+        return 1/*failed*/;
+    }
+    assert(tag  &&  user  &&  pass);
+    if (!*user)
+        return 1/*failed*/;
+    userlen = strlen(user);
+    passlen = strlen(pass);
+    s = buf + sizeof(buf) - passlen;
+    if (pass[0] == '['  &&  pass[passlen - 1] == ']') {
+        if (BASE64_Decode(pass + 1, passlen - 2, &len, s, passlen, &n)
+            &&  len == passlen - 2) {
+            len = n;
+        } else
+            len = 0;
+    } else
+        len = 0;
+    s -= userlen;
+    memcpy(--s, user, userlen);
+    s[userlen++] = ':';
+    if (!len) {
+        memcpy(s + userlen, pass, passlen);
+        len  = userlen + passlen;
+    } else
+        len += userlen;
+    /* usable room */
+    userlen = (size_t)(s - buf);
+    assert(userlen > taglen);
+    userlen -= taglen + 1;
+    BASE64_Encode(s, len, &n, buf + taglen, userlen, &passlen, 0);
+    if (len != n  ||  buf[taglen + passlen])
+        return 1/*failed*/;
+    memcpy(buf, tag, taglen);
+    return !ConnNetInfo_OverrideUserHeader(uuu->net_info, buf);
+}
+
+
 /* Try to fix connection parameters (called for an unconnected connector) */
-static int/*bool*/ s_Adjust(SHttpConnector* uuu,
-                            char**          retry,
+static EIO_Status s_Adjust(SHttpConnector* uuu,
+                           const SRetry*   retry,
                             EReadMode       read_mode)
 {
-    assert(!uuu->sock  &&  uuu->can_connect != eCC_None);
+    EIO_Status status;
 
-    /* we're here because something is going wrong */
-    if (++uuu->failure_count >= uuu->net_info->max_try) {
-        if (*retry)
-            free(*retry);
-        if (read_mode != eRM_DropUnread  &&  uuu->failure_count > 1) {
-            CORE_LOGF_X(1, eLOG_Error,
-                        ("[HTTP]  Too many failed attempts (%d), giving up",
-                         uuu->failure_count));
-        }
-        uuu->can_connect = eCC_None;
-        return 0/*failure*/;
-    }
+    assert(!uuu->sock  &&  uuu->can_connect != eCC_None);
 
+    if (retry  &&  retry->mode  &&  ++uuu->minor_fault < 3) {
+        int fail;
     /* adjust info before yet another connection attempt */
-    if (*retry) {
-        int fail/*parse*/;
-        assert(**retry);
-        if (**retry != '?') {
-            if (uuu->net_info->req_method == eReqMethod_Get  ||  !uuu->w_len
-                ||  (uuu->flags & fHCC_InsecureRedirect)) {
+        switch (retry->mode) {
+        case eRetry_Redirect:
+            if (retry->data  &&  retry->data[0] != '?') {
+                if (uuu->net_info->req_method == eReqMethod_Get
+                    ||  (uuu->flags & fHCC_InsecureRedirect)
+                    ||  !uuu->w_len) {
                 int secure = uuu->net_info->scheme == eURL_Https ? 1 : 0;
                 *uuu->net_info->args = '\0'/*arguments not inherited*/;
-                fail = !ConnNetInfo_ParseURL(uuu->net_info, *retry);
-                if (!fail  &&  secure  &&  uuu->net_info->scheme != eURL_Https
+                    fail = !ConnNetInfo_ParseURL(uuu->net_info, retry->data);
+                    if (!fail  &&  secure
+                        &&  uuu->net_info->scheme != eURL_Https
                     &&  !(uuu->flags & fHCC_InsecureRedirect)) {
                     fail = -1;
                 }
@@ -161,29 +235,73 @@ static int/*bool*/ s_Adjust(SHttpConnector* uuu,
             fail = 1;
         if (fail) {
             CORE_LOGF_X(2, eLOG_Error,
-                        ("[HTTP]  %s redirect to \"%s\"",
-                         fail < 0 ? "Prohibited" : "Cannot", *retry));
-        }
-        free(*retry);
+                            ("[HTTP]  %s redirect to %s%s%s",
+                             fail < 0 ? "Prohibited" : "Cannot",
+                             retry->data ? "\""        : "<",
+                             retry->data ? retry->data : "NULL",
+                             retry->data ? "\""        : ">"));
+                status = eIO_Closed;
+            } else
+                status = eIO_Success;
+            break;
+        case eRetry_Authenticate:
+        case eRetry_ProxyAuthenticate:
+            if (retry->data  &&  strncasecmp(retry->data, "basic ", 6) == 0) {
+                fail = x_Authorize(uuu, retry);
+                if (fail < 0)
+                    fail = 2;
+            } else
+                fail = -1;
         if (fail) {
+                CORE_LOGF_X(3, eLOG_Error,
+                            ("[HTTP]  %s %s %c%s%c",
+                             retry->mode == eRetry_Authenticate
+                             ? "Authorization" : "Proxy authorization",
+                             fail < 0 ? "not yet implemented" :
+                             fail > 1 ? "prohibited" : "failed",
+                             "(<"[!retry->data],
+                             retry->data ? retry->data : "NULL",
+                             ")>"[!retry->data]));
+                status = fail < 0 ? eIO_NotSupported : eIO_Closed;
+            } else
+                status = eIO_Success;
+            break;
+        default:
+            status = eIO_Unknown;
+            assert(0);
+            break;
+        }
+        if (status != eIO_Success) {
             uuu->can_connect = eCC_None;
-            return 0/*failure*/;
+            return status;
         }
+    } else {
+        const char* msg;
+        uuu->minor_fault = 0;
+        /* we're here because something is going wrong */
+        if (++uuu->major_fault >= uuu->net_info->max_try) {
+            msg = read_mode != eRM_DropUnread  &&  uuu->major_fault > 1
+                ? "[HTTP]  Too many failed attempts (%d), giving up" : "";
     } else if (!uuu->adjust_net_info
                ||  uuu->adjust_net_info(uuu->net_info,
                                         uuu->adjust_data,
-                                        uuu->failure_count) == 0) {
-        if (read_mode != eRM_DropUnread  &&  uuu->failure_count > 1) {
-            CORE_LOGF_X(3, eLOG_Error,
-                        ("[HTTP]  Retry attempts (%d) exhausted, giving up",
-                         uuu->failure_count));
+                                            uuu->major_fault) == 0) {
+            msg = read_mode != eRM_DropUnread  &&  uuu->major_fault > 1
+                ? "[HTTP]  Retry attempts (%d) exhausted, giving up" : "";
+        } else
+            msg = 0;
+        if (msg) {
+            if (*msg) {
+                CORE_LOGF_X(1, eLOG_Error,
+                            (msg, uuu->major_fault));
         }
         uuu->can_connect = eCC_None;
-        return 0/*failure*/;
+            return eIO_Closed;
+        }
     }
 
-    ConnNetInfo_AdjustForHttpProxy(uuu->net_info);
-    return 1/*success*/;
+    return ConnNetInfo_AdjustForHttpProxy(uuu->net_info)
+        ? eIO_Success : eIO_Unknown;
 }
 
 
@@ -192,6 +310,9 @@ static void s_DropConnection(SHttpConnector* uuu, const STimeout* timeout)
 {
     assert(uuu->sock);
     BUF_Erase(uuu->http);
+    if (uuu->read_header)
+        SOCK_Abort(uuu->sock);
+    else
     SOCK_SetTimeout(uuu->sock, eIO_Close, timeout);
     SOCK_Close(uuu->sock);
     uuu->sock = 0;
@@ -210,6 +331,7 @@ static EIO_Status s_Connect(SHttpConnector* uuu,
 
     assert(!uuu->sock);
     if (uuu->can_connect == eCC_None) {
+        if (read_mode == eRM_Regular)
         CORE_LOG_X(5, eLOG_Error, "[HTTP]  Connector no longer usable");
         return eIO_Closed;
     }
@@ -218,7 +340,6 @@ static EIO_Status s_Connect(SHttpConnector* uuu,
     for (;;) {
         int/*bool*/ reset_user_header = 0;
         char*       http_user_header = 0;
-        char*       null = 0;
         TSOCK_Flags flags;
 
         uuu->w_len = BUF_Size(uuu->w_buf);
@@ -262,8 +383,8 @@ static EIO_Status s_Connect(SHttpConnector* uuu,
             break/*success*/;
 
         /* connection failed, no socket was created */
-        if (!s_Adjust(uuu, &null, read_mode))
-            break/*closed*/;
+        if (s_Adjust(uuu, 0, read_mode) != eIO_Success)
+            break;
     }
 
     return status;
@@ -283,7 +404,6 @@ static EIO_Status s_ConnectAndSend(SHttpConnector* uuu,
     for (;;) {
         size_t body_size;
         char   buf[4096];
-        char*  null = 0;
 
         if (!uuu->sock) {
             if ((status = s_Connect(uuu, read_mode)) != eIO_Success)
@@ -344,25 +464,73 @@ static EIO_Status s_ConnectAndSend(SHttpConnector* uuu,
                     ("[HTTP]  Error %s (%s)", buf, IO_StatusStr(status)));
 
         /* write failed; close and try to use another server */
-        SOCK_Abort(uuu->sock);
         s_DropConnection(uuu, 0/*no wait*/);
-        if (!s_Adjust(uuu, &null, read_mode)) {
-            uuu->can_connect = eCC_None;
-            status = eIO_Closed;
-            break;
-        }
+        if ((status = s_Adjust(uuu, 0, read_mode)) != eIO_Success)
+            break/*closed*/;
     }
 
     return status;
 }
 
 
+static int/*bool*/ s_IsValidParam(const char* param, size_t parlen)
+{
+    const char* e = (const char*) memchr(param, '=', parlen);
+    size_t toklen;
+    if (!e  ||  e == param)
+        return 0/*false*/;
+    if ((toklen = (size_t)(++e - param)) >= parlen)
+        return 0/*false*/;
+    assert(!isspace((unsigned char)(*param)));
+    if (strcspn(param, " \t") < toklen)
+        return 0/*false*/;
+    if (*e == '\''  ||  *e == '"') {
+        /* a quoted string */
+        toklen = parlen - toklen;
+        if (!(e = (const char*) memchr(e + 1, *e, --toklen)))
+            return 0/*false*/;
+        e++/*skip the quote*/;
+    } else
+        e += strcspn(e, " \t");
+    if (e != param + parlen  &&  e + strspn(e, " \t") != param + parlen)
+        return 0/*false*/;
+    return 1/*true*/;
+}
+
+
+static int/*bool*/ s_IsValidAuth(const char* challenge, size_t len)
+{
+    /* Challenge must contain a scheme name token and a non-empty param
+     * list (comma-separated pairs token={token|quoted_string}), with at
+     * least one parameter being named "realm=".
+     */
+    size_t word = strcspn(challenge, " \t");
+    int retval = 0/*false*/;
+    if (word < len) {
+        /* 1st word is always the scheme name */
+        const char* param = challenge + word;
+        for (param += strspn(param, " \t");  param < challenge + len;
+             param += strspn(param, ", \t")) {
+            size_t parlen = (size_t)(challenge + len - param);
+            const char* c = (const char*) memchr(param, ',', parlen);
+            if (c)
+                parlen = (size_t)(c - param);
+            if (!s_IsValidParam(param, parlen))
+                return 0/*false*/;
+            if (parlen > 6  &&  strncasecmp(param, "realm=", 6) == 0)
+                retval = 1/*true, but keep scanning*/;
+            param += c ? ++parlen : parlen;
+        }
+    }
+    return retval;
+}
+
+
 /* Parse HTTP header */
 static EIO_Status s_ReadHeader(SHttpConnector* uuu,
-                               char**          retry,
+                               SRetry*         retry,
                                EReadMode       read_mode)
 {
-    ERetry     redirect = eRetry_None; 
     int        server_error = 0;
     int        http_status;
     EIO_Status status;
@@ -370,7 +538,8 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu,
     size_t     size;
 
     assert(uuu->sock  &&  uuu->read_header);
-    *retry = 0;
+    retry->mode = eRetry_None;
+    retry->data = 0;
 
     /* line by line HTTP header input */
     for (;;) {
@@ -418,12 +587,12 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu,
         http_status = -1;
     if (http_status < 200  ||  299 < http_status) {
         server_error = http_status;
-        if      (http_status == 301  ||  http_status == 302)
-            redirect = eRetry_Redirect;
+        if (http_status == 301  ||  http_status == 302  ||  http_status == 307)
+            retry->mode = eRetry_Redirect;
         else if (http_status == 401)
-            redirect = eRetry_Authenticate;
+            retry->mode = eRetry_Authenticate;
         else if (http_status == 407)
-            redirect = eRetry_ProxyAuthenticate;
+            retry->mode = eRetry_ProxyAuthenticate;
         else if (http_status < 0  ||  http_status == 403 || http_status == 404)
             uuu->net_info->max_try = 0;
     }
@@ -438,7 +607,7 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu,
             header_header = "HTTP header";
         else if (uuu->flags & fHCC_KeepHeader)
             header_header = "HTTP header (error)";
-        else if (uuu->code == 301  ||  uuu->code == 302)
+        else if (uuu->code == 301  ||  uuu->code == 302  ||  uuu->code == 307)
             header_header = "HTTP header (moved)";
         else if (!uuu->net_info->max_try)
             header_header = "HTTP header (unrecoverable error)";
@@ -495,7 +664,7 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu,
         server_error = 1/*fake, but still boolean true*/;
     }
 
-    if (redirect == eRetry_Redirect) {
+    if (retry->mode == eRetry_Redirect) {
         /* parsing "Location" pointer */
         static const char kLocationTag[] = "\nLocation: ";
         char* s;
@@ -506,7 +675,8 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu,
                     location++;
                 if (!(s = strchr(location, '\r')))
                     s = strchr(location, '\n');
-                assert(s);
+                if (!s)
+                    break;
                 do {
                     if (!isspace((unsigned char) s[-1]))
                         break;
@@ -515,25 +685,46 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu,
                     size_t len = (size_t)(s - location);
                     memmove(header, location, len);
                     header[len] = '\0';
-                    *retry = header;
+                    retry->data = header;
                 }
                 break;
             }
         }
-    } else if (redirect != eRetry_None) {
+    } else if (retry->mode != eRetry_None) {
         /* parsing "Authenticate" tags */
         static const char kAuthenticateTag[] = "-Authenticate: ";
         char* s;
         for (s = strchr(header, '\n');  s  &&  *s;  s = strchr(s + 1, '\n')) {
-            if (strncasecmp(s + (redirect == eRetry_Authenticate ? 4 : 6),
+            if (strncasecmp(s + (retry->mode == eRetry_Authenticate ? 4 : 6),
                             kAuthenticateTag, sizeof(kAuthenticateTag)-1)==0){
-                if ((redirect == eRetry_Authenticate
-                     &&  strncasecmp(s, "\nWWW",   4) != 0)  ||
-                    (redirect == eRetry_ProxyAuthenticate
-                     &&  strncasecmp(s, "\nProxy", 6) != 0)) {
-                    continue;
+                if ((retry->mode == eRetry_Authenticate
+                     &&  strncasecmp(s, "\nWWW",   4) == 0)  ||
+                    (retry->mode == eRetry_ProxyAuthenticate
+                     &&  strncasecmp(s, "\nProxy", 6) == 0)) {
+                    char* challenge = s + sizeof(kAuthenticateTag) - 1, *e;
+                    challenge += retry->mode == eRetry_Authenticate ? 4 : 6;
+                    while (*challenge && isspace((unsigned char)(*challenge)))
+                        challenge++;
+                    if (!(e = strchr(challenge, '\r')))
+                        e = strchr(challenge, '\n');
+                    else
+                        s = e;
+                    if (!e)
+                        break;
+                    do {
+                        if (!isspace((unsigned char) e[-1]))
+                            break;
+                    } while (--e > challenge);
+                    if (e != challenge) {
+                        size_t len = (size_t)(e - challenge);
+                        if (s_IsValidAuth(challenge, len)) {
+                            memmove(header, challenge, len);
+                            header[len] = '\0';
+                            retry->data = header;
+                            break;
+                        }
+                    }
                 }
-                /* TODO */
             }
         }
     } else if (!server_error) {
@@ -564,7 +755,7 @@ static EIO_Status s_ReadHeader(SHttpConnector* uuu,
             }
         }
     }
-    if (!*retry)
+    if (!retry->data)
         free(header);
 
     /* skip & printout the content, if server error was flagged */
@@ -612,9 +803,11 @@ static EIO_Status s_PreRead(SHttpConnector* uuu,
                             EReadMode       read_mode)
 {
     EIO_Status status;
-    char* retry;
 
     for (;;) {
+        EIO_Status adjust_status;
+        SRetry     retry;
+
         status = s_ConnectAndSend(uuu, read_mode);
         if (!uuu->sock) {
             assert(status != eIO_Success);
@@ -627,29 +820,34 @@ static EIO_Status s_PreRead(SHttpConnector* uuu,
         }
 
         /* set timeout */
-        SOCK_SetTimeout(uuu->sock, eIO_Read, timeout);
+        verify(SOCK_SetTimeout(uuu->sock, eIO_Read, timeout) == eIO_Success);
 
         if (!uuu->read_header)
             break;
 
         if ((status = s_ReadHeader(uuu, &retry, read_mode)) == eIO_Success) {
             /* pending output data no longer needed */
-            assert(!uuu->read_header  &&  !retry);
+            assert(!uuu->read_header  &&  !retry.mode);
             BUF_Erase(uuu->w_buf);
             break;
         }
+        assert(status != eIO_Timeout  ||  !retry.mode);
         /* if polling then bail out with eIO_Timeout */
         if (status == eIO_Timeout
             &&  (read_mode == eRM_WaitCalled
                  ||  (timeout  &&  !(timeout->sec | timeout->usec)))) {
+            assert(!retry.data);
             break;
         }
 
         /* HTTP header read error; disconnect and try to use another server */
-        SOCK_Abort(uuu->sock);
         s_DropConnection(uuu, 0/*no wait*/);
-        if (!s_Adjust(uuu, &retry, read_mode)) {
-            uuu->can_connect = eCC_None;
+        adjust_status = s_Adjust(uuu, retry.mode ? &retry : 0, read_mode);
+        if (retry.data)
+            free((void*) retry.data);
+        if (adjust_status != eIO_Success) {
+            if (adjust_status != eIO_Closed)
+                status = adjust_status;
             break;
         }
     }
@@ -744,28 +942,15 @@ static EIO_Status s_Disconnect(SHttpConnector* uuu,
 }
 
 
-/* Send the accumulated output data(if any) to server, then close socket.
- * Regardless of the flush, clear both input and output buffer.
- * This function is only called to either re-open or close the connector.
+/* Send the accumulated output data(if any) to server, then close the socket.
+ * Regardless of the flush, clear both input and output buffers.
  */
 static void s_FlushAndDisconnect(SHttpConnector* uuu,
-                                 int/*bool*/     close,
                                  const STimeout* timeout)
 {
-    /* store timeouts for later use */
-    if (timeout) {
-        uuu->oo_timeout = *timeout;
-        uuu->o_timeout  = &uuu->oo_timeout;
-        uuu->ww_timeout = *timeout;
-        uuu->w_timeout  = &uuu->ww_timeout;
-    } else {
-        uuu->o_timeout  = timeout;
-        uuu->w_timeout  = timeout;
-    }
-
-    if (close  &&  uuu->can_connect != eCC_None  &&  !uuu->sock
+    if (uuu->can_connect != eCC_None  &&  !uuu->sock
         &&  ((uuu->flags & fHCC_SureFlush)  ||  BUF_Size(uuu->w_buf))) {
-        /* "WRITE" mode and data (or just flag) pending */
+        /* "WRITE" mode and data (or just flag) is still pending */
         s_PreRead(uuu, timeout, eRM_DropUnread);
     }
     s_Disconnect(uuu, timeout, eRM_DropUnread);
@@ -810,11 +995,6 @@ extern "C" {
     static void        s_Setup      (SMetaConnector *meta,
                                      CONNECTOR connector);
     static void        s_Destroy    (CONNECTOR connector);
-#  ifdef IMPLEMENTED__CONN_WaitAsync
-    static EIO_Status s_VT_WaitAsync(CONNECTOR     connector,
-                                     FConnectorAsyncHandler  func,
-                                     SConnectorAsyncHandler* data);
-#  endif
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
@@ -831,26 +1011,7 @@ static const char* s_VT_GetType
 static char* s_VT_Descr
 (CONNECTOR connector)
 {
-    SHttpConnector* uuu = (SHttpConnector*) connector->handle;
-    size_t len = 8/*"http[s]://"*/ + strlen(uuu->net_info->host) +
-        (uuu->net_info->port ? 6/*:port*/ : 0) +
-        (uuu->net_info->http_proxy_adjusted ? 2 : 0) +
-        strlen(uuu->net_info->path) + 1 +
-        (*uuu->net_info->args ? 2 + strlen(uuu->net_info->args) : 1);
-    char* buf = (char*) malloc(len);
-    if (buf) {
-        len = sprintf(buf, "http%s://%s",
-                      &"s"[uuu->net_info->scheme != eURL_Https],
-                      uuu->net_info->host);
-        if (uuu->net_info->port)
-            len += sprintf(&buf[len], ":%hu", uuu->net_info->port);
-        sprintf(&buf[len], "%s%s%s%s%s", uuu->net_info->http_proxy_adjusted
-                ? "<" : *uuu->net_info->path != '/'
-                ? "/" : "", uuu->net_info->path,
-                &"?"[!*uuu->net_info->args], uuu->net_info->args,
-                ">" + !uuu->net_info->http_proxy_adjusted);
-    }
-    return buf;
+    return ConnNetInfo_URL(((SHttpConnector*) connector->handle)->net_info);
 }
 
 
@@ -861,15 +1022,28 @@ static EIO_Status s_VT_Open
     SHttpConnector* uuu = (SHttpConnector*) connector->handle;
 
     /* NOTE: the real connect will be performed on the first "READ", or
-     * "CLOSE", or on "WAIT" on read -- see in "s_ConnectAndSend()";
-     * we just close underlying socket and prepare to open it later */
-    s_FlushAndDisconnect(uuu, 0/*open*/, timeout);
+     * "CLOSE", or on "WAIT" on read -- see in "s_ConnectAndSend()" */
+
+    assert(!uuu->sock);
+
+    /* store timeouts for later use */
+    if (timeout) {
+        uuu->oo_timeout = *timeout;
+        uuu->o_timeout  = &uuu->oo_timeout;
+        uuu->ww_timeout = *timeout;
+        uuu->w_timeout  = &uuu->ww_timeout;
+    } else {
+        uuu->o_timeout  = timeout;
+        uuu->w_timeout  = timeout;
+    }
 
     /* reset the auto-reconnect feature */
-    uuu->can_connect = uuu->flags & fHCC_AutoReconnect
-        ? eCC_Unlimited : eCC_Once;
-    uuu->failure_count = 0;
-    uuu->auth_sent = 0;
+    uuu->can_connect = (uuu->flags & fHCC_AutoReconnect
+                        ? eCC_Unlimited : eCC_Once);
+    uuu->major_fault     = 0;
+    uuu->minor_fault     = 0;
+    uuu->auth_done       = 0;
+    uuu->proxy_auth_done = 0;
 
     return eIO_Success;
 }
@@ -881,19 +1055,18 @@ static EIO_Status s_VT_Wait
  const STimeout* timeout)
 {
     SHttpConnector* uuu = (SHttpConnector*) connector->handle;
+    EIO_Status status;
 
+    assert(event == eIO_Read  ||  event == eIO_Write);
     switch (event) {
     case eIO_Read:
         if (BUF_Size(uuu->r_buf))
             return eIO_Success;
         if (uuu->can_connect == eCC_None)
             return eIO_Closed;
-        if (!uuu->sock  ||  uuu->read_header) {
-            EIO_Status status = s_PreRead(uuu, timeout, eRM_WaitCalled);
-            if (status != eIO_Success)
+        if ((status = s_PreRead(uuu, timeout, eRM_WaitCalled)) != eIO_Success)
                 return status;
             assert(uuu->sock);
-        }
         return SOCK_Wait(uuu->sock, eIO_Read, timeout);
     case eIO_Write:
         /* Return 'Closed' if no more writes are allowed (and now - reading) */
@@ -901,9 +1074,9 @@ static EIO_Status s_VT_Wait
             ||  (uuu->sock  &&  uuu->can_connect == eCC_Once)
             ? eIO_Closed : eIO_Success;
     default:
+        assert(0);
         break;
     }
-    assert(0);
     return eIO_InvalidArg;
 }
 
@@ -930,14 +1103,13 @@ static EIO_Status s_VT_Write
         return eIO_Closed; /* no more connects permitted */
 
     /* accumulate all output in the memory buffer */
-    if (uuu->flags & fHCC_UrlEncodeOutput) {
+    if (size  &&  (uuu->flags & fHCC_UrlEncodeOutput)) {
         /* with URL-encoding */
         size_t dst_size = 3 * size;
         void* dst = malloc(dst_size);
-        size_t dst_written;
-        URL_Encode(buf, size, n_written, dst, dst_size, &dst_written);
-        assert(*n_written == size);
-        if (!BUF_Write(&uuu->w_buf, dst, dst_written)) {
+        URL_Encode(buf, size, n_written, dst, dst_size, &dst_size);
+        if (*n_written != size  ||  !BUF_Write(&uuu->w_buf, dst, dst_size)) {
+            if (dst)
             free(dst);
             return eIO_Unknown;
         }
@@ -955,7 +1127,6 @@ static EIO_Status s_VT_Write
         uuu->w_timeout  = &uuu->ww_timeout;
     } else
         uuu->w_timeout  = timeout;
-
     return eIO_Success;
 }
 
@@ -1025,23 +1196,11 @@ static EIO_Status s_VT_Close
 (CONNECTOR       connector,
  const STimeout* timeout)
 {
-    s_FlushAndDisconnect((SHttpConnector*) connector->handle,
-                         1/*close*/, timeout);
+    s_FlushAndDisconnect((SHttpConnector*) connector->handle, timeout);
     return eIO_Success;
 }
 
 
-#ifdef IMPLEMENTED__CONN_WaitAsync
-static EIO_Status s_VT_WaitAsync
-(void*                   connector,
- FConnectorAsyncHandler  func,
- SConnectorAsyncHandler* data)
-{
-    return eIO_NotSupported;
-}
-#endif
-
-
 static void s_Setup(SMetaConnector *meta, CONNECTOR connector)
 {
     SHttpConnector* uuu = (SHttpConnector*) connector->handle;
@@ -1056,9 +1215,6 @@ static void s_Setup(SMetaConnector *meta, CONNECTOR connector)
     CONN_SET_METHOD(meta, read,       s_VT_Read,      connector);
     CONN_SET_METHOD(meta, status,     s_VT_Status,    connector);
     CONN_SET_METHOD(meta, close,      s_VT_Close,     connector);
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
-#endif
     CONN_SET_DEFAULT_TIMEOUT(meta, uuu->net_info->timeout);
 }
 
@@ -1066,6 +1222,7 @@ static void s_Setup(SMetaConnector *meta, CONNECTOR connector)
 static void s_Destroy(CONNECTOR connector)
 {
     SHttpConnector* uuu = (SHttpConnector*) connector->handle;
+    connector->handle = 0;
 
     if (uuu->adjust_cleanup)
         uuu->adjust_cleanup(uuu->adjust_data);
@@ -1074,29 +1231,46 @@ static void s_Destroy(CONNECTOR connector)
     BUF_Destroy(uuu->r_buf);
     BUF_Destroy(uuu->w_buf);
     free(uuu);
-    connector->handle = 0;
     free(connector);
 }
 
 
-/* NB: HTTP tag name misspelled as "Referer" as per the standard. */
-static void s_AddReferer(SConnNetInfo* net_info)
+/* NB: per the standard, HTTP tag name misspelled as "Referer" */
+static void s_AddRefererStripCAF(SConnNetInfo* net_info)
 {
     const char* s;
     char* referer;
-    if (!net_info  ||  !net_info->http_referer  ||  !*net_info->http_referer)
+    if (!net_info)
         return;
     if ((s = net_info->http_user_header) != 0) {
-        int/*bool*/ first;
-        for (first = 1;  *s;  first = 0) {
-            if (strncasecmp(s++, "\nReferer: " + first, 10 - first) == 0)
-                return;
-            if (!(s = strchr(s, '\n')))
+        int/*bool*/ found = 0/*false*/;
+        int/*bool*/ first = 1/*true*/;
+        while (*s) {
+            if (strncasecmp(s, "\nReferer: " + first, 10 - first) == 0) {
+                found = 1/*true*/;
+#ifdef HAVE_LIBCONNEXT
+            } else if (strncasecmp(s, "\nCAF" + first, 4 - first) == 0
+                       &&  (s[4 - first] == '-'  ||  s[4 - first] == ':')) {
+                size_t off = (size_t)(s - net_info->http_user_header);
+                ConnNetInfo_DeleteUserHeader(net_info, s + !first);
+                if (!(s = net_info->http_user_header)  ||  !*(s += off))
                 break;
+                continue;
+#else
+                break;
+#endif /*HAVE_LIBCONNEXT*/
         }
+            if (!(s = strchr(++s, '\n')))
+                break;
+            first = 0/*false*/;
     }
-    if (!(referer = (char*) malloc(strlen(net_info->http_referer) + 12)))
+        if (found)
         return;
+    }
+    if (!net_info->http_referer  ||  !*net_info->http_referer  ||
+        !(referer = (char*) malloc(strlen(net_info->http_referer) + 12))) {
+        return;
+    }
     sprintf(referer, "Referer: %s\r\n", net_info->http_referer);
     ConnNetInfo_ExtendUserHeader(net_info, referer);
     free(referer);
@@ -1116,6 +1290,7 @@ static CONNECTOR s_CreateConnector
     CONNECTOR       ccc;
     SHttpConnector* uuu;
     SConnNetInfo*   xxx;
+    char*           fff;
 
     xxx = net_info ? ConnNetInfo_Clone(net_info) : ConnNetInfo_Create(0);
     if (!xxx)
@@ -1123,13 +1298,17 @@ static CONNECTOR s_CreateConnector
     if ((flags & fHCC_NoAutoRetry)  ||  !xxx->max_try)
         xxx->max_try = 1;
 
+    if ((fff = strchr(xxx->args, '#')) != 0)
+        *fff = '\0';
     if ((xxx->scheme != eURL_Unspec  && 
          xxx->scheme != eURL_Https   &&
-         xxx->scheme != eURL_Http)   ||
-        !ConnNetInfo_AdjustForHttpProxy(xxx)) {
+         xxx->scheme != eURL_Http)
+        ||  !ConnNetInfo_AdjustForHttpProxy(xxx)) {
         ConnNetInfo_Destroy(xxx);
         return 0;
     }
+    if (xxx->scheme == eURL_Unspec)
+        xxx->scheme = eURL_Http;
 
     if (!(ccc = (SConnector    *) malloc(sizeof(SConnector    )))  ||
         !(uuu = (SHttpConnector*) malloc(sizeof(SHttpConnector)))) {
@@ -1140,15 +1319,11 @@ static CONNECTOR s_CreateConnector
     }
     if (user_header)
         ConnNetInfo_OverrideUserHeader(xxx, user_header);
-    s_AddReferer(xxx);
+    s_AddRefererStripCAF(xxx);
 
     ConnNetInfo_GetValue(0, "HTTP_INSECURE_REDIRECT", value, sizeof(value),"");
-    if (*value  &&  (strcmp    (value, "1")    == 0  ||
-                     strcasecmp(value, "true") == 0  ||
-                     strcasecmp(value, "yes")  == 0  ||
-                     strcasecmp(value, "on")   == 0)) {
+    if (ConnNetInfo_Boolean(value))
         flags |= fHCC_InsecureRedirect;
-    }
 
     /* initialize internal data structure */
     uuu->net_info         = xxx;
@@ -1160,13 +1335,10 @@ static CONNECTOR s_CreateConnector
 
     uuu->flags            = flags;
     uuu->reserved         = 0;
-    uuu->can_connect      = eCC_Once;         /* will be properly set at open*/
+    uuu->can_connect     = eCC_None;         /* will be properly set at open*/
 
     ConnNetInfo_GetValue(0, "HTTP_ERROR_HEADER_ONLY", value, sizeof(value),"");
-    uuu->error_header = (*value  &&  (strcmp    (value, "1")    == 0  ||
-                                      strcasecmp(value, "true") == 0  ||
-                                      strcasecmp(value, "yes")  == 0  ||
-                                      strcasecmp(value, "on")   == 0));
+    uuu->error_header    = ConnNetInfo_Boolean(value);
 
     uuu->sock             = 0;
     uuu->o_timeout        = kDefaultTimeout;  /* deliberately bad values --  */
diff --git a/connect/ncbi_memory_connector.c b/connect/ncbi_memory_connector.c
index 7202719..eaabc48 100644
--- a/connect/ncbi_memory_connector.c
+++ b/connect/ncbi_memory_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_memory_connector.c,v 6.12 2009/06/23 16:04:40 kazimird Exp $
+/* $Id: ncbi_memory_connector.c,v 6.13 2010/02/01 13:54:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -82,11 +82,6 @@ extern "C" {
     static void        s_Setup      (SMetaConnector* meta,
                                      CONNECTOR       connector);
     static void        s_Destroy    (CONNECTOR       connector);
-#  ifdef IMPLEMENTED__CONN_WaitAsync
-    static EIO_Status s_VT_WaitAsync(void*                   connector,
-                                     FConnectorAsyncHandler  func,
-                                     SConnectorAsyncHandler* data);
-#  endif
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
@@ -113,6 +108,29 @@ static EIO_Status s_VT_Open
 
 
 /*ARGSUSED*/
+static EIO_Status s_VT_Wait
+(CONNECTOR       connector,
+ EIO_Event       event,
+ const STimeout* timeout)
+{
+    SMemoryConnector* xxx = (SMemoryConnector*) connector->handle;
+    assert(event == eIO_Read  ||  event == eIO_Write);
+    switch (event) {
+    case eIO_Read:
+        if (!BUF_Size(xxx->buf))
+            return eIO_Closed;
+        /*FALLTHRU*/
+    case eIO_Write:
+        return eIO_Success;
+    default:
+        assert(0);
+        break;
+    }
+    return eIO_InvalidArg;
+}
+
+
+/*ARGSUSED*/
 static EIO_Status s_VT_Write
 (CONNECTOR       connector,
  const void*     buf,
@@ -148,25 +166,13 @@ static EIO_Status s_VT_Read
     if ( !size )
         return eIO_Success;
 
-    xxx->r_status = (!(*n_read = BUF_Read(xxx->buf, buf, size))
-                     ? eIO_Closed : eIO_Success);
+    *n_read = BUF_Read(xxx->buf, buf, size);
+    xxx->r_status = *n_read ? eIO_Success : eIO_Closed;
 
     return xxx->r_status;
 }
 
 
-/*ARGSUSED*/
-static EIO_Status s_VT_Wait
-(CONNECTOR       connector,
- EIO_Event       event,
- const STimeout* timeout)
-{
-    SMemoryConnector* xxx = (SMemoryConnector*) connector->handle;
-    return event == eIO_Read  &&  !BUF_Size(xxx->buf)
-        ? eIO_Closed : eIO_Success;
-}
-
-
 static EIO_Status s_VT_Status
 (CONNECTOR connector,
  EIO_Event dir)
@@ -179,8 +185,9 @@ static EIO_Status s_VT_Status
         return xxx->w_status;
     default:
         assert(0); /* should never happen as checked by connection */
-        return eIO_InvalidArg;
+        break;
     }
+    return eIO_InvalidArg;
 }
 
 
@@ -208,10 +215,7 @@ static void s_Setup
     CONN_SET_METHOD(meta, read,       s_VT_Read,      connector);
     CONN_SET_METHOD(meta, status,     s_VT_Status,    connector);
     CONN_SET_METHOD(meta, close,      s_VT_Close,     connector);
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
-#endif
-    meta->default_timeout = 0/*infinite*/;
+    meta->default_timeout = kInfiniteTimeout;
 }
 
 
@@ -219,10 +223,13 @@ static void s_Destroy
 (CONNECTOR connector)
 {
     SMemoryConnector* xxx = (SMemoryConnector*) connector->handle;
-    if (xxx->own_buf)
+    connector->handle = 0;
+
+    if (xxx->own_buf) {
         BUF_Destroy(xxx->buf);
+        xxx->buf = 0;
+    }
     free(xxx);
-    connector->handle = 0;
     free(connector);
 }
 
diff --git a/connect/ncbi_priv.c b/connect/ncbi_priv.c
index 0712ca7..e61ec6e 100644
--- a/connect/ncbi_priv.c
+++ b/connect/ncbi_priv.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_priv.c,v 6.14 2008/12/01 16:34:35 kazimird Exp $
+/* $Id: ncbi_priv.c,v 6.15 2010/02/03 19:09:43 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -62,6 +62,32 @@ extern int g_NCBI_ConnectSrandAddend(void)
 }
 
 
+#ifdef _DEBUG
+
+static MT_LOCK s_CoreLock = 0;
+
+extern int g_NCBI_CoreCheckLock(void)
+{
+    /* save last lock accessed */
+    s_CoreLock = g_CORE_MT_Lock;
+    return 1/*success*/;
+}
+
+
+extern int g_NCBI_CoreCheckUnlock(void)
+{
+    /* check that unlock operates on the same lock */
+    if (s_CoreLock != g_CORE_MT_Lock) {
+        CORE_LOG(eLOG_Critical, "Inconsistent use of CORE MT-Lock detected");
+        assert(0);
+        return 0/*failure*/;
+    }
+    return 1/*success*/;
+}
+
+#endif /*_DEBUG*/
+
+
 extern const char* g_CORE_Sprintf(const char* fmt, ...)
 {
     static const size_t buf_size = 4096;
diff --git a/connect/ncbi_priv.h b/connect/ncbi_priv.h
index f64f23b..644985c 100644
--- a/connect/ncbi_priv.h
+++ b/connect/ncbi_priv.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_PRIV__H
 #define CONNECT___NCBI_PRIV__H
 
-/* $Id: ncbi_priv.h,v 6.45 2009/07/06 18:49:30 kazimird Exp $
+/* $Id: ncbi_priv.h,v 6.52 2010/05/22 15:09:36 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -66,14 +66,29 @@ extern NCBI_XCONNECT_EXPORT int g_NCBI_ConnectSrandAddend(void);
  *  Multi-Thread SAFETY
  */
 
+
+#ifdef _DEBUG
+extern NCBI_XCONNECT_EXPORT int g_NCBI_CoreCheckLock  (void);
+extern NCBI_XCONNECT_EXPORT int g_NCBI_CoreCheckUnlock(void);
+#  define CORE_CHECK_LOCK   g_NCBI_CoreCheckLock()
+#  define CORE_CHECK_UNLOCK g_NCBI_CoreCheckUnlock()
+#else
+#  define CORE_CHECK_LOCK   1/*TRUE*/
+#  define CORE_CHECK_UNLOCK 1/*TRUE*/
+#endif
+
+
 /* Always use the following macros and functions to access "g_CORE_MT_Lock",
- * dont access/change it directly!
+ * do not access/change it directly!
  */
 extern NCBI_XCONNECT_EXPORT MT_LOCK g_CORE_MT_Lock;
 
-#define CORE_LOCK_WRITE  verify(MT_LOCK_Do(g_CORE_MT_Lock, eMT_Lock    ))
-#define CORE_LOCK_READ   verify(MT_LOCK_Do(g_CORE_MT_Lock, eMT_LockRead))
-#define CORE_UNLOCK      verify(MT_LOCK_Do(g_CORE_MT_Lock, eMT_Unlock  ))
+#define CORE_LOCK_WRITE  verify(CORE_CHECK_LOCK  &&                     \
+                                MT_LOCK_Do(g_CORE_MT_Lock, eMT_Lock    ))
+#define CORE_LOCK_READ   verify(CORE_CHECK_LOCK  &&                     \
+                                MT_LOCK_Do(g_CORE_MT_Lock, eMT_LockRead))
+#define CORE_UNLOCK      verify(CORE_CHECK_UNLOCK  &&                   \
+                                MT_LOCK_Do(g_CORE_MT_Lock, eMT_Unlock  ))
 
 
 
@@ -229,15 +244,15 @@ extern NCBI_XCONNECT_EXPORT const char* g_CORE_Sprintf(const char* fmt, ...)
  */
 NCBI_C_DEFINE_ERRCODE_X(Connect_Connection, 301,  32);
 NCBI_C_DEFINE_ERRCODE_X(Connect_MetaConn,   302,   2);
-NCBI_C_DEFINE_ERRCODE_X(Connect_Util,       303,  12);
+NCBI_C_DEFINE_ERRCODE_X(Connect_Util,       303,  14);
 NCBI_C_DEFINE_ERRCODE_X(Connect_Dispd,      304,   2);
-NCBI_C_DEFINE_ERRCODE_X(Connect_FTP,        305,   2);
+NCBI_C_DEFINE_ERRCODE_X(Connect_FTP,        305,   4);
 NCBI_C_DEFINE_ERRCODE_X(Connect_HeapMgr,    306,  33);
 NCBI_C_DEFINE_ERRCODE_X(Connect_HTTP,       307,  20);
 NCBI_C_DEFINE_ERRCODE_X(Connect_LB,         308,   0);
 NCBI_C_DEFINE_ERRCODE_X(Connect_Sendmail,   309,  31);
-NCBI_C_DEFINE_ERRCODE_X(Connect_Service,    310,   6);
-NCBI_C_DEFINE_ERRCODE_X(Connect_Socket,     311, 143);
+NCBI_C_DEFINE_ERRCODE_X(Connect_Service,    310,   8);
+NCBI_C_DEFINE_ERRCODE_X(Connect_Socket,     311, 147);
 NCBI_C_DEFINE_ERRCODE_X(Connect_Crypt,      312,   6);
 NCBI_C_DEFINE_ERRCODE_X(Connect_LocalNet,   313,  11);
 NCBI_C_DEFINE_ERRCODE_X(Connect_Mghbn,      319,  16);
diff --git a/connect/ncbi_sendmail.c b/connect/ncbi_sendmail.c
index dac46a6..00b9358 100644
--- a/connect/ncbi_sendmail.c
+++ b/connect/ncbi_sendmail.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_sendmail.c,v 6.42 2009/03/26 15:29:29 kazimird Exp $
+/* $Id: ncbi_sendmail.c,v 6.45 2010/04/05 13:59:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -188,11 +188,13 @@ static int/*bool*/ s_SockWrite(SOCK sock, const char* buf, size_t len)
 }
 
 
-static void s_MakeFrom(char* buf, size_t size)
+static void s_MakeFrom(char* buf, size_t size, const char* user)
 {
     size_t len;
 
-    if (!CORE_GetUsername(buf, size)  ||  !*buf)
+    if (user  &&  *user)
+        strncpy0(buf, user, size - 1);
+    else if (!CORE_GetUsername(buf, size)  ||  !*buf)
         strncpy0(buf, "anonymous", size - 1);
     len = strlen(buf);
     size -= len;
@@ -201,19 +203,32 @@ static void s_MakeFrom(char* buf, size_t size)
         *buf++ = '@';
         if ((!SOCK_gethostbyaddr(0, buf, size)  ||  !strchr(buf, '.'))
             &&  SOCK_gethostname(buf, size) != 0) {
+            const char* host = getenv("HOSTNAME");
+            if (!host  &&  !(host = getenv("HOST")))
             *--buf = '\0';
+            else
+                strncpy0(buf, host, size - 1);
         }
     }
 }
 
 
+/* FIXME:  To remove altogether */
+#undef SendMailInfo_Init
 SSendMailInfo* SendMailInfo_Init(SSendMailInfo* info)
 {
+    return SendMailInfo_InitEx(info, 0);
+}
+
+
+SSendMailInfo* SendMailInfo_InitEx(SSendMailInfo* info,
+                                   const char*    user)
+{
     if (info) {
         info->magic_number    = MX_MAGIC_NUMBER;
         info->cc              = 0;
         info->bcc             = 0;
-        s_MakeFrom(info->from, sizeof(info->from));
+        s_MakeFrom(info->from, sizeof(info->from), user);
         info->header          = 0;
         info->body_size       = 0;
         info->mx_host         = "mailgw.ncbi.nlm.nih.gov";
@@ -372,6 +387,7 @@ const char* CORE_SendMailEx(const char*          to,
         SENDMAIL_RETURN(8, "Cannot connect to sendmail");
     }
     SOCK_SetTimeout(sock, eIO_ReadWrite, &info->mx_timeout);
+    SOCK_SetTimeout(sock, eIO_Close,     &info->mx_timeout);
 
     /* Follow the protocol conversation, RFC821 */
     if (!SENDMAIL_READ_RESPONSE(220, 0, buffer))
diff --git a/connect/ncbi_sendmail.h b/connect/ncbi_sendmail.h
index 24ce278..7589f30 100644
--- a/connect/ncbi_sendmail.h
+++ b/connect/ncbi_sendmail.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_SENDMAIL__H
 #define CONNECT___NCBI_SENDMAIL__H
 
-/*  $Id: ncbi_sendmail.h,v 6.20 2006/07/13 17:54:01 lavr Exp $
+/* $Id: ncbi_sendmail.h,v 6.21 2010/04/05 13:59:32 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -97,12 +97,12 @@ typedef struct {
  * the caller's responsibility.
  */
 
-
 /* Initialize SSendMailInfo structure, setting:
  *   'magic_number' to a proper value (verified by CORE_SendMailEx()!);
  *   'cc', 'bcc', 'header' to NULL (means no recipients/additional headers);
- *   'from' filled out using the current user name (if discovered, 'anonymous'
- *          otherwise) and host in the form: username@hostname; may be later
+ *   'from' filled out using either the provided (non-empty) user name
+ *          or the name of the current user if discovered, 'anonymous'
+ *          otherwise, and host in the form: username@hostname; may be later
  *          reset by the application to "" for sending no-return messages
  *          (aka MAILER-DAEMON messages);
  *   'mx_*' filled out in accordance with some hard-coded defaults, which are
@@ -111,10 +111,12 @@ typedef struct {
  * Return value equals the argument passed in.
  * Note: This call is the only valid way to properly init SSendMailInfo.
  */
-extern NCBI_XCONNECT_EXPORT SSendMailInfo* SendMailInfo_Init
-(SSendMailInfo*       info
+extern NCBI_XCONNECT_EXPORT SSendMailInfo* SendMailInfo_InitEx
+(SSendMailInfo*       info,
+ const char*          user
  );
 
+#define SendMailInfo_Init(info)  SendMailInfo_InitEx(info, 0)
 
 /* Send a simple message to recipient(s) defined in 'to',
  * and having subject 'subject', which may be empty (both NULL and "" treated
@@ -161,71 +163,4 @@ extern NCBI_XCONNECT_EXPORT const char* CORE_SendMailEx
 
 /* @} */
 
-
-/*
- * --------------------------------------------------------------------------
- * $Log: ncbi_sendmail.h,v $
- * Revision 6.20  2006/07/13 17:54:01  lavr
- * Remove macros: MX_HOST, MX_PORT, MX_TIMEOUT, and mx_no_header
- *
- * Revision 6.19  2006/06/15 19:52:26  lavr
- * Compatibility support in SSendMailInfo::mx_options
- *
- * Revision 6.18  2006/06/15 02:56:05  lavr
- * SSendMailInfo::mx_options implemented
- *
- * Revision 6.17  2005/04/28 14:18:12  lavr
- * A bit of clarification about multiple/single email address formats
- *
- * Revision 6.16  2003/12/09 15:38:02  lavr
- * +SSendMailInfo::body_size and remarks about its use
- *
- * Revision 6.15  2003/12/04 14:54:39  lavr
- * Extend API with no-header and multiple recipient capabilities
- *
- * Revision 6.14  2003/09/02 20:45:45  lavr
- * -<connect/connect_export.h> -- now included from <connect/ncbi_types.h>
- *
- * Revision 6.13  2003/04/09 19:05:47  siyan
- * Added doxygen support
- *
- * Revision 6.12  2003/01/21 20:02:54  lavr
- * Added missing <connect/connect_export.h>
- *
- * Revision 6.11  2003/01/17 19:44:20  lavr
- * Reduce dependencies
- *
- * Revision 6.10  2003/01/08 01:59:33  lavr
- * DLL-ize CONNECT library for MSVC (add NCBI_XCONNECT_EXPORT)
- *
- * Revision 6.9  2002/09/24 15:01:17  lavr
- * File description indented uniformly
- *
- * Revision 6.8  2002/08/14 18:51:33  lavr
- * Change MX from "nes" to more generic mail hub "mailgw.ncbi.nlm.nih.gov"
- *
- * Revision 6.7  2002/08/14 16:38:55  lavr
- * Change default MX from "ncbi" to "nes"
- *
- * Revision 6.6  2002/06/12 20:07:32  lavr
- * Tiny correction of file description
- *
- * Revision 6.5  2002/06/12 19:20:12  lavr
- * Few patches in comments; guard macro name standardized; log moved down
- *
- * Revision 6.4  2001/07/10 15:07:51  lavr
- * More comments added
- *
- * Revision 6.3  2001/03/01 01:03:46  lavr
- * SendMailInfo_Init got extern
- *
- * Revision 6.2  2001/02/28 18:13:02  lavr
- * Heavily documented
- *
- * Revision 6.1  2001/02/28 00:52:37  lavr
- * Initial revision
- *
- * ==========================================================================
- */
-
 #endif /* CONNECT___NCBI_SENDMAIL__H */
diff --git a/connect/ncbi_server_info.c b/connect/ncbi_server_info.c
index a5b9d10..3102e85 100644
--- a/connect/ncbi_server_info.c
+++ b/connect/ncbi_server_info.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_server_info.c,v 6.70 2008/10/16 18:25:42 kazimird Exp $
+/* $Id: ncbi_server_info.c,v 6.71 2009/10/30 15:09:20 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -426,11 +426,11 @@ int/*bool*/ SERV_EqualInfo(const SSERV_Info *i1, const SSERV_Info *i2)
 static char* s_Ncbid_Write(size_t reserve, const USERV_Info* u)
 {
     const SSERV_NcbidInfo* info = &u->ncbid;
-    char* str = (char*) malloc(reserve + strlen(SERV_NCBID_ARGS(info))+3);
+    const char* args = SERV_NCBID_ARGS(info);
+    char* str = (char*) malloc(reserve + strlen(args) + 3);
 
     if (str) {
-        sprintf(str + reserve, "%s",
-                *SERV_NCBID_ARGS(info) ? SERV_NCBID_ARGS(info) : "''");
+        sprintf(str + reserve, "%s", *args ? args : "''");
     }
     return str;
 }
@@ -582,13 +582,13 @@ SSERV_Info* SERV_CreateStandaloneInfo(unsigned int host, unsigned short port)
 static char* s_Http_Write(size_t reserve, const USERV_Info* u)
 {
     const SSERV_HttpInfo* info = &u->http;
-    char* str = (char*) malloc(reserve + strlen(SERV_HTTP_PATH(info))+1 +
-                               strlen(SERV_HTTP_ARGS(info))+1);
+    const char* path = SERV_HTTP_PATH(info);
+    const char* args = SERV_HTTP_ARGS(info);
+    char* str = (char*) malloc(reserve + strlen(path) + strlen(args) + 2);
     if (str) {
-        int n = sprintf(str + reserve, "%s", SERV_HTTP_PATH(info));
-        
-        if (*SERV_HTTP_ARGS(info))
-            sprintf(str + reserve + n, "?%s", SERV_HTTP_ARGS(info));
+        int n = sprintf(str + reserve, "%s", path);
+        if (*args)
+            sprintf(str + reserve + n, "%s%s", &"?"[*args == '#'], args);
     }
     return str;
 }
@@ -603,21 +603,18 @@ static SSERV_Info* s_HttpAny_Read(ESERV_Type   type,
 
     if (!**str || !(path = strdup(*str)))
         return 0;
-    for (c = path; *c; c++)
+    for (c = path;  *c;  c++) {
         if (isspace((unsigned char)(*c))) {
             *c++ = '\0';
             while (*c && isspace((unsigned char)(*c)))
                 c++;
             break;
         }
+    }
     if ((args = strchr(path, '?')) != 0)
         *args++ = '\0';
-    /* Sanity check: no parameter delimiter allowed within path */
-    if (!strchr(path, '&') &&
-        (info = SERV_CreateHttpInfoEx(type, 0, 80, path, args, add)) != 0)
+    if ((info = SERV_CreateHttpInfoEx(type, 0, 80, path, args, add)) != 0)
         *str += c - path;
-    else
-        info = 0;
     free(path);
     return info;
 }
diff --git a/connect/ncbi_service.c b/connect/ncbi_service.c
index fb351ef..a4ffd15 100644
--- a/connect/ncbi_service.c
+++ b/connect/ncbi_service.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_service.c,v 6.108 2009/03/26 15:34:34 kazimird Exp $
+/* $Id: ncbi_service.c,v 6.114 2010/04/01 14:15:35 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -58,28 +58,40 @@ ESwitch SERV_DoFastOpens(ESwitch on)
 
 static char* s_ServiceName(const char* service, size_t depth)
 {
-    char*  s;
     char   buf[128];
     char   srv[128];
     size_t len;
+    char*  s;
 
-    if (++depth > 8 || !service || !*service ||
+    if (depth > 7) {
+        CORE_LOGF_X(7, eLOG_Error,
+                    ("[%s]  Maximal service name recursion depth reached: %lu",
+                     service, (unsigned long) depth));
+        return 0/*failure*/;
+    }
+    if (!service  ||  !*service  ||
         (len = strlen(service)) + sizeof(CONN_SERVICE_NAME) >= sizeof(buf)) {
+        CORE_LOGF_X(8, eLOG_Error,
+                    ("%s%s%s%s service name",
+                     !service  ||  !*service ? "" : "[",
+                     !service ? "" : service,
+                     !service  ||  !*service ? "" : "]  ",
+                     !service ? "NULL" : !*service ? "Empty" : "Too long"));
         return 0/*failure*/;
     }
     s = (char*) memcpy(buf, service, len) + len;
     *s++ = '_';
     memcpy(s, CONN_SERVICE_NAME, sizeof(CONN_SERVICE_NAME));
-    /* Looking for "service_CONN_SERVICE_NAME" in environment */
+    /* Looking for "service_CONN_SERVICE_NAME" in the environment */
     if (!(s = getenv(strupr(buf)))  ||  !*s) {
         /* Looking for "CONN_SERVICE_NAME" in registry's section [service] */
         buf[len++] = '\0';
         CORE_REG_GET(buf, buf + len, srv, sizeof(srv), 0);
-        if (!*srv)
+        s = srv;
+    }
+    if (!*s  ||  strcasecmp(s, service) == 0)
             return strdup(service);
-    } else
-        strncpy0(srv, s, sizeof(srv) - 1);
-    return s_ServiceName(srv, depth);
+    return s_ServiceName(s, ++depth);
 }
 
 
@@ -130,14 +142,11 @@ inline
 #endif /*__GNUC__*/
 static int/*bool*/ s_IsMapperConfigured(const char* service, const char* key)
 {
-    char str[80];
+    char val[32];
     if (s_Fast)
         return 0;
-    ConnNetInfo_GetValue(service, key, str, sizeof(str), 0);
-    return *str  &&  (strcmp(str, "1") == 0  ||
-                      strcasecmp(str, "true") == 0  ||
-                      strcasecmp(str, "yes" ) == 0  ||
-                      strcasecmp(str, "on"  ) == 0);
+    ConnNetInfo_GetValue(service, key, val, sizeof(val), 0);
+    return ConnNetInfo_Boolean(val);
 }
 
 
@@ -578,34 +587,15 @@ static void s_SetDefaultReferer(SERV_ITER iter, SConnNetInfo* net_info)
 {
     char* str, *referer = 0;
 
-    if (strcasecmp(iter->op->name, "DISPD") == 0) {
-        const char* host = net_info->host;
-        const char* path = net_info->path;
-        const char* args = net_info->args;
-        char        port[8];
-
-        if (net_info->port)
-            sprintf(port, ":%hu", net_info->port);
-        else
-            *port = '\0';
-        if (!(referer = (char*) malloc(8 + 1 + 1 + strlen(host) + strlen(port)
-                                       + strlen(path) + strlen(args)))) {
-            return;
-        }
-        if (net_info->scheme == eURL_Https)
-            strcpy(referer, "https://"/*8*/);
-        else
-            strcpy(referer, "http://"/*7*/);
-        strcat(strcat(strcat(referer, host), port), path);
-        if (*args)
-            strcat(strcat(referer, "?"), args);
-    } else if ((str = strdup(iter->op->name)) != 0) {
+    if (strcasecmp(iter->op->name, "DISPD") == 0)
+        referer = ConnNetInfo_URL(net_info);
+    else if ((str = strdup(iter->op->name)) != 0) {
         const char* host = net_info->client_host;
         const char* args = net_info->args;
         const char* name = iter->name;
 
-        if (!*net_info->client_host  &&
-            !SOCK_gethostbyaddr(0, net_info->client_host,
+        if (!*net_info->client_host
+            &&  !SOCK_gethostbyaddr(0, net_info->client_host,
                                 sizeof(net_info->client_host))) {
             SOCK_gethostname(net_info->client_host,
                              sizeof(net_info->client_host));
@@ -772,6 +762,10 @@ unsigned short SERV_ServerPort(const char*  name,
     SSERV_Info*    info;
     unsigned short port;
 
+    /* FIXME:  SERV_LOCALHOST may not need to be resolved here,
+     *         but taken from LBSMD table (or resolved later in DISPD/LOCAL
+     *         if needed).
+     */
     if (!host  ||  host == SERV_LOCALHOST)
         host = SOCK_GetLocalHostAddress(eDefault);
     if (!(info = s_GetInfo(name, fSERV_Standalone | fSERV_Promiscuous,
diff --git a/connect/ncbi_service.h b/connect/ncbi_service.h
index 230ff28..9e993ce 100644
--- a/connect/ncbi_service.h
+++ b/connect/ncbi_service.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_SERVICE__H
 #define CONNECT___NCBI_SERVICE__H
 
-/* $Id: ncbi_service.h,v 6.56 2009/01/23 19:44:42 kazimird Exp $
+/* $Id: ncbi_service.h,v 6.58 2010/07/29 18:19:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -39,7 +39,7 @@
 
 /* Revision 6.250 */
 #define SERV_CLIENT_REVISION_MAJOR  6
-#define SERV_CLIENT_REVISION_MINOR  250
+#define SERV_CLIENT_REVISION_MINOR  260
 
 
 /** @addtogroup ServiceSupport
@@ -100,12 +100,12 @@ typedef enum {
     fSERV_All               = 0x0000FFFF,
     /* Only stateless servers should be returned */
     fSERV_Stateless         = 0x00100000,
-    fSERV_Reserved_1        = 0x00200000, /*MBZ*/
+    fSERV_Reserved          = 0x00200000, /* Reserved, MBZ */
     /* Do reverse DNS translation of the would-be resulting info */
     fSERV_ReverseDns        = 0x00800000,
-    fSERV_Reserved_2        = 0x10000000, /*MBZ*/
     /* Allows to get even down services (but not the off ones!)
-     * NB: flex preference params are ignored */
+     * NB: most flex preference params are ignored */
+    fSERV_IncludeReserved   = 0x10000000, /* w/local LBSMD only */
     fSERV_IncludeDown       = 0x20000000,
     fSERV_IncludeSuppressed = 0x40000000,
     fSERV_Promiscuous       = 0x60000000
diff --git a/connect/ncbi_service_connector.c b/connect/ncbi_service_connector.c
index 02de97a..db8a0bb 100644
--- a/connect/ncbi_service_connector.c
+++ b/connect/ncbi_service_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_service_connector.c,v 6.87 2009/06/23 16:04:40 kazimird Exp $
+/* $Id: ncbi_service_connector.c,v 6.94 2010/06/10 19:14:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -42,6 +42,9 @@
 #define NCBI_USE_ERRCODE_X   Connect_Service
 
 
+static const char kFWDaemon[] = "fwdaemon.ncbi.nlm.nih.gov";
+
+
 typedef struct SServiceConnectorTag {
     const char*     name;               /* Verbal connector type             */
     TSERV_Type      types;              /* Server types, record keeping only */
@@ -54,7 +57,7 @@ typedef struct SServiceConnectorTag {
     unsigned short  port;               /*                       ... (h.b.o) */
     ticket_t        ticket;             /* Network byte order (none if zero) */
     SSERVICE_Extra  params;
-    char            service[1];         /* Untranslated service name         */
+    const char      service[1];         /* Untranslated service name         */
 } SServiceConnector;
 
 
@@ -110,9 +113,6 @@ static void s_Reset(SMetaConnector *meta)
     CONN_SET_METHOD(meta, flush,      0,           0);
     CONN_SET_METHOD(meta, read,       0,           0);
     CONN_SET_METHOD(meta, status,     s_VT_Status, 0);
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    CONN_SET_METHOD(meta, wait_async, 0,           0);
-#endif
 }
 
 
@@ -155,7 +155,7 @@ static int/*bool*/ s_ParseHeader(const char* header,
                     CORE_LOGF_X(2, eLOG_Note,
                                 ("[%s]  Fallback to stateless", uuu->service));
                 }
-#endif
+#endif /*_DEBUG && !NDEBUG*/
             } else {
                 int n;
                 if (sscanf(header, "%u.%u.%u.%u %hu %x%n",
@@ -408,12 +408,16 @@ static int/*bool*/ s_AdjustNetInfo(SConnNetInfo* net_info,
         return 0/*false - not adjusted*/;
 
     if (uuu->user_header) {
+        assert(*uuu->user_header);
         ConnNetInfo_DeleteUserHeader(net_info, uuu->user_header);
         free((void*) uuu->user_header);
     }
-    uuu->user_header = *user_header ? user_header : 0;
+    if (*user_header) {
+        uuu->user_header = user_header;
     if (!ConnNetInfo_OverrideUserHeader(net_info, user_header))
         return 0/*false - not adjusted*/;
+    } else
+        uuu->user_header = 0;
 
     if (info->type == fSERV_Ncbid  ||  (info->type & fSERV_Http)) {
         SOCK_ntoa(info->host, net_info->host, sizeof(net_info->host));
@@ -423,9 +427,8 @@ static int/*bool*/ s_AdjustNetInfo(SConnNetInfo* net_info,
         net_info->port = uuu->net_info->port;
     }
 
-    if (net_info->http_proxy_adjusted)
+    ConnNetInfo_DeleteUserHeader(net_info, "Host:");
         net_info->http_proxy_adjusted = 0/*false*/;
-
     return 1/*true - adjusted*/;
 }
 
@@ -561,7 +564,7 @@ static CONNECTOR s_Open(SServiceConnector* uuu,
         free((void*) uuu->user_header);
     }
     uuu->user_header = user_header;
-    if (!ConnNetInfo_OverrideUserHeader(net_info, user_header))
+    if (user_header && !ConnNetInfo_OverrideUserHeader(net_info, user_header))
         return 0;
 
     if (!second_try) {
@@ -582,6 +585,7 @@ static CONNECTOR s_Open(SServiceConnector* uuu,
         /* HTTP connector is auxiliary only */
         EIO_Status status = eIO_Success;
         CONNECTOR conn;
+        char val[32];
         CONN c;
 
         /* Clear connection info */
@@ -621,7 +625,13 @@ static CONNECTOR s_Open(SServiceConnector* uuu,
         }
         if (net_info->firewall  &&  *net_info->proxy_host)
             strcpy(net_info->host, net_info->proxy_host);
-        else
+        else if (ConnNetInfo_GetValue(net_info->service,
+                                      "FWDAEMON_COMPATIBILITY",
+                                      val, sizeof(val), "")
+                 &&  ConnNetInfo_Boolean(val)) {
+            assert(sizeof(kFWDaemon) <= sizeof(net_info->host));
+            memcpy(net_info->host, kFWDaemon, sizeof(kFWDaemon));
+        } else
             SOCK_ntoa(uuu->host, net_info->host, sizeof(net_info->host));
         net_info->port = uuu->port;
         /* Build and return target SOCKET connector */
@@ -643,15 +653,11 @@ static CONNECTOR s_Open(SServiceConnector* uuu,
 }
 
 
-static EIO_Status s_Close(CONNECTOR       connector,
+static void s_Close(CONNECTOR       connector,
                           const STimeout* timeout,
                           int/*bool*/     close_dispatcher)
 {
     SServiceConnector* uuu = (SServiceConnector*) connector->handle;
-    EIO_Status status = eIO_Success;
-
-    if (uuu->meta.close)
-        status = uuu->meta.close(uuu->meta.c_close, timeout);
 
     if (uuu->name) {
         free((void*) uuu->name);
@@ -674,9 +680,6 @@ static EIO_Status s_Close(CONNECTOR       connector,
         uuu->meta.list = 0;
         s_Reset(meta);
     }
-
-    uuu->status = status;
-    return status;
 }
 
 
@@ -741,10 +744,6 @@ static EIO_Status s_VT_Open(CONNECTOR connector, const STimeout* timeout)
         CONN_SET_METHOD(meta, flush,  uuu->meta.flush,  uuu->meta.c_flush);
         CONN_SET_METHOD(meta, read,   uuu->meta.read,   uuu->meta.c_read);
         CONN_SET_METHOD(meta, status, uuu->meta.status, uuu->meta.c_status);
-#ifdef IMPLEMENTED__CONN_WaitAsync
-        CONN_SET_METHOD(meta, wait_async,
-                        uuu->meta.wait_async, uuu->meta.c_wait_async);
-#endif
         if (uuu->meta.get_type) {
             const char* type;
             if ((type = uuu->meta.get_type(uuu->meta.c_get_type)) != 0) {
@@ -776,7 +775,6 @@ static EIO_Status s_VT_Open(CONNECTOR connector, const STimeout* timeout)
                          uuu->service, !info ? "Firewall" : "Stateful relay",
                          IO_StatusStr(status), kFWLink));
         }
-
         s_Close(connector, timeout, 0/*don't close dispatcher yet!*/);
     }
 
@@ -794,7 +792,12 @@ static EIO_Status s_VT_Status(CONNECTOR connector, EIO_Event dir)
 
 static EIO_Status s_VT_Close(CONNECTOR connector, const STimeout* timeout)
 {
-    return s_Close(connector, timeout, 1/*close_dispatcher*/);
+    SServiceConnector* uuu = (SServiceConnector*) connector->handle;
+    EIO_Status status = uuu->meta.close
+        ? uuu->meta.close(uuu->meta.c_close, timeout)
+        : eIO_Success;
+    s_Close(connector, timeout, 1/*close_dispatcher*/);
+    return status;
 }
 
 
@@ -814,16 +817,18 @@ static void s_Setup(SMetaConnector *meta, CONNECTOR connector)
 static void s_Destroy(CONNECTOR connector)
 {
     SServiceConnector* uuu = (SServiceConnector*) connector->handle;
+    connector->handle = 0;
 
     if (uuu->iter)
         s_CloseDispatcher(uuu);
     if (uuu->params.cleanup)
         uuu->params.cleanup(uuu->params.data);
     ConnNetInfo_Destroy(uuu->net_info);
-    if (uuu->name)
+    if (uuu->name) {
         free((void*) uuu->name);
+        uuu->name = 0;
+    }
     free(uuu);
-    connector->handle = 0;
     free(connector);
 }
 
@@ -865,7 +870,7 @@ extern CONNECTOR SERVICE_CreateConnectorEx
         s_Destroy(ccc);
         return 0;
     }
-    strcpy(xxx->service, service);
+    strcpy((char*) xxx->service, service);
     free(x_service);
 
     /* now get ready for first probe dispatching */
diff --git a/connect/ncbi_socket.c b/connect/ncbi_socket.c
index 10bba04..d99cdbc 100644
--- a/connect/ncbi_socket.c
+++ b/connect/ncbi_socket.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_socket.c,v 6.283 2009/07/30 16:24:29 kazimird Exp $
+/* $Id: ncbi_socket.c,v 6.314 2010/06/29 20:35:03 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -77,6 +77,7 @@
  * 0) you are compiling this outside of the NCBI C or C++ Toolkits
  *    (USE_NCBICONF is not #define'd), and
  * 1) on your platform, struct sockaddr_in contains a field called "sin_len"
+ *    (and sockaddr_un::sun_len is then assumed to be also present).
  */
 
 /* #define HAVE_SIN_LEN 1 */
@@ -84,7 +85,8 @@
 /* Platform-specific system headers remaining
  */
 
-#if   defined(NCBI_OS_UNIX)
+#ifdef NCBI_OS_UNIX
+
 #  include <unistd.h>
 #  include <netdb.h>
 #  include <fcntl.h>
@@ -99,9 +101,13 @@
 #    include <arpa/inet.h>
 #  endif /*NCBI_OS_BEOS*/
 #  include <signal.h>
+#  ifdef HAVE_POLL_H
+#    include <sys/poll.h>
+#  endif /*HAVE_POLL_H*/
+#  include <sys/stat.h>
 #  include <sys/un.h>
 
-#endif /*NCBI_OS*/
+#endif /*NCBI_OS_UNIX*/
 
 /* Portable standard C headers
  */
@@ -160,8 +166,13 @@
 typedef socklen_t  SOCK_socklen_t;
 #else
 typedef int	       SOCK_socklen_t;
-#endif
+#endif /*HAVE_SOCKLEN_T || _SOCKLEN_T*/
+
 
+#define MAXIDLEN              80
+#if MAXIDLEN > SOCK_BUF_CHUNK_SIZE
+#  error "SOCK_BUF_CHUNK_SIZE too small"
+#endif /*MAXIDLEN<SOCK_BUF_CHUNK_SIZE*/
 
 
 /******************************************************************************
@@ -172,6 +183,9 @@ typedef int	       SOCK_socklen_t;
 /* Flag to indicate whether the API has been [de]initialized */
 static int/*bool*/ s_Initialized = 0/*-1=deinited;0=uninited;1=inited*/;
 
+/* Which wait API to use, UNIX only */
+static ESOCK_IOWaitSysAPI s_IOWaitSysAPI = eSOCK_IOWaitSysAPIAuto;
+
 /* SOCK counter */
 static unsigned int s_ID_Counter = 0;
 
@@ -179,7 +193,7 @@ static unsigned int s_ID_Counter = 0;
 static ESwitch s_ReadOnWrite = eOff;        /* no read-on-write by default   */
 
 /* Reuse address flag for newly created stream sockets */
-static int/*bool*/ s_ReuseAddress = 0;      /* off by default                */
+static ESwitch s_ReuseAddress = eOff;       /* off by default                */
 
 /* I/O restart on signals */
 static ESwitch s_InterruptOnSignal = eOff;  /* restart I/O by default        */
@@ -397,17 +411,54 @@ static char* s_WinStrerror(DWORD error)
  */
 
 
-static const char* s_ID(const SOCK sock, char* buf)
+static unsigned short x_GetLocalPort(TSOCK_Handle fd)
+{
+    struct sockaddr_in sin;
+    SOCK_socklen_t sinlen = (SOCK_socklen_t) sizeof(sin);
+    memset(&sin, 0, sizeof(sin));
+#ifdef HAVE_SIN_LEN
+    sin.sin_len = sinlen;
+#endif /*HAVE_SIN_LEN*/
+    if (getsockname(fd, (struct sockaddr*) &sin, &sinlen) == 0
+        &&  sin.sin_family == AF_INET) {
+        return ntohs(sin.sin_port);
+    }
+    return 0;
+}
+
+
+static const char* x_CP(unsigned int host, unsigned short port,
+                        const char* path, char* buf, size_t bufsize)
+{
+    if (path[0])
+        return path;
+    SOCK_HostPortToString(host, port, buf, bufsize);
+    return buf;
+}
+
+
+static const char* s_ID(const SOCK sock, char buf[MAXIDLEN])
 {
     const char* sname;
+    const char* cp;
+    char addr[40];
+    int n;
 
     if (!sock)
         return "";
     switch (sock->type) {
     case eTrigger:
+        cp = "";
         sname = "TRIGGER";
         break;
     case eSocket:
+        cp = x_CP(sock->host, sock->port,
+#ifdef NCBI_OS_UNIX
+                  sock->path,
+#else
+                  "",
+#endif /*NCBI_OS_UNIX*/
+                  addr, sizeof(addr));
 #ifdef NCBI_OS_UNIX
         if (sock->path[0])
             sname = sock->session ? "SUSOCK" : "USOCK";
@@ -417,19 +468,40 @@ static const char* s_ID(const SOCK sock, char* buf)
         break;
     case eDatagram:
         sname = "DSOCK";
+        addr[0] = '\0';
+        n = sock->myport ? sprintf(addr, "(:%hu)", sock->myport) : 0;
+        if (sock->host  ||  sock->port) {
+            SOCK_HostPortToString(sock->host, sock->port,
+                                  addr + n, sizeof(addr) - n);
+        }
+        cp = addr;
         break;
     case eListening:
+#ifdef NCBI_OS_UNIX
+        if (!sock->myport)
+            cp = ((LSOCK) sock)->path;
+        else
+#endif /*NCBI_OS_UNIX*/
+        {
+            sprintf(addr, ":%hu", sock->myport);
+            cp = addr;
+        }
         sname = "LSOCK";
         break;
     default:
+        cp = "";
         sname = "?";
         assert(0);
         break;
     }
-    if (sock->sock == SOCK_INVALID)
+    if (sock->sock != SOCK_INVALID) {
+        size_t len = cp  &&  *cp ? strlen(cp) : 0;
+        n = (int)(len > sizeof(addr) - 1 ? sizeof(addr) - 1 : len);
+        sprintf(buf, "%s#%u[%u]%s%s%.*s: ",
+                sname, sock->id, (unsigned int) sock->sock,
+                &"@"[!n], (size_t) n < len ? "..." : "", n, cp + len - n);
+    } else
         sprintf(buf, "%s#%u[?]: ",  sname, sock->id);
-    else
-        sprintf(buf, "%s#%u[%u]: ", sname, sock->id, (unsigned int)sock->sock);
     return buf;
 }
 
@@ -439,11 +511,11 @@ static const char* s_ID(const SOCK sock, char* buf)
 static void s_DoLog(ELOG_Level  level, const SOCK sock, EIO_Event   event,
                     const void* data,  size_t     size, const void* ptr)
 {
-    const struct sockaddr* sa = (const struct sockaddr*) ptr;
+    const struct sockaddr_in* sin;
+    char _id[MAXIDLEN];
     const char* what;
     char head[128];
     char tail[128];
-    char _id[32];
     int n;
 
     if (!CORE_GetLOG())
@@ -452,46 +524,53 @@ static void s_DoLog(ELOG_Level  level, const SOCK sock, EIO_Event   event,
     assert(sock  &&  (sock->type & eSocket));
     switch (event) {
     case eIO_Open:
-        if (sock->type == eDatagram) {
-            if (!sa) {
-                strcpy(head, "Datagram socket created");
-                *tail = 0;
-            } else {
-                const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;
-                if (!data) {
-                    strcpy(head, "Datagram socket bound to port :");
-                    sprintf(tail, "%hu", ntohs(sin->sin_port));
-                } else if (sin->sin_family == AF_INET) {
-                    strcpy(head, "Datagram socket associated with ");
-                    SOCK_HostPortToString(sin->sin_addr.s_addr,
-                                          ntohs(sin->sin_port),
-                                          tail, sizeof(tail));
+        assert(sock->type & eSocket);
+        if (sock->type != eDatagram) {
+            unsigned short port;
+            if (sock->side == eSOCK_Client) {
+                strcpy(head, ptr ? "Connected" : "Connecting");
+                port = sock->myport;
+            } else if (ptr) {
+                strcpy(head, "Accepted");
+                port = 0;
                 } else {
-                    strcpy(head, "Datagram socket disassociated");
-                    *tail = '\0';
+                strcpy(head, "Created");
+                port = sock->myport;
                 }
+            if (!port) {
+#ifdef NCBI_OS_UNIX
+                if (!sock->path[0])
+#endif /*NCBI_OS_UNIX*/
+                    port = x_GetLocalPort(sock->sock);
             }
+            if (port) {
+                sprintf(tail, " @:%hu", port);
+                if (!sock->myport) {
+                    /* here: not LSOCK_Accept()'d network sockets only */
+                    assert(sock->side == eSOCK_Client  ||  !ptr);
+                    sock->myport = port;
+                }
+            } else
+                *tail = '\0';
+        } else if (!(sin = (const struct sockaddr_in*) ptr)) {
+            strcpy(head, "Created");
+            *tail = '\0';
+        } else if (!data) {
+            if (sin->sin_port) {
+                strcpy(head, "Bound @");
+                sprintf(tail, "(:%hu)", ntohs(sin->sin_port));
         } else {
-            if (sock->side == eSOCK_Client)
-                strcpy(head, "Connecting to ");
-            else if (data)
-                strcpy(head, "Connected to ");
-            else
-                strcpy(head, "Accepted from ");
-            if (sa->sa_family == AF_INET) {
-                const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;
+                strcpy(head, "Unbound");
+                *tail = '\0';
+            }
+        } else if (sin->sin_family == AF_INET) {
+            strcpy(head, "Associated with ");
                 SOCK_HostPortToString(sin->sin_addr.s_addr,
                                       ntohs(sin->sin_port),
                                       tail, sizeof(tail));
-            }
-#ifdef NCBI_OS_UNIX
-            else if (sa->sa_family == AF_UNIX) {
-                const struct sockaddr_un* un = (const struct sockaddr_un*) sa;
-                strncpy0(tail, un->sun_path, sizeof(tail) - 1);
-            }
-#endif /*NCBI_OS_UNIX*/
-            else
-                strcpy(tail, "???");
+        } else {
+            strcpy(head, "Disassociated");
+            *tail = '\0';
         }
         CORE_LOGF_X(112, level,
                     ("%s%s%s", s_ID(sock, _id), head, tail));
@@ -504,15 +583,16 @@ static void s_DoLog(ELOG_Level  level, const SOCK sock, EIO_Event   event,
                    ? (data ? s_StrError(sock, *((int*) data)) : "EOF hit")
                    : "Read")
                 : (sock->type != eDatagram  &&  !size
-                   ? s_StrError(sock, *((int*) data)) : "Written"));
+                   ? s_StrError(sock, *((int*) data))
+                   : "Written"));
         n = (int) strlen(what);
         while (n  &&  isspace((unsigned char) what[n - 1]))
             n--;
         if (n > 1  &&  what[n - 1] == '.')
             n--;
         if (sock->type == eDatagram) {
-            const struct sockaddr_in* sin = (const struct sockaddr_in*) sa;
-            assert(sa  &&  sa->sa_family == AF_INET);
+            sin = (const struct sockaddr_in*) ptr;
+            assert(sin  &&  sin->sin_family == AF_INET);
             SOCK_HostPortToString(sin->sin_addr.s_addr, ntohs(sin->sin_port),
                                   head, sizeof(head));
             sprintf(tail, ", msg# %u",
@@ -539,42 +619,37 @@ static void s_DoLog(ELOG_Level  level, const SOCK sock, EIO_Event   event,
         break;
 
     case eIO_Close:
-        n = sprintf(tail, "%lu byte%s",
+        n = sprintf(head, "%lu byte%s",
                     (unsigned long) sock->n_written,
-                    sock->n_written == 1 ? "" : "s");
+                    &"s"[sock->n_written == 1]);
         if (sock->type == eDatagram  ||
             sock->n_out != sock->n_written) {
-            sprintf(tail + n, "/%lu %s%s",
+            sprintf(head + n, "/%lu %s%s",
                     (unsigned long) sock->n_out,
                     sock->type == eDatagram ? "msg" : "total byte",
-                    sock->n_out == 1 ? "" : "s");
+                    &"s"[sock->n_out == 1]);
         }
-        n = sprintf(tail + sizeof(tail)/2, "%lu byte%s",
+        n = sprintf(tail, "%lu byte%s",
                     (unsigned long) sock->n_read,
-                    sock->n_read == 1 ? "" : "s");
+                    &"s"[sock->n_read == 1]);
         if (sock->type == eDatagram  ||
             sock->n_in != sock->n_read) {
-            sprintf(tail + sizeof(tail)/2 + n, "/%lu %s%s",
+            sprintf(tail + n, "/%lu %s%s",
                     (unsigned long) sock->n_in,
                     sock->type == eDatagram ? "msg" : "total byte",
-                    sock->n_in == 1 ? "" : "s");
+                    &"s"[sock->n_in == 1]);
         }
-        if (sock->type != eDatagram) {
-            head[0] = ' ';
-            SOCK_HostPortToString(sock->host, sock->port,
-                                  head + 1, sizeof(head) - 1);
-        } else
-            *head = '\0';
         CORE_LOGF_X(113, level,
-                    ("%s%s%s (out: %s, in: %s)", s_ID(sock, _id),
+                    ("%s%s (out: %s, in: %s)", s_ID(sock, _id),
                      ptr ? (const char*) ptr :
-                     sock->keep ? "Leaving" : "Closing", head,
-                     tail, tail + sizeof(tail)/2));
+                     sock->keep ? "Leaving" : "Closing",
+                     head, tail));
         break;
 
     default:
         CORE_LOGF_X(1, eLOG_Error,
-                    ("%s[SOCK::DoLog]  Invalid event %u",
+                    ("%s[SOCK::DoLog] "
+                     " Invalid event #%u",
                      s_ID(sock, _id), (unsigned int) event));
         assert(0);
         break;
@@ -585,8 +660,7 @@ static void s_DoLog(ELOG_Level  level, const SOCK sock, EIO_Event   event,
 extern ESwitch SOCK_SetDataLoggingAPI(ESwitch log)
 {
     ESwitch old = s_Log;
-    if (log == eDefault)
-        log = eOff;
+    if (log != eDefault)
     s_Log = log;
     return old;
 }
@@ -614,21 +688,22 @@ extern void SOCK_AllowSigPipeAPI(void)
     return;
 }
 
+#if defined(_DEBUG)  &&  !defined(NDEBUG)
+#  if !defined(__GNUC__)  &&  !defined(offsetof)
+#    define offsetof(T, F)  ((size_t)((char*) &(((T*) 0)->F) - (char*) 0))
+#  endif
+#endif /*_DEBUG && !NDEBUG*/
 
-#if 0/*defined(_DEBUG) && !defined(NDEBUG)*/
+#if defined(_DEBUG)  &&  !defined(NDEBUG)
 
 #  ifndef   SOCK_HAVE_SHOWDATALAYOUT
 #    define SOCK_HAVE_SHOWDATALAYOUT 1
 #  endif
 
-#endif /*_DEBUG && !NDEBUG*/
+#endif /*__GNUC__ && _DEBUG && !NDEBUG*/
 
 #ifdef SOCK_HAVE_SHOWDATALAYOUT
 
-#  if !defined(__GNUC__)  &&  !defined(offsetof)
-#    define offsetof(T, F)  ((size_t)((char*) &(((T*) 0)->F) - (char*) 0))
-#  endif
-
 #  define   extentof(T, F)  (sizeof(((T*) 0)->F))
 
 #  define   infof(T, F)     (unsigned int) offsetof(T, F), \
@@ -636,14 +711,15 @@ extern void SOCK_AllowSigPipeAPI(void)
 
 static void s_ShowDataLayout(void)
 {
-    CORE_LOGF_X(2, eLOG_Note,
-                ("SOCK data layout:\n"
+    static const char kLayoutFormat[] = {
+        "SOCK data layout:\n"
                  "    Sizeof(SOCK_struct) = %u, offsets (sizes) follow\n"
                  "\tsock:      %3u (%u)\n"
                  "\tid:        %3u (%u)\n"
                  "\thost:      %3u (%u)\n"
                  "\tport:      %3u (%u)\n"
                  "\tmyport:    %3u (%u)\n"
+        "\tisset:     %3u (%u)\n"
 				 "\ttype:      %3u (%u)\n"
                  "\tbitfield:      (3)\n"
 #  ifdef NCBI_OS_MSWIN
@@ -669,51 +745,89 @@ static void s_ShowDataLayout(void)
 #  ifdef NCBI_OS_UNIX
                  "\n\tpath:      %3u (%u)"
 #  endif /*NCBI_OS_UNIX*/
-                 , (unsigned int) sizeof(SOCK_struct),
-                 infof(SOCK_struct, sock),
-                 infof(SOCK_struct, id),
-                 infof(SOCK_struct, host),
-                 infof(SOCK_struct, port),
-                 infof(SOCK_struct, myport),
-                 infof(SOCK_struct, type),
+    };
 #  ifdef NCBI_OS_MSWIN
-				 infof(SOCK_struct, event),
-#  endif /*NCBI_OS_MSWIN*/
-                 infof(SOCK_struct, session),
-                 infof(SOCK_struct, r_timeout),
-                 infof(SOCK_struct, r_tv),
-                 infof(SOCK_struct, r_to),
-                 infof(SOCK_struct, w_timeout),
-                 infof(SOCK_struct, w_tv),
-                 infof(SOCK_struct, w_to),
-                 infof(SOCK_struct, c_timeout),
-                 infof(SOCK_struct, c_tv),
-                 infof(SOCK_struct, c_to),
-                 infof(SOCK_struct, r_buf),
-                 infof(SOCK_struct, w_buf),
-                 infof(SOCK_struct, w_len),
-                 infof(SOCK_struct, n_read),
-                 infof(SOCK_struct, n_written),
-                 infof(SOCK_struct, n_in),
+#    define SOCK_SHOWDATALAYOUT_PARAMS              \
+        infof(SOCK_struct,    sock),                \
+        infof(SOCK_struct,    id),                  \
+        infof(SOCK_struct,    host),                \
+        infof(SOCK_struct,    port),                \
+        infof(SOCK_struct,    myport),              \
+        infof(TRIGGER_struct, isset),               \
+        infof(SOCK_struct,    type),                \
+        infof(SOCK_struct,    event),               \
+        infof(SOCK_struct,    session),             \
+        infof(SOCK_struct,    r_timeout),           \
+        infof(SOCK_struct,    r_tv),                \
+        infof(SOCK_struct,    r_to),                \
+        infof(SOCK_struct,    w_timeout),           \
+        infof(SOCK_struct,    w_tv),                \
+        infof(SOCK_struct,    w_to),                \
+        infof(SOCK_struct,    c_timeout),           \
+        infof(SOCK_struct,    c_tv),                \
+        infof(SOCK_struct,    c_to),                \
+        infof(SOCK_struct,    r_buf),               \
+        infof(SOCK_struct,    w_buf),               \
+        infof(SOCK_struct,    w_len),               \
+        infof(SOCK_struct,    n_read),              \
+        infof(SOCK_struct,    n_written),           \
+        infof(SOCK_struct,    n_in),                \
                  infof(SOCK_struct, n_out)
-#  ifdef NCBI_OS_UNIX
-                 , infof(SOCK_struct, path)
-#  endif /*NCBI_OS_UNIX*/
-                 ));
-
-    assert(offsetof(SOCK_struct, type)    == offsetof(TRIGGER_struct, type));
-    assert(offsetof(SOCK_struct, type)    == offsetof(LSOCK_struct,   type));
-    assert(offsetof(SOCK_struct, session) == offsetof(LSOCK_struct, context));
-#ifdef NCBI_OS_MSWIN
-    assert(offsetof(SOCK_struct, event)   == offsetof(LSOCK_struct, event));
-#endif /*NCBI_OS_MSWIN*/
+#  else
+#    define SOCK_SHOWDATALAYOUT_PARAMS              \
+        infof(SOCK_struct,    sock),                \
+        infof(SOCK_struct,    id),                  \
+        infof(SOCK_struct,    host),                \
+        infof(SOCK_struct,    port),                \
+        infof(SOCK_struct,    myport),              \
+        infof(TRIGGER_struct, isset),               \
+        infof(SOCK_struct,    type),                \
+        infof(SOCK_struct,    session),             \
+        infof(SOCK_struct,    r_timeout),           \
+        infof(SOCK_struct,    r_tv),                \
+        infof(SOCK_struct,    r_to),                \
+        infof(SOCK_struct,    w_timeout),           \
+        infof(SOCK_struct,    w_tv),                \
+        infof(SOCK_struct,    w_to),                \
+        infof(SOCK_struct,    c_timeout),           \
+        infof(SOCK_struct,    c_tv),                \
+        infof(SOCK_struct,    c_to),                \
+        infof(SOCK_struct,    r_buf),               \
+        infof(SOCK_struct,    w_buf),               \
+        infof(SOCK_struct,    w_len),               \
+        infof(SOCK_struct,    n_read),              \
+        infof(SOCK_struct,    n_written),           \
+        infof(SOCK_struct,    n_in),                \
+        infof(SOCK_struct,    n_out),               \
+        infof(SOCK_struct,    path)
+#  endif /*NCBI_OS_MSWIN*/
+    CORE_LOGF_X(2, eLOG_Note,
+                (kLayoutFormat, (unsigned int) sizeof(SOCK_struct),
+                 SOCK_SHOWDATALAYOUT_PARAMS));
+#  undef SOCK_SHOWDATALAYOUT_PARAMS
 }
 
 #endif /*SOCK_HAVE_SHOWDATALAYOUT*/
 
 
+extern ESOCK_IOWaitSysAPI SOCK_SetIOWaitSysAPI(ESOCK_IOWaitSysAPI api)
+{
+    ESOCK_IOWaitSysAPI retval = s_IOWaitSysAPI;
+#if !defined(NCBI_OS_UNIX)  ||  !defined(HAVE_POLL_H)
+    if (api == eSOCK_IOWaitSysAPIPoll) {
+        CORE_LOG_X(2, eLOG_Critical, "[SOCK::SetIOWaitSysAPI] "
+                   " Poll API requested but not supported on this platform");
+    } else
+#endif /*!NCBI_OS_UNIX || !HAVE_POLL_H*/
+        s_IOWaitSysAPI = api;
+    return retval;
+}
+
+
 extern EIO_Status SOCK_InitializeAPI(void)
 {
+    CORE_TRACE("[SOCK::InitializeAPI]  Begin");
+
     CORE_LOCK_WRITE;
     if (s_Initialized) {
         CORE_UNLOCK;
@@ -721,9 +835,21 @@ extern EIO_Status SOCK_InitializeAPI(void)
     }
 
 #ifdef SOCK_HAVE_SHOWDATALAYOUT
+    if (s_Log == eOn)
     s_ShowDataLayout();
 #endif /*SOCK_HAVE_SHOWDATALAYOUT*/
 
+#if defined(_DEBUG)  &&  !defined(NDEBUG)
+    /* Layout / alignment sanity check */
+    assert(sizeof(TRIGGER_Handle)         == sizeof(TSOCK_Handle));
+    assert(offsetof(SOCK_struct, type)    == offsetof(TRIGGER_struct, type));
+    assert(offsetof(SOCK_struct, type)    == offsetof(LSOCK_struct,   type));
+    assert(offsetof(SOCK_struct, session) == offsetof(LSOCK_struct, context));
+#  ifdef NCBI_OS_MSWIN
+    assert(offsetof(SOCK_struct, event)   == offsetof(LSOCK_struct, event));
+#  endif /*NCBI_OS_MSWIN*/
+#endif /*_DEBUG && !NDEBUG*/
+
 #if defined(NCBI_OS_MSWIN)
     {{
         WSADATA wsadata;
@@ -732,7 +858,8 @@ extern EIO_Status SOCK_InitializeAPI(void)
             CORE_UNLOCK;
             CORE_LOG_ERRNO_EXX(3, eLOG_Error,
                                x_error, SOCK_STRERROR(x_error),
-                               "[SOCK::InitializeAPI]  Failed WSAStartup()");
+                               "[SOCK::InitializeAPI] "
+                               " Failed WSAStartup()");
             return eIO_NotSupported;
         }
     }}
@@ -759,6 +886,7 @@ extern EIO_Status SOCK_InitializeAPI(void)
 #endif
 
     CORE_UNLOCK;
+    CORE_TRACE("[SOCK::InitializeAPI]  End");
     return eIO_Success;
 }
 
@@ -807,6 +935,8 @@ static EIO_Status s_InitAPI(int secure)
 
 extern EIO_Status SOCK_ShutdownAPI(void)
 {
+    CORE_TRACE("[SOCK::ShutdownAPI]  Begin");
+
     CORE_LOCK_WRITE;
     if (s_Initialized <= 0) {
         CORE_UNLOCK;
@@ -829,7 +959,8 @@ extern EIO_Status SOCK_ShutdownAPI(void)
         if (x_error) {
             CORE_LOG_ERRNO_EXX(4, eLOG_Warning,
                                x_error, SOCK_STRERROR(x_error),
-                               "[SOCK::ShutdownAPI]  Failed WSACleanup()");
+                               "[SOCK::ShutdownAPI] "
+                               " Failed WSACleanup()");
             return eIO_NotSupported;
         }
     }}
@@ -837,6 +968,7 @@ extern EIO_Status SOCK_ShutdownAPI(void)
     CORE_UNLOCK;
 #endif /*NCBI_OS_MSWIN*/
 
+    CORE_TRACE("[SOCK::ShutdownAPI]  End");
     return eIO_Success;
 }
 
@@ -885,21 +1017,25 @@ static int/*bool*/ s_SetNonblock(TSOCK_Handle sock, int/*bool*/ nonblock)
                  fcntl(sock, F_GETFL, 0) & (int) ~O_NONBLOCK) != -1;
 #else
 #   error "Unsupported platform"
-#endif /*platform-specific ioctl*/
+#endif /*NCBI_OS*/
 }
 
 
-#ifdef NCBI_OS_UNIX
 /* Set close-on-exec flag
  */
-static int/*bool*/ s_SetCloexec(int fd, int/*bool*/ cloexec)
+static int/*bool*/ s_SetCloexec(TSOCK_Handle x_sock, int/*bool*/ cloexec)
 {
-    return fcntl(fd, F_SETFD,
+#if defined(NCBI_OS_UNIX)
+    return fcntl(x_sock, F_SETFD,
                  cloexec ?
-                 fcntl(fd, F_GETFD, 0) | FD_CLOEXEC :
-                 fcntl(fd, F_GETFD, 0) & (int) ~FD_CLOEXEC) != -1;
+                 fcntl(x_sock, F_GETFD, 0) |        FD_CLOEXEC :
+                 fcntl(x_sock, F_GETFD, 0) & (int) ~FD_CLOEXEC) != -1;
+#elif defined(NCBI_OS_MSWIN)
+    return SetHandleInformation((HANDLE)x_sock,HANDLE_FLAG_INHERIT,!cloexec);
+#else
+#   error "Unsupported platform"
+#endif /*NCBI_OS*/
 }
-#endif /*NCBI_OS_UNIX*/
 
 
 /*ARGSUSED*/
@@ -955,21 +1091,28 @@ static EIO_Status s_Status(SOCK sock, EIO_Event direction)
 #if !defined(NCBI_OS_MSWIN)  &&  defined(FD_SETSIZE)
 static int/*bool*/ x_TryLowerSockFileno(SOCK sock)
 {
-    int fd = fcntl(sock->sock, F_DUPFD, STDERR_FILENO + 1);
+#  ifdef STDERR_FILENO
+#    define SOCK_DUPOVER  STDERR_FILENO
+#  else
+#    define SOCK_DUPOVER  2
+#  endif /*STDERR_FILENO*/
+    int fd = fcntl(sock->sock, F_DUPFD, SOCK_DUPOVER + 1);
     if (fd >= 0) {
         if (fd < FD_SETSIZE) {
-            char _id[32];
+            char _id[MAXIDLEN];
             int cloexec = fcntl(sock->sock, F_GETFD, 0);
             if (cloexec > 0  &&  (cloexec & FD_CLOEXEC))
                 fcntl(fd, F_SETFD, cloexec);
             CORE_LOGF_X(111, eLOG_Note,
-                        ("%s[SOCK::Select]  File descriptor lowered to %d",
+                        ("%s[SOCK::Select] "
+                         " File descriptor has been lowered to %d",
                          s_ID(sock, _id), fd));
             close(sock->sock);
             sock->sock = fd;
             return 1/*success*/;
         }
         close(fd);
+        errno = 0;
     }
     return 0/*failure*/;
 }
@@ -995,6 +1138,581 @@ static int/*bool*/ s_IsSmallerTimeout(const struct timeval* v1,
 }
 
 
+#if !defined(NCBI_OS_MSWIN)  ||  !defined(NCBI_CXX_TOOLKIT)
+
+
+static EIO_Status s_Select_(size_t                n,
+                            SSOCK_Poll            polls[],
+                            const struct timeval* tv,
+                            int/*bool*/           asis)
+{
+    char           _id[MAXIDLEN];
+    int/*bool*/    write_only;
+    int/*bool*/    read_only;
+    fd_set         rfds;
+    fd_set         wfds;
+    fd_set         efds;
+    int            nfds;
+    struct timeval x_tv;
+    size_t         i;
+
+    if (tv)
+        x_tv = *tv;
+    else /* won't be used but keeps compilers happy */
+        memset(&x_tv, 0, sizeof(x_tv));
+
+    for (;;) { /* optionally auto-resume if interrupted / sliced */
+        int/*bool*/    ready = 0/*false*/;
+        int/*bool*/    bad   = 0/*false*/;
+#  ifdef NCBI_OS_MSWIN
+        unsigned int   count = 0;
+#  endif /*NCBI_OS_MSWIN*/
+        struct timeval xx_tv;
+
+        write_only = 1/*true*/;
+        read_only = 1/*true*/;
+        FD_ZERO(&efds);
+        nfds = 0;
+
+        for (i = 0;  i < n;  i++) {
+            EIO_Event    event;
+            SOCK         sock;
+            ESOCK_Type   type;
+            TSOCK_Handle fd;
+
+            if (!(sock = polls[i].sock)) {
+                assert(!polls[i].revent/*eIO_Open*/);
+                continue;
+            }
+
+            type = (ESOCK_Type) sock->type;
+            event = polls[i].event;
+            if (!type || (EIO_Event)(event | eIO_ReadWrite) != eIO_ReadWrite) {
+                polls[i].revent = eIO_Close;
+                if (!bad) {
+                    ready = 0/*false*/;
+                    bad   = 1/*true*/;
+                }
+                continue;
+            }
+            if (!event) {
+                assert(!polls[i].revent/*eIO_Open*/);
+                continue;
+            }
+            if (bad)
+                continue;
+
+            if ((fd = sock->sock) == SOCK_INVALID) {
+                polls[i].revent = eIO_Close;
+                ready = 1/*true*/;
+                continue;
+            }
+            if (polls[i].revent) {
+                ready = 1;
+                if (polls[i].revent == eIO_Close)
+                    continue;
+                assert((EIO_Event)
+                       (polls[i].revent | eIO_ReadWrite) == eIO_ReadWrite);
+                event = (EIO_Event)(event & ~polls[i].revent);
+            }
+
+#  if !defined(NCBI_OS_MSWIN)  &&  defined(FD_SETSIZE)
+            if (fd >= FD_SETSIZE) {
+                if (!x_TryLowerSockFileno(sock)) {
+                    /* NB: only once here, as this sets "bad" to "1" */
+                    CORE_LOGF_ERRNO_X(145, eLOG_Error, errno,
+                                      ("%s[SOCK::Select] "
+                                       " Socket file descriptor must "
+                                       " be less than %d",
+                                       s_ID(sock, _id), FD_SETSIZE));
+                    polls[i].revent = eIO_Close;
+                    ready = bad = 1;
+                    continue;
+                }
+                fd = sock->sock;
+                assert(fd < FD_SETSIZE);
+            }
+#  endif /*!NCBI_OS_MSWIN && FD_SETSIZE*/
+
+            switch (type & eSocket ? event : event & eIO_Read) {
+            case eIO_Write:
+            case eIO_ReadWrite:
+                assert(type & eSocket);
+                if (type == eDatagram  ||  sock->w_status != eIO_Closed) {
+                    if (read_only) {
+                        FD_ZERO(&wfds);
+                        read_only = 0/*false*/;
+                    }
+                    FD_SET(fd, &wfds);
+                }
+                if (event == eIO_Write  &&
+                    (type == eDatagram  ||  asis
+                     ||  (sock->r_on_w == eOff
+                          ||  (sock->r_on_w == eDefault
+                               &&  s_ReadOnWrite != eOn)))) {
+                    break;
+                }
+                /*FALLTHRU*/
+
+            case eIO_Read:
+                if (type != eSocket
+                    ||  (sock->r_status != eIO_Closed  &&  !sock->eof)) {
+                    if (write_only) {
+                        FD_ZERO(&rfds);
+                        write_only = 0/*false*/;
+                    }
+                    FD_SET(fd, &rfds);
+                }
+                if (type != eSocket  ||  asis  ||  event != eIO_Read
+                    ||  sock->w_status == eIO_Closed
+                    ||  !(sock->pending | sock->w_len)) {
+                    break;
+                }
+                if (read_only) {
+                    FD_ZERO(&wfds);
+                    read_only = 0/*false*/;
+                }
+                FD_SET(fd, &wfds);
+                break;
+
+            default:
+                /*fully pre-ready*/
+                break;
+            }
+
+            FD_SET(fd, &efds);
+            if (nfds < (int) fd)
+                nfds = (int) fd;
+
+#  ifdef NCBI_OS_MSWIN
+            /* check whether FD_SETSIZE has been exceeded */
+            if (!FD_ISSET(fd, &efds)) {
+                /* NB: only once here, as this sets "bad" to "1" */
+                CORE_LOGF_X(145, eLOG_Error,
+                            ("[SOCK::Select] "
+                             " Too many sockets in select(),"
+                             " must be less than %u", count));
+                polls[i].revent = eIO_Close;
+                ready = bad = 1;
+                continue;
+            }
+#  endif /*NCBI_OS_MSWIN*/
+        }
+        assert(i >= n);
+
+        if (bad) {
+            if (!ready) {
+                errno = EINVAL;
+                return eIO_InvalidArg;
+            } else {
+                errno = SOCK_ETOOMANY;
+                return eIO_Unknown;
+            }
+        }
+
+        if (ready)
+            memset(&xx_tv, 0, sizeof(xx_tv));
+        else if (tv  &&  s_IsSmallerTimeout(&x_tv, s_SelectTimeout))
+            xx_tv = x_tv;
+        else if (s_SelectTimeout)
+            xx_tv = *s_SelectTimeout;
+        /* else infinite (0) timeout will be used */
+
+        nfds = select(SOCK_NFDS((TSOCK_Handle) nfds),
+                      write_only ? 0 : &rfds,
+                      read_only  ? 0 : &wfds, &efds,
+                      ready  ||  tv  ||  s_SelectTimeout ? &xx_tv : 0);
+
+        if (nfds > 0)
+            break;
+
+        if (!nfds) {
+            /* timeout has expired */
+            if (!ready) {
+                if (!tv)
+                    continue;
+                if (s_IsSmallerTimeout(s_SelectTimeout, &x_tv)) {
+                    x_tv.tv_sec -= s_SelectTimeout->tv_sec;
+                    if (x_tv.tv_usec < s_SelectTimeout->tv_usec) {
+                        x_tv.tv_sec--;
+                        x_tv.tv_usec += 1000000;
+                    }
+                    x_tv.tv_usec -= s_SelectTimeout->tv_usec;
+                    continue;
+                }
+                return eIO_Timeout;
+            }
+        } else { /* nfds < 0 */
+            int x_error = SOCK_ERRNO;
+            if (x_error != SOCK_EINTR) {
+                CORE_LOGF_ERRNO_EXX(5, eLOG_Warning,
+                                    x_error, SOCK_STRERROR(x_error),
+                                    ("%s[SOCK::Select] "
+                                     " Failed select()",
+                                     n == 1 ? s_ID(polls[0].sock, _id) : ""));
+                if (!ready)
+                    return eIO_Unknown;
+            }
+        }
+        if (ready) {
+            n = 0;
+            break;
+        }
+
+        if ((n != 1  &&  s_InterruptOnSignal == eOn)  ||
+            (n == 1  &&  (polls[0].sock->i_on_sig == eOn
+                          ||  (polls[0].sock->i_on_sig == eDefault
+                               &&  s_InterruptOnSignal == eOn)))) {
+            return eIO_Interrupt;
+        }
+    }
+
+    nfds = 0;
+    for (i = 0;  i < n;  i++) {
+        SOCK sock = polls[i].sock;
+        if (sock  &&  polls[i].event) {
+            TSOCK_Handle fd = sock->sock;
+            if (polls[i].revent == eIO_Close) {
+                nfds++;
+                continue;
+            }
+            if (fd == SOCK_INVALID) {
+                polls[i].revent = eIO_Close;
+                nfds++;
+                continue;
+            }
+#  if !defined(NCBI_OS_MSWIN)  &&  defined(FD_SETSIZE)
+            assert(fd < FD_SETSIZE);
+#  endif /*!NCBI_OS_MSWIN && FD_SETSIZE*/
+            if (!write_only  &&  FD_ISSET(fd, &rfds)) {
+                polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Read);
+#  ifdef NCBI_OS_MSWIN
+                sock->readable = 1/*true*/;
+#  endif /*NCBI_OS_MSWIN*/
+            }
+            if (!read_only   &&  FD_ISSET(fd, &wfds)) {
+                polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Write);
+#  ifdef NCBI_OS_MSWIN
+                sock->writable = 1/*true*/;
+#  endif /*NCBI_OS_MSWIN*/
+            }
+            if (polls[i].revent == eIO_Open) {
+                if (!FD_ISSET(fd, &efds))
+                    continue;
+                polls[i].revent = eIO_Close;
+            } else if (sock->type == eTrigger)
+                polls[i].revent = polls[i].event;
+            nfds++;
+        } else
+            assert(polls[i].revent == eIO_Open);
+    }
+
+    assert(!n/*pre-ready*/  ||  nfds);
+    /* success; can do I/O now */
+    return eIO_Success;
+}
+
+
+#  if defined(NCBI_OS_UNIX)  &&  defined(HAVE_POLL_H)
+
+
+#    define NPOLLS ((3 * sizeof(fd_set)) / sizeof(struct pollfd))
+
+
+static unsigned int s_CountPolls(size_t n, SSOCK_Poll polls[])
+{
+    int/*bool*/  bigfd = 0/*false*/;
+    int/*bool*/  good  = 1/*true*/;
+    unsigned int count = 0;
+    size_t i;
+
+    for (i = 0;  i < n;  i++) {
+        if (!polls[i].sock) {
+            assert(!polls[i].revent/*eIO_Open*/);
+            continue;
+        }
+        if (!polls[i].sock->type
+            ||  (EIO_Event)(polls[i].event | eIO_ReadWrite) != eIO_ReadWrite) {
+            good = 0/*false*/;
+            continue;
+        }
+        if (!polls[i].event) {
+            assert(!polls[i].revent/*eIO_Open*/);
+            continue;
+        }
+        if (polls[i].sock->sock == SOCK_INVALID
+            ||  polls[i].revent == eIO_Closed) {
+            /* pre-ready */
+            continue;
+        }
+#    ifdef FD_SETSIZE
+        if (polls[i].sock->sock >= FD_SETSIZE
+            &&  (s_IOWaitSysAPI == eSOCK_IOWaitSysAPIPoll
+                 ||  !x_TryLowerSockFileno(polls[i].sock))) {
+            bigfd = 1/*true*/;
+        }
+#    endif /*FD_SETSIZE*/
+        count++;
+    }
+    return good  &&  (s_IOWaitSysAPI != eSOCK_IOWaitSysAPIAuto
+                      ||  count <= NPOLLS  ||  bigfd) ? count : 0;
+}
+
+
+static EIO_Status s_Poll_(size_t                n,
+                          SSOCK_Poll            polls[],
+                          const struct timeval* tv,
+                          int/*bool*/           asis)
+{
+    struct pollfd  xx_polls[NPOLLS];
+    char           _id[MAXIDLEN];
+    struct pollfd* x_polls;
+    EIO_Status     status;
+    unsigned int   ready;
+    unsigned int   count;
+    int            wait;
+    unsigned int   m;
+    size_t         i;
+
+    if (s_IOWaitSysAPI != eSOCK_IOWaitSysAPIAuto)
+        m = (unsigned int) n;
+    else
+#ifdef FD_SETSIZE
+    if (n > FD_SETSIZE)
+        m = (unsigned int) n;
+    else
+#endif /*FD_SETSIZE*/
+    if (!(m = s_CountPolls(n, polls)))
+        return s_Select_(n, polls, tv, asis);
+
+    if (m <= NPOLLS)
+        x_polls = xx_polls;
+    else if (!(x_polls = (struct pollfd*) malloc(m * sizeof(*x_polls)))) {
+        CORE_LOGF_ERRNO_X(146, eLOG_Critical, errno,
+                          ("%s[SOCK::Select] "
+                           " Cannot allocate poll vector(%u)",
+                           n == 1 ? s_ID(polls[0].sock, _id) : "", m));
+        return eIO_Unknown;
+    }
+
+    status = eIO_Success;
+    wait = tv ? (int)(tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000) : -1;
+    for (;;) { /* optionally auto-resume if interrupted / sliced */
+        int/*bool*/ bad = 0/*false*/;
+        int         x_ready;
+        int         slice;
+
+        ready = count = 0;
+        for (i = 0;  i < n;  i++) {
+            short        bitset;
+            EIO_Event    event;
+            SOCK         sock;
+            ESOCK_Type   type;
+            TSOCK_Handle fd;
+
+            if (!(sock = polls[i].sock)) {
+                assert(!polls[i].revent/*eIO_Open*/);
+                continue;
+            }
+
+            type = (ESOCK_Type) sock->type;
+            event = polls[i].event;
+            if (!type || (EIO_Event)(event | eIO_ReadWrite) != eIO_ReadWrite) {
+                polls[i].revent = eIO_Close;
+                bad = 1/*true*/;
+                continue;
+            }
+            if (!event) {
+                assert(!polls[i].revent/*eIO_Open*/);
+                continue;
+            }
+            if (bad)
+                continue;
+
+            if ((fd = sock->sock) == SOCK_INVALID) {
+                polls[i].revent = eIO_Close;
+                ready++;
+                continue;
+            }
+            if (polls[i].revent) {
+                ready++;
+                if (polls[i].revent == eIO_Close)
+                    continue;
+                assert((EIO_Event)
+                       (polls[i].revent | eIO_ReadWrite) == eIO_ReadWrite);
+                event = (EIO_Event)(event & ~polls[i].revent);
+            }
+
+            bitset = 0;
+            switch (type & eSocket ? event : event & eIO_Read) {
+            case eIO_Write:
+            case eIO_ReadWrite:
+                assert(type & eSocket);
+                if (type == eDatagram  ||  sock->w_status != eIO_Closed)
+                    bitset |= POLLOUT;
+                if (event == eIO_Write  &&
+                    (type == eDatagram  ||  asis
+                     ||  (sock->r_on_w == eOff
+                          ||  (sock->r_on_w == eDefault
+                               &&  s_ReadOnWrite != eOn)))) {
+                    break;
+                }
+                /*FALLTHRU*/
+
+            case eIO_Read:
+                if (type != eSocket
+                    ||  (sock->r_status != eIO_Closed  &&  !sock->eof))
+                    bitset |= POLLIN;
+                if (type != eSocket  ||  asis  ||  event != eIO_Read
+                    ||  sock->w_status == eIO_Closed
+                    ||  !(sock->pending | sock->w_len)) {
+                    break;
+                }
+                bitset |= POLLOUT;
+                break;
+
+            default:
+                /*fully pre-ready*/
+                continue;
+            }
+
+            if (!bitset)
+                continue;
+            assert(count < m);
+            x_polls[count].fd      = fd;
+            x_polls[count].events  = bitset;
+            x_polls[count].revents = 0;
+            count++;
+        }
+        assert(i >= n);
+
+        if (bad) {
+            errno = EINVAL;
+            return eIO_InvalidArg;
+        }
+
+        if (s_SelectTimeout) {
+            slice = ( s_SelectTimeout->tv_sec         * 1000 +
+                     (s_SelectTimeout->tv_usec + 500) / 1000);
+            if (wait != -1  &&  wait < slice)
+                slice = wait;
+        } else
+            slice = wait;
+
+        x_ready = !count && ready? 0 : poll(x_polls, count, ready ? 0 : slice);
+
+        if (x_ready > 0) {
+            ready = x_ready;
+            break;
+        }
+
+        if (!x_ready) {
+            /* timeout has expired */
+            if (!ready) {
+                if (!tv)
+                    continue;
+                if (wait > slice) {
+                    wait -= slice;
+                    continue;
+                }
+                status = eIO_Timeout;
+                break;
+            }
+        } else { /* x_ready < 0 */
+            if ((x_ready = SOCK_ERRNO) != SOCK_EINTR) {
+                CORE_LOGF_ERRNO_EXX(147, eLOG_Warning,
+                                    x_ready, SOCK_STRERROR(x_ready),
+                                    ("%s[SOCK::Select] "
+                                     " Failed poll()",
+                                     n == 1 ? s_ID(polls[0].sock, _id) : ""));
+                if (!ready) {
+                    status = eIO_Unknown;
+                    break;
+                }
+            }
+        }
+        if (ready) {
+            assert(status == eIO_Success);
+            count = ready = 0;
+            n = 0;
+            break;
+        }
+
+        if ((n != 1  &&  s_InterruptOnSignal == eOn)  ||
+            (n == 1  &&  (polls[0].sock->i_on_sig == eOn
+                          ||  (polls[0].sock->i_on_sig == eDefault
+                               &&  s_InterruptOnSignal == eOn)))) {
+            status = eIO_Interrupt;
+            break;
+        }
+    }
+
+    if (status == eIO_Success) {
+        unsigned int seen;
+        int nfds = 0;
+        for (m = 0, i = 0, seen = 0;  i < n;  i++) {
+            SOCK sock = polls[i].sock;
+            if (sock  &&  polls[i].event) {
+                short events, revents;
+                if (polls[i].revent == eIO_Close) {
+                    nfds++;
+                    continue;
+                }
+                if (sock->sock == SOCK_INVALID) {
+                    polls[i].revent = eIO_Close;
+                    nfds++;
+                    continue;
+                }
+                events = revents = 0;
+                if (seen < ready) {
+                    unsigned int j, x_seen;
+                    assert(m < count);
+                    for (j = m, x_seen = 0;  j < count;  j++) {
+                        if (x_polls[j].revents)
+                            j == m ? ++seen : ++x_seen;
+                        if (x_polls[j].fd == sock->sock) {
+                            events  = x_polls[j].events;
+                            revents = x_polls[j].revents;
+                            seen += x_seen;
+                            m = j;
+                            break;
+                        }
+                    }
+                    m++;
+                }
+                if ((events & POLLIN)
+                     &&  (revents & (POLLIN | POLLHUP | POLLPRI))) {
+                    polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Read);
+                }
+                if ((events & POLLOUT)
+                    &&  (revents & (POLLOUT | POLLHUP))) {
+                    polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Write);
+                }
+                if (polls[i].revent == eIO_Open) {
+                    if (!(revents & (POLLERR | POLLNVAL)))
+                        continue;
+                    polls[i].revent = eIO_Close;
+                } else if (sock->type == eTrigger)
+                    polls[i].revent = polls[i].event;
+                nfds++;
+            } else
+                assert(polls[i].revent == eIO_Open);
+        }
+        assert(!n  ||  nfds);
+    }
+
+    if (x_polls != xx_polls)
+        free(x_polls);
+    return status;
+}
+
+
+#endif /*NCBI_OS_UNIX && HAVE_POLL_H*/
+
+
+#endif /*!NCBI_OS_MSWIN || !NCBI_CXX_TOOLKIT*/
+
+
 /* Select on the socket I/O (multiple sockets).
  *
  * "Event" field is not considered for entries, whose "sock" field is 0,
@@ -1008,7 +1726,7 @@ static int/*bool*/ s_IsSmallerTimeout(const struct timeval* v1,
  *
  * This function always checks datagram and listening sockets, and triggers
  * exactly as they are requested (according to "event").  For stream sockets,
- * the call behaves differently only if the last parameter is passed non-zero:
+ * the call behaves differently only if the last parameter is passed as zero:
  *
  * If "eIO_Write" event is inquired on a stream socket, and the socket is
  * marked for upread, then returned "revent" may also include "eIO_Read" to
@@ -1032,48 +1750,54 @@ static EIO_Status s_Select(size_t                n,
                            int/*bool*/           asis)
 {
 #if defined(NCBI_OS_MSWIN)  &&  defined(NCBI_CXX_TOOLKIT)
-    DWORD wait = tv ? tv->tv_sec * 1000 + tv->tv_usec / 1000 : INFINITE;
+    DWORD wait = tv? tv->tv_sec * 1000 + (tv->tv_usec + 500) / 1000 : INFINITE;
 
     for (;;) { /* timeslice loop */
         HANDLE             what[MAXIMUM_WAIT_OBJECTS];
         long               want[MAXIMUM_WAIT_OBJECTS];
+        char        _id[MAXIDLEN];
+        int/*bool*/ ready = 0/*false*/;
+        int/*bool*/ bad = 0/*false*/;
         DWORD              count = 0;
-        int/*signed bool*/ ready = 0;
-        int/*bool*/        bad = 0;
-        char               _id[32];
         DWORD              slice;
         size_t             i;
 
         for (i = 0;  i < n;  i++) {
+            long       bitset;
             EIO_Event  event;
             ESOCK_Type type;
             SOCK       sock;
+            HANDLE     ev;
 
             if (!(sock = polls[i].sock)) {
-                polls[i].revent = eIO_Open;
+                assert(!polls[i].revent/*eIO_Open*/);
                 continue;
             }
 
             type = (ESOCK_Type) sock->type;
-            if (!type  ||  !(event = polls[i].event)
-                ||  (EIO_Event)(event | eIO_ReadWrite) != eIO_ReadWrite) {
+            event = polls[i].event;
+            if (!type || (EIO_Event)(event | eIO_ReadWrite) != eIO_ReadWrite) {
                 polls[i].revent = eIO_Close;
                 if (!bad) {
-                    ready = 0;
-                    bad   = 1;
+                    ready = 0/*false*/;
+                    bad   = 1/*true*/;
                 }
                 continue;
             }
+            if (!event) {
+                assert(!polls[i].revent/*eIO_Open*/);
+                continue;
+            }
+            if (bad)
+                continue;
 
             if (sock->sock == SOCK_INVALID) {
                 polls[i].revent = eIO_Close;
-                if (!bad)
-                    ready = 1;
+                ready = 1/*true*/;
                 continue;
             }
-
-            if (!bad  &&  polls[i].revent) {
-                ready = 1;
+            if (polls[i].revent) {
+                ready = 1/*true*/;
                 if (polls[i].revent == eIO_Close)
                     continue;
                 assert((EIO_Event)
@@ -1081,16 +1805,8 @@ static EIO_Status s_Select(size_t                n,
                 event = (EIO_Event)(event & ~polls[i].revent);
             }
 
-            if (bad)
-                continue;
-
-            if (count >= sizeof(what)/sizeof(what[0])) {
-                ready = bad = 1;
-                continue;
-            }
-
+            bitset = 0;
             if (type != eTrigger) {
-                long mask = 0;
                 EIO_Event readable = sock->readable ? eIO_Read  : eIO_Open;
                 EIO_Event writable = sock->writable ? eIO_Write : eIO_Open;
                 switch (type & eSocket ? event : event & eIO_Read) {
@@ -1099,11 +1815,11 @@ static EIO_Status s_Select(size_t                n,
                     if (type == eDatagram  ||  sock->w_status != eIO_Closed) {
                         if (writable) {
                             polls[i].revent |= eIO_Write;
-                            ready = 1;
+                            ready = 1/*true*/;
                         }
                         if (!sock->connected)
-                            mask |= FD_CONNECT/*C*/;
-                        mask     |= FD_WRITE/*W*/;
+                            bitset |= FD_CONNECT/*C*/;
+                        bitset     |= FD_WRITE/*W*/;
                     }
                     if (event == eIO_Write  &&
                         (type == eDatagram  ||  asis
@@ -1119,14 +1835,14 @@ static EIO_Status s_Select(size_t                n,
                         ||  (sock->r_status != eIO_Closed  &&  !sock->eof)) {
                         if (readable) {
                             polls[i].revent |= eIO_Read;
-                            ready = 1;
+                            ready = 1/*true*/;
                         }
                         if (type & eSocket) {
                             if (type == eSocket)
-                                mask |= FD_OOB/*O*/;
-                            mask     |= FD_READ/*R*/;
+                                bitset |= FD_OOB/*O*/;
+                            bitset     |= FD_READ/*R*/;
                         } else
-                            mask     |= FD_ACCEPT/*A*/;
+                            bitset     |= FD_ACCEPT/*A*/;
                     }
                     if (type != eSocket  ||  asis  ||  event != eIO_Read
                         ||  sock->w_status == eIO_Closed
@@ -1135,9 +1851,9 @@ static EIO_Status s_Select(size_t                n,
                     }
                     if (writable) {
                         polls[i].revent |= eIO_Write;
-                        ready = 1;
+                        ready = 1/*true*/;
                     }
-                    mask |= FD_WRITE/*W*/;
+                    bitset |= FD_WRITE/*W*/;
                     break;
 
                 default:
@@ -1145,11 +1861,24 @@ static EIO_Status s_Select(size_t                n,
                     continue;
                 }
 
-                assert(mask);
-                want[count]   = mask;
-                what[count++] = sock->event;
+                if (!bitset)
+                    continue;
+                ev = sock->event;
             } else
-                what[count++] = ((TRIGGER) sock)->fd;
+                ev = ((TRIGGER) sock)->fd;
+
+            if (count >= sizeof(what)/sizeof(what[0])) {
+                /* NB: only once here, as this sets "bad" to "1" */
+                CORE_LOGF_X(145, eLOG_Error,
+                            ("[SOCK::Select] "
+                             " Too many objects, must be less than %u",
+                             (unsigned int) count));
+                polls[i].revent = eIO_Close;
+                ready = bad = 1/*true*/;
+                continue;
+            }
+            want[count]   = bitset;
+            what[count++] = ev;
         }
         assert(i >= n);
 
@@ -1157,16 +1886,15 @@ static EIO_Status s_Select(size_t                n,
             if (!ready) {
                 errno = EINVAL;
                 return eIO_InvalidArg;
-            } else if (ready > 0) {
+            } else {
                 errno = SOCK_ETOOMANY;
                 return eIO_Unknown;
-            } else
-                return eIO_NotSupported;
+            }
         }
 
         if (s_SelectTimeout) {
-            slice = (s_SelectTimeout->tv_sec  * 1000 +
-                     s_SelectTimeout->tv_usec / 1000);
+            slice = ( s_SelectTimeout->tv_sec         * 1000 +
+                     (s_SelectTimeout->tv_usec + 500) / 1000);
             if (wait != INFINITE  &&  wait < slice)
                 slice = wait;
         } else
@@ -1187,8 +1915,8 @@ static EIO_Status s_Select(size_t                n,
                     char* strerr = s_WinStrerror(err);
                     CORE_LOGF_ERRNO_EXX(133, eLOG_Error,
                                         err, strerr ? strerr : "",
-                                        ("[SOCK::Select]  Failed"
-                                         " WaitForMultipleObjects"));
+                                        ("[SOCK::Select] "
+                                         " Failed WaitForMultipleObjects"));
                     if (strerr)
                         LocalFree(strerr);
                     break;
@@ -1197,9 +1925,9 @@ static EIO_Status s_Select(size_t                n,
                     break;
                 if (r < WAIT_OBJECT_0  ||  r >= WAIT_OBJECT_0 + m) {
                     CORE_LOGF_X(134, ready ? eLOG_Trace : eLOG_Error,
-                                ("[SOCK::Select]  WaitForMultipleObjects(%u)"
-                                 " returned %d", (unsigned int) m,
-                                 (int)(r - WAIT_OBJECT_0)));
+                                ("[SOCK::Select] "
+                                 " WaitForMultipleObjects(%u) returned %d",
+                                 (unsigned int) m, (int)(r - WAIT_OBJECT_0)));
                     r = WAIT_FAILED;
                     break;
                 }
@@ -1209,8 +1937,8 @@ static EIO_Status s_Select(size_t                n,
                 for (j = i;  j < n;  j++) {
                     SOCK sock = polls[j].sock;
                     WSANETWORKEVENTS e;
-                    long mask;
-                    if (!sock)
+                    long bitset;
+                    if (!sock  ||  !polls[j].event)
                         continue;
                     if (sock->type == eTrigger) {
                         if (what[i] != ((TRIGGER) sock)->fd)
@@ -1241,48 +1969,49 @@ static EIO_Status s_Select(size_t                n,
                         break;
                     }
                     /* NB: the bits are XCAOWR */
-                    if (!(mask = e.lNetworkEvents)) {
+                    if (!(bitset = e.lNetworkEvents)) {
                         if (sock->type == eListening
                             &&  (sock->log == eOn  || 
                                  (sock->log == eDefault  &&  s_Log == eOn))) {
                             LSOCK lsock = (LSOCK) sock;
                             ELOG_Level level;
-                            if (lsock->n_log < 10) {
-                                lsock->n_log++;
+                            if (lsock->away < 10) {
+                                lsock->away++;
                                 level = eLOG_Warning;
                             } else
                                 level = eLOG_Trace;
                             CORE_LOGF_X(141, level,
                                         ("%s[SOCK::Select] "
-                                         " Run-away connection has"
-                                         " been detected", s_ID(sock, _id)));
+                                         " Run-away connection detected",
+                                         s_ID(sock, _id)));
                         }
                         break;
                     }
-                    if (mask & FD_CLOSE/*X*/) {
+                    if (bitset & FD_CLOSE/*X*/) {
                         if (sock->type != eSocket) {
                             polls[j].revent = eIO_Close;
                             ready = 1;
                             break;
                         }
+                        bitset |= FD_READ/*at least SHUT_WR @ remote end*/;
                         sock->readable = 1/*true*/;
-                        sock->closeing = 1/*true*/;
+                        sock->closing  = 1/*true*/;
                     } else {
-                        if (mask & (FD_CONNECT | FD_WRITE)) {
+                        if (bitset & (FD_CONNECT | FD_WRITE)) {
                             assert(sock->type & eSocket);
                             sock->writable = 1/*true*/;
                         }
-                        if (mask & (FD_ACCEPT | FD_OOB | FD_READ))
+                        if (bitset & (FD_ACCEPT | FD_OOB | FD_READ))
                             sock->readable = 1/*true*/;
                     }
-                    mask &= want[i];
-                    if ((mask & (FD_CONNECT | FD_WRITE))
+                    bitset &= want[i];
+                    if ((bitset & (FD_CONNECT | FD_WRITE))
                         &&  sock->writable) {
                         assert(sock->type & eSocket);
                         polls[j].revent=(EIO_Event)(polls[j].revent|eIO_Write);
                         ready = 1;
                     }
-                    if ((mask & (FD_ACCEPT | FD_OOB | FD_READ))
+                    if ((bitset & (FD_ACCEPT | FD_OOB | FD_READ))
                         &&  sock->readable) {
                         polls[j].revent=(EIO_Event)(polls[j].revent|eIO_Read);
                         ready = 1;
@@ -1330,290 +2059,19 @@ static EIO_Status s_Select(size_t                n,
             break;
     }
 
-#else
-    int/*bool*/    write_only;
-    int/*bool*/    read_only;
-    fd_set         r_fds;
-    fd_set         w_fds;
-    fd_set         e_fds;
-    int            n_fds;
-    struct timeval x_tv;
-    size_t         i;
-
-    if (tv)
-        x_tv = *tv;
-    else /* won't be used but keeps compilers happy */
-        memset(&x_tv, 0, sizeof(x_tv));
-
-    for (;;) { /* optionally auto-resume if interrupted */
-        int/*bool*/    ready = 0;
-        int/*bool*/    bad = 0;
-        int            x_error;
-        struct timeval xx_tv;
-        EIO_Event      event;
-        ESOCK_Type     type;
-        SOCK           sock;
-        TSOCK_Handle   fd;
-
-        n_fds = 0;
-        FD_ZERO(&r_fds);
-        FD_ZERO(&w_fds);
-        FD_ZERO(&e_fds);
-        write_only = 1;
-        read_only = 1;
-
-        for (i = 0;  i < n;  i++) {
-            if (!(sock = polls[i].sock)) {
-                polls[i].revent = eIO_Open;
-                continue;
-            }
-
-            type = (ESOCK_Type) sock->type;
-            if (!type  ||  !(event = polls[i].event)
-                ||  (EIO_Event)(event | eIO_ReadWrite) != eIO_ReadWrite) {
-                polls[i].revent = eIO_Close;
-                if (!bad) {
-                    ready = 0;
-                    bad   = 1;
-                }
-                continue;
-            }
-
-            if ((fd = sock->sock) == SOCK_INVALID) {
-                polls[i].revent = eIO_Close;
-                if (!bad)
-                    ready = 1;
-                continue;
-            }
-
-            if (!bad  &&  polls[i].revent) {
-                ready = 1;
-                if (polls[i].revent == eIO_Close)
-                    continue;
-                assert((EIO_Event)
-                       (polls[i].revent | eIO_ReadWrite) == eIO_ReadWrite);
-                event = (EIO_Event)(event & ~polls[i].revent);
-            }
-
-            if (bad)
-                continue;
-
-#  if !defined(NCBI_OS_MSWIN)  &&  defined(FD_SETSIZE)
-            if (fd >= FD_SETSIZE) {
-                if (!x_TryLowerSockFileno(sock)) {
-                    polls[i].revent = eIO_Close;
-                    ready = bad = 1;
-                    continue;
-                }
-                fd = sock->sock;
-                assert(fd < FD_SETSIZE);
-            }
-#  endif /*!NCBI_MSWIN && FD_SETSIZE*/
-
-            if (type == eTrigger  &&  *((void**) &((TRIGGER) sock)->isset)) {
-                polls[i].revent = polls[i].event;
-                ready = 1;
-                continue;
-            }
-
-            switch (type & eSocket ? event : event & eIO_Read) {
-            case eIO_Write:
-            case eIO_ReadWrite:
-                assert(type & eSocket);
-                if (type == eDatagram  ||  sock->w_status != eIO_Closed) {
-                    read_only = 0;
-                    FD_SET(fd, &w_fds);
-                }
-                if (event == eIO_Write  &&
-                    (type == eDatagram  ||  asis
-                     ||  (sock->r_on_w == eOff
-                          ||  (sock->r_on_w == eDefault
-                               &&  s_ReadOnWrite != eOn)))) {
-                    break;
-                }
-                /*FALLTHRU*/
-
-            case eIO_Read:
-                if (type != eSocket
-                    ||  (sock->r_status != eIO_Closed  &&  !sock->eof)) {
-                    write_only = 0;
-                    FD_SET(fd, &r_fds);
-                }
-                if (type != eSocket  ||  asis  ||  event != eIO_Read
-                    ||  sock->w_status == eIO_Closed
-                    ||  !(sock->pending | sock->w_len)) {
-                    break;
-                }
-                read_only = 0;
-                FD_SET(fd, &w_fds);
-                break;
-
-            default:
-                /*fully pre-ready*/
-                break;
-            }
-
-            FD_SET(fd, &e_fds);
-            if (n_fds < (int) fd)
-                n_fds = (int) fd;
-#  ifdef NCBI_OS_MSWIN
-            /* check whether FD_SETSIZE has been overcome */
-            if (!FD_ISSET(fd, &e_fds)) {
-                polls[i].revent = eIO_Close;
-                ready = bad = 1;
-                continue;
-            }
-#  endif /*NCBI_OS_MSWIN*/
-        }
-        assert(i >= n);
-
-        if (bad) {
-            if (!ready) {
-                errno = EINVAL;
-                return eIO_InvalidArg;
-            } else {
-                errno = SOCK_ETOOMANY;
-                return eIO_Unknown;
-            }
-        }
-
-        if (ready)
-            memset(&xx_tv, 0, sizeof(xx_tv));
-        else if (tv  &&  s_IsSmallerTimeout(&x_tv, s_SelectTimeout))
-            xx_tv = x_tv;
-        else if (s_SelectTimeout)
-            xx_tv = *s_SelectTimeout;
-        /* else infinite (0) timeout will be used */
-
-        n_fds = select(SOCK_NFDS((TSOCK_Handle) n_fds),
-                       write_only ? 0 : &r_fds,
-                       read_only  ? 0 : &w_fds, &e_fds,
-                       ready  ||  tv  ||  s_SelectTimeout ? &xx_tv : 0);
-
-        /* timeout has expired */
-        if (n_fds == 0) {
-            if (ready)
-                return eIO_Success;
-            if (!tv)
-                continue;
-            if (s_IsSmallerTimeout(s_SelectTimeout, &x_tv)) {
-                x_tv.tv_sec -= s_SelectTimeout->tv_sec;
-                if (x_tv.tv_usec < s_SelectTimeout->tv_usec) {
-                    x_tv.tv_sec--;
-                    x_tv.tv_usec += 1000000;
-                }
-                x_tv.tv_usec -= s_SelectTimeout->tv_usec;
-                continue;
-            }
-            return eIO_Timeout;
-        }
-
-        if (n_fds > 0)
-            break;
-
-        /* n_fds < 0 */
-        if ((x_error = SOCK_ERRNO) != SOCK_EINTR) {
-            char _id[32];
-            CORE_LOGF_ERRNO_EXX(5, eLOG_Trace,
-                                x_error, SOCK_STRERROR(x_error),
-                                ("%s[SOCK::Select]  Failed select()",
-                                 n == 1 ? s_ID(polls[0].sock, _id) : ""));
-            if (!ready)
-                return eIO_Unknown;
-        }
-        if (ready) {
-            n = 0;
-            break;
-        }
-
-        if ((n != 1  &&  s_InterruptOnSignal == eOn)  ||
-            (n == 1  &&  (polls[0].sock->i_on_sig == eOn
-                          ||  (polls[0].sock->i_on_sig == eDefault
-                               &&  s_InterruptOnSignal == eOn)))) {
-            return eIO_Interrupt;
-        }
-    }
-
-    n_fds = 0;
-    for (i = 0;  i < n;  i++) {
-        SOCK sock = polls[i].sock;
-        if (sock) {
-            TSOCK_Handle fd = sock->sock;
-            if (fd == SOCK_INVALID) {
-                polls[i].revent = eIO_Close;
-                n_fds++;
-                continue;
-            }
-            if (polls[i].revent != eIO_Close) {
-                if (!write_only  &&  FD_ISSET(fd, &r_fds)) {
-                    polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Read);
-#  ifdef NCBI_OS_MSWIN
-                    sock->readable = 1/*true*/;
-#  endif /*NCBI_OS_MSWIN*/
-                }
-                if (!read_only   &&  FD_ISSET(fd, &w_fds)) {
-                    polls[i].revent = (EIO_Event)(polls[i].revent | eIO_Write);
-#  ifdef NCBI_OS_MSWIN
-                    sock->writable = 1/*true*/;
-#  endif /*NCBI_OS_MSWIN*/
-                }
-                if (polls[i].revent == eIO_Open) {
-                    if (!FD_ISSET(fd, &e_fds))
-                        continue;
-                    polls[i].revent = eIO_Close;
-                } else if (sock->type == eTrigger)
-                    polls[i].revent = polls[i].event;
-            }
-            n_fds++;
-        } else
-            assert(polls[i].revent == eIO_Open);
-    }
-    assert(!n  ||  n_fds);
-
-#endif /*NCBI_OS_MSWIN && NCBI_CXX_TOOLKIT*/
-
     /* success; can do I/O now */
     return eIO_Success;
-}
 
+#else /*!NCBI_OS_MSWIN || !NCBI_CXX_TOOLKIT*/
 
-#ifdef __GNUC__
-inline
-#endif /*__GNUC__*/
-static const char* x_ConnPoint(const SOCK sock, char* buf, size_t bufsize)
-{
-#ifdef NCBI_OS_UNIX
-    if (*sock->path) {
-        size_t      pathlen = strlen(sock->path);
-        int/*bool*/ trunc;
-        if (pathlen > bufsize - 3) {
-            bufsize -= 6;
-            trunc = 1;
-        } else
-            trunc = 0;
-        sprintf(buf, "\"%s%.*s\"", trunc ? "..."   : "", 
-                (int)(trunc ? bufsize : pathlen),
-                sock->path + (trunc ? pathlen - bufsize : 0));
-    } else
-#endif /*NCBI_OS_UNIX*/
-        SOCK_HostPortToString(sock->host, sock->port, buf, bufsize);
-    return buf;
-}
+#  if defined(NCBI_OS_UNIX)  &&  defined(HAVE_POLL_H)
+    if (s_IOWaitSysAPI != eSOCK_IOWaitSysAPISelect)
+        return s_Poll_(n, polls, tv, asis);
+#  endif /*NCBI_OS_UNIX && HAVE_POLL_H*/
 
+    return s_Select_(n, polls, tv, asis);
 
-static unsigned short x_GetLocalPort(TSOCK_Handle fd)
-{
-    struct sockaddr_in addr;
-    SOCK_socklen_t addrlen = (SOCK_socklen_t) sizeof(addr);
-    memset(&addr, 0, sizeof(addr));
-#ifdef HAVE_SIN_LEN
-    addr.sin_len = addrlen;
-#endif /*HAVE_SIN_LEN*/
-    if (getsockname(fd, (struct sockaddr*) &addr, &addrlen) == 0) {
-        assert(addr.sin_family == AF_INET);
-        return ntohs(addr.sin_port);
-    }
-    return 0;
+#endif /*NCBI_OS_MSWIN && NCBI_CXX_TOOLKIT*/
 }
 
 
@@ -1626,9 +2084,9 @@ static EIO_Status s_IsConnected(SOCK                  sock,
                                 int*                  error,
                                 int/*bool*/           writeable)
 {
+    char _id[MAXIDLEN];
     EIO_Status status;
     SSOCK_Poll poll;
-    char _id[32];
 
     *error = 0;
     if (sock->w_status == eIO_Closed)
@@ -1676,29 +2134,17 @@ static EIO_Status s_IsConnected(SOCK                  sock,
     if (!sock->connected) {
 #if defined(_DEBUG)  &&  !defined(NDEBUG)
         int  mtu;
-        char buf[80];
-        char _id[32];
 #  if defined(SOL_IP)  &&  defined(IP_MTU)
         SOCK_socklen_t mtulen = (SOCK_socklen_t) sizeof(mtu);
         if (getsockopt(sock->sock, SOL_IP, IP_MTU, &mtu, &mtulen) != 0)
 #  endif /*SOL_IP && IP_MTU*/
             mtu = -1;
-#  ifdef NCBI_OS_UNIX
-        if (*sock->path)
-            x_ConnPoint(sock, buf, sizeof(buf));
-        else
-#  endif /*NCBI_OS_UNIX*/
-        {
-            if (!sock->myport)
-                sock->myport = x_GetLocalPort(sock->sock);
-            sprintf(buf, ":%hu", sock->myport);
-        }
         if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn)) {
-            CORE_TRACEF(("%sConnection established at %s, MTU = %d",
-                         s_ID(sock, _id), buf, mtu));
+            CORE_TRACEF(("%sConnection established, MTU = %d%s",
+                         s_ID(sock, _id), mtu, mtu < 0 ? " [unknown]" : ""));
         }
 #endif /*_DEBUG && !NDEBUG*/
-        if (s_ReuseAddress
+        if (s_ReuseAddress == eOn
 #ifdef NCBI_OS_UNIX
             &&  !*sock->path
 #endif /*NCBI_OS_UNIX*/
@@ -1706,8 +2152,9 @@ static EIO_Status s_IsConnected(SOCK                  sock,
             int x_error = SOCK_ERRNO;
             CORE_LOGF_ERRNO_EXX(6, eLOG_Note,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("%s[SOCK::IsConnected]  Failed"
-                                 " setsockopt(REUSEADDR)", s_ID(sock, _id)));
+                                ("%s[SOCK::IsConnected] "
+                                 " Failed setsockopt(REUSEADDR)",
+                                 s_ID(sock, _id)));
         }
         sock->connected = 1;
     }
@@ -1728,8 +2175,9 @@ static EIO_Status s_IsConnected(SOCK                  sock,
                     if (status != eIO_Timeout) {
                         CORE_LOGF_ERRNO_EXX(126, eLOG_Trace,
                                             *error, s_StrError(sock, *error),
-                                            ("%s[SOCK::IsConnected]  Failed"
-                                             " SSL hello", s_ID(sock, _id)));
+                                            ("%s[SOCK::IsConnected] "
+                                             " Failed SSL hello",
+                                             s_ID(sock, _id)));
                     }
                 } else
                     sock->pending = 0;
@@ -1756,33 +2204,37 @@ static EIO_Status s_Recv(SOCK    sock,
                          size_t* n_read,
                          int     flag)
 {
+    int/*bool*/ readable;
+    char _id[MAXIDLEN];
+
     assert(sock->type == eSocket  &&  buf  &&  size > 0  &&  !*n_read);
 
     if (sock->r_status == eIO_Closed  ||  sock->eof)
         return eIO_Closed;
 
     /* read from the socket */
+    readable = 0/*false*/;
     for (;;) { /* optionally auto-resume if interrupted */
         int x_read = recv(sock->sock, buf, size, 0);
         int x_error;
 
 #ifdef NCBI_OS_MSWIN
         /* recv() resets IO event recording */
-        sock->readable = sock->closeing;
+        sock->readable = sock->closing;
 #endif /*NCBI_OS_MSWIN*/
 
         /* success/EOF? */
         if (x_read >= 0  ||
             (x_read < 0  &&  ((x_error = SOCK_ERRNO) == SOCK_ENOTCONN      ||
                               x_error                == SOCK_ETIMEDOUT     ||
+                              x_error                == SOCK_ENETRESET   ||
                               x_error                == SOCK_ECONNRESET    ||
-                              x_error                == SOCK_ECONNABORTED  ||
-                              x_error                == SOCK_ENETRESET))) {
+                              x_error                == SOCK_ECONNABORTED))) {
             /* statistics & logging */
             if (x_read < 0  ||
                 ((sock->log == eOn || (sock->log == eDefault && s_Log == eOn))
                  &&  (!sock->session  ||  flag > 0))) {
-                s_DoLog(x_read < 0  &&  sock->n_read  &&  sock->n_written
+                s_DoLog(x_read < 0  &&  (sock->n_read & sock->n_written)
                         ? eLOG_Error : eLOG_Trace, sock, eIO_Read,
                         x_read < 0 ? (void*) &x_error :
                         x_read > 0 ? buf              : 0,
@@ -1801,6 +2253,9 @@ static EIO_Status s_Recv(SOCK    sock,
                     break;
                     /*return eIO_Unknown;*/
                 }
+#ifdef NCBI_OS_MSWIN
+                sock->closing = 1/*true*/;
+#endif /*NCBI_OS_MSWIN*/
             }
             sock->r_status = eIO_Success;
             break;
@@ -1815,6 +2270,11 @@ static EIO_Status s_Recv(SOCK    sock,
 
             if (tv  &&  !(tv->tv_sec | tv->tv_usec))
                 return eIO_Timeout;
+            if (readable) {
+                CORE_TRACEF(("%s[SOCK::Recv] "
+                             " Spurious false indication of data ready",
+                             s_ID(sock, _id)));
+            }
             poll.sock   = sock;
             poll.event  = eIO_Read;
             poll.revent = eIO_Open;
@@ -1825,14 +2285,15 @@ static EIO_Status s_Recv(SOCK    sock,
             if (poll.revent == eIO_Close)
                 return eIO_Unknown;
             assert(poll.revent == eIO_Read);
+            readable = 1/*true*/;
             continue/*read again*/;
         }
 
         if (x_error != SOCK_EINTR) {
-            char _id[32];
             CORE_LOGF_ERRNO_EXX(7, eLOG_Trace,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("%s[SOCK::Recv]  Failed recv()",
+                                ("%s[SOCK::Recv] "
+                                 " Failed recv()",
                                  s_ID(sock, _id)));            
             /* don't want to handle all possible errors...
                let them be "unknown" */
@@ -1895,8 +2356,9 @@ static EIO_Status s_Read(SOCK    sock,
         if (*n_read)
             return eIO_Success;
         if (!sock->eof) {
-            CORE_TRACEF(("%s[SOCK::Read]  Socket has already"
-                         " been shut down for reading", s_ID(sock, xx_buf)));
+            CORE_TRACEF(("%s[SOCK::Read] "
+                         " Socket already shut down for reading",
+                         s_ID(sock, xx_buf)));
         }
         return eIO_Closed;
     }
@@ -1971,8 +2433,9 @@ static EIO_Status s_Read(SOCK    sock,
                 x_read = n_todo;
             if (error) {
                 CORE_LOGF_ERRNO_X(8, eLOG_Error, errno,
-                                  ("%s[SOCK::Read]  Cannot store data in"
-                                   " peek buffer", s_ID(sock, xx_buf)));
+                                  ("%s[SOCK::Read] "
+                                   " Cannot store data in peek buffer",
+                                   s_ID(sock, xx_buf)));
                 sock->eof      = 1/*failure*/;
                 sock->r_status = eIO_Closed;
                 status = eIO_Unknown;
@@ -2102,9 +2565,10 @@ static EIO_Status s_WipeRBuf(SOCK sock)
     size_t     size = BUF_Size(sock->r_buf);
 
     if (size  &&  BUF_Read(sock->r_buf, 0, size) != size) {
-        char _id[32];
+        char _id[MAXIDLEN];
         CORE_LOGF_X(9, eLOG_Error,
-                    ("%s[SOCK::WipeRBuf]  Cannot drop aux. data buf",
+                    ("%s[SOCK::WipeRBuf] "
+                     " Cannot drop aux. data buffer",
                      s_ID(sock, _id)));
         assert(0);
         status = eIO_Unknown;
@@ -2122,9 +2586,10 @@ static EIO_Status s_WipeWBuf(SOCK sock)
 
     assert(sock->type == eDatagram);
     if (size  &&  BUF_Read(sock->w_buf, 0, size) != size) {
-        char _id[32];
+        char _id[MAXIDLEN];
         CORE_LOGF_X(10, eLOG_Error,
-                    ("%s[SOCK::WipeWBuf]  Cannot drop aux. data buf",
+                    ("%s[SOCK::WipeWBuf] "
+                     " Cannot drop aux. data buffer",
                      s_ID(sock, _id)));
         assert(0);
         status = eIO_Unknown;
@@ -2160,9 +2625,9 @@ static EIO_Status s_Send(SOCK        sock,
                          int         flag)
 {
 #ifdef NCBI_OS_MSWIN
-    int no_buffer_wait = 0;
-    struct timeval timeout;
-    memset(&timeout, 0, sizeof(timeout));
+    int wait_buf_ms = 0;
+    struct timeval waited;
+    memset(&waited, 0, sizeof(waited));
 #endif /*NCBI_OS_MSWIN*/
 
     assert(sock->type == eSocket  &&  data  &&  size > 0  &&  !*n_written);
@@ -2171,50 +2636,44 @@ static EIO_Status s_Send(SOCK        sock,
         return eIO_Closed;
 
     for (;;) { /* optionally auto-resume if interrupted */
-        int x_error;
+        int x_error = 0;
         int x_written = send(sock->sock, (void*) data, size,
                              flag < 0 ? MSG_OOB : 0);
-        if (x_written > 0  ||
+        if (x_written >= 0  ||
             (x_written < 0  &&  ((x_error= SOCK_ERRNO) == SOCK_EPIPE       ||
                                  x_error               == SOCK_ENOTCONN    ||
                                  x_error               == SOCK_ETIMEDOUT   ||
-                                 x_error               == SOCK_ECONNRESET  ||
                                  x_error               == SOCK_ENETRESET   ||
+                                 x_error               == SOCK_ECONNRESET  ||
                                  x_error               == SOCK_ECONNABORTED))){
             /* statistics & logging */
-            if (x_written < 0  ||
+            if (x_written <= 0  ||
                 ((sock->log == eOn || (sock->log == eDefault && s_Log == eOn))
                  &&  (!sock->session  ||  flag > 0))) {
-                s_DoLog(x_written < 0  &&  sock->n_read  &&  sock->n_written
+                s_DoLog(x_written <= 0  &&  (sock->n_read & sock->n_written)
                         ? eLOG_Error : eLOG_Trace, sock, eIO_Write,
-                        x_written < 0 ? (void*) &x_error : data,
-                        (size_t)(x_written < 0 ? 0 : x_written),
+                        x_written <= 0 ? (void*) &x_error : data,
+                        (size_t)(x_written <= 0 ? 0 : x_written),
                         flag < 0 ? "" : 0);
             }
 
+            if (x_written > 0) {
+                sock->n_written += x_written;
+                *n_written       = x_written;
+                sock->w_status = eIO_Success;
+                break;
+            }
             if (x_written < 0) {
-                sock->w_status = eIO_Closed;
                 if (x_error != SOCK_EPIPE)
                     sock->r_status = eIO_Closed;
+                sock->w_status = eIO_Closed;
                 break;
-                /*return eIO_Unknown;*/
             }
-            sock->n_written += x_written;
-            *n_written       = x_written;
-            sock->w_status = eIO_Success;
-            break;
         }
 
-#ifdef NCBI_OS_MSWIN
-        /* special write()'s semantics of IO event recording reset */
-        sock->writable = 0/*false*/;
-#endif /*NCBI_OS_MSWIN*/
-
         if (flag < 0/*OOB*/  ||  !x_written)
             return eIO_Unknown;
 
-        x_error = SOCK_ERRNO;
-
         /* blocked -- retry if unblocked before the timeout expires
          * (use stall protection if specified) */
         if (x_error == SOCK_EWOULDBLOCK  ||  x_error == SOCK_EAGAIN
@@ -2224,30 +2683,57 @@ static EIO_Status s_Send(SOCK        sock,
             ) {
             SSOCK_Poll poll;
             EIO_Status status;
+            const struct timeval* timeout;
 
 #ifdef NCBI_OS_MSWIN
-            /* special kludge for Windows */
+            struct timeval        slice;
+            unsigned int          writable = sock->writable;
+
+            /* special send()'s semantics of IO event recording reset */
+            sock->writable = 0/*false*/;
             if (x_error == WSAENOBUFS) {
-                s_AddTimeout(&timeout, no_buffer_wait);
-                if (s_IsSmallerTimeout(sock->w_timeout, &timeout))
+                if (size < SOCK_BUF_CHUNK_SIZE) {
+                    s_AddTimeout(&waited, wait_buf_ms);
+                    if (s_IsSmallerTimeout(sock->w_timeout, &waited))
                     return eIO_Timeout;
-                if (no_buffer_wait)
-                    Sleep(no_buffer_wait);
-                if (no_buffer_wait == 0)
-                    no_buffer_wait = 10;
-                else if (no_buffer_wait < 160)
-                    no_buffer_wait <<= 1;
+                    if (wait_buf_ms == 0)
+                        wait_buf_ms = 10;
+                    else if (wait_buf_ms < 160)
+                        wait_buf_ms <<= 1;
+                    slice.tv_sec  = 0;
+                    slice.tv_usec = wait_buf_ms * 1000;
+                } else {
+                    size >>= 1;
+                    memset(&slice, 0, sizeof(slice));
+                }
+                timeout = &slice;
             } else {
-                no_buffer_wait = 0;
-                memset(&timeout, 0, sizeof(timeout));
+                if (wait_buf_ms) {
+                    wait_buf_ms = 0;
+                    memset(&waited, 0, sizeof(waited));
+                }
+                timeout = sock->w_timeout;
+            }
+#else
+            {
+                timeout = sock->w_timeout;
             }
 #endif /*NCBI_OS_MSWIN*/
+
             poll.sock   = sock;
             poll.event  = eIO_Write;
             poll.revent = eIO_Open;
             /* stall protection:  try pulling incoming data from the socket */
-            status = s_SelectStallsafe(1, &poll, sock->w_timeout, 0);
+            status = s_SelectStallsafe(1, &poll, timeout, 0);
             assert(poll.event == eIO_Write);
+#ifdef NCBI_OS_MSWIN
+            if (x_error == WSAENOBUFS) {
+                assert(timeout == &slice);
+                sock->writable = writable/*restore*/;
+                if (status == eIO_Timeout)
+                    continue/*try to write again*/;
+            }
+#endif /*NCBI_OS_MSWIN*/
             if (status != eIO_Success)
                 return status;
             if (poll.revent == eIO_Close)
@@ -2257,10 +2743,11 @@ static EIO_Status s_Send(SOCK        sock,
         }
 
         if (x_error != SOCK_EINTR) {
-            char _id[32];
+            char _id[MAXIDLEN];
             CORE_LOGF_ERRNO_EXX(11, eLOG_Trace,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("%s[SOCK::Send]  Failed send()",
+                                ("%s[SOCK::Send] "
+                                 " Failed send()",
                                  s_ID(sock, _id)));
             /* don't want to handle all possible errors...
                let them be "unknown" */
@@ -2367,14 +2854,12 @@ static EIO_Status s_WritePending(SOCK                  sock,
         status = s_IsConnected(sock, tv, &x_error, writeable);
         if (status != eIO_Success) {
             if (status != eIO_Timeout) {
-                char _id[32];
-                char buf[80];
+                char _id[MAXIDLEN];
                 CORE_LOGF_ERRNO_EXX(12, eLOG_Error,
                                     x_error, s_StrError(sock, x_error),
                                     ("%s[SOCK::WritePending] "
-                                     " Failed pending connect(%s): %s",
+                                     " Failed pending connect(): %s",
                                      s_ID(sock, _id),
-                                     x_ConnPoint(sock, buf, sizeof(buf)),
                                      IO_StatusStr(status)));
                 sock->w_status = status;
             }
@@ -2430,9 +2915,10 @@ static EIO_Status s_Write(SOCK        sock,
 
     if (sock->w_status == eIO_Closed) {
         if (size) {
-            CORE_DEBUG_ARG(char _id[32]);
-            CORE_TRACEF(("%s[SOCK::Write]  Socket has already"
-                         " been shut down for writing", s_ID(sock, _id)));
+            CORE_DEBUG_ARG(char _id[MAXIDLEN]);
+            CORE_TRACEF(("%s[SOCK::Write] "
+                         " Socket already shut down for writing",
+                         s_ID(sock, _id)));
         }
         *n_written = 0;
         return eIO_Closed;
@@ -2456,8 +2942,8 @@ static EIO_Status s_Shutdown(SOCK                  sock,
                              EIO_Event             dir,
                              const struct timeval* tv)
 {
-    char       _id[32];
     int        x_error;
+    char       _id[MAXIDLEN];
     EIO_Status status = eIO_Success;
     int        how = SOCK_SHUTDOWN_WR;
 
@@ -2467,20 +2953,16 @@ static EIO_Status s_Shutdown(SOCK                  sock,
     case eIO_Read:
         if (sock->eof) {
             /* hit EOF (and may be not yet shut down) -- so, flag it as been
-             * shut down, but do not call the actual system shutdown(),
-             * as it can cause smart OS'es like Linux to complain
+             * shut down, but do not perform the actual system call,
+             * as it can cause smart OS'es like Linux to complain.
              */
             sock->eof = 0/*false*/;
             sock->r_status = eIO_Closed;
         }
         if (sock->r_status == eIO_Closed)
             return eIO_Success;  /* has been shut down already */
-        how = SOCK_SHUTDOWN_RD;
         sock->r_status = eIO_Closed;
-#ifdef NCBI_OS_MSWIN
-        /* see comments at the end of eIO_Write case */
-        return eIO_Success;
-#endif /*NCBI_OS_MSWIN*/
+        how = SOCK_SHUTDOWN_RD;
         break;
 
     case eIO_ReadWrite:
@@ -2500,10 +2982,11 @@ static EIO_Status s_Shutdown(SOCK                  sock,
             if ((status = s_WritePending(sock, tv, 0, 0)) != eIO_Success) {
                 CORE_LOGF_X(13, !tv  ||  (tv->tv_sec | tv->tv_usec)
                             ? eLOG_Warning : eLOG_Trace,
-                            ("%s[SOCK::Shutdown]  Shutting down for"
-                             " %s with some output still pending (%s)",
+                            ("%s[SOCK::Shutdown] "
+                             " Shutting down for %s with"
+                             " output still pending (%s)",
                              s_ID(sock, _id),
-                             dir == eIO_Write ? "write" : "R/W",
+                             dir == eIO_Write ? "write" : "read/write",
                              IO_StatusStr(status)));
             }
 
@@ -2521,8 +3004,9 @@ static EIO_Status s_Shutdown(SOCK                  sock,
                     if (status != eIO_Success) {
                         CORE_LOGF_ERRNO_EXX(127, eLOG_Trace,
                                             x_error, s_StrError(sock, x_error),
-                                            ("%s[SOCK::Shutdown]  Failed"
-                                             " SSL bye", s_ID(sock, _id)));
+                                            ("%s[SOCK::Shutdown] "
+                                             " Failed SSL bye",
+                                             s_ID(sock, _id)));
                     }
                 }
             }
@@ -2532,55 +3016,65 @@ static EIO_Status s_Shutdown(SOCK                  sock,
         if (dir != eIO_Write) {
             sock->eof = 0/*false*/;
             sock->r_status = eIO_Closed;
-            break;
         }
-
-#ifdef NCBI_OS_MSWIN
-        /* on MS-Win, socket shutdown for write apparently messes up (?!) *
-         * with the later reading, esp. when reading a lot of data...    */
-        return status;
-#endif /*NCBI_OS_MSWIN*/
         break;
 
     default:
         CORE_LOGF_X(15, eLOG_Error,
-                    ("%s[SOCK::Shutdown]  Invalid direction %u",
+                    ("%s[SOCK::Shutdown] "
+                     " Invalid direction #%u",
                      s_ID(sock, _id), (unsigned int) dir));
         return eIO_InvalidArg;
     }
 
+#ifndef NCBI_OS_MSWIN
+    /* on MS-Win, socket shutdown for write apparently messes up (?!) *
+     * with the later reading, esp. when reading a lot of data...    */
+
+#  ifdef NCBI_OS_BSD
+    /* at least on FreeBSD: shutting down a socket for write (i.e. forcing to
+     * send a FIN) for a socket that has been already closed by another end
+     * (e.g. when it was done writing, so this end has done reading and is
+     * about to close) seems to cause ECONNRESET in the coming close()... */
+    if (dir == eIO_ReadWrite  &&  how != SOCK_SHUTDOWN_RDWR)
+        return status;
+#  endif /*NCBI_OS_BSD*/
+
     if (s_Initialized > 0  &&  SOCK_SHUTDOWN(sock->sock, how) != 0) {
         x_error = SOCK_ERRNO;
-#ifdef NCBI_OS_MSWIN
+#  ifdef NCBI_OS_MSWIN
         if (x_error == WSANOTINITIALISED)
             s_Initialized = -1/*deinited*/;
         else
-#endif /*NCBI_OS_MSWIN*/
+#  endif /*NCBI_OS_MSWIN*/
         if (
-#if   defined(NCBI_OS_LINUX)/*bug in the Linux kernel to report*/  || \
+#  if   defined(NCBI_OS_LINUX)/*bug in the Linux kernel to report*/  || \
       defined(NCBI_OS_IRIX)                                        || \
       defined(NCBI_OS_OSF1)
             x_error != SOCK_ENOTCONN
-#else
+#  else
             x_error != SOCK_ENOTCONN  ||  sock->pending
-#endif /*UNIX flavors*/
-            )
+#  endif /*UNIX flavors*/
+            ) {
             CORE_LOGF_ERRNO_EXX(16, eLOG_Warning,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("%s[SOCK::Shutdown]  Failed shutdown(%s)",
-                                 s_ID(sock, _id), dir == eIO_Read ? "READ" :
-                                 dir == eIO_Write ? "WRITE" : "READ/WRITE"));
+                                ("%s[SOCK::Shutdown] "
+                                 " Failed shutdown(%s)",
+                                 s_ID(sock, _id), dir == eIO_Read ? "R" :
+                                 dir == eIO_Write ? "W" : "RW"));
     }
+    }
+#endif /*NCBI_OS_MSWIN*/
 
     return status;
 }
 
 
-/* Close the socket (orderly or abrupt)
+/* Close the socket (either orderly or abruptly)
  */
 static EIO_Status s_Close(SOCK sock, int abort)
 {
-    char       _id[32];
+    char       _id[MAXIDLEN];
     int        x_error;
     EIO_Status status;
 
@@ -2592,7 +3086,11 @@ static EIO_Status s_Close(SOCK sock, int abort)
         /* set the close()'s linger period be equal to the close timeout */
 #if (defined(NCBI_OS_UNIX) && !defined(NCBI_OS_BEOS)) || defined(NCBI_OS_MSWIN)
         /* setsockopt() is not implemented for MAC (MIT socket emulation lib)*/
-        if (sock->w_status != eIO_Closed) {
+        if (sock->w_status != eIO_Closed
+#  ifdef NCBI_OS_UNIX
+            &&  !sock->path[0]
+#  endif /*NCBI_OS_UNIX*/
+            ) {
             const struct timeval* tv = sock->c_timeout;
             struct linger lgr;
 
@@ -2618,8 +3116,9 @@ static EIO_Status s_Close(SOCK sock, int abort)
                 x_error = SOCK_ERRNO;
                 CORE_LOGF_ERRNO_EXX(17, eLOG_Trace,
                                     x_error, SOCK_STRERROR(x_error),
-                                    ("%s[SOCK::%s]  Failed setsockopt"
-                                     "(SO_LINGER)", s_ID(sock, _id),
+                                    ("%s[SOCK::%s] "
+                                     " Failed setsockopt(SO_LINGER)",
+                                     s_ID(sock, _id),
                                      abort ? "Abort" : "Close"));
             }
 #  ifdef TCP_LINGER2
@@ -2631,8 +3130,9 @@ static EIO_Status s_Close(SOCK sock, int abort)
                     x_error = SOCK_ERRNO;
                     CORE_LOGF_ERRNO_EXX(18, eLOG_Trace,
                                         x_error, SOCK_STRERROR(x_error),
-                                        ("%s[SOCK::%s]  Failed setsockopt"
-                                         "(TCP_LINGER2)", s_ID(sock, _id),
+                                        ("%s[SOCK::%s] "
+                                         " Failed setsockopt(TCP_LINGER2)",
+                                         s_ID(sock, _id),
                                          abort ? "Abort" : "Close"));
                 }
             }
@@ -2640,7 +3140,11 @@ static EIO_Status s_Close(SOCK sock, int abort)
         }
 #endif /*(NCBI_OS_UNIX && !NCBI_OS_BEOS) || NCBI_OS_MSWIN*/
 
-        if (!abort) {
+        if (!abort
+#ifdef NCBI_OS_UNIX
+            &&  !sock->path[0]
+#endif /*NCBI_OS_UNIX*/
+            ) {
             /* orderly shutdown in both directions */
             s_Shutdown(sock, eIO_ReadWrite, sock->c_timeout);
         } else
@@ -2655,15 +3159,16 @@ static EIO_Status s_Close(SOCK sock, int abort)
             x_error = SOCK_ERRNO;
             CORE_LOGF_ERRNO_EXX(19, eLOG_Trace,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("%s[SOCK::Close]  Cannot set socket"
-                                 " back to blocking mode", s_ID(sock, _id)));
+                                ("%s[SOCK::Close] "
+                                 " Cannot set socket back to blocking mode",
+                                 s_ID(sock, _id)));
         }
     } else if (sock->w_status != eIO_Closed) {
         status = s_WritePending(sock, sock->c_timeout, 0, 0);
         if (status != eIO_Success) {
             CORE_LOGF_X(20, eLOG_Warning,
-                        ("%s[SOCK::Close]  Leaving with some"
-                         " output data still pending (%s)",
+                        ("%s[SOCK::Close] "
+                         " Leaving with some output data pending (%s)",
                          s_ID(sock, _id), IO_StatusStr(status)));
         }
     }
@@ -2707,16 +3212,26 @@ static EIO_Status s_Close(SOCK sock, int abort)
                 break;
             }
 #endif /*NCBI_OS_MSWIN*/
+            if (x_error == SOCK_ENOTCONN/*already closed by now*/
+                ||  (!(sock->n_read | sock->n_written)
+                     &&  (x_error == SOCK_ENETRESET   ||
+                          x_error == SOCK_ECONNRESET  ||
+                          x_error == SOCK_ECONNABORTED))) {
+                break;
+            }
             if (abort  ||  x_error != SOCK_EINTR) {
                 CORE_LOGF_ERRNO_EXX(21, abort > 1 ? eLOG_Error : eLOG_Warning,
                                     x_error, SOCK_STRERROR(x_error),
-                                    ("%s[SOCK::%s]  Failed close()",
+                                    ("%s[SOCK::%s] "
+                                     " Failed close()",
                                      s_ID(sock, _id),
                                      abort ? "Abort" : "Close"));
-                if (abort++ > 1  ||  x_error != SOCK_EINTR) {
+                if (abort > 1  ||  x_error != SOCK_EINTR) {
                     status = eIO_Unknown;
                     break;
                 }
+                if (abort)
+                    abort++;
             }
         }
     }
@@ -2746,13 +3261,12 @@ static EIO_Status s_Connect(SOCK            sock,
 {
     union {
         struct sockaddr    sa;
-        struct sockaddr_in sin;
+        struct sockaddr_in in;
 #ifdef NCBI_OS_UNIX
-        struct sockaddr_un sun;
+        struct sockaddr_un un;
 #endif /*NCBI_OS_UNIX*/
     } addr;
-    char           buf[160];
-    char           _id[32];
+    char           _id[MAXIDLEN];
     int            x_error;
     SOCK_socklen_t addrlen;
     TSOCK_Handle   x_sock;
@@ -2777,8 +3291,9 @@ static EIO_Status s_Connect(SOCK            sock,
         if (!session) {
             CORE_LOGF_ERRNO_EXX(131, eLOG_Error,
                                 x_error, s_StrError(sock, x_error),
-                                ("%s[SOCK::Connect]  Failed to initialize"
-                                 " secure session", s_ID(sock, _id)));
+                                ("%s[SOCK::Connect] "
+                                 " Failed to initialize secure session",
+                                 s_ID(sock, _id)));
             return eIO_NotSupported;
         }
         assert(session != SESSION_INVALID);
@@ -2789,17 +3304,20 @@ static EIO_Status s_Connect(SOCK            sock,
 #ifdef NCBI_OS_UNIX
     if (sock->path[0]) {
         size_t pathlen = strlen(sock->path);
-        if (sizeof(addr.sun.sun_path) <= pathlen++/*account for end '\0'*/) {
+        if (sizeof(addr.un.sun_path) <= pathlen++/*account for end '\0'*/) {
             CORE_LOGF_X(142, eLOG_Error,
-                        ("%s[SOCK::Connect]  Failed to store path"
-                         " \"%s\" (%lu bytes long, %lu bytes allowed)",
-                         s_ID(sock, _id), sock->path, (unsigned long) pathlen,
-                         (unsigned long) sizeof(addr.sun.sun_path)));
-            return eIO_Unknown;
+                        ("%s[SOCK::Connect] "
+                         " Path too long (%lu vs %lu bytes allowed)",
+                         s_ID(sock, _id), (unsigned long) pathlen,
+                         (unsigned long) sizeof(addr.un.sun_path)));
+            return eIO_InvalidArg;
         }
-        addrlen = (SOCK_socklen_t) sizeof(addr.sun);
-        addr.sun.sun_family = AF_UNIX;
-        memcpy(addr.sun.sun_path, sock->path, pathlen);
+        addrlen = (SOCK_socklen_t) sizeof(addr.un);
+#  ifdef HAVE_SIN_LEN
+        addr.un.sun_len    = addrlen;
+#  endif /*HASE_SIN_LEN*/
+        addr.un.sun_family = AF_UNIX;
+        memcpy(addr.un.sun_path, sock->path, pathlen);
     } else
 #endif /*NCBI_OS_UNIX*/
     {
@@ -2814,13 +3332,13 @@ static EIO_Status s_Connect(SOCK            sock,
         /* set the port to connect to (same port if "port" is zero) */
         if (port)
             sock->port = port;
-        addrlen = (SOCK_socklen_t) sizeof(addr.sin);
-        addr.sin.sin_family = AF_INET;
-        addr.sin.sin_addr.s_addr =       sock->host;
-        addr.sin.sin_port        = htons(sock->port);
+        addrlen = (SOCK_socklen_t) sizeof(addr.in);
 #ifdef HAVE_SIN_LEN
-        addr.sin.sin_len = addrlen;
+        addr.in.sin_len         = addrlen;
 #endif /*HAVE_SIN_LEN*/
+        addr.in.sin_family      = AF_INET;
+        addr.in.sin_addr.s_addr =       sock->host;
+        addr.in.sin_port        = htons(sock->port);
     }
 
     /* create the new socket */
@@ -2894,16 +3412,12 @@ static EIO_Status s_Connect(SOCK            sock,
     }
 #endif /*SO_OOBINLINE*/
 
-    /* statistics & logging */
-    if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
-        s_DoLog(eLOG_Trace, sock, eIO_Open, 0, 0, &addr.sa);
-
     /* establish connection to the peer */
-    sock->connected = 0;
+    sock->connected = 0/*false*/;
 #ifdef NCBI_OS_MSWIN
-    sock->readable = 0;
-    sock->closeing = 0;
-    sock->writable = 0;
+    sock->readable  = 0/*false*/;
+    sock->writable  = 0/*false*/;
+    sock->closing   = 0/*false*/;
 #endif /*NCBI_OS_MSWIN*/
     for (n = 0; ; n = 1) { /* optionally auto-resume if interrupted */
         if (connect(x_sock, &addr.sa, addrlen) == 0) {
@@ -2917,6 +3431,10 @@ static EIO_Status s_Connect(SOCK            sock,
         }
     }
 
+    /* statistics & logging */
+    if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
+        s_DoLog(eLOG_Trace, sock, eIO_Open, 0, 0, x_error ? 0 : "");
+
     if (x_error) {
         if ((n != 0  ||  x_error != SOCK_EINPROGRESS)  &&
             (n == 0  ||  x_error != SOCK_EALREADY)     &&
@@ -2925,9 +3443,15 @@ static EIO_Status s_Connect(SOCK            sock,
                 CORE_LOGF_ERRNO_EXX(25, eLOG_Error,
                                     x_error, SOCK_STRERROR(x_error),
                                     ("%s[SOCK::Connect] "
-                                     " Failed connect(%s)",
-                                     s_ID(sock, _id),
-                                     x_ConnPoint(sock, buf, sizeof(buf)/2)));
+                                     " Failed connect()",
+                                     s_ID(sock, _id)));
+                if (x_error == SOCK_ECONNREFUSED
+#ifdef NCBI_OS_UNIX
+                    ||  (sock->path[0]  &&  x_error == ENOENT)
+#endif /*NCBI_OS_UNIX*/
+                    ) {
+                    status = eIO_Closed;
+                } else
                 status = eIO_Unknown;
             } else
                 status = eIO_Interrupt;
@@ -2944,40 +3468,48 @@ static EIO_Status s_Connect(SOCK            sock,
 
         status = s_IsConnected(sock, x_tv, &x_error, !x_error);
         if (status != eIO_Success) {
+            char buf[64];
             const char* reason;
             if (status == eIO_Timeout) {
                 assert(x_tv/*it is also normalized*/);
-                sprintf(buf + sizeof(buf)/2, "%s[%u.%06u]",
+                sprintf(buf, "%s[%u.%06u]",
                         IO_StatusStr(status),
                         (unsigned int) x_tv->tv_sec,
                         (unsigned int) x_tv->tv_usec);
-                reason = buf + sizeof(buf)/2;
-                assert(strlen(reason) < sizeof(buf)/2);
+                reason = buf;
             } else
                 reason = IO_StatusStr(status);
             CORE_LOGF_ERRNO_EXX(26, eLOG_Error,
                                 x_error, s_StrError(sock, x_error),
                                 ("%s[SOCK::Connect] "
-                                 " Failed pending connect(%s): %s",
-                                 s_ID(sock, _id),
-                                 x_ConnPoint(sock, buf, sizeof(buf)/2),
-                                 reason));
+                                 " Failed pending connect(): %s",
+                                 s_ID(sock, _id), reason));
             s_Close(sock, -1/*abort*/);
             return status;
         }
     }
 
-#ifdef NCBI_OS_UNIX
     if ((!sock->crossexec  ||  sock->session)
-        &&  !s_SetCloexec(x_sock, 1/*true*/)){
-        x_error = SOCK_ERRNO;
+        &&  !s_SetCloexec(x_sock, 1/*true*/)) {
+        const char* errstr;
+#ifdef NCBI_OS_MSWIN
+        DWORD err = GetLastError();
+        errstr = s_WinStrerror(err);
+        x_error = err;
+#else
+        x_error = errno;
+        errstr = SOCK_STRERROR(x_error);
+#endif /*NCBI_OS_MSWIN*/
         CORE_LOGF_ERRNO_EXX(129, eLOG_Warning,
-                            x_error, SOCK_STRERROR(x_error),
+                            x_error, errstr ? errstr : "",
                             ("%s[SOCK::Connect] "
                              " Cannot set socket close-on-exec mode",
                              s_ID(sock, _id)));
+#ifdef NCBI_OS_MSWIN
+        if (errstr)
+            LocalFree((char*) errstr);
+#endif /*NCBI_OS_MSWIN*/
     }
-#endif /*NCBI_OS_UNIX*/
 
     /* success: do not change any timeouts */
     sock->w_len = BUF_Size(sock->w_buf);
@@ -2995,7 +3527,7 @@ static EIO_Status s_Create(const char*     hostpath,
 {
     size_t       x_n = port ? 0 : strlen(hostpath);
     unsigned int x_id = ++s_ID_Counter * 1000;
-    char         _id[32];
+    char         _id[MAXIDLEN];
     EIO_Status   status;
     SOCK         x_sock;
 
@@ -3013,9 +3545,8 @@ static EIO_Status s_Create(const char*     hostpath,
     x_sock->keep      = flags & fSOCK_KeepOnClose ? 1/*true*/  : 0/*false*/;
     x_sock->r_on_w    = flags & fSOCK_ReadOnWrite       ? eOn  : eDefault;
     x_sock->i_on_sig  = flags & fSOCK_InterruptOnSignal ? eOn  : eDefault;
-
-#ifdef NCBI_OS_UNIX
     x_sock->crossexec = flags & fSOCK_KeepOnExec ? 1/*true*/ : 0/*false*/;
+#ifdef NCBI_OS_UNIX
     if (!port)
         strcpy(x_sock->path, hostpath);
 #endif /*NCBI_OS_UNIX*/
@@ -3026,14 +3557,14 @@ static EIO_Status s_Create(const char*     hostpath,
         if (!BUF_SetChunkSize(&x_sock->w_buf, datalen) ||
             !BUF_Write(&x_sock->w_buf, data, datalen)) {
             CORE_LOGF_ERRNO_X(27, eLOG_Error, errno,
-                              ("%s[SOCK::Create]  Cannot store initial data",
+                              ("%s[SOCK::Create] "
+                               " Cannot store initial data",
                                s_ID(x_sock, _id)));
             SOCK_Close(x_sock);
             return eIO_Unknown;
         }
     }
 
-
     /* connect */
     status = s_Connect(x_sock, hostpath, port, timeout);
     if (status != eIO_Success)
@@ -3096,7 +3627,7 @@ extern EIO_Status TRIGGER_Create(TRIGGER* trigger, ESwitch log)
              * of the way to spare precious "selectable" fd numbers */
             CORE_LOGF_ERRNO_X(143, eLOG_Warning, errno,
                               ("TRIGGER#%u[?]: [TRIGGER::Create] "
-                               " Failed to dup(%d) to higher fd(%d))",
+                               " Failed to dup(%d) to higher fd(%d+))",
                                x_id, fd[1], FD_SETSIZE));
         } else {
             close(fd[1]);
@@ -3146,8 +3677,8 @@ extern EIO_Status TRIGGER_Create(TRIGGER* trigger, ESwitch log)
         if (!event) {
             DWORD err = GetLastError();
             char* strerr = s_WinStrerror(err);
-            CORE_LOGF_ERRNO_EXX(14, eLOG_Error, err,
-                                strerr ? strerr : "",
+            CORE_LOGF_ERRNO_EXX(14, eLOG_Error,
+                                err, strerr ? strerr : "",
                                 ("TRIGGER#%u: [TRIGGER::Create] "
                                  " Cannot create event object", x_id));
             if (strerr)
@@ -3166,7 +3697,8 @@ extern EIO_Status TRIGGER_Create(TRIGGER* trigger, ESwitch log)
 
         /* statistics & logging */
         if (log == eOn  ||  (log == eDefault  &&  s_Log == eOn)) {
-            CORE_TRACEF(("TRIGGER#%u: Ready", x_id));
+            CORE_LOGF_X(116, eLOG_Trace,
+                        ("TRIGGER#%u: Ready", x_id));
         }
 	}}
 
@@ -3227,7 +3759,7 @@ extern EIO_Status TRIGGER_Set(TRIGGER trigger)
 
 #  if   defined(NCBI_OS_UNIX)
 
-    if (!NCBI_SwapPointers((void**) &trigger->isset, (void*) 1)) {
+    if (!NCBI_SwapPointers((void**) &trigger->isset.ptr, (void*) 1/*true*/)) {
         if (write(trigger->out, "", 1) < 0  &&  errno != EAGAIN)
             return eIO_Unknown;
     }
@@ -3241,7 +3773,8 @@ extern EIO_Status TRIGGER_Set(TRIGGER trigger)
 #  else
 
     CORE_LOG_X(32, eLOG_Error,
-               "[TRIGGER::Set]  Not yet supported on this platform");
+               "[TRIGGER::Set] "
+               " Not yet supported on this platform");
     return eIO_NotSupported;
 
 #  endif /*NCBI_OS*/
@@ -3270,12 +3803,12 @@ extern EIO_Status TRIGGER_IsSet(TRIGGER trigger)
     ssize_t     x_read;
 
     while ((x_read = read(trigger->fd, x_buf, sizeof(x_buf))) > 0)
-        *((void**) &trigger->isset) = (void*) 1/*true*/;
+        trigger->isset.ptr = (void*) 1/*true*/;
 
     if (x_read == 0/*EOF?*/)
         return eIO_Unknown;
 
-    return *((void**) &trigger->isset) ? eIO_Success : eIO_Closed;
+    return trigger->isset.ptr ? eIO_Success : eIO_Closed;
 
 #  elif defined(NCBI_OS_MSWIN)
 
@@ -3293,7 +3826,8 @@ extern EIO_Status TRIGGER_IsSet(TRIGGER trigger)
 #  else
 
     CORE_LOG_X(33, eLOG_Error,
-               "[TRIGGER::IsSet]  Not yet supported on this platform");
+               "[TRIGGER::IsSet] "
+               " Not yet supported on this platform");
     return eIO_NotSupported;
 
 #  endif /*NCBI_OS*/
@@ -3312,7 +3846,7 @@ extern EIO_Status TRIGGER_Reset(TRIGGER trigger)
 
 #if   defined(NCBI_OS_UNIX)
 
-	*((void**) &trigger->isset) = 0/*false*/;
+	trigger->isset.ptr = (void*) 0/*false*/;
 
 #elif defined(NCBI_OS_MSWIN)
 
@@ -3342,16 +3876,19 @@ static EIO_Status s_CreateListening(const char*    path,
     SOCK_socklen_t addrlen;
     union {
         struct sockaddr    sa;
-        struct sockaddr_in sin;
+        struct sockaddr_in in;
 #ifdef NCBI_OS_UNIX
-        struct sockaddr_un sun;
+        struct sockaddr_un un;
 #endif /*NCBI_OS_UNIX*/
     } addr;
+    char        _id[MAXIDLEN];
 #ifdef NCBI_OS_MSWIN
 	WSAEVENT    event;
 #endif /*NCBI_OS_MSWIN*/
-    char        s[80];
-    const char* c;
+    const char* cp;
+#ifdef NCBI_OS_UNIX
+    mode_t      u;
+#endif /*NCBI_OS_UNIX*/
 
     *lsock = 0;
 
@@ -3362,33 +3899,48 @@ static EIO_Status s_CreateListening(const char*    path,
     assert(!path ^ !port);
 
     if (flags & fSOCK_Secure) {
-        /*FIXME:  Add secure support later*/
+        /*FIXME:  Add secure server support later*/
         return eIO_NotSupported;
     }
 
+    memset(&addr, 0, sizeof(addr));
     if (path) {
 #ifdef NCBI_OS_UNIX
+        size_t pathlen = strlen(path);
+        if (sizeof(addr.un.sun_path) <= pathlen++/*account for end '\0'*/) {
+            CORE_LOGF_X(144, eLOG_Error,
+                        ("LSOCK#%u[?]@%s: [LSOCK::Create] "
+                         " Path too long (%lu vs %lu bytes allowed)",
+                         x_id, path, (unsigned long) pathlen,
+                         (unsigned long) sizeof(addr.un.sun_path)));
+            return eIO_InvalidArg;
+        }
         addr.sa.sa_family = AF_UNIX;
 #else
         return eIO_NotSupported;
-#endif
+#endif /*NCBI_OS_UNIX*/
     } else
         addr.sa.sa_family = AF_INET;
 
     /* create new(listening) socket */
     if ((x_lsock = socket(addr.sa.sa_family, SOCK_STREAM, 0)) == SOCK_INVALID){
-        int x_error = SOCK_ERRNO;
+        x_error = SOCK_ERRNO;
+        if (port) {
+            sprintf(_id, ":%hu", port);
+            cp = _id;
+        } else
+            cp = path;
         CORE_LOGF_ERRNO_EXX(34, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("LSOCK#%u[?]: [LSOCK::Create] "
-                             " Cannot create socket", x_id));
+                            ("LSOCK#%u[?]@%s: [LSOCK::Create] "
+                             " Failed socket()", x_id, cp));
         return eIO_Unknown;
     }
 
     if (port) {
         /*
          * It was confirmed(?) that at least on Solaris 2.5 this precaution:
-         * 1) makes the address released immediately after the process
+         * 1) makes the address released immediately upon the process
          *    termination;
          * 2) still issues EADDRINUSE error on the attempt to bind() to the
          *    same address being in-use by a living process (if SOCK_STREAM).
@@ -3397,108 +3949,160 @@ static EIO_Status s_CreateListening(const char*    path,
             x_error = SOCK_ERRNO;
             CORE_LOGF_ERRNO_EXX(35, eLOG_Error,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("LSOCK#%u[%u]: [LSOCK::Create] "
+                                ("LSOCK#%u[%u]@:%hu: [LSOCK::Create] "
                                  " Failed setsockopt(REUSEADDR)",
-                                 x_id, (unsigned int) x_lsock));
+                                 x_id, (unsigned int) x_lsock, port));
             SOCK_CLOSE(x_lsock);
             return eIO_Unknown;
         }
     }
 
     /* bind */
-    memset(&addr, 0, sizeof(addr));
 #ifdef NCBI_OS_UNIX
     if (path) {
-        addrlen = (SOCK_socklen_t) sizeof(addr.sun);
-        addr.sun.sun_family = AF_UNIX;
-        strncpy0(addr.sun.sun_path, path, sizeof(addr.sun.sun_path) - 1);
-        c = path;
+        assert(addr.un.sun_family == AF_UNIX);
+        addrlen = (SOCK_socklen_t) sizeof(addr.un);
+#  ifdef HAVE_SIN_LEN
+        addr.un.sun_len = addrlen;
+#  endif /*HAVE_SIN_LEN*/
+        strcpy(addr.un.sun_path, path);
+        cp = path;
+        u = umask(0);
     } else
 #endif /*NCBI_OS_UNIX*/
     {
         unsigned int host =
             htonl(flags & fSOCK_BindLocal ? INADDR_LOOPBACK : INADDR_ANY);
-        addrlen = sizeof(addr.sin);
-        addr.sin.sin_family      = AF_INET;
-        addr.sin.sin_addr.s_addr =       host;
-        addr.sin.sin_port        = htons(port);
+        assert(addr.in.sin_family == AF_INET);
+        addrlen = sizeof(addr.in);
 #ifdef HAVE_SIN_LEN
-        addr.sin.sin_len         = addrlen;
+        addr.in.sin_len         = addrlen;
 #endif /*HAVE_SIN_LEN*/
-        SOCK_HostPortToString(host, port, s, sizeof(s));
-        c = s;
+        addr.in.sin_addr.s_addr =       host;
+        addr.in.sin_port        = htons(port);
+#ifdef NCBI_OS_UNIX
+        u = 0/*dummy*/;
+#endif /*NCBI_OS_UNIX*/
     }
-    if (bind(x_lsock, &addr.sa, addrlen) != 0) {
-        x_error = SOCK_ERRNO;
+    x_error = bind(x_lsock, &addr.sa, addrlen) != 0 ? SOCK_ERRNO : 0;
+#ifdef NCBI_OS_UNIX
+    if (path)
+        umask(u);
+#endif /*NCBI_OS_UNIX*/
+    if (x_error) {
+        if (port) {
+            SOCK_HostPortToString(addr.in.sin_addr.s_addr, port,
+                                  _id, sizeof(_id));
+            cp = _id;
+        } else
+            cp = path;
         CORE_LOGF_ERRNO_EXX(36, x_error == SOCK_EADDRINUSE
                             ? eLOG_Trace : eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("LSOCK#%u[%u]: [LSOCK::Create] "
-                             " Failed bind(%s)",
-                             x_id, (unsigned int) x_lsock, c));
+                            ("LSOCK#%u[%u]@%s: [LSOCK::Create] "
+                             " Failed bind()",
+                             x_id, (unsigned int) x_lsock, cp));
         SOCK_CLOSE(x_lsock);
         return x_error == SOCK_EADDRINUSE ? eIO_Closed : eIO_Unknown;
     }
+#ifdef NCBI_OS_IRIX
+    fchmod(path, S_IRWXU | S_IRWXG | S_IRWXO);
+#endif /*NCBI_OS_IRIX*/
 
 #ifdef NCBI_OS_MSWIN
 	if (!(event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
         DWORD err = GetLastError();
         char* strerr = s_WinStrerror(err);
+        if (port) {
+            sprintf(_id, ":%hu", port);
+            cp = _id;
+        } else
+            cp = path;
         CORE_LOGF_ERRNO_EXX(118, eLOG_Error,
                             err, strerr ? strerr : "",
-                            ("LSOCK#%u[%u]: [LSOCK::Create] "
+                            ("LSOCK#%u[%u]@%s: [LSOCK::Create] "
                              " Failed to create IO event",
-                             x_id, (unsigned int) x_lsock));
+                             x_id, (unsigned int) x_lsock, cp));
         if (strerr)
             LocalFree(strerr);
         SOCK_CLOSE(x_lsock);
         return eIO_Unknown;
     }
+    /* NB: WSAEventSelect() sets non-blocking automatically */
     if (WSAEventSelect(x_lsock, event, FD_CLOSE/*X*/ | FD_ACCEPT/*A*/) != 0) {
-        int x_error = SOCK_ERRNO;
+        x_error = SOCK_ERRNO;
+        if (port) {
+            sprintf(_id, ":%hu", port);
+            cp = _id;
+        } else
+            cp = path;
         CORE_LOGF_ERRNO_EXX(119, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("LSOCK#%u[%u]: [LSOCK::Create] "
+                            ("LSOCK#%u[%u]@%s: [LSOCK::Create] "
                              " Failed to bind IO event",
-                             x_id, (unsigned int) x_lsock));
+                             x_id, (unsigned int) x_lsock, cp));
         SOCK_CLOSE(x_lsock);
         CloseHandle(event);
         return eIO_Unknown;
     }
 #else
-    /* NB: WSAEventSelect() sets non-blocking automatically */
     /* set non-blocking mode */
     if (!s_SetNonblock(x_lsock, 1/*true*/)) {
         x_error = SOCK_ERRNO;
+        if (port) {
+            sprintf(_id, ":%hu", port);
+            cp = _id;
+        } else
+            cp = path;
         CORE_LOGF_ERRNO_EXX(38, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("LSOCK#%u[%u]: [LSOCK::Create] "
+                            ("LSOCK#%u[%u]@%s: [LSOCK::Create] "
                              " Cannot set socket to non-blocking mode",
-                             x_id, (unsigned int) x_lsock));
+                             x_id, (unsigned int) x_lsock, cp));
         SOCK_CLOSE(x_lsock);
         return eIO_Unknown;
     }
 #endif /*NCBI_OS_MSWIN*/
 
-#ifdef NCBI_OS_UNIX
     if (!(flags & fSOCK_KeepOnExec)  &&  !s_SetCloexec(x_lsock, 1/*true*/)) {
-        x_error = SOCK_ERRNO;
+        const char* errstr;
+#ifdef NCBI_OS_MSWIN
+        DWORD err = GetLastError();
+        errstr = s_WinStrerror(err);
+        x_error = err;
+#else
+        x_error = errno;
+        errstr = SOCK_STRERROR(x_error);
+#endif /*NCBI_OS_MSWIN*/
+        if (port) {
+            sprintf(_id, ":%hu", port);
+            cp = _id;
+        } else
+            cp = path;
         CORE_LOGF_ERRNO_EXX(110, eLOG_Warning,
-                            x_error, SOCK_STRERROR(x_error),
-                            ("LSOCK#%u[%u]: [LSOCK::Create] "
+                            x_error, errstr ? errstr : "",
+                            ("LSOCK#%u[%u]@%s: [LSOCK::Create] "
                              " Cannot set socket close-on-exec mode",
-                             x_id, (unsigned int) x_lsock));
+                             x_id, (unsigned int) x_lsock, cp));
+#ifdef NCBI_OS_MSWIN
+        if (errstr)
+            LocalFree((char*) errstr);
+#endif /*NCBI_OS_MSWIN*/
     }
-#endif /*NCBI_OS_UNIX*/
 
     /* listen */
     if (listen(x_lsock, backlog) != 0) {
         x_error = SOCK_ERRNO;
+        if (port) {
+            sprintf(_id, ":%hu", port);
+            cp = _id;
+        } else
+            cp = path;
         CORE_LOGF_ERRNO_EXX(37, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("LSOCK#%u[%u]: [LSOCK::Create] "
-                             " Failed listen(%hu) on %s",
-                             x_id, (unsigned int) x_lsock, backlog, c));
+                            ("LSOCK#%u[%u]@%s: [LSOCK::Create] "
+                             " Failed listen(%hu)",
+                             x_id, (unsigned int) x_lsock, cp, backlog));
         SOCK_CLOSE(x_lsock);
 #ifdef NCBI_OS_MSWIN
         CloseHandle(event);
@@ -3532,8 +4136,7 @@ static EIO_Status s_CreateListening(const char*    path,
     /* statistics & logging */
     if ((*lsock)->log == eOn  ||  ((*lsock)->log == eDefault && s_Log == eOn)){
         CORE_LOGF_X(115, eLOG_Trace,
-                    ("LSOCK#%u[%u]: Listening on %s",
-                     x_id, (unsigned int) x_lsock, c));
+                    ("%sListening", s_ID((SOCK)(*lsock), _id)));
     }
 
     return eIO_Success;
@@ -3585,24 +4188,28 @@ static EIO_Status s_Accept(LSOCK           lsock,
 {
     union {
         struct sockaddr    sa;
-        struct sockaddr_in sin;
+        struct sockaddr_in in;
 #ifdef NCBI_OS_UNIX
-        struct sockaddr_un sun;
+        struct sockaddr_un un;
 #endif /*NCBI_OS_UNIX*/
     } addr;
     unsigned int   x_id;
+    const char*    path;
+    unsigned int   host;
+    unsigned short port;
 #ifdef NCBI_OS_MSWIN
 	WSAEVENT	   event;
 #endif /*NCBI_OS_MSWIN*/
     TSOCK_Handle   x_sock;
-    char           _id[32];
     int            x_error;
     SOCK_socklen_t addrlen;
+    char           _id[MAXIDLEN];
 
-    if (lsock->sock == SOCK_INVALID) {
+    if (!lsock  ||  lsock->sock == SOCK_INVALID) {
         CORE_LOGF_X(39, eLOG_Error,
-                    ("LSOCK#%u[?]: [LSOCK::Accept]  Invalid socket",
-                     lsock->id));
+                    ("%s[LSOCK::Accept] "
+                     " Invalid socket",
+                     s_ID((SOCK) lsock, _id)));
         assert(0);
         return eIO_Unknown;
     }
@@ -3638,36 +4245,54 @@ static EIO_Status s_Accept(LSOCK           lsock,
     /* accept next connection */
     memset(&addr, 0, sizeof(addr));
 #ifdef NCBI_OS_UNIX
-    if (lsock->path[0])
-        addrlen = (SOCK_socklen_t) sizeof(addr.sun);
-    else
+    if (lsock->path[0]) {
+        addrlen = (SOCK_socklen_t) sizeof(addr.un);
+#  ifdef HAVE_SIN_LEN
+        addr.un.sun_len = addrlen;
+#  endif /*HAVE_SIN_LEN*/
+    } else
 #endif /*NCBI_OS_UNIX*/
     {
-        addrlen = (SOCK_socklen_t) sizeof(addr.sin);
+        addrlen = (SOCK_socklen_t) sizeof(addr.in);
 #ifdef HAVE_SIN_LEN
-        addr.sin.sin_len = addrlen;
+        addr.in.sin_len = addrlen;
 #endif /*HAVE_SIN_LEN*/
     }
     if ((x_sock = accept(lsock->sock, &addr.sa, &addrlen)) == SOCK_INVALID) {
         x_error = SOCK_ERRNO;
         CORE_LOGF_ERRNO_EXX(40, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("LSOCK#%u[%u]: [LSOCK::Accept] "
-                             " Failed accept()", lsock->id,
-                             (unsigned int) lsock->sock));
+                            ("%s[LSOCK::Accept] "
+                             " Failed accept()",
+                             s_ID((SOCK) lsock, _id)));
         return eIO_Unknown;
     }
     lsock->n_accept++;
 
+#ifndef NCBI_OS_UNIX
+    path = "";
+#else
+    path = lsock->path;
+    if (path[0]) {
+        host = 0;
+        port = 0;
+    } else
+#endif /*!NCBI_OS_UNIX*/
+    {
+        host =       addr.in.sin_addr.s_addr;
+        port = ntohs(addr.in.sin_port);
+    }
+
 #ifdef NCBI_OS_MSWIN
 	if (!(event = CreateEvent(NULL, TRUE, FALSE, NULL))) {
         DWORD err = GetLastError();
 		char* strerr = s_WinStrerror(err);
         CORE_LOGF_ERRNO_EXX(120, eLOG_Error,
                             err, strerr ? strerr : "",
-                            ("SOCK#%u[%u]: [LSOCK::Accept] "
+                            ("SOCK#%u[%u]@%s: [LSOCK::Accept] "
                              " Failed to create IO event",
-                             x_id, (unsigned int) x_sock));
+                             x_id, (unsigned int) x_sock,
+                             x_CP(host, port, path, _id, sizeof(_id))));
         if (strerr)
             LocalFree(strerr);
         SOCK_ABORT(x_sock);
@@ -3677,9 +4302,10 @@ static EIO_Status s_Accept(LSOCK           lsock,
         int x_error = SOCK_ERRNO;
         CORE_LOGF_ERRNO_EXX(121, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("SOCK#%u[%u]: [LSOCK::Accept] "
+                            ("SOCK#%u[%u]@%s: [LSOCK::Accept] "
                              " Failed to bind IO event",
-                             x_id, (unsigned int) x_sock));
+                             x_id, (unsigned int) x_sock,
+                             x_CP(host, port, path, _id, sizeof(_id))));
         CloseHandle(event);
         SOCK_ABORT(x_sock);
         return eIO_Unknown;
@@ -3691,9 +4317,10 @@ static EIO_Status s_Accept(LSOCK           lsock,
         x_error = SOCK_ERRNO;
         CORE_LOGF_ERRNO_EXX(41, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("SOCK#%u[%u]: [LSOCK::Accept] "
+                            ("SOCK#%u[%u]@%s: [LSOCK::Accept] "
                              " Cannot set socket to non-blocking mode",
-                             x_id, (unsigned int) x_sock));
+                             x_id, (unsigned int) x_sock,
+                             x_CP(host, port, path, _id, sizeof(_id))));
         SOCK_ABORT(x_sock);
         return eIO_Unknown;
     }
@@ -3716,13 +4343,13 @@ static EIO_Status s_Accept(LSOCK           lsock,
 
     /* success */
 #ifdef NCBI_OS_UNIX
-    if (lsock->path[0]) {
-        strcpy((*sock)->path, lsock->path);
+    if (path[0]) {
+        strcpy((*sock)->path, path);
     } else
 #endif /*NCBI_OS_UNIX*/
     {
-        (*sock)->host =       addr.sin.sin_addr.s_addr;
-        (*sock)->port = ntohs(addr.sin.sin_port);
+        (*sock)->host = host;
+        (*sock)->port = port;
     }
     (*sock)->myport    = lsock->port;
     (*sock)->sock      = x_sock;
@@ -3740,18 +4367,16 @@ static EIO_Status s_Accept(LSOCK           lsock,
     (*sock)->writable  = 1/*true*/;
 	(*sock)->event     = event;
 #endif /*NCBI_OS_MSWIN*/
-#ifdef NCBI_OS_UNIX
     (*sock)->crossexec = flags & fSOCK_KeepOnExec ? 1/*true*/ : 0/*false*/;
-#endif /*NCBI_OS_UNIX*/
     /* all timeouts zeroed - infinite */
     BUF_SetChunkSize(&(*sock)->r_buf, SOCK_BUF_CHUNK_SIZE);
     /* w_buf is unused for accepted sockets */
     if ((*sock)->log == eDefault)
         (*sock)->log = lsock->log;
 
-    if (s_ReuseAddress
+    if (s_ReuseAddress == eOn
 #ifdef NCBI_OS_UNIX
-        &&  !lsock->path[0]
+        &&  !path[0]
 #endif /*NCBI_OS_UNIX*/
         &&  !s_SetReuseAddress(x_sock, 1/*true*/)) {
         x_error = SOCK_ERRNO;
@@ -3765,7 +4390,7 @@ static EIO_Status s_Accept(LSOCK           lsock,
 #ifdef SO_OOBINLINE
     if (
 #  ifdef NCBI_OS_UNIX
-        !(*sock)->path[0]  &&
+        !path[0]  &&
 #  endif /*NCBI_OS_UNIX*/
         !s_SetOobInline(x_sock, 1/*true*/)) {
         x_error = SOCK_ERRNO;
@@ -3777,20 +4402,30 @@ static EIO_Status s_Accept(LSOCK           lsock,
     }
 #endif /*SO_OOBINLINE*/
 
-#ifdef NCBI_OS_UNIX
     if (!(*sock)->crossexec  &&  !s_SetCloexec(x_sock, 1/*true*/)) {
-        x_error = SOCK_ERRNO;
+        const char* errstr;
+#ifdef NCBI_OS_MSWIN
+        DWORD err = GetLastError();
+        errstr = s_WinStrerror(err);
+        x_error = err;
+#else
+        x_error = errno;
+        errstr = SOCK_STRERROR(x_error);
+#endif /*NCBI_OS_MSWIN*/
         CORE_LOGF_ERRNO_EXX(128, eLOG_Warning,
-                            x_error, SOCK_STRERROR(x_error),
+                            x_error, errstr ? errstr : "",
                             ("%s[LSOCK::Accept] "
                              " Cannot set socket close-on-exec mode",
                              s_ID(*sock, _id)));
+#ifdef NCBI_OS_MSWIN
+        if (errstr)
+            LocalFree((char*) errstr);
+#endif /*NCBI_OS_MSWIN*/
     }
-#endif /*NCBI_OS_UNIX*/
 
     /* statistics & logging */
     if ((*sock)->log == eOn  ||  ((*sock)->log == eDefault  &&  s_Log == eOn))
-        s_DoLog(eLOG_Trace, *sock, eIO_Open, 0, 0, &addr.sa);
+        s_DoLog(eLOG_Trace, *sock, eIO_Open, 0, 0, _id);
 
     return eIO_Success;
 }
@@ -3821,7 +4456,8 @@ extern EIO_Status LSOCK_Close(LSOCK lsock)
 
     if (lsock->sock == SOCK_INVALID) {
         CORE_LOGF_X(43, eLOG_Error,
-                    ("LSOCK#%u[?]: [LSOCK::Close]  Invalid socket",
+                    ("LSOCK#%u[?]: [LSOCK::Close] "
+                     " Invalid socket",
                      lsock->id));
         assert(0);
         return eIO_Unknown;
@@ -3853,9 +4489,8 @@ extern EIO_Status LSOCK_Close(LSOCK lsock)
             c = buf;
         }
         CORE_LOGF_X(114, eLOG_Trace,
-                    ("LSOCK#%u[%u]: Closing at %s "
-                     "(%u accept%s total)", lsock->id,
-                     (unsigned int) lsock->sock, c,
+                    ("LSOCK#%u[%u]: Closing at %s (%u accept%s total)",
+                     lsock->id, (unsigned int) lsock->sock, c,
                      lsock->n_accept, lsock->n_accept == 1 ? "" : "s"));
     }
 
@@ -3876,8 +4511,8 @@ extern EIO_Status LSOCK_Close(LSOCK lsock)
                 CORE_LOGF_ERRNO_EXX(45, eLOG_Error,
                                     x_error, SOCK_STRERROR(x_error),
                                     ("LSOCK#%u[%u]: [LSOCK::Close] "
-                                     " Failed close()", lsock->id,
-                                     (unsigned int) lsock->sock));
+                                     " Failed close()",
+                                     lsock->id, (unsigned int) lsock->sock));
                 status = eIO_Unknown;
                 break;
             }
@@ -3905,8 +4540,9 @@ extern EIO_Status LSOCK_GetOSHandle(LSOCK  lsock,
     if (!handle  ||  handle_size != sizeof(lsock->sock)) {
         CORE_LOGF_X(46, eLOG_Error,
                     ("LSOCK#%u[%u]: [LSOCK::GetOSHandle] "
-                     " Invalid handle %s%lu", lsock->id,
-                     (unsigned int) lsock->sock, handle? "size ": "",
+                     " Invalid handle%s %lu",
+                     lsock->id, (unsigned int) lsock->sock,
+                     handle ? " size"                     : "",
                      handle ? (unsigned long) handle_size : 0));
         assert(0);
         return eIO_InvalidArg;
@@ -3965,14 +4601,6 @@ extern EIO_Status SOCK_CreateUNIX(const char*     path,
 }
 
 
-extern EIO_Status SOCK_CreateOnTop(const void* handle,
-                                   size_t      handle_size,
-                                   SOCK*       sock)
-{
-    return SOCK_CreateOnTopEx(handle, handle_size, sock, 0,0,fSOCK_LogDefault);
-}
-
-
 extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
                                      size_t      handle_size,
                                      SOCK*       sock,
@@ -3988,13 +4616,13 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
 #endif /*NCBI_OS_UNIX*/
     } peer;
     TSOCK_Handle   fd;
-    char           _id[32];
     SOCK           x_sock;
     int            x_error;
     BUF            w_buf = 0;
-    unsigned int   x_id = ++s_ID_Counter * 1000;
     SOCK_socklen_t peerlen;
     size_t         socklen;
+    char           _id[MAXIDLEN];
+    unsigned int   x_id = ++s_ID_Counter * 1000;
 
     *sock = 0;
 
@@ -4003,8 +4631,9 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
     if (!handle  ||  handle_size != sizeof(fd)) {
         CORE_LOGF_X(47, eLOG_Error,
                     ("SOCK#%u[?]: [SOCK::CreateOnTop] "
-                     " Invalid handle %s%lu", x_id,
-                     handle ? "size " : "",
+                     " Invalid handle%s %lu",
+                     x_id,
+                     handle ? " size"                     : "",
                      handle ? (unsigned long) handle_size : 0));
         assert(0);
         return eIO_InvalidArg;
@@ -4020,7 +4649,7 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
     memset(&peer, 0, sizeof(peer));
 #ifdef HAVE_SIN_LEN
     peer.sa.sa_len = peerlen;
-#endif
+#endif /*HAVE_SIN_LEN*/
     if (getpeername(fd, &peer.sa, &peerlen) < 0)
         return eIO_Closed;
 #ifdef NCBI_OS_UNIX
@@ -4049,14 +4678,15 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
             memset(&peer, 0, sizeof(peer));
 #  ifdef HAVE_SIN_LEN
             peer.sa.sa_len = peerlen;
-#  endif
+#  endif /*HAVE_SIN_LEN*/
             if (getsockname(fd, &peer.sa, &peerlen) < 0)
                 return eIO_Closed;
             assert(peer.sa.sa_family == AF_UNIX);
             if (!peer.un.sun_path[0]) {
                 CORE_LOGF_X(48, eLOG_Error,
                             ("SOCK#%u[%u]: [SOCK::CreateOnTop] "
-                             " Unbound UNIX socket", x_id, (unsigned int) fd));
+                             " Unbound UNIX socket",
+                             x_id, (unsigned int) fd));
                 assert(0);
                 return eIO_InvalidArg;
             }
@@ -4070,8 +4700,9 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
     if (datalen  &&  (!BUF_SetChunkSize(&w_buf, datalen)  ||
                       !BUF_Write(&w_buf, data, datalen))) {
         CORE_LOGF_ERRNO_X(49, eLOG_Error, errno,
-                          ("SOCK#%u[%u]: [SOCK::CreateOnTop]  Cannot store"
-                           " initial data", x_id, (unsigned int) fd));
+                          ("SOCK#%u[%u]: [SOCK::CreateOnTop] "
+                           " Cannot store initial data",
+                           x_id, (unsigned int) fd));
         BUF_Destroy(w_buf);
         return eIO_Unknown;
     }
@@ -4102,9 +4733,7 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
     x_sock->r_status  = eIO_Success;
     x_sock->w_status  = eIO_Success;
     x_sock->pending   = 1/*have to check at the nearest I/O*/;
-#ifdef NCBI_OS_UNIX
     x_sock->crossexec = flags * fSOCK_KeepOnExec ? 1/*true*/ : 0/*false*/;
-#endif /*NCBI_OS_UNIX*/
     /* all timeouts zeroed - infinite */
     BUF_SetChunkSize(&x_sock->r_buf, SOCK_BUF_CHUNK_SIZE);
     x_sock->w_buf     = w_buf;
@@ -4121,8 +4750,9 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
         if (!session) {
             CORE_LOGF_ERRNO_EXX(132, eLOG_Error,
                                 x_error, s_StrError(x_sock, x_error),
-                                ("%s[SOCK::CreateOnTop]  Failed to initialize"
-                                 " secure session", s_ID(x_sock, _id)));
+                                ("%s[SOCK::CreateOnTop] "
+                                 " Failed to initialize secure session",
+                                 s_ID(x_sock, _id)));
             x_sock->sock = SOCK_INVALID;
             SOCK_Close(x_sock);
             return eIO_NotSupported;
@@ -4136,8 +4766,9 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
         x_error = SOCK_ERRNO;
         CORE_LOGF_ERRNO_EXX(50, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("%s[SOCK::CreateOnTop]  Cannot set socket"
-                             " to non-blocking mode", s_ID(x_sock, _id)));
+                            ("%s[SOCK::CreateOnTop] "
+                             " Cannot set socket to non-blocking mode",
+                             s_ID(x_sock, _id)));
         x_sock->sock = SOCK_INVALID;
         SOCK_Close(x_sock);
         return eIO_Unknown;
@@ -4152,24 +4783,36 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
         x_error = SOCK_ERRNO;
         CORE_LOGF_ERRNO_EXX(138, eLOG_Warning,
                             x_error, SOCK_STRERROR(x_error),
-                            ("%s[SOCK::CreateOnTop]  Failed"
-                             " setsockopt(OOBINLINE)", s_ID(x_sock, _id)));
+                            ("%s[SOCK::CreateOnTop] "
+                             " Failed setsockopt(OOBINLINE)",
+                             s_ID(x_sock, _id)));
     }
 #endif /*SO_OOBINLINE*/
 
-#ifdef NCBI_OS_UNIX
     if (!s_SetCloexec(fd, !x_sock->crossexec  ||  x_sock->session)) {
-        x_error = SOCK_ERRNO;
+        const char* errstr;
+#ifdef NCBI_OS_MSWIN
+        DWORD err = GetLastError();
+        errstr = s_WinStrerror(err);
+        x_error = err;
+#else
+        x_error = errno;
+        errstr = SOCK_STRERROR(x_error);
+#endif /*NCBI_OS_MSWIN*/
         CORE_LOGF_ERRNO_EXX(124, eLOG_Warning,
-                            x_error, SOCK_STRERROR(x_error),
-                            ("%s[SOCK::CreateOnTop]  Cannot modify socket"
-                             " close-on-exec mode", s_ID(x_sock, _id)));
+                            x_error, errstr ? errstr : "",
+                            ("%s[SOCK::CreateOnTop] "
+                             " Cannot modify socket close-on-exec mode",
+                             s_ID(x_sock, _id)));
+#ifdef NCBI_OS_MSWIN
+        if (errstr)
+            LocalFree((char*) errstr);
+#endif /*NCBI_OS_MSWIN*/
     }
-#endif /*NCBI_OS_UNIX*/
  
     /* statistics & logging */
     if (x_sock->log == eOn  ||  (x_sock->log == eDefault  &&  s_Log == eOn))
-        s_DoLog(eLOG_Trace, x_sock, eIO_Open, &peer, 0, &peer.sa);
+        s_DoLog(eLOG_Trace, x_sock, eIO_Open, 0, 0, 0);
 
     /* success */
     *sock = x_sock;
@@ -4177,33 +4820,11 @@ extern EIO_Status SOCK_CreateOnTopEx(const void* handle,
 }
 
 
-static EIO_Status s_Reconnect(SOCK            sock,
-                              const char*     host,
-                              unsigned short  port,
-                              const STimeout* timeout)
+extern EIO_Status SOCK_CreateOnTop(const void* handle,
+                                   size_t      handle_size,
+                                   SOCK*       sock)
 {
-    /* special treatment for server-side socket */
-    if (sock->side == eSOCK_Server) {
-        char _id[32];
-        if (!host  ||  !*host  ||  !port) {
-            CORE_LOGF_X(51, eLOG_Error,
-                        ("%s[SOCK::Reconnect]  Attempt to reconnect"
-                         " server-side socket as the client one to"
-                         " its peer address", s_ID(sock, _id)));
-            return eIO_InvalidArg;
-        }
-    }
-
-    /* close the socket if necessary */
-    if (sock->sock != SOCK_INVALID)
-        s_Close(sock, 0/*orderly*/);
-
-    /* connect */
-    sock->id++;
-    sock->side      = eSOCK_Client;
-    sock->n_read    = 0;
-    sock->n_written = 0;
-    return s_Connect(sock, host, port, timeout);
+    return SOCK_CreateOnTopEx(handle, handle_size, sock, 0,0,fSOCK_LogDefault);
 }
 
 
@@ -4212,11 +4833,13 @@ extern EIO_Status SOCK_Reconnect(SOCK            sock,
                                  unsigned short  port,
                                  const STimeout* timeout)
 {
-    char _id[32];
+    char _id[MAXIDLEN];
 
     if (sock->type == eDatagram) {
         CORE_LOGF_X(52, eLOG_Error,
-                    ("%s[SOCK::Reconnect]  Datagram socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Reconnect] "
+                     " Datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
@@ -4227,29 +4850,56 @@ extern EIO_Status SOCK_Reconnect(SOCK            sock,
     if (sock->path[0]  &&  (host  ||  port)) {
         CORE_LOGF_X(53, eLOG_Error,
                     ("%s[SOCK::Reconnect] "
-                     " Cannot reconnect UNIX socket \"%s\" as INET",
-                     s_ID(sock, _id), sock->path));
+                     " Unable to reconnect UNIX socket as INET at \"%s:%hu\"",
+                     s_ID(sock, _id), host, port));
         assert(0);
         return eIO_InvalidArg;
     }
 #endif /*NCBI_OS_UNIX*/
-    return s_Reconnect(sock, host, port, timeout);
+
+    /* special treatment for server-side socket */
+    if (sock->side == eSOCK_Server) {
+        if (!host  ||  !port) {
+            CORE_LOGF_X(51, eLOG_Error,
+                        ("%s[SOCK::Reconnect] "
+                         " Attempt to reconnect server-side socket as"
+                         " client one to its peer address",
+                         s_ID(sock, _id)));
+            return eIO_InvalidArg;
+        }
+    }
+
+    /* close the socket if necessary */
+    if (sock->sock != SOCK_INVALID)
+        s_Close(sock, 0/*orderly*/);
+
+    /* connect */
+    sock->id++;
+    sock->myport    = 0;
+    sock->side      = eSOCK_Client;
+    sock->n_read    = 0;
+    sock->n_written = 0;
+    return s_Connect(sock, host, port, timeout);
 }
 
 
 extern EIO_Status SOCK_Shutdown(SOCK      sock,
                                 EIO_Event dir)
 {
-    char _id[32];
+    char _id[MAXIDLEN];
 
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(54, eLOG_Error,
-                    ("%s[SOCK::Shutdown]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Shutdown] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
     if (sock->type == eDatagram) {
         CORE_LOGF_X(55, eLOG_Error,
-                    ("%s[SOCK::Shutdown]  Datagram socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Shutdown] "
+                     " Datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
@@ -4288,11 +4938,13 @@ extern EIO_Status SOCK_Wait(SOCK            sock,
                             EIO_Event       event,
                             const STimeout* timeout)
 {
-    char _id[32];
+    char _id[MAXIDLEN];
 
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(56, eLOG_Error,
-                    ("%s[SOCK::Wait]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Wait] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
 
@@ -4319,7 +4971,8 @@ extern EIO_Status SOCK_Wait(SOCK            sock,
             return eIO_Closed;
         if (sock->r_status == eIO_Closed) {
             CORE_LOGF_X(57, eLOG_Warning,
-                        ("%s[SOCK::Wait(R)]  Socket has already been %s",
+                        ("%s[SOCK::Wait(R)] "
+                         " Socket already %s",
                          s_ID(sock, _id), sock->eof ? "closed" : "shut down"));
             return eIO_Closed;
         }
@@ -4332,8 +4985,9 @@ extern EIO_Status SOCK_Wait(SOCK            sock,
             return eIO_Success;
         if (sock->w_status == eIO_Closed) {
             CORE_LOGF_X(58, eLOG_Warning,
-                        ("%s[SOCK::Wait(W)]  Socket has already "
-                         "been shut down", s_ID(sock, _id)));
+                        ("%s[SOCK::Wait(W)] "
+                         " Socket already shut down",
+                         s_ID(sock, _id)));
             return eIO_Closed;
         }
         break;
@@ -4345,16 +4999,18 @@ extern EIO_Status SOCK_Wait(SOCK            sock,
             (sock->w_status == eIO_Closed)) {
             if (sock->r_status == eIO_Closed) {
                 CORE_LOGF_X(59, eLOG_Warning,
-                            ("%s[SOCK::Wait(RW)]  Socket has "
-                             "already been shut down", s_ID(sock, _id)));
+                            ("%s[SOCK::Wait(RW)] "
+                             " Socket already shut down",
+                             s_ID(sock, _id)));
             }
             return eIO_Closed;
         }
         if (sock->r_status == eIO_Closed  ||  sock->eof) {
             if (sock->r_status == eIO_Closed) {
                 CORE_LOGF_X(60, eLOG_Note,
-                            ("%s[SOCK::Wait(RW)]  Socket has already "
-                             "been %s", s_ID(sock, _id), sock->eof
+                            ("%s[SOCK::Wait(RW)] "
+                             " Socket already %s",
+                             s_ID(sock, _id), sock->eof
                              ? "closed" : "shut down for reading"));
             }
             event = eIO_Write;
@@ -4362,8 +5018,9 @@ extern EIO_Status SOCK_Wait(SOCK            sock,
         }
         if (sock->w_status == eIO_Closed) {
             CORE_LOGF_X(61, eLOG_Note,
-                        ("%s[SOCK::Wait(RW)]  Socket has already been "
-                         "shut down for writing", s_ID(sock, _id)));
+                        ("%s[SOCK::Wait(RW)] "
+                         " Socket already shut down for writing",
+                         s_ID(sock, _id)));
             event = eIO_Read;
             break;
         }
@@ -4371,7 +5028,8 @@ extern EIO_Status SOCK_Wait(SOCK            sock,
 
     default:
         CORE_LOGF_X(62, eLOG_Error,
-                    ("%s[SOCK::Wait]  Invalid event %u",
+                    ("%s[SOCK::Wait] "
+                     " Invalid event #%u",
                      s_ID(sock, _id), (unsigned int) event));
         return eIO_InvalidArg;
     }
@@ -4414,10 +5072,11 @@ extern EIO_Status SOCK_Poll(size_t          n,
 
     for (i = 0;  i < n;  i++) {
         SOCK sock = polls[i].sock;
-        if (!(sock = polls[i].sock))
-            continue;
-        polls[i].revent = eIO_Open;
-        if (sock->type != eSocket  ||  sock->sock == SOCK_INVALID)
+        polls[i].revent =
+            sock  &&  sock->type == eTrigger  &&  ((TRIGGER) sock)->isset.ptr
+            ? polls[i].event
+            : eIO_Open;
+        if (!sock  ||  sock->type != eSocket  ||  sock->sock == SOCK_INVALID)
             continue;
         if (polls[i].event & eIO_Read) {
             if (BUF_Size(sock->r_buf) != 0)
@@ -4488,7 +5147,7 @@ extern EIO_Status SOCK_SetTimeout(SOCK            sock,
                                   EIO_Event       event,
                                   const STimeout* timeout)
 {
-    char _id[32];
+    char _id[MAXIDLEN];
 
     switch (event) {
     case eIO_Read:
@@ -4506,7 +5165,8 @@ extern EIO_Status SOCK_SetTimeout(SOCK            sock,
         break;
     default:
         CORE_LOGF_X(63, eLOG_Error,
-                    ("%s[SOCK::SetTimeout]  Invalid event %u",
+                    ("%s[SOCK::SetTimeout] "
+                     " Invalid event #%u",
                      s_ID(sock, _id), (unsigned int) event));
         assert(0);
         return eIO_InvalidArg;
@@ -4519,7 +5179,7 @@ extern const STimeout* SOCK_GetTimeout(SOCK      sock,
                                        EIO_Event event)
 {
     const STimeout *tr, *tw;
-    char _id[32];
+    char _id[MAXIDLEN];
 
     switch (event) {
     case eIO_Read:
@@ -4544,7 +5204,8 @@ extern const STimeout* SOCK_GetTimeout(SOCK      sock,
         return s_tv2to(sock->c_timeout, &sock->c_to);
     default:
         CORE_LOGF_X(64, eLOG_Error,
-                    ("%s[SOCK::GetTimeout]  Invalid event %u",
+                    ("%s[SOCK::GetTimeout] "
+                     " Invalid event #%u",
                      s_ID(sock, _id), (unsigned int) event));
         assert(0);
     }
@@ -4560,7 +5221,7 @@ extern EIO_Status SOCK_Read(SOCK           sock,
 {
     EIO_Status status;
     size_t     x_read;
-    char       _id[32];
+    char       _id[MAXIDLEN];
 
     if (sock->sock != SOCK_INVALID) {
         switch (how) {
@@ -4585,7 +5246,8 @@ extern EIO_Status SOCK_Read(SOCK           sock,
 
         default:
             CORE_LOGF_X(65, eLOG_Error,
-                        ("%s[SOCK::Read]  Invalid read method %u",
+                        ("%s[SOCK::Read] "
+                         " Invalid read method #%u",
                          s_ID(sock, _id), (unsigned int) how));
             assert(0);
             x_read = 0;
@@ -4594,7 +5256,9 @@ extern EIO_Status SOCK_Read(SOCK           sock,
         }
     } else {
         CORE_LOGF_X(66, eLOG_Error,
-                    ("%s[SOCK::Read]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Read] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         x_read = 0;
         status = eIO_Closed;
     }
@@ -4692,9 +5356,11 @@ extern EIO_Status SOCK_ReadLine(SOCK    sock,
                                 size_t* n_read)
 {
     if (sock->sock == SOCK_INVALID) {
-        char _id[32];
+        char _id[MAXIDLEN];
         CORE_LOGF_X(125, eLOG_Error,
-                    ("%s[SOCK::ReadLine]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[SOCK::ReadLine] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
 
@@ -4707,9 +5373,11 @@ extern EIO_Status SOCK_PushBack(SOCK        sock,
                                 size_t      size)
 {
     if (sock->sock == SOCK_INVALID) {
-        char _id[32];
+        char _id[MAXIDLEN];
         CORE_LOGF_X(67, eLOG_Error,
-                    ("%s[SOCK::PushBack]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[SOCK::PushBack] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
 
@@ -4724,8 +5392,8 @@ extern EIO_Status SOCK_Write(SOCK            sock,
                              EIO_WriteMethod how)
 {
     EIO_Status status;
-    char       _id[32];
     size_t     x_written;
+    char       _id[MAXIDLEN];
     
     if (sock->sock != SOCK_INVALID) {
         switch (how) {
@@ -4759,7 +5427,8 @@ extern EIO_Status SOCK_Write(SOCK            sock,
 
         default:
             CORE_LOGF_X(69, eLOG_Error,
-                        ("%s[SOCK::Write]  Invalid write method %u",
+                        ("%s[SOCK::Write] "
+                         " Invalid write method #%u",
                          s_ID(sock, _id), (unsigned int) how));
             assert(0);
             x_written = 0;
@@ -4768,7 +5437,9 @@ extern EIO_Status SOCK_Write(SOCK            sock,
         }
     } else {
         CORE_LOGF_X(70, eLOG_Error,
-                    ("%s[SOCK::Write]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Write] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         x_written = 0;
         status = eIO_Closed;
     }
@@ -4781,16 +5452,20 @@ extern EIO_Status SOCK_Write(SOCK            sock,
 
 extern EIO_Status SOCK_Abort(SOCK sock)
 {
-    char _id[32];
+    char _id[MAXIDLEN];
 
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(71, eLOG_Warning,
-                    ("%s[SOCK::Abort]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Abort] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
     if (sock->type == eDatagram) {
         CORE_LOGF_X(72, eLOG_Error,
-                    ("%s[SOCK::Abort]  Datagram socket", s_ID(sock, _id)));
+                    ("%s[SOCK::Abort] "
+                     " Datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
@@ -4823,9 +5498,12 @@ extern EIO_Status SOCK_Status(SOCK      sock,
 }
 
 
-extern unsigned short SOCK_GetLocalPort(SOCK          sock,
+extern unsigned short SOCK_GetLocalPortEx(SOCK          sock,
+                                          int/*bool*/   trueport,
                                         ENH_ByteOrder byte_order)
 {
+    unsigned short port;
+
     if (sock->sock == SOCK_INVALID)
         return 0;
 
@@ -4834,9 +5512,20 @@ extern unsigned short SOCK_GetLocalPort(SOCK          sock,
         return 0/*UNIX socket*/;
 #endif /*NCBI_OS_UNIX*/
 
-    if (!sock->myport)
-        sock->myport = x_GetLocalPort(sock->sock);
-    return byte_order != eNH_HostByteOrder? htons(sock->myport) : sock->myport;
+    if (trueport  ||  !sock->myport) {
+        port = x_GetLocalPort(sock->sock);
+        if (!trueport)
+            sock->myport = port;
+    } else
+        port = sock->myport;
+    return byte_order != eNH_HostByteOrder ? htons(port) : port;
+}
+
+
+extern unsigned short SOCK_GetLocalPort(SOCK          sock,
+                                        ENH_ByteOrder byte_order)
+{
+    return SOCK_GetLocalPortEx(sock, 0/*false*/, byte_order);
 }
 
 
@@ -4869,7 +5558,7 @@ extern char* SOCK_GetPeerAddressStringEx(SOCK                sock,
                                          size_t              buflen,
                                          ESOCK_AddressFormat format)
 {
-    char port[8];
+    char   port[10];
     size_t len;
 
     if (!buf  ||  !buflen)
@@ -4912,10 +5601,12 @@ extern EIO_Status SOCK_GetOSHandle(SOCK   sock,
                                    size_t handle_size)
 {
     if (!handle  ||  handle_size != sizeof(sock->sock)) {
-        char _id[32];
+        char _id[MAXIDLEN];
         CORE_LOGF_X(73, eLOG_Error,
-                    ("%s[SOCK::GetOSHandle]  Invalid handle %s%lu",
-                     s_ID(sock, _id), handle ? "size " : "",
+                    ("%s[SOCK::GetOSHandle] "
+                     " Invalid handle%s %lu",
+                     s_ID(sock, _id),
+                     handle ? " size"                     : "",
                      handle ? (unsigned long) handle_size : 0));
         assert(0);
         return eIO_InvalidArg;
@@ -4930,8 +5621,7 @@ extern EIO_Status SOCK_GetOSHandle(SOCK   sock,
 extern ESwitch SOCK_SetReadOnWriteAPI(ESwitch on_off)
 {
     ESwitch old = s_ReadOnWrite;
-    if (on_off == eDefault)
-        on_off = eOff;
+    if (on_off != eDefault)
     s_ReadOnWrite = on_off;
     return old;
 }
@@ -4951,8 +5641,7 @@ extern ESwitch SOCK_SetReadOnWrite(SOCK sock, ESwitch on_off)
 extern ESwitch SOCK_SetInterruptOnSignalAPI(ESwitch on_off)
 {
     ESwitch old = s_InterruptOnSignal;
-    if (on_off == eDefault)
-        on_off = eOff;
+    if (on_off != eDefault)
     s_InterruptOnSignal = on_off;
     return old;
 }
@@ -4968,9 +5657,10 @@ extern ESwitch SOCK_SetInterruptOnSignal(SOCK sock, ESwitch on_off)
 
 extern ESwitch SOCK_SetReuseAddressAPI(ESwitch on_off)
 {
-    int old = s_ReuseAddress;
-    s_ReuseAddress = on_off == eOn ? 1 : 0;
-    return old ? eOn : eOff;
+    ESwitch old = s_ReuseAddress;
+    if (on_off != eDefault)
+        s_ReuseAddress = on_off;
+    return old;
 }
 
 
@@ -4978,7 +5668,7 @@ extern void SOCK_SetReuseAddress(SOCK sock, int/*bool*/ on_off)
 {
     if (sock->sock != SOCK_INVALID && !s_SetReuseAddress(sock->sock, on_off)) {
         int x_error = SOCK_ERRNO;
-        char _id[32];
+        char _id[MAXIDLEN];
         CORE_LOGF_ERRNO_EXX(74, eLOG_Warning,
                             x_error, SOCK_STRERROR(x_error),
                             ("%s[SOCK::SetReuseAddress] "
@@ -4997,7 +5687,7 @@ extern void SOCK_DisableOSSendDelay(SOCK sock, int/*bool*/ on_off)
         if (setsockopt(sock->sock, IPPROTO_TCP, TCP_NODELAY,
                        (void*)&n, sizeof(n)) != 0) {
             int x_error = SOCK_ERRNO;
-            char _id[32];
+            char _id[MAXIDLEN];
             CORE_LOGF_ERRNO_EXX(75, eLOG_Warning,
                                 x_error, SOCK_STRERROR(x_error),
                                 ("%s[SOCK::DisableOSSendDelay] "
@@ -5036,7 +5726,8 @@ extern EIO_Status DSOCK_CreateEx(SOCK* sock, TSOCK_Flags flags)
         CORE_LOGF_ERRNO_EXX(76, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
                             ("DSOCK#%u[?]: [DSOCK::Create] "
-                             " Cannot create socket", x_id));
+                             " Cannot create socket",
+                             x_id));
         return eIO_Unknown;
     }
 
@@ -5103,24 +5794,32 @@ extern EIO_Status DSOCK_CreateEx(SOCK* sock, TSOCK_Flags flags)
     (*sock)->event     = event;
     (*sock)->writable  = 1/*true*/;
 #endif /*NCBI_OS_MSWIN*/
-#ifdef NCBI_OS_UNIX
     (*sock)->crossexec = flags & fSOCK_KeepOnExec ? 1/*true*/ : 0/*false*/;
-#endif /*NCBI_OS_UNIX*/
     /* all timeouts cleared - infinite */
     BUF_SetChunkSize(&(*sock)->r_buf, SOCK_BUF_CHUNK_SIZE);
     BUF_SetChunkSize(&(*sock)->w_buf, SOCK_BUF_CHUNK_SIZE);
 
-#ifdef NCBI_OS_UNIX
     if (!(*sock)->crossexec  &&  !s_SetCloexec(x_sock, 1/*true*/)) {
-        char _id[32];
-        x_error = SOCK_ERRNO;
+        const char* errstr;
+        char _id[MAXIDLEN];
+#ifdef NCBI_OS_MSWIN
+        DWORD err = GetLastError();
+        errstr = s_WinStrerror(err);
+        x_error = err;
+#else
+        x_error = errno;
+        errstr = SOCK_STRERROR(x_error);
+#endif /*NCBI_OS_MSWIN*/
         CORE_LOGF_ERRNO_EXX(130, eLOG_Warning,
-                            x_error, SOCK_STRERROR(x_error),
+                            x_error, errstr ? errstr : "",
                             ("%s[DSOCK::Create]  Cannot set"
                              " socket close-on-exec mode",
                              s_ID(*sock, _id)));
+#ifdef NCBI_OS_MSWIN
+        if (errstr)
+            LocalFree((char*) errstr);
+#endif /*NCBI_OS_MSWIN*/
     }
-#endif /*NCBI_OS_UNIX*/
 
     /* statistics & logging */
     if ((*sock)->log == eOn  ||  ((*sock)->log == eDefault  &&  s_Log == eOn))
@@ -5132,45 +5831,49 @@ extern EIO_Status DSOCK_CreateEx(SOCK* sock, TSOCK_Flags flags)
 
 extern EIO_Status DSOCK_Bind(SOCK sock, unsigned short port)
 {
-    struct sockaddr_in addr;
-    char _id[32];
+    struct sockaddr_in sin;
+    char _id[MAXIDLEN];
 
     if (sock->type != eDatagram) {
         CORE_LOGF_X(78, eLOG_Error,
                     ("%s[DSOCK::Bind] "
-                     " Not a datagram socket", s_ID(sock, _id)));
+                     " Not a datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(79, eLOG_Error,
-                    ("%s[DSOCK::Bind]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[DSOCK::Bind] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
 
     /* bind */
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family      = AF_INET;
-    addr.sin_addr.s_addr = htonl(INADDR_ANY);
-    addr.sin_port        = htons(port);
+    memset(&sin, 0, sizeof(sin));
 #ifdef HAVE_SIN_LEN
-    addr.sin_len         = sizeof(addr);
+    sin.sin_len         = (SOCK_socklen_t) sizeof(sin);
 #endif /*HAVE_SIN_LEN*/
-    if (bind(sock->sock, (struct sockaddr*) &addr, sizeof(addr)) != 0) {
+    sin.sin_family      = AF_INET;
+    sin.sin_addr.s_addr = htonl(INADDR_ANY);
+    sin.sin_port        = htons(port);
+    if (bind(sock->sock, (struct sockaddr*) &sin, sizeof(sin)) != 0) {
         int x_error = SOCK_ERRNO;
         CORE_LOGF_ERRNO_EXX(80, x_error == SOCK_EADDRINUSE
                             ? eLOG_Trace : eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("%s[DSOCK::Bind]  Failed bind(:%hu)",
+                            ("%s[DSOCK::Bind] "
+                             " Failed bind(:%hu)",
                              s_ID(sock,_id), port));
         return x_error == SOCK_EADDRINUSE ? eIO_Closed : eIO_Unknown;
     }
-    sock->myport = port;
 
     /* statistics & logging */
     if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
-        s_DoLog(eLOG_Trace, sock, eIO_Open, 0, 0, (struct sockaddr*) &addr);
+        s_DoLog(eLOG_Trace, sock, eIO_Open, 0, 0, &sin);
 
+    sock->myport = port;
     return eIO_Success;
 }
 
@@ -5179,19 +5882,23 @@ extern EIO_Status DSOCK_Connect(SOCK sock,
                                 const char* hostname, unsigned short port)
 {
     struct sockaddr_in peer;
+    char _id[MAXIDLEN];
     unsigned int host;
-    char _id[32];
+    char addr[64];
 
     if (sock->type != eDatagram) {
         CORE_LOGF_X(81, eLOG_Error,
                     ("%s[DSOCK::Connect] "
-                     " Not a datagram socket", s_ID(sock, _id)));
+                     " Not a datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(82, eLOG_Error,
-                    ("%s[DSOCK::Connect]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[DSOCK::Connect] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
 
@@ -5213,15 +5920,19 @@ extern EIO_Status DSOCK_Connect(SOCK sock,
         host = 0;
 
     if (!host != !port) {
+        SOCK_HostPortToString(host, port, addr, sizeof(addr));
         CORE_LOGF_X(84, eLOG_Error,
                     ("%s[DSOCK::Connect] "
-                     " Address incomplete, missing %s", s_ID(sock, _id),
-                     port ? "host" : "port"));
+                     " Address \"%s\" incomplete, missing %s",
+                     s_ID(sock, _id), addr, port ? "host" : "port"));
         return eIO_InvalidArg;
     }
 
     /* connect (non-empty address) or drop association (on empty address) */
     memset(&peer, 0, sizeof(peer));
+#ifdef HAVE_SIN_LEN
+    peer.sin_len             = (SOCK_socklen_t) sizeof(peer);
+#endif /*HAVE_SIN_LEN*/
     if (host/*  &&  port*/) {
         peer.sin_family      = AF_INET;
         peer.sin_addr.s_addr =       host;
@@ -5231,11 +5942,7 @@ extern EIO_Status DSOCK_Connect(SOCK sock,
     else
         peer.sin_family      = AF_UNSPEC;
 #endif /*AF_UNSPEC*/
-#ifdef HAVE_SIN_LEN
-    peer.sin_len             = sizeof(peer);
-#endif /*HAVE_SIN_LEN*/
     if (connect(sock->sock, (struct sockaddr*) &peer, sizeof(peer)) != 0) {
-        char addr[80];
         int x_error = SOCK_ERRNO;
         if (host)
             SOCK_HostPortToString(host, port, addr, sizeof(addr));
@@ -5243,18 +5950,19 @@ extern EIO_Status DSOCK_Connect(SOCK sock,
             *addr = '\0';
         CORE_LOGF_ERRNO_EXX(85, eLOG_Error,
                             x_error, SOCK_STRERROR(x_error),
-                            ("%s[DSOCK::Connect]  Failed %sconnect%s%s%s",
+                            ("%s[DSOCK::Connect] "
+                             " Failed %sconnect%s%s%s",
                              s_ID(sock, _id), *addr ? "" : "to dis",
                              &"("[!*addr], addr, &")"[!*addr]));
         return eIO_Unknown;
     }
-    sock->host = host;
-    sock->port = port;
 
     /* statistics & logging */
     if (sock->log == eOn  ||  (sock->log == eDefault  &&  s_Log == eOn))
-        s_DoLog(eLOG_Trace, sock, eIO_Open, &peer, 0, (struct sockaddr*)&peer);
+        s_DoLog(eLOG_Trace, sock, eIO_Open, "", 0, &peer);
 
+    sock->host = host;
+    sock->port = port;
     return eIO_Success;
 }
 
@@ -5271,18 +5979,21 @@ extern EIO_Status DSOCK_SendMsg(SOCK           sock,
     unsigned short     x_port;
     unsigned int       x_host;
     void*              x_msg;
-    struct sockaddr_in addr;
+    struct sockaddr_in sin;
 
     if (sock->type != eDatagram) {
         CORE_LOGF_X(86, eLOG_Error,
                     ("%s[DSOCK::SendMsg] "
-                     " Not a datagram socket", s_ID(sock, w)));
+                     " Not a datagram socket",
+                     s_ID(sock, w)));
         assert(0);
         return eIO_InvalidArg;
     }
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(87, eLOG_Error,
-                    ("%s[DSOCK::SendMsg]  Invalid socket", s_ID(sock, w)));
+                    ("%s[DSOCK::SendMsg] "
+                     " Invalid socket",
+                     s_ID(sock, w)));
         return eIO_Closed;
     }
 
@@ -5296,8 +6007,8 @@ extern EIO_Status DSOCK_SendMsg(SOCK           sock,
     if (host  &&  *host) {
         if (!(x_host = SOCK_gethostbyname(host))) {
             CORE_LOGF_X(88, eLOG_Error,
-                        ("%s[DSOCK::SendMsg]  Failed "
-                         "SOCK_gethostbyname(\"%.64s\")",
+                        ("%s[DSOCK::SendMsg] "
+                         " Failed SOCK_gethostbyname(\"%.64s\")",
                          s_ID(sock, w), host));
             return eIO_Unknown;
         }
@@ -5305,9 +6016,11 @@ extern EIO_Status DSOCK_SendMsg(SOCK           sock,
         x_host = sock->host;
 
     if (!x_host  ||  !x_port) {
+        SOCK_HostPortToString(x_host, x_port, w, sizeof(w)/2);
         CORE_LOGF_X(89, eLOG_Error,
                     ("%s[DSOCK::SendMsg] "
-                     " Address incomplete, missing %s", s_ID(sock, w),
+                     " Address \"%s\" incomplete, missing %s",
+                     s_ID(sock, w + sizeof(w)/2), w,
                      x_port ? "host" : &"host:port"[x_host ? 5 : 0]));
          return eIO_Unknown;
     }
@@ -5321,33 +6034,40 @@ extern EIO_Status DSOCK_SendMsg(SOCK           sock,
     } else
         x_msg = 0;
 
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family      = AF_INET;
-    addr.sin_addr.s_addr =       x_host;
-    addr.sin_port        = htons(x_port);
+    memset(&sin, 0, sizeof(sin));
 #ifdef HAVE_SIN_LEN
-    addr.sin_len         = sizeof(addr);
+    sin.sin_len         = (SOCK_socklen_t) sizeof(sin);
 #endif /*HAVE_SIN_LEN*/
+    sin.sin_family      = AF_INET;
+    sin.sin_addr.s_addr =       x_host;
+    sin.sin_port        = htons(x_port);
 
     for (;;) { /* optionally auto-resume if interrupted */
         int  x_written;
         int  x_error;
         if ((x_written = sendto(sock->sock, x_msg, x_msgsize, 0/*flags*/,
-                                (struct sockaddr*) &addr, sizeof(addr))) >= 0){
+                                (struct sockaddr*) &sin, sizeof(sin))) >= 0){
 
             /* statistics & logging */
             if (sock->log == eOn  ||  (sock->log == eDefault && s_Log == eOn)){
-                s_DoLog(eLOG_Trace, sock, eIO_Write, x_msg, (size_t) x_written,
-                        (struct sockaddr*) &addr);
+                s_DoLog(eLOG_Trace, sock, eIO_Write, x_msg,
+                        (size_t) x_written, &sin);
             }
 
             sock->n_written += x_written;
             sock->n_out++;
             if ((size_t) x_written != x_msgsize) {
                 sock->w_status = status = eIO_Closed;
+                if (!host  &&  !port)
+                    w[0] = '\0';
+                else
+                    SOCK_HostPortToString(x_host, x_port, w, sizeof(w)/2);
                 CORE_LOGF_X(90, eLOG_Error,
                             ("%s[DSOCK::SendMsg] "
-                             " Partial datagram sent", s_ID(sock, w)));
+                             " Partial datagram sent (%lu out of %lu)%s%s",
+                             s_ID(sock, w + sizeof(w)/2),
+                             (unsigned long) x_written,
+                             (unsigned long) x_msgsize, *w ? " to " : "", w));
                 break;
             }
             sock->w_status = status = eIO_Success;
@@ -5383,10 +6103,15 @@ extern EIO_Status DSOCK_SendMsg(SOCK           sock,
             }
             continue;
         } else {
+            if (!host  &&  !port)
+                w[0] = '\0';
+            else
+                SOCK_HostPortToString(x_host, x_port, w, sizeof(w)/2);
             CORE_LOGF_ERRNO_EXX(91, eLOG_Trace,
                                 x_error, SOCK_STRERROR(x_error),
                                 ("%s[DSOCK::SendMsg] "
-                                 " Failed sendto()", s_ID(sock, w)));
+                                 " Failed sendto(%s)",
+                                 s_ID(sock, w + sizeof(w)/2), w));
         }
         /* don't want to handle all possible errors... let them be "unknown" */
         sock->w_status = status = eIO_Unknown;
@@ -5417,13 +6142,16 @@ extern EIO_Status DSOCK_RecvMsg(SOCK            sock,
     if (sock->type != eDatagram) {
         CORE_LOGF_X(92, eLOG_Error,
                     ("%s[DSOCK::RecvMsg] "
-                     " Not a datagram socket", s_ID(sock, w)));
+                     " Not a datagram socket",
+                     s_ID(sock, w)));
         assert(0);
         return eIO_InvalidArg;
     }
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(93, eLOG_Error,
-                    ("%s[DSOCK::RecvMsg]  Invalid socket", s_ID(sock, w)));
+                    ("%s[DSOCK::RecvMsg] "
+                     " Invalid socket",
+                     s_ID(sock, w)));
         return eIO_Closed;
     }
 
@@ -5447,14 +6175,14 @@ extern EIO_Status DSOCK_RecvMsg(SOCK            sock,
     for (;;) { /* auto-resume if either blocked or interrupted (optional) */
         int                x_error;
         int                x_read;
-        struct sockaddr_in addr;
-        SOCK_socklen_t     addrlen = (SOCK_socklen_t) sizeof(addr);
-        memset(&addr, 0, sizeof(addr));
+        struct sockaddr_in sin;
+        SOCK_socklen_t     sinlen = (SOCK_socklen_t) sizeof(sin);
+        memset(&sin, 0, sizeof(sin));
 #ifdef HAVE_SIN_LEN
-        addr.sin_len = addrlen;
+        sin.sin_len = sinlen;
 #endif
         x_read = recvfrom(sock->sock, x_msg, x_msgsize, 0,
-                          (struct sockaddr*) &addr, &addrlen);
+                          (struct sockaddr*) &sin, &sinlen);
 
 #ifdef NCBI_OS_MSWIN
         /* recvfrom() resets IO event recording */
@@ -5468,9 +6196,9 @@ extern EIO_Status DSOCK_RecvMsg(SOCK            sock,
                 if (msglen)
                     *msglen = x_read;
                 if (sender_addr)
-                    *sender_addr =       addr.sin_addr.s_addr;
+                    *sender_addr =       sin.sin_addr.s_addr;
                 if (sender_port)
-                    *sender_port = ntohs(addr.sin_port);
+                    *sender_port = ntohs(sin.sin_port);
                 if ((size_t) x_read > buflen  &&
                     !BUF_Write(&sock->r_buf,
                                (char*) x_msg  + buflen,
@@ -5483,8 +6211,8 @@ extern EIO_Status DSOCK_RecvMsg(SOCK            sock,
 
             /* statistics & logging */
             if (sock->log == eOn  ||  (sock->log == eDefault && s_Log == eOn)){
-                s_DoLog(eLOG_Trace, sock, eIO_Read, x_msg, (size_t) x_read,
-                        (struct sockaddr*) &addr);
+                s_DoLog(eLOG_Trace, sock, eIO_Read, x_msg,
+                        (size_t) x_read, &sin);
             }
 
             sock->n_read += x_read;
@@ -5519,7 +6247,8 @@ extern EIO_Status DSOCK_RecvMsg(SOCK            sock,
             CORE_LOGF_ERRNO_EXX(94, eLOG_Trace,
                                 x_error, SOCK_STRERROR(x_error),
                                 ("%s[DSOCK::RecvMsg] "
-                                 " Failed recvfrom()", s_ID(sock, w)));
+                                 " Failed recvfrom()",
+                                 s_ID(sock, w)));
         }
         /* don't want to handle all possible errors... let them be "unknown" */
         sock->r_status = status = eIO_Unknown;
@@ -5534,7 +6263,7 @@ extern EIO_Status DSOCK_RecvMsg(SOCK            sock,
 
 extern EIO_Status DSOCK_WaitMsg(SOCK sock, const STimeout* timeout)
 {
-    char           _id[32];
+    char           _id[MAXIDLEN];
     EIO_Status     status;
     SSOCK_Poll     poll;
     struct timeval tv;
@@ -5542,13 +6271,16 @@ extern EIO_Status DSOCK_WaitMsg(SOCK sock, const STimeout* timeout)
     if (sock->type != eDatagram) {
         CORE_LOGF_X(95, eLOG_Error,
                     ("%s[DSOCK::WaitMsg] "
-                     " Not a datagram socket", s_ID(sock, _id)));
+                     " Not a datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(96, eLOG_Error,
-                    ("%s[DSOCK::WaitMsg]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[DSOCK::WaitMsg] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
 
@@ -5566,19 +6298,22 @@ extern EIO_Status DSOCK_WaitMsg(SOCK sock, const STimeout* timeout)
 
 extern EIO_Status DSOCK_WipeMsg(SOCK sock, EIO_Event direction)
 {
-    char _id[32];
+    char _id[MAXIDLEN];
     EIO_Status status;
 
     if (sock->type != eDatagram) {
         CORE_LOGF_X(97, eLOG_Error,
                     ("%s[DSOCK::WipeMsg] "
-                     " Not a datagram socket", s_ID(sock, _id)));
+                     " Not a datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(98, eLOG_Error,
-                    ("%s[DSOCK::WipeMsg]  Invalid socket", s_ID(sock, _id)));
+                    ("%s[DSOCK::WipeMsg] "
+                     " Invalid socket",
+                     s_ID(sock, _id)));
         return eIO_Closed;
     }
 
@@ -5591,7 +6326,8 @@ extern EIO_Status DSOCK_WipeMsg(SOCK sock, EIO_Event direction)
         break;
     default:
         CORE_LOGF_X(99, eLOG_Error,
-                    ("%s[DSOCK::WipeMsg]  Invalid direction %u",
+                    ("%s[DSOCK::WipeMsg] "
+                     " Invalid direction #%u",
                      s_ID(sock, _id), (unsigned int) direction));
         assert(0);
         status = eIO_InvalidArg;
@@ -5604,18 +6340,20 @@ extern EIO_Status DSOCK_WipeMsg(SOCK sock, EIO_Event direction)
 
 extern EIO_Status DSOCK_SetBroadcast(SOCK sock, int/*bool*/ broadcast)
 {
-    char _id[32];
+    char _id[MAXIDLEN];
 
     if (sock->type != eDatagram) {
         CORE_LOGF_X(100, eLOG_Error,
                     ("%s[DSOCK::SetBroadcast] "
-                     " Not a datagram socket", s_ID(sock, _id)));
+                     " Not a datagram socket",
+                     s_ID(sock, _id)));
         assert(0);
         return eIO_InvalidArg;
     }
     if (sock->sock == SOCK_INVALID) {
         CORE_LOGF_X(101, eLOG_Error,
-                    ("%s[DSOCK::SetBroadcast]  Invalid socket",
+                    ("%s[DSOCK::SetBroadcast] "
+                     " Invalid socket",
                      s_ID(sock, _id)));
         return eIO_Closed;
     }
@@ -5689,6 +6427,8 @@ extern int SOCK_gethostname(char*  name,
     if (s_InitAPI(0) != eIO_Success)
         return eIO_NotSupported;
 
+    CORE_TRACEF(("[SOCK::gethostname]  Begin"));
+
     error = 0/*false*/;
     assert(name  &&  namelen > 0);
     name[0] = name[namelen - 1] = '\0';
@@ -5696,19 +6436,21 @@ extern int SOCK_gethostname(char*  name,
         int x_error = SOCK_ERRNO;
         CORE_LOG_ERRNO_EXX(103, eLOG_Error,
                            x_error, SOCK_STRERROR(x_error),
-                           "[SOCK_gethostname]  Failed gethostname()");
+                           "[SOCK_gethostname] "
+                           " Failed gethostname()");
         error = 1/*true*/;
     } else if (name[namelen - 1]) {
         CORE_LOG_X(104, eLOG_Error,
-                   "[SOCK_gethostname]  Buffer too small");
+                   "[SOCK_gethostname] "
+                   " Buffer too small");
         error = 1/*true*/;
     }
+    if (error)
+        name[0] = '\0';
 
-    if (!error)
-        return 0/*success*/;
+    CORE_TRACEF(("[SOCK::gethostname]  End: \"%s\"", name));
 
-    name[0] = '\0';
-    return -1/*failed*/;
+    return error ? -1/*failed*/ : 0/*success*/;
 }
 
 
@@ -5808,6 +6550,8 @@ extern unsigned int SOCK_gethostbyname(const char* hostname)
         hostname = buf;
     }
 
+    CORE_TRACEF(("[SOCK::gethostbyname]  \"%s\"", hostname));
+
     host = inet_addr(hostname);
     if (host == htonl(INADDR_NONE)) {
         int x_error;
@@ -5816,9 +6560,9 @@ extern unsigned int SOCK_gethostbyname(const char* hostname)
         memset(&hints, 0, sizeof(hints));
         hints.ai_family = AF_INET; /* currently, we only handle IPv4 */
         if ((x_error = getaddrinfo(hostname, 0, &hints, &out)) == 0  &&  out) {
-            struct sockaddr_in* addr = (struct sockaddr_in *) out->ai_addr;
-            assert(addr->sin_family == AF_INET);
-            host = addr->sin_addr.s_addr;
+            struct sockaddr_in* sin = (struct sockaddr_in *) out->ai_addr;
+            assert(sin->sin_family == AF_INET);
+            host = sin->sin_addr.s_addr;
         } else {
             if (s_Log == eOn) {
                 if (x_error == EAI_SYSTEM)
@@ -5827,8 +6571,9 @@ extern unsigned int SOCK_gethostbyname(const char* hostname)
                     x_error += EAI_BASE;
                 CORE_LOGF_ERRNO_EXX(105, eLOG_Warning,
                                     x_error, SOCK_STRERROR(x_error),
-                                    ("[SOCK_gethostbyname]  Failed "
-                                     "getaddrinfo(\"%.64s\")", hostname));
+                                    ("[SOCK_gethostbyname] "
+                                     " Failed getaddrinfo(\"%.64s\")",
+                                     hostname));
             }
             host = 0;
         }
@@ -5880,8 +6625,8 @@ extern unsigned int SOCK_gethostbyname(const char* hostname)
 #  endif /*NETDB_INTERNAL*/
             CORE_LOGF_ERRNO_EXX(106, eLOG_Warning,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("[SOCK_gethostbyname]  Failed "
-                                 "gethostbyname%s(\"%.64s\")",
+                                ("[SOCK_gethostbyname] "
+                                 " Failed gethostbyname%s(\"%.64s\")",
                                  suffix, hostname));
         }
 
@@ -5904,22 +6649,23 @@ extern char* SOCK_gethostbyaddr(unsigned int host,
         return 0;
     }
 
-    if (!host) {
-        host = SOCK_gethostbyname(0);
-    }
+    if (!host)
+        host = SOCK_GetLocalHostAddress(eDefault);
+
+    CORE_TRACEF(("[SOCK::gethostbyaddr]  0x%08X", (unsigned int) ntohl(host)));
 
     if (host) {
         int x_error;
 #if defined(HAVE_GETNAMEINFO) && defined(EAI_SYSTEM)
-        struct sockaddr_in addr;
+        struct sockaddr_in sin;
 
-        memset(&addr, 0, sizeof(addr));
-        addr.sin_family      = AF_INET; /* currently, we only handle IPv4 */
-        addr.sin_addr.s_addr = host;
+        memset(&sin, 0, sizeof(sin));
 #  ifdef HAVE_SIN_LEN
-        addr.sin_len = sizeof(addr);
+        sin.sin_len = (SOCK_socklen_t) sizeof(sin);
 #  endif /*HAVE_SIN_LEN*/
-        if ((x_error = getnameinfo((struct sockaddr*) &addr, sizeof(addr),
+        sin.sin_family      = AF_INET; /* we only handle IPv4 currently */
+        sin.sin_addr.s_addr = host;
+        if ((x_error = getnameinfo((struct sockaddr*) &sin, sizeof(sin),
                                    name, namelen, 0, 0, 0)) != 0  ||  !*name) {
             if (SOCK_ntoa(host, name, namelen) != 0) {
                 if (!x_error) {
@@ -5941,8 +6687,9 @@ extern char* SOCK_gethostbyaddr(unsigned int host,
                     x_error += EAI_BASE;
                 CORE_LOGF_ERRNO_EXX(107, eLOG_Warning,
                                     x_error, SOCK_STRERROR(x_error),
-                                    ("[SOCK_gethostbyaddr]  Failed "
-                                     "getnameinfo(%s)", addr));
+                                    ("[SOCK_gethostbyaddr] "
+                                     " Failed getnameinfo(%s)",
+                                     addr));
             }
         }
         return name;
@@ -6002,8 +6749,9 @@ extern char* SOCK_gethostbyaddr(unsigned int host,
             SOCK_ntoa(host, addr, sizeof(addr));
             CORE_LOGF_ERRNO_EXX(108, eLOG_Warning,
                                 x_error, SOCK_STRERROR(x_error),
-                                ("[SOCK_gethostbyaddr]  Failed "
-                                 "gethostbyaddr%s(%s)", suffix, addr));
+                                ("[SOCK_gethostbyaddr] "
+                                 " Failed gethostbyaddr%s(%s)",
+                                 suffix, addr));
         }
 
         return name;
diff --git a/connect/ncbi_socket.h b/connect/ncbi_socket.h
index 25296ad..f83b0d5 100644
--- a/connect/ncbi_socket.h
+++ b/connect/ncbi_socket.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_SOCKET__H
 #define CONNECT___NCBI_SOCKET__H
 
-/* $Id: ncbi_socket.h,v 6.71 2009/05/04 15:54:29 kazimird Exp $
+/* $Id: ncbi_socket.h,v 6.75 2010/05/06 16:49:35 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -75,7 +75,7 @@
  *  SOCK_Status
  *  SOCK_Write
  *  SOCK_Abort
- *  SOCK_GetLocalPort
+ *  SOCK_GetLocalPort[Ex]
  *  SOCK_GetPeerAddress
  *  SOCK_GetPeerAddressString
  *
@@ -126,6 +126,11 @@
  *  SOCK_StringToHostPort
  *  SOCK_HostPortToString
  *
+ * Utility:
+ *
+ *  SOCK_SetSelectInternalRestartTimeout
+ *  SOCK_SetIOWaitSysAPI
+ *
  *  Secure:
  *
  *  SOCK_SetupSSL
@@ -320,6 +325,8 @@ extern NCBI_XCONNECT_EXPORT void SOCK_SetReuseAddress
  *  [in]  Break down long waits on I/O into smaller chunks of at most "timeout"
  *  duration each.  This can help recover "hanging" sockets from indefinite
  *  wait and allow them to report an exceptional I/O condition.
+ * @return
+ *   Previous value of the timeout
  * @sa
  *  SOCK_Wait, SOCK_Poll
  */
@@ -328,6 +335,33 @@ SOCK_SetSelectInternalRestartTimeout
 (const STimeout* timeout);
 
 
+/** Selector of I/O wait system API:  auto, poll(), or select().
+ * @sa
+ *  SOCK_SetIOWaitSysAPI
+ */
+typedef enum {
+    eSOCK_IOWaitSysAPIAuto,   /** default; use some euristics to choose API */
+    eSOCK_IOWaitSysAPIPoll,   /** always use poll()                         */
+    eSOCK_IOWaitSysAPISelect  /** always use select()                       */
+} ESOCK_IOWaitSysAPI;
+
+/** This is a helper call that can improve I/O behavior (ignored for Windows).
+ * @param api
+ *  [in]  Default behavior is to wait on I/O such a way that accomodates the
+ *  requested sockets accordingly.  There is a known limitation of select()
+ *  API that requires all sockets to have low-level IO descriptors less than
+ *  1024, but works faster than poll() API that does not have limits on the
+ *  numeric values of the descriptors.  Either API can be enforced here.
+ * @return
+ *  Previous value of the API selector
+ * @sa
+ *  SOCK_Wait, SOCK_Poll
+ */
+extern NCBI_XCONNECT_EXPORT ESOCK_IOWaitSysAPI
+SOCK_SetIOWaitSysAPI
+(ESOCK_IOWaitSysAPI api);
+
+
 /** By default (on UNIX platforms) the SOCK API functions automagically call
  * "signal(SIGPIPE, SIG_IGN)" on initialization.  To prohibit this feature,
  * you must call SOCK_AllowSigPipeAPI() before you call any other
@@ -459,7 +493,7 @@ typedef enum {
     fSOCK_ReadOnWrite       = 0x100,
     fSOCK_InterruptOnSignal = 0x200
 } ESOCK_Flags;
-typedef unsigned int TSOCK_Flags;
+typedef unsigned int TSOCK_Flags;  /** Bitwise "OR" of ESOCK_Flags */
 
 
 /******************************************************************************
@@ -529,8 +563,23 @@ extern NCBI_XCONNECT_EXPORT EIO_Status LSOCK_Create
  *  all I/O timeouts are infinite by default.
  * @param sock
  *  [out] handle of the accepted socket
+ * @param flags
+ *  [in]  properties for the accepted socket to have
  * @sa
- *  SOCK_Create, SOCK_Close
+ *  SOCK_Create, SOCK_Close, TSOCK_Flags
+ */
+extern NCBI_XCONNECT_EXPORT EIO_Status LSOCK_AcceptEx
+(LSOCK           lsock,    
+ const STimeout* timeout, 
+ SOCK*           sock,
+ TSOCK_Flags     flags
+ );
+
+
+/** [SERVER-side]  Accept connection from a client.
+ * Same as LSOCK_AcceptEx(.,.,.,fSOCK_LogDefault)
+ * @sa
+ *  LSOCK_AcceptEx
  */
 extern NCBI_XCONNECT_EXPORT EIO_Status LSOCK_Accept
 (LSOCK           lsock,    
@@ -699,11 +748,12 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_CreateOnTop
  *        if "port" is zero then connect to the same port # as before.
  *
  * @li <b>NOTE 1:</b> "new" socket inherits old I/O timeouts;
- * @li <b>NOTE 2:</b> the call is only applicable to stream [not datagram] sockets.
- * @li <b>NOTE 3:</b> "timeout"==NULL is infinite; "timeout"=={0,0} causes no wait for
- *        connection to be established and to return immediately.
- * @li <b>NOTE 4:</b> UNIX sockets can only be reconnected to the same file thus both
- *        host and port have to be passed as 0s.
+ * @li <b>NOTE 2:</b> the call is only applicable to stream [not datagram]
+          sockets.
+ * @li <b>NOTE 3:</b> "timeout"==NULL is infinite; "timeout"=={0,0} causes
+ *        no wait for connection to be established and to return immediately.
+ * @li <b>NOTE 4:</b> UNIX sockets can only be reconnected to the same file
+ *        thus both host and port have to be passed as 0s.
  * @param sock
  *  [in]  handle of the socket to reconnect
  * @param host
@@ -813,7 +863,7 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_Wait
  */
 typedef struct {
     SOCK      sock;   /** [in]          SOCK to poll (NULL if not to poll)  */
-    EIO_Event event;  /** [in]  one of: eIO_Read, eIO_Write, eIO_ReadWrite  */
+    EIO_Event event;  /** [in]  one of: eIO_Open/Read/Write/ReadWrite       */
     EIO_Event revent; /** [out] one of: eIO_Open/Read/Write/ReadWrite/Close */
 } SSOCK_Poll;
 
@@ -823,22 +873,28 @@ typedef struct {
  * or until timeout expires (wait indefinitely if timeout is passed NULL).
  * Return eIO_Success if at least one socket was found ready;  eIO_Timeout
  * if timeout expired;  eIO_Unknown if underlying system call(s) failed.
- * @li <b>NOTE 1:</b> For a socket found not ready for an operation, eIO_Open is returned
- *        in its "revent"; for a failing socket, eIO_Close is returned;
- * @li <b>NOTE 2:</b> This call may return eIO_InvalidArg if
+ * @li <b>NOTE 1:</b> NULL sockets as well as non-NULL sockets with eIO_Open
+ *        requested in their "event" do not get polled;
+ * @li <b>NOTE 2:</b> For a socket found not ready for an operation, eIO_Open
+ *        is returned in its "revent"; for a failing socket, eIO_Close
+ *        is returned;
+ * @li <b>NOTE 3:</b> This call may return eIO_InvalidArg if
  *        - parameters to the call are inconsistent;
- *        - a non-NULL socket polled with a bad "event" (eIO_Open, eIO_Close).
+ *        - a non-NULL socket polled with a bad "event" (eIO_Close).
  *        With this return code, the calling program cannot rely on "revent"
- *        fields the "polls" array as they might not be properly updated.
- * @li <b>NOTE 3:</b> If either both "n" and "polls" are NULL, or all sockets in "polls"
- *        are NULL, then the returned result is either
- *        eIO_Timeout (after the specified amount of time was spent idle), or
- *        eIO_Interrupted (if signal came while the waiting was in progress).
- * @li <b>NOTE 4:</b> For datagram sockets, the readiness for reading is determined by
- *        message data latched since last message receive call (DSOCK_RecvMsg).
- * @li <b>NOTE 5:</b> This call allows intermixture of stream and datagram sockets.
- * @li <b>NOTE 6:</b> This call can cause some socket I/O in those sockets marked for
- *        read-on-write and those with pending connection or output data.
+ *        fields in the "polls" array as they might not be properly updated.
+ * @li <b>NOTE 4:</b> If either both "n" and "polls" are NULL, or all sockets
+ *        in "polls" are NULL, then the returned result is either:
+ *        - eIO_Timeout (after the specified amount of time was spent idle), or
+ *        - eIO_Interrupted (if signal came while the waiting was in progress).
+ * @li <b>NOTE 5:</b> For datagram sockets, the readiness for reading is
+ *        determined by message data latched since last message receive call
+ *        (DSOCK_RecvMsg).
+ * @li <b>NOTE 6:</b> This call allows intermixture of stream and
+ *        datagram sockets.
+ * @li <b>NOTE 7:</b> This call can cause some socket I/O in those sockets
+ *        marked for read-on-write and those with pending connection or
+ *        output data.
  * @param n
  *  [in]  # of SSOCK_Poll elems in "polls"  
  * @param polls[]
@@ -900,7 +956,7 @@ extern NCBI_XCONNECT_EXPORT TRIGGER  POLLABLE_ToTRIGGER(POLLABLE);
 
 /** Specify timeout for the connection i/o (see SOCK_[Read|Write|Close] funcs).
  * If "timeout" is NULL then set the timeout to be infinite;
- * @li <b>NOTE:</b> the default timeout is infinite (wait "ad infinitum" on I/O).
+ * @li <b>NOTE:</b> the default timeout is infinite (to wait indefinitely).
  * @param sock
  *  [in]  socket handle 
  * @param event
@@ -916,10 +972,11 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_SetTimeout
 
 
 /** Get the connection's i/o timeout (or NULL, if the timeout is infinite).
- * @li <b>NOTE 1:</b>  the returned timeout is guaranteed to be pointing to a valid
- *         (and correct) structure in memory at least until the SOCK is closed
+ * @li <b>NOTE 1:</b>  the returned timeout is guaranteed to be pointing to
+ *         a valid structure in memory at least until the SOCK is closed
  *         or SOCK_SetTimeout is called for this "sock".
- * @li <b>NOTE 2:</b>  eIO_ReadWrite timeout is the least of eIO_Read and eIO_Write ones.
+ * @li <b>NOTE 2:</b>  eIO_ReadWrite timeout is the least of
+ *         eIO_Read and eIO_Write ones.
  * @param sock
  *  [in]  socket handle 
  * @param event
@@ -931,7 +988,7 @@ extern NCBI_XCONNECT_EXPORT const STimeout* SOCK_GetTimeout
  );
 
 
-/** Read/peek up to "size" bytes from "sock" to the mem.buffer pointed by "buf".
+/** Read/peek up to "size" bytes from "sock" to a buffer pointed to by "buf".
  * In "*n_read", return the number of successfully read bytes.
  * Read method "how" can be either of the following:
  * eIO_ReadPlain   -- read as many as "size" bytes and return (eIO_Success);
@@ -954,7 +1011,7 @@ extern NCBI_XCONNECT_EXPORT const STimeout* SOCK_GetTimeout
  * Both mothods return any other code when no data at all were available.
  * eIO_ReadPersist differs from the other two methods as it can return an
  * error condition even if some data were actually obtained from the socket.
- * Hence, as a rule of thumb, an application should always check the number
+ * Hence, as the *rule of thumb*, an application should always check the number
  * of read bytes BEFORE checking the return status, which merely advises
  * whether it is okay to read again.
  *
@@ -964,14 +1021,15 @@ extern NCBI_XCONNECT_EXPORT const STimeout* SOCK_GetTimeout
  *   eIO_Read[Persist] -- discard up to "size" bytes from internal buffer
  *                        and socket (check "*n_read" to know how many).
  *
- * @li <b>NOTE 1:</b> "Read" and "peek" methods differ:  if "read" is performed and not
- *        enough but some data available immediately from the internal buffer,
- *        then the call completes with eIO_Success status.  For "peek", if
- *        not all requested data were available, the real I/O occurs to pick up
- *        additional data (if any) from the system. Keep this difference in
- *        mind when programming loops that heavily use "peek"s without "read"s.
- * @li <b>NOTE 2:</b> If on input "size" == 0, then "*n_read" is set to 0, and the
- *        return value can be either of eIO_Success, eIO_Closed or
+ * @li <b>NOTE 1:</b> "Read" and "peek" methods differ:  if "read" is
+ *        performed and not enough but only some data available immediately
+ *        from the internal buffer, then the call still completes with
+ *        eIO_Success status.  For "peek", if not all requested data were
+ *        available, the real I/O occurs to pick up additional data (if any)
+ *        from the system.  Keep this difference in mind when programming
+ *        loops that heavily use "peek"s without "read"s.
+ * @li <b>NOTE 2:</b> If on input "size" == 0, then "*n_read" is set to 0,
+ *        and the return value can be either of eIO_Success, eIO_Closed or
  *        eIO_Unknown depending on connection status of the socket.
  * @param sock
  *  [in]  socket handle 
@@ -1098,15 +1156,17 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_Status
  *                other code denotes an error, but some bytes might have
  *                been sent nevertheless (always check *n_written to know).
  *
- * @li <b>NOTE 1:</b> With eIO_WritePlain the call returns eIO_Success iff some data
- *        were actually written to the socket. If no data could be written
- *        (and perhaps timeout expired) this call always returns an error.
- * @li <b>NOTE 2:</b> eIO_WritePlain and eIO_WritePersist differs that the latter can
- *        flag an error condition even if some data were actually written
+ * @li <b>NOTE 1:</b> With eIO_WritePlain the call returns eIO_Success iff
+ *        some data were actually written to the socket.  If no data could
+ *        be written (and perhaps timeout expired) this call always returns
+ *        an error.
+ * @li <b>NOTE 2:</b> eIO_WritePlain and eIO_WritePersist differ that
+ *        the latter can flag an error condition even if some data were
+ *        actually written
  *        (see "the rule of thumb" in the comments for SOCK_Read() above).
- * @li <b>NOTE 3:</b> if "size"==0, return value can be eIO_Success if no pending data
- *        left in the socket, or eIO_Timeout if there are still data pending.
- *        In either case, "*n_written" is set to 0 on return.
+ * @li <b>NOTE 3:</b> if "size"==0, return value can be eIO_Success if no
+ *        pending data left in the socket, or eIO_Timeout if there are still
+ *        data pending.  In either case, "*n_written" is set to 0 on return.
  */
 extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_Write
 (SOCK            sock,
@@ -1133,7 +1193,37 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_Abort
  );
 
 
+/** Get local port of the socket (true or cached / stored).
+ * For most users, a simpler SOCK_GetLocalPort() call is going to be the
+ * most suitable.  This call allows to inquire the network level about
+ * a temporary port number assigned when a socket was created as a result
+ * of accepting the connection (otherwise, the listening socket port number
+ * gets returned as the local port).  For connecting sockets, both "trueport"
+ * and no "trueport" results are identical (with the exception that "trueport"
+ * causes an additional system call, and the result is not stored).
+ * @param sock
+ *  [in] socket handle
+ * @param trueport
+ *  [in] non-zero causes to refetch / no-cache port from the network layer
+ * @param byte_order
+ *  [in] port byte order
+ * @return
+ *  If "network_byte_order" is true(non-zero) then return the port in the
+ *  network byte order; otherwise return it in the local host byte order.
+ * @sa
+ *  SOCK_GetLocalPort
+ */
+extern NCBI_XCONNECT_EXPORT unsigned short SOCK_GetLocalPortEx
+(SOCK            sock,
+ int/*bool*/     trueport,
+ ENH_ByteOrder   byte_order          
+ );
+
+
 /** Get local port of the socket.
+ * The returned port number is also cached within "sock" so all following
+ * inquires for the local port do not cause any system calls to occur.
+ * Has exactly same effect as SOCK_GetLocalPortEx(sock, 0, byte_order)
  * @param sock
  *  [in] socket handle 
  * @param byte_order
@@ -1141,6 +1231,8 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_Abort
  * @return
  *  If "network_byte_order" is true(non-zero) then return the port in the
  *  network byte order; otherwise return it in the local host byte order.
+ * @sa
+ *  SOCK_GetLocalPortEx
  */
 extern NCBI_XCONNECT_EXPORT unsigned short SOCK_GetLocalPort
 (SOCK            sock,
@@ -1208,11 +1300,11 @@ extern NCBI_XCONNECT_EXPORT char* SOCK_GetPeerAddressString
 /** Get an OS-dependent native socket handle to use by platform-specific API.
  * FYI:  on MS-Windows it will be "SOCKET", on other platforms -- "int".
  * @param sock
- *   Socket handle
+ *  [in]  socket handle
  * @param handle_buf
- *  pointer to a memory area to put the OS handle at
+ *  [out] pointer to a memory area to put the OS handle at
  * @param handle_size
- *  the exact(!) size of the expected OS handle
+ *  [in]  the exact(!) size of the expected OS handle
  */
 extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_GetOSHandle
 (SOCK   sock,
@@ -1229,7 +1321,7 @@ extern NCBI_XCONNECT_EXPORT EIO_Status SOCK_GetOSHandle
  * 
  * @return
  *  Prior setting.
-*/
+ */
 extern NCBI_XCONNECT_EXPORT ESwitch SOCK_SetReadOnWriteAPI
 (ESwitch on_off
  );
@@ -1419,7 +1511,7 @@ extern NCBI_XCONNECT_EXPORT EIO_Status DSOCK_RecvMsg
  * @param sock
  *  [in] SOCK from DSOCK_Create[Ex]()
  * @param direction
- *  [in] either of eIO_Read|eIO_Write
+ *  [in] either of eIO_Read, eIO_Write
  */
 extern NCBI_XCONNECT_EXPORT EIO_Status DSOCK_WipeMsg
 (SOCK            sock,                 
@@ -1430,7 +1522,7 @@ extern NCBI_XCONNECT_EXPORT EIO_Status DSOCK_WipeMsg
  * @param sock
  *  [in] SOCK from DSOCK_Create[Ex]()
  * @param broadcast
- *  [in] set(1)/unset(0) bcast capab
+ *  [in] set(1)/unset(0) broadcast capability
  */
 extern NCBI_XCONNECT_EXPORT EIO_Status DSOCK_SetBroadcast
 (SOCK            sock,                  
@@ -1604,7 +1696,7 @@ unsigned short SOCK_htons(unsigned short);
  *  @li <b>NOTE:</b> "0.0.0.0" and "255.255.255.255" are considered invalid.
  */
 extern NCBI_XCONNECT_EXPORT unsigned int SOCK_gethostbyname
-(const char* hostname \
+(const char* hostname
  );
 
 
diff --git a/connect/ncbi_socket_connector.c b/connect/ncbi_socket_connector.c
index 30044f1..b766760 100644
--- a/connect/ncbi_socket_connector.c
+++ b/connect/ncbi_socket_connector.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_socket_connector.c,v 6.24 2008/10/31 11:25:51 kazimird Exp $
+/* $Id: ncbi_socket_connector.c,v 6.27 2010/05/10 16:59:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -34,6 +34,7 @@
  */
 
 #include "ncbi_ansi_ext.h"
+#include "ncbi_assert.h"
 #include <connect/ncbi_socket_connector.h>
 #include <assert.h>
 #include <stdio.h>
@@ -50,11 +51,11 @@
  */
 typedef struct {
     SOCK           sock;      /* socket;  NULL if not connected yet       */
-    char*          host;      /* server:  host                            */
+    const char*    host;      /* server:  host                            */
     unsigned short port;      /* server:  service port                    */
-    unsigned int   max_try;   /* max.number of attempts to establish conn */
-    void*          init_data; /* data to send to the server on connect    */
-    size_t         init_size; /* size of the "inst_str" buffer            */
+    unsigned int   try_own;   /* max.number of attempts to establish conn */
+    const void*    init_data; /* data to send to the server on connect    */
+    size_t         init_size; /* size of the "init_data" buffer           */
     TSOCK_Flags    flags;     /* see socket flags in ncbi_socket.h        */
 } SSockConnector;
 
@@ -90,11 +91,6 @@ extern "C" {
     static void        s_Setup      (SMetaConnector* meta,
                                      CONNECTOR       connector);
     static void        s_Destroy    (CONNECTOR       connector);
-#  ifdef IMPLEMENTED__CONN_WaitAsync
-    static EIO_Status s_VT_WaitAsync(void*                   connector,
-                                     FConnectorAsyncHandler  func,
-                                     SConnectorAsyncHandler* data);
-#  endif
 #ifdef __cplusplus
 } /* extern "C" */
 #endif /* __cplusplus */
@@ -125,53 +121,31 @@ static EIO_Status s_VT_Open
  const STimeout* timeout)
 {
     SSockConnector* xxx = (SSockConnector*) connector->handle;
-    EIO_Status   status = eIO_Unknown;
-    unsigned int i = 0;
-
-    do {
-        if (xxx->sock  &&  !xxx->host) {
-            /* on-top (connected) connector for the 1st time - only once here*/
-            unsigned int   host;
-            unsigned short port;
-            char           addr[MAX_IP_ADDR_LEN];
-
-            SOCK_GetPeerAddress(xxx->sock, &host, &port, eNH_HostByteOrder);
-            if (SOCK_ntoa(SOCK_HostToNetLong(host), addr, sizeof(addr)) != 0)
-                return eIO_Unknown;
-            xxx->host = strdup(addr);
-            xxx->port = port;
-            status = eIO_Success;
-        } else {
-            if (!xxx->max_try)
-                break;
-            /* connect/reconnect */
-            status = xxx->sock ?
-                SOCK_Reconnect(xxx->sock, 0, 0, timeout) :
-                SOCK_CreateEx(xxx->host, xxx->port, timeout, &xxx->sock,
-                              xxx->init_data, xxx->init_size,
-                              xxx->flags);
+    EIO_Status status = eIO_Success;
+
+    if (!xxx->sock) {
+        unsigned int i;
+        assert(xxx->try_own);
+        for (i = 0;  i < xxx->try_own;  i++) {
+            /* connect */
+            status = SOCK_CreateEx(xxx->host, xxx->port, timeout, &xxx->sock,
+                                   xxx->init_data, xxx->init_size, xxx->flags);
+            if (xxx->sock) {
             if (xxx->init_data) {
-                free(xxx->init_data);
+                    assert(xxx->init_size);
+                    free((void*) xxx->init_data);
                 xxx->init_data = 0;
-                xxx->init_size = 0;
             }
-            i++;
+                break;
+            }
+            assert(status != eIO_Success);
         }
-    } while (status != eIO_Success  &&  i < xxx->max_try);
-
+    }
+    assert(xxx->sock  ||  status != eIO_Success);
     return status;
 }
 
 
-static EIO_Status s_VT_Status
-(CONNECTOR connector,
- EIO_Event dir)
-{
-    SSockConnector* xxx = (SSockConnector*) connector->handle;
-    return xxx->sock ? SOCK_Status(xxx->sock, dir) : eIO_Success;
-}
-
-
 static EIO_Status s_VT_Wait
 (CONNECTOR       connector,
  EIO_Event       event,
@@ -179,7 +153,8 @@ static EIO_Status s_VT_Wait
 {
     SSockConnector* xxx = (SSockConnector*) connector->handle;
     assert(event == eIO_Read || event == eIO_Write);
-    return xxx->sock ? SOCK_Wait(xxx->sock, event, timeout) : eIO_Closed;
+    assert(xxx->sock);
+    return SOCK_Wait(xxx->sock, event, timeout);
 }
 
 
@@ -191,10 +166,8 @@ static EIO_Status s_VT_Write
  const STimeout* timeout)
 {
     SSockConnector* xxx = (SSockConnector*) connector->handle;
-
-    if (!xxx->sock)
-        return eIO_Closed;
-    SOCK_SetTimeout(xxx->sock, eIO_Write, timeout);
+    assert(xxx->sock);
+    verify(SOCK_SetTimeout(xxx->sock, eIO_Write, timeout) == eIO_Success);
     return SOCK_Write(xxx->sock, buf, size, n_written, eIO_WritePlain);
 }
 
@@ -207,40 +180,38 @@ static EIO_Status s_VT_Read
  const STimeout* timeout)
 {
     SSockConnector* xxx = (SSockConnector*) connector->handle;
-    if (!xxx->sock)
-        return eIO_Closed;
-    SOCK_SetTimeout(xxx->sock, eIO_Read, timeout);
+    assert(xxx->sock);
+    verify(SOCK_SetTimeout(xxx->sock, eIO_Read, timeout) == eIO_Success);
     return SOCK_Read(xxx->sock, buf, size, n_read, eIO_ReadPlain);
 }
 
 
+static EIO_Status s_VT_Status
+(CONNECTOR connector,
+ EIO_Event dir)
+{
+    SSockConnector* xxx = (SSockConnector*) connector->handle;
+    assert(xxx->sock);
+    return SOCK_Status(xxx->sock, dir);
+}
+
+
 static EIO_Status s_VT_Close
 (CONNECTOR       connector,
  const STimeout* timeout)
 {
     SSockConnector* xxx = (SSockConnector*) connector->handle;
     EIO_Status status = eIO_Success;
-
-    if (xxx->sock) {
-        SOCK_SetTimeout(xxx->sock, eIO_Write, timeout);
+    assert(xxx->sock);
+    if (xxx->try_own) {
+        SOCK_SetTimeout(xxx->sock, eIO_Close, timeout);
         status = SOCK_Close(xxx->sock);
-        xxx->sock = 0;
     }
+    xxx->sock = 0;
     return status;
 }
 
 
-#ifdef IMPLEMENTED__CONN_WaitAsync
-static EIO_Status s_VT_WaitAsync
-(void*                   connector,
- FConnectorAsyncHandler  func,
- SConnectorAsyncHandler* data)
-{
-    return eIO_NotSupported;
-}
-#endif
-
-
 static void s_Setup
 (SMetaConnector* meta,
  CONNECTOR       connector)
@@ -255,10 +226,7 @@ static void s_Setup
     CONN_SET_METHOD(meta, read,       s_VT_Read,      connector);
     CONN_SET_METHOD(meta, status,     s_VT_Status,    connector);
     CONN_SET_METHOD(meta, close,      s_VT_Close,     connector);
-#ifdef IMPLEMENTED__CONN_WaitAsync
-    CONN_SET_METHOD(meta, wait_async, s_VT_WaitAsync, connector);
-#endif
-    meta->default_timeout = 0; /*infinite*/
+    meta->default_timeout = kInfiniteTimeout;
 }
 
 
@@ -266,13 +234,15 @@ static void s_Destroy
 (CONNECTOR connector)
 {
     SSockConnector* xxx = (SSockConnector*) connector->handle;
+    connector->handle = 0;
 
-    if (xxx->host)
-        free(xxx->host);
-    if (xxx->init_data)
-        free(xxx->init_data);
+    xxx->host = 0;
+    if (xxx->init_data) {
+        assert(xxx->init_size);
+        free((void*) xxx->init_data);
+        xxx->init_data = 0;
+    }
     free(xxx);
-    connector->handle = 0;
     free(connector);
 }
 
@@ -281,31 +251,44 @@ static CONNECTOR s_Init
 (SOCK           sock,
  const char*    host,
  unsigned short port,
- unsigned int   max_try,
+ unsigned int   try_own,
  const void*    init_data,
  size_t         init_size,
  TSOCK_Flags    flags)
 {
     CONNECTOR       ccc = (SConnector    *) malloc(sizeof(SConnector));
-    SSockConnector* xxx = (SSockConnector*) malloc(sizeof(*xxx));
+    SSockConnector* xxx = (SSockConnector*) malloc(sizeof(*xxx) +
+                                                   (port
+                                                    ? strlen(host) + 1
+                                                    : MAX_IP_ADDR_LEN));
 
-    /* parameter check: either sock or host/port, not both */
+    /* sanity check: either sock or host/port, not both */
     assert((!sock && host && port)  ||  (sock && !host && !port));
+    assert(!sock  ||  !(init_size || init_data || flags));  
     assert(!init_size || init_data);
+
     /* initialize internal data structures */
+    if (sock) {
+        unsigned int x_host;
+        char* addr = (char*) xxx + sizeof(*xxx);
+        SOCK_GetPeerAddress(sock, &x_host, &xxx->port, eNH_HostByteOrder);
+        SOCK_ntoa(SOCK_HostToNetLong(x_host), addr, MAX_IP_ADDR_LEN);
     xxx->sock        = sock;
-    xxx->host        = host ? strdup(host) : 0;
+        xxx->host      = addr;
+        assert(xxx->port);
+        xxx->try_own   = try_own ? 1       : 0;
+        xxx->init_data = 0;
+    } else {
+        xxx->sock      = 0;
+        xxx->host      = strcpy((char*) xxx + sizeof(*xxx), host);
     xxx->port        = port;
-    if (sock)
-        xxx->max_try = SOCK_IsServerSide(sock) ? 0 : max_try;
-    else
-        xxx->max_try = max_try ? max_try : 1;
+        xxx->try_own   = try_own ? try_own : 1;
     xxx->flags       = flags;
     xxx->init_size   = init_data ? init_size : 0;
     if (xxx->init_size) {
-        xxx->init_data = malloc(init_size);
-        memcpy(xxx->init_data, init_data, xxx->init_size);
-    } else {
+            void* data     = malloc(init_size);
+            xxx->init_data = data ? memcpy(data, init_data, init_size) : 0;
+        } else
         xxx->init_data = 0;
     }
 
@@ -347,16 +330,7 @@ extern CONNECTOR SOCK_CreateConnectorEx
 
 extern CONNECTOR SOCK_CreateConnectorOnTop
 (SOCK         sock,
- unsigned int max_try)
-{
-    return s_Init(sock, 0, 0, max_try, 0, 0, fSOCK_LogDefault);
-}
-
-
-extern CONNECTOR SOCK_CreateConnectorOnTopEx
-(SOCK         sock,
- unsigned int max_try,
- TSOCK_Flags  flags)
+ unsigned int/*bool*/ own_sock)
 {
-    return s_Init(sock, 0, 0, max_try, 0, 0, flags);
+    return s_Init(sock, 0,    0,    own_sock, 0,         0,         0);
 }
diff --git a/connect/ncbi_socket_connector.h b/connect/ncbi_socket_connector.h
index dc47a3d..d968dc1 100644
--- a/connect/ncbi_socket_connector.h
+++ b/connect/ncbi_socket_connector.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_SOCKET_CONNECTOR__H
 #define CONNECT___NCBI_SOCKET_CONNECTOR__H
 
-/* $Id: ncbi_socket_connector.h,v 6.11 2008/10/31 11:25:51 kazimird Exp $
+/* $Id: ncbi_socket_connector.h,v 6.12 2010/02/01 13:54:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -71,7 +71,8 @@ typedef enum { /* DEPRECATED -- DON'T USE! */
  * Make up to "max_try" attempts to connect to the "host:port" before
  * giving up.
  * On successful connect, send the first "init_size" bytes from buffer
- * "init_data"(can be NULL -- then send nothing) to the opened connection.
+ * "init_data"(can be NULL -- then send nothing, regardless of "init_size")
+ * to the newly opened connection.
  * NOTE:  the connector makes (and then uses) its own copy of the "init_data".
  * Return NULL on error.
  */
@@ -85,28 +86,17 @@ extern NCBI_XCONNECT_EXPORT CONNECTOR SOCK_CreateConnectorEx
  );
 
 
-/* Equivalent to SOCK_CreateConnectorOnTopEx(sock, max_try, 0,0,0),
- * see below.
- */
-extern NCBI_XCONNECT_EXPORT CONNECTOR SOCK_CreateConnectorOnTop
-(SOCK         sock,   /* socket object                                       */
- unsigned int max_try /* max.number of tries to re-establish the link if lost*/
- );
-
-
 /* Create new CONNECTOR structure on top of existing socket object (SOCK),
- * acquiring the ownership of the socket, and overriding all timeouts
- * that might have been set already in it. Timeout values will be taken from
- * connection (CONN), after the connector is used in CONN_Create() call.
- * Please note that this function revokes all ownership of the socket, and
- * further assumes the passed socket is for the sole use of the connector.
- * A socket obtained as a result of accepting connection on a listening socket
- * (aka server-side socket) is not allowed to have reconnects (max_try = 0).
+ * acquiring the ownership of the socket "sock" if "own_sock" passed non-zero,
+ * and overriding all timeouts that might have been set already in it.
+ * Timeout values will be taken from connection (CONN), after the connector
+ * is used in CONN_Create() call.
+ * Non-owned socket will not be closed when the connection gets closed;
+ * and may further be used, as necessary (including closing it explicitly).
  */
-extern NCBI_XCONNECT_EXPORT CONNECTOR SOCK_CreateConnectorOnTopEx
+extern NCBI_XCONNECT_EXPORT CONNECTOR SOCK_CreateConnectorOnTop
 (SOCK         sock,      /* socket object                                    */
- unsigned int max_try,   /* max.# of tries to reconnect if disconnected      */
- TSOCK_Flags  flags      /* bitwise OR of additional flags: see above        */
+ unsigned int/*bool*/ own_sock /* non-zero if connector will own "sock"      */
  );
 
 
diff --git a/connect/ncbi_socketp.h b/connect/ncbi_socketp.h
index 3284973..096682c 100644
--- a/connect/ncbi_socketp.h
+++ b/connect/ncbi_socketp.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_SOCKETP__H
 #define CONNECT___NCBI_SOCKETP__H
 
-/* $Id: ncbi_socketp.h,v 1.11 2009/03/02 20:14:30 kazimird Exp $
+/* $Id: ncbi_socketp.h,v 1.19 2010/05/01 15:54:36 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -47,22 +47,26 @@
 /* Pull in a minial set of platform-specific system headers here.
  */
 
-#if defined(NCBI_OS_MSWIN)
+#ifdef NCBI_OS_MSWIN
 #  include <winsock2.h>
-#elif defined(NCBI_OS_UNIX)
+#else /*NCBI_OS_UNIX*/
 #  include <sys/socket.h>
 #  include <sys/time.h>
-#endif
+#endif /*NCBI_OS_MSWIN*/
 
 /* Portable error codes.
  */
 #include <errno.h>
 
-#if   defined(NCBI_OS_MSWIN)
+#ifdef NCBI_OS_MSWIN
 
 typedef SOCKET TSOCK_Handle;
 typedef HANDLE TRIGGER_Handle;
 
+#  ifdef _WIN64
+#    pragma pack(push, 4)
+#  endif /*_WIN64*/
+
 #  define SOCK_EINTR          WSAEINTR
 #  define SOCK_EWOULDBLOCK    WSAEWOULDBLOCK/*EAGAIN*/
 #  define SOCK_EADDRINUSE     WSAEADDRINUSE
@@ -80,7 +84,7 @@ typedef HANDLE TRIGGER_Handle;
 #  define SOCK_SHUTDOWN_WR    SD_SEND
 #  define SOCK_SHUTDOWN_RDWR  SD_BOTH
 
-#else
+#else /*NCBI_OS_UNIX*/
 
 typedef int TSOCK_Handle;
 typedef int TRIGGER_Handle;
@@ -112,7 +116,7 @@ typedef int TRIGGER_Handle;
 #  endif /*SHUT_RDWR*/
 #  define SOCK_SHUTDOWN_RDWR  SHUT_RDWR
 
-#endif
+#endif /*NCBI_OS_MSWIN*/
 
 #if   defined(ENFILE)
 #  define SOCK_ETOOMANY       ENFILE
@@ -154,8 +158,10 @@ typedef struct TRIGGER_tag {
     TRIGGER_Handle   fd;        /* OS-specific trigger handle                */
     unsigned int     id;        /* the internal ID (cf. "s_ID_Counter")      */
 
-    volatile int     isset;     /* trigger state (UNIX only, otherwise MBZ)  */
-    volatile int     isset_;    /* CAUTION: "isset" pointer protrusion area! */
+    union {
+        volatile void* ptr;     /* trigger state (UNIX only, otherwise MBZ)  */
+        int            int_[2]; /* pointer storage area w/proper alignment   */
+    } isset;
 
     /* type, status, EOF, log, read-on-write etc bit-field indicators */
     TSOCK_Type          type;   /* eTrigger                                  */
@@ -184,7 +190,7 @@ typedef struct LSOCK_tag {
     unsigned int     id;        /* the internal ID (see also "s_ID_Counter") */
 
     unsigned int     n_accept;  /* total number of accepted clients          */
-    unsigned short   n_log;     /* MSWIN: run-away connect warning counter   */
+    unsigned short   away;      /* MSWIN: run-away connect warning counter   */
     unsigned short   port;      /* port on which listening (host byte order) */
 
     /* type, status, EOF, log, read-on-write etc bit-field indicators */
@@ -199,17 +205,15 @@ typedef struct LSOCK_tag {
     EBIO_Status     w_status:3; /* MBZ (NB: eIO_Success)                     */
     unsigned/*bool*/ pending:1; /* MBZ                                       */
 
-    unsigned          unused:1; /* MBZ                                       */
-#ifdef NCBI_OS_MSWIN
-    unsigned        readable:1; /* =1 if known to have a pending accept      */
-    unsigned        reserved:6; /* MBZ                                       */
+#ifndef NCBI_OS_MSWIN
+    unsigned        reserved:8; /* MBZ                                       */
 #else
-    unsigned        reserved:7; /* MBZ                                       */
-#endif /*NCBI_OS_MSWIN*/
+    unsigned        reserved:5; /* MBZ                                       */
+    unsigned        readable:1; /* =1 if known to have a pending accept      */
+    unsigned          unused:2; /* MBZ                                       */
 
-#ifdef NCBI_OS_MSWIN
 	WSAEVENT         event;     /* event bound to I/O                        */
-#endif /*NCBI_OS_MSWIN*/
+#endif /*!NCBI_OS_MSWIN*/
 
     void*            context;   /* per-server credentials                    */
 
@@ -252,20 +256,18 @@ typedef struct SOCK_tag {
     EBIO_Status     w_status:3; /* write status:  eIO_Closed if was shut down*/
     unsigned/*bool*/ pending:1; /* =1 if connection is still initing         */
 
+    unsigned       crossexec:1; /* =1 if close-on-exec must NOT be set       */
     unsigned       connected:1; /* =1 if remote end-point is fully connected */
-#ifdef NCBI_OS_MSWIN
+#ifndef NCBI_OS_MSWIN
+    unsigned        reserved:6; /* MBZ                                       */
+#else
+    unsigned        reserved:3; /* MBZ                                       */
     unsigned        readable:1; /* =1 if known to be readable                */
-    unsigned        closeing:1; /* =1 if FD_CLOSE posted (as ugly as spelled)*/
     unsigned        writable:1; /* =1 if known to be writeable               */
-    unsigned        reserved:4; /* MBZ                                       */
-#else
-    unsigned        reserved:6; /* MBZ                                       */
-    unsigned       crossexec:1; /* =1 if close-on-exec must NOT be set       */
-#endif /*NCBI_OS_MSWIN*/
+    unsigned         closing:1; /* =1 if FD_CLOSE posted                     */
 
-#ifdef NCBI_OS_MSWIN
 	WSAEVENT         event;     /* event bound to I/O                        */
-#endif /*NCBI_OS_MSWIN*/
+#endif /*!NCBI_OS_MSWIN*/
 
     void*            session;   /* secure session id if secure, else 0       */
 
@@ -330,4 +332,9 @@ typedef struct SOCK_tag {
  */
 
 
+#if defined(NCBI_OS_MSWIN)  &&  defined(_WIN64)
+#  pragma pack(pop)
+#endif /*NCBI_OS_MSWIN && _WIN64*/
+
+
 #endif /* CONNECT___NCBI_SOCKETP__H */
diff --git a/connect/ncbi_types.h b/connect/ncbi_types.h
index 6e050e6..0986aaa 100644
--- a/connect/ncbi_types.h
+++ b/connect/ncbi_types.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_TYPES__H
 #define CONNECT___NCBI_TYPES__H
 
-/*  $Id: ncbi_types.h,v 6.15 2008/07/21 16:55:48 kazimird Exp $
+/* $Id: ncbi_types.h,v 6.16 2009/11/10 15:54:40 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -63,8 +63,10 @@ extern "C" {
 
 
 /** Timeout structure
+ *
+ * @sa CTimeout, g_CTimeoutToSTimeout, g_STimeoutToCTimeout
  */
-typedef struct {
+typedef struct STimeoutTag {
     unsigned int sec;  /**< seconds (truncated to the platf.-dep. max. limit)*/
     unsigned int usec; /**< microseconds (always truncated by mod. 1,000,000)*/
 } STimeout;
diff --git a/connect/ncbi_util.c b/connect/ncbi_util.c
index aadbc66..9f6efd8 100644
--- a/connect/ncbi_util.c
+++ b/connect/ncbi_util.c
@@ -1,4 +1,4 @@
-/* $Id: ncbi_util.c,v 6.59 2009/02/06 16:14:36 kazimird Exp $
+/* $Id: ncbi_util.c,v 6.64 2010/05/29 01:14:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -322,7 +322,7 @@ extern const char* NcbiMessagePlusError
         if (*dynamic  &&  message)
             free((void*) message);
         *dynamic = 0;
-        return "<Ouch! Out of memory>";
+        return "Ouch! Out of memory";
     }
 
     if (message) {
@@ -429,7 +429,8 @@ extern char* LOG_ComposeMessage
 
     if (call_data->raw_size) {
         data_len = (sizeof(kRawData_Begin) + 20
-                    + UTIL_PrintableStringSize(call_data->raw_data,
+                    + UTIL_PrintableStringSize((const char*)
+                                               call_data->raw_data,
                                                call_data->raw_size) +
                     sizeof(kRawData_End));
     }
@@ -474,7 +475,8 @@ extern char* LOG_ComposeMessage
                      (unsigned long) call_data->raw_size,
                      &"s"[call_data->raw_size == 1]);
 
-        s = UTIL_PrintableString(call_data->raw_data,
+        s = UTIL_PrintableString((const char*)
+                                 call_data->raw_data,
                                  call_data->raw_size,
                                  s, format_flags & fLOG_FullOctal);
 
@@ -615,7 +617,7 @@ extern const char* CORE_GetUsername(char* buf, size_t bufsize)
     struct passwd* pw;
 #  if !defined(NCBI_OS_SOLARIS)  &&  defined(NCBI_HAVE_GETPWUID_R)
     struct passwd pwd;
-    char pwdbuf[256];
+    char pwdbuf[1024];
 #  endif
 #elif defined(NCBI_OS_MSWIN)
     char  loginbuf[256 + 1];
@@ -670,12 +672,16 @@ extern const char* CORE_GetUsername(char* buf, size_t bufsize)
 #  ifndef NCBI_OS_SOLARIS
     CORE_LOCK_WRITE;
 #  endif
-    if ((pw = getpwuid(getuid())) != 0  &&  pw->pw_name)
+    if ((pw = getpwuid(getuid())) != 0) {
+        if (pw->pw_name)
         strncpy0(buf, pw->pw_name, bufsize - 1);
+        else
+            pw = 0;
+    }
 #  ifndef NCBI_OS_SOLARIS
     CORE_UNLOCK;
 #  endif
-    if (pw  &&  pw->pw_name)
+    if (pw)
         return buf;
 #  elif defined(NCBI_HAVE_GETPWUID_R)
 #    if   NCBI_HAVE_GETPWUID_R == 4
@@ -857,26 +863,77 @@ static void s_CRC32_Init(void)
 #endif /*NCBI_USE_PRECOMPILED_CRC32_TABLES*/
 
 
-extern unsigned int CRC32_Update(unsigned int checksum,
-                                 const void *ptr, size_t count)
+extern unsigned int UTIL_CRC32_Update(unsigned int checksum,
+                                      const void *ptr, size_t len)
 {
-    size_t j;
-    const char* str = (const char*) ptr;
+    const unsigned char* data = (const unsigned char*) ptr;
+    size_t i;
 
 #ifndef NCBI_USE_PRECOMPILED_CRC32_TABLES
     s_CRC32_Init();
 #endif /*NCBI_USE_PRECOMPILED_CRC32_TABLES*/
 
-    for (j = 0;  j < count;  j++) {
-        size_t i = ((checksum >> 24) ^ *str++) & 0xFF;
+    for (i = 0;  i < len;  i++) {
+        size_t k = ((checksum >> 24) ^ *data++) & 0xFF;
         checksum <<= 8;
-        checksum  ^= s_CRC32Table[i];
+        checksum  ^= s_CRC32Table[k];
     }
 
     return checksum;
 }
 
 
+#define MOD_ADLER          65521
+#define MAXLEN_ADLER       5548  /* max len to run without overflows */
+#define ADJUST_ADLER(a)    a = (a & 0xFFFF) + (a >> 16) * (0x10000 - MOD_ADLER)
+#define FINALIZE_ADLER(a)  if (a >= MOD_ADLER) a -= MOD_ADLER
+
+unsigned int UTIL_Adler32_Update(unsigned int checksum,
+                                 const void* ptr, size_t len)
+{
+    const unsigned char* data = (const unsigned char*) ptr;
+    unsigned int a = checksum & 0xFFFF, b = checksum >> 16;
+
+    while (len) {
+        size_t i;
+        if (len >= MAXLEN_ADLER) {
+            len -= MAXLEN_ADLER;
+            for (i = 0;  i < MAXLEN_ADLER/4;  ++i) {
+                b += a += data[0];
+                b += a += data[1];
+                b += a += data[2];
+                b += a += data[3];
+                data += 4;
+            }
+        } else {
+            for (i = len >> 2;  i;  --i) {
+                b += a += data[0];
+                b += a += data[1];
+                b += a += data[2];
+                b += a += data[3];
+                data += 4;
+            }
+            for (len &= 3;  len;  --len) {
+                b += a += *data++;
+            }
+        }
+        ADJUST_ADLER(a);
+        ADJUST_ADLER(b);
+    }
+    /* It can be shown that a <= 0x1013A here, so a single subtract will do. */
+    FINALIZE_ADLER(a);
+    /* It can be shown that b can reach 0xFFEF1 here. */
+    ADJUST_ADLER(b);
+    FINALIZE_ADLER(b);
+    return (b << 16) | a;
+}
+
+#undef MOD_ADLER
+#undef MAXLEN_ADLER
+#undef ADJUST_ADLER
+#undef FINALIZE_ADLER
+
+
 
 /******************************************************************************
  *  MISCELLANEOUS
@@ -929,10 +986,10 @@ extern char* UTIL_NcbiLocalHostName(char* hostname)
 {
     static const struct {
         const char* text;
-        size_t      len;
+        const size_t len;
     } kEndings[] = {
-        { ".ncbi.nlm.nih.gov", 17},
-        { ".ncbi.nih.gov", 13}
+        {".ncbi.nlm.nih.gov", 17},
+        {".ncbi.nih.gov",     13}
     };
     size_t len = hostname ? strlen(hostname) : 0;
 
diff --git a/connect/ncbi_util.h b/connect/ncbi_util.h
index e743006..ebdb1bf 100644
--- a/connect/ncbi_util.h
+++ b/connect/ncbi_util.h
@@ -1,7 +1,7 @@
 #ifndef CONNECT___NCBI_UTIL__H
 #define CONNECT___NCBI_UTIL__H
 
-/* $Id: ncbi_util.h,v 6.38 2008/12/01 16:34:35 kazimird Exp $
+/* $Id: ncbi_util.h,v 6.39 2010/02/04 15:17:12 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -50,8 +50,9 @@
  *       CORE_GetUsername()
  *       CORE_GetVMPageSize()
  *
- * 3. CRC32 support:
- *       CRC32_Update()
+ * 3. Checksumming support:
+ *       UTIL_CRC32_Update()
+ *       UTIL_Adler32_Update()
  *
  * 4. Miscellaneous:
  *       UTIL_MatchesMask[Ex]()
@@ -305,7 +306,7 @@ extern NCBI_XCONNECT_EXPORT void LOG_ToFILE
  *  LOG_ComposeMessage
  */
 extern NCBI_XCONNECT_EXPORT const char* NcbiMessagePlusError
-(int*/*bool*/ dynamic,
+(int/*bool*/ *dynamic,
  const char*  message,
  int          error,
  const char*  descr
@@ -414,23 +415,45 @@ extern NCBI_XCONNECT_EXPORT size_t CORE_GetVMPageSize(void);
  *  CRC32
  */
 
-/** Calculate/Update CRC32
+/** Calculate/Update CRC-32 checksum
+ * NB:  Initial checksum is "0".
  * @param checksum
  *  Checksum to update (start with 0)
  * @param ptr
  *  Block of data
- * @param count
- *  Size of data
+ * @param len
+ *  Size of block of data
  * @return
  *  Return the checksum updated according to the contents of the block
- *  pointed to by "ptr" and having "count" bytes in it.
+ *  pointed to by "ptr" and having "len" bytes in it.
  */
-extern NCBI_XCONNECT_EXPORT unsigned int CRC32_Update
+extern NCBI_XCONNECT_EXPORT unsigned int UTIL_CRC32_Update
 (unsigned int checksum,
  const void*  ptr,
- size_t       count
+ size_t       len
  );
 
+/* FIXME: Compatibility (to remove in the future) */
+#define CRC32_Update(c, p, l)  UTIL_CRC32_Update(c, p, l)
+
+
+/** Calculate/Update Adler-32 checksum
+ * NB:  Initial checksum is "1".
+ * @param checksum
+ *  Checksum to update (start with 1)
+ * @param ptr
+ *  Block of data
+ * @param len
+ *  Size of block of data
+ * @return
+ *  Return the checksum updated according to the contents of the block
+ *  pointed to by "ptr" and having "len" bytes in it.
+ */
+extern NCBI_XCONNECT_EXPORT unsigned int UTIL_Adler32_Update
+(unsigned int checksum,
+ const void*  ptr,
+ size_t       len
+ );
 
 
 /******************************************************************************
diff --git a/connect/ncbi_version.c b/connect/ncbi_version.c
new file mode 100644
index 0000000..d6464c2
--- /dev/null
+++ b/connect/ncbi_version.c
@@ -0,0 +1,61 @@
+/* $Id: ncbi_version.c,v 1.1 2010/04/13 16:56:49 lavr Exp $
+ * ==========================================================================
+ *
+ *                            PUBLIC DOMAIN NOTICE
+ *            National Center for Biotechnology Information (NCBI)
+ *
+ *  This software/database is a "United States Government Work" under the
+ *  terms of the United States Copyright Act.  It was written as part of
+ *  the author's official duties as a United States Government employee and
+ *  thus cannot be copyrighted.  This software/database is freely available
+ *  to the public for use. The National Library of Medicine and the U.S.
+ *  Government do not place any restriction on its use or reproduction.
+ *  We would, however, appreciate having the NCBI and the author cited in
+ *  any work or product based on this material
+ *
+ *  Although all reasonable efforts have been taken to ensure the accuracy
+ *  and reliability of the software and data, the NLM and the U.S.
+ *  Government do not and cannot warrant the performance or results that
+ *  may be obtained by using this software or data. The NLM and the U.S.
+ *  Government disclaim all warranties, express or implied, including
+ *  warranties of performance, merchantability or fitness for any particular
+ *  purpose.
+ *
+ * ==========================================================================
+ *
+ * Author:  Anton Lavrentiev
+ *
+ * File Description:
+ *   Versioning
+ *
+ */
+
+#include "ncbi_version.h"
+#include <string.h>
+
+
+/*ARGSUSED*/
+const char* g_VersionStr(const char* rev)
+{
+#ifndef NCBI_PACKAGE
+    static const char* s_Version = 0;
+    if (!s_Version) {
+        if (rev  &&  *rev) {
+            static char buf[80];
+            const char* s = rev + (*rev == '$' ? strcspn(rev, " \t") : 0);
+            size_t len = strspn(s += strspn(s, " \t"), "0123456789");
+            const char* t = NETDAEMONS_VERSION;
+            if (len  &&  len + strlen(t += strcspn(t, "/[")) < sizeof(buf)) {
+                memcpy(buf,       s, len);
+                strcpy(buf + len, t);
+                s_Version = buf;
+                return s_Version;
+            }
+        }
+        s_Version = NETDAEMONS_VERSION;
+    }
+    return s_Version;
+#else
+    return NETDAEMONS_VERSION;
+#endif /*!NCBI_PACKAGE*/
+}
diff --git a/connect/version.h b/connect/ncbi_version.h
similarity index 62%
rename from connect/version.h
rename to connect/ncbi_version.h
index 0f0b7f5..61ea5eb 100644
--- a/connect/version.h
+++ b/connect/ncbi_version.h
@@ -1,7 +1,7 @@
-#ifndef CONNECT_DAEMONS___VERSION__H
-#define CONNECT_DAEMONS___VERSION__H
+#ifndef CONNECT___NCBI_VERSION__H
+#define CONNECT___NCBI_VERSION__H
 
-/* $Id: version.h,v 1.2 2009/02/05 14:54:29 kazimird Exp $
+/* $Id: ncbi_version.h,v 1.3 2010/06/02 18:39:41 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -31,14 +31,16 @@
  * File Description:
  *   Daemon collection version number
  *
- *   UNIX only !!!
- *
  */
 
+#include <connect/connect_export.h>
+#include "ncbi_config.h"
+
 #ifdef   NCBI_CXX_TOOLKIT
 #  include <common/ncbi_package_ver.h>
 #endif /*NCBI_CXX_TOOLKIT*/
 
+
 #ifdef NCBI_PACKAGE
 
 #  define   NETDAEMONS_MAJOR        NCBI_PACKAGE_VERSION_MAJOR
@@ -51,7 +53,7 @@
 
 #  define   NETDAEMONS_MAJOR        2
 #  define   NETDAEMONS_MINOR        0
-#  define   NETDAEMONS_PATCH        1
+#  define   NETDAEMONS_PATCH        2
 
 #  ifdef NCBI_CXX_TOOLKIT
 #    define NETDAEMONS_VERSION_STR  NCBI_PACKAGE_VERSION_COMPOSE_STR    \
@@ -71,6 +73,7 @@
 
 #endif /*NCBI_PACKAGE*/
 
+
 #define   NETDAEMONS_VERSION_OF(ma, mi, pa)  ((unsigned int)              \
                                               ((ma)*100000 + (mi)*1000 + (pa)))
 
@@ -83,4 +86,41 @@
                                     NETDAEMONS_MINOR,                   \
                                     NETDAEMONS_PATCH)
 
-#endif /*CONNECT_DAEMONS___VERSION__H*/
+
+#ifdef NCBI_CXX_TOOLKIT
+
+#  if !defined(NDEBUG)  ||  defined(_DEBUG)
+#    if NCBI_PLATFORM_BITS == 64
+#      define NETDAEMONS_VERSION    NETDAEMONS_VERSION_STR "/64[DEBUG]"
+#    else
+#      define NETDAEMONS_VERSION    NETDAEMONS_VERSION_STR "[DEBUG]"
+#    endif /*NCBI_PLATFORM_BITS==64*/
+#  else
+#    if NCBI_PLATFORM_BITS == 64
+#      define NETDAEMONS_VERSION    NETDAEMONS_VERSION_STR "/64"
+#    else
+#      define NETDAEMONS_VERSION    NETDAEMONS_VERSION_STR
+#    endif /*NCBI_PLATFORM_BITS==64*/
+#  endif /*!NDEBUG || _DEBUG*/
+
+#else
+
+#  define NETDAEMONS_VERSION        NETDAEMONS_VERSION_STR
+
+#endif /*NCBI_CXX_TOOLKIT*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern NCBI_XCONNECT_EXPORT
+const char* g_VersionStr(const char* revision);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /*CONNECT___NCBI_VERSION__H*/
diff --git a/connect/test/http_connector_hit.c b/connect/test/http_connector_hit.c
index b4625f8..c3585c2 100644
--- a/connect/test/http_connector_hit.c
+++ b/connect/test/http_connector_hit.c
@@ -1,4 +1,4 @@
-/*  $Id: http_connector_hit.c,v 6.16 2005/04/20 18:23:11 lavr Exp $
+/* $Id: http_connector_hit.c,v 6.19 2010/02/03 19:04:42 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,10 +30,9 @@
  *
  */
 
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_assert.h"
 #include <connect/ncbi_http_connector.h>
-#include <connect/ncbi_util.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 /* This header must go last */
 #include "test_assert.h"
 
@@ -102,7 +101,6 @@ int main(int argc, const char* argv[])
     char   buffer[100];
     size_t n_read, n_written;
 
-
     /* Prepare to connect:  parse and check cmd.-line args, etc. */
     s_Args.host         = (argc > 1) ? argv[1] : "";
     s_Args.port         = (argc > 2) ? argv[2] : "";
@@ -116,12 +114,14 @@ int main(int argc, const char* argv[])
             "  URL args:        '%s'\n"
             "  Input data file: '%s'\n"
             "  User header:     '%s'\n"
-            " Reply(if any) from the hit URL goes to the standard output.\n\n",
+            "Reply(if any) from the hit URL goes to the standard output.\n\n",
             argv[0],
             s_Args.host, s_Args.port, s_Args.path, s_Args.args,
             inp_file, user_header);
 
     /* Log stream */
+    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
+                           fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
 
     /* Tune to the test URL using hard-coded pseudo-registry */
@@ -146,12 +146,25 @@ int main(int argc, const char* argv[])
     /* If the input file is specified,
      * then send its content (as the HTTP request body) to URL
      */
-    if ( *inp_file ) {
-        FILE* inp_fp = fopen(inp_file, "rb");
-        if ( !inp_fp ) {
-            fprintf(stderr, "Cannot open file '%s' for read", inp_file);
+    if (*inp_file) {
+        FILE* inp_fp;
+
+        if (strcmp(inp_file, "-") != 0) {
+            static const char kDevNull[] =
+#ifdef NCBI_OS_MSWIN
+                "NUL"
+#else
+                "/dev/null"
+#endif /*NCBI_OS_MSWIN*/
+                ;
+            if (strcmp(inp_file, "+") == 0)
+                inp_file = kDevNull;
+            if (!(inp_fp = fopen(inp_file, "rb"))) {
+                fprintf(stderr, "Cannot open file '%s' for reading", inp_file);
             assert(0);
         }
+        } else
+            inp_fp = stdin;
 
         for (;;) {
             n_read = fread(buffer, 1, sizeof(buffer), inp_fp);
@@ -173,16 +186,20 @@ int main(int argc, const char* argv[])
     }
 
     /* Read reply from connection, write it to standard output */
-    fprintf(stdout, "\n\n----- [BEGIN] HTTP Content -----\n");
     for (;;) {
         status = CONN_Read(conn,buffer,sizeof(buffer),&n_read,eIO_ReadPlain);
         if (status != eIO_Success)
             break;
-
+        if (connector)
+            puts("----- [BEGIN] HTTP Content -----");
         fwrite(buffer, 1, n_read, stdout);
         fflush(stdout);
+        connector = 0;
+    }
+    if (!connector) {
+        puts("\n----- [END] HTTP Content -----");
+        fclose(stdout);
     }
-    fprintf(stdout, "\n----- [END] HTTP Content -----\n\n");
 
     if (status != eIO_Closed) {
         fprintf(stderr, "Error reading from URL (%s)", IO_StatusStr(status));
@@ -192,61 +209,7 @@ int main(int argc, const char* argv[])
     /* Success:  close the connection, cleanup, and exit */
     CONN_Close(conn);
     CORE_SetREG(0);
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
-
-
-/*
- * --------------------------------------------------------------------------
- * $Log: http_connector_hit.c,v $
- * Revision 6.16  2005/04/20 18:23:11  lavr
- * +"../ncbi_assert.h"
- *
- * Revision 6.15  2004/11/23 15:04:26  lavr
- * Use public bounce.cgi from "www"
- *
- * Revision 6.14  2004/11/22 20:24:53  lavr
- * "yar" replaced with "graceland"
- *
- * Revision 6.13  2004/04/01 14:14:02  lavr
- * Spell "occurred", "occurrence", and "occurring"
- *
- * Revision 6.12  2004/02/23 15:23:42  lavr
- * New (last) parameter "how" added in CONN_Write() API call
- *
- * Revision 6.11  2003/04/15 14:06:09  lavr
- * Changed ray.nlm.nih.gov -> ray.ncbi.nlm.nih.gov
- *
- * Revision 6.10  2002/11/22 15:09:40  lavr
- * Replace all occurrences of "ray" with "yar"
- *
- * Revision 6.9  2002/10/28 15:47:12  lavr
- * Use "ncbi_ansi_ext.h" privately and use strncpy0()
- *
- * Revision 6.8  2002/08/07 16:38:08  lavr
- * EIO_ReadMethod enums changed accordingly; log moved to end
- *
- * Revision 6.7  2002/03/22 19:45:55  lavr
- * Test_assert.h made last among the include files
- *
- * Revision 6.6  2002/01/16 21:23:14  vakatov
- * Utilize header "test_assert.h" to switch on ASSERTs in the Release mode too
- *
- * Revision 6.5  2001/01/11 16:42:45  lavr
- * Registry Get/Set methods got the 'user_data' argument, forgotten earlier
- *
- * Revision 6.4  2000/11/15 17:27:29  vakatov
- * Fixed path to the test CGI application.
- *
- * Revision 6.3  2000/09/27 16:00:24  lavr
- * Registry entries adjusted
- *
- * Revision 6.2  2000/05/30 23:24:40  vakatov
- * Cosmetic fix for the C++ compilation
- *
- * Revision 6.1  2000/04/21 19:56:28  vakatov
- * Initial revision
- *
- * ==========================================================================
- */
diff --git a/connect/test/ncbi_conntest.c b/connect/test/ncbi_conntest.c
index 9e943fa..3dbf1af 100644
--- a/connect/test/ncbi_conntest.c
+++ b/connect/test/ncbi_conntest.c
@@ -1,4 +1,4 @@
-/*  $Id: ncbi_conntest.c,v 6.11 2007/04/17 11:25:54 kazimird Exp $
+/* $Id: ncbi_conntest.c,v 6.16 2010/02/05 20:35:04 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -31,9 +31,9 @@
  *
  */
 
-#include "ncbi_conntest.h"
-#include "../ncbi_priv.h"
 #include <connect/ncbi_connection.h>
+#include "../ncbi_priv.h"               /* CORE logging facilities */
+#include "ncbi_conntest.h"
 #include <string.h>
 /* This header must go last */
 #include "test_assert.h"
@@ -62,6 +62,7 @@ static void s_SingleBouncePrint
 {
     static const char write_str[] = "This is a s_*BouncePrint test string.\n";
     size_t     n_written, n_read;
+    char       message[128];
     char       buf[8192];
     EIO_Status status;
 
@@ -70,14 +71,18 @@ static void s_SingleBouncePrint
     /* WRITE */
     status = CONN_Write(conn, write_str, strlen(write_str),
                         &n_written, eIO_WritePersist);
-    if (status != eIO_Success  ||  n_written != strlen(write_str))
-        TEST_LOG(status, "[s_SingleBouncePrint] Write failed!");
+    if (status != eIO_Success  ||  n_written != strlen(write_str)) {
+        TEST_LOG(status,
+                 "[s_SingleBouncePrint]  CONN_Write(persistent) failed");
+    }
     assert(n_written == strlen(write_str));
     assert(status == eIO_Success);
 
     /* READ the "bounced" data from the connection */
     status = CONN_Read(conn, buf, sizeof(buf) - 1, &n_read, eIO_ReadPersist);
-    TEST_LOG(status, "[s_SingleBouncePrint] after READ");
+    sprintf(message, "[s_SingleBouncePrint]  CONN_Read(persistent)"
+            " %lu byte%s read", (unsigned long) n_read, &"s"[n_read == 1]);
+    TEST_LOG(status, message);
 
     /* Printout to data file, if any */
     if (data_file  &&  n_read) {
@@ -91,6 +96,8 @@ static void s_SingleBouncePrint
     assert(n_read >= n_written);
     buf[n_read] = '\0';
     assert(strstr(buf, write_str));
+
+    TEST_LOG(eIO_Success, "[s_SingleBouncePrint]  ...finished");
 }
 
 
@@ -123,10 +130,11 @@ static void s_SingleBounceCheck
  const STimeout* timeout,
  FILE*           data_file)
 {
-    EIO_Status status;
     static const char sym[] = {
         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
     };
+    EIO_Status status;
+    char message[128];
 
 #define TEST_N_LINES 200
 #define TEST_BUF_SIZE (TEST_N_LINES * (TEST_N_LINES + 3) / 2)
@@ -134,7 +142,6 @@ static void s_SingleBounceCheck
 
     TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  Starting...");
 
-
     /* WRITE to the connection:  "0\n12\n345\n6789\n01234\n........"
      */
     {{
@@ -158,7 +165,9 @@ static void s_SingleBounceCheck
                 if (n_write % 5 == 3) {
                     status = CONN_Wait(conn, eIO_Write, timeout);
                     if (status != eIO_Success) {
-                        TEST_LOG(status, "The pre-WRITE CONN_Wait failed");
+                        TEST_LOG(status,
+                                 "[s_SingleBounceCheck]  CONN_Wait(write)"
+                                 " failed, retrying...");
                         assert(status == eIO_Timeout);
                     }
                 }
@@ -167,11 +176,12 @@ static void s_SingleBounceCheck
                 status = CONN_Write(conn, buf, n_write,
                                     &n_written, eIO_WritePersist);
                 if (status != eIO_Success) {
-                    TEST_LOG(status, "Write failed. Retrying...");
+                    TEST_LOG(status,
+                             "[s_SingleBounceCheck]  CONN_Write(persistent)"
+                             " failed, retrying...");
                     assert(n_written < n_write);
                     assert(status == eIO_Timeout);
-                }
-                else {
+                } else {
                     assert(n_written == n_write);
                 }
             } while (status != eIO_Success);
@@ -192,21 +202,32 @@ static void s_SingleBounceCheck
         n_to_read = TEST_BUF_SIZE/3;
 
         do {
+            TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  1/3 PEEK...");
             status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPeek);
             if (status != eIO_Success) {
-                TEST_LOG(status, "The 1/3 PEEK failed. Retrying...");
+                TEST_LOG(status,
+                         "[s_SingleBounceCheck]  1/3 CONN_Read(peek)"
+                         " failed, retrying...");
                 assert(n_read < n_to_read);
                 assert(status == eIO_Timeout);
             }
             if (n_read < n_to_read) {
-                TEST_LOG(status, "Not all of the expected data is peeked yet."
-                         " Continue...");
+                sprintf(message, "[s_SingleBounceCheck]  1/3 CONN_Read(peek)"
+                        " %lu byte%s peeked out of %lu byte%s, continuing...",
+                        (unsigned long) n_read,    &"s"[n_read    == 1],
+                        (unsigned long) n_to_read, &"s"[n_to_read == 1]);
+                TEST_LOG(status, message);
             }
         } while (n_read != n_to_read);
 
         /* READ 1st 1/3 of "bounced" data, compare it with the PEEKed data */
+        TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  1/3 READ...");
         status = CONN_Read(conn, x_buf + n_to_read, n_to_read, &n_read,
                            eIO_ReadPlain);
+        if (status != eIO_Success) {
+            TEST_LOG(status,
+                     "[s_SingleBounceCheck]  1/3 CONN_Read(plain) failed");
+        }
         assert(status == eIO_Success);
         assert(n_read == n_to_read);
         assert(memcmp(x_buf, x_buf + n_to_read, n_to_read) == 0);
@@ -215,7 +236,8 @@ static void s_SingleBounceCheck
         /* WAIT on read */
         status = CONN_Wait(conn, eIO_Read, timeout);
         if (status != eIO_Success) {
-            TEST_LOG(status, "The 2/3 pre-READ CONN_Wait failed");
+            TEST_LOG(status,
+                     "[s_SingleBounceCheck]  CONN_Wait(read) failed");
             assert(status == eIO_Timeout);
         }
 
@@ -224,10 +246,14 @@ static void s_SingleBounceCheck
         n_to_read = TEST_BUF_SIZE/3;
 
         while ( n_to_read ) {
-            TEST_LOG(status, "2/3 READ...");
+            TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  2/3 READ...");
             status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPlain);
             if (status != eIO_Success) {
-                TEST_LOG(status, "The 2/3 READ failed. Retrying...");
+                sprintf(message, "[s_SingleBounceCheck]  2/3 CONN_Read(plain)"
+                        " %lu byte%s read out of %lu byte%s, retrying...",
+                        (unsigned long) n_read,    &"s"[n_read    == 1],
+                        (unsigned long) n_to_read, &"s"[n_to_read == 1]);
+                TEST_LOG(status, message);
                 assert(n_read < n_to_read);
                 assert(status == eIO_Timeout);
             } else {
@@ -241,9 +267,13 @@ static void s_SingleBounceCheck
         /* Persistently READ the 3rd 1/3 of "bounced" data */
         n_to_read = TEST_BUF_SIZE - (x_buf - buf);
 
+        TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  3/3 READ...");
         status = CONN_Read(conn, x_buf, n_to_read, &n_read, eIO_ReadPersist);
         if (status != eIO_Success) {
-            TEST_LOG(status, "The 3/3 (persistent) READ failed!");
+            sprintf(message, "[s_SingleBounceCheck]  3/3 CONN_Read(persistent)"
+                    " %lu byte%s read",
+                    (unsigned long) n_read, &"s"[n_read == 1]);
+            TEST_LOG(status, message);
             assert(n_read < n_to_read);
             assert(0);
         } else {
@@ -271,18 +301,19 @@ static void s_SingleBounceCheck
     /* Now when the "bounced" data is read and tested, READ an arbitrary extra
      * data sent in by the peer and print it out to LOG file
      */
-    if ( !data_file )
-        return;
-
+    if ( data_file ) {
     fprintf(data_file, "\ns_SingleBounceCheck(BEGIN EXTRA DATA)\n");
     fflush(data_file);
     for (;;) {
-        size_t n_read;
+            size_t n;
 
-        status = CONN_Read(conn, buf, sizeof(buf), &n_read, eIO_ReadPersist);
-        TEST_LOG(status, "s_SingleBounceCheck(The extra data READ...)");
-        if ( n_read ) {
-            assert(fwrite(buf, n_read, 1, data_file) == 1);
+            TEST_LOG(eIO_Success,
+                     "[s_SingleBounceCheck]  EXTRA READ...");
+            status = CONN_Read(conn, buf, sizeof(buf), &n, eIO_ReadPersist);
+            TEST_LOG(status,
+                     "[s_SingleBounceCheck]  EXTRA CONN_Read(persistent)");
+            if ( n ) {
+                assert(fwrite(buf, n, 1, data_file) == 1);
             fflush(data_file);
         }
         if (status == eIO_Closed  ||  status == eIO_Timeout)
@@ -292,6 +323,9 @@ static void s_SingleBounceCheck
     }
     fprintf(data_file, "\ns_SingleBounceCheck(END EXTRA DATA)\n\n");
     fflush(data_file);
+    }
+
+    TEST_LOG(eIO_Success, "[s_SingleBounceCheck]  ...finished");
 }
 
 
@@ -318,26 +352,23 @@ extern void CONN_TestConnector
      */
     assert(CONN_Create(connector, &conn) == eIO_Success);
 
-    CONN_SetTimeout(conn, eIO_Open,      timeout);
-    CONN_SetTimeout(conn, eIO_Read,      timeout);
-    CONN_SetTimeout(conn, eIO_ReadWrite, timeout);
-    CONN_SetTimeout(conn, eIO_Close,     timeout);
+    assert(CONN_SetTimeout(conn, eIO_Open,      timeout) == eIO_Success);
+    assert(CONN_SetTimeout(conn, eIO_ReadWrite, timeout) == eIO_Success);
+    assert(CONN_SetTimeout(conn, eIO_Close,     timeout) == eIO_Success);
 
     assert(CONN_ReInit(conn, connector) == eIO_Success);
 
-    CONN_SetTimeout(conn, eIO_Write, timeout);
-
     status = CONN_Wait(conn, eIO_Write, timeout);
     if (status != eIO_Success) {
-        TEST_LOG(status, "First CONN_Wait failed");
+        TEST_LOG(status, "[CONN_TestConnector]  CONN_Wait(write) failed");
         assert(status == eIO_Timeout);
     }
 
     /* Run the specified TESTs
      */
-    if ( !flags )
+    if ( !flags ) {
         flags = fTC_Everything;
-
+    }
     if (flags & fTC_SingleBouncePrint) {
         s_SingleBouncePrint(conn, data_file);
     }
@@ -352,5 +383,5 @@ extern void CONN_TestConnector
      */
     assert(CONN_Close(conn) == eIO_Success);
 
-    TEST_LOG(status, "Test completed successfully");
+    TEST_LOG(eIO_Success, "[CONN_TestConnector]  Completed");
 }
diff --git a/connect/test/socket_io_bouncer.c b/connect/test/socket_io_bouncer.c
index b0ee4d5..cc2769d 100644
--- a/connect/test/socket_io_bouncer.c
+++ b/connect/test/socket_io_bouncer.c
@@ -1,4 +1,4 @@
-/*  $Id: socket_io_bouncer.c,v 6.11 2009/04/10 23:04:30 kazimird Exp $
+/* $Id: socket_io_bouncer.c,v 6.16 2010/06/10 19:19:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -31,12 +31,10 @@
  *
  */
 
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_assert.h"
 #include <connect/ncbi_connutil.h>
-#include <connect/ncbi_socket.h>
 #include <connect/ncbi_util.h>
-#include <stdio.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_assert.h"
 /* This header must go last */
 #include "test_assert.h"
 
diff --git a/connect/test/test_assert.h b/connect/test/test_assert.h
index 230de2b..d514710 100644
--- a/connect/test/test_assert.h
+++ b/connect/test/test_assert.h
@@ -1,7 +1,7 @@
 #ifndef TEST_ASSERT__H
 #define TEST_ASSERT__H
 
-/*  $Id: test_assert.h,v 6.28 2006/03/07 19:55:43 lavr Exp $
+/* $Id: test_assert.h,v 6.31 2010/05/22 22:29:49 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
diff --git a/connect/test/test_assert_impl.h b/connect/test/test_assert_impl.h
index ec301e6..c2ec1a6 100644
--- a/connect/test/test_assert_impl.h
+++ b/connect/test/test_assert_impl.h
@@ -1,7 +1,7 @@
-#ifndef TEST_ASSERT_IMPL__H
-#define TEST_ASSERT_IMPL__H
+#ifndef COMMON__TEST_ASSERT_IMPL__H
+#define COMMON__TEST_ASSERT_IMPL__H
 
-/*  $Id: test_assert_impl.h,v 1.3 2009/01/22 17:59:35 kazimird Exp $
+/* $Id: test_assert_impl.h,v 1.6 2009/09/21 16:24:42 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -39,14 +39,18 @@
 #endif /*TEST_ASSERT__H*/
 
 #if defined(NCBI_OS_MSWIN)
+#  ifndef NCBI_MSWIN_NO_POPUP
 #  ifdef   _ASSERT
 #    undef _ASSERT
 #  endif
 #  define  Type aType
+#  endif
 #  include <crtdbg.h>
 #  include <stdio.h>
 #  include <windows.h>
+#  ifndef NCBI_MSWIN_NO_POPUP
 #  undef   Type
+#  endif
 
 /* Suppress popup messages on execution errors.
  * NOTE: Windows-specific, suppresses all error message boxes in both runtime
@@ -63,9 +67,11 @@ static LONG CALLBACK _SEH_Handler(EXCEPTION_POINTERS* ep)
 
 static int _SuppressDiagPopupMessages(void)
 {
+#ifndef NCBI_MSWIN_NO_POPUP_EVER
     /* Check environment variable for silent abort app at error */
     const char* value = getenv("DIAG_SILENT_ABORT");
     if (value  &&  (*value == 'Y'  ||  *value == 'y')) {
+#endif
         /* Windows GPF errors */
         SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
                      SEM_NOOPENFILEERRORBOX);
@@ -83,7 +89,9 @@ static int _SuppressDiagPopupMessages(void)
 
         /* Exceptions */
         SetUnhandledExceptionFilter(_SEH_Handler);
+#ifndef NCBI_MSWIN_NO_POPUP_EVER
     }
+#endif
     return 0;
 }
 
@@ -91,7 +99,7 @@ static int _SuppressDiagPopupMessages(void)
  * base RTL init, which happens at preceding levels in alphabetical order.
  */
 #  if _MSC_VER >= 1400
-#    pragma section( ".CRT$XIV", read)
+#    pragma section(".CRT$XIV", read)
 #  endif
 #  pragma data_seg(".CRT$XIV")
 static int (*_SDPM)(void) = _SuppressDiagPopupMessages;
@@ -100,6 +108,10 @@ static int (*_SDPM)(void) = _SuppressDiagPopupMessages;
 #endif /*defined(NCBI_OS_...)*/
 
 
+/* Emulate <corelib/mswin_no_popup.h> if specified
+ */
+#ifndef NCBI_MSWIN_NO_POPUP
+
 #ifdef   NDEBUG
 #  undef NDEBUG
 #endif
@@ -134,9 +146,12 @@ static int (*_SDPM)(void) = _SuppressDiagPopupMessages;
 #  undef _ASSERT
 #endif
 #define  _ASSERT assert
-#ifdef _DEBUG_ARG
-#  undef _DEBUG_ARG
+
+#ifdef   _TROUBLE
+#  undef _TROUBLE
 #endif
-#define _DEBUG_ARG(arg) arg
+#define  _TROUBLE assert(0)
+
+#endif /* NCBI_MSWIN_NO_POPUP */
 
-#endif  /* TEST_ASSERT_IMPL__H */
+#endif /* COMMON__TEST_ASSERT_IMPL__H */
diff --git a/connect/test/test_ncbi_connutil_hit.c b/connect/test/test_ncbi_connutil_hit.c
index f1d7408..358447f 100644
--- a/connect/test/test_ncbi_connutil_hit.c
+++ b/connect/test/test_ncbi_connutil_hit.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_connutil_hit.c,v 6.14 2006/04/20 14:01:43 lavr Exp $
+/* $Id: test_ncbi_connutil_hit.c,v 6.17 2010/02/05 20:35:04 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -31,7 +31,7 @@
  */
 
 #include <connect/ncbi_connutil.h>
-#include <connect/ncbi_util.h>
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <stdlib.h>
 /* This header must go last */
 #include "test_assert.h"
@@ -66,7 +66,7 @@ int main(int argc, char** argv)
             "  URL args:        '%s'\n"
             "  Input data file: '%s'\n"
             "  User header:     '%s'\n"
-            " Reply(if any) from the hit URL goes to the standard output.\n\n",
+            "Response(if any) from the hit URL goes to standard output.\n\n",
             argv[0],
             host, (unsigned short) port, path, args, inp_file, user_header);
 
@@ -161,56 +161,8 @@ int main(int argc, char** argv)
 
     /* Success:  close the socket, cleanup, and exit */
     SOCK_Close(sock);
-    CORE_SetLOG(0);
 
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
+    CORE_SetLOG(0);
     return 0;
 }
-
-
-/*
- * ---------------------------------------------------------------------------
- * $Log: test_ncbi_connutil_hit.c,v $
- * Revision 6.14  2006/04/20 14:01:43  lavr
- * Cleanup to demonstrate no leaks
- *
- * Revision 6.13  2005/07/22 16:09:43  lavr
- * Add severity and timestamp to log message format
- *
- * Revision 6.12  2002/08/12 15:10:43  lavr
- * Use persistent SOCK_Write()
- *
- * Revision 6.11  2002/08/07 16:38:08  lavr
- * EIO_ReadMethod enums changed accordingly; log moved to end
- *
- * Revision 6.10  2002/04/15 19:21:44  lavr
- * +#include "../test/test_assert.h"
- *
- * Revision 6.9  2002/03/22 19:48:56  lavr
- * Removed <stdio.h>: included from ncbi_util.h or ncbi_priv.h
- *
- * Revision 6.8  2002/02/05 21:45:55  lavr
- * Included header files rearranged
- *
- * Revision 6.7  2001/03/02 20:03:57  lavr
- * Typos fixed
- *
- * Revision 6.6  2001/01/23 23:21:21  lavr
- * Added new argument to URL_Connect
- *
- * Revision 6.5  2001/01/08 22:42:14  lavr
- * eRequestMethodAny -> eRequestMethod_Any
- *
- * Revision 6.4  2000/12/29 18:24:40  lavr
- * File size is now discovered without use of stat call.
- *
- * Revision 6.3  2000/09/27 13:49:29  lavr
- * URL_Connect args adjusted
- *
- * Revision 6.2  2000/03/29 17:21:47  vakatov
- * + CORE_SetLOG(0) at the program end.
- *
- * Revision 6.1  2000/03/24 22:53:38  vakatov
- * Initial revision
- *
- * ===========================================================================
- */
diff --git a/connect/test/test_ncbi_connutil_misc.c b/connect/test/test_ncbi_connutil_misc.c
index f8345b9..2ea71ca 100644
--- a/connect/test/test_ncbi_connutil_misc.c
+++ b/connect/test/test_ncbi_connutil_misc.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_connutil_misc.c,v 6.28 2009/02/07 02:29:30 kazimird Exp $
+/* $Id: test_ncbi_connutil_misc.c,v 6.36 2010/06/08 15:14:44 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,12 +30,10 @@
  *
  */
 
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_priv.h"
 #include <connect/ncbi_connutil.h>
-#include <connect/ncbi_util.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <stdlib.h>
-#include <string.h>
 #include <time.h>
 /* This header must go last */
 #include "test_assert.h"
@@ -242,6 +240,7 @@ static void TEST_MIME(void)
 static void TEST_ConnNetInfo(void)
 {
     size_t n;
+    char* url;
     SConnNetInfo* net_info;
 
     CORE_LOG(eLOG_Note, "ConnNetInfo test started");
@@ -260,20 +259,43 @@ static void TEST_ConnNetInfo(void)
     assert(strcmp(net_info->path, "/ro.t/p@th")              == 0);
     assert(strcmp(net_info->args, "arg/arg:arg@arg:arg/arg") == 0);
 
-    assert(ConnNetInfo_ParseURL(net_info, "http://www/path"
-                                "?arg:arg@arg"));
-    assert(       net_info->scheme       == eURL_Http);
+    assert(ConnNetInfo_ParseURL(net_info, "https://www/path"
+                                "?arg:arg@arg#frag"));
+    assert(       net_info->scheme           == eURL_Https);
     assert(      *net_info->user                 == 0);
     assert(      *net_info->pass                 == 0);
     assert(strcmp(net_info->host, "www")         == 0);
     assert(       net_info->port                 == 0);
     assert(strcmp(net_info->path, "/path")       == 0);
-    assert(strcmp(net_info->args, "arg:arg@arg") == 0);
+    assert(strcmp(net_info->args, "arg:arg@arg#frag") == 0);
+
+    assert(ConnNetInfo_ParseURL(net_info, "/path1?arg1#frag2"));
+    assert(strcmp(net_info->args, "arg1#frag2")       == 0);
+
+    assert(ConnNetInfo_ParseURL(net_info, "path0/0"));
+    assert(strcmp(net_info->path, "/path0/0")         == 0);
+    assert(strcmp(net_info->args, "#frag2")           == 0);
+
+    assert(ConnNetInfo_ParseURL(net_info, "#frag3"));
+    assert(strcmp(net_info->args, "#frag3")           == 0);
+
+    assert(ConnNetInfo_ParseURL(net_info, "path2"));
+    assert(strcmp(net_info->path, "/path0/path2")     == 0);
+    assert(strcmp(net_info->args, "#frag3")           == 0);
+
+    assert(ConnNetInfo_ParseURL(net_info, "/path3?arg3"));
+    assert(strcmp(net_info->path, "/path3")           == 0);
+    assert(strcmp(net_info->args, "arg3#frag3")       == 0);
+
+    url = ConnNetInfo_URL(net_info);
+    assert(url);
+    assert(strcmp(url, "https://www/path3?arg3#frag3") == 0);
+    free(url);
 
     printf("HTTP User Header:\n\"%s\"\n",
            net_info->http_user_header ? net_info->http_user_header : "<NONE>");
     ConnNetInfo_AppendUserHeader(net_info,
-                                 "My-Tag1: Value1\r\n"
+                                 "My-Tag1:Value1\r\n"
                                  "My-Tag2: Value2\r\n"
                                  "My-Tag3: Value3\r\n");
     printf("HTTP User Header after append:\n\"%s\"\n",
@@ -289,6 +311,12 @@ static void TEST_ConnNetInfo(void)
                                  "My-Tag4: Value 4.1\r\n"
                                  "My-Tag5: \t \r\n"
                                  "My-Tag6: Value 6\r\n");
+    ConnNetInfo_ExtendUserHeader(net_info,
+                                 "My-Tag4: Value 4.1\r\n"
+                                 "My-Tag6: Value 6\r\n");
+    ConnNetInfo_ExtendUserHeader(net_info,
+                                 "My-Tag4:Value 4\r\n"
+                                 "My-Tag6:Value 6\r\n");
     printf("HTTP User Header after extend:\n\"%s\"\n",
            net_info->http_user_header ? net_info->http_user_header : "<NONE>");
     ConnNetInfo_SetUserHeader(net_info, 0);
@@ -329,7 +357,7 @@ static void TEST_ConnNetInfo(void)
     ConnNetInfo_DeleteAllArgs(net_info, "a=b&p=q&f=d");
     printf("HTTP Arg after delete-all: \"%s\"\n", net_info->args);
 
-    ConnNetInfo_Log(net_info, CORE_GetLOG());
+    ConnNetInfo_LogEx(net_info, eLOG_Note, CORE_GetLOG());
 
     ConnNetInfo_Destroy(net_info);
 
@@ -347,7 +375,8 @@ int main(void)
     g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND;
     srand(g_NCBI_ConnectRandomSeed);
 
-    CORE_SetLOGFormatFlags(fLOG_Short | fLOG_DateTime | fLOG_OmitNoteLevel);
+    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
+                           fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
 
     CORE_LOG(eLOG_Note, "Miscellaneous tests started");
@@ -356,8 +385,7 @@ int main(void)
     TEST_MIME();
     TEST_ConnNetInfo();
 
-    CORE_LOG(eLOG_Note, "All tests completed");
-
+    CORE_LOG(eLOG_Note, "All tests completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
diff --git a/connect/test/test_ncbi_core.c b/connect/test/test_ncbi_core.c
index 461767b..53b45dc 100644
--- a/connect/test/test_ncbi_core.c
+++ b/connect/test/test_ncbi_core.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_core.c,v 6.18 2008/11/28 23:59:43 kazimird Exp $
+/* $Id: test_ncbi_core.c,v 6.20 2010/02/05 20:35:04 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -32,8 +32,8 @@
  *
  */
 
-#include "../ncbi_assert.h"
 #include <connect/ncbi_util.h>
+#include "../ncbi_assert.h"
 #include <stdlib.h>
 #include <errno.h>
 /* This header must go last */
diff --git a/connect/test/test_ncbi_disp.c b/connect/test/test_ncbi_disp.c
index 742f343..439a429 100644
--- a/connect/test/test_ncbi_disp.c
+++ b/connect/test/test_ncbi_disp.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_disp.c,v 6.35 2009/02/03 16:39:35 kazimird Exp $
+/* $Id: test_ncbi_disp.c,v 6.38 2010/06/04 14:59:37 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -33,8 +33,6 @@
 #include "../ncbi_ansi_ext.h"
 #include "../ncbi_lbsmd.h"
 #include "../ncbi_priv.h"               /* CORE logging facilities */
-#include "../ncbi_servicep.h"
-#include <connect/ncbi_heapmgr.h>
 #include <stdlib.h>
 #include <time.h>
 /* This header must go last */
@@ -180,7 +178,7 @@ int main(int argc, const char* argv[])
     }
 
     if (n_found != 0)
-        CORE_LOGF(eLOG_Note, ("Test complete: %d server(s) found", n_found));
+        CORE_LOGF(eLOG_Note, ("%d server(s) found", n_found));
     else
         CORE_LOG(eLOG_Fatal, "Requested service not found");
 
@@ -203,6 +201,7 @@ int main(int argc, const char* argv[])
     }
 #endif
 
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
diff --git a/connect/test/test_ncbi_dsock.c b/connect/test/test_ncbi_dsock.c
index fc8b410..64040bc 100644
--- a/connect/test/test_ncbi_dsock.c
+++ b/connect/test/test_ncbi_dsock.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_dsock.c,v 6.21 2008/10/20 16:55:43 kazimird Exp $
+/* $Id: test_ncbi_dsock.c,v 6.24 2010/02/05 20:35:04 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,16 +30,19 @@
  *
  */
 
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <connect/ncbi_connutil.h>
 #include <connect/ncbi_socket.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <errno.h>
 #include <stdlib.h>
 #include <time.h>
 /* This header must go last */
 #include "test_assert.h"
 
+/* maximal UDP packet size as allowed by the standard */
+#define MAX_UDP_DGRAM_SIZE 65535
+
 #if defined(NCBI_OS_BSD) || defined(NCBI_OS_OSF1) || defined(NCBI_OS_DARWIN)
    /* FreeBSD has this limit :-/ Source: `sysctl net.inet.udp.maxdgram` */
    /* For OSF1 (and FreeBSD) see also: /usr/include/netinet/udp_var.h   */
@@ -51,8 +54,7 @@
    /* Larger sizes do not seem to work everywhere */
 #  define MAX_DGRAM_SIZE 59550
 #else
-   /* This is the maximal datagram size defined by the UDP standard */
-#  define MAX_DGRAM_SIZE 65535
+#  define MAX_DGRAM_SIZE MAX_UDP_DGRAM_SIZE
 #endif
 /* NOTE: x86_64 (AMD) kernel does not allow dgrams bigger than MTU minus
  * small overhead;  for these we use the script and pass the MTU via argv.
@@ -229,6 +231,8 @@ static int s_Client(int x_port, unsigned int max_try)
     msglen = (size_t)(((double)rand()/(double)RAND_MAX) * s_MTU);
     if (msglen < sizeof(time_t) + 10)
         msglen = sizeof(time_t) + 10;
+    if (msglen == MAX_UDP_DGRAM_SIZE)
+        msglen--;
 
     CORE_LOGF(eLOG_Note, ("[Client]  Generating a message %lu bytes long",
                           (unsigned long) msglen));
@@ -327,7 +331,8 @@ static int s_Client(int x_port, unsigned int max_try)
         return 1;
     }
 
-    CORE_LOG(eLOG_Note, "[Client]  Completed successfully");
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
+    CORE_SetLOG(0);
     return 0;
 }
 
diff --git a/connect/test/test_ncbi_file_connector.c b/connect/test/test_ncbi_file_connector.c
index 29b1b9c..e0d0059 100644
--- a/connect/test/test_ncbi_file_connector.c
+++ b/connect/test/test_ncbi_file_connector.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_file_connector.c,v 6.7 2008/10/20 16:55:43 kazimird Exp $
+/* $Id: test_ncbi_file_connector.c,v 6.10 2010/02/05 20:35:04 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,10 +30,9 @@
  *
  */
 
-#include "../ncbi_assert.h"
 #include <connect/ncbi_connection.h>
 #include <connect/ncbi_file_connector.h>
-#include <connect/ncbi_util.h>
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <stdlib.h>
 /* This header must go last */
 #include "test_assert.h"
@@ -65,6 +64,8 @@ int main(int argc, const char* argv[])
     inp_file = argv[1];
 
     /* log and data log streams */
+    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
+                           fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
 
     /* run the test */
@@ -109,6 +110,7 @@ int main(int argc, const char* argv[])
     
     /* cleanup, exit */
     verify(CONN_Close(conn) == eIO_Success);
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
diff --git a/connect/test/test_ncbi_ftp_connector.c b/connect/test/test_ncbi_ftp_connector.c
index 98640a7..95c813c 100644
--- a/connect/test/test_ncbi_ftp_connector.c
+++ b/connect/test/test_ncbi_ftp_connector.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_ftp_connector.c,v 1.17 2008/10/21 19:25:44 kazimird Exp $
+/* $Id: test_ncbi_ftp_connector.c,v 1.26 2010/06/04 14:59:37 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,12 +30,14 @@
  *
  */
 
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_priv.h"
-#include <connect/ncbi_connection.h>
 #include <connect/ncbi_connutil.h>
 #include <connect/ncbi_ftp_connector.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <stdlib.h>
+#ifdef HAVE_GETTIMEOFDAY
+#  include <sys/time.h>
+#endif /*HAVE_GETTIMEOFDAY*/
 #include <time.h>
 /* This header must go last */
 #include "test_assert.h"
@@ -47,6 +49,18 @@
 #define TEST_PATH ((char*) 0)
 
 
+static double s_GetTime(void)
+{
+#ifdef HAVE_GETTIMEOFDAY
+    struct timeval t;
+    return gettimeofday(&t, 0) == 0 ? t.tv_sec + t.tv_usec / 1000000.0 : 0.0;
+#else
+    time_t t = time(0);
+    return (double)((unsigned long) t);
+#endif /*HAVE_GETTIMEOFDAY*/
+}
+
+
 int main(int argc, char* argv[])
 {
     static const char kChdir[] = "CWD /toolbox/ncbi_tools\n";
@@ -59,6 +73,7 @@ int main(int argc, char* argv[])
     FILE*         data_file;
     size_t        size, n;
     EIO_Status    status;
+    double        elapse;
     CONN          conn;
 
     g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND;
@@ -68,20 +83,19 @@ int main(int argc, char* argv[])
     CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
                            fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
-    data_file = fopen("test_ncbi_ftp_connector.out", "wb");
+    data_file = fopen("test_ncbi_ftp_connector.dat", "wb");
     assert(data_file);
 
     assert((net_info = ConnNetInfo_Create(0)) != 0);
     if (net_info->debug_printout == eDebugPrintout_Some)
         flag |= fFCDC_LogControl;
-    else if (net_info->debug_printout == eDebugPrintout_Data)
-        flag |= fFCDC_LogData;
-    else {
+    else if (net_info->debug_printout == eDebugPrintout_Data) {
         char val[32];
-        ConnNetInfo_GetValue(0, REG_CONN_DEBUG_PRINTOUT, val, sizeof(val), "");
-        if (strcasecmp(val, "ALL") == 0)
-            flag |= fFCDC_LogAll;
+        ConnNetInfo_GetValue(0, REG_CONN_DEBUG_PRINTOUT, val, sizeof(val),
+                             DEF_CONN_DEBUG_PRINTOUT);
+        flag |= strcasecmp(val, "all") == 0 ? fFCDC_LogAll : fFCDC_LogData;
     }
+    flag |= fFCDC_UseFeatures;
 
     if (TEST_PORT) {
         sprintf(buf, ":%hu", TEST_PORT);
@@ -111,13 +125,23 @@ int main(int argc, char* argv[])
     if (CONN_Write(conn, "aaa", 3, &n, eIO_WritePlain) != eIO_Success)
         CORE_LOG(eLOG_Fatal, "Cannot write FTP command");
 
-    if (CONN_Wait(conn, eIO_Read, net_info->timeout) != eIO_Unknown)
+    if (CONN_Wait(conn, eIO_Read, net_info->timeout) != eIO_NotSupported)
         CORE_LOG(eLOG_Fatal, "Test failed in waiting on READ");
-    CORE_LOG(eLOG_Note, "Unrecognized command was correctly rejected");
+    CORE_LOG(eLOG_Note, "Unrecognized command correctly rejected");
 
     if (CONN_Write(conn, "LIST\nSIZE", 9, &n, eIO_WritePlain) != eIO_Unknown)
         CORE_LOG(eLOG_Fatal, "Test failed to reject multiple commands");
-    CORE_LOG(eLOG_Note, "Multiple commands were correctly rejected");
+    CORE_LOG(eLOG_Note, "Multiple commands correctly rejected");
+
+    status = CONN_Write(conn, "SIZE 1GB\n", 9, &n, eIO_WritePersist);
+    if (status == eIO_Success) {
+        char buf[128];
+        CONN_ReadLine(conn, buf, sizeof(buf) - 1, &n);
+        CORE_LOGF(eLOG_Note, ("SIZE file: %.*s", (int) n, buf));
+    } else {
+        CORE_LOGF(eLOG_Note, ("SIZE command not accepted: %s",
+                              IO_StatusStr(status)));
+    }
 
     if (CONN_Write(conn, "LIST", 4, &n, eIO_WritePlain) != eIO_Success)
         CORE_LOG(eLOG_Fatal, "Cannot write LIST command");
@@ -129,10 +153,12 @@ int main(int argc, char* argv[])
         if (n != 0) {
             printf("%.*s", (int) n, buf);
             first = 0/*false*/;
+            fflush(stdout);
         }
     } while (status == eIO_Success);
-    if (first) {
-        printf("<EOF>\n");
+    if (first  ||  status != eIO_Closed) {
+        printf("<%s>\n", status != eIO_Success ? IO_StatusStr(status) : "EOF");
+        fflush(stdout);
     }
 
     if (CONN_Write(conn, "NLST\r\n", 6, &n, eIO_WritePlain) != eIO_Success)
@@ -145,10 +171,25 @@ int main(int argc, char* argv[])
         if (n != 0) {
             printf("%.*s", (int) n, buf);
             first = 0/*false*/;
-        }
+            fflush(stdout);
+        } else
+            assert(status != eIO_Success);
     } while (status == eIO_Success);
-    if (first) {
-        printf("<EOF>\n");
+    if (first  ||  status != eIO_Closed) {
+        printf("<%s>\n", status != eIO_Success ? IO_StatusStr(status) : "EOF");
+        fflush(stdout);
+    }
+
+    if (CONN_Write(conn, "SIZE ", 5, &n, eIO_WritePlain) != eIO_Success)
+        CORE_LOG(eLOG_Fatal, "Cannot write SIZE directory command");
+    size = strlen(kChdir + 4);
+    if (CONN_Write(conn, kChdir + 4, size, &n, eIO_WritePersist)==eIO_Success){
+        char buf[128];
+        CONN_ReadLine(conn, buf, sizeof(buf) - 1, &n);
+        CORE_LOGF(eLOG_Note, ("SIZE directory returned: %.*s", (int) n, buf));
+    } else {
+        CORE_LOGF(eLOG_Note, ("SIZE directory not accepted: %s",
+                              IO_StatusStr(status)));
     }
 
     if (CONN_Write(conn, kChdir, sizeof(kChdir) - 1, &n, eIO_WritePlain)
@@ -157,23 +198,51 @@ int main(int argc, char* argv[])
                                (int) sizeof(kChdir) - 2, kChdir));
     }
 
+    size = strlen(kFile + 5);
+    if ((status = CONN_Write(conn, "MDTM ", 5, &n, eIO_WritePlain))
+        == eIO_Success  &&
+        (status = CONN_Write(conn, kFile + 5, size, &n, eIO_WritePersist))
+        == eIO_Success) {
+        unsigned long val;
+        char buf[128];
+        CONN_ReadLine(conn, buf, sizeof(buf) - 1, &n);
+        if (n  &&  sscanf(buf, "%lu", &val) > 0) {
+            struct tm* tm;
+            time_t t = (time_t) val;
+            if ((tm = localtime(&t)) != 0)
+                n = strftime(buf, sizeof(buf), "%m/%d/%Y %H:%M:%S", tm);
+        }
+        CORE_LOGF(eLOG_Note, ("MDTM returned: %.*s", (int) n, buf));
+    } else {
+        CORE_LOGF(eLOG_Note, ("MDTM command not accepted: %s",
+                              IO_StatusStr(status)));
+    }
+
     if (CONN_Write(conn, kFile, sizeof(kFile) - 1, &n, eIO_WritePersist)
         != eIO_Success) {
         CORE_LOGF(eLOG_Fatal, ("Cannot write %s", kFile));
     }
 
     size = 0;
+    elapse = s_GetTime();
     do {
         status = CONN_Read(conn, buf, sizeof(buf), &n, eIO_ReadPlain);
         if (n != 0) {
             fwrite(buf, n, 1, data_file);
+            fflush(data_file);
             size += n;
-        }
+            rand();
         if (argc > 1  &&  rand() % 100 == 0) {
             aborting = 1;
             break;
         }
+        } else {
+            assert(status != eIO_Success);
+            if (status != eIO_Closed  ||  !size)
+                CORE_LOGF(eLOG_Error, ("Read error: %s",IO_StatusStr(status)));
+        }
     } while (status == eIO_Success);
+    elapse = s_GetTime() - elapse;
 
     if (!aborting  ||  (rand() & 1) == 0) {
         if (CONN_Write(conn, "NLST blah*", 10, &n, eIO_WritePlain)
@@ -188,10 +257,12 @@ int main(int argc, char* argv[])
             if (n != 0) {
                 printf("%.*s", (int) n, buf);
                 first = 0/*false*/;
+                fflush(stdout);
             }
         } while (status == eIO_Success);
         if (first) {
             printf("<EOF>\n");
+            fflush(stdout);
         }
     }
 
@@ -202,14 +273,16 @@ int main(int argc, char* argv[])
 
     /* Cleanup and exit */
     fclose(data_file);
-    if (aborting) {
-        remove("test_ncbi_ftp_connector.out");
-    } else {
-        CORE_LOGF(eLOG_Note, ("%lu bytes downloaded", (unsigned long) size));
-    }
-
-    CORE_LOG(eLOG_Note, "Test completed");
+    if (!aborting) {
+        CORE_LOGF(size ? eLOG_Note : eLOG_Fatal,
+                  ("%lu byte(s) downloaded in %.2f second(s) @ %.2fKB/s",
+                   (unsigned long) size, elapse,
+                   (unsigned long) size / (1024 * (elapse ? elapse : 1.0))));
+    } else
+        remove("test_ncbi_ftp_connector.dat");
     ConnNetInfo_Destroy(net_info);
+
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
diff --git a/connect/test/test_ncbi_heapmgr.c b/connect/test/test_ncbi_heapmgr.c
index ffba52f..0e9fbb6 100644
--- a/connect/test/test_ncbi_heapmgr.c
+++ b/connect/test/test_ncbi_heapmgr.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_heapmgr.c,v 6.18 2006/11/21 14:47:58 lavr Exp $
+/* $Id: test_ncbi_heapmgr.c,v 6.21 2010/02/05 20:35:04 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,8 +30,8 @@
  *
  */
 
-#include "../ncbi_priv.h"
 #include <connect/ncbi_heapmgr.h>
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
@@ -106,7 +106,8 @@ int main(int argc, const char* argv[])
     HEAP heap;
     char* c;
 
-    /* CORE_SetLOGFormatFlags(fLOG_None | fLOG_Level | fLOG_OmitNoteLevel); */
+    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
+                           fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
     if (argc > 1)
         g_NCBI_ConnectRandomSeed = atoi(argv[1]);
@@ -241,68 +242,7 @@ int main(int argc, const char* argv[])
         HEAP_Destroy(heap);
         CORE_LOGF(eLOG_Note, ("Heap %d done", j));
     }
-    CORE_LOG(eLOG_Note, "Test completed");
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
-
-
-/*
- * --------------------------------------------------------------------------
- * $Log: test_ncbi_heapmgr.c,v $
- * Revision 6.18  2006/11/21 14:47:58  lavr
- * Implement correct fast freeing and fast allocation checks
- *
- * Revision 6.17  2006/11/20 17:25:00  lavr
- * Test extended to use HEAP_FreeFast() and HEAP_AttachFast()
- *
- * Revision 6.16  2006/11/20 16:42:31  lavr
- * Test extended to be more thorough
- *
- * Revision 6.15  2006/03/05 17:42:10  lavr
- * Adjust for revised API
- *
- * Revision 6.14  2005/07/11 18:24:46  lavr
- * Spell ADDEND
- *
- * Revision 6.13  2005/05/02 16:12:32  lavr
- * Use global random seed
- *
- * Revision 6.12  2003/08/25 14:58:10  lavr
- * Adjust test to take advantage of modified API
- *
- * Revision 6.11  2003/07/31 17:54:16  lavr
- * +HEAP_Trim() test
- *
- * Revision 6.10  2003/02/27 15:34:35  lavr
- * Log moved to end
- *
- * Revision 6.9  2002/04/15 19:21:44  lavr
- * +#include "../test/test_assert.h"
- *
- * Revision 6.8  2001/07/03 20:53:38  lavr
- * HEAP_Copy() test added
- *
- * Revision 6.7  2001/06/19 19:12:04  lavr
- * Type change: size_t -> TNCBI_Size; time_t -> TNCBI_Time
- *
- * Revision 6.6  2001/01/23 23:22:05  lavr
- * Patched logging (in a few places)
- *
- * Revision 6.5  2001/01/12 23:59:53  lavr
- * Message logging modified for use LOG facility only
- *
- * Revision 6.4  2000/12/29 18:23:42  lavr
- * getpagesize() replaced by a constant 4096, which is "more portable".
- *
- * Revision 6.3  2000/05/31 23:12:32  lavr
- * First try to assemble things together to get working service mapper
- *
- * Revision 6.2  2000/05/16 15:21:03  lavr
- * Cleaned up with format - argument correspondence; #include <time.h> added
- *
- * Revision 6.1  2000/05/12 19:35:13  lavr
- * First working revision
- *
- * ==========================================================================
- */
diff --git a/connect/test/test_ncbi_http_connector.c b/connect/test/test_ncbi_http_connector.c
index 7c8f9f5..9f0dd18 100644
--- a/connect/test/test_ncbi_http_connector.c
+++ b/connect/test/test_ncbi_http_connector.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_http_connector.c,v 6.18 2004/11/23 15:04:39 lavr Exp $
+/* $Id: test_ncbi_http_connector.c,v 6.19 2010/01/27 06:49:45 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,10 +30,10 @@
  *
  */
 
-#include "ncbi_conntest.h"
-#include "../ncbi_ansi_ext.h"
 #include <connect/ncbi_http_connector.h>
-#include <connect/ncbi_util.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
+#include "ncbi_conntest.h"
 /* This header must go last */
 #include "test_assert.h"
 
@@ -101,6 +101,7 @@ int main(void)
     CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
                            fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
+
     data_file = fopen("test_ncbi_http_connector.log", "ab");
     assert(data_file);
 
@@ -134,67 +135,8 @@ int main(void)
     /* Cleanup and Exit */
     CORE_SetREG(0);
     fclose(data_file);
+
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
-
-
-/*
- * --------------------------------------------------------------------------
- * $Log: test_ncbi_http_connector.c,v $
- * Revision 6.18  2004/11/23 15:04:39  lavr
- * Use public bounce.cgi from "www"
- *
- * Revision 6.17  2004/11/22 20:27:32  lavr
- * Weird 5.123456 timeout restored to the form it used to be
- *
- * Revision 6.16  2004/11/22 20:25:27  lavr
- * "yar" replaced with "graceland"
- *
- * Revision 6.15  2004/04/01 14:14:02  lavr
- * Spell "occurred", "occurrence", and "occurring"
- *
- * Revision 6.14  2003/11/04 12:26:06  lavr
- * s_GetReg() marked with ARGSUSED, because user_data is not used in there
- *
- * Revision 6.13  2003/05/14 03:58:43  lavr
- * Match changes in respective APIs of the tests
- *
- * Revision 6.12  2003/04/15 14:06:09  lavr
- * Changed ray.nlm.nih.gov -> ray.ncbi.nlm.nih.gov
- *
- * Revision 6.11  2002/12/04 16:59:21  lavr
- * Open log file in append mode
- *
- * Revision 6.10  2002/11/22 15:09:40  lavr
- * Replace all occurrences of "ray" with "yar"
- *
- * Revision 6.9  2002/10/28 15:47:12  lavr
- * Use "ncbi_ansi_ext.h" privately and use strncpy0()
- *
- * Revision 6.8  2002/03/22 19:47:16  lavr
- * Test_assert.h made last among the include files
- *
- * Revision 6.7  2002/01/16 21:23:15  vakatov
- * Utilize header "test_assert.h" to switch on ASSERTs in the Release mode too
- *
- * Revision 6.6  2001/01/11 16:42:50  lavr
- * Registry Get/Set methods got the 'user_data' argument, forgotten earlier
- *
- * Revision 6.5  2001/01/08 23:48:51  lavr
- * REQ_METHOD "any" added to SConnNetInfo
- *
- * Revision 6.4  2000/11/15 17:29:52  vakatov
- * Fixed path to the test CGI application.
- *
- * Revision 6.3  2000/09/27 15:58:17  lavr
- * Registry entries adjusted
- *
- * Revision 6.2  2000/05/30 23:25:03  vakatov
- * Cosmetic fix for the C++ compilation
- *
- * Revision 6.1  2000/04/21 19:57:02  vakatov
- * Initial revision
- *
- * ==========================================================================
- */
diff --git a/connect/test/test_ncbi_http_get.c b/connect/test/test_ncbi_http_get.c
index 1e2d256..4c72a58 100644
--- a/connect/test/test_ncbi_http_get.c
+++ b/connect/test/test_ncbi_http_get.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_http_get.c,v 6.19 2008/11/10 17:14:42 kazimird Exp $
+/* $Id: test_ncbi_http_get.c,v 6.26 2010/06/08 15:14:44 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,17 +30,17 @@
  *
  */
 
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_priv.h"
 #include <connect/ncbi_gnutls.h>
 #include <connect/ncbi_http_connector.h>
 #include <connect/ncbi_util.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <errno.h>
 #include <stdlib.h>
 #include <time.h>
-#ifdef NCBI_OS_UNIX
+#if defined(NCBI_OS_UNIX)  &&  defined(HAVE_USLEEP)
 #  include <unistd.h>
-#endif
+#endif /*NCBI_OS_UNIX && HAVE_USLEEP*/
 /* This header must go last */
 #include "test_assert.h"
 
@@ -75,20 +75,14 @@ int main(int argc, char* argv[])
         fp = 0;
 
     ConnNetInfo_GetValue(0, "RECONNECT", blk, 32, "");
-    if (*blk  &&  (strcmp    (blk, "1")    == 0  ||
-                   strcasecmp(blk, "ON")   == 0  ||
-                   strcasecmp(blk, "YES")  == 0  ||
-                   strcasecmp(blk, "TRUE") == 0)) {
+    if (ConnNetInfo_Boolean(blk)) {
         CORE_LOG(eLOG_Note, "Reconnect mode acknowledged");
         flags = fHCC_AutoReconnect;
     } else
         flags = 0;
 
     ConnNetInfo_GetValue(0, "USESSL", blk, 32, "");
-    if (*blk  &&  (strcmp    (blk, "1")    == 0  ||
-                   strcasecmp(blk, "ON")   == 0  ||
-                   strcasecmp(blk, "YES")  == 0  ||
-                   strcasecmp(blk, "TRUE") == 0)) {
+    if (ConnNetInfo_Boolean(blk)) {
 #ifdef HAVE_LIBGNUTLS
         CORE_LOG(eLOG_Note,    "SSL request acknowledged");
         SOCK_SetupSSL(NcbiSetupGnuTls);
@@ -128,38 +122,42 @@ int main(int argc, char* argv[])
     t = time(0);
     do {
         status = CONN_Wait(conn, eIO_Read, net_info->timeout);
-        if (status != eIO_Success) {
-            if (status != eIO_Timeout)
-                break;
+        if (status == eIO_Timeout) {
             if ((net_info->timeout  &&
                  (net_info->timeout->sec | net_info->timeout->usec))
-                ||  (unsigned long)(time(0) - t) > DEF_CONN_TIMEOUT)
+                 ||  (unsigned long)(time(0) - t) > DEF_CONN_TIMEOUT) {
                 CORE_LOG(eLOG_Fatal, "Timed out");
-#ifdef NCBI_OS_UNIX
+            }
+#if defined(NCBI_OS_UNIX)  &&  defined(HAVE_USLEEP)
             usleep(500);
-#endif /*NCBI_OS_UNIX*/
+#endif /*NCBI_OS_UNIX && HAVE_USLEEP*/
             continue;
         }
-
+        if (status == eIO_Success)
         status = CONN_ReadLine(conn, blk, sizeof(blk), &n);
-        if (status == eIO_Timeout)
-            continue;
-        if (status != eIO_Success  &&  status != eIO_Closed)
-            CORE_LOGF(eLOG_Fatal, ("Read error: %s", IO_StatusStr(status)));
-        if (n == sizeof(blk))
-            CORE_LOGF(eLOG_Warning, ("Line too long, continuing..."));
+        else
+            n = 0;
         if (n) {
+            connector = 0/*as bool, visited*/;
             fwrite(blk, 1, n, stdout);
+            if (status != eIO_Timeout)
             fputc('\n', stdout);
             fflush(stdout);
+            if (n == sizeof(blk)  &&  status != eIO_Closed)
+                CORE_LOGF(eLOG_Warning, ("Line too long, continuing..."));
         }
+        if (status == eIO_Timeout)
+            continue;
+        if (status != eIO_Success  &&  (status != eIO_Closed  ||  connector))
+            CORE_LOGF(eLOG_Fatal, ("Read error: %s", IO_StatusStr(status)));
+
     } while (status == eIO_Success  ||  status == eIO_Timeout);
 
     ConnNetInfo_Destroy(net_info);
     CORE_LOG(eLOG_Note, "Closing connection");
     CONN_Close(conn);
 
-    CORE_LOG(eLOG_Note, "Completed");
+    CORE_LOG(eLOG_Note, "Completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
diff --git a/connect/test/test_ncbi_memory_connector.c b/connect/test/test_ncbi_memory_connector.c
index e2e8b73..25cd11d 100644
--- a/connect/test/test_ncbi_memory_connector.c
+++ b/connect/test/test_ncbi_memory_connector.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_memory_connector.c,v 6.5 2006/03/30 17:46:40 lavr Exp $
+/* $Id: test_ncbi_memory_connector.c,v 6.7 2010/01/28 15:34:33 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,9 +30,9 @@
  *
  */
 
-#include "ncbi_conntest.h"
 #include <connect/ncbi_memory_connector.h>
-#include <connect/ncbi_util.h>
+#include "../ncbi_priv.h"               /* CORE logging facilities */
+#include "ncbi_conntest.h"
 /* This header must go last */
 #include "test_assert.h"
 
@@ -44,6 +44,8 @@ int main(void)
     FILE*           data_file;
 
     /* Log and data-log streams */
+    CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
+                           fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
     data_file = fopen("test_ncbi_memory_connector.log", "wb");
     assert(data_file);
@@ -57,28 +59,7 @@ int main(void)
 
     /* Cleanup and Exit */
     fclose(data_file);
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0;
 }
-
-
-/*
- * --------------------------------------------------------------------------
- * $Log: test_ncbi_memory_connector.c,v $
- * Revision 6.5  2006/03/30 17:46:40  lavr
- * Adjust for lock-less MEMORY_Connector API
- *
- * Revision 6.4  2002/12/04 16:58:49  lavr
- * Move change log to end
- *
- * Revision 6.3  2002/03/22 19:47:31  lavr
- * Test_assert.h made last among the include files
- *
- * Revision 6.2  2002/02/20 20:53:48  lavr
- * Use xconntest to perform standard tests
- *
- * Revision 6.1  2002/02/20 19:14:40  lavr
- * Initial revision
- *
- * ==========================================================================
- */
diff --git a/connect/test/test_ncbi_sendmail.c b/connect/test/test_ncbi_sendmail.c
index 2e928b0..1c14824 100644
--- a/connect/test/test_ncbi_sendmail.c
+++ b/connect/test/test_ncbi_sendmail.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_sendmail.c,v 6.20 2008/03/15 11:25:53 kazimird Exp $
+/* $Id: test_ncbi_sendmail.c,v 6.25 2010/06/04 14:59:37 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,13 +30,12 @@
  *
  */
 
-#include "../ncbi_priv.h"               /* CORE logging facilities */
-#include "../ncbi_ansi_ext.h"
+#include <connect/ncbi_connutil.h>
 #include <connect/ncbi_sendmail.h>
-#include <connect/ncbi_socket.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <errno.h>
 #include <stdlib.h>
-#include <string.h>
 #include <time.h>
 /* This header must go last */
 #include "test_assert.h"
@@ -74,13 +73,14 @@ int main(int argc, const char* argv[])
         "lavr@pavo",
         " \"Anton Lavrentiev\"   <lavr@pavo>  , lavr, <lavr>   ",
     };
-    const char* mx_host, *p;
     size_t i, j, k, n, m;
+    const char* mx_host;
     SSendMailInfo info;
     const char* retval;
     STimeout mx_tmo;
     char* huge_body;
     short mx_port;
+    char val[32];
     FILE* fp;
 
     g_NCBI_ConnectRandomSeed = (int) time(0) ^ NCBI_CONNECT_SRAND_ADDEND;
@@ -90,16 +90,14 @@ int main(int argc, const char* argv[])
                            fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
 
-    if ((p = getenv("CONN_DEBUG_PRINTOUT")) != 0) {
-        if (strcasecmp(p, "1")    == 0  ||
-            strcasecmp(p, "ON")   == 0  ||
-            strcasecmp(p, "YES")  == 0  ||
-            strcasecmp(p, "TRUE") == 0  ||
-            strcasecmp(p, "SOME") == 0  ||
-            strcasecmp(p, "DATA") == 0) {
+    ConnNetInfo_GetValue(0, REG_CONN_DEBUG_PRINTOUT, val, sizeof(val),
+                         DEF_CONN_DEBUG_PRINTOUT);
+    if (ConnNetInfo_Boolean(val)
+        ||  (*val  &&  (strcasecmp(val, "all")  == 0  ||
+                        strcasecmp(val, "some") == 0  ||
+                        strcasecmp(val, "data") == 0))) {
             SOCK_SetDataLoggingAPI(eOn);
         }
-    }
 
     if (argc > 1) {
         CORE_LOG(eLOG_Note, "Special test requested");
@@ -289,6 +287,7 @@ int main(int argc, const char* argv[])
         CORE_LOG(eLOG_Fatal, "Test failed");
     CORE_LOGF(eLOG_Note, ("Test passed: %s", retval));
 
-    CORE_LOG(eLOG_Note, "Test completed");
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
+    CORE_SetLOG(0);
     return 0;
 }
diff --git a/connect/test/test_ncbi_service_connector.c b/connect/test/test_ncbi_service_connector.c
index 04492d4..b39b256 100644
--- a/connect/test/test_ncbi_service_connector.c
+++ b/connect/test/test_ncbi_service_connector.c
@@ -1,4 +1,4 @@
-/*  $Id: test_ncbi_service_connector.c,v 6.37 2006/04/23 18:28:44 lavr Exp $
+/* $Id: test_ncbi_service_connector.c,v 6.41 2010/07/12 18:39:31 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,9 +30,9 @@
  *
  */
 
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_priv.h"
 #include <connect/ncbi_service_connector.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <stdlib.h>
 #include <time.h>
 /* This header must go last */
@@ -42,7 +42,6 @@
 int main(int argc, const char* argv[])
 {
     const char* service = argc > 1 && *argv[1] ? argv[1] : "bounce";
-    const char* host = argc > 2 && *argv[2] ? argv[2] : "www.ncbi.nlm.nih.gov";
     static char obuf[8192 + 2];
     SConnNetInfo* net_info;
     CONNECTOR connector;
@@ -59,13 +58,11 @@ int main(int argc, const char* argv[])
     CORE_SetLOGFILE(stderr, 0/*false*/);
 
     net_info = ConnNetInfo_Create(service);
-    strcpy(net_info->host, host);
-    if (argc > 3) {
-        strncpy0(obuf, argv[3], sizeof(obuf) - 2);
-        obuf[n = strlen(obuf)] = '\n';
-        obuf[++n]              = 0;
-    }
-    strcpy(net_info->args, "testarg=val&service=none&platform=none&address=2");
+    ConnNetInfo_AppendArg(net_info, "testarg",  "val");
+    ConnNetInfo_AppendArg(net_info, "service",  "none");
+    ConnNetInfo_AppendArg(net_info, "platform", "none");
+    ConnNetInfo_AppendArg(net_info, "address",  "2010");
+    ConnNetInfo_LogEx(net_info, eLOG_Note, CORE_GetLOG());
 
     connector = SERVICE_CreateConnectorEx(service, fSERV_Any, net_info, 0);
 
@@ -75,7 +72,10 @@ int main(int argc, const char* argv[])
     if (CONN_Create(connector, &conn) != eIO_Success)
         CORE_LOG(eLOG_Fatal, "Failed to create connection");
 
-    if (argc > 3) {
+    if (argc > 2) {
+        strncpy0(obuf, argv[2], sizeof(obuf) - 2);
+        obuf[n = strlen(obuf)] = '\n';
+        obuf[++n]              = '\0';
         if (CONN_Write(conn, obuf, strlen(obuf), &n, eIO_WritePersist)
             != eIO_Success) {
             CONN_Close(conn);
@@ -86,7 +86,7 @@ int main(int argc, const char* argv[])
         for (n = 0; n < 10; n++) {
             size_t m;
             for (m = 0; m < sizeof(obuf) - 2; m++)
-                obuf[m] = "01234567890\n"[rand() % 12];
+                obuf[m] = "0123456789\n"[rand() % 11];
             obuf[m++] = '\n';
             obuf[m]   = '\0';
 
@@ -111,7 +111,8 @@ int main(int argc, const char* argv[])
         status = CONN_Read(conn, ibuf, sizeof(ibuf), &n, eIO_ReadPersist);
         if (n) {
             char* descr = CONN_Description(conn);
-            CORE_DATAF(ibuf, n, ("%lu bytes read from service (%s%s%s):",
+            CORE_DATAF_EX(eLOG_Note, ibuf, n,
+                          ("%lu bytes read from service (%s%s%s):",
                                  (unsigned long) n, CONN_GetType(conn),
                                  descr ? ", " : "", descr ? descr : ""));
             if (descr)
@@ -157,124 +158,7 @@ int main(int argc, const char* argv[])
     CONN_Close(conn);
 #endif
 
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
     CORE_SetLOG(0);
     return 0/*okay*/;
 }
-
-
-/*
- * --------------------------------------------------------------------------
- * $Log: test_ncbi_service_connector.c,v $
- * Revision 6.37  2006/04/23 18:28:44  lavr
- * Do not destroy SConnNetInfo prematurely; timeout is still in use
- *
- * Revision 6.36  2006/04/20 14:01:58  lavr
- * Cleanup to demonstrate no leaks; use short diag format
- *
- * Revision 6.35  2006/01/12 18:13:36  lavr
- * Add arguments to show that they must be replaced by standard ones
- *
- * Revision 6.34  2005/07/15 21:16:03  lavr
- * Fix int<->size_t mismatch bug causing 64-bit builds to check lamely
- *
- * Revision 6.33  2005/07/11 18:25:36  lavr
- * Spell ADDEND; better testing w/o ugly hardcoded pattern
- *
- * Revision 6.32  2005/05/02 16:12:43  lavr
- * Use global random seed
- *
- * Revision 6.31  2005/01/28 17:44:48  lavr
- * Fix:  forgotten to merge status variable relocation
- *
- * Revision 6.30  2005/01/28 17:41:22  lavr
- * Allow CONN_TIMEOUT from the environment to be used in Wait-on-Read
- *
- * Revision 6.29  2004/02/23 15:23:43  lavr
- * New (last) parameter "how" added in CONN_Write() API call
- *
- * Revision 6.28  2003/10/21 11:37:47  lavr
- * Set write timeout from the environment/registry instead of explicitly
- *
- * Revision 6.27  2003/07/24 16:38:59  lavr
- * Add conditional check for early connection drops (#if 0'd)
- *
- * Revision 6.26  2003/05/29 18:03:49  lavr
- * Extend read error message with a reason (if any)
- *
- * Revision 6.25  2003/05/14 03:58:43  lavr
- * Match changes in respective APIs of the tests
- *
- * Revision 6.24  2003/05/05 20:31:23  lavr
- * Add date/time stamp to each log message printed
- *
- * Revision 6.23  2003/04/04 21:01:06  lavr
- * Modify readout procedure
- *
- * Revision 6.22  2002/10/28 15:47:12  lavr
- * Use "ncbi_ansi_ext.h" privately and use strncpy0()
- *
- * Revision 6.21  2002/09/24 15:10:09  lavr
- * Fix test not to dereference NULL pointer resulting from failed connection
- *
- * Revision 6.20  2002/08/07 16:38:08  lavr
- * EIO_ReadMethod enums changed accordingly; log moved to end
- *
- * Revision 6.19  2002/03/22 19:47:41  lavr
- * Test_assert.h made last among the include files
- *
- * Revision 6.18  2002/03/21 22:02:16  lavr
- * Change default server from "ray" into "www.ncbi.nlm.nih.gov"
- *
- * Revision 6.17  2002/02/05 21:45:55  lavr
- * Included header files rearranged
- *
- * Revision 6.16  2002/01/16 21:23:15  vakatov
- * Utilize header "test_assert.h" to switch on ASSERTs in the Release mode too
- *
- * Revision 6.15  2001/09/24 20:36:22  lavr
- * Adjusted parameters in SERVICE_CreateConnectorEx()
- *
- * Revision 6.14  2001/06/11 22:17:28  lavr
- * Wait-for-reading timeout made finite
- *
- * Revision 6.13  2001/06/07 17:53:47  lavr
- * Persistent reading from test connection
- *
- * Revision 6.12  2001/06/01 16:19:10  lavr
- * Added (ifdef'ed out) an internal test connection to service ID1
- *
- * Revision 6.11  2001/05/11 16:05:41  lavr
- * Change log message corrected
- *
- * Revision 6.10  2001/05/11 15:38:01  lavr
- * Print connector type along with read data
- *
- * Revision 6.9  2001/04/24 21:42:43  lavr
- * Brushed code to use CORE_LOG facility only.
- *
- * Revision 6.8  2001/01/25 17:13:22  lavr
- * Added: close/free everything on program exit: useful to check memory leaks
- *
- * Revision 6.7  2001/01/23 23:22:34  lavr
- * debug_printout was given an enum value (instead of "boolean" 1)
- *
- * Revision 6.6  2001/01/09 15:35:20  lavr
- * Removed header <unistd.h>, unknown on WinNT
- *
- * Revision 6.5  2001/01/08 23:13:19  lavr
- * C/C++ -> C only
- *
- * Revision 6.4  2001/01/08 22:42:42  lavr
- * Further development of the test-suite
- *
- * Revision 6.3  2001/01/03 22:40:24  lavr
- * Minor adjustment
- *
- * Revision 6.2  2000/12/29 18:25:27  lavr
- * More tests added (still not yet complete).
- *
- * Revision 6.1  2000/10/20 17:31:07  lavr
- * Initial revision
- *
- * ==========================================================================
- */
diff --git a/connect/test/test_ncbi_socket.c b/connect/test/test_ncbi_socket.c
index 7be2e87..f1a64ad 100644
--- a/connect/test/test_ncbi_socket.c
+++ b/connect/test/test_ncbi_socket.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_socket.c,v 6.40 2009/05/04 15:54:29 kazimird Exp $
+/* $Id: test_ncbi_socket.c,v 6.53 2010/06/10 19:19:46 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,16 +30,8 @@
  *
  */
 
-#include "../ncbi_config.h"
-#include "../ncbi_priv.h"
-
-/* OS must be specified in the command-line ("-D....") or in the conf. header
- */
-#if !defined(NCBI_OS_UNIX) && !defined(NCBI_OS_MSWIN)
-#  error "Unknown OS, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN!"
-#endif
-
 #include <connect/ncbi_socket.h>
+#include "../ncbi_priv.h"               /* CORE logging facilities */
 #include <stdlib.h>
 #include <string.h>
 #if defined(NCBI_OS_UNIX)
@@ -54,6 +46,12 @@
 /* This header must go last */
 #include "test_assert.h"
 
+/* OS must be specified in the command-line ("-D....") or in the conf. header
+ */
+#if !defined(NCBI_OS_UNIX) && !defined(NCBI_OS_MSWIN)
+#  error "Unknown OS, must be one of NCBI_OS_UNIX, NCBI_OS_MSWIN!"
+#endif
+
 #define MIN_PORT 4096
 #define DEF_PORT 5555
 #define DEF_HOST "localhost"
@@ -124,7 +122,6 @@ static void TEST__client_1(SOCK sock)
     assert(SOCK_Status(sock, eIO_Read) == eIO_Success);
     assert(strcmp(buf, s_S1) == 0);
 
-    SOCK_SetDataLoggingAPI(eDefault);
     SOCK_SetDataLogging(sock, eDefault);
 
     /* Send a very big binary blob */
@@ -249,7 +246,6 @@ static void TEST__server_1(SOCK sock)
                            &n_io_done, eIO_ReadPersist);
         assert(status == eIO_Success  &&  n_io_done == DO_LOG_SIZE);
         SOCK_SetDataLogging(sock, eDefault);
-        SOCK_SetDataLoggingAPI(eDefault);
 
         for (n_io = 0;  n_io < BIG_BLOB_SIZE;  n_io++)
             assert(blob[n_io] == (unsigned char) n_io);
@@ -258,8 +254,6 @@ static void TEST__server_1(SOCK sock)
 
     /* Receive a very big binary blob, and write data back */
     {{
-#define DO_LOG_SIZE    300
-#define DONT_LOG_SIZE  BIG_BLOB_SIZE - DO_LOG_SIZE
         unsigned char* blob = (unsigned char*) malloc(BIG_BLOB_SIZE);
         int i;
         for (i = 0;  i < 10;  i++) {
@@ -300,13 +294,13 @@ static void TEST__server_1(SOCK sock)
  *      "TEST__server_2(SOCK sock)"
  */
 
-static void s_DoubleTimeout(STimeout *to) {
-    if (!to->sec  &&  !to->usec) {
-        to->usec = 1;
-    } else {
-        to->sec   = 2 * to->sec + (2 * to->usec) / 1000000;
+static void s_DoubleTimeout(STimeout *to)
+{
+    if (to->sec | to->usec) {
+        to->sec  = (2 * to->usec) / 1000000 + 2 * to->sec;
         to->usec = (2 * to->usec) % 1000000;
-    }
+    } else
+        to->usec = 1;
 }
 
 
@@ -320,7 +314,9 @@ static void TEST__client_2(SOCK sock)
     size_t     n_io, n_io_done, i;
     char       buf[W_FIELD * N_FIELD + 1];
 
-    CORE_LOG(eLOG_Note, "TEST__client_2(TC2)");
+    CORE_LOGF(eLOG_Note,
+              ("TEST__client_2(TC2) @:%hu",
+               SOCK_GetLocalPort(sock, eNH_HostByteOrder)));
 
     /* fill out a buffer to send to server */
     memset(buf, 0, sizeof(buf));
@@ -333,7 +329,7 @@ static void TEST__client_2(SOCK sock)
         char        buf1[sizeof(buf)];
         STimeout    w_to, r_to;
         int/*bool*/ w_timeout_on = (int)(i%2); /* if to start from     */
-        int/*bool*/ r_timeout_on = (int)(i%3); /* zero or inf. timeout */
+        int/*bool*/ r_timeout_on = (int)(i%2); /* zero or inf. timeout */
         char*       x_buf;
 
         /* set timeout */
@@ -347,9 +343,12 @@ static void TEST__client_2(SOCK sock)
         if ((i % N_RECONNECT) == 0) {
             size_t j = i / N_RECONNECT;
             do {
+                SOCK_SetDataLogging(sock, eOn);
                 status = SOCK_Reconnect(sock, 0, 0, 0);
+                SOCK_SetDataLogging(sock, eDefault);
                 CORE_LOGF(eLOG_Note,
-                          ("TEST__client_2::reconnect: i=%lu, j=%lu, status=%s",
+                          ("TC2::reconnect @:%hu: i=%lu, j=%lu, status=%s",
+                           SOCK_GetLocalPort(sock, eNH_HostByteOrder),
                            (unsigned long) i, (unsigned long) j,
                            IO_StatusStr(status)));
                 assert(status == eIO_Success);
@@ -375,11 +374,10 @@ static void TEST__client_2(SOCK sock)
             CORE_LOGF(eLOG_Note,
                       ("TC2::write:"
                        " i=%d, status=%7s, n_io=%5lu, n_io_done=%5lu"
-                       " timeout(%d): %5lu sec, %6lu msec",
-                       (int)i, IO_StatusStr(status),
-                       (unsigned long)n_io, (unsigned long)n_io_done,
-                       (int)w_timeout_on,
-                       (unsigned long)w_to.sec, (unsigned long)w_to.usec));
+                       " timeout(%d): %5u.%06us",
+                       (int) i, IO_StatusStr(status),
+                       (unsigned long) n_io, (unsigned long) n_io_done,
+                       (int) w_timeout_on, w_to.sec, w_to.usec));
             if ( !w_timeout_on ) {
                 assert(status == eIO_Success  &&  n_io_done == n_io);
             } else {
@@ -400,7 +398,7 @@ static void TEST__client_2(SOCK sock)
         /* get back the just sent data */
         r_to.sec  = 0;
         r_to.usec = 0;
-        status = SOCK_SetTimeout(sock, eIO_Read, (r_timeout_on ? &r_to : 0));
+        status = SOCK_SetTimeout(sock, eIO_Read, r_timeout_on ? &r_to : 0);
         assert(status == eIO_Success);
 
         x_buf = buf1;
@@ -424,12 +422,12 @@ static void TEST__client_2(SOCK sock)
                 CORE_LOG(eLOG_Fatal, "TC2::read: connection closed");
             }
             CORE_LOGF(eLOG_Note,
-                      ("TC2::read:"
+                      ("TC2::read: "
                        " i=%d, status=%7s, n_io=%5lu, n_io_done=%5lu"
-                       " timeout(%d): %5u sec, %6u usec",
-                       (int)i, IO_StatusStr(status),
-                       (unsigned long)n_io, (unsigned long)n_io_done,
-                       (int)r_timeout_on, r_to.sec, r_to.usec));
+                       " timeout(%d): %5u.%06us",
+                       (int) i, IO_StatusStr(status),
+                       (unsigned long) n_io, (unsigned long) n_io_done,
+                       (int) r_timeout_on, r_to.sec, r_to.usec));
             if ( !r_timeout_on ) {
                 assert(status == eIO_Success  &&  n_io_done > 0);
             } else {
@@ -593,6 +591,8 @@ static void TEST__client(const char*     server_host,
     /* Connect to server */
     status = SOCK_Create(server_host, server_port, timeout, &sock);
     assert(status == eIO_Success);
+    verify(SOCK_SetTimeout(sock, eIO_ReadWrite, timeout) == eIO_Success);
+    verify(SOCK_SetTimeout(sock, eIO_Close,     timeout) == eIO_Success);
 
     /* Test the simplest randezvous(plain request-reply)
      * The two peer functions are:
@@ -610,7 +610,7 @@ static void TEST__client(const char*     server_host,
     status = SOCK_Close(sock);
     assert(status == eIO_Success  ||  status == eIO_Closed);
 
-    CORE_LOG(eLOG_Note, "TEST COMPLETED");
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
 }
 
 
@@ -636,8 +636,6 @@ static void TEST__server(unsigned short port)
         assert(status == eIO_Success);
 
         assert(SOCK_GetPeerAddressString  (sock, full,sizeof(full)));
-        SOCK_GetPeerAddressStringEx(sock, addr,sizeof(addr),eSAF_IP);
-        printf("ADDR = %s\n", addr);
         assert(SOCK_GetPeerAddressStringEx(sock, addr,sizeof(addr),eSAF_IP));
         assert(SOCK_GetPeerAddressStringEx(sock, port,sizeof(port),eSAF_Port));
         assert(strcmp(full, strcat(strcat(addr, ":"), port)) == 0);
@@ -917,14 +915,6 @@ extern int main(int argc, char** argv)
     argc = 3;
 #endif
 
-    /* Printout local hostname */
-    {{
-        char local_host[64];
-        assert(SOCK_gethostname(local_host, sizeof(local_host)) == 0);
-        CORE_LOGF(eLOG_Note,
-                  ("Running NCBISOCK test on host \"%s\"", local_host));
-    }}
-
     /* Parse cmd.-line args and decide whether it's a client or a server
      */
     switch ( argc ) {
@@ -936,10 +926,24 @@ extern int main(int argc, char** argv)
         CORE_SetLOCK(0);
         CORE_SetLOCK( MT_LOCK_Create(&TEST_LockUserData,
                                      TEST_LockHandler, TEST_LockCleanup) );
+
+        SOCK_SetDataLoggingAPI(eOn);
+        assert(SOCK_InitializeAPI() == eIO_Success);
+        SOCK_SetDataLoggingAPI(eOff);
+
+        {{
+            char local_host[64];
+            assert(SOCK_gethostname(local_host, sizeof(local_host)) == 0);
+            CORE_LOGF(eLOG_Note,
+                      ("Running NCBISOCK test on host \"%s\"", local_host));
+        }}
+
         TEST_gethostby();
 
         TEST_SOCK_isip();
 
+        assert(SOCK_ShutdownAPI() == eIO_Success);
+
         CORE_SetLOCK(0);
         break;
 
diff --git a/connect/test/test_ncbi_socket_connector.c b/connect/test/test_ncbi_socket_connector.c
index f21f68b..72ecd79 100644
--- a/connect/test/test_ncbi_socket_connector.c
+++ b/connect/test/test_ncbi_socket_connector.c
@@ -1,4 +1,4 @@
-/* $Id: test_ncbi_socket_connector.c,v 6.11 2009/04/10 23:04:30 kazimird Exp $
+/* $Id: test_ncbi_socket_connector.c,v 6.13 2010/02/05 20:35:05 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -30,11 +30,11 @@
  *
  */
 
-#include "ncbi_conntest.h"
-#include "../ncbi_ansi_ext.h"
-#include "../ncbi_priv.h"
 #include <connect/ncbi_socket_connector.h>
 #include <connect/ncbi_connutil.h>
+#include "../ncbi_ansi_ext.h"
+#include "../ncbi_priv.h"               /* CORE logging facilities */
+#include "ncbi_conntest.h"
 #include <stdlib.h>
 /* This header must go last */
 #include "test_assert.h"
@@ -71,13 +71,14 @@ int main(int argc, const char* argv[])
     char          tmo[32];
     SOCK          sock;
 
-    /* registry */
-    CORE_SetREG(REG_Create(0, s_REG_Get, 0, 0, 0));
     /* log and data log streams */
     CORE_SetLOGFormatFlags(fLOG_None          | fLOG_Level   |
                            fLOG_OmitNoteLevel | fLOG_DateTime);
     CORE_SetLOGFILE(stderr, 0/*false*/);
 
+    /* registry */
+    CORE_SetREG(REG_Create(0, s_REG_Get, 0, 0, 0));
+
     assert((net_info = ConnNetInfo_Create(0)) != 0);
 
     /* parse cmd.-line args */
@@ -170,7 +171,9 @@ int main(int argc, const char* argv[])
     /* cleanup, exit */
     ConnNetInfo_Destroy(net_info);
     fclose(data_file);
-    CORE_SetLOG(0);
     CORE_SetREG(0);
+
+    CORE_LOG(eLOG_Note, "TEST completed successfully");
+    CORE_SetLOG(0);
     return 0/*okay*/;
 }
diff --git a/connect/urlquery.c b/connect/urlquery.c
index a56b5db..7d9c52c 100644
--- a/connect/urlquery.c
+++ b/connect/urlquery.c
@@ -1,4 +1,4 @@
-/* $Id: urlquery.c,v 6.40 2006/10/17 02:19:07 lavr Exp $
+/* $Id: urlquery.c,v 6.49 2009/09/24 14:58:19 lavr Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -29,13 +29,40 @@
  *
  * Version Creation Date:   4/16/98
  *
- * $Revision: 6.40 $
+ * $Revision: 6.49 $
  *
  * File Description: 
  *
  * Modifications:  
  * --------------------------------------------------------------------------
  * $Log: urlquery.c,v $
+ * Revision 6.49  2009/09/24 14:58:19  lavr
+ * Fix timeout comparison bug
+ *
+ * Revision 6.48  2009/09/22 13:46:33  lavr
+ * Speedup queue insertion
+ *
+ * Revision 6.47  2009/09/21 20:38:30  lavr
+ * Properly treat timeout settings
+ *
+ * Revision 6.46  2009/09/18 19:58:40  lavr
+ * +QUERY_QueueSize()
+ *
+ * Revision 6.45  2009/09/12 01:28:49  lavr
+ * Correct comment in setting HTTP header
+ *
+ * Revision 6.44  2009/08/14 19:02:44  lavr
+ * x_SetupUserHeader() to override C-T only and to extend User-Agent
+ *
+ * Revision 6.43  2009/08/14 18:14:43  lavr
+ * Formatting
+ *
+ * Revision 6.42  2009/08/14 18:04:53  lavr
+ * StringHasText->StringDoesHaveText
+ *
+ * Revision 6.41  2009/08/14 18:02:24  lavr
+ * Use GetProgramName() when setting HTTP user-header
+ *
  * Revision 6.40  2006/10/17 02:19:07  lavr
  * Use "const char*" wherever appropriate
  *
@@ -169,6 +196,45 @@ NLM_EXTERN void QUERY_WaitForNextMacEvent (void)
 #endif
 
 
+/* Set HTTP user header */
+static void x_SetupUserHeader (
+  SConnNetInfo*  net_info,
+  const char*    appName,
+  EMIME_Type     type,
+  EMIME_SubType  subtype,
+  EMIME_Encoding encoding
+)
+{
+  const char* userAgentName = NULL;
+  char        user_header [MAX_CONTENT_TYPE_LEN + 80];
+
+  /* content-type if specified */
+  if (type < eMIME_T_Unknown) {
+    VERIFY( MIME_ComposeContentTypeEx (type, subtype, encoding,
+                                       user_header, MAX_CONTENT_TYPE_LEN) );
+    ConnNetInfo_OverrideUserHeader (net_info, user_header);
+  }
+
+  /* allow the user to specify a prog. name, otherwise get it from elsewhere */
+  if (StringHasNoText (appName)) {
+    const char* progName = GetProgramName();
+    if (StringHasNoText (progName)) {
+      char path [PATH_MAX];
+      Nlm_ProgramPath (path, sizeof (path));
+      userAgentName = StringRChr (path, DIRDELIMCHR);
+      if (userAgentName)
+        ++userAgentName;
+    } else
+      userAgentName = progName;
+  } else
+    userAgentName = appName;
+  if (StringDoesHaveText (userAgentName)) {
+    sprintf (user_header, "User-Agent: %.80s\r\n", userAgentName);
+    ConnNetInfo_ExtendUserHeader (net_info, user_header);
+  }
+}
+
+
 NLM_EXTERN CONN QUERY_OpenUrlQuery (
   const char* host_machine,
   Nlm_Uint2 host_port,
@@ -184,67 +250,47 @@ NLM_EXTERN CONN QUERY_OpenUrlQuery (
 {
   CONN           conn;
   CONNECTOR      connector;
-  char           contentType [MAX_CONTENT_TYPE_LEN];
-  SConnNetInfo*  info;
-  char           path [PATH_MAX];
+  SConnNetInfo*  net_info;
   EIO_Status     status;
-  const char*    userAgentName = NULL;
-  char           user_header [sizeof(contentType) + 256];
 
   if (StringHasNoText (host_path))
     return NULL;
 
-  /* allow the user to specify a prog. name, otherwise get from ProgramPath */
-  if (! StringHasNoText (appName)) {
-    userAgentName = appName;
-  } else {
-    Nlm_ProgramPath (path, sizeof (path));
-    userAgentName = StringRChr (path, DIRDELIMCHR);
-    if (userAgentName != NULL) {
-      userAgentName++;
-    }
-  }
-  if (StringHasNoText (userAgentName)) {
-    userAgentName = "?";
-  }
-
-  contentType [0] = '\0';
-  if (type < eMIME_T_Unknown) {
-    VERIFY( MIME_ComposeContentTypeEx (type, subtype, encoding,
-                                       contentType, sizeof(contentType)) );
-  }
-
-  /* set HTML header with program name as user agent */
-  sprintf (user_header, "%sUser-Agent: %s\r\n", contentType, userAgentName);
-
   /* fill in connection info fields and create the connection */
-  info = ConnNetInfo_Create(0);
-  ASSERT ( info );
+  net_info = ConnNetInfo_Create(0);
+  ASSERT ( net_info );
+
+  x_SetupUserHeader (net_info, appName, type, subtype, encoding);
 
-  if (! StringHasNoText (host_machine)) {
-    StringNCpy_0 (info->host, host_machine, sizeof(info->host));
+  if (StringDoesHaveText (host_machine)) {
+    StringNCpy_0 (net_info->host, host_machine, sizeof (net_info->host));
   }
   if ( host_port ) {
-    info->port = host_port;
+    net_info->port = host_port;
   }
-  if ( !StringHasNoText (arguments)) {
-    StringNCpy_0 (info->args, arguments, sizeof(info->args));
+  StringNCpy_0 (net_info->path, host_path, sizeof (net_info->path));
+  if (StringDoesHaveText (arguments)) {
+    StringNCpy_0 (net_info->args, arguments, sizeof (net_info->args));
   }
-  StringNCpy_0 (info->path, host_path, sizeof(info->path));
 
-  if ( info->timeout ) {
-    info->timeout->sec  = timeoutsec;
-    info->timeout->usec = 0;
+  if (timeoutsec == (Nlm_Uint4)(-1L)) {
+    net_info->timeout       = 0;
+  } else if ( timeoutsec ) {
+    net_info->timeout       = &net_info->tmo;
+    net_info->timeout->sec  = timeoutsec;
+    net_info->timeout->usec = 0;
   }
 
-  connector = HTTP_CreateConnector (info, user_header, flags);
-  ConnNetInfo_Destroy (info);
+  connector = HTTP_CreateConnector (net_info, NULL, flags);
+
+  ConnNetInfo_Destroy (net_info);
 
   if (connector == NULL) {
     ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenUrlQuery failed in HTTP_CreateConnector");
     conn = NULL;
-  } else if ((status = CONN_Create(connector, &conn)) != eIO_Success) {
-    ErrPostEx(SEV_ERROR, 0, 0, "QUERY_OpenUrlQuery failed in CONN_Create");
+  } else if ((status = CONN_Create (connector, &conn)) != eIO_Success) {
+    ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenUrlQuery failed in CONN_Create: %s",
+              IO_StatusStr (status));
     ASSERT (conn == NULL);
   }
 
@@ -261,22 +307,27 @@ NLM_EXTERN CONN QUERY_OpenServiceQueryEx (
 {
   CONN           conn;
   CONNECTOR      connector;
-  size_t         n_written;
   SConnNetInfo*  net_info;
+  size_t         n_written;
   EIO_Status     status;
 
   /* fill in connection info fields and create the connection */
   net_info = ConnNetInfo_Create (service);
   ASSERT ( net_info );
 
-  if (timeoutsec == (Nlm_Uint4)(-1)) {
+  /* let the user agent be set with a program name */
+  x_SetupUserHeader (net_info,
+                     NULL, eMIME_T_Unknown, eMIME_Unknown, eENCOD_None);
+
+  if (timeoutsec == (Nlm_Uint4)(-1L)) {
     net_info->timeout  = 0;
   } else if ( timeoutsec ) {
-    net_info->tmo.sec  = timeoutsec;
-    net_info->tmo.usec = 0;
     net_info->timeout  = &net_info->tmo;
+    net_info->timeout->sec  = timeoutsec;
+    net_info->timeout->usec = 0;
   }
-  ConnNetInfo_PostOverrideArg(net_info, arguments, 0);
+
+  ConnNetInfo_PostOverrideArg (net_info, arguments, 0);
 
   connector = SERVICE_CreateConnectorEx (service, fSERV_Any, net_info, 0);
 
@@ -286,12 +337,14 @@ NLM_EXTERN CONN QUERY_OpenServiceQueryEx (
     ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed in SERVICE_CreateConnectorEx");
     conn = NULL;
   } else if ((status = CONN_Create (connector, &conn)) != eIO_Success) {
-    ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed in CONN_Create");
+    ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed in CONN_Create:"
+               " %s", IO_StatusStr (status));
     ASSERT (conn == NULL);
-  } else if (! StringHasNoText (parameters)) {
-    status = CONN_Write (conn, parameters, StringLen (parameters), &n_written, eIO_WritePersist);
+  } else if (StringDoesHaveText (parameters)) {
+    status = CONN_Write (conn, parameters, StringLen (parameters),
+                         &n_written, eIO_WritePersist);
     if (status != eIO_Success) {
-      ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed to write service parameters in CONN_Write");
+      ErrPostEx (SEV_ERROR, 0, 0, "QUERY_OpenServiceQuery failed to write service parameters in CONN_Write: %s", IO_StatusStr (status));
       CONN_Close (conn);
       conn = NULL;
     }
@@ -316,13 +369,13 @@ NLM_EXTERN EIO_Status QUERY_SendQuery (
 )
 
 {
-  static const STimeout timeout = { 0 };
+  static const STimeout kPollTimeout = { 0 };
   EIO_Status            status;
 
   if (conn == NULL) return eIO_Closed;
 
   /* flush buffer, sending query, without waiting for response */
-  status = CONN_Wait (conn, eIO_Read, &timeout);
+  status = CONN_Wait (conn, eIO_Read, &kPollTimeout);
   return status == eIO_Timeout ? eIO_Success : status;
 }
 
@@ -468,7 +521,8 @@ NLM_EXTERN void QUERY_AddToQueue (
 {
   QueuePtr       cqp;
   QueuePtr PNTR  qptr;
-  QueuePtr       tmp;
+
+  ASSERT (queue != NULL);
 
   if (conn == NULL || resultproc == NULL) return;
 
@@ -485,20 +539,8 @@ NLM_EXTERN void QUERY_AddToQueue (
 
   /* add to polling queue */
 
-  qptr = (QueuePtr PNTR) queue;
-  if (qptr != NULL) {
-    if (*qptr != NULL) {
-      tmp = *qptr;
-      if (tmp != NULL) {
-        while (tmp->next != NULL) {
-          tmp = tmp->next;
-        }
-        tmp->next = cqp;
-      }
-    } else {
+  for (qptr = (QueuePtr PNTR) queue;  *qptr != NULL;  qptr = &(*qptr)->next);
       *qptr = cqp;
-    }
-  }
 }
 
 
@@ -536,12 +578,12 @@ NLM_EXTERN Nlm_Int4 QUERY_CheckQueue (
   QUEUE* queue
 )
 {
+  static const STimeout kPollTimeout = { 0 };
   Nlm_Int4       count = 0;
   QueuePtr       curr;
   QueuePtr       next;
   QueuePtr PNTR  qptr;
   EIO_Status     status;
-  STimeout       timeout;
 
   qptr = (QueuePtr PNTR) queue;
   if (qptr == NULL || *qptr == NULL) return 0;
@@ -552,9 +594,7 @@ NLM_EXTERN Nlm_Int4 QUERY_CheckQueue (
     next = curr->next;
 
     if (curr->conn != NULL && (! curr->protect)) {
-      timeout.sec  = 0;
-      timeout.usec = 0;
-      status = CONN_Wait (curr->conn, eIO_Read, &timeout);
+      status = CONN_Wait (curr->conn, eIO_Read, &kPollTimeout);
 
       if (status == eIO_Success || status == eIO_Closed) {
         /* protect against reentrant calls if resultproc is GUI and processes timer */
@@ -579,6 +619,21 @@ NLM_EXTERN Nlm_Int4 QUERY_CheckQueue (
 }
 
 
+NLM_EXTERN Nlm_Int4 QUERY_QueueSize (
+  QUEUE queue
+)
+{
+  Nlm_Int4  count = 0;
+  QueuePtr  qptr;
+
+  for (qptr = (QueuePtr) queue;  qptr;  qptr = qptr->next) {
+    count++;
+  }
+
+  return count;
+}
+
+
 NLM_EXTERN void QUERY_CloseQueue (
   QUEUE* queue
 )
diff --git a/connect/urlquery.h b/connect/urlquery.h
index 92741a1..c11fab8 100644
--- a/connect/urlquery.h
+++ b/connect/urlquery.h
@@ -29,13 +29,16 @@
  *
  * Version Creation Date:   4/16/98
  *
- * $Revision: 6.16 $
+ * $Revision: 6.17 $
  *
  * File Description: 
  *
  * Modifications:  
  * --------------------------------------------------------------------------
  * $Log: urlquery.h,v $
+ * Revision 6.17  2009/09/18 19:58:40  lavr
+ * +QUERY_QueueSize()
+ *
  * Revision 6.16  2006/10/17 02:19:07  lavr
  * Use "const char*" wherever appropriate
  *
@@ -217,13 +220,20 @@ typedef Nlm_Boolean (LIBCALLBACK *QueryResultProc) (
   CONN conn, Nlm_VoidPtr userdata, EIO_Status status
 );
 
-/* Opaque handle type.  Variable must be kept by application and initialized
- * to NULL.
- */
+/* Opaque handle type.
+   Variable must be kept by application and initialized to NULL.
+*/
 struct SQueueTag;
 typedef struct SQueueTag* QUEUE;  /* queue handle */
 
 /*
+  Return number of currently queued connections.
+*/
+NLM_EXTERN Nlm_Int4 QUERY_QueueSize (
+  QUEUE q
+);
+
+/*
   Records connection, completion routine, and user data in queue.
 */
 NLM_EXTERN void QUERY_AddToQueue (
@@ -238,7 +248,7 @@ NLM_EXTERN void QUERY_AddToQueue (
   Checks queued connections (with CONN_Wait), calls completion routine, then
   removes query from queue and closes connection (if closeConn was TRUE).
   Application is responsible for calling QUERY_CheckQueue() every once in a
-  while, typically with a timer.
+  while, typically with a timer.  Returns the number of pending connections.
 */
 NLM_EXTERN Nlm_Int4 QUERY_CheckQueue (
   QUEUE* q
diff --git a/corelib/ncbiargs.c b/corelib/ncbiargs.c
index ea2f24d..8cc898f 100644
--- a/corelib/ncbiargs.c
+++ b/corelib/ncbiargs.c
@@ -35,6 +35,12 @@
 * Modifications:  
 * --------------------------------------------------------------------------
 * $Log: ncbiargs.c,v $
+* Revision 6.12  2009/08/17 19:42:08  lavr
+* Formatting
+*
+* Revision 6.11  2009/08/14 18:01:09  lavr
+* Use {Get|Set}ProgramName()
+*
 * Revision 6.10  2006/10/19 14:57:03  lavr
 * Fix repetitive arg error message to show no argument value since it's empty
 *
@@ -104,6 +110,9 @@ NLM_EXTERN Nlm_Boolean Nlm_GetArgs(const char* progname,
   Nlm_Int4     xx_argc = Nlm_GetArgc();
   char**       xx_argv = Nlm_GetArgv();
 
+  if (StringHasNoText(GetProgramName()))
+    SetProgramName(progname);
+
   if (!ap  ||  numargs <= 0)
     return FALSE;
 
diff --git a/corelib/ncbienv.c b/corelib/ncbienv.c
index d34b27d..f9e04ae 100644
--- a/corelib/ncbienv.c
+++ b/corelib/ncbienv.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/7/91
 *
-* $Revision: 6.46 $
+* $Revision: 6.49 $
 *
 * File Description:
 *       portable environment functions, companions for ncbimain.c
@@ -37,6 +37,16 @@
 * Modifications:
 * --------------------------------------------------------------------------
 * $Log: ncbienv.c,v $
+* Revision 6.49  2010/06/30 15:54:38  ucko
+* Handle 64-bit Darwin builds, which require disabling WIN_MAC because
+* Carbon is 32-bit-only.
+*
+* Revision 6.48  2009/08/17 19:56:13  lavr
+* Delete explicit cast from SetProgramName() argument
+*
+* Revision 6.47  2009/08/14 18:01:09  lavr
+* Use {Get|Set}ProgramName()
+*
 * Revision 6.46  2007/05/04 13:43:59  kans
 * GetOpSysString now checks for Windows VISTA
 *
@@ -1934,7 +1944,7 @@ static int    targc = 0;
 static char **targv = NULL;
 
 
-#if defined(WIN_MAC)
+#if defined(WIN_MAC) || defined(OS_UNIX_DARWIN)
 static FSSpec       apFileSpec;
 static Str255       apName;
 static Handle       apParam;
@@ -1955,7 +1965,7 @@ static Nlm_Boolean Nlm_SetupArguments_ST_Mac(void)
   Nlm_PtoCstr ((Nlm_Char*) apFileSpec.name);
   Nlm_PtoCstr ((Nlm_Char*) apName);
 
-  SetAppProperty("ProgramName",(void*)apName);
+  SetProgramName(apName);
 #endif
   return TRUE;
 }
@@ -2049,7 +2059,7 @@ static void Nlm_ProgramPath_ST(Nlm_Char* buf, size_t maxsize)
   }
 }
 #endif /* defined(OS_UNIX_DARWIN) */
-#endif /* defined(WIN_MAC) */
+#endif /* defined(WIN_MAC) || defined(OS_UNIX_DARWIN) */
 
 
 #if defined(OS_MSWIN) || defined(OS_VMS)
@@ -2147,9 +2157,7 @@ NLM_EXTERN Nlm_Boolean Nlm_ParseCmdLineArguments
     return FALSE;
 
   /* Figure out program name */
-  if ( !prog_name )
-    prog_name = (const char *) GetAppProperty("ProgramName");
-  if ( !prog_name )
+  if (!prog_name  &&  !(prog_name = GetProgramName()))
     prog_name = "";
 
   /* Special case -- no cmd.-line parameters */
@@ -2242,15 +2250,16 @@ NLM_EXTERN void Nlm_SetupArguments(int argc, char *argv[])
 {
   NlmMutexLockEx( &corelibMutex );
   wasSetup = TRUE;
-#if defined(WIN_MAC)
+#if defined(WIN_MAC) || defined(OS_UNIX_DARWIN)
   wasSetup = Nlm_SetupArguments_ST_Mac();
 #elif defined(OS_UNIX)
   {{
     char *p;
-    if ((p = strrchr(argv[0],DIRDELIMCHR)) != NULL)  p++;
+    if ((p = strrchr(argv[0],DIRDELIMCHR)) != NULL)
+      p++;
     else
       p = argv[0];
-    SetAppProperty("ProgramName", (void*)p);  
+    SetProgramName(p);
   }}
 #endif
   targc = argc;
@@ -2421,7 +2430,7 @@ NLM_EXTERN Nlm_CharPtr Nlm_GetOpSysString (void)
   int          mib [2];
   Nlm_Char     model [32];
 #endif
-  long         sysVer;
+  Nlm_Int4     sysVer;
 #endif
   Nlm_CharPtr  str = "unknown";
 
diff --git a/corelib/ncbierr.c b/corelib/ncbierr.c
index 0cd5f29..0429d86 100644
--- a/corelib/ncbierr.c
+++ b/corelib/ncbierr.c
@@ -23,9 +23,9 @@
 *
 * ===========================================================================
 *
-* $Id: ncbierr.c,v 6.25 2008/01/18 17:09:13 lavr Exp $
+* $Id: ncbierr.c,v 6.26 2009/08/14 18:01:09 lavr Exp $
 *
-* $Revision: 6.25 $
+* $Revision: 6.26 $
 *
 * Authors:  Schuler, Sirotkin (UserErr stuff)
 *
@@ -71,6 +71,9 @@
 * 03-06-95 Schuler     Fixed problem with ErrMsgRoot_fopen
 *
 * $Log: ncbierr.c,v $
+* Revision 6.26  2009/08/14 18:01:09  lavr
+* Use {Get|Set}ProgramName()
+*
 * Revision 6.25  2008/01/18 17:09:13  lavr
 * Use SEV_MIN (instead of explicit SEV_INFO) in level setting routines
 *
@@ -782,7 +785,7 @@ NLM_EXTERN int LIBCALL Nlm_ErrShow (void)
       if (severity >= info->opts.msg_level)
         {
           size_t bytes;
-          const char *caption = (char*)GetAppProperty("ProgramName");
+          const char *caption = GetProgramName();
           char *message;
           const char *msgtext;
           char *p;
diff --git a/corelib/ncbifile.c b/corelib/ncbifile.c
index 07edefe..5d0e47b 100644
--- a/corelib/ncbifile.c
+++ b/corelib/ncbifile.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   3/4/91
 *
-* $Revision: 6.41 $
+* $Revision: 6.42 $
 *
 * File Description: 
 *     portable file routines
@@ -110,7 +110,7 @@ static char * _this_file = __FILE__;
 **
 **	File:		MoreFilesExtras.c
 **
-**	Copyright © 1992-1999 Apple Computer, Inc.
+**	Copyright (c) 1992-1999 Apple Computer, Inc.
 **	All rights reserved.
 **
 **	You may incorporate this sample code into your applications without
@@ -1158,9 +1158,9 @@ NLM_EXTERN Nlm_Int4 Nlm_DirExplore (
           sprintf (file, "%s%s", str, suffix);
           Nlm_FileBuildPath (path, NULL, file);
 
-          /* check full path/file name for desired filter */
+          /* check file name (NOT full path) for desired filter */
 
-          if (Nlm_StringHasNoText (filter) || Nlm_StringStr (path, filter) != NULL) {
+          if (Nlm_StringHasNoText (filter) || Nlm_StringStr (file, filter) != NULL) {
 
             /* process file that satisfies optional filter and suffix constraints */
 
diff --git a/corelib/ncbilcl.lnx b/corelib/ncbilcl.lnx
index b4d22b5..46e2978 100644
--- a/corelib/ncbilcl.lnx
+++ b/corelib/ncbilcl.lnx
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   8/1/94
 *
-* $Revision: 6.10 $
+* $Revision: 6.11 $
 *
 * File Description:
 *		system dependent header
@@ -38,6 +38,9 @@
 * Modifications:
 * --------------------------------------------------------------------------
 * $Log: ncbilcl.lnx,v $
+* Revision 6.11  2010/05/21 16:40:19  lavr
+* _GNU_SOURCE -> ncbilcl.lnx
+*
 * Revision 6.10  2009/07/07 20:21:43  ucko
 * Don't bother with #cpu() or #machine() checks, which are redundant and
 * moreover yield noisy deprecation warnings with GCC 4.4.
@@ -139,6 +142,7 @@
 
 /* good for the EGCS C/C++ compiler on Linux(e.g. putenv(), tempnam() proto) */
 #define _SVID_SOURCE 1
+#define _GNU_SOURCE 1
 
 /*----------------------------------------------------------------------*/
 /*      #includes                                                       */
diff --git a/corelib/ncbimisc.c b/corelib/ncbimisc.c
index 8822c84..3568e99 100644
--- a/corelib/ncbimisc.c
+++ b/corelib/ncbimisc.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/23/91
 *
-* $Revision: 6.37 $
+* $Revision: 6.38 $
 *
 * File Description: 
 *   	miscellaneous functions
@@ -38,155 +38,6 @@
 * --------------------------------------------------------------------------
 * Date     Name        Description of modification
 * -------  ----------  -----------------------------------------------------
-* 04-15-93 Schuler     Changed _cdecl to LIBCALL
-* 06-15-93 Schuler     SGML functions moved to ncbisgml.c
-* 02-16-94 Epstein     Retired Gestalt functions and definitions
-*
-* $Log: ncbimisc.c,v $
-* Revision 6.37  2008/12/04 15:05:11  bollin
-* Added ValNodeInsert, which inserts a new ValNode into a sorted list at the
-* correct position.
-*
-* Revision 6.36  2008/09/11 20:30:37  bollin
-* Added ValNodePurge function.
-*
-* Revision 6.35  2008/07/21 20:15:22  bollin
-* Added ValNodeCompare function.
-*
-* Revision 6.34  2008/04/29 13:40:53  kans
-* fixes for warnings caught by mingw cross-compiler
-*
-* Revision 6.33  2008/04/04 13:15:48  bollin
-* Added ValNodeUnique function
-*
-* Revision 6.32  2006/11/09 17:47:16  kans
-* added ValNodeMergeStrs
-*
-* Revision 6.31  2006/10/17 14:16:48  lavr
-* ValNodeCopyStr() to take "const char*"
-*
-* Revision 6.30  2005/11/16 16:36:11  kans
-* support for PowerPC and Intel chips for Macintosh
-*
-* Revision 6.29  2005/04/13 21:36:18  kans
-* restored mac ifdefs around Nlm_P2Cstr and Nlm_C2Pstr functions
-*
-* Revision 6.28  2005/04/13 21:28:44  kans
-* Nlm_CtoPstr and Nlm_PtoCstr always uses our own code so we are not dependent on a particular version of Carbon
-*
-* Revision 6.27  2005/04/13 18:03:21  rsmith
-* On OSX don't define C2Pstr/P2Cstr, just implement Nlm_CtoPstr.
-*
-* Revision 6.26  2004/03/25 15:37:24  lavr
-* Change UINT64_MAX into UINT8_MAX back for the toolkit to compile portably
-*
-* Revision 6.25  2004/03/24 18:48:49  lebedev
-* Use UINT64_MAX in divray_init function
-*
-* Revision 6.24  2003/12/03 02:10:23  kans
-* added defines missing from Mac OS 10.3 headers
-*
-* Revision 6.23  2002/11/06 21:25:10  ucko
-* Don't assume MIPS is IRIX, or HPPA is HP/UX; allow Linux too, for both.
-*
-* Revision 6.22  2002/06/13 16:14:07  kans
-* fix includes for OS_UNIX_DARWIN with WIN_MAC (EN)
-*
-* Revision 6.21  2001/04/05 03:03:28  juran
-* Defined our own C2PStr() and P2Cstr() for use with Carbon (which omits them).
-*
-* Revision 6.20  2000/10/30 18:11:41  beloslyu
-* FreeBSD was added
-*
-* Revision 6.19  2000/08/28 18:41:29  vakatov
-* Added type cast in ValNodeSort() to pass C++ compilation
-*
-* Revision 6.18  2000/03/10 17:29:12  kans
-* changed divray to Uint8 - fix supplied by DDBJ for Cray computer
-*
-* Revision 6.17  1999/12/21 17:52:40  kans
-* removed MPW/THINKC conditional code, starting upgrade to Carbon compatibility - Churchill
-*
-* Revision 6.16  1999/07/29 15:58:48  kans
-* added bigintvalue, ValNodeAddBigInt (PD)
-*
-* Revision 6.15  1999/06/07 18:22:20  beloslyu
-* NetBSD port
-*
-* Revision 6.14  1999/04/23 18:00:15  beloslyu
-* change Uint4 to Nlm_Uint4 and CharPtr to Nlm_CharPtr
-*
-* Revision 6.13  1999/04/23 17:28:50  shavirin
-* Changed Uint4 to the Nlm_Uint4
-*
-* Revision 6.12  1999/04/23 16:10:26  shavirin
-* Added new function Nlm_GetChecksum() which calculates
-* checksum from given string
-*
-* Revision 6.11  1999/04/14 19:37:23  madden
-* Add Nlm_ prefix to Int8
-*
-* Revision 6.10  1999/04/14 15:31:06  madden
-* add Nlm_Int8tostr function
-*
-* Revision 6.9  1999/03/11 16:21:51  kans
-* ValNodeSort is more visible copy of jzmisc SortValNode
-*
-* Revision 6.8  1999/01/29 19:23:05  kans
-* use C2PStr and P2CStr from <TextUtils.h>
-*
-* Revision 6.7  1999/01/21 20:08:37  ostell
-* added SwitchUint2 and 4, added integer bytestores
-*
-* Revision 6.6  1999/01/07 15:20:57  victorov
-* added Nlm_ prefix to MD5 functions to avoid conflicts
-*
-* Revision 6.5  1999/01/06 22:49:26  victorov
-* added MD5 hash calculator
-*
-* Revision 6.4  1998/10/13 20:49:38  vakatov
-* + Nlm_PlatformName()
-*
-* Revision 6.3  1998/07/02 18:24:28  vakatov
-* Cleaned the code & made it pass through the C++ compilation
-*
-* Revision 6.2  1998/04/08 16:49:56  kans
-* ValNodeLen returns Int4
-*
-* Revision 6.1  1997/12/12 21:42:28  kans
-* Strings.h dragged in QuickDraw.h, so it is now out of the header
-*
-* Revision 6.0  1997/08/25 18:16:45  madden
-* Revision changed to 6.0
-*
-* Revision 5.4  1997/01/31 15:37:12  vakatov
-* ListSort():  replaced Boolean --> Nlm_Boolean
-*
- * Revision 5.3  1997/01/28  21:26:56  epstein
- * move doubly-linked list handling functions from ni_list.[ch]
- *
- * Revision 5.2  1996/12/10  16:09:16  kans
- * added ValNodeLen function
- *
- * Revision 5.1  1996/12/03  21:48:33  vakatov
- * Adopted for 32-bit MS-Windows DLLs
- *
- * Revision 5.0  1996/05/28  13:18:57  ostell
- * Set to revision 5.0
- *
- * Revision 4.2  1996/03/26  16:31:06  epstein
- * migrate byte-swapping functions to ncbimisc.[ch]
- *
- * Revision 4.1  1995/10/28  15:03:20  ostell
- * added casts to quiet DOS compile warnings
- *
- * Revision 4.0  1995/07/26  13:46:50  ostell
- * force revision to 4.0
- *
- * Revision 2.17  1995/05/15  18:45:58  ostell
- * added Log line
- *
-*
 *
 * ==========================================================================
 */
diff --git a/corelib/ncbimisc.h b/corelib/ncbimisc.h
index f268f95..a5e7df0 100644
--- a/corelib/ncbimisc.h
+++ b/corelib/ncbimisc.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/23/91
 *
-* $Revision: 6.20 $
+* $Revision: 6.21 $
 *
 * File Description:
 *   	prototypes of miscellaneous functions
@@ -38,100 +38,6 @@
 * --------------------------------------------------------------------------
 * Date     Name        Description of modification
 * -------  ----------  -----------------------------------------------------
-* 04-15-93 Schuler     Changed _cdecl to LIBCALL
-* 06-15-93 Schuler     SGML functions moved to ncbisgml.c
-* 06-15-93 Schuler     Added macros for Gestalt functins.
-*
-* $Log: ncbimisc.h,v $
-* Revision 6.20  2008/12/04 15:05:11  bollin
-* Added ValNodeInsert, which inserts a new ValNode into a sorted list at the
-* correct position.
-*
-* Revision 6.19  2008/09/11 20:30:37  bollin
-* Added ValNodePurge function.
-*
-* Revision 6.18  2008/07/21 20:15:22  bollin
-* Added ValNodeCompare function.
-*
-* Revision 6.17  2008/04/04 13:15:48  bollin
-* Added ValNodeUnique function
-*
-* Revision 6.16  2006/11/09 17:47:16  kans
-* added ValNodeMergeStrs
-*
-* Revision 6.15  2006/10/17 14:16:48  lavr
-* ValNodeCopyStr() to take "const char*"
-*
-* Revision 6.14  2002/12/17 16:45:09  kans
-* CtoPstr and PtoCstr if OS_MAC or OS_UNIX_DARWIN
-*
-* Revision 6.13  1999/09/22 23:08:26  kans
-* added extended flag to valnode for SeqDesc, maybe later SeqId and SeqLoc
-*
-* Revision 6.12  1999/07/29 15:58:48  kans
-* added bigintvalue, ValNodeAddBigInt (PD)
-*
-* Revision 6.11  1999/04/23 16:25:36  shavirin
-* Added definition of the function Nlm_GetChecksum()
-*
-* Revision 6.10  1999/04/14 19:37:23  madden
-* Add Nlm_ prefix to Int8
-*
-* Revision 6.9  1999/04/14 15:31:07  madden
-* add Nlm_Int8tostr function
-*
-* Revision 6.8  1999/03/11 16:21:51  kans
-* ValNodeSort is more visible copy of jzmisc SortValNode
-*
-* Revision 6.7  1999/01/27 01:59:52  kans
-* cleaned up comment problem
-*
-* Revision 6.6  1999/01/21 20:08:37  ostell
-* added SwitchUint2 and 4, added integer bytestores
-*
-* Revision 6.5  1999/01/07 20:18:51  victorov
-* MD5 functions declarations fixed
-*
-* Revision 6.4  1999/01/07 15:20:58  victorov
-* added Nlm_ prefix to MD5 functions to avoid conflicts
-*
-* Revision 6.3  1999/01/06 22:49:27  victorov
-* added MD5 hash calculator
-*
-* Revision 6.2  1998/10/13 20:49:40  vakatov
-* + Nlm_PlatformName()
-*
-* Revision 6.1  1998/04/08 16:49:59  kans
-* ValNodeLen returns Int4
-*
-* Revision 6.0  1997/08/25 18:16:49  madden
-* Revision changed to 6.0
-*
-* Revision 5.3  1997/01/28 21:26:51  epstein
-* move doubly-linked list handling functions from ni_list.[ch]
-*
- * Revision 5.2  1996/12/10  16:09:16  kans
- * added ValNodeLen function
- *
- * Revision 5.1  1996/12/03  21:48:33  vakatov
- * Adopted for 32-bit MS-Windows DLLs
- *
- * Revision 5.0  1996/05/28  13:18:57  ostell
- * Set to revision 5.0
- *
- * Revision 4.2  1996/03/27  15:45:53  epstein
- * make byte-swapping macros safer on big-endian systems
- *
- * Revision 4.1  1996/03/26  16:31:00  epstein
- * migrate byte-swapping functions to ncbimisc.[ch]
- *
- * Revision 4.0  1995/07/26  13:46:50  ostell
- * force revision to 4.0
- *
- * Revision 2.14  1995/05/15  18:45:58  ostell
- * added Log line
- *
-*
 *
 * ==========================================================================
 */
@@ -316,6 +222,12 @@ NLM_EXTERN void LIBCALL ValNodeInsert PROTO ((ValNodePtr PNTR list, ValNodePtr n
 NLM_EXTERN int LIBCALL ValNodeCompare PROTO ((ValNodePtr vnp1, ValNodePtr vnp2, int (LIBCALLBACK *compar) (VoidPtr, VoidPtr)));
 NLM_EXTERN Nlm_CharPtr LIBCALL ValNodeMergeStrs PROTO((ValNodePtr list));
 
+/* convenience structure for holding head and tail of ValNode list for efficient tail insertion */
+typedef struct valnodeblock {
+  ValNodePtr  head;
+  ValNodePtr  tail;
+} ValNodeBlock, PNTR ValNodeBlockPtr;
+
 /*** old prototypes ******
 NLM_EXTERN ValNodePtr LIBCALL ValNodeLink PROTO((ValNodePtr vnp, ValNodePtr newnode));
 NLM_EXTERN ValNodePtr LIBCALL ValNodeExtract PROTO((ValNodePtr PNTR headptr, Nlm_Uint1 choice));
diff --git a/corelib/ncbimsg.c b/corelib/ncbimsg.c
index cce9d8a..e92f8b1 100644
--- a/corelib/ncbimsg.c
+++ b/corelib/ncbimsg.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   2/13/91
 *
-* $Revision: 6.13 $
+* $Revision: 6.15 $
 *
 * File Description:
 *   	user alert and error messages
@@ -54,6 +54,12 @@
 *                      input will be read properly.
 *
 * $Log: ncbimsg.c,v $
+* Revision 6.15  2009/08/14 18:14:35  lavr
+* Heed a warning
+*
+* Revision 6.14  2009/08/14 18:01:09  lavr
+* Use {Get|Set}ProgramName()
+*
 * Revision 6.13  2008/04/04 20:36:46  kans
 * cast MessageBox to (MsgAnswer) in Windows version to silence CodeWarrior warning
 *
@@ -284,7 +290,7 @@ va_dcl
 NLM_EXTERN MsgAnswer CDECL Nlm_Message (Nlm_Int2 sevkey, const char *fmt, ...)
 #endif
 {
-  char *caption = (char*) GetAppProperty("ProgramName");
+  const char *caption = GetProgramName();
   MsgKey key = KEY_OK;
   ErrSev sev = SEV_INFO;
   MsgAnswer ans;
diff --git a/corelib/ncbiprop.h b/corelib/ncbiprop.h
index b3ec04e..606c7cc 100644
--- a/corelib/ncbiprop.h
+++ b/corelib/ncbiprop.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   06-04-93
 *
-* $Revision: 6.1 $
+* $Revision: 6.2 $
 *
 * File Description:
 *   	Application Property functions.
@@ -41,6 +41,9 @@
 * 06-14-94 Schuler     Added GetProgramName and SetProgramName macros
 *
 * $Log: ncbiprop.h,v $
+* Revision 6.2  2009/08/17 19:37:47  lavr
+* SetProgramName to use StringSave()
+*
 * Revision 6.1  2001/04/12 22:42:42  vakatov
 * Define #GetProgramName and #SetProgramName only if they have not
 * been defined yet
@@ -108,7 +111,8 @@ NLM_EXTERN long  LIBCALL Nlm_GetAppProcessID PROTO((void));
 #endif
 
 #if !defined(SetProgramName)
-#  define SetProgramName(x)  MemFree(SetAppProperty("ProgramName",(void*)(x)))
+#  define SetProgramName(x)  MemFree(SetAppProperty("ProgramName",  \
+                                                    (void*)StringSave(x)))
 #endif
 
 #ifdef __cplusplus
diff --git a/corelib/ncbistr.c b/corelib/ncbistr.c
index cc6f6eb..d0b3c23 100644
--- a/corelib/ncbistr.c
+++ b/corelib/ncbistr.c
@@ -29,147 +29,15 @@
 *
 * Version Creation Date:   3/4/91
 *
-* $Revision: 6.16 $
+* $Revision: 6.17 $
 *
 * File Description: 
 *   	portable string routines
 *
 * Modifications:  
 * --------------------------------------------------------------------------
-* $Log: ncbistr.c,v $
-* Revision 6.16  2006/10/17 02:02:31  lavr
-* Fix a typo
-*
-* Revision 6.15  2006/10/16 21:06:27  lavr
-* String{HasNo|DoesHave}Text() to accept const pointer
-*
-* Revision 6.14  2006/09/12 16:22:55  ludwigf
-* CHANGED: Internal logic on LabelCopy() to no longer touch memory outside
-*  the buffer it is given to operate on.
-* NOTE: This change was necessary as there are instances in the code calling
-*  that function that are not aware that LabelCopy() expects to also own
-*  the bytes adjacent to the given buffer range.
-*
-* Revision 6.13  2003/12/03 02:10:24  kans
-* added defines missing from Mac OS 10.3 headers
-*
-* Revision 6.12  2003/09/15 16:21:32  kans
-* moved StringDoesHaveText from sqnutils3.c
-*
-* Revision 6.11  2002/01/16 16:58:38  camacho
-* Changed type of buflen parameter in LabelCopy from Int2 to Uint4
-*
-* Revision 6.10  2001/01/05 22:43:58  shavirin
-* Added functions, that transfer Uint8 values to platform-independent
-* objects and back.
-*
-* Revision 6.9  2000/12/04 23:48:02  kans
-* trim spaces around string now handles trailing tabs, newlines, etc.
-*
-* Revision 6.8  2000/11/30 22:46:07  lavr
-* Added the following functions for conversions of Int8 and Uint8
-* to strings and back; test suite attached at the end of the file.
-* Nlm_Int8ToString, Nlm_Uint8ToString, Nlm_StringToInt8, Nlm_StringToUint8
-*
-* Revision 6.7  2000/08/28 18:36:25  vakatov
-* un-const casts in some functions to pass C++ compilation
-*
-* Revision 6.6  1999/04/15 20:24:06  vakatov
-* Dont use "list" name as it can clash with the standard "list<>" template
-* on some raw C++ compilers
-*
-* Revision 6.5  1999/03/11 16:10:00  kans
-* StringHasNoText and TrimSpacesAroundString moved from vibforms
-*
-* Revision 6.4  1998/11/23 00:09:47  kans
-* fixed bug in StringTokMT (found by Hugues)
-*
-* Revision 6.3  1998/10/07 19:09:00  kans
-* added Nlm_StringTokMT, multithread-safe version
-*
-* Revision 6.2  1997/11/26 21:26:25  vakatov
-* Fixed errors and warnings issued by C and C++ (GNU and Sun) compilers
-*
-* Revision 6.1  1997/10/29 02:44:52  vakatov
-* Type castings to pass through the C++ compiler
-*
-* Revision 5.5  1997/07/16 19:49:18  vakatov
-* Added Nlm_StringPrintable() function
-*
-* Revision 5.4  1997/04/11 17:57:25  brandon
-* added StrIPCmp, StrNIPCmp
-*
- * Revision 5.3  1997/03/04  22:01:12  vakatov
- * Added a set of functions to format(stream2text), unformat(text2stream)
- * and adjust(rule_line) text and test/demo code #TEST_TEXT_FMT for these
- *
- * Revision 5.2  1997/01/03  15:56:28  vakatov
- * Added auxiliary function Nlm_StringNCpy_0() -- that guarantees the
- * resulting string be '\0'-terminated
- *
- * Revision 5.1  1996/12/03  21:48:33  vakatov
- * Adopted for 32-bit MS-Windows DLLs
- *
- * Revision 4.12  1996/05/22  18:04:14  kans
- * changed nulls to '\0' in new string functions
- *
- * Revision 4.11  1996/05/22  14:46:19  brandon
- * Fixed SkipToString, SkipPastString to work with short strings
- *
- * Revision 4.10  1996/05/07  13:22:37  kans
- * more protection for stringsearch
- *
- * Revision 4.9  1996/05/06  15:07:58  kans
- * fixed StringISearch to set d [] based on TO_UPPER, not to crash if nonASCII
- *
- * Revision 4.8  1996/03/14  03:42:44  epstein
- * change String variables to theString to work around SGI4 problem
- *
- * Revision 4.7  1996/01/05  02:29:37  ostell
- * provided return value for TruncateStringCopy()
- *
- * Revision 4.6  1996/01/03  21:04:46  epstein
- * modify StringSubString() API and add other new functions, per Brandon
- *
- * Revision 4.5  1996/01/02  14:17:32  ostell
- * added a number of Brandons functions
- *
- * Revision 4.4  1995/12/28  15:41:56  epstein
- * added Brylawskin to revision history and author list
- *
- * Revision 4.3  1995/12/27  20:53:48  epstein
- * add Brandon's string-management functions
- *
- * Revision 4.2  1995/10/28  15:03:20  ostell
- * added casts to quiet DOS compile warnings
- *
- * Revision 4.1  1995/10/16  13:43:29  epstein
- * fix brain-dmanaged string-compare logic to handle null strings correctly
- *
- * Revision 2.12  1995/07/18  19:56:10  tatiana
- * add Nlm_LabelCopyNext()
- *
- * Revision 2.11  1995/05/30  13:19:37  kans
- * fixed StringSearch algorithm - check until i <= strLen, not just < strLen
- *
-* 3/4/91   Kans        Stricter typecasting for GNU C and C++.
-* 09-19-91 Schuler     Changed all types expressing sizes to size_t.
-* 09-19-91 Schuler     Changed return type for compare functions to int.
-* 09-19-91 Schuler     Changed all functions to _cdecl calling convention.
-* 09-19-91 Schuler     Where possible, NCBI functions call the actual ANSI
-*                       functions after checking for NULL pointers.
-* 09-19-91 Schuler     Debug-class error posted on any NULL argument.
-* 09-19-91 Schuler     StringSave() calls MemGet() instead of MemNew().
-* 09-19-91 Schuler     StringSave(NULL) returns NULL.
-* 10-17-91 Schuler     Removed ErrPost() calls on NULL arguments.
-* 10-17-91 Schuler     Added Nlm_StringCnt(),Nlm_StringStr(),Nlm_StringTok()
-* 11-18-91 Schuler     Added more ANSI-style functions
-* 04-15-93 Schuler     Changed _cdecl to LIBCALL
-* 05-27-93 Schuler     Added const qualifiers to match ANSI cognates
-* 06-14-94 Schuler     Added StrUpper() and StrLower() functions
-* 03-08-95 Kans        Added StringSearch and StringISearch
-* 12-27-95 Brylawski   Added a variety of functions, including search-and-
-*                      replace functions.
+* Date     Name        Description of modification
+* -------  ----------  -----------------------------------------------------
 *
 * ==========================================================================
 */
@@ -674,6 +542,96 @@ NLM_EXTERN Nlm_Int2 LIBCALL Nlm_MeshStringICmp (const char FAR *str1, const char
    Englewood Cliffs, NJ., 1986, p. 69.  The original had an error, where
    UNTIL (j < 0) OR (p[j] # s[i]) should be UNTIL (j < 0) OR (p[j] # s[k]). */
 
+/* New functions allow array data to be precomputed and kept for multiple uses */
+
+NLM_EXTERN Nlm_Boolean Nlm_SetupSubString (
+  const char FAR *sub,
+  Nlm_Boolean caseCounts,
+  Nlm_SubStringData PNTR data
+)
+
+{
+  int     ch;
+  int     j;
+  size_t  subLen;
+
+  if (data == NULL) return FALSE;
+  MemSet ((Nlm_VoidPtr) data, 0, sizeof (Nlm_SubStringData));
+  if (sub == NULL || sub [0] == '\0') return FALSE;
+
+  subLen = Nlm_StringLen (sub);
+
+  for (ch = 0; ch < 256; ch++) {
+    data->d [ch] = subLen;
+  }
+  for (j = 0; j < (int)(subLen - 1); j++) {
+    ch = (int) (caseCounts ? sub [j] : TO_UPPER (sub [j]));
+    if (ch >= 0 && ch <= 255) {
+      data->d [ch] = subLen - j - 1;
+    }
+  }
+
+  data->subLen = subLen;
+  data->caseCounts = caseCounts;
+  data->initialized = TRUE;
+  data->sub = sub;
+
+  return TRUE;
+}
+
+NLM_EXTERN Nlm_CharPtr Nlm_SearchSubString (
+  const char FAR *str,
+  Nlm_SubStringData PNTR data
+)
+
+{
+  Nlm_Boolean     caseCounts;
+  int             ch;
+  int             i;
+  int             j;
+  int             k;
+  size_t          strLen;
+  size_t          subLen;
+  const char FAR  *sub;
+
+  if (str == NULL || str [0] == '\0') return NULL;
+  if (data == NULL || ! data->initialized) return NULL;
+
+  strLen = Nlm_StringLen (str);
+  subLen = data->subLen;
+  if (strLen < subLen) return NULL;
+
+  caseCounts = data->caseCounts;
+  sub = data->sub;
+  if (sub == NULL || sub [0] == '\0') return NULL;
+
+  i = subLen;
+  do {
+	j = subLen;
+	k = i;
+	do {
+	  k--;
+	  j--;
+	} while (j >= 0 &&
+			 (caseCounts ? sub [j] : TO_UPPER (sub [j])) ==
+			 (caseCounts ? str [k] : TO_UPPER (str [k])));
+	if (j >= 0) {
+	  ch = (int) (caseCounts ? str [i - 1] : TO_UPPER (str [i - 1]));
+	  if (ch >= 0 && ch <= 255) {
+		i += data->d [ch];
+	  } else {
+		i++;
+	  }
+	}
+  } while (j >= 0 && i <= (int) strLen);
+  if (j < 0) {
+	i -= subLen;
+	return (Nlm_CharPtr) (str + i);
+  }
+
+  return NULL;
+}
+
 static Nlm_CharPtr Nlm_FindSubString (const char FAR *str, const char FAR *sub,
                                       Nlm_Boolean caseCounts)
 
diff --git a/corelib/ncbistr.h b/corelib/ncbistr.h
index de276cf..a56d1fb 100644
--- a/corelib/ncbistr.h
+++ b/corelib/ncbistr.h
@@ -29,83 +29,15 @@
 *
 * Version Creation Date:   1/1/91
 *
-* $Revision: 6.9 $
+* $Revision: 6.11 $
 *
 * File Description:
 *   	prototypes for portable string routines
 *
 * Modifications:
 * --------------------------------------------------------------------------
-* $Log: ncbistr.h,v $
-* Revision 6.9  2006/10/16 21:06:27  lavr
-* String{HasNo|DoesHave}Text() to accept const pointer
-*
-* Revision 6.8  2003/09/15 16:21:32  kans
-* moved StringDoesHaveText from sqnutils3.c
-*
-* Revision 6.7  2002/01/16 16:58:38  camacho
-* Changed type of buflen parameter in LabelCopy from Int2 to Uint4
-*
-* Revision 6.6  2001/01/05 22:43:58  shavirin
-* Added functions, that transfer Uint8 values to platform-independent
-* objects and back.
-*
-* Revision 6.5  2000/11/30 22:46:08  lavr
-* Added the following functions for conversions of Int8 and Uint8
-* to strings and back; test suite attached at the end of the file.
-* Nlm_Int8ToString, Nlm_Uint8ToString, Nlm_StringToInt8, Nlm_StringToUint8
-*
-* Revision 6.4  1999/04/15 20:24:07  vakatov
-* Dont use "list" name as it can clash with the standard "list<>" template
-* on some raw C++ compilers
-*
-* Revision 6.3  1999/03/11 16:10:00  kans
-* StringHasNoText and TrimSpacesAroundString moved from vibforms
-*
-* Revision 6.2  1998/11/27 19:08:59  vakatov
-* Removed proto of StringAppend() -- it is not implemented anyway, and
-* there are more standard functions from the "String[N]Cat" family
-*
-* Revision 6.1  1998/10/07 19:09:01  kans
-* added Nlm_StringTokMT, multithread-safe version
-*
-* Revision 6.0  1997/08/25 18:17:10  madden
-* Revision changed to 6.0
-*
-* Revision 5.6  1997/07/16 19:49:20  vakatov
-* Added Nlm_StringPrintable() function
-*
-* Revision 5.5  1997/04/11 17:57:49  brandon
-* added StrIPCmp, StrNIPCmp
-*
- * Revision 5.4  1997/03/13  17:47:58  kans
- * added IS_PRINT
- *
- * Revision 5.3  1997/03/04  21:59:57  vakatov
- * Added a set of functions to format(stream2text), unformat(text2stream)
- * and adjust(rule_line) text
- *
- * Revision 5.2  1997/01/03  16:07:50  vakatov
- * +Nlm_StringNCpy_0 prototype and comment;  +Nlm_StringNCat comment
- *
- * Revision 5.1  1996/12/03  21:48:33  vakatov
- * Adopted for 32-bit MS-Windows DLLs
- *
- * Revision 4.3  1996/05/22  14:46:47  brandon
- * Added NoCaseSkipPastString
- *
- * Revision 4.2  1996/01/03  21:04:50  epstein
- * modify StringSubString() API and add other new functions, per Brandon
- *
- * Revision 4.1  1995/12/27  20:53:51  epstein
- * add Brandon's string-management functions
- *
- * Revision 2.9  1995/07/18  19:56:55  tatiana
- * add Nlm_LabelCopyNext()
-* 09-19-91 Schuler     Added macros to alias actual ANSI string functions
-* 04-15-93 Schuler     Changed _cdecl to LIBCALL
-* 05-27-93 Schuler     Added const qualifiers to match ANSI cognates
-* 03-08-95 Kans        Added StringSearch and StringISearch
+* Date     Name        Description of modification
+* -------  ----------  -----------------------------------------------------
 *
 * ==========================================================================
 */
@@ -429,6 +361,31 @@ NLM_EXTERN char * LIBCALL Nlm_StrLower PROTO((char *string));
 #define Int8ToString  Nlm_Int8ToString
 #define Uint8ToString Nlm_Uint8ToString
 
+/* Search with Boyer-Moore algorithm */
+
+typedef struct substringdata {
+  int             d [256];
+  size_t          subLen;
+  Nlm_Boolean     caseCounts;
+  Nlm_Boolean     initialized;
+  const char FAR  *sub;        /* points to the original substring, not copied */
+} Nlm_SubStringData, PNTR Nlm_SubStringDataPtr;
+
+NLM_EXTERN Nlm_Boolean Nlm_SetupSubString (
+  const char FAR *sub,
+  Nlm_Boolean caseCounts,
+  Nlm_SubStringData PNTR data
+);
+NLM_EXTERN Nlm_CharPtr Nlm_SearchSubString (
+  const char FAR *str,
+  Nlm_SubStringData PNTR data
+);
+
+#define SubStringData Nlm_SubStringData
+#define SubStringDataPtr Nlm_SubStringDataPtr
+#define SetupSubString Nlm_SetupSubString
+#define SearchSubString Nlm_SearchSubString
+
 /*----------------------------------------*/
 /*      Misc Text Oriented Macros         */
 /*----------------------------------------*/
diff --git a/corelib/ncbiwin.h b/corelib/ncbiwin.h
index 81eb9e7..0545223 100644
--- a/corelib/ncbiwin.h
+++ b/corelib/ncbiwin.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/1/91
 *
-* $Revision: 6.12 $
+* $Revision: 6.13 $
 *
 * File Description:
 *               underlying window toolbox import
@@ -37,6 +37,10 @@
 * Modifications:
 * --------------------------------------------------------------------------
 * $Log: ncbiwin.h,v $
+* Revision 6.13  2010/06/30 15:54:38  ucko
+* Handle 64-bit Darwin builds, which require disabling WIN_MAC because
+* Carbon is 32-bit-only.
+*
 * Revision 6.12  2006/11/24 20:05:36  kans
 * include Carbon/Carbon.h if not MWERKS - attempting to simplify Xcode search paths
 *
@@ -168,6 +172,8 @@
 #include <Sound.h>
 #include <Folders.h>
 #endif
+#elif defined(OS_UNIX_DARWIN)
+#include <CoreServices/CoreServices.h>
 #endif
 
 	                   /* used in ncbifile.c *****/
diff --git a/ctools/asn_connection.c b/ctools/asn_connection.c
index 9579123..7f3f1e1 100644
--- a/ctools/asn_connection.c
+++ b/ctools/asn_connection.c
@@ -1,4 +1,4 @@
-/*  $Id: asn_connection.c,v 1.9 2007/10/17 15:25:44 kazimird Exp $
+/* $Id: asn_connection.c,v 1.12 2010/01/07 19:34:35 kazimird Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -40,32 +40,32 @@
 
 #ifdef __cplusplus
 extern "C" {
-    static Int2 LIBCALLBACK s_AsnRead(Pointer p, CharPtr buff, Uint2 len);
-    static Int2 LIBCALLBACK s_AsnWrite(Pointer p, CharPtr buff, Uint2 len);
+    static Int2 LIBCALLBACK s_AsnRead (Pointer conn, CharPtr buf, Uint2 len);
+    static Int2 LIBCALLBACK s_AsnWrite(Pointer conn, CharPtr buf, Uint2 len);
     static void s_CloseAsnConn(CONN conn, ECONN_Callback type, void* data);
 }
 #endif
 
 
-static Int2 LIBCALLBACK s_AsnRead(Pointer p, CharPtr buff, Uint2 len)
+static Int2 LIBCALLBACK s_AsnRead(Pointer conn, CharPtr buf, Uint2 len)
 {
     size_t n_read;
-    CONN_Read((CONN) p, buff, len, &n_read, eIO_ReadPlain);
+    CONN_Read((CONN) conn, buf, len, &n_read, eIO_ReadPlain);
     return (Int2) n_read;
 }
 
 
-static Int2 LIBCALLBACK s_AsnWrite(Pointer p, CharPtr buff, Uint2 len)
+static Int2 LIBCALLBACK s_AsnWrite(Pointer conn, CharPtr buf, Uint2 len)
 {
     size_t n_written;
-    CONN_Write((CONN) p, buff, len, &n_written, eIO_WritePersist);
+    CONN_Write((CONN) conn, buf, len, &n_written, eIO_WritePersist);
     return (Int2) n_written;
 }
 
 
 struct SAsnConn_Cbdata {
     SCONN_Callback cb;
-    AsnIoPtr       ptr;
+    AsnIoPtr       aip;
 };
 
 
@@ -73,30 +73,31 @@ static void s_CloseAsnConn(CONN conn, ECONN_Callback type, void* data)
 {
     struct SAsnConn_Cbdata* cbdata = (struct SAsnConn_Cbdata*) data;
 
-    assert(type == eCONN_OnClose && cbdata && cbdata->ptr);
+    assert(type == eCONN_OnClose && cbdata && cbdata->aip);
     CONN_SetCallback(conn, type, &cbdata->cb, 0);
-    AsnIoFree(cbdata->ptr, 0/*not a file - don't close*/);
+    AsnIoFree(cbdata->aip, FALSE/*not a file - don't close*/);
     if ( cbdata->cb.func )
         (*cbdata->cb.func)(conn, type, cbdata->cb.data);
     free(cbdata);
 }
 
 
-static void s_SetAsnConn_CloseCb(CONN conn, AsnIoPtr ptr)
+static void s_SetAsnConn_CloseCb(CONN conn, AsnIoPtr aip)
 {
-    struct SAsnConn_Cbdata* cbdata = (struct SAsnConn_Cbdata*)
-        malloc(sizeof(*cbdata));
+    struct SAsnConn_Cbdata* cbdata =
+        (struct SAsnConn_Cbdata*) malloc(sizeof(*cbdata));
 
-    assert( ptr );
+    assert( aip );
     if ( cbdata ) {
         SCONN_Callback cb;
-        cbdata->ptr = ptr;
+        cbdata->aip = aip;
         cb.func = s_CloseAsnConn;
         cb.data = cbdata;
         CONN_SetCallback(conn, eCONN_OnClose, &cb, &cbdata->cb);
-    } else
+    } else {
         CORE_LOG_X(1, eLOG_Error,
                    "Cannot create cleanup callback for ASN conn-based stream");
+    }
 }
 
 
@@ -104,15 +105,16 @@ AsnIoPtr CreateAsnConn(CONN               conn,
                        EAsnConn_Direction direction,
                        EAsnConn_Format    fmt)
 {
-    AsnIoPtr ptr;
-    int flags;
+    /* NB: Do not use ASNIO_{TEXT|BIN}_{IN|OUT} because they subsume FILE */
+    AsnIoPtr aip;
+    int type;
 
     switch (fmt) {
     case eAsnConn_Binary:
-        flags = ASNIO_BIN;
+        type = ASNIO_BIN;
         break;
     case eAsnConn_Text:
-        flags = ASNIO_TEXT;
+        type = ASNIO_TEXT;
         break;
     default:
         return 0;
@@ -120,18 +122,18 @@ AsnIoPtr CreateAsnConn(CONN               conn,
 
     switch (direction) {
     case eAsnConn_Input:
-        ptr = AsnIoNew(flags | ASNIO_IN, 0, (void*) conn, s_AsnRead, 0);
+        aip = AsnIoNew(type | ASNIO_IN, 0, (void*) conn, s_AsnRead, 0);
         break;
     case eAsnConn_Output:
-        ptr = AsnIoNew(flags | ASNIO_OUT, 0, (void*) conn, 0, s_AsnWrite);
+        aip = AsnIoNew(type | ASNIO_OUT, 0, (void*) conn, 0, s_AsnWrite);
         break;
     default:
         return 0;
     }
 
-    if (ptr)
-        s_SetAsnConn_CloseCb(conn, ptr);
-    return ptr;
+    if (aip)
+        s_SetAsnConn_CloseCb(conn, aip);
+    return aip;
 }
 
 
diff --git a/ctools/asn_connection.h b/ctools/asn_connection.h
index dd6b3ea..a77d5fb 100644
--- a/ctools/asn_connection.h
+++ b/ctools/asn_connection.h
@@ -1,7 +1,7 @@
 #ifndef CTOOLS___ASN_CONNECTION__H
 #define CTOOLS___ASN_CONNECTION__H
 
-/*  $Id: asn_connection.h,v 1.9 2004/11/23 16:14:25 lavr Exp $
+/*  $Id: asn_connection.h,v 1.10 2009/08/13 14:58:22 lavr Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -29,7 +29,7 @@
  * Author:  Denis Vakatov, Anton Lavrentiev
  *
  * File Description:
- *    Build C Toolkit ANS streams on top of CONN (connection).
+ *    Build C Toolkit ASN streams on top of CONN (connection).
  *
  */
 
@@ -68,7 +68,7 @@ typedef enum {
  * Return ASN stream pointer on success, or 0 on error.
  * NOTE: Returned stream is valid while the underlying conn exists. After call
  *       to CONN_Close() the stream becomes invalid, and should not be used.
- *       Don't destroy the ASN stream explicitly using AsnIoFree or AsnIoFree!
+ *       Don't destroy the ASN stream explicitly using AsnIoFree!
  */
 AsnIoPtr CreateAsnConn
 (CONN               conn,
@@ -88,7 +88,7 @@ AsnIoPtr CreateAsnConn
  * NOTE: Returned ASN stream pointers are valid as long as connection
  *       handle exists, that is after the connection handle is passed to
  *       CONN_Close(), both pointers become invalid, and should not be used.
- *       Don't destroy the ASN streams explicitly using AsnIoFree or AsnIoFree!
+ *       Don't destroy the ASN streams explicitly using AsnIoFree!
  */
 CONN CreateAsnConn_ServiceEx
 (const char*           service,
@@ -124,6 +124,9 @@ CONN CreateAsnConn_Service
 /*
  * ===========================================================================
  * $Log: asn_connection.h,v $
+ * Revision 1.10  2009/08/13 14:58:22  lavr
+ * Inline doc fixed of duplicates
+ *
  * Revision 1.9  2004/11/23 16:14:25  lavr
  * +<connect/ncbi_service_connector.h>
  *
diff --git a/debian/.gitignore b/debian/.gitignore
new file mode 100644
index 0000000..5180eb4
--- /dev/null
+++ b/debian/.gitignore
@@ -0,0 +1,18 @@
+*.xpm
+*.debhelper
+*.debhelper.log
+*.menu
+*.substvars
+blast2
+files
+libncbi6
+libvibrant6a
+lib*-dbg
+lib*-dev
+ncbi-data
+ncbi-tools-bin
+ncbi-tools-x11
+ncbi-tools6
+tmp
+vibrant6
+ncbi-rrna-data
diff --git a/debian/changelog b/debian/changelog
index 7b8233e..1f6a4cc 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,29 @@
+ncbi-tools6 (6.1.20100808-1) experimental; urgency=low
+
+  * New upstream release; the upgrade to BLAST 2.2.24 (from 2.2.21) should
+    address a formatdb regression.  (LP: #586219.)
+  * Uploading to experimental because squeeze is frozen.
+  * debian/rules
+    - Clean up compilation settings; in particular, use dpkg-buildflags rather
+      than relying on dpkg-buildpackage to have set CFLAGS appropriately.
+    - (clean): restore expected empty directories if necessary,
+      for compatibility with VCSes (notably git) that don't track them.
+    - (install-indep-stamp): adapt to new ncbilogo.ico contents.
+    - (VIB): add asndisc, as upstream takes care to publish binaries thereof.
+  * debian/ncbi-tools6.install: likewise add asndisc.
+  * (debian/).gitignore: Ignore content generated during build.
+  * debian/lib{ncbi6,vibrant6a}.symbols: update for latest release.
+  * make/makenet.unx: don't link asndisc against extraneous libraries.
+  * doc/man/*.1: update for latest release.
+  * doc/man/asndisc.1: throw together a man page for asndisc.
+  * doc/man/cleanasn.1: fix SEE ALSO formatting.
+  * debian/control:
+    - bump dpkg-dev build-dep to >= 1.15.7 for dpkg-buildflags.
+    - Standards-Version: 3.9.1 (already compliant).
+    - note switch to git-mediated Debian-Med team maintenance.
+
+ -- Aaron M. Ucko <ucko@debian.org>  Fri, 03 Sep 2010 17:43:17 -0400
+
 ncbi-tools6 (6.1.20090809-1) unstable; urgency=low
 
   * New upstream release.
diff --git a/debian/control b/debian/control
index 66016e2..d2b82f3 100644
--- a/debian/control
+++ b/debian/control
@@ -1,11 +1,14 @@
 Source: ncbi-tools6
 Section: libdevel
 Priority: optional
-Maintainer: Aaron M. Ucko <ucko@debian.org>
-Build-Depends: csh | c-shell, debhelper (>= 7), dpkg-dev (>= 1.14.17), lesstif2-dev, libglu1-mesa-dev | libglu-dev, libpcre3-dev, libpng12-dev | libpng-dev, libxmu-dev
+Maintainer: Debian Med Packaging Team <debian-med-packaging@lists.alioth.debian.org>
+Uploaders: Aaron M. Ucko <ucko@debian.org>
+Build-Depends: csh | c-shell, debhelper (>= 7), dpkg-dev (>= 1.15.7), lesstif2-dev, libglu1-mesa-dev | libglu-dev, libpcre3-dev, libpng12-dev | libpng-dev, libxmu-dev
 Build-Depends-Indep: icoutils, imagemagick
-Standards-Version: 3.8.2
+Standards-Version: 3.9.1
 Homepage: http://www.ncbi.nlm.nih.gov/IEB/ToolBox/
+Vcs-Browser: http://git.debian.org/?p=debian-med/ncbi-tools6.git
+Vcs-Git: git://git.debian.org/debian-med/ncbi-tools6.git
 
 Package: libncbi6
 Architecture: any
diff --git a/debian/libncbi6.symbols b/debian/libncbi6.symbols
index 8c3ce2e..e6af7d8 100644
--- a/debian/libncbi6.symbols
+++ b/debian/libncbi6.symbols
@@ -182,6 +182,7 @@ libblast.so.6 libncbi6 #MINVER#
  BlastRPSScanSubject@Base 6.1.20040505
  BlastRPSWordFinder@Base 6.1.20070822
  BlastSaveInitHsp@Base 6.1.20040204
+ BlastScoreBlkCheck@Base 6.1.20100808
  BlastScoreBlkFree@Base 6.1.20040204
  BlastScoreBlkNew@Base 6.1.20040204
  BlastScoreBlkNuclMatrixCreate@Base 6.1.20041020
@@ -271,7 +272,7 @@ libblast.so.6 libncbi6 #MINVER#
  Blast_HSPListPurgeHSPsWithCommonEndpoints@Base 6.1.20050605
  Blast_HSPListPurgeNullHSPs@Base 6.1.20040505
  Blast_HSPListReapByEvalue@Base 6.1.20040505
- Blast_HSPListReevaluateWithAmbiguitiesUngapped@Base 6.1.20070822
+ Blast_HSPListReevaluateUngapped@Base 6.1.20100808
  Blast_HSPListSaveHSP@Base 6.1.20040505
  Blast_HSPListSortByEvalue@Base 6.1.20041020
  Blast_HSPListSortByScore@Base 6.1.20041020
@@ -286,7 +287,6 @@ libblast.so.6 libncbi6 #MINVER#
  Blast_HSPResultsFromHSPStreamWithLimit@Base 6.1.20060301
  Blast_HSPResultsInsertHSPList@Base 6.1.20040616
  Blast_HSPResultsNew@Base 6.1.20050429
- Blast_HSPResultsPerformCulling@Base 6.1.20050429
  Blast_HSPResultsReverseOrder@Base 6.1.20041020
  Blast_HSPResultsReverseSort@Base 6.1.20080302
  Blast_HSPResultsSortByEvalue@Base 6.1.20040505
@@ -346,7 +346,6 @@ libblast.so.6 libncbi6 #MINVER#
  Blast_ScoreFreqNew@Base 6.1.20040616
  Blast_SemiGappedAlign@Base 6.1.20050429
  Blast_SetPHIPatternInfo@Base 6.1.20050429
- Blast_SetUpSubjectTranslation@Base 6.1.20050429
  Blast_SubjectIsNucleotide@Base 6.1.20050828
  Blast_SubjectIsProtein@Base 6.1.20050828
  Blast_SubjectIsPssm@Base 6.1.20050828
@@ -473,11 +472,13 @@ libblast.so.6 libncbi6 #MINVER#
  SSegOptionsNew@Base 6.1.20050429
  SSeqRangeArrayLessThanOrEqual@Base 6.1.20090301
  SSeqRangeNew@Base 6.1.20081116
+ SUBJECT_SPLIT_DONE@Base 6.1.20100808
+ SUBJECT_SPLIT_NO_RANGE@Base 6.1.20100808
+ SUBJECT_SPLIT_OK@Base 6.1.20100808
  SWindowMaskerOptionsFree@Base 6.1.20081116
  SWindowMaskerOptionsNew@Base 6.1.20081116
  SWindowMaskerOptionsResetDB@Base 6.1.20081116
  ScoreCompareHSPs@Base 6.1.20050429
- ScoreDifferenceSort@Base 6.1.20080302
  SegParametersFree@Base 6.1.20040204
  SegParametersNewAa@Base 6.1.20040204
  SeqBufferSeg@Base 6.1.20040204
@@ -487,6 +488,7 @@ libblast.so.6 libncbi6 #MINVER#
  SplitQueryBlk_AddContextOffsetToChunk@Base 6.1.20070822
  SplitQueryBlk_AddContextToChunk@Base 6.1.20070822
  SplitQueryBlk_AddQueryToChunk@Base 6.1.20070822
+ SplitQueryBlk_AllowGap@Base 6.1.20100808
  SplitQueryBlk_GetChunkBounds@Base 6.1.20070822
  SplitQueryBlk_GetChunkOverlapSize@Base 6.1.20070822
  SplitQueryBlk_GetContextOffsetsForChunk@Base 6.1.20070822
@@ -577,8 +579,6 @@ libblast.so.6 libncbi6 #MINVER#
  debruijn@Base 6.1.20040204
  iexp@Base 6.1.20040204
  ilog2@Base 6.1.20040204
- ir_fp_entry_create@Base 6.1.20070822
- ir_fp_entry_destroy@Base 6.1.20070822
  ir_hash_create@Base 6.1.20070822
  ir_hash_destroy@Base 6.1.20070822
  ir_locate@Base 6.1.20070822
@@ -829,6 +829,9 @@ libncbi.so.6 libncbi6 #MINVER#
  AsnGenericUserSeqOfAsnRead@Base 6.1.20030421
  AsnGenericUserSeqOfAsnWrite@Base 6.1.20030421
  AsnGenericUserSeqOfFree@Base 6.1.20030421
+ AsnGenericValNodeSetAsnRead@Base 6.1.20100808
+ AsnGenericValNodeSetAsnWrite@Base 6.1.20100808
+ AsnGenericValNodeSetFree@Base 6.1.20100808
  AsnGetLevel@Base 6.1.20030421
  AsnGetType@Base 6.1.20030421
  AsnGetXMLmodulePrefix@Base 6.1.20030421
@@ -951,12 +954,14 @@ libncbi.so.6 libncbi6 #MINVER#
  AsnWriteChoice@Base 6.1.20030421
  AsnWriteEx@Base 6.1.20031028
  BUF_Append@Base 6.1.20050429
+ BUF_AppendEx@Base 6.1.20100808
  BUF_Destroy@Base 6.1.20030421
  BUF_Erase@Base 6.1.20050429
  BUF_Peek@Base 6.1.20030421
  BUF_PeekAt@Base 6.1.20030421
  BUF_PeekAtCB@Base 6.1.20070822
  BUF_Prepend@Base 6.1.20050429
+ BUF_PrependEx@Base 6.1.20100808
  BUF_PushBack@Base 6.1.20030421
  BUF_Read@Base 6.1.20030421
  BUF_SetChunkSize@Base 6.1.20030421
@@ -971,6 +976,8 @@ libncbi.so.6 libncbi6 #MINVER#
  B_NewGlobal@Base 6.1.20030421
  BreakString@Base 6.1.20030421
  BytesToUint8@Base 6.1.20030421
+ CONNECT_BASE64_Decode@Base 6.1.20100808
+ CONNECT_BASE64_Encode@Base 6.1.20100808
  CONNECT_Init@Base 6.1.20030421
  CONN_Close@Base 6.1.20030421
  CONN_Create@Base 6.1.20030421
@@ -1004,11 +1011,11 @@ libncbi.so.6 libncbi6 #MINVER#
  CORE_SetLOGFILE_NAME_Ex@Base 6.1.20070822
  CORE_SetLOGFormatFlags@Base 6.1.20030421
  CORE_SetREG@Base 6.1.20030421
- CRC32_Update@Base 6.1.20051206
  CleanSpaces@Base 6.1.20030421
  ConnNetInfo_AdjustForHttpProxy@Base 6.1.20030421
  ConnNetInfo_AppendArg@Base 6.1.20030421
  ConnNetInfo_AppendUserHeader@Base 6.1.20030421
+ ConnNetInfo_Boolean@Base 6.1.20100808
  ConnNetInfo_Clone@Base 6.1.20030421
  ConnNetInfo_Create@Base 6.1.20030421
  ConnNetInfo_DeleteAllArgs@Base 6.1.20060301
@@ -1017,7 +1024,7 @@ libncbi.so.6 libncbi6 #MINVER#
  ConnNetInfo_Destroy@Base 6.1.20030421
  ConnNetInfo_ExtendUserHeader@Base 6.1.20030421
  ConnNetInfo_GetValue@Base 6.1.20060507
- ConnNetInfo_Log@Base 6.1.20030421
+ ConnNetInfo_LogEx@Base 6.1.20100808
  ConnNetInfo_OverrideUserHeader@Base 6.1.20030421
  ConnNetInfo_ParseURL@Base 6.1.20030421
  ConnNetInfo_PostOverrideArg@Base 6.1.20030421
@@ -1025,6 +1032,7 @@ libncbi.so.6 libncbi6 #MINVER#
  ConnNetInfo_PrependArg@Base 6.1.20030421
  ConnNetInfo_SetUserHeader@Base 6.1.20030421
  ConnNetInfo_SetupStandardArgs@Base 6.1.20060301
+ ConnNetInfo_URL@Base 6.1.20100808
  CountChar@Base 6.1.20030421
  CountSet@Base 6.1.20030421
  CountStrings@Base 6.1.20030421
@@ -1056,6 +1064,7 @@ libncbi.so.6 libncbi6 #MINVER#
  ErrTestOptFlags@Base 6.1.20030421
  FILE_CreateConnector@Base 6.1.20030421
  FILE_CreateConnectorEx@Base 6.1.20030421
+ FTP_CreateConnector@Base 6.1.20100808
  FTP_CreateDownloadConnector@Base 6.1.20050429
  GetAppParamBoolean@Base 6.1.20030421
  GetAppParamLong@Base 6.1.20030421
@@ -1379,6 +1388,7 @@ libncbi.so.6 libncbi6 #MINVER#
  Nlm_ReleaseAppContext@Base 6.1.20030421
  Nlm_RemoveAppProperty@Base 6.1.20030421
  Nlm_RombergIntegrate@Base 6.1.20030421
+ Nlm_SearchSubString@Base 6.1.20100808
  Nlm_SetAppParam@Base 6.1.20030421
  Nlm_SetAppProperty@Base 6.1.20030421
  Nlm_SetBeepHook@Base 6.1.20030421
@@ -1388,6 +1398,7 @@ libncbi.so.6 libncbi6 #MINVER#
  Nlm_SetMonitorHook@Base 6.1.20030421
  Nlm_SetProgMon@Base 6.1.20030421
  Nlm_SetupArguments@Base 6.1.20030421
+ Nlm_SetupSubString@Base 6.1.20100808
  Nlm_Sgml2Ascii@Base 6.1.20030421
  Nlm_Sgml2AsciiLen@Base 6.1.20030421
  Nlm_SgmlLoadTable@Base 6.1.20030421
@@ -1485,6 +1496,7 @@ libncbi.so.6 libncbi6 #MINVER#
  QUERY_OpenServiceQuery@Base 6.1.20030421
  QUERY_OpenServiceQueryEx@Base 6.1.20060507
  QUERY_OpenUrlQuery@Base 6.1.20030421
+ QUERY_QueueSize@Base 6.1.20100808
  QUERY_SendQuery@Base 6.1.20030421
  REG_AddRef@Base 6.1.20030421
  REG_Create@Base 6.1.20030421
@@ -1549,7 +1561,6 @@ libncbi.so.6 libncbi6 #MINVER#
  SOCK_CreateConnector@Base 6.1.20030421
  SOCK_CreateConnectorEx@Base 6.1.20030421
  SOCK_CreateConnectorOnTop@Base 6.1.20030421
- SOCK_CreateConnectorOnTopEx@Base 6.1.20030421
  SOCK_CreateEx@Base 6.1.20030421
  SOCK_CreateOnTop@Base 6.1.20030421
  SOCK_CreateOnTopEx@Base 6.1.20031028
@@ -1557,6 +1568,7 @@ libncbi.so.6 libncbi6 #MINVER#
  SOCK_DisableOSSendDelay@Base 6.1.20050429
  SOCK_GetLocalHostAddress@Base 6.1.20070822
  SOCK_GetLocalPort@Base 6.1.20080302
+ SOCK_GetLocalPortEx@Base 6.1.20100808
  SOCK_GetLoopbackAddress@Base 6.1.20050828
  SOCK_GetOSHandle@Base 6.1.20030421
  SOCK_GetPeerAddress@Base 6.1.20030421
@@ -1579,6 +1591,7 @@ libncbi.so.6 libncbi6 #MINVER#
  SOCK_Reconnect@Base 6.1.20030421
  SOCK_SetDataLogging@Base 6.1.20030421
  SOCK_SetDataLoggingAPI@Base 6.1.20030421
+ SOCK_SetIOWaitSysAPI@Base 6.1.20100808
  SOCK_SetInterruptOnSignal@Base 6.1.20030421
  SOCK_SetInterruptOnSignalAPI@Base 6.1.20030421
  SOCK_SetReadOnWrite@Base 6.1.20030421
@@ -1604,6 +1617,7 @@ libncbi.so.6 libncbi6 #MINVER#
  SOCK_isipEx@Base 6.1.20070822
  SOCK_ntoa@Base 6.1.20030421
  SendMailInfo_Init@Base 6.1.20030421
+ SendMailInfo_InitEx@Base 6.1.20100808
  SetAppParamBoolean@Base 6.1.20030421
  SetAppParamLong@Base 6.1.20030421
  SkipChar@Base 6.1.20030421
@@ -1637,6 +1651,8 @@ libncbi.so.6 libncbi6 #MINVER#
  URL_Decode@Base 6.1.20030421
  URL_DecodeEx@Base 6.1.20030421
  URL_Encode@Base 6.1.20030421
+ UTIL_Adler32_Update@Base 6.1.20100808
+ UTIL_CRC32_Update@Base 6.1.20100808
  UTIL_MatchesMask@Base 6.1.20050828
  UTIL_MatchesMaskEx@Base 6.1.20060507
  UTIL_NcbiLocalHostName@Base 6.1.20080302
@@ -1709,6 +1725,7 @@ libncbi.so.6 libncbi6 #MINVER#
  g_CORE_Sprintf@Base 6.1.20030421
  g_NCBI_ConnectRandomSeed@Base 6.1.20050605
  g_NCBI_ConnectSrandAddend@Base 6.1.20050828
+ g_VersionStr@Base 6.1.20100808
  g_bBadPtr@Base 6.1.20030421
  g_corelib@Base 6.1.20030421
  gdImageArc@Base 6.1.20030421
@@ -3281,6 +3298,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AddBioSampleIDsToDBLinkUserObject@Base 6.1.20090301
  AddBioSourceToGBQual@Base 6.1.20030421
  AddBiomolToEntry@Base 6.1.20030421
+ AddCAGEBlock@Base 6.1.20100808
  AddCDSGapComment@Base 6.1.20080302
  AddCodeBreakToCdRegion@Base 6.1.20030421
  AddCommentBlock@Base 6.1.20040204
@@ -3295,6 +3313,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AddCreateDateToEntry@Base 6.1.20030421
  AddCuratorToRefGeneTrackUserObject@Base 6.1.20030421
  AddCuratorURLToRefGeneTrackUserObject@Base 6.1.20081116
+ AddDatabaseNameToStructuredComment@Base 6.1.20100808
  AddDateBlock@Base 6.1.20040204
  AddDblinkBlock@Base 6.1.20090719
  AddDbsourceBlock@Base 6.1.20040204
@@ -3307,6 +3326,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AddECNumberNoteDiscrepancies@Base 6.1.20070822
  AddEmptyBlocks@Base 6.1.20030421
  AddEmptySegments@Base 6.1.20030421
+ AddExceptionsToShortIntrons@Base 6.1.20100808
  AddExtraAccessions@Base 6.1.20030421
  AddFakeGapToDeltaSeq@Base 6.1.20030421
  AddFeatFunc@Base 6.1.20030421
@@ -3345,6 +3365,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AddModifsToGBQual@Base 6.1.20030421
  AddMrnaOrESTtoModelEvidence@Base 6.1.20030421
  AddMutSetToSubmission@Base 6.1.20030421
+ AddNewUniqueAnnotations@Base 6.1.20100808
+ AddNewUniqueDescriptors@Base 6.1.20100808
  AddNonExtendableException@Base 6.1.20090719
  AddNucProtToSubmission@Base 6.1.20030421
  AddOffsetToAlignNode@Base 6.1.20030421
@@ -3365,6 +3387,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AddPntToSeqLoc@Base 6.1.20070822
  AddPointToFeature@Base 6.1.20030421
  AddPopSetToSubmission@Base 6.1.20030421
+ AddPopsetDeflineWithClause@Base 6.1.20100808
+ AddPopsetTitles@Base 6.1.20100808
  AddPrimaryBlock@Base 6.1.20040204
  AddProbeDBIDsToDBLinkUserObject@Base 6.1.20090719
  AddProteinQuals@Base 6.1.20030421
@@ -3389,6 +3413,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AddSeqId@Base 6.1.20030421
  AddSeqLocPoint@Base 6.1.20050429
  AddSeqOnlyToSubmission@Base 6.1.20030421
+ AddSeqReadArchiveIDsToDBLinkUserObject@Base 6.1.20100808
  AddSeqToNucProtEntry@Base 6.1.20030421
  AddSeqToSegmentedEntry@Base 6.1.20030421
  AddSequenceBlock@Base 6.1.20040204
@@ -3400,8 +3425,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AddStatusToRefGeneTrackUserObject@Base 6.1.20030421
  AddStringToNcbiCleanupUserObject@Base 6.1.20090719
  AddStringWithTildes@Base 6.1.20040204
+ AddStructuredCommentKeywords@Base 6.1.20100808
  AddSubSourceToEntry@Base 6.1.20030421
  AddTechToEntry@Base 6.1.20030421
+ AddTextToTabTableColumn@Base 6.1.20100808
  AddTitleToEntry@Base 6.1.20030421
  AddToGeneOntologyUserObject@Base 6.1.20030421
  AddToolToSub@Base 6.1.20030421
@@ -3419,6 +3446,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AdjustFeaturesForInsertion@Base 6.1.20050429
  AdjustFrame@Base 6.1.20080302
  AdjustOffSetsInSeqAlign@Base 6.1.20030421
+ AdjustSeqEntryForConsensusSplice@Base 6.1.20100808
+ AdjustSeqEntryForConsensusSpliceEx@Base 6.1.20100808
  AdjustmRNAProductToMatchProteinProduct@Base 6.1.20080302
  AdvcLockFarComponents@Base 6.1.20070822
  AffilAsnRead@Base 6.1.20030421
@@ -3666,6 +3695,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  AnnotIdSetAsnRead@Base 6.1.20030421
  AnnotIdSetAsnWrite@Base 6.1.20030421
  AnnotIdSetFree@Base 6.1.20030421
+ AnyDiscrepanciesChosen@Base 6.1.20100808
  ApplyActionAsnRead@Base 6.1.20080302
  ApplyActionAsnWrite@Base 6.1.20080302
  ApplyActionFree@Base 6.1.20080302
@@ -3681,7 +3711,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ApplyFeatureActionFree@Base 6.1.20080302
  ApplyFeatureActionNew@Base 6.1.20080302
  ApplyMacroToSeqEntry@Base 6.1.20080302
+ ApplyMacroToSeqEntryEx@Base 6.1.20100808
  ApplyMolinfoBlockToSeqEntry@Base 6.1.20081116
+ ApplyOneFeatureToBioseq@Base 6.1.20100808
  ApplyOneSpecificHostFix@Base 6.1.20070822
  ApplyTableToFeatures@Base 6.1.20080302
  ApplyTableValuesToObjectTable@Base 6.1.20080302
@@ -3751,12 +3783,14 @@ libncbiobj.so.6 libncbi6 #MINVER#
  BarcodeTestConfigNew@Base 6.1.20070822
  BarcodeTestGenbankIdString@Base 6.1.20070822
  BarcodeTestResultsCopy@Base 6.1.20070822
+ BarcodeTestResultsForBioseq@Base 6.1.20100808
  BarcodeTestResultsFree@Base 6.1.20070822
  BarcodeTestResultsListFree@Base 6.1.20070822
  BarcodeTestResultsNew@Base 6.1.20070822
  BarcodeValidateOneSeqEntry@Base 6.1.20081116
  BaseSegFree@Base 6.1.20090301
  BaseSegNew@Base 6.1.20090301
+ BasicSeqAnnotCleanup@Base 6.1.20100808
  BasicSeqEntryCleanup@Base 6.1.20030421
  BatchExtraFree@Base 6.1.20090301
  BatchExtraNew@Base 6.1.20090301
@@ -3789,6 +3823,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  BioseqCopy@Base 6.1.20030421
  BioseqCopyEx@Base 6.1.20030421
  BioseqDelete@Base 6.1.20030421
+ BioseqDeleteEx@Base 6.1.20100808
  BioseqFastaMemStream@Base 6.1.20041020
  BioseqFastaStream@Base 6.1.20040204
  BioseqFastaStreamEx@Base 6.1.20070822
@@ -3811,6 +3846,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  BioseqGetSegLens@Base 6.1.20030421
  BioseqGetSeqDescr@Base 6.1.20030421
  BioseqGetTitle@Base 6.1.20030421
+ BioseqHasBarcodeKeyword@Base 6.1.20100808
  BioseqHasFeature@Base 6.1.20030421
  BioseqHasLandMark@Base 6.1.20030421
  BioseqHasMapLegend@Base 6.1.20030421
@@ -3890,6 +3926,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  BuildDefinitionLinesFromFeatureClauseLists@Base 6.1.20080302
  BuildFieldPairFromFromField@Base 6.1.20081116
  BuildGeneList@Base 6.1.20030421
+ BuildNonFeatureListClause@Base 6.1.20100808
+ BuildOneDefinitionLine@Base 6.1.20100808
  BuildProtLoc@Base 6.1.20081116
  CCStrToInt@Base 6.1.20030421
  CCStrToLong@Base 6.1.20030421
@@ -3954,6 +3992,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  CheckTaxNamesAgainstTaxDatabase@Base 6.1.20070822
  CheckXrefFeat@Base 6.1.20030421
  CheckXrefLine@Base 6.1.20030421
+ ChooseAllDiscrepancies@Base 6.1.20100808
  ChooseFixableDiscrepancies@Base 6.1.20090719
  CitArtAsnRead@Base 6.1.20030421
  CitArtAsnWrite@Base 6.1.20030421
@@ -4014,10 +4053,15 @@ libncbiobj.so.6 libncbi6 #MINVER#
  CleanSubSourceList@Base 6.1.20080302
  CleanSubSourcePrimers@Base 6.1.20081116
  CleanUpAmbiguousYAC@Base 6.1.20030421
+ CleanUpPubdescAuthors@Base 6.1.20100808
+ CleanUpPubdescBody@Base 6.1.20100808
  CleanUpSegGap@Base 6.1.20081116
  CleanUpSeqFeat@Base 6.1.20050429
+ CleanUpSeqLoc@Base 6.1.20100808
  CleanUpTaxName@Base 6.1.20080302
  CleanupBlocks@Base 6.1.20030421
+ CleanupOneSeqFeat@Base 6.1.20100808
+ CleanupStringsForOneDescriptor@Base 6.1.20100808
  ClearBioseqFindCache@Base 6.1.20070822
  ClearFeatIDXrefs@Base 6.1.20050828
  ClearFeatIDs@Base 6.1.20050828
@@ -4026,6 +4070,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ClearProteinTitlesInNucProts@Base 6.1.20030421
  ClearStructures@Base 6.1.20030421
  ClickableItemFree@Base 6.1.20080302
+ ClickableItemObjectListCopy@Base 6.1.20100808
+ ClickableItemObjectListFree@Base 6.1.20100808
  CloneRefAsnRead@Base 6.1.20090719
  CloneRefAsnWrite@Base 6.1.20090719
  CloneRefFree@Base 6.1.20090719
@@ -4060,7 +4106,11 @@ libncbiobj.so.6 libncbi6 #MINVER#
  CollectItemForSeqLocEx@Base 6.1.20030421
  CollectSegMapSTSAlign@Base 6.1.20030421
  CollectSeqLocFromAlignNode@Base 6.1.20030421
+ CollectionDateIsInTheFuture@Base 6.1.20100808
+ CollectionDateIsValid@Base 6.1.20100808
+ CombineTabTableColumns@Base 6.1.20100808
  CombineUserObjects@Base 6.1.20030421
+ CommentHasSuspiciousHtml@Base 6.1.20100808
  CommentRuleAsnRead@Base 6.1.20090719
  CommentRuleAsnWrite@Base 6.1.20090719
  CommentRuleFree@Base 6.1.20090719
@@ -4089,10 +4139,25 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ComposeCodonsRecognizedString@Base 6.1.20030421
  ComposeGBQuals@Base 6.1.20030421
  ComposeNoteFromNoteStruct@Base 6.1.20030421
+ CompressSpaces@Base 6.1.20100808
  ConfigureForBigSequence@Base 6.1.20081116
  ConfigureForGenomes@Base 6.1.20081116
  ConsensusReadAlnFree@Base 6.1.20090301
  ConsensusReadAlnNew@Base 6.1.20090301
+ ConsequenceAsnRead@Base 6.1.20100808
+ ConsequenceAsnWrite@Base 6.1.20100808
+ ConsequenceFree@Base 6.1.20100808
+ Consequence_elementAsnRead@Base 6.1.20100808
+ Consequence_elementAsnWrite@Base 6.1.20100808
+ Consequence_elementFree@Base 6.1.20100808
+ Consequence_frameshiftAsnRead@Base 6.1.20100808
+ Consequence_frameshiftAsnWrite@Base 6.1.20100808
+ Consequence_frameshiftFree@Base 6.1.20100808
+ Consequence_frameshiftNew@Base 6.1.20100808
+ Consequence_loss_of_heterozygosityAsnRead@Base 6.1.20100808
+ Consequence_loss_of_heterozygosityAsnWrite@Base 6.1.20100808
+ Consequence_loss_of_heterozygosityFree@Base 6.1.20100808
+ Consequence_loss_of_heterozygosityNew@Base 6.1.20100808
  ConstraintChoiceAsnRead@Base 6.1.20080302
  ConstraintChoiceAsnWrite@Base 6.1.20080302
  ConstraintChoiceFree@Base 6.1.20080302
@@ -4119,6 +4184,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ConvertBioSrcToRepeatRegion@Base 6.1.20081116
  ConvertCDSToMatPeptideForOverlappingCDS@Base 6.1.20090719
  ConvertCDSToRNA@Base 6.1.20081116
+ ConvertCommentsWithSpacesToStructuredCommentsForSeqEntry@Base 6.1.20100808
  ConvertEmbedQual@Base 6.1.20030421
  ConvertFeatureActionAsnRead@Base 6.1.20081116
  ConvertFeatureActionAsnWrite@Base 6.1.20081116
@@ -4179,6 +4245,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  CountPolymorphismsInBioseq@Base 6.1.20081116
  CountProteins@Base 6.1.20070822
  CountTabTableBlanks@Base 6.1.20080302
+ CountryBoxesOverlap@Base 6.1.20100808
  CountryIsValid@Base 6.1.20080302
  CpNoteToCharPtrStack@Base 6.1.20030421
  CreateAnnotDescCommentPolicyUserObject@Base 6.1.20060301
@@ -4192,6 +4259,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  CreateFeatureFetchPolicyUserObject@Base 6.1.20060301
  CreateGeneOntologyUserObject@Base 6.1.20030421
  CreateGenomeProjectsDBUserObject@Base 6.1.20060301
+ CreateJoinRequest@Base 6.1.20100808
  CreateMaskByteStore@Base 6.1.20041020
  CreateMasterAsnIndex@Base 6.1.20070822
  CreateMatPeptideFromCDS@Base 6.1.20090719
@@ -4209,9 +4277,14 @@ libncbiobj.so.6 libncbi6 #MINVER#
  CreatePropaStruc@Base 6.1.20030421
  CreateRefGeneTrackUserObject@Base 6.1.20030421
  CreateSeqIdFromText@Base 6.1.20080302
+ CreateStructuredCommentTableFromSeqEntry@Base 6.1.20100808
  CreateStructuredCommentUserObject@Base 6.1.20060507
  CreateStructuredCommentsFromFile@Base 6.1.20081116
+ CreateStructuredCommentsFromRow@Base 6.1.20100808
  CreateSubmissionUserObject@Base 6.1.20030421
+ CreateTPAAssemblyAccessionField@Base 6.1.20100808
+ CreateTPAAssemblyFromField@Base 6.1.20100808
+ CreateTPAAssemblyToField@Base 6.1.20100808
  CreateTaxon3Request@Base 6.1.20041020
  CreateTpaAssemblyUserObject@Base 6.1.20030421
  CreateWholeInterval@Base 6.1.20030421
@@ -4463,6 +4536,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  DateFree@Base 6.1.20030421
  DateMatch@Base 6.1.20030421
  DateNew@Base 6.1.20030421
+ DateParse@Base 6.1.20100808
  DatePrint@Base 6.1.20030421
  DateRead@Base 6.1.20030421
  DateTimeCurr@Base 6.1.20030421
@@ -4499,6 +4573,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  DeleteRemainingViews@Base 6.1.20061015
  DeleteSeqHistAssembliesForList@Base 6.1.20081116
  DeleteSites@Base 6.1.20030421
+ DeltaItemAsnRead@Base 6.1.20100808
+ DeltaItemAsnWrite@Base 6.1.20100808
+ DeltaItemFree@Base 6.1.20100808
+ DeltaItemNew@Base 6.1.20100808
  DeltaLitOnly@Base 6.1.20050828
  DeltaSeqAsnRead@Base 6.1.20030421
  DeltaSeqAsnWrite@Base 6.1.20030421
@@ -4529,6 +4607,16 @@ libncbiobj.so.6 libncbi6 #MINVER#
  DenseSegNew@Base 6.1.20030421
  DenseSegStats@Base 6.1.20030421
  DenseSegToDenseDiag@Base 6.1.20030421
+ DependentFieldRuleAsnRead@Base 6.1.20100808
+ DependentFieldRuleAsnWrite@Base 6.1.20100808
+ DependentFieldRuleFree@Base 6.1.20100808
+ DependentFieldRuleNew@Base 6.1.20100808
+ DependentFieldSetAsnRead@Base 6.1.20100808
+ DependentFieldSetAsnWrite@Base 6.1.20100808
+ DependentFieldSetFree@Base 6.1.20100808
+ DescStreamFree@Base 6.1.20100808
+ DescStreamListFree@Base 6.1.20100808
+ DescStreamNew@Base 6.1.20100808
  DetachDataForProc@Base 6.1.20030421
  DisableTRNATests@Base 6.1.20070822
  DiscReportOutputConfigFree@Base 6.1.20081116
@@ -4565,6 +4653,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  DoesBiosourceMatchConstraint@Base 6.1.20080302
  DoesDeltaSeqHaveGapTypeOrLinkage@Base 6.1.20070822
  DoesObjectMatchConstraintChoiceSet@Base 6.1.20081116
+ DoesSeqIDListMeetStringConstraint@Base 6.1.20100808
  DoesSeqLitHaveGapTypeOrLinkage@Base 6.1.20070822
  DoesSingleStringMatchConstraint@Base 6.1.20080302
  DoesStringMatchConstraint@Base 6.1.20080302
@@ -4765,6 +4854,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ExpandClickableItemList@Base 6.1.20081116
  ExpandDiscrepancyReportTestsFromString@Base 6.1.20080302
  ExportFieldTable@Base 6.1.20081116
+ ExtLocAsnRead@Base 6.1.20100808
+ ExtLocAsnWrite@Base 6.1.20100808
+ ExtLocFree@Base 6.1.20100808
+ ExtLocNew@Base 6.1.20100808
  Extend3PartialSeqIntToEndOrGap@Base 6.1.20090809
  Extend5PartialSeqIntToEndOrGap@Base 6.1.20090809
  ExtendPartialsToEndOrGap@Base 6.1.20090301
@@ -4931,7 +5024,6 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FindAdjacentDuplicateLocusTagGenes@Base 6.1.20080302
  FindAlignSeqAnnotsForBioseq@Base 6.1.20050429
  FindAlignmentsForBioseq@Base 6.1.20041020
- FindBacterialExtendablePartials@Base 6.1.20090719
  FindBacterialNonExtendablePartials@Base 6.1.20090719
  FindBadLocusTagsInList@Base 6.1.20080302
  FindBestModifiers@Base 6.1.20080302
@@ -4944,10 +5036,12 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FindCDSmRNAGeneLocationDiscrepancies@Base 6.1.20070822
  FindCit@Base 6.1.20030421
  FindCodingRegion@Base 6.1.20030421
+ FindCommentDescriptors@Base 6.1.20100808
  FindContigDB@Base 6.1.20030421
  FindContigList@Base 6.1.20030421
  FindDuplicateGeneLocus@Base 6.1.20070822
- FindExactStringInStrings@Base 6.1.20080302
+ FindExactStringListMatch@Base 6.1.20100808
+ FindExtendablePartials@Base 6.1.20100808
  FindFeatDefType@Base 6.1.20030421
  FindFeatDefTypeFromKey@Base 6.1.20030421
  FindFeatFromFeatDefType@Base 6.1.20030421
@@ -4956,8 +5050,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FindIDForEntry@Base 6.1.20030421
  FindInconsistentSourceAndDefline@Base 6.1.20070822
  FindKeyFromFeatDefType@Base 6.1.20030421
+ FindMismatchedComments@Base 6.1.20100808
  FindMissingProteinIDs@Base 6.1.20070822
  FindModelEvidenceField@Base 6.1.20030421
+ FindNcbiCleanupUserObject@Base 6.1.20100808
  FindNonmatchingContigSources@Base 6.1.20070822
  FindNthBioseq@Base 6.1.20030421
  FindNthGeneOnBspByLabelOrLocusTag@Base 6.1.20070822
@@ -4967,6 +5063,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FindNucBioseq@Base 6.1.20030421
  FindNucSeqEntry@Base 6.1.20030421
  FindNucleotideLocationForProteinFeatureConversion@Base 6.1.20081116
+ FindOrderedLocations@Base 6.1.20100808
  FindParticalCDSsInCompleteSequences@Base 6.1.20070822
  FindProt@Base 6.1.20030421
  FindProteinIDCallback@Base 6.1.20080302
@@ -4977,6 +5074,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FindResidueByName@Base 6.1.20041020
  FindSE@Base 6.1.20030421
  FindSeqAlignInSeqEntry@Base 6.1.20030421
+ FindSeqAnnotCleanupUserObj@Base 6.1.20100808
  FindSeqIdinSeqAlign@Base 6.1.20030421
  FindSeqSubmitForSeqEntry@Base 6.1.20090719
  FindShortContigs@Base 6.1.20070822
@@ -4988,6 +5086,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FindStringsInEntity@Base 6.1.20060301
  FindSuspectPhrases@Base 6.1.20070822
  FindSuspectProductNames@Base 6.1.20070822
+ FindSuspectProductNamesInNameList@Base 6.1.20100808
+ FindTitlesOnSets@Base 6.1.20100808
  FindTranslExceptNotes@Base 6.1.20070822
  FindTrnaAA3@Base 6.1.20030421
  FindTrnaAA@Base 6.1.20030421
@@ -5000,11 +5100,24 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FirstResidueInCode@Base 6.1.20030421
  FixAbbreviationsInElement@Base 6.1.20080302
  FixAffiliationShortWordsInElement@Base 6.1.20090719
- FixBacterialExtendablePartials@Base 6.1.20090719
  FixBacterialNonExtendablePartials@Base 6.1.20090719
+ FixCapitalizationInAuthor@Base 6.1.20100808
  FixCapitalizationInElement@Base 6.1.20080302
+ FixCapitalizationInString@Base 6.1.20100808
+ FixCapitalizationInTitle@Base 6.1.20100808
+ FixCapsInPubAffil@Base 6.1.20100808
+ FixExtendablePartials@Base 6.1.20100808
+ FixHumanHosts@Base 6.1.20100808
  FixLatLonFormat@Base 6.1.20070822
+ FixMismatchedComments@Base 6.1.20100808
+ FixNonWGSSets@Base 6.1.20100808
+ FixOrderedLocations@Base 6.1.20100808
  FixOrgNamesInString@Base 6.1.20080302
+ FixPubCapsActionAsnRead@Base 6.1.20100808
+ FixPubCapsActionAsnWrite@Base 6.1.20100808
+ FixPubCapsActionFree@Base 6.1.20100808
+ FixPubCapsActionNew@Base 6.1.20100808
+ FixUsaAndStateAbbreviations@Base 6.1.20100808
  FlatAlignNode@Base 6.1.20030421
  FlatAnnotPartial@Base 6.1.20030421
  FlatAuthor@Base 6.1.20030421
@@ -5058,6 +5171,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FreeBufferedReadList@Base 6.1.20040505
  FreeClickableList@Base 6.1.20070822
  FreeContextList@Base 6.1.20080302
+ FreeDeflineFeatureRequestList@Base 6.1.20100808
  FreeEquivAlign@Base 6.1.20030421
  FreeFeatureList@Base 6.1.20030421
  FreeGlobalDiscrepancyList@Base 6.1.20080302
@@ -5075,10 +5189,31 @@ libncbiobj.so.6 libncbi6 #MINVER#
  FreeSequenceLists@Base 6.1.20081116
  FreeTabTable@Base 6.1.20080302
  FreeTextAlignList@Base 6.1.20030421
+ GBAltSeqDataAsnRead@Base 6.1.20100808
+ GBAltSeqDataAsnWrite@Base 6.1.20100808
+ GBAltSeqDataFree@Base 6.1.20100808
+ GBAltSeqDataNew@Base 6.1.20100808
+ GBAltSeqItemAsnRead@Base 6.1.20100808
+ GBAltSeqItemAsnWrite@Base 6.1.20100808
+ GBAltSeqItemFree@Base 6.1.20100808
+ GBAltSeqItemNew@Base 6.1.20100808
  GBBlockAsnRead@Base 6.1.20030421
  GBBlockAsnWrite@Base 6.1.20030421
  GBBlockFree@Base 6.1.20030421
+ GBBlockIsCompletelyEmpty@Base 6.1.20100808
  GBBlockNew@Base 6.1.20030421
+ GBCommentAsnRead@Base 6.1.20100808
+ GBCommentAsnWrite@Base 6.1.20100808
+ GBCommentFree@Base 6.1.20100808
+ GBCommentItemAsnRead@Base 6.1.20100808
+ GBCommentItemAsnWrite@Base 6.1.20100808
+ GBCommentItemFree@Base 6.1.20100808
+ GBCommentItemNew@Base 6.1.20100808
+ GBCommentNew@Base 6.1.20100808
+ GBCommentParagraphAsnRead@Base 6.1.20100808
+ GBCommentParagraphAsnWrite@Base 6.1.20100808
+ GBCommentParagraphFree@Base 6.1.20100808
+ GBCommentParagraphNew@Base 6.1.20100808
  GBDescrComFeat@Base 6.1.20030421
  GBFeatErrSpec@Base 6.1.20030421
  GBFeatKeyNameValid@Base 6.1.20030421
@@ -5087,6 +5222,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GBFeatureAsnWrite@Base 6.1.20030421
  GBFeatureFree@Base 6.1.20030421
  GBFeatureNew@Base 6.1.20030421
+ GBFeatureSetAsnRead@Base 6.1.20100808
+ GBFeatureSetAsnWrite@Base 6.1.20100808
+ GBFeatureSetFree@Base 6.1.20100808
+ GBFeatureSetNew@Base 6.1.20100808
  GBGetAuthNames@Base 6.1.20030421
  GBIntervalAsnRead@Base 6.1.20030421
  GBIntervalAsnWrite@Base 6.1.20030421
@@ -5117,27 +5256,14 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GBSetAsnRead@Base 6.1.20030421
  GBSetAsnWrite@Base 6.1.20030421
  GBSetFree@Base 6.1.20030421
- GBTagAsnRead@Base 6.1.20090301
- GBTagAsnWrite@Base 6.1.20090301
- GBTagFree@Base 6.1.20090301
- GBTagNamesAsnRead@Base 6.1.20090301
- GBTagNamesAsnWrite@Base 6.1.20090301
- GBTagNamesFree@Base 6.1.20090301
- GBTagNew@Base 6.1.20090301
- GBTagsAsnRead@Base 6.1.20090301
- GBTagsAsnWrite@Base 6.1.20090301
- GBTagsFree@Base 6.1.20090301
- GBTagsetAsnRead@Base 6.1.20090301
- GBTagsetAsnWrite@Base 6.1.20090301
- GBTagsetFree@Base 6.1.20090301
- GBTagsetNew@Base 6.1.20090301
- GBTagsetRuleSetAsnRead@Base 6.1.20090301
- GBTagsetRuleSetAsnWrite@Base 6.1.20090301
- GBTagsetRuleSetFree@Base 6.1.20090301
- GBTagsetRulesAsnRead@Base 6.1.20090301
- GBTagsetRulesAsnWrite@Base 6.1.20090301
- GBTagsetRulesFree@Base 6.1.20090301
- GBTagsetRulesNew@Base 6.1.20090301
+ GBStrucCommentAsnRead@Base 6.1.20100808
+ GBStrucCommentAsnWrite@Base 6.1.20100808
+ GBStrucCommentFree@Base 6.1.20100808
+ GBStrucCommentItemAsnRead@Base 6.1.20100808
+ GBStrucCommentItemAsnWrite@Base 6.1.20100808
+ GBStrucCommentItemFree@Base 6.1.20100808
+ GBStrucCommentItemNew@Base 6.1.20100808
+ GBStrucCommentNew@Base 6.1.20100808
  GBXrefAsnRead@Base 6.1.20060301
  GBXrefAsnWrite@Base 6.1.20060301
  GBXrefFree@Base 6.1.20060301
@@ -5231,11 +5357,13 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetBankitCommentsOnSep@Base 6.1.20081116
  GetBarcodeDiscrepancies@Base 6.1.20070822
  GetBarcodeFailedAccessionList@Base 6.1.20070822
+ GetBarcodeLowTraceList@Base 6.1.20100808
  GetBarcodePassFail@Base 6.1.20070822
  GetBarcodeTestFailureReasons@Base 6.1.20081116
  GetBarcodeTestName@Base 6.1.20070822
  GetBarcodeTestNumFromBarcodeTestName@Base 6.1.20070822
  GetBestProteinFeatureUnindexed@Base 6.1.20030421
+ GetBestSeqEntryForItem@Base 6.1.20100808
  GetBestTopParentForData@Base 6.1.20030421
  GetBestTopParentForDataEx@Base 6.1.20030421
  GetBestTopParentForItemID@Base 6.1.20030421
@@ -5254,11 +5382,13 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetCitListsForSeqEntry@Base 6.1.20090301
  GetCitationNumberForMinPub@Base 6.1.20090301
  GetCommentRuleFromRuleSet@Base 6.1.20090719
+ GetCommonOrgRefForSeqEntry@Base 6.1.20100808
  GetCompletednessTypeList@Base 6.1.20080302
  GetConsensusReadAln@Base 6.1.20090301
  GetCorrectedCountryCapitalization@Base 6.1.20090301
  GetCountryFix@Base 6.1.20070822
  GetDBXrefFromGene@Base 6.1.20030421
+ GetDBxrefFromBioSource@Base 6.1.20100808
  GetDNAbyAccessionDotVersion@Base 6.1.20030421
  GetDaysInMonth@Base 6.1.20081116
  GetDefinitionLine@Base 6.1.20030421
@@ -5316,11 +5446,13 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetIndexForResidue@Base 6.1.20030421
  GetItemIDGivenPointer@Base 6.1.20030421
  GetKeywordLine@Base 6.1.20030421
+ GetKeywordPrefix@Base 6.1.20100808
  GetLODScoreBitValue@Base 6.1.20030421
  GetLODScoreNumber@Base 6.1.20030421
  GetLeftAndRightOffsetsInBioseq@Base 6.1.20090301
  GetLocationList@Base 6.1.20080302
  GetLocusPartsAwp@Base 6.1.20030421
+ GetLocusTagPrefixList@Base 6.1.20100808
  GetLongSymbolForResidue@Base 6.1.20030421
  GetMacroBondTypeName@Base 6.1.20081116
  GetMacroSiteTypeName@Base 6.1.20081116
@@ -5334,6 +5466,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetMonthAbbrev@Base 6.1.20081116
  GetMonthFromToken@Base 6.1.20081116
  GetMonthNumFromAbbrev@Base 6.1.20081116
+ GetMultipleFieldValuesForObject@Base 6.1.20100808
+ GetMultipleSourceQualsFromBioSource@Base 6.1.20100808
  GetNAFeatKey@Base 6.1.20030421
  GetNameForResidue@Base 6.1.20030421
  GetNameForRnaField@Base 6.1.20081116
@@ -5341,6 +5475,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetNumFeatQual@Base 6.1.20080302
  GetNumOfSeqBlks@Base 6.1.20030421
  GetNumberObjMgrSelect@Base 6.1.20030421
+ GetObjectIdString@Base 6.1.20100808
  GetObjectListForAECRAction@Base 6.1.20080302
  GetObjectListForAECRActionEx@Base 6.1.20090301
  GetObjectListForFieldType@Base 6.1.20081116
@@ -5349,7 +5484,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetOffsetInBioseqEx@Base 6.1.20090301
  GetOffsetInLoc@Base 6.1.20030421
  GetOrderBySeqId@Base 6.1.20030421
+ GetOrgModQualFromSrcQual@Base 6.1.20100808
  GetOrgModQualName@Base 6.1.20070822
+ GetOrgModSearch@Base 6.1.20100808
  GetOrganismTaxLookupFailuresInSeqEntry@Base 6.1.20070822
  GetOriginList@Base 6.1.20080302
  GetPDBSourceLine@Base 6.1.20030421
@@ -5373,6 +5510,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetQualFromFeature@Base 6.1.20080302
  GetQualFromFeatureEx@Base 6.1.20090301
  GetRNAProductString@Base 6.1.20090301
+ GetRNARefProductString@Base 6.1.20100808
  GetRNATypeList@Base 6.1.20081116
  GetRemovableItemName@Base 6.1.20080302
  GetRepresentativeBioseqFromBioseqSet@Base 6.1.20081116
@@ -5389,11 +5527,13 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetSeqIdForGI@Base 6.1.20030421
  GetSeqIdList@Base 6.1.20030421
  GetSeqIdSetForGI@Base 6.1.20030421
+ GetSeqLocPartialSet@Base 6.1.20100808
  GetSequenceByBsp@Base 6.1.20030421
  GetSequenceByFeature@Base 6.1.20030421
  GetSequenceByIdOrAccnDotVer@Base 6.1.20030421
  GetSequenceForObject@Base 6.1.20081116
  GetSequenceListsForMatchTypeInTabTable@Base 6.1.20081116
+ GetSetClassName@Base 6.1.20100808
  GetSiteTypeList@Base 6.1.20081116
  GetSourceQualDescList@Base 6.1.20080302
  GetSourceQualFieldListFromBioSource@Base 6.1.20081116
@@ -5405,6 +5545,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetSourceQualTypeByName@Base 6.1.20080302
  GetSpecialCharacterReplacement@Base 6.1.20080302
  GetSpecialMacCharacterReplacement@Base 6.1.20080302
+ GetSpecialPlastidGenCode@Base 6.1.20100808
  GetSpecialWinCharacterReplacement@Base 6.1.20080302
  GetSrcQualFromSubSrcOrOrgMod@Base 6.1.20081116
  GetStateAbbreviation@Base 6.1.20080302
@@ -5430,6 +5571,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  GetYearFromToken@Base 6.1.20081116
  GetmRNAForFeature@Base 6.1.20080302
  GetmRNALocationFromCDSLocation@Base 6.1.20090719
+ GetncRNAClass@Base 6.1.20100808
+ GetsDocsumTitle@Base 6.1.20100808
+ GettmRNATagPeptide@Base 6.1.20100808
  GiAccVerAsynchronousQuery@Base 6.1.20041020
  GiAccVerCheckQueue@Base 6.1.20041020
  GiAccVerOpenConnection@Base 6.1.20041020
@@ -5464,11 +5608,37 @@ libncbiobj.so.6 libncbi6 #MINVER#
  H_atoms@Base 6.1.20030421
  HasBARCODETech@Base 6.1.20090719
  HasExistingSeqHistAssembly@Base 6.1.20081116
+ HasKeywordForStructuredCommentName@Base 6.1.20100808
+ HasLowTrace@Base 6.1.20100808
  HasTpaUserObject@Base 6.1.20070822
+ INSDAltSeqDataAsnRead@Base 6.1.20100808
+ INSDAltSeqDataAsnWrite@Base 6.1.20100808
+ INSDAltSeqDataFree@Base 6.1.20100808
+ INSDAltSeqDataNew@Base 6.1.20100808
+ INSDAltSeqItemAsnRead@Base 6.1.20100808
+ INSDAltSeqItemAsnWrite@Base 6.1.20100808
+ INSDAltSeqItemFree@Base 6.1.20100808
+ INSDAltSeqItemNew@Base 6.1.20100808
+ INSDCommentAsnRead@Base 6.1.20100808
+ INSDCommentAsnWrite@Base 6.1.20100808
+ INSDCommentFree@Base 6.1.20100808
+ INSDCommentItemAsnRead@Base 6.1.20100808
+ INSDCommentItemAsnWrite@Base 6.1.20100808
+ INSDCommentItemFree@Base 6.1.20100808
+ INSDCommentItemNew@Base 6.1.20100808
+ INSDCommentNew@Base 6.1.20100808
+ INSDCommentParagraphAsnRead@Base 6.1.20100808
+ INSDCommentParagraphAsnWrite@Base 6.1.20100808
+ INSDCommentParagraphFree@Base 6.1.20100808
+ INSDCommentParagraphNew@Base 6.1.20100808
  INSDFeatureAsnRead@Base 6.1.20040505
  INSDFeatureAsnWrite@Base 6.1.20040505
  INSDFeatureFree@Base 6.1.20040505
  INSDFeatureNew@Base 6.1.20040505
+ INSDFeatureSetAsnRead@Base 6.1.20100808
+ INSDFeatureSetAsnWrite@Base 6.1.20100808
+ INSDFeatureSetFree@Base 6.1.20100808
+ INSDFeatureSetNew@Base 6.1.20100808
  INSDIntervalAsnRead@Base 6.1.20040505
  INSDIntervalAsnWrite@Base 6.1.20040505
  INSDIntervalFree@Base 6.1.20040505
@@ -5488,27 +5658,14 @@ libncbiobj.so.6 libncbi6 #MINVER#
  INSDSetAsnRead@Base 6.1.20040505
  INSDSetAsnWrite@Base 6.1.20040505
  INSDSetFree@Base 6.1.20040505
- INSDTagAsnRead@Base 6.1.20090301
- INSDTagAsnWrite@Base 6.1.20090301
- INSDTagFree@Base 6.1.20090301
- INSDTagNamesAsnRead@Base 6.1.20090301
- INSDTagNamesAsnWrite@Base 6.1.20090301
- INSDTagNamesFree@Base 6.1.20090301
- INSDTagNew@Base 6.1.20090301
- INSDTagsAsnRead@Base 6.1.20090301
- INSDTagsAsnWrite@Base 6.1.20090301
- INSDTagsFree@Base 6.1.20090301
- INSDTagsetAsnRead@Base 6.1.20090301
- INSDTagsetAsnWrite@Base 6.1.20090301
- INSDTagsetFree@Base 6.1.20090301
- INSDTagsetNew@Base 6.1.20090301
- INSDTagsetRuleSetAsnRead@Base 6.1.20090301
- INSDTagsetRuleSetAsnWrite@Base 6.1.20090301
- INSDTagsetRuleSetFree@Base 6.1.20090301
- INSDTagsetRulesAsnRead@Base 6.1.20090301
- INSDTagsetRulesAsnWrite@Base 6.1.20090301
- INSDTagsetRulesFree@Base 6.1.20090301
- INSDTagsetRulesNew@Base 6.1.20090301
+ INSDStrucCommentAsnRead@Base 6.1.20100808
+ INSDStrucCommentAsnWrite@Base 6.1.20100808
+ INSDStrucCommentFree@Base 6.1.20100808
+ INSDStrucCommentItemAsnRead@Base 6.1.20100808
+ INSDStrucCommentItemAsnWrite@Base 6.1.20100808
+ INSDStrucCommentItemFree@Base 6.1.20100808
+ INSDStrucCommentItemNew@Base 6.1.20100808
+ INSDStrucCommentNew@Base 6.1.20100808
  INSDXrefAsnRead@Base 6.1.20060301
  INSDXrefAsnWrite@Base 6.1.20060301
  INSDXrefFree@Base 6.1.20060301
@@ -5541,8 +5698,11 @@ libncbiobj.so.6 libncbi6 #MINVER#
  IndexedFastaLibFetchDisable@Base 6.1.20030421
  IndexedFastaLibFetchEnable@Base 6.1.20030421
  InitFeatureRequests@Base 6.1.20080302
+ InitOrganismDescriptionModifiers@Base 6.1.20100808
  InitWWW@Base 6.1.20040204
  InstantiateMatPeptideProducts@Base 6.1.20081116
+ InstantiateNCTitle@Base 6.1.20100808
+ InstantiateNMTitles@Base 6.1.20100808
  InstantiateProteinTitles@Base 6.1.20030421
  IntFuzzAsnRead@Base 6.1.20030421
  IntFuzzAsnWrite@Base 6.1.20030421
@@ -5566,7 +5726,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  IsFieldConstraintEmpty@Base 6.1.20081116
  IsFieldTypeCDSProduct@Base 6.1.20080302
  IsFieldTypeEmpty@Base 6.1.20080302
+ IsFieldTypeNonText@Base 6.1.20100808
+ IsFixPubCapsActionEmpty@Base 6.1.20100808
  IsGenomeProjectIDDescriptor@Base 6.1.20081116
+ IsIBOL@Base 6.1.20100808
  IsLocAInBonSameStrand@Base 6.1.20080302
  IsLocationConstraintEmpty@Base 6.1.20081116
  IsMobileElement@Base 6.1.20080302
@@ -5577,6 +5740,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  IsNucleotideChar@Base 6.1.20030421
  IsNumString@Base 6.1.20030421
  IsPopPhyEtcSet@Base 6.1.20030421
+ IsProductNameOk@Base 6.1.20100808
  IsProteinChar@Base 6.1.20030421
  IsPseudo@Base 6.1.20090301
  IsPublicationConstraintEmpty@Base 6.1.20081116
@@ -5595,6 +5759,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  IsStructuredCommentValidForRule@Base 6.1.20090719
  IsTSA@Base 6.1.20081116
  IsTestTypeAppropriateForReportType@Base 6.1.20081116
+ IsTextMarkerEmpty@Base 6.1.20100808
  IsValidId@Base 6.1.20030421
  IsValidIdChar@Base 6.1.20030421
  IsWholeWordSubstr@Base 6.1.20040204
@@ -5602,6 +5767,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  KeyFromTag@Base 6.1.20030421
  KeyTagClear@Base 6.1.20030421
  KeyTagInit@Base 6.1.20030421
+ KeywordForStructuredCommentName@Base 6.1.20100808
  LastResidueInCode@Base 6.1.20030421
  LeaveBestCDD@Base 6.1.20030421
  LinkCDSmRNAbyLabel@Base 6.1.20061015
@@ -5615,6 +5781,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ListCodingRegionsContainedInSourceFeatures@Base 6.1.20080302
  ListFeaturesInLocation@Base 6.1.20080302
  ListFeaturesOverlappingLocation@Base 6.1.20080302
+ ListFeaturesOverlappingLocationEx@Base 6.1.20100808
  ListFree@Base 6.1.20030421
  LoadCommentRuleSet@Base 6.1.20090719
  LoadDict@Base 6.1.20030421
@@ -5643,6 +5810,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  LocationIntervalAsnWrite@Base 6.1.20080302
  LocationIntervalFree@Base 6.1.20080302
  LocationIntervalNew@Base 6.1.20080302
+ LocationPosConstraintAsnRead@Base 6.1.20100808
+ LocationPosConstraintAsnWrite@Base 6.1.20100808
+ LocationPosConstraintFree@Base 6.1.20100808
  LockFarAlignmentBioseqs@Base 6.1.20061015
  LockFarComponents@Base 6.1.20030421
  LockFarComponentsEx@Base 6.1.20030421
@@ -5670,8 +5840,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  MakeCodeBreakList@Base 6.1.20070822
  MakeCommentFeature@Base 6.1.20030421
  MakeCompleteChromTitle@Base 6.1.20081116
+ MakeFeatureRequestsMatchExpectedTitle@Base 6.1.20100808
  MakeGBSelectNote@Base 6.1.20030421
  MakeGeneFeature@Base 6.1.20030421
+ MakeGroupsForUniqueValues@Base 6.1.20100808
  MakeImpFeature@Base 6.1.20030421
  MakeNewProteinSeqId@Base 6.1.20030421
  MakeNewProteinSeqIdEx@Base 6.1.20030421
@@ -5689,6 +5861,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  MakeSiteFeature@Base 6.1.20030421
  MakeSplitPubListFromTabList@Base 6.1.20081116
  MakeSyntheticSeqFeat@Base 6.1.20030421
+ MakeTextTextMarker@Base 6.1.20100808
  MakeTokensFromLine@Base 6.1.20081116
  MakeTranscriptomeAssemblySeqHist@Base 6.1.20081116
  MakeUniqueSeqID@Base 6.1.20030421
@@ -5748,6 +5921,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  MedlineSiAsnRead@Base 6.1.20030421
  MedlineSiAsnWrite@Base 6.1.20030421
  MedlineSiFree@Base 6.1.20030421
+ MergeAdjacentAnnotsInList@Base 6.1.20100808
  MergeFFValNodeStrs@Base 6.1.20040204
  MergeFeatureIntervalsToParts@Base 6.1.20070822
  MergeFunc@Base 6.1.20030421
@@ -6030,6 +6204,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ObjMgrSelect@Base 6.1.20030421
  ObjMgrSelectPrint@Base 6.1.20030421
  ObjMgrSendMsg@Base 6.1.20030421
+ ObjMgrSendMsgNoFeatureChange@Base 6.1.20100808
+ ObjMgrSendMsgOnlyFeatLabelChange@Base 6.1.20100808
  ObjMgrSendProcMsg@Base 6.1.20030421
  ObjMgrSendRowMsg@Base 6.1.20030421
  ObjMgrSetChoice@Base 6.1.20030421
@@ -6060,6 +6236,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ObjectIdNew@Base 6.1.20030421
  OffsetFeatureIDXrefs@Base 6.1.20060507
  OffsetFeatureIDs@Base 6.1.20060507
+ OncallerToolPseudoDiscrepanciesFix@Base 6.1.20100808
  OneLetterCode@Base 6.1.20030421
  OpenLog@Base 6.1.20090719
  OpenMMDBAPI@Base 6.1.20030421
@@ -6174,6 +6351,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ParseStringIntoStructuredComment@Base 6.1.20060507
  ParseStructuredVoucher@Base 6.1.20081116
  ParseTRnaString@Base 6.1.20030421
+ ParseTaxNameToQuals@Base 6.1.20100808
  ParseTitleIntoBioSource@Base 6.1.20030421
  ParseTitleIntoBioseq@Base 6.1.20030421
  ParseTitleIntoGenBank@Base 6.1.20030421
@@ -6182,6 +6360,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ParseTitleIntoMolInfo@Base 6.1.20030421
  ParseTitleIntoProtRef@Base 6.1.20030421
  ParseTitleIntoSeqHist@Base 6.1.20030421
+ ParseTitleIntoSubmitBlock@Base 6.1.20100808
  ParseTitleIntoTpaAssembly@Base 6.1.20030421
  Partial3SetActionAsnRead@Base 6.1.20080302
  Partial3SetActionAsnWrite@Base 6.1.20080302
@@ -6205,6 +6384,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  PdbBlockAsnWrite@Base 6.1.20030421
  PdbBlockFree@Base 6.1.20030421
  PdbBlockNew@Base 6.1.20030421
+ PercentNInBioseq@Base 6.1.20100808
  PersistentTransTableByCdRegion@Base 6.1.20030421
  PersistentTransTableByGenCode@Base 6.1.20030421
  PersonIdAsnRead@Base 6.1.20030421
@@ -6214,13 +6394,24 @@ libncbiobj.so.6 libncbi6 #MINVER#
  PersonIdMatch@Base 6.1.20050605
  PersonIdNew@Base 6.1.20030421
  PersonIdPrint@Base 6.1.20030421
+ PhenotypeAsnRead@Base 6.1.20100808
+ PhenotypeAsnWrite@Base 6.1.20100808
+ PhenotypeFree@Base 6.1.20100808
+ PhenotypeNew@Base 6.1.20100808
  PhrapGraphForContig@Base 6.1.20030421
  PirBlockAsnRead@Base 6.1.20030421
  PirBlockAsnWrite@Base 6.1.20030421
  PirBlockFree@Base 6.1.20030421
  PirBlockNew@Base 6.1.20030421
+ PopSetAutoDefRetro@Base 6.1.20100808
+ PopulationDataAsnRead@Base 6.1.20100808
+ PopulationDataAsnWrite@Base 6.1.20100808
+ PopulationDataFree@Base 6.1.20100808
+ PopulationDataNew@Base 6.1.20100808
  PostARefErrMessage@Base 6.1.20030421
  PowerBLASTASN1Detected@Base 6.1.20030421
+ PrepareSequenceListForSegregateByNumberOfSets@Base 6.1.20100808
+ PrepareSequenceListForSegregateByNumberPerSet@Base 6.1.20100808
  PrepareSourceFeatQuals@Base 6.1.20030421
  PrfBlockAsnRead@Base 6.1.20030421
  PrfBlockAsnWrite@Base 6.1.20030421
@@ -6249,6 +6440,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  PrintDiscrepancyTestList@Base 6.1.20081116
  PrintEPLocusLine@Base 6.1.20030421
  PrintEPSequence@Base 6.1.20030421
+ PrintFTCodeBreak@Base 6.1.20100808
  PrintFeatHeader@Base 6.1.20030421
  PrintFirstComment@Base 6.1.20030421
  PrintFormAsnRead@Base 6.1.20030421
@@ -6346,6 +6538,10 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ProjdescFree@Base 6.1.20030421
  ProjectAsnRead@Base 6.1.20030421
  ProjectAsnWrite@Base 6.1.20030421
+ ProjectDataAsnRead@Base 6.1.20100808
+ ProjectDataAsnWrite@Base 6.1.20100808
+ ProjectDataFree@Base 6.1.20100808
+ ProjectDataNew@Base 6.1.20100808
  ProjectDescrAsnRead@Base 6.1.20030421
  ProjectDescrAsnWrite@Base 6.1.20030421
  ProjectDescrFree@Base 6.1.20030421
@@ -6355,6 +6551,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ProjectItemAsnWrite@Base 6.1.20030421
  ProjectItemFree@Base 6.1.20030421
  ProjectNew@Base 6.1.20030421
+ PromoteCommonTitlesToSet@Base 6.1.20100808
  PromoteXrefs@Base 6.1.20030421
  PromoteXrefsEx@Base 6.1.20030421
  PromoteXrefsExEx@Base 6.1.20041020
@@ -6412,6 +6609,13 @@ libncbiobj.so.6 libncbi6 #MINVER#
  PubFieldConstraintAsnWrite@Base 6.1.20081116
  PubFieldConstraintFree@Base 6.1.20081116
  PubFieldConstraintNew@Base 6.1.20081116
+ PubFieldSpecialConstraintAsnRead@Base 6.1.20100808
+ PubFieldSpecialConstraintAsnWrite@Base 6.1.20100808
+ PubFieldSpecialConstraintFree@Base 6.1.20100808
+ PubFieldSpecialConstraintNew@Base 6.1.20100808
+ PubFieldSpecialConstraintTypeAsnRead@Base 6.1.20100808
+ PubFieldSpecialConstraintTypeAsnWrite@Base 6.1.20100808
+ PubFieldSpecialConstraintTypeFree@Base 6.1.20100808
  PubFree@Base 6.1.20030421
  PubIsEffectivelyEmpty@Base 6.1.20080302
  PubLabel@Base 6.1.20030421
@@ -6478,6 +6682,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  QBlastWaitForReply@Base 6.1.20030421
  QualLocCreate@Base 6.1.20030421
  QualLocWrite@Base 6.1.20030421
+ QuantityConstraintAsnRead@Base 6.1.20100808
+ QuantityConstraintAsnWrite@Base 6.1.20100808
+ QuantityConstraintFree@Base 6.1.20100808
  RDBTaxNamesClone@Base 6.1.20030421
  RDBTaxNamesFree@Base 6.1.20030421
  RID_glb@Base 6.1.20030421
@@ -6515,12 +6722,14 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ReadElandStandaloneFile@Base 6.1.20081116
  ReadFastaOnly@Base 6.1.20051206
  ReadFeatureTableFile@Base 6.1.20070822
+ ReadFilteredAsn@Base 6.1.20100808
  ReadFromElandMostCompressed@Base 6.1.20081116
  ReadFromElandSanger@Base 6.1.20081116
  ReadFromElandStandalone@Base 6.1.20081116
  ReadFromMAQString@Base 6.1.20081116
  ReadMAQFile@Base 6.1.20081116
  ReadNumberFromToken@Base 6.1.20081116
+ ReadOneColumnList@Base 6.1.20100808
  ReadPhrapFile@Base 6.1.20030421
  ReadPhrapQuality@Base 6.1.20030421
  ReadPhrapQualityFC@Base 6.1.20050828
@@ -6539,41 +6748,58 @@ libncbiobj.so.6 libncbi6 #MINVER#
  RegionTypeAsnWrite@Base 6.1.20081116
  RegionTypeFree@Base 6.1.20081116
  RegionTypeNew@Base 6.1.20081116
+ ReintegrateFilteredAsn@Base 6.1.20100808
  RemoveActionAsnRead@Base 6.1.20080302
  RemoveActionAsnWrite@Base 6.1.20080302
  RemoveActionFree@Base 6.1.20080302
  RemoveActionNew@Base 6.1.20080302
  RemoveAllNcbiCleanupUserObjects@Base 6.1.20090719
+ RemoveAllSeqAnnotCleanupUserObjs@Base 6.1.20100808
  RemoveBarcodeKeywords@Base 6.1.20070822
+ RemoveBarcodeKeywordsFromObjectList@Base 6.1.20100808
  RemoveBarcodeTech@Base 6.1.20090719
  RemoveConsortiumFromPub@Base 6.1.20090719
  RemoveConsortiums@Base 6.1.20090719
+ RemoveDBxrefForBioSource@Base 6.1.20100808
  RemoveDescriptorActionAsnRead@Base 6.1.20090301
  RemoveDescriptorActionAsnWrite@Base 6.1.20090301
  RemoveDescriptorActionFree@Base 6.1.20090301
  RemoveDescriptorActionNew@Base 6.1.20090301
  RemoveDuplicateItems@Base 6.1.20081116
+ RemoveDuplicateNestedSetsForEntityID@Base 6.1.20100808
+ RemoveExonsOnMrna@Base 6.1.20100808
  RemoveFeatureActionAsnRead@Base 6.1.20080302
  RemoveFeatureActionAsnWrite@Base 6.1.20080302
  RemoveFeatureActionFree@Base 6.1.20080302
  RemoveFeatureActionNew@Base 6.1.20080302
  RemoveGapCharsFromSequenceString@Base 6.1.20081116
  RemoveNucProtSetTitles@Base 6.1.20080302
+ RemovePopsetTitles@Base 6.1.20100808
+ RemoveProteinTitles@Base 6.1.20100808
+ RemoveQualFromFeature@Base 6.1.20100808
  RemoveQuotesFromTabTable@Base 6.1.20081116
+ RemoveRNAProductString@Base 6.1.20100808
+ RemoveSegGapsInSeqEntry@Base 6.1.20100808
  RemoveSeqEntryFromSeqEntry@Base 6.1.20030421
  RemoveSequenceFromAlignments@Base 6.1.20050429
  RemoveSourceQualFromBioSource@Base 6.1.20081116
  RemoveStringConstraintPortionFromString@Base 6.1.20081116
+ RemoveStructuredCommentKeywords@Base 6.1.20100808
  RemoveTaxRef@Base 6.1.20080302
+ RemoveTextPortionFromString@Base 6.1.20100808
  RemoveValNodeStringMatch@Base 6.1.20090719
  RenormalizeNucProtSets@Base 6.1.20030421
+ ReparseTabTableConvertFirstSpaceToTab@Base 6.1.20100808
+ ReparseTabTableConvertMultiSpaceToTab@Base 6.1.20100808
  ReplaceBioSourceAndPubs@Base 6.1.20030421
  ReplaceConsensusSequenceFromTraces@Base 6.1.20081116
  ReplaceDataForProc@Base 6.1.20030421
+ ReplaceDefinitionLine@Base 6.1.20100808
  ReplaceDiscrepancyItemWithFeatureTableStrings@Base 6.1.20080302
  ReplaceSeqAlignInSeqEntry@Base 6.1.20030421
  ReplaceSeqEntryWithSeqEntry@Base 6.1.20030421
  ReplaceSeqIdWithSeqId@Base 6.1.20081116
+ ReplaceSeqIdWithSeqIdInFeat@Base 6.1.20100808
  ReportBadLocusTagFormat@Base 6.1.20080302
  ReportConsensusMatchForBioseqSeqHist@Base 6.1.20081116
  ReportCoverageForBioseqSeqHist@Base 6.1.20081116
@@ -6590,6 +6816,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  RestoreSeqEntryObjMgrData@Base 6.1.20030421
  ResynchCDSPartials@Base 6.1.20030421
  ResynchCodingRegionPartials@Base 6.1.20030421
+ ResynchCodingRegionPartialsEx@Base 6.1.20100808
  ResynchMRNAPartials@Base 6.1.20030421
  ResynchMessengerRNAPartials@Base 6.1.20030421
  ResynchPeptidePartials@Base 6.1.20031028
@@ -6597,7 +6824,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  RetranslateOneCDS@Base 6.1.20090301
  RevCompOneFeatForBioseq@Base 6.1.20081116
  ReverseAlignmentStrand@Base 6.1.20081116
+ ReverseQualityScores@Base 6.1.20100808
  ReverseSeqData@Base 6.1.20080302
+ ReverseSeqGraph@Base 6.1.20100808
  RnaFeatTypeAsnRead@Base 6.1.20081116
  RnaFeatTypeAsnWrite@Base 6.1.20081116
  RnaFeatTypeFree@Base 6.1.20081116
@@ -6673,6 +6902,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SalpStatsResultsFree@Base 6.1.20030421
  SalpStatsResultsNew@Base 6.1.20030421
  SaveDiscrepancyConfig@Base 6.1.20070822
+ SaveDiscrepancyConfigEx@Base 6.1.20100808
  SaveNoteToCharPtrStack@Base 6.1.20030421
  SaveSeqEntryObjMgrData@Base 6.1.20030421
  Saved_ch@Base 6.1.20030421
@@ -6696,6 +6926,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SegLocToParts@Base 6.1.20030421
  SegLocToPartsEx@Base 6.1.20030421
  SegOrDeltaBioseqToRaw@Base 6.1.20030421
+ SegregateSetsByNumber@Base 6.1.20100808
+ SegregateSetsByNumberPerSet@Base 6.1.20100808
  SelEdStructAdd@Base 6.1.20030421
  SelEdStructDel@Base 6.1.20030421
  SelEdStructDup@Base 6.1.20030421
@@ -6843,6 +7075,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SeqDataAsnWriteXML@Base 6.1.20050429
  SeqDataFree@Base 6.1.20070822
  SeqDeleteByLoc@Base 6.1.20030421
+ SeqDeleteByLocEx@Base 6.1.20100808
  SeqDescAsnRead@Base 6.1.20030421
  SeqDescAsnWrite@Base 6.1.20030421
  SeqDescFree@Base 6.1.20030421
@@ -6854,6 +7087,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SeqDescrExtraCheck@Base 6.1.20030421
  SeqDescrFree@Base 6.1.20030421
  SeqDescrNew@Base 6.1.20030421
+ SeqEdAdjustFeatureInterval@Base 6.1.20100808
  SeqEdDeleteFromBsp@Base 6.1.20041020
  SeqEdFeatureAdjust@Base 6.1.20041020
  SeqEdFixProteinFeatures@Base 6.1.20080302
@@ -6880,6 +7114,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SeqEntryContainsSeqIdOfMolType@Base 6.1.20030421
  SeqEntryConvert@Base 6.1.20030421
  SeqEntryDelFeat@Base 6.1.20030421
+ SeqEntryDelFeatEx@Base 6.1.20100808
  SeqEntryDoConvert@Base 6.1.20030421
  SeqEntryFasta@Base 6.1.20030421
  SeqEntryFastaStream@Base 6.1.20040505
@@ -7018,6 +7253,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SeqLocBadSortOrder@Base 6.1.20030421
  SeqLocCheck@Base 6.1.20030421
  SeqLocCompare@Base 6.1.20030421
+ SeqLocCompareEx@Base 6.1.20100808
  SeqLocCopy@Base 6.1.20050429
  SeqLocCopyPart@Base 6.1.20030421
  SeqLocCopyRegion@Base 6.1.20030421
@@ -7148,6 +7384,8 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SeqMgrMapPartToSegmentedBioseq@Base 6.1.20030421
  SeqMgrReadLock@Base 6.1.20030421
  SeqMgrReapBioseqExtraFunc@Base 6.1.20030421
+ SeqMgrRedoDescriptorIndexes@Base 6.1.20100808
+ SeqMgrRedoFeatByLabelIndexes@Base 6.1.20100808
  SeqMgrReloadBioseqExtraFunc@Base 6.1.20030421
  SeqMgrReplaceInBioseqIndex@Base 6.1.20030421
  SeqMgrSelect@Base 6.1.20030421
@@ -7227,6 +7465,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SeqTableSparseIndexAsnWrite@Base 6.1.20080302
  SeqTableSparseIndexFree@Base 6.1.20080302
  SeqToAwp@Base 6.1.20030421
+ Seq_seqAsnRead@Base 6.1.20100808
+ Seq_seqAsnWrite@Base 6.1.20100808
+ Seq_seqFree@Base 6.1.20100808
  SeqfeatlistFree@Base 6.1.20030421
  SeqfeatlistFree_fromID@Base 6.1.20030421
  SequenceConstraintAsnRead@Base 6.1.20080302
@@ -7244,27 +7485,42 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SequenceListChoiceAsnWrite@Base 6.1.20080302
  SequenceListChoiceFree@Base 6.1.20080302
  SequenceListFree@Base 6.1.20080302
+ SequenceOfIntAsnRead@Base 6.1.20100808
+ SequenceOfIntAsnWrite@Base 6.1.20100808
+ SequenceOfIntFree@Base 6.1.20100808
  SequenceStringToSeqEntry@Base 6.1.20081116
  SequinEntryList@Base 6.1.20030421
  SerialNumberInString@Base 6.1.20030421
+ SetAutoDefIDModifiers@Base 6.1.20100808
+ SetDBxrefForBioSource@Base 6.1.20100808
+ SetDescriptorPropagate@Base 6.1.20100808
+ SetDiscrepancyLevels@Base 6.1.20100808
  SetDiscrepancyReportTestsFromString@Base 6.1.20080302
  SetEmptyGeneticCodes@Base 6.1.20030421
  SetFieldValueForObject@Base 6.1.20081116
  SetFieldValueForObjectEx@Base 6.1.20090301
  SetGeneticCodeForEntry@Base 6.1.20030421
+ SetObjectIdString@Base 6.1.20100808
  SetPhrapContigOrder@Base 6.1.20030421
  SetProductSequencePartials@Base 6.1.20080302
+ SetQualOnFeature@Base 6.1.20100808
+ SetRNAProductString@Base 6.1.20100808
+ SetRNARefProductString@Base 6.1.20100808
  SetRequiredModifiers@Base 6.1.20080302
  SetSeqFeatData@Base 6.1.20030421
  SetSeqFeatProduct@Base 6.1.20030421
  SetSeqLocPartial@Base 6.1.20030421
+ SetSeqLocPartialSet@Base 6.1.20100808
  SetSourceQualInBioSource@Base 6.1.20080302
  SetStringValue@Base 6.1.20081116
  SetStringsInValNodeStringList@Base 6.1.20090719
+ SetncRNAClass@Base 6.1.20100808
+ SettmRNATagPeptide@Base 6.1.20100808
  SetupDataBuffer@Base 6.1.20030421
  SetupDataPanel@Base 6.1.20030421
  SetupMatchPatList@Base 6.1.20030421
  ShortWordList@Base 6.1.20080302
+ ShouldExcludeSp@Base 6.1.20100808
  ShowAlignNodeText2@Base 6.1.20030421
  ShowAlignNodeText@Base 6.1.20030421
  ShowAlignmentText@Base 6.1.20030421
@@ -7287,12 +7543,14 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SortPairwiseAlignmentsByFirstSeqRange@Base 6.1.20081116
  SortSeqAlign@Base 6.1.20030421
  SortSeqAlignFromList@Base 6.1.20030421
+ SortSeqEntryQualifiers@Base 6.1.20100808
  SortUniqueFieldTypeList@Base 6.1.20081116
  SortValNode@Base 6.1.20030421
  SortVnpByClickableItemChosen@Base 6.1.20081116
  SortVnpByClickableItemDescription@Base 6.1.20070822
  SortVnpByDiscrepancyDescription@Base 6.1.20081116
  SortVnpByDiscrepancyItemText@Base 6.1.20081116
+ SortVnpByFieldRule@Base 6.1.20100808
  SortVnpByGlobalDiscrepancyString@Base 6.1.20080302
  SortVnpByObject@Base 6.1.20090301
  SortVnpByPCRSetOrder@Base 6.1.20070822
@@ -7302,6 +7560,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SortVnpByStringCILCFirst@Base 6.1.20090719
  SortVnpByStringCIUCFirst@Base 6.1.20090719
  SortVnpByStringCS@Base 6.1.20090719
+ SortVnpByUserField@Base 6.1.20100808
  SourceConstraintAsnRead@Base 6.1.20080302
  SourceConstraintAsnWrite@Base 6.1.20080302
  SourceConstraintFree@Base 6.1.20080302
@@ -7370,6 +7629,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SplitPubsByList@Base 6.1.20081116
  SpreadGapsInDeltaSeq@Base 6.1.20030421
  SqnTagFind@Base 6.1.20030421
+ SqnTagFindMultiple@Base 6.1.20100808
  SqnTagFindUnused@Base 6.1.20070822
  SqnTagFree@Base 6.1.20030421
  SqnTagParse@Base 6.1.20030421
@@ -7397,6 +7657,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  StrandFromAlignNode@Base 6.1.20030421
  StrandFromStrandType@Base 6.1.20080302
  StrandNameFromStrand@Base 6.1.20080302
+ StreamAsnForDescriptors@Base 6.1.20100808
  StreamCacheGetResidue@Base 6.1.20040505
  StreamCacheSetPosition@Base 6.1.20040505
  StreamCacheSetup@Base 6.1.20040505
@@ -7419,6 +7680,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  StripGeneRnaPcrAsnFilter@Base 6.1.20090719
  StripLocusFromSeqLoc@Base 6.1.20030421
  StripNewFeatMolInfoFieldsAsnFilter@Base 6.1.20081116
+ StripOrgNamePgcodeAsnFilter@Base 6.1.20100808
  StripPCRPrimerAsnFilter@Base 6.1.20081116
  StripSeqDataGapAsnFilter@Base 6.1.20070822
  StructuredCommentFieldAsnRead@Base 6.1.20081116
@@ -7444,10 +7706,21 @@ libncbiobj.so.6 libncbi6 #MINVER#
  SubmitBlockLabel@Base 6.1.20030421
  SubmitBlockMatch@Base 6.1.20050605
  SubmitBlockNew@Base 6.1.20030421
+ SummarizeAECRAction@Base 6.1.20100808
+ SummarizeAutodefAction@Base 6.1.20100808
+ SummarizeConstraint@Base 6.1.20100808
+ SummarizeConstraintSet@Base 6.1.20100808
+ SummarizeExistingText@Base 6.1.20100808
  SummarizeFeatQual@Base 6.1.20090301
  SummarizeFieldType@Base 6.1.20080302
+ SummarizeFixPubCapsAction@Base 6.1.20100808
+ SummarizeParseAction@Base 6.1.20100808
+ SummarizeParseDst@Base 6.1.20100808
+ SummarizeParseSrc@Base 6.1.20100808
+ SummarizeRemoveDescriptorAction@Base 6.1.20100808
  SummarizeRnaType@Base 6.1.20081116
  SummarizeSourceQual@Base 6.1.20080302
+ SummarizeTextPortion@Base 6.1.20100808
  SwapActionAsnRead@Base 6.1.20080302
  SwapActionAsnWrite@Base 6.1.20080302
  SwapActionFree@Base 6.1.20080302
@@ -7516,6 +7789,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  Taxon3GetTaxIdByName@Base 6.1.20041020
  Taxon3GetTaxIdByOrgRef@Base 6.1.20041020
  Taxon3ReplaceOrgInSeqEntry@Base 6.1.20041020
+ Taxon3ReplaceOrgInSeqEntryEx@Base 6.1.20100808
  Taxon3ReplyAsnRead@Base 6.1.20041020
  Taxon3ReplyAsnWrite@Base 6.1.20041020
  Taxon3ReplyFree@Base 6.1.20041020
@@ -7541,6 +7815,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  TextFsaGetStats@Base 6.1.20070822
  TextFsaNew@Base 6.1.20030421
  TextFsaNext@Base 6.1.20030421
+ TextMarkerAsnRead@Base 6.1.20100808
+ TextMarkerAsnWrite@Base 6.1.20100808
+ TextMarkerFree@Base 6.1.20100808
  TextPortionAsnRead@Base 6.1.20080302
  TextPortionAsnWrite@Base 6.1.20080302
  TextPortionFree@Base 6.1.20080302
@@ -7580,10 +7857,12 @@ libncbiobj.so.6 libncbi6 #MINVER#
  TranslateCdRegion@Base 6.1.20030421
  TranslationFastaStream@Base 6.1.20090301
  TrimLocInSegment@Base 6.1.20030421
+ TrimPrimerSeqJunkInSeqEntry@Base 6.1.20100808
  TrimQualityScores@Base 6.1.20060301
  TrimSeqGraph@Base 6.1.20060301
  TrimSpacesAndJunkFromEnds@Base 6.1.20030421
  TrimSpacesAndSemicolons@Base 6.1.20030421
+ TrimStopsFromCompleteCodingRegions@Base 6.1.20100808
  TxGetQueryIdFromSeqAlign@Base 6.1.20030421
  TxGetSubjectIdFromSeqAlign@Base 6.1.20030421
  TxinitAsnRead@Base 6.1.20030421
@@ -7626,6 +7905,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  UniqueStringValNodeCS@Base 6.1.20090719
  UniqueValNode@Base 6.1.20030421
  UniqueVnpByPCRSetSeq@Base 6.1.20070822
+ UnitTestSeqLocCompare@Base 6.1.20100808
  UnlockFarComponents@Base 6.1.20030421
  UpdateAceFileIds@Base 6.1.20081116
  UpdateContigIds@Base 6.1.20090301
@@ -7647,8 +7927,11 @@ libncbiobj.so.6 libncbi6 #MINVER#
  UserObjectAsnWrite@Base 6.1.20030421
  UserObjectFree@Base 6.1.20030421
  UserObjectNew@Base 6.1.20030421
+ ValNodeAddPointerToEnd@Base 6.1.20100808
+ ValNodeAddPointerToFront@Base 6.1.20100808
  ValNodeCopyPtr@Base 6.1.20081116
  ValNodeCopyStrToHead@Base 6.1.20040204
+ ValNodeDupIntList@Base 6.1.20100808
  ValNodeDupStringList@Base 6.1.20080302
  ValNodeFind@Base 6.1.20030421
  ValNodeFreeType@Base 6.1.20030421
@@ -7682,6 +7965,25 @@ libncbiobj.so.6 libncbi6 #MINVER#
  ValidateSeqLoc@Base 6.1.20030421
  ValidateTabTableValues@Base 6.1.20080302
  Validate_ParFlat_GBFeat@Base 6.1.20050828
+ VarRefDataAsnRead@Base 6.1.20100808
+ VarRefDataAsnWrite@Base 6.1.20100808
+ VarRefDataFree@Base 6.1.20100808
+ VarRefDataSetAsnRead@Base 6.1.20100808
+ VarRefDataSetAsnWrite@Base 6.1.20100808
+ VarRefDataSetFree@Base 6.1.20100808
+ VarRefDataSetNew@Base 6.1.20100808
+ VariantPropertiesAsnRead@Base 6.1.20100808
+ VariantPropertiesAsnWrite@Base 6.1.20100808
+ VariantPropertiesFree@Base 6.1.20100808
+ VariantPropertiesNew@Base 6.1.20100808
+ VariationInstAsnRead@Base 6.1.20100808
+ VariationInstAsnWrite@Base 6.1.20100808
+ VariationInstFree@Base 6.1.20100808
+ VariationInstNew@Base 6.1.20100808
+ VariationRefAsnRead@Base 6.1.20100808
+ VariationRefAsnWrite@Base 6.1.20100808
+ VariationRefFree@Base 6.1.20100808
+ VariationRefNew@Base 6.1.20100808
  VecScreenAsynchronousRequest@Base 6.1.20030421
  VecScreenCheckQueue@Base 6.1.20030421
  VecScreenOpenConnection@Base 6.1.20030421
@@ -7771,9 +8073,12 @@ libncbiobj.so.6 libncbi6 #MINVER#
  WeightedAlignmentPercentIdentity@Base 6.1.20070822
  WriteACEFile@Base 6.1.20081116
  WriteAsnDiscReport@Base 6.1.20080302
+ WriteAsnWithReplacedDescriptors@Base 6.1.20100808
  WriteBarcodeDiscrepancies@Base 6.1.20070822
+ WriteBarcodeFailureReport@Base 6.1.20100808
  WriteBarcodeTagTable@Base 6.1.20070822
  WriteBarcodeTestCompliance@Base 6.1.20070822
+ WriteBarcodeTestComplianceEx@Base 6.1.20100808
  WriteBarcodeTestComprehensive@Base 6.1.20080302
  WriteContigQualScores@Base 6.1.20090301
  WriteDiscrepancy@Base 6.1.20070822
@@ -7786,6 +8091,7 @@ libncbiobj.so.6 libncbi6 #MINVER#
  WritePDBAllModel@Base 6.1.20030421
  WritePDBRemarks@Base 6.1.20030421
  WriteStructSummary@Base 6.1.20030421
+ WriteTabTableToFile@Base 6.1.20100808
  WriteTraceArchiveRead@Base 6.1.20081116
  WriteTraceAssemblyFromAceFile@Base 6.1.20081116
  WriteTraceAssemblyFromContig@Base 6.1.20090301
@@ -7829,19 +8135,16 @@ libncbiobj.so.6 libncbi6 #MINVER#
  asn2hp_setup@Base 6.1.20030421
  asn2pr_setup@Base 6.1.20030421
  bb_sort@Base 6.1.20030421
- begin_with_punct_name@Base 6.1.20070822
  binary_search_by_chunk@Base 6.1.20030421
  binary_search_on_uint2_list@Base 6.1.20030421
  binary_search_on_uint4_list@Base 6.1.20030421
  binary_search_segment_array@Base 6.1.20030421
  blk_PrintSABP@Base 6.1.20030421
  bondList@Base 6.1.20040204
- brackets_name@Base 6.1.20070822
  buf2array@Base 6.1.20030421
  build_seqalign_fromstart@Base 6.1.20030421
  calculate_ruler@Base 6.1.20030421
  cds_gap_comment@Base 6.1.20080302
- cds_product_find_wholeword_start@Base 6.1.20081116
  cds_to_pept@Base 6.1.20030421
  char_to_insert@Base 6.1.20030421
  checkCDSselect_forprotein@Base 6.1.20030421
@@ -7898,9 +8201,6 @@ libncbiobj.so.6 libncbi6 #MINVER#
  do_no_loc_errors@Base 6.1.20030421
  empty_citgen@Base 6.1.20080302
  emptystring@Base 6.1.20030421
- end_with_end@Base 6.1.20081116
- end_with_punct_name@Base 6.1.20070822
- end_with_start@Base 6.1.20081116
  expand_seq_loc@Base 6.1.20030421
  extract_lollipop_feature@Base 6.1.20030421
  extract_node@Base 6.1.20030421
@@ -8038,6 +8338,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  kNumWGSOrganelles@Base 6.1.20081116
  kOverlappingCDSNeedsNoteFmt@Base 6.1.20081116
  kOverlappingCDSNoteText@Base 6.1.20081116
+ kTaxnameAfterBinomialString@Base 6.1.20100808
+ k_NumQuantityWords@Base 6.1.20100808
+ k_NumSpecialPubFieldWords@Base 6.1.20100808
  kmRNAVariant@Base 6.1.20090301
  label_feature@Base 6.1.20030421
  legalDbXrefs@Base 6.1.20040204
@@ -8078,11 +8381,12 @@ libncbiobj.so.6 libncbi6 #MINVER#
  nomial_keywords@Base 6.1.20080302
  not_empty_string@Base 6.1.20030421
  num_bad_misc_comment_phrases@Base 6.1.20090719
+ num_cds_product_find@Base 6.1.20100808
  num_ignore_similar_product_words@Base 6.1.20070822
  num_nomial_keywords@Base 6.1.20080302
  num_similar_product_words@Base 6.1.20070822
  num_suspect_phrases@Base 6.1.20070822
- num_suspect_product_names@Base 6.1.20070822
+ num_suspect_product_terms@Base 6.1.20100808
  num_suspect_rna_product_names@Base 6.1.20090301
  num_suspect_rrna_product_names@Base 6.1.20090719
  num_suspicious_note_phrases@Base 6.1.20081116
@@ -8110,7 +8414,6 @@ libncbiobj.so.6 libncbi6 #MINVER#
  orgmod_subtype@Base 6.1.20030421
  overlapp_ssp@Base 6.1.20030421
  overlapp_startssp@Base 6.1.20030421
- plural_name@Base 6.1.20070822
  precede_ssp@Base 6.1.20030421
  print_label@Base 6.1.20030421
  print_label_to_buffer@Base 6.1.20030421
@@ -8132,7 +8435,9 @@ libncbiobj.so.6 libncbi6 #MINVER#
  reverse_string@Base 6.1.20030421
  s_AddPeriodToEnd@Base 6.1.20040204
  s_OtherGetValue@Base 6.1.20030421
+ s_QuantityWords@Base 6.1.20100808
  s_RemovePeriodFromEnd@Base 6.1.20040204
+ s_SpecialPubFieldWords@Base 6.1.20100808
  s_tRNAGeneFromProduct@Base 6.1.20090301
  s_witch@Base 6.1.20030421
  secStrText@Base 6.1.20040204
@@ -8149,15 +8454,11 @@ libncbiobj.so.6 libncbi6 #MINVER#
  setposition_toses@Base 6.1.20030421
  setposition_tossp@Base 6.1.20030421
  showfastagap_fromalign@Base 6.1.20030421
- singleword_end@Base 6.1.20070822
- singleword_start@Base 6.1.20070822
  siteList@Base 6.1.20040204
  slp_list_len@Base 6.1.20030421
  sort_align_by_score@Base 6.1.20030421
  ss_to_ses@Base 6.1.20030421
  start_new_stack@Base 6.1.20030421
- start_with_end@Base 6.1.20081116
- start_with_start@Base 6.1.20081116
  stringhasnochar@Base 6.1.20030421
  stringhasnocharplus@Base 6.1.20030421
  subSourceToSourceIdx@Base 6.1.20040204
@@ -8168,20 +8469,13 @@ libncbiobj.so.6 libncbi6 #MINVER#
  tRNACountFeaturesAndFindDups@Base 6.1.20070822
  tRNAFindBadLength@Base 6.1.20070822
  tail_www@Base 6.1.20030421
- term_end@Base 6.1.20070822
- term_start@Base 6.1.20070822
  tie_next@Base 6.1.20030421
  tie_qual@Base 6.1.20030421
  tloc_offset@Base 6.1.20030421
  to_lower@Base 6.1.20030421
  tx_fprintf@Base 6.1.20031028
- unknown_name@Base 6.1.20070822
  update_seq_loc@Base 6.1.20030421
  use_multiple_dimension@Base 6.1.20030421
- wholeword_casesensitive_end@Base 6.1.20081116
- wholeword_casesensitive_start@Base 6.1.20081116
- wholeword_end@Base 6.1.20070822
- wholeword_start@Base 6.1.20070822
  write_out_put@Base 6.1.20030421
  www_PrintComment@Base 6.1.20030421
  www_accession@Base 6.1.20030421
@@ -8609,6 +8903,7 @@ libncbitool.so.6 libncbi6 #MINVER#
  ConvertPseudoStoE@Base 6.1.20030421
  ConvertPtoPseudoS@Base 6.1.20030421
  CopyResultHspToHSP@Base 6.1.20041020
+ CorrectGenCodes@Base 6.1.20100808
  CorrectSourceFeat@Base 6.1.20030421
  CountNodes@Base 6.1.20030421
  CountNodesOnLevel@Base 6.1.20030421
@@ -9105,6 +9400,7 @@ libncbitool.so.6 libncbi6 #MINVER#
  SeqAlignToPSeqAlignInfo@Base 6.1.20030421
  SeqEntryMoveDbxrefs@Base 6.1.20030421
  SeqEntryPubsAsn4@Base 6.1.20030421
+ SeqEntryPubsAsn4Ex@Base 6.1.20100808
  SeqEntryToAsn3@Base 6.1.20030421
  SeqEntryToAsn3Ex@Base 6.1.20030421
  SeqEntrysToBLAST@Base 6.1.20030421
@@ -9124,6 +9420,7 @@ libncbitool.so.6 libncbi6 #MINVER#
  SeqNew@Base 6.1.20030421
  SeqlocSegAa@Base 6.1.20030421
  SeqlocSegsToSeqLoc@Base 6.1.20030421
+ SeriousSeqAnnotCleanup@Base 6.1.20100808
  SeriousSeqEntryCleanup@Base 6.1.20030421
  SeriousSeqEntryCleanupBulk@Base 6.1.20030421
  SetAllCoordinates@Base 6.1.20030421
diff --git a/debian/libvibrant6a.symbols b/debian/libvibrant6a.symbols
index 5ccf101..778ee1a 100644
--- a/debian/libvibrant6a.symbols
+++ b/debian/libvibrant6a.symbols
@@ -261,7 +261,6 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  AddFeaturesToReplaceList@Base 6.1.20081116
  AddGraphSentinelToPicture@Base 6.1.20060507
  AddIntervalForImage@Base 6.1.20060507
- AddRnaSpecificQuals@Base 6.1.20080302
  AddScrollControl@Base 6.1.20060507
  AddStringToValNodeChain@Base 6.1.20060507
  AddToComment@Base 6.1.20080302
@@ -273,6 +272,9 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  AlreadyHasRNA@Base 6.1.20080302
  AnnotAlgEditFunc@Base 6.1.20060507
  AppendReplaceMessage@Base 6.1.20060507
+ ApplyFeatureDetailsDialog@Base 6.1.20100808
+ ApplyFeatureDetailsFree@Base 6.1.20100808
+ ApplyFeatureDetailsNew@Base 6.1.20100808
  ApplyFeatureToAlignment@Base 6.1.20060507
  ApplyProductToRNA@Base 6.1.20080302
  ApplyRnaTypeToSeqFeat@Base 6.1.20080302
@@ -297,10 +299,12 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  CCFetchFromNet@Base 6.1.20060507
  CCReadAnythingLoop@Base 6.1.20060507
  CalculateAlignmentOffsets@Base 6.1.20061015
+ CapChangeDialog@Base 6.1.20100808
  CdRgnFeatFormActnProc@Base 6.1.20060507
  CdRgnGenFunc@Base 6.1.20060507
  CdRgnToProtProc@Base 6.1.20060507
  CdRgnTranslateWithFrame@Base 6.1.20060507
+ ChangeComplexConstraintFieldType@Base 6.1.20100808
  ChangeDataForTabColumnConfigListDialog@Base 6.1.20090301
  CheckAlignmentSequenceLengths@Base 6.1.20061015
  CitSubFromContactInfo@Base 6.1.20060507
@@ -319,15 +323,16 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  CompareImpFeatEnumFieldAssoc@Base 6.1.20060507
  CompileMatrix@Base 6.1.20060507
  ComplexConstraintDialog@Base 6.1.20081116
+ ConstraintSetDialog@Base 6.1.20100808
  ConvertPairwiseToMultipleAlignment@Base 6.1.20060507
  ConvertProductQualToRnaRefName@Base 6.1.20080302
- ConvertToOldRNAFormat@Base 6.1.20080302
  CopyMedlineViewFormToClipboard@Base 6.1.20060507
  CopyTableDisplayRowList@Base 6.1.20060507
  CountIvals@Base 6.1.20060507
  CountMaxSeqLabel@Base 6.1.20060507
  CreateAffilDialog@Base 6.1.20060507
  CreateAlnEditorWindow@Base 6.1.20060507
+ CreateAlnEditorWindowEx@Base 6.1.20100808
  CreateAppearance@Base 6.1.20060507
  CreateAuthorDialog@Base 6.1.20060507
  CreateBioSourceDescForm@Base 6.1.20060507
@@ -437,7 +442,9 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  DatePtrToVibrant@Base 6.1.20060507
  DefinePanelDialog@Base 6.1.20060507
  DescFormReplaceWithoutUpdateProc@Base 6.1.20060507
+ DescFormReplaceWithoutUpdateProcEx@Base 6.1.20100808
  DescriptorPropagate@Base 6.1.20060507
+ DescriptorStreamEditor@Base 6.1.20100808
  DestroyAppearance@Base 6.1.20060507
  DestroyFilter@Base 6.1.20060507
  DisplayEntrezReply@Base 6.1.20060507
@@ -483,8 +490,10 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  EditBioseqToFasta@Base 6.1.20060507
  EditCitDescDirectly@Base 6.1.20090719
  EditCitFeatDirectly@Base 6.1.20090719
+ EditPubdescInPlace@Base 6.1.20100808
  EditPublicationInDialog@Base 6.1.20060507
  EnableDisableLegendItem@Base 6.1.20060507
+ EndDistanceDialog@Base 6.1.20100808
  EntityAlreadyHasViewer@Base 6.1.20061015
  EnumAssocSelectionDialog@Base 6.1.20060507
  EnumGenFunc@Base 6.1.20060507
@@ -581,6 +590,7 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  GridMatchSetUp@Base 6.1.20060507
  GroupFeatNode@Base 6.1.20060507
  HandleExistingText@Base 6.1.20070822
+ HideBioseqView@Base 6.1.20100808
  HideFeatureFunc@Base 6.1.20060507
  HideValidateDoc@Base 6.1.20060507
  HscrlProc@Base 6.1.20060507
@@ -664,6 +674,7 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  IsANamedAlignment@Base 6.1.20060507
  IsNonTextModifier@Base 6.1.20070822
  IsSegmentedBioseqWithoutParts@Base 6.1.20060507
+ IsTaxValidationRequested@Base 6.1.20100808
  ItemAlreadyHasEditor@Base 6.1.20060507
  JK_NTPattern2@Base 6.1.20060507
  JK_NTPattern2Ex@Base 6.1.20060507
@@ -682,6 +693,7 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  LaunchGeneralTextViewer@Base 6.1.20060507
  LaunchGeneralTextViewerWithRepopulate@Base 6.1.20060507
  LaunchMacroEditor@Base 6.1.20080302
+ LaunchMacroEditorBaseForm@Base 6.1.20100808
  LaunchNewBioseqViewer@Base 6.1.20060507
  LaunchRecViewer@Base 6.1.20060507
  LaunchViewerNotEditor@Base 6.1.20060507
@@ -788,6 +800,7 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  PanelOffsetFromCharOffsetEx@Base 6.1.20080302
  ParseCollectionDateOk@Base 6.1.20070822
  ParseConfigFile@Base 6.1.20060507
+ ParseDstDialog@Base 6.1.20100808
  ParseInferenceText@Base 6.1.20070822
  PicForAlignNode@Base 6.1.20060507
  PopulateGenePopup@Base 6.1.20060507
@@ -826,9 +839,11 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  RemoveFeatureFromFilterItem@Base 6.1.20060507
  RemoveFeaturesFromReplaceList@Base 6.1.20081116
  RemoveSelectedFeaturesFromList@Base 6.1.20081116
+ RemoveSeqEdCloseFunc@Base 6.1.20100808
  RemoveSeqEntryViewer@Base 6.1.20060507
  RemoveTextFromTextFreeSubSourceModifiers@Base 6.1.20060507
  ReplaceBioSourceGencodePopup@Base 6.1.20060507
+ ReplaceToolFormForBioseqView@Base 6.1.20100808
  RepopulateValidateFilter@Base 6.1.20060507
  ResetFeatureFunc@Base 6.1.20060507
  RestoreEntityIDFromFile@Base 6.1.20080302
@@ -857,6 +872,7 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  SelectionDialog@Base 6.1.20060507
  SelectionDialogEx@Base 6.1.20060507
  SelectionDialogExEx@Base 6.1.20081116
+ SeqAlnWindowScrollToAlnPos@Base 6.1.20100808
  SeqAnalFormFree@Base 6.1.20060507
  SeqAnalFormNew@Base 6.1.20060507
  SeqEdCorrectBarMax@Base 6.1.20060507
@@ -884,10 +900,9 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  SetClickableListDialogTitles@Base 6.1.20080302
  SetClickableListDisplayChosen@Base 6.1.20081116
  SetClosestParentIfDuplicating@Base 6.1.20060507
- SetDescriptorPropagate@Base 6.1.20060507
+ SetDescriptorStreamEditorIdList@Base 6.1.20100808
  SetGenome@Base 6.1.20060507
  SetNewFeatureDefaultInterval@Base 6.1.20060507
- SetRnaSpecificQuals@Base 6.1.20080302
  SetSequenceAndStrandForIntervalPage@Base 6.1.20060507
  SetupGeneticCodes@Base 6.1.20060507
  SetupPrintOptions@Base 6.1.20060507
@@ -914,6 +929,7 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  SortbySimItem@Base 6.1.20060507
  SpecialEntrezSynchronousQuery@Base 6.1.20060507
  StdDescFormActnProc@Base 6.1.20060507
+ StdDescFormActnProcNoFeatureChangeNoMolInfoChange@Base 6.1.20100808
  StdDescFormCleanupProc@Base 6.1.20060507
  StdFeatFormAcceptButtonProc@Base 6.1.20060507
  StdFeatFormActnProc@Base 6.1.20060507
@@ -933,7 +949,11 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  TableDisplayDialog@Base 6.1.20060507
  TermList_UnselectAll@Base 6.1.20060507
  TestInference@Base 6.1.20060507
+ TextPortionDialog@Base 6.1.20100808
  TextScrollWindowNew@Base 6.1.20060507
+ TextToFeatID@Base 6.1.20100808
+ TextToFeatXref@Base 6.1.20100808
+ ThreeOptionsDlg@Base 6.1.20100808
  TranslateAllBioseq@Base 6.1.20060507
  TruncateLocation@Base 6.1.20070822
  TwoStepExistingText@Base 6.1.20081116
@@ -1020,6 +1040,7 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  VSMFastaNucSave@Base 6.1.20060507
  VSMFastaProtOpen@Base 6.1.20060507
  VSMFastaProtSave@Base 6.1.20060507
+ VSMFastaProtSaveWithProduct@Base 6.1.20100808
  VSMFastaSortedProtSave@Base 6.1.20060507
  VSMFileInit@Base 6.1.20060507
  VSMGenericBinAsnOpen@Base 6.1.20060507
@@ -1039,6 +1060,10 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  ValNodeSelectionDialog@Base 6.1.20060507
  ValNodeSelectionDialogEx@Base 6.1.20060507
  ValNodeSelectionDialogExEx@Base 6.1.20081116
+ ValNodeSeqIdCopy@Base 6.1.20100808
+ ValNodeSeqIdFree@Base 6.1.20100808
+ ValNodeSeqIdMatch@Base 6.1.20100808
+ ValNodeSeqIdName@Base 6.1.20100808
  ValNodeSimpleDataFree@Base 6.1.20060507
  ValNodeStringCopy@Base 6.1.20060507
  ValNodeStringMatch@Base 6.1.20060507
@@ -1151,7 +1176,6 @@ libncbidesk.so.6 libvibrant6a #MINVER#
  inval_selstructpos@Base 6.1.20060507
  inval_selstructpos_tobottom@Base 6.1.20060507
  inval_window@Base 6.1.20060507
- kTaxnameAfterBinomialString@Base 6.1.20080302
  load_align_label_rectangle@Base 6.1.20060507
  load_align_option_for_graphic@Base 6.1.20060507
  locate_point@Base 6.1.20060507
diff --git a/debian/ncbi-tools-bin.install b/debian/ncbi-tools-bin.install
index bfddd1d..611c906 100644
--- a/debian/ncbi-tools-bin.install
+++ b/debian/ncbi-tools-bin.install
@@ -6,6 +6,7 @@ usr/bin/asn2gb
 usr/bin/asn2idx
 usr/bin/asn2xml
 usr/bin/asndhuff
+usr/bin/asndisc
 usr/bin/asnval
 usr/bin/checksub
 usr/bin/cleanasn
diff --git a/debian/rules b/debian/rules
index 6ff0e7f..112a6ed 100755
--- a/debian/rules
+++ b/debian/rules
@@ -18,7 +18,7 @@ testversions:
 
 # Set these here, rather than using the csh hackage that passes for an
 # upstream build system.  Mostly taken from ../platform/{ppc,}linux.ncbi.mk.
-# CC = gcc -pipe
+CC = gcc # -pipe
 VIBFLAG = -DWIN_MOTIF
 VIBLIBS = -lXm -lXmu -lXt -lX11 # -lXext # -lXp
 OTHERLIBS = -lm
@@ -32,7 +32,7 @@ THREAD_OBJ =
 endif
 NETENTREZVERSION = 2.02c2ASN1SPEC6
 
-CFLAGS += -Wall
+CFLAGS := $(shell dpkg-buildflags --get CFLAGS) -Wall
 ifeq ($(DEB_HOST_ARCH),alpha)
 CFLAGS += -mieee
 endif
@@ -44,7 +44,7 @@ OGLLIBS = -lGLU -lGL
 PNG_INCLUDE = -D_PNG
 PNG_LIBS = -lpng # -lz
 
-USESHLIB = NCBI_LINKINGLIBDIR="../shlib -L../lib" # Kludge.
+USESHLIB = NCBI_LINKINGLIBDIR="../shlib"
 MAKESHLIB = $(USESHLIB) NCBI_SHLIBS=shlib
 # Controls how shared libraries are built; appropriate for ELF w/GNU tools.
 
@@ -62,8 +62,9 @@ MTAPPS = blast blastall blastall_old blastpgp seedtop megablast rpsblast \
          blastclust
 
 VIB = Psequin sbtedit udv ddv blastcl3 taxblast idfetch bl2seq asn2gb tbl2asn \
-      gene2xml entrez2 gbseqget asn2all asn2asn asn2fsa asn2xml asnval \
-      cleanasn insdseqget nps2gps spidey trna2sap trna2tbl $(OGL_TARGETS)
+      gene2xml entrez2 gbseqget asn2all asn2asn asn2fsa asn2xml asndisc \
+      asnval cleanasn insdseqget nps2gps spidey trna2sap trna2tbl \
+      $(OGL_TARGETS)
 
 #OTHERS = others
 OTHERS = libncbimla.a libnetblast.a libncbitxc2.a libncbiid1.a shlib
@@ -119,6 +120,7 @@ endif
 clean:
 	dh clean
 	-rm -rf build/* bin/* include/* lib/* shlib
+	mkdir -p build bin include lib
 	-rm -f debian/*.menu $(ICONS)
 
 install-common: install-common-stamp
@@ -202,12 +204,11 @@ install-arch-stamp: install-common-stamp
 
 icon_in = link/mswin/ncbilogo.ico
 hi = debian/ncbi-data/usr/share/icons/hicolor
-lo = debian/ncbi-data/usr/share/icons/locolor
 
 install-indep: install-indep-stamp
 install-indep-stamp: install-common-stamp
 	convert link/mswin/asntool.ico debian/asntool.xpm
-	icotool -x -w 32 -b 8 -o - $(icon_in) | \
+	icotool -x -w 32 -b 32 -o - $(icon_in) | \
 	    convert png:- debian/ncbilogo.xpm
 	install -d debian/ncbi-data/etc/ncbi
 	install -m 644 debian/.*rc debian/ncbi-data/etc/ncbi
@@ -220,10 +221,9 @@ install-indep-stamp: install-common-stamp
 	    debian/ncbi-rrna-data/usr/share/ncbi/data/
 	install -d debian/ncbi-data/usr/share/pixmaps
 	install -m 644 $(ICONS) debian/ncbi-data/usr/share/pixmaps
-	for w in 16 32 48; do \
+	for w in 16 32 48 256; do \
 	    d=$${w}x$${w} && \
-	    install -d $(lo)/$$d $(hi)/$$d && \
-	    icotool -x -w $$w -b 4 -o $(lo)/$$d/ncbilogo.png $(icon_in) && \
+	    install -d $(hi)/$$d && \
 	    icotool -x -w $$w -b 32 -o $(hi)/$$d/ncbilogo.png $(icon_in) \
 	    || exit 1 ; \
 	done
diff --git a/demo/.BLAST_VERSION b/demo/.BLAST_VERSION
index eae4a66..8389c48 100644
--- a/demo/.BLAST_VERSION
+++ b/demo/.BLAST_VERSION
@@ -1 +1 @@
-2.2.21
+2.2.24
diff --git a/demo/aceread_tst.c b/demo/aceread_tst.c
index fef23db..a3003a1 100644
--- a/demo/aceread_tst.c
+++ b/demo/aceread_tst.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/22/08
 *
-* $Revision: 1.26 $
+* $Revision: 1.30 $
 *
 * File Description: 
 *
@@ -85,7 +85,8 @@ typedef enum {
   c_argChunkSize,
   n_argReadNameType,
   z_argIncludeReads,
-  l_argLimitNumContigs
+  l_argLimitNumContigs,
+  e_argReturnErrCode
 } EArgNum;
 
 Args myargs [] = {
@@ -131,6 +132,8 @@ Args myargs [] = {
     TRUE, 'z', ARG_BOOLEAN, 0.0, 0, NULL},
   {"Limit number of contigs to read", NULL, NULL, NULL,
     TRUE, 'l', ARG_INT, 0.0, 0, NULL},
+  {"Return error code", "F", NULL, NULL,
+    TRUE, 'e', ARG_BOOLEAN, 0.0, 0, NULL},
 };
 
 
@@ -1356,15 +1359,17 @@ static void ReadLargeAceFile
   }
   rbd.current_data = NULL;
 
-  ProcessLargeACEFileForContigFastaAndQualScores ( AbstractReadFunction, &rbd, 
+  if (!ProcessLargeACEFileForContigFastaAndQualScores ( AbstractReadFunction, &rbd, 
                                                           qual_scores_out == NULL ? make_qual_scores : TRUE,
-                                                          has_errors, ProcessContigCountCallback, &file_count_list);
+                                                        has_errors, ProcessContigCountCallback, &file_count_list)) {
+    goto escape;
+  }
 
   FileClose (rbd.fp);
   rbd.fp = NULL;
 
   /* prepare XML output */
-  if (c.xml_base != NULL) {
+  if (!StringHasNoText (c.xml_base)) {
     if (chunk_size < 1) {
       summ = SummarizeContigCountList (file_count_list.list);
       c.xml_out = FileOpen (c.xml_base, "w");
@@ -1429,7 +1434,7 @@ static void ReadLargeAceFile
       } else if (datatype == OBJ_SUBMIT_BLOCK) {
         c.sbp = (SubmitBlockPtr) dataptr;
       } else if (datatype == OBJ_SEQDESC) {
-        sdp = (SeqDescrPtr) datatype;
+        sdp = (SeqDescrPtr) dataptr;
         if (sdp->choice == Seq_descr_source) {
           has_source = TRUE;
         }
@@ -1570,6 +1575,7 @@ Int2 Main (void)
   SeqSubmitPtr ssp;
   CharPtr      id_substitution_file = NULL;
   Int4         taxon_id = 0;
+  Boolean      return_err_code = FALSE;
 
   /* standard setup */
 
@@ -1640,6 +1646,7 @@ Int2 Main (void)
   suppress_lookup = (Boolean) myargs [L_argSuppressIdLookup].intvalue;
   srr_ids = (Boolean) myargs[R_argSRRids].intvalue;
   fasta_out = (Boolean) myargs[f_argFASTA].intvalue;
+  return_err_code = (Boolean) myargs[e_argReturnErrCode].intvalue;
 
   /* ASN.1 file to validate against */
   asn_file = (CharPtr) myargs [V_argValidateAgainstAsn1File].strvalue;
@@ -1651,13 +1658,13 @@ Int2 Main (void)
                                &assembly,
                                &taxon_id)) {
     Message (MSG_FATAL, "Error reading TSA fields");
-    return 1;
+    return return_err_code ? 1 : 0;
   }
 
   if (!StringHasNoText (xmlfile) && (StringHasNoText (center_name) || taxon_id < 1)) {
     PrintACEFormatErrorXML ("Must specify center name and taxid for XML output", NULL, &has_errors);
     printf ("</aceread>\n");
-    return 1;
+    return return_err_code ? 1 : 0;
   }        
 
   len = StringLen (infile);
@@ -1691,7 +1698,7 @@ Int2 Main (void)
                       (Boolean) myargs [z_argIncludeReads].intvalue);
     if (has_errors) {
       printf ("</aceread>\n");
-      return 1;
+      return return_err_code ? 1 : 0;
     } else {
       return 0;
     }
@@ -1701,7 +1708,7 @@ Int2 Main (void)
     f = FileOpen (id_substitution_file, "r");
     if (f == NULL) {
       Message (MSG_FATAL, "Unable to open %s", id_substitution_file);
-      return 1;
+      return return_err_code ? 1 : 0;
     }
   }
 
@@ -1709,7 +1716,7 @@ Int2 Main (void)
     rbd.fp = FileOpen (infile, "r");
     if (rbd.fp == NULL) {
       Message (MSG_FATAL, "Unable to open %s", infile);
-      return 1;
+      return return_err_code ? 1 : 0;
     }
 
     rbd.current_data = NULL;
@@ -1718,7 +1725,7 @@ Int2 Main (void)
     rbd.fp = FileOpen (infile, "r");
     if (rbd.fp == NULL) {
       Message (MSG_FATAL, "Unable to open %s", infile);
-      return 1;
+      return return_err_code ? 1 : 0;
     }
 
     rbd.current_data = NULL;
@@ -1727,13 +1734,13 @@ Int2 Main (void)
     rbd.fp = OpenAceFile (infile);
     if (rbd.fp == NULL) {
       Message (MSG_FATAL, "Unable to open %s", infile);
-      return 1;
+      return return_err_code ? 1 : 0;
     }
     rbd.current_data = NULL;
     afp = ReadACEFile ( AbstractReadFunction, &rbd, make_qual_scores, &has_errors);
   } else {
     Message (MSG_FATAL, "Unrecognized format: %s\n", format);
-    return 1;
+    return return_err_code ? 1 : 0;
   }
   FileClose (rbd.fp);
   if (afp == NULL) {
diff --git a/demo/asn2all.c b/demo/asn2all.c
index f81b5eb..96b6e02 100644
--- a/demo/asn2all.c
+++ b/demo/asn2all.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/26/04
 *
-* $Revision: 1.64 $
+* $Revision: 1.76 $
 *
 * File Description:
 *
@@ -53,7 +53,7 @@
 #include <pmfapi.h>
 #include <lsqfetch.h>
 
-#define ASN2ALL_APP_VER "5.2"
+#define ASN2ALL_APP_VER "6.3"
 
 CharPtr ASN2ALL_APPLICATION = ASN2ALL_APP_VER;
 
@@ -97,6 +97,7 @@ typedef enum {
 typedef struct appflags {
   AppFormat     format;
   Boolean       automatic;
+  Boolean       catenated;
   Boolean       batch;
   Boolean       binary;
   Boolean       compressed;
@@ -108,6 +109,7 @@ typedef struct appflags {
   ModType       mode;
   Boolean       extended;
   Boolean       failed;
+  Uint4         cdsID;
   FILE          *nt;
   FILE          *aa;
   AsnIoPtr      an;
@@ -236,37 +238,55 @@ static void IsItFar (
 }
 
 static void DoCDSFasta (
-  SeqFeatPtr sfp,
+  BioseqPtr bsp,
   Pointer userdata
 )
 
 {
   AppFlagPtr  afp;
+  Char               buf [32];
+  SeqMgrFeatContext  fcontext;
+  SeqFeatPtr         sfp;
 
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return;
+  if (bsp == NULL || ! ISA_na (bsp->mol)) return;
   afp = (AppFlagPtr) userdata;
   if (afp == NULL) return;
 
+  sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &fcontext);
+  while (sfp != NULL) {
+    afp->cdsID++;
+    sprintf (buf, "_cds_%ld", (long) afp->cdsID);
   CdRegionFastaStream (sfp, afp->nt,
                        STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL,
-                       afp->linelen, 0, 0, TRUE);
+                         afp->linelen, 0, 0, TRUE, buf);
+    sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &fcontext);
+  }
 }
 
 static void DoTransFasta (
-  SeqFeatPtr sfp,
+  BioseqPtr bsp,
   Pointer userdata
 )
 
 {
   AppFlagPtr  afp;
+  Char               buf [32];
+  SeqMgrFeatContext  fcontext;
+  SeqFeatPtr         sfp;
 
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) return;
+  if (bsp == NULL || ! ISA_na (bsp->mol)) return;
   afp = (AppFlagPtr) userdata;
   if (afp == NULL) return;
 
+  sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, 0, &fcontext);
+  while (sfp != NULL) {
+    afp->cdsID++;
+    sprintf (buf, "_prt_%ld", (long) afp->cdsID);
   TranslationFastaStream (sfp, afp->aa,
                           STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL,
-                          afp->linelen, 0, 0, TRUE);
+                            afp->linelen, 0, 0, TRUE, buf);
+    sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, 0, &fcontext);
+  }
 }
 
 static void FormatRecord (
@@ -332,7 +352,8 @@ static void FormatRecord (
         top = GetTopSeqEntryForEntityID (entityID);
         if (top != NULL) {
           SeqMgrIndexFeatures (0, top->data.ptrvalue);
-          VisitFeaturesInSep (top, (Pointer) afp, DoCDSFasta);
+          afp->cdsID = 0;
+          VisitBioseqsInSep (top, (Pointer) afp, DoCDSFasta);
         }
       }
       if (afp->aa != NULL) {
@@ -340,7 +361,8 @@ static void FormatRecord (
         top = GetTopSeqEntryForEntityID (entityID);
         if (top != NULL) {
           SeqMgrIndexFeatures (0, top->data.ptrvalue);
-          VisitFeaturesInSep (top, (Pointer) afp, DoTransFasta);
+          afp->cdsID = 0;
+          VisitBioseqsInSep (top, (Pointer) afp, DoTransFasta);
         }
       }
       break;
@@ -404,7 +426,7 @@ static void ProcessSingleRecord (
   ValNodePtr    bsplist;
   BioseqSetPtr  bssp;
   Pointer       dataptr = NULL;
-  Uint2         datatype, entityID = 0;
+  Uint2         datatype = 0, entityID = 0;
   FILE          *fp;
   ObjMgrPtr     omp;
   SeqEntryPtr   sep;
@@ -748,6 +770,11 @@ static void ProcessOneRecord (
 
 {
   AppFlagPtr  afp;
+  Pointer      dataptr;
+  Uint2        datatype;
+  Uint2        entityID;
+  FILE         *fp;
+  SeqEntryPtr  sep;
 
   if (StringHasNoText (filename)) return;
   afp = (AppFlagPtr) userdata;
@@ -755,6 +782,15 @@ static void ProcessOneRecord (
 
   if (afp->automatic) {
     ReadSequenceAsnFile (filename, afp->binary, afp->compressed, (Pointer) afp, FormatWrapper);
+  } else if (afp->catenated) {
+    fp = FileOpen (filename, "r");
+    if (fp != NULL) {
+      while ((dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE)) != NULL) {
+        sep = GetTopSeqEntryForEntityID (entityID);
+        FormatWrapper (sep, afp);
+      }
+      FileClose (fp);
+    }
   } else if (afp->batch) {
     ProcessMultipleRecord (filename, afp);
   } else {
@@ -763,23 +799,48 @@ static void ProcessOneRecord (
 }
 
 static SeqEntryPtr SeqEntryFromAccnOrGi (
-  CharPtr accn
+  CharPtr str,
+  AppFlagPtr afp
 )
 
 {
+  CharPtr      accn;
   Boolean      alldigits;
   BioseqPtr    bsp;
+  Char         buf [64];
   Char         ch;
+  Int4         flags = 0;
   CharPtr      ptr;
+  Int2         retcode = 0;
   SeqEntryPtr  sep = NULL;
   SeqIdPtr     sip;
+  CharPtr      tmp1 = NULL;
+  CharPtr      tmp2 = NULL;
   Int4         uid = 0;
   long int     val;
   ValNode      vn;
 
-  if (StringHasNoText (accn)) return NULL;
+  if (StringHasNoText (str)) return NULL;
+  StringNCpy_0 (buf, str, sizeof (buf));
+  TrimSpacesAroundString (buf);
 
-  TrimSpacesAroundString (accn);
+  accn = buf;
+  tmp1 = StringChr (accn, ',');
+  if (tmp1 != NULL) {
+    *tmp1 = '\0';
+    tmp1++;
+    tmp2 = StringChr (tmp1, ',');
+    if (tmp2 != NULL) {
+      *tmp2 = '\0';
+      tmp2++;
+      if (StringDoesHaveText (tmp2) && sscanf (tmp2, "%ld", &val) == 1) {
+        flags = (Int4) val;
+      }
+    }
+    if (StringDoesHaveText (tmp1) && sscanf (tmp1, "%ld", &val) == 1) {
+      retcode = (Int2) val;
+    }
+  }
 
   alldigits = TRUE;
   ptr = accn;
@@ -805,13 +866,16 @@ static SeqEntryPtr SeqEntryFromAccnOrGi (
   }
 
   if (uid > 0) {
-    sep = PubSeqSynchronousQuery (uid, 0, -1);
+    sep = PubSeqSynchronousQuery (uid, retcode, flags);
     if (sep != NULL) {
       MemSet ((Pointer) &vn, 0, sizeof (ValNode));
       vn.choice = SEQID_GI;
       vn.data.intvalue = uid;
       bsp = BioseqFind (&vn);
       if (bsp != NULL) {
+        if (afp != NULL) {
+          if (afp->format == ASN_FORMAT || afp->format == XML_FORMAT) return sep;
+        }
         sep = SeqMgrGetSeqEntryForData ((Pointer) bsp);
       }
     }
@@ -924,6 +988,7 @@ Args myargs [] = {
     TRUE, 'f', ARG_STRING, 0.0, 0, NULL},
   {"ASN.1 Type\n"
    "      a Automatic\n"
+   "      c Catenated\n"
    "      z Any\n"
    "      e Seq-entry\n"
    "      b Bioseq\n"
@@ -1050,6 +1115,7 @@ Int2 Main (void)
   /* populate parameter structure */
 
   afd.automatic = FALSE;
+  afd.catenated = FALSE;
   afd.batch = FALSE;
   afd.binary = (Boolean) myargs [b_argBinary].intvalue;
   afd.compressed = (Boolean) myargs [c_argCompressed].intvalue;
@@ -1118,6 +1184,11 @@ Int2 Main (void)
     case 'a' :
       afd.type = 1;
       afd.automatic = TRUE;
+      break;
+    case 'c' :
+      afd.type = 1;
+      afd.catenated = TRUE;
+      break;
     case 'z' :
       afd.type = 1;
       break;
@@ -1311,7 +1382,7 @@ Int2 Main (void)
   if (StringDoesHaveText (accn)) {
 
     if (remote) {
-      sep = SeqEntryFromAccnOrGi (accn);
+      sep = SeqEntryFromAccnOrGi (accn, &afd);
       if (sep != NULL) {
         bsplist = NULL;
         if (afd.lock) {
diff --git a/demo/asn2fsa.c b/demo/asn2fsa.c
index 5a12ddd..3826a7f 100644
--- a/demo/asn2fsa.c
+++ b/demo/asn2fsa.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   3/4/04
 *
-* $Revision: 1.53 $
+* $Revision: 1.55 $
 *
 * File Description:
 *
@@ -61,7 +61,7 @@
 #include <accpubseq.h>
 #endif
 
-#define ASN2FSA_APP_VER "3.5"
+#define ASN2FSA_APP_VER "4.0"
 
 CharPtr ASN2FSA_APPLICATION = ASN2FSA_APP_VER;
 
diff --git a/demo/asn2gb.c b/demo/asn2gb.c
index 7197d7c..d5c1d43 100644
--- a/demo/asn2gb.c
+++ b/demo/asn2gb.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/21/98
 *
-* $Revision: 6.134 $
+* $Revision: 6.145 $
 *
 * File Description:  New GenBank flatfile generator application
 *
@@ -48,13 +48,14 @@
 #include <sequtil.h>
 #include <sqnutils.h>
 #include <explore.h>
+#include <gather.h>
 #include <toasn3.h>
 #include <asn2gnbp.h>
 
 /* asn2gnbi.h needed to test PUBSEQGetAccnVer in accpubseq.c */
 #include <asn2gnbi.h>
 
-#define ASN2GB_APP_VER "7.2"
+#define ASN2GB_APP_VER "8.5"
 
 CharPtr ASN2GB_APPLICATION = ASN2GB_APP_VER;
 
@@ -1237,18 +1238,18 @@ static void CompareFlatFiles (
 
     if (FindNucBioseq (sep) != NULL) {
 
-      sprintf (cmmd, "./oldasn2gb -i %s -o %s -m e -g 1", path3, path1);
+      sprintf (cmmd, "./oldasn2gb -i %s -o %s", path3, path1);
       system (cmmd);
 
-      sprintf (cmmd, "./newasn2gb -i %s -o %s -m e -g 1", path3, path2);
+      sprintf (cmmd, "./newasn2gb -i %s -o %s", path3, path2);
       system (cmmd);
 
     } else {
 
-      sprintf (cmmd, "./oldasn2gb -f p -i %s -o %s -m e -g 1", path3, path1);
+      sprintf (cmmd, "./oldasn2gb -f p -i %s -o %s", path3, path1);
       system (cmmd);
 
-      sprintf (cmmd, "./newasn2gb -f p -i %s -o %s -m e -g 1", path3, path2);
+      sprintf (cmmd, "./newasn2gb -f p -i %s -o %s", path3, path2);
       system (cmmd);
 
     }
@@ -1256,6 +1257,12 @@ static void CompareFlatFiles (
     sprintf (cmmd, "diff -b %s %s > %s", path1, path2, path3);
     diff = system (cmmd);
 
+    fsep = FindNthBioseq (sep, 1);
+    if (fsep == NULL || fsep->choice != 1) return;
+    bsp = (BioseqPtr) fsep->data.ptrvalue;
+    if (bsp == NULL) return;
+    SeqIdWrite (bsp->id, buf, PRINTID_FASTA_LONG, sizeof (buf));
+
     if (diff > 0) {
       sprintf (cmmd, "cat %s", path3);
       fpo = popen (cmmd, "r");
@@ -1355,7 +1362,7 @@ static Int2 HandleMultipleRecords (
 {
   AsnIoPtr        aip;
   AsnModulePtr    amp;
-  AsnTypePtr      atp, atp_bss, atp_desc, atp_sbp, atp_se, atp_ssp;
+  AsnTypePtr      atp, atp_bss, atp_desc, atp_sbp, atp_se = NULL, atp_ssp;
   Boolean         atp_se_seen = FALSE;
   BioseqPtr       bsp;
   BioseqSetPtr    bssp;
@@ -1430,11 +1437,27 @@ static Int2 HandleMultipleRecords (
     return 1;
   }
 
+  if (type == 4) {
   atp_se = AsnFind ("Bioseq-set.seq-set.E");
   if (atp_se == NULL) {
     Message (MSG_POSTERR, "Unable to find ASN.1 type Bioseq-set.seq-set.E");
     return 1;
   }
+  } else if (type == 5) {
+    atp_se = AsnFind ("Seq-submit.data.entrys.E");
+    if (atp_se == NULL) {
+      Message (MSG_POSTERR, "Unable to find ASN.1 type Seq-submit.data.entrys.E");
+      return 1;
+    }
+  } else {
+    Message (MSG_POSTERR, "Batch processing type not set properly");
+    return 1;
+  }
+
+  if (atp_se == NULL) {
+    Message (MSG_POSTERR, "Unable to find ASN.1 type for atp_se");
+    return 1;
+  }
 
 #ifdef OS_UNIX
   if (compressed) {
@@ -1480,7 +1503,7 @@ static Int2 HandleMultipleRecords (
     return 1;
   }
 
-  if ((batch == 1 || batch == 4 || batch == 5 || format != GENBANK_FMT) &&
+  if ((batch == 1 || batch == 4 || batch == 5 || batch == 7 || format != GENBANK_FMT) &&
       (extra == NULL || extra->gbseq == NULL)) {
     ofp = FileOpen (outputFile, "w");
     if (ofp == NULL) {
@@ -1912,6 +1935,7 @@ static ValNodePtr PubSeqRemoteLock (
     if (sep != NULL && IS_Bioseq (sep)) {
       bsp = (BioseqPtr) sep->data.ptrvalue;
       if (bsp != NULL) {
+        AssignIDsInEntity (0, OBJ_SEQENTRY, (Pointer) sep);
         VisitAnnotsInSep (sep, NULL, MarkLocalAnnots);
         DeleteMarkedObjects (0, OBJ_BIOSEQ, (Pointer) bsp);
         sap = bsp->annot;
@@ -2361,7 +2385,7 @@ Int2 Main (
       return 1;
     }
     xtra.aip = aip;
-    if ((Boolean) ((flags & PRODUCE_OLD_GBSEQ) != 0)) {
+    if ((Boolean) (((flags & PRODUCE_OLD_GBSEQ) != 0)) || ((custom & OLD_GBSEQ_XML) != 0)) {
       do_insdseq = FALSE;
     }
     if (do_insdseq) {
diff --git a/demo/asnbarval.c b/demo/asnbarval.c
index 74097a5..d11ac9a 100644
--- a/demo/asnbarval.c
+++ b/demo/asnbarval.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/23/07
 *
-* $Revision: 1.6 $
+* $Revision: 1.7 $
 *
 * File Description:
 *
@@ -82,6 +82,7 @@ typedef struct brflags {
   ValNodePtr            sep_list;
   ValNodePtr            bsplist;
   BarcodeTestConfigData bcd;
+  Boolean comprehensive;
 } BRFlagData, PNTR BRFlagPtr;
 
 #ifdef INTERNAL_NCBI_ASNBARVAL
@@ -552,9 +553,13 @@ static void ProcessSeqEntryList (BRFlagPtr drfp, CharPtr filename)
   for (vnp = drfp->sep_list; vnp != NULL; vnp = vnp->next) {
     sep = (SeqEntryPtr) vnp->data.ptrvalue;
     pass_fail_list = GetBarcodePassFail (sep, &(drfp->bcd));
+    if (drfp->comprehensive) {
+      WriteBarcodeTestComprehensive (ofp, pass_fail_list);
+    } else {
     WriteBarcodeTestCompliance (ofp, pass_fail_list);
   }
   pass_fail_list = BarcodeTestResultsListFree (pass_fail_list);
+  }
   for (vnp = drfp->sep_list; vnp != NULL; vnp = vnp->next) {
     sep = vnp->data.ptrvalue;
     SeqEntryFree (sep);
@@ -918,6 +923,7 @@ typedef enum {
   k_argLocalFetch,
   I_argAsnIdx,
   T_argThreads,
+  R_argComprehensiveReport,
   C_argMaxCount
 } BRFlagNum;
 
@@ -960,6 +966,8 @@ Args myargs [] = {
     TRUE, 'I', ARG_STRING, 0.0, 0, NULL},
   {"Use Threads", "F", NULL, NULL,
     TRUE, 'T', ARG_BOOLEAN, 0.0, 0, NULL},
+  {"Comprehensive Report", "F", NULL, NULL,
+    TRUE, 'R', ARG_BOOLEAN, 0.0, 0, NULL},
   {"Max Count", "0", NULL, NULL,
     TRUE, 'C', ARG_INT, 0.0, 0, NULL},
 };
@@ -1109,6 +1117,8 @@ Int2 Main (void)
   usethreads = (Boolean) myargs [T_argThreads].intvalue;
   dfd.farFetchCDSproducts = (Boolean) myargs [Z_argRemoteCDS].intvalue;
 
+  dfd.comprehensive = (Boolean) myargs [R_argComprehensiveReport].intvalue;
+
   /* maximum Percent Ns */
   max_n = myargs [n_argMaxPercentN].intvalue;
   dfd.bcd.min_n_percent = (FloatLo)(max_n);
diff --git a/demo/asndisc.c b/demo/asndisc.c
index 8afe8c9..720e226 100644
--- a/demo/asndisc.c
+++ b/demo/asndisc.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/23/07
 *
-* $Revision: 1.26 $
+* $Revision: 1.27 $
 *
 * File Description:
 *
@@ -948,6 +948,7 @@ typedef enum {
   X_argExpandCategories,
   S_argSummaryReport,
   B_argBigSequenceReport,
+  N_argProductNameFile,
   C_argMaxCount
 } DRFlagNum;
 
@@ -1011,6 +1012,8 @@ Args myargs [] = {
     TRUE, 'S', ARG_BOOLEAN, 0.0, 0, NULL},
   {"Big Sequence Report", "F", NULL, NULL,
   TRUE, 'B', ARG_BOOLEAN, 0.0, 0, NULL},
+  {"File with list of product names to check", "", NULL, NULL,
+    TRUE, 'N', ARG_FILE_IN, 0.0, 0, NULL},
   {"Max Count", "0", NULL, NULL,
     TRUE, 'C', ARG_INT, 0.0, 0, NULL},
 };
@@ -1039,11 +1042,27 @@ static CharPtr GetTestNameList (CharPtr intro)
 }
 
 
+static Boolean ValidateNameList (CharPtr filename, FILE *outputfile)
+{
+  FILE *fp;
+
+  fp = FileOpen (filename, "r");
+  if (fp == NULL) {
+    Message (MSG_FATAL, "Cannot open %s", filename);
+    return FALSE;
+  } else {
+    FindSuspectProductNamesInNameList (fp, outputfile);
+    FileClose (fp);
+    return TRUE;
+  }
+}
+
+
 Int2 Main (void)
 
 {
   Char         app [64];
-  CharPtr      asnidx, directory, infile, outfile, str, suffix, output_dir;
+  CharPtr      asnidx, directory, infile, outfile, str, suffix, output_dir, product_name_file;
   CharPtr      enabled_list, disabled_list, err_msg;
   Boolean      batch, binary, compressed, dorecurse,
                indexed, local, lock, remote, usethreads;
@@ -1103,6 +1122,7 @@ Int2 Main (void)
   infile = (CharPtr) myargs [i_argInputFile].strvalue;
   outfile = (CharPtr) myargs [o_argOutputFile].strvalue;
   output_dir = (CharPtr) myargs [r_argOutputDir].strvalue;
+  product_name_file = (CharPtr) myargs [N_argProductNameFile].strvalue;
   if (StringDoesHaveText (outfile) && StringDoesHaveText (output_dir)) {
     Message (MSG_FATAL, "-o and -q are incompatible: specify the output file name with the full path.");
     return 1;
@@ -1217,7 +1237,7 @@ Int2 Main (void)
     }
   }
 
-  if (StringHasNoText (directory) && StringHasNoText (infile)) {
+  if (StringHasNoText (directory) && StringHasNoText (infile) && StringHasNoText (product_name_file)) {
     Message (MSG_FATAL, "Input path or input file must be specified");
     return 1;
   }
@@ -1241,6 +1261,38 @@ Int2 Main (void)
     }
   }
 
+  if (!StringHasNoText (product_name_file)) {
+    ValidateNameList (product_name_file, dfd.outfp);
+    if (StringHasNoText (directory) && (StringHasNoText (infile) || StringCmp (infile, "stdin") == 0)) {
+      if (dfd.outfp != NULL) {
+        FileClose (dfd.outfp);
+      }
+      if (indexed) {
+        AsnIndexedLibFetchDisable ();
+      }
+
+      if (local) {
+        LocalSeqFetchDisable ();
+      }
+
+      if (remote) {
+#ifdef INTERNAL_NCBI_ASNDISC
+        PUBSEQBioseqFetchDisable ();
+#else
+        PubSeqFetchDisable ();
+#endif
+        SeqMgrSetPreCache (NULL);
+        SeqMgrSetSeqIdSetFunc (NULL);
+      }
+
+      TransTableFreeAll ();
+
+      ECNumberFSAFreeAll ();
+
+      return 0;
+    }      
+  }
+
   /* register fetch functions */
 
   if (remote) {
diff --git a/demo/asnmacro.c b/demo/asnmacro.c
index 26dc972..fae807a 100755
--- a/demo/asnmacro.c
+++ b/demo/asnmacro.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/12/07
 *
-* $Revision: 1.5 $
+* $Revision: 1.6 $
 *
 * File Description: 
 *
@@ -558,7 +558,7 @@ Args myargs [] = {
   {"Input is Seq-entry", "F", NULL, NULL,
     TRUE, 'e', ARG_BOOLEAN, 0.0, 0, NULL},
   {"Output is binary", "F", NULL, NULL,
-    TRUE, 'b', ARG_BOOLEAN, 0.0, 0, NULL},
+    TRUE, 'd', ARG_BOOLEAN, 0.0, 0, NULL},
   {"Macro file", "NULL", NULL, NULL,
     TRUE, 'm', ARG_FILE_IN, 0.0, 0, NULL}
 };
diff --git a/demo/asnval.c b/demo/asnval.c
index 30562d9..b493693 100644
--- a/demo/asnval.c
+++ b/demo/asnval.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11/3/04
 *
-* $Revision: 1.98 $
+* $Revision: 1.111 $
 *
 * File Description:
 *
@@ -56,11 +56,12 @@
 #include <lsqfetch.h>
 #include <valid.h>
 #include <pmfapi.h>
+#include <gbftdef.h>
 #ifdef INTERNAL_NCBI_ASN2VAL
 #include <accpubseq.h>
 #endif
 
-#define ASNVAL_APP_VER "7.3"
+#define ASNVAL_APP_VER "8.6"
 
 CharPtr ASNVAL_APPLICATION = ASNVAL_APP_VER;
 
@@ -84,8 +85,10 @@ typedef struct valflags {
   Boolean  inferenceAccnCheck;
   Boolean  testLatLonSubregion;
   Boolean  strictLatLonCountry;
+  Boolean  rubiscoTest;
   Boolean  indexerVersion;
   Boolean  automatic;
+  Boolean  catenated;
   Boolean  batch;
   Boolean  binary;
   Boolean  compressed;
@@ -484,6 +487,57 @@ static Boolean TPASmartFetchEnable (void)
 }
 #endif
 
+static void LookForBigFarSeqs (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  Int4         count = 0;
+  DeltaSeqPtr  dsp;
+  Boolean      is_ddbj = FALSE;
+  SeqIdPtr     sip;
+  BoolPtr      toomanyfarP;
+
+  if (bsp == NULL || userdata == NULL) return;
+
+  if (bsp->repr != Seq_repr_delta) return;
+  if (bsp->seq_ext_type != 4) return;
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_DDBJ) {
+      is_ddbj = TRUE;
+    }
+  }
+
+  if (! is_ddbj) return;
+
+  for (dsp = (DeltaSeqPtr) bsp->seq_ext; dsp != NULL; dsp = dsp->next) {
+    if (dsp->choice == 1) {
+      count++;
+    }
+  }
+
+  if (count > 10000) {
+    toomanyfarP = (BoolPtr) userdata;
+    *toomanyfarP = TRUE;
+  }
+}
+
+static Boolean TooManyFarComponents (
+  SeqEntryPtr sep
+)
+
+{
+  Boolean  toomanyfar = FALSE;
+
+  if (sep == NULL) return FALSE;
+
+  VisitBioseqsInSep (sep, (Pointer) &toomanyfar, LookForBigFarSeqs);
+
+  return toomanyfar;
+}
+
 static ValNodePtr DoLockFarComponents (
   SeqEntryPtr sep,
   ValFlagPtr vfp
@@ -769,6 +823,7 @@ static void DoValidation (
   vsp->inferenceAccnCheck = vfp->inferenceAccnCheck;
   vsp->testLatLonSubregion = vfp->testLatLonSubregion;
   vsp->strictLatLonCountry = vfp->strictLatLonCountry;
+  vsp->rubiscoTest = vfp->rubiscoTest;
   vsp->indexerVersion = vfp->indexerVersion;
 
   if (ofp == NULL && vfp->outfp != NULL) {
@@ -826,7 +881,7 @@ static void ProcessSingleRecord (
   BioseqSetPtr   bssp;
   Char           buf [64], path [PATH_MAX];
   Pointer        dataptr = NULL;
-  Uint2          datatype, entityID = 0;
+  Uint2          datatype = 0, entityID = 0;
   FILE           *fp, *ofp = NULL;
   SeqEntryPtr    fsep, sep;
   ObjMgrPtr      omp;
@@ -944,7 +999,7 @@ static void ProcessSingleRecord (
 
       if (vfp->outpath != NULL) {
         ErrSetLogfile (vfp->outpath, ELOG_APPEND);
-      } else if (vfp->verbosity == 0) {
+      } else if (vfp->verbosity == 0 || vfp->verbosity == 1) {
         ErrSetLogfile (path, ELOG_APPEND);
       } else if (vfp->outfp == NULL) {
         ofp = FileOpen (path, "w");
@@ -952,12 +1007,14 @@ static void ProcessSingleRecord (
 
       bsplist = NULL;
     
+      if (! TooManyFarComponents (sep)) {
       if (vfp->inferenceAccnCheck) {
         LookupFarSeqIDs (sep, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
       }
       if (vfp->lock) {
         bsplist = DoLockFarComponents (sep, vfp);
       }
+      }
 
       DoValidation (sep, vfp, ofp);
 
@@ -1164,7 +1221,7 @@ static void ProcessMultipleRecord (
 
   if (vfp->outpath != NULL) {
     ErrSetLogfile (vfp->outpath, ELOG_APPEND);
-  } else if (vfp->verbosity == 0) {
+  } else if (vfp->verbosity == 0 || vfp->verbosity == 1) {
     ErrSetLogfile (path, ELOG_APPEND);
   } else if (vfp->outfp == NULL) {
     ofp = FileOpen (path, "w");
@@ -1222,12 +1279,14 @@ static void ProcessMultipleRecord (
 
           bsplist = NULL;
     
+          if (! TooManyFarComponents (sep)) {
           if (vfp->inferenceAccnCheck) {
             LookupFarSeqIDs (sep, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
           }
           if (vfp->lock) {
             bsplist = DoLockFarComponents (sep, vfp);
           }
+          }
 
           DoValidation (sep, vfp, ofp);
 
@@ -1405,7 +1464,7 @@ static void ValidWrapper (
 
   if (vfp->outpath != NULL) {
     ErrSetLogfile (vfp->outpath, ELOG_APPEND);
-  } else if (vfp->verbosity == 0) {
+  } else if (vfp->verbosity == 0 || vfp->verbosity == 1) {
     ErrSetLogfile (vfp->path, ELOG_APPEND);
   } else if (vfp->outfp == NULL) {
     ofp = FileOpen (vfp->path, "w");
@@ -1413,6 +1472,7 @@ static void ValidWrapper (
 
   bsplist = NULL;
 
+  if (! TooManyFarComponents (sep)) {
   sev = ErrSetMessageLevel (SEV_WARNING);
   if (vfp->inferenceAccnCheck) {
     LookupFarSeqIDs (sep, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE);
@@ -1421,6 +1481,7 @@ static void ValidWrapper (
     bsplist = DoLockFarComponents (sep, vfp);
   }
   ErrSetMessageLevel (sev);
+  }
 
   DoValidation (sep, vfp, ofp);
 
@@ -1450,6 +1511,11 @@ static void ProcessOneRecord (
 )
 
 {
+  Pointer      dataptr;
+  Uint2        datatype;
+  Uint2        entityID;
+  FILE         *fp;
+  SeqEntryPtr  sep;
   ValFlagPtr  vfp;
 
   vfp = (ValFlagPtr) userdata;
@@ -1463,6 +1529,15 @@ static void ProcessOneRecord (
   if (vfp->automatic) {
     StringNCpy_0 (vfp->path, filename, sizeof (vfp->path));
     ReadSequenceAsnFile (filename, vfp->binary, vfp->compressed, (Pointer) vfp, ValidWrapper);
+  } else if (vfp->catenated) {
+    fp = FileOpen (filename, "r");
+    if (fp != NULL) {
+      while ((dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE)) != NULL) {
+        sep = GetTopSeqEntryForEntityID (entityID);
+        ValidWrapper (sep, vfp);
+      }
+      FileClose (fp);
+    }
   } else if (vfp->batch) {
     ProcessMultipleRecord (filename, vfp);
   } else {
@@ -1472,43 +1547,46 @@ static void ProcessOneRecord (
 
 /* Args structure contains command-line arguments */
 
-#define p_argInputPath     0
-#define i_argInputFile     1
-#define o_argOutputFile    2
-#define x_argSuffix        3
-#define u_argRecurse       4
-#define R_argSeverity      5
-#define Q_argLowCutoff     6
-#define P_argHighCutoff    7
-#define E_argOnlyThisErr   8
-#define A_argAlignments    9
-#define J_argIsoJta       10
-#define Z_argRemoteCDS    11
-#define X_argExonSplice   12
-#define G_argInfAccns     13
-#define N_argLatLonStrict 14
-#define M_argMatchTag     15
-#define Y_argCheckOld     16
-#define e_argIgnoreExcept 17
-#define v_argVerbosity    18
-#define a_argType         19
-#define b_argBinary       20
-#define c_argCompressed   21
-#define r_argRemote       22
-#define k_argLocalFetch   23
-#define d_argAsnIdx       24
-#define l_argLockFar      25
-#define T_argThreads      26
-#define L_argLogFile      27
-#define K_argSummmary     28
-#define S_argSkipCount    29
-#define B_argBarcodeVal   30
-#define C_argMaxCount     31
+typedef enum {
+  p_argInputPath = 0,
+  i_argInputFile,
+  o_argOutputFile,
+  f_argFilter,
+  x_argSuffix,
+  u_argRecurse,
+  R_argSeverity,
+  Q_argLowCutoff,
+  P_argHighCutoff,
+  E_argOnlyThisErr,
+  A_argAlignments,
+  J_argIsoJta,
+  Z_argRemoteCDS,
+  X_argExonSplice,
+  G_argInfAccns,
+  N_argLatLonStrict,
+  M_argMatchTag,
+  Y_argCheckOld,
+  e_argIgnoreExcept,
+  v_argVerbosity,
+  a_argType,
+  b_argBinary,
+  c_argCompressed,
+  r_argRemote,
+  k_argLocalFetch,
+  d_argAsnIdx,
+  l_argLockFar,
+  T_argThreads,
+  L_argLogFile,
+  K_argSummmary,
+  S_argSkipCount,
+  B_argBarcodeVal,
+  C_argMaxCount,
 #ifdef INTERNAL_NCBI_ASN2VAL
-#define w_argSeqSubParent 32
-#define H_argAccessHUP    33
-#define y_argAIndexer     34
+  w_argSeqSubParent,
+  H_argAccessHUP,
+  y_argAIndexer,
 #endif
+} Arguments;
 
 #define LAT_LON_STATE    1
 #define LAT_LON_STRICT   2
@@ -1520,11 +1598,13 @@ Args myargs [] = {
     TRUE, 'i', ARG_FILE_IN, 0.0, 0, NULL},
   {"Single Output File", NULL, NULL, NULL,
     TRUE, 'o', ARG_FILE_OUT, 0.0, 0, NULL},
+  {"Substring Filter", NULL, NULL, NULL,
+    TRUE, 'f', ARG_STRING, 0.0, 0, NULL},
   {"File Selection Substring", ".ent", NULL, NULL,
     TRUE, 'x', ARG_STRING, 0.0, 0, NULL},
   {"Recurse", "F", NULL, NULL,
     TRUE, 'u', ARG_BOOLEAN, 0.0, 0, NULL},
-  {"Severity for Error in Return Code", "4", "0", "4",
+  {"Severity for Error in Return Code", "4", "0", "6",
     FALSE, 'R', ARG_INT, 0.0, 0, NULL},
   {"Lowest Severity for Error to Show", "3", "0", "4",
     FALSE, 'Q', ARG_INT, 0.0, 0, NULL},
@@ -1552,7 +1632,7 @@ Args myargs [] = {
     TRUE, 'e', ARG_BOOLEAN, 0.0, 0, NULL},
   {"Verbosity", "1", "0", "4",
     FALSE, 'v', ARG_INT, 0.0, 0, NULL},
-  {"ASN.1 Type (a Automatic, z Any, e Seq-entry, b Bioseq, s Bioseq-set, m Seq-submit, t Batch Bioseq-set, u Batch Seq-submit)", "a", NULL, NULL,
+  {"ASN.1 Type (a Automatic, c Catenated, z Any, e Seq-entry, b Bioseq, s Bioseq-set, m Seq-submit, t Batch Bioseq-set, u Batch Seq-submit)", "a", NULL, NULL,
     TRUE, 'a', ARG_STRING, 0.0, 0, NULL},
   {"Batch File is Binary", "F", NULL, NULL,
     TRUE, 'b', ARG_BOOLEAN, 0.0, 0, NULL},
@@ -1592,12 +1672,13 @@ Int2 Main (void)
 
 {
   Char         app [64];
-  CharPtr      asnidx, directory, infile, logfile, outfile, str, suffix;
-  Boolean      automatic, batch, binary, compressed, dorecurse,
+  CharPtr      asnidx, directory, filter, infile, logfile, outfile, str, suffix;
+  Boolean      automatic, batch, binary, catenated, compressed, dorecurse,
                indexed, local, lock, remote, summary, usethreads;
 #ifdef INTERNAL_NCBI_ASN2VAL
   Boolean      hup = FALSE;
 #endif
+  ValNodePtr   parflat_list, vnp;
   time_t       run_time, start_time, stop_time;
   Int2         type = 0, val;
   ValFlagData  vfd;
@@ -1634,6 +1715,17 @@ Int2 Main (void)
     return 1;
   }
 
+  parflat_list = Validate_ParFlat_GBFeat ();
+  if (parflat_list != NULL) {
+    Message (MSG_POSTERR, "Validate_ParFlat_GBFeat warnings");
+    for (vnp = parflat_list; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      Message (MSG_POSTERR, "%s", str);
+    }
+    ValNodeFreeData (parflat_list);
+  }
+
   /* process command line arguments */
 
   sprintf (app, "asnval %s", ASNVAL_APPLICATION);
@@ -1647,6 +1739,7 @@ Int2 Main (void)
 
   directory = (CharPtr) myargs [p_argInputPath].strvalue;
   suffix = (CharPtr) myargs [x_argSuffix].strvalue;
+  filter = (CharPtr) myargs [f_argFilter].strvalue;
   infile = (CharPtr) myargs [i_argInputFile].strvalue;
   outfile = (CharPtr) myargs [o_argOutputFile].strvalue;
   dorecurse = (Boolean) myargs [u_argRecurse].intvalue;
@@ -1701,6 +1794,7 @@ Int2 Main (void)
 #endif
 
   automatic = FALSE;
+  catenated = FALSE;
   batch = FALSE;
   binary = (Boolean) myargs [b_argBinary].intvalue;
   compressed = (Boolean) myargs [c_argCompressed].intvalue;
@@ -1709,6 +1803,9 @@ Int2 Main (void)
   if (StringICmp (str, "a") == 0) {
     type = 1;
     automatic = TRUE;
+  } else if (StringICmp (str, "c") == 0) {
+    type = 1;
+    catenated = TRUE;
   } else if (StringICmp (str, "z") == 0) {
     type = 1;
   } else if (StringICmp (str, "e") == 0) {
@@ -1749,6 +1846,7 @@ Int2 Main (void)
   /* populate parameter structure */
 
   vfd.automatic = automatic;
+  vfd.catenated = catenated;
   vfd.batch = batch;
   vfd.binary = binary;
   vfd.compressed = compressed;
@@ -1765,7 +1863,7 @@ Int2 Main (void)
   vfd.numrecords = 0;
 
   if (! StringHasNoText (outfile)) {
-    if (vfd.verbosity == 0) {
+    if (vfd.verbosity == 0 || vfd.verbosity == 1) {
       vfd.outpath = outfile;
     } else {
       vfd.outfp = FileOpen (outfile, "w");
@@ -1823,7 +1921,7 @@ Int2 Main (void)
 
   if (StringDoesHaveText (directory)) {
 
-    DirExplore (directory, NULL, suffix, dorecurse, ProcessOneRecord, (Pointer) &vfd);
+    DirExplore (directory, filter, suffix, dorecurse, ProcessOneRecord, (Pointer) &vfd);
 
   } else if (StringDoesHaveText (infile)) {
 
diff --git a/demo/cleanasn.c b/demo/cleanasn.c
index 9cd3d86..73d85b7 100644
--- a/demo/cleanasn.c
+++ b/demo/cleanasn.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/19/99
 *
-* $Revision: 6.37 $
+* $Revision: 6.159 $
 *
 * File Description: 
 *
@@ -53,10 +53,14 @@
 #include <explore.h>
 #include <tofasta.h>
 #include <toasn3.h>
+#include <toporg.h>
 #include <subutil.h>
 #include <asn2gnbk.h>
 #include <pmfapi.h>
 #include <tax3api.h>
+#include <asn2gnbi.h>
+#include <ent2api.h>
+#include <gbftdef.h>
 #ifdef INTERNAL_NCBI_CLEANASN
 #include <accpubseq.h>
 #endif
@@ -64,22 +68,69 @@
 #include <objmacro.h>
 #include <macroapi.h>
 
-#define CLEANASN_APP_VER "2.8"
+#define CLEANASN_APP_VER "6.0"
 
 CharPtr CLEANASN_APPLICATION = CLEANASN_APP_VER;
 
+typedef struct sums {
+  Int4          nucs;
+  Int4          prts;
+  Int4          recs;
+} SumData, PNTR SumDataPtr;
+
+typedef struct dbsums {
+  SumData      genbank;
+  SumData      embl;
+  SumData      ddbj;
+  SumData      refseq;
+  SumData      other;
+} DbSumData, PNTR DbSumPtr;
+
+typedef struct counts {
+  Int4          auth;
+  Int4          bsec;
+  Int4          clnr;
+  Int4          gbbk;
+  Int4          modr;
+  Int4          move;
+  Int4          norm;
+  Int4          nucs;
+  Int4          okay;
+  Int4          othr;
+  Int4          pack;
+  Int4          prts;
+  Int4          publ;
+  Int4          recs;
+  Int4          sloc;
+  Int4          sort;
+  Int4          ssec;
+  Int4          titl;
+} CountData, PNTR CountDataPtr;
+
 typedef struct cleanflags {
   Char          buf [64];
   Int4          gi;
+  Int2          year;
+  Boolean       stripSerial;
+  Boolean       isRefSeq;
+  Boolean       isEmblDdbj;
   Boolean       batch;
   Boolean       binary;
   Boolean       compressed;
   Int2          type;
   CharPtr       results;
   CharPtr       outfile;
+  CharPtr       firstfile;
+  CharPtr       lastfile;
+  Boolean       foundfirst;
+  Boolean       foundlast;
+  CharPtr       sourcedb;
   CharPtr       report;
-  CharPtr       ffdiff;
+  CharPtr       selective;
   ModType       ffmode;
+  CharPtr       ffdiff;
+  CharPtr       asn2flat;
+  CharPtr       asnval;
   CharPtr       clean;
   CharPtr       modernize;
   CharPtr       link;
@@ -88,15 +139,13 @@ typedef struct cleanflags {
   CharPtr       mods;
   ValNodePtr    action_list;
   Boolean       taxon;
-  Boolean       pub;
-  Int4          okay;
-  Int4          bsec;
-  Int4          ssec;
-  Int4          norm;
-  Int4          cumokay;
-  Int4          cumbsec;
-  Int4          cumssec;
-  Int4          cumnorm;
+  CharPtr       pub;
+  Int4          unpubcount;
+  ValNodePtr    unpublist;
+  ValNodePtr    lastunpub;
+  CountData     rawcounts;
+  CountData     cumcounts;
+  DbSumData     dbsums;
   AsnModulePtr  amp;
   AsnTypePtr    atp_bss;
   AsnTypePtr    atp_bsss;
@@ -107,6 +156,377 @@ typedef struct cleanflags {
   FILE          *logfp;
 } CleanFlagData, PNTR CleanFlagPtr;
 
+#ifdef INTERNAL_NCBI_CLEANASN
+static CharPtr smartfetchproc = "SmartBioseqFetch";
+
+static CharPtr smartfetchcmd = NULL;
+
+extern Pointer ReadFromSmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID);
+extern Pointer ReadFromSmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID)
+
+{
+  Char     cmmd [256];
+  Pointer  dataptr;
+  FILE*    fp;
+  Char     path [PATH_MAX];
+
+  if (datatype != NULL) {
+    *datatype = 0;
+  }
+  if (entityID != NULL) {
+    *entityID = 0;
+  }
+  if (StringHasNoText (accn)) return NULL;
+
+  if (smartfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "SMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+      smartfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (smartfetchcmd == NULL) return NULL;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (cmmd, "csh %s %s > %s 2> /dev/null", smartfetchcmd, accn, path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", smartfetchcmd, accn, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+    return NULL;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, datatype, entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+  return dataptr;
+}
+
+static Int2 LIBCALLBACK SmartBioseqFetchFunc (Pointer data)
+
+{
+  BioseqPtr         bsp;
+  Char              cmmd [256];
+  Pointer           dataptr;
+  Uint2             datatype;
+  Uint2             entityID;
+  FILE*             fp;
+  OMProcControlPtr  ompcp;
+  ObjMgrProcPtr     ompp;
+  Char              path [PATH_MAX];
+  SeqEntryPtr       sep = NULL;
+  SeqIdPtr          sip;
+  TextSeqIdPtr      tsip;
+
+  ompcp = (OMProcControlPtr) data;
+  if (ompcp == NULL) return OM_MSG_RET_ERROR;
+  ompp = ompcp->proc;
+  if (ompp == NULL) return OM_MSG_RET_ERROR;
+  sip = (SeqIdPtr) ompcp->input_data;
+  if (sip == NULL) return OM_MSG_RET_ERROR;
+
+  if (sip->choice != SEQID_GENBANK) return OM_MSG_RET_ERROR;
+  tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+  if (tsip == NULL || StringHasNoText (tsip->accession)) return OM_MSG_RET_ERROR;
+
+  if (smartfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "SMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+      smartfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (smartfetchcmd == NULL) return OM_MSG_RET_ERROR;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (cmmd, "csh %s %s > %s 2> /dev/null", smartfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", smartfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+    return OM_MSG_RET_ERROR;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+
+  if (dataptr == NULL) return OM_MSG_RET_OK;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL) return OM_MSG_RET_ERROR;
+  bsp = BioseqFindInSeqEntry (sip, sep);
+  ompcp->output_data = (Pointer) bsp;
+  ompcp->output_entityID = ObjMgrGetEntityIDForChoice (sep);
+  return OM_MSG_RET_DONE;
+}
+
+static Boolean SmartFetchEnable (void)
+
+{
+  ObjMgrProcLoad (OMPROC_FETCH, smartfetchproc, smartfetchproc,
+                  OBJ_SEQID, 0, OBJ_BIOSEQ, 0, NULL,
+                  SmartBioseqFetchFunc, PROC_PRIORITY_DEFAULT);
+  return TRUE;
+}
+
+static CharPtr tpasmartfetchproc = "TPASmartBioseqFetch";
+
+static CharPtr tpasmartfetchcmd = NULL;
+
+extern Pointer ReadFromTPASmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID);
+extern Pointer ReadFromTPASmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID)
+
+{
+  Char     cmmd [256];
+  Pointer  dataptr;
+  FILE*    fp;
+  Char     path [PATH_MAX];
+
+  if (datatype != NULL) {
+    *datatype = 0;
+  }
+  if (entityID != NULL) {
+    *entityID = 0;
+  }
+  if (StringHasNoText (accn)) return NULL;
+
+  if (tpasmartfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "TPASMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+      tpasmartfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (tpasmartfetchcmd == NULL) return NULL;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (cmmd, "csh %s %s > %s 2> /dev/null", tpasmartfetchcmd, accn, path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", tpasmartfetchcmd, accn, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+    return NULL;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, datatype, entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+  return dataptr;
+}
+
+static Int2 LIBCALLBACK TPASmartBioseqFetchFunc (Pointer data)
+
+{
+  BioseqPtr         bsp;
+  Char              cmmd [256];
+  Pointer           dataptr;
+  Uint2             datatype;
+  Uint2             entityID;
+  FILE*             fp;
+  OMProcControlPtr  ompcp;
+  ObjMgrProcPtr     ompp;
+  Char              path [PATH_MAX];
+  SeqEntryPtr       sep = NULL;
+  SeqIdPtr          sip;
+  TextSeqIdPtr      tsip;
+
+  ompcp = (OMProcControlPtr) data;
+  if (ompcp == NULL) return OM_MSG_RET_ERROR;
+  ompp = ompcp->proc;
+  if (ompp == NULL) return OM_MSG_RET_ERROR;
+  sip = (SeqIdPtr) ompcp->input_data;
+  if (sip == NULL) return OM_MSG_RET_ERROR;
+
+  if (sip->choice != SEQID_TPG) return OM_MSG_RET_ERROR;
+  tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+  if (tsip == NULL || StringHasNoText (tsip->accession)) return OM_MSG_RET_ERROR;
+
+  if (tpasmartfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "TPASMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+      tpasmartfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (tpasmartfetchcmd == NULL) return OM_MSG_RET_ERROR;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (cmmd, "csh %s %s > %s 2> /dev/null", tpasmartfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", tpasmartfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+    return OM_MSG_RET_ERROR;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+
+  if (dataptr == NULL) return OM_MSG_RET_OK;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL) return OM_MSG_RET_ERROR;
+  bsp = BioseqFindInSeqEntry (sip, sep);
+  ompcp->output_data = (Pointer) bsp;
+  ompcp->output_entityID = ObjMgrGetEntityIDForChoice (sep);
+  return OM_MSG_RET_DONE;
+}
+
+static Boolean TPASmartFetchEnable (void)
+
+{
+  ObjMgrProcLoad (OMPROC_FETCH, tpasmartfetchproc, tpasmartfetchproc,
+                  OBJ_SEQID, 0, OBJ_BIOSEQ, 0, NULL,
+                  TPASmartBioseqFetchFunc, PROC_PRIORITY_DEFAULT);
+  return TRUE;
+}
+
+static CharPtr hupfetchproc = "HUPBioseqFetch";
+
+static CharPtr hupfetchcmd = NULL;
+
+extern Pointer ReadFromHUP (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID);
+extern Pointer ReadFromHUP (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID)
+
+{
+  Char     cmmd [256];
+  Pointer  dataptr;
+  FILE*    fp;
+  Char     path [PATH_MAX];
+
+  if (datatype != NULL) {
+    *datatype = 0;
+  }
+  if (entityID != NULL) {
+    *entityID = 0;
+  }
+  if (StringHasNoText (accn)) return NULL;
+
+  if (hupfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "HUP", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+      hupfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (hupfetchcmd == NULL) return NULL;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (cmmd, "csh %s %s > %s 2> /dev/null", hupfetchcmd, accn, path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", hupfetchcmd, accn, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+    return NULL;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, datatype, entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+  return dataptr;
+}
+
+static Int2 LIBCALLBACK HUPBioseqFetchFunc (Pointer data)
+
+{
+  BioseqPtr         bsp;
+  Char              cmmd [256];
+  Pointer           dataptr;
+  Uint2             datatype;
+  Uint2             entityID;
+  FILE*             fp;
+  OMProcControlPtr  ompcp;
+  ObjMgrProcPtr     ompp;
+  Char              path [PATH_MAX];
+  SeqEntryPtr       sep = NULL;
+  SeqIdPtr          sip;
+  TextSeqIdPtr      tsip;
+
+  ompcp = (OMProcControlPtr) data;
+  if (ompcp == NULL) return OM_MSG_RET_ERROR;
+  ompp = ompcp->proc;
+  if (ompp == NULL) return OM_MSG_RET_ERROR;
+  sip = (SeqIdPtr) ompcp->input_data;
+  if (sip == NULL) return OM_MSG_RET_ERROR;
+
+  if (sip->choice != SEQID_GENBANK) return OM_MSG_RET_ERROR;
+  tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+  if (tsip == NULL || StringHasNoText (tsip->accession)) return OM_MSG_RET_ERROR;
+
+  if (hupfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "HUP", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+      hupfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (hupfetchcmd == NULL) return OM_MSG_RET_ERROR;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (cmmd, "csh %s %s > %s 2> /dev/null", hupfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", hupfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+    return OM_MSG_RET_ERROR;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+
+  if (dataptr == NULL) return OM_MSG_RET_OK;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL) return OM_MSG_RET_ERROR;
+  bsp = BioseqFindInSeqEntry (sip, sep);
+  ompcp->output_data = (Pointer) bsp;
+  ompcp->output_entityID = ObjMgrGetEntityIDForChoice (sep);
+  return OM_MSG_RET_DONE;
+}
+
+static Boolean HUPFetchEnable (void)
+
+{
+  ObjMgrProcLoad (OMPROC_FETCH, hupfetchproc, hupfetchproc,
+                  OBJ_SEQID, 0, OBJ_BIOSEQ, 0, NULL,
+                  HUPBioseqFetchFunc, PROC_PRIORITY_DEFAULT);
+  return TRUE;
+}
+#endif
+
 static void RemoveFeatUser (
   SeqFeatPtr sfp,
   Pointer userdata
@@ -148,7 +568,6 @@ static Boolean LIBCALLBACK CADummySMFEProc (
   SeqMgrFeatContextPtr context
 )
 
-
 {
   DummySmfePtr  dsp;
   Int4          len;
@@ -241,50 +660,6 @@ static void MarkTitles (
   ovn->idx.deleteme = TRUE;
 }
 
-static void AddSpTaxnameToList (
-  SeqDescrPtr sdp,
-  Pointer userdata
-)
-{
-  BioSourcePtr biop;
-
-  if (sdp == NULL || sdp->choice != Seq_descr_source || userdata == NULL) return;
-
-  biop = (BioSourcePtr) sdp->data.ptrvalue;
-  if (biop == NULL || biop->org == NULL || !IsSpName (biop->org->taxname)) return;
-
-  ValNodeAddPointer ((ValNodePtr PNTR) userdata, 0, biop->org->taxname);
-}
-
-
-static Boolean ShouldExcludeSp (
-  SeqEntryPtr sep
-)
-
-{
-  ValNodePtr name_list = NULL, vnp1, vnp2;
-  Boolean    all_diff = TRUE;
-
-  if (sep == NULL) return TRUE;
-  VisitDescriptorsInSep (sep, &name_list, AddSpTaxnameToList);
-
-  name_list = ValNodeSort (name_list, SortVnpByString);
-
-  if (name_list != NULL && name_list->next != NULL) {
-    for (vnp1 = name_list; vnp1 != NULL && vnp1->next != NULL && all_diff; vnp1 = vnp1->next) {
-      for (vnp2 = vnp1->next; vnp2 != NULL && all_diff; vnp2 = vnp2->next) {
-        if (StringCmp (vnp1->data.ptrvalue, vnp2->data.ptrvalue) == 0) {
-          all_diff = FALSE;
-        }
-      }
-    }
-  }
-
-  name_list = ValNodeFree (name_list);
-
-  return all_diff;
-}
-
 static void DoAutoDef (
   SeqEntryPtr sep,
   Uint2 entityID
@@ -310,18 +685,7 @@ static void DoAutoDef (
   SetRequiredModifiers (modList);
   CountModifiers (modList, sep);
 
-  odmp.use_labels = TRUE;
-  odmp.max_mods = -99;
-  odmp.keep_paren = TRUE;
-  odmp.exclude_sp = ShouldExcludeSp (sep);
-  odmp.exclude_cf = FALSE;
-  odmp.exclude_aff = FALSE;
-  odmp.exclude_nr = FALSE;
-  odmp.include_country_extra = FALSE;
-  odmp.clone_isolate_HIV_rule_num = clone_isolate_HIV_rule_want_both;
-  odmp.use_modifiers = FALSE;
-  odmp.allow_semicolon_in_modifier = FALSE;
-
+  InitOrganismDescriptionModifiers (&odmp, sep);
 
   RemoveNucProtSetTitles (sep);  
   oldscope = SeqEntrySetScope (sep);
@@ -348,6 +712,10 @@ static void DoAutoDef (
 
   ClearProteinTitlesInNucProts (entityID, NULL);
   InstantiateProteinTitles (entityID, NULL);
+  /*
+  RemovePopsetTitles (sep);
+  */
+  AddPopsetTitles (sep, &feature_requests, DEFAULT_ORGANELLE_CLAUSE, FALSE, FALSE);
 
   SeqEntrySetScope (oldscope);
 }
@@ -396,24 +764,322 @@ static void LookupPubdesc (
   PubmedEntryFree (pep);
 }
 
-static void ModGenes (SeqFeatPtr sfp, Pointer userdata)
+static AuthListPtr AppendConsortiumToAuthList (
+  AuthListPtr alp,
+  CharPtr consortium
+)
+
+{
+  AuthorPtr    ap;
+  ValNodePtr   names;
+  PersonIdPtr  pid;
+
+  if (StringHasNoText (consortium)) return alp;
+  if (alp == NULL) {
+    alp = AuthListNew ();
+    alp->choice = 1;
+  }
+  pid = PersonIdNew ();
+  if (pid == NULL) return NULL;
+  pid->choice = 5;
+  pid->data = StringSave (consortium);
+  ap = AuthorNew ();
+  if (ap == NULL) return NULL;
+  ap->name = pid;
+  names = ValNodeAdd (&(alp->names));
+  names->choice = 1;
+  names->data.ptrvalue = ap;
+  return alp;
+}
+
+static void ReplaceUnpub (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  CharPtr          authors = NULL, consortium = NULL;
+  CitArtPtr        cap;
+  CitGenPtr        cgp = NULL;
+  Int2             count = 0;
+  Boolean          hasUnpublished = FALSE;
+  MedlineEntryPtr  mep;
+  PubmedEntryPtr   pep;
+  Int4             pmid;
+  Int4Ptr          pmP;
+  ValNodePtr       vnp = NULL;
+
+  if (pdp == NULL || userdata == NULL) return;
+  pmP = (Int4Ptr) userdata;
+  pmid = *pmP;
+  if (pmid == 0) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    count++;
+    if (vnp->choice == PUB_Gen) {
+      cgp = (CitGenPtr) vnp->data.ptrvalue;
+      if (cgp != NULL) {
+        if (StringICmp (cgp->cit, "Unpublished") == 0) {
+          if (StringICmp (cgp->title, "Direct Submission") != 0) {
+            hasUnpublished = TRUE;
+          }
+        }
+      }
+    } else if (vnp->choice == PUB_Muid || vnp->choice == PUB_PMid) {
+      return;
+    } else if (vnp->choice == PUB_Article || vnp->choice == PUB_Book || vnp->choice == PUB_Man) {
+      return;
+    }
+  }
+
+  if (! hasUnpublished) return;
+
+  /* assume only a cit-gen for now */
+  if (count != 1 || cgp == NULL) return;
+
+  authors = GetAuthorsString (GENBANK_FMT, cgp->authors, &consortium, NULL, NULL);
+  MemFree (authors);
+
+  pep = GetPubMedForUid (pmid);
+  if (pep == NULL) return;
+  mep = (MedlineEntryPtr) pep->medent;
+  if (mep != NULL && mep->cit != NULL) {
+    /* remove cit-gen */
+    CitGenFree (cgp);
+    ValNodeFree (pdp->pub);
+    pdp->pub = NULL;
+
+    ValNodeAddInt (&(pdp->pub), PUB_PMid, pmid);
+    cap = AsnIoMemCopy ((Pointer) mep->cit,
+                        (AsnReadFunc) CitArtAsnRead,
+                        (AsnWriteFunc) CitArtAsnWrite);
+    ValNodeAddPointer (&(pdp->pub), PUB_Article, (Pointer) cap);
+    if (consortium != NULL) {
+      AppendConsortiumToAuthList (cap->authors, consortium);
+    }
+  }
+
+  MemFree (consortium);
+
+  PubmedEntryFree (pep);
+}
+
+static void CleanupLocation (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  BioseqPtr  bsp;
+  SeqIntPtr  sintp;
+  SeqLocPtr  slp;
+
+  if (sfp == NULL || sfp->location == NULL) return;
+
+  CleanUpSeqLoc (sfp->location);
+
+  if (sfp->data.choice == SEQFEAT_REGION ||
+      sfp->data.choice == SEQFEAT_SITE ||
+      sfp->data.choice == SEQFEAT_BOND ||
+      sfp->data.choice == SEQFEAT_PROT) {
+    bsp = BioseqFind (SeqLocId (sfp->location));
+    if (bsp != NULL && ISA_aa (bsp->mol)) {
+      slp = SeqLocFindNext (sfp->location, NULL);
+      while (slp != NULL) {
+        if (slp->choice == SEQLOC_INT) {
+          sintp = (SeqIntPtr) slp->data.ptrvalue;
+          if (sintp != NULL) {
+            if (sintp->strand != Seq_strand_unknown) {
+              sintp->strand = Seq_strand_unknown;
+            }
+          }
+        }
+        slp = SeqLocFindNext (sfp->location, slp);
+      }
+    }
+  }
+}
+
+static void CleanupMostRNAs (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  RnaRefPtr  rrp;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return;
+  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
+  if (rrp == NULL || rrp->type == 255) return;
+
+  CleanUpSeqFeat (sfp, FALSE, FALSE, TRUE, FALSE, NULL);
+}
+
+static void CleanupRemainingRNAs (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return;
+
+  CleanUpSeqFeat (sfp, FALSE, FALSE, TRUE, FALSE, NULL);
+}
+
+static void CleanupPubAuthors (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  if (pdp == NULL) return;
+
+  CleanUpPubdescAuthors (pdp);
+}
+
+static void CleanupPubBody (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  CleanFlagPtr  cfp;
+
+  if (pdp == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp == NULL) return;
+
+  CleanUpPubdescBody (pdp, cfp->stripSerial);
+}
+
+static void ModGenes (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
 
 {
   ModernizeGeneFields (sfp);
 }
 
-static void ModRNAs (SeqFeatPtr sfp, Pointer userdata)
+static void ModRNAs (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
 
 {
   ModernizeRNAFields (sfp);
 }
 
-static void ModPCRs (BioSourcePtr biop, Pointer userdata)
+static void ModPCRs (
+  BioSourcePtr biop,
+  Pointer userdata
+)
 
 {
   ModernizePCRPrimers (biop);
 }
 
+static void FixBspMol (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  SeqDescrPtr  desc;
+  MolInfoPtr   mip;
+
+  if (bsp == NULL) return;
+
+  desc = GetNextDescriptorUnindexed (bsp, Seq_descr_molinfo, NULL);
+  if (desc == NULL || desc->choice != Seq_descr_molinfo) return;
+  mip = (MolInfoPtr) desc->data.ptrvalue;
+  if (mip == NULL) return;
+  if (bsp->mol == 0) {
+    switch (mip->biomol) {
+      case MOLECULE_TYPE_GENOMIC :
+        bsp->mol = Seq_mol_na;
+        break;
+      case MOLECULE_TYPE_PRE_MRNA :
+      case MOLECULE_TYPE_MRNA :
+      case MOLECULE_TYPE_RRNA :
+      case MOLECULE_TYPE_TRNA :
+      case MOLECULE_TYPE_SNRNA :
+      case MOLECULE_TYPE_SCRNA :
+      case MOLECULE_TYPE_CRNA :
+      case MOLECULE_TYPE_SNORNA :
+      case MOLECULE_TYPE_TRANSCRIBED_RNA :
+      case MOLECULE_TYPE_NCRNA :
+      case MOLECULE_TYPE_TMRNA :
+        bsp->mol = Seq_mol_rna;
+        break;
+      case MOLECULE_TYPE_PEPTIDE :
+        bsp->mol = Seq_mol_aa;
+        break;
+      case MOLECULE_TYPE_OTHER_GENETIC_MATERIAL :
+        bsp->mol = Seq_mol_other;
+        break;
+      case MOLECULE_TYPE_GENOMIC_MRNA_MIX :
+        bsp->mol = Seq_mol_na;
+        break;
+      default :
+        break;
+    }
+  } else if (bsp->mol != Seq_mol_rna
+             && (mip->biomol == MOLECULE_TYPE_CRNA || mip->biomol == MOLECULE_TYPE_MRNA)) {
+    bsp->mol = Seq_mol_rna;
+  }
+}
+
+static ByteStorePtr Se2Bs (
+  SeqEntryPtr sep
+)
+
+{
+  AsnIoBSPtr    aibp;
+  ByteStorePtr  bs;
+
+  if (sep == NULL) return NULL;
+
+  bs = BSNew (1000);
+  if (bs == NULL) return NULL;
+  aibp = AsnIoBSOpen ("wb", bs);
+  if (aibp == NULL || aibp->aip == NULL) return NULL;
+
+  SeqEntryAsnWrite (sep, aibp->aip, NULL);
+
+  AsnIoFlush (aibp->aip);
+  AsnIoBSClose (aibp);
+
+  return bs;
+}
+
+static ByteStorePtr Se2BsX (
+  SeqEntryPtr sep
+)
+
+{
+  AsnIoBSPtr    aibp;
+  ByteStorePtr  bs;
+
+  if (sep == NULL) return NULL;
+
+  bs = BSNew (1000);
+  if (bs == NULL) return NULL;
+  aibp = AsnIoBSOpen ("wb", bs);
+  if (aibp == NULL || aibp->aip == NULL) return NULL;
+
+  aibp->aip->asn_no_newline = TRUE;
+  aibp->aip->asn_alt_struct = TRUE;
+
+  SeqEntryAsnWrite (sep, aibp->aip, NULL);
+
+  AsnIoFlush (aibp->aip);
+  AsnIoBSClose (aibp);
+
+  return bs;
+}
+
+/*
 static CharPtr Se2Str (
   SeqEntryPtr sep
 )
@@ -440,14 +1106,33 @@ static CharPtr Se2Str (
 
   return str;
 }
+*/
 
 typedef struct chgdata {
+  Boolean       isRefSeq;
+  Boolean       sgml;
+  Boolean       cdscodon;
   Boolean       rubisco;
   Boolean       rbc;
   Boolean       its;
   Boolean       rnaother;
   Boolean       trnanote;
   Boolean       oldbiomol;
+  Boolean       oldgbqual;
+  Boolean       badDbxref;
+  Boolean       refDbxref;
+  Boolean       srcDbxref;
+  Boolean       capDbxref;
+  Boolean       oldDbxref;
+  Boolean       privDbxref;
+  Boolean       multDbxref;
+  Boolean       rareDbxref;
+  Boolean       badOrg;
+  Boolean       rpt_unit_seq;
+  Boolean       hasUnpublished;
+  Boolean       hasPublished;
+  Boolean       protNucSet;
+  Boolean       noPopsetTitle;
   Int4          protdesc;
   Int4          sfpnote;
   Int4          gbsource;
@@ -491,19 +1176,165 @@ static Boolean IsITS (
           StringICmp (name, "internal transcribed spacer 3 (ITS3)") == 0);
 }
 
+static Boolean HasSgml (
+  CharPtr str
+)
+
+{
+  Int2  ascii_len;
+  Char  buf [1024];
+
+  if (StringHasNoText (str)) return FALSE;
+
+  ascii_len = Sgml2AsciiLen (str);
+  if (ascii_len + 2 > sizeof (buf)) return FALSE;
+
+  Sgml2Ascii (str, buf, ascii_len + 1);
+  if (StringCmp (str, buf) != 0) {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static void LookForBadDbxref (
+  ValNodePtr list,
+  ChangeDataPtr cdp,
+  Boolean isSource
+)
+
+{
+  Boolean      cap;
+  DbtagPtr     dp;
+  CharPtr      good;
+  ObjectIdPtr  oip;
+  Boolean      ref;
+  Boolean      src;
+  CharPtr      str;
+  ValNodePtr   vnp;
+
+  if (list == NULL || cdp == NULL) return;
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    dp = (DbtagPtr) vnp->data.ptrvalue;
+    if (dp != NULL && StringDoesHaveText (dp->db)) {
+
+      oip = dp->tag;
+      if (oip != NULL && StringDoesHaveText (oip->str)) {
+        if (StringChr (oip->str, ':') != NULL) {
+          cdp->multDbxref = TRUE;
+        }
+      }
+
+      str = dp->db;
+      if (StringICmp (str, "PID") == 0 ||
+          StringICmp (str, "PIDg") == 0 ||
+          StringICmp (str, "PIDd") == 0 ||
+          StringICmp (str, "PIDe") == 0 ||
+          StringICmp (str, "NID") == 0 ||
+          StringICmp (str, "GI") == 0) {
+        cdp->privDbxref = TRUE;
+        continue;
+      }
+      if (StringICmp (str, "SWISS-PROT") == 0 ||
+          StringICmp (str, "SWISSPROT") == 0 ||
+          StringICmp (str, "SPTREMBL") == 0 ||
+          StringICmp (str, "SUBTILIS") == 0 ||
+          StringICmp (str, "MGD") == 0 ||
+          StringCmp (str, "cdd") == 0 ||
+          StringICmp (str, "TrEMBL") == 0 ||
+          StringICmp (str, "LocusID") == 0 ||
+          StringICmp (str, "MaizeDB") == 0 ||
+          StringICmp (str, "UniProt/Swiss-Prot") == 0 ||
+          StringICmp (str, "UniProt/TrEMBL") == 0 ||
+          StringICmp (str, "Genew") == 0 ||
+          StringICmp (str, "GENEDB") == 0 ||
+          StringICmp (str, "GreengenesID") == 0 ||
+          StringICmp (str, "HMPID") == 0 ||
+          StringICmp (str, "IFO") == 0 ||
+          StringICmp (str, "BHB") == 0 ||
+          StringICmp (str, "BioHealthBase") == 0) {
+        cdp->oldDbxref = TRUE;
+        continue;
+      }
+      if (StringICmp (str, "ATCC(dna)") == 0 ||
+          StringICmp (str, "ATCC(in host)") == 0 ||
+          StringICmp (str, "BDGP_EST") == 0 ||
+          StringICmp (str, "BDGP_INS") == 0 ||
+          StringICmp (str, "CGNC") == 0 ||
+          StringICmp (str, "CloneID") == 0 ||
+          StringICmp (str, "ENSEMBL") == 0 ||
+          StringICmp (str, "ESTLIB") == 0 ||
+          StringICmp (str, "GDB") == 0 ||
+          /*
+          StringICmp (str, "GOA") == 0 ||
+          */
+          StringICmp (str, "IMGT/HLA") == 0 ||
+          StringICmp (str, "PIR") == 0 ||
+          StringICmp (str, "PSEUDO") == 0 ||
+          StringICmp (str, "RZPD") == 0 ||
+          StringICmp (str, "SoyBase") == 0 ||
+          StringICmp (str, "UNILIB") == 0) {
+        cdp->rareDbxref = TRUE;
+        continue;
+      }
+      if (StringICmp (str, "MGD") == 0 || StringICmp (str, "MGI") == 0) {
+        oip = dp->tag;
+        if (oip != NULL && StringDoesHaveText (oip->str)) {
+          str = oip->str;
+          if (StringNICmp (str, "MGI:", 4) == 0 || StringNICmp (str, "MGD:", 4) == 0) {
+            cdp->oldDbxref = TRUE;
+            continue;
+          }
+        }
+      } else if (StringICmp (str, "HPRD") == 0) {
+        oip = dp->tag;
+        if (oip != NULL && StringDoesHaveText (oip->str)) {
+          str = oip->str;
+          if (StringNICmp (str, "HPRD_", 5) == 0) {
+            cdp->oldDbxref = TRUE;
+            continue;
+          }
+        }
+      }
+
+      if (isSource && StringCmp (str, "taxon") == 0) continue;
+
+      if (DbxrefIsValid (str, &ref, &src, &cap, &good)) {
+        if (ref && (! cdp->isRefSeq)) {
+          cdp->refDbxref = TRUE;
+        }
+        if (isSource && (! src)) {
+          cdp->srcDbxref = TRUE;
+        }
+        if (cap) {
+          cdp->capDbxref = TRUE;
+        }
+      } else {
+        cdp->badDbxref = TRUE;
+      }
+    }
+  }
+}
+
 static void ScoreFeature (
   SeqFeatPtr sfp,
   Pointer userdata
 )
 
 {
+  BioSourcePtr   biop;
   ChangeDataPtr  cdp;
+  Char           ch;
   CharPtr        comment;
   CdRegionPtr    crp;
   CharPtr        desc;
   GBQualPtr      gbq;
+  GeneRefPtr     grp;
   CharPtr        name;
+  OrgRefPtr      orp;
   ProtRefPtr     prp;
+  CharPtr        ptr;
   Uint1          residue;
   RnaRefPtr      rrp;
   CharPtr        str;
@@ -518,6 +1349,38 @@ static void ScoreFeature (
     (cdp->sfpnote)++;
   }
 
+  for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+    if (StringCmp (gbq->qual, "partial") == 0 ||
+        StringCmp (gbq->qual, "evidence") == 0 ||
+        StringCmp (gbq->qual, "exception") == 0 ||
+        StringCmp (gbq->qual, "note") == 0 ||
+        StringCmp (gbq->qual, "notes") == 0 ||
+        StringCmp (gbq->qual, "comment") == 0 ||
+        StringCmp (gbq->qual, "db_xref") == 0 ||
+        StringCmp (gbq->qual, "gdb_xref") == 0 ||
+        StringCmp (gbq->qual, "rpt_unit") == 0 ||
+        StringCmp (gbq->qual, "pseudo") == 0 ||
+        StringCmp (gbq->qual, "gene") == 0 ||
+        StringCmp (gbq->qual, "codon_start") == 0 ||
+        StringCmp (gbq->qual, "transposon") == 0 ||
+        StringCmp (gbq->qual, "insertion_seq") == 0) {
+      cdp->oldgbqual = TRUE;
+    } else if (StringICmp (gbq->qual, "rpt_unit_seq") == 0) {
+      if (StringHasNoText (gbq->val)) continue;
+      ptr = gbq->val;
+      ch = *ptr;
+      while (ch != '\0') {
+        if (IS_UPPER (ch)) {
+          cdp->rpt_unit_seq = TRUE;
+        }
+        ptr++;
+        ch = *ptr;
+      }
+    }
+  }
+
+  LookForBadDbxref (sfp->dbxref, cdp, FALSE);
+
   /* skip feature types that do not use data.value.ptrvalue */
   switch (sfp->data.choice) {
     case SEQFEAT_COMMENT:
@@ -532,11 +1395,49 @@ static void ScoreFeature (
   if (sfp->data.value.ptrvalue == NULL) return;
 
   switch (sfp->data.choice) {
+    case SEQFEAT_GENE:
+      grp = (GeneRefPtr) sfp->data.value.ptrvalue;
+      if (HasSgml (grp->locus)) {
+        cdp->sgml = TRUE;
+      }
+      if (HasSgml (grp->desc)) {
+        cdp->sgml = TRUE;
+      }
+      for (vnp = grp->syn; vnp != NULL; vnp = vnp->next) {
+        str = (CharPtr) vnp->data.ptrvalue;
+        if (StringHasNoText (str)) continue;
+        if (HasSgml (str)) {
+          cdp->sgml = TRUE;
+        }
+      }
+      for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+        if (StringCmp (gbq->qual, "map") == 0 ||
+            StringCmp (gbq->qual, "allele") == 0 ||
+            StringCmp (gbq->qual, "locus_tag") == 0 ||
+            StringCmp (gbq->qual, "old_locus_tag") == 0) {
+          cdp->oldgbqual = TRUE;
+        }
+      }
+      LookForBadDbxref (grp->db, cdp, FALSE);
+      break;
     case SEQFEAT_CDREGION:
       crp = (CdRegionPtr) sfp->data.value.ptrvalue;
       if (crp->conflict) {
         (cdp->cdsconf)++;
       }
+      for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+        if (StringCmp (gbq->qual, "codon") != 0) continue;
+        if (StringHasNoText (gbq->val)) continue;
+        cdp->cdscodon = TRUE;
+      }
+      for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+        if (StringCmp (gbq->qual, "product") == 0 ||
+            StringCmp (gbq->qual, "function") == 0 ||
+            StringCmp (gbq->qual, "EC_number") == 0 ||
+            StringCmp (gbq->qual, "prot_note") == 0) {
+          cdp->oldgbqual = TRUE;
+        }
+      }
       break;
     case SEQFEAT_PROT:
       prp = (ProtRefPtr) sfp->data.value.ptrvalue;
@@ -554,6 +1455,19 @@ static void ScoreFeature (
           cdp->rbc = TRUE;
         }
       }
+      for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+        if (StringCmp (gbq->qual, "product") == 0 ||
+            StringCmp (gbq->qual, "function") == 0 ||
+            StringCmp (gbq->qual, "EC_number") == 0 ||
+            StringCmp (gbq->qual, "label") == 0 ||
+            StringCmp (gbq->qual, "allele") == 0) {
+          cdp->oldgbqual = TRUE;
+        }
+        if (StringCmp (gbq->qual, "standard_name") == 0 && prp->name == NULL) {
+          cdp->oldgbqual = TRUE;
+        }
+      }
+      LookForBadDbxref (prp->db, cdp, FALSE);
       break;
     case SEQFEAT_RNA :
       rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
@@ -590,7 +1504,25 @@ static void ScoreFeature (
           }
         }
       }
+      for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+        if (StringCmp (gbq->qual, "product") == 0 ||
+            StringCmp (gbq->qual, "ncRNA_class") == 0 ||
+            StringCmp (gbq->qual, "tag_peptide") == 0) {
+          cdp->oldgbqual = TRUE;
+        }
+      }
       break;
+    case SEQFEAT_ORG :
+      orp = (OrgRefPtr) sfp->data.value.ptrvalue;
+      LookForBadDbxref (orp->db, cdp, TRUE);
+      cdp->badOrg = TRUE;
+      break;
+    case SEQFEAT_BIOSRC :
+      biop = (BioSourcePtr) sfp->data.value.ptrvalue;
+      orp = biop->org;
+      if (orp != NULL) {
+        LookForBadDbxref (orp->db, cdp, TRUE);
+      }
     default:
       break;
   }
@@ -602,9 +1534,11 @@ static void ScoreDescriptor (
 )
 
 {
+  BioSourcePtr   biop;
   ChangeDataPtr  cdp;
   GBBlockPtr     gbp;
   MolInfoPtr     mip;
+  OrgRefPtr      orp;
 
   if (sdp == NULL) return;
   cdp = (ChangeDataPtr) userdata;
@@ -633,11 +1567,95 @@ static void ScoreDescriptor (
         }
       }
       break;
+    case Seq_descr_org :
+      orp = (OrgRefPtr) sdp->data.ptrvalue;
+      if (orp != NULL) {
+        LookForBadDbxref (orp->db, cdp, TRUE);
+      }
+      cdp->badOrg = TRUE;
+      break;
+    case Seq_descr_source :
+      biop = (BioSourcePtr) sdp->data.ptrvalue;
+      if (biop != NULL) {
+        orp = biop->org;
+        if (orp != NULL) {
+          LookForBadDbxref (orp->db, cdp, TRUE);
+        }
+      }
+      break;
     default :
       break;
   }
 }
 
+static void CheckForUnpubPub (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  ChangeDataPtr  cdp;
+  CitGenPtr      cgp;
+  ValNodePtr     vnp;
+
+  if (pdp == NULL) return;
+  cdp = (ChangeDataPtr) userdata;
+  if (cdp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Gen) {
+      cgp = (CitGenPtr) vnp->data.ptrvalue;
+      if (cgp != NULL) {
+        if (StringICmp (cgp->cit, "Unpublished") == 0) {
+          if (StringICmp (cgp->title, "Direct Submission") != 0) {
+            cdp->hasUnpublished = TRUE;
+          }
+        }
+      }
+    } else if (vnp->choice == PUB_Muid || vnp->choice == PUB_PMid) {
+      cdp->hasPublished = TRUE;
+    } else if (vnp->choice == PUB_Article || vnp->choice == PUB_Book || vnp->choice == PUB_Man) {
+      cdp->hasPublished = TRUE;
+    }
+  }
+}
+
+static void CheckForSetTitle (
+  BioseqSetPtr bssp,
+  Pointer userdata
+)
+
+{
+  BioseqPtr      bsp;
+  ChangeDataPtr  cdp;
+  SeqDescrPtr    sdp;
+  SeqEntryPtr    sep;
+  CharPtr        title;
+
+  if (bssp == NULL) return;
+  cdp = (ChangeDataPtr) userdata;
+  if (cdp == NULL) return;
+
+  if (bssp->_class == BioseqseqSet_class_nuc_prot) {
+    sep = bssp->seq_set;
+    if (sep != NULL && IS_Bioseq (sep)) {
+      bsp = (BioseqPtr) sep->data.ptrvalue;
+      if (bsp != NULL) {
+        if (ISA_aa (bsp->mol)) {
+          cdp->protNucSet = TRUE;
+        }
+      }
+    }
+  } else if (bssp->_class >= BioseqseqSet_class_mut_set && bssp->_class <= BioseqseqSet_class_eco_set) {
+    for (sdp = bssp->descr; sdp != NULL; sdp = sdp->next) {
+      if (sdp->choice != Seq_descr_title) continue;
+      title = (CharPtr) sdp->data.ptrvalue;
+      if (StringDoesHaveText (title)) continue;
+      cdp->noPopsetTitle = TRUE;
+    }
+  }
+}
+
 static void CheckForChanges (
   SeqEntryPtr sep,
   ChangeDataPtr cdp
@@ -648,75 +1666,1397 @@ static void CheckForChanges (
 
   VisitFeaturesInSep (sep, (Pointer) cdp, ScoreFeature);
   VisitDescriptorsInSep (sep, (Pointer) cdp, ScoreDescriptor);
+  VisitPubdescsInSep (sep, (Pointer) cdp, CheckForUnpubPub);
+  VisitSetsInSep (sep, (Pointer) cdp, CheckForSetTitle);
 }
 
-static void DoASNReport (
+static void StripBadProtTitles (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  CharPtr            buf;
+  size_t             buflen = 1001;
+  ObjValNodePtr      ovp;
+  SeqIdPtr           sip;
+  CharPtr            title;
+  ValNodePtr         vnp;
+
+  if (bsp == NULL) return;
+  if (! ISA_aa (bsp->mol)) return;
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_OTHER) return;
+  }
+
+  vnp = BioseqGetSeqDescr (bsp, Seq_descr_title, NULL);
+  if (vnp == NULL) return;
+  title = (CharPtr) vnp->data.ptrvalue;
+  if (StringHasNoText (title)) return;
+
+  buf = MemNew (sizeof (Char) * (buflen + 1));
+  if (buf == NULL) return;
+
+  if (NewCreateDefLineBuf (NULL, bsp, buf, buflen, TRUE, FALSE)) {
+    if (StringICmp (buf, title) != 0) {
+      if (vnp->extended != 0) {
+        ovp = (ObjValNodePtr) vnp;
+        ovp->idx.deleteme = TRUE;
+      }
+    }
+  }
+
+  MemFree (buf);
+}
+
+static void BadProtTitleProc (
+  SeqEntryPtr sep,
+  Pointer mydata,
+  Int4 index,
+  Int2 indent
+)
+
+{
+  BioseqSetPtr  bssp;
+
+  if (sep == NULL) return;
+  if (! IS_Bioseq_set (sep)) return;
+  bssp = (BioseqSetPtr) sep->data.ptrvalue;
+  if (bssp->_class != BioseqseqSet_class_nuc_prot) return;
+  VisitBioseqsInSep (sep, NULL, StripBadProtTitles);
+}
+
+static void BadNCTitleProc (
+  SeqEntryPtr sep,
+  Pointer mydata,
+  Int4 index,
+  Int2 indent
+)
+
+{
+  BioseqPtr      bsp;
+  Boolean        is_nc;
+  ObjValNodePtr  ovp;
+  SeqIdPtr       sip;
+  TextSeqIdPtr   tsip;
+  ValNodePtr     vnp;
+
+  if (sep == NULL) return;
+  if (! IS_Bioseq (sep)) return;
+  bsp = (BioseqPtr) sep->data.ptrvalue;
+  if (bsp == NULL) return;
+
+  is_nc = FALSE;
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_OTHER) {
+      tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+      if (tsip != NULL && tsip->accession != NULL) {
+        if (StringNICmp (tsip->accession, "NC_", 3) == 0) {
+          is_nc = TRUE;
+        }
+      }
+    }
+  }
+  if (! is_nc) return;
+
+  vnp = BioseqGetSeqDescr (bsp, Seq_descr_title, NULL);
+  if (vnp == NULL) return;
+  if (vnp->extended != 0) {
+    ovp = (ObjValNodePtr) vnp;
+    ovp->idx.deleteme = TRUE;
+  }
+}
+
+static void BadNMTitleProc (
+  SeqEntryPtr sep,
+  Pointer mydata,
+  Int4 index,
+  Int2 indent
+)
+
+{
+  BioseqPtr      bsp;
+  Boolean        is_nm;
+  ObjValNodePtr  ovp;
+  SeqIdPtr       sip;
+  TextSeqIdPtr   tsip;
+  ValNodePtr     vnp;
+
+  if (sep == NULL) return;
+  if (! IS_Bioseq (sep)) return;
+  bsp = (BioseqPtr) sep->data.ptrvalue;
+  if (bsp == NULL) return;
+
+  is_nm = FALSE;
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_OTHER) {
+      tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+      if (tsip != NULL && tsip->accession != NULL) {
+        if (StringNICmp (tsip->accession, "NM_", 3) == 0) {
+          is_nm = TRUE;
+        } else if (StringNICmp (tsip->accession, "XM_", 3) == 0) {
+          is_nm = TRUE;
+        }
+      }
+    }
+  }
+  if (! is_nm) return;
+
+  vnp = BioseqGetSeqDescr (bsp, Seq_descr_title, NULL);
+  if (vnp == NULL) return;
+  if (vnp->extended != 0) {
+    ovp = (ObjValNodePtr) vnp;
+    ovp->idx.deleteme = TRUE;
+  }
+}
+
+typedef struct xmfeatdata {
+  SeqFeatPtr  gene;
+  SeqFeatPtr  cds;
+  Int2        numgenes;
+  Int2        numcds;
+  Int2        numprots;
+} XmFeatData, PNTR XmFeatPtr;
+
+static void FindXMFeats (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  XmFeatPtr  xfp;
+
+  if (sfp == NULL) return;
+  xfp = (XmFeatPtr) userdata;
+  if (xfp == NULL) return;
+
+  switch (sfp->data.choice) {
+    case SEQFEAT_GENE :
+      xfp->gene = sfp;
+      (xfp->numgenes)++;
+      break;
+    case SEQFEAT_CDREGION :
+      xfp->cds = sfp;
+      (xfp->numcds++);
+      break;
+    case SEQFEAT_PROT :
+      (xfp->numprots)++;
+      break;
+    default :
+      break;
+  }
+}
+
+static CharPtr GetNmTaxname (BioseqPtr bsp)
+
+{
+  BioSourcePtr  biop;
+  OrgRefPtr     orp;
+  SeqDescrPtr   sdp;
+
+  if (bsp == NULL) return NULL;
+
+  sdp = GetNextDescriptorUnindexed (bsp, Seq_descr_source, NULL);
+  if (sdp == NULL) return NULL;
+  biop = (BioSourcePtr) sdp->data.ptrvalue;
+  if (biop == NULL) return NULL;
+  orp = biop->org;
+  if (orp == NULL) return NULL;
+  if (StringHasNoText (orp->taxname)) return NULL;
+
+  return orp->taxname;
+}
+
+static CharPtr CreateSpecialXmTitle (BioseqPtr bsp)
+
+{
+  Char         buf [512];
+  CharPtr      cds = NULL, gene = NULL, result = NULL, taxname = NULL;
+  Uint2        entityID;
+  size_t       len;
+  SeqEntryPtr  sep;
+  XmFeatData   xfd;
+
+  if (bsp == NULL) return NULL;
+
+  taxname = GetNmTaxname (bsp);
+  if (StringHasNoText (taxname)) return NULL;
+
+  MemSet ((Pointer) &xfd, 0, sizeof (XmFeatData));
+
+  entityID = ObjMgrGetEntityIDForPointer (bsp);
+  sep = GetBestTopParentForDataEx (entityID, bsp, TRUE);
+
+  VisitFeaturesInSep (sep, (Pointer) &xfd, FindXMFeats);
+  if (xfd.numgenes != 1 || xfd.numcds != 1 || xfd.numprots < 1) return NULL;
+
+  FeatDefLabel (xfd.gene, buf, sizeof (buf) - 1, OM_LABEL_CONTENT);
+  gene = StringSaveNoNull (buf);
+
+  FeatDefLabel (xfd.cds, buf, sizeof (buf) - 1, OM_LABEL_CONTENT);
+  cds = StringSaveNoNull (buf);
+
+  len = StringLen (taxname) + StringLen (cds) +
+        StringLen (gene) + StringLen ("  (), partial mRNA") + 10;
+
+  result = (CharPtr) MemNew (sizeof (Char) * len);
+
+  if (result != NULL) {
+    if (xfd.cds != NULL && xfd.cds->partial) {
+      sprintf (result, "%s %s partial mRNA", taxname, cds);
+    } else {
+      sprintf (result, "%s %s mRNA", taxname, cds);
+    }
+  }
+
+  MemFree (gene);
+  MemFree (cds);
+
+  return result;
+}
+
+static Boolean AddSpecialXmTitles (GatherObjectPtr gop)
+{
+  BioseqPtr     bsp;
+  Boolean       is_nm;
+  SeqIdPtr      sip;
+  CharPtr       str;
+  TextSeqIdPtr  tsip;
+
+  if (gop == NULL || gop->itemtype != OBJ_BIOSEQ) return TRUE;
+  bsp = (BioseqPtr) gop->dataptr;
+  if (bsp == NULL) return TRUE;
+  is_nm = FALSE;
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_OTHER) {
+      tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+      if (tsip != NULL && tsip->accession != NULL) {
+        if (StringNICmp (tsip->accession, "NM_", 3) == 0) {
+          is_nm = TRUE;
+        } else if (StringNICmp (tsip->accession, "XM_", 3) == 0) {
+          is_nm = TRUE;
+        }
+      }
+    }
+  }
+  if (! is_nm) return TRUE;
+  str = CreateSpecialXmTitle (bsp);
+  if (str == NULL) return TRUE;
+  SeqDescrAddPointer (&(bsp->descr), Seq_descr_title, (Pointer) str);
+  return TRUE;
+}
+
+static void InstantiateSpecialXMTitles (
+  Uint2 entityID,
+  Pointer ptr
+)
+
+{
+  Boolean  objMgrFilt [OBJ_MAX];
+
+  if (entityID == 0) {
+    entityID = ObjMgrGetEntityIDForPointer (ptr);
+  }
+  if (entityID == 0) return;
+
+  AssignIDsInEntity (entityID, 0, NULL);
+  MemSet ((Pointer) objMgrFilt, FALSE, sizeof (objMgrFilt));
+  objMgrFilt [OBJ_BIOSEQ] = TRUE;
+  GatherObjectsInEntity (entityID, 0, NULL, AddSpecialXmTitles, NULL, objMgrFilt);
+}
+
+static void BSSaveToFile (
+  ByteStorePtr bs,
+  CharPtr path
+)
+
+{
+  Byte  buf [256];
+  Int4  count;
+  FILE  *fp;
+
+  if (bs == NULL || StringHasNoText (path)) return;
+
+  fp = FileOpen (path, "w");
+  if (fp != NULL) {
+    Nlm_BSSeek (bs, 0, SEEK_SET);
+    count = BSRead (bs, buf, sizeof (buf));
+    while (count > 0) {
+      FileWrite (buf, count, 1, fp);
+      count = BSRead (bs, buf, sizeof (buf));
+    }
+    FileClose (fp);
+  }
+}
+
+typedef struct diffblock {
+  ValNodePtr  head;
+  ValNodePtr  tail;
+} DiffBlock, PNTR DiffBlockPtr;
+
+static void RecordDiffBlock (
+  DiffBlockPtr dbp,
+  CharPtr str
+)
+
+{
+  ValNodePtr  vnp;
+
+  if (dbp == NULL || StringHasNoText (str)) return;
+
+  vnp = ValNodeCopyStr (&(dbp->tail), 0, str);
+  if (dbp->head == NULL) {
+    dbp->head = vnp;
+  }
+  dbp->tail = vnp;
+}
+
+static void WriteDiffBlock (
+  DiffBlockPtr dbp,
+  FILE *fp
+)
+
+{
+  Char        ch;
+  Int2        idx;
+  Int2        margin = INT2_MAX;
+  CharPtr     ptr;
+  Int2        spaces;
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (dbp == NULL || dbp->head == NULL || fp == NULL) return;
+
+  for (vnp = dbp->head; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    ch = str [0];
+    if (ch == '<' || ch == '>') {
+      ptr = str + 1;
+      ch = *ptr;
+      spaces = 0;
+      while (ch == ' ') {
+        spaces++;
+        ptr++;
+        ch = *ptr;
+      }
+      if (spaces < margin) {
+        margin = spaces;
+      }
+    }
+  }
+
+  if (margin > 80) {
+    margin = 80;
+  }
+
+  for (vnp = dbp->head; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    ch = str [0];
+    if (ch == '<' || ch == '>') {
+      ptr = str + 1;
+      ch = *ptr;
+      idx = 0;
+      while (idx < margin && ch == ' ') {
+        idx++;
+        ptr++;
+        ch = *ptr;
+      }
+      fprintf (fp, "%c %s\n", str [0], ptr);
+    } else if (ch == '-') {
+      fprintf (fp, "---\n");
+    } else if (ch == '=') {
+      fprintf (fp, "===\n");
+    }
+  }
+
+  fprintf (fp, "\n");
+  fflush (fp);
+}
+
+static void ResetDiffBlock (
+  DiffBlockPtr dbp
+)
+
+{
+  if (dbp == NULL) return;
+
+  dbp->head = ValNodeFreeData (dbp->head);
+  dbp->tail = NULL;
+}
+
+static void ReportAsnDiffs (
+  FILE *logfp,
+  CharPtr id,
+  ByteStorePtr bs1,
+  ByteStorePtr bs2)
+
+{
+#ifdef OS_UNIX
+  Char       ch;
+  Char       cmmd [512];
+  DiffBlock  db;
+  int        diff;
+  FileCache  fc;
+  FILE       *fp;
+  Char       line [512];
+  Char       path1 [PATH_MAX];
+  Char       path2 [PATH_MAX];
+  Char       path3 [PATH_MAX];
+  CharPtr    str;
+
+  if (logfp == NULL || StringHasNoText (id)) return;
+  if (bs1 == NULL || bs2 == NULL) return;
+
+  TmpNam (path1);
+  TmpNam (path2);
+  TmpNam (path3);
+
+  BSSaveToFile (bs1, path1);
+  BSSaveToFile (bs2, path2);
+
+  db.head = NULL;
+  db.tail = NULL;
+
+  sprintf (cmmd, "diff -b -h %s %s > %s", path1, path2, path3);
+  diff = system (cmmd);
+
+  if (diff > 0) {
+    fp = FileOpen (path3, "r");
+    if (fp != NULL) {
+      fprintf (logfp, "\n\n%s\n\n", id);
+      fflush (logfp);
+      if (FileCacheSetup (&fc, fp)) {
+        str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+        while (str != NULL) {
+          ch = line [0];
+          if (ch == '<' || ch == '>') {
+            RecordDiffBlock (&db, line);
+          } else if (ch == '-') {
+            RecordDiffBlock (&db, "---");
+          } else if (IS_DIGIT (ch)) {
+            WriteDiffBlock (&db, logfp);
+            ResetDiffBlock (&db);
+            RecordDiffBlock (&db, "===");
+          } else if (StringHasNoText (str)) {
+            WriteDiffBlock (&db, logfp);
+            ResetDiffBlock (&db);
+          }
+          str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+        }
+        WriteDiffBlock (&db, logfp);
+        ResetDiffBlock (&db);
+      }
+      fprintf (logfp, "//\n\n");
+      FileClose (fp);
+    }
+  }
+
+  sprintf (cmmd, "rm %s; rm %s; rm %s", path1, path2, path3);
+  system (cmmd);
+#endif
+}
+
+static void LogPopSetTitleResults (FILE *fp, PopSetRetroStatPtr stat, SeqEntryPtr sep)
+{
+  ValNode vn;
+  CharPtr txt;
+
+  if (fp == NULL || stat == NULL || sep == NULL || !IS_Bioseq_set (sep)) {
+    return;
+  }
+  /* if test wasn't run, return */
+  if (stat->feature_clause == 0 && stat->common_title == 0 && stat->uncalculatable == 0) {
+    return;
+  }
+
+  MemSet (&vn, 0, sizeof (ValNode));
+  vn.choice = OBJ_BIOSEQSET;
+  vn.data.ptrvalue = sep->data.ptrvalue;
+  txt = GetDiscrepancyItemText (&vn);
+  fprintf (fp, "AutoDefPopSetResults: %s", txt);
+  txt = MemFree (txt);
+  fprintf (fp, "\tFeature Clause: %d\n\tCommon Title: %d\n\tUncalculatable: %d\n",
+           stat->feature_clause, stat->common_title, stat->uncalculatable);
+}
+
+static void DoAsnDiffReport (
   SeqEntryPtr sep,
   CleanFlagPtr cfp
 )
 
 {
-  Boolean     bsec = FALSE, ssec = FALSE, norm = FALSE;
+  ByteStorePtr         bs = NULL, tmp = NULL;
+  Uint2                entityID;
+  Boolean              okay = FALSE;
+  PopSetRetroStatData  stat;
+
+  if (sep == NULL || cfp == NULL) return;
+
+  MemSet ((Pointer) &stat, 0, sizeof (PopSetRetroStatData));
+
+  RemoveAllNcbiCleanupUserObjects (sep);
+
+  entityID = ObjMgrGetEntityIDForChoice (sep);
+
+  /* Capital letters avoid unwanted diffs on issues already fixed in ID */
+
+  if (StringChr (cfp->selective, 'S') != NULL) {
+    SeriousSeqEntryCleanup (sep, NULL, NULL);
+    RemoveAllNcbiCleanupUserObjects (sep);
+    NormalizeDescriptorOrder (sep);
+  }
+  if (StringChr (cfp->selective, 'B') != NULL) {
+    BasicSeqEntryCleanup (sep);
+  }
+  if (StringChr (cfp->selective, 'A') != NULL) {
+    VisitPubdescsInSep (sep, NULL, CleanupPubAuthors);
+  }
+  if (StringChr (cfp->selective, 'P') != NULL) {
+    VisitPubdescsInSep (sep, (Pointer) cfp, CleanupPubBody);
+  }
+  if (StringChr (cfp->selective, 'L') != NULL) {
+    VisitFeaturesInSep (sep, NULL, CleanupLocation);
+  }
+  if (StringChr (cfp->selective, 'R') != NULL) {
+    VisitFeaturesInSep (sep, NULL, CleanupMostRNAs);
+    VisitFeaturesInSep (sep, NULL, CleanupRemainingRNAs);
+    VisitFeaturesInSep (sep, NULL, ModRNAs);
+  }
+  if (StringChr (cfp->selective, 'Q') != NULL) {
+    SortSeqEntryQualifiers (sep);
+  }
+  if (StringChr (cfp->selective, 'G') != NULL) {
+    EntryChangeGBSource (sep);
+    EntryCheckGBBlock (sep);
+  }
+  if (StringChr (cfp->selective, 'K') != NULL) {
+    MoveFeatsFromPartsSet (sep);
+    move_cds_ex (sep, TRUE);
+  }
+  if (StringChr (cfp->selective, 'M') != NULL) {
+    SeqEntryPubsAsn4 (sep, cfp->isEmblDdbj);
+  }
+  if (StringChr (cfp->selective, 'O') != NULL) {
+    SeqEntryPubsAsn4Ex (sep, cfp->isEmblDdbj, FALSE);
+  }
+  if (StringChr (cfp->selective, 'D') != NULL) {
+    SeqMgrIndexFeatures (entityID, 0);
+    DoAutoDef (sep, entityID);
+  }
+  if (StringChr (cfp->selective, 'E') != NULL) {
+    SeqMgrIndexFeatures (entityID, 0);
+    PopSetAutoDefRetro (sep, &stat);
+    LogPopSetTitleResults (cfp->logfp, &stat, sep);
+  }
+
+  NormalizeDescriptorOrder (sep);
+
+  /* Look for change in single issue */
+
+  bs = Se2BsX (sep);
+  if (StringHasNoText (cfp->selective)) {
+    okay = TRUE;
+  } else if (StringChr (cfp->selective, 's') != NULL) {
+    SeriousSeqEntryCleanup (sep, NULL, NULL);
+    RemoveAllNcbiCleanupUserObjects (sep);
+    NormalizeDescriptorOrder (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'b') != NULL) {
+    BasicSeqEntryCleanup (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'a') != NULL) {
+    VisitPubdescsInSep (sep, NULL, CleanupPubAuthors);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'p') != NULL) {
+    VisitPubdescsInSep (sep, (Pointer) cfp, CleanupPubBody);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'l') != NULL) {
+    VisitFeaturesInSep (sep, NULL, CleanupLocation);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'r') != NULL) {
+    VisitFeaturesInSep (sep, NULL, CleanupMostRNAs);
+    VisitFeaturesInSep (sep, NULL, CleanupRemainingRNAs);
+    VisitFeaturesInSep (sep, NULL, ModRNAs);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'q') != NULL) {
+    SortSeqEntryQualifiers (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'g') != NULL) {
+    EntryChangeGBSource (sep);
+    EntryCheckGBBlock (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'k') != NULL) {
+    MoveFeatsFromPartsSet (sep);
+    move_cds_ex (sep, TRUE);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'm') != NULL) {
+    SeqEntryPubsAsn4 (sep, cfp->isEmblDdbj);
+    NormalizeDescriptorOrder (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'o') != NULL) {
+    SeqEntryPubsAsn4Ex (sep, cfp->isEmblDdbj, FALSE);
+    NormalizeDescriptorOrder (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'd') != NULL) {
+    SeqMgrIndexFeatures (entityID, 0);
+    DoAutoDef (sep, entityID);
+    NormalizeDescriptorOrder (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      okay = TRUE;
+    }
+    tmp = BSFree (tmp);
+  } else if (StringChr (cfp->selective, 'e') != NULL) {
+    SeqMgrIndexFeatures (entityID, 0);
+    PopSetAutoDefRetro (sep, &stat);
+    LogPopSetTitleResults (cfp->logfp, &stat, sep);
+    NormalizeDescriptorOrder (sep);
+    if (stat.title_added) {
+      okay = TRUE;
+    }
+  } else {
+    okay = TRUE;
+  }
+
+  /* Report incremental diff */
+
+  if (okay) {
+    SeriousSeqEntryCleanup (sep, NULL, NULL);
+    RemoveAllNcbiCleanupUserObjects (sep);
+    NormalizeDescriptorOrder (sep);
+    tmp = Se2BsX (sep);
+    if (! BSEqual (bs, tmp)) {
+      if (cfp->logfp != NULL) {
+        ReportAsnDiffs (cfp->logfp, cfp->buf, bs, tmp);
+      }
+    }
+    tmp = BSFree (tmp);
+  }
+
+  BSFree (bs);
+}
+
+static void GetPopPhyMutEcoType (
+  BioseqSetPtr bssp,
+  Pointer userdata
+)
+
+{
+  CharPtr PNTR  set_type;
+
+  if (bssp == NULL || userdata == NULL) return;
+  set_type = (CharPtr PNTR) userdata;
+
+  if (bssp->_class >= BioseqseqSet_class_mut_set && bssp->_class <= BioseqseqSet_class_eco_set) {
+    switch (bssp->_class) {
+      case BioseqseqSet_class_mut_set :
+        *set_type = "MUT";
+        break;
+      case BioseqseqSet_class_pop_set :
+        *set_type = "POP";
+        break;
+      case BioseqseqSet_class_phy_set :
+        *set_type = "PHY";
+        break;
+      case BioseqseqSet_class_eco_set :
+        *set_type = "ECO";
+        break;
+      default :
+        break;
+    }
+  }
+}
+
+/*
+static void ChromosomeScanCallback (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  BioSourcePtr       biop = NULL;
+  CleanFlagPtr       cfp;
+  Boolean            complete = FALSE;
+  SeqMgrDescContext  dcontext;
+  CharPtr            genome = NULL;
+  MolInfoPtr         mip = NULL;
+  OrgNamePtr         onp;
+  OrgRefPtr          orp;
+  SeqDescrPtr        sdp;
+
+  if (bsp == NULL || userdata == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp->logfp == NULL) return;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+  if (sdp != NULL) {
+    biop = (BioSourcePtr) sdp->data.ptrvalue;
+  }
+  if (biop == NULL) return;
+  if (biop->genome == GENOME_chromosome) {
+    genome = "CHROM";
+  } else if (biop->genome == GENOME_genomic) {
+    genome = "GENOM";
+  } else if (biop->genome == GENOME_unknown) {
+    genome = "UNKWN";
+  } else {
+    return;
+  }
+  orp = biop->org;
+  if (orp == NULL) return;
+  onp = orp->orgname;
+  if (onp == NULL) return;
+  if (StringNICmp (onp->lineage, "Eukaryota; ", 11) != 0) return;
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &dcontext);
+  if (sdp != NULL) {
+    mip = (MolInfoPtr) sdp->data.ptrvalue;
+  }
+  if (mip != NULL && mip->completeness == 1) {
+    complete = TRUE;
+  }
+
+  if (cfp->logfp != NULL) {
+    if (complete) {
+      fprintf (cfp->logfp, "COMP %s %s\n", genome, cfp->buf);
+    } else {
+      fprintf (cfp->logfp, "PART %s %s\n", genome, cfp->buf);
+    }
+    fflush (cfp->logfp);
+  }
+}
+*/
+
+/*
+static void PopPhyMutEcoScanCallback (
+  BioseqSetPtr bssp,
+  Pointer userdata
+)
+
+{
+  CleanFlagPtr  cfp;
+  SeqDescrPtr   sdp;
+  CharPtr       set_type = NULL;
+  CharPtr       title = NULL;
+
+  if (bssp == NULL || userdata == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp->logfp == NULL) return;
+
+  if (bssp->_class >= BioseqseqSet_class_mut_set && bssp->_class <= BioseqseqSet_class_eco_set) {
+    GetPopPhyMutEcoType (bssp, (Pointer) &set_type);
+    switch (bssp->_class) {
+      case BioseqseqSet_class_mut_set :
+        set_type = "MUT";
+        break;
+      case BioseqseqSet_class_pop_set :
+        set_type = "POP";
+        break;
+      case BioseqseqSet_class_phy_set :
+        set_type = "PHY";
+        break;
+      case BioseqseqSet_class_eco_set :
+        set_type = "ECO";
+        break;
+      default :
+        break;
+    }
+    for (sdp = bssp->descr; sdp != NULL; sdp = sdp->next) {
+      if (sdp->choice != Seq_descr_title) continue;
+      title = (CharPtr) sdp->data.ptrvalue;
+    }
+    if (StringHasNoText (set_type)) {
+      set_type = "UNK";
+    }
+    if (StringDoesHaveText (title)) {
+      fprintf (cfp->logfp, "%s set TITLE %s\n", set_type, cfp->buf);
+    } else {
+      fprintf (cfp->logfp, "%s set ANNON %s\n", set_type, cfp->buf);
+    }
+  }
+}
+*/
+
+/*
+static void PseudoScanCallback (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  CleanFlagPtr  cfp;
+  CharPtr       str;
+
+  if (sfp == NULL || userdata == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp->logfp == NULL) return;
+
+  if (! sfp->pseudo) return;
+
+  str = FindKeyFromFeatDefType (sfp->idx.subtype, FALSE);
+  if (StringHasNoText (str)) {
+    str = "?";
+  }
+
+  fprintf (cfp->logfp, "%s Pseudo %s\n", cfp->buf, str);
+}
+*/
+
+/*
+static void PubScanCallback (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  CitArtPtr     cap;
+  CleanFlagPtr  cfp;
+  CitJourPtr    cjp;
+  ImprintPtr    imp;
+  ValNodePtr    vnp;
+
+  if (pdp == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp == NULL || cfp->logfp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Article) {
+      cap = (CitArtPtr) vnp->data.ptrvalue;
+      if (cap != NULL && cap->from == 1) {
+        cjp = (CitJourPtr) cap->fromptr;
+        if (cjp != NULL) {
+          imp = cjp->imp;
+          if (imp != NULL) {
+            if (imp->part_sup != NULL && StringHasNoText (imp->part_sup)) {
+              fprintf (cfp->logfp, "EMPTY PART_SUP %s\n", cfp->buf);
+            }
+            if (StringDoesHaveText (imp->issue)) {
+              if (StringNICmp (imp->issue, "PT ", 3) == 0) {
+                fprintf (cfp->logfp, "IMP_PT %s\n", cfp->buf);
+              }
+              if (StringDoesHaveText (imp->part_sup)) {
+                fprintf (cfp->logfp, "SUPN %s\n", cfp->buf);
+              }
+              if (StringDoesHaveText (imp->part_supi)) {
+                fprintf (cfp->logfp, "SUPI %s\n", cfp->buf);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+*/
+
+static void DoASNScan (
+  SeqEntryPtr sep,
+  CleanFlagPtr cfp
+)
+
+{
+  /*
+  ByteStorePtr  bs = NULL, tmp = NULL;
+
+  if (sep == NULL || cfp == NULL || cfp->logfp == NULL) return;
+  */
+
+  /*
+  VisitBioseqsInSep (sep, (Pointer) cfp, ChromosomeScanCallback);
+  */
+
+  /*
+  VisitSetsInSep (sep, (Pointer) cfp, PopPhyMutEcoScanCallback);
+  */
+
+  /*
+  SeriousSeqEntryCleanup (sep, NULL, NULL);
+  RemoveAllNcbiCleanupUserObjects (sep);
+  NormalizeDescriptorOrder (sep);
+
+  bs = Se2Bs (sep);
+
+  SeqEntryPubsAsn4Ex (sep, cfp->isEmblDdbj, TRUE);
+  NormalizeDescriptorOrder (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    fprintf (cfp->logfp, "%s\n", cfp->buf);
+    fflush (cfp->logfp);
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  BSFree (bs);
+  */
+
+  /*
+  VisitFeaturesInSep (sep, (Pointer) cfp, PseudoScanCallback);
+  */
+
+  /*
+  VisitPubdescsInSep (sep, (Pointer) cfp, PubScanCallback);
+  */
+}
+
+static void DoASNReport (
+  SeqEntryPtr sep,
+  CleanFlagPtr cfp,
+  Boolean dossec,
+  Boolean quick,
+  Boolean popphymutdef
+)
+
+{
+  Boolean              auth = FALSE, bsec = FALSE, clnr = FALSE, gbbk = FALSE,
+                       modr = FALSE, move = FALSE, norm = FALSE, othr = FALSE,
+                       pack = FALSE, publ = FALSE, ssec = FALSE, sloc = FALSE,
+                       sort = FALSE, titl = FALSE, popphymuttitle = FALSE,
+                       chkseg = FALSE, chknps = FALSE, dnarna = FALSE,
+                       ncbiusrobj = FALSE;
+  ByteStorePtr         bs = NULL, tmp = NULL;
   ChangeData  cdbefore, cdafter;
-  CharPtr     str1, str2, str3, str4;
+  Int2                 chk_nuc_prot_val = 0;
+  Uint2                entityID;
+  CharPtr              set_type = NULL;
+  PopSetRetroStatData  stat;
 
   if (sep == NULL || cfp == NULL) return;
 
+  if (FindNcbiCleanupUserObject (sep) != NULL) {
+    ncbiusrobj = TRUE;
+  }
+
+  MemSet ((Pointer) &stat, 0, sizeof (PopSetRetroStatData));
+
+  RemoveAllNcbiCleanupUserObjects (sep);
+
+  if (popphymutdef) {
+    VisitSetsInSep (sep, (Pointer) &set_type, GetPopPhyMutEcoType);
+    if (StringHasNoText (set_type)) return;
+
+    entityID = ObjMgrGetEntityIDForChoice (sep);
+
+    SeqMgrIndexFeatures (entityID, 0);
+    PopSetAutoDefRetro (sep, &stat);
+    LogPopSetTitleResults (cfp->logfp, &stat, sep);
+
+    if (stat.title_added) {
+      popphymuttitle = TRUE;
+    }
+
+    if (popphymuttitle) {
+      if (cfp->logfp != NULL) {
+        if (StringHasNoText (set_type)) {
+          set_type = "UNK";
+        }
+        fprintf (cfp->logfp, "%s_SET %s\n", set_type, cfp->buf);
+        fflush (cfp->logfp);
+      }
+    }
+
+    return;
+  }
+
+  if (quick) {
+    bs = Se2Bs (sep);
+
+    NormalizeDescriptorOrder (sep);
+    tmp = Se2Bs (sep);
+    if (! BSEqual (bs, tmp)) {
+      norm = TRUE;
+    }
+    BSFree (bs);
+    bs = tmp;
+
+    SeriousSeqEntryCleanup (sep, NULL, NULL);
+    RemoveAllNcbiCleanupUserObjects (sep);
+    NormalizeDescriptorOrder (sep);
+    tmp = Se2Bs (sep);
+    if (! BSEqual (bs, tmp)) {
+      ssec = TRUE;
+    }
+    BSFree (bs);
+    bs = tmp;
+
+    BSFree (bs);
+
+    if (ssec) {
+      (cfp->rawcounts.ssec)++;
+      (cfp->cumcounts.ssec)++;
+      if (cfp->logfp != NULL) {
+        fprintf (cfp->logfp, "SSEC %s\n", cfp->buf);
+        fflush (cfp->logfp);
+      }
+    } else if (norm) {
+      (cfp->rawcounts.norm)++;
+      (cfp->cumcounts.norm)++;
+      if (cfp->logfp != NULL) {
+        fprintf (cfp->logfp, "NORM %s\n", cfp->buf);
+        fflush (cfp->logfp);
+      }
+    } else {
+      (cfp->rawcounts.okay)++;
+      (cfp->cumcounts.okay)++;
+      if (cfp->logfp != NULL) {
+        fprintf (cfp->logfp, "OKAY %s\n", cfp->buf);
+        fflush (cfp->logfp);
+      }
+    }
+
+    return;
+  }
+
   MemSet ((Pointer) &cdbefore, 0, sizeof (ChangeData));
   MemSet ((Pointer) &cdafter, 0, sizeof (ChangeData));
 
+  cdbefore.isRefSeq = cfp->isRefSeq;
+  cdafter.isRefSeq = cfp->isRefSeq;
+
   CheckForChanges (sep, &cdbefore);
 
-  str1 = Se2Str (sep);
+  bs = Se2Bs (sep);
+
   NormalizeDescriptorOrder (sep);
-  str2 = Se2Str (sep);
-  if (StringCmp (str1, str2) != 0) {
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
     norm = TRUE;
   }
+  BSFree (bs);
+  bs = tmp;
+
+  VisitFeaturesInSep (sep, NULL, CleanupLocation);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    sloc = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  VisitFeaturesInSep (sep, NULL, CleanupMostRNAs);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    clnr = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  VisitFeaturesInSep (sep, NULL, CleanupRemainingRNAs);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    othr = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  VisitFeaturesInSep (sep, NULL, ModRNAs);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    modr = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  VisitPubdescsInSep (sep, NULL, CleanupPubAuthors);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    auth = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  VisitPubdescsInSep (sep, (Pointer) cfp, CleanupPubBody);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    publ = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  SortSeqEntryQualifiers (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    sort = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  VisitBioseqsInSep (sep, NULL, FixBspMol);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    dnarna = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
   BasicSeqEntryCleanup (sep);
-  str3 = Se2Str (sep);
-  if (StringCmp (str2, str3) != 0) {
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
     bsec = TRUE;
   }
+  BSFree (bs);
+  bs = tmp;
+
+  EntryChangeGBSource (sep);
+  EntryCheckGBBlock (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    gbbk = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  entityID = ObjMgrGetEntityIDForChoice (sep);
+  SeqMgrIndexFeatures (entityID, NULL);
+  SeqEntryExplore (sep, NULL, BadProtTitleProc);
+  DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
+  SeqMgrIndexFeatures (entityID, NULL);
+  InstantiateProteinTitles (entityID, NULL);
+  SeqMgrClearFeatureIndexes (entityID, NULL);
+  BasicSeqEntryCleanup (sep);
+  NormalizeDescriptorOrder (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    titl = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  MoveFeatsFromPartsSet (sep);
+  move_cds_ex (sep, TRUE);
+  NormalizeDescriptorOrder (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    pack = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  SeqEntryExplore(sep, NULL, ChkSegset);
+  NormalizeDescriptorOrder (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    chkseg = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  SeqEntryExplore(sep, (Pointer) &chk_nuc_prot_val, ChkNucProt);
+  NormalizeDescriptorOrder (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    chknps = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  SeqEntryPubsAsn4 (sep, cfp->isEmblDdbj);
+  NormalizeDescriptorOrder (sep);
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
+    move = TRUE;
+  }
+  BSFree (bs);
+  bs = tmp;
+
+  if (dossec) {
   SeriousSeqEntryCleanup (sep, NULL, NULL);
+    RemoveAllNcbiCleanupUserObjects (sep);
   NormalizeDescriptorOrder (sep);
-  str4 = Se2Str (sep);
-  if (StringCmp (str3, str4) != 0) {
+    tmp = Se2Bs (sep);
+    if (! BSEqual (bs, tmp)) {
     ssec = TRUE;
   }
+    BSFree (bs);
+    bs = tmp;
+  }
+
+  BSFree (bs);
 
   CheckForChanges (sep, &cdafter);
 
-  if (ssec) {
-    (cfp->ssec)++;
-    (cfp->cumssec)++;
+  if (ssec || chkseg || chknps) {
+    (cfp->rawcounts.ssec)++;
+    (cfp->cumcounts.ssec)++;
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "SSEC %s\n", cfp->buf);
       fflush (cfp->logfp);
     }
-  } else if (bsec) {
-    (cfp->bsec)++;
-    (cfp->cumbsec)++;
+  } else if (move) {
+    (cfp->rawcounts.move)++;
+    (cfp->cumcounts.move)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "MOVE %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (pack) {
+    (cfp->rawcounts.pack)++;
+    (cfp->cumcounts.pack)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "PACK %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (titl) {
+    (cfp->rawcounts.titl)++;
+    (cfp->cumcounts.titl)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "TITL %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (gbbk) {
+    (cfp->rawcounts.gbbk)++;
+    (cfp->cumcounts.gbbk)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "GBBK %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (bsec || dnarna) {
+    (cfp->rawcounts.bsec)++;
+    (cfp->cumcounts.bsec)++;
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "BSEC %s\n", cfp->buf);
       fflush (cfp->logfp);
     }
+  } else if (sort) {
+    (cfp->rawcounts.sort)++;
+    (cfp->cumcounts.sort)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "SORT %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (sloc) {
+    (cfp->rawcounts.sloc)++;
+    (cfp->cumcounts.sloc)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "SLOC %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (clnr) {
+    (cfp->rawcounts.clnr)++;
+    (cfp->cumcounts.clnr)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "CLNR %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (othr) {
+    (cfp->rawcounts.othr)++;
+    (cfp->cumcounts.othr)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "OTHR %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (modr) {
+    (cfp->rawcounts.modr)++;
+    (cfp->cumcounts.modr)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "MODR %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (publ) {
+    (cfp->rawcounts.publ)++;
+    (cfp->cumcounts.publ)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "PUBL %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  } else if (auth) {
+    (cfp->rawcounts.auth)++;
+    (cfp->cumcounts.auth)++;
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "AUTH %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
   } else if (norm) {
-    (cfp->norm)++;
-    (cfp->cumnorm)++;
+    (cfp->rawcounts.norm)++;
+    (cfp->cumcounts.norm)++;
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "NORM %s\n", cfp->buf);
       fflush (cfp->logfp);
     }
   } else {
-    (cfp->okay)++;
-    (cfp->cumokay)++;
+    (cfp->rawcounts.okay)++;
+    (cfp->cumcounts.okay)++;
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "OKAY %s\n", cfp->buf);
       fflush (cfp->logfp);
     }
   }
 
+  if (cdbefore.protNucSet) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "PNS %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.noPopsetTitle) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "PST %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.oldgbqual) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "GBQ %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.sgml) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "SGM %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.cdscodon) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "CDN %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
   if (cdbefore.rubisco) {
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "RUB %s\n", cfp->buf);
@@ -753,6 +3093,152 @@ static void DoASNReport (
       fflush (cfp->logfp);
     }
   }
+  if (cdbefore.badOrg) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "ORG %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.rpt_unit_seq) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "RUS %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+
+  if (cdbefore.badDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "BDX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.refDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "FDX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.srcDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "SDX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.capDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "CDX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.privDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "PDX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.oldDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "ODX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.multDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "MDX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdbefore.rareDbxref) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "RDX %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (cdafter.hasUnpublished && ! cdafter.hasPublished) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "UNP %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+
+  if (sort) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "SRT %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (sloc) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "SLC %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (clnr) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "RCN %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (othr) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "RNO %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (modr) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "RMD %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (publ) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "PBC %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (auth) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "ATH %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (pack) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "PKG %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (move) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "MVP %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (titl) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "TTL %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (chkseg) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "SEG %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (chknps) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "NSS%d %s\n", (int) chk_nuc_prot_val, cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
+  if (dnarna) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "MRN %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
 
   if (cdbefore.protdesc != cdafter.protdesc) {
     if (cfp->logfp != NULL) {
@@ -779,35 +3265,51 @@ static void DoASNReport (
     }
   }
 
-  MemFree (str1);
-  MemFree (str2);
-  MemFree (str3);
-  MemFree (str4);
+  if (ncbiusrobj) {
+    if (cfp->logfp != NULL) {
+      fprintf (cfp->logfp, "USR %s\n", cfp->buf);
+      fflush (cfp->logfp);
+    }
+  }
 }
 
+static CharPtr ffmod [] = {
+  "",
+  "release",
+  "entrez",
+  "gbench",
+  "dump",
+  NULL
+};
+
 static void DoGBFFReport (
   SeqEntryPtr sep,
-  CleanFlagPtr cfp
+  CleanFlagPtr cfp,
+  Int2 batch
 )
 
 {
 #ifdef OS_UNIX
+  AsnIoPtr     aip;
+  Char         arguments [128];
   BioseqPtr    bsp;
-  Char         cmmd [256];
+  Char         ch;
+  Char         cmmd [512];
+  int          diff;
+  FileCache    fc;
   FILE         *fp;
   SeqEntryPtr  fsep;
+  Char         line [512];
+  FILE         *ofp;
   Char         path1 [PATH_MAX];
   Char         path2 [PATH_MAX];
+  Char         path3 [PATH_MAX];
   CharPtr      rep = "reports";
   SeqIdPtr     sip;
+  CharPtr      str;
 
   if (sep == NULL || cfp == NULL) return;
 
-  if (cfp->logfp != NULL) {
-    fprintf (cfp->logfp, "%s\n", cfp->buf);
-    fflush (cfp->logfp);
-  }
-
   fsep = FindNthBioseq (sep, 1);
   if (fsep != NULL && fsep->choice == 1) {
     bsp = (BioseqPtr) fsep->data.ptrvalue;
@@ -833,6 +3335,13 @@ static void DoGBFFReport (
     }
   }
 
+  if (cfp->logfp != NULL) {
+    fprintf (cfp->logfp, "%s\n", cfp->buf);
+    fflush (cfp->logfp);
+  }
+
+  if (batch == 1) {
+
   TmpNam (path1);
   TmpNam (path2);
 
@@ -853,6 +3362,147 @@ static void DoGBFFReport (
 
   sprintf (cmmd, "rm %s; rm %s", path1, path2);
   system (cmmd);
+
+  } else if (batch == 2) {
+
+    TmpNam (path1);
+    TmpNam (path2);
+    TmpNam (path3);
+
+    aip = AsnIoOpen (path3, "w");
+    if (aip == NULL) return;
+
+    SeqEntryAsnWrite (sep, aip, NULL);
+    AsnIoClose (aip);
+
+    fp = FileOpen (path1, "w");
+    if (fp != NULL) {
+      SeqEntryToGnbk (sep, NULL, GENBANK_FMT, cfp->ffmode, NORMAL_STYLE, 0, 0, 0, NULL, fp);
+    }
+    FileClose (fp);
+
+    arguments [0] = '\0';
+    sprintf (arguments,
+             "-format genbank -mode %s -style normal -view nuc -nocleanup",
+             ffmod [(int) cfp->ffmode]);
+
+    sprintf (cmmd, "%s %s -i %s -o %s", cfp->asn2flat, arguments, path3, path2);
+    system (cmmd);
+
+    sprintf (cmmd, "diff -h %s %s > %s", path1, path2, path3);
+    diff = system (cmmd);
+
+    if (diff > 0) {
+      fp = FileOpen (path3, "r");
+      ofp = FileOpen (rep, "a");
+      if (fp != NULL && ofp != NULL) {
+        fprintf (ofp, "\n\n%s\n", cfp->buf);
+        fflush (ofp);
+        if (FileCacheSetup (&fc, fp)) {
+          str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+          while (str != NULL) {
+            ch = line [0];
+            if (ch == '<' || ch == '>' || ch == '-') {
+              fprintf (ofp, "%s\n", line);
+            } else if (IS_DIGIT (ch)) {
+              fprintf (ofp, "\n%s\n", "===");
+            }
+            str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+          }
+        }
+      }
+      FileClose (ofp);
+      FileClose (fp);
+    }
+
+    sprintf (cmmd, "rm %s; rm %s; rm %s", path1, path2, path3);
+    system (cmmd);
+  }
+#endif
+}
+
+static void DoValidatorReport (
+  SeqEntryPtr sep,
+  FILE *logfp,
+  CharPtr id,
+  CharPtr asnval
+)
+
+{
+#ifdef OS_UNIX
+  AsnIoPtr   aip;
+  Char       ch;
+  Char       cmmd [512];
+  int        diff;
+  FileCache  fc;
+  FILE       *fp;
+  Char       line [512];
+  Char       path1 [PATH_MAX];
+  Char       path2 [PATH_MAX];
+  Char       path3 [PATH_MAX];
+  Char       path4 [PATH_MAX];
+  Char       path5 [PATH_MAX];
+  CharPtr    str;
+
+  if (sep == NULL || logfp == NULL) return;
+  if (StringHasNoText (id) || StringHasNoText (asnval)) return;
+
+  TmpNam (path1);
+  TmpNam (path2);
+  TmpNam (path3);
+  TmpNam (path4);
+  TmpNam (path5);
+
+  RemoveAllNcbiCleanupUserObjects (sep);
+
+  aip = AsnIoOpen (path3, "w");
+  if (aip == NULL) return;
+
+  SeqEntryAsnWrite (sep, aip, NULL);
+  AsnIoClose (aip);
+
+  SeriousSeqEntryCleanup (sep, NULL, NULL);
+  RemoveAllNcbiCleanupUserObjects (sep);
+
+  aip = AsnIoOpen (path4, "w");
+  if (aip == NULL) return;
+
+  SeqEntryAsnWrite (sep, aip, NULL);
+  AsnIoClose (aip);
+
+  sprintf (cmmd, "%s -i %s -o stdout -Q 1 -r -l | sort > %s", asnval, path3, path1);
+  system (cmmd);
+
+  sprintf (cmmd, "%s -i %s -o stdout -Q 1 -r -l | sort > %s", asnval, path4, path2);
+  system (cmmd);
+
+  sprintf (cmmd, "diff -h %s %s > %s", path1, path2, path5);
+  diff = system (cmmd);
+
+  if (diff > 0) {
+    fp = FileOpen (path5, "r");
+    if (fp != NULL) {
+      fprintf (logfp, "\n\n%s\n", id);
+      fflush (logfp);
+      if (FileCacheSetup (&fc, fp)) {
+        str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+        while (str != NULL) {
+          ch = line [0];
+          if (ch == '<' || ch == '>' || ch == '-') {
+            fprintf (logfp, "%s\n", line);
+          } else if (IS_DIGIT (ch)) {
+            fprintf (logfp, "\n%s\n", "===");
+          }
+          str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
+        }
+      }
+      fflush (logfp);
+    }
+    FileClose (fp);
+  }
+
+  sprintf (cmmd, "rm %s; rm %s; rm %s; rm %s; rm %s", path1, path2, path3, path4, path5);
+  system (cmmd);
 #endif
 }
 
@@ -862,61 +3512,1789 @@ static void DoModernizeReport (
 )
 
 {
-  CharPtr  str1, str2, str3, str4;
+  ByteStorePtr  bs = NULL, tmp = NULL;
+
+  bs = Se2Bs (sep);
 
-  str1 = Se2Str (sep);
   VisitFeaturesInSep (sep, NULL, ModGenes);
-  str2 = Se2Str (sep);
-  if (StringCmp (str1, str2) != 0) {
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "GEN %s\n", cfp->buf);
       fflush (cfp->logfp);
     }
   }
+  BSFree (bs);
+  bs = tmp;
+
   VisitFeaturesInSep (sep, NULL, ModRNAs);
-  str3 = Se2Str (sep);
-  if (StringCmp (str2, str3) != 0) {
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "NCR %s\n", cfp->buf);
       fflush (cfp->logfp);
     }
   }
+  BSFree (bs);
+  bs = tmp;
+
   VisitBioSourcesInSep (sep, NULL, ModPCRs);
-  str4 = Se2Str (sep);
-  if (StringCmp (str3, str4) != 0) {
+  tmp = Se2Bs (sep);
+  if (! BSEqual (bs, tmp)) {
     if (cfp->logfp != NULL) {
       fprintf (cfp->logfp, "PCR %s\n", cfp->buf);
       fflush (cfp->logfp);
     }
   }
+  BSFree (bs);
+  bs = tmp;
 
-  MemFree (str1);
-  MemFree (str2);
-  MemFree (str3);
-  MemFree (str4);
+  BSFree (bs);
 }
 
-static ByteStorePtr Se2Bs (
-  SeqEntryPtr sep
+static CharPtr GetLocString (
+  SeqLocPtr slp
 )
 
 {
-  AsnIoBSPtr    aibp;
-  ByteStorePtr  bs;
+  return SeqLocPrint (slp);
+}
 
-  if (sep == NULL) return NULL;
+static void DoOverlapReport (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
 
-  bs = BSNew (1000);
-  if (bs == NULL) return NULL;
-  aibp = AsnIoBSOpen ("w", bs);
-  if (aibp == NULL) return NULL;
+{
+  BioseqPtr          bsp;
+  Char               buf0 [1000], buf1 [1000], buf2 [1000];
+  CleanFlagPtr       cfp;
+  SeqMgrFeatContext  fcontext;
+  SeqFeatPtr         feat;
+  CharPtr            key, locstr1, locstr2;
+  SeqIdPtr           sip, siphead;
 
-  SeqEntryAsnWrite (sep, aibp->aip, NULL);
+  if (sfp == NULL || sfp->location == NULL || userdata == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp->logfp == NULL) return;
 
-  AsnIoFlush (aibp->aip);
-  AsnIoBSClose (aibp);
+  if (sfp->data.choice == SEQFEAT_GENE) return;
 
-  return bs;
+  bsp = BioseqFindFromSeqLoc (sfp->location);
+  if (bsp == NULL) return;
+  if (! ISA_na (bsp->mol)) return;
+
+  siphead = SeqIdSetDup (bsp->id);
+  for (sip = siphead; sip != NULL; sip = sip->next) {
+    SeqIdStripLocus (sip);
+  }
+  SeqIdWrite (siphead, buf0, PRINTID_FASTA_LONG, sizeof (buf0));
+  SeqIdSetFree (siphead);
+
+  key = FindKeyFromFeatDefType (sfp->idx.subtype, FALSE);
+  if (key == NULL) {
+    key = "?";
+  }
+
+  locstr1 = GetLocString (sfp->location);
+  if (locstr1 == NULL) {
+    locstr1 = StringSave ("?");
+  }
+
+  buf1 [0] = '\0';
+  FeatDefLabel (sfp, buf1, sizeof (buf1) - 1, OM_LABEL_BOTH);
+
+  feat = SeqMgrGetOverlappingFeature (sfp->location, FEATDEF_GENE, NULL, 0, NULL, CONTAINED_WITHIN, &fcontext);
+  if (feat != NULL) {
+    buf2 [0] = '\0';
+    FeatDefLabel (feat, buf2, sizeof (buf2) - 1, OM_LABEL_BOTH);
+    locstr2 = GetLocString (feat->location);
+    if (locstr2 == NULL) {
+      locstr2 = StringSave ("?");
+    }
+    fprintf (cfp->logfp, "%s\t%s\t%s\t%s\t%s\n", buf0, buf1, locstr1, buf2, locstr2);
+    MemFree (locstr2);
+  }
+
+  if (sfp->data.choice != SEQFEAT_CDREGION) return;
+
+  feat = SeqMgrGetOverlappingFeature (sfp->location, FEATDEF_mRNA, NULL, 0, NULL, CHECK_INTERVALS, &fcontext);
+  if (feat != NULL) {
+    buf2 [0] = '\0';
+    FeatDefLabel (feat, buf2, sizeof (buf2) - 1, OM_LABEL_BOTH);
+    locstr2 = GetLocString (feat->location);
+    if (locstr2 == NULL) {
+      locstr2 = StringSave ("?");
+    }
+    fprintf (cfp->logfp, "%s\t%s\t%s\t%s\t%s\n", buf0, buf1, locstr1, buf2, locstr2);
+    MemFree (locstr2);
+  }
+
+  MemFree (locstr1);
+}
+
+static CharPtr stopWords [] = {
+  "a",
+  "about",
+  "again",
+  "all",
+  "almost",
+  "also",
+  "although",
+  "always",
+  "among",
+  "an",
+  "and",
+  "another",
+  "any",
+  "are",
+  "as",
+  "at",
+  "be",
+  "because",
+  "been",
+  "before",
+  "being",
+  "between",
+  "both",
+  "but",
+  "by",
+  "can",
+  "could",
+  "did",
+  "do",
+  "does",
+  "done",
+  "due",
+  "during",
+  "each",
+  "either",
+  "enough",
+  "especially",
+  "etc",
+  "for",
+  "found",
+  "from",
+  "further",
+  "had",
+  "has",
+  "have",
+  "having",
+  "here",
+  "how",
+  "however",
+  "i",
+  "if",
+  "in",
+  "into",
+  "is",
+  "it",
+  "its",
+  "itself",
+  "just",
+  "kg",
+  "km",
+  "made",
+  "mainly",
+  "make",
+  "may",
+  "mg",
+  "might",
+  "ml",
+  "mm",
+  "most",
+  "mostly",
+  "must",
+  "nearly",
+  "neither",
+  "no",
+  "nor",
+  "obtained",
+  "of",
+  "often",
+  "on",
+  "our",
+  "overall",
+  "perhaps",
+  "pmid",
+  "quite",
+  "rather",
+  "really",
+  "regarding",
+  "seem",
+  "seen",
+  "several",
+  "should",
+  "show",
+  "showed",
+  "shown",
+  "shows",
+  "significantly",
+  "since",
+  "so",
+  "some",
+  "such",
+  "than",
+  "that",
+  "the",
+  "their",
+  "theirs",
+  "them",
+  "then",
+  "there",
+  "therefore",
+  "these",
+  "they",
+  "this",
+  "those",
+  "through",
+  "thus",
+  "to",
+  "upon",
+  "use",
+  "used",
+  "using",
+  "various",
+  "very",
+  "was",
+  "we",
+  "were",
+  "what",
+  "when",
+  "which",
+  "while",
+  "with",
+  "within",
+  "without",
+  "would",
+  NULL
+};
+
+static Boolean IsStopWord (
+  CharPtr str
+)
+
+{
+  Int2  i;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  for (i = 0; stopWords [i] != NULL; i++) {
+    if (StringICmp (str, stopWords [i]) == 0) return TRUE;
+  }
+
+  return FALSE;
+}
+
+static ValNodePtr GetAuthorMLNameList (
+  AuthListPtr alp
+)
+
+{
+  AuthorPtr    ap;
+  Char         buf [128];
+  Char         ch;
+  Char         chr [4];
+  ValNodePtr   head = NULL;
+  Char         initials [32];
+  ValNodePtr   last = NULL;
+  NameStdPtr   nsp;
+  PersonIdPtr  pid;
+  CharPtr      ptr;
+  CharPtr      str;
+  ValNodePtr   tmp;
+  ValNodePtr   vnp;
+
+  if (alp == NULL) return NULL;
+
+  for (vnp = alp->names; vnp != NULL; vnp = vnp->next) {
+    buf [0] = '\0';
+    initials [0] = '\0';
+    switch (alp->choice) {
+      case 1 :
+        ap = (AuthorPtr) vnp->data.ptrvalue;
+        if (ap == NULL) continue;
+        pid = ap->name;
+        if (pid == NULL) continue;
+        if (pid->choice == 2) {
+          nsp = pid->data;
+          if (nsp == NULL) continue;
+          str = nsp->names [0];
+          if (StringHasNoText (str)) continue;
+          StringNCpy_0 (buf, str, sizeof (buf));
+          StringNCpy_0 (initials, nsp->names [4], sizeof (initials));
+        }
+        break;
+      case 2 :
+      case 3 :
+        str = (CharPtr) vnp->data.ptrvalue;
+        if (StringHasNoText (str)) continue;
+        StringNCpy_0 (buf, str, sizeof (buf));
+        ptr = StringChr (buf, ',');
+        if (ptr == NULL) {
+          ptr = StringChr (buf, ' ');
+        }
+        if (ptr != NULL) {
+          *ptr = '\0';
+          ptr++;
+          StringNCpy_0 (initials, ptr, sizeof (initials));
+        }
+        break;
+      default :
+        break;
+    }
+    if (StringHasNoText (buf)) continue;
+    if (StringDoesHaveText (initials)) {
+      StringCat (buf, " ");
+      chr [1] = '\0';
+      ptr = initials;
+      ch = *ptr;
+      while (ch != '\0') {
+        if (ch != ' ' && ch != '.' && ch != ',') {
+          chr [0] = ch;
+          StringCat (buf, chr);
+        }
+        ptr++;
+        ch = *ptr;
+      }
+    }
+    TrimSpacesAroundString (buf);
+    tmp = ValNodeCopyStr (&last, 0, buf);
+    if (head == NULL) {
+      head = tmp;
+    }
+    last = tmp;
+  }
+
+  return head;
+}
+
+static ValNodePtr GetTitleWords (
+  CharPtr title
+)
+
+{
+  Char        ch;
+  Boolean     goOn = TRUE;
+  ValNodePtr  head = NULL;
+  ValNodePtr  last = NULL;
+  CharPtr     ptr;
+  CharPtr     str;
+  CharPtr     tmp;
+  ValNodePtr  vnp;
+
+  if (StringHasNoText (title)) return NULL;
+
+  tmp = StringSave (title);
+  if (tmp == NULL) return NULL;
+
+  ptr = tmp;
+  ch = *ptr;
+  if (ch == '\0') {
+    goOn = FALSE;
+  }
+  while (goOn) {
+    while (ch != '\0' && (! IS_ALPHANUM (ch))) {
+      ptr++;
+      ch = *ptr;
+    }
+    str = ptr;
+    while (ch != '\0' && IS_ALPHANUM (ch)) {
+      ptr++;
+      ch = *ptr;
+    }
+    if (ch == '\0') {
+      goOn = FALSE;
+    }
+    *ptr = '\0';
+    ptr++;
+    ch = *ptr;
+    TrimSpacesAroundString (str);
+    /*
+    if (! IsStopWord (str)) {
+      vnp = ValNodeCopyStr (&last, 0, str);
+      if (head == NULL) {
+        head = vnp;
+      }
+      last = vnp;
+    }
+    */
+    vnp = ValNodeCopyStr (&last, 0, str);
+    if (head == NULL) {
+      head = vnp;
+    }
+    last = vnp;
+  }
+
+  MemFree (tmp);
+
+  return head;
+}
+
+static ValNodePtr DuplicateStringList (
+  ValNodePtr list
+)
+
+{
+  ValNodePtr  head = NULL;
+  ValNodePtr  last = NULL;
+  CharPtr     str;
+  ValNodePtr  tmp;
+  ValNodePtr  vnp;
+
+  if (list == NULL) return NULL;
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    tmp = ValNodeCopyStr (&last, 0, str);
+    if (head == NULL) {
+      head = tmp;
+    }
+    last = tmp;
+  }
+
+  return head;
+}
+
+typedef enum {
+  FULL_INITIALS,
+  NO_HYPHENS,
+  TWO_INITIALS,
+  ONE_INITIAL,
+  NO_INITIALS
+} InitialsPolicy;
+
+static void TrimInitials (
+  CharPtr auth,
+  InitialsPolicy initials
+)
+
+{
+  Char     ch;
+  CharPtr  dst;
+  CharPtr  ptr;
+
+  if (StringHasNoText (auth)) return;
+
+  switch (initials) {
+    case FULL_INITIALS :
+      break;
+    case NO_HYPHENS :
+      dst = auth;
+      ptr = auth;
+      ch = *ptr;
+      while (ch != '\0') {
+        if (ch != '-') {
+          *dst = ch;
+          dst++;
+        }
+        ptr++;
+        ch = *ptr;
+      }
+      *dst = '\0';
+      break;
+    case TWO_INITIALS :
+      ptr = StringRChr (auth, ' ');
+      if (ptr != NULL) {
+        ptr++;
+        ch = *ptr;
+        if (IS_ALPHANUM (ch)) {
+          ptr++;
+          ch = *ptr;
+          if (IS_ALPHANUM (ch)) {
+            ptr++;
+            *ptr = '\0';
+          }
+        }
+      }
+      break;
+    case ONE_INITIAL :
+      ptr = StringRChr (auth, ' ');
+      if (ptr != NULL) {
+        ptr++;
+        ch = *ptr;
+        if (IS_ALPHANUM (ch)) {
+          ptr++;
+          *ptr = '\0';
+        }
+      }
+      break;
+    case NO_INITIALS :
+      ptr = StringRChr (auth, ' ');
+      if (ptr != NULL) {
+        *ptr = '\0';
+      }
+      break;
+    default :
+      break;
+  }
+}
+
+static Int4 DoUnpubBooleanQuery (
+  ValNodePtr authors,
+  InitialsPolicy initials,
+  Boolean firstLastOnly,
+  ValNodePtr titlewords,
+  Int2 year,
+  Boolean expand,
+  Uint4Ptr uidp
+)
+
+{
+  Boolean                 addOpAnd = FALSE;
+  Char                    buf [128];
+  Int4                    count = 0;
+  Entrez2BooleanReplyPtr  e2br;
+  Entrez2IdListPtr        e2id;
+  Entrez2RequestPtr       e2rp = NULL;
+  Entrez2ReplyPtr         e2ry;
+  CharPtr                 str;
+  ValNodePtr              vnp;
+
+  if (uidp != NULL) {
+    *uidp = 0;
+  }
+
+  e2rp = EntrezCreateBooleanRequest (TRUE, FALSE, "PubMed", NULL, 0, 0, NULL, 20, 0);
+  if (e2rp == NULL) return 0;
+
+  for (vnp = authors; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    if (firstLastOnly) {
+      if (vnp != authors && vnp->next != NULL) continue;
+    }
+    StringNCpy_0 (buf, str, sizeof (buf));
+    switch (initials) {
+      case NO_HYPHENS :
+        TrimInitials (buf, NO_HYPHENS);
+        break;
+      case TWO_INITIALS :
+        TrimInitials (buf, TWO_INITIALS);
+        break;
+      case ONE_INITIAL :
+        TrimInitials (buf, ONE_INITIAL);
+        break;
+      case NO_INITIALS :
+        TrimInitials (buf, NO_INITIALS);
+        break;
+      default :
+        break;
+    }
+    if (addOpAnd) {
+      EntrezAddToBooleanRequest (e2rp, NULL, ENTREZ_OP_AND, NULL, NULL, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+    }
+    EntrezAddToBooleanRequest (e2rp, NULL, 0, "AUTH", buf, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+    addOpAnd = TRUE;
+  }
+
+  for (vnp = titlewords; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    if (IsStopWord (str)) continue;
+    StringNCpy_0 (buf, str, sizeof (buf));
+    if (addOpAnd) {
+      EntrezAddToBooleanRequest (e2rp, NULL, ENTREZ_OP_AND, NULL, NULL, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+    }
+    EntrezAddToBooleanRequest (e2rp, NULL, 0, "TITL", buf, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+    addOpAnd = TRUE;
+  }
+
+  if (year > 0) {
+    if (addOpAnd) {
+      EntrezAddToBooleanRequest (e2rp, NULL, ENTREZ_OP_AND, NULL, NULL, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+    }
+    if (expand) {
+      EntrezAddToBooleanRequest (e2rp, NULL, ENTREZ_OP_LEFT_PAREN, NULL, NULL, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+      sprintf (buf, "%d", (int) year - 1);
+      EntrezAddToBooleanRequest (e2rp, NULL, 0, "EDAT", buf, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+      EntrezAddToBooleanRequest (e2rp, NULL, ENTREZ_OP_OR, NULL, NULL, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+      sprintf (buf, "%d", (int) year);
+      EntrezAddToBooleanRequest (e2rp, NULL, 0, "EDAT", buf, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+      EntrezAddToBooleanRequest (e2rp, NULL, ENTREZ_OP_OR, NULL, NULL, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+      sprintf (buf, "%d", (int) year + 1);
+      EntrezAddToBooleanRequest (e2rp, NULL, 0, "EDAT", buf, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+      EntrezAddToBooleanRequest (e2rp, NULL, ENTREZ_OP_RIGHT_PAREN, NULL, NULL, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+    } else {
+      sprintf (buf, "%d", (int) year);
+      EntrezAddToBooleanRequest (e2rp, NULL, 0, "EDAT", buf, NULL, 0, 0, NULL, NULL, FALSE, FALSE);
+    }
+    addOpAnd = TRUE;
+  }
+
+  e2ry = EntrezSynchronousQuery (e2rp);
+
+  e2rp = Entrez2RequestFree (e2rp);
+  if (e2ry == NULL) return 0;
+  e2br = EntrezExtractBooleanReply (e2ry);
+  if (e2br == NULL) return 0;
+
+  count = e2br->count;
+
+  if (count > 0 && uidp != NULL) {
+    e2id = e2br->uids;
+    if (e2id != NULL && e2id->num == 1 && e2id->uids != NULL) {
+      BSSeek (e2id->uids, 0, SEEK_SET);
+      *uidp = Nlm_BSGetUint4 (e2id->uids);
+    }
+  }
+
+  Entrez2BooleanReplyFree (e2br);
+
+  return count;
+}
+
+static CharPtr GetBestJournal (
+  ValNodePtr journaltitle
+)
+
+{
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (journaltitle == NULL) return NULL;
+
+  for (vnp = journaltitle; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == Cit_title_iso_jta) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      return str;
+    }
+  }
+
+  for (vnp = journaltitle; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == Cit_title_name || vnp->choice == Cit_title_jta) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      return str;
+    }
+  }
+
+  return NULL;
+}
+
+typedef struct pubref {
+  Int4        unpubcount;
+  ValNodePtr  seqids;
+  ValNodePtr  authors;
+  Boolean     firstLastOnly;
+  ValNodePtr  titlewords;
+  CharPtr     fulltitle;
+  CharPtr     uniquestr;
+  CharPtr     journal;
+  ImprintPtr  imp;
+  Int2        year;
+  Uint4       pmid;
+} PubRef, PNTR PubRefPtr;
+
+static void PrintPubAuthors (
+  CleanFlagPtr cfp,
+  PubRefPtr prp
+)
+
+{
+  CharPtr     prefix = "";
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (cfp == NULL || cfp->logfp == NULL || prp == NULL) return;
+
+  for (vnp = prp->authors; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    fprintf (cfp->logfp, "%s%s", prefix, str);
+    prefix = ", ";
+  }
+}
+
+static void PrintPubTitle (
+  CleanFlagPtr cfp,
+  PubRefPtr prp
+)
+
+{
+  CharPtr     prefix = "";
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (cfp == NULL || cfp->logfp == NULL || prp == NULL) return;
+
+  if (StringDoesHaveText (prp->fulltitle)) {
+    fprintf (cfp->logfp, "%s%s", prefix, prp->fulltitle);
+  } else {
+    for (vnp = prp->titlewords; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      fprintf (cfp->logfp, "%s%s", prefix, str);
+      prefix = " ";
+    }
+  }
+}
+
+static void PrintPubJournal (
+  CleanFlagPtr cfp,
+  PubRefPtr prp
+)
+
+{
+  DatePtr     dp = NULL;
+  ImprintPtr  imp;
+  CharPtr     prefix = "";
+  Int2        year;
+
+  if (cfp == NULL || cfp->logfp == NULL || prp == NULL) return;
+
+  if (StringHasNoText (prp->journal) && prp->imp == NULL) {
+    fprintf (cfp->logfp, "Unpublished");
+    prefix = " ";
+    if (prp->year > 0) {
+      fprintf (cfp->logfp, "%s[%d]", prefix, (int) prp->year);
+      prefix = " ";
+    }
+    return;
+  }
+
+  if (StringDoesHaveText (prp->journal)) {
+    fprintf (cfp->logfp, "%s%s", prefix, prp->journal);
+    prefix = " ";
+  }
+
+  imp = prp->imp;
+  if (imp != NULL) {
+    dp = imp->date;
+    if (dp != NULL && dp->data [0] == 1) {
+      year = (Int2) dp->data [1] + 1900;
+      fprintf (cfp->logfp, "%s[%d]", prefix, (int) year);
+      prefix = " ";
+    }
+    if (StringDoesHaveText (imp->volume)) {
+      fprintf (cfp->logfp, "%s%s", prefix, imp->volume);
+      prefix = " ";
+    }
+    /*
+    if (StringDoesHaveText (imp->issue)) {
+      fprintf (cfp->logfp, "%s(%s)", prefix, imp->issue);
+      prefix = " ";
+    }
+    */
+    if (StringDoesHaveText (imp->pages)) {
+      fprintf (cfp->logfp, "%s: %s", prefix, imp->pages);
+      prefix = " ";
+    }
+  }
+
+  if (prp->pmid > 0) {
+    fprintf (cfp->logfp, "%s<%ld>", prefix, (long) prp->pmid);
+    prefix = " ";
+  }
+}
+
+typedef enum {
+  NO_NAME_MATCH,
+  LAST_NAME_MATCH,
+  ONE_INIT_MATCH,
+  TWO_INIT_MATCH,
+  NO_HYPHEN_MATCH,
+  FULL_NAME_MATCH
+} AuthComp;
+
+static CharPtr authlabel [] = {
+  "AUTH_MISMATCH", "LAST_NAMES", "ONE_INIT", "TWO_INITS", "NO_HYPHENS", "FULL_NAMES"
+};
+
+static AuthComp AuthorCompare (
+  CharPtr auth1,
+  CharPtr auth2
+)
+
+{
+  Char  buf1 [128];
+  Char  buf2 [128];
+
+  if (StringHasNoText (auth1) || StringHasNoText (auth2)) return NO_NAME_MATCH;
+
+  StringNCpy_0 (buf1, auth1, sizeof (buf1));
+  StringNCpy_0 (buf2, auth2, sizeof (buf2));
+
+  if (StringICmp (buf1, buf2) == 0) return FULL_NAME_MATCH;
+
+  TrimInitials (buf1, NO_HYPHENS);
+  TrimInitials (buf2, NO_HYPHENS);
+
+  if (StringICmp (buf1, buf2) == 0) return NO_HYPHEN_MATCH;
+
+  TrimInitials (buf1, TWO_INITIALS);
+  TrimInitials (buf2, TWO_INITIALS);
+
+  if (StringICmp (buf1, buf2) == 0) return TWO_INIT_MATCH;
+
+  TrimInitials (buf1, ONE_INITIAL);
+  TrimInitials (buf2, ONE_INITIAL);
+
+  if (StringICmp (buf1, buf2) == 0) return ONE_INIT_MATCH;
+
+  TrimInitials (buf1, NO_INITIALS);
+  TrimInitials (buf2, NO_INITIALS);
+
+  if (StringICmp (buf1, buf2) == 0) return LAST_NAME_MATCH;
+
+  return NO_NAME_MATCH;
+}
+
+static AuthComp AuthorsIdentical (
+  ValNodePtr oldauthors,
+  ValNodePtr newauthors
+)
+
+{
+  AuthComp    curr, rsult = FULL_NAME_MATCH;
+  CharPtr     str1, str2;
+  ValNodePtr  vnp1, vnp2;
+
+  if (oldauthors == NULL || newauthors == NULL) return NO_NAME_MATCH;
+
+  for (vnp1 = oldauthors, vnp2 = newauthors;
+       vnp1 != NULL && vnp2 != NULL;
+       vnp1 = vnp1->next, vnp2 = vnp2->next) {
+    str1 = (CharPtr) vnp1->data.ptrvalue;
+    str2 = (CharPtr) vnp2->data.ptrvalue;
+    curr = AuthorCompare (str1, str2);
+    if (curr == NO_NAME_MATCH) return NO_NAME_MATCH;
+    if (curr < rsult) {
+      rsult = curr;
+    }
+  }
+
+  if (vnp1 != NULL || vnp2 != NULL) return NO_NAME_MATCH;
+
+  return rsult;
+}
+
+static AuthComp AuthorInList (
+  CharPtr author,
+  ValNodePtr newauthors
+)
+
+{
+  AuthComp    curr, rsult = FULL_NAME_MATCH;
+  Boolean     okay = FALSE;
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (StringHasNoText (author) || newauthors == NULL) return NO_NAME_MATCH;
+
+  for (vnp = newauthors; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    curr = AuthorCompare (author, str);
+    if (curr == NO_NAME_MATCH) continue;
+    okay = TRUE;
+    if (curr < rsult) {
+      rsult = curr;
+    }
+  }
+
+  if (! okay) return NO_NAME_MATCH;
+
+  return rsult;
+}
+
+static Boolean WordInList (
+  CharPtr word,
+  ValNodePtr newtitlewords
+)
+
+{
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (StringHasNoText (word) || newtitlewords == NULL) return NO_NAME_MATCH;
+
+  for (vnp = newtitlewords; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    if (StringICmp (word, str) == 0) return TRUE;
+  }
+
+  return FALSE;
+}
+
+static void PrintComparison (
+  CleanFlagPtr cfp,
+  PubRefPtr oldprp,
+  PubRefPtr newprp
+)
+
+{
+  AuthComp    authcomp, curr, best = FULL_NAME_MATCH;
+  Boolean     bothokay = TRUE, titlsame;
+  Int2        matches, newcount, oldcount;
+  CharPtr     str, str1, str2;
+  ValNodePtr  vnp;
+
+  if (cfp == NULL || cfp->logfp == NULL || oldprp == NULL || newprp == NULL) return;
+
+  authcomp = AuthorsIdentical (oldprp->authors, newprp->authors);
+  titlsame = (Boolean) (StringICmp (oldprp->fulltitle, newprp->fulltitle) == 0);
+
+  fprintf (cfp->logfp, "PMID %ld", (long) newprp->pmid);
+  fprintf (cfp->logfp, "\t");
+
+  if (oldprp->seqids != NULL) {
+    oldprp->seqids = ValNodeSort (oldprp->seqids, SortVnpByString);
+    for (vnp = oldprp->seqids; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      fprintf (cfp->logfp, "SEQID %s", str);
+      fprintf (cfp->logfp, "\t");
+    }
+  } else {
+    fprintf (cfp->logfp, "%s", cfp->buf);
+    fprintf (cfp->logfp, "\t");
+  }
+
+  /*
+  fprintf (cfp->logfp, "REF_COUNT %ld", (long) oldprp->unpubcount);
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "ORIG_NAMES %ld", (long) ValNodeLen (oldprp->authors));
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "ADDL_NAMES %ld", (long) (ValNodeLen (newprp->authors) - ValNodeLen (oldprp->authors)));
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "ORIG_WORDS %ld", (long) ValNodeLen (oldprp->titlewords));
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "ADDL_WORDS %ld", (long) (ValNodeLen (newprp->titlewords) - ValNodeLen (oldprp->titlewords)));
+  fprintf (cfp->logfp, "\t");
+  */
+
+  if (StringDoesHaveText (oldprp->uniquestr)) {
+    fprintf (cfp->logfp, "UNIQ_CIT %s", oldprp->uniquestr);
+  } else {
+    fprintf (cfp->logfp, "?");
+  }
+  fprintf (cfp->logfp, "\t");
+
+  if (authcomp != NO_NAME_MATCH) {
+    str = authlabel [(int) authcomp];
+    if (oldprp->firstLastOnly) {
+      fprintf (cfp->logfp, "AUTHORS_FIRST_LAST [%s]", str);
+    } else {
+      fprintf (cfp->logfp, "AUTHORS_SAME [%s]", str);
+    }
+    fprintf (cfp->logfp, "\t");
+  } else {
+    newcount = ValNodeLen (newprp->authors);
+    oldcount = ValNodeLen (oldprp->authors);
+
+    matches = 0;
+    for (vnp = oldprp->authors; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      curr = AuthorInList (str, newprp->authors);
+      if (curr == NO_NAME_MATCH) continue;
+      matches++;
+      if (curr < best) {
+        best = curr;
+      }
+    }
+
+    str = authlabel [(int) best];
+    if (newcount > 0 && matches == oldcount) {
+      if (oldcount < 3 && newcount > 4) {
+        fprintf (cfp->logfp, "AUTHORS_QUESTIONABLE [%s] %d -> %d ", str, (int) oldcount, (int) newcount);
+        bothokay = FALSE;
+      } else if (oldcount < newcount) {
+        fprintf (cfp->logfp, "AUTHORS_ADDED [%s] %d ", str, (int) (newcount - oldcount));
+      } else {
+        fprintf (cfp->logfp, "AUTHORS_REORDERED [%s]", str);
+      }
+    } else if (oldprp->firstLastOnly) {
+      fprintf (cfp->logfp, "AUTHORS_REMOVED [%s] %d", str, (int) matches);
+      bothokay = FALSE;
+    } else {
+      fprintf (cfp->logfp, "AUTHORS_CHANGED [%s] %d / %d", str, (int) matches, (int) newcount);
+      bothokay = FALSE;
+    }
+    fprintf (cfp->logfp, "\t");
+  }
+
+  if (titlsame) {
+    fprintf (cfp->logfp, "TITLE_SAME [IDENTICAL]");
+  } else {
+    newcount = 0;
+    oldcount = 0;
+    matches = 0;
+
+    for (vnp = newprp->titlewords; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      if (IsStopWord (str)) continue;
+      newcount++;
+    }
+
+    for (vnp = oldprp->titlewords; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      if (IsStopWord (str)) continue;
+      oldcount++;
+      if (! WordInList (str, newprp->titlewords)) continue;
+      matches++;
+    }
+
+    str1 = NULL;
+    str2 = NULL;
+    vnp = oldprp->titlewords;
+    if (vnp != NULL) {
+      str1 = (CharPtr) vnp->data.ptrvalue;
+      while (StringDoesHaveText (str1) && IsStopWord (str1) && vnp != NULL) {
+        vnp = vnp->next;
+        str1 = (CharPtr) vnp->data.ptrvalue;
+      }
+    }
+    vnp = newprp->titlewords;
+    if (vnp != NULL) {
+      str2 = (CharPtr) vnp->data.ptrvalue;
+      while (StringDoesHaveText (str2) && IsStopWord (str2) && vnp != NULL) {
+        vnp = vnp->next;
+        str2 = (CharPtr) vnp->data.ptrvalue;
+      }
+    }
+
+    if (oldcount < 3 && newcount > 4) {
+      fprintf (cfp->logfp, "TITLE_QUESTIONABLE %d -> %d", (int) oldcount, (int) newcount);
+      bothokay = FALSE;
+    } else if (StringDoesHaveText (str1) && StringDoesHaveText (str2) &&
+        StringICmp (str1, str2) == 0 && newcount > 0 && matches == newcount) {
+      fprintf (cfp->logfp, "TITLE_SAME [SIMILAR] %d", (int) matches);
+    } else if (newcount > 0 && matches == newcount) {
+      fprintf (cfp->logfp, "TITLE_ALTERED %d", (int) matches);
+      bothokay = FALSE;
+    } else {
+      fprintf (cfp->logfp, "TITLE_DIFFERS %d / %d", (int) matches, (int) newcount);
+      bothokay = FALSE;
+    }
+  }
+  fprintf (cfp->logfp, "\t");
+
+  if (bothokay) {
+    fprintf (cfp->logfp, "PROBABLE");
+  } else {
+    fprintf (cfp->logfp, "POSSIBLE");
+  }
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "OLD_AUTH ");
+  PrintPubAuthors (cfp, oldprp);
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "NEW_AUTH ");
+  PrintPubAuthors (cfp, newprp);
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "OLD_TITL ");
+  PrintPubTitle (cfp, oldprp);
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "NEW_TITL ");
+  PrintPubTitle (cfp, newprp);
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "OLD_JOUR ");
+  PrintPubJournal (cfp, oldprp);
+  fprintf (cfp->logfp, "\t");
+
+  fprintf (cfp->logfp, "NEW_JOUR ");
+  PrintPubJournal (cfp, newprp);
+
+  fprintf (cfp->logfp, "\n");
+}
+
+static void StrStripSpaces (
+  CharPtr str
+)
+
+{
+  CharPtr  new_str;
+
+  if (str == NULL) return;
+
+  new_str = str;
+  while (*str != '\0') {
+    *new_str++ = *str;
+    if (*str == ' ' || *str == '\t' || *str == '(') {
+      for (str++; *str == ' ' || *str == '\t'; str++) continue;
+      if (*str == ')' || *str == ',') {
+        new_str--;
+      }
+    } else {
+      str++;
+    }
+  }
+  *new_str = '\0';
+}
+
+static void StrStripBrackets (
+  CharPtr str
+)
+
+{
+  size_t  len;
+
+  if (str == NULL) return;
+
+  len = StringLen (str);
+  if (len < 2) return;
+
+  if (str [0] == '[') {
+    str [0] = ' ';
+  }
+
+  if (str [len - 1] == ']') {
+    str [len - 1] = ' ';
+  }
+}
+
+static void PrintPubMedCit (
+  CleanFlagPtr cfp,
+  Uint4 pmid,
+  PubRefPtr oldprp
+)
+
+{
+  CitArtPtr        cap;
+  CitJourPtr       cjp;
+  DatePtr          dp;
+  ImprintPtr       imp;
+  MedlineEntryPtr  mep;
+  PubmedEntryPtr   pep;
+  PubRef           pr;
+  CharPtr          str;
+  CharPtr          tmp;
+  ValNodePtr       vnp;
+
+  if (cfp == NULL || cfp->logfp == NULL || pmid < 1) return;
+
+  MemSet ((Pointer) &pr, 0, sizeof (PubRef));
+
+  pep = PubMedSynchronousQuery (pmid);
+  if (pep == NULL) return;
+
+  mep = (MedlineEntryPtr) pep->medent;
+  if (mep != NULL && mep->cit != NULL) {
+    cap = mep->cit;
+    if (cap != NULL) {
+      pr.authors = GetAuthorMLNameList (cap->authors);
+      for (vnp = cap->title; vnp != NULL; vnp = vnp->next) {
+        if (vnp->choice == Cit_title_name) {
+          str = (CharPtr) vnp->data.ptrvalue;
+          if (StringHasNoText (str)) continue;
+          pr.titlewords = GetTitleWords (str);
+          tmp = StringSave (str);
+          TrimSpacesAndJunkFromEnds (tmp, TRUE);
+          s_RemovePeriodFromEnd (tmp);
+          StrStripBrackets (tmp);
+          StrStripSpaces (tmp);
+          TrimSpacesAroundString (tmp);
+          pr.fulltitle = tmp;
+        }
+      }
+      if (cap->from == 1) {
+        cjp = (CitJourPtr) cap->fromptr;
+        if (cjp != NULL) {
+          pr.journal = GetBestJournal (cjp->title);
+          imp = cjp->imp;
+          pr.imp = imp;
+          if (imp != NULL) {
+            dp = imp->date;
+            if (dp != NULL && dp->data [0] == 1) {
+              pr.year = (Int2) dp->data [1] + 1900;
+            }
+          }
+        }
+      }
+      pr.pmid = pmid;
+      if (pr.authors != NULL && pr.titlewords != NULL) {
+        PrintComparison (cfp, oldprp, &pr);
+      }
+      ValNodeFreeData (pr.authors);
+      ValNodeFreeData (pr.titlewords);
+      MemFree (pr.fulltitle);
+    }
+  }
+
+  pep = PubmedEntryFree (pep);
+}
+
+static void TryEntrezQueries (
+  CleanFlagPtr cfp,
+  PubRefPtr prp
+)
+
+{
+  Int4        count;
+  Uint4       pmid = 0;
+  CharPtr     str;
+  ValNodePtr  vnp;
+
+  if (cfp == NULL || cfp->logfp == NULL || prp == NULL || prp->authors == NULL) return;
+
+  count = DoUnpubBooleanQuery (prp->authors, ONE_INITIAL, FALSE, prp->titlewords, prp->year, TRUE, &pmid);
+
+  if (count > 1) {
+    count = DoUnpubBooleanQuery (prp->authors, TWO_INITIALS, FALSE, prp->titlewords, prp->year, TRUE, &pmid);
+  }
+
+  if (count < 1) {
+    count = DoUnpubBooleanQuery (prp->authors, ONE_INITIAL, TRUE, prp->titlewords, prp->year, TRUE, &pmid);
+    if (count == 1) {
+      prp->firstLastOnly = TRUE;
+    }
+  }
+
+  if (count < 1) {
+
+    if (prp->seqids != NULL) {
+      fprintf (cfp->logfp, "0\t");
+      for (vnp = prp->seqids; vnp != NULL; vnp = vnp->next) {
+        str = (CharPtr) vnp->data.ptrvalue;
+        if (StringHasNoText (str)) continue;
+        fprintf (cfp->logfp, "SEQID %s", str);
+        fprintf (cfp->logfp, "\t");
+      }
+      fprintf (cfp->logfp, "UNPUB\t");
+    } else {
+      fprintf (cfp->logfp, "0\t%s\tUNPUB\t", cfp->buf);
+    }
+
+    PrintPubAuthors (cfp, prp);
+    fprintf (cfp->logfp, "\t");
+    PrintPubTitle (cfp, prp);
+    fprintf (cfp->logfp, "\t");
+    PrintPubJournal (cfp, prp);
+    fprintf (cfp->logfp, "\n");
+
+  } else if (count > 1) {
+
+    if (prp->seqids != NULL) {
+      fprintf (cfp->logfp, "0\t");
+      for (vnp = prp->seqids; vnp != NULL; vnp = vnp->next) {
+        str = (CharPtr) vnp->data.ptrvalue;
+        if (StringHasNoText (str)) continue;
+        fprintf (cfp->logfp, "SEQID %s", str);
+        fprintf (cfp->logfp, "\t");
+      }
+      fprintf (cfp->logfp, "COUNT %ld\t", (long) count);
+    } else {
+      fprintf (cfp->logfp, "0\t%s\tCOUNT %ld\t", cfp->buf, (long) count);
+    }
+
+    PrintPubAuthors (cfp, prp);
+    fprintf (cfp->logfp, "\t");
+    PrintPubTitle (cfp, prp);
+    fprintf (cfp->logfp, "\t");
+    PrintPubJournal (cfp, prp);
+    fprintf (cfp->logfp, "\n");
+
+  } else {
+
+    PrintPubMedCit (cfp, pmid, prp);
+  }
+
+  fflush (cfp->logfp);
+}
+
+static void CountUnpubPub (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  CleanFlagPtr  cfp;
+  CitGenPtr     cgp = NULL;
+  Boolean       hasUnpublished = FALSE;
+  ValNodePtr    vnp;
+
+  if (pdp == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Gen) {
+      cgp = (CitGenPtr) vnp->data.ptrvalue;
+      if (cgp != NULL) {
+        if (StringICmp (cgp->cit, "Unpublished") == 0) {
+          if (StringICmp (cgp->title, "Direct Submission") != 0) {
+            hasUnpublished = TRUE;
+          }
+        }
+      }
+    } else if (vnp->choice == PUB_Muid || vnp->choice == PUB_PMid) {
+      return;
+    } else if (vnp->choice == PUB_Article || vnp->choice == PUB_Book || vnp->choice == PUB_Man) {
+      return;
+    }
+  }
+
+  if (! hasUnpublished) return;
+  if (cgp == NULL) return;
+
+  (cfp->unpubcount)++;
+}
+
+static void ProcessUnpubPub (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  AuthListPtr   authors = NULL;
+  Char          buf [521];
+  CitArtPtr     cap = NULL;
+  CleanFlagPtr  cfp;
+  CitGenPtr     cgp = NULL;
+  CitJourPtr    cjp;
+  DatePtr       dp = NULL;
+  Boolean       hasUnpublished = FALSE;
+  ImprintPtr    imp;
+  CharPtr       journal = NULL;
+  PubRef        pr;
+  CharPtr       str;
+  CharPtr       title = NULL;
+  CharPtr       tmp;
+  ValNodePtr    vnp, vnpcgp = NULL;
+  Int2          year = 0;
+
+  if (pdp == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Gen) {
+      cgp = (CitGenPtr) vnp->data.ptrvalue;
+      if (cgp != NULL) {
+        if (StringICmp (cgp->cit, "Unpublished") == 0) {
+          if (StringICmp (cgp->title, "Direct Submission") != 0) {
+            hasUnpublished = TRUE;
+            vnpcgp = vnp;
+            authors = cgp->authors;
+            title = cgp->title;
+            journal = GetBestJournal (cgp->journal);
+            dp = cgp->date;
+          }
+        }
+      }
+    } else if (vnp->choice == PUB_Muid || vnp->choice == PUB_PMid) {
+      return;
+    } else if (vnp->choice == PUB_Article) {
+      cap = (CitArtPtr) vnp->data.ptrvalue;
+      if (cap != NULL) {
+        if (cap->from == 1) {
+          cjp = (CitJourPtr) cap->fromptr;
+          if (cjp != NULL) {
+            imp = cjp->imp;
+            if (imp != NULL) {
+              if (imp->prepub == 2 || imp->pubstatus == PUBSTATUS_aheadofprint) {
+                hasUnpublished = TRUE;
+                vnpcgp = vnp;
+                authors = cap->authors;
+                for (vnp = cap->title; vnp != NULL; vnp = vnp->next) {
+                  if (vnp->choice != Cit_title_name) continue;
+                  str = (CharPtr) vnp->data.ptrvalue;
+                  if (StringHasNoText (str)) continue;
+                  title = str;
+                }
+                journal = GetBestJournal (cjp->title);
+                dp = imp->date;
+              }
+            }
+          }
+        }
+      }
+    } else if (vnp->choice == PUB_Book || vnp->choice == PUB_Man) {
+      return;
+    }
+  }
+
+  if (! hasUnpublished) return;
+
+  MemSet ((Pointer) &pr, 0, sizeof (PubRef));
+
+  pr.unpubcount = cfp->unpubcount;
+
+  pr.seqids = ValNodeCopyStr (NULL, 0, cfp->buf);
+
+  pr.authors = GetAuthorMLNameList (authors);
+  pr.titlewords = GetTitleWords (title);
+  if (vnpcgp != NULL) {
+    if (PubLabelUnique (vnpcgp, buf, sizeof (buf) - 1, OM_LABEL_CONTENT, TRUE) > 0) {
+      pr.uniquestr = StringSaveNoNull (buf);
+    }
+  }
+
+  tmp = StringSave (title);
+  TrimSpacesAndJunkFromEnds (tmp, TRUE);
+  s_RemovePeriodFromEnd (tmp);
+  StrStripBrackets (tmp);
+  StrStripSpaces (tmp);
+  TrimSpacesAroundString (tmp);
+  pr.fulltitle = tmp;
+
+  pr.journal = journal;
+  pr.imp = NULL;
+
+  if (dp != NULL && dp->data [0] == 1) {
+    year = (Int2) dp->data [1] + 1900;
+  }
+  if (year == 0) {
+    year = cfp->year;
+  }
+  pr.year = year;
+  pr.pmid = 0;
+
+  if (pr.authors != NULL && pr.titlewords != NULL) {
+    TryEntrezQueries (cfp, &pr);
+  }
+
+  ValNodeFreeData (pr.seqids);
+  ValNodeFreeData (pr.authors);
+  ValNodeFreeData (pr.titlewords);
+  MemFree (pr.fulltitle);
+  MemFree (pr.uniquestr);
+}
+
+static void DoUnpublishedReport (
+  SeqEntryPtr sep,
+  CleanFlagPtr cfp
+)
+
+{
+   if (sep == NULL || cfp == NULL) return;
+
+  cfp->unpubcount = 0;
+  cfp->unpublist = NULL;
+  cfp->lastunpub = NULL;
+  VisitPubdescsInSep (sep, (Pointer) cfp, CountUnpubPub);
+  VisitPubdescsInSep (sep, (Pointer) cfp, ProcessUnpubPub);
+}
+
+static void CreateUnpubList (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  AuthComp      authcomp;
+  AuthListPtr   authors = NULL;
+  Char          buf [521];
+  CitArtPtr     cap = NULL;
+  CleanFlagPtr  cfp;
+  CitGenPtr     cgp = NULL;
+  CitJourPtr    cjp;
+  PubRefPtr     curr, prp;
+  DatePtr       dp = NULL;
+  Boolean       hasUnpublished = FALSE;
+  ImprintPtr    imp;
+  CharPtr       journal = NULL;
+  CharPtr       str, tmp;
+  CharPtr       title = NULL;
+  Boolean       titlsame, uniqsame;
+  ValNodePtr    vnp, vnpx, vnpy, vnpcgp = NULL;
+  Int2          year = 0;
+
+  if (pdp == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Gen) {
+      cgp = (CitGenPtr) vnp->data.ptrvalue;
+      if (cgp != NULL) {
+        if (StringICmp (cgp->cit, "Unpublished") == 0) {
+          if (StringICmp (cgp->title, "Direct Submission") != 0) {
+            hasUnpublished = TRUE;
+            vnpcgp = vnp;
+            authors = cgp->authors;
+            title = cgp->title;
+            journal = GetBestJournal (cgp->journal);
+            dp = cgp->date;
+          }
+        }
+      }
+    } else if (vnp->choice == PUB_Article) {
+      cap = (CitArtPtr) vnp->data.ptrvalue;
+      if (cap != NULL) {
+        if (cap->from == 1) {
+          cjp = (CitJourPtr) cap->fromptr;
+          if (cjp != NULL) {
+            imp = cjp->imp;
+            if (imp != NULL) {
+              if (imp->prepub == 2 || imp->pubstatus == PUBSTATUS_aheadofprint) {
+                hasUnpublished = TRUE;
+                vnpcgp = vnp;
+                authors = cap->authors;
+                for (vnpy = cap->title; vnpy != NULL; vnpy = vnpy->next) {
+                  if (vnpy->choice != Cit_title_name) continue;
+                  str = (CharPtr) vnpy->data.ptrvalue;
+                  if (StringHasNoText (str)) continue;
+                  title = str;
+                }
+                journal = GetBestJournal (cjp->title);
+                dp = imp->date;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (! hasUnpublished) return;
+
+  prp = (PubRefPtr) MemNew (sizeof (PubRef));
+  if (prp == NULL) return;
+
+  prp->unpubcount = cfp->unpubcount;
+
+  prp->seqids = ValNodeCopyStr (NULL, 0, cfp->buf);
+
+  prp->authors = GetAuthorMLNameList (authors);
+  prp->titlewords = GetTitleWords (title);
+  if (vnpcgp != NULL) {
+    if (PubLabelUnique (vnpcgp, buf, sizeof (buf) - 1, OM_LABEL_CONTENT, TRUE) > 0) {
+      prp->uniquestr = StringSaveNoNull (buf);
+    }
+  }
+
+  tmp = StringSave (title);
+  TrimSpacesAndJunkFromEnds (tmp, TRUE);
+  s_RemovePeriodFromEnd (tmp);
+  StrStripBrackets (tmp);
+  StrStripSpaces (tmp);
+  TrimSpacesAroundString (tmp);
+  prp->fulltitle = tmp;
+
+  prp->journal = journal;
+  prp->imp = NULL;
+
+  if (dp != NULL && dp->data [0] == 1) {
+    year = (Int2) dp->data [1] + 1900;
+  }
+  if (year == 0) {
+    year = cfp->year;
+  }
+  prp->year = year;
+  prp->pmid = 0;
+
+  for (vnp = cfp->unpublist; vnp != NULL; vnp = vnp->next) {
+    curr = (PubRefPtr) vnp->data.ptrvalue;
+    if (curr == NULL) continue;
+
+    authcomp = AuthorsIdentical (prp->authors, curr->authors);
+    titlsame = (Boolean) (StringICmp (prp->fulltitle, curr->fulltitle) == 0);
+    uniqsame = (Boolean) (StringICmp (prp->uniquestr, curr->uniquestr) == 0);
+
+    if (authcomp == FULL_NAME_MATCH && titlsame && uniqsame) {
+      for (vnpx = curr->seqids; vnpx != NULL; vnpx = vnpx->next) {
+        str = (CharPtr) vnpx->data.ptrvalue;
+        if (str == NULL) continue;
+        if (StringCmp (str, cfp->buf) == 0) {
+          ValNodeFreeData (prp->seqids);
+          ValNodeFreeData (prp->authors);
+          ValNodeFreeData (prp->titlewords);
+          MemFree (prp->fulltitle);
+          MemFree (prp->uniquestr);
+          MemFree (prp);
+          return;
+        }
+      }
+
+      ValNodeCopyStr (&(curr->seqids), 0, cfp->buf);
+      ValNodeFreeData (prp->seqids);
+      ValNodeFreeData (prp->authors);
+      ValNodeFreeData (prp->titlewords);
+      MemFree (prp->fulltitle);
+      MemFree (prp->uniquestr);
+      MemFree (prp);
+      return;
+    }
+  }
+
+  vnp = ValNodeAddPointer (&(cfp->lastunpub), 0, (Pointer) prp);
+  if (cfp->unpublist == NULL) {
+    cfp->unpublist = vnp;
+  }
+  cfp->lastunpub = vnp;
+}
+
+static void DoUnpublishedList (
+  SeqEntryPtr sep,
+  CleanFlagPtr cfp
+)
+
+{
+  if (sep == NULL || cfp == NULL) return;
+
+  cfp->unpubcount = 0;
+  VisitPubdescsInSep (sep, (Pointer) cfp, CountUnpubPub);
+  VisitPubdescsInSep (sep, (Pointer) cfp, CreateUnpubList);
+}
+
+static void FinishUnpublishedList (
+  CleanFlagPtr cfp
+)
+
+{
+  PubRefPtr   prp;
+  ValNodePtr  vnp;
+
+  if (cfp == NULL) return;
+
+  for (vnp = cfp->unpublist; vnp != NULL; vnp = vnp->next) {
+    prp = (PubRefPtr) vnp->data.ptrvalue;
+    if (prp == NULL) continue;
+    if (prp->authors != NULL && prp->titlewords != NULL) {
+      TryEntrezQueries (cfp, prp);
+    }
+  }
+
+  for (vnp = cfp->unpublist; vnp != NULL; vnp = vnp->next) {
+    prp = (PubRefPtr) vnp->data.ptrvalue;
+    if (prp == NULL) continue;
+    ValNodeFreeData (prp->seqids);
+    ValNodeFreeData (prp->authors);
+    ValNodeFreeData (prp->titlewords);
+    MemFree (prp->fulltitle);
+    MemFree (prp->uniquestr);
+    MemFree (prp);
+  }
+  ValNodeFree (cfp->unpublist);
+}
+
+static void CountPublishedPub (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  CleanFlagPtr  cfp;
+  CitArtPtr     cap = NULL;
+  ValNodePtr    vnp;
+
+  if (pdp == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Article) {
+      cap = (CitArtPtr) vnp->data.ptrvalue;
+    } else if (vnp->choice == PUB_PMid) {
+      return;
+    }
+  }
+
+  if (cap == NULL) return;
+
+  (cfp->unpubcount)++;
+}
+
+static void ProcessPublishedPub (
+  PubdescPtr pdp,
+  Pointer userdata
+)
+
+{
+  CleanFlagPtr  cfp;
+  CitArtPtr     cap = NULL;
+  CitJourPtr    cjp;
+  DatePtr       dp = NULL;
+  ImprintPtr    imp;
+  PubRef        pr;
+  CharPtr       str;
+  CharPtr       tmp;
+  ValNodePtr    vnp;
+  Int2          year = 0;
+
+  if (pdp == NULL) return;
+  cfp = (CleanFlagPtr) userdata;
+  if (cfp == NULL) return;
+
+  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Article) {
+      cap = (CitArtPtr) vnp->data.ptrvalue;
+    } else if (vnp->choice == PUB_PMid) {
+      return;
+    }
+  }
+
+  if (cap == NULL) return;
+
+  MemSet ((Pointer) &pr, 0, sizeof (PubRef));
+
+  pr.seqids = ValNodeCopyStr (NULL, 0, cfp->buf);
+
+  pr.authors = GetAuthorMLNameList (cap->authors);
+  for (vnp = cap->title; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == Cit_title_name) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      pr.titlewords = GetTitleWords (str);
+      tmp = StringSave (str);
+      TrimSpacesAndJunkFromEnds (tmp, TRUE);
+      s_RemovePeriodFromEnd (tmp);
+      StrStripBrackets (tmp);
+      StrStripSpaces (tmp);
+      TrimSpacesAroundString (tmp);
+      pr.fulltitle = tmp;
+    }
+  }
+
+  if (cap->from == 1) {
+    cjp = (CitJourPtr) cap->fromptr;
+    if (cjp != NULL) {
+      pr.journal = GetBestJournal (cjp->title);
+      imp = cjp->imp;
+      pr.imp = imp;
+      if (imp != NULL) {
+        dp = imp->date;
+        if (dp != NULL && dp->data [0] == 1) {
+          year = (Int2) dp->data [1] + 1900;
+        }
+      }
+    }
+  }
+
+  if (year == 0) {
+    year = cfp->year;
+  }
+  pr.year = year;
+  pr.pmid = 0;
+
+  if (pr.authors != NULL && pr.titlewords != NULL) {
+    TryEntrezQueries (cfp, &pr);
+  }
+
+  ValNodeFreeData (pr.seqids);
+  ValNodeFreeData (pr.authors);
+  ValNodeFreeData (pr.titlewords);
+  MemFree (pr.fulltitle);
+}
+
+static void DoPublishedReport (
+  SeqEntryPtr sep,
+  CleanFlagPtr cfp
+)
+
+{
+  if (sep == NULL || cfp == NULL) return;
+
+  cfp->unpubcount = 0;
+  cfp->unpublist = NULL;
+  cfp->lastunpub = NULL;
+  VisitPubdescsInSep (sep, (Pointer) cfp, CountPublishedPub);
+  VisitPubdescsInSep (sep, (Pointer) cfp, ProcessPublishedPub);
 }
 
 static void RemoveFeatureCitations (
@@ -939,7 +5317,7 @@ static SeqEntryPtr CppBasicCleanup (
 {
   AsnIoPtr      aip, aop;
   ByteStorePtr  bs1, bs2;
-  Char          cmmd [256];
+  Char          cmmd [512];
   SeqEntryPtr   csep, nsep;
   Char          path1 [PATH_MAX];
   Char          path2 [PATH_MAX];
@@ -1014,6 +5392,60 @@ static SeqEntryPtr CppBasicCleanup (
 }
 #endif
 
+/* now only strips serials for local, general, refseq, and 2+6 genbank ids */
+static void CheckForSwissProtIDX (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+  BioseqPtr     bsp;
+  SeqIdPtr      sip;
+  BoolPtr       stripSerial;
+  TextSeqIdPtr  tsip;
+
+  if (sep == NULL) return;
+  if (IS_Bioseq (sep)) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    if (bsp == NULL) return;
+    stripSerial = (BoolPtr) mydata;
+    if (stripSerial == NULL) return;
+    for (sip = bsp->id; sip != NULL; sip = sip->next) {
+      switch (sip->choice) {
+        case SEQID_GIBBSQ :
+        case SEQID_GIBBMT :
+          *stripSerial = FALSE;
+          break;
+        case SEQID_EMBL :
+        case SEQID_PIR :
+        case SEQID_SWISSPROT :
+        case SEQID_PATENT :
+        case SEQID_DDBJ :
+        case SEQID_PRF :
+        case SEQID_PDB :
+        case SEQID_TPE:
+        case SEQID_TPD:
+        case SEQID_GPIPE:
+          *stripSerial = FALSE;
+          break;
+        case SEQID_GENBANK :
+        case SEQID_TPG:
+          tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+          if (tsip != NULL) {
+            if (StringLen (tsip->accession) == 6) {
+              *stripSerial = FALSE;
+            }
+          }
+          break;
+        case SEQID_NOT_SET :
+        case SEQID_LOCAL :
+        case SEQID_OTHER :
+        case SEQID_GENERAL :
+          break;
+        default :
+          break;
+      }
+    }
+  }
+}
+
 static time_t DoCleanup (
   SeqEntryPtr sep,
   Uint2 entityID,
@@ -1024,17 +5456,36 @@ static time_t DoCleanup (
 )
 
 {
+  Boolean              all_digits = TRUE, isDdbj = FALSE, isEmbl = FALSE,
+                       isGenBank = FALSE, isNcbi = FALSE, isRefSeq = FALSE,
+                       stripSerial = TRUE;
   BioseqPtr    bsp;
+  Char                 ch;
+  DatePtr              dp;
   SeqEntryPtr  fsep, nsep = NULL;
+  Int4                 nucs, prts, pmid = 0;
+  CharPtr              ptr;
+  SumDataPtr           sdp;
   SeqIdPtr     sip, siphead;
   time_t       starttime, stoptime;
+  long int             val;
+  SeqDescrPtr          vnp;
+  PopSetRetroStatData  stat;
 
   if (sep == NULL || cfp == NULL) return 0;
 
+  MemSet ((Pointer) &stat, 0, sizeof (PopSetRetroStatData));
+
+  AssignIDsInEntityEx (entityID, 0, NULL, NULL);
+
   starttime = GetSecs ();
 
   StringCpy (cfp->buf, "");
   cfp->gi = 0;
+  cfp->year = 0;
+  cfp->isRefSeq = FALSE;
+  cfp->isEmblDdbj = FALSE;
+
   fsep = FindNthBioseq (sep, 1);
   if (fsep != NULL && fsep->choice == 1) {
     bsp = (BioseqPtr) fsep->data.ptrvalue;
@@ -1044,20 +5495,127 @@ static time_t DoCleanup (
         SeqIdStripLocus (sip);
         if (sip->choice == SEQID_GI) {
           cfp->gi = (Int4) sip->data.intvalue;
+        } else if (sip->choice == SEQID_GENBANK || sip->choice == SEQID_TPG) {
+          isGenBank = TRUE;
+          isNcbi = TRUE;
+        } else if (sip->choice == SEQID_EMBL || sip->choice == SEQID_TPE) {
+          isEmbl = TRUE;
+          cfp->isEmblDdbj = TRUE;
+        } else if (sip->choice == SEQID_DDBJ || sip->choice == SEQID_TPD) {
+          isDdbj = TRUE;
+          cfp->isEmblDdbj = TRUE;
+        } else if (sip->choice == SEQID_OTHER) {
+          isRefSeq = TRUE;
+          isNcbi = TRUE;
+          cfp->isRefSeq = TRUE;
         }
       }
       SeqIdWrite (siphead, cfp->buf, PRINTID_FASTA_LONG, sizeof (cfp->buf));
       SeqIdSetFree (siphead);
     }
+    vnp = GetNextDescriptorUnindexed (bsp, Seq_descr_update_date, NULL);
+    if (vnp == NULL) {
+      vnp = GetNextDescriptorUnindexed (bsp, Seq_descr_create_date, NULL);
+    }
+    if (vnp != NULL) {
+      dp = (DatePtr) vnp->data.ptrvalue;
+      if (dp != NULL && dp->data [0] == 1) {
+        cfp->year = (Int2) dp->data [1] + 1900;
+      }
+    }
+  }
+
+  SeqEntryExplore (sep, (Pointer) &stripSerial, CheckForSwissProtIDX);
+  cfp->stripSerial = stripSerial;
+
+  if (StringDoesHaveText (cfp->sourcedb)) {
+    if (StringChr (cfp->sourcedb, 'g') != NULL) {
+      if (! isGenBank) return 0;
+    }
+    if (StringChr (cfp->sourcedb, 'e') != NULL) {
+      if (! isEmbl) return 0;
+    }
+    if (StringChr (cfp->sourcedb, 'd') != NULL) {
+      if (! isDdbj) return 0;
+    }
+    if (StringChr (cfp->sourcedb, 'r') != NULL) {
+      if (! isRefSeq) return 0;
+    }
+    if (StringChr (cfp->sourcedb, 'n') != NULL) {
+      if (! isNcbi) return 0;
+    }
+    if (StringChr (cfp->sourcedb, 'x') != NULL) {
+      if (isEmbl || isDdbj) return 0;
+    }
   }
 
+  nucs = VisitSequencesInSep (sep, NULL, VISIT_NUCS, NULL);
+  prts = VisitSequencesInSep (sep, NULL, VISIT_PROTS, NULL);
+  cfp->rawcounts.nucs += nucs;
+  cfp->rawcounts.prts += prts;
+  (cfp->rawcounts.recs)++;
+  cfp->cumcounts.nucs += nucs;
+  cfp->cumcounts.prts += prts;
+  (cfp->cumcounts.recs)++;
+
+  sdp = NULL;
+  if (isGenBank) {
+    sdp = &(cfp->dbsums.genbank);
+  } else if (isEmbl) {
+    sdp = &(cfp->dbsums.embl);
+  } else if (isDdbj) {
+    sdp = &(cfp->dbsums.ddbj);
+  } else if (isRefSeq) {
+    sdp = &(cfp->dbsums.refseq);
+  } else {
+    sdp = &(cfp->dbsums.other);
+  }
+  if (sdp != NULL) {
+    sdp->nucs += nucs;
+    sdp->prts += prts;
+    (sdp->recs)++;
+  }
+
+  if (StringChr (cfp->report, 'c') != NULL) {
+    return 0;
+  }
   if (StringChr (cfp->report, 'r') != NULL) {
-    DoASNReport (sep, cfp);
+    DoASNReport (sep, cfp, FALSE, FALSE, FALSE);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 's') != NULL) {
+    DoASNReport (sep, cfp, TRUE, FALSE, FALSE);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'n') != NULL) {
+    DoASNReport (sep, cfp, TRUE, TRUE, FALSE);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'e') != NULL) {
+    DoASNReport (sep, cfp, FALSE, FALSE, TRUE);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'd') != NULL) {
+    DoAsnDiffReport (sep, cfp);
     stoptime = GetSecs ();
     return stoptime - starttime;
   }
   if (StringChr (cfp->report, 'g') != NULL) {
-    DoGBFFReport (sep, cfp);
+    DoGBFFReport (sep, cfp, 1);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'f') != NULL) {
+    DoGBFFReport (sep, cfp, 2);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'v') != NULL) {
+    DoValidatorReport (sep, cfp->logfp, cfp->buf, cfp->asnval);
     stoptime = GetSecs ();
     return stoptime - starttime;
   }
@@ -1066,12 +5624,58 @@ static time_t DoCleanup (
     stoptime = GetSecs ();
     return stoptime - starttime;
   }
+  if (StringChr (cfp->report, 'o') != NULL) {
+    SeqMgrIndexFeatures (entityID, 0);
+    VisitFeaturesInSep (sep, (Pointer) cfp, DoOverlapReport);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'u') != NULL) {
+    DoUnpublishedList (sep, cfp);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'p') != NULL) {
+    DoPublishedReport (sep, cfp);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+  if (StringChr (cfp->report, 'x') != NULL) {
+    DoASNScan (sep, cfp);
+    stoptime = GetSecs ();
+    return stoptime - starttime;
+  }
+
+  if (StringDoesHaveText (cfp->report)) return 0;
 
   if (cfp->logfp != NULL) {
     fprintf (cfp->logfp, "%s\n", cfp->buf);
     fflush (cfp->logfp);
   }
 
+  if (cfp->taxon) {
+    Taxon3ReplaceOrgInSeqEntry (sep, FALSE);
+  }
+
+  if (StringChr (cfp->pub, 'u') != NULL) {
+    VisitPubdescsInSep (sep, NULL, LookupPubdesc);
+  }
+  if (cfp->pub != NULL) {
+    ptr = cfp->pub;
+    ch = *ptr;
+    while (ch != '\0') {
+      if (! IS_DIGIT (ch)) {
+        all_digits = FALSE;
+      }
+      ptr++;
+      ch = *ptr;
+    }
+    if (all_digits && sscanf (cfp->pub, "%ld", &val) == 1 && val != 0) {
+      pmid = (Int4) val;
+      VisitPubdescsInSep (sep, (Pointer) &pmid, ReplaceUnpub);
+    }
+  }
+
   if (StringChr (cfp->clean, 'b') != NULL) {
     BasicSeqEntryCleanup (sep);
   }
@@ -1092,6 +5696,9 @@ static time_t DoCleanup (
   if (StringChr (cfp->clean, 'u') != NULL) {
     RemoveAllNcbiCleanupUserObjects (sep);
   }
+  if (StringChr (cfp->clean, 'c') != NULL) {
+    CorrectGenCodes (sep, entityID);
+  }
 
   if (StringChr (cfp->modernize, 'g') != NULL) {
     VisitFeaturesInSep (sep, NULL, ModGenes);
@@ -1103,12 +5710,15 @@ static time_t DoCleanup (
     VisitBioSourcesInSep (sep, NULL, ModPCRs);
   }
 
-  if (cfp->taxon) {
-    Taxon3ReplaceOrgInSeqEntry (sep, FALSE);
+  if (StringChr (cfp->feat, 'u') != NULL) {
+    VisitFeaturesInSep (sep, NULL, RemoveFeatUser);
   }
-
-  if (cfp->pub) {
-    VisitPubdescsInSep (sep, NULL, LookupPubdesc);
+  if (StringChr (cfp->feat, 'd') != NULL) {
+    VisitFeaturesInSep (sep, NULL, RemoveFeatDbxref);
+  }
+  if (StringChr (cfp->feat, 'r') != NULL) {
+    SeqMgrIndexFeatures (entityID, 0);
+    VisitFeaturesInSep (sep, NULL, RemoveUnnecGeneXref);
   }
 
   if (StringChr (cfp->link, 'o') != NULL) {
@@ -1127,19 +5737,20 @@ static time_t DoCleanup (
     ClearFeatureIDs (sep);
   }
 
-  if (StringChr (cfp->feat, 'u') != NULL) {
-    VisitFeaturesInSep (sep, NULL, RemoveFeatUser);
+  if (StringChr (cfp->desc, 't') != NULL) {
+    VisitDescriptorsInSep (sep, NULL, MarkTitles);
+    DeleteMarkedObjects (entityID, 0, NULL);
   }
-  if (StringChr (cfp->feat, 'd') != NULL) {
-    VisitFeaturesInSep (sep, NULL, RemoveFeatDbxref);
+  if (StringChr (cfp->desc, 'n') != NULL) {
+    RemoveNucProtSetTitles (sep);
+    DeleteMarkedObjects (entityID, 0, NULL);
   }
-  if (StringChr (cfp->feat, 'r') != NULL) {
-    SeqMgrIndexFeatures (entityID, 0);
-    VisitFeaturesInSep (sep, NULL, RemoveUnnecGeneXref);
+  if (StringChr (cfp->desc, 'e') != NULL) {
+    RemovePopsetTitles (sep);
+    DeleteMarkedObjects (entityID, 0, NULL);
   }
-
-  if (StringChr (cfp->desc, 't') != NULL) {
-    VisitDescriptorsInSep (sep, NULL, MarkTitles);
+  if (StringChr (cfp->desc, 'p') != NULL) {
+    RemoveProteinTitles (sep);
     DeleteMarkedObjects (entityID, 0, NULL);
   }
 
@@ -1147,11 +5758,57 @@ static time_t DoCleanup (
     SeqMgrIndexFeatures (entityID, 0);
     DoAutoDef (sep, entityID);
   }
+  if (StringChr (cfp->mods, 'e') != NULL) {
+    SeqMgrIndexFeatures (entityID, 0);
+    PopSetAutoDefRetro (sep, &stat);
+    LogPopSetTitleResults (cfp->logfp, &stat, sep);
+  }
+  if (StringChr (cfp->mods, 'n') != NULL) {
+    SeqMgrIndexFeatures (entityID, NULL);
+    SeqEntryExplore (sep, NULL, BadNCTitleProc);
+    DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
+    SeqMgrIndexFeatures (entityID, NULL);
+    InstantiateNCTitle (entityID, NULL);
+    SeqMgrClearFeatureIndexes (entityID, NULL);
+    BasicSeqEntryCleanup (sep);
+  }
+  if (StringChr (cfp->mods, 'm') != NULL) {
+    SeqMgrIndexFeatures (entityID, NULL);
+    SeqEntryExplore (sep, NULL, BadNMTitleProc);
+    DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
+    SeqMgrIndexFeatures (entityID, NULL);
+    InstantiateNMTitles (entityID, NULL);
+    SeqMgrClearFeatureIndexes (entityID, NULL);
+    BasicSeqEntryCleanup (sep);
+  }
+  if (StringChr (cfp->mods, 'x') != NULL) {
+    SeqMgrIndexFeatures (entityID, NULL);
+    SeqEntryExplore (sep, NULL, BadNMTitleProc);
+    DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
+    SeqMgrIndexFeatures (entityID, NULL);
+    InstantiateSpecialXMTitles (entityID, NULL);
+    SeqMgrClearFeatureIndexes (entityID, NULL);
+    BasicSeqEntryCleanup (sep);
+  }
+  if (StringChr (cfp->mods, 'p') != NULL) {
+    SeqMgrIndexFeatures (entityID, NULL);
+    SeqEntryExplore (sep, NULL, BadProtTitleProc);
+    DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
+    SeqMgrIndexFeatures (entityID, NULL);
+    InstantiateProteinTitles (entityID, NULL);
+    SeqMgrClearFeatureIndexes (entityID, NULL);
+    BasicSeqEntryCleanup (sep);
+  }
 
   if (cfp->action_list != NULL) {
     ApplyMacroToSeqEntry (sep, cfp->action_list, NULL, NULL);
   }
 
+  /* normalize order again at end */
+  if (StringChr (cfp->clean, 'n') != NULL) {
+    NormalizeDescriptorOrder (sep);
+  }
+
   stoptime = GetSecs ();
 
   if (aop != NULL) {
@@ -1174,7 +5831,7 @@ static void CleanupSingleRecord (
 )
 
 {
-  AsnIoPtr      aip, aop;
+  AsnIoPtr      aip, aop = NULL;
   BioseqPtr     bsp;
   BioseqSetPtr  bssp;
   Pointer       dataptr = NULL;
@@ -1290,9 +5947,11 @@ static void CleanupSingleRecord (
       }
 
       sep = GetTopSeqEntryForEntityID (entityID);
-      if (sep != NULL && StringDoesHaveText (path)) {
+      if (sep != NULL) {
 
+        if (StringHasNoText (cfp->report) && StringDoesHaveText (path)) {
         aop = AsnIoOpen (path, "w");
+        }
 
         DoCleanup (sep, entityID, cfp, aop, NULL, ssp);
 
@@ -1317,9 +5976,10 @@ static void CleanupMultipleRecord (
 )
 
 {
-  AsnIoPtr     aip, aop;
+  AsnIoPtr     aip, aop = NULL;
   AsnTypePtr   atp;
   DataVal      av;
+  Char         ch;
   Uint2        entityID;
   FILE         *fp;
   size_t       len;
@@ -1330,7 +5990,7 @@ static void CleanupMultipleRecord (
   SeqEntryPtr  sep;
   time_t       timediff, worsttime;
 #ifdef OS_UNIX
-  Char         cmmd [256];
+  Char         cmmd [512];
   CharPtr      gzcatprog;
   int          ret;
   Boolean      usedPopen = FALSE;
@@ -1360,7 +6020,7 @@ static void CleanupMultipleRecord (
       FileBuildPath (path, NULL, ptr);
     }
   }
-  if (StringHasNoText (path)) return;
+  if (StringHasNoText (cfp->report) && StringHasNoText (path)) return;
 
 #ifndef OS_UNIX
   if (cfp->compressed) {
@@ -1414,21 +6074,25 @@ static void CleanupMultipleRecord (
   }
 
   if (cfp->logfp != NULL) {
+    if (StringChr (cfp->report, 'c') == NULL) {
     fprintf (cfp->logfp, "%s\n\n", filename);
     fflush (cfp->logfp);
   }
+  }
 
   longest [0] = '\0';
   worsttime = 0;
   numrecords = 0;
 
+  if (StringHasNoText (cfp->report)) {
   aop = AsnIoOpen (path, cfp->binary? "wb" : "w");
   if (aop != NULL) {
-
     AsnOpenStruct (aop, cfp->bssp_atp, (Pointer) &(cfp->bss));
     av.intvalue = 7;
     AsnWrite (aop, cfp->atp_bsc, &av);
     AsnOpenStruct (aop, cfp->atp_bsss, (Pointer) &(cfp->bss.seq_set));
+    }
+  }
 
     atp = cfp->atp_bss;
 
@@ -1448,6 +6112,15 @@ static void CleanupMultipleRecord (
           if (timediff > worsttime) {
             worsttime = timediff;
             StringCpy (longest, cfp->buf);
+          ptr = longest;
+          ch = *ptr;
+          while (ch != '\0') {
+            if (ch == '|') {
+              *ptr = ' ';
+            }
+            ptr++;
+            ch = *ptr;
+          }
           }
           numrecords++;
 
@@ -1460,11 +6133,12 @@ static void CleanupMultipleRecord (
       }
     }
 
+  if (aop != NULL) {
     AsnCloseStruct (aop, cfp->atp_bsss, (Pointer) &(cfp->bss.seq_set));
     AsnCloseStruct (aop, cfp->bssp_atp, (Pointer) &(cfp->bss));
+    AsnIoClose (aop);
   }
 
-  AsnIoClose (aop);
   AsnIoFree (aip, FALSE);
 
 #ifdef OS_UNIX
@@ -1477,17 +6151,35 @@ static void CleanupMultipleRecord (
   FileClose (fp);
 #endif
   if (cfp->logfp != NULL) {
-    fprintf (cfp->logfp, "Total number of records %ld\n", (long) numrecords);
+    if (StringChr (cfp->report, 'c') == NULL) {
+      fprintf (cfp->logfp, "\nTotal number of records %ld\n", (long) numrecords);
     if (StringDoesHaveText (longest)) {
       fprintf (cfp->logfp, "Longest processing time %ld seconds on %s\n",
                (long) worsttime, longest);
     }
-    if (cfp->okay > 0 || cfp->norm > 0 || cfp->bsec > 0 || cfp->ssec > 0) {
-      fprintf (cfp->logfp, "%ld OKAY, %ld NORM, %ld BSEC, %ld SSEC\n",
-               (long) cfp->okay, (long) cfp->norm, (long) cfp->bsec, (long) cfp->ssec);
-    }
+      fprintf (cfp->logfp, "Counts ");
+      fprintf (cfp->logfp, "- %9ld RECS", (long) cfp->rawcounts.recs);
+      fprintf (cfp->logfp, ", %9ld NUCS", (long) cfp->rawcounts.nucs);
+      fprintf (cfp->logfp, ", %9ld PRTS", (long) cfp->rawcounts.prts);
+      fprintf (cfp->logfp, ", %9ld OKAY", (long) cfp->rawcounts.okay);
+      fprintf (cfp->logfp, ", %9ld NORM", (long) cfp->rawcounts.norm);
+      fprintf (cfp->logfp, ", %9ld CLNR", (long) cfp->rawcounts.clnr);
+      fprintf (cfp->logfp, ", %9ld OTHR", (long) cfp->rawcounts.othr);
+      fprintf (cfp->logfp, ", %9ld MODR", (long) cfp->rawcounts.modr);
+      fprintf (cfp->logfp, ", %9ld SLOC", (long) cfp->rawcounts.sloc);
+      fprintf (cfp->logfp, ", %9ld PUBL", (long) cfp->rawcounts.publ);
+      fprintf (cfp->logfp, ", %9ld AUTH", (long) cfp->rawcounts.auth);
+      fprintf (cfp->logfp, ", %9ld SORT", (long) cfp->rawcounts.sort);
+      fprintf (cfp->logfp, ", %9ld BSEC", (long) cfp->rawcounts.bsec);
+      fprintf (cfp->logfp, ", %9ld GBBK", (long) cfp->rawcounts.gbbk);
+      fprintf (cfp->logfp, ", %9ld TITL", (long) cfp->rawcounts.titl);
+      fprintf (cfp->logfp, ", %9ld PACK", (long) cfp->rawcounts.pack);
+      fprintf (cfp->logfp, ", %9ld MOVE", (long) cfp->rawcounts.move);
+      fprintf (cfp->logfp, ", %9ld SSEC", (long) cfp->rawcounts.ssec);
+      fprintf (cfp->logfp, "\n");
     fflush (cfp->logfp);
   }
+  }
 }
 
 static void CleanupOneRecord (
@@ -1497,48 +6189,289 @@ static void CleanupOneRecord (
 
 {
   CleanFlagPtr  cfp;
+  CharPtr       ptr;
+  SumDataPtr    sdp;
 
   if (StringHasNoText (filename)) return;
   cfp = (CleanFlagPtr) userdata;
   if (cfp == NULL) return;
 
-  cfp->okay = 0;
-  cfp->bsec = 0;
-  cfp->ssec = 0;
-  cfp->norm = 0;
+  MemSet ((Pointer) &(cfp->rawcounts), 0, sizeof (CountData));
+  MemSet ((Pointer) &(cfp->dbsums), 0, sizeof (DbSumData));
+
+  if (StringChr (cfp->sourcedb, 'y') != NULL) {
+    ptr = StringRChr (filename, DIRDELIMCHR);
+    if (ptr != NULL) {
+      ptr++;
+      if (StringStr (ptr, "gbcon") != NULL ||
+          StringStr (ptr, "gbest") != NULL ||
+          StringStr (ptr, "gbgss") != NULL ||
+          StringStr (ptr, "gbhtg") != NULL ||
+          StringStr (ptr, "gbpat") != NULL ||
+          StringStr (ptr, "gbsts") != NULL) return;
+    }
+  }
 
   if (cfp->batch) {
+    ptr = StringRChr (filename, DIRDELIMCHR);
+    if (ptr != NULL) {
+      ptr++;
+      if (StringDoesHaveText (cfp->firstfile)) {
+        if (StringICmp (cfp->firstfile, ptr) == 0) {
+          cfp->foundfirst = TRUE;
+        }
+        if (! cfp->foundfirst) return;
+      }
+
+      if (StringDoesHaveText (cfp->lastfile)) {
+        if (cfp->foundlast) return;
+        if (StringICmp (cfp->lastfile, ptr) == 0) {
+          cfp->foundlast = TRUE;
+        }
+      }
+    }
+
     CleanupMultipleRecord (filename, cfp);
   } else {
     CleanupSingleRecord (filename, cfp);
   }
+
+  if (cfp->logfp != NULL) {
+    if (StringChr (cfp->report, 'c') != NULL) {
+      ptr = StringRChr (filename, DIRDELIMCHR);
+      if (ptr != NULL) {
+        ptr++;
+        fprintf (cfp->logfp, "%s", ptr);
+      }
+      sdp = &(cfp->dbsums.genbank);
+      if (sdp != NULL) {
+        fprintf (cfp->logfp, "\t%ld\t%ld\t%ld", (long) sdp->recs, (long) sdp->nucs, (long) sdp->prts);
+      }
+      sdp = &(cfp->dbsums.embl);
+      if (sdp != NULL) {
+        fprintf (cfp->logfp, "\t%ld\t%ld\t%ld", (long) sdp->recs, (long) sdp->nucs, (long) sdp->prts);
+      }
+      sdp = &(cfp->dbsums.ddbj);
+      if (sdp != NULL) {
+        fprintf (cfp->logfp, "\t%ld\t%ld\t%ld", (long) sdp->recs, (long) sdp->nucs, (long) sdp->prts);
+      }
+      sdp = &(cfp->dbsums.refseq);
+      if (sdp != NULL) {
+        fprintf (cfp->logfp, "\t%ld\t%ld\t%ld", (long) sdp->recs, (long) sdp->nucs, (long) sdp->prts);
+      }
+      sdp = &(cfp->dbsums.other);
+      if (sdp != NULL) {
+        fprintf (cfp->logfp, "\t%ld\t%ld\t%ld", (long) sdp->recs, (long) sdp->nucs, (long) sdp->prts);
+      }
+      fprintf (cfp->logfp, "\t%ld\t%ld\t%ld", (long) cfp->rawcounts.recs, (long) cfp->rawcounts.nucs, (long) cfp->rawcounts.prts);
+      fprintf (cfp->logfp, "\n");
+      fflush (cfp->logfp);
+    }
+  }
+}
+
+static Boolean IsAllDigits (CharPtr str)
+
+{
+  CharPtr cp;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  cp = str;
+  while (*cp != 0 && isdigit (*cp)) {
+    cp++;
+  }
+  if (*cp == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+static Boolean PvtStrToLong (CharPtr str, Int4Ptr longval)
+
+{
+  Char     ch;
+  Int2     i;
+  Int2     len;
+  Char     local [64];
+  Boolean  nodigits;
+  Boolean  rsult;
+  long int     val;
+
+  rsult = FALSE;
+  if (longval != NULL) {
+    *longval = (Int4) 0;
+  }
+  len = (Int2) StringLen (str);
+  if (len != 0) {
+    rsult = TRUE;
+    nodigits = TRUE;
+    for (i = 0; i < len; i++) {
+      ch = str [i];
+      if (ch == ' ' || ch == '+' || ch == '-') {
+      } else if (ch < '0' || ch > '9') {
+        rsult = FALSE;
+      } else {
+        nodigits = FALSE;
+      }
+    }
+    if (nodigits) {
+      rsult = FALSE;
+    }
+    if (rsult && longval != NULL) {
+      StringNCpy_0 (local, str, sizeof (local));
+      if (sscanf (local, "%ld", &val) == 1) {
+        *longval = val;
+      }
+    }
+  }
+  return rsult;
+}
+
+static Int4 AccessionToGi (CharPtr string)
+
+{
+   Int4      gi;
+   SeqIdPtr  sip;
+
+   sip = SeqIdFromAccessionDotVersion (string);
+   if (sip == NULL) return 0;
+   gi = GetGIForSeqId (sip);
+   SeqIdFree (sip);
+   return gi;
+}
+
+static void ProcessAccessionList (
+  CharPtr accnfile,
+  CleanFlagPtr cfp
+)
+
+{
+  AsnIoPtr     aop = NULL;
+  BioseqPtr    bsp;
+  Uint2        entityID;
+  FileCache    fc;
+  FILE         *fp;
+  Char         line [1023];
+  Char         path [PATH_MAX];
+  SeqEntryPtr  sep;
+  ErrSev       sev;
+  SeqIdPtr     sip;
+  CharPtr      str;
+  Char         tmp [64];
+
+  if (StringHasNoText (accnfile) || cfp == NULL) return;
+
+  fp = FileOpen (accnfile, "r");
+  if (fp == NULL) return;
+
+  if (FileCacheSetup (&fc, fp)) {
+    str = FileCacheGetString (&fc, line, sizeof (line));
+    while (str != NULL) {
+      TrimSpacesAroundString (str);
+
+      bsp = NULL;
+      entityID = 0;
+      sep = NULL;
+      sip = NULL;
+
+      if (IsAllDigits (str)) {
+        sprintf (tmp, "gi|%s", str);
+        sip = SeqIdParse (tmp);
+      } else {
+        sip = SeqIdFromAccessionDotVersion (str);
+      }
+
+      if (sip != NULL) {
+        sev = ErrSetMessageLevel (SEV_MAX);
+        bsp = BioseqLockById (sip);
+        ErrSetMessageLevel (sev);
+        sip = SeqIdFree (sip);
+      }
+
+      if (bsp != NULL) {
+        entityID = ObjMgrGetEntityIDForPointer (bsp);
+        sep = GetTopSeqEntryForEntityID (entityID);
+
+        if (sep != NULL) {
+
+          path [0] = '\0';
+          if (StringDoesHaveText (cfp->outfile)) {
+
+            StringNCpy_0 (path, cfp->outfile, sizeof (path));
+
+          } else if (StringDoesHaveText (cfp->results)) {
+
+            StringNCpy_0 (path, cfp->results, sizeof (path));
+            FileBuildPath (path, NULL, str);
+            StringCat (path, ".asn");
+          }
+
+          entityID = ObjMgrGetEntityIDForChoice (sep);
+          if (entityID > 0) {
+
+            if (StringHasNoText (cfp->report) && StringDoesHaveText (path)) {
+              aop = AsnIoOpen (path, "w");
+            }
+
+            DoCleanup (sep, entityID, cfp, aop, NULL, NULL);
+
+            if (aop != NULL) {
+              AsnIoFlush (aop);
+              AsnIoClose (aop);
+            }
+          }
+        }
+
+        BioseqUnlock (bsp);
+        SeqEntryFree (sep);
+      }
+
+      str = FileCacheGetString (&fc, line, sizeof (line));
+    }
+  }
+
+  FileClose (fp);
 }
 
 /* Args structure contains command-line arguments */
 
-#define p_argInputPath     0
-#define r_argOutputPath    1
-#define i_argInputFile     2
-#define o_argOutputFile    3
-#define f_argFilter        4
-#define x_argSuffix        5
-#define a_argType          6
-#define b_argBinary        7
-#define c_argCompressed    8
-#define L_argLogFile       9
-#define R_argRemote       10
-#define Q_argReport       11
-#define q_argFfDiff       12
-#define m_argFfMode       13
-#define K_argClean        14
-#define U_argModernize    15
-#define N_argLink         16
-#define F_argFeat         17
-#define D_argDesc         18
-#define X_argMods         19
-#define M_argMacro        20
-#define T_argTaxonLookup  21
-#define P_argPubLookup    22
+typedef enum {
+  p_argInputPath = 0,
+  r_argOutputPath,
+  i_argInputFile,
+  o_argOutputFile,
+  f_argFilter,
+  x_argSuffix,
+  j_argFirstFile,
+  k_argLastFile,
+  d_argSourceDb,
+  a_argType,
+  b_argBinary,
+  c_argCompressed,
+  L_argLogFile,
+  R_argRemote,
+  Q_argReport,
+  S_argSelective,
+  m_argFfMode,
+  q_argFfDiff,
+  n_argAsn2Flat,
+  v_argAsnVal,
+  K_argClean,
+  U_argModernize,
+  N_argLink,
+  F_argFeat,
+  D_argDesc,
+  X_argMods,
+  M_argMacro,
+  T_argTaxonLookup,
+  P_argPubLookup,
+  A_argAccnFile,
+#ifdef INTERNAL_NCBI_CLEANASN
+  H_argHup,
+#endif
+} Arguments;
 
 Args myargs [] = {
   {"Path to Files", NULL, NULL, NULL,
@@ -1553,13 +6486,27 @@ Args myargs [] = {
     TRUE, 'f', ARG_STRING, 0.0, 0, NULL},
   {"File Selection Suffix", ".ent", NULL, NULL,
     TRUE, 'x', ARG_STRING, 0.0, 0, NULL},
+  {"First File Name", NULL, NULL, NULL,
+    TRUE, 'j', ARG_STRING, 0.0, 0, NULL},
+  {"Last File Name", NULL, NULL, NULL,
+    TRUE, 'k', ARG_STRING, 0.0, 0, NULL},
+  {"Source Database\n"
+   "      a Any\n"
+   "      g GenBank\n"
+   "      e EMBL\n"
+   "      d DDBJ\n"
+   "      r RefSeq\n"
+   "      n NCBI\n"
+   "      x Exclude EMBL/DDBJ\n"
+   "      y Exclude gbcon, gbest, gbgss, gbhtg, gbpat, gbsts\n", "a", NULL, NULL,
+    TRUE, 'd', ARG_STRING, 0.0, 0, NULL},
   {"ASN.1 Type\n"
    "      a Any\n"
    "      e Seq-entry\n"
    "      b Bioseq\n"
    "      s Bioseq-set\n"
    "      m Seq-submit\n"
-   "      t Batch Processing", "a", NULL, NULL,
+   "      t Batch Processing\n", "a", NULL, NULL,
     TRUE, 'a', ARG_STRING, 0.0, 0, NULL},
   {"Bioseq-set is Binary", "F", NULL, NULL,
     TRUE, 'b', ARG_BOOLEAN, 0.0, 0, NULL},
@@ -1570,67 +6517,118 @@ Args myargs [] = {
   {"Remote Fetching from ID", "F", NULL, NULL,
     TRUE, 'R', ARG_BOOLEAN, 0.0, 0, NULL},
   {"Report\n"
-   "      r ASN.1 BSEC/SSEC Report\n"
+   "      c Record Count\n"
+   "      r ASN.1 BSEC Report\n"
+   "      s ASN.1 SSEC Report\n"
+   "      n NORM vs. SSEC Report\n"
+   "      e PopPhyMutEco AutoDef Report\n"
+   "      o Overlap Report\n"
+   "      d Log SSEC Differences\n"
    "      g GenBank SSEC Diff\n"
-   "      m Modernize Gene/RNA/PCR", NULL, NULL, NULL,
+   "      f asn2gb/asn2flat Diff\n"
+   "      v Validator SSEC Diff\n"
+   "      m Modernize Gene/RNA/PCR\n"
+   "      u Unpublished Pub Lookup\n"
+   "      p Published Pub Lookup\n"
+   "      x Custom Scan\n", NULL, NULL, NULL,
     TRUE, 'Q', ARG_STRING, 0.0, 0, NULL},
-  {"Ffdiff Executable", "/netopt/genbank/subtool/bin/ffdiff", NULL, NULL,
-    TRUE, 'q', ARG_FILE_IN, 0.0, 0, NULL},
+  {"Selective Difference Filter\n"
+   "      s SSEC\n"
+   "      b BSEC\n"
+   "      a Author\n"
+   "      p Publication\n"
+   "      l Location\n"
+   "      r RNA\n"
+   "      q Qualifier Sort Order\n"
+   "      g Genbank Block\n"
+   "      k Package CdRegion or Parts Features\n"
+   "      m Move Publication\n"
+   "      o Leave Duplicate Bioseq Publication\n"
+   "      d Automatic Definition Line\n"
+   "      e Pop/Phy/Mut/Eco Set Definition Line\n"
+   "      (Capital Letters Skip)\n", NULL, NULL, NULL,
+    TRUE, 'S', ARG_STRING, 0.0, 0, NULL},
   {"Flatfile Mode\n"
    "      r Release\n"
    "      e Entrez\n"
    "      s Sequin\n"
    "      d Dump\n", NULL, NULL, NULL,
     TRUE, 'm', ARG_STRING, 0.0, 0, NULL},
+  {"ffdiff Executable", "/netopt/genbank/subtool/bin/ffdiff", NULL, NULL,
+    TRUE, 'q', ARG_FILE_IN, 0.0, 0, NULL},
+  {"asn2flat Executable", "/netopt/ncbi_tools/bin/asn2flat", NULL, NULL,
+    TRUE, 'n', ARG_FILE_IN, 0.0, 0, NULL},
+  {"asnval Executable", "/netopt/ncbi_tools/bin/asnval", NULL, NULL,
+    TRUE, 'v', ARG_FILE_IN, 0.0, 0, NULL},
   {"Cleanup\n"
    "      b BasicSeqEntryCleanup\n"
    "      p C++ BasicCleanup\n"
    "      s SeriousSeqEntryCleanup\n"
    "      g GpipeSeqEntryCleanup\n"
    "      n Normalize Descriptor Order\n"
-   "      u Remove NcbiCleanup User Objects", NULL, NULL, NULL,
+   "      u Remove NcbiCleanup User Objects\n"
+   "      c Synchronize Genetic Codes\n", NULL, NULL, NULL,
     TRUE, 'K', ARG_STRING, 0.0, 0, NULL},
   {"Modernize\n"
    "      g Gene\n"
    "      r RNA\n"
-   "      p PCR Primers", NULL, NULL, NULL,
+   "      p PCR Primers\n", NULL, NULL, NULL,
     TRUE, 'U', ARG_STRING, 0.0, 0, NULL},
   {"Link\n"
    "      o LinkCDSmRNAbyOverlap\n"
    "      p LinkCDSmRNAbyProduct\n"
    "      r ReassignFeatureIDs\n"
-   "      c ClearFeatureIDs", NULL, NULL, NULL,
+   "      c ClearFeatureIDs\n", NULL, NULL, NULL,
     TRUE, 'N', ARG_STRING, 0.0, 0, NULL},
   {"Feature\n"
    "      u Remove User Object\n"
    "      d Remove db_xref\n"
-   "      r Remove Redundant Gene xref", NULL, NULL, NULL,
+   "      r Remove Redundant Gene xref\n", NULL, NULL, NULL,
     TRUE, 'F', ARG_STRING, 0.0, 0, NULL},
   {"Descriptor\n"
-   "      t Remove Title", NULL, NULL, NULL,
+   "      t Remove Title\n"
+   "      n Remove Nuc-Prot Set Title\n"
+   "      e Remove Pop/Phy/Mut/Eco Set Title\n"
+   "      p Remove Protein Title\n", NULL, NULL, NULL,
     TRUE, 'D', ARG_STRING, 0.0, 0, NULL},
   {"Miscellaneous\n"
-   "      d Automatic Definition Line", NULL, NULL, NULL,
+   "      d Automatic Definition Line\n"
+   "      e Pop/Phy/Mut/Eco Set Definition Line\n"
+   "      n Instantiate NC Title\n"
+   "      m Instantiate NM Titles\n"
+   "      x Special XM Titles\n"
+   "      p Instantiate Protein Titles\n", NULL, NULL, NULL,
     TRUE, 'X', ARG_STRING, 0.0, 0, NULL},
   {"Macro File", NULL, NULL, NULL,
     TRUE, 'M', ARG_FILE_IN, 0.0, 0, NULL},
   {"Taxonomy Lookup", "F", NULL, NULL,
     TRUE, 'T', ARG_BOOLEAN, 0.0, 0, NULL},
-  {"Publication Lookup", "F", NULL, NULL,
-    TRUE, 'P', ARG_BOOLEAN, 0.0, 0, NULL},
+  {"Publication Lookup\n"
+   "      u Update PMID-only Publication\n"
+   "      # Replace Unpublished With PMID\n", NULL, NULL, NULL,
+    TRUE, 'P', ARG_STRING, 0.0, 0, NULL},
+  {"Accession List File", NULL, NULL, NULL,
+    TRUE, 'A', ARG_FILE_IN, 0.0, 0, NULL},
+#ifdef INTERNAL_NCBI_CLEANASN
+  {"Internal Access to HUP", "F", NULL, NULL,
+    TRUE, 'H', ARG_BOOLEAN, 0.0, 0, NULL},
+#endif
 };
 
 Int2 Main (void)
 
 {
-  ValNodePtr     action_list;
+  ValNodePtr     action_list, parflat_list, vnp;
   AsnIoPtr       aip;
   Char           app [64], mode, type;
   CleanFlagData  cfd;
-  CharPtr        directory, filter, infile, logfile, outfile,
+  CharPtr        directory, filter, accnfile, infile, logfile, outfile,
                  macro_file, results, str, suffix;
   Boolean        remote;
   time_t         runtime, starttime, stoptime;
+#ifdef INTERNAL_NCBI_CLEANASN
+  Boolean        hup;
+#endif
 
   /* standard setup */
 
@@ -1662,6 +6660,17 @@ Int2 Main (void)
     return 1;
   }
 
+  parflat_list = Validate_ParFlat_GBFeat ();
+  if (parflat_list != NULL) {
+    Message (MSG_POSTERR, "Validate_ParFlat_GBFeat warnings");
+    for (vnp = parflat_list; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      Message (MSG_POSTERR, "%s", str);
+    }
+    ValNodeFreeData (parflat_list);
+  }
+
   /* process command line arguments */
 
   sprintf (app, "cleanasn %s", CLEANASN_APPLICATION);
@@ -1676,6 +6685,7 @@ Int2 Main (void)
   if (StringHasNoText (results)) {
     results = directory;
   }
+  accnfile = (CharPtr) myargs [A_argAccnFile].strvalue;
   infile = (CharPtr) myargs [i_argInputFile].strvalue;
   outfile = (CharPtr) myargs [o_argOutputFile].strvalue;
   filter = (CharPtr) myargs [f_argFilter].strvalue;
@@ -1686,6 +6696,10 @@ Int2 Main (void)
   cfd.compressed = (Boolean) myargs [c_argCompressed].intvalue;
   cfd.type = 1;
 
+  cfd.foundfirst = FALSE;
+  cfd.foundlast = FALSE;
+  cfd.sourcedb = myargs [d_argSourceDb].strvalue;
+
   str = myargs [a_argType].strvalue;
   TrimSpacesAroundString (str);
   if (StringDoesHaveText (str)) {
@@ -1721,9 +6735,18 @@ Int2 Main (void)
   }
 
   remote = (Boolean) myargs [R_argRemote].intvalue;
+  if (StringDoesHaveText (accnfile)) {
+    remote = TRUE;
+  }
+#ifdef INTERNAL_NCBI_CLEANASN
+  hup = (Boolean) myargs [H_argHup].intvalue;
+#endif
 
   cfd.report = myargs [Q_argReport].strvalue;
+  cfd.selective = myargs [S_argSelective].strvalue;
   cfd.ffdiff = myargs [q_argFfDiff].strvalue;
+  cfd.asn2flat = myargs [n_argAsn2Flat].strvalue;
+  cfd.asnval = myargs [v_argAsnVal].strvalue;
 
   str = myargs [m_argFfMode].strvalue;
   TrimSpacesAroundString (str);
@@ -1759,7 +6782,10 @@ Int2 Main (void)
   cfd.desc = myargs [D_argDesc].strvalue;
   cfd.mods = myargs [X_argMods].strvalue;
   cfd.taxon = (Boolean) myargs [T_argTaxonLookup].intvalue;
-  cfd.pub = (Boolean) myargs [P_argPubLookup].intvalue;
+  cfd.pub = myargs [P_argPubLookup].strvalue;
+  cfd.unpubcount = 0;
+  cfd.unpublist = NULL;
+  cfd.lastunpub = NULL;
 
   macro_file = myargs [M_argMacro].strvalue;
   if (StringDoesHaveText (macro_file)) {
@@ -1794,6 +6820,11 @@ Int2 Main (void)
       Message (MSG_POSTERR, "PUBSEQBioseqFetchEnable failed");
       return 1;
     }
+    if (hup) {
+      SmartFetchEnable ();
+      TPASmartFetchEnable ();
+      HUPFetchEnable ();
+    }
 #else
     PubSeqFetchEnable ();
 #endif
@@ -1803,19 +6834,43 @@ Int2 Main (void)
     PubMedFetchEnable ();
   }
 
+  /*
+  if (cfd.logfp != NULL && StringChr (cfd.report, 'c') != NULL) {
+    fprintf (cfd.logfp, "FILE\t\tGENBANK\t\t\tEMBL\t\t\tDDBJ\t\t\tREFSEQ\t\t\tOTHER\n");
+    fprintf (cfd.logfp, "\tREC\tNUC\tPRT\tREC\tNUC\tPRT\tREC\tNUC\tPRT\tREC\tNUC\tPRT\tREC\tNUC\tPRT\n");
+    fflush (cfd.logfp);
+  }
+  */
+
   starttime = GetSecs ();
 
   if (StringDoesHaveText (directory)) {
-    if (StringCmp (directory, results) == 0) {
+    if (StringHasNoText (cfd.report) && StringCmp (directory, results) == 0) {
       Message (MSG_POSTERR, "-r results path must be different than -p data path");
       if (cfd.logfp != NULL) {
         fprintf (cfd.logfp, "-r results path must be different than -p data path\n");
       }
     } else {
 
+      cfd.firstfile = (CharPtr) myargs [j_argFirstFile].strvalue;
+      cfd.lastfile = (CharPtr) myargs [k_argLastFile].strvalue;
+
       cfd.results = results;
 
-      DirExplore (directory, NULL, suffix, FALSE, CleanupOneRecord, (Pointer) &cfd);
+      DirExplore (directory, filter, suffix, FALSE, CleanupOneRecord, (Pointer) &cfd);
+    }
+
+  } else if (StringDoesHaveText (accnfile)) {
+    if (StringHasNoText (cfd.report) && StringHasNoText (results)) {
+      Message (MSG_POSTERR, "-r results path must be set when -A accession list is used");
+      if (cfd.logfp != NULL) {
+        fprintf (cfd.logfp, "-r results path must be set when -A accession list is used\n");
+      }
+    } else {
+
+      cfd.results = results;
+
+      ProcessAccessionList (accnfile, (Pointer) &cfd);
     }
 
   } else if (StringDoesHaveText (infile) && StringDoesHaveText (outfile)) {
@@ -1825,13 +6880,40 @@ Int2 Main (void)
     CleanupOneRecord (infile, (Pointer) &cfd);
   }
 
+  if (StringChr (cfd.report, 'u') != NULL) {
+    if (cfd.logfp != NULL) {
+      fprintf (cfd.logfp, "\n\nTrying %ld Entrez Queries\n\n", (long) ValNodeLen (cfd.unpublist));
+    }
+    FinishUnpublishedList (&cfd);
+  }
+
   stoptime = GetSecs ();
   runtime = stoptime - starttime;
+
   if (cfd.logfp != NULL) {
-    fprintf (cfd.logfp, "Finished in %ld seconds\n", (long) runtime);
-    if (cfd.cumokay > 0 || cfd.cumnorm > 0 || cfd.cumbsec > 0 || cfd.cumssec > 0) {
-      fprintf (cfd.logfp, "Cumulative counts - %ld OKAY, %ld NORM, %ld BSEC, %ld SSEC\n",
-               (long) cfd.cumokay, (long) cfd.cumnorm, (long) cfd.cumbsec, (long) cfd.cumssec);
+    if (StringChr (cfd.report, 'c') == NULL) {
+      fprintf (cfd.logfp, "\nFinished in %ld seconds\n", (long) runtime);
+      fprintf (cfd.logfp, "Cumulative counts ");
+      fprintf (cfd.logfp, "- %9ld RECS", (long) cfd.cumcounts.recs);
+      fprintf (cfd.logfp, ", %9ld NUCS", (long) cfd.cumcounts.nucs);
+      fprintf (cfd.logfp, ", %9ld PRTS", (long) cfd.cumcounts.prts);
+      fprintf (cfd.logfp, ", %9ld OKAY", (long) cfd.cumcounts.okay);
+      fprintf (cfd.logfp, ", %9ld NORM", (long) cfd.cumcounts.norm);
+      fprintf (cfd.logfp, ", %9ld CLNR", (long) cfd.cumcounts.clnr);
+      fprintf (cfd.logfp, ", %9ld OTHR", (long) cfd.cumcounts.othr);
+      fprintf (cfd.logfp, ", %9ld MODR", (long) cfd.cumcounts.modr);
+      fprintf (cfd.logfp, ", %9ld SLOC", (long) cfd.cumcounts.sloc);
+      fprintf (cfd.logfp, ", %9ld PUBL", (long) cfd.cumcounts.publ);
+      fprintf (cfd.logfp, ", %9ld AUTH", (long) cfd.cumcounts.auth);
+      fprintf (cfd.logfp, ", %9ld SORT", (long) cfd.cumcounts.sort);
+      fprintf (cfd.logfp, ", %9ld BSEC", (long) cfd.cumcounts.bsec);
+      fprintf (cfd.logfp, ", %9ld GBBK", (long) cfd.cumcounts.gbbk);
+      fprintf (cfd.logfp, ", %9ld TITL", (long) cfd.cumcounts.titl);
+      fprintf (cfd.logfp, ", %9ld PACK", (long) cfd.cumcounts.pack);
+      fprintf (cfd.logfp, ", %9ld MOVE", (long) cfd.cumcounts.move);
+      fprintf (cfd.logfp, ", %9ld SSEC", (long) cfd.cumcounts.ssec);
+      fprintf (cfd.logfp, "\n");
+      fflush (cfd.logfp);
     }
     FileClose (cfd.logfp);
   }
diff --git a/demo/cspeedtest.c b/demo/cspeedtest.c
index bfebd65..1472438 100644
--- a/demo/cspeedtest.c
+++ b/demo/cspeedtest.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   12/17/07
 *
-* $Revision: 1.22 $
+* $Revision: 1.25 $
 *
 * File Description: 
 *
@@ -57,14 +57,7 @@
 #include <valid.h>
 #include <suggslp.h>
 
-NLM_EXTERN CharPtr NewCreateDefLine (
-  ItemInfoPtr iip,
-  BioseqPtr bsp,
-  Boolean ignoreTitle,
-  Boolean extProtTitle
-);
-
-#define CSPEEDTEST_APP_VER "2.0"
+#define CSPEEDTEST_APP_VER "2.1"
 
 CharPtr CSPEEDTEST_APPLICATION = CSPEEDTEST_APP_VER;
 
@@ -333,7 +326,8 @@ static void DoFastaDefline (
 
 static void DoNewFastaDefline (
   BioseqPtr bsp,
-  Pointer userdata
+  Pointer userdata,
+  Boolean ignoreExisting
 )
 
 {
@@ -361,7 +355,7 @@ static void DoNewFastaDefline (
 
   id [0] = '\0';
   SeqIdWrite (bsp->id, id, PRINTID_FASTA_LONG, sizeof (id) - 1);
-  title = NewCreateDefLine (NULL, bsp, FALSE, FALSE);
+  title = NewCreateDefLine (NULL, bsp, ignoreExisting, FALSE);
   if (StringHasNoText (title)) {
     title = StringSave ("?");
   }
@@ -373,6 +367,24 @@ static void DoNewFastaDefline (
   MemFree (title);
 }
 
+static void DoNewFastaExist (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  DoNewFastaDefline (bsp, userdata, FALSE);
+}
+
+static void DoNewFastaRegen (
+  BioseqPtr bsp,
+  Pointer userdata
+)
+
+{
+  DoNewFastaDefline (bsp, userdata, TRUE);
+}
+
 static void DoFastaComp (
   BioseqPtr bsp,
   Pointer userdata,
@@ -574,6 +586,43 @@ static void MarkTitles (
   ovn->idx.deleteme = TRUE;
 }
 
+static void RemoveTitles (
+  SeqEntryPtr sep,
+  Pointer mydata,
+  Int4 index,
+  Int2 indent
+)
+
+{
+  BioseqPtr         bsp;
+  BioseqSetPtr      bssp;
+  SeqDescrPtr PNTR  prev = NULL;
+  SeqDescrPtr       sdp = NULL, next = NULL;
+
+  if (sep == NULL || sep->data.ptrvalue == NULL) return;
+  if (IS_Bioseq (sep)) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    sdp = bsp->descr;
+    prev = &(bsp->descr);
+  } else if (IS_Bioseq_set (sep)) {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    sdp = bssp->descr;
+    prev = &(bssp->descr);
+  } else return;
+
+  while (sdp != NULL) {
+    next = sdp->next;
+    if (sdp->choice == Seq_descr_title) {
+      *prev = sdp->next;
+      sdp->next = NULL;
+      SeqDescFree (sdp);
+    } else {
+      prev = (SeqDescrPtr PNTR) &(sdp->next);
+    }
+    sdp = next;
+  }
+}
+
 static void DoProcess (
   SeqEntryPtr sep,
   Uint2 entityID,
@@ -587,10 +636,18 @@ static void DoProcess (
 
   if (sep == NULL || cfp == NULL) return;
 
-  if (StringChr (cfp->clean, 't') != NULL) {
+  if (StringChr (cfp->clean, 'm') != NULL) {
     VisitDescriptorsInSep (sep, NULL, MarkTitles);
+  }
+  if (StringChr (cfp->clean, 'd') != NULL) {
     DeleteMarkedObjects (entityID, 0, NULL);
   }
+  if (StringChr (cfp->clean, 'c') != NULL) {
+    SeqMgrClearFeatureIndexes (entityID, NULL);
+  }
+  if (StringChr (cfp->clean, 't') != NULL) {
+    SeqEntryExplore (sep, NULL, RemoveTitles);
+  }
   if (StringChr (cfp->clean, 'a') != NULL) {
     AssignIDsInEntity (entityID, 0, NULL);
   }
@@ -602,7 +659,7 @@ static void DoProcess (
   }
 
   if (StringChr (cfp->index, 'f') != NULL) {
-    SeqMgrIndexFeatures (entityID, 0);
+    SeqMgrIndexFeatures (entityID, NULL);
   }
 
   if (StringChr (cfp->seq, 'c') != NULL) {
@@ -616,7 +673,7 @@ static void DoProcess (
   }
   if (StringChr (cfp->seq, 'S') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     VisitBioseqsInSep (sep, (Pointer) cfp, DoFastaSeq);
   }
@@ -628,24 +685,26 @@ static void DoProcess (
   }
   if (StringChr (cfp->seq, 'D') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     VisitBioseqsInSep (sep, (Pointer) cfp, DoFastaDefline);
   }
   if (StringChr (cfp->seq, 'T') != NULL) {
     VisitDescriptorsInSep (sep, NULL, MarkTitles);
     DeleteMarkedObjects (entityID, 0, NULL);
-    SeqMgrIndexFeatures (entityID, 0);
+    SeqMgrIndexFeatures (entityID, NULL);
     VisitBioseqsInSep (sep, (Pointer) cfp, DoFastaDefline);
   }
   if (StringChr (cfp->seq, 'x') != NULL) {
-    VisitBioseqsInSep (sep, (Pointer) cfp, DoNewFastaDefline);
+    VisitBioseqsInSep (sep, (Pointer) cfp, DoNewFastaExist);
   }
   if (StringChr (cfp->seq, 'X') != NULL) {
+    /*
     VisitDescriptorsInSep (sep, NULL, MarkTitles);
     DeleteMarkedObjects (entityID, 0, NULL);
-    SeqMgrIndexFeatures (entityID, 0);
-    VisitBioseqsInSep (sep, (Pointer) cfp, DoNewFastaDefline);
+    SeqMgrIndexFeatures (entityID, NULL);
+    */
+    VisitBioseqsInSep (sep, (Pointer) cfp, DoNewFastaRegen);
   }
   
   if (StringChr (cfp->seq, 'f') != NULL) {
@@ -660,13 +719,13 @@ static void DoProcess (
   }
   if (StringChr (cfp->feat, 'g') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     VisitFeaturesInSep (sep, (Pointer) cfp, DoGeneOverlapPrintTest);
   }
   if (StringChr (cfp->feat, 'h') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     VisitFeaturesInSep (sep, (Pointer) cfp, DoGeneOverlapSpeedTest);
   }
@@ -682,13 +741,15 @@ static void DoProcess (
   }
   if (StringChr (cfp->feat, 's') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     cfp->nucbsp = FindNucBioseq (sep);
     if (cfp->nucbsp != NULL) {
       BioseqToGeneticCode (cfp->nucbsp, &(cfp->genCode), NULL, NULL, NULL, 0, NULL);
       SeqIdWrite (cfp->nucbsp->id, id, PRINTID_FASTA_LONG, sizeof (id) - 1);
+      if (cfp->ofp != NULL) {
       fprintf (cfp->ofp, "%s\n", id);
+      }
       VisitBioseqsInSep (sep, (Pointer) cfp, DoSuggestIntervals);
       cfp->nucbsp = NULL;
       cfp->genCode = 0;
@@ -696,14 +757,16 @@ static void DoProcess (
   }
   if (StringChr (cfp->feat, 'S') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     cfp->nucbsp = FindNucBioseq (sep);
     if (cfp->nucbsp != NULL) {
       BioseqToGeneticCode (cfp->nucbsp, &(cfp->genCode), NULL, NULL, NULL, 0, NULL);
       SetBatchSuggestNucleotide (cfp->nucbsp, cfp->genCode);
       SeqIdWrite (cfp->nucbsp->id, id, PRINTID_FASTA_LONG, sizeof (id) - 1);
+      if (cfp->ofp != NULL) {
       fprintf (cfp->ofp, "%s\n", id);
+      }
       VisitBioseqsInSep (sep, (Pointer) cfp, DoSuggestIntervals);
       ClearBatchSuggestNucleotide ();
       cfp->nucbsp = NULL;
@@ -721,7 +784,7 @@ static void DoProcess (
 
   if (StringChr (cfp->verify, 'v') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     vsp = ValidStructNew ();
     if (vsp != NULL) {
@@ -740,7 +803,7 @@ static void DoProcess (
   }
   if (StringChr (cfp->verify, 'b') != NULL) {
     if (SeqMgrFeaturesAreIndexed (entityID) == 0) {
-      SeqMgrIndexFeatures (entityID, 0);
+      SeqMgrIndexFeatures (entityID, NULL);
     }
     SeqEntryToGnbk (sep, NULL, GENBANK_FMT, SEQUIN_MODE, NORMAL_STYLE,
                     0, 0, 0, NULL, cfp->ofp);
@@ -1213,6 +1276,9 @@ Args myargs [] = {
    "      wb Write Binary ASN.1", NULL, NULL, NULL,
     TRUE, 'O', ARG_STRING, 0.0, 0, NULL},
   {"Cleanup\n"
+   "      m Mark Titles\n"
+   "      d Delete Marked Objects\n"
+   "      c Clear Feature Indexes\n"
    "      t Remove Titles\n"
    "      a AssignIDsInEntity\n"
    "      b BasicSeqEntryCleanup\n"
diff --git a/demo/entrez2.c b/demo/entrez2.c
index e34f837..28dbf34 100644
--- a/demo/entrez2.c
+++ b/demo/entrez2.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   06/16/00
 *
-* $Revision: 6.32 $
+* $Revision: 6.33 $
 *
 * File Description: 
 *
@@ -61,7 +61,7 @@
 
 #include <entrez2.h>
 
-#define ENTREZ_APP_VERSION "10.3"
+#define ENTREZ_APP_VERSION "11.0"
 
 #define MAX_QUERY_FORMS 256
 
diff --git a/demo/gene2xml.c b/demo/gene2xml.c
index d08cf96..31a42e2 100644
--- a/demo/gene2xml.c
+++ b/demo/gene2xml.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/27/05
 *
-* $Revision: 1.8 $
+* $Revision: 1.10 $
 *
 * File Description:
 *
@@ -48,7 +48,7 @@
 #define NLM_GENERATED_CODE_PROTO
 #include <objentgene.h>
 
-#define GENE2XMLAPP_VER "1.1"
+#define GENE2XMLAPP_VER "1.3"
 
 CharPtr GENE2XMLAPPLICATION = GENE2XMLAPP_VER;
 
@@ -220,7 +220,9 @@ static Boolean GenerateXML (
     if (atp == atp_egse) {
       egp = EntrezgeneAsnRead (aip, atp);
       if (taxid == 0 || HasDesiredTaxId (egp, taxid)) {
-        EntrezgeneAsnWrite (egp, aop, atp);
+        if (! EntrezgeneAsnWrite (egp, aop, atp)) {
+          Message (MSG_POSTERR, "EntrezgeneAsnWrite failure");
+        }
       }
       EntrezgeneFree (egp);
     } else {
diff --git a/demo/scantest.c b/demo/scantest.c
index 2c7251e..cfbb374 100644
--- a/demo/scantest.c
+++ b/demo/scantest.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/20/95
 *
-* $Revision: 6.57 $
+* $Revision: 6.61 $
 *
 * File Description: 
 *       template for custom scans of ASN.1 release files
@@ -1031,8 +1031,11 @@ static void ReportObsoleteDbxref (
           StringICmp (str, "UniProt/TrEMBL") == 0 ||
           StringICmp (str, "Genew") == 0 ||
           StringICmp (str, "GENEDB") == 0 ||
+          StringICmp (str, "GreengenesID") == 0 ||
+          StringICmp (str, "HMPID") == 0 ||
           StringICmp (str, "IFO") == 0 ||
-          StringICmp (str, "BHB") == 0) {
+          StringICmp (str, "BHB") == 0 ||
+          StringICmp (str, "BioHealthBase") == 0) {
         cdp->oldDbxref = TRUE;
         if (tdp->verbose) {
           TSPrintLine (tdp->fp, "OLDDBX", tdp->id, str, NULL, "\t");
@@ -1434,6 +1437,40 @@ static void CommentDescrTrailingCommaFix (
   }
 }
 
+static void LookForGeneOverlapChange (
+  SeqFeatPtr sfp,
+  Pointer userdata
+)
+
+{
+  ChangeDataPtr  cdp;
+  SeqFeatPtr     gene1, gene2;
+  GeneRefPtr     grp;
+  ThrdDataPtr    tdp;
+
+  if (sfp == NULL) return;
+  cdp = (ChangeDataPtr) userdata;
+  if (cdp == NULL) return;
+  tdp = cdp->tdp;
+  if (tdp == NULL) return;
+
+  if (sfp->data.choice != SEQFEAT_CDREGION) return;
+
+  grp = SeqMgrGetGeneXref (sfp);
+  if (grp != NULL) return;
+
+  gene1 = SeqMgrGetOverlappingFeature (sfp->location, FEATDEF_GENE, NULL, 0, NULL, CONTAINED_WITHIN, NULL);
+  gene2 = SeqMgrGetOverlappingFeature (sfp->location, FEATDEF_GENE, NULL, 0, NULL, LOCATION_SUBSET, NULL);
+
+  if (gene1 != gene2) {
+    if (tdp->verbose) {
+      TSPrintLine (tdp->fp, "OVL", tdp->id, NULL, NULL, "\t");
+    } else {
+      TSPrintLine (tdp->fp, "OVL", tdp->id, NULL, NULL, " ");
+    }
+  }
+}
+
 static void StripBadProtTitles (
   BioseqPtr bsp,
   Pointer userdata
@@ -1535,6 +1572,7 @@ static void DoReport (
   VisitFeaturesInSep (sep, (Pointer) &cdbefore, FindCommaInGene);
   VisitFeaturesInSep (sep, (Pointer) &cdbefore, FindMuidCitations);
   VisitGraphsInSep (sep, (Pointer) &cdbefore, FindWholeGraphLocs);
+  VisitFeaturesInSep (sep, (Pointer) &cdbefore, LookForGeneOverlapChange);
 
   tmp = Se2Bs (sep);
   if (! BSEqual (bs, tmp)) {
@@ -1715,7 +1753,7 @@ static void DoReport (
       TSPrintLine (tdp->fp, "RDBX", tdp->id, NULL, NULL, " ");
     }
     if (cdbefore.srcDbxref) {
-      TSPrintLine (tdp->fp, "XXXXX", tdp->id, NULL, NULL, " ");
+      TSPrintLine (tdp->fp, "SDBX", tdp->id, NULL, NULL, " ");
     }
     if (cdbefore.capDbxref) {
       TSPrintLine (tdp->fp, "CDBX", tdp->id, NULL, NULL, " ");
diff --git a/demo/src_chk.c b/demo/src_chk.c
index 57741db..5b80ffe 100755
--- a/demo/src_chk.c
+++ b/demo/src_chk.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/12/07
 *
-* $Revision: 1.11 $
+* $Revision: 1.23 $
 *
 * File Description: 
 *
@@ -64,179 +64,362 @@
 
 CharPtr SRC_CHK_APPLICATION = SRC_CHK_APP_VER;
 
-#ifdef INTERNAL_NCBI_SRC_CHK
-static CharPtr dirsubfetchproc = "DirSubBioseqFetch";
+static Boolean debug_mode = FALSE;
+
+static Boolean IsAllDigits (CharPtr str)
+{
+  CharPtr cp;
 
-static CharPtr dirsubfetchcmd = NULL;
+  if (StringHasNoText (str)) return FALSE;
 
-extern Pointer ReadFromDirSub (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID);
-extern Pointer ReadFromDirSub (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID)
+  cp = str;
+  while (*cp != 0 && isdigit (*cp)) {
+    cp++;
+  }
+  if (*cp == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
 
+
+static SeqIdPtr SmartGuessMakeId (CharPtr str)
 {
-  Char     cmmd [256];
-  Pointer  dataptr;
-  FILE*    fp;
-  Char     path [PATH_MAX];
+  CharPtr id_txt;
+  SeqIdPtr sip = NULL;
 
-  if (datatype != NULL) {
-    *datatype = 0;
+  if (StringHasNoText (str)) {
+    return NULL;
+  } else if (StringChr (str, '|') != NULL) {
+    sip = MakeSeqID (str);
+  } else if (IsAllDigits (str)) {
+    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 4));
+    sprintf (id_txt, "gi|%s", str);
+    sip = MakeSeqID (id_txt);
+    id_txt = MemFree (id_txt);
+  } else if (StringChr (str, '_') != NULL) {
+    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 5));
+    sprintf (id_txt, "oth|%s", str);
+    sip = MakeSeqID (id_txt);
+    id_txt = MemFree (id_txt);
+  } else {
+    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 4));
+    sprintf (id_txt, "gb|%s", str);
+    sip = MakeSeqID (id_txt);
+    id_txt = MemFree (id_txt);
   }
-  if (entityID != NULL) {
-    *entityID = 0;
+  return sip;
+}
+
+
+typedef struct fetchitem {
+  SeqIdPtr sip;
+  CharPtr  id_txt;
+  Int4     index_pos;
+  ValNodePtr field_values;
+} FetchItemData, PNTR FetchItemPtr;
+
+
+static FetchItemPtr FetchItemNew (CharPtr accn) 
+{
+  FetchItemPtr item;
+  
+  item = (FetchItemPtr) MemNew (sizeof (FetchItemData));
+  item->id_txt = StringSave (accn);
+  item->sip = SmartGuessMakeId(accn);
+  item->field_values = NULL;
+  item->index_pos = -1;
+  return item;
+}
+
+
+static ValNodePtr FetchItemFieldValuesFree (ValNodePtr field_values)
+{
+  ValNodePtr vnp;
+
+  for (vnp = field_values; vnp != NULL; vnp = vnp->next) {
+    vnp->data.ptrvalue = ValNodeFreeData (vnp->data.ptrvalue);
   }
-  if (StringHasNoText (accn)) return NULL;
+  field_values = ValNodeFree (field_values);
+  return field_values;
+}
+
 
-  if (dirsubfetchcmd == NULL) {
-    if (GetAppParam ("SEQUIN", "DIRSUB", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
-    	dirsubfetchcmd = StringSaveNoNull (cmmd);
+static FetchItemPtr FetchItemFree (FetchItemPtr item)
+{
+  if (item != NULL) {
+    item->id_txt = MemFree (item->id_txt);
+    item->sip = SeqIdFree (item->sip);
+    item->field_values = FetchItemFieldValuesFree (item->field_values);
+    item = MemFree (item);
     }
+  return item;
+}
+
+
+static ValNodePtr FetchItemListFree (ValNodePtr list)
+{
+  ValNodePtr list_next;
+
+  while (list != NULL) {
+    list_next = list->next;
+    list->next = NULL;
+    list->data.ptrvalue = FetchItemFree (list->data.ptrvalue);
+    list = ValNodeFree (list);
+    list = list_next;
   }
-  if (dirsubfetchcmd == NULL) return NULL;
+  return list;
+}
 
-  TmpNam (path);
 
-#ifdef OS_UNIX
-  sprintf (cmmd, "csh %s %s > %s", dirsubfetchcmd, accn, path);
-  system (cmmd);
-#endif
-#ifdef OS_MSWIN
-  sprintf (cmmd, "%s %s -o %s", dirsubfetchcmd, accn, path);
-  system (cmmd);
-#endif
+static int FetchItemCompare (FetchItemPtr f1, FetchItemPtr f2)
+{
+  if (f1 == NULL || f2 == NULL) {
+    return 0;
+  } else {
+    return StringCmp (f1->id_txt, f2->id_txt);
+  }
+}
 
-  fp = FileOpen (path, "r");
-  if (fp == NULL) {
-    FileRemove (path);
-    return NULL;
+
+static ValNodePtr FetchItemListFromFile (FILE *fp)
+{
+  CharPtr          line;
+  ReadBufferData   rbd;
+  ValNodePtr       list = NULL, prev = NULL, this_item;
+
+  rbd.fp = fp;
+  rbd.current_data = NULL;
+  line = AbstractReadFunction (&rbd);  
+  while (line != NULL && line[0] != EOF) {
+    if (!StringHasNoText (line)) {
+      this_item = ValNodeNew (NULL);
+      this_item->data.ptrvalue = FetchItemNew (line);
+      if (prev == NULL) {
+        list = this_item;
+      } else {
+        prev->next = this_item;
   }
-  dataptr = ReadAsnFastaOrFlatFile (fp, datatype, entityID, FALSE, FALSE, TRUE, FALSE);
-  FileClose (fp);
-  FileRemove (path);
-  return dataptr;
+      prev = this_item;
+    }
+    line = MemFree (line);
+    line = AbstractReadFunction (&rbd);
+  }
+  return list;
 }
 
 
-static Int2 LIBCALLBACK DirSubBioseqFetchFunc (Pointer data)
+static void ResetFetchItemListIndex (ValNodePtr list)
+{
+  FetchItemPtr fetch_item;
+
+  while (list != NULL) {
+    fetch_item = (FetchItemPtr) list->data.ptrvalue;
+    if (fetch_item != NULL) {
+      fetch_item->index_pos = -1;
+    } 
+    list = list->next;
+  }
+}
+
 
+static void FetchItemFieldValuesPrint (FILE *fp, ValNodePtr field_values)
 {
-  BioseqPtr         bsp;
-  Char              cmmd [256];
-  Pointer           dataptr;
-  Uint2             datatype;
-  Uint2             entityID;
-  FILE*             fp;
-  OMProcControlPtr  ompcp;
-  ObjMgrProcPtr     ompp;
-  Char              path [PATH_MAX];
-  SeqEntryPtr       sep = NULL;
-  SeqIdPtr          sip;
-  TextSeqIdPtr      tsip;
+  ValNodePtr vnp, vnp_val;
 
-  ompcp = (OMProcControlPtr) data;
-  if (ompcp == NULL) return OM_MSG_RET_ERROR;
-  ompp = ompcp->proc;
-  if (ompp == NULL) return OM_MSG_RET_ERROR;
-  sip = (SeqIdPtr) ompcp->input_data;
-  if (sip == NULL) return OM_MSG_RET_ERROR;
+  for (vnp = field_values; vnp != NULL; vnp = vnp->next) {
+    for (vnp_val = vnp->data.ptrvalue; vnp_val != NULL; vnp_val = vnp_val->next) {
+      fprintf (fp, "%s%s", vnp_val->data.ptrvalue == NULL ? "" : vnp_val->data.ptrvalue, vnp_val->next == NULL ? "\n" : "\t");
+    }
+  }
+}
 
-  if (sip->choice != SEQID_GENBANK) return OM_MSG_RET_ERROR;
-  tsip = (TextSeqIdPtr) sip->data.ptrvalue;
-  if (tsip == NULL || StringHasNoText (tsip->accession)) return OM_MSG_RET_ERROR;
 
-  if (dirsubfetchcmd == NULL) {
-    if (GetAppParam ("SEQUIN", "DIRSUB", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
-    	dirsubfetchcmd = StringSaveNoNull (cmmd);
+static int LIBCALLBACK SortVnpByFetchItem (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      return FetchItemCompare (vnp1->data.ptrvalue, vnp2->data.ptrvalue);
     }
   }
-  if (dirsubfetchcmd == NULL) return OM_MSG_RET_ERROR;
+  return 0;
+}
 
-  TmpNam (path);
 
-#ifdef OS_UNIX
-  sprintf (cmmd, "csh %s %s > %s", dirsubfetchcmd, tsip->accession, path);
-  system (cmmd);
-#endif
-#ifdef OS_MSWIN
-  sprintf (cmmd, "%s %s -o %s", dirsubfetchcmd, tsip->accession, path);
-  system (cmmd);
-#endif
+static FetchItemPtr PNTR sFetchIndex = NULL;
+static Int4 sFetchIndexSize = 0;
 
-  fp = FileOpen (path, "r");
-  if (fp == NULL) {
-    FileRemove (path);
-    return OM_MSG_RET_ERROR;
+static void MakeFetchItemIndex(ValNodePtr fetch_list)
+{
+  Int4 num;
+  ValNodePtr tmp_list = NULL, prev = NULL, vnp, vnp_new;
+
+  if (sFetchIndex != NULL) {
+    sFetchIndex = MemFree (sFetchIndex);
+    sFetchIndexSize = 0;
   }
-  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
-  FileClose (fp);
-  FileRemove (path);
 
-  if (dataptr == NULL) return OM_MSG_RET_OK;
+  if (fetch_list == NULL) {
+    return;
+  }
 
-  sep = GetTopSeqEntryForEntityID (entityID);
-  if (sep == NULL) return OM_MSG_RET_ERROR;
-  bsp = BioseqFindInSeqEntry (sip, sep);
-  ompcp->output_data = (Pointer) bsp;
-  ompcp->output_entityID = ObjMgrGetEntityIDForChoice (sep);
-  return OM_MSG_RET_DONE;
+  tmp_list = ValNodeNew (NULL);
+  tmp_list->data.ptrvalue = fetch_list->data.ptrvalue;
+  prev = tmp_list;
+  for (vnp = fetch_list->next; vnp != NULL; vnp = vnp->next) {
+    vnp_new = ValNodeNew (prev);
+    vnp_new->data.ptrvalue = vnp->data.ptrvalue;
+    prev = vnp_new;
+  }
+
+  tmp_list = ValNodeSort (tmp_list, SortVnpByFetchItem);
+  sFetchIndexSize = ValNodeLen (tmp_list);
+  sFetchIndex = (FetchItemPtr PNTR) MemNew (sizeof (FetchItemPtr) * sFetchIndexSize);
+  for (vnp = tmp_list, num = 0; vnp != NULL; vnp = vnp->next, num++) {
+    sFetchIndex[num] = vnp->data.ptrvalue;
+  }
+  tmp_list = ValNodeFree (tmp_list);
 }
 
-static Boolean DirSubFetchEnable (void)
 
+static FetchItemPtr FindInFetchIndex (CharPtr str)
 {
-  ObjMgrProcLoad (OMPROC_FETCH, dirsubfetchproc, dirsubfetchproc,
-                  OBJ_SEQID, 0, OBJ_BIOSEQ, 0, NULL,
-                  DirSubBioseqFetchFunc, PROC_PRIORITY_DEFAULT);
-  return TRUE;
+  Int4 imin = 0;
+  Int4 imax = sFetchIndexSize - 1;
+  Int4 num = -1, i, j;
+  FetchItemPtr fetch_item;
+  CharPtr      tmp;
+
+  while (imax >= imin)
+  {
+    i = (imax + imin)/2;
+    tmp = sFetchIndex[i]->id_txt;
+    if ((j = StringCmp(tmp, str)) > 0)
+      imax = i - 1;
+    else if (j < 0)
+      imin = i + 1;
+    else
+    {
+      num = i;
+      break;
+    }
+  }
+  if (num == -1) {
+    return NULL;
+  } else {
+    return sFetchIndex[num];
+  }
 }
 
+
+#ifdef INTERNAL_NCBI_SRC_CHK
+
 static CharPtr smartfetchproc = "SmartBioseqFetch";
 
+static CharPtr srcchkfetchcmd = NULL;
 static CharPtr smartfetchcmd = NULL;
 
-extern Pointer ReadFromSmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID);
-extern Pointer ReadFromSmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID)
 
+static Int4 NumInSet (BioseqSetPtr bssp)
+{
+  SeqEntryPtr  sep;
+  Int4         num = 0;
+
+  if (bssp != NULL) {
+    sep = bssp->seq_set;
+    while (sep != NULL) {
+      num++;
+      sep = sep->next;
+    }
+  }
+  return num;
+}
+   
+
+static BioseqPtr FetchBioseqFromSmartNotId (CharPtr accn, Uint2Ptr pEntityID)
 {
+  BioseqPtr         bsp;
   Char     cmmd [256];
   Pointer  dataptr;
+  Uint2             datatype;
+  Uint2             entityID;
   FILE*    fp;
+  OMProcControlPtr  ompcp;
+  ObjMgrProcPtr     ompp;
   Char     path [PATH_MAX];
+  Char              err_path [PATH_MAX];
+  SeqEntryPtr       sep = NULL;
+  SeqIdPtr          sip;
+  TextSeqIdPtr      tsip;
+  Int4              gi = 0;
+  ValNodePtr        vnp;
+  time_t            t1, t2;
 
-  if (datatype != NULL) {
-    *datatype = 0;
+  if (srcchkfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "SRC_CHK", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+    	srcchkfetchcmd = StringSaveNoNull (cmmd);
   }
-  if (entityID != NULL) {
-    *entityID = 0;
   }
-  if (StringHasNoText (accn)) return NULL;
-
-  if (smartfetchcmd == NULL) {
+  if (srcchkfetchcmd == NULL) {
     if (GetAppParam ("SEQUIN", "SMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
-    	smartfetchcmd = StringSaveNoNull (cmmd);
+    	srcchkfetchcmd = StringSaveNoNull (cmmd);
     }
   }
-  if (smartfetchcmd == NULL) return NULL;
+  if (srcchkfetchcmd == NULL) return NULL;
 
   TmpNam (path);
 
+  t1 = time(NULL);
 #ifdef OS_UNIX
-  sprintf (cmmd, "csh %s %s > %s", smartfetchcmd, accn, path);
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", srcchkfetchcmd, accn, path, err_path);
   system (cmmd);
 #endif
 #ifdef OS_MSWIN
-  sprintf (cmmd, "%s %s -o %s", smartfetchcmd, accn, path);
+  sprintf (cmmd, "%s %s -o %s", srcchkfetchcmd, accn, path);
   system (cmmd);
 #endif
 
   fp = FileOpen (path, "r");
   if (fp == NULL) {
     FileRemove (path);
-    return NULL;
+#ifdef OS_UNIX
+    FileRemove (err_path);
+#endif
+    return OM_MSG_RET_ERROR;
   }
-  dataptr = ReadAsnFastaOrFlatFile (fp, datatype, entityID, FALSE, FALSE, TRUE, FALSE);
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
   FileClose (fp);
   FileRemove (path);
-  return dataptr;
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
+
+  if (dataptr == NULL) return NULL;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+
+  if (sep == NULL) return NULL;
+  sip = SmartGuessMakeId (accn);
+  bsp = BioseqFindInSeqEntry (sip, sep);
+  sip = SeqIdFree (sip);
+  if (debug_mode) {
+    t2 = time(NULL);
+    if (t2 - t1 > 1) {
+      printf("Time to download %s from SMART:%d\n", accn, t2 - t1);
+    }
+  }
+  if (pEntityID != NULL) {
+    *pEntityID = entityID;
+  }
+  return bsp;
 }
 
 
@@ -252,9 +435,12 @@ static Int2 LIBCALLBACK SmartBioseqFetchFunc (Pointer data)
   OMProcControlPtr  ompcp;
   ObjMgrProcPtr     ompp;
   Char              path [PATH_MAX];
+  Char              err_path [PATH_MAX];
   SeqEntryPtr       sep = NULL;
   SeqIdPtr          sip;
   TextSeqIdPtr      tsip;
+  Int4              gi = 0;
+  ValNodePtr        vnp;
 
   ompcp = (OMProcControlPtr) data;
   if (ompcp == NULL) return OM_MSG_RET_ERROR;
@@ -277,7 +463,8 @@ static Int2 LIBCALLBACK SmartBioseqFetchFunc (Pointer data)
   TmpNam (path);
 
 #ifdef OS_UNIX
-  sprintf (cmmd, "csh %s %s > %s", smartfetchcmd, tsip->accession, path);
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", smartfetchcmd, tsip->accession, path, err_path);
   system (cmmd);
 #endif
 #ifdef OS_MSWIN
@@ -288,15 +475,22 @@ static Int2 LIBCALLBACK SmartBioseqFetchFunc (Pointer data)
   fp = FileOpen (path, "r");
   if (fp == NULL) {
     FileRemove (path);
+#ifdef OS_UNIX
+    FileRemove (err_path);
+#endif
     return OM_MSG_RET_ERROR;
   }
   dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
   FileClose (fp);
   FileRemove (path);
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
 
   if (dataptr == NULL) return OM_MSG_RET_OK;
 
   sep = GetTopSeqEntryForEntityID (entityID);
+
   if (sep == NULL) return OM_MSG_RET_ERROR;
   bsp = BioseqFindInSeqEntry (sip, sep);
   ompcp->output_data = (Pointer) bsp;
@@ -325,6 +519,7 @@ extern Pointer ReadFromTPASmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entit
   Pointer  dataptr;
   FILE*    fp;
   Char     path [PATH_MAX];
+  Char     err_path [PATH_MAX];
 
   if (datatype != NULL) {
     *datatype = 0;
@@ -344,7 +539,8 @@ extern Pointer ReadFromTPASmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entit
   TmpNam (path);
 
 #ifdef OS_UNIX
-  sprintf (cmmd, "csh %s %s > %s", tpasmartfetchcmd, accn, path);
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", tpasmartfetchcmd, accn, path, err_path);
   system (cmmd);
 #endif
 #ifdef OS_MSWIN
@@ -360,6 +556,9 @@ extern Pointer ReadFromTPASmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entit
   dataptr = ReadAsnFastaOrFlatFile (fp, datatype, entityID, FALSE, FALSE, TRUE, FALSE);
   FileClose (fp);
   FileRemove (path);
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
   return dataptr;
 }
 
@@ -376,6 +575,7 @@ static Int2 LIBCALLBACK TPASmartBioseqFetchFunc (Pointer data)
   OMProcControlPtr  ompcp;
   ObjMgrProcPtr     ompp;
   Char              path [PATH_MAX];
+  Char              err_path [PATH_MAX];
   SeqEntryPtr       sep = NULL;
   SeqIdPtr          sip;
   TextSeqIdPtr      tsip;
@@ -401,7 +601,8 @@ static Int2 LIBCALLBACK TPASmartBioseqFetchFunc (Pointer data)
   TmpNam (path);
 
 #ifdef OS_UNIX
-  sprintf (cmmd, "csh %s %s > %s", tpasmartfetchcmd, tsip->accession, path);
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", tpasmartfetchcmd, tsip->accession, path, err_path);
   system (cmmd);
 #endif
 #ifdef OS_MSWIN
@@ -412,11 +613,17 @@ static Int2 LIBCALLBACK TPASmartBioseqFetchFunc (Pointer data)
   fp = FileOpen (path, "r");
   if (fp == NULL) {
     FileRemove (path);
+#ifdef OS_UNIX
+    FileRemove (err_path);
+#endif
     return OM_MSG_RET_ERROR;
   }
   dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
   FileClose (fp);
   FileRemove (path);
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
 
   if (dataptr == NULL) return OM_MSG_RET_OK;
 
@@ -498,6 +705,174 @@ static Int4 GetTaxIdFromOrgRef (OrgRefPtr orp)
 }
 
 
+static ValNodePtr CollectBioSourceValues (BioSourcePtr biop, ValNodePtr field_list)
+{
+  Char       taxid_buf[30];
+  ValNodePtr field_values = NULL;
+  CharPtr    txt;
+
+  sprintf (taxid_buf, "%d", GetTaxIdFromOrgRef(biop->org));
+  ValNodeAddPointer (&field_values, 0, StringSave (taxid_buf));
+ 
+  while (field_list != NULL) {
+    txt = GetSourceQualFromBioSource (biop, field_list->data.ptrvalue, NULL);
+    ValNodeAddPointer (&field_values, 0, txt);
+    field_list = field_list->next;
+  }
+  return field_values;
+}
+
+
+static ValNodePtr CollectBioseqLineValues (BioseqPtr bsp, ValNodePtr field_list, Boolean want_gi)
+{
+  SeqDescrPtr       sdp;
+  SeqMgrDescContext dcontext;
+  Char              id_txt[255], id_txt2[255];
+  SeqIdPtr          sip, sip_gi = NULL, sip_gb = NULL;
+  ValNodePtr        line_list = NULL, line_values;
+
+  if (bsp == NULL) {
+    return NULL;
+  }
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_GENBANK
+        || (sip->choice == SEQID_EMBL && sip_gb == NULL)
+        || (sip->choice == SEQID_SWISSPROT && sip_gb == NULL)
+        || (sip->choice == SEQID_DDBJ && sip_gb == NULL)
+        || (sip->choice == SEQID_PIR && sip_gb == NULL)) {
+      sip_gb = sip;
+    } else if (sip->choice == SEQID_GI) {
+      sip_gi = sip;
+    }
+  }
+
+  if (sip_gb == NULL && sip_gi == NULL) {
+    SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+    id_txt2[0] = 0;
+  } else {
+    if (sip_gb == NULL) {
+      id_txt[0] = 0;
+    } else {
+      SeqIdWrite (sip_gb, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+    }
+    if (sip_gi == NULL) {
+      id_txt2[0] = 0;
+    } else {
+      SeqIdWrite (sip_gi, id_txt2, PRINTID_REPORT, sizeof (id_txt2) - 1);
+    }
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_source, &dcontext)) {
+    line_values = NULL;
+    ValNodeAddPointer (&line_values, 0, StringSave (id_txt));
+    if (want_gi) {
+      ValNodeAddPointer (&line_values, 0, StringSave (id_txt2));
+    }
+    ValNodeLink (&line_values, CollectBioSourceValues (sdp->data.ptrvalue, field_list));
+    ValNodeAddPointer (&line_list, 0, line_values);
+  }
+  return line_list;
+}
+
+
+#ifdef INTERNAL_NCBI_SRC_CHK
+
+typedef struct populate {
+  ValNodePtr field_list;
+  Boolean    want_gi;
+} PopulateData, PNTR PopulatePtr;
+
+static void PopulateFetchItemCallback (BioseqPtr bsp, Pointer data)
+{
+  PopulatePtr pp;
+  SeqIdPtr    sip;
+  TextSeqIdPtr tsip;
+  Char         buffer[15];
+  FetchItemPtr fetch_item = NULL;
+
+  if (bsp == NULL || ISA_aa(bsp->mol) || (pp = (PopulatePtr)data) == NULL) {
+    return;
+  }
+
+  for (sip = bsp->id; sip != NULL && fetch_item == NULL; sip = sip->next) {
+    switch (sip->choice) {
+      case SEQID_GI:
+        printf (buffer, "%d", sip->data.intvalue);
+        fetch_item = FindInFetchIndex(buffer);
+        break;
+      case SEQID_GENBANK :
+      case SEQID_EMBL :
+      case SEQID_DDBJ :
+      case SEQID_TPG :
+      case SEQID_TPE :
+      case SEQID_TPD :
+      case SEQID_OTHER :
+        tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+        if (tsip != NULL) {
+          fetch_item = FindInFetchIndex(tsip->accession);
+        }
+        break;
+      default :
+        break;
+    }
+  }
+
+  if (fetch_item != NULL && fetch_item->index_pos < 0) {
+    /* collect field values */
+    fetch_item->field_values = CollectBioseqLineValues (bsp, pp->field_list, pp->want_gi);
+    fetch_item->index_pos = 0;
+  }
+}
+
+
+static void PopulateFetchItemCache (Uint2 entityID, ValNodePtr fetch_list, ValNodePtr field_list, Boolean want_gi)
+{
+  SeqEntryPtr sep;
+  BioseqSetPtr bssp;
+  ValNodePtr   vnp;
+  FetchItemPtr fetch_item;
+  BioseqPtr    bsp;
+  time_t       t1, t2;
+  Int4         num_in_list, num_in_set;
+  PopulateData pd;
+
+  t1 = time(NULL);
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep != NULL && IS_Bioseq_set(sep) && (bssp = (BioseqSetPtr)sep->data.ptrvalue) != NULL
+      && bssp->_class != BioseqseqSet_class_nuc_prot) {
+    num_in_set = NumInSet (bssp);
+    if (num_in_set < sFetchIndexSize) {
+      for (vnp = fetch_list; vnp != NULL; vnp = vnp->next) {
+        fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+        if (fetch_item->index_pos < 0) {
+          bsp = BioseqFindInSeqEntry (fetch_item->sip, sep);
+          if (bsp != NULL) {
+            /* collect field values */
+            fetch_item->field_values = CollectBioseqLineValues (bsp, field_list, want_gi);
+            fetch_item->index_pos = 0;
+          }
+        }
+      }
+    } else {
+      pd.field_list = field_list;
+      pd.want_gi = want_gi;
+      VisitBioseqsInSep (sep, &pd, PopulateFetchItemCallback);
+    }     
+  }
+  if (debug_mode) {
+    t2 = time(NULL);
+    if (t2 - t1 > 2) {
+      printf ("Time to populate cache: %d\n", t2 - t1);
+    }
+  }
+}
+
+#endif
+
+
 static void PrintBioSourceLine (FILE *fp, BioSourcePtr biop, ValNodePtr field_list)
 {
   CharPtr txt;
@@ -517,14 +892,14 @@ static void PrintBioSourceLine (FILE *fp, BioSourcePtr biop, ValNodePtr field_li
 }
 
 
-static void PrintBioseqLines (FILE *fp, BioseqPtr bsp, ValNodePtr field_list)
+static void PrintBioseqLines (FILE *fp, BioseqPtr bsp, ValNodePtr field_list, Boolean want_gi)
 {
   SeqDescrPtr       sdp;
   SeqMgrDescContext dcontext;
   Char              id_txt[255], id_txt2[255];
   SeqIdPtr          sip, sip_gi = NULL, sip_gb = NULL;
 
-  if (fp == NULL || bsp == NULL || field_list == NULL) {
+  if (fp == NULL || bsp == NULL) {
     return;
   }
 
@@ -559,7 +934,11 @@ static void PrintBioseqLines (FILE *fp, BioseqPtr bsp, ValNodePtr field_list)
   for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
        sdp != NULL;
        sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_source, &dcontext)) {
+    if (want_gi) {
     fprintf (fp, "%s\t%s", id_txt, id_txt2);
+    } else {
+      fprintf (fp, "%s", id_txt);
+    }
     PrintBioSourceLine (fp, sdp->data.ptrvalue, field_list);
     fprintf (fp, "\n");
   }
@@ -584,58 +963,25 @@ static void PrintBioseqErrorLine (FILE *fp, SeqIdPtr sip)
 }
 
 
-static Boolean IsAllDigits (CharPtr str)
-{
-  CharPtr cp;
-
-  if (StringHasNoText (str)) return FALSE;
-
-  cp = str;
-  while (*cp != 0 && isdigit (*cp)) {
-    cp++;
-  }
-  if (*cp == 0) {
-    return TRUE;
-  } else {
-    return FALSE;
-  }
-}
-
-
-static SeqIdPtr SmartGuessMakeId (CharPtr str)
-{
-  CharPtr id_txt;
-  SeqIdPtr sip = NULL;
-
-  if (StringHasNoText (str)) {
-    return NULL;
-  } else if (StringChr (str, '|') != NULL) {
-    sip = MakeSeqID (str);
-  } else if (IsAllDigits (str)) {
-    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 4));
-    sprintf (id_txt, "gi|%s", str);
-    sip = MakeSeqID (id_txt);
-    id_txt = MemFree (id_txt);
-  } else {
-    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 4));
-    sprintf (id_txt, "gb|%s", str);
-    sip = MakeSeqID (id_txt);
-    id_txt = MemFree (id_txt);
-  }
-  return sip;
-}
-
-
 /* Args structure contains command-line arguments */
 
 #define i_argInputFile         0
 #define o_argOutputFile        1
+#define j_argJustAccessions    2
+#define f_argFieldList         3
+#define D_argDebugMode         4
 
 Args myargs [] = {
   {"Input File", NULL, NULL, NULL,
     TRUE, 'i', ARG_FILE_IN, 0.0, 0, NULL},
   {"Output File", NULL, NULL, NULL,
-    TRUE, 'o', ARG_FILE_OUT, 0.0, 0, NULL}
+    TRUE, 'o', ARG_FILE_OUT, 0.0, 0, NULL},
+  {"Just Accessions", "F", NULL, NULL,
+    TRUE, 'j', ARG_BOOLEAN, 0.0, 0, NULL},
+  {"Field List", NULL, NULL, NULL,
+    TRUE, 'f', ARG_STRING, 0.0, 0, NULL},
+  {"Debug Mode", "F", NULL, NULL,
+    TRUE, 'D', ARG_BOOLEAN, 0.0, 0, NULL}
 };
 
 
@@ -669,18 +1015,267 @@ static void SortFieldListForSrcChk (ValNodePtr PNTR field_list)
 }
 
 
+static ValNodePtr FieldsFromFieldListString (CharPtr str)
+{
+  CharPtr cpy, val, comma;
+  Int4    qual;
+  ValNodePtr field_list = NULL, qc;
+
+  if (StringHasNoText (str)) {
+    return NULL;
+  }
+  cpy = StringSave (str);
+  val = cpy;
+  comma = StringChr(val, ',');
+  while (comma != NULL) {
+    *comma = 0;
+    qual = GetSourceQualTypeByName(val);
+    if (qual < 0) {
+      Message (MSG_ERROR, "%s is not a recognized source field name", val);
+    } else {
+      qc = ValNodeNew (NULL);
+      qc->choice = SourceQualChoice_textqual;
+      qc->data.intvalue = qual;
+      ValNodeAddPointer (&field_list, FieldType_source_qual, qc);
+    }
+    *comma = ',';
+    val = comma + 1;
+    comma = StringChr (val, ',');
+  }
+
+  qual = GetSourceQualTypeByName(val);
+  if (qual < 0) {
+    Message (MSG_ERROR, "%s is not a recognized source field name", val);
+  } else {
+    qc = ValNodeNew (NULL);
+    qc->choice = SourceQualChoice_textqual;
+    qc->data.intvalue = qual;
+    ValNodeAddPointer (&field_list, FieldType_source_qual, qc);
+  }
+
+  cpy = MemFree (cpy);
+  return field_list;
+}
+
+
+static Boolean PvtStrToLong (CharPtr str, Int4Ptr longval)
+
+{
+   Char     ch;
+   Int2     i;
+   Int2     len;
+   Char     local [64];
+   Boolean  nodigits;
+   Boolean  rsult;
+   long int     val;
+
+   rsult = FALSE;
+   if (longval != NULL) {
+     *longval = (Int4) 0;
+   }
+   len = (Int2) StringLen (str);
+   if (len != 0) {
+     rsult = TRUE;
+     nodigits = TRUE;
+     for (i = 0; i < len; i++) {
+       ch = str [i];
+       if (ch == ' ' || ch == '+' || ch == '-') {
+       } else if (ch < '0' || ch > '9') {
+         rsult = FALSE;
+       } else {
+         nodigits = FALSE;
+       }
+     }
+     if (nodigits) {
+       rsult = FALSE;
+     }
+     if (rsult && longval != NULL) {
+       StringNCpy_0 (local, str, sizeof (local));
+       if (sscanf (local, "%ld", &val) == 1) {
+         *longval = val;
+       }
+     }
+   }
+   return rsult;
+}
+
+static Int4 AccessionToGi (CharPtr string)
+
+{
+    Int4      gi;
+    SeqIdPtr  sip;
+
+    sip = SeqIdFromAccessionDotVersion (string);
+    if (sip == NULL) return 0;
+    gi = GetGIForSeqId (sip);
+    SeqIdFree (sip);
+    return gi;
+}
+
+
+static BioseqPtr FetchOnlyBioseqFromID (CharPtr str)
+{
+   BioseqPtr    bsp = NULL;
+   Uint2        entityID;
+   SeqEntryPtr  sep;
+   SeqIdPtr     sip = NULL;
+   Int4         uid;
+   time_t       t1, t2;
+
+   t1 = time (NULL);
+   uid = 0;
+   TrimSpacesAroundString (str);
+   if (IsAllDigits (str)) {
+     if (PvtStrToLong (str, &uid)) {
+       sip = ValNodeNew(NULL);
+       sip->choice = SEQID_GI;
+       sip->data.intvalue = uid;
+     } else {
+      uid = 0;
+     }
+   } else {
+     sip = SeqIdFromAccessionDotVersion (str);
+     uid = AccessionToGi (str);
+   }
+   sep = NULL;
+   if (uid > 0) {
+     sep = PubSeqSynchronousQuery (uid, 3, 0); /* retcode was 0 */
+     if (sep != NULL) {
+       bsp = BioseqFindInSeqEntry (sip, sep);
+       entityID = ObjMgrGetEntityIDForChoice (sep); 
+     }
+   }
+   sip = SeqIdFree (sip);
+   if (debug_mode) {
+    t2 = time (NULL);
+    if (t2 - t1 > 1) {
+      printf ("Time to download %s from ID:%d\n", str, t2 - t1);
+    }
+   }
+   return bsp;
+}
+
+
+static void CollectFieldsInFetchItemCache (Uint2 entityID, ValNodePtr PNTR field_list, ValNodePtr fetch_list)
+{
+  SeqEntryPtr sep;
+  BioseqSetPtr bssp;
+  ValNodePtr   vnp;
+  FetchItemPtr fetch_item;
+  BioseqPtr    bsp;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep != NULL && IS_Bioseq_set(sep) && (bssp = (BioseqSetPtr)sep->data.ptrvalue) != NULL
+      && bssp->_class != BioseqseqSet_class_nuc_prot) {
+    for (vnp = fetch_list; vnp != NULL; vnp = vnp->next) {
+      fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+      if (fetch_item->index_pos < 0) {
+        bsp = BioseqFindInSeqEntry (fetch_item->sip, sep);
+        if (bsp != NULL) {
+          ValNodeLink (field_list, CollectFieldList(bsp));
+          fetch_item->index_pos = 0;
+        }
+      }
+    }
+  }
+}
+
+
+static ValNodePtr CollectBioseqFieldsWithCaching (ValNodePtr fetch_list) 
+{
+  ValNodePtr   vnp;
+  ValNodePtr   field_list = NULL;
+  BioseqPtr    bsp;
+  FetchItemPtr fetch_item;
+  Uint2        entityID;
+
+  for (vnp = fetch_list; vnp != NULL; vnp = vnp->next) {
+    fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+    if (fetch_item->index_pos < 0) {
+      entityID = 0;
+#ifdef INTERNAL_NCBI_SRC_CHK
+      bsp = FetchBioseqFromSmartNotId (fetch_item->id_txt, &entityID);
+      if (bsp != NULL) {
+        CollectFieldsInFetchItemCache (entityID, &field_list, vnp->next);
+      } else {
+        bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+      }
+#else
+      bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+#endif
+      ValNodeLink (&field_list, CollectFieldList(bsp));
+    }
+  }
+  ResetFetchItemListIndex (fetch_list);
+  return field_list;
+}
+
+
+static Int2 ProcessBioseqsWithCaching (ValNodePtr fetch_list, ValNodePtr field_list, Boolean just_acc, FILE *out)
+{
+  ValNodePtr vnp;
+  BioseqPtr  bsp;
+  FetchItemPtr fetch_item;
+  Uint2        entityID;
+  Int4         num_processed = 0;
+  time_t       t, last_t;
+
+  last_t = time(NULL);
+  for (vnp = fetch_list; vnp != NULL; vnp = vnp->next) {
+    fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+    if (fetch_item->index_pos < 0) {
+      entityID = 0;
+#ifdef INTERNAL_NCBI_SRC_CHK
+      bsp = FetchBioseqFromSmartNotId (fetch_item->id_txt, &entityID);
+      if (bsp != NULL) {
+        PopulateFetchItemCache (entityID, vnp->next, field_list, !just_acc);
+      } else {
+        bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+        if (bsp == NULL) {
+          printf ("Unable to download Bioseq for %s\n", fetch_item->id_txt);
+        }
+      }
+#else
+      bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+#endif
+      fetch_item->field_values = CollectBioseqLineValues (bsp, field_list, !just_acc);
+    }
+    if (fetch_item->field_values == NULL) {
+      fprintf (out, "%s\n", fetch_item->id_txt);
+    } else {
+      FetchItemFieldValuesPrint (out, fetch_item->field_values);
+      fetch_item->field_values = FetchItemFieldValuesFree (fetch_item->field_values);
+    }
+    fflush(out);
+    if (debug_mode) {
+      num_processed++;
+      if (num_processed == 10) {
+        t = time (NULL);
+        printf ("Time to process %d: %d\n", num_processed, t - last_t); 
+        num_processed = 0;
+        last_t = t;
+      }    
+    }
+  }
+
+  return 0;
+}
+
+
 Int2 Main(void)
 {
   Char             app [64];
   Int4             rval = 0;
   CharPtr          id_file, line;
   ReadBufferData   rbd;
+  ValNodePtr       fetch_list = NULL;
   ValNodePtr       field_list = NULL;
   SeqIdPtr         sip;
   ValNodePtr       bsp_list = NULL, vnp;
   BioseqPtr        bsp;
   FILE *fp;
-
+  Boolean          just_acc = FALSE;
+  CharPtr          desired_fields;
 
   /* standard setup */
 
@@ -713,7 +1308,6 @@ Int2 Main(void)
   }
 
 #ifdef INTERNAL_NCBI_SRC_CHK
-    DirSubFetchEnable ();
     SmartFetchEnable ();
     TPASmartFetchEnable ();
 
@@ -732,56 +1326,49 @@ Int2 Main(void)
     return 0;
   }
 
+  just_acc = (Boolean) myargs [j_argJustAccessions].intvalue;
+  desired_fields = (CharPtr) myargs [f_argFieldList].strvalue;
   id_file = (CharPtr) myargs [i_argInputFile].strvalue;
+  debug_mode = (Boolean) myargs [D_argDebugMode].intvalue;
 
-  rbd.fp = FileOpen (id_file, "r");
-  if (rbd.fp == NULL) {
-    Message (MSG_ERROR, "Unable to open %s", (CharPtr) myargs [i_argInputFile].strvalue);
+  fp = FileOpen (id_file, "r");
+  if (fp == NULL) {
+    Message (MSG_ERROR, "Unable to open %s", id_file);
     return 1;
   }
-  rbd.current_data = NULL;
-  line = AbstractReadFunction (&rbd);  
-  while (line != NULL && line[0] != EOF) {
-    if (!StringHasNoText (line)) {
 
-      sip = SmartGuessMakeId (line);
-      bsp = BioseqLockById (sip);
-      if (bsp == NULL) {
-        printf ("Unable to download Bioseq for %s\n", line);
-      } else {
-        ValNodeLink (&field_list, CollectFieldList (bsp));
-        BioseqUnlock (bsp);
-      }
-      ValNodeAddPointer (&bsp_list, 0, sip);
-    }
-    line = MemFree (line);
-    line = AbstractReadFunction (&rbd);
-  }
+  fetch_list = FetchItemListFromFile (fp);
+  FileClose (fp);
 
-  FileClose (rbd.fp);
+  MakeFetchItemIndex(fetch_list);
+
+  if (just_acc) {
+    /* don't need to pre-collect */
+  } else if (!StringHasNoText (desired_fields)) {
+    /* don't need to pre-collect, create list from string */
+    field_list = FieldsFromFieldListString (desired_fields);
+  } else {
+    field_list = CollectBioseqFieldsWithCaching (fetch_list); 
 
   SortFieldListForSrcChk (&field_list);
+  }
 
   fp = FileOpen ((CharPtr) myargs [o_argOutputFile].strvalue, "w");
   if (fp == NULL) {
     Message (MSG_ERROR, "Unable to open %s", (CharPtr) myargs [o_argOutputFile].strvalue);
     rval = 1;
   } else {
+    if (!just_acc) {
     PrintHeader (fp, field_list);
-    for (vnp = bsp_list; vnp != NULL; vnp = vnp->next) {
-      bsp = BioseqLockById (vnp->data.ptrvalue);
-      if (bsp == NULL) {
-        PrintBioseqErrorLine (fp, vnp->data.ptrvalue);
-      } else {
-        PrintBioseqLines (fp, bsp, field_list);
-      }
-      BioseqUnlock (bsp);
-      vnp->data.ptrvalue = SeqIdFree (vnp->data.ptrvalue);
     }
+    ProcessBioseqsWithCaching (fetch_list, field_list, just_acc, fp);
   }
   FileClose (fp);
   bsp_list = ValNodeFree (bsp_list);
   field_list = FieldTypeListFree (field_list);
+  fetch_list = FetchItemListFree (fetch_list);
+  MakeFetchItemIndex(NULL);
 
   return rval;
 }
+
diff --git a/demo/tbl2asn.c b/demo/tbl2asn.c
index ceae97b..11c2f82 100644
--- a/demo/tbl2asn.c
+++ b/demo/tbl2asn.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   5/5/00
 *
-* $Revision: 6.297 $
+* $Revision: 6.327 $
 *
 * File Description:
 *
@@ -73,7 +73,7 @@ static char *date_of_compilation = __DATE__;
 #include <objmacro.h>
 #include <macroapi.h>
 
-#define TBL2ASN_APP_VER "14.3"
+#define TBL2ASN_APP_VER "15.4"
 
 CharPtr TBL2ASN_APPLICATION = TBL2ASN_APP_VER;
 
@@ -83,6 +83,7 @@ typedef struct cleanupargs {
   Boolean add_notes_to_overlapping_cds_without_abc;
   Boolean extend_partial_features_to_gaps_or_ends;
   Boolean add_exception_to_nonextendable_partials;
+  Boolean add_exception_to_short_introns;
   FILE *  cleanup_log;
 } CleanupArgsData, PNTR CleanupArgsPtr;
 
@@ -96,6 +97,7 @@ typedef struct tblargs {
   Boolean     alignset;
   Boolean     gapped;
   Boolean     phrapace;
+  Boolean     ftable;
   Boolean     genprodset;
   Boolean     linkbyoverlap;
   Boolean     linkbyproduct;
@@ -108,6 +110,7 @@ typedef struct tblargs {
   Boolean     dopublookup;
   CharPtr     accn;
   CharPtr     center;
+  Int4        project_version;
   CharPtr     organism;
   CharPtr     srcquals;
   CharPtr     comment;
@@ -1031,6 +1034,8 @@ static void PrintOneGeneLine (
   SeqIdPtr      sip;
   CharPtr       str;
   TextSeqIdPtr  tsip;
+  RnaRefPtr     rrp;
+  RNAGenPtr     rgp;
 
   if (fp == NULL) return; 
 
@@ -1142,6 +1147,13 @@ static void PrintOneGeneLine (
             rna_type = gbq->val;
           }
         }
+        if (rna->data.choice == SEQFEAT_RNA 
+            && (rrp = (RnaRefPtr) rna->data.value.ptrvalue) != NULL
+            && rrp->ext.choice == 3
+            && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL
+            && StringDoesHaveText (rgp->_class)) {
+          rna_type = rgp->_class;
+        }            
         break;
       case FEATDEF_tmRNA :
         rna_type = "tmRNA";
@@ -1295,7 +1307,7 @@ static void GeneReportOneBsp (
   SeqMgrFeatContext  fcontext;
   GmcDataPtr         gdp, head;
   GeneRefPtr         grp;
-  Int2               i, j, k, numgene, numcds, numrna, total;
+  Int2               i, j = 1, k, numgene, numcds, numrna, total;
   SeqFeatPtr         matchsfp, sfp, tmp;
   SeqFeatXrefPtr     xref;
 
@@ -1331,7 +1343,6 @@ static void GeneReportOneBsp (
   if (head == NULL) return;
 
   gdp = head;
-  total = 0;
   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
   while (sfp != NULL) {
     if (sfp->data.choice == SEQFEAT_CDREGION || sfp->data.choice == SEQFEAT_RNA) {
@@ -1348,11 +1359,9 @@ static void GeneReportOneBsp (
         }
       }
       gdp++;
-      total++;
     } else if (sfp->data.choice == SEQFEAT_GENE) {
       gdp->gene = sfp;
       gdp++;
-      total++;
     }
     sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
   }
@@ -1647,7 +1656,7 @@ static void EnhanceOneRna (
               StringCat (nwstr, tmp);
               if (nm_gbq != NULL) {
                 nm_gbq->val = (Pointer) nwstr;
-              } else {
+              } else if (rrp != NULL) {
                 rrp->ext.value.ptrvalue = (Pointer) nwstr;
               }
               MemFree (name);
@@ -1667,7 +1676,7 @@ static void EnhanceOneRna (
             StringCat (nwstr, str);
             if (nm_gbq != NULL) {
               nm_gbq->val = (Pointer) nwstr;
-            } else {
+            } else if (rrp != NULL) {
               rrp->ext.value.ptrvalue = (Pointer) nwstr;
             }
             MemFree (name);
@@ -2032,96 +2041,6 @@ static void GetFirstBiop (
   *biopp = biop;
 }
 
-static DatePtr DateParse (
-  CharPtr str
-)
-
-{
-  Int4      day = -1, month = -1, year = -1;
-  DatePtr   dp;
-  CharPtr   ptr;
-  Char      tmp [64];
-  long int  val;
-
-  if (StringHasNoText (str)) return NULL;
-
-  StringNCpy_0 (tmp, str, sizeof (tmp));
-  ptr = StringChr (tmp, '/');
-  if (ptr == NULL) {
-    ptr = StringChr (tmp, '-');
-  }
-  if (ptr != NULL) {
-    *ptr = '\0';
-    ptr++;
-    if (sscanf (tmp, "%ld", &val) == 1) {
-      month = (Int4) val;
-    }
-    str = StringChr (ptr, '/');
-    if (str == NULL) {
-      str = StringChr (ptr, '-');
-    }
-    if (str != NULL) {
-      *str = '\0';
-      str++;
-      if (sscanf (ptr, "%ld", &val) == 1) {
-        day = (Int4) val;
-      }
-      if (sscanf (str, "%ld", &val) == 1) {
-        year = (Int4) val;
-     }
-    }
-  }
-
-  if (month < 0 || day < 0 || year < 2000) return NULL;
-  if (month > 12 || day > 31 || year > 2099) return NULL;
-
-  dp = DateNew ();
-  if (dp == NULL) return NULL;
-
-  dp->data [0] = 1;
-  dp->data [1] = (Uint1) (year - 1900);
-  dp->data [2] = (Uint1) month;
-  dp->data [3] = (Uint1) day;
-
-  return dp;
-}
-
-static void ParseTitleIntoSubmitBlock (
-  SqnTagPtr stp,
-  SubmitBlockPtr sbp
-)
-
-{
-  DatePtr  dp;
-  CharPtr  str;
-
-  if (stp == NULL || sbp == NULL) return;
-
-  str = SqnTagFind (stp, "hup");
-  if (str != NULL) {
-    sbp->hup = FALSE;
-    sbp->reldate = DateFree (sbp->reldate);
-    if (StringDoesHaveText (str)) {
-      if (StringICmp (str, "y") == 0) {
-        sbp->hup = TRUE;
-        dp = DateCurr ();
-        sbp->reldate = dp;
-        if (dp != NULL) {
-          if (dp->data [0] == 1) {
-            (dp->data [1])++;
-          }
-        }
-      } else {
-        dp = DateParse (str);
-        if (dp != NULL) {
-          sbp->hup = TRUE;
-          sbp->reldate = dp;
-        }
-      }
-    }
-  }
-}
-
 static void ProcessOneNuc (
   Uint2 entityID,
   BioseqPtr bsp,
@@ -2827,6 +2746,25 @@ static void RnaProtTrailingCommaFix (SeqFeatPtr sfp, Pointer userdata)
   }
 }
 
+
+static Boolean FileHasMoreData (FILE *fp)
+{
+  Pointer        dataptr;
+  Uint2          datatype;
+  Boolean        rval = FALSE;
+
+  if (fp == NULL) {
+    return FALSE;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, NULL, TRUE, FALSE, TRUE, FALSE);
+  if (dataptr != NULL) {
+    rval = TRUE;
+    ObjMgrFree (datatype, dataptr);
+  }
+  return rval;
+}
+
+
 static Uint2 ProcessOneAsn (
   FILE* fp,
   SubmitBlockPtr sbp,
@@ -2884,6 +2822,10 @@ static Uint2 ProcessOneAsn (
   }
   if (dataptr == NULL) return 0;
 
+  if (FileHasMoreData(fp)) {
+    Message (MSG_POSTERR, "File contains unexpected extra data");
+  }
+
   sep = GetTopSeqEntryForEntityID (entityID);
   bsp = FindNucBioseq (sep);
   if (bsp == NULL) {
@@ -3677,7 +3619,7 @@ static Uint2 ProcessPhrapAce (
 
   if (StringDoesHaveText (localname)) {
     sip = MakeSeqID (localname);
-    if (sip != NULL) {
+    if (sip != NULL && bsp != NULL) {
       bsp->id = SeqIdSetFree (bsp->id);
       bsp->id = sip;
       SeqMgrReplaceInBioseqIndex (bsp);
@@ -3703,6 +3645,8 @@ static Uint2 ProcessBulkSet (
   BioseqSetPtr  bssp;
   Uint2         entityID;
   SeqEntryPtr   lastsep, sep, topsep;
+  Raw2DeltData   r;
+
   /*
   Pointer       dataptr;
   Uint2         datatype;
@@ -3771,8 +3715,17 @@ static Uint2 ProcessBulkSet (
     }
     lastsep = sep;
 
+    if (tbl->raw2delt) {
+      r.entityID = entityID;
+      r.sbp = sbp;
+      r.src = src;
+      r.tbl = tbl;
+      r.template_molinfo = template_molinfo;
+      ProcessRaw2DeltCallback (bsp, &r);
+    } else {
     ProcessOneNuc (entityID, bsp, sbp, src, tbl, template_molinfo);
   }
+  }
 
   SeqMgrLinkSeqEntry (topsep, 0, NULL);
 
@@ -4021,7 +3974,7 @@ static Uint2 ProcessDeltaSet (
 
   if (StringDoesHaveText (localname)) {
     sip = MakeSeqID (localname);
-    if (sip != NULL) {
+    if (sip != NULL && bsp != NULL) {
       bsp->id = SeqIdSetFree (bsp->id);
       bsp->id = sip;
       SeqMgrReplaceInBioseqIndex (bsp);
@@ -5596,75 +5549,290 @@ static void AddTemplateDescriptors (
   }
 }
 
-static void GenomizeSeqId (
-  SeqIdPtr sip,
-  Pointer userdata
-)
 
+static Boolean UseProjectVersion (BioseqPtr bsp)
 {
-  CharPtr      accn = NULL;
+  SeqDescrPtr sdp;
+  SeqMgrDescContext context;
+  BioSourcePtr      biop;
+  MolInfoPtr        mip;
+
+  if (bsp == NULL) {
+    return FALSE;
+  }
+  if (ISA_aa (bsp->mol)) {
+    return FALSE;
+  }
+  if (bsp->repr != Seq_repr_delta) {
+    if (bsp->mol == Seq_mol_rna) {
+      /* suppress for mRNA */
+      sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
+      if (sdp != NULL && (mip = (MolInfoPtr) sdp->data.ptrvalue) != NULL && mip->biomol == MOLECULE_TYPE_MRNA) {
+        return FALSE;
+      }
+    }
+    /* it's a contig */
+    return TRUE;
+  } else {
+    sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &context);
+    if (sdp != NULL && (biop = (BioSourcePtr) sdp->data.ptrvalue) != NULL && biop->genome == GENOME_chromosome) {
+      /* it's a chromosome */
+      return FALSE;
+    } else {
+      /* it's a scaffold */
+      return TRUE;
+    }
+  }
+}
+
+
+typedef struct genomizeseqid {
   CharPtr      center;
-  DbtagPtr     dbt;
+  Int4    version;
+} GenomizeSeqIdData, PNTR GenomizeSeqIdPtr;
+
+
+static void UpdateGenomeId (SeqIdPtr sip, GenomizeSeqIdPtr gs)
+{
+  DbtagPtr db;
+  CharPtr  fmt = "%s%02d";
+
+  if (sip == NULL || sip->choice != SEQID_GENERAL || gs == NULL || StringHasNoText (gs->center)) {
+    return;
+  }
+
+  db = (DbtagPtr) sip->data.ptrvalue;
+
+  db->db = MemFree (db->db);
+  if (gs->version < 1) {
+    db->db = StringSave (gs->center);
+  } else {
+    db->db = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (gs->center) + 15));
+    sprintf (db->db, fmt, gs->center, gs->version);
+  }
+}
+
+
+static void ReplaceLocalIdWithGenome (SeqIdPtr sip, GenomizeSeqIdPtr gs)
+{
   ObjectIdPtr  oip;
+  DbtagPtr db;
+  CharPtr  fmt = "%s%02d";
 
-  if (sip == NULL || sip->choice != SEQID_LOCAL) return;
-  center = (CharPtr) userdata;
-  if (StringHasNoText (center)) return;
+  if (sip == NULL || sip->choice != SEQID_LOCAL || gs == NULL || StringHasNoText (gs->center)) {
+    return;
+  }
 
   oip = (ObjectIdPtr) sip->data.ptrvalue;
-  if (oip == NULL) return;
-  accn = oip->str;
-  if (StringHasNoText (accn)) return;
 
-  dbt = DbtagNew ();
-  if (dbt == NULL) return;
-  oip = ObjectIdNew ();
-  if (oip == NULL) return;
-  oip->str = StringSave (accn);
-  dbt->db = StringSave (center);
-  dbt->tag = oip;
+  db = DbtagNew ();
 
-  sip->data.ptrvalue = ObjectIdFree ((ObjectIdPtr) sip->data.ptrvalue);
-  sip->data.ptrvalue = (Pointer) dbt;
+  if (gs->version < 1) {
+    db->db = StringSave (gs->center);
+  } else {
+    db->db = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (gs->center) + 15));
+    sprintf (db->db, fmt, gs->center, gs->version);
+  }
+
+  db->tag = oip;
   sip->choice = SEQID_GENERAL;
+  sip->data.ptrvalue = db;
+}
+
+
+static void GenomizeSeqId (
+  SeqIdPtr sip,
+  Pointer userdata
+)
+
+{
+  GenomizeSeqIdPtr gs;
+  Int4             project_version;
+  BioseqPtr        bsp;
+  SeqIdPtr         cpy = NULL;
+
+  if (sip == NULL || (gs = (GenomizeSeqIdPtr) userdata) == NULL) {
+    return;
+  }
+  if (sip->choice != SEQID_LOCAL && sip->choice != SEQID_GENERAL) {
+    return;
+  }
+  
+  project_version = gs->version;
+  if (gs->version > 0) {
+    bsp = BioseqFind (sip);
+    if (bsp == NULL) {
+      cpy = SeqIdDup (sip);
+      if (cpy->choice == SEQID_LOCAL) {
+        ReplaceLocalIdWithGenome (cpy, gs);
+      } else if (cpy->choice == SEQID_GENERAL) {
+        UpdateGenomeId (cpy, gs);
+      }
+      bsp = BioseqFind (cpy);
+      if (bsp == NULL) {
+        gs->version = 0;
+        if (cpy->choice == SEQID_LOCAL) {
+          ReplaceLocalIdWithGenome (cpy, gs);
+        } else if (cpy->choice == SEQID_GENERAL) {
+          UpdateGenomeId (cpy, gs);
+        }
+        gs->version = project_version;
+      }
+      cpy = SeqIdFree (cpy);
+    }
+    if (bsp != NULL && !UseProjectVersion (bsp)) {
+      gs->version = 0;
+    }
+  }
+
+  if (sip->choice == SEQID_LOCAL) {
+    ReplaceLocalIdWithGenome (sip, gs);
+  } else if (sip->choice == SEQID_GENERAL) {
+    UpdateGenomeId (sip, gs);
+  }
+
+  gs->version = project_version;
 }
 
+
 static void GenomizeFeatureSeqIds (
   SeqFeatPtr sfp,
-  Pointer userdata
+  GenomizeSeqIdPtr gs
 )
 
 {
-  VisitSeqIdsInSeqLoc (sfp->location, userdata, GenomizeSeqId);
+  RnaRefPtr     rrp;
+  tRNAPtr       trp;
+  CodeBreakPtr  cbp;
+  CdRegionPtr   crp;
+  GBQualPtr     gbq;
+  SeqIdPtr      sip;
+  Char          id_txt[500];
+  Int4          project_version;
+
+  /* replace ids in locations common to all features */
+  VisitSeqIdsInSeqLoc (sfp->location, gs, GenomizeSeqId);
+
+  project_version = gs->version;
+  if (sfp->data.choice == SEQFEAT_CDREGION) {
+    /* protein IDs don't use version */
+    gs->version = 0;
+  }
+  VisitSeqIdsInSeqLoc (sfp->product, gs, GenomizeSeqId);
+  gs->version = project_version;
+  for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
+    if (StringICmp (gbq->qual, "protein_id") == 0 || StringICmp (gbq->qual, "transcript_id") == 0) {
+      sip = MakeSeqID (gbq->val);
+      if (sip != NULL) {
+        /* protein IDs and mRNA IDs don't use version */
+        gs->version = 0;
+        GenomizeSeqId (sip, gs);
+        gs->version = project_version;
+        SeqIdWrite (sip, id_txt, PRINTID_FASTA_SHORT, sizeof (id_txt) - 1);
+        if (StringICmp (gbq->val, id_txt) != 0) {
+          gbq->val = MemFree (gbq->val);
+          gbq->val = StringSave (id_txt);
+        }
+      }
+    }
+  }
+
+  /* specific feature data */
+  if (sfp->data.choice == SEQFEAT_RNA 
+      && (rrp = (RnaRefPtr) sfp->data.value.ptrvalue) != NULL
+      && rrp->ext.choice == 2
+      && (trp = (tRNAPtr) rrp->ext.value.ptrvalue) != NULL
+      && trp->anticodon != NULL) 
+  {
+    VisitSeqIdsInSeqLoc (trp->anticodon, gs, GenomizeSeqId);
+  }
+  else if (sfp->data.choice == SEQFEAT_CDREGION
+           && (crp = (CdRegionPtr) sfp->data.value.ptrvalue) != NULL) 
+  {
+    for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
+      VisitSeqIdsInSeqLoc (cbp->loc, gs, GenomizeSeqId);
+    }
+  }
 }
 
-static void GenomizeGraphSeqIds (
+
+static void GenomizeGraphIds (
   SeqGraphPtr sgp,
-  Pointer userdata
+  GenomizeSeqIdPtr gs
 )
 
 {
-  VisitSeqIdsInSeqGraph (sgp, userdata, GenomizeSeqId);
+  if (sgp != NULL && gs != NULL) {
+    VisitSeqIdsInSeqLoc (sgp->loc, gs, GenomizeSeqId);
+  }
 }
 
+
 static void MakeGenomeCenterID (
   BioseqPtr bsp,
   Pointer userdata
 )
 
 {
-  CharPtr  center;
+  GenomizeSeqIdPtr gs;
+  SeqEntryPtr top_sep;
+  SeqIdPtr    sip, sip_new, sip_local;
+  Int4        project_version;
 
   if (bsp == NULL) return;
-  center = (CharPtr) userdata;
-  if (StringHasNoText (center)) return;
 
-  VisitSeqIdsInBioseq (bsp, userdata, GenomizeSeqId);
-  SeqMgrReplaceInBioseqIndex (bsp);
-  VisitFeaturesOnBsp (bsp, userdata, GenomizeFeatureSeqIds);
-  VisitGraphsOnBsp (bsp, userdata, GenomizeGraphSeqIds);
+  top_sep = GetTopSeqEntryForEntityID (bsp->idx.entityID);
+
+  gs = (GenomizeSeqIdPtr) userdata;
+  if (gs == NULL || StringHasNoText (gs->center)) return;
+
+  project_version = gs->version;
+  if (!UseProjectVersion(bsp)) {
+    gs->version = 0;
+  }
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_LOCAL || sip->choice == SEQID_GENERAL) {
+      sip_local = SeqIdDup (sip);
+      sip_new = SeqIdDup (sip);
+      if (sip->choice == SEQID_LOCAL) {
+        ReplaceLocalIdWithGenome (sip_new, gs);
+      } else {
+        UpdateGenomeId (sip_new, gs);
+      }
+      ReplaceSeqIdWithSeqId (sip_local, sip_new, top_sep);
+      sip_local = SeqIdFree (sip_local);
+      sip_new = SeqIdFree (sip_new);
+      break;
+    }
+  }
+  gs->version = project_version;
 }
 
+
+static void GenomizeSeqAnnot (SeqAnnotPtr sap, GenomizeSeqIdPtr gs)
+{
+  SeqFeatPtr       sfp;
+  SeqGraphPtr      sgp;
+  
+  if (gs == NULL || StringHasNoText (gs->center)) return;
+
+  switch (sap->type) {
+    case 1: /* feature table */
+      for (sfp = sap->data; sfp != NULL; sfp = sfp->next) {
+        GenomizeFeatureSeqIds (sfp, gs);
+      }
+      break;
+    case 3: /* graph */
+      for (sgp = sap->data; sgp != NULL; sgp = sgp->next) {
+        GenomizeGraphIds (sgp, gs);
+      }
+      break;
+  }
+
+}
+
+
 static void MakeAccessionID (
   BioseqPtr bsp,
   Pointer userdata
@@ -5941,7 +6109,7 @@ static ValNodePtr FindItemListForClickableItemCategory (ValNodePtr list, CharPtr
 }
 
 
-static void Tbl2AsnFixBacterialExtendablePartials (ValNodePtr discrepancy_list, FILE *cleanup_log)
+static void Tbl2AsnFixExtendablePartials (ValNodePtr discrepancy_list, FILE *cleanup_log)
 {
   ValNodePtr vnp, vnp_c;
   ClickableItemPtr cip;
@@ -5987,7 +6155,7 @@ static void Tbl2AsnFixBacterialExtendablePartials (ValNodePtr discrepancy_list,
         }
         orig_location = MemFree (orig_location);
       }
-      Tbl2AsnFixBacterialExtendablePartials (cip->subcategories, cleanup_log);
+      Tbl2AsnFixExtendablePartials (cip->subcategories, cleanup_log);
     }
   }
 }
@@ -6043,6 +6211,56 @@ static void Tbl2AsnFixBacterialNonExtendablePartials (ValNodePtr discrepancy_lis
 }
 
 
+static void RemoveTitleForShortIntronProtein (SeqFeatPtr sfp) 
+{
+  BioseqPtr   prot_bsp;
+  SeqDescrPtr sdp;
+  SeqMgrDescContext context;
+  CharPtr           title;
+  ObjValNodePtr     ovp;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION || sfp->product == NULL
+      || (prot_bsp = BioseqFindFromSeqLoc (sfp->product)) == NULL) {
+    return;
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (prot_bsp, NULL, Seq_descr_title, &context);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (prot_bsp, sdp, Seq_descr_title, &context)) {
+    title = (CharPtr) sdp->data.ptrvalue;
+    if (StringNCmp (title, "LOW QUALITY PROTEIN:", 20) != 0
+        && sdp->extended != 0
+        && (ovp = (ObjValNodePtr) sdp) != NULL) {
+      ovp->idx.deleteme = TRUE;
+    }
+  }
+}
+
+
+static void Tbl2AsnAddExceptionsToShortIntrons (ValNodePtr discrepancy_list, FILE *cleanup_log)
+{
+  ValNodePtr vnp, vnp_c;
+  ClickableItemPtr cip;
+  LogInfoData      lid;
+
+  MemSet (&lid, 0, sizeof (LogInfoData));
+  lid.data_in_log = FALSE;
+  lid.fp = cleanup_log;
+  for (vnp_c = discrepancy_list; vnp_c != NULL; vnp_c = vnp_c->next) {
+    cip = vnp_c->data.ptrvalue;
+    if (cip != NULL) {
+      AddExceptionsToShortIntrons (cip->item_list, NULL, &lid);
+      for (vnp = cip->item_list; vnp != NULL; vnp = vnp->next) {
+        if (vnp->choice == OBJ_SEQFEAT) {
+          RemoveTitleForShortIntronProtein (vnp->data.ptrvalue);
+        }
+      }
+      Tbl2AsnAddExceptionsToShortIntrons (cip->subcategories, cleanup_log);
+    }
+  }
+}
+
+
 static void DoTbl2AsnCleanup (SeqEntryPtr sep, CleanupArgsPtr c)
 {
   ValNodePtr sep_list = NULL;
@@ -6084,12 +6302,12 @@ static void DoTbl2AsnCleanup (SeqEntryPtr sep, CleanupArgsPtr c)
     SeqMgrIndexFeatures (entityID, NULL);
 
     if (c->extend_partial_features_to_gaps_or_ends) {
-      FindBacterialExtendablePartials (&discrepancy_list, sep_list);
+      FindExtendablePartials (&discrepancy_list, sep_list);
       if (discrepancy_list != NULL) {
         if (c->cleanup_log != NULL) {
           fprintf (c->cleanup_log, "\nExtended Partial Features\n");
         }
-        Tbl2AsnFixBacterialExtendablePartials (discrepancy_list, c->cleanup_log);
+        Tbl2AsnFixExtendablePartials (discrepancy_list, c->cleanup_log);
         SeqMgrClearFeatureIndexes (entityID, NULL);
         SeqMgrIndexFeatures (entityID, NULL);
         discrepancy_list = FreeClickableList (discrepancy_list);
@@ -6107,6 +6325,19 @@ static void DoTbl2AsnCleanup (SeqEntryPtr sep, CleanupArgsPtr c)
     }
     sep_list = ValNodeFree (sep_list);
   }    
+
+  if (c->add_exception_to_short_introns) {
+    ValNodeAddPointer (&sep_list, 0, sep);
+    entityID = ObjMgrGetEntityIDForChoice (sep);
+    SeqMgrIndexFeatures (entityID, NULL);
+    FindShortIntrons(&discrepancy_list, sep_list);
+    Tbl2AsnAddExceptionsToShortIntrons (discrepancy_list, c->cleanup_log);
+    discrepancy_list = FreeClickableList (discrepancy_list);
+    sep_list = ValNodeFree (sep_list);
+    DeleteMarkedObjects (entityID, 0, NULL);
+    InstantiateProteinTitles (entityID, NULL);
+  }
+
 }
 
 
@@ -6156,6 +6387,65 @@ static Boolean SeqEntryHasConflictingIDs (SeqEntryPtr sep)
   }
 }
 
+static void ProcessFeatTable (
+  FILE *fp,
+  CharPtr directory,
+  CharPtr results,
+  CharPtr base,
+  TblArgsPtr tbl
+)
+
+{
+  AsnIoPtr     aip;
+  Pointer      dataptr;
+  Uint2        datatype;
+  Boolean      failure = FALSE;
+  Int4         linenum = 0;
+  Char         path [PATH_MAX];
+  SeqAnnotPtr  sap;
+
+  if (fp == NULL || tbl == NULL) return;
+
+  if (StringHasNoText (results)) {
+    results = directory;
+  }
+
+  dataptr = ReadFeatureTableFile (fp, &datatype, NULL, &linenum, &failure);
+  if (failure) return;
+  if (datatype != OBJ_SEQANNOT) return;
+
+  sap = (SeqAnnotPtr) dataptr;
+  if (sap == NULL) return;
+
+  BasicSeqAnnotCleanup (sap);
+
+  StringNCpy_0 (path, results, sizeof (path));
+  FileBuildPath (path, NULL, base);
+  StringCat (path, ".sap");
+
+  aip = AsnIoOpen (path, "w");
+  if (aip == NULL) return;
+
+  SeqAnnotAsnWrite (sap, aip, NULL);
+
+  AsnIoFlush (aip);
+  AsnIoClose (aip);
+}
+
+
+static Boolean IsGenProdSet (SeqEntryPtr sep)
+{
+  BioseqSetPtr bssp;
+
+  if (sep == NULL || !IS_Bioseq_set (sep)
+      || (bssp = (BioseqSetPtr) sep->data.ptrvalue) == NULL
+      || bssp->_class != BioseqseqSet_class_gen_prod_set) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
 
 static void ProcessOneRecord (
   SubmitBlockPtr sbp,
@@ -6175,8 +6465,7 @@ static void ProcessOneRecord (
 {
   AsnTypePtr         atp_bssse;
   BioSourcePtr       biop;
-  BioseqPtr          bsp, feat_bsp;
-  Boolean            already_converted_ids = FALSE;
+  BioseqPtr          bsp;
   BioseqSetPtr       bssp = NULL;
   Char               buf [256];
   SeqMgrFeatContext  context;
@@ -6220,6 +6509,16 @@ static void ProcessOneRecord (
   SeqEntryPtr        tmp;
   MolInfoPtr         template_molinfo = NULL;
   ValNodePtr         cmt_errors, vnp;
+  GenomizeSeqIdData  gs;
+
+  if (tbl->ftable) {
+    fp = OpenOneFile (directory, base, ".tbl");
+    if (fp != NULL) {
+      ProcessFeatTable (fp, directory, results, base, tbl);
+      FileClose (fp);
+    }
+    return;
+  }
 
   fp = OpenOneFile (directory, base, suffix);
   if (fp == NULL) return;
@@ -6281,28 +6580,8 @@ static void ProcessOneRecord (
     return;
   }
 
-  if (tbl->dotaxlookup) {
-    sep = GetTopSeqEntryForEntityID (entityID);
-    if (sep != NULL) {
-
-      /* optionally do network taxonomy lookup - prior to instantiating mRNA and protein titles */
-
-      Taxon3ReplaceOrgInSeqEntry (sep, FALSE);
-    }
-  }
-
-  if (tbl->dopublookup) {
-    sep = GetTopSeqEntryForEntityID (entityID);
-    if (sep != NULL) {
-
-      /* optionally do network publication lookup of just PMID references */
-
-      VisitPubdescsInSep (sep, NULL, LookupPubdesc);
-    }
-  }
-
   organism = NULL;
-  if (tbl->genprodset) {
+  if (tbl->genprodset && bssp != NULL) {
     descr = ExtractBioSourceAndPubs (bssp->seq_set);
     for (sdp = descr; sdp != NULL; sdp = sdp->next) {
       if (sdp->choice != Seq_descr_source) continue;
@@ -6317,6 +6596,17 @@ static void ProcessOneRecord (
     ReplaceBioSourceAndPubs (gsep, descr);
   }
 
+  gs.center = tbl->center;
+  /* get version from args later */
+  gs.version = tbl->project_version;
+  /* genomize the IDs */
+  if (!StringHasNoText (gs.center)) {
+    sep = GetTopSeqEntryForEntityID (entityID);
+    SeqMgrIndexFeatures (entityID, NULL);
+
+    VisitBioseqsInSep (sep, &gs, MakeGenomeCenterID);
+  }
+
   /* read one or more feature tables from .tbl file */
 
   if (StringDoesHaveText (tbl->tableFile)) {
@@ -6340,12 +6630,8 @@ static void ProcessOneRecord (
 
         sap = (SeqAnnotPtr) dataptr;
 
-        if (!StringHasNoText (tbl->center) && !already_converted_ids) {
-          feat_bsp = GetBioseqReferencedByAnnot (sap, entityID);
-          if (feat_bsp == NULL) {
-            VisitBioseqsInSep (sep, tbl->center, MakeGenomeCenterID);
-            already_converted_ids = TRUE;
-          }
+        if (!StringHasNoText (gs.center)) {
+          GenomizeSeqAnnot (sap, &gs);
         }
 
         ProcessOneAnnot (sap, entityID, tbl);
@@ -6549,6 +6835,15 @@ static void ProcessOneRecord (
     FileClose (fp);
   }
 
+  /* re-genomize the IDs, in case a source descriptor was added that makes a sequence a chromosome (and therefore should not have the version) */
+  if (!StringHasNoText (gs.center) && gs.version > 0) {
+    sep = GetTopSeqEntryForEntityID (entityID);
+    SeqMgrIndexFeatures (entityID, NULL);
+
+    VisitBioseqsInSep (sep, &gs, MakeGenomeCenterID);
+  }
+
+
   /* finish processing */
 
   if (sbp == NULL) {
@@ -6576,7 +6871,7 @@ static void ProcessOneRecord (
       sep = GetTopSeqEntryForEntityID (entityID);
     }
 
-    if (! tbl->genprodset) {
+    if (! tbl->genprodset && (!IsGenProdSet(sep) || tbl->gpstonps)) {
       VisitFeaturesInSep (sep, NULL, RemoveGBQualIDs);
     }
     if (sdphead != NULL) {
@@ -6625,6 +6920,18 @@ static void ProcessOneRecord (
       FileClose (fp);
     }
 
+    if (tbl->dotaxlookup) {
+      /* optionally do network taxonomy lookup - prior to instantiating mRNA and protein titles */
+
+      Taxon3ReplaceOrgInSeqEntry (sep, FALSE);
+    }
+
+    if (tbl->dopublookup) {
+      /* optionally do network publication lookup of just PMID references */
+
+      VisitPubdescsInSep (sep, NULL, LookupPubdesc);
+    }
+
     msev = ErrSetMessageLevel (SEV_MAX);
     move_cds (sep);
 
@@ -6655,7 +6962,7 @@ static void ProcessOneRecord (
       /* currently copying ncRNA feature onto product */
       VisitFeaturesInSep (sep, NULL, CopyNcRna);
     }
-    if (! tbl->genprodset) {
+    if (! tbl->genprodset && (!IsGenProdSet(sep) || tbl->gpstonps)) {
     VisitFeaturesInSep (sep, NULL, ClearRnaProducts);
     }
 
@@ -6680,6 +6987,18 @@ static void ProcessOneRecord (
       SeqMgrIndexFeatures (entityID, NULL);
       bsp = FindNucBioseq (sep);
 
+      /* get organism name after any taxonomy lookup */
+      sdp = GetNextDescriptorUnindexed (bsp, Seq_descr_source, NULL);
+      if (sdp != NULL) {
+        biop = (BioSourcePtr) sdp->data.ptrvalue;
+        if (biop != NULL) {
+          orp = biop->org;
+          if (orp != NULL && StringDoesHaveText (orp->taxname)) {
+            organism = orp->taxname;
+          }
+        }
+      }
+
       if (tbl->smarttitle) {
         MakeSmartRnaTitles (bsp, organism);
       } else {
@@ -6691,10 +7010,6 @@ static void ProcessOneRecord (
       }
     }
 
-    if (StringDoesHaveText (tbl->center) && !already_converted_ids) {
-      VisitBioseqsInSep (sep, tbl->center, MakeGenomeCenterID);
-    }
-
     if (StringDoesHaveText (tbl->accn)) {
       bsp = FindNucBioseq (sep);
       MakeAccessionID (bsp, tbl->accn);
@@ -7280,6 +7595,64 @@ static Boolean MoreThanYearOld (void)
   return FALSE;
 }
 
+
+static void AddStructuredCommentsFromTabFileToDescriptorList (CharPtr fname, ValNodePtr PNTR descr_list)
+{
+  ValNodePtr err_list = NULL;
+  ValNodePtr table, header, line, vnp_l, tmp;
+  UserObjectPtr uop;
+  SeqDescrPtr sdp;
+  FILE *fp;
+
+  if (StringHasNoText (fname) || descr_list == NULL) {
+    return;
+  }
+  fp = FileOpen (fname, "r");
+  if (fp == NULL) {
+    Message (MSG_POSTERR, "Unable to open structured comment file %s", fname);
+    return;
+  }
+
+  table = ReadTabTableFromFile (fp);
+  if (table == NULL || table->next == NULL || table->data.ptrvalue == NULL) {
+    ValNodeAddPointer (&err_list, 0, StringSave ("Unable to read table from file"));
+  } else {
+    tmp = FlipTabTableAxes (table);
+    table = FreeTabTable (table);
+    table = tmp;
+
+    header = table->data.ptrvalue;
+    header = table->data.ptrvalue;
+    if (header == NULL || header->data.ptrvalue == NULL || header->next == NULL) {
+      ValNodeAddPointer (&err_list, 0, StringSave ("Bad header line"));
+    } else {
+      line = table->next;
+
+      while (line != NULL) {
+        tmp = CreateStructuredCommentsFromRow (header, line->data.ptrvalue, NULL, &err_list);
+        for (vnp_l = tmp; vnp_l != NULL; vnp_l = vnp_l->next) {
+          uop = (UserObjectPtr) vnp_l->data.ptrvalue;
+          sdp = SeqDescrNew (*descr_list);
+          if (*descr_list == NULL) {
+            *descr_list = sdp;
+          }
+          sdp->choice = Seq_descr_user;
+          sdp->data.ptrvalue = uop;
+        }
+        tmp = ValNodeFree (tmp);
+        line = line->next;
+      }
+    }
+  }
+  table = FreeTabTable (table);    
+  FileClose (fp);
+  for (tmp = err_list; tmp != NULL; tmp = tmp->next) {
+    Message (MSG_POSTERR, "Error processing structured comment file %s: %s", fname, tmp->data.ptrvalue);
+  }
+  err_list = ValNodeFreeData (err_list);
+}
+
+
 /* Args structure contains command-line arguments */
 
 #define p_argInputPath         0
@@ -7323,6 +7696,8 @@ static Boolean MoreThanYearOld (void)
 #define c_argCleanupOptions   38
 #define z_argCleanupLogFile   39
 #define X_argExtraFlags       40
+#define N_argProjectVersion   41
+#define w_argStructuredCommentFile 42
 
 
 Args myargs [] = {
@@ -7427,7 +7802,8 @@ Args myargs [] = {
    "      d Correct Collection Dates (assume month first)\n"
    "      D Correct Collection Dates (assume day first)\n"
    "      b Append note to coding regions that overlap other coding regions with similar product names and do not contain 'ABC'\n"
-   "      x Extend partial ends of features by one or two nucleotides to abut gaps or sequence ends",
+   "      x Extend partial ends of features by one or two nucleotides to abut gaps or sequence ends\n"
+   "      s Add exception to short introns",
     NULL, NULL, NULL,
     TRUE, 'c', ARG_STRING, 0.0, 0, NULL},
   {"Cleanup Log File", NULL, NULL, NULL,
@@ -7435,6 +7811,10 @@ Args myargs [] = {
   {"Extra Flags (combine any of the following letters)\n"
    "      C Apply comments in .cmt files to all sequences\n",  NULL, NULL, NULL,
     TRUE, 'X', ARG_STRING, 0.0, 0, NULL},
+  {"Project Version Number",  "0", NULL, NULL,
+    TRUE, 'N', ARG_INT, 0.0, 0, NULL},
+  {"Single Structured Comment File", NULL, NULL, NULL,
+    TRUE, 'w', ARG_FILE_IN, 0.0, 0, NULL},
 };
 
 Int2 Main (void)
@@ -7444,6 +7824,7 @@ Int2 Main (void)
   Char            app [64];
   CharPtr         base;
   AsnTypePtr      bssp_atp = NULL;
+  DatePtr         cd;
   CitSubPtr       csp;
   Pointer         dataptr;
   Uint2           datatype;
@@ -7551,39 +7932,46 @@ Int2 Main (void)
   /* process new -a type argument */
 
   ptr = myargs [a_argType].strvalue;
-  if (StringICmp (ptr, "r20u") == 0) {
+  if (StringISearch (ptr, "r20u") != NULL) {
     tbl.raw2delt = TRUE;
     tbl.r2dmin = 20;
     tbl.r2dunk100 = TRUE;
-  } else if (StringICmp (ptr, "r20k") == 0) {
+  } else if (StringISearch (ptr, "r20k") != NULL) {
     tbl.raw2delt = TRUE;
     tbl.r2dmin = 20;
     tbl.r2dunk100 = FALSE;
-  } else if (StringICmp (ptr, "s") == 0) {
-    tbl.fastaset = TRUE;
-  } else if (StringICmp (ptr, "w1") == 0 || StringICmp (ptr, "s1") == 0) {
+  } else if (StringISearch (ptr, "di") != NULL) {
+    tbl.deltaset = TRUE;
+    tbl.implicitgaps = TRUE;
+  } else if (StringISearch (ptr, "d") != NULL) {
+    tbl.deltaset = TRUE;
+  } 
+
+  if (StringISearch (ptr, "w1") != NULL || StringISearch (ptr, "s1") != NULL) {
     tbl.fastaset = TRUE;
     tbl.whichclass = 1;
-  } else if (StringICmp (ptr, "w2") == 0 || StringICmp (ptr, "s2") == 0) {
+  } else if (StringISearch (ptr, "w2") != NULL || StringISearch (ptr, "s2") != NULL) {
     tbl.fastaset = TRUE;
     tbl.whichclass = 2;
-  } else if (StringICmp (ptr, "w3") == 0 || StringICmp (ptr, "s3") == 0) {
+  } else if (StringISearch (ptr, "w3") != NULL || StringISearch (ptr, "s3") != NULL) {
     tbl.fastaset = TRUE;
     tbl.whichclass = 3;
-  } else if (StringICmp (ptr, "w4") == 0 || StringICmp (ptr, "s4") == 0) {
+  } else if (StringISearch (ptr, "w4") != NULL || StringISearch (ptr, "s4") != NULL) {
     tbl.fastaset = TRUE;
     tbl.whichclass = 4;
-  } else if (StringICmp (ptr, "d") == 0) {
-    tbl.deltaset = TRUE;
-  } else if (StringICmp (ptr, "di") == 0) {
-    tbl.deltaset = TRUE;
-    tbl.implicitgaps = TRUE;
-  } else if (StringICmp (ptr, "l") == 0) {
+  } else if (StringISearch (ptr, "s") != NULL) {
+    tbl.fastaset = TRUE;
+  } else if (StringISearch (ptr, "l") != NULL) {
     tbl.alignset = TRUE;
-  } else if (StringICmp (ptr, "z") == 0) {
+  } else if (StringISearch (ptr, "z") != NULL) {
     tbl.gapped = TRUE;
-  } else if (StringICmp (ptr, "e") == 0) {
+  } else if (StringISearch (ptr, "e") != NULL) {
     tbl.phrapace = TRUE;
+  /*
+  } else if (StringICmp (ptr, "t") == 0) {
+    tbl.ftable = TRUE;
+    suffix = ".tbl";
+  */
   }
 
   tbl.genprodset = (Boolean) myargs [g_argGenProdSet].intvalue;
@@ -7598,6 +7986,7 @@ Int2 Main (void)
   tbl.gnltonote = (Boolean) myargs [h_argGnlToNote].intvalue;
   tbl.accn = (CharPtr) myargs [A_argAccession].strvalue;
   tbl.center = (CharPtr) myargs [C_argCenter].strvalue;
+  tbl.project_version = myargs[N_argProjectVersion].intvalue;
   tbl.organism = (CharPtr) myargs [n_argOrgName].strvalue;
   tbl.srcquals = (CharPtr) myargs [j_argSrcQuals].strvalue;
   tbl.comment = (CharPtr) myargs [y_argComment].strvalue;
@@ -7771,6 +8160,10 @@ Int2 Main (void)
     tbl.cleanup_args.add_exception_to_nonextendable_partials = TRUE;
   }
 
+  if (StringChr (ptr, 's') != NULL) {
+    tbl.cleanup_args.add_exception_to_short_introns = TRUE;
+  }
+
   ptr = (CharPtr) myargs [z_argCleanupLogFile].strvalue;
   if (StringDoesHaveText (ptr)) {
     tbl.cleanup_args.cleanup_log = FileOpen (ptr, "w");
@@ -7850,6 +8243,13 @@ Int2 Main (void)
           if (dp != NULL) {
             sbp->hup = TRUE;
             sbp->reldate = dp;
+            cd = DateCurr ();
+            if (cd != NULL) {
+              if (DateMatch (dp, cd, FALSE) == -1) {
+                Message (MSG_POSTERR, "Record release date has already passed");
+              }
+            }
+            DateFree (cd);
           }
         }
       }
@@ -7902,6 +8302,13 @@ Int2 Main (void)
     }
   }
 
+  /* if the user has specified a single file for structured comments, use it to create a descriptor
+   * to be added to all entries
+   */
+  AddStructuredCommentsFromTabFileToDescriptorList ((CharPtr) myargs [w_argStructuredCommentFile].strvalue,
+                                                    &sdphead);
+  
+
   gotags = TextFsaNew ();
   TextFsaAdd (gotags, "go_component");
   TextFsaAdd (gotags, "go_function");
diff --git a/demo/tbl_chk.c b/demo/tbl_chk.c
new file mode 100755
index 0000000..4b95977
--- /dev/null
+++ b/demo/tbl_chk.c
@@ -0,0 +1,1459 @@
+/*   tbl_chk.c
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*            National Center for Biotechnology Information (NCBI)
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government do not place any restriction on its use or reproduction.
+*  We would, however, appreciate having the NCBI and the author cited in
+*  any work or product based on this material
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+* ===========================================================================
+*
+* File Name:  tbl_chk.c
+*
+* Author:  Colleen Bollin
+*
+* Version Creation Date:   8/05/10
+*
+* $Revision: 1.3 $
+*
+* File Description: 
+*
+* Modifications:  
+* --------------------------------------------------------------------------
+* Date     Name        Description of modification
+* -------  ----------  -----------------------------------------------------
+*
+*
+* ==========================================================================
+*/
+
+#include <ncbi.h>
+#include <objall.h>
+#include <objsset.h>
+#include <objsub.h>
+#include <objfdef.h>
+#include <sequtil.h>
+#include <gather.h>
+#include <sqnutils.h>
+#include <explore.h>
+#include <pmfapi.h>
+#define NLM_GENERATED_CODE_PROTO
+#include <asnmacro.h>
+#include <objmacro.h>
+#include <macroapi.h>
+#ifdef INTERNAL_NCBI_TBL_CHK
+#include <accpubseq.h>
+#endif
+
+#define TBL_CHK_APP_VER "1.0"
+
+CharPtr TBL_CHK_APPLICATION = TBL_CHK_APP_VER;
+
+static Boolean debug_mode = FALSE;
+
+static Boolean IsAllDigits (CharPtr str)
+{
+  CharPtr cp;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  cp = str;
+  while (*cp != 0 && isdigit (*cp)) {
+    cp++;
+  }
+  if (*cp == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static SeqIdPtr SmartGuessMakeId (CharPtr str)
+{
+  CharPtr id_txt;
+  SeqIdPtr sip = NULL;
+
+  if (StringHasNoText (str)) {
+    return NULL;
+  } else if (StringChr (str, '|') != NULL) {
+    sip = MakeSeqID (str);
+  } else if (IsAllDigits (str)) {
+    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 4));
+    sprintf (id_txt, "gi|%s", str);
+    sip = MakeSeqID (id_txt);
+    id_txt = MemFree (id_txt);
+  } else if (StringChr (str, '_') != NULL) {
+    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 5));
+    sprintf (id_txt, "oth|%s", str);
+    sip = MakeSeqID (id_txt);
+    id_txt = MemFree (id_txt);
+  } else {
+    id_txt = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + 4));
+    sprintf (id_txt, "gb|%s", str);
+    sip = MakeSeqID (id_txt);
+    id_txt = MemFree (id_txt);
+  }
+  return sip;
+}
+
+
+typedef struct fetchitem {
+  SeqIdPtr sip;
+  CharPtr  id_txt;
+  Int4     index_pos;
+  ValNodePtr field_values;
+} FetchItemData, PNTR FetchItemPtr;
+
+
+static FetchItemPtr FetchItemNew (CharPtr accn) 
+{
+  FetchItemPtr item;
+  
+  item = (FetchItemPtr) MemNew (sizeof (FetchItemData));
+  item->id_txt = StringSave (accn);
+  item->sip = SmartGuessMakeId(accn);
+  item->field_values = NULL;
+  item->index_pos = -1;
+  return item;
+}
+
+
+static ValNodePtr FetchItemFieldValuesFree (ValNodePtr field_values)
+{
+  ValNodePtr vnp;
+
+  for (vnp = field_values; vnp != NULL; vnp = vnp->next) {
+    vnp->data.ptrvalue = ValNodeFreeData (vnp->data.ptrvalue);
+  }
+  field_values = ValNodeFree (field_values);
+  return field_values;
+}
+
+
+static FetchItemPtr FetchItemFree (FetchItemPtr item)
+{
+  if (item != NULL) {
+    item->id_txt = MemFree (item->id_txt);
+    item->sip = SeqIdFree (item->sip);
+    item->field_values = FetchItemFieldValuesFree (item->field_values);
+    item = MemFree (item);
+  }
+  return item;
+}
+
+
+static ValNodePtr FetchItemListFree (ValNodePtr list)
+{
+  ValNodePtr list_next;
+
+  while (list != NULL) {
+    list_next = list->next;
+    list->next = NULL;
+    list->data.ptrvalue = FetchItemFree (list->data.ptrvalue);
+    list = ValNodeFree (list);
+    list = list_next;
+  }
+  return list;
+}
+
+
+static int FetchItemCompare (FetchItemPtr f1, FetchItemPtr f2)
+{
+  if (f1 == NULL || f2 == NULL) {
+    return 0;
+  } else {
+    return StringCmp (f1->id_txt, f2->id_txt);
+  }
+}
+
+
+static ValNodePtr FetchItemListFromTable (ValNodePtr table)
+{
+  ValNodePtr       list = NULL, prev = NULL, this_item, row, col;
+
+  if (table == NULL || table->next == NULL) {
+    return NULL;
+  }
+  for (row = table->next; row != NULL; row = row->next) {
+    col = (ValNodePtr) row->data.ptrvalue;
+    if (col != NULL) {
+      this_item = ValNodeNew (NULL);
+      this_item->data.ptrvalue = FetchItemNew (col->data.ptrvalue);
+      if (prev == NULL) {
+        list = this_item;
+      } else {
+        prev->next = this_item;
+      }
+      prev = this_item;
+    }
+  }
+  return list;
+}
+
+
+static void ResetFetchItemListIndex (ValNodePtr list)
+{
+  FetchItemPtr fetch_item;
+
+  while (list != NULL) {
+    fetch_item = (FetchItemPtr) list->data.ptrvalue;
+    if (fetch_item != NULL) {
+      fetch_item->index_pos = -1;
+    } 
+    list = list->next;
+  }
+}
+
+
+static void FetchItemFieldValuesPrint (FILE *fp, ValNodePtr field_values)
+{
+  ValNodePtr vnp, vnp_val;
+
+  for (vnp = field_values; vnp != NULL; vnp = vnp->next) {
+    for (vnp_val = vnp->data.ptrvalue; vnp_val != NULL; vnp_val = vnp_val->next) {
+      fprintf (fp, "%s%s", vnp_val->data.ptrvalue == NULL ? "" : (char *) vnp_val->data.ptrvalue, vnp_val->next == NULL ? "\n" : "\t");
+    }
+  }
+}
+
+
+static int LIBCALLBACK SortVnpByFetchItem (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      return FetchItemCompare (vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+    }
+  }
+  return 0;
+}
+
+
+static FetchItemPtr PNTR sFetchIndex = NULL;
+static Int4 sFetchIndexSize = 0;
+
+static void MakeFetchItemIndex(ValNodePtr fetch_list)
+{
+  Int4 num;
+  ValNodePtr tmp_list = NULL, prev = NULL, vnp, vnp_new;
+
+  if (sFetchIndex != NULL) {
+    sFetchIndex = MemFree (sFetchIndex);
+    sFetchIndexSize = 0;
+  }
+
+  if (fetch_list == NULL) {
+    return;
+  }
+
+  tmp_list = ValNodeNew (NULL);
+  tmp_list->data.ptrvalue = fetch_list->data.ptrvalue;
+  prev = tmp_list;
+  for (vnp = fetch_list->next; vnp != NULL; vnp = vnp->next) {
+    vnp_new = ValNodeNew (prev);
+    vnp_new->data.ptrvalue = vnp->data.ptrvalue;
+    prev = vnp_new;
+  }
+
+  tmp_list = ValNodeSort (tmp_list, SortVnpByFetchItem);
+  sFetchIndexSize = ValNodeLen (tmp_list);
+  sFetchIndex = (FetchItemPtr PNTR) MemNew (sizeof (FetchItemPtr) * sFetchIndexSize);
+  for (vnp = tmp_list, num = 0; vnp != NULL; vnp = vnp->next, num++) {
+    sFetchIndex[num] = vnp->data.ptrvalue;
+  }
+  tmp_list = ValNodeFree (tmp_list);
+}
+
+
+static FetchItemPtr FindInFetchIndex (CharPtr str)
+{
+  Int4 imin = 0;
+  Int4 imax = sFetchIndexSize - 1;
+  Int4 num = -1, i, j;
+  CharPtr tmp;
+
+  while (imax >= imin)
+  {
+    i = (imax + imin)/2;
+    tmp = sFetchIndex[i]->id_txt;
+    if ((j = StringCmp(tmp, str)) > 0)
+      imax = i - 1;
+    else if (j < 0)
+      imin = i + 1;
+    else
+    {
+      num = i;
+      break;
+    }
+  }
+  if (num == -1) {
+    return NULL;
+  } else {
+    return sFetchIndex[num];
+  }
+}
+
+
+#ifdef INTERNAL_NCBI_TBL_CHK
+
+static CharPtr smartfetchproc = "SmartBioseqFetch";
+
+static CharPtr srcchkfetchcmd = NULL;
+static CharPtr smartfetchcmd = NULL;
+
+
+static Int4 NumInSet (BioseqSetPtr bssp)
+{
+  SeqEntryPtr  sep;
+  Int4         num = 0;
+
+  if (bssp != NULL) {
+    sep = bssp->seq_set;
+    while (sep != NULL) {
+      num++;
+      sep = sep->next;
+    }
+  }
+  return num;
+}
+   
+
+static BioseqPtr FetchBioseqFromSmartNotId (CharPtr accn, Uint2Ptr pEntityID)
+{
+  BioseqPtr         bsp;
+  Char              cmmd [256];
+  Pointer           dataptr;
+  Uint2             datatype;
+  Uint2             entityID;
+  FILE*             fp;
+  OMProcControlPtr  ompcp;
+  ObjMgrProcPtr     ompp;
+  Char              path [PATH_MAX];
+  Char              err_path [PATH_MAX];
+  SeqEntryPtr       sep = NULL;
+  SeqIdPtr          sip;
+  TextSeqIdPtr      tsip;
+  Int4              gi = 0;
+  ValNodePtr        vnp;
+  time_t            t1, t2;
+
+  if (srcchkfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "TBL_CHK", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+    	srcchkfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (srcchkfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "SMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+    	srcchkfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (srcchkfetchcmd == NULL) return NULL;
+
+  TmpNam (path);
+
+  t1 = time(NULL);
+#ifdef OS_UNIX
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", srcchkfetchcmd, accn, path, err_path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", srcchkfetchcmd, accn, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+#ifdef OS_UNIX
+    FileRemove (err_path);
+#endif
+    return OM_MSG_RET_ERROR;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
+
+  if (dataptr == NULL) return NULL;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+
+  if (sep == NULL) return NULL;
+  sip = SmartGuessMakeId (accn);
+  bsp = BioseqFindInSeqEntry (sip, sep);
+  sip = SeqIdFree (sip);
+  if (debug_mode) {
+    t2 = time(NULL);
+    if (t2 - t1 > 1) {
+      printf("Time to download %s from SMART:%d\n", accn, t2 - t1);
+    }
+  }
+  if (pEntityID != NULL) {
+    *pEntityID = entityID;
+  }
+  return bsp;
+}
+
+
+static Int2 LIBCALLBACK SmartBioseqFetchFunc (Pointer data)
+
+{
+  BioseqPtr         bsp;
+  Char              cmmd [256];
+  Pointer           dataptr;
+  Uint2             datatype;
+  Uint2             entityID;
+  FILE*             fp;
+  OMProcControlPtr  ompcp;
+  ObjMgrProcPtr     ompp;
+  Char              path [PATH_MAX];
+  Char              err_path [PATH_MAX];
+  SeqEntryPtr       sep = NULL;
+  SeqIdPtr          sip;
+  TextSeqIdPtr      tsip;
+  Int4              gi = 0;
+  ValNodePtr        vnp;
+
+  ompcp = (OMProcControlPtr) data;
+  if (ompcp == NULL) return OM_MSG_RET_ERROR;
+  ompp = ompcp->proc;
+  if (ompp == NULL) return OM_MSG_RET_ERROR;
+  sip = (SeqIdPtr) ompcp->input_data;
+  if (sip == NULL) return OM_MSG_RET_ERROR;
+
+  if (sip->choice != SEQID_GENBANK) return OM_MSG_RET_ERROR;
+  tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+  if (tsip == NULL || StringHasNoText (tsip->accession)) return OM_MSG_RET_ERROR;
+
+  if (smartfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "SMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+    	smartfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (smartfetchcmd == NULL) return OM_MSG_RET_ERROR;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", smartfetchcmd, tsip->accession, path, err_path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", smartfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+#ifdef OS_UNIX
+    FileRemove (err_path);
+#endif
+    return OM_MSG_RET_ERROR;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
+
+  if (dataptr == NULL) return OM_MSG_RET_OK;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+
+  if (sep == NULL) return OM_MSG_RET_ERROR;
+  bsp = BioseqFindInSeqEntry (sip, sep);
+  ompcp->output_data = (Pointer) bsp;
+  ompcp->output_entityID = ObjMgrGetEntityIDForChoice (sep);
+  return OM_MSG_RET_DONE;
+}
+
+static Boolean SmartFetchEnable (void)
+
+{
+  ObjMgrProcLoad (OMPROC_FETCH, smartfetchproc, smartfetchproc,
+                  OBJ_SEQID, 0, OBJ_BIOSEQ, 0, NULL,
+                  SmartBioseqFetchFunc, PROC_PRIORITY_DEFAULT);
+  return TRUE;
+}
+
+static CharPtr tpasmartfetchproc = "TPASmartBioseqFetch";
+
+static CharPtr tpasmartfetchcmd = NULL;
+
+extern Pointer ReadFromTPASmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID);
+extern Pointer ReadFromTPASmart (CharPtr accn, Uint2Ptr datatype, Uint2Ptr entityID)
+
+{
+  Char     cmmd [256];
+  Pointer  dataptr;
+  FILE*    fp;
+  Char     path [PATH_MAX];
+  Char     err_path [PATH_MAX];
+
+  if (datatype != NULL) {
+    *datatype = 0;
+  }
+  if (entityID != NULL) {
+    *entityID = 0;
+  }
+  if (StringHasNoText (accn)) return NULL;
+
+  if (tpasmartfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "TPASMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+    	tpasmartfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (tpasmartfetchcmd == NULL) return NULL;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", tpasmartfetchcmd, accn, path, err_path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", tpasmartfetchcmd, accn, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+    return NULL;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, datatype, entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
+  return dataptr;
+}
+
+
+static Int2 LIBCALLBACK TPASmartBioseqFetchFunc (Pointer data)
+
+{
+  BioseqPtr         bsp;
+  Char              cmmd [256];
+  Pointer           dataptr;
+  Uint2             datatype;
+  Uint2             entityID;
+  FILE*             fp;
+  OMProcControlPtr  ompcp;
+  ObjMgrProcPtr     ompp;
+  Char              path [PATH_MAX];
+  Char              err_path [PATH_MAX];
+  SeqEntryPtr       sep = NULL;
+  SeqIdPtr          sip;
+  TextSeqIdPtr      tsip;
+
+  ompcp = (OMProcControlPtr) data;
+  if (ompcp == NULL) return OM_MSG_RET_ERROR;
+  ompp = ompcp->proc;
+  if (ompp == NULL) return OM_MSG_RET_ERROR;
+  sip = (SeqIdPtr) ompcp->input_data;
+  if (sip == NULL) return OM_MSG_RET_ERROR;
+
+  if (sip->choice != SEQID_TPG) return OM_MSG_RET_ERROR;
+  tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+  if (tsip == NULL || StringHasNoText (tsip->accession)) return OM_MSG_RET_ERROR;
+
+  if (tpasmartfetchcmd == NULL) {
+    if (GetAppParam ("SEQUIN", "TPASMART", "FETCHSCRIPT", NULL, cmmd, sizeof (cmmd))) {
+    	tpasmartfetchcmd = StringSaveNoNull (cmmd);
+    }
+  }
+  if (tpasmartfetchcmd == NULL) return OM_MSG_RET_ERROR;
+
+  TmpNam (path);
+
+#ifdef OS_UNIX
+  sprintf (err_path, "%s.err", path);
+  sprintf (cmmd, "csh %s %s > %s 2>%s", tpasmartfetchcmd, tsip->accession, path, err_path);
+  system (cmmd);
+#endif
+#ifdef OS_MSWIN
+  sprintf (cmmd, "%s %s -o %s", tpasmartfetchcmd, tsip->accession, path);
+  system (cmmd);
+#endif
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    FileRemove (path);
+#ifdef OS_UNIX
+    FileRemove (err_path);
+#endif
+    return OM_MSG_RET_ERROR;
+  }
+  dataptr = ReadAsnFastaOrFlatFile (fp, &datatype, &entityID, FALSE, FALSE, TRUE, FALSE);
+  FileClose (fp);
+  FileRemove (path);
+#ifdef OS_UNIX
+  FileRemove (err_path);
+#endif
+
+  if (dataptr == NULL) return OM_MSG_RET_OK;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL) return OM_MSG_RET_ERROR;
+  bsp = BioseqFindInSeqEntry (sip, sep);
+  ompcp->output_data = (Pointer) bsp;
+  ompcp->output_entityID = ObjMgrGetEntityIDForChoice (sep);
+  return OM_MSG_RET_DONE;
+}
+
+static Boolean TPASmartFetchEnable (void)
+
+{
+  ObjMgrProcLoad (OMPROC_FETCH, tpasmartfetchproc, tpasmartfetchproc,
+                  OBJ_SEQID, 0, OBJ_BIOSEQ, 0, NULL,
+                  TPASmartBioseqFetchFunc, PROC_PRIORITY_DEFAULT);
+  return TRUE;
+}
+#endif
+
+
+static ValNodePtr CollectFieldList(BioseqPtr bsp)
+{
+  BioSourcePtr biop;
+  SeqDescrPtr sdp;
+  SeqMgrDescContext dcontext;
+  ValNodePtr list = NULL, vnp;
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_source, &dcontext)) {
+    biop = (BioSourcePtr) sdp->data.ptrvalue;
+    vnp = GetSourceQualFieldListFromBioSource (biop);
+    ValNodeLink (&list, vnp);
+  }
+  return list;
+}
+
+
+static void PrintHeader (FILE *fp, ValNodePtr field_list)
+{
+  CharPtr txt;
+
+  if (fp == NULL || field_list == NULL) {
+    return;
+  }
+  /* first field accession, second field GI, third field tax ID */
+  fprintf (fp, "\t\tTaxID");
+  while (field_list != NULL) {
+    txt = SummarizeFieldType (field_list);
+    fprintf (fp, "\t%s", txt);
+    txt = MemFree (txt);
+    field_list = field_list->next;
+  }
+  fprintf (fp, "\n");
+}
+
+
+static Int4 GetTaxIdFromOrgRef (OrgRefPtr orp)
+{
+  Int4       tax_id = -1;
+  ValNodePtr vnp;
+  DbtagPtr   d;
+
+  if (orp != NULL)
+  {
+    for (vnp = orp->db; vnp != NULL; vnp = vnp->next) 
+    {
+      d = (DbtagPtr) vnp->data.ptrvalue;
+      if (StringCmp(d->db, "taxon") == 0) 
+      {
+        tax_id = d->tag->id;
+        break;
+      }
+    }
+  }
+  return tax_id;
+}
+
+
+static ValNodePtr CollectBioSourceValues (BioSourcePtr biop, ValNodePtr field_list)
+{
+  Char       taxid_buf[30];
+  ValNodePtr field_values = NULL;
+  CharPtr    txt;
+
+  sprintf (taxid_buf, "%d", GetTaxIdFromOrgRef(biop->org));
+  ValNodeAddPointer (&field_values, 0, StringSave (taxid_buf));
+ 
+  while (field_list != NULL) {
+    txt = GetSourceQualFromBioSource (biop, field_list->data.ptrvalue, NULL);
+    ValNodeAddPointer (&field_values, 0, txt);
+    field_list = field_list->next;
+  }
+  return field_values;
+}
+
+
+static ValNodePtr CollectBioseqLineValues (BioseqPtr bsp, ValNodePtr field_list, Boolean want_gi)
+{
+  SeqDescrPtr       sdp;
+  SeqMgrDescContext dcontext;
+  Char              id_txt[255], id_txt2[255];
+  SeqIdPtr          sip, sip_gi = NULL, sip_gb = NULL;
+  ValNodePtr        line_list = NULL, line_values;
+
+  if (bsp == NULL) {
+    return NULL;
+  }
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_GENBANK
+        || (sip->choice == SEQID_EMBL && sip_gb == NULL)
+        || (sip->choice == SEQID_SWISSPROT && sip_gb == NULL)
+        || (sip->choice == SEQID_DDBJ && sip_gb == NULL)
+        || (sip->choice == SEQID_PIR && sip_gb == NULL)) {
+      sip_gb = sip;
+    } else if (sip->choice == SEQID_GI) {
+      sip_gi = sip;
+    }
+  }
+
+  if (sip_gb == NULL && sip_gi == NULL) {
+    SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+    id_txt2[0] = 0;
+  } else {
+    if (sip_gb == NULL) {
+      id_txt[0] = 0;
+    } else {
+      SeqIdWrite (sip_gb, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+    }
+    if (sip_gi == NULL) {
+      id_txt2[0] = 0;
+    } else {
+      SeqIdWrite (sip_gi, id_txt2, PRINTID_REPORT, sizeof (id_txt2) - 1);
+    }
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_source, &dcontext)) {
+    line_values = NULL;
+    ValNodeAddPointer (&line_values, 0, StringSave (id_txt));
+    if (want_gi) {
+      ValNodeAddPointer (&line_values, 0, StringSave (id_txt2));
+    }
+    ValNodeLink (&line_values, CollectBioSourceValues (sdp->data.ptrvalue, field_list));
+    ValNodeAddPointer (&line_list, 0, line_values);
+  }
+  return line_list;
+}
+
+
+#ifdef INTERNAL_NCBI_TBL_CHK
+
+typedef struct populate {
+  ValNodePtr field_list;
+  Boolean    want_gi;
+} PopulateData, PNTR PopulatePtr;
+
+static void PopulateFetchItemCallback (BioseqPtr bsp, Pointer data)
+{
+  PopulatePtr pp;
+  SeqIdPtr    sip;
+  TextSeqIdPtr tsip;
+  Char         buffer[15];
+  FetchItemPtr fetch_item = NULL;
+
+  if (bsp == NULL || ISA_aa(bsp->mol) || (pp = (PopulatePtr)data) == NULL) {
+    return;
+  }
+
+  for (sip = bsp->id; sip != NULL && fetch_item == NULL; sip = sip->next) {
+    switch (sip->choice) {
+      case SEQID_GI:
+        printf (buffer, "%d", sip->data.intvalue);
+        fetch_item = FindInFetchIndex(buffer);
+        break;
+      case SEQID_GENBANK :
+      case SEQID_EMBL :
+      case SEQID_DDBJ :
+      case SEQID_TPG :
+      case SEQID_TPE :
+      case SEQID_TPD :
+      case SEQID_OTHER :
+        tsip = (TextSeqIdPtr) sip->data.ptrvalue;
+        if (tsip != NULL) {
+          fetch_item = FindInFetchIndex(tsip->accession);
+        }
+        break;
+      default :
+        break;
+    }
+  }
+
+  if (fetch_item != NULL && fetch_item->index_pos < 0) {
+    /* collect field values */
+    fetch_item->field_values = CollectBioseqLineValues (bsp, pp->field_list, pp->want_gi);
+    fetch_item->index_pos = 0;
+  }
+}
+
+
+static void PopulateFetchItemCache (Uint2 entityID, ValNodePtr fetch_list, ValNodePtr field_list, Boolean want_gi)
+{
+  SeqEntryPtr sep;
+  BioseqSetPtr bssp;
+  ValNodePtr   vnp;
+  FetchItemPtr fetch_item;
+  BioseqPtr    bsp;
+  time_t       t1, t2;
+  Int4         num_in_list, num_in_set;
+  PopulateData pd;
+
+  t1 = time(NULL);
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep != NULL && IS_Bioseq_set(sep) && (bssp = (BioseqSetPtr)sep->data.ptrvalue) != NULL
+      && bssp->_class != BioseqseqSet_class_nuc_prot) {
+    num_in_set = NumInSet (bssp);
+    if (num_in_set < sFetchIndexSize) {
+      for (vnp = fetch_list; vnp != NULL; vnp = vnp->next) {
+        fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+        if (fetch_item->index_pos < 0) {
+          bsp = BioseqFindInSeqEntry (fetch_item->sip, sep);
+          if (bsp != NULL) {
+            /* collect field values */
+            fetch_item->field_values = CollectBioseqLineValues (bsp, field_list, want_gi);
+            fetch_item->index_pos = 0;
+          }
+        }
+      }
+    } else {
+      pd.field_list = field_list;
+      pd.want_gi = want_gi;
+      VisitBioseqsInSep (sep, &pd, PopulateFetchItemCallback);
+    }     
+  }
+  if (debug_mode) {
+    t2 = time(NULL);
+    if (t2 - t1 > 2) {
+      printf ("Time to populate cache: %d\n", t2 - t1);
+    }
+  }
+}
+
+#endif
+
+
+static void PrintBioSourceLine (FILE *fp, BioSourcePtr biop, ValNodePtr field_list)
+{
+  CharPtr txt;
+
+  if (fp == NULL || biop == NULL || field_list == NULL) {
+    return;
+  }
+
+  fprintf (fp, "\t%d", GetTaxIdFromOrgRef(biop->org));
+ 
+  while (field_list != NULL) {
+    txt = GetSourceQualFromBioSource (biop, field_list->data.ptrvalue, NULL);
+    fprintf (fp, "\t%s", txt == NULL ? "" : txt);
+    txt = MemFree (txt);
+    field_list = field_list->next;
+  }
+}
+
+
+static void PrintBioseqLines (FILE *fp, BioseqPtr bsp, ValNodePtr field_list, Boolean want_gi)
+{
+  SeqDescrPtr       sdp;
+  SeqMgrDescContext dcontext;
+  Char              id_txt[255], id_txt2[255];
+  SeqIdPtr          sip, sip_gi = NULL, sip_gb = NULL;
+
+  if (fp == NULL || bsp == NULL) {
+    return;
+  }
+
+  for (sip = bsp->id; sip != NULL; sip = sip->next) {
+    if (sip->choice == SEQID_GENBANK
+        || (sip->choice == SEQID_EMBL && sip_gb == NULL)
+        || (sip->choice == SEQID_SWISSPROT && sip_gb == NULL)
+        || (sip->choice == SEQID_DDBJ && sip_gb == NULL)
+        || (sip->choice == SEQID_PIR && sip_gb == NULL)) {
+      sip_gb = sip;
+    } else if (sip->choice == SEQID_GI) {
+      sip_gi = sip;
+    }
+  }
+
+  if (sip_gb == NULL && sip_gi == NULL) {
+    SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+    id_txt2[0] = 0;
+  } else {
+    if (sip_gb == NULL) {
+      id_txt[0] = 0;
+    } else {
+      SeqIdWrite (sip_gb, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+    }
+    if (sip_gi == NULL) {
+      id_txt2[0] = 0;
+    } else {
+      SeqIdWrite (sip_gi, id_txt2, PRINTID_REPORT, sizeof (id_txt2) - 1);
+    }
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &dcontext);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_source, &dcontext)) {
+    if (want_gi) {
+      fprintf (fp, "%s\t%s", id_txt, id_txt2);
+    } else {
+      fprintf (fp, "%s", id_txt);
+    }
+    PrintBioSourceLine (fp, sdp->data.ptrvalue, field_list);
+    fprintf (fp, "\n");
+  }
+}
+
+
+static void PrintBioseqErrorLine (FILE *fp, SeqIdPtr sip)
+{
+  Char              id_txt[255];
+
+  if (fp == NULL || sip == NULL) {
+    return;
+  }
+
+  SeqIdWrite (sip, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
+
+  if (sip->choice == SEQID_GI) {
+    fprintf (fp, "\t%s\n", id_txt);
+  } else {
+    fprintf (fp, "%s\t\n", id_txt);
+  }
+}
+
+
+/* Args structure contains command-line arguments */
+
+#define i_argInputFile         0
+#define o_argOutputFile        1
+#define D_argDebugMode         2
+#define m_argMetaMode          3
+
+Args myargs [] = {
+  {"Input File", NULL, NULL, NULL,
+    TRUE, 'i', ARG_FILE_IN, 0.0, 0, NULL},
+  {"Output File", NULL, NULL, NULL,
+    TRUE, 'o', ARG_FILE_OUT, 0.0, 0, NULL},
+  {"Debug Mode", "F", NULL, NULL,
+    TRUE, 'D', ARG_BOOLEAN, 0.0, 0, NULL},
+  {"Metadata Mode", "F", NULL, NULL,
+    TRUE, 'm', ARG_BOOLEAN, 0.0, 0, NULL}
+};
+
+
+static void SortFieldListForSrcChk (ValNodePtr PNTR field_list)
+{
+  ValNodePtr vnp, vnp_s, vnp_prev = NULL;
+
+  if (field_list == NULL || *field_list == NULL) return;
+
+  SortUniqueFieldTypeList (field_list);
+
+  /* move taxname to front of list */
+  for (vnp = *field_list; vnp != NULL; vnp_prev = vnp, vnp = vnp->next) {
+    if (vnp->choice == FieldType_source_qual) {
+      vnp_s = vnp->data.ptrvalue;
+      if (vnp_s != NULL
+          && vnp_s->choice == SourceQualChoice_textqual
+          && vnp_s->data.intvalue == Source_qual_taxname) {
+        /* only need to move if not already at front of list */
+        if (vnp_prev != NULL) {
+          vnp_prev->next = vnp->next;
+          vnp->next = *field_list;
+          *field_list = vnp;
+        }
+        break;
+      }
+    }
+  }       
+
+
+}
+
+
+static ValNodePtr FieldsFromFieldListString (CharPtr str)
+{
+  CharPtr cpy, val, comma;
+  Int4    qual;
+  ValNodePtr field_list = NULL, qc;
+
+  if (StringHasNoText (str)) {
+    return NULL;
+  }
+  cpy = StringSave (str);
+  val = cpy;
+  comma = StringChr(val, ',');
+  while (comma != NULL) {
+    *comma = 0;
+    qual = GetSourceQualTypeByName(val);
+    if (qual < 0) {
+      Message (MSG_ERROR, "%s is not a recognized source field name", val);
+    } else {
+      qc = ValNodeNew (NULL);
+      qc->choice = SourceQualChoice_textqual;
+      qc->data.intvalue = qual;
+      ValNodeAddPointer (&field_list, FieldType_source_qual, qc);
+    }
+    *comma = ',';
+    val = comma + 1;
+    comma = StringChr (val, ',');
+  }
+
+  qual = GetSourceQualTypeByName(val);
+  if (qual < 0) {
+    Message (MSG_ERROR, "%s is not a recognized source field name", val);
+  } else {
+    qc = ValNodeNew (NULL);
+    qc->choice = SourceQualChoice_textqual;
+    qc->data.intvalue = qual;
+    ValNodeAddPointer (&field_list, FieldType_source_qual, qc);
+  }
+
+  cpy = MemFree (cpy);
+  return field_list;
+}
+
+
+static Boolean PvtStrToLong (CharPtr str, Int4Ptr longval)
+
+{
+   Char     ch;
+   Int2     i;
+   Int2     len;
+   Char     local [64];
+   Boolean  nodigits;
+   Boolean  rsult;
+   long int     val;
+
+   rsult = FALSE;
+   if (longval != NULL) {
+     *longval = (Int4) 0;
+   }
+   len = (Int2) StringLen (str);
+   if (len != 0) {
+     rsult = TRUE;
+     nodigits = TRUE;
+     for (i = 0; i < len; i++) {
+       ch = str [i];
+       if (ch == ' ' || ch == '+' || ch == '-') {
+       } else if (ch < '0' || ch > '9') {
+         rsult = FALSE;
+       } else {
+         nodigits = FALSE;
+       }
+     }
+     if (nodigits) {
+       rsult = FALSE;
+     }
+     if (rsult && longval != NULL) {
+       StringNCpy_0 (local, str, sizeof (local));
+       if (sscanf (local, "%ld", &val) == 1) {
+         *longval = val;
+       }
+     }
+   }
+   return rsult;
+}
+
+static Int4 AccessionToGi (CharPtr string)
+
+{
+    Int4      gi;
+    SeqIdPtr  sip;
+
+    sip = SeqIdFromAccessionDotVersion (string);
+    if (sip == NULL) return 0;
+    gi = GetGIForSeqId (sip);
+    SeqIdFree (sip);
+    return gi;
+}
+
+
+static BioseqPtr FetchOnlyBioseqFromID (CharPtr str)
+{
+   BioseqPtr    bsp = NULL;
+   Uint2        entityID;
+   SeqEntryPtr  sep;
+   SeqIdPtr     sip = NULL;
+   Int4         uid;
+   time_t       t1, t2;
+
+   t1 = time (NULL);
+   uid = 0;
+   TrimSpacesAroundString (str);
+   if (IsAllDigits (str)) {
+     if (PvtStrToLong (str, &uid)) {
+       sip = ValNodeNew(NULL);
+       sip->choice = SEQID_GI;
+       sip->data.intvalue = uid;
+     } else {
+      uid = 0;
+     }
+   } else {
+     sip = SeqIdFromAccessionDotVersion (str);
+     uid = AccessionToGi (str);
+   }
+   sep = NULL;
+   if (uid > 0) {
+     sep = PubSeqSynchronousQuery (uid, 3, 0); /* retcode was 0 */
+     if (sep != NULL) {
+       bsp = BioseqFindInSeqEntry (sip, sep);
+       entityID = ObjMgrGetEntityIDForChoice (sep); 
+     }
+   }
+   sip = SeqIdFree (sip);
+   if (debug_mode) {
+    t2 = time (NULL);
+    if (t2 - t1 > 1) {
+      printf ("Time to download %s from ID:%d\n", str, (int) (t2 - t1));
+    }
+   }
+   return bsp;
+}
+
+
+static void CollectFieldsInFetchItemCache (Uint2 entityID, ValNodePtr PNTR field_list, ValNodePtr fetch_list)
+{
+  SeqEntryPtr sep;
+  BioseqSetPtr bssp;
+  ValNodePtr   vnp;
+  FetchItemPtr fetch_item;
+  BioseqPtr    bsp;
+
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep != NULL && IS_Bioseq_set(sep) && (bssp = (BioseqSetPtr)sep->data.ptrvalue) != NULL
+      && bssp->_class != BioseqseqSet_class_nuc_prot) {
+    for (vnp = fetch_list; vnp != NULL; vnp = vnp->next) {
+      fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+      if (fetch_item->index_pos < 0) {
+        bsp = BioseqFindInSeqEntry (fetch_item->sip, sep);
+        if (bsp != NULL) {
+          ValNodeLink (field_list, CollectFieldList(bsp));
+          fetch_item->index_pos = 0;
+        }
+      }
+    }
+  }
+}
+
+
+static ValNodePtr CollectBioseqFieldsWithCaching (ValNodePtr fetch_list) 
+{
+  ValNodePtr   vnp;
+  ValNodePtr   field_list = NULL;
+  BioseqPtr    bsp;
+  FetchItemPtr fetch_item;
+  Uint2        entityID;
+
+  for (vnp = fetch_list; vnp != NULL; vnp = vnp->next) {
+    fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+    if (fetch_item->index_pos < 0) {
+      entityID = 0;
+#ifdef INTERNAL_NCBI_TBL_CHK
+      bsp = FetchBioseqFromSmartNotId (fetch_item->id_txt, &entityID);
+      if (bsp != NULL) {
+        CollectFieldsInFetchItemCache (entityID, &field_list, vnp->next);
+      } else {
+        bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+      }
+#else
+      bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+#endif
+      ValNodeLink (&field_list, CollectFieldList(bsp));
+    }
+  }
+  ResetFetchItemListIndex (fetch_list);
+  return field_list;
+}
+
+
+static Boolean HasMismatch
+(ValNodePtr values,
+ ValNodePtr col)
+{
+  Boolean rval = FALSE;
+
+  while (!rval && values != NULL && col != NULL) {
+    if (StringHasNoText (values->data.ptrvalue)
+        && StringHasNoText (col->data.ptrvalue)) {
+      /* both empty, ignore */
+    } else if (StringCmp (values->data.ptrvalue, col->data.ptrvalue)) {
+      rval = TRUE;
+    }
+    values = values->next;
+    col = col->next;
+  }
+  if (values != NULL || col != NULL) {
+    rval = TRUE;
+  }
+  return rval;
+}
+ 
+static void PrintMisMatches(FILE *out, CharPtr id_txt, ValNodePtr val, ValNodePtr col, ValNodePtr field)
+{
+  CharPtr label = NULL;
+
+  while (field != NULL && (val != NULL || col != NULL)) {
+    if (val == NULL) {
+      if (!StringHasNoText (col->data.ptrvalue)) {
+        label = SummarizeFieldType (field);
+        fprintf (out, "%s\t%s\t\t%s\n", id_txt, label, (char *) col->data.ptrvalue);
+      }
+    } else if (col == NULL) {
+      if (!StringHasNoText (val->data.ptrvalue)) {
+        label = SummarizeFieldType (field);
+        fprintf (out, "%s\t%s\t%s\t\n", id_txt, label, (char *) val->data.ptrvalue);
+      }
+    } else if (!StringHasNoText (val->data.ptrvalue) && !StringHasNoText (col->data.ptrvalue)
+               && StringCmp (val->data.ptrvalue, col->data.ptrvalue) != 0) {
+      label = SummarizeFieldType (field);
+      fprintf (out, "%s\t%s\t%s\t%s\n", id_txt, label, (char *) val->data.ptrvalue, (char *) col->data.ptrvalue);
+    }
+    label = MemFree (label);
+
+    if (val != NULL) {
+      val = val->next;
+    }
+    if (col != NULL) {
+      col = col->next;
+    }
+    field = field->next;
+  }
+}
+
+static Int2 
+ProcessBioseqsWithCaching 
+(ValNodePtr fetch_list,
+ ValNodePtr field_list,
+ ValNodePtr table,
+ Boolean    meta_mode,
+ FILE *out)
+{
+  ValNodePtr vnp, row, col, line, val;
+  BioseqPtr  bsp;
+  FetchItemPtr fetch_item;
+  Uint2        entityID;
+  Int4         num_processed = 0;
+  time_t       t, last_t;
+
+  last_t = time(NULL);
+
+  for (vnp = fetch_list, row = table->next; 
+       vnp != NULL && row != NULL; 
+       vnp = vnp->next, row = row->next) {
+    fetch_item = (FetchItemPtr) vnp->data.ptrvalue;
+    if (fetch_item->index_pos < 0) {
+      entityID = 0;
+#ifdef INTERNAL_NCBI_TBL_CHK
+      bsp = FetchBioseqFromSmartNotId (fetch_item->id_txt, &entityID);
+      if (bsp != NULL) {
+        PopulateFetchItemCache (entityID, vnp->next, field_list, TRUE);
+      } else {
+        bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+        if (bsp == NULL) {
+          printf ("Unable to download Bioseq for %s\n", fetch_item->id_txt);
+        }
+      }
+#else
+      bsp = FetchOnlyBioseqFromID (fetch_item->id_txt);
+#endif
+      fetch_item->field_values = CollectBioseqLineValues (bsp, field_list, FALSE);
+    }
+    if (fetch_item->field_values == NULL) {
+      fprintf (out, "%s: Bioseq not found\n", fetch_item->id_txt);
+    } else {
+      for (line = fetch_item->field_values; line != NULL; line = line->next) {
+        val = line->data.ptrvalue;
+        col = row->data.ptrvalue;
+        if (meta_mode) {
+          PrintMisMatches(out, fetch_item->id_txt, val->next->next, col->next, field_list);
+        } else {
+          if (HasMismatch(val->next->next, col->next)) {
+            fprintf (out, "%s\n", fetch_item->id_txt);
+          }
+        }
+      }
+      fetch_item->field_values = FetchItemFieldValuesFree (fetch_item->field_values);
+    }
+    fflush(out);
+    if (debug_mode) {
+      num_processed++;
+      if (num_processed == 10) {
+        t = time (NULL);
+        printf ("Time to process %d: %d\n", num_processed, (int) (t - last_t)); 
+        num_processed = 0;
+        last_t = t;
+      }    
+    }
+  }
+
+  return 0;
+}
+
+
+static ValNodePtr GetFieldListFromHeader(ValNodePtr col)
+{
+  ValNodePtr val, list = NULL, field, prev = NULL;
+
+  /* note - first item is accession */
+  if (col == NULL || col->next == NULL) {
+    return NULL;
+  }
+  for (val = col->next; val != NULL; val = val->next) {
+    field = FieldTypeFromString (val->data.ptrvalue);
+    if (field == NULL) {
+      Message (MSG_ERROR, "Unable to match field name for %s", val->data.ptrvalue);
+      list = FieldTypeListFree (list);
+      return NULL;
+    } else if (prev == NULL) {
+      list = field;
+    } else {
+      prev->next = field;
+    }
+    prev = field;
+  }
+  return list;
+}
+
+
+Int2 Main(void)
+{
+  Char             app [64];
+  Int4             rval = 0;
+  CharPtr          id_file;
+  ValNodePtr       fetch_list = NULL;
+  ValNodePtr       field_list = NULL;
+  ValNodePtr       table;
+  Boolean          meta_mode = FALSE;
+  FILE *fp;
+
+  /* standard setup */
+
+  ErrSetFatalLevel (SEV_MAX);
+  ErrClearOptFlags (EO_SHOW_USERSTR);
+  UseLocalAsnloadDataAndErrMsg ();
+  ErrPathReset ();
+
+  /* finish resolving internal connections in ASN.1 parse tables */
+
+  if (! AllObjLoad ()) {
+    Message (MSG_FATAL, "AllObjLoad failed");
+    return 1;
+  }
+  if (! SubmitAsnLoad ()) {
+    Message (MSG_FATAL, "SubmitAsnLoad failed");
+    return 1;
+  }
+  if (! FeatDefSetLoad ()) {
+    Message (MSG_FATAL, "FeatDefSetLoad failed");
+    return 1;
+  }
+  if (! SeqCodeSetLoad ()) {
+    Message (MSG_FATAL, "SeqCodeSetLoad failed");
+    return 1;
+  }
+  if (! GeneticCodeTableLoad ()) {
+    Message (MSG_FATAL, "GeneticCodeTableLoad failed");
+    return 1;
+  }
+
+#ifdef INTERNAL_NCBI_TBL_CHK
+    SmartFetchEnable ();
+    TPASmartFetchEnable ();
+
+    if (! PUBSEQBioseqFetchEnable ("tbl_chk", FALSE)) {
+      Message (MSG_POSTERR, "PUBSEQBioseqFetchEnable failed");
+      return 1;
+    } 
+#else
+  PubSeqFetchEnable ();
+#endif
+
+  /* process command line arguments */
+
+  sprintf (app, "tbl_chk %s", TBL_CHK_APPLICATION);
+  if (! GetArgs (app, sizeof (myargs) / sizeof (Args), myargs)) {
+    return 0;
+  }
+
+  id_file = (CharPtr) myargs [i_argInputFile].strvalue;
+  debug_mode = (Boolean) myargs [D_argDebugMode].intvalue;
+  meta_mode = (Boolean) myargs [m_argMetaMode].intvalue;
+
+  fp = FileOpen (id_file, "r");
+  if (fp == NULL) {
+    Message (MSG_ERROR, "Unable to open %s", id_file);
+    return 1;
+  }
+
+  table = ReadTabTableFromFile (fp);
+  FileClose (fp);
+  if (table == NULL || table->next == NULL) {
+    Message (MSG_ERROR, "Table must have at least two rows, one header and one data");
+    return 1;
+  }
+
+  field_list = GetFieldListFromHeader(table->data.ptrvalue);
+  if (field_list == NULL) {
+    Message (MSG_ERROR, "Unable to read table header");
+    table = FreeTabTable (table);
+    return 1;
+  }
+  fetch_list = FetchItemListFromTable (table);
+  MakeFetchItemIndex(fetch_list);
+
+  fp = FileOpen ((CharPtr) myargs [o_argOutputFile].strvalue, "w");
+  if (fp == NULL) {
+    Message (MSG_ERROR, "Unable to open %s", (CharPtr) myargs [o_argOutputFile].strvalue);
+    rval = 1;
+  } else {
+    if (meta_mode) {
+      fprintf (fp, "Accession\tField\tOld Value\tNew Value\n");
+    }
+    ProcessBioseqsWithCaching (fetch_list, field_list, table, meta_mode, fp);
+  }
+  FileClose (fp);
+  field_list = FieldTypeListFree (field_list);
+  fetch_list = FetchItemListFree (fetch_list);
+  MakeFetchItemIndex(NULL);
+
+  return rval;
+}
+
diff --git a/desktop/asn2graphic.c b/desktop/asn2graphic.c
index dc05bd3..208e729 100644
--- a/desktop/asn2graphic.c
+++ b/desktop/asn2graphic.c
@@ -28,7 +28,7 @@
 *
 * Version Creation Date:   11/8/01
 *
-* $Revision: 6.130 $
+* $Revision: 6.132 $
 *
 * File Description:
 *
@@ -100,6 +100,7 @@ typedef struct viewerInstanceData {
   Uint4           featureCount;
   ValNodePtr      featVNP;      /* data.ptrvalue == RelevantFeatureItem [RELEVANT_FEATS_PER_CHUNK] */
   ValNodePtr      BSPsegmentVNP;
+  ValNodePtr      BSPsegmentTail;
   AppearancePtr   AppPtr;
   FilterPtr       FltPtr;
   LayoutAlgorithm overrideLayout;
@@ -3468,7 +3469,7 @@ static RelevantFeatureItemPtr GetNextRFIPinFeatureFilter (
 {
   ValNodePtr              currentRFIPblockVNP;
   FeatureFilterStatePtr   featSP;
-  RelevantFeatureItemPtr  RFIP;
+  RelevantFeatureItemPtr  RFIP = NULL;
   ViewerContextPtr        vContext;
   FilterItemPtr           currentFIP;
   FilterPtr               FP;
@@ -3717,7 +3718,7 @@ static Uint2 GeneProductsLayoutInternal (
   RelevantFeatureItemPtr  RFIP, RFIPcds, RFIPmrna, tRFIP;
   InternalRowPtr          thisRow, thisRow2, lastRow;
   ValNodePtr              fifoHead = NULL, fifoTail = NULL;
-  ValNodePtr              bumpedListHead, bumpedListTail;
+  ValNodePtr              bumpedListHead = NULL, bumpedListTail = NULL;
   ValNodePtr              potCDSvnp, potRNAvnp;
   ValNodePtr              GroupsHead = NULL, GroupsTailVNP, MemberTailVNP;
   ValNodePtr              groupVNP, featVNP;
@@ -4572,11 +4573,17 @@ static Boolean LIBCALLBACK Asn2gphSegmentExploreProc (
   AppearancePtr      AP;
   BioseqAppearanceItemPtr BioAIP;
   BioseqPtr          bsp;
+  ValNodePtr         vnp;
 
   if ((RFIP = MemNew (sizeof (RelevantFeatureItem))) == NULL) return FALSE;
   vContext = context->userdata;
   bsp = vContext->BSP;
-  ValNodeAddPointer (&vContext->BSPsegmentVNP, 0, RFIP);
+  vnp = ValNodeAddPointer (&vContext->BSPsegmentTail, 0, RFIP);
+  if (vContext->BSPsegmentVNP == NULL) {
+    vContext->BSPsegmentVNP = vnp;
+  }
+  vContext->BSPsegmentTail = vnp;
+  /* ValNodeAddPointer (&vContext->BSPsegmentVNP, 0, RFIP); */
   sip = SeqLocId (slp);
   if (sip != NULL && sip->choice == SEQID_GI /* && BioseqFindCore (sip) != NULL */) {
     gi = sip->data.intvalue;
@@ -4638,6 +4645,7 @@ static Int4 DrawBioseqSegments (
   Uint2         oldMaxScale;
 
   vContext->BSPsegmentVNP = NULL;
+  vContext->BSPsegmentTail = NULL;
   SeqMgrExploreSegments (vContext->BSP, vContext, Asn2gphSegmentExploreProc);
   listHead = vContext->BSPsegmentVNP;
   segmentCount = 0;
@@ -4700,6 +4708,7 @@ static Int4 DrawBioseqSegments (
   }
   ValNodeFreeData (listHead);
   vContext->BSPsegmentVNP = NULL;
+  vContext->BSPsegmentTail = NULL;
   vContext->AppPtr->FeaturesAppearanceItem[0] = oldAIPzero;
   vContext->FltPtr->MaxScaleWithLabels = oldMaxScale;
   return 2 * rowHeight + 7 + FIP->IntraRowPaddingPixels + FIP->GroupPadding;
@@ -6516,7 +6525,7 @@ NLM_EXTERN SegmenT CreateGraphicViewFromBsp (
       sintp = (SeqIntPtr) location->data.ptrvalue;
       if (sintp != NULL && sintp->from == 0 && sintp->to == bsp->length - 1) {
         location = NULL;
-      } else {
+      } else if (sintp != NULL) {
         from = sintp->from;
         to = sintp->to;
         allFeatures = FALSE;
diff --git a/desktop/biosrc.c b/desktop/biosrc.c
index e3850e3..b4bc013 100644
--- a/desktop/biosrc.c
+++ b/desktop/biosrc.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.93 $
+* $Revision: 6.96 $
 *
 * File Description: 
 *
@@ -120,6 +120,7 @@ typedef struct genbiopage {
   DoC             orglist;
   Int2            nuclGC;
   Int2            mitoGC;
+  Int2            pstdGC;
   Int4            taxID;
   DialoG          genome;
   PopuP           origin;
@@ -127,6 +128,7 @@ typedef struct genbiopage {
   PopuP           simplecode;
   PopuP           gcode;
   PopuP           mgcode;
+  PopuP           pgcode;
   TexT            lineage;
   TexT            gbDiv;
   DialoG          db;
@@ -1403,17 +1405,24 @@ static void ChangeGencodePopups (GenBioPagePtr gbp)
                    genome == GENOME_cyanelle ||
                    genome == GENOME_apicoplast ||
                    genome == GENOME_leucoplast ||
-                   genome == GENOME_proplastid) {
+                   genome == GENOME_proplastid ||
+                   genome == GENOME_chromatophore) {
+          if (gbp->pstdGC > 0) {
+            SafeSetValue (gbp->simplecode, gcIdToIndex [gbp->pstdGC]);
+          } else {
           SafeSetValue (gbp->simplecode, gcIdToIndex [11]);
+          }
         } else {
           SafeSetValue (gbp->simplecode, gcIdToIndex [gbp->nuclGC]);
         }
       }
       SafeSetValue (gbp->gcode, gcIdToIndex [gbp->nuclGC]);
       SafeSetValue (gbp->mgcode, gcIdToIndex [gbp->mitoGC]);
+      SafeSetValue (gbp->pgcode, gcIdToIndex [gbp->pstdGC]);
     } else {
       SafeSetValue (gbp->gcode, gcIdToIndex [gbp->nuclGC]);
       SafeSetValue (gbp->mgcode, gcIdToIndex [gbp->mitoGC]);
+      SafeSetValue (gbp->pgcode, gcIdToIndex [gbp->pstdGC]);
     }
   }
 }
@@ -1428,6 +1437,7 @@ static void SetCodes (GenBioPagePtr gbp, Int2 row, Boolean changepopups)
     StrToInt (str, &gbp->nuclGC);
     CopyStrFromTaxPtr (str, sizeof (str) - 2, row, 4);
     StrToInt (str, &gbp->mitoGC);
+    gbp->pstdGC = 0;
     CopyStrFromTaxPtr (str, sizeof (str) - 2, row, 5);
     SafeSetTitle (gbp->gbDiv, str);
     CopyStrFromTaxPtr (str, sizeof (str) - 2, row, 6);
@@ -1463,6 +1473,7 @@ static void AutoScrollTax (GenBioPagePtr gbp, TexT t, Boolean isSciName,
   if (gbp != NULL && t != NULL) {
     gbp->nuclGC = 0;
     gbp->mitoGC = 0;
+    gbp->pstdGC = 0;
     gbp->taxID = 0;
     SafeSetTitle (gbp->gbDiv, "");
     GetTitle (t, str, sizeof (str) - 2);
@@ -1630,6 +1641,7 @@ static void ReleaseTaxName (DoC d, PoinT pt)
   if (gbp != NULL) {
     gbp->nuclGC = 0;
     gbp->mitoGC = 0;
+    gbp->pstdGC = 0;
     gbp->taxID = 0;
     SafeSetTitle (gbp->gbDiv, "");
     MapDocPoint (d, pt, &item, &row, NULL, NULL);
@@ -1822,6 +1834,7 @@ static void BioSourcePtrToGenBioPage (DialoG d, Pointer data)
     gbp->clickedOrg = 0;
     gbp->nuclGC = 0;
     gbp->mitoGC = 0;
+    gbp->pstdGC = 0;
     gbp->taxID = 0;
     SafeSetTitle (gbp->gbDiv, "");
     SafeSetValue (gbp->genome, 2);
@@ -1829,6 +1842,7 @@ static void BioSourcePtrToGenBioPage (DialoG d, Pointer data)
     SafeSetStatus (gbp->is_focus, FALSE);
     SafeSetValue (gbp->gcode, 1);
     SafeSetValue (gbp->mgcode, 1);
+    SafeSetValue (gbp->pgcode, 1);
     SafeSetValue (gbp->simplecode, 1);
     SafeSetTitle (gbp->gbacr, "");
     SafeSetTitle (gbp->gbana, "");
@@ -1899,6 +1913,7 @@ static void BioSourcePtrToGenBioPage (DialoG d, Pointer data)
         SafeSetTitle (gbp->gbDiv, "");
         SafeSetValue (gbp->gcode, 1);
         SafeSetValue (gbp->mgcode, 1);
+        SafeSetValue (gbp->pgcode, 1);
         SafeSetValue (gbp->simplecode, 1);
       }
     }
@@ -1910,6 +1925,9 @@ static void BioSourcePtrToGenBioPage (DialoG d, Pointer data)
       if (onp->mgcode > 0) {
         gbp->mitoGC = onp->mgcode;
       }
+      if (onp->pgcode > 0) {
+        gbp->pstdGC = onp->pgcode;
+      }
       if (gbp->simplecode != NULL) {
         vnp = DialogToPointer (gbp->genome);
         if (vnp != NULL) {
@@ -1923,7 +1941,8 @@ static void BioSourcePtrToGenBioPage (DialoG d, Pointer data)
                      genome == GENOME_cyanelle ||
                      genome == GENOME_apicoplast ||
                      genome == GENOME_leucoplast ||
-                     genome == GENOME_proplastid) {
+                     genome == GENOME_proplastid ||
+                     genome == GENOME_chromatophore) {
             SafeSetValue (gbp->simplecode, gcIdToIndex [11]);
           } else {
             SafeSetValue (gbp->simplecode, gcIdToIndex [onp->gcode]);
@@ -1931,9 +1950,11 @@ static void BioSourcePtrToGenBioPage (DialoG d, Pointer data)
         }
         SafeSetValue (gbp->gcode, gcIdToIndex [onp->gcode]);
         SafeSetValue (gbp->mgcode, gcIdToIndex [onp->mgcode]);
+        SafeSetValue (gbp->pgcode, gcIdToIndex [onp->pgcode]);
       } else {
         SafeSetValue (gbp->gcode, gcIdToIndex [onp->gcode]);
         SafeSetValue (gbp->mgcode, gcIdToIndex [onp->mgcode]);
+        SafeSetValue (gbp->pgcode, gcIdToIndex [onp->pgcode]);
       }
     }
     RestorePort (tempPort);
@@ -2035,14 +2056,17 @@ static Pointer GenBioPageToBioSourcePtr (DialoG d)
               if (genome == 4 || genome == 5) {
                 onp->mgcode = gcIndexToId [GetValue (gbp->simplecode)];
                 onp->gcode = gcIndexToId [GetValue (gbp->gcode)];
+                onp->pgcode = gcIndexToId [GetValue (gbp->pgcode)];
               } else {
                 onp->gcode = gcIndexToId [GetValue (gbp->simplecode)];
                 onp->mgcode = gcIndexToId [GetValue (gbp->mgcode)];
+                onp->pgcode = gcIndexToId [GetValue (gbp->pgcode)];
               }
             }
           } else {
             onp->gcode = gcIndexToId [GetValue (gbp->gcode)];
             onp->mgcode = gcIndexToId [GetValue (gbp->mgcode)];
+            onp->pgcode = gcIndexToId [GetValue (gbp->pgcode)];
           }
           if (! TextHasNoText (gbp->gbDiv)) {
             onp->div = SaveStringFromText (gbp->gbDiv);
@@ -2157,7 +2181,7 @@ static Pointer GenBioPageToBioSourcePtr (DialoG d)
             }
           }
           if (onp->lineage == NULL && onp->mod == NULL &&
-              onp->gcode == 0 && onp->mgcode == 0) {
+              onp->gcode == 0 && onp->mgcode == 0 && onp->pgcode == 0) {
             orp->orgname = OrgNameFree (orp->orgname);
           }
         }
@@ -2176,7 +2200,8 @@ static Pointer GenBioPageToBioSourcePtr (DialoG d)
           && biop->genome != GENOME_plastid
           && biop->genome != GENOME_apicoplast
           && biop->genome != GENOME_leucoplast
-          && biop->genome != GENOME_proplastid)
+          && biop->genome != GENOME_proplastid
+          && biop->genome != GENOME_chromatophore)
       {
         tmpssp = biop->subtype;
         while (tmpssp != NULL)
@@ -2406,8 +2431,12 @@ extern DialoG CreateSimpleBioSourceDialog (GrouP h, CharPtr title)
     gbp->mgcode = PopupList (x, TRUE, NULL);
     PopulateGeneticCodePopup (gbp->mgcode);
     SetValue (gbp->mgcode, 1);
+    gbp->pgcode = PopupList (x, TRUE, NULL);
+    PopulateGeneticCodePopup (gbp->pgcode);
+    SetValue (gbp->pgcode, 1);
     Hide (gbp->gcode);
     Hide (gbp->mgcode);
+    Hide (gbp->pgcode);
 
     SelectFont (systemFont);
   }
@@ -3326,6 +3355,10 @@ static DialoG CreateBioSourceDialog (GrouP h, CharPtr title, GrouP PNTR pages,
     gbp->mgcode = PopupList (f, TRUE, NULL);
     PopulateGeneticCodePopup (gbp->mgcode);
     SetValue (gbp->mgcode, 1);
+    StaticPrompt (f, "Plastid", 0, popupMenuHeight, programFont, 'l');
+    gbp->pgcode = PopupList (f, TRUE, NULL);
+    PopulateGeneticCodePopup (gbp->pgcode);
+    SetValue (gbp->pgcode, 1);
 
     Hide (gbp->orgGrp [2]);
 
@@ -3764,6 +3797,7 @@ static void BioSourceDescFormAcceptButtonProc (ButtoN b)
 
 {
   if (OkayToAcceptBioSource (b)) {
+
     StdAcceptFormButtonProc (b);
   }
 }
@@ -4267,7 +4301,11 @@ extern Int2 LIBCALLBACK BioSourceGenFunc (Pointer data)
   } else if (sdp != NULL) {
     w = (WindoW) CreateBioSourceDescForm (-50, -33, -10, -10,
                                           "Organism Information", sdp, sep,
+#if 0
                                           StdDescFormActnProc, NULL);
+#else
+                                          StdDescFormActnProcNoFeatureChangeNoMolInfoChange, NULL);
+#endif
   } else {
     itemtype = proc->inputtype;
     subtype = proc->subinputtype;
diff --git a/desktop/bspview.c b/desktop/bspview.c
index f830405..2c3d839 100644
--- a/desktop/bspview.c
+++ b/desktop/bspview.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/30/95
 *
-* $Revision: 6.142 $
+* $Revision: 6.145 $
 *
 * File Description: 
 *
@@ -351,6 +351,7 @@ static void AddOneBlastAlignment (BioseqPtr subject, BioseqPtr query)
   SeqAnnotPtr          curr;
   BLAST_OptionsBlkPtr  options = NULL;
   SeqAlignPtr          prev;
+  CharPtr              program_name = NULL;
   SeqAlignPtr          salp;
   SeqAnnotPtr          sap;
   SeqAnnotPtr PNTR     sapp;
@@ -363,7 +364,8 @@ static void AddOneBlastAlignment (BioseqPtr subject, BioseqPtr query)
   if (ISA_na (subject->mol)) {
     if (! ISA_na (query->mol)) return;
     align_type = 1;
-    options = BLASTOptionNew ("blastn", TRUE);
+    program_name = "blastn";
+    options = BLASTOptionNew (program_name, TRUE);
     if (options != NULL) {
       options->gapped_calculation = TRUE;
       options->db_length = 100000000;
@@ -376,14 +378,15 @@ static void AddOneBlastAlignment (BioseqPtr subject, BioseqPtr query)
   } else if (ISA_aa (subject->mol)) {
     if (! ISA_aa (query->mol)) return;
     align_type = 2;
-    options = BLASTOptionNew ("blastp", TRUE);
+    program_name = "blastp";
+    options = BLASTOptionNew (program_name, TRUE);
     if (options != NULL) {
       options->gapped_calculation = TRUE;
       options->db_length = 20000000;
       options->threshold_second = 12;
     }
   } else return;
-  search = BLASTSetUpSearch (subject, options->program_name, 0, 0, NULL, options, NULL);
+  search = BLASTSetUpSearch (subject, program_name, 0, 0, NULL, options, NULL);
 
   salp = BlastSequencesOnTheFly (search, query);
   if (salp != NULL) {
@@ -1667,6 +1670,26 @@ static void AdjustDynamicGraphicViewer (BioseqViewPtr bvp)
   }
 }
 
+
+NLM_EXTERN void HideBioseqView (WindoW w)
+{
+  BioseqViewFormPtr bfp;
+  BioseqPagePtr     bpp;
+
+  bfp = (BioseqViewFormPtr) GetObjectExtra (w);
+  if (bfp != NULL) {
+    WatchCursor ();
+    bfp->bvd.scaleNotCalculated = TRUE;
+    bfp->bvd.moveToOldPos = FALSE;
+    bpp = bfp->currentBioseqPage;
+    if (bpp != NULL && bpp->show != NULL) {
+      bpp->show (&(bfp->bvd), FALSE);
+    }
+    Update ();
+  }
+}
+
+
 static void ChangeBioseqViewTabs (VoidPtr data, Int2 newval, Int2 oldval)
 
 {
@@ -2927,7 +2950,7 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti
         if (svpp->initNucLabel != NULL) {
           bpp = bfp->bioseqNucPageList;
           str = svpp->initNucLabel;
-          if (bsp->length > 350000) {
+          if (bsp != NULL && bsp->length > 350000) {
             /*
             if (is_nc) {
               str = "GenBank";
@@ -3007,7 +3030,7 @@ static ForM LIBCALL CreateNewSeqEntryViewFormEx (Int2 left, Int2 top, CharPtr ti
       h = HiddenGroup (d, 0, 0, NULL);
     } else {
       d = HiddenGroup (g, -2, 0, NULL);
-      if (svpp->hasDuplicateButton) {
+      if (svpp != NULL && svpp->hasDuplicateButton) {
         dp = PushButton (d, "Duplicate", DuplicateViewProc);
         SetObjectExtra (dp, bfp, NULL);
       }
@@ -3849,6 +3872,43 @@ extern ForM MakeToolFormForBioseqView (BaseFormPtr bafp, GrpActnProc createToolB
   return (ForM) w;
 }
 
+extern ForM ReplaceToolFormForBioseqView (BaseFormPtr bafp, GrpActnProc createToolBar)
+
+{
+  BioseqViewFormPtr  bfp;
+  GrouP              g;
+  CharPtr            ptr;
+  Char               str [256];
+  WindoW             w;
+  Int2               left, top;
+
+  bfp = (BioseqViewFormPtr) bafp;
+  if (bfp == NULL || createToolBar == NULL) return NULL;
+  if (bfp->toolForm != NULL) {
+    bfp->toolForm = Remove (bfp->toolForm);
+  }
+  
+  GetTitle (bfp->form, str, sizeof (str));
+  TrimSpacesAroundString (str);
+  ptr = StringStr (str, " - ");
+  if (ptr != NULL) {
+    *ptr = '\0';
+  }
+  if (StringHasNoText (str)) {
+    StringCpy (str, "ToolBar");
+  }
+  
+  GetToolBarRect (&left, &top);
+  w = FixedWindow (left, top, -10, -10, str, ToolFormHideWindowProc);
+  if (w == NULL) return NULL;
+  g = HiddenGroup (w, -1, 0, NULL);
+  SetObjectExtra (g, bfp, NULL);
+  createToolBar (g);
+  RealizeWindow (w);
+  bfp->toolForm = (ForM) w;
+  return (ForM) w;
+}
+
 extern ForM RemoveSeqEntryViewer (ForM f)
 
 {
diff --git a/desktop/bspview.h b/desktop/bspview.h
index 693df44..e05d944 100644
--- a/desktop/bspview.h
+++ b/desktop/bspview.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/30/95
 *
-* $Revision: 6.63 $
+* $Revision: 6.65 $
 *
 * File Description: 
 *
@@ -377,9 +377,12 @@ extern BioseqPagePtr LIBCALL BioseqPageListFree (BioseqPagePtr bpp);
 extern IteM CreateLegendItem (MenU m, BaseFormPtr bfp);
 
 extern ForM MakeToolFormForBioseqView (BaseFormPtr bfp, GrpActnProc createToolBar);
+extern ForM ReplaceToolFormForBioseqView (BaseFormPtr bafp, GrpActnProc createToolBar);
 extern void SetBioseqViewTarget (BaseFormPtr fp, CharPtr seqId);
 extern BioseqPtr GetBioseqViewTarget (BaseFormPtr fp);
 
+NLM_EXTERN void HideBioseqView (WindoW w);
+
 extern BioseqViewPtr GetBioseqViewPtrFromBaseFormPtr (BaseFormPtr fp);
 NLM_EXTERN void Nlm_LaunchWebPage (Char *url);
 
diff --git a/desktop/cdrgn.c b/desktop/cdrgn.c
index e8e1390..fdd935b 100644
--- a/desktop/cdrgn.c
+++ b/desktop/cdrgn.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.120 $
+* $Revision: 6.126 $
 *
 * File Description: 
 *
@@ -58,6 +58,10 @@
 #include <explore.h>
 #include <pmfapi.h>
 #include <seqpanel.h>
+#include <sqnutils.h>
+#define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
+#include <macroapi.h>
 
 #define CODING_REGION_PAGE    0
 #define GENE_PAGE             0
@@ -1769,6 +1773,8 @@ static void DoPredictCdRegion (CdRgnFormPtr cfp)
         slp = PredictCodingRegion (nucbsp, protbsp, code);
         if (slp != NULL && SeqLocStop (slp) > nucbsp->length - 1) {
           Message (MSG_ERROR, "Warning!  Nucleotide is not long enough for protein sequence!");
+        } else if (slp == NULL && nucbsp->length / 3 < protbsp->length) {
+          Message (MSG_ERROR, "Warning!  Nucleotide is not long enough for protein sequence!");
         }
         PointerToDialog (cfp->location, slp);
         if (slp != NULL) {
@@ -2232,7 +2238,7 @@ static void AddProteinToCDSDialog (
 
 static void DownloadProteinFromEntrez (ButtoN b)
 {
-  SeqEntryPtr   sep;
+  SeqEntryPtr   sep = NULL;
   Int4          uid;
   BioseqPtr     bsp;
   CdRgnFormPtr  cfp;
@@ -2541,7 +2547,7 @@ static Boolean LengthenLocation (SeqLocPtr head, Int4 len)
     slp = SeqLocFindNext (head, slp);
   }
 
-  if (last_slp->choice == SEQLOC_INT) {
+  if (last_slp != NULL && last_slp->choice == SEQLOC_INT) {
     sintp = (SeqIntPtr) last_slp->data.ptrvalue;
     if (sintp->strand == Seq_strand_minus) {
       if (sintp->from - len_diff >= 0) {
@@ -2555,7 +2561,7 @@ static Boolean LengthenLocation (SeqLocPtr head, Int4 len)
         rval = TRUE;
       }
     }      
-  } else if (last_slp->choice == SEQLOC_PNT) {
+  } else if (last_slp != NULL && last_slp->choice == SEQLOC_PNT) {
     spp = (SeqPntPtr) last_slp->data.ptrvalue;
     rval = TRUE;
     if (spp->strand == Seq_strand_minus) {
@@ -3283,6 +3289,335 @@ static CharPtr infWarning2 =
 static CharPtr infAccept =
 "Do you want to accept changes with bad inference data?  The bad qualifier will be converted to a note!";
 
+static Boolean SeeIfProtTitleNeedsFixing (BioseqPtr bsp, Uint2 entityID);
+
+
+static Boolean NoChangeInGene (CdRgnFormPtr cfp, SeqFeatPtr sfp)
+{
+  Int2 usexref, val, i;
+  GeneRefPtr grp_new, grp_orig, grpfeat;
+  Boolean    rval = TRUE;
+  ValNodePtr vnp;
+  CharPtr    str;
+  SeqFeatPtr gene;
+  Char       symbol [128];
+  Char       allele [128];
+  Char       locustag [128];
+  Char       desc [128];
+  BioseqPtr  bsp;
+  SeqMgrFeatContext fcontext;
+
+  usexref = GetValue (cfp->useGeneXref);
+  if (usexref == 3) {
+    /* protein feature can now suppress gene on GenBank view */
+    grp_orig = SeqMgrGetGeneXref (sfp);
+    if (SeqMgrGeneIsSuppressed(grp_orig)) {
+      rval = TRUE;
+    } else {
+      rval = FALSE;
+    }
+  } else if (cfp->gene != NULL) {
+    val = GetValue (cfp->gene);
+    if (usexref == 2) {
+      if (val == 2) {
+        /* new gene - ok if "new" gene xref matches old gene xref (represents gene not on sequence) */
+        grp_orig = SeqMgrGetGeneXref (sfp);
+        GetTitle (cfp->geneSymbol, symbol, sizeof (symbol));
+        GetTitle (cfp->geneAllele, allele, sizeof (allele));
+        GetTitle (cfp->geneDesc, desc, sizeof (desc));
+        GetTitle (cfp->locusTag, locustag, sizeof (locustag));
+        grp_new = CreateNewGeneRef (symbol, allele, desc, FALSE);
+        if (! StringHasNoText (locustag)) {
+          if (grp_new == NULL) {
+            grp_new = GeneRefNew ();
+          }
+          grp_new->locus_tag = StringSave (locustag);
+        }
+        if (!TextHasNoText (cfp->geneSynonym)) {
+          if (grp_new == NULL) {
+            grp_new = GeneRefNew ();
+          }
+          ValNodeAddPointer (&(grp_new->syn), 0, SaveStringFromText (cfp->geneSynonym));
+        }
+        if (AsnIoMemComp (grp_orig, grp_new, (AsnWriteFunc) GeneRefAsnWrite)) {
+          rval = TRUE;
+        } else {
+          rval = FALSE;
+        }
+        grp_new = GeneRefFree (grp_new);
+      } else {
+        /* mapping by crossref to existing gene - ok if mapping to same gene */
+        grp_orig = SeqMgrGetGeneXref (sfp);
+        grp_new = NULL;
+        vnp = cfp->geneNames;
+        i = val - 3;
+        while (i > 0 && vnp != NULL) {
+          vnp = vnp->next;
+          i--;
+        }
+        if (vnp != NULL) {
+          if (vnp->choice == 1) {
+            str = (CharPtr) vnp->data.ptrvalue;
+            if (StringDoesHaveText (str)) {
+              grp_new = CreateNewGeneRef (str, NULL, NULL, FALSE);
+              bsp = BioseqFindFromSeqLoc (sfp->location);
+              gene = SeqMgrGetFeatureByLabel (bsp, str, SEQFEAT_GENE, 0, &fcontext);
+              if (gene != NULL && gene->data.choice == SEQFEAT_GENE) {
+                grpfeat = (GeneRefPtr) gene->data.value.ptrvalue;
+                if (grpfeat != NULL) {
+                  grp_new->locus_tag = StringSaveNoNull (grpfeat->locus_tag);
+                }
+              }
+            }
+          } else if (vnp->choice == 2) {
+            grp_new = GeneRefNew ();
+            if (grp_new != NULL) {
+              grp_new->desc = StringSave ((CharPtr) vnp->data.ptrvalue);
+            }
+         } else if (vnp->choice == 3) {
+            grp_new = GeneRefNew ();
+            if (grp_new != NULL) {
+              grp_new->locus_tag = StringSave ((CharPtr) vnp->data.ptrvalue);
+            }
+          }
+        }
+        if (AsnIoMemComp (grp_orig, grp_new, (AsnWriteFunc) GeneRefAsnWrite)) {
+          rval = TRUE;
+        } else {
+          rval = FALSE;
+        }
+        grp_new = GeneRefFree (grp_new);
+      }
+    } else if (usexref == 1 && val == 2) {
+      /* overlap to new gene, creates new gene */
+      rval = FALSE;
+    }
+  }
+  return rval;
+}
+
+
+static Boolean LabelChangeOnly (CdRgnFormPtr cfp)
+{
+  SeqFeatPtr        sfp;
+  SeqMgrFeatContext context;
+  SeqLocPtr         slp;
+  Int2              cmp;
+  Boolean           pseudo;
+  GBQualPtr         qual, gbq;
+  BioseqPtr         bsp_new, bsp_old = NULL;
+  Boolean           match;
+  CharPtr           str1, str2;
+  Int2              expev;
+  SeqFeatPtr        mrna, prot;
+  RnaRefPtr         rrp;
+  ProtRefPtr        prp;
+  SeqFeatPtr        sfp_tmp;
+
+  if (cfp == NULL || cfp->input_itemtype != OBJ_SEQFEAT) 
+  {
+    return FALSE;
+  }
+
+  if (GetStatus (cfp->convertToMiscFeat))
+  {
+    return FALSE;
+  }
+  
+  if (cfp->autoRetranslate) 
+  {
+    return FALSE;
+  }
+
+  sfp = SeqMgrGetDesiredFeature (cfp->input_entityID, NULL, cfp->input_itemID, 0, NULL, &context);
+  if (sfp == NULL) 
+  {
+    return FALSE;
+  }
+
+  /* location needs to be the same */
+  slp = DialogToPointer (cfp->location);
+  match = AsnIoMemComp (slp, sfp->location, (AsnWriteFunc) SeqLocAsnWrite);
+  slp = SeqLocFree (slp);
+  if (!match)
+  {
+    return FALSE;
+  }
+
+  /* either was and is pseudo, or was not and is not pseudo */
+  pseudo = FALSE;
+  if (GetStatus (cfp->pseudo))
+  {
+    pseudo = TRUE;
+  }
+  else
+  {
+    qual = (GBQualPtr) DialogToPointer (cfp->gbquals);
+    gbq = qual;
+    while (gbq != NULL) {
+      if (StringICmp (gbq->qual, "pseudo") == 0) {
+        pseudo = TRUE;
+      }
+      gbq = gbq->next;
+    }
+    GBQualFree (qual);
+  }
+
+  if ((pseudo && !sfp->pseudo) || (!pseudo && sfp->pseudo)) 
+  {
+    return FALSE;
+  }
+
+  if (!pseudo) 
+  {
+    /* products need to be the same */
+    slp = DialogToPointer (cfp->product);
+    cmp = SeqLocCompare (slp, sfp->product);
+    
+    if (cmp != SLC_A_EQ_B) 
+    {
+      slp = SeqLocFree (slp);
+      return FALSE;
+    }
+    /* check translation */
+    bsp_new = (BioseqPtr) DialogToPointer (cfp->protseq);
+    bsp_old = BioseqFindFromSeqLoc (slp);
+    slp = SeqLocFree (slp);
+    match = TRUE;
+    if (bsp_new == NULL || bsp_old == NULL) {
+      match = FALSE;
+    } else if (bsp_new->length != bsp_old->length) {
+      match = FALSE;
+    } else {
+      str1 = GetSequenceByBsp (bsp_new);
+      str2 = GetSequenceByBsp (bsp_old);
+      if (StringCmp (str1, str2) != 0) {
+        match = FALSE;
+      }
+      str1 = MemFree (str1);
+      str2 = MemFree (str2);
+    }
+    bsp_new = BioseqFree (bsp_new);
+    if (!match) {
+      return FALSE;
+    }
+  }
+
+  if (!NoChangeInGene(cfp, sfp)) {
+    return FALSE;
+  }
+
+  /* check feature IDs - no change allowed */
+  sfp_tmp = SeqFeatNew ();
+  if (cfp->featid != NULL) {
+    TextToFeatID (cfp->featid, &(sfp_tmp->id));
+  }
+  if ((sfp->id.choice == 0 && sfp_tmp->id.choice != 0)
+      || (sfp->id.choice != 0 && sfp_tmp->id.choice == 0)) {
+    match = FALSE;
+  } else {
+    match = AsnIoMemComp (&(sfp_tmp->id), &(sfp->id), (AsnWriteFunc) SeqFeatIdAsnWrite);
+  }
+  if (match) {
+    /* check feature ID xrefs - no change allowed */
+    if (cfp->fidxref != NULL) {
+      TextToFeatXref (cfp->fidxref, sfp_tmp);
+    }
+    if (sfp->xref != NULL || sfp_tmp->xref != NULL) {
+      match = AsnIoMemComp (sfp->xref, sfp_tmp->xref, (AsnWriteFunc) SeqFeatXrefAsnWrite);
+    }
+  }
+  sfp_tmp = SeqFeatFree (sfp_tmp);
+  if (!match) {
+    return FALSE;
+  }
+
+
+  /* do replacements */
+  sfp->data.value.ptrvalue = CdRegionFree (sfp->data.value.ptrvalue);
+  sfp->data.value.ptrvalue = DialogToPointer (cfp->data);
+  sfp->comment = MemFree (sfp->comment);
+  sfp->comment = SaveStringFromText (cfp->comment);
+  NewlinesToTildes (sfp->comment);
+  expev = GetValue (cfp->evidence);
+  if (expev > 0 && expev <= 3) {
+    sfp->exp_ev = expev - 1;
+  } else {
+    sfp->exp_ev = 0;
+  }
+  sfp->partial = GetStatus (cfp->partial);
+  sfp->excpt = GetStatus (cfp->exception);
+  sfp->pseudo = GetStatus (cfp->pseudo);
+  sfp->except_text = MemFree (sfp->except_text);
+  sfp->except_text = SaveStringFromText (cfp->exceptText);
+  sfp->title = NULL;
+  sfp->cit = PubSetFree(sfp->cit);
+  sfp->cit = DialogToPointer (cfp->featcits);
+  sfp->xref = SeqFeatXrefFree(sfp->xref);
+  sfp->dbxref = DialogToPointer (cfp->dbxrefs);
+
+  CleanupEvidenceGBQuals (&(sfp->qual));
+  VisStringDialogToGbquals (sfp, cfp->experiment, "experiment");
+  InferenceDialogToGBQuals (cfp->inference, sfp, TRUE);
+
+  FixSpecialCharactersForObject (OBJ_SEQFEAT, sfp, "You may not include special characters in the text.\nIf you do not choose replacement characters, these special characters will be replaced with '#'.", TRUE, NULL);
+  if (cfp->gbquals != NULL) {
+    sfp->qual = GBQualFree(sfp->qual);
+    sfp->qual = DialogToPointer (cfp->gbquals);
+  }
+
+ 
+  /* clean up the feature */
+  CleanupOneSeqFeat (sfp);
+ 
+  if (pseudo) {
+    /* TODO - put product name/description in comment? */
+  } else {
+    prot = SeqMgrGetNextFeature (bsp_old, NULL, SEQFEAT_PROT, FEATDEF_PROT, &context);
+    if (prot != NULL) {
+      prp = (ProtRefPtr) prot->data.value.ptrvalue;
+      if (prp == NULL) {
+        prp = ProtRefNew ();
+        prot->data.value.ptrvalue = prp;
+      }
+      if (prp->name == NULL) {
+        ValNodeAddPointer (&(prp->name), 0, SaveStringFromText (cfp->protNameText));
+      } else {
+        prp->name->data.ptrvalue = MemFree (prp->name->data.ptrvalue);
+        prp->name->data.ptrvalue = SaveStringFromText (cfp->protNameText);
+      }
+      prp->desc = MemFree (prp->desc);
+      prp->desc = SaveStringFromText (cfp->protDescText);
+    }
+    SeeIfProtTitleNeedsFixing (bsp_old, bsp_old->idx.entityID);
+  }
+
+  /* adjust mRNA product name */
+  if (GetStatus (cfp->makemRNAMatch)) {
+    mrna = SeqMgrGetOverlappingmRNA (sfp->location, &context);
+    if (mrna != NULL && mrna->idx.subtype == FEATDEF_mRNA) {
+      rrp = (RnaRefPtr) mrna->data.value.ptrvalue;
+      if (rrp == NULL) {
+        rrp = RnaRefNew();
+        mrna->data.value.ptrvalue = rrp;
+      }
+      rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+      if (TextHasNoText (cfp->protNameText)) {
+        rrp->ext.choice = 0;
+      } else {
+        rrp->ext.choice = 1;
+        rrp->ext.value.ptrvalue = SaveStringFromText (cfp->protNameText);
+      }
+    }
+  }
+
+  ObjMgrSendMsgOnlyFeatLabelChange (OM_MSG_UPDATE, cfp->input_entityID,
+                     cfp->input_itemID, cfp->input_itemtype);
+
+  return TRUE;
+}
+
+
 static void CdRgnFormAcceptButtonProc (ButtoN b)
 
 {
@@ -3299,7 +3634,7 @@ static void CdRgnFormAcceptButtonProc (ButtoN b)
   GBQualPtr      qual;
   SeqEntryPtr    sep;
   SeqIdPtr       sip;
-  SeqLocPtr      slp;
+  SeqLocPtr      slp = NULL;
   Char           str [128];
   WindoW         w;
   SeqLocPtr      prod_slp;
@@ -3310,6 +3645,7 @@ static void CdRgnFormAcceptButtonProc (ButtoN b)
   if (b != NULL) {
     w = ParentWindow (b);
     cfp = (CdRgnFormPtr) GetObjectExtra (b);
+
     if (cfp != NULL && cfp->form != NULL && cfp->actproc != NULL) {
       sep = GetTopSeqEntryForEntityID (cfp->input_entityID);
       oldscope = SeqEntrySetScope (sep);
@@ -3488,8 +3824,11 @@ static void CdRgnFormAcceptButtonProc (ButtoN b)
           }
         }
       }
+      if (LabelChangeOnly(cfp)) {
       
+      } else {
       (cfp->actproc) (cfp->form);
+      }
       SeqEntrySetScope (oldscope);
     }
     SeqLocFree (slp);
@@ -4225,195 +4564,6 @@ extern Int2 LIBCALLBACK CdRgnGenFunc (Pointer data)
   return OM_MSG_RET_DONE;
 }
 
-typedef struct geneuserpage {
-  DIALOG_MESSAGE_BLOCK
-  TexT          symbol;
-  TexT          name;
-  TexT          source;
-  GrouP         status;
-} GeneUserData, PNTR GeneUserPtr;
-
-static void UserObjectPtrToGene (DialoG d, Pointer data)
-
-{
-  GeneUserPtr    gup;
-  ObjectIdPtr    oip;
-  CharPtr        str;
-  UserFieldPtr   ufp;
-  UserObjectPtr  uop;
-
-  gup = (GeneUserPtr) GetObjectExtra (d);
-  uop = (UserObjectPtr) data;
-  if (gup != NULL) {
-    if (uop != NULL && uop->type != NULL && StringICmp (uop->type->str, "OfficialNomenclature") == 0) {
-      for (ufp = uop->data; ufp != NULL; ufp = ufp->next) {
-        oip = ufp->label;
-        if (oip == NULL || oip->str == NULL) continue;
-        if (StringICmp (oip->str, "Symbol") == 0) {
-          if (ufp->choice == 1) {
-            str = (CharPtr) ufp->data.ptrvalue;
-            if (str != NULL) {
-              SetTitle (gup->symbol, str);
-            }
-          }
-        } else if (StringICmp (oip->str, "Name") == 0) {
-          if (ufp->choice == 1) {
-            str = (CharPtr) ufp->data.ptrvalue;
-            if (str != NULL) {
-              SetTitle (gup->name, str);
-            }
-          }
-        } else if (StringICmp (oip->str, "DataSource") == 0) {
-          if (ufp->choice == 1) {
-            str = (CharPtr) ufp->data.ptrvalue;
-            if (str != NULL) {
-              SetTitle (gup->source, str);
-            }
-          }
-        } else if (StringICmp (oip->str, "Status") == 0) {
-          if (ufp->choice == 1) {
-            str = (CharPtr) ufp->data.ptrvalue;
-            if (str != NULL) {
-              if (StringICmp (str, "Official") == 0) {
-                SetValue (gup->status, 1);
-              } else if (StringICmp (str, "Interim") == 0) {
-                SetValue (gup->status, 2);
-              }
-            }
-          }
-        }
-      }
-      ufp = uop->data;
-      if (ufp != NULL && ufp->choice == 1) {
-        oip = ufp->label;
-        if (oip != NULL && oip->str != NULL && StringICmp (oip->str, "Symbol") == 0) {
-          str = (CharPtr) ufp->data.ptrvalue;
-          if (str != NULL) {
-            SetTitle (gup->symbol, str);
-          }
-        }
-      }
-    }
-  }
-}
-
-static UserObjectPtr CreateGeneUserObject (
-  GeneUserPtr gup
-)
-
-{
-  UserFieldPtr   last = NULL;
-  ObjectIdPtr    oip;
-  UserFieldPtr   ufp;
-  UserObjectPtr  uop;
-  Int2           val;
-
-  if (gup == NULL) return NULL;
-  if (TextHasNoText (gup->symbol)) return NULL;
-
-  uop = UserObjectNew ();
-  oip = ObjectIdNew ();
-  oip->str = StringSave ("OfficialNomenclature");
-  uop->type = oip;
-
-  ufp = UserFieldNew ();
-  oip = ObjectIdNew ();
-  oip->str = StringSave ("Symbol");
-  ufp->label = oip;
-  ufp->choice = 1; /* visible string */
-  ufp->data.ptrvalue = (Pointer) SaveStringFromText (gup->symbol);
-
-  uop->data = ufp;
-  last = ufp;
-
-  if (! TextHasNoText (gup->name)) {
-    ufp = UserFieldNew ();
-    oip = ObjectIdNew ();
-    oip->str = StringSave ("Name");
-    ufp->label = oip;
-    ufp->choice = 1; /* visible string */
-    ufp->data.ptrvalue = (Pointer) SaveStringFromText (gup->name);
-    last->next = ufp;
-    last = ufp;
-  }
-
-  if (! TextHasNoText (gup->source)) {
-    ufp = UserFieldNew ();
-    oip = ObjectIdNew ();
-    oip->str = StringSave ("DataSource");
-    ufp->label = oip;
-    ufp->choice = 1; /* visible string */
-    ufp->data.ptrvalue = (Pointer) SaveStringFromText (gup->source);
-    last->next = ufp;
-    last = ufp;
-  }
-
-  val = GetValue (gup->status);
-  if (val == 1 || val == 2) {
-    ufp = UserFieldNew ();
-    oip = ObjectIdNew ();
-    oip->str = StringSave ("Status");
-    ufp->label = oip;
-    ufp->choice = 1; /* visible string */
-    if (val == 1) {
-      ufp->data.ptrvalue = (Pointer) StringSave ("Official");
-    } else if (val == 2) {
-      ufp->data.ptrvalue = (Pointer) StringSave ("Interim");
-    }
-    last->next = ufp;
-    last = ufp;
-  }
-
-  return uop;
-}
-
-static Pointer GeneToUserObjectPtr (DialoG d)
-
-{
-  GeneUserPtr    gup;
-  UserObjectPtr  uop;
-
-  uop = NULL;
-  gup = (GeneUserPtr) GetObjectExtra (d);
-  if (gup != NULL) {
-    uop = CreateGeneUserObject (gup);
-  }
-  return (Pointer) uop;
-}
-
-static DialoG CreateGeneUserObjectDialog (GrouP h)
-
-{
-  GrouP        g;
-  GeneUserPtr  gup;
-  GrouP        p;
-
-  p = HiddenGroup (h, -1, 0, NULL);
-  SetGroupSpacing (p, 10, 10);
-
-  gup = (GeneUserPtr) MemNew (sizeof (GeneUserData));
-  if (gup != NULL) {
-    SetObjectExtra (p, gup, StdCleanupExtraProc);
-    gup->dialog = (DialoG) p;
-    gup->todialog = UserObjectPtrToGene;
-    gup->fromdialog = GeneToUserObjectPtr;
-    gup->testdialog = NULL;
-    g = HiddenGroup (p, 2, 0, NULL);
-    StaticPrompt (g, "Symbol", 0, 0, programFont, 'l');
-    gup->symbol = DialogText (g, "", 15, NULL);
-    StaticPrompt (g, "Name", 0, 0, programFont, 'l');
-    gup->name = DialogText (g, "", 15, NULL);
-    StaticPrompt (g, "Data Source", 0, 0, programFont, 'l');
-    gup->source = DialogText (g, "", 15, NULL);
-    StaticPrompt (g, "Status", 0, 0, programFont, 'l');
-    gup->status = HiddenGroup (g, 3, 0, NULL);
-    RadioButton (gup->status, "Official");
-    RadioButton (gup->status, "Interim");
-  }
-
-  return (DialoG) p;
-}
-
 typedef struct genepage {
   DIALOG_MESSAGE_BLOCK
   TexT          locus;
@@ -4424,6 +4574,11 @@ typedef struct genepage {
   ButtoN        pseudo;
   DialoG        db;
   DialoG        syn;
+  TexT          symbol;
+  TexT          name;
+  TexT          provider;
+  TexT          source;
+  GrouP         status;
   GrouP         geneGrp [4];
 } GenePage, PNTR GenePagePtr;
 
@@ -4438,7 +4593,13 @@ typedef struct geneform {
 static void GeneRefPtrToGenePage (DialoG d, Pointer data)
 
 {
+  Char                 buf [32];
+  CharPtr              db = NULL;
+  CharPtr              ds = NULL;
+  DbtagPtr             dbt;
+  ObjectIdPtr          oip;
   GenePagePtr  gpp;
+  GeneNomenclaturePtr  gnp;
   GeneRefPtr   grp;
 
   gpp = (GenePagePtr) GetObjectExtra (d);
@@ -4452,6 +4613,35 @@ static void GeneRefPtrToGenePage (DialoG d, Pointer data)
       SafeSetTitle (gpp->locus_tag, grp->locus_tag);
       PointerToDialog (gpp->db, grp->db);
       PointerToDialog (gpp->syn, grp->syn);
+      gnp = grp->formal_name;
+      if (gnp != NULL) {
+        SafeSetValue (gpp->status, gnp->status);
+        SafeSetTitle (gpp->symbol, gnp->symbol);
+        SafeSetTitle (gpp->name, gnp->name);
+        dbt = gnp->source;
+        if (dbt != NULL) {
+          if (StringDoesHaveText (dbt->db)) {
+            db = dbt->db;
+          }
+          oip = dbt->tag;
+          if (oip != NULL) {
+            if (StringDoesHaveText (oip->str)) {
+              ds = oip->str;
+            } else {
+              sprintf (buf, "%ld", (long) oip->id);
+              ds = buf;
+            }
+          }
+        }
+        SafeSetTitle (gpp->provider, db);
+        SafeSetTitle (gpp->source, ds);
+      } else {
+        SafeSetValue (gpp->status, 0);
+        SafeSetTitle (gpp->symbol, "");
+        SafeSetTitle (gpp->name, "");
+        SafeSetTitle (gpp->provider, NULL);
+        SafeSetTitle (gpp->source, NULL);
+      }
     } else {
       SafeSetTitle (gpp->locus, "");
       SafeSetTitle (gpp->allele, "");
@@ -4460,15 +4650,43 @@ static void GeneRefPtrToGenePage (DialoG d, Pointer data)
       SafeSetTitle (gpp->locus_tag, "");
       PointerToDialog (gpp->db, NULL);
       PointerToDialog (gpp->syn, NULL);
+      SafeSetValue (gpp->status, 0);
+      SafeSetTitle (gpp->symbol, "");
+      SafeSetTitle (gpp->name, "");
+      SafeSetTitle (gpp->provider, NULL);
+      SafeSetTitle (gpp->source, NULL);
+    }
+  }
+}
+
+static Boolean IsAllDigits (CharPtr str)
+{
+  CharPtr cp;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  cp = str;
+  while (*cp != 0 && isdigit (*cp)) {
+    cp++;
     }
+  if (*cp == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
   }
 }
 
 static Pointer GenePageToGeneRefPtr (DialoG d)
 
 {
+  CharPtr              db = NULL;
+  CharPtr              ds = NULL;
+  DbtagPtr             dbt;
+  ObjectIdPtr          oip;
   GenePagePtr  gpp;
+  GeneNomenclaturePtr  gnp;
   GeneRefPtr   grp;
+  long int             val;
 
   grp = NULL;
   gpp = (GenePagePtr) GetObjectExtra (d);
@@ -4482,6 +4700,40 @@ static Pointer GenePageToGeneRefPtr (DialoG d)
       grp->locus_tag = SaveStringFromText (gpp->locus_tag);
       grp->db = DialogToPointer (gpp->db);
       grp->syn = DialogToPointer (gpp->syn);
+      gnp = GeneNomenclatureNew ();
+      if (gnp != NULL) {
+        gnp->status = GetValue (gpp->status);
+        gnp->symbol = SaveStringFromText (gpp->symbol);
+        gnp->name = SaveStringFromText (gpp->name);
+        db = SaveStringFromText (gpp->provider);
+        ds = SaveStringFromText (gpp->source);
+        if (StringDoesHaveText (db) && StringDoesHaveText (ds)) {
+          dbt = DbtagNew ();
+          if (dbt != NULL) {
+            oip = ObjectIdNew ();
+            if (oip != NULL) {
+              if (IsAllDigits (ds)) {
+                sscanf (ds, "%ld", &val);
+                oip->id = val;
+              } else {
+                oip->str = StringSave (ds);
+              }
+              dbt->db = StringSave (db);
+              dbt->tag = oip;
+              gnp->source = dbt;
+            }
+          }
+        }
+        MemFree (db);
+        MemFree (ds);
+        if (gnp->status == 0 &&
+            StringHasNoText (gnp->symbol) &&
+            StringHasNoText (gnp->name) &&
+            gnp->source == NULL) {
+          gnp = GeneNomenclatureFree (gnp);
+        }
+        grp->formal_name = gnp;
+      }
     }
   }
   return (Pointer) grp;
@@ -4552,6 +4804,7 @@ static DialoG CreateGeneDialog (GrouP h, CharPtr title, GeneRefPtr grp, GeneForm
   GrouP         f;
   GrouP         g;
   GenePagePtr   gpp;
+  GrouP         j;
   Char          just;
   GrouP         k;
   GrouP         m;
@@ -4637,7 +4890,21 @@ static DialoG CreateGeneDialog (GrouP h, CharPtr title, GeneRefPtr grp, GeneForm
 
     if (showNomen) {
       gpp->geneGrp [x] = HiddenGroup (k, -1, 0, NULL);
-      gfp->usrobjext = CreateGeneUserObjectDialog (gpp->geneGrp [x]);
+      j = HiddenGroup (gpp->geneGrp [x], 2, 0, NULL);
+
+      StaticPrompt (j, "Symbol", 0, 0, programFont, 'l');
+      gpp->symbol = DialogText (j, "", 15, NULL);
+      StaticPrompt (j, "Name", 0, 0, programFont, 'l');
+      gpp->name = DialogText (j, "", 15, NULL);
+      StaticPrompt (j, "Provider", 0, 0, programFont, 'l');
+      gpp->provider = DialogText (j, "", 15, NULL);
+      StaticPrompt (j, "Source", 0, 0, programFont, 'l');
+      gpp->source = DialogText (j, "", 15, NULL);
+      StaticPrompt (j, "Status", 0, 0, programFont, 'l');
+      gpp->status = HiddenGroup (j, 3, 0, NULL);
+      RadioButton (gpp->status, "Official");
+      RadioButton (gpp->status, "Interim");
+      AlignObjects (ALIGN_CENTER, (HANDLE) gpp->status, (HANDLE) j, NULL);
       Hide (gpp->geneGrp [x]);
       x++;
     }
@@ -5937,13 +6204,14 @@ static ENUM_ALIST(rna_type_alist)
   {"rRNA",         4},
   {"ncRNA",        8},
   {"tmRNA",        9},
-  {"misc_RNA",   255},
+  {"misc_RNA",     10},
+  {"otherRNA",    255},
 END_ENUM_ALIST
 
 static Uint1 check_rna_type (Uint1 type)
 
 {
-  if (type > 9 && type != 255) return 0;
+  if (type > 10 && type != 255) return 0;
   return type;
 }
 
@@ -5986,8 +6254,8 @@ static void UserObjectPtrToProtein (DialoG d, Pointer data)
         }
       }
     }
-  }
   PointerToDialog (mup->protein, NULL);
+  }
 }
 
 static Pointer ProteinToUserObjectPtr (DialoG d)
@@ -6069,17 +6337,17 @@ static Uint1 RnaFeatDefFromRnaRef (RnaRefPtr rrp)
     case 7:
       return FEATDEF_snoRNA;
       break;
-    case 255:
-      if (rrp->ext.choice != 1 || StringHasNoText (rrp->ext.value.ptrvalue)) {
-        return FEATDEF_otherRNA;
-      } else if (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0
-                 || IsStringInNcRNAClassList(rrp->ext.value.ptrvalue)) {
+    case 8:
         return FEATDEF_ncRNA;
-      } else if (StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0) {
+      break;
+    case 9:
         return FEATDEF_tmRNA;
-      } else {
-        return FEATDEF_otherRNA;
-      }
+      break;
+    case 10:
+      return FEATDEF_misc_RNA;
+      break;
+
+    case 255:
     default:
       return FEATDEF_otherRNA;
       break;
@@ -6087,29 +6355,6 @@ static Uint1 RnaFeatDefFromRnaRef (RnaRefPtr rrp)
 }
 
 
-static Uint1 RnaSubtypeFromRnaRef (RnaRefPtr rrp)
-{
-  if (rrp == NULL) {
-    return 0;
-  }
-
-  if (rrp->type == 255) {
-    if (rrp->ext.choice == 1 && StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0) {
-      return 9;
-    } else if (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0
-               || IsStringInNcRNAClassList (rrp->ext.value.ptrvalue)) {
-      return 8;
-    } else {
-      return 255;
-    }
-  } else if (rrp->type == 5 || rrp->type == 6 || rrp->type == 7) {
-    return 8;
-  } else {
-    return rrp->type;
-  }
-}
-
-
 static void RnaRefPtrToRnaPage (DialoG d, Pointer data)
 
 {
@@ -6126,14 +6371,16 @@ static void RnaRefPtrToRnaPage (DialoG d, Pointer data)
   Char            str [8];
   tRNAPtr         trna;
   ValNodePtr      vnp;
+  RNAGenPtr       rgp;
+  CharPtr         tag_peptide;
+  CharPtr         product;
 
   rpp = (RnaPagePtr) GetObjectExtra (d);
   rrp = (RnaRefPtr) data;
 
   if (rrp != NULL) {
 
-    SetEnumPopup (rpp->type, rna_type_alist,
-                  RnaSubtypeFromRnaRef(rrp));
+    SetEnumPopup (rpp->type, rna_type_alist, rrp->type);
     SafeSetStatus (rpp->pseudo, rrp->pseudo);
     switch (rrp->type) {
       case 0 :
@@ -6262,64 +6509,61 @@ static void RnaRefPtrToRnaPage (DialoG d, Pointer data)
       case 6:
       case 7:
       case 8:
-      case 255 :
         SafeHide (rpp->trnaGrp);
         SafeHide (rpp->nameGrp);
         SafeHide (rpp->rrnaPrompt);
         SafeHide (rpp->ornaPrompt);
         if (rrp->type == 5) {
           PointerToDialog (rpp->ncrnaClass, "snRNA");
-          SafeHide (rpp->tmrnaGrp);
-          SafeShow (rpp->ncrnaGrp); 
         } else if (rrp->type == 6) {
           PointerToDialog (rpp->ncrnaClass, "scRNA");
-          SafeHide (rpp->tmrnaGrp);
-          SafeShow (rpp->ncrnaGrp); 
         } else if (rrp->type == 7) {
           PointerToDialog (rpp->ncrnaClass, "snoRNA");
+        }
           SafeHide (rpp->tmrnaGrp);
           SafeShow (rpp->ncrnaGrp); 
-        } else if (rrp->type == 255) {
-          if (rrp->ext.choice == 1) {
-            if (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0) {
-              SafeHide (rpp->tmrnaGrp);
-              SafeShow (rpp->ncrnaGrp);
-              /* get class from qual */
-            } else if (IsStringInNcRNAClassList (rrp->ext.value.ptrvalue)) {
-              SafeHide (rpp->tmrnaGrp);
-              SafeShow (rpp->ncrnaGrp);
-              /* get class from rrp */
-              PointerToDialog (rpp->ncrnaClass, rrp->ext.value.ptrvalue);
-            } else if (StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0) {
-              SafeHide (rpp->ncrnaGrp);
-              SafeShow (rpp->tmrnaGrp);
-            } else {
-              if (StringCmp (rrp->ext.value.ptrvalue, "misc_RNA") != 0) {
-                SafeSetTitle (rpp->name, (CharPtr) rrp->ext.value.ptrvalue);
+        product = GetRNARefProductString (rrp, NULL);
+        SetTitle (rpp->ncrnaProduct, product);
+        product = MemFree (product);
+        if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL 
+            && rrp->type == 8 && !StringHasNoText (rgp->_class)) {
+          PointerToDialog (rpp->ncrnaClass, rgp->_class);
               }
+        break;
+      case 9:
+        SafeHide (rpp->trnaGrp);
               SafeHide (rpp->ornaPrompt);
-              SafeShow (rpp->rrnaPrompt);
-              SafeShow (rpp->nameGrp);
+        SafeHide (rpp->rrnaPrompt);
+        SafeHide (rpp->nameGrp);
               SafeHide (rpp->ncrnaGrp);
-              SafeHide (rpp->tmrnaGrp);
+        SafeShow (rpp->tmrnaGrp);
+        product = GetRNARefProductString (rrp, NULL);
+        SetTitle (rpp->tmrnaProduct, product);
+        product = MemFree (product);
+        if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL) {
+          tag_peptide = GettmRNATagPeptide (rrp, NULL);
+          if (tag_peptide != NULL) {
+            PointerToDialog (rpp->tmrnaTagPeptide, tag_peptide);
+            tag_peptide = MemFree (tag_peptide);
             }
-          } else {
-            SafeSetTitle (rpp->name, "");
-            SafeHide (rpp->ornaPrompt);
-            SafeShow (rpp->rrnaPrompt);
+        }
+        break;
+      case 10 :
+        SafeHide (rpp->trnaGrp);
             SafeShow (rpp->nameGrp);
+        SafeShow (rpp->rrnaPrompt);
             SafeHide (rpp->ncrnaGrp);
             SafeHide (rpp->tmrnaGrp);
-          }
-        }
+        SafeHide (rpp->ornaPrompt);
+        product = GetRNARefProductString (rrp, NULL);
+        SetTitle (rpp->name, product);
+        product = MemFree (product);
         break;
       default :
         SafeHide (rpp->trnaGrp);
-        if (rrp->ext.choice == 1 && rrp->ext.value.ptrvalue != NULL) {
-          SafeSetTitle (rpp->name, (CharPtr) rrp->ext.value.ptrvalue);
-        } else {
-          SafeSetTitle (rpp->name, "");
-        }
+        product = GetRNARefProductString (rrp, NULL);
+        SetTitle (rpp->name, product);
+        product = MemFree (product);
         SafeHide (rpp->rrnaPrompt);
         SafeHide (rpp->ornaPrompt);
         SafeShow (rpp->nameGrp);
@@ -6360,6 +6604,8 @@ static Pointer RnaPageToRnaRefPtr (DialoG d)
   tRNAPtr     trna;
   UIEnum      val;
   ValNodePtr  vnp;
+  RNAGenPtr   rgp;
+  CharPtr     tmp;
 
   rrp = NULL;
   rpp = (RnaPagePtr) GetObjectExtra (d);
@@ -6367,12 +6613,8 @@ static Pointer RnaPageToRnaRefPtr (DialoG d)
     rrp = RnaRefNew ();
     if (rrp != NULL) {
       if (GetEnumPopup (rpp->type, rna_type_alist, &val)) {
-        if (val == 8 || val == 9) {
-          rrp->type = 255;
-        } else {
           rrp->type = (Uint1) val;
         }
-      }
       rrp->pseudo = GetStatus (rpp->pseudo);
       switch (val) {
         case 3 :
@@ -6447,12 +6689,30 @@ static Pointer RnaPageToRnaRefPtr (DialoG d)
         case 6:
         case 7:
         case 8: /* ncRNA */
-          rrp->ext.choice = 1;
-          rrp->ext.value.ptrvalue = StringSave ("ncRNA");
+          rgp = RNAGenNew ();
+          rgp->_class = DialogToPointer (rpp->ncrnaClass);
+          rgp->product = SaveStringFromText (rpp->ncrnaProduct);
+          rrp->ext.choice = 3;
+          rrp->ext.value.ptrvalue = rgp;
           break;
         case 9: /* tmRNA */
-          rrp->ext.choice = 1;
-          rrp->ext.value.ptrvalue = StringSave ("tmRNA");
+          rgp = RNAGenNew ();
+          rrp->ext.choice = 3;
+          rrp->ext.value.ptrvalue = rgp;
+          if (!TextHasNoText (rpp->tmrnaProduct)) {
+            rgp->product = SaveStringFromText (rpp->tmrnaProduct);
+          }
+          tmp = DialogToPointer (rpp->tmrnaTagPeptide);
+          if (!StringHasNoText (tmp)) {
+            SettmRNATagPeptide (rrp, NULL, tmp, ExistingTextOption_replace_old);
+          }
+          tmp = MemFree (tmp);
+          break;
+        case 10:
+          rgp = RNAGenNew ();
+          rgp->product = SaveStringFromText (rpp->name);
+          rrp->ext.choice = 3;
+          rrp->ext.value.ptrvalue = rgp;
           break;
         case 255:
         default :
@@ -6520,35 +6780,6 @@ static void RemoveQualByName (SeqFeatPtr sfp, CharPtr qual_name)
   }
 }
 
-static void SetRNAMiscNameForType (SeqFeatPtr sfp, UIEnum val)
-{
-  RnaRefPtr  rrp;
-
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return;
-  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-  
-  if (rrp == NULL) { 
-    rrp = RnaRefNew ();
-    sfp->data.value.ptrvalue = rrp;
-  }
-
-  if (val == 8) {
-    rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-    rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-    rrp->ext.choice = 1;
-  } else if (val == 9) {
-    rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-    rrp->ext.value.ptrvalue = StringSave ("tmRNA");
-    rrp->ext.choice = 1;
-  } else if (val == 255) {
-    rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-    rrp->ext.value.ptrvalue = StringSave ("misc_RNA");
-    rrp->ext.choice = 1;
-  }
-
-}
-
-
 extern void ConvertProductQualToRnaRefName (SeqFeatPtr sfp)
 {
   RnaRefPtr rrp;
@@ -6595,244 +6826,6 @@ static void ConvertRnaRefNameToProductQual (SeqFeatPtr sfp)
 }
 
 
-static void AddRnaSpecificQualsForType (SeqFeatPtr sfp, RnaPagePtr rpp, UIEnum val)
-{
-  CharPtr    str;
-  GBQualPtr  gbq;
-  RnaRefPtr  rrp;
-
-  if (rpp == NULL || sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return;
-  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-
-  if (val == 8) {
-    str = DialogToPointer (rpp->ncrnaClass);
-    if (StringHasNoText (str)) {
-      str = MemFree (str);
-      RemoveQualByName (sfp, "ncRNA_class"); 
-    } else {
-      gbq = FindOrAddQual (sfp, "ncRNA_class");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = str;
-    }
-    if (TextHasNoText (rpp->ncrnaProduct)) {
-      RemoveQualByName (sfp, "product");
-    } else {
-      gbq = FindOrAddQual (sfp, "product");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = SaveStringFromText (rpp->ncrnaProduct);
-    }
-  } else if (val == 9) {
-    str = DialogToPointer (rpp->tmrnaTagPeptide);
-    if (StringHasNoText (str)) {
-      str = MemFree (str);
-      RemoveQualByName (sfp, "tag_peptide");
-    } else {
-      gbq = FindOrAddQual (sfp, "tag_peptide");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = str;
-    }
-    if (TextHasNoText (rpp->tmrnaProduct)) {
-      RemoveQualByName (sfp, "product");
-    } else {
-      gbq = FindOrAddQual (sfp, "product");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = SaveStringFromText (rpp->tmrnaProduct);
-    }
-  } else if (val == 255) {
-    if (TextHasNoText (rpp->name)) {
-      RemoveQualByName (sfp, "product");
-    } else {
-      str = SaveStringFromText (rpp->name);
-      if (StringCmp (str, "misc_RNA") == 0) {
-        str = MemFree (str);
-      } else {
-        gbq = FindOrAddQual (sfp, "product");
-        gbq->val = MemFree (gbq->val);
-        gbq->val = str;
-      }
-    }
-  } else {
-    /* product should now be in extension, this is an old qualifier no longer needed */
-    RemoveQualByName (sfp, "product");
-  }
-}
-
-
-extern void AddRnaSpecificQuals (SeqFeatPtr sfp, DialoG d)
-{
-  RnaPagePtr rpp;
-  UIEnum     val;
-
-  rpp = (RnaPagePtr) GetObjectExtra (d);
-  if (rpp == NULL || sfp == NULL) return;
-
-  if (GetEnumPopup (rpp->type, rna_type_alist, &val)) {
-    AddRnaSpecificQualsForType (sfp, rpp, val);
-    SetRNAMiscNameForType (sfp, val);
-    if (val != 8) {
-      RemoveQualByName (sfp, "ncRNA_class");
-    }
-    if (val != 8 && val != 9 && val != 255) {
-      ConvertProductQualToRnaRefName (sfp);
-    }
-  }
-}
-
-
-extern void SetRnaSpecificQuals (SeqFeatPtr sfp, DialoG d)
-{
-  RnaPagePtr rpp;
-  RnaRefPtr  rrp;
-  GBQualPtr  gbq;
-
-  rpp = (RnaPagePtr) GetObjectExtra (d);
-  if (rpp == NULL || sfp == NULL || sfp->data.choice != SEQFEAT_RNA || sfp->data.value.ptrvalue == NULL) return;
-
-  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-  if ((rrp->type == 5 || rrp->type == 6 || rrp->type == 7)
-      && rrp->ext.choice == 1
-      && StringCmp (rrp->ext.value.ptrvalue, "ncRNA") != 0) {
-    SetTitle (rpp->ncrnaProduct, rrp->ext.value.ptrvalue);
-  }
-  else if (rrp->type != 255 || rrp->ext.choice != 1) return;
-
-  if (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0) {
-    gbq = sfp->qual;
-    while (gbq != NULL) {
-      if (StringCmp (gbq->qual, "ncRNA_class") == 0) {
-        PointerToDialog (rpp->ncrnaClass, gbq->val);
-      } else if (StringCmp (gbq->qual, "product") == 0) {
-        SetTitle (rpp->ncrnaProduct, gbq->val);
-      }
-      gbq = gbq->next;
-    }
-  } else if (StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0) {
-    gbq = sfp->qual;
-    while (gbq != NULL) {
-      if (StringCmp (gbq->qual, "tag_peptide") == 0) {
-        PointerToDialog (rpp->tmrnaTagPeptide, gbq->val);
-      } else if (StringCmp (gbq->qual, "product") == 0) {
-        SetTitle (rpp->tmrnaProduct, gbq->val);
-      }
-      gbq = gbq->next;
-    }
-  } else if (IsStringInNcRNAClassList (rrp->ext.value.ptrvalue)) {
-    gbq = sfp->qual;
-    while (gbq != NULL) {
-      if (StringCmp (gbq->qual, "product") == 0) {
-        SetTitle (rpp->ncrnaProduct, gbq->val);
-      }
-      gbq = gbq->next;
-    }
-  } else if (StringCmp (rrp->ext.value.ptrvalue, "misc_RNA") == 0) {
-    gbq = sfp->qual;
-    while (gbq != NULL) {
-      if (StringCmp (gbq->qual, "product") == 0) {
-        SetTitle (rpp->name, gbq->val);
-      }
-      gbq = gbq->next;
-    }
-  }
-}
-
-
-extern void ConvertToOldRNAFormat (SeqFeatPtr sfp)
-{
-  RnaRefPtr rrp;
-  GBQualPtr gbq, gbq_prod = NULL, gbq_class = NULL, gbq_prev = NULL, gbq_next;
-  Boolean   do_convert = TRUE;
-
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA)
-  {
-    return;
-  }
-
-  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-  if (rrp == NULL || rrp->type != 255 || rrp->ext.choice != 1
-      || StringCmp (rrp->ext.value.ptrvalue, "ncRNA") != 0)
-  {
-    return;
-  }
-  for (gbq = sfp->qual; gbq != NULL && (gbq_prod == NULL || gbq_class == NULL); gbq = gbq->next)
-  {
-    if (StringCmp (gbq->qual, "ncRNA_class") == 0)
-    {
-      gbq_class = gbq;
-    }
-    else if (StringCmp (gbq->qual, "product") == 0)
-    {
-      gbq_prod = gbq;
-    }
-  }
-
-  if (gbq_class == NULL)
-  {
-    do_convert = FALSE;
-  }
-  else if (StringCmp (gbq_class->val, "snRNA") == 0)
-  {
-    rrp->type = 5;
-  }
-  else if (StringCmp (gbq_class->val, "scRNA") == 0)
-  {
-    rrp->type = 6;
-  }
-  else if (StringCmp (gbq_class->val, "snoRNA") == 0)
-  {
-    rrp->type = 7;
-  }
-  else if (IsStringInNcRNAClassList (gbq_class->val))
-  {
-    do_convert = FALSE;
-    rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-    rrp->ext.value.ptrvalue = StringSave (gbq_class->val);
-    RemoveQualByName (sfp, "ncRNA_class");
-  }
-  else
-  {
-    do_convert = FALSE;
-  }
-  if (do_convert)
-  {
-    if (gbq_prod == NULL)
-    {
-      rrp->ext.choice = 0;
-      rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-    }
-    else
-    {
-      rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-      rrp->ext.value.ptrvalue = gbq_prod->val;
-      gbq_prod->val = NULL;
-    }
-    gbq = sfp->qual;
-    while (gbq != NULL)
-    {
-      gbq_next = gbq->next;
-      if (StringCmp (gbq->qual, "ncRNA_class") == 0
-          || StringCmp (gbq->qual, "product") == 0)
-      {
-        if (gbq_prev == NULL)
-        {
-          sfp->qual = gbq->next;
-        }
-        else
-        {
-          gbq_prev->next = gbq->next;
-        }
-        gbq->next = NULL;
-        gbq = GBQualFree (gbq);
-      }
-      else
-      {
-        gbq_prev = gbq;
-      }
-      gbq = gbq_next;
-    }
-  }
-}
-
-
 static void SetRnaImportExportItems (RnaFormPtr rfp)
 
 {
@@ -7085,6 +7078,9 @@ static Uint1 RnaTypeFromFeatdef (Uint2 featdef)
     case FEATDEF_tmRNA:
       return 9; 
       break;
+    case FEATDEF_misc_RNA:
+      return 10;
+      break;
     case FEATDEF_otherRNA:
     default:
       return 255;
@@ -7096,123 +7092,63 @@ static Uint1 RnaTypeFromFeatdef (Uint2 featdef)
 static void ChangeRNAType (PopuP p)
 
 {
-  Char             ch;
-  Int2             expev;
-  Int2             geneval;
-  HelpMessageFunc  helpfunc;
   RnaFormPtr       rfp;
-  RnaFormPtr       newrfp;
   RnaRefPtr        rrp;
   RnaPagePtr       rpp;
-  ObjMgrPtr        omp;
-  ObjMgrTypePtr    omtp;
-  CharPtr          ptr;
-  SeqEntryPtr      sep;
-  SeqFeatPtr       sfp;
-  Char             title [128];
-  WindoW           w;
   UIEnum           val;
-  GBQualPtr        gbq;
+  CharPtr          product = NULL;
 
   rfp = (RnaFormPtr) GetObjectExtra (p);
   if (rfp == NULL) return;
   rpp = (RnaPagePtr) GetObjectExtra (rfp->data);
   if (rpp == NULL) return;
-  sfp = SeqFeatNew ();
-  if (sfp != NULL) {
-    if (GetEnumPopup (rpp->type, rna_type_alist, &val)) {
 
-      sfp->data.choice = SEQFEAT_RNA;
-      sfp->data.value.ptrvalue = DialogToPointer (rfp->data);
-      sfp->comment = SaveStringFromText (rfp->comment);
-      ptr = sfp->comment;
-      if (ptr != NULL) {
-        ch = *ptr;
-        while (ch != '\0') {
-          if (ch < ' ' || ch > '~') {
-            *ptr = '~';
-          }
-          ptr++;
-          ch = *ptr;
-        }
-      }
-      expev = GetValue (rfp->evidence);
-      if (expev > 0 && expev <= 3) {
-        sfp->exp_ev = expev - 1;
-      } else {
-        sfp->exp_ev = 0;
+  if (GetEnumPopup (rpp->type, rna_type_alist, &val)) {
+    switch (rpp->prev_rna_type) {
+      case 5:
+      case 6:
+      case 7:
+      case 8:
+        if (!TextHasNoText (rpp->ncrnaProduct)) {
+          product = SaveStringFromText (rpp->ncrnaProduct);
       }
-      sfp->partial = GetStatus (rfp->partial);
-      sfp->excpt = GetStatus (rfp->exception);
-      sfp->title = NULL;
-      sfp->product = DialogToPointer (rfp->product);
-      sfp->location = DialogToPointer (rfp->location);
-      sfp->cit = DialogToPointer (rfp->featcits);
-      sfp->dbxref = DialogToPointer (rfp->dbxrefs);
-      sfp->qual = DialogToPointer (rfp->gbquals);
-      CleanupEvidenceGBQuals (&(sfp->qual));
-      VisStringDialogToGbquals (sfp, rfp->experiment, "experiment");
-      InferenceDialogToGBQuals (rfp->inference, sfp, TRUE);
-      AddRnaSpecificQualsForType (sfp, rpp, rpp->prev_rna_type < 0 ? val : rpp->prev_rna_type);
-      if (rpp->prev_rna_type == 8 && val != 8) {
-        RemoveQualByName (sfp, "ncRNA_class");
+        break;
+      case 9:
+        if (!TextHasNoText (rpp->tmrnaProduct)) {
+          product = SaveStringFromText (rpp->tmrnaProduct);
       }
-      if (rpp->prev_rna_type == 8 || rpp->prev_rna_type == 9 || rpp->prev_rna_type == 255) {
-        if (val != 8 && val != 9 && val != 255) {
-          ConvertProductQualToRnaRefName (sfp);
+        break;
+      case 3:
+        /* don't collect product for tRNA */
+        break;
+      default:
+        if (!TextHasNoText (rpp->name)) {
+          product = SaveStringFromText (rpp->name);
         }
-      } else if (val == 8 || val == 9 || val == 255) {
-        if (rpp->name != NULL && !TextHasNoText (rpp->name)) {
-          gbq = FindOrAddQual (sfp, "product");
-          gbq->val = SaveStringFromText (rpp->name);
+        break;
         }
+    switch (val) {
+      case 3:
+        /* don't set product for tRNA */
+        break;
+      case 5:
+      case 6:
+      case 7:
+      case 8:
+        SetTitle (rpp->ncrnaProduct, product);
+        break;
+      case 9:
+        SetTitle (rpp->tmrnaProduct, product);
+        break;
+      default:
+        SetTitle (rpp->name, product);
+        break;
       }
-
-      SetRNAMiscNameForType (sfp, val);
+    product = MemFree (product);
+    rrp = RnaPageToRnaRefPtr (rpp->dialog);
+    RnaRefPtrToRnaPage (rpp->dialog, rrp);
+    rrp = RnaRefFree (rrp);
       rpp->prev_rna_type = val;
-
-      geneval = GetValue (rfp->gene);
-      sep = GetTopSeqEntryForEntityID (rfp->input_entityID);
-      StringCpy (title, "RNA");
-      if (sfp != NULL && sfp->data.value.ptrvalue != NULL) {
-        rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-        /* set title based on type of RNA feature */
-      }
-      /* need to set subtype to correctly calculate which quals should be suppressed */
-      sfp->idx.subtype = RnaFeatDefFromRnaRef ((RnaRefPtr)sfp->data.value.ptrvalue);
-      w = (WindoW) CreateRnaForm (-50, -33, title, sfp, sep, RnaFeatDefFromRnaRef (rrp),
-                                     StdFeatFormActnProc);
-      newrfp = (RnaFormPtr) GetObjectExtra (w);
-      if (newrfp != NULL) {
-        newrfp->input_entityID = rfp->input_entityID;
-        newrfp->input_itemID = rfp->input_itemID;
-        newrfp->input_itemtype = rfp->input_itemtype;
-        newrfp->this_itemtype = rfp->this_itemtype;
-        newrfp->this_subtype = rfp->this_subtype;
-        if (sfp != NULL) {
-          omp = ObjMgrGet ();
-          if (omp != NULL) {
-            omtp = ObjMgrTypeFind (omp, OBJ_SEQFEAT, NULL, NULL);
-            if (omtp != NULL && omtp->subtypefunc != NULL) {
-              newrfp->this_subtype = (*(omtp->subtypefunc)) (sfp);
-            }
-          }
-        }
-        SendMessageToForm (newrfp->form, VIB_MSG_INIT);
-        SetValue (newrfp->gene, geneval);
-        if (sfp != NULL) {
-          PointerToForm (newrfp->form, (Pointer) sfp);
-        }
-      }
-      Remove (rfp->form);
-      Show (w);
-      Select (w);
-      helpfunc = (HelpMessageFunc) GetAppProperty ("HelpMessageProc");
-      if (helpfunc != NULL) {
-        helpfunc ("Features", title);
-      }
-    }
-    SeqFeatFree (sfp);
     Update ();
   }
 }
@@ -7348,11 +7284,8 @@ static DialoG CreateRnaDialog (GrouP h, CharPtr title,
     rpp->tmrnaProduct = DialogText (rpp->tmrnaGrp, "", 10, NULL);
     Hide (rpp->tmrnaGrp);
 
-    if (sfp != NULL && sfp->data.choice == SEQFEAT_RNA && sfp->data.value.ptrvalue != NULL) {
-      rna_type = RnaSubtypeFromRnaRef ((RnaRefPtr)sfp->data.value.ptrvalue);
-    } else {
       rna_type = RnaTypeFromFeatdef (subtype);
-    }
+
     SetEnumPopup (rpp->type, rna_type_alist, (UIEnum) rna_type);
     rpp->prev_rna_type = rna_type;
 
@@ -7681,7 +7614,6 @@ extern ForM CreateRnaForm (Int2 left, Int2 top, CharPtr title,
     s = HiddenGroup (h, -1, 0, NULL);
     SetGroupSpacing (s, 3, 10);
     rfp->data = CreateRnaDialog (s, NULL, subtype, sep, sfp, rfp);
-    SetRnaSpecificQuals (sfp, rfp->data);
     rfp->pages [RNA_PAGE] = s;
     Hide (rfp->pages [RNA_PAGE]);
     rnaFormTabs [0] = NULL;
@@ -7794,7 +7726,7 @@ extern Int2 LIBCALLBACK RnaGenFunc (Pointer data)
   if (sfp != NULL && sfp->data.value.ptrvalue != NULL) {
     rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
     StringNCpy_0 (title,
-                GetEnumName (RnaSubtypeFromRnaRef(rrp), rna_type_alist),
+                GetEnumName (rrp->type, rna_type_alist),
                 sizeof (title));
     if (StringHasNoText (title)) {
       StringCpy (title, "Unknown RNA");
@@ -7815,6 +7747,7 @@ extern Int2 LIBCALLBACK RnaGenFunc (Pointer data)
     }
   }
   sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
+  ModernizeRNAFields (sfp);
   w = (WindoW) CreateRnaForm (-50, -33, title, sfp, sep,
                               subtype, StdFeatFormActnProc);
   rfp = (RnaFormPtr) GetObjectExtra (w);
@@ -8046,7 +7979,7 @@ extern RnaTypePtr RnaTypeFree (RnaTypePtr rtp)
 extern Boolean MatchesRnaType (SeqFeatPtr sfp, RnaTypePtr rtp)
 {
   RnaRefPtr rrp;
-  GBQualPtr gbq;
+  RNAGenPtr rgp;
   Uint1     featdef;
   Boolean   matches = TRUE;
 
@@ -8064,25 +7997,11 @@ extern Boolean MatchesRnaType (SeqFeatPtr sfp, RnaTypePtr rtp)
     if (rtp->ncrna_class == NULL) {
       matches = TRUE;
     } else {
-      gbq = sfp->qual;
-      while (gbq != NULL && StringCmp (gbq->qual, "ncRNA_class") != 0)
-      {
-        gbq = gbq->next;
-      }
-      if (gbq == NULL)
-      {
-        if (rrp->ext.choice == 1 && StringCmp (rrp->ext.value.ptrvalue, rtp->ncrna_class) == 0)
-        {
+      if (rrp->ext.choice == 3) {
+        rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+        if (StringCmp (rgp->_class, rtp->ncrna_class) == 0) {
           matches = TRUE;
         }
-        else if (StringDoesHaveText (rtp->ncrna_class)) 
-        {
-          matches = FALSE;
-        }
-      }
-      else if (StringCmp (gbq->val, rtp->ncrna_class) != 0)
-      {
-        matches = FALSE;
       }
     }
   }
@@ -8090,59 +8009,10 @@ extern Boolean MatchesRnaType (SeqFeatPtr sfp, RnaTypePtr rtp)
 }
 
 
-static void ClearRNAProduct (RnaRefPtr rrp)
-{
-  tRNAPtr trna;
-
-  if (rrp == NULL || rrp->ext.choice == 0)
-  {
-    return;
-  }
-  if (rrp->ext.choice == 2)
-  {
-		trna = (tRNAPtr)(rrp->ext.value.ptrvalue);
-    if (trna != NULL) {
-		  trna->anticodon = SeqLocFree(trna->anticodon);
-    }
-  }
-
-  rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-  rrp->ext.choice = 0;
-}
-
-
-static void MoveRnaProductToQual (SeqFeatPtr sfp)
-{
-  RnaRefPtr rrp;
-  CharPtr   product = NULL;
-  GBQualPtr gbq;
-
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || sfp->data.value.ptrvalue == NULL)
-  {
-    return;
-  }
-
-  rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-  if (rrp->ext.choice == 1)
-  { 
-    product = rrp->ext.value.ptrvalue;
-    rrp->ext.value.ptrvalue = NULL;
-  }
-  ClearRNAProduct (rrp);
-  rrp->ext.choice = 1;
-  rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-  if (product != NULL)
-  {
-    gbq = FindOrAddQual (sfp, "product");
-    gbq->val = product;
-  }
-}
-
-
 extern void ApplyRnaTypeToSeqFeat (SeqFeatPtr sfp, RnaTypePtr rtp)
 {
   RnaRefPtr rrp;
-  GBQualPtr gbq;
+  RNAGenPtr rgp;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA)
   {
@@ -8176,48 +8046,75 @@ extern void ApplyRnaTypeToSeqFeat (SeqFeatPtr sfp, RnaTypePtr rtp)
       rrp->type = 4;
       break;
     case FEATDEF_scRNA:
-      rrp->type = 255;
-      MoveRnaProductToQual (sfp);
-      gbq = FindOrAddQual (sfp, "ncRNA_class");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = StringSave ("scRNA");
-      break;
     case FEATDEF_snRNA:
-      rrp->type = 255;
-      MoveRnaProductToQual (sfp);
-      gbq = FindOrAddQual (sfp, "ncRNA_class");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = StringSave ("snRNA");
-      break;
     case FEATDEF_snoRNA:
-      rrp->type = 255;
-      MoveRnaProductToQual (sfp);
-      gbq = FindOrAddQual (sfp, "ncRNA_class");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = StringSave ("snoRNA");
-      break;
     case FEATDEF_ncRNA:
-      rrp->type = 255;
-      MoveRnaProductToQual (sfp);
-      gbq = FindOrAddQual (sfp, "ncRNA_class");
-      gbq->val = MemFree (gbq->val);
-      gbq->val = StringSave (rtp->ncrna_class);
+    case FEATDEF_misc_RNA:
+      rrp->type = 8;
+      if (rrp->ext.choice == 1) {
+        rgp = RNAGenNew ();
+        rgp->product = rrp->ext.value.ptrvalue;
+        rrp->ext.value.ptrvalue = rgp;
+        rrp->ext.choice = 3;
+      }
+
+      if (rrp->ext.choice != 3) {
+        rrp->ext.choice = 3;        
+        rrp->ext.value.ptrvalue = RNAGenNew ();
+      }
+
+      rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+      if (rgp == NULL) {
+        rgp = RNAGenNew ();
+        rrp->ext.value.ptrvalue = rgp;
+      }
+      if (rtp->rna_featdef == FEATDEF_scRNA) {
+        rgp->_class = StringSave ("scRNA");
+      } else if (rtp->rna_featdef == FEATDEF_snRNA) {
+        rgp->_class = StringSave ("snRNA");
+      } else if (rtp->rna_featdef == FEATDEF_snoRNA) {
+        rgp->_class = StringSave ("snoRNA");
+      } else if (rtp->rna_featdef == FEATDEF_ncRNA) {
+        rgp->_class = StringSave (rtp->ncrna_class);
+      } else if (rtp->rna_featdef == FEATDEF_misc_RNA) {
+        if (IsStringInNcRNAClassList (rgp->product)) {
+          rgp->_class = rgp->product;
+          rgp->product = NULL;
+        } else {
+          rrp->type = 10;
+        }
+      } 
       break;
     case FEATDEF_tmRNA:
-      rrp->type = 255;
-      MoveRnaProductToQual (sfp);
-      rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-      rrp->ext.value.ptrvalue = StringSave ("tmRNA");
-      rrp->ext.choice = 1;
+      rrp->type = 9;
+      if (rrp->ext.choice == 1) {
+        rgp = RNAGenNew ();
+        rgp->product = rrp->ext.value.ptrvalue;
+        rrp->ext.value.ptrvalue = rgp;
+        rrp->ext.choice = 3;
+      }
+
+      if (rrp->ext.choice != 3) {
+        rrp->ext.choice = 3;        
+        rrp->ext.value.ptrvalue = RNAGenNew ();
+      }
+
+      rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+      if (rgp == NULL) {
+        rgp = RNAGenNew ();
+        rrp->ext.value.ptrvalue = rgp;
+      }
       break;
     case FEATDEF_otherRNA:
       rrp->type = 255;
-      if (rrp->ext.choice == 1 && IsStringInNcRNAClassList (rrp->ext.value.ptrvalue))
-      {
-        gbq = FindOrAddQual (sfp, "ncRNA_class");
-        gbq->val = MemFree (gbq->val);
-        gbq->val = rrp->ext.value.ptrvalue;
-        rrp->ext.value.ptrvalue = StringSave ("ncRNA");
+      if (rrp->ext.choice == 3) {
+        rrp->ext.value.ptrvalue = RNAGenFree (rrp->ext.value.ptrvalue);
+        rrp->ext.choice = 0;
+      }
+      if (rrp->ext.choice == 1 || rrp->ext.choice == 0) {
+        rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+        rrp->ext.value.ptrvalue = StringSave ("misc_RNA");
+        rrp->ext.choice = 1;
       }
       break;
   }
@@ -8249,7 +8146,6 @@ extern void AddToComment (SeqFeatPtr sfp, CharPtr comment)
 extern void ApplyProductToRNA (SeqFeatPtr sfp, CharPtr product)
 {
   RnaRefPtr rrp;
-  GBQualPtr gbq;
   Uint1     aa;
   Int4      j;
   Boolean   justTrnaText = FALSE;
@@ -8265,7 +8161,7 @@ extern void ApplyProductToRNA (SeqFeatPtr sfp, CharPtr product)
   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
   if (rrp->type == 3)
   {
-    ClearRNAProduct (rrp);
+    RemoveRNAProductString (sfp, NULL);
 
     aa = ParseTRnaString (product, &justTrnaText, (Uint1Ptr) codon, TRUE);
     if (aa != 0) 
@@ -8295,21 +8191,9 @@ extern void ApplyProductToRNA (SeqFeatPtr sfp, CharPtr product)
       AddToComment (sfp, product);
     }
   }
-  else if (rrp->type == 255 
-           && rrp->ext.choice == 1 
-           && (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0
-               || StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0
-               || StringCmp (rrp->ext.value.ptrvalue, "misc_RNA") == 0))
-  {
-    gbq = FindOrAddQual (sfp, "product");
-    gbq->val = MemFree (gbq->val);
-    gbq->val = StringSave (product);    
-  }
   else
   {
-    ClearRNAProduct (rrp);
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave (product);
+    SetRNAProductString (sfp, NULL, product, ExistingTextOption_replace_old);
   }
 }
 
@@ -8366,53 +8250,7 @@ static void PointerToRnaTypeDialog (DialoG d, Pointer data)
   }
   else
   {
-    switch (rtp->rna_featdef)
-    {
-      case FEATDEF_preRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 1);
-        PointerToDialog (dlg->ncrna_class, NULL);
-        break;
-      case FEATDEF_mRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 2);
-        PointerToDialog (dlg->ncrna_class, NULL);
-        break;
-      case FEATDEF_tRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 3);
-        PointerToDialog (dlg->ncrna_class, NULL);
-        break;
-      case FEATDEF_rRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 4);
-        PointerToDialog (dlg->ncrna_class, NULL);
-        break;
-      case FEATDEF_scRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 8);
-        PointerToDialog (dlg->ncrna_class, "scRNA");
-        break;
-      case FEATDEF_snRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 8);
-        PointerToDialog (dlg->ncrna_class, "snRNA");
-        break;
-      case FEATDEF_snoRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 8);
-        PointerToDialog (dlg->ncrna_class, "snoRNA");
-        break;
-      case FEATDEF_ncRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 8);
-        PointerToDialog (dlg->ncrna_class, rtp->ncrna_class);
-        break;
-      case FEATDEF_tmRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 9);
-        PointerToDialog (dlg->ncrna_class, NULL);
-        break;
-      case FEATDEF_otherRNA:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 255);
-        PointerToDialog (dlg->ncrna_class, NULL);
-        break;
-      default:
-        SetEnumPopup (dlg->rna_type, rna_type_alist, (UIEnum) 0);
-        PointerToDialog (dlg->ncrna_class, NULL);
-        break;
-    }
+    SetEnumPopup (dlg->rna_type, rna_type_alist, RnaTypeFromFeatdef (rtp->rna_featdef));
   }
   ChangeRnaTypeDlg (dlg->rna_type);
 }
@@ -8456,6 +8294,9 @@ static Pointer RnaTypeDialogToPointer (DialoG d)
       case 9:
         rtp->rna_featdef = FEATDEF_tmRNA;
         break;
+      case 10:
+        rtp->rna_featdef = FEATDEF_misc_RNA;
+        break;
       case 255:
         rtp->rna_featdef = FEATDEF_otherRNA;
         break;
diff --git a/desktop/cdrgn.h b/desktop/cdrgn.h
index 3b19dfe..83587b5 100644
--- a/desktop/cdrgn.h
+++ b/desktop/cdrgn.h
@@ -29,13 +29,16 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.13 $
+* $Revision: 6.14 $
 *
 * File Description: 
 *
 * Modifications:  
 * --------------------------------------------------------------------------
 * $Log: cdrgn.h,v $
+* Revision 6.14  2009/09/02 15:08:39  bollin
+* New RNA editing.
+*
 * Revision 6.13  2008/01/17 21:18:09  bollin
 * Fixes for RNA dialog for ncRNA product/class handling
 *
@@ -118,10 +121,7 @@ extern ForM CreateRnaForm (Int2 left, Int2 top, CharPtr title,
                            Uint2 subtype, FormActnFunc actproc);
 extern Int2 LIBCALLBACK RnaGenFunc (Pointer data);
 
-extern void AddRnaSpecificQuals (SeqFeatPtr sfp, DialoG d);
 extern void ConvertProductQualToRnaRefName (SeqFeatPtr sfp);
-extern void SetRnaSpecificQuals (SeqFeatPtr sfp, DialoG d);
-extern void ConvertToOldRNAFormat (SeqFeatPtr sfp);
 
 extern SeqLocPtr TruncateLocation (SeqLocPtr head, Int4 len);
 
diff --git a/desktop/dlgutil1.c b/desktop/dlgutil1.c
index f4fa676..c7d727c 100644
--- a/desktop/dlgutil1.c
+++ b/desktop/dlgutil1.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.149 $
+* $Revision: 6.162 $
 *
 * File Description: 
 *
@@ -57,6 +57,10 @@
 #include <vibforms.h>
 #include <cdrgn.h>
 #include <findrepl.h>
+#include <pubdesc.h>
+
+/* for formatting */
+#include <asn2gnbp.h>
 
 #define NUMBER_OF_SUFFIXES    8
 
@@ -139,41 +143,6 @@ ENUM_ALIST(months_alist)
   {"Dec",  12},
 END_ENUM_ALIST
 
-extern void SetDescriptorPropagate (BioseqSetPtr bssp)
-{
-  BioseqPtr         bsp;
-  SeqEntryPtr       seqentry;
-  ValNodePtr        sourcedescr;
-
-  if (bssp != NULL) {
-    sourcedescr = bssp->descr;
-    if (sourcedescr != NULL) {
-      bssp->descr = NULL;
-      seqentry = bssp->seq_set;
-      while (seqentry != NULL) {
-        if (seqentry->data.ptrvalue != NULL) {
-          if (seqentry->choice == 1) {
-            bsp = (BioseqPtr) seqentry->data.ptrvalue;
-            ValNodeLink (&(bsp->descr),
-                         AsnIoMemCopy ((Pointer) sourcedescr,
-                                       (AsnReadFunc) SeqDescrAsnRead,
-                                       (AsnWriteFunc) SeqDescrAsnWrite));
-          } else if (seqentry->choice == 2) {
-            bssp = (BioseqSetPtr) seqentry->data.ptrvalue;
-            ValNodeLink (&(bssp->descr),
-                         AsnIoMemCopy ((Pointer) sourcedescr,
-                                       (AsnReadFunc) SeqDescrAsnRead,
-                                       (AsnWriteFunc) SeqDescrAsnWrite));
-          }
-        }
-        seqentry = seqentry->next;
-      }
-      SeqDescrFree (sourcedescr);
-    }
-  }
-}
-
-
 static void CopyOneDescriptorToSeqEntry (SeqDescrPtr sdp, SeqEntryPtr sep)
 {
   BioseqPtr bsp;
@@ -255,7 +224,7 @@ extern Int2 LIBCALLBACK DescriptorPropagate (Pointer data)
   return OM_MSG_RET_DONE;
 }
 
-extern Boolean DescFormReplaceWithoutUpdateProc (ForM f)
+extern Boolean DescFormReplaceWithoutUpdateProcEx (ForM f, Boolean feature_or_molinfo_change)
 
 {
   MsgAnswer          ans;
@@ -291,6 +260,10 @@ extern Boolean DescFormReplaceWithoutUpdateProc (ForM f)
           break;
       }
       FixSpecialCharactersForObject (OBJ_SEQDESC, sdp, "You may not include special characters in the text.\nIf you do not choose replacement characters, these special characters will be replaced with '#'.", TRUE, NULL);
+      if (!feature_or_molinfo_change) {
+        sep = GetTopSeqEntryForEntityID (dfp->input_entityID);
+        CleanupStringsForOneDescriptor (sdp, sep);
+      }
 
       ompc.output_data = (Pointer) sdp;
       if (ompc.input_entityID == 0) {
@@ -329,25 +302,53 @@ extern Boolean DescFormReplaceWithoutUpdateProc (ForM f)
   return rsult;
 }
 
-extern void StdDescFormActnProc (ForM f)
 
+extern Boolean DescFormReplaceWithoutUpdateProc (ForM f)
+{
+  return DescFormReplaceWithoutUpdateProcEx (f, TRUE);
+}
+
+
+static void StdDescFormActnProcEx (ForM f, Boolean feature_or_molinfo_change)
 {
   DescriptorFormPtr  dfp;
 
-  if (DescFormReplaceWithoutUpdateProc (f)) {
+  if (DescFormReplaceWithoutUpdateProcEx (f, feature_or_molinfo_change)) {
     dfp = (DescriptorFormPtr) GetObjectExtra (f);
     if (dfp != NULL) {
       GetRidOfEmptyFeatsDescStrings (dfp->input_entityID, NULL);
-      if (GetAppProperty ("InternalNcbiSequin") != NULL) {
+      if (feature_or_molinfo_change && GetAppProperty ("InternalNcbiSequin") != NULL) {
         ExtendGeneFeatIfOnMRNA (dfp->input_entityID, NULL);
       }
+      
       ObjMgrSetDirtyFlag (dfp->input_entityID, TRUE);
+      if (feature_or_molinfo_change) {
       ObjMgrSendMsg (OM_MSG_UPDATE, dfp->input_entityID,
                      dfp->input_itemID, dfp->input_itemtype);
+      } else {
+        ObjMgrSendMsgNoFeatureChange(OM_MSG_UPDATE, dfp->input_entityID,
+                       dfp->input_itemID, dfp->input_itemtype);
+      }
     }
   }
+
+}
+
+
+extern void StdDescFormActnProc (ForM f)
+
+{
+  StdDescFormActnProcEx (f, TRUE);
+}
+
+
+extern void StdDescFormActnProcNoFeatureChangeNoMolInfoChange (ForM f)
+
+{
+  StdDescFormActnProcEx (f, FALSE);
 }
 
+
 extern void StdDescFormCleanupProc (GraphiC g, VoidPtr data)
 
 {
@@ -1006,7 +1007,7 @@ static void FeatIDtoText (TexT t, ChoicePtr cp)
   SetTitle (t, "");
 }
 
-static void TextToFeatID (TexT t, ChoicePtr cp)
+NLM_EXTERN void TextToFeatID (TexT t, ChoicePtr cp)
 
 {
   Boolean      all_digits = TRUE;
@@ -1079,7 +1080,7 @@ static void FeatXreftoText (TexT t, SeqFeatPtr sfp)
   SetTitle (t, "");
 }
 
-static void TextToFeatXref (TexT t, SeqFeatPtr sfp)
+NLM_EXTERN void TextToFeatXref (TexT t, SeqFeatPtr sfp)
 
 {
   Boolean         all_digits = TRUE;
@@ -1940,11 +1941,6 @@ extern Boolean FeatFormReplaceWithoutUpdateProc (ForM f)
         sfp->qual = DialogToPointer (ffp->gbquals);
         VisStringDialogToGbquals (sfp, ffp->experiment, "experiment");
         InferenceDialogToGBQuals (ffp->inference, sfp, TRUE);
-        if (sfp->data.choice == SEQFEAT_RNA) {
-          AddRnaSpecificQuals (sfp, ffp->data);
-          /* NOTE - we will remove this line when we convert to the new data format */
-/*          ConvertToOldRNAFormat (sfp); */
-        }
 
         sfp->ext = DialogToPointer (ffp->usrobjext);
         if (ffp->goTermUserObj != NULL) {
@@ -1971,11 +1967,6 @@ extern Boolean FeatFormReplaceWithoutUpdateProc (ForM f)
         sfp->qual = DialogToPointer (ffp->gbquals);
         VisStringDialogToGbquals (sfp, ffp->experiment, "experiment");
         InferenceDialogToGBQuals (ffp->inference, sfp, TRUE);
-        if (sfp->data.choice == SEQFEAT_RNA) {
-          AddRnaSpecificQuals (sfp, ffp->data);
-          /* NOTE - we will remove this line when we convert to the new data format */
-/*          ConvertToOldRNAFormat (sfp); */
-        }
 
         sfp->ext = DialogToPointer (ffp->usrobjext);
         if (ffp->goTermUserObj != NULL) {
@@ -2029,11 +2020,6 @@ extern Boolean FeatFormReplaceWithoutUpdateProc (ForM f)
         rd.sfp = sfp;
         GatherItem (ompc.input_entityID, ompc.input_itemID, ompc.input_itemtype,
                     (Pointer) &rd, ReplaceFeatureExtras);
-        if (sfp->data.choice == SEQFEAT_RNA) {
-          AddRnaSpecificQuals (sfp, ffp->data);
-          /* NOTE - we will remove this line when we convert to the new data format */
-/*          ConvertToOldRNAFormat (sfp); */
-        }
         if (HasExceptionGBQual (sfp)) {
           sfp->excpt = TRUE;
         }
@@ -2261,7 +2247,7 @@ extern void StdFeatFormAcceptButtonProc (ButtoN b)
       SeqEntrySetScope (oldscope);
     }
     Update ();
-    if (ffp->leave_dlg_up == NULL || ! GetStatus (ffp->leave_dlg_up))
+    if (ffp != NULL && (ffp->leave_dlg_up == NULL || ! GetStatus (ffp->leave_dlg_up)))
     {
       Remove (w);
     }
@@ -3010,7 +2996,7 @@ static AuthListPtr ReadAuthorListFromTextFile (CharPtr path)
 {
   ReadBufferData rbd;
   CharPtr        line;
-  AuthListPtr    alp;
+  AuthListPtr    alp = NULL;
   AuthorPtr      ap;
   CharPtr        cp, next_cp;
   NameStdPtr     n;
@@ -3823,7 +3809,8 @@ extern void GetAlignmentsInSeqEntryCallback (SeqAnnotPtr sap, Pointer userdata)
   salp_list = (SeqAlignPtr PNTR) userdata;
   salp = (SeqAlignPtr) sap->data;
   if (salp == NULL) return;
-  salp = SeqAlignListDup(salp);
+  if (salp->segtype == SAS_SPLICED || salp->segtype == SAS_SPARSE) return;
+  salp = AlnMgr2DupAlnAndIndexes(salp);
   AlnMgr2IndexSeqAlign(salp);
   if (*salp_list == NULL)
   {
@@ -6674,13 +6661,17 @@ static void ShowIntervalChoice (IntervalChoicePtr dlg)
   }
   if (GetValue (dlg->seq_or_aln) == 1)
   {
-    Show (dlg->seq_dlg);
     Hide (dlg->aln_dlg);
+    Update ();
+    Show (dlg->seq_dlg);
+    Update ();
   }
   else
   {
-    Show (dlg->aln_dlg);
     Hide (dlg->seq_dlg);
+    Update ();
+    Show (dlg->aln_dlg);
+    Update ();
   }
 }
 
@@ -8884,7 +8875,7 @@ static void AddTypeStrainProc (ButtoN b)
     StringCpy(new_orgcomment, old_orgcomment);
     StringCat(new_orgcomment, sep);
   }
-  else
+  else if (new_orgcomment != NULL)
   {
     new_orgcomment[0] = 0;
   }
@@ -9147,3 +9138,579 @@ NLM_EXTERN void CloseLog (LogInfoPtr lip)
   FileRemove (lip->path);  
 }
 
+
+extern CharPtr ValNodeSeqIdName (ValNodePtr vnp)
+{
+  Char buf[100];
+
+  if (vnp == NULL || vnp->data.ptrvalue == NULL)
+  {
+    return NULL;
+  }
+  else
+  {
+    SeqIdWrite (vnp->data.ptrvalue, buf, PRINTID_FASTA_SHORT, sizeof (buf) - 1);
+    return StringSave (buf);
+  }
+}
+
+
+extern void ValNodeSeqIdFree (ValNodePtr vnp)
+{
+  if (vnp != NULL && vnp->data.ptrvalue != NULL)
+  {
+    vnp->data.ptrvalue = SeqIdFree (vnp->data.ptrvalue);
+  }
+}
+
+
+extern ValNodePtr ValNodeSeqIdCopy (ValNodePtr vnp)
+{
+  ValNodePtr vnp_copy = NULL;
+  if (vnp != NULL)
+  {
+    ValNodeAddPointer (&vnp_copy, vnp->choice, SeqIdDup (vnp->data.ptrvalue));
+  }
+  return vnp_copy;
+}
+
+extern Boolean ValNodeSeqIdMatch (ValNodePtr vnp1, ValNodePtr vnp2)
+{
+  if (vnp1 == NULL || vnp2 == NULL)
+  {
+    return FALSE;
+  }
+  if (SeqIdComp (vnp1->data.ptrvalue, vnp2->data.ptrvalue) == SIC_YES) 
+  {
+    return TRUE;
+  } 
+  else 
+  {
+    return FALSE;
+  }
+}
+
+
+static ValNodePtr ValNodeSeqIdListFree (ValNodePtr list)
+{
+  ValNodePtr list_next;
+
+  while (list != NULL) {
+    list_next = list->next;
+    list->next = NULL;
+    list->data.ptrvalue = SeqIdFree (list->data.ptrvalue);
+    list = ValNodeFree (list);
+    list = list_next;
+  }
+  return list;
+}
+
+
+static ValNodePtr ValNodeSeqIdListCopy (ValNodePtr list)
+{
+  ValNodePtr vnp, list_copy = NULL, list_prev = NULL;
+
+  while (list != NULL) {
+    vnp = ValNodeNew (list_prev);
+    vnp->data.ptrvalue = SeqIdDup (list->data.ptrvalue);
+    if (list_copy == NULL) {
+      list_copy = vnp;
+    }
+    list_prev = vnp;
+    list = list->next;
+  }
+  return list_copy;
+}
+
+
+static ValNodePtr SeqIdListToValNodeSeqIdList (SeqIdPtr sip_list)
+{
+  SeqIdPtr sip;
+  ValNodePtr list = NULL, vnp_p = NULL, vnp;
+
+  for (sip = sip_list; sip != NULL; sip = sip->next) {
+    vnp = ValNodeNew (vnp_p);
+    if (vnp_p == NULL) {
+      list = vnp;
+    }
+    vnp->data.ptrvalue = SeqIdDup (sip);
+    vnp_p = vnp;
+  }
+  return list;
+}
+
+
+static SeqIdPtr ValNodeSeqIdListToSeqIdList (ValNodePtr vnp_list)
+{
+  ValNodePtr vnp;
+  SeqIdPtr sip_list = NULL, sip_prev = NULL, sip;
+
+  for (vnp = vnp_list; vnp != NULL; vnp = vnp->next) {
+    sip = SeqIdDup (vnp->data.ptrvalue);
+    if (sip_prev == NULL) {
+      sip_list = sip;
+    } else {
+      sip_prev->next = sip;
+    }
+    sip_prev = sip;
+  }
+  return sip_list;
+}
+
+
+static void EditIdList (SeqIdPtr PNTR sip_list, SeqIdPtr all_list)
+{
+  ModalAcceptCancelData acd;
+  DialoG                dlg;
+  WindoW                w;
+  ButtoN                b;
+  GrouP                 h, c;
+  ValNodePtr            tmp;
+  
+  if (sip_list == NULL || *sip_list == NULL) return;
+
+  w = MovableModalWindow(-20, -13, -10, -10, "Constraint", NULL);
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  /* create dialog with list of sequence IDs */
+  dlg = ValNodeSelectionDialogExEx (h, ValNodeSeqIdListCopy(all_list), TALL_SELECTION_LIST, ValNodeSeqIdName,
+                                           ValNodeSeqIdFree, ValNodeSeqIdCopy,
+                                           ValNodeSeqIdMatch, "location", 
+                                           NULL, NULL, TRUE, TRUE, FALSE, NULL);
+  
+  /* populate */
+  tmp = SeqIdListToValNodeSeqIdList (*sip_list);
+  PointerToDialog (dlg, tmp);
+  tmp = ValNodeSeqIdListFree(tmp);
+
+  c = HiddenGroup (h, 2, 0, NULL);
+  SetGroupSpacing (c, 10, 10);
+  b = PushButton (c, "Accept", ModalAcceptButton);
+  SetObjectExtra (b, &acd, NULL);
+  b = PushButton (c, "Cancel", ModalCancelButton);
+  SetObjectExtra (b, &acd, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) dlg,
+                              (HANDLE) c, 
+                              NULL);
+
+  Show (w);
+  Select (w);
+  acd.accepted = FALSE;
+  acd.cancelled = FALSE;
+  while (!acd.accepted && ! acd.cancelled)
+  {
+    ProcessExternalEvent ();
+    Update ();
+  }
+  ProcessAnEvent ();
+  if (!acd.cancelled)
+  {
+    tmp = DialogToPointer (dlg);
+    *sip_list = ValNodeSeqIdListToSeqIdList (tmp);
+    tmp = ValNodeSeqIdListFree(tmp);
+  }
+  Remove (w);
+}
+
+
+static Boolean EditOneDescriptor (SeqDescPtr sdp)
+{
+  Boolean rval = FALSE;
+
+  if (sdp == NULL) 
+  {
+    return FALSE;
+  }
+  else if (sdp->choice == Seq_descr_pub) 
+  {
+    rval = EditPubdescInPlace(sdp);
+  }
+  return rval;
+}
+
+typedef struct descriptorstreameditordlg {
+  DIALOG_MESSAGE_BLOCK
+
+  DialoG pubdesc_table;
+
+  ValNodePtr               desc_stream_list;
+  ValNodePtr               sip_list;
+  Nlm_ChangeNotifyProc     change_notify;
+  Pointer                  change_userdata;
+} DescriptorStreamEditorDlgData, PNTR DescriptorStreamEditorDlgPtr;
+
+
+static Boolean HasAllIds (SeqIdPtr sip_list, ValNodePtr all_sip)
+{
+  Boolean found = FALSE, any_missing = FALSE;
+  ValNodePtr vnp;
+
+  if (sip_list == NULL || all_sip == NULL) {
+    return FALSE;
+  }
+
+  while (sip_list != NULL) {
+    found = FALSE;
+    for (vnp = all_sip; vnp != NULL && !found; vnp = vnp->next) {
+      if (vnp->choice == 0 && SeqIdComp (vnp->data.ptrvalue, sip_list) == SIC_YES) {
+        vnp->choice = 1;
+        found = TRUE;
+      }
+    }
+    sip_list = sip_list->next;
+  }
+  for (vnp = all_sip; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == 0) {
+      any_missing = TRUE;
+    }
+    vnp->choice = 0;
+  }
+  return !any_missing;
+}
+
+
+#define k_WideColumnWidth 40
+
+
+static CharPtr GetDescriptorFlatFileText (SeqDescPtr sdp)
+{
+  Asn2gbJobPtr   ajp;
+  BaseBlockPtr   bbp;
+  XtraBlock      extra;
+  BioseqPtr      bsp;
+  ErrSev         level;
+  CharPtr        desc_text = NULL, cp;
+  Int4           index;
+
+  
+  if (sdp == NULL) 
+  {
+    return NULL;
+  }
+  bsp = BioseqNew ();
+  bsp->descr = AsnIoMemCopy (sdp, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite);
+  bsp->repr = Seq_repr_raw;
+
+  level = ErrSetMessageLevel (SEV_MAX);
+
+  MemSet ((Pointer) &extra, 0, sizeof (XtraBlock));
+  ajp = asn2gnbk_setup (bsp, NULL, NULL, (FmtType)GENBANK_FMT, SEQUIN_MODE, NORMAL_STYLE, 0, 0, 0, &extra);
+  if (ajp != NULL) 
+  {
+    for (index = 0; index < ajp->numParagraphs; index++) 
+    {
+      bbp = ajp->paragraphArray [index];
+      if (bbp->blocktype == REFERENCE_BLOCK)
+      {
+        desc_text = asn2gnbk_format (ajp, (Int4) index);
+        if (desc_text != NULL) {
+          /* skip first line */
+          cp = StringChr (desc_text, 10);
+          if (cp != NULL) {
+            StringCpy (desc_text, cp + 1);
+            while ((cp = StringChr (desc_text, 10)) != NULL) {
+              *cp = '~';
+            }
+          }
+        }
+      }
+    }
+  }
+
+  ErrSetMessageLevel (level);    
+
+  ajp = asn2gnbk_cleanup (ajp);
+  bsp = BioseqFree (bsp);
+  return desc_text;  
+}
+
+
+static CharPtr GetDescriptorText (SeqDescPtr sdp, StdPrintOptionsPtr spop)
+{
+  CharPtr text;
+
+  if (sdp == NULL) {
+    return NULL;
+  } else {
+    text = GetDescriptorFlatFileText (sdp);
+    if (text == NULL) 
+    {
+      if (StdFormatPrint ((Pointer) sdp, (AsnWriteFunc) SeqDescAsnWrite,
+                                        "StdSeqDesc", spop))
+      {
+        if (StringNICmp (spop->ptr, "citation;", 9) == 0)
+        {
+          text = StringSave (spop->ptr + 9);
+        }
+        else
+        {
+          text = StringSave (spop->ptr);
+        }
+        spop->ptr = MemFree (spop->ptr);
+      } else {
+        text = StringSave ("Unable to format");
+      }
+    }
+  }
+  return text;
+}
+
+
+static void 
+AddOnePublicationToTableDisplayList 
+(ValNodePtr PNTR    row_list, 
+ DescStreamPtr      d,
+ StdPrintOptionsPtr spop,
+ ValNodePtr         sip_list)
+
+{
+  ValNodePtr     new_row = NULL;
+  Char           buf[k_WideColumnWidth];
+
+  if (row_list == NULL || d == NULL)
+  {
+    return;
+  }
+
+  if (d->replace == NULL) {
+    ValNodeAddPointer (&new_row, 4, StringSave ("    "));
+    ValNodeAddPointer (&new_row, 8, StringSave ("Undelete"));
+  } else {
+    ValNodeAddPointer (&new_row, 4, StringSave ("Edit"));
+    ValNodeAddPointer (&new_row, 8, StringSave ("Delete"));
+  }
+
+  if (d->orig == NULL) {
+    ValNodeAddPointer (&new_row, k_WideColumnWidth, StringSave ("New"));
+  } else {
+    ValNodeAddPointer (&new_row, k_WideColumnWidth, GetDescriptorText (d->orig, spop));
+  }
+
+  if (d->replace == NULL) {
+    ValNodeAddPointer (&new_row, k_WideColumnWidth, StringSave ("Deleted"));
+  } else {
+    ValNodeAddPointer (&new_row, k_WideColumnWidth, GetDescriptorText (d->replace, spop));
+  }
+
+  if (d->owners == NULL) {
+    ValNodeAddPointer (&new_row, k_WideColumnWidth, StringSave ("No owners - will be deleted"));
+  } else if (HasAllIds(d->owners, sip_list)) {
+    ValNodeAddPointer (&new_row, k_WideColumnWidth, StringSave ("All"));
+  } else {
+    SeqIdWrite (d->owners, buf, PRINTID_FASTA_ALL, sizeof (buf) - 1);
+    ValNodeAddPointer (&new_row, k_WideColumnWidth, StringSave (buf));
+  }
+
+  if (d->num_dependent == 0) {
+    ValNodeAddPointer (&new_row, 20, StringSave (""));
+  } else {
+    sprintf (buf, "%d featcit", d->num_dependent);
+    ValNodeAddPointer (&new_row, 20, StringSave (buf));
+  }
+    
+  ValNodeAddPointer (row_list, 0, new_row);
+}
+
+
+static ValNodePtr AddNewControls (void)
+{
+  ValNodePtr row = NULL;
+
+  ValNodeAddPointer (&row, 4, StringSave ("    "));
+  ValNodeAddPointer (&row, 8, StringSave ("        "));
+  ValNodeAddPointer (&row, k_WideColumnWidth, StringSave ("Add new publication"));
+  return row;
+}
+
+
+static void PublicationListDialogRedraw (DescriptorStreamEditorDlgPtr dlg)
+{
+  StdPrintOptionsPtr       spop = NULL;
+  ValNodePtr               row_list = NULL, vnp;
+
+  if (dlg == NULL)
+  {
+    return;
+  }
+  
+  spop = StdPrintOptionsNew (NULL);
+  if (spop == NULL) 
+  {
+    Message (MSG_FATAL, "StdPrintOptionsNew failed");
+    return;
+  }
+  
+  spop->newline = ";";
+  spop->indent = "";
+  
+  /* make row list for table display and update table display */
+  for (vnp = dlg->desc_stream_list;
+       vnp != NULL;
+       vnp = vnp->next)
+  {
+    AddOnePublicationToTableDisplayList (&row_list, vnp->data.ptrvalue, spop, dlg->sip_list);
+  }
+  ValNodeAddPointer (&row_list, 0, AddNewControls());
+  PointerToDialog (dlg->pubdesc_table, row_list);
+  row_list = FreeTableDisplayRowList (row_list);
+  spop = StdPrintOptionsFree (spop);
+  
+  
+}
+
+
+static void PublicationListDblClick (PoinT cell_coord, CharPtr header_text, CharPtr cell_text, Pointer userdata)
+{
+  DescriptorStreamEditorDlgPtr dlg;
+  ValNodePtr                   vnp;
+  Int4                         d_num;
+  DescStreamPtr                d;
+  
+  dlg = (DescriptorStreamEditorDlgPtr) userdata;
+  if (dlg == NULL)
+  {
+    return;
+  }
+  
+  for (vnp = dlg->desc_stream_list, d_num = 0;
+       vnp != NULL && d_num < cell_coord.y;
+       vnp = vnp->next, d_num++)
+  {
+  }
+  
+  if (vnp == NULL || (d = (DescStreamPtr) vnp->data.ptrvalue) == NULL)
+  {
+    if (cell_coord.y == d_num && cell_coord.x == 2) 
+    {
+      d = DescStreamNew (NULL, NULL);
+      d->replace = SeqDescrNew (NULL);
+      d->replace->choice = Seq_descr_pub;
+      d->replace->data.ptrvalue = PubdescNew ();
+      if (EditOneDescriptor (d->replace))
+      {
+        d->owners = ValNodeSeqIdListToSeqIdList (dlg->sip_list);
+        ValNodeAddPointer (&(dlg->desc_stream_list), 0, d);
+      }
+      else
+      {
+        d = DescStreamFree (d);
+      }
+    } 
+    else 
+    {
+      return;
+    }
+  } 
+  else if (cell_coord.x == 1)
+  {
+    if (d->replace == NULL) {
+      d->replace = AsnIoMemCopy (d->orig, (AsnReadFunc) SeqDescAsnRead, (AsnWriteFunc) SeqDescAsnWrite);
+    } else {
+      if (ANS_YES != Message (MSG_YN, "Are you sure you want to delete the publication?"))
+      {
+        return;
+      }
+      d->replace = SeqDescFree (d->replace);
+    }
+  }
+  else if (cell_coord.x == 4) 
+  {
+    /* edit owner list */
+    EditIdList (&(d->owners), dlg->sip_list);
+  }
+  else
+  {
+    EditOneDescriptor (d->replace);
+  }
+  PublicationListDialogRedraw (dlg);
+ 
+}
+
+
+static void DescriptorStreamToDialog (DialoG d, Pointer userdata)
+{
+  DescriptorStreamEditorDlgPtr dlg;
+  
+  dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL)
+  {
+    return;
+  }
+
+  dlg->desc_stream_list = (ValNodePtr) userdata;
+
+  PublicationListDialogRedraw(dlg);
+
+
+}
+
+static Pointer DialogToDescriptorStream (DialoG d)
+{
+  DescriptorStreamEditorDlgPtr dlg;
+  ValNodePtr                   list = NULL;
+  
+  dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL)
+  {
+    return NULL;
+  }
+  
+  return (Pointer) list;
+}
+
+
+static void CleanupDescriptorStreamEditorDlg (GraphiC g, VoidPtr data)
+{
+  DescriptorStreamEditorDlgPtr dlg;
+
+  dlg = (DescriptorStreamEditorDlgPtr) data;
+  if (dlg != NULL) {
+    dlg->sip_list = ValNodeSeqIdListFree(dlg->sip_list);
+  } 
+  StdCleanupExtraProc (g, data);
+}
+
+
+NLM_EXTERN DialoG DescriptorStreamEditor (GrouP h,  Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+{
+  DescriptorStreamEditorDlgPtr dlg;
+  GrouP           p;
+  
+  dlg = (DescriptorStreamEditorDlgPtr) MemNew (sizeof (DescriptorStreamEditorDlgData));
+  if (dlg == NULL)
+  {
+    return NULL;
+  }
+
+  p = HiddenGroup (h, -1, 0, NULL);
+  SetObjectExtra (p, dlg, CleanupDescriptorStreamEditorDlg);
+  SetGroupSpacing (p, 10, 10);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = DescriptorStreamToDialog;
+  dlg->fromdialog = DialogToDescriptorStream;
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  dlg->pubdesc_table = TableDisplayDialog (p, stdCharWidth * 110, stdLineHeight * 16, 0, 2,
+                                       PublicationListDblClick, dlg,
+                                       NULL, NULL);
+
+
+  return (DialoG) p;
+}
+
+
+NLM_EXTERN void SetDescriptorStreamEditorIdList (DialoG d, SeqIdPtr sip_list)
+{
+  DescriptorStreamEditorDlgPtr dlg;
+  
+  dlg = (DescriptorStreamEditorDlgPtr) GetObjectExtra (d);
+  if (dlg != NULL) {
+    dlg->sip_list = ValNodeSeqIdListFree (dlg->sip_list);
+    dlg->sip_list = SeqIdListToValNodeSeqIdList (sip_list);
+  }
+}
+
+
diff --git a/desktop/dlgutil2.c b/desktop/dlgutil2.c
index cbdc60d..781f849 100644
--- a/desktop/dlgutil2.c
+++ b/desktop/dlgutil2.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.206 $
+* $Revision: 6.216 $
 *
 * File Description: 
 *
@@ -1193,6 +1193,7 @@ static Boolean ShouldSuppressGBQual(Uint1 subtype, CharPtr qual_name)
       return TRUE;
     }
   }
+
   return FALSE;
 }
     
@@ -1211,15 +1212,18 @@ static Boolean ShouldBeAGBQual (Uint1 subtype, Int2 qual, Boolean allowProductGB
       qual == GBQUAL_insertion_seq ||
       qual == GBQUAL_label ||
       qual == GBQUAL_locus_tag ||
+      qual == GBQUAL_non_functional ||
       qual == GBQUAL_note ||
       qual == GBQUAL_partial ||
       qual == GBQUAL_product ||
       qual == GBQUAL_pseudo ||
+      qual == GBQUAL_pseudogene ||
       qual == GBQUAL_rpt_unit ||
       qual == GBQUAL_transposon ||
       qual == GBQUAL_experiment ||
       qual == GBQUAL_trans_splicing ||
       qual == GBQUAL_ribosomal_slippage ||
+      qual == GBQUAL_standard_name ||
       qual == GBQUAL_inference) {
     return FALSE;
   }
@@ -3395,6 +3399,72 @@ extern void ModalThirdOptionButton (ButtoN b)
   }
 }
 
+
+NLM_EXTERN Int4 
+ThreeOptionsDlg
+(CharPtr title_txt,
+ CharPtr explain_txt,
+ CharPtr opt1,
+ CharPtr opt2,
+ CharPtr opt3)
+{
+  WindoW w;
+  GrouP  h, c;
+  ButtoN b;
+  GrouP  p;
+  ModalAcceptCancelData acd;
+  
+  
+  w = MovableModalWindow (-20, -13, -10, -10, title_txt, NULL);
+  h = HiddenGroup(w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  p = MultiLinePrompt (h, explain_txt, 300, programFont);
+    
+  c = HiddenGroup (h, 3, 0, NULL);
+  b = PushButton (c, opt1, ModalAcceptButton);
+  SetObjectExtra (b, &acd, NULL);
+  b = PushButton (c, opt2, ModalCancelButton);
+  SetObjectExtra (b, &acd, NULL);
+  
+  if (!StringHasNoText (opt3)) {
+    b = PushButton (c, opt3, ModalThirdOptionButton);
+    SetObjectExtra (b, &acd, NULL);
+  }
+  
+  AlignObjects (ALIGN_CENTER, (HANDLE) p,
+                              (HANDLE) c, 
+                              NULL);
+
+  Show (w);
+  Select (w);
+  
+  acd.cancelled = FALSE;
+  acd.third_option = FALSE;
+  acd.accepted = FALSE;
+  while (!acd.accepted && ! acd.cancelled && !acd.third_option)
+  {
+    ProcessExternalEvent ();
+    Update ();
+  }
+  ProcessAnEvent ();
+  Remove (w);
+  
+  if (acd.accepted)
+  {
+    return 1;
+  }
+  else if (acd.cancelled)
+  {
+    return 2;
+  }
+  else
+  {
+    return 3;
+  }
+}
+
+
 typedef struct tabledisplay 
 {
   DIALOG_MESSAGE_BLOCK
@@ -6963,7 +7033,7 @@ extern void InferenceDialogToGBQuals (DialoG d, SeqFeatPtr sfp, Boolean convertB
       StringCat (str, first);
       StringCat (str, ":");
       StringCat (str, second);
-      if (StringCmp (prefix, "alignment") == 0 && accession_list != NULL) {
+      if (StringCmp (prefix, "alignment") == 0 && StringDoesHaveText (accession_list)) {
         StringCat (str, ":");
         StringCat (str, accession_list);
       }
@@ -7773,7 +7843,7 @@ extern DialoG EditApplyDialog
  Pointer                  change_userdata)
 {
   EditApplyDlgPtr dlg;
-  GrouP           p, p1;
+  GrouP           p, p1 = NULL;
   ButtoN          b;
   ValNodePtr      cpy;
   
@@ -8478,7 +8548,7 @@ static void PointerToClickableItemListDlg (DialoG d, Pointer data)
   dlg->col_fmt[2].pixWidth = (r.right - r.left - dlg->col_fmt[0].pixWidth) / 3;
   dlg->col_fmt[3].pixWidth = (r.right - r.left - dlg->col_fmt[0].pixWidth) / 3;
 
-  dlg->item_list = ValNodeFree (dlg->item_list);
+  dlg->item_list = ClickableItemObjectListFree (dlg->item_list);
   dlg->item_list = (ValNodePtr) data; 
  
   if (dlg->item_list == NULL)
@@ -8577,7 +8647,7 @@ static void CleanupClickableItemListDlg (GraphiC g, VoidPtr data)
 
   dlg = (ClickableItemListDlgPtr) data;
   if (dlg != NULL) {
-    dlg->item_list = ValNodeFree (dlg->item_list);
+    dlg->item_list = ClickableItemObjectListFree (dlg->item_list);
   } 
   StdCleanupExtraProc (g, data);
 }
@@ -9176,7 +9246,7 @@ static void PopulateClickableItemList (DialoG d, ClickableItemPtr cip)
   if (d == NULL) return;
   if (cip != NULL)
   {
-    ValNodeLinkCopy (&list, cip->item_list);
+    ValNodeLink (&list, ClickableItemObjectListCopy (cip->item_list));
   }
   PointerToDialog (d, list);
 
@@ -9911,7 +9981,9 @@ extern void ScrollToPreviousClickableTextDescription (CharPtr txt, DialoG d)
     while (vnp != NULL && vnp->next != NULL) {
       vnp = vnp->next;
     }
+    if (vnp != NULL) {
     row_offset = vnp->data.intvalue;
+    }
   } else {
     row_offset = vnp_prev->data.intvalue;
   }
@@ -11513,6 +11585,9 @@ static void StringToSingleGBQualEditDialog (DialoG d, Pointer data)
       Disable (dlg->editor);
     }
   }
+  if (dlg->tlp_callback != NULL) {
+    (dlg->tlp_callback)(dlg->callback_data);
+  }
 }
 
 static Pointer SingleGBQualEditDialogToString (DialoG d)
@@ -11934,6 +12009,73 @@ static GBQualPtr CopyGBQualList (GBQualPtr origgbq)
   return head;
 }
 
+
+static void ChangeRptTypeForSatellite (Pointer data)
+{
+  NewFieldPagePtr fpf;
+  GBQualPtr       gbq_it;
+  Int4            i;
+  Int4            rpt_type_num = -1;
+  Boolean         tandem = FALSE, found_satellite = FALSE;
+  CharPtr         val, new_val, src;
+  CharPtr         fmt = "(tandem,%s)";
+
+  fpf = (NewFieldPagePtr) data;
+
+  if (fpf == NULL) {
+    return;
+  }
+
+  /* find satellite qualifier, get type */
+  for (gbq_it = fpf->new_gbq, i = 0; gbq_it != NULL; gbq_it = gbq_it->next, i++) {
+    if (StringICmp (gbq_it->qual, "satellite") == 0) {
+      val = DialogToPointer (fpf->editors[i]);
+      if (StringCmp (val, "microsatellite") == 0 
+          || StringCmp (val, "minisatellite") == 0
+          || StringNICmp (val, "microsatellite:", 15) == 0
+          || StringNICmp (val, "minisatellite:", 14) == 0) {
+        tandem = TRUE;
+      }
+      val = MemFree (val);
+      found_satellite = TRUE;
+    } else if (StringICmp (gbq_it->qual, "rpt_type") == 0) {
+      rpt_type_num = i;
+    }
+  }
+
+  /* now set rpt_type */
+  if (found_satellite && rpt_type_num > -1) {
+    val = DialogToPointer (fpf->editors[rpt_type_num]);
+
+    if (tandem) {
+      if (StringISearch (val, "tandem") == NULL) {
+        /* add tandem */
+        if (StringHasNoText (val)) {
+          PointerToDialog (fpf->editors[rpt_type_num], "tandem");
+        } else {
+          src = StringChr (val, '}');
+          if (src != NULL) {
+            *src = 0;
+          }
+          src = val;
+          if (*src == '{') {
+            src++;
+          }
+          new_val = (CharPtr) MemNew (sizeof (Char) * (StringLen (src) + StringLen (fmt)));                        
+          sprintf (new_val, fmt, src);
+          PointerToDialog (fpf->editors[rpt_type_num], new_val);
+          new_val = MemFree (new_val);
+        }
+      }
+    }
+
+    /* set */
+
+    val = MemFree (val);
+  }
+}
+
+
 extern DialoG NewCreateImportFields (GrouP h, CharPtr name, SeqFeatPtr sfp, Boolean allowProductGBQual)
 {
   NewFieldPagePtr fpf;
@@ -12038,7 +12180,8 @@ extern DialoG NewCreateImportFields (GrouP h, CharPtr name, SeqFeatPtr sfp, Bool
         StaticPrompt (g, gbq_it->qual, 0, dialogTextHeight, programFont, 'l');
         fpf->editors[j] = CreateSingleGBQualEditDialog (g, NULL, gbq_it->qual,
                                                         j < num_legal ? FALSE : TRUE,
-                                                        NULL, NULL);
+                                                        StringCmp (gbq_it->qual, "satellite") == 0 ? ChangeRptTypeForSatellite : NULL,
+                                                        StringCmp (gbq_it->qual, "satellite") == 0 ? fpf : NULL);
         PointerToDialog (fpf->editors[j], gbq_it->val);
         j++;
       }   
@@ -12765,7 +12908,7 @@ static void ClickFeatureReplaceList (DoC d, PoinT pt)
   Int2             col;
   FeatureReplaceListDlgPtr dlg;
   Int4             offset;
-  Int2             first_shown;
+  Int2             first_shown = 0;
   RecT             r;
   BaR              vbar;
   Int4             scroll_pos;
@@ -13094,7 +13237,7 @@ static void ClickFeatureSelectList (DoC d, PoinT pt)
 
 {
   Int2             item, numItems;
-  Int2             first_shown;
+  Int2             first_shown = 0;
   Int2             row;
   Int2             col;
   Int4             offset;
diff --git a/desktop/dlogutil.h b/desktop/dlogutil.h
index 4b4ffea..6c52f41 100644
--- a/desktop/dlogutil.h
+++ b/desktop/dlogutil.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.104 $
+* $Revision: 6.110 $
 *
 * File Description: 
 *
@@ -132,10 +132,11 @@ typedef struct featform {
   FEATURE_FORM_BLOCK
 } FeatureForm, PNTR FeatureFormPtr;
 
-extern void SetDescriptorPropagate (BioseqSetPtr bssp);
 extern Int2 LIBCALLBACK DescriptorPropagate (Pointer data);
 extern Boolean DescFormReplaceWithoutUpdateProc (ForM f);
+extern Boolean DescFormReplaceWithoutUpdateProcEx (ForM f, Boolean feature_or_molinfo_change);
 extern void StdDescFormActnProc (ForM f);
+extern void StdDescFormActnProcNoFeatureChangeNoMolInfoChange (ForM f);
 
 extern void StdDescFormCleanupProc (GraphiC g, VoidPtr data);
 
@@ -373,6 +374,7 @@ typedef struct modalacceptcancel
 extern void ModalAcceptButton (ButtoN b);
 extern void ModalCancelButton (ButtoN b);
 extern void ModalThirdOptionButton (ButtoN b);
+NLM_EXTERN Int4 ThreeOptionsDlg (CharPtr title_txt, CharPtr explain_txt, CharPtr opt1, CharPtr opt2, CharPtr opt3);
 
 typedef void (*TableDisplayDblClick) PROTO((PoinT, CharPtr, CharPtr, Pointer));
 typedef Boolean (*TableDisplayLeftInRed) PROTO ((Int4, ValNodePtr, Pointer));
@@ -795,6 +797,11 @@ NLM_EXTERN Boolean AutomatchFeatures (DialoG d, ValNodePtr PNTR existing_feature
 
 NLM_EXTERN void CloseLog (LogInfoPtr lip);
 
+NLM_EXTERN void TextToFeatID (TexT t, ChoicePtr cp);
+NLM_EXTERN void TextToFeatXref (TexT t, SeqFeatPtr sfp);
+
+NLM_EXTERN DialoG DescriptorStreamEditor (GrouP h,  Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+NLM_EXTERN void SetDescriptorStreamEditorIdList (DialoG d, SeqIdPtr sip_list);
 
 #ifdef __cplusplus
 }
diff --git a/desktop/e2docsum.c b/desktop/e2docsum.c
index b7e7c30..e0ffe73 100644
--- a/desktop/e2docsum.c
+++ b/desktop/e2docsum.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/30/01
 *
-* $Revision: 6.56 $
+* $Revision: 6.57 $
 *
 * File Description: 
 *
@@ -2586,6 +2586,7 @@ static void AddBlastAlignment (Int4 uid, Int2 numAlign, Int4Ptr alignuids, Uint2
   Int2                 i;
   BLAST_OptionsBlkPtr  options = NULL;
   SeqAlignPtr          prev;
+  CharPtr              program_name = NULL;
   BioseqPtr            query;
   SeqAlignPtr          salp;
   SeqAnnotPtr          sap;
@@ -2599,7 +2600,8 @@ static void AddBlastAlignment (Int4 uid, Int2 numAlign, Int4Ptr alignuids, Uint2
     return;
   if (ISA_na (subject->mol)) {
     align_type = 1;
-    options = BLASTOptionNew ("blastn", TRUE);
+    program_name = "blastn";
+    options = BLASTOptionNew (program_name, TRUE);
     if (options != NULL) {
       options->gapped_calculation = TRUE;
       options->db_length = 100000000;
@@ -2611,7 +2613,8 @@ static void AddBlastAlignment (Int4 uid, Int2 numAlign, Int4Ptr alignuids, Uint2
     }
   } else if (ISA_aa (subject->mol)) {
     align_type = 2;
-    options = BLASTOptionNew ("blastp", TRUE);
+    program_name = "blastp";
+    options = BLASTOptionNew (program_name, TRUE);
     if (options != NULL) {
       options->gapped_calculation = TRUE;
       options->db_length = 20000000;
@@ -2619,7 +2622,7 @@ static void AddBlastAlignment (Int4 uid, Int2 numAlign, Int4Ptr alignuids, Uint2
     }
   } else
     return;
-  search = BLASTSetUpSearch (subject, options->program_name, 0, 0, NULL, options, NULL);
+  search = BLASTSetUpSearch (subject, program_name, 0, 0, NULL, options, NULL);
 
   for (i = 0; i < numAlign; i++) {
     if (alignuids [i] != uid) {
diff --git a/desktop/e2trmlst.c b/desktop/e2trmlst.c
index 57f84c3..c341011 100644
--- a/desktop/e2trmlst.c
+++ b/desktop/e2trmlst.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   10/30/01
 *
-* $Revision: 6.43 $
+* $Revision: 6.44 $
 *
 * File Description: 
 *
@@ -1851,6 +1851,7 @@ static Int2 FindLineOfText (CharPtr text, CharPtr str)
 
   /* Do a binary search for the search string */
 
+  if (index != NULL) {
   left = 1;
   right = numLines;
   while (left <= right) {
@@ -1881,6 +1882,7 @@ static Int2 FindLineOfText (CharPtr text, CharPtr str)
       mid = 0;
     */
   }
+  }
   
   /* Clean up and return */
 
@@ -5920,7 +5922,7 @@ static void AddTermToList (FormInfoPtr pFormInfo, StateDataPtr newTerm, Int2 ite
   /*----------------------------------*/
 
   newTerm->group = GROUP_SINGLE;
-  if (merge) {
+  if (merge && currTerm != NULL) {
     switch (currTerm->group) {
       case GROUP_SINGLE:
         currTerm->group = GROUP_FIRST;
diff --git a/desktop/gbfview.c b/desktop/gbfview.c
index 127647f..4292104 100644
--- a/desktop/gbfview.c
+++ b/desktop/gbfview.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   2/5/97
 *
-* $Revision: 6.100 $
+* $Revision: 6.102 $
 *
 * File Description: 
 *
@@ -1186,6 +1186,25 @@ static void LookForTpa (
   *hastpaP = TRUE;
 }
 
+static void LookForTsa (
+  SeqDescrPtr sdp,
+  Pointer userdata
+)
+
+{
+  BoolPtr     hastsaP;
+  MolInfoPtr  mip;
+
+  if (sdp == NULL || sdp->choice != Seq_descr_molinfo) return;
+  mip = (MolInfoPtr) sdp->data.ptrvalue;
+  if (mip == NULL) return;
+
+  if (mip->tech != MI_TECH_tsa) return;
+
+  hastsaP = (BoolPtr) userdata;
+  *hastsaP = TRUE;
+}
+
 static void LookForFarBsp (
   BioseqPtr bsp,
   Pointer userdata
@@ -1271,6 +1290,7 @@ static void PopulateFlatFile (BioseqViewPtr bvp, FmtType format, FlgType flags)
   Boolean            forceOnlyNearFeats = FALSE;
   FILE               *fp;
   Boolean            hastpaaligns;
+  Boolean            hastsaaligns;
   Int2               into;
   Boolean            isAEorCH;
   Boolean            isGED;
@@ -1457,8 +1477,10 @@ static void PopulateFlatFile (BioseqViewPtr bvp, FmtType format, FlgType flags)
     }
     if (lookupFar) {
       hastpaaligns = FALSE;
+      hastsaaligns = FALSE;
       VisitDescriptorsInSep (sep, (Pointer) &hastpaaligns, LookForTpa);
-      LookupFarSeqIDs (sep, TRUE, TRUE, TRUE, FALSE, hastpaaligns, FALSE, TRUE);
+      VisitDescriptorsInSep (sep, (Pointer) &hastsaaligns, LookForTsa);
+      LookupFarSeqIDs (sep, TRUE, TRUE, TRUE, FALSE, hastpaaligns || hastsaaligns, FALSE, TRUE);
     }
   }
 
@@ -1618,13 +1640,13 @@ static void PopulateFasta (BioseqViewPtr bvp)
   FonT             fnt;
   FILE             *fp;
   Uint1            group_segs;
-  Int2             into;
-  Int2             item;
+  Int2             into = 0;
+  Int2             item = 0;
   Boolean          master_style;
   Char             path [PATH_MAX];
   BaR              sb = NULL;
   SeqEntryPtr      sep;
-  Int4             startsAt;
+  Int4             startsAt = 0;
   SeqViewProcsPtr  svpp;
   TexT             txt;
 
@@ -1840,7 +1862,7 @@ static void PopulateQuality (BioseqViewPtr bvp)
   FonT         fnt;
   FILE         *fp;
   Int2         into;
-  Int2         item;
+  Int2         item = 0;
   Char         path [PATH_MAX];
   BaR          sb = NULL;
   SeqEntryPtr  sep;
@@ -1937,15 +1959,15 @@ static void PopulateAsnOrXML (BioseqViewPtr bvp, CharPtr outmode, Boolean doGbse
   FmtType      format = GENBANK_FMT;
   GBSeq        gbsq;
   GBSet        gbst;
-  Int2         into;
-  Int2         item;
+  Int2         into = 0;
+  Int2         item = 0;
   Boolean      lockFar = FALSE;
   Boolean      lookupFar = FALSE;
   ModType      mode = SEQUIN_MODE;
   Char         path [PATH_MAX];
   BaR          sb = NULL;
   SeqEntryPtr  sep;
-  Int4         startsAt;
+  Int4         startsAt = 0;
   StlType      style = NORMAL_STYLE;
   TexT         txt;
   Int2         val;
diff --git a/desktop/import.c b/desktop/import.c
index 3805d54..88900be 100644
--- a/desktop/import.c
+++ b/desktop/import.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   6/18/95
 *
-* $Revision: 6.72 $
+* $Revision: 6.75 $
 *
 * File Description: 
 *
@@ -618,6 +618,7 @@ extern ForM CreateImportForm (Int2 left, Int2 top, CharPtr title,
   WindoW             w;
   GrouP              x;
   GrouP              z;
+  Boolean            indexerVersion;
 
   w = NULL;
   ifp = (ImprtFormPtr) MemNew (sizeof (ImprtForm));
@@ -729,10 +730,15 @@ extern ForM CreateImportForm (Int2 left, Int2 top, CharPtr title,
                   NULL);
     AlignObjects (ALIGN_CENTER, (HANDLE) ifp->foldertabs, (HANDLE) h, NULL);
 
-    c = HiddenGroup (w, 2, 0, NULL);
+    c = HiddenGroup (w, 3, 0, NULL);
     b = PushButton (c, "Accept", StdFeatFormAcceptButtonProc);
     SetObjectExtra (b, ifp, NULL);
     PushButton (c, "Cancel", StdCancelButtonProc);
+    indexerVersion = (Boolean) (GetAppProperty ("InternalNcbiSequin") != NULL);
+    if (sfp == NULL && indexerVersion) {
+      ifp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
+    }
+
     AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
     RealizeWindow (w);
 
@@ -3681,6 +3687,7 @@ typedef struct replacevisstr {
   Uint1       subtype;
   CharPtr     deleteThis;
   CharPtr     replaceWith;
+  Boolean     replace_all;
 } ReplaceVisStrData, PNTR ReplaceVisStrPtr;
 
 static void ReplaceAllCallback (SeqDescrPtr sdp, Pointer data)
@@ -3713,6 +3720,8 @@ static void ReplaceAllVisibleStringsButtonProc (ButtoN b)
     return;
   }
 
+  sep = GetTopSeqEntryForEntityID (vfp->input_entityID);
+
   rd.subtype = vfp->subtype;
   rd.replaceWith = DialogToPointer (vfp->data);
   if (rd.replaceWith == NULL || StringHasNoText (rd.replaceWith)) {
@@ -3741,7 +3750,6 @@ static void ReplaceAllVisibleStringsButtonProc (ButtoN b)
     }
   }
 
-  sep = GetTopSeqEntryForEntityID (vfp->input_entityID);
   VisitDescriptorsInSep (sep, &rd, ReplaceAllCallback);
   
   GetRidOfEmptyFeatsDescStrings (vfp->input_entityID, NULL);
diff --git a/desktop/macrodlg.c b/desktop/macrodlg.c
index 76d9c94..29546ba 100755
--- a/desktop/macrodlg.c
+++ b/desktop/macrodlg.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11/23/2007
 *
-* $Revision: 1.157 $
+* $Revision: 1.185 $
 *
 * File Description: 
 *
@@ -371,6 +371,7 @@ static void RunMacro (ButtoN b)
   Uint2               entityID;
   Int4                num_fields = 0, num_features = 0;
   Int4                tmp_fields, tmp_features;
+  LogInfoPtr          lip;
 
   f = (MacroEditorFormPtr) GetObjectExtra (b);
   if (f == NULL) return;
@@ -387,12 +388,13 @@ static void RunMacro (ButtoN b)
     } else {
       WatchCursor();
       Update();
+      lip = OpenLog ("Macro Actions");
       for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
         sep = vnp->data.ptrvalue;
         entityID = ObjMgrGetEntityIDForChoice(sep);
         tmp_fields = 0;
         tmp_features = 0;
-        ApplyMacroToSeqEntry (sep, f->macro_list, &tmp_fields, &tmp_features);
+        lip->data_in_log |= ApplyMacroToSeqEntryEx (sep, f->macro_list, &tmp_fields, &tmp_features, lip->fp);
         num_fields += tmp_fields;
         num_features += tmp_features;
         ObjMgrSetDirtyFlag (entityID, TRUE);
@@ -402,6 +404,12 @@ static void RunMacro (ButtoN b)
       ArrowCursor ();
       Update ();   
       Message (MSG_OK, "Macro script affected %d fields and created %d features", num_fields, num_features);
+      if (!lip->data_in_log) {
+        fprintf (lip->fp, "Macro had no effect\n");
+        lip->data_in_log = TRUE;
+      }
+      CloseLog (lip);
+      lip = FreeLog (lip);
     }
   }
 }
@@ -800,19 +808,13 @@ static void DrawMacroDocControls (DoC d, RectPtr r, Int2 item, Int2 firstLine)
 }
 
 
-NLM_EXTERN void LaunchMacroEditor (IteM i)
+NLM_EXTERN void LaunchMacroEditorBaseForm (BaseFormPtr bfp)
 {
-  BaseFormPtr         bfp;
   WindoW              w;
   MacroEditorFormPtr  f;
   GrouP               h, c;
   MenU                m;
 
-#ifdef WIN_MAC
-  bfp = currentFormDataPtr;
-#else
-  bfp = GetObjectExtra (i);
-#endif
   if (bfp == NULL) return;
 
   f = (MacroEditorFormPtr) MemNew (sizeof (MacroEditorFormData));
@@ -862,6 +864,19 @@ NLM_EXTERN void LaunchMacroEditor (IteM i)
 }
 
 
+NLM_EXTERN void LaunchMacroEditor (IteM i)
+{
+  BaseFormPtr         bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  LaunchMacroEditorBaseForm (bfp);
+}
+
+
 static void ClearDialogBtn (ButtoN b)
 {
   DialoG d;
@@ -872,14 +887,198 @@ static void ClearDialogBtn (ButtoN b)
 }
 
 
+typedef struct textmarkerdialog
+{
+  DIALOG_MESSAGE_BLOCK
+
+  GrouP marker_choice;
+  TexT  marker_text;
+
+  Nlm_ChangeNotifyProc     change_notify;
+  Pointer                  change_userdata;
+} TextMarkerDialogData, PNTR TextMarkerDialogPtr;
+
+
+static void ResetTextMarkerDialog (DialoG d)
+{
+  TextMarkerDialogPtr tp;
+
+  tp = (TextMarkerDialogPtr) GetObjectExtra (d);
+  if (tp == NULL) {
+    return;
+  }
+  SetValue (tp->marker_choice, 1);
+  SetTitle (tp->marker_text, "");
+  Enable (tp->marker_text);
+}
+
+
+static void TextMarkerToDialog(DialoG d, Pointer data)
+{
+  TextMarkerDialogPtr tp;
+  TextMarkerPtr       tdata;
+
+  tp = (TextMarkerDialogPtr) GetObjectExtra (d);
+  if (tp == NULL) {
+    return;
+  }
+
+  tdata = (TextMarkerPtr) data;
+
+  if (tdata == NULL) {
+    ResetTextMarkerDialog(d);
+  } else {
+    if (tdata->choice == TextMarker_free_text) {
+      SetValue (tp->marker_choice, 1);
+      SetTitle (tp->marker_text, tdata->data.ptrvalue == NULL ? "" : tdata->data.ptrvalue);
+      Enable (tp->marker_text);
+    } else if (tdata->choice == TextMarker_digits) {
+      SetValue (tp->marker_choice, 3);
+      SetTitle (tp->marker_text, "");
+      Disable (tp->marker_text);
+    } else if (tdata->choice == TextMarker_letters) {
+      SetValue (tp->marker_choice, 4);
+      SetTitle (tp->marker_text, "");
+      Disable (tp->marker_text);
+    } else {
+      SetValue (tp->marker_choice, 1);
+      SetTitle (tp->marker_text, "");
+      Enable (tp->marker_text);
+    }
+  }
+}
+
+
+static Pointer DialogToTextMarker (DialoG d)
+{
+  TextMarkerDialogPtr tp;
+  Int2                val;
+  ValNodePtr          tdata = NULL;
+
+  tp = (TextMarkerDialogPtr) GetObjectExtra (d);
+  if (tp == NULL) {
+    return NULL;
+  }
+
+  val = GetValue (tp->marker_choice);
+  if (val == 1) {
+    ValNodeAddPointer (&tdata, TextMarker_free_text, JustSaveStringFromText (tp->marker_text));
+  } else if (val == 3) {
+    tdata = ValNodeNew (NULL);
+    tdata->choice = TextMarker_digits;
+  } else if (val == 4) {
+    tdata = ValNodeNew (NULL);
+    tdata->choice = TextMarker_letters;
+  }
+
+  return tdata;
+}
+
+
+static void TextMarkerMessage (DialoG d, Int2 mssg)
+
+{
+  TextMarkerDialogPtr tp;
+
+  tp = (TextMarkerDialogPtr) GetObjectExtra (d);
+  if (tp != NULL) {
+    switch (mssg) {
+      case VIB_MSG_INIT :
+        ResetTextMarkerDialog (d);        
+        break;
+      case VIB_MSG_ENTER :
+        Select (tp->marker_text);
+        break;
+      default :
+        break;
+    }
+  }
+}
+
+
+static void ChangeTextMarkerChoice (GrouP g)
+{
+  TextMarkerDialogPtr tp;
+  Int2 val;
+
+  tp = (TextMarkerDialogPtr) GetObjectExtra (g);
+  if (tp == NULL) {
+    return;
+  }
+
+  val = GetValue (tp->marker_choice);
+  if (val == 1) {
+    Enable (tp->marker_text);
+  } else {
+    Disable (tp->marker_text);
+  }
+
+  if (tp->change_notify != NULL) {
+    (tp->change_notify) (tp->change_userdata);
+  }
+}
+
+
+static void ChangeTextMarkerText (TexT t)
+{
+  TextMarkerDialogPtr tp;
+
+  tp = (TextMarkerDialogPtr) GetObjectExtra (t);
+  if (tp == NULL) {
+    return;
+  }
+
+  if (tp->change_notify != NULL) {
+    (tp->change_notify) (tp->change_userdata);
+  }
+}
+
+
+static DialoG TextMarkerDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+{
+  TextMarkerDialogPtr tp;
+  GrouP               p;
+  
+  tp = (TextMarkerDialogPtr) MemNew (sizeof (TextMarkerDialogData));
+  if (tp == NULL)
+  {
+    return NULL;
+  }
+  
+  p = HiddenGroup (h, -1, 0, NULL);
+  SetObjectExtra (p, tp, StdCleanupExtraProc);
+
+  tp->dialog = (DialoG) p;
+  tp->todialog = TextMarkerToDialog;
+  tp->fromdialog = DialogToTextMarker;
+  tp->dialogmessage = TextMarkerMessage;
+  tp->testdialog = NULL;
+
+  tp->change_notify = change_notify;
+  tp->change_userdata = change_userdata;
+
+  tp->marker_choice = HiddenGroup (p, 4, 0, ChangeTextMarkerChoice);
+  SetObjectExtra (tp->marker_choice, tp, NULL);
+  SetGroupSpacing (tp->marker_choice, 10, 10);
+
+  RadioButton (tp->marker_choice, "Text");
+  tp->marker_text = DialogText (tp->marker_choice, "", 10, ChangeTextMarkerText);
+  RadioButton (tp->marker_choice, "Digits");
+  RadioButton (tp->marker_choice, "Letters");
+  SetValue (tp->marker_choice, 1);
+
+  return (DialoG) p;
+}
+
+
 typedef struct textportiondialog
 {
   DIALOG_MESSAGE_BLOCK
 
   GrouP  start_choice;
-  TexT   start_text;
+  DialoG start_marker;
   GrouP  end_choice;
-  TexT   end_text;
+  DialoG end_marker;
   ButtoN rem_before;
   ButtoN also_rem_before;
   ButtoN rem_after;
@@ -902,22 +1101,22 @@ static void OutsideEnableDisable (TextPortionDialogPtr tp)
   }
   if (GetStatus (tp->rem_before)) 
   {
-    Enable (tp->start_text);
+    Enable (tp->start_marker);
     Enable (tp->also_rem_before);
   }
   else
   {
-    Disable (tp->start_text);
+    Disable (tp->start_marker);
     Disable (tp->also_rem_before);
   }
   if (GetStatus (tp->rem_after)) 
   {
-    Enable (tp->end_text);
+    Enable (tp->end_marker);
     Enable (tp->also_rem_after);
   }
   else
   {
-    Disable (tp->end_text);
+    Disable (tp->end_marker);
     Disable (tp->also_rem_after);
   }
 }
@@ -940,8 +1139,8 @@ static void ResetTextPortionDialog (TextPortionDialogPtr tp)
     SetStatus (tp->rem_after, FALSE);
     SetStatus (tp->also_rem_after, FALSE);
   }
-  SetTitle (tp->start_text, "");
-  SetTitle (tp->end_text, "");
+  PointerToDialog (tp->start_marker, NULL);
+  PointerToDialog (tp->end_marker, NULL);
   SetStatus (tp->insensitive, FALSE);
   SetStatus (tp->whole_word, FALSE);
   OutsideEnableDisable (tp);
@@ -971,18 +1170,13 @@ static void TextPortionToDialog (DialoG d, Pointer data)
         SetValue (tdlg->end_choice, 1);
       }
     } else {
-      SetStatus (tdlg->rem_before, StringHasNoText (tdata->left_text));
-      SetStatus (tdlg->rem_after, StringHasNoText (tdata->right_text));
+      SetStatus (tdlg->rem_before, !IsTextMarkerEmpty(tdata->left_marker));
+      SetStatus (tdlg->rem_after, !IsTextMarkerEmpty(tdata->right_marker));
       SetStatus (tdlg->also_rem_before, tdata->include_left);
       SetStatus (tdlg->also_rem_after, tdata->include_right);
     }
-    if (tdata->left_text != NULL) {
-      SetTitle (tdlg->start_text, tdata->left_text);
-    }
-    if (tdata->right_text != NULL)
-    {
-      SetTitle (tdlg->end_text, tdata->right_text);
-    }
+    PointerToDialog (tdlg->start_marker, tdata->left_marker);
+    PointerToDialog (tdlg->end_marker, tdata->right_marker);
     SetStatus (tdlg->insensitive, !tdata->case_sensitive);
     SetStatus (tdlg->whole_word, tdata->whole_word);
   }
@@ -1007,24 +1201,24 @@ static Pointer DialogToTextPortion (DialoG d)
       } else {
         tdata->include_left = TRUE;
       }
-      tdata->left_text = JustSaveStringFromText (tdlg->start_text);
+      tdata->left_marker = DialogToPointer (tdlg->start_marker);
 
       if (GetValue (tdlg->end_choice) == 1) {
         tdata->include_right = FALSE;
       } else {
         tdata->include_right = TRUE;
       }
-      tdata->right_text = JustSaveStringFromText (tdlg->end_text);
+      tdata->right_marker = DialogToPointer (tdlg->end_marker);
     } else {
       if (GetStatus (tdlg->rem_before)) {
-        tdata->left_text = JustSaveStringFromText (tdlg->start_text);
+        tdata->left_marker = DialogToPointer (tdlg->start_marker);
       } else {
-        tdata->left_text = NULL;
+        tdata->left_marker = NULL;
       }
       if (GetStatus (tdlg->rem_after)) {
-        tdata->right_text = JustSaveStringFromText (tdlg->end_text);
+        tdata->right_marker = DialogToPointer (tdlg->end_marker);
       } else {
-        tdata->right_text = NULL;
+        tdata->right_marker = NULL;
       }
 
       tdata->include_left = GetStatus (tdlg->also_rem_before);
@@ -1050,7 +1244,7 @@ static void TextPortionMessage (DialoG d, Int2 mssg)
         ResetTextPortionDialog (tp);        
         break;
       case VIB_MSG_ENTER :
-        Select (tp->start_text);
+        Select (tp->start_marker);
         break;
       default :
         break;
@@ -1140,7 +1334,7 @@ static GrouP GetTextPortionEndChoiceGroup (DialoG d)
 }
 
 
-static DialoG TextPortionDialog (GrouP h, Boolean inside, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+NLM_EXTERN DialoG TextPortionDialog (GrouP h, Boolean inside, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
 {
   TextPortionDialogPtr tp;
   GrouP                p, g1, g2;
@@ -1176,8 +1370,7 @@ static DialoG TextPortionDialog (GrouP h, Boolean inside, Nlm_ChangeNotifyProc c
     SetValue (tp->start_choice, 1);
     SetObjectExtra (tp->start_choice, tp, NULL);
 
-    tp->start_text = DialogText (g1, "", 10, ChangeTextPortionText);
-    SetObjectExtra (tp->start_text, tp, NULL);
+    tp->start_marker = TextMarkerDialog (g1, tp->change_notify, tp->change_userdata);
     
     StaticPrompt (g1, "And", 0, popupMenuHeight, programFont, 'r');
     tp->end_choice = HiddenGroup (g1, 2, 0, ChangeTextPortionGroup);
@@ -1186,21 +1379,18 @@ static DialoG TextPortionDialog (GrouP h, Boolean inside, Nlm_ChangeNotifyProc c
     SetValue (tp->end_choice, 1);
     SetObjectExtra (tp->end_choice, tp, NULL);
       
-    tp->end_text = DialogText (g1, "", 10, ChangeTextPortionText);
-    SetObjectExtra (tp->start_text, tp, NULL);
+    tp->end_marker = TextMarkerDialog (g1, tp->change_notify, tp->change_userdata);
   }
   else
   {
     tp->rem_before = CheckBox (g1, "Before", ChangeTextPortionBtn);
     SetObjectExtra (tp->rem_before, tp, NULL);
-    tp->start_text = DialogText (g1, "", 10, ChangeTextPortionText);
-    SetObjectExtra (tp->start_text, tp, NULL);
+    tp->start_marker = TextMarkerDialog (g1, tp->change_notify, tp->change_userdata);
     tp->also_rem_before = CheckBox (g1, "Also Remove Entered Text", ChangeTextPortionBtn);
 
     tp->rem_after = CheckBox (g1, "After", ChangeTextPortionBtn);
     SetObjectExtra (tp->rem_after, tp, NULL);
-    tp->end_text = DialogText (g1, "", 10, ChangeTextPortionText);
-    SetObjectExtra (tp->end_text, tp, NULL);
+    tp->end_marker = TextMarkerDialog (g1, tp->change_notify, tp->change_userdata);
     tp->also_rem_after = CheckBox (g1, "Also Remove Entered Text", ChangeTextPortionBtn);    
   }
   
@@ -1771,11 +1961,12 @@ NLM_EXTERN Uint2 TwoStepExistingText (Int4 num_found, Boolean non_text, Boolean
   
   ppt = StaticPrompt (h, "Separate new text and old text with", 
                       0, dialogTextHeight, programFont, 'c');
-  etdd.delim_grp = HiddenGroup (h, 0, 4, NULL);
+  etdd.delim_grp = HiddenGroup (h, 0, 5, NULL);
   SetGroupSpacing (etdd.delim_grp, 10, 10);
   RadioButton (etdd.delim_grp, "Semicolon");
   RadioButton (etdd.delim_grp, "Space");
   RadioButton (etdd.delim_grp, "Colon");
+  RadioButton (etdd.delim_grp, "Comma");
   RadioButton (etdd.delim_grp, "Do not separate");
   SetValue (etdd.delim_grp, 1);
   
@@ -1821,6 +2012,9 @@ NLM_EXTERN Uint2 TwoStepExistingText (Int4 num_found, Boolean non_text, Boolean
           existing_text = ExistingTextOption_append_colon;
           break;
         case 4:
+          existing_text = ExistingTextOption_append_comma;
+          break;
+        case 5:
           existing_text = ExistingTextOption_append_none;
           break;
       }
@@ -1839,6 +2033,9 @@ NLM_EXTERN Uint2 TwoStepExistingText (Int4 num_found, Boolean non_text, Boolean
           existing_text = ExistingTextOption_prefix_colon;
           break;
         case 4:
+          existing_text = ExistingTextOption_prefix_comma;
+          break;
+        case 5:
           existing_text = ExistingTextOption_prefix_none;
           break;
       }
@@ -2157,6 +2354,217 @@ NLM_EXTERN DialoG StringConstraintDialog (GrouP h, CharPtr label, Boolean clear_
   return (DialoG) p;
 }
 
+
+static Boolean IsAllDigits (CharPtr str)
+
+{
+  CharPtr cp;
+
+  if (StringHasNoText (str)) return FALSE;
+
+  cp = str;
+  while (*cp != 0 && isdigit (*cp)) {
+    cp++;
+  }
+  if (*cp == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+typedef struct enddistancedialog
+{
+  DIALOG_MESSAGE_BLOCK
+  PopuP dist_type;
+  TexT  dist_val;
+
+  Nlm_ChangeNotifyProc change_notify;
+  Pointer change_userdata; 
+} EndDistanceDialogData, PNTR EndDistanceDialogPtr;
+
+
+static void ChangeEndDistanceDialogPopup (PopuP p)
+{
+  EndDistanceDialogPtr dlg;
+  Int2 val;
+
+  dlg = (EndDistanceDialogPtr) GetObjectExtra (p);
+  if (dlg == NULL) {
+    return;
+  }
+
+  val = GetValue (dlg->dist_type);
+  if (val == 2 || val == 3 || val == 4) {
+    Show (dlg->dist_val);
+  } else {
+    Hide (dlg->dist_val);
+  }
+
+  if (dlg->change_notify != NULL) {
+    (dlg->change_notify) (dlg->change_userdata);
+  }
+}
+
+
+static void ChangeEndDistanceDialogTexT (TexT t)
+{
+  EndDistanceDialogPtr dlg;
+
+  dlg = (EndDistanceDialogPtr) GetObjectExtra (t);
+  if (dlg != NULL && dlg->change_notify != NULL) {
+    (dlg->change_notify) (dlg->change_userdata);
+  }
+}
+
+
+static void EndDistanceToDialog (DialoG d, Pointer data)
+{
+  EndDistanceDialogPtr dlg;
+  ValNodePtr v;
+  Char       buf[15];
+
+  dlg = (EndDistanceDialogPtr) GetObjectExtra (d);
+  if (dlg == NULL) return;
+
+  v = (ValNodePtr) data;
+  if (v == NULL) {
+    SetValue (dlg->dist_type, 1);
+    SetTitle (dlg->dist_val, "");
+    Hide (dlg->dist_val);
+  } else {
+    switch (v->choice) {
+      case LocationPosConstraint_dist_from_end:
+        SetValue (dlg->dist_type, 2);
+        sprintf (buf, "%d", v->data.intvalue);
+        SetTitle (dlg->dist_val, buf);
+        Show (dlg->dist_val);
+        break;
+      case LocationPosConstraint_max_dist_from_end:
+        SetValue (dlg->dist_type, 3);
+        sprintf (buf, "%d", v->data.intvalue);
+        SetTitle (dlg->dist_val, buf);
+        Show (dlg->dist_val);
+        break;
+      case LocationPosConstraint_min_dist_from_end:
+        SetValue (dlg->dist_type, 4);
+        sprintf (buf, "%d", v->data.intvalue);
+        SetTitle (dlg->dist_val, buf);
+        Show (dlg->dist_val);
+        break;
+      default:
+        SetValue (dlg->dist_type, 1);
+        SetTitle (dlg->dist_val, "");
+        Hide (dlg->dist_val);
+        break;
+    }
+  }
+}
+
+
+static Pointer DialogToEndDistance (DialoG d)
+{
+  EndDistanceDialogPtr dlg;
+  Int2       val;
+  ValNodePtr v = NULL;
+  CharPtr    str;
+
+  dlg = (EndDistanceDialogPtr) GetObjectExtra (d);
+  if (dlg == NULL) return NULL;
+
+  val = GetValue (dlg->dist_type);
+  if (val == 2 || val == 3 || val == 4
+      && !TextHasNoText(dlg->dist_val))
+  {
+    str = SaveStringFromText (dlg->dist_val);
+    if (IsAllDigits (str)) {
+      v = ValNodeNew (NULL);
+      switch (val) {
+        case 2:
+          v->choice = LocationPosConstraint_dist_from_end;
+          break;
+        case 3:
+          v->choice = LocationPosConstraint_max_dist_from_end;
+          break;
+        case 4:
+          v->choice = LocationPosConstraint_min_dist_from_end;
+          break;
+      }
+      str = SaveStringFromText (dlg->dist_val);
+      v->data.intvalue = atoi (str);
+    }
+    str = MemFree (str);
+  }
+  return v;
+}
+
+
+static ValNodePtr TestEndDistanceDialog (DialoG d)
+{
+  EndDistanceDialogPtr dlg;
+  Int2       val;
+  CharPtr    str;
+  ValNodePtr err_list = NULL;
+
+  dlg = (EndDistanceDialogPtr) GetObjectExtra (d);
+  if (dlg != NULL) {
+    val = GetValue (dlg->dist_type);
+    if (val == 2 || val == 3 || val == 4) {
+      if (TextHasNoText (dlg->dist_val)) {
+        ValNodeAddPointer (&err_list, 0, "No distance value");
+      } else {
+        str = SaveStringFromText (dlg->dist_val);
+        if (!IsAllDigits (str)) {
+          ValNodeAddPointer (&err_list, 0, "Non-numeric value");
+        }
+      }
+    }
+  }
+
+  return err_list;
+}
+
+
+NLM_EXTERN DialoG EndDistanceDialog (GrouP h, CharPtr title, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+
+{
+  EndDistanceDialogPtr dlg;
+  GrouP                p;
+  
+  dlg = (EndDistanceDialogPtr) MemNew (sizeof (EndDistanceDialogData));
+  if (dlg == NULL)
+  {
+    return NULL;
+  }
+
+  p = HiddenGroup (h, 4, 0, NULL);
+  SetObjectExtra (p, dlg, StdCleanupExtraProc);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = EndDistanceToDialog;
+  dlg->fromdialog = DialogToEndDistance;
+  dlg->testdialog = TestEndDistanceDialog;
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  StaticPrompt (p, "Where end of sequence is ", 0, dialogTextHeight, systemFont, 'l');
+  dlg->dist_type = PopupList (p, TRUE, ChangeEndDistanceDialogPopup);
+  SetObjectExtra (dlg->dist_type, dlg, NULL);
+  PopupItem (dlg->dist_type, "Any distance");
+  PopupItem (dlg->dist_type, "Exactly");
+  PopupItem (dlg->dist_type, "No more than");
+  PopupItem (dlg->dist_type, "No less than");
+  SetValue (dlg->dist_type, 1);
+  dlg->dist_val = DialogText (p, "", 5, ChangeEndDistanceDialogTexT);
+  SetObjectExtra (dlg->dist_val, dlg, NULL);
+  Hide (dlg->dist_val);
+  StaticPrompt (p, title, 0, dialogTextHeight, systemFont, 'l');
+
+  return (DialoG) p;
+}
+
+
 typedef struct locationconstraintdialog 
 {
   DIALOG_MESSAGE_BLOCK
@@ -2164,6 +2572,9 @@ typedef struct locationconstraintdialog
   PopuP  sequence_type;
   PopuP  partial5;
   PopuP  partial3;
+  PopuP  location_type;
+  DialoG dist5;
+  DialoG dist3;
 
   Nlm_ChangeNotifyProc change_notify;
   Pointer change_userdata; 
@@ -2195,6 +2606,9 @@ static void LocationConstraintToDialog (DialoG d, Pointer data)
     SetValue (dlg->sequence_type, 1);
     SetValue (dlg->partial5, 1);
     SetValue (dlg->partial3, 1);
+    SetValue (dlg->location_type, 1);
+    PointerToDialog (dlg->dist5, NULL);
+    PointerToDialog (dlg->dist3, NULL);
   } else {
     switch (l->strand) {
       case Strand_constraint_any:
@@ -2246,6 +2660,22 @@ static void LocationConstraintToDialog (DialoG d, Pointer data)
         SetValue (dlg->partial3, 3);
         break;
     }
+    switch (l->location_type) {
+      case Location_type_constraint_any:
+        SetValue (dlg->location_type, 1);
+        break;
+      case Location_type_constraint_single_interval:
+        SetValue (dlg->location_type, 2);
+        break;
+      case Location_type_constraint_joined:
+        SetValue (dlg->location_type, 3);
+        break;
+      case Location_type_constraint_ordered:
+        SetValue (dlg->location_type, 4);
+        break;
+    }
+    PointerToDialog (dlg->dist5, l->end5);
+    PointerToDialog (dlg->dist3, l->end3);
   }
   ChangeLocationConstraintDialogPopup (dlg->strand);
 }
@@ -2310,6 +2740,22 @@ static Pointer DialogToLocationConstraint (DialoG d)
         l->partial3 = Partial_constraint_complete;
         break;
     }
+    switch (GetValue (dlg->location_type)) {
+      case 1:
+        l->location_type = Location_type_constraint_any;
+        break;
+      case 2:
+        l->location_type = Location_type_constraint_single_interval;
+        break;
+      case 3:
+        l->location_type = Location_type_constraint_joined;
+        break;
+      case 4:
+        l->location_type = Location_type_constraint_ordered;
+        break;
+    }
+    l->end5 = DialogToPointer (dlg->dist5);
+    l->end3 = DialogToPointer (dlg->dist3);
   }
   if (IsLocationConstraintEmpty (l)) {
     l = LocationConstraintFree (l);
@@ -2322,23 +2768,27 @@ static ValNodePtr TestLocationConstraintDialog (DialoG d)
 {
   LocationConstraintDialogPtr dlg;
   ValNodePtr err_list = NULL;
+  LocationConstraintPtr lcp;
 
   dlg = (LocationConstraintDialogPtr) GetObjectExtra (d);
   if (dlg != NULL) {
-    if (GetValue (dlg->sequence_type) == 1 && GetValue (dlg->strand) == 1
-        && GetValue (dlg->partial5) == 1 && GetValue (dlg->partial3) == 1) {
-      ValNodeAddPointer (&err_list, 0, "empty location constraint");
+    lcp = DialogToPointer (d);
+    if (IsLocationConstraintEmpty (lcp)) {
+      ValNodeAddPointer (&err_list, 0, "location constraint empty");
     }
+    lcp = LocationConstraintFree (lcp);
+    ValNodeLink (&err_list, TestDialog (dlg->dist5));
+    ValNodeLink (&err_list, TestDialog (dlg->dist3));
   }
   return err_list;
 }
 
 
-extern DialoG LocationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+NLM_EXTERN DialoG LocationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
 
 {
   LocationConstraintDialogPtr dlg;
-  GrouP                     p;
+  GrouP                     p, g1, g2;
   
   dlg = (LocationConstraintDialogPtr) MemNew (sizeof (LocationConstraintDialogData));
   if (dlg == NULL)
@@ -2346,7 +2796,8 @@ extern DialoG LocationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_not
     return NULL;
   }
 
-  p = HiddenGroup (h, 4, 0, NULL);
+  p = HiddenGroup (h, -1, 0, NULL);
+  SetGroupSpacing (p, 10, 10);
   SetObjectExtra (p, dlg, StdCleanupExtraProc);
 
   dlg->dialog = (DialoG) p;
@@ -2356,38 +2807,56 @@ extern DialoG LocationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_not
   dlg->change_notify = change_notify;
   dlg->change_userdata = change_userdata;
 
-  StaticPrompt (p, "on", 0, dialogTextHeight, systemFont, 'l');
-  dlg->strand = PopupList (p, TRUE, ChangeLocationConstraintDialogPopup);
+  g1 = HiddenGroup (p, 4, 0, NULL);
+  SetGroupSpacing (g1, 10, 10);  
+  StaticPrompt (g1, "on", 0, dialogTextHeight, systemFont, 'l');
+  dlg->strand = PopupList (g1, TRUE, ChangeLocationConstraintDialogPopup);
   SetObjectExtra (dlg->strand, dlg, NULL);
   PopupItem (dlg->strand, "Any strand");
   PopupItem (dlg->strand, "Plus strand");
   PopupItem (dlg->strand, "Minus strand");
   SetValue (dlg->strand, 1);
   
-  StaticPrompt (p, "on", 0, dialogTextHeight, systemFont, 'l');
-  dlg->sequence_type = PopupList (p, TRUE, ChangeLocationConstraintDialogPopup);
+  StaticPrompt (g1, "on", 0, dialogTextHeight, systemFont, 'l');
+  dlg->sequence_type = PopupList (g1, TRUE, ChangeLocationConstraintDialogPopup);
   SetObjectExtra (dlg->sequence_type, dlg, NULL);
   PopupItem (dlg->sequence_type, "nucleotide and protein sequences");
   PopupItem (dlg->sequence_type, "nucleotide sequences only");
   PopupItem (dlg->sequence_type, "protein sequences only");
   SetValue (dlg->sequence_type, 1);
 
-  StaticPrompt (p, "5' end", 0, dialogTextHeight, systemFont, 'l');
-  dlg->partial5 = PopupList (p, TRUE, ChangeLocationConstraintDialogPopup);
+  StaticPrompt (g1, "5' end", 0, dialogTextHeight, systemFont, 'l');
+  dlg->partial5 = PopupList (g1, TRUE, ChangeLocationConstraintDialogPopup);
   SetObjectExtra (dlg->partial5, dlg, NULL);
   PopupItem (dlg->partial5, "Partial or Complete");
   PopupItem (dlg->partial5, "Partial");
   PopupItem (dlg->partial5, "Complete");
   SetValue (dlg->partial5, 1);
 
-  StaticPrompt (p, "3' end", 0, dialogTextHeight, systemFont, 'l');
-  dlg->partial3 = PopupList (p, TRUE, ChangeLocationConstraintDialogPopup);
+  StaticPrompt (g1, "3' end", 0, dialogTextHeight, systemFont, 'l');
+  dlg->partial3 = PopupList (g1, TRUE, ChangeLocationConstraintDialogPopup);
   SetObjectExtra (dlg->partial3, dlg, NULL);
   PopupItem (dlg->partial3, "Partial or Complete");
   PopupItem (dlg->partial3, "Partial");
   PopupItem (dlg->partial3, "Complete");
   SetValue (dlg->partial3, 1);
 
+  StaticPrompt (g1, "location type", 0, dialogTextHeight, systemFont, 'l');
+  dlg->location_type = PopupList (g1, TRUE, ChangeLocationConstraintDialogPopup);
+  SetObjectExtra (dlg->location_type, dlg, NULL);
+  PopupItem (dlg->location_type, "Any");
+  PopupItem (dlg->location_type, "Single Interval");
+  PopupItem (dlg->location_type, "Joined");
+  PopupItem (dlg->location_type, "Ordered");
+  SetValue (dlg->location_type, 1);
+
+  g2 = HiddenGroup (p, 0, 2, NULL);
+  SetGroupSpacing (g2, 10, 10);
+  dlg->dist5 = EndDistanceDialog (g2, "from 5' end of feature", dlg->change_notify, dlg->change_userdata);
+  dlg->dist3 = EndDistanceDialog (g2, "from 3' end of feature", dlg->change_notify, dlg->change_userdata);
+  
+  AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) g2, NULL);
+
   return (DialoG) p;
 }
 
@@ -4178,10 +4647,10 @@ static DialoG MolInfoBlockListDialog (GrouP h, CharPtr any_name, Nlm_ChangeNotif
     vnp->next = val_list;
     val_list = vnp;
   }
-  dlg->technique = ValNodeSelectionDialog (p, val_list, SHORT_SELECTION_LIST, ValNodeStringName,
+  dlg->technique = ValNodeSelectionDialogExEx (p, val_list, SHORT_SELECTION_LIST, ValNodeStringName,
                                            ValNodeSimpleDataFree, ValNodeStringCopy,
                                            ValNodeChoiceMatch, "location", 
-                                           change_notify, change_userdata, FALSE);
+                                           change_notify, change_userdata, FALSE, FALSE, TRUE, NULL);
 
   /* completedness */
   StaticPrompt (p, molinfo_block_labels[2], wid, popupMenuHeight, programFont, 'l');
@@ -4301,7 +4770,6 @@ static Pointer MolInfoBlockFromDialog (DialoG d)
   return (Pointer) mib;
 }
   
-static void ChangeComplexConstraintFieldType (DialoG d, Uint2 qual_type, ValNodePtr rna_type, Int2 feat_type);
 
 NLM_EXTERN DialoG MolInfoBlockDialog (GrouP h, Boolean edit, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
 {
@@ -4353,12 +4821,17 @@ static DialoG PubFieldDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Point
 }
 
 
+
+
 typedef struct PublicationConstraintdlg {
   DIALOG_MESSAGE_BLOCK
   PopuP pub_type;
   DialoG field_type;
   DialoG string_constraint;
 
+  DialoG special_field;
+  PopuP  special_field_type;
+
   Nlm_ChangeNotifyProc change_notify;
   Pointer change_userdata;
 } PublicationConstraintDialogData, PNTR PublicationConstraintDialogPtr;
@@ -4419,6 +4892,29 @@ static Pointer DialogToPublicationConstraint (DialoG d)
   }
   vnp = ValNodeFree (vnp);
   string_constraint = StringConstraintFree (string_constraint);
+
+  vnp = DialogToPointer (dlg->special_field);
+  if (vnp != NULL) {
+    val = GetValue (dlg->special_field_type);
+    if (val > 1 && val <= k_NumSpecialPubFieldWords + 1) {
+      constraint->special_field = PubFieldSpecialConstraintNew ();
+      constraint->special_field->field = vnp->choice;
+      constraint->special_field->constraint = ValNodeNew (NULL);
+      switch (val) {
+        case 2:
+          constraint->special_field->constraint->choice = PubFieldSpecialConstraintType_is_present;
+          break;
+        case 3:
+          constraint->special_field->constraint->choice = PubFieldSpecialConstraintType_is_not_present;
+          break;
+        case 4:
+          constraint->special_field->constraint->choice = PubFieldSpecialConstraintType_is_all_caps;
+          break;
+      }
+    }
+    vnp = ValNodeFree (vnp);
+  }
+
   return (Pointer) constraint;
 }
 
@@ -4437,6 +4933,8 @@ static void PublicationConstraintToDialog (DialoG d, Pointer data)
     SetValue (dlg->pub_type, 1);
     PointerToDialog (dlg->field_type, NULL);
     PointerToDialog (dlg->string_constraint, NULL);
+    PointerToDialog (dlg->special_field, NULL);
+    SetValue (dlg->special_field_type, 1);
   } else {
     switch (constraint->type) {
       case Pub_type_published:
@@ -4466,6 +4964,33 @@ static void PublicationConstraintToDialog (DialoG d, Pointer data)
       PointerToDialog (dlg->field_type, &vn);
       PointerToDialog (dlg->string_constraint, constraint->field->constraint);
     }
+    if (constraint->special_field == NULL) {
+      PointerToDialog (dlg->special_field, NULL);
+      SetValue (dlg->special_field_type, 1);
+    } else {
+      vn.choice = constraint->special_field->field;
+      vn.data.ptrvalue = NULL;
+      vn.next = NULL;
+      PointerToDialog (dlg->special_field, &vn);
+      if (constraint->special_field->constraint == NULL) {
+        SetValue (dlg->special_field_type, 1);
+      } else {
+        switch (constraint->special_field->constraint->choice) {
+          case PubFieldSpecialConstraintType_is_present:
+            SetValue (dlg->special_field_type, 2);
+            break;
+          case PubFieldSpecialConstraintType_is_not_present:
+            SetValue (dlg->special_field_type, 3);
+            break;
+          case PubFieldSpecialConstraintType_is_all_caps:
+            SetValue (dlg->special_field_type, 4);
+            break;
+          default:
+            SetValue (dlg->special_field_type, 1);
+            break;
+        }
+      }
+    }
   } 
 }
 
@@ -4483,7 +5008,7 @@ static ValNodePtr TestPublicationConstraintDialog (DialoG d)
 }
 
 
-static void ChangePublicationConstraintPubType (PopuP p)
+static void ChangePublicationConstraintPopup (PopuP p)
 {
   PublicationConstraintDialogPtr dlg;
 
@@ -4498,6 +5023,7 @@ static DialoG PublicationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_
 {
   PublicationConstraintDialogPtr dlg;
   GrouP                  p, g1, g2;
+  Int4       i;
   
   dlg = (PublicationConstraintDialogPtr) MemNew (sizeof (PublicationConstraintDialogData));
   if (dlg == NULL)
@@ -4518,7 +5044,7 @@ static DialoG PublicationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_
 
   g1 = HiddenGroup (p, 2, 0, NULL);
   StaticPrompt (g1, "Publication Status", 0, dialogTextHeight, programFont, 'r');
-  dlg->pub_type = PopupList (g1, TRUE, ChangePublicationConstraintPubType);
+  dlg->pub_type = PopupList (g1, TRUE, ChangePublicationConstraintPopup);
   SetObjectExtra (dlg->pub_type, dlg, NULL);
   PopupItem (dlg->pub_type, "Any");
   PopupItem (dlg->pub_type, "Published");
@@ -4531,12 +5057,210 @@ static DialoG PublicationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_
   dlg->field_type = PubFieldDialog (g2, change_notify, change_userdata);
   dlg->string_constraint = StringConstraintDialog (g2, NULL, FALSE, change_notify, change_userdata);
 
+  dlg->special_field = PubFieldDialog (g2, change_notify, change_userdata);
+  dlg->special_field_type = PopupList (g2, TRUE, ChangePublicationConstraintPopup);
+  SetObjectExtra (dlg->special_field_type, dlg, NULL);
+  PopupItem (dlg->special_field_type, "Any");
+  for (i = 0; i < k_NumSpecialPubFieldWords; i++) {
+    PopupItem (dlg->special_field_type, s_SpecialPubFieldWords[i]);
+  }
+  SetValue (dlg->special_field_type, 1);
+
   AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) g2, NULL);
 
   return (DialoG) p;
 }
 
 
+
+typedef struct quantityconstraintdlg {
+  DIALOG_MESSAGE_BLOCK
+  PopuP quantity_type;
+  TexT  quantity;
+
+  Nlm_ChangeNotifyProc change_notify;
+  Pointer change_userdata;
+} QuantityConstraintDlgDaga, PNTR QuantityConstraintDlgPtr;
+
+
+static void QuantityConstraintToDialog (DialoG d, Pointer data)
+{
+  QuantityConstraintDlgPtr dlg;
+  ValNodePtr               vnp;
+  Char                     buf[15];
+
+  dlg = (QuantityConstraintDlgPtr) GetObjectExtra (d);
+
+  if (dlg == NULL) {
+    return;
+  }
+
+  vnp = (ValNodePtr) data;
+  if (vnp == NULL) {
+    SetValue (dlg->quantity_type, 1);
+    Hide (dlg->quantity);
+  } else if (vnp->choice == QuantityConstraint_equals) {
+    SetValue (dlg->quantity_type, 2);
+    sprintf (buf, "%d", vnp->data.intvalue);
+    SetTitle (dlg->quantity, buf);
+    Show (dlg->quantity);
+  } else if (vnp->choice == QuantityConstraint_greater_than) {
+    SetValue (dlg->quantity_type, 3);
+    sprintf (buf, "%d", vnp->data.intvalue);
+    SetTitle (dlg->quantity, buf);
+    Show (dlg->quantity);
+  } else if (vnp->choice == QuantityConstraint_less_than) {
+    SetValue (dlg->quantity_type, 4);
+    sprintf (buf, "%d", vnp->data.intvalue);
+    SetTitle (dlg->quantity, buf);
+    Show (dlg->quantity);
+  } else {
+    SetValue (dlg->quantity_type, 1);
+    Hide (dlg->quantity);
+  }
+}
+
+
+static Pointer DialogToQuantityConstraint (DialoG d)
+{
+  QuantityConstraintDlgPtr dlg;
+  ValNodePtr               vnp = NULL;
+  Int2                     val;
+  CharPtr                  num_text;
+
+  dlg = (QuantityConstraintDlgPtr) GetObjectExtra (d);
+
+  if (dlg == NULL) {
+    return NULL;
+  }
+
+  if (!TextHasNoText (dlg->quantity)) {
+    num_text = SaveStringFromText (dlg->quantity);
+    if (IsAllDigits(num_text)) {
+      val = GetValue (dlg->quantity_type);
+      switch (val) {
+        case 2:
+          vnp = ValNodeNew (NULL);
+          vnp->choice = QuantityConstraint_equals;
+          vnp->data.intvalue = atoi (num_text);
+          break;
+        case 3:
+          vnp = ValNodeNew (NULL);
+          vnp->choice = QuantityConstraint_greater_than;
+          vnp->data.intvalue = atoi (num_text);
+          break;
+        case 4:
+          vnp = ValNodeNew (NULL);
+          vnp->choice = QuantityConstraint_less_than;
+          vnp->data.intvalue = atoi (num_text);
+          break;
+      }
+    }
+    num_text = MemFree (num_text);
+  }
+  return vnp;
+}
+
+
+static ValNodePtr TestQuantityConstraintDialog (DialoG d)
+{
+  QuantityConstraintDlgPtr dlg;
+  Int2                     val;
+  CharPtr                  num_text;
+  ValNodePtr err_list = NULL;
+
+  dlg = (QuantityConstraintDlgPtr) GetObjectExtra (d);
+  if (dlg != NULL) {
+    val = GetValue (dlg->quantity_type);
+    if (val > 1 && val <= k_NumQuantityWords + 1) {
+      if (TextHasNoText (dlg->quantity)) {
+        ValNodeAddPointer (&err_list, 0, "missing value");
+      } else {
+        num_text = SaveStringFromText (dlg->quantity);
+        if (!IsAllDigits (num_text)) {
+          ValNodeAddPointer (&err_list, 0, "bad value");
+        }
+        num_text = MemFree (num_text);
+      }
+    }
+  }
+  return err_list;
+}
+
+
+static void ChangeQuantityConstraintQuantityType (PopuP p)
+{
+  QuantityConstraintDlgPtr dlg;
+  Int2 val;
+
+  dlg = (QuantityConstraintDlgPtr) GetObjectExtra (p);
+  if (dlg == NULL) {
+    return;
+  }
+  val = GetValue (dlg->quantity_type);
+
+  if (val < 2 || val > k_NumQuantityWords + 1) {
+    Hide (dlg->quantity);
+  } else {
+    Show (dlg->quantity);
+  }
+  if (dlg->change_notify != NULL) {
+    (dlg->change_notify)(dlg->change_userdata);
+  }
+}
+
+
+static void ChangeQuantityConstraintQuantity (TexT t)
+{
+  QuantityConstraintDlgPtr dlg;
+
+  dlg = (QuantityConstraintDlgPtr) GetObjectExtra (t);
+  if (dlg != NULL && dlg->change_notify != NULL) {
+    (dlg->change_notify)(dlg->change_userdata);
+  }
+}
+
+
+static DialoG QuantityConstraintDialog (GrouP h, CharPtr title, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+{
+  QuantityConstraintDlgPtr dlg;
+  GrouP                    p;
+  Int4                     i;
+  
+  dlg = (QuantityConstraintDlgPtr) MemNew (sizeof (QuantityConstraintDlgDaga));
+  if (dlg == NULL)
+  {
+    return NULL;
+  }
+
+  p = HiddenGroup (h, 3, 0, NULL);
+  SetGroupSpacing (p, 10, 10);
+  SetObjectExtra (p, dlg, StdCleanupExtraProc);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = QuantityConstraintToDialog;
+  dlg->fromdialog = DialogToQuantityConstraint;
+  dlg->testdialog = TestQuantityConstraintDialog;
+
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  StaticPrompt (p, title, 0, dialogTextHeight, programFont, 'r');
+  dlg->quantity_type = PopupList (p, TRUE, ChangeQuantityConstraintQuantityType);
+  SetObjectExtra (dlg->quantity_type, dlg, NULL);
+  PopupItem (dlg->quantity_type, "Any");
+  for (i = 0; i < k_NumQuantityWords; i++) {
+    PopupItem (dlg->quantity_type, s_QuantityWords[i]);
+  }
+  SetValue (dlg->quantity_type, 1);
+  dlg->quantity = DialogText (p, "1", 5, ChangeQuantityConstraintQuantity);
+  SetObjectExtra (dlg->quantity, dlg, NULL);
+  Hide (dlg->quantity);
+
+  return (DialoG) p;
+}
+
+
 typedef struct sequenceconstraintdlg {
   DIALOG_MESSAGE_BLOCK
   GrouP seqtype;
@@ -4544,6 +5268,7 @@ typedef struct sequenceconstraintdlg {
   DialoG rna_subtype;
   ButtoN feat_present;
   DialoG feature_type;
+  DialoG num_features;
   DialoG id;
 
   Nlm_ChangeNotifyProc change_notify;
@@ -4605,6 +5330,7 @@ static void SequenceConstraintToDialog (DialoG d, Pointer data)
     SetStatus (dlg->feat_present, FALSE);
     PointerToDialog (dlg->feature_type, NULL);
     PointerToDialog (dlg->id, NULL);
+    PointerToDialog (dlg->num_features, NULL);
   } else {
     if (constraint->seqtype == NULL) {
       SetValue (dlg->seqtype, 2);
@@ -4655,6 +5381,7 @@ static void SequenceConstraintToDialog (DialoG d, Pointer data)
     }
 
     PointerToDialog (dlg->id, constraint->id);
+    PointerToDialog (dlg->num_features, constraint->num_features);
   }
   ChangeSequenceConstraintButton (dlg->feat_present);
 }
@@ -4716,6 +5443,7 @@ static Pointer SequenceConstraintFromDialog (DialoG d)
   if (IsStringConstraintEmpty (constraint->id)) {
     constraint->id = StringConstraintFree (constraint->id);
   }
+  constraint->num_features = DialogToPointer (dlg->num_features);
   return constraint;
 }
 
@@ -4757,6 +5485,7 @@ static ValNodePtr TestSequenceConstraintDialog (DialoG d)
     if (IsSequenceConstraintEmpty (constraint)) {
       ValNodeAddPointer (&err_list, 0, "empty constraint");
     }
+    ValNodeLink (&err_list, TestDialog (dlg->num_features));
     constraint = SequenceConstraintFree (constraint);
   }
   return err_list;
@@ -4803,9 +5532,16 @@ static DialoG SequenceConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_not
   SetObjectExtra (dlg->feat_present, dlg, NULL);
   dlg->feature_type = FeatureTypeDialog (g, change_notify, change_userdata);
 
+  dlg->num_features = QuantityConstraintDialog (g, "Number of features present (any type)", change_notify, change_userdata);
+
   dlg->id = StringConstraintDialog (p, "Where sequence ID", FALSE, change_notify, change_userdata);
 
-  AlignObjects (ALIGN_CENTER, (HANDLE) dlg->seqtype, (HANDLE) dlg->rna_subtype_grp, (HANDLE) dlg->id, (HANDLE) g, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) dlg->seqtype, 
+                              (HANDLE) dlg->rna_subtype_grp, 
+                              (HANDLE) dlg->num_features,
+                              (HANDLE) dlg->id, 
+                              (HANDLE) g, 
+                               NULL);
   return (DialoG) p;
 }
 
@@ -5177,8 +5913,6 @@ static Boolean EditConstraint (ValNodePtr constraint)
 }
 
 
-static CharPtr SummarizeConstraint (ValNodePtr constraint);
-
 typedef struct constraintsetdlg {
   DIALOG_MESSAGE_BLOCK
   DoC                  constraint_doc;
@@ -5481,7 +6215,7 @@ static void AddConstraintBtn (ButtoN b)
 }
 
 
-static DialoG ConstraintSetDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+NLM_EXTERN DialoG ConstraintSetDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
 {
   ConstraintSetDlgPtr dlg;
   GrouP               p, g;
@@ -6620,7 +7354,7 @@ static ValNodePtr DefaultFeatureFieldConstraint (Int2 feat_type)
 }
 
 
-static void ChangeComplexConstraintFieldType (DialoG d, Uint2 qual_type, ValNodePtr rna_type, Int2 feat_type)
+NLM_EXTERN void ChangeComplexConstraintFieldType (DialoG d, Uint2 qual_type, ValNodePtr rna_type, Int2 feat_type)
 {
   ComplexConstraintDlgPtr dlg;
   ValNodePtr              default_constraint;
@@ -7453,10 +8187,10 @@ static void ChangeStructureCommentFieldChoice (PopuP p)
 
   val = GetValue (dlg->field_type);
   switch (val) {
-    case 1:
+    case 2:
       Hide (dlg->field_name);
       break;
-    case 2:
+    case 1:
       Show (dlg->field_name);
       break;
     case 3:
@@ -7486,10 +8220,10 @@ static void StructuredCommentFieldToDialog (DialoG d, Pointer data)
   } else {
     switch (field->choice) {
       case StructuredCommentField_database:
-        SetValue (dlg->field_type, 1);
+        SetValue (dlg->field_type, 2);
         break;
       case StructuredCommentField_named:
-        SetValue (dlg->field_type, 2);
+        SetValue (dlg->field_type, 1);
         SetTitle (dlg->field_name, field->data.ptrvalue);
         break;
       case StructuredCommentField_field_name:
@@ -7517,10 +8251,10 @@ static Pointer StructuredCommentFieldFromDialog (DialoG d)
   val = GetValue (dlg->field_type);
 
   switch (val) {
-    case 1:
+    case 2:
       field->choice = StructuredCommentField_database;
       break;
-    case 2:
+    case 1:
       field->choice = StructuredCommentField_named;
       field->data.ptrvalue = SaveStringFromText (dlg->field_name);
       if (StringHasNoText (field->data.ptrvalue)) {
@@ -7590,8 +8324,8 @@ static DialoG StructuredCommentFieldDialog (GrouP h, Nlm_ChangeNotifyProc change
 
   dlg->field_type = PopupList (p, TRUE, ChangeStructureCommentFieldChoice);
   SetObjectExtra (dlg->field_type, dlg, NULL);
-  PopupItem (dlg->field_type, "Database Name");
   PopupItem (dlg->field_type, "Field");
+  PopupItem (dlg->field_type, "Database Name");
   PopupItem (dlg->field_type, "Field Name");
   SetValue (dlg->field_type, 1);
 
@@ -8330,43 +9064,6 @@ static DialoG FieldPairTypeDialog (GrouP h, Boolean for_convert, Nlm_ChangeNotif
 }
 
 
-static Boolean IsFieldTypeNonText (ValNodePtr field_type)
-{
-  ValNodePtr      vnp;
-  FeatureFieldPtr ffp;
-  Boolean         rval = FALSE;
-
-  if (field_type == NULL) {
-    return FALSE;
-  } 
-  switch (field_type->choice) {
-    case FieldType_source_qual :
-      vnp = (ValNodePtr) field_type->data.ptrvalue;
-      if (vnp != NULL) {
-        if (vnp->choice == SourceQualChoice_location || vnp->choice == SourceQualChoice_origin) {
-          rval = TRUE;
-        } else if (vnp->choice == SourceQualChoice_textqual) {
-          if (IsNonTextSourceQual (vnp->data.intvalue)) {
-            rval = TRUE;
-          }
-        }
-      }
-      break;
-    case FieldType_feature_field :
-      ffp = (FeatureFieldPtr) field_type->data.ptrvalue;
-      if (ffp != NULL && ffp->field != NULL && ffp->field->choice == FeatQualChoice_legal_qual
-          && ffp->field->data.intvalue == Feat_qual_legal_pseudo) {
-        rval = TRUE;
-      }
-      break;
-    case FieldType_molinfo_field :
-      rval = TRUE;
-      break;
-  } 
-  return rval;
-}
-
-
 #define AECR_DLG_BLOCK       \
   DIALOG_MESSAGE_BLOCK \
   DialoG qual_type_dlg; \
@@ -8521,7 +9218,6 @@ typedef struct applyactiondlg {
 static Pointer DialogToApplyAction (DialoG d)
 {
   ApplyActionDlgPtr dlg;
-  Uint1              qual_type = FieldType_source_qual;
   ApplyActionPtr     apply;
 
   dlg = (ApplyActionDlgPtr) GetObjectExtra (d);
@@ -8848,6 +9544,7 @@ typedef struct convertactiondlg {
 
   ButtoN strip_name;
   ButtoN keep_original;
+  DialoG capitalization;
   DialoG existing_text;
 
 } ConvertActionDlgData, PNTR ConvertActionDlgPtr;
@@ -8866,11 +9563,13 @@ static void PointerToConvertActionDlg (DialoG d, Pointer data)
     FieldPairToAECRActionDlg (d, NULL);
     SetStatus (dlg->strip_name, FALSE);
     SetStatus (dlg->keep_original, FALSE);
+    PointerToDialog (dlg->capitalization, NULL);
     PointerToDialog (dlg->existing_text, NULL);
   } else {    
     FieldPairToAECRActionDlg (d, convert->fields);
     SetStatus (dlg->strip_name, convert->strip_name);
     SetStatus (dlg->keep_original, convert->keep_original);
+    PointerToDialog (dlg->capitalization, (Pointer) convert->capitalization);
     PointerToDialog (dlg->existing_text, (Pointer) convert->existing_text);
   }
 }
@@ -8888,6 +9587,7 @@ static Pointer DialogToConvertAction (DialoG d)
   convert->fields = DialogToPointer (dlg->field_dlg);
   convert->strip_name = GetStatus (dlg->strip_name);
   convert->keep_original = GetStatus (dlg->keep_original);
+  convert->capitalization = (Uint2) DialogToPointer (dlg->capitalization);
   convert->existing_text = (Uint2) DialogToPointer (dlg->existing_text);
   return convert;
 }
@@ -8912,6 +9612,7 @@ static ValNodePtr TestConvertActionDialog (DialoG d)
   }
 
   ValNodeLink (&err_list, TestDialog (dlg->field_dlg));
+  ValNodeLink (&err_list, TestDialog (dlg->capitalization));
   ValNodeLink (&err_list, TestDialog (dlg->existing_text));
 
   field_pair = DialogToPointer (dlg->field_dlg);
@@ -8960,13 +9661,15 @@ ConvertActionDialog
   dlg->keep_original = CheckBox (g, "Leave on original", NULL);
   dlg->strip_name = CheckBox (g, "Strip name from text", NULL);
 
+  dlg->capitalization = CapChangeDialog(p, change_notify, change_userdata);
+
   if (show_existing_text) {
     dlg->existing_text = ExistingTextDialog (p, change_notify, change_userdata);
   } else {
     dlg->existing_text = NULL;
   }
 
-  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) dlg->existing_text, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) dlg->capitalization, (HANDLE) dlg->existing_text, NULL);
   
   return (DialoG) p;
 }
@@ -9810,20 +10513,112 @@ EditAECRActionDialog
 }
 
 
-typedef struct applyfeatureactiondlg {
+static SeqFeatPtr CreateFeatureWithImportFeatureQuals (Uint1 featdef_type, ValNodePtr fields)
+{
+  SeqFeatPtr sfp;
+  ValNodePtr vnp;
+  FeatQualLegalValPtr q;
+  GBQualPtr gbq;
+  CharPtr   qualname, cp;
+
+  sfp = SeqFeatNew();
+  sfp->idx.subtype = featdef_type;
+  sfp->data.choice = FindFeatFromFeatDefType (sfp->idx.subtype);
+
+  for (vnp = fields; vnp != NULL; vnp = vnp->next) {
+    q = (FeatQualLegalValPtr) vnp->data.ptrvalue;
+    if (q != NULL && q->qual != Feat_qual_legal_gene && q->qual != Feat_qual_legal_gene_description && q->qual != Feat_qual_legal_note) {
+      gbq = GBQualNew ();
+      qualname = StringSave (GetFeatQualName(q->qual));
+      cp = StringChr (qualname, '-');
+      while (cp != NULL) {
+        *cp = '_';
+        cp = StringChr (cp + 1, '-');
+      }
+      gbq->qual = qualname;
+      gbq->val = StringSave (q->val);
+      gbq->next = sfp->qual;
+      sfp->qual = gbq;
+    }
+  }
+  return sfp;  
+}
+
+
+static CharPtr FindFeatQualValue (ValNodePtr vnp, Int4 featqual)
+{
+  FeatQualLegalValPtr q;
+  CharPtr str = NULL;
+  while (vnp != NULL && str == NULL) {
+    q = (FeatQualLegalValPtr) vnp->data.ptrvalue;
+    if (q != NULL && q->qual == featqual) {
+      str = q->val;
+    }
+    vnp = vnp->next;
+  }
+  if (str == NULL) {
+    str = "";
+  }
+  return str;
+}
+
+
+static void SetFeatQualValue (ValNodePtr PNTR fields, Int4 featqual, CharPtr val)
+{
+  FeatQualLegalValPtr q;
+
+  q = FeatQualLegalValNew ();
+  q->qual = featqual;
+  q->val = StringSave (val);
+  ValNodeAddPointer (fields, 1, q);
+}
+
+
+static void AddGBQualsToActionFields (GBQualPtr gbq, ValNodePtr PNTR fields)
+{
+  Int4 qualtype;
+
+  if (fields == NULL) return;
+
+  while (gbq != NULL) {
+    qualtype = GetFeatQualByName (gbq->qual);
+    if (qualtype > -1) {
+      SetFeatQualValue (fields, qualtype, gbq->val);
+    }
+    gbq = gbq->next;
+  }
+}
+
+
+NLM_EXTERN ApplyFeatureDetailsPtr ApplyFeatureDetailsNew (ApplyFeatureActionPtr action)
+{
+  ApplyFeatureDetailsPtr details;
+
+  details = (ApplyFeatureDetailsPtr) MemNew (sizeof (ApplyFeatureDetailsData));
+
+  if (action != NULL) {
+    details->add_mrna = action->add_mrna;
+    details->fields = AsnIoMemCopy (action->fields, (AsnReadFunc) FeatQualLegalSetAsnRead, (AsnWriteFunc) FeatQualLegalSetAsnWrite);
+    details->src_fields = AsnIoMemCopy(action->src_fields, (AsnReadFunc) SourceQualValSetAsnRead, (AsnWriteFunc) SourceQualValSetAsnWrite);
+  }
+  return details;
+}
+
+
+NLM_EXTERN ApplyFeatureDetailsPtr ApplyFeatureDetailsFree (ApplyFeatureDetailsPtr details) 
+{
+  if (details != NULL) {
+    details->fields = FeatQualLegalSetFree (details->fields);
+    details->src_fields = SourceQualValSetFree (details->src_fields);
+    details = MemFree (details);
+  }
+  return details;
+}
+
+
+typedef struct applyfeaturedetailsdlg {
   DIALOG_MESSAGE_BLOCK
-  DialoG                   feature_type_dlg;
-  ButtoN                   apply_to_parts;
-  TexT                     only_this_part;
-  ButtoN                   partial5;
-  ButtoN                   partial3;
-  GrouP                    strand_group;
-  GrouP                    use_whole_interval;
-  TexT                     left_end;
-  TexT                     right_end;
-  GrouP                    all_or_some_group;
-  TexT                     accession_list_txt;
-  ButtoN                   add_redundant;
+
   /* for CDS */
   ButtoN                   add_mrna;
   PopuP                    reading_frame;
@@ -9845,6 +10640,351 @@ typedef struct applyfeatureactiondlg {
   TexT                     gene_description;
   TexT                     comment;
 
+  Uint2                    featdef_type;
+  Nlm_ChangeNotifyProc     change_notify;
+  Pointer                  change_userdata;
+} ApplyFeatureDetailsDlgData, PNTR ApplyFeatureDetailsDlgPtr;
+
+
+static void ApplyFeatureDetailsToDialog (DialoG d, Pointer data)
+{
+  ApplyFeatureDetailsDlgPtr dlg;
+  ApplyFeatureDetailsPtr    details;
+  CharPtr                   txt;
+  BioSourcePtr              biop;
+
+  dlg = (ApplyFeatureDetailsDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return;
+  }
+  details = (ApplyFeatureDetailsPtr) data;
+
+  if (data == NULL) {
+    /* for CDS */
+    SafeSetStatus (dlg->add_mrna, FALSE);
+    SafeSetValue (dlg->reading_frame, 4);
+    SafeSetTitle (dlg->protein_name, "");
+    SafeSetTitle (dlg->protein_description, "");
+
+    /* for RNA */
+    PointerToDialog (dlg->ncrna_class, NULL);
+    SafeSetTitle (dlg->rna_name, "");
+
+    /* for import features */
+    PointerToDialog (dlg->quals, NULL);
+
+    /* for source features */
+    PointerToDialog (dlg->src_quals, NULL);
+  
+    /* for all */
+    SafeSetTitle (dlg->gene_locus, "");
+    SafeSetTitle (dlg->gene_description, "");
+    SafeSetTitle (dlg->comment, "");
+  } else {
+    /* for CDS */
+    SafeSetStatus (dlg->add_mrna, details->add_mrna);
+    txt = FindFeatQualValue (details->fields, Feat_qual_legal_codon_start);
+    if (StringICmp (txt, "best") == 0) {
+      SafeSetValue (dlg->reading_frame, 4);
+    } else {
+      SafeSetValue (dlg->reading_frame, atoi (txt));
+    }
+
+    SafeSetTitle (dlg->protein_name, FindFeatQualValue (details->fields, Feat_qual_legal_product));
+    SafeSetTitle (dlg->protein_description, FindFeatQualValue (details->fields, Feat_qual_legal_description));
+
+    /* for source feature */
+    biop = BioSourceFromSourceQualVals (details->src_fields);
+    PointerToDialog (dlg->src_quals, biop);
+    biop = BioSourceFree (biop);
+
+    /* for RNA */
+    PointerToDialog (dlg->ncrna_class, FindFeatQualValue (details->fields, Feat_qual_legal_ncRNA_class));
+    SafeSetTitle (dlg->rna_name, FindFeatQualValue (details->fields, Feat_qual_legal_product));
+  
+    /* for all */
+    SafeSetTitle (dlg->gene_locus, FindFeatQualValue (details->fields, Feat_qual_legal_gene));
+    SafeSetTitle (dlg->gene_description, FindFeatQualValue (details->fields, Feat_qual_legal_gene_description));
+    SafeSetTitle (dlg->comment, FindFeatQualValue (details->fields, Feat_qual_legal_note));
+  }
+
+  if (dlg->change_notify != NULL) {
+    (dlg->change_notify) (dlg->change_userdata);
+  }
+}
+
+static Pointer DialogToApplyFeatureDetails (DialoG d)
+{
+  ApplyFeatureDetailsDlgPtr dlg;
+  ApplyFeatureDetailsPtr    details;
+  CharPtr                  txt;
+  Char                     num[15];
+  Int4                     frame;
+  GBQualPtr                gbq;
+  BioSourcePtr             biop;
+
+  dlg = (ApplyFeatureDetailsDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return NULL;
+  }
+
+  details = ApplyFeatureDetailsNew (NULL);
+
+  /* for CDS */
+  if (dlg->add_mrna != NULL && GetStatus (dlg->add_mrna)) {
+    details->add_mrna = TRUE;
+  } else {
+    details->add_mrna = FALSE;
+  }
+
+  if (dlg->reading_frame != NULL) {
+    frame = GetValue (dlg->reading_frame);
+    if (frame > 0 && frame < 4) {
+      sprintf (num, "%d", frame);
+      SetFeatQualValue (&(details->fields), Feat_qual_legal_codon_start, num);
+    } else {
+      SetFeatQualValue (&(details->fields), Feat_qual_legal_codon_start, "best");
+    }
+  }
+
+  if (dlg->protein_name != NULL && !TextHasNoText (dlg->protein_name)) {
+    txt = SaveStringFromText (dlg->protein_name);
+    SetFeatQualValue (&(details->fields), Feat_qual_legal_product, txt);
+    txt = MemFree (txt);
+  }
+  if (dlg->protein_name != NULL && !TextHasNoText (dlg->protein_description)) {
+    txt = SaveStringFromText (dlg->protein_description);
+    SetFeatQualValue (&(details->fields), Feat_qual_legal_description, txt);
+    txt = MemFree (txt);
+  }
+
+  /* for RNA */
+  if (dlg->ncrna_class != NULL) {
+    txt = DialogToPointer (dlg->ncrna_class);
+    if (!StringHasNoText (txt)) {
+      SetFeatQualValue (&(details->fields), Feat_qual_legal_ncRNA_class, txt);
+    }
+    txt = MemFree (txt);
+  }
+  if (dlg->rna_name != NULL && !TextHasNoText (dlg->rna_name)) {
+    txt = SaveStringFromText (dlg->rna_name);
+    SetFeatQualValue (&(details->fields), Feat_qual_legal_product, txt);
+    txt = MemFree (txt);
+  }
+
+  /* for source features */
+  if (dlg->src_quals != NULL) {
+    biop = DialogToPointer (dlg->src_quals);
+    details->src_fields = SourceQualValsFromBioSourcePtr (biop);
+    biop = BioSourceFree (biop);
+  }
+
+  /* for import features */
+  if (dlg->quals != NULL) {
+    gbq = DialogToPointer (dlg->quals);
+    AddGBQualsToActionFields (gbq, &(details->fields));
+    gbq = GBQualFree (gbq);
+  }
+  
+  /* for all */
+  if (dlg->gene_locus != NULL && !TextHasNoText (dlg->gene_locus)) {
+    txt = SaveStringFromText (dlg->gene_locus);
+    SetFeatQualValue (&(details->fields), Feat_qual_legal_gene, txt);
+    txt = MemFree (txt);
+  }
+  if (dlg->gene_description != NULL && !TextHasNoText (dlg->gene_description)) {
+    txt = SaveStringFromText (dlg->gene_description);
+    SetFeatQualValue (&(details->fields), Feat_qual_legal_gene_description, txt);
+    txt = MemFree (txt);
+  }
+  if (dlg->comment != NULL && !TextHasNoText (dlg->comment)) {
+    txt = SaveStringFromText (dlg->comment);
+    SetFeatQualValue (&(details->fields), Feat_qual_legal_note, txt);
+    txt = MemFree (txt);
+  }
+
+  return (Pointer) details;
+}
+
+static void AddTextToComment (ButtoN b, CharPtr text)
+{
+  ApplyFeatureDetailsDlgPtr dlg;
+  CharPtr                  orig_comment;
+  CharPtr                  new_comment;
+  
+  dlg = (ApplyFeatureDetailsDlgPtr) GetObjectExtra (b);
+  if (dlg == NULL || StringHasNoText (text))
+  {
+    return;
+  }
+  
+  orig_comment = SaveStringFromText (dlg->comment);
+  if (StringHasNoText (orig_comment))
+  {
+    SetTitle (dlg->comment, text);
+  }
+  else
+  {
+    new_comment = (CharPtr) MemNew ((StringLen (orig_comment) + StringLen (text) + 3) * sizeof (Char));
+    if (new_comment != NULL)
+    {
+      StringCpy (new_comment, orig_comment);
+      StringCat (new_comment, "; ");
+      StringCat (new_comment, text);
+      SetTitle (dlg->comment, new_comment);
+      new_comment = MemFree (new_comment);
+    }
+  } 
+  orig_comment = MemFree (orig_comment);
+}
+
+
+static void Add18SITS28SToComment (ButtoN b) 
+{
+  AddTextToComment (b, "contains 18S ribosomal RNA, internal transcribed spacer 1, 5.8S ribosomal RNA, internal transcribed spacer 2, and 28S ribosomal RNA");
+}
+
+
+static void Add16SIGS23SToComment (ButtoN b)
+{
+  AddTextToComment (b, "contains 16S ribosomal RNA, 16S-23S ribosomal RNA intergenic spacer, and 23S ribosomal RNA");
+}
+
+
+static void ChangeApplyFeatureDetailsBtn (ButtoN b)
+{
+  ApplyFeatureDetailsDlgPtr dlg;
+
+  dlg = (ApplyFeatureDetailsDlgPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  if (dlg->change_notify != NULL) {
+    (dlg->change_notify) (dlg->change_userdata);
+  }
+}
+
+
+NLM_EXTERN DialoG ApplyFeatureDetailsDialog (GrouP h, Uint1 featdef_type, ApplyFeatureDetailsPtr details, Boolean indexer_version, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+{
+  ApplyFeatureDetailsDlgPtr dlg;
+  GrouP                 p;
+  GrouP                 r, frame_grp = NULL, comment_btns_grp = NULL;
+  ButtoN                comment_btn;
+  Int4                  seqfeattype;
+  SeqFeatPtr            sfp;
+
+  dlg = (ApplyFeatureDetailsDlgPtr) MemNew (sizeof (ApplyFeatureDetailsDlgData));
+  p = HiddenGroup (h, -1, 0, NULL);
+  SetGroupSpacing (p, 10, 10);
+  SetObjectExtra (p, dlg, StdCleanupExtraProc);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = ApplyFeatureDetailsToDialog;
+  dlg->fromdialog = DialogToApplyFeatureDetails;
+  dlg->dialogmessage = NULL;
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  dlg->featdef_type = featdef_type;
+
+  seqfeattype = FindFeatFromFeatDefType (featdef_type);
+
+  if (featdef_type == FEATDEF_CDS) {
+    if (indexer_version) {
+      dlg->add_mrna = CheckBox (p, "Also add mRNA", ChangeApplyFeatureDetailsBtn);
+      SetObjectExtra (dlg->add_mrna, dlg, NULL);
+    }
+
+    frame_grp = HiddenGroup (p, 2, 0, NULL);
+    StaticPrompt (frame_grp, "Reading Frame", 0, dialogTextHeight, programFont, 'l');
+    dlg->reading_frame = PopupList (frame_grp, TRUE, NULL);
+    PopupItem (dlg->reading_frame, "1");
+    PopupItem (dlg->reading_frame, "2");
+    PopupItem (dlg->reading_frame, "3");
+    PopupItem (dlg->reading_frame, "Best");
+    SetValue (dlg->reading_frame, 4);
+  } else if (featdef_type == FEATDEF_source) {
+    dlg->src_quals = BioSourceDialog (p);
+  } 
+
+  r = HiddenGroup (p, 2, 0, NULL);
+  if (featdef_type == FEATDEF_CDS) {
+
+    StaticPrompt (r, "Protein Name", 0, dialogTextHeight, programFont, 'l');
+    dlg->protein_name = DialogText (r, "", 20, NULL);
+    StaticPrompt (r, "Protein Description", 0, dialogTextHeight, programFont, 'l');
+    dlg->protein_description = DialogText (r, "", 20, NULL);
+  } else if (seqfeattype == SEQFEAT_RNA) {
+    /* RNA name */
+    StaticPrompt (r, "RNA Name", 0, dialogTextHeight, programFont, 'l');
+    dlg->rna_name = DialogText (r, "", 20, NULL);
+    /* ncRNA class */
+    if (featdef_type == FEATDEF_ncRNA) {
+      StaticPrompt (r, "ncRNA Class", 0, dialogTextHeight, programFont, 'l');
+      dlg->ncrna_class = CreatencRNAClassDialog (r, FALSE, NULL, NULL);
+    }
+  } else if (featdef_type != FEATDEF_GENE && featdef_type != FEATDEF_source) {
+    StaticPrompt (r, "Qualifiers", 0, dialogTextHeight, programFont, 'l');
+    sfp = CreateFeatureWithImportFeatureQuals (featdef_type, details == NULL ? NULL : details->fields);
+    dlg->quals = NewCreateImportFields (r, GetFeatureNameFromFeatureType (GetFeatureTypeFromFeatdef(featdef_type)), sfp, FALSE);
+    sfp = SeqFeatFree (sfp);
+  }
+
+  /* gene qualifiers ( for all ) */
+  StaticPrompt (r, "Gene Locus", 0, dialogTextHeight, programFont, 'l');
+  dlg->gene_locus = DialogText (r, "", 20, NULL);
+  StaticPrompt (r, "Gene Description", 0, dialogTextHeight, programFont, 'l');
+  dlg->gene_description = DialogText (r, "", 20, NULL);
+  StaticPrompt (r, "Comment", 0, dialogTextHeight, programFont, 'l');
+  dlg->comment = DialogText (r, "", 20, NULL);  
+  if ((featdef_type == FEATDEF_otherRNA || featdef_type == FEATDEF_misc_RNA) && indexer_version) {
+    comment_btns_grp = HiddenGroup (p, 2, 0, NULL);
+    comment_btn = PushButton (comment_btns_grp, "Add '18S-ITS-5.8S-ITS-28S' to comment", Add18SITS28SToComment);
+    SetObjectExtra (comment_btn, dlg, NULL);
+    comment_btn = PushButton (comment_btns_grp, "Add '16S-IGS-23S' to comment", Add16SIGS23SToComment);
+    SetObjectExtra (comment_btn, dlg, NULL);
+  }
+
+  if (frame_grp != NULL) {
+    AlignObjects (ALIGN_CENTER, (HANDLE) r,
+                                (HANDLE) frame_grp,
+                                (HANDLE) dlg->add_mrna,
+                                NULL);
+  } else if (comment_btns_grp != NULL) {
+    AlignObjects (ALIGN_CENTER, (HANDLE) r,
+                                (HANDLE) comment_btns_grp,
+                                NULL);
+  } else if (dlg->src_quals != NULL) {
+    AlignObjects (ALIGN_CENTER, (HANDLE) r,
+                                (HANDLE) dlg->src_quals,
+                                NULL);
+  } else {
+    AlignObjects (ALIGN_CENTER, (HANDLE) r,
+                                NULL);
+  }
+  return (DialoG) p;
+}
+
+
+typedef struct applyfeatureactiondlg {
+  DIALOG_MESSAGE_BLOCK
+  DialoG                   feature_type_dlg;
+  ButtoN                   apply_to_parts;
+  TexT                     only_this_part;
+  ButtoN                   partial5;
+  ButtoN                   partial3;
+  GrouP                    strand_group;
+  GrouP                    use_whole_interval;
+  TexT                     left_end;
+  TexT                     right_end;
+  GrouP                    all_or_some_group;
+  TexT                     accession_list_txt;
+  ButtoN                   add_redundant;
+
+  DialoG                   details;
+
   Nlm_ChangeNotifyProc     change_notify;
   Pointer                  change_userdata;
 
@@ -9949,83 +11089,6 @@ static ValNodePtr SequenceListCollect (CharPtr txt)
 }
 
 
-static CharPtr FindFeatQualValue (ValNodePtr vnp, Int4 featqual)
-{
-  FeatQualLegalValPtr q;
-  CharPtr str = NULL;
-  while (vnp != NULL && str == NULL) {
-    q = (FeatQualLegalValPtr) vnp->data.ptrvalue;
-    if (q != NULL && q->qual == featqual) {
-      str = q->val;
-    }
-    vnp = vnp->next;
-  }
-  if (str == NULL) {
-    str = "";
-  }
-  return str;
-}
-
-
-static void SetFeatQualValue (ValNodePtr PNTR fields, Int4 featqual, CharPtr val)
-{
-  FeatQualLegalValPtr q;
-
-  q = FeatQualLegalValNew ();
-  q->qual = featqual;
-  q->val = StringSave (val);
-  ValNodeAddPointer (fields, 1, q);
-}
-
-
-static SeqFeatPtr CreateFeatureWithImportFeatureQuals (ApplyFeatureActionPtr action)
-{
-  SeqFeatPtr sfp;
-  ValNodePtr vnp;
-  FeatQualLegalValPtr q;
-  GBQualPtr gbq;
-  CharPtr   qualname, cp;
-
-  sfp = SeqFeatNew();
-  sfp->idx.subtype = GetFeatdefFromFeatureType (action->type);
-  sfp->data.choice = FindFeatFromFeatDefType (sfp->idx.subtype);
-
-  for (vnp = action->fields; vnp != NULL; vnp = vnp->next) {
-    q = (FeatQualLegalValPtr) vnp->data.ptrvalue;
-    if (q != NULL && q->qual != Feat_qual_legal_gene && q->qual != Feat_qual_legal_gene_description && q->qual != Feat_qual_legal_note) {
-      gbq = GBQualNew ();
-      qualname = StringSave (GetFeatQualName(q->qual));
-      cp = StringChr (qualname, '-');
-      while (cp != NULL) {
-        *cp = '_';
-        cp = StringChr (cp + 1, '-');
-      }
-      gbq->qual = qualname;
-      gbq->val = StringSave (q->val);
-      gbq->next = sfp->qual;
-      sfp->qual = gbq;
-    }
-  }
-  return sfp;  
-}
-
-
-static void AddGBQualsToActionFields (GBQualPtr gbq, ApplyFeatureActionPtr action)
-{
-  Int4 qualtype;
-
-  if (action == NULL) return;
-
-  while (gbq != NULL) {
-    qualtype = GetFeatQualByName (gbq->qual);
-    if (qualtype > -1) {
-      SetFeatQualValue (&(action->fields), qualtype, gbq->val);
-    }
-    gbq = gbq->next;
-  }
-}
-
-
 static void ApplyFeatureActionToDialog (DialoG d, Pointer data)
 {
   ApplyFeatureActionDlgPtr dlg;
@@ -10034,7 +11097,7 @@ static void ApplyFeatureActionToDialog (DialoG d, Pointer data)
   LocationIntervalPtr      lint;
   CharPtr                  txt;
   ValNode                  vn;
-  BioSourcePtr             biop;
+  ApplyFeatureDetailsPtr   details;
 
   dlg = (ApplyFeatureActionDlgPtr) GetObjectExtra (d);
   if (dlg == NULL) {
@@ -10057,26 +11120,6 @@ static void ApplyFeatureActionToDialog (DialoG d, Pointer data)
     SetTitle (dlg->accession_list_txt, "");
     SetStatus (dlg->add_redundant, FALSE);
 
-    /* for CDS */
-    SafeSetStatus (dlg->add_mrna, FALSE);
-    SafeSetValue (dlg->reading_frame, 4);
-    SafeSetTitle (dlg->protein_name, "");
-    SafeSetTitle (dlg->protein_description, "");
-
-    /* for RNA */
-    PointerToDialog (dlg->ncrna_class, NULL);
-    SafeSetTitle (dlg->rna_name, "");
-
-    /* for import features */
-    PointerToDialog (dlg->quals, NULL);
-
-    /* for source features */
-    PointerToDialog (dlg->src_quals, NULL);
-  
-    /* for all */
-    SafeSetTitle (dlg->gene_locus, "");
-    SafeSetTitle (dlg->gene_description, "");
-    SafeSetTitle (dlg->comment, "");
   } else {
     vn.choice = (Uint1) action->type;
     vn.next = NULL;
@@ -10103,6 +11146,7 @@ static void ApplyFeatureActionToDialog (DialoG d, Pointer data)
       SetTitle (dlg->right_end, "");
     } else {
       SetValue (dlg->use_whole_interval, 2);
+      if (action->location->choice == LocationChoice_interval) {
       lint = (LocationIntervalPtr) action->location->data.ptrvalue;
       if (lint == NULL) {
         SetTitle (dlg->left_end, "");
@@ -10113,6 +11157,15 @@ static void ApplyFeatureActionToDialog (DialoG d, Pointer data)
         sprintf (num, "%d", lint->to);  
         SetTitle (dlg->right_end, num);
       }
+      } else if (action->location->choice == LocationChoice_point) {
+        sprintf (num, "%d^", action->location->data.intvalue);
+        SetTitle (dlg->left_end, num);
+        sprintf (num, "%d", action->location->data.intvalue + 1);  
+        SetTitle (dlg->right_end, num);
+      } else {
+        SetTitle (dlg->left_end, "");
+        SetTitle (dlg->right_end, "");
+      }
     }
 
     if (action->seq_list == NULL || action->seq_list->choice == SequenceListChoice_all) {
@@ -10126,34 +11179,11 @@ static void ApplyFeatureActionToDialog (DialoG d, Pointer data)
     }
 
     SetStatus (dlg->add_redundant, action->add_redundant);
-
-    /* for CDS */
-    SafeSetStatus (dlg->add_mrna, action->add_mrna);
-    txt = FindFeatQualValue (action->fields, Feat_qual_legal_codon_start);
-    if (StringICmp (txt, "best") == 0) {
-      SafeSetValue (dlg->reading_frame, 4);
-    } else {
-      SafeSetValue (dlg->reading_frame, atoi (txt));
-    }
-
-    SafeSetTitle (dlg->protein_name, FindFeatQualValue (action->fields, Feat_qual_legal_product));
-    SafeSetTitle (dlg->protein_description, FindFeatQualValue (action->fields, Feat_qual_legal_description));
-
-    /* for source feature */
-    biop = BioSourceFromSourceQualVals (action->src_fields);
-    PointerToDialog (dlg->src_quals, biop);
-    biop = BioSourceFree (biop);
-
-    /* for RNA */
-    PointerToDialog (dlg->ncrna_class, FindFeatQualValue (action->fields, Feat_qual_legal_ncRNA_class));
-    SafeSetTitle (dlg->rna_name, FindFeatQualValue (action->fields, Feat_qual_legal_product));
-  
-    /* for all */
-    SafeSetTitle (dlg->gene_locus, FindFeatQualValue (action->fields, Feat_qual_legal_gene));
-    SafeSetTitle (dlg->gene_description, FindFeatQualValue (action->fields, Feat_qual_legal_gene_description));
-    SafeSetTitle (dlg->comment, FindFeatQualValue (action->fields, Feat_qual_legal_note));
   }
 
+  details = ApplyFeatureDetailsNew (action);
+  PointerToDialog (dlg->details, details);
+  details = ApplyFeatureDetailsFree (details);
   ChangeApplyFeatureActionDlg (dlg);
   if (dlg->change_notify != NULL) {
     (dlg->change_notify) (dlg->change_userdata);
@@ -10165,13 +11195,10 @@ static Pointer DialogToApplyFeatureAction (DialoG d)
 {
   ApplyFeatureActionDlgPtr dlg;
   ApplyFeatureActionPtr    action;
-  CharPtr                  num_txt, txt;
-  Char                     num[15];
+  CharPtr                  num_txt;
   LocationIntervalPtr      lint;
-  Int4                     frame;
-  GBQualPtr                gbq;
   ValNodePtr               vnp;
-  BioSourcePtr             biop;
+  ApplyFeatureDetailsPtr   details;
 
   dlg = (ApplyFeatureActionDlgPtr) GetObjectExtra (d);
   if (dlg == NULL) {
@@ -10207,6 +11234,22 @@ static Pointer DialogToApplyFeatureAction (DialoG d)
     action->location = ValNodeNew(NULL);
     action->location->choice = LocationChoice_whole_sequence;
   } else {
+    num_txt = SaveStringFromText (dlg->left_end);
+    if (num_txt != NULL && num_txt[StringLen(num_txt) - 1] == '^') {
+      action->location = ValNodeNew(NULL);
+      action->location->choice = LocationChoice_point;
+      action->location->data.intvalue = atoi (num_txt);
+      num_txt = MemFree (num_txt);
+    } else {
+      num_txt = MemFree (num_txt);
+      num_txt = SaveStringFromText (dlg->right_end);
+      if (num_txt != NULL && num_txt[0] == '^') {
+        action->location = ValNodeNew(NULL);
+        action->location->choice = LocationChoice_point;
+        action->location->data.intvalue = atoi (num_txt + 1) - 1;
+        num_txt = MemFree (num_txt);
+      } else {
+        num_txt = MemFree (num_txt);
     lint = LocationIntervalNew ();
     num_txt = SaveStringFromText (dlg->left_end);
     lint->from = atoi (num_txt);
@@ -10218,7 +11261,8 @@ static Pointer DialogToApplyFeatureAction (DialoG d)
     action->location->choice = LocationChoice_interval;
     action->location->data.ptrvalue = lint;
   }
-
+    }
+  }
   if (GetValue (dlg->all_or_some_group) == 1) {
     action->seq_list = ValNodeNew(NULL);
     action->seq_list->choice = SequenceListChoice_all;
@@ -10232,128 +11276,18 @@ static Pointer DialogToApplyFeatureAction (DialoG d)
 
   action->add_redundant = GetStatus (dlg->add_redundant);
 
-  /* for CDS */
-  if (dlg->add_mrna != NULL && GetStatus (dlg->add_mrna)) {
-    action->add_mrna = TRUE;
-  } else {
-    action->add_mrna = FALSE;
-  }
-
-  if (dlg->reading_frame != NULL) {
-    frame = GetValue (dlg->reading_frame);
-    if (frame > 0 && frame < 4) {
-      sprintf (num, "%d", frame);
-      SetFeatQualValue (&(action->fields), Feat_qual_legal_codon_start, num);
-    } else {
-      SetFeatQualValue (&(action->fields), Feat_qual_legal_codon_start, "best");
-    }
-  }
-
-  if (dlg->protein_name != NULL && !TextHasNoText (dlg->protein_name)) {
-    txt = SaveStringFromText (dlg->protein_name);
-    SetFeatQualValue (&(action->fields), Feat_qual_legal_product, txt);
-    txt = MemFree (txt);
-  }
-  if (dlg->protein_name != NULL && !TextHasNoText (dlg->protein_description)) {
-    txt = SaveStringFromText (dlg->protein_description);
-    SetFeatQualValue (&(action->fields), Feat_qual_legal_description, txt);
-    txt = MemFree (txt);
-  }
-
-  /* for RNA */
-  if (dlg->ncrna_class != NULL) {
-    txt = DialogToPointer (dlg->ncrna_class);
-    if (!StringHasNoText (txt)) {
-      SetFeatQualValue (&(action->fields), Feat_qual_legal_ncRNA_class, txt);
-    }
-    txt = MemFree (txt);
-  }
-  if (dlg->rna_name != NULL && !TextHasNoText (dlg->rna_name)) {
-    txt = SaveStringFromText (dlg->rna_name);
-    SetFeatQualValue (&(action->fields), Feat_qual_legal_product, txt);
-    txt = MemFree (txt);
-  }
-
-  /* for source features */
-  if (dlg->src_quals != NULL) {
-    biop = DialogToPointer (dlg->src_quals);
-    action->src_fields = SourceQualValsFromBioSourcePtr (biop);
-    biop = BioSourceFree (biop);
-  }
-
-  /* for import features */
-  if (dlg->quals != NULL) {
-    gbq = DialogToPointer (dlg->quals);
-    AddGBQualsToActionFields (gbq, action);
-    gbq = GBQualFree (gbq);
-  }
-  
-  /* for all */
-  if (dlg->gene_locus != NULL && !TextHasNoText (dlg->gene_locus)) {
-    txt = SaveStringFromText (dlg->gene_locus);
-    SetFeatQualValue (&(action->fields), Feat_qual_legal_gene, txt);
-    txt = MemFree (txt);
-  }
-  if (dlg->gene_description != NULL && !TextHasNoText (dlg->gene_description)) {
-    txt = SaveStringFromText (dlg->gene_description);
-    SetFeatQualValue (&(action->fields), Feat_qual_legal_gene_description, txt);
-    txt = MemFree (txt);
-  }
-  if (dlg->comment != NULL && !TextHasNoText (dlg->comment)) {
-    txt = SaveStringFromText (dlg->comment);
-    SetFeatQualValue (&(action->fields), Feat_qual_legal_note, txt);
-    txt = MemFree (txt);
-  }
+  details = DialogToPointer (dlg->details);
+  action->add_mrna = details->add_mrna;
+  action->fields = details->fields;
+  details->fields = NULL;
+  action->src_fields = details->src_fields;
+  details->src_fields = NULL;
+  details = ApplyFeatureDetailsFree (details);
 
   return action;
 }
 
 
-static void AddTextToComment (ButtoN b, CharPtr text)
-{
-  ApplyFeatureActionDlgPtr dlg;
-  CharPtr                  orig_comment;
-  CharPtr                  new_comment;
-  
-  dlg = (ApplyFeatureActionDlgPtr) GetObjectExtra (b);
-  if (dlg == NULL || StringHasNoText (text))
-  {
-    return;
-  }
-  
-  orig_comment = SaveStringFromText (dlg->comment);
-  if (StringHasNoText (orig_comment))
-  {
-    SetTitle (dlg->comment, text);
-  }
-  else
-  {
-    new_comment = (CharPtr) MemNew ((StringLen (orig_comment) + StringLen (text) + 3) * sizeof (Char));
-    if (new_comment != NULL)
-    {
-      StringCpy (new_comment, orig_comment);
-      StringCat (new_comment, "; ");
-      StringCat (new_comment, text);
-      SetTitle (dlg->comment, new_comment);
-      new_comment = MemFree (new_comment);
-    }
-  } 
-  orig_comment = MemFree (orig_comment);
-}
-
-
-static void Add18SITS28SToComment (ButtoN b) 
-{
-  AddTextToComment (b, "contains 18S ribosomal RNA, internal transcribed spacer 1, 5.8S ribosomal RNA, internal transcribed spacer 2, and 28S ribosomal RNA");
-}
-
-
-static void Add16SIGS23SToComment (ButtoN b)
-{
-  AddTextToComment (b, "contains 16S ribosomal RNA, 16S-23S ribosomal RNA intergenic spacer, and 23S ribosomal RNA");
-}
-
-
 static void ChangeApplyFeatureActionDlgBtn (ButtoN b)
 {
   ApplyFeatureActionDlgPtr dlg;
@@ -10386,11 +11320,9 @@ ApplyFeatureActionDialog
 {
   ApplyFeatureActionDlgPtr dlg;
   GrouP                 p, g, parts_group, x, indexer_only_group;
-  GrouP                 r, r2, r3, r4, frame_grp = NULL, comment_btns_grp = NULL;
-  ButtoN                comment_btn;
+  GrouP                 r2, r3, r4;
   ValNodePtr            feature_type_list = NULL;
-  SeqFeatPtr            sfp;
-  BioSourcePtr          biop;
+  ApplyFeatureDetailsPtr details;
 
   dlg = (ApplyFeatureActionDlgPtr) MemNew (sizeof (ApplyFeatureActionDlgData));
   p = HiddenGroup (h, -1, 0, NULL);
@@ -10472,112 +11404,22 @@ ApplyFeatureActionDialog
     
     dlg->add_redundant = CheckBox (indexer_only_group, "Add even if feature of same type already present", ChangeApplyFeatureActionDlgBtn);
     SetObjectExtra (dlg->add_redundant, dlg, NULL);
-    if (action != NULL && action->type == Feature_type_cds) {
-      dlg->add_mrna = CheckBox (indexer_only_group, "Also add mRNA", ChangeApplyFeatureActionDlgBtn);
-      SetObjectExtra (dlg->add_mrna, dlg, NULL);
-    }
-
-    AlignObjects (ALIGN_CENTER, (HANDLE) r2, (HANDLE) dlg->all_or_some_group, (HANDLE) dlg->add_redundant, (HANDLE) dlg->add_mrna, NULL);
-  }  
-
-  if (action != NULL && action->type == Feature_type_cds) {
-    frame_grp = HiddenGroup (p, 2, 0, NULL);
-    StaticPrompt (frame_grp, "Reading Frame", 0, dialogTextHeight, programFont, 'l');
-    dlg->reading_frame = PopupList (frame_grp, TRUE, NULL);
-    PopupItem (dlg->reading_frame, "1");
-    PopupItem (dlg->reading_frame, "2");
-    PopupItem (dlg->reading_frame, "3");
-    PopupItem (dlg->reading_frame, "Best");
-    SetValue (dlg->reading_frame, 4);
-  } else if (action != NULL && action->type == Feature_type_source) {
-    dlg->src_quals = BioSourceDialog (p);
-    biop = BioSourceFromSourceQualVals (action->src_fields);
-    PointerToDialog (dlg->src_quals, biop);
-    biop = BioSourceFree (biop);
-  } 
 
-  r = HiddenGroup (p, 2, 0, NULL);
-  if (action != NULL && action->type == Feature_type_cds) {
-
-    StaticPrompt (r, "Protein Name", 0, dialogTextHeight, programFont, 'l');
-    dlg->protein_name = DialogText (r, "", 20, NULL);
-    StaticPrompt (r, "Protein Description", 0, dialogTextHeight, programFont, 'l');
-    dlg->protein_description = DialogText (r, "", 20, NULL);
-  } else if (action != NULL && (action->type == Feature_type_preRNA
-                                || action->type == Feature_type_mRNA
-                                || action->type == Feature_type_tRNA
-                                || action->type == Feature_type_rRNA
-                                || action->type == Feature_type_snRNA
-                                || action->type == Feature_type_scRNA 
-                                || action->type == Feature_type_otherRNA
-                                || action->type == Feature_type_tmRNA
-                                || action->type == Feature_type_ncRNA)) {
-    /* RNA name */
-    StaticPrompt (r, "RNA Name", 0, dialogTextHeight, programFont, 'l');
-    dlg->rna_name = DialogText (r, "", 20, NULL);
-    /* ncRNA class */
-    if (action->type == Feature_type_ncRNA) {
-      StaticPrompt (r, "ncRNA Class", 0, dialogTextHeight, programFont, 'l');
-      dlg->ncrna_class = CreatencRNAClassDialog (r, FALSE, NULL, NULL);
-    }
-  } else if (action != NULL && action->type != Feature_type_gene && action->type != Feature_type_source) {
-    StaticPrompt (r, "Qualifiers", 0, dialogTextHeight, programFont, 'l');
-    sfp = CreateFeatureWithImportFeatureQuals (action);
-    dlg->quals = NewCreateImportFields (r, GetFeatureNameFromFeatureType (action->type), sfp, FALSE);
-    sfp = SeqFeatFree (sfp);
+    AlignObjects (ALIGN_CENTER, (HANDLE) r2, (HANDLE) dlg->all_or_some_group, (HANDLE) dlg->add_redundant, NULL);
   }
 
-  /* gene qualifiers ( for all ) */
-  StaticPrompt (r, "Gene Locus", 0, dialogTextHeight, programFont, 'l');
-  dlg->gene_locus = DialogText (r, "", 20, NULL);
-  StaticPrompt (r, "Gene Description", 0, dialogTextHeight, programFont, 'l');
-  dlg->gene_description = DialogText (r, "", 20, NULL);
-  StaticPrompt (r, "Comment", 0, dialogTextHeight, programFont, 'l');
-  dlg->comment = DialogText (r, "", 20, NULL);  
-  if (action != NULL && action->type == Feature_type_otherRNA && indexer_version) {
-    comment_btns_grp = HiddenGroup (p, 2, 0, NULL);
-    comment_btn = PushButton (comment_btns_grp, "Add '18S-ITS-5.8S-ITS-28S' to comment", Add18SITS28SToComment);
-    SetObjectExtra (comment_btn, dlg, NULL);
-    comment_btn = PushButton (comment_btns_grp, "Add '16S-IGS-23S' to comment", Add16SIGS23SToComment);
-    SetObjectExtra (comment_btn, dlg, NULL);
-  }
+  details = ApplyFeatureDetailsNew (action);
+  dlg->details = ApplyFeatureDetailsDialog (p, action == NULL ? FEATDEF_CDS : GetFeatdefFromFeatureType(action->type),
+                                            details, indexer_version, change_notify, change_userdata);
+  details = ApplyFeatureDetailsFree (details);
 
-  if (frame_grp != NULL) {
     AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_type_dlg,
                                 (HANDLE) parts_group,
                                 (HANDLE) g,
                                 (HANDLE) dlg->strand_group,
                                 (HANDLE) indexer_only_group,
-                                (HANDLE) r,
-                                (HANDLE) frame_grp,
-                                NULL);
-  } else if (comment_btns_grp != NULL) {
-    AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_type_dlg,
-                                (HANDLE) parts_group,
-                                (HANDLE) g,
-                                (HANDLE) dlg->strand_group,
-                                (HANDLE) indexer_only_group,
-                                (HANDLE) r,
-                                (HANDLE) comment_btns_grp,
-                                NULL);
-  } else if (dlg->src_quals != NULL) {
-    AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_type_dlg,
-                                (HANDLE) parts_group,
-                                (HANDLE) g,
-                                (HANDLE) dlg->strand_group,
-                                (HANDLE) indexer_only_group,
-                                (HANDLE) r,
-                                (HANDLE) dlg->src_quals,
+                              (HANDLE) dlg->details,
                                 NULL);
-  } else {
-    AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_type_dlg,
-                                (HANDLE) parts_group,
-                                (HANDLE) g,
-                                (HANDLE) dlg->strand_group,
-                                (HANDLE) indexer_only_group,
-                                (HANDLE) r,
-                                NULL);
-  }
 
   return (DialoG) p;  
 }
@@ -11363,6 +12205,7 @@ static DialoG AutodefActionDialog
 
   ValNodeAddPointer (&src_quals, 0, StringSave ("clone"));
   ValNodeAddPointer (&src_quals, 0, StringSave ("cultivar"));
+  ValNodeAddPointer (&src_quals, 0, StringSave ("culture-collection"));
   ValNodeAddPointer (&src_quals, 0, StringSave ("haplogroup"));
   ValNodeAddPointer (&src_quals, 0, StringSave ("isolate"));
   ValNodeAddPointer (&src_quals, 0, StringSave ("strain"));
@@ -11395,6 +12238,139 @@ static DialoG AutodefActionDialog
 }
 
 
+typedef struct fixpubcapsdlg {
+  DIALOG_MESSAGE_BLOCK
+
+  ButtoN fix_title;
+  ButtoN fix_author;
+  ButtoN fix_affil;
+  DialoG constraint;
+
+  Nlm_ChangeNotifyProc     change_notify;
+  Pointer                  change_userdata;
+} FixPubCapsDlgData, PNTR FixPubCapsDlgPtr;
+
+
+static void FixPubCapsActionToDialog (DialoG d, Pointer data)
+{
+  FixPubCapsDlgPtr dlg;
+  FixPubCapsActionPtr action;
+
+  dlg = (FixPubCapsDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return;
+  }
+
+  action = (FixPubCapsActionPtr) data;
+  if (action == NULL) {
+    SetStatus (dlg->fix_title, FALSE);
+    SetStatus (dlg->fix_author, FALSE);
+    SetStatus (dlg->fix_affil, FALSE);
+    PointerToDialog (dlg->constraint, NULL);
+  } else {
+    SetStatus (dlg->fix_title, action->title);
+    SetStatus (dlg->fix_author, action->authors);
+    SetStatus (dlg->fix_affil, action->affiliation);
+    PointerToDialog (dlg->constraint, action->constraint);
+  }
+
+}
+
+
+static Pointer DialogToFixPubCapsAction (DialoG d)
+{
+  FixPubCapsDlgPtr dlg;
+  FixPubCapsActionPtr action = NULL;
+
+  dlg = (FixPubCapsDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return NULL;
+  }
+
+  action = FixPubCapsActionNew ();
+  action->title = GetStatus (dlg->fix_title);
+  action->authors = GetStatus (dlg->fix_author);
+  action->affiliation = GetStatus (dlg->fix_affil);
+  if (IsFixPubCapsActionEmpty(action)) {
+    action = FixPubCapsActionFree (action);
+  } else {
+    action->constraint = DialogToPointer (dlg->constraint);
+  }
+  return action;
+}
+
+
+static void ChangeFixPubCapsActionBtn (ButtoN b)
+{
+  FixPubCapsDlgPtr dlg;
+
+  dlg = (FixPubCapsDlgPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  if (dlg->change_notify != NULL) {
+    (dlg->change_notify) (dlg->change_userdata);
+  }
+}
+
+
+static ValNodePtr TestFixPubCapsActionDialog (DialoG d)
+{
+  FixPubCapsDlgPtr dlg;
+  FixPubCapsActionPtr a;
+  ValNodePtr err_list = NULL;
+
+  dlg = (FixPubCapsDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) return NULL;
+  a = (FixPubCapsActionPtr) DialogToPointer (d);
+  if (a == NULL) {
+    ValNodeAddPointer (&err_list, 0, "bad action");
+  }
+  return err_list;
+}
+
+
+static DialoG FixPubCapsDialog 
+(GrouP h,
+ Boolean indexer_version, 
+ Nlm_ChangeNotifyProc     change_notify,
+ Pointer                  change_userdata)
+{
+  FixPubCapsDlgPtr dlg;
+  GrouP            p, g1;
+
+  dlg = (FixPubCapsDlgPtr) MemNew (sizeof (FixPubCapsDlgData));
+  p = HiddenGroup (h, -1, 0, NULL);
+  SetGroupSpacing (p, 10, 10);
+  SetObjectExtra (p, dlg, StdCleanupExtraProc);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = FixPubCapsActionToDialog;
+  dlg->fromdialog = DialogToFixPubCapsAction;
+  dlg->dialogmessage = NULL;
+  dlg->testdialog = TestFixPubCapsActionDialog;
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  g1 = HiddenGroup (p, 0, 3, NULL);
+  SetGroupSpacing (g1, 10, 10);
+  dlg->fix_title = CheckBox (g1, "Fix title", ChangeFixPubCapsActionBtn);
+  SetObjectExtra (dlg->fix_title, dlg, NULL);
+  dlg->fix_author = CheckBox (g1, "Fix authors", ChangeFixPubCapsActionBtn);
+  SetObjectExtra (dlg->fix_author, dlg, NULL);
+  dlg->fix_affil = CheckBox (g1, "Fix affiliation", ChangeFixPubCapsActionBtn);
+  SetObjectExtra (dlg->fix_affil, dlg, NULL);
+
+  dlg->constraint = ConstraintSetDialog (p, change_notify, change_userdata);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) dlg->constraint, NULL);
+
+  return (DialoG) p;
+}
+
+
+
 typedef struct editfeaturelocationactiondlg {
   DIALOG_MESSAGE_BLOCK
   DialoG                   feature_type_dlg;
@@ -11647,6 +12623,12 @@ static void EditFeatureLocationActionToDialog (DialoG d, Pointer data)
               break;
           }
           break;
+        case LocationEditType_extend_5:
+          SetValue (dlg->feature_edit_type, 7);
+          break;
+        case LocationEditType_extend_3:
+          SetValue (dlg->feature_edit_type, 8);
+          break;
         default:
           ResetFeatureLocationActionEditType (dlg);
           break;
@@ -11837,6 +12819,14 @@ static Pointer DialogToEditFeatureLocationAction (DialoG d)
           break;
       }
       break;
+    case 7:
+      action->action = ValNodeNew (NULL);
+      action->action->choice = LocationEditType_extend_5;
+      break;
+    case 8:
+      action->action = ValNodeNew (NULL);
+      action->action->choice = LocationEditType_extend_3;
+      break;
     default:
       action = EditFeatureLocationActionFree (action);
       break;
@@ -11921,6 +12911,8 @@ EditFeatureLocationActionDialog
   PopupItem (dlg->feature_edit_type, "Set 3' Partial");
   PopupItem (dlg->feature_edit_type, "Clear 3' Partial");
   PopupItem (dlg->feature_edit_type, "Convert location");
+  PopupItem (dlg->feature_edit_type, "Extend 5' end to end of sequence");
+  PopupItem (dlg->feature_edit_type, "Extend 3' end to end of sequence");
   SetValue (dlg->feature_edit_type, 1);
 
   g = HiddenGroup (p, 0, 0, NULL);
@@ -12023,8 +13015,6 @@ typedef struct parsesrcdlg {
 } ParseSrcDlgData, PNTR ParseSrcDlgPtr;
 
 
-const CharPtr kTaxnameAfterBinomialString = "Taxname after binomial";
-
 static void ChangeParseSrcDialogPopup (PopuP p)
 {
   ParseSrcDlgPtr dlg;
@@ -12554,10 +13544,10 @@ static void ParseDstToDialog (DialoG d, Pointer data)
               SetValue (dlg->feat_or_desc, 1);
               break;
             case Object_type_constraint_feature:
-              SetValue (dlg->feat_or_desc, 2);
+              SetValue (dlg->feat_or_desc, 3);
               break;
             case Object_type_constraint_descriptor:
-              SetValue (dlg->feat_or_desc, 3);
+              SetValue (dlg->feat_or_desc, 2);
               break;
             default:
               SetValue (dlg->feat_or_desc, 1);
@@ -12646,10 +13636,10 @@ static Pointer DialogToParseDst (DialoG d)
         case 1:
           org->type = Object_type_constraint_any;
           break;
-        case 2:
+        case 3:
           org->type = Object_type_constraint_feature;
           break;
-        case 3:
+        case 2:
           org->type = Object_type_constraint_descriptor;
           break;
         default:
@@ -12684,10 +13674,10 @@ static Pointer DialogToParseDst (DialoG d)
         case 1:
           org->type = Object_type_constraint_any;
           break;
-        case 2:
+        case 3:
           org->type = Object_type_constraint_feature;
           break;
-        case 3:
+        case 2:
           org->type = Object_type_constraint_descriptor;
           break;
         default:
@@ -12938,7 +13928,7 @@ static ValNodePtr TestParseDstDialog (DialoG d)
 }
 
 
-static DialoG ParseDstDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+NLM_EXTERN DialoG ParseDstDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
 {
   ParseDstDlgPtr dlg;
   GrouP          p, g, g2;
@@ -13045,12 +14035,143 @@ static DialoG ParseDstDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Point
 }
 
 
+typedef struct capchangedlg {
+ DIALOG_MESSAGE_BLOCK
+ GrouP  cap_change;
+ Nlm_ChangeNotifyProc change_notify;
+ Pointer              change_userdata;
+} CapChangeDlgData, PNTR CapChangeDlgPtr;
+
+
+static void CapChangeToDialog (DialoG d, Pointer data)
+{
+  CapChangeDlgPtr dlg;
+  Int4 cap_change;
+
+  dlg = (CapChangeDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return;
+  }
+  cap_change = (Int4) data;
+  switch (cap_change) {
+    case Cap_change_none:
+      SetValue (dlg->cap_change, 1);
+      break;
+    case Cap_change_tolower:
+      SetValue (dlg->cap_change, 2);
+      break;
+    case Cap_change_toupper:
+      SetValue (dlg->cap_change, 3);
+      break;
+    case Cap_change_firstcap:
+      SetValue (dlg->cap_change, 4);
+      break;
+    case Cap_change_firstcaprestnochange:
+      SetValue (dlg->cap_change, 5);
+      break;
+    default:
+      SetValue (dlg->cap_change, 1);
+      break;
+  }
+  if (dlg->change_notify != NULL) {
+    (dlg->change_notify) (dlg->change_userdata);
+  }
+}
+
+
+static Pointer DialogToCapChange (DialoG d)
+{
+  CapChangeDlgPtr dlg;
+  Int4 cap_change = Cap_change_none;
+
+  dlg = (CapChangeDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) return NULL;
+
+  switch (GetValue (dlg->cap_change)) {
+    case 1:
+      cap_change = Cap_change_none;
+      break;
+    case 2:
+      cap_change = Cap_change_tolower;
+      break;
+    case 3:
+      cap_change = Cap_change_toupper;
+      break;
+    case 4:
+      cap_change = Cap_change_firstcap;
+      break;
+    case 5:
+      cap_change = Cap_change_firstcaprestnochange;
+      break;
+    default:
+      cap_change = Cap_change_none;
+      break;
+  }
+  return (Pointer) cap_change;
+}
+
+
+static ValNodePtr TestCapChangeDialog (DialoG d)
+{
+  CapChangeDlgPtr dlg;
+  ValNodePtr err_list = NULL;
+  Int2 val;
+
+  dlg = (CapChangeDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) return NULL;
+
+  val = GetValue (dlg->cap_change);
+  if (val < 1 || val > 5) {
+    ValNodeAddPointer (&err_list, 0, "cap change");
+  }
+  return err_list;
+}
+
+
+NLM_EXTERN DialoG 
+CapChangeDialog
+(GrouP h,
+ Nlm_ChangeNotifyProc     change_notify,
+ Pointer                  change_userdata)
+{
+  CapChangeDlgPtr dlg;
+  GrouP           p;
+
+  dlg = (CapChangeDlgPtr) MemNew (sizeof (CapChangeDlgData));
+  p = NormalGroup (h, 5, 0, "Capitalization", programFont, NULL);
+  SetGroupSpacing (p, 10, 10);
+  SetObjectExtra (p, dlg, StdCleanupExtraProc);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = CapChangeToDialog;
+  dlg->fromdialog = DialogToCapChange;
+  dlg->dialogmessage = NULL;
+  dlg->testdialog = TestCapChangeDialog;
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  dlg->cap_change = p;
+  SetGroupSpacing (dlg->cap_change, 10, 10);
+
+  RadioButton (dlg->cap_change, "No change");
+  RadioButton (dlg->cap_change, "To lower");
+  RadioButton (dlg->cap_change, "To upper");
+  RadioButton (dlg->cap_change, "First cap, rest lower");
+  RadioButton (dlg->cap_change, "First cap, rest no change");
+  SetValue (dlg->cap_change, 1);
+
+  return (DialoG) p;  
+}
+
+
+
+
 typedef struct parseactiondlg {
  DIALOG_MESSAGE_BLOCK
  DialoG text_portion;
  DialoG src;
  DialoG dst;
- GrouP  cap_change;
+ DialoG cap_change;
  ButtoN remove_from_parsed;
  DialoG existing_text;
  Nlm_ChangeNotifyProc change_notify;
@@ -13073,30 +14194,14 @@ static void ParseActionToDialog (DialoG d, Pointer data)
     PointerToDialog (dlg->text_portion, NULL);
     PointerToDialog (dlg->src, NULL);
     PointerToDialog (dlg->dst, NULL);
-    SetValue (dlg->cap_change, 1);
+    PointerToDialog (dlg->cap_change, NULL);
     SetStatus (dlg->remove_from_parsed, FALSE);
     PointerToDialog (dlg->existing_text, NULL);
   } else {
     PointerToDialog (dlg->text_portion, action->portion);
     PointerToDialog (dlg->src, action->src);
     PointerToDialog (dlg->dst, action->dest);
-    switch (action->capitalization) {
-      case Cap_change_none:
-        SetValue (dlg->cap_change, 1);
-        break;
-      case Cap_change_tolower:
-        SetValue (dlg->cap_change, 2);
-        break;
-      case Cap_change_toupper:
-        SetValue (dlg->cap_change, 3);
-        break;
-      case Cap_change_firstcap:
-        SetValue (dlg->cap_change, 4);
-        break;
-      default:
-        SetValue (dlg->cap_change, 1);
-        break;
-    }
+    PointerToDialog (dlg->cap_change, (Pointer) action->capitalization);
     SetStatus (dlg->remove_from_parsed, action->remove_from_parsed);
     PointerToDialog (dlg->existing_text, (Pointer) action->existing_text);
   }    
@@ -13116,23 +14221,7 @@ static Pointer DialogToParseAction (DialoG d)
   action->src = DialogToPointer (dlg->src);
   action->dest = DialogToPointer (dlg->dst);
   action->remove_from_parsed = GetStatus (dlg->remove_from_parsed);
-  switch (GetValue (dlg->cap_change)) {
-    case 1:
-      action->capitalization = Cap_change_none;
-      break;
-    case 2:
-      action->capitalization = Cap_change_tolower;
-      break;
-    case 3:
-      action->capitalization = Cap_change_toupper;
-      break;
-    case 4:
-      action->capitalization = Cap_change_firstcap;
-      break;
-    default:
-      action->capitalization = Cap_change_none;
-      break;
-  }
+  action->capitalization = (Int4) DialogToPointer (dlg->cap_change);
   action->existing_text = (Uint2) DialogToPointer (dlg->existing_text);
   return action;
 }
@@ -13142,7 +14231,6 @@ static ValNodePtr TestParseActionDialog (DialoG d)
 {
   ParseActionDlgPtr dlg;
   ValNodePtr err_list = NULL;
-  Int2 val;
 
   dlg = (ParseActionDlgPtr) GetObjectExtra (d);
   if (dlg == NULL) return NULL;
@@ -13151,10 +14239,7 @@ static ValNodePtr TestParseActionDialog (DialoG d)
   ValNodeLink (&err_list, TestDialog (dlg->src));
   ValNodeLink (&err_list, TestDialog (dlg->dst));
   ValNodeLink (&err_list, TestDialog (dlg->existing_text));
-  val = GetValue (dlg->cap_change);
-  if (val < 1 || val > 4) {
-    ValNodeAddPointer (&err_list, 0, "cap change");
-  }
+  ValNodeLink (&err_list, TestDialog (dlg->cap_change));
   return err_list;
 }
 
@@ -13168,7 +14253,7 @@ ParseActionDialogEx
  Pointer                  change_userdata)
 {
   ParseActionDlgPtr dlg;
-  GrouP                 p, g;
+  GrouP                 p, g1, g2, g3;
 
   dlg = (ParseActionDlgPtr) MemNew (sizeof (ParseActionDlgData));
   p = HiddenGroup (h, -1, 0, NULL);
@@ -13183,21 +14268,17 @@ ParseActionDialogEx
   dlg->change_notify = change_notify;
   dlg->change_userdata = change_userdata;
 
-  dlg->text_portion = TextPortionDialog (p, TRUE, change_notify, change_userdata);
-
-  g = HiddenGroup (p, 2, 0, NULL);
-  StaticPrompt (g, "From", 0, popupMenuHeight, programFont, 'r');
-  dlg->src = ParseSrcDialog (g, change_notify, change_userdata);
-  StaticPrompt (g, "And place in", 0, popupMenuHeight, programFont, 'r');
-  dlg->dst = ParseDstDialog (g, change_notify, change_userdata);
-  dlg->cap_change = NormalGroup (p, 4, 0, "Capitalization", programFont, NULL);
-  SetGroupSpacing (dlg->cap_change, 10, 10);
+  g3 =HiddenGroup (p, 2, 0, NULL);
+  StaticPrompt (g3, "Select text", 0, dialogTextHeight, systemFont, 'l');
+  dlg->text_portion = TextPortionDialog (g3, TRUE, change_notify, change_userdata);
 
-  RadioButton (dlg->cap_change, "No change");
-  RadioButton (dlg->cap_change, "To lower");
-  RadioButton (dlg->cap_change, "To upper");
-  RadioButton (dlg->cap_change, "First cap, rest lower");
-  SetValue (dlg->cap_change, 1);
+  g1 = HiddenGroup (p, 2, 0, NULL);
+  StaticPrompt (g1, "From", 0, dialogTextHeight, systemFont, 'r');
+  dlg->src = ParseSrcDialog (g1, change_notify, change_userdata);
+  g2 = HiddenGroup (p, 2, 0, NULL);
+  StaticPrompt (g2, "And place in", 0, dialogTextHeight, systemFont, 'r');
+  dlg->dst = ParseDstDialog (g2, change_notify, change_userdata);
+  dlg->cap_change = CapChangeDialog (p, NULL, NULL);
 
   dlg->remove_from_parsed = CheckBox (p, "Remove from parsed field", NULL);
 
@@ -13207,8 +14288,8 @@ ParseActionDialogEx
 
   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->cap_change,
                               (HANDLE) dlg->remove_from_parsed,
-                              (HANDLE) dlg->text_portion,
-                              (HANDLE) g,
+                              (HANDLE) g3,
+                              (HANDLE) g1, (HANDLE) g2,
                               (HANDLE) dlg->existing_text,
                               NULL);
 
@@ -13292,6 +14373,7 @@ static void RunMacroInEditor (ButtoN b)
   Uint2       entityID;
   Int4        num_fields = 0, num_features = 0;
   Int4        tmp_fields, tmp_features;
+  LogInfoPtr  lip;
 
   e = (EditMacroActionPtr) GetObjectExtra (b);
   if (e == NULL) return;
@@ -13336,6 +14418,31 @@ static void RunMacroInEditor (ButtoN b)
       action->choice = MacroActionChoice_autodef;
       action->data.ptrvalue = DialogToPointer (e->action_dlg);
       break;
+    case 15:
+      action->choice = MacroActionChoice_removesets;
+      action->data.ptrvalue = DialogToPointer (e->action_dlg);
+      break;
+    case 16:
+      action->choice = MacroActionChoice_trim_junk_from_primer_seq;
+      break;
+    case 17:
+      action->choice = MacroActionChoice_fix_usa_and_states;
+      break;
+    case 18:
+      action->choice = MacroActionChoice_trim_stop_from_complete_cds;
+      break;
+    case 19:
+      action->choice = MacroActionChoice_synchronize_cds_partials;
+      break;
+    case 20:
+      action->choice = MacroActionChoice_adjust_for_consensus_splice;
+      break;
+    case 21:
+      action->choice = MacroActionChoice_fix_pub_caps;
+      break;
+    case 22:
+      action->choice = MacroActionChoice_remove_seg_gaps;
+      break;
   }
 
   sep_list = GetViewedSeqEntryList ();
@@ -13347,12 +14454,13 @@ static void RunMacroInEditor (ButtoN b)
   } else {
     WatchCursor();
     Update();
+    lip = OpenLog ("Macro Actions");
     for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
       sep = vnp->data.ptrvalue;
       entityID = ObjMgrGetEntityIDForChoice(sep);
       tmp_fields = 0;
       tmp_features = 0;
-      ApplyMacroToSeqEntry (sep, action, &tmp_fields, &tmp_features);
+      lip->data_in_log |= ApplyMacroToSeqEntryEx (sep, action, &tmp_fields, &tmp_features, lip->fp);
       num_fields += tmp_fields;
       num_features += tmp_features;
       ObjMgrSetDirtyFlag (entityID, TRUE);
@@ -13362,6 +14470,12 @@ static void RunMacroInEditor (ButtoN b)
     ArrowCursor ();
     Update ();  
     Message (MSG_OK, "Macro action affected %d fields and created %d features", num_fields, num_features); 
+    if (!lip->data_in_log) {
+      fprintf (lip->fp, "Macro had no effect\n");
+      lip->data_in_log = TRUE;
+    }
+    CloseLog (lip);
+    lip = FreeLog (lip);
   }  
 
   action = MacroActionChoiceFree (action);
@@ -13479,6 +14593,7 @@ BuildEditMacroActionWindow
   ParseActionPtr        parse = NULL;
   RemoveDescriptorActionPtr remove_desc = NULL;
   AutodefActionPtr      autodef = NULL;
+  FixPubCapsActionPtr   fix_pubs = NULL;
   WindoW                w;
   GrouP                 h, c;
   ButtoN                b;
@@ -13508,6 +14623,14 @@ BuildEditMacroActionWindow
   PopupItem (d->action_type, "Convert Feature");
   PopupItem (d->action_type, "Remove Descriptor");
   PopupItem (d->action_type, "Autodef");
+  PopupItem (d->action_type, "Remove Duplicate Nested Sets");
+  PopupItem (d->action_type, "Trim Junk in Primer Seqs");
+  PopupItem (d->action_type, "Fix USA and state abbreviations in publications");
+  PopupItem (d->action_type, "Remove trailing * from Coding Regions");
+  PopupItem (d->action_type, "Synchronize Coding Region Partials");
+  PopupItem (d->action_type, "Adjust coding regions for consensus splice sites");
+  PopupItem (d->action_type, "Fix publication capitalization");
+  PopupItem (d->action_type, "Remove Seg-gaps");
 
   if (d->action_copy == NULL) {
     SetValue (d->action_type, 1);
@@ -13574,6 +14697,31 @@ BuildEditMacroActionWindow
         SetValue (d->action_type, 14);
         autodef = (AutodefActionPtr) d->action_copy->data.ptrvalue;
         break;
+      case MacroActionChoice_removesets:
+        SetValue (d->action_type, 15);
+        break;
+      case MacroActionChoice_trim_junk_from_primer_seq:
+        SetValue (d->action_type, 16);
+        break;
+      case MacroActionChoice_fix_usa_and_states:
+        SetValue (d->action_type, 17);
+        break;
+      case MacroActionChoice_trim_stop_from_complete_cds:
+        SetValue (d->action_type, 18);
+        break;
+      case MacroActionChoice_synchronize_cds_partials:
+        SetValue (d->action_type, 19);
+        break;
+      case MacroActionChoice_adjust_for_consensus_splice:
+        SetValue (d->action_type, 20);
+        break;
+      case MacroActionChoice_fix_pub_caps:
+        SetValue (d->action_type, 21);
+        fix_pubs = (FixPubCapsActionPtr) d->action_copy->data.ptrvalue;
+        break;
+      case MacroActionChoice_remove_seg_gaps:
+        SetValue (d->action_type, 22);
+        break;
       default:
         SetValue (d->action_type, 1);
         break;
@@ -13621,7 +14769,12 @@ BuildEditMacroActionWindow
     case 14:
       d->action_dlg = AutodefActionDialog (h, d->indexer_version, EnableEditMacroActionAccept, d);
       break;
+    case 21: 
+      d->action_dlg = FixPubCapsDialog (h, d->indexer_version, EnableEditMacroActionAccept, d);
+      PointerToDialog (d->action_dlg, fix_pubs);
+      break;
   }
+
   c = HiddenGroup (h, 4, 0, NULL);
   SetGroupSpacing (c, 10, 10);
   d->accept_btn = PushButton (c, "Accept", ModalAcceptButton);
@@ -13731,6 +14884,31 @@ static Boolean EditMacroAction (ValNodePtr action, Boolean indexer_version)
           d.action_copy = ValNodeNew (NULL);
           d.action_copy->choice = MacroActionChoice_autodef;
           d.action_copy->data.ptrvalue = BuildDefaultAutodefAction ();
+        } else if (action_type == 15) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_removesets;
+        } else if (action_type == 16) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_trim_junk_from_primer_seq;
+        } else if (action_type == 17) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_fix_usa_and_states;
+        } else if (action_type == 18) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_trim_stop_from_complete_cds;
+        } else if (action_type == 19) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_synchronize_cds_partials;
+        } else if (action_type == 20) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_adjust_for_consensus_splice;
+        } else if (action_type == 21) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_fix_pub_caps;
+          d.action_copy->data.ptrvalue = FixPubCapsActionNew();
+        } else if (action_type == 22) {
+          d.action_copy = ValNodeNew (NULL);
+          d.action_copy->choice = MacroActionChoice_remove_seg_gaps;
         }
       }
 
@@ -13773,6 +14951,30 @@ static Boolean EditMacroAction (ValNodePtr action, Boolean indexer_version)
       case MacroActionChoice_autodef:
         action->data.ptrvalue = AutodefActionFree (action->data.ptrvalue);
         break;
+      case MacroActionChoice_removesets:
+        action->data.ptrvalue = NULL;
+        break;
+      case MacroActionChoice_trim_junk_from_primer_seq:
+        action->data.ptrvalue = NULL;
+        break;
+      case MacroActionChoice_fix_usa_and_states:
+        action->data.ptrvalue = NULL;
+        break;
+      case MacroActionChoice_trim_stop_from_complete_cds:
+        action->data.ptrvalue = NULL;
+        break;
+      case MacroActionChoice_synchronize_cds_partials:
+        action->data.ptrvalue = NULL;
+        break;
+      case MacroActionChoice_adjust_for_consensus_splice:
+        action->data.ptrvalue = NULL;
+        break;
+      case MacroActionChoice_fix_pub_caps:
+        action->data.ptrvalue = FixPubCapsActionFree(action->data.ptrvalue);
+        break;
+      case MacroActionChoice_remove_seg_gaps:
+        action->data.ptrvalue = NULL;
+        break;
     }
     switch (GetValue (d.action_type)) {
       case 1:
@@ -13813,6 +15015,38 @@ static Boolean EditMacroAction (ValNodePtr action, Boolean indexer_version)
         action->choice = MacroActionChoice_autodef;
         action->data.ptrvalue = DialogToPointer (d.action_dlg);
         break;
+      case 15:
+        action->choice = MacroActionChoice_removesets;
+        action->data.ptrvalue = NULL;
+        break;
+      case 16:
+        action->choice = MacroActionChoice_trim_junk_from_primer_seq;
+        action->data.ptrvalue = NULL;
+        break;
+      case 17:
+        action->choice = MacroActionChoice_fix_usa_and_states;
+        action->data.ptrvalue = NULL;
+        break;
+      case 18:
+        action->choice = MacroActionChoice_trim_stop_from_complete_cds;
+        action->data.ptrvalue = NULL;
+        break;
+      case 19:
+        action->choice = MacroActionChoice_synchronize_cds_partials;
+        action->data.ptrvalue = NULL;
+        break;
+      case 20:
+        action->choice = MacroActionChoice_adjust_for_consensus_splice;
+        action->data.ptrvalue = NULL;
+        break;
+      case 21:
+        action->choice = MacroActionChoice_fix_pub_caps;
+        action->data.ptrvalue = DialogToPointer (d.action_dlg);
+        break;
+      case 22:
+        action->choice = MacroActionChoice_remove_seg_gaps;
+        action->data.ptrvalue = NULL;
+        break;
     }
   }
   Remove (w);
@@ -13914,6 +15148,38 @@ static void AddMacroActions (MacroEditorFormPtr f, Int2 item)
             d.action_copy = ValNodeNew (NULL);
             d.action_copy->choice = MacroActionChoice_autodef;
             d.action_copy->data.ptrvalue = BuildDefaultAutodefAction();
+          } else if (action_type == 15) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_removesets;
+            d.action_copy->data.ptrvalue = NULL;
+          } else if (action_type == 16) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_trim_junk_from_primer_seq;
+            d.action_copy->data.ptrvalue = NULL;
+          } else if (action_type == 17) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_fix_usa_and_states;
+            d.action_copy->data.ptrvalue = NULL;
+          } else if (action_type == 18) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_trim_stop_from_complete_cds;
+            d.action_copy->data.ptrvalue = NULL;
+          } else if (action_type == 19) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_synchronize_cds_partials;
+            d.action_copy->data.ptrvalue = NULL;
+          } else if (action_type == 20) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_adjust_for_consensus_splice;
+            d.action_copy->data.ptrvalue = NULL;
+          } else if (action_type == 21) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_fix_pub_caps;
+            d.action_copy->data.ptrvalue = FixPubCapsActionNew();
+          } else if (action_type == 22) {
+            d.action_copy = ValNodeNew (NULL);
+            d.action_copy->choice = MacroActionChoice_remove_seg_gaps;
+            d.action_copy->data.ptrvalue = NULL;
           }
         }
 
@@ -13985,6 +15251,38 @@ static void AddMacroActions (MacroEditorFormPtr f, Int2 item)
           new_action->choice = MacroActionChoice_autodef;
           new_action->data.ptrvalue = DialogToPointer (d.action_dlg);
           break;
+        case 15:
+          new_action->choice = MacroActionChoice_removesets;
+          new_action->data.ptrvalue = NULL;
+          break;
+        case 16:
+          new_action->choice = MacroActionChoice_trim_junk_from_primer_seq;
+          new_action->data.ptrvalue = NULL;
+          break;
+        case 17:
+          new_action->choice = MacroActionChoice_fix_usa_and_states;
+          new_action->data.ptrvalue = NULL;
+          break;
+        case 18:
+          new_action->choice = MacroActionChoice_trim_stop_from_complete_cds;
+          new_action->data.ptrvalue = NULL;
+          break;
+        case 19:
+          new_action->choice = MacroActionChoice_synchronize_cds_partials;
+          new_action->data.ptrvalue = NULL;
+          break;
+        case 20:
+          new_action->choice = MacroActionChoice_adjust_for_consensus_splice;
+          new_action->data.ptrvalue = NULL;
+          break;
+        case 21:
+          new_action->choice = MacroActionChoice_fix_pub_caps;
+          new_action->data.ptrvalue = DialogToPointer (d.action_dlg);
+          break;
+        case 22:
+          new_action->choice = MacroActionChoice_remove_seg_gaps;
+          new_action->data.ptrvalue = NULL;
+          break;
       }
       /* add action to macro list */
       if (prev_action == NULL) {
@@ -15130,7 +16428,6 @@ static void ChangeSingleMacroActionPopup (PopuP p)
   OneMacroActionPtr d;
   Int2              val;
   Int4              i;
-  ValNodePtr        rna_type = NULL;
 
   d = (OneMacroActionPtr) GetObjectExtra (p);
   if (d == NULL || d->no_callback) return;
@@ -15848,9 +17145,9 @@ SingleMacroAction (Uint2 entityID, Boolean indexer_version)
   g5 = HiddenGroup (h, 0, 0, NULL);
   /* temporarily shut off callbacks */
   frm->no_callback = TRUE;
-  frm->action_dlgs[0] = ApplyActionDialog (g5, frm->indexer_version, FALSE, AutopopulateSingleMacroDialog, frm, EnableSingleMacroActionAccept, frm, EnableSingleMacroActionAccept, frm);
+  frm->action_dlgs[0] = ApplyActionDialog (g5, frm->indexer_version, FALSE, (Nlm_ChangeNotifyProc) AutopopulateSingleMacroDialog, frm, EnableSingleMacroActionAccept, frm, EnableSingleMacroActionAccept, frm);
   SetAECRActionDlgFieldTypeDialogs (frm->action_dlgs[0], frm->single_qual_type_dlg, frm->single_field);
-  frm->action_dlgs[1] = EditActionDialog (g5, frm->indexer_version, AutopopulateSingleMacroDialog, frm, EnableSingleMacroActionAccept, frm, EnableSingleMacroActionAccept, frm);
+  frm->action_dlgs[1] = EditActionDialog (g5, frm->indexer_version, (Nlm_ChangeNotifyProc) AutopopulateSingleMacroDialog, frm, EnableSingleMacroActionAccept, frm, EnableSingleMacroActionAccept, frm);
   SetAECRActionDlgFieldTypeDialogs (frm->action_dlgs[1], frm->single_qual_type_dlg, frm->single_field);
   frm->action_dlgs[2] = ConvertActionDialog (g5, frm->indexer_version, FALSE, EnableSingleMacroActionAccept, frm, EnableSingleMacroActionAccept, frm);
   SetAECRActionDlgFieldTypeDialogs (frm->action_dlgs[2], frm->pair_qual_type_dlg, frm->field_pair_convert);
@@ -16029,8 +17326,8 @@ static void ClearTextSingleParseAction (ButtoN b)
   parse = DialogToPointer (frm->dlg);
 
   if (parse != NULL && parse->portion != NULL) {
-    parse->portion->left_text = MemFree (parse->portion->left_text);
-    parse->portion->right_text = MemFree (parse->portion->right_text);
+    parse->portion->left_marker = TextMarkerFree (parse->portion->left_marker);
+    parse->portion->right_marker = TextMarkerFree (parse->portion->right_marker);
     PointerToDialog (frm->dlg, parse);
     parse = ParseActionFree (parse);
     ChangeSingleParseAction (frm);
@@ -16168,1202 +17465,6 @@ NLM_EXTERN ForM SingleParseAction (Uint2 entityID)
 
 /* Functions for summarizing macro actions for display */
 
-static CharPtr SummarizeExistingText (Uint2 existing_text)
-{
-  CharPtr str = NULL;
-
-  switch (existing_text) {
-    case ExistingTextOption_append_semi :
-      str = "append separated by semicolon";
-      break;
-    case ExistingTextOption_append_space :
-      str = "append separated by space";
-      break;
-    case ExistingTextOption_append_colon :
-      str = "append separated by colon";
-      break;
-    case ExistingTextOption_append_none :
-      str = "append (no separator)";
-      break;
-    case ExistingTextOption_prefix_semi :
-      str = "prefix separated by semicolon";
-      break;
-    case ExistingTextOption_prefix_space :
-      str = "prefix separated by space";
-      break;
-    case ExistingTextOption_prefix_colon :
-      str = "prefix separated by colon";
-      break;
-    case ExistingTextOption_prefix_none :
-      str = "prefix (no separator)";
-      break;
-    case ExistingTextOption_leave_old :
-      str = "ignore new text when existing text is present";
-      break;
-    case ExistingTextOption_replace_old :
-      str = "overwrite existing text";
-      break;
-    case ExistingTextOption_add_qual :
-      str = "add new qual";
-      break;
-    default:
-      str = "invalid existing_text option";
-      break;
-  }
-  return str;    
-}
-
-
-static CharPtr GetStringLocationPhrase (Uint2 match_location, Boolean not_present)
-{
-  CharPtr location_word = NULL;
-
-  switch (match_location) {
-    case String_location_contains :
-      if (not_present) {
-        location_word = "does not contain";
-      } else {
-        location_word = "contains";
-      }
-      break;
-    case String_location_equals :
-      if (not_present) {
-        location_word = "does not equal";
-      } else {
-        location_word = "equals";
-      }
-      break;
-    case String_location_starts :
-      if (not_present) {
-        location_word = "does not start with";
-      } else {
-        location_word = "starts with";
-      }
-      break;
-    case String_location_ends :
-      if (not_present) {
-        location_word = "does not end with";
-      } else {
-        location_word = "ends with";
-      }
-      break;
-    case String_location_inlist :
-      if (not_present) {
-        location_word = "is not one of";
-      } else {
-        location_word = "is one of";
-      }
-      break;
-  }
-  return location_word;
-}
-
-
-/* summarizing constraints */
-static CharPtr SummarizeStringConstraint (StringConstraintPtr constraint)
-{
-  CharPtr location_word = NULL;
-  CharPtr case_sensitive = "case-sensitive";
-  CharPtr whole_word = "whole word";
-  CharPtr str = NULL;
-  Int4 len;
-  CharPtr fmt = "%s '%s'";
-
-  if (constraint == NULL || constraint->match_text == NULL) return NULL;
-
-  location_word = GetStringLocationPhrase (constraint->match_location, constraint->not_present);
-  if (location_word == NULL) return NULL;
-  len = StringLen (location_word) + StringLen (constraint->match_text) + StringLen (fmt);
-  if (constraint->case_sensitive) {
-    len += StringLen (case_sensitive) + 3;
-  }
-  if (constraint->whole_word) {
-    len += StringLen (whole_word) + 3;
-  }
-  str = (CharPtr) MemNew (sizeof (Char) * len);
-  sprintf (str, fmt, location_word, constraint->match_text);
-  if (constraint->case_sensitive || constraint->whole_word) {
-    StringCat (str, " (");
-  }
-  if (constraint->case_sensitive) {
-    StringCat (str, case_sensitive);
-    if (constraint->whole_word) {
-      StringCat (str, ", ");
-    }
-  }
-  if (constraint->whole_word) {
-    StringCat (str, whole_word);
-  }
-  if (constraint->case_sensitive || constraint->whole_word) {
-    StringCat (str, ")");
-  }
-
-  return str;
-}
-
-
-static CharPtr SummarizePartialnessForLocationConstraint (LocationConstraintPtr constraint)
-{
-  if (constraint == NULL 
-      || (constraint->partial5 == Partial_constraint_either
-      && constraint->partial3 == Partial_constraint_either)) {
-    return NULL;
-  }
-  if (constraint->partial5 == Partial_constraint_either) {
-    if (constraint->partial3 == Partial_constraint_partial) {
-      return "that are 3' partial";
-    } else {
-      return "that are 3' complete";
-    }
-  } else if (constraint->partial3 == Partial_constraint_either) {
-    if (constraint->partial5 == Partial_constraint_partial) {
-      return "that are 5' partial";
-    } else {
-      return "that are 5' complete";
-    }
-  } else if (constraint->partial5 == Partial_constraint_partial
-             && constraint->partial3 == Partial_constraint_partial) {
-    return "that are partial on both ends";
-  } else if (constraint->partial5 == Partial_constraint_complete
-             && constraint->partial3 == Partial_constraint_complete) {
-    return "that are complete on both ends";
-  } else if (constraint->partial5 == Partial_constraint_complete
-             && constraint->partial3 == Partial_constraint_partial) {
-    return "that are 5' complete and 3' partial";
-  } else if (constraint->partial5 == Partial_constraint_partial
-             && constraint->partial3 == Partial_constraint_complete) {
-    return "that are 5' partial and 3' complete";
-  } else {
-    return NULL;
-  }
-}
-
-static CharPtr SummarizeLocationConstraint (LocationConstraintPtr constraint)
-{
-  CharPtr str = NULL;
-  CharPtr strand_word = NULL, seq_word = NULL;
-  CharPtr fmt = "only objects";
-  CharPtr partial;
-  Int4    len = 0;
-
-  if (IsLocationConstraintEmpty (constraint)) {
-    return NULL;
-  }
-
-  partial = SummarizePartialnessForLocationConstraint (constraint);
-
-  if (constraint->seq_type == Seqtype_constraint_nuc) {
-    seq_word = "nucleotide sequences";
-  } else if (constraint->seq_type == Seqtype_constraint_prot) {
-    seq_word = "protein sequences";
-  }
-
-  if (constraint->strand == Strand_constraint_plus) {
-    strand_word = " on plus strands";
-  } else if (constraint->strand == Strand_constraint_minus) {
-    strand_word = " on minus strands";
-  }
-
-  len = StringLen (fmt) + 1;
-  if (strand_word != NULL) {
-    len += StringLen (strand_word);
-  }
-  if (seq_word != NULL) {
-    len += StringLen (seq_word) + 4;
-  }
-  if (partial != NULL) {
-    len += StringLen (partial) + 2;
-  }
-  str = (CharPtr) MemNew (sizeof (Char) * len);
-  sprintf (str, fmt);
-  if (strand_word == NULL && seq_word != NULL) {
-    StringCat (str, " on ");
-    StringCat (str, seq_word);
-  } else if (strand_word != NULL) {
-    StringCat (str, strand_word);
-    if (seq_word != NULL) {
-      StringCat (str, " of ");
-      StringCat (str, seq_word);
-    }
-  }
-  if (partial != NULL) {
-    StringCat (str, " ");
-    StringCat (str, partial);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeSourceConstraint (SourceConstraintPtr constraint)
-{
-  CharPtr string, intro = NULL, field1, field2;
-  CharPtr match_fmt = "%s %s matches %s";
-  CharPtr present_fmt = "%s %s is present";
-  CharPtr text_fmt = "%s text %s";
-  CharPtr two_match_fmt = "%s %s matches %s and %s %s";
-  CharPtr one_match_fmt = "%s %s %s";
-  CharPtr summ = NULL;
-
-  if (constraint == NULL) return NULL;
-
-  string = SummarizeStringConstraint (constraint->constraint);
-  field1 = SummarizeSourceQual (constraint->field1);
-  field2 = SummarizeSourceQual (constraint->field2);
-
-  if (constraint->field1 == NULL && constraint->field2 == NULL && string == NULL) {
-    if (constraint->type_constraint == Object_type_constraint_feature) {
-      summ = StringSave ("where source is a feature");
-    } else if (constraint->type_constraint == Object_type_constraint_descriptor) {
-      summ = StringSave ("where source is a descriptor");
-    }
-  } else { 
-    if (constraint->type_constraint == Object_type_constraint_any) {
-      intro = "where source";
-    } else if (constraint->type_constraint == Object_type_constraint_feature) {
-      intro = "where source feature";
-    } else if (constraint->type_constraint == Object_type_constraint_descriptor) {
-      intro = "where source descriptor";
-    } else {
-      string = MemFree (string);
-      field1 = MemFree (field1);
-      field2 = MemFree (field2);
-      return NULL;
-    }
-
-    if (string == NULL) {
-      if (field1 == NULL && field2 == NULL) {
-        if (constraint->type_constraint == Object_type_constraint_feature) {
-          summ = StringSave ("where source is a feature");
-        } else if (constraint->type_constraint == Object_type_constraint_descriptor) {
-          summ = StringSave ("where source is a descriptor");
-        }
-      } else if (field1 != NULL && field2 != NULL) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (match_fmt) + StringLen (intro) + StringLen (field1) + StringLen (field2)));
-        sprintf (summ, match_fmt, intro, field1, field2);
-      } else if (field1 != NULL) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (intro) + StringLen (field1)));
-        sprintf (summ, present_fmt, intro, field1);
-      } else if (field2 != NULL) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (intro) + StringLen (field2)));
-        sprintf (summ, present_fmt, intro, field2);
-      }
-    } else {
-      if (field1 == NULL && field2 == NULL) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (text_fmt) + StringLen (intro) + StringLen (string)));
-        sprintf (summ, text_fmt, intro, string);
-      } else if (field1 != NULL && field2 != NULL) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (two_match_fmt) + StringLen (intro) 
-                                                   + 2 * StringLen (field1) + StringLen (field2) + StringLen (string)));
-        sprintf (summ, two_match_fmt, intro, field1, field2, field1, string);
-      } else if (field1 != NULL) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (intro) + StringLen (field1) + StringLen (string)));
-        sprintf (summ, one_match_fmt, intro, field1, string);
-      } else if (field2 != NULL) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (intro) + StringLen (field2) + StringLen (string)));
-        sprintf (summ, one_match_fmt, intro, field2, string);
-      }
-    }
-  }
-  string = MemFree (string);
-  field1 = MemFree (field1);
-  field2 = MemFree (field2);
-  return summ;
-}
-
-
-
-static CharPtr SummarizeCDSGeneProtPseudoConstraint (CDSGeneProtPseudoConstraintPtr constraint)
-{
-  CharPtr summ = NULL, pseudo_feat;
-  CharPtr is_pseudo_fmt = "where %s is pseudo";
-  CharPtr not_pseudo_fmt = "where %s is not pseudo";
-
-  if (constraint != NULL) {
-    pseudo_feat = CDSGeneProtFeatureNameFromFeatureType (constraint->feature);
-    if (pseudo_feat != NULL) {
-      if (constraint->is_pseudo) {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (is_pseudo_fmt) + StringLen (pseudo_feat)));
-        sprintf (summ, is_pseudo_fmt, pseudo_feat);
-      } else {
-        summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (not_pseudo_fmt) + StringLen (pseudo_feat)));
-        sprintf (summ, not_pseudo_fmt, pseudo_feat);
-      }
-    }
-  }
-     
-  return summ;
-}
-
-
-static CharPtr SummarizeCDSGeneProtQualConstraint (CDSGeneProtQualConstraintPtr constraint)
-{
-  CharPtr string, field1 = NULL, field2 = NULL;
-  CharPtr match_fmt = "where %s matches %s";
-  CharPtr present_fmt = "where %s is present";
-  CharPtr text_fmt = "where CDS-gene-prot text %s";
-  CharPtr two_match_fmt = "where %s matches %s and %s %s";
-  CharPtr one_match_fmt = "where %s %s";
-  CharPtr summ = NULL;
-
-  if (constraint == NULL) return NULL;
-
-  string = SummarizeStringConstraint (constraint->constraint);
-  if (constraint->field1 != NULL && constraint->field1->choice == CDSGeneProtConstraintField_field) {
-    field1 = CDSGeneProtNameFromField (constraint->field1->data.intvalue);
-  }
-  if (constraint->field2 != NULL && constraint->field2->choice == CDSGeneProtConstraintField_field) {
-    field2 = CDSGeneProtNameFromField (constraint->field2->data.intvalue);
-  }
-
-  if (string == NULL) {
-    if (field1 != NULL && field2 != NULL) {
-      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (match_fmt) + StringLen (field1) + StringLen (field2)));
-      sprintf (summ, match_fmt, field1, field2);
-    } else if (field1 != NULL) {
-      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (field1)));
-      sprintf (summ, present_fmt, field1);
-    } else if (field2 != NULL) {
-      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (present_fmt) + StringLen (field2)));
-      sprintf (summ, present_fmt, field2);
-    }
-  } else {
-    if (field1 == NULL && field2 == NULL) {
-      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (text_fmt) + StringLen (string)));
-      sprintf (summ, text_fmt, string);
-    } else if (field1 != NULL && field2 != NULL) {
-      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (two_match_fmt)  
-                                                  + 2 * StringLen (field1) + StringLen (field2) + StringLen (string)));
-      sprintf (summ, two_match_fmt, field1, field2, field1, string);
-    } else if (field1 != NULL) {
-      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (field1) + StringLen (string)));
-      sprintf (summ, one_match_fmt, field1, string);
-    } else if (field2 != NULL) {
-      summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (one_match_fmt) + StringLen (field2) + StringLen (string)));
-      sprintf (summ, one_match_fmt, field2, string);
-    }
-  }
-  
-  string = MemFree (string);
-  /* note - field1 and field2 aren't allocated, so we don't need to free them */
-
-  return summ;
-}
-
-
-static CharPtr SummarizeSequenceConstraint (SequenceConstraintPtr constraint)
-{
-  CharPtr summ = NULL;
-  CharPtr seq_word = NULL, featpresent = NULL, id = NULL;
-  Int4    len = 0;
-  CharPtr seq_word_intro = "where sequence type is ";
-  CharPtr feat_after = " is present";
-  CharPtr id_intro = "sequence ID ";
-  
-  if (IsSequenceConstraintEmpty (constraint)) {
-    summ = StringSave ("Missing sequence constraint");
-  } else {
-    if (constraint->seqtype != NULL && constraint->seqtype->choice != SequenceConstraintMolTypeConstraint_any) {
-      switch (constraint->seqtype->choice) {
-        case SequenceConstraintMolTypeConstraint_nucleotide:
-          seq_word = "nucleotide";
-          break;
-        case SequenceConstraintMolTypeConstraint_dna:
-          seq_word = "DNA";
-          break;
-        case SequenceConstraintMolTypeConstraint_rna:
-          if (constraint->seqtype->data.intvalue == Sequence_constraint_rnamol_any) {
-            seq_word = "RNA";
-          } else {
-            seq_word = GetBiomolNameForRnaType (constraint->seqtype->data.intvalue);
-          }
-          break;
-        case SequenceConstraintMolTypeConstraint_protein:
-          seq_word = "protein";
-          break;
-      }
-    }
-
-    if (constraint->feature != Feature_type_any) {
-      featpresent = GetFeatureNameFromFeatureType (constraint->feature);
-    }
-
-    if (!IsStringConstraintEmpty (constraint->id)) {
-      id = SummarizeStringConstraint (constraint->id);
-    }
- 
-    if (seq_word != NULL) {
-      len += StringLen (seq_word) + StringLen (seq_word_intro);
-    }
-
-    if (featpresent != NULL) {
-      if (len == 0) {
-        len += 6;
-      } else {
-        len += 5;
-      }
-      len += StringLen (featpresent);
-      len += StringLen (feat_after);
-    }
-
-    if (id != NULL) {
-      if (len == 0) {
-        len += 6;
-      } else {
-        len += 5;
-      }
-      len += StringLen (id_intro);
-      len += StringLen (id);
-    }
-
-    if (len == 0) {
-      summ = StringSave ("missing sequence constraint");
-    } else {
-      len++;
-      summ = (CharPtr) MemNew (sizeof (Char) * len);
-      summ[0] = 0;
-      if (seq_word != NULL) {
-        StringCat (summ, seq_word_intro);
-        StringCat (summ, seq_word);
-      }
-      if (featpresent != NULL) {
-        if (seq_word == NULL) {
-          StringCat (summ, "where ");
-        } else {
-          StringCat (summ, " and ");
-        }
-        StringCat (summ, featpresent);
-        StringCat (summ, feat_after);
-      }
-      if (id != NULL) {
-        if (seq_word == NULL && featpresent == NULL) {
-          StringCat (summ, "where ");
-        } else {
-          StringCat (summ, " and ");
-        }
-        StringCat (summ, id_intro);
-        StringCat (summ, id);
-      }
-    }
-    id = MemFree (id);
-  }
-  return summ;
-}
-
-static CharPtr SummarizePublicationConstraint (PublicationConstraintPtr constraint)
-{
-  CharPtr rval = NULL;
-  CharPtr type = NULL, string = NULL, label = NULL;
-  CharPtr type_and_field_fmt = "%s and %s %s";
-  CharPtr fmt = "where %s %s";
-
-  if (IsPublicationConstraintEmpty (constraint)) return NULL;
-
-  switch (constraint->type) {
-    case Pub_type_published:
-      type = "where pub is published";
-      break;
-    case Pub_type_unpublished:
-      type = "where pub is unpublished";
-      break;
-    case Pub_type_in_press:
-      type = "where pub is in press";
-      break;
-    case Pub_type_submitter_block:
-      type = "where pub is submitter block";
-      break;
-  }
-  if (constraint->field != NULL) {
-    string = SummarizeStringConstraint (constraint->field->constraint);
-    label = GetPubFieldLabel (constraint->field->field);
-  }
-
-  if (type != NULL && string != NULL && label != NULL) {
-    rval = (CharPtr) MemNew (sizeof (Char) * (StringLen (type_and_field_fmt) + StringLen (type) + StringLen (label) + StringLen (string)));
-    sprintf (rval, fmt, label, string);
-  } else if (string != NULL && label != NULL) {
-    rval = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (label) + StringLen (string)));
-    sprintf (rval, fmt, label, string);
-  } else if (type != NULL) {
-    rval = StringSave (type);
-  }    
-  string = MemFree (string);
-
-  return rval;
-}
-
-
-static CharPtr SummarizeFieldConstraint (FieldConstraintPtr constraint)
-{
-  CharPtr rval = NULL;
-  CharPtr string = NULL, label = NULL;
-  CharPtr fmt = "where %s %s";
-
-  if (IsFieldConstraintEmpty (constraint)) return NULL;
-
-  string = SummarizeStringConstraint (constraint->string_constraint);
-  label = SummarizeFieldType (constraint->field);
-
-  if (string != NULL && label != NULL) {
-    rval = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (label) + StringLen (string)));
-    sprintf (rval, fmt, label, string);
-  }    
-  string = MemFree (string);
-  label = MemFree (label);
-
-  return rval;
-}
-
-
-static CharPtr SummarizeConstraint (ValNodePtr constraint)
-{
-  CharPtr phrase = NULL, tmp;
-  CharPtr fmt = "where object text %s";
-
-  if (constraint == NULL) return NULL;
-  switch (constraint->choice) {
-    case ConstraintChoice_string:
-      tmp = SummarizeStringConstraint (constraint->data.ptrvalue);
-      if (tmp != NULL) {
-        phrase = (CharPtr) MemNew (sizeof (Char) * (StringLen (tmp) + StringLen (fmt)));
-        sprintf (phrase, fmt, tmp);
-        tmp = MemFree (tmp);
-      }
-      break;
-    case ConstraintChoice_location:
-      phrase = SummarizeLocationConstraint (constraint->data.ptrvalue);
-      break;
-    case ConstraintChoice_source:
-      phrase = SummarizeSourceConstraint (constraint->data.ptrvalue);
-      break;
-    case ConstraintChoice_cdsgeneprot_qual:
-      phrase = SummarizeCDSGeneProtQualConstraint (constraint->data.ptrvalue);
-      break;
-    case ConstraintChoice_cdsgeneprot_pseudo:
-      phrase = SummarizeCDSGeneProtPseudoConstraint (constraint->data.ptrvalue);
-      break;
-    case ConstraintChoice_sequence:
-      phrase = SummarizeSequenceConstraint (constraint->data.ptrvalue);
-      break;
-    case ConstraintChoice_pub:
-      phrase = SummarizePublicationConstraint (constraint->data.ptrvalue);
-      break;
-    case ConstraintChoice_field:
-      phrase = SummarizeFieldConstraint (constraint->data.ptrvalue);
-      break;
-  }
-  return phrase;
-}
-
-
-static CharPtr SummarizeConstraintSet (ValNodePtr constraint_set)
-{
-  ValNodePtr phrases = NULL, vnp;
-  Int4 len = 0;
-  CharPtr phrase, str = NULL;
-
-  while (constraint_set != NULL) {
-    phrase = SummarizeConstraint (constraint_set);
-    if (phrase != NULL) {
-      ValNodeAddPointer (&phrases, 0, phrase);
-      if (len > 0) {
-        len += 5; /* for " and " */
-      } else {
-        len += 1; /* for terminal NULL */
-      }
-      len += StringLen (phrase);
-    }
-    constraint_set = constraint_set->next;
-  }
-  if (len > 0) {
-    str = (CharPtr) MemNew (sizeof (Char) * len);
-    for (vnp = phrases; vnp != NULL; vnp = vnp->next) {
-      StringCat (str, vnp->data.ptrvalue);
-      if (vnp->next != NULL) {
-        StringCat (str, " and ");
-      }
-    }
-  }
-  return str;
-}
-
-/* summarizing AECR actions */
-static CharPtr SummarizeFieldPairType (ValNodePtr vnp, CharPtr connect_word)
-{
-  FeatureFieldPairPtr ffp;
-  CDSGeneProtFieldPairPtr cgp;
-  SourceQualPairPtr     quals;
-  MolinfoFieldPairPtr   m_fields;
-  RnaQualPairPtr        rna_quals;
-  CharPtr str = NULL;
-  CharPtr from_label = NULL, to_label = NULL;
-  CharPtr label_fmt = "%s %s %s";
-  CharPtr type_label_fmt = "%s %s %s %s";
-  CharPtr    label = NULL;
-
-  if (connect_word == NULL) {
-    connect_word = "to";
-  }
-  if (vnp == NULL) {
-    str = StringSave ("missing field");
-  } else {
-    switch (vnp->choice) {
-      case FieldPairType_source_qual:
-        if (vnp->data.ptrvalue != NULL) {
-          quals = (SourceQualPairPtr) vnp->data.ptrvalue;
-          from_label = GetSourceQualName (quals->field_from);
-          to_label = GetSourceQualName (quals->field_to);
-        }
-        if (from_label != NULL && to_label != NULL) {
-          str = (CharPtr) MemNew (sizeof (Char) *
-                                  (StringLen (from_label) + StringLen (connect_word) + StringLen (to_label)
-                                  + 3));
-          sprintf (str, "%s %s %s", from_label, connect_word, to_label);
-        } else {
-          str = StringSave ("missing field");
-        }
-        break;
-      case FieldPairType_feature_field:
-        ffp = (FeatureFieldPairPtr) vnp->data.ptrvalue;
-        if (ffp == NULL || ffp->field_from == NULL || ffp->field_to == NULL) {
-          str = StringSave ("missing field");
-        } else {
-          label = GetFeatureNameFromFeatureType (ffp->type);
-          from_label = FeatureFieldLabel (label, ffp->field_from);
-          to_label = FeatureFieldLabel (label, ffp->field_to);
-          str = (CharPtr) MemNew (sizeof (Char) * 
-                                  (StringLen (label_fmt) 
-                                   + StringLen (from_label) + StringLen (to_label)
-                                   + StringLen (connect_word)));
-          sprintf (str, label_fmt, from_label, connect_word, to_label);
-          from_label = MemFree (from_label);
-          to_label = MemFree (to_label);
-        }
-        break;
-      case FieldPairType_cds_gene_prot:
-        cgp = (CDSGeneProtFieldPairPtr) vnp->data.ptrvalue;
-        from_label = CDSGeneProtNameFromField (cgp->field_from);
-        to_label = CDSGeneProtNameFromField (cgp->field_to);
-        str = (CharPtr) MemNew (sizeof (Char) *
-                                StringLen (from_label) + StringLen (connect_word) + StringLen (to_label)
-                                + 3);
-        sprintf (str, "%s %s %s", from_label, connect_word, to_label);
-        break;
-      case FieldPairType_molinfo_field:
-        m_fields = (MolinfoFieldPairPtr) vnp->data.ptrvalue;
-        from_label = NULL;
-        to_label = NULL;
-        label = NULL;
-        switch (m_fields->choice) {
-          case MolinfoFieldPair_molecule:
-            from_label = BiomolNameFromBiomol (BiomolFromMoleculeType (((MolinfoMoleculePairPtr) m_fields->data.ptrvalue)->from));
-            to_label = BiomolNameFromBiomol (BiomolFromMoleculeType (((MolinfoMoleculePairPtr) m_fields->data.ptrvalue)->to));
-            label = "molecule";
-            break;
-          case MolinfoFieldPair_technique:
-            from_label = TechNameFromTech (TechFromTechniqueType (((MolinfoTechniquePairPtr) m_fields->data.ptrvalue)->from));
-            to_label = TechNameFromTech (TechFromTechniqueType (((MolinfoTechniquePairPtr) m_fields->data.ptrvalue)->to));
-            label = "technique";
-            break;
-          case MolinfoFieldPair_completedness:
-            from_label = CompletenessNameFromCompleteness (CompletenessFromCompletednessType (((MolinfoCompletednessPairPtr) m_fields->data.ptrvalue)->from));
-            to_label = CompletenessNameFromCompleteness (CompletenessFromCompletednessType (((MolinfoCompletednessPairPtr) m_fields->data.ptrvalue)->to));
-            label = "completeness";
-            break;
-          case MolinfoFieldPair_mol_class:
-            from_label = MolNameFromMol (MolFromMoleculeClassType (((MolinfoMolClassPairPtr) m_fields->data.ptrvalue)->from));
-            to_label = MolNameFromMol (MolFromMoleculeClassType (((MolinfoMolClassPairPtr) m_fields->data.ptrvalue)->to));
-            label = "class";
-            break;
-          case MolinfoFieldPair_topology:
-            from_label = TopologyNameFromTopology (TopologyFromTopologyType (((MolinfoTopologyPairPtr) m_fields->data.ptrvalue)->from));
-            to_label = TopologyNameFromTopology (TopologyFromTopologyType (((MolinfoTopologyPairPtr) m_fields->data.ptrvalue)->to));
-            label = "topology";
-            break;
-          case MolinfoFieldPair_strand:
-            from_label = StrandNameFromStrand (StrandFromStrandType (((MolinfoStrandPairPtr) m_fields->data.ptrvalue)->from));
-            to_label = StrandNameFromStrand (StrandFromStrandType (((MolinfoStrandPairPtr) m_fields->data.ptrvalue)->to));
-            label = "strand";
-            break;
-        }
-        if (from_label == NULL) {
-          from_label = "Unknown value";
-        }
-        if (to_label == NULL) {
-          to_label = "Unknown value";
-        }
-        if (label == NULL) {
-          label = "Unknown molinfo field";
-        }
-        str = (CharPtr) MemNew (sizeof (Char) * (StringLen (type_label_fmt)
-                                                 + StringLen (label)
-                                                 + StringLen (from_label)
-                                                 + StringLen (to_label)
-                                                 + StringLen (connect_word)));
-        sprintf (str, type_label_fmt, label, from_label, connect_word, to_label);
-        break;
-      case FieldPairType_rna_field:
-        if (vnp->data.ptrvalue != NULL) {
-          rna_quals = (RnaQualPairPtr) vnp->data.ptrvalue;
-          label = SummarizeRnaType (rna_quals->type);
-          from_label = GetNameForRnaField (rna_quals->field_from);
-          to_label = GetNameForRnaField (rna_quals->field_to);
-        }
-        if (from_label != NULL && to_label != NULL && label != NULL) {
-          str = (CharPtr) MemNew (sizeof (Char) * (StringLen (type_label_fmt)
-                                  + StringLen (label)
-                                  + StringLen (from_label) + StringLen (connect_word) + StringLen (to_label)));
-          sprintf (str, type_label_fmt, label, from_label, connect_word, to_label);
-        } else {
-          str = StringSave ("missing field");
-        }
-        label = MemFree (label);        
-        break;
-
-      default:
-        str = StringSave ("Invalid field type");
-        break;
-    }
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeTextPortion (TextPortionPtr text_portion)
-{
-  CharPtr summ = NULL;
-  CharPtr left_fmt = NULL, right_fmt = NULL;
-  Int4 len = 6;
-
-  if (text_portion == NULL 
-      || ((text_portion->left_text == NULL || text_portion->left_text[0] == 0)
-          && (text_portion->right_text == NULL || text_portion->right_text[0] == 0))) {
-    summ = StringSave ("entire text");
-  } else if (text_portion->inside) {
-    if (text_portion->left_text != NULL && text_portion->left_text[0] != 0) {
-      if (text_portion->include_left) {
-        left_fmt = "starting with ";
-      } else {
-        left_fmt = "just after ";
-      }
-      len += StringLen (left_fmt) + StringLen (text_portion->left_text) + 3;
-    }
-    if (text_portion->right_text != NULL && text_portion->right_text[0] != 0) {
-      if (text_portion->include_right) {
-        right_fmt = "up to and including ";
-      } else {
-        right_fmt = "up to ";
-      }
-      len += StringLen (right_fmt) + StringLen (text_portion->right_text) + 3;
-      if (left_fmt != NULL) {
-        len += 2;
-      }
-    }
-    if (left_fmt == NULL && right_fmt == NULL) {
-      summ = StringSave ("entire text");
-    } else {
-      summ = (CharPtr) MemNew (sizeof (Char) * len);
-      StringCat (summ, "text ");
-      if (left_fmt != NULL) {
-        StringCat (summ, left_fmt);
-        StringCat (summ, "'");
-        StringCat (summ, text_portion->left_text);
-        StringCat (summ, "'");
-        if (right_fmt != NULL) {
-          StringCat (summ, ", ");
-        }
-      }
-      if (right_fmt != NULL) {
-        StringCat (summ, right_fmt);
-        StringCat (summ, "'");
-        StringCat (summ, text_portion->right_text);
-        StringCat (summ, "'");
-      }
-    }      
-  } else {
-    if (text_portion->right_text != NULL && text_portion->right_text[0] != 0) {
-      if (text_portion->include_right) {
-        right_fmt = "starting with ";
-      } else {
-        right_fmt = "after ";
-      }
-      len += StringLen (right_fmt) + StringLen (text_portion->right_text) + 3;
-    }
-    if (text_portion->left_text != NULL && text_portion->left_text[0] != 0) {
-      if (text_portion->include_left) {
-        left_fmt = "up to and including ";
-      } else {
-        left_fmt = "before ";
-      }
-      len += StringLen (left_fmt) + StringLen (text_portion->left_text) + 3;
-      if (right_fmt != NULL) {
-        len += 5;
-      }
-    }
-
-    if (left_fmt == NULL && right_fmt == NULL) {
-      summ = StringSave ("entire text");
-    } else {
-      summ = (CharPtr) MemNew (sizeof (Char) * len);
-      StringCat (summ, "text ");
-      if (right_fmt != NULL) {
-        StringCat (summ, right_fmt);
-        StringCat (summ, "'");
-        StringCat (summ, text_portion->right_text);
-        StringCat (summ, "'");
-        if (left_fmt != NULL) {
-          StringCat (summ, " and ");
-        }
-      }
-      if (left_fmt != NULL) {
-        StringCat (summ, left_fmt);
-        StringCat (summ, "'");
-        StringCat (summ, text_portion->left_text);
-        StringCat (summ, "'");
-      }
-    }          
-  }
-  return summ;
-}
-
-
-static CharPtr SummarizeApplyAction (ApplyActionPtr a)
-{
-  CharPtr str = NULL;
-  CharPtr fmt = "Apply %s to %s (%s)";
-  CharPtr nontextqual_fmt = "Apply %s (%s)";
-  CharPtr field, existing_text;
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->value == NULL || a->field == NULL) {
-    str = StringSave ("Invalid action");
-  } else {
-    field = SummarizeFieldType (a->field);
-    existing_text = SummarizeExistingText (a->existing_text);
-    if (IsFieldTypeNonText (a->field)) {
-      str = (CharPtr) MemNew (sizeof (Char) * StringLen (nontextqual_fmt) + StringLen (field) + StringLen (existing_text));
-      sprintf (str, nontextqual_fmt, field, existing_text);
-    } else {
-      str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (a->value) + StringLen (field) + StringLen (existing_text)));
-      sprintf (str, fmt, a->value, field, existing_text);
-    }
-    field = MemFree (field);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeEditAction (EditActionPtr a)
-{
-  CharPtr str = NULL;
-  CharPtr fmt = "Edit %s replace '%s' with '%s'";
-  CharPtr field;
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->field == NULL || a->field == NULL || a->edit == NULL || a->edit->find_txt == NULL) {
-    str = StringSave ("Invalid action");
-  } else {
-    field = SummarizeFieldType (a->field);
-    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (field) + StringLen (a->edit->find_txt) + StringLen (a->edit->repl_txt)));
-    sprintf (str, fmt, field, a->edit->find_txt, a->edit->repl_txt == NULL ? "" : a->edit->repl_txt);
-    field = MemFree (field);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeConvertAction (ConvertActionPtr a)
-{
-  CharPtr str = NULL;
-  CharPtr fmt = "Convert %s (%s)";
-  CharPtr fields, existing_text;
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->fields == NULL || a->fields == NULL) {
-    str = StringSave ("Invalid action");
-  } else {
-    fields = SummarizeFieldPairType (a->fields, "to");
-    existing_text = SummarizeExistingText (a->existing_text);
-    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (fields) + StringLen (existing_text)));
-    sprintf (str, fmt, fields, existing_text);
-    fields = MemFree (fields);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeCopyAction (CopyActionPtr a)
-{
-  CharPtr str = NULL;
-  CharPtr fmt = "Copy %s (%s)";
-  CharPtr fields, existing_text;
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->fields == NULL) {
-    str = StringSave ("Invalid action");
-  } else {
-    fields = SummarizeFieldPairType (a->fields, "to");
-    existing_text = SummarizeExistingText (a->existing_text);
-    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (fields) + StringLen (existing_text)));
-    sprintf (str, fmt, fields, existing_text);
-    fields = MemFree (fields);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeSwapAction (SwapActionPtr a)
-{
-  CharPtr str = NULL;
-  CharPtr fmt = "Swap %s";
-  CharPtr fields;
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->fields == NULL) {
-    str = StringSave ("Invalid action");
-  } else {
-    fields = SummarizeFieldPairType (a->fields, "with");
-    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (fields)));
-    sprintf (str, fmt, fields);
-    fields = MemFree (fields);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeAECRParseAction (AECRParseActionPtr a)
-{
-  CharPtr str = NULL;
-  CharPtr fmt = "Parse %s from %s (%s)";
-  CharPtr fields, existing_text, text_portion;
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->fields == NULL) {
-    str = StringSave ("Invalid action");
-  } else {
-    fields = SummarizeFieldPairType (a->fields, "to");
-    existing_text = SummarizeExistingText (a->existing_text);
-    text_portion = SummarizeTextPortion (a->portion);
-    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (text_portion) + StringLen (fields) + StringLen (existing_text)));
-    sprintf (str, fmt, text_portion, fields, existing_text);
-    fields = MemFree (fields);
-    text_portion = MemFree (text_portion);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeRemoveAction (RemoveActionPtr a)
-{
-  CharPtr str = NULL;
-  CharPtr fmt = "Remove %s";
-  CharPtr field;
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->field == NULL || a->field == NULL) {
-    str = StringSave ("Invalid action");
-  } else {
-    field = SummarizeFieldType (a->field);
-    str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (field)));
-    sprintf (str, fmt, field);
-    field = MemFree (field);
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeAECRAction (AECRActionPtr a)
-{
-  CharPtr str = NULL, act = NULL, constraint = NULL;
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else if (a->action == NULL) {
-    str = StringSave ("Invalid command");
-  } else {
-    switch (a->action->choice) {
-      case ActionChoice_apply:
-        act = SummarizeApplyAction (a->action->data.ptrvalue);
-        break;
-      case ActionChoice_edit:
-        act = SummarizeEditAction (a->action->data.ptrvalue);
-        break;
-      case ActionChoice_convert:
-        act = SummarizeConvertAction (a->action->data.ptrvalue);
-        break;
-      case ActionChoice_copy:
-        act = SummarizeCopyAction (a->action->data.ptrvalue);
-        break;
-      case ActionChoice_swap:
-        act = SummarizeSwapAction (a->action->data.ptrvalue);
-        break;
-      case ActionChoice_remove:
-        act = SummarizeRemoveAction (a->action->data.ptrvalue);
-        break;
-      case ActionChoice_parse:
-        act = SummarizeAECRParseAction (a->action->data.ptrvalue);
-        break;
-    }
-    if (act == NULL) {
-      str = StringSave ("Invalid action");
-    } else {
-      constraint = SummarizeConstraintSet (a->constraint);
-      if (constraint == NULL) {
-        str = act;
-      } else {
-        str = (CharPtr) MemNew (sizeof (Char) * (StringLen(act) + 2 + StringLen (constraint)));
-        sprintf (str, "%s %s", act, constraint);
-        act = MemFree (act);
-        constraint = MemFree (constraint);
-      }
-    }
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeParseSrc (ValNodePtr src)
-{
-  CharPtr summ = NULL;
-  CharPtr fmt = "structured comment field %s";
-  ParseSrcOrgPtr src_org;
-  Boolean need_to_save = TRUE;
-  
-  if (src != NULL) {
-    switch (src->choice) {
-      case ParseSrc_defline:
-        summ = "defline";
-        break;
-      case ParseSrc_flatfile:
-        summ = "flat file";
-        break;
-      case ParseSrc_local_id:
-        summ = "local ID";
-        break;
-      case ParseSrc_org:
-        src_org = (ParseSrcOrgPtr) src->data.ptrvalue;
-        if (src_org != NULL) {
-          if (src_org->field != NULL) {
-            if (src_org->field->choice == ParseSrcOrgChoice_taxname_after_binomial) {
-              summ = kTaxnameAfterBinomialString;
-            } else if (src_org->field->choice == ParseSrcOrgChoice_source_qual) {
-              summ = GetSourceQualName (src_org->field->data.intvalue);
-            }
-          }
-        }
-        break;
-      case ParseSrc_comment:
-        summ = "comment";
-        break;
-      case ParseSrc_bankit_comment:
-        summ = "BankIT comment";
-        break;
-      case ParseSrc_structured_comment:
-        if (!StringHasNoText (src->data.ptrvalue)) {
-          summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (src->data.ptrvalue) + StringLen (fmt)));
-          sprintf (summ, fmt, src->data.ptrvalue);
-          need_to_save = FALSE;
-        }
-        break;
-      case ParseSrc_file_id:
-        summ = "file ID";
-        break;
-    }
-  }
-  if (summ == NULL) {
-    summ = StringSave ("missing field");
-  } else if (need_to_save) {
-    summ = StringSave (summ);
-  } 
-  return summ;
-}
-
-
-static CharPtr SummarizeParseDst (ValNodePtr dst)
-{
-  CharPtr summ = NULL;
-  CharPtr fmt = "%s %s";
-  CharPtr feature, field;
-  ParseDstOrgPtr dst_org;
-  Boolean need_to_save = TRUE;
-  FeatureFieldLegalPtr ffp;
-  
-  if (dst != NULL) {
-    switch (dst->choice) {
-      case ParseDest_defline:
-        summ = "defline";
-        break;
-      case ParseDest_org:
-        dst_org = (ParseDstOrgPtr) dst->data.ptrvalue;
-        if (dst_org != NULL) {
-          if (dst_org->field != NULL) {
-            switch (dst_org->field->choice) {
-              case SourceQualChoice_textqual:
-                summ = GetSourceQualName (dst_org->field->data.intvalue);
-                break;
-              case SourceQualChoice_location:
-                summ = "location";
-                break;
-              case SourceQualChoice_origin:
-                summ = "origin";
-                break;
-            }
-          }
-        }
-        break;
-      case ParseDest_featqual:
-        ffp = (FeatureFieldLegalPtr) dst->data.ptrvalue;
-        if (ffp != NULL) {
-          feature = GetFeatureNameFromFeatureType (ffp->type);
-          field = GetFeatQualName (ffp->field);
-          summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (feature) + StringLen (field)));
-          sprintf (summ, fmt, feature, field);
-          need_to_save = FALSE;
-        }
-        break;
-      case ParseDest_dbxref:
-        summ = "dbxref";
-        break;
-    }
-  }
-  if (summ == NULL) {
-    summ = StringSave ("missing field");
-  } else if (need_to_save) {
-    summ = StringSave (summ);
-  } 
-  return summ;
-}
-
-
-static CharPtr SummarizeParseAction (ParseActionPtr p)
-{
-  CharPtr field_from = NULL, field_to = NULL;
-  CharPtr existing_text = NULL, text_portion = NULL;
-  CharPtr summ = NULL;
-  CharPtr fmt = "Parse %s from %s to %s (%s)";
-
-  if (p == NULL) {
-    summ = StringSave ("No action");
-  } else {
-    field_from = SummarizeParseSrc (p->src);
-    field_to = SummarizeParseDst (p->dest);
-    existing_text = SummarizeExistingText (p->existing_text);
-    text_portion = SummarizeTextPortion (p->portion);
-    summ = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (text_portion) + StringLen (field_from) + StringLen (field_to) + StringLen (existing_text)));
-    sprintf (summ, fmt, text_portion, field_from, field_to, existing_text);
-    text_portion = MemFree (text_portion);
-    field_from = MemFree (field_from);
-    field_to = MemFree (field_to);
-  }
-  return summ;
-}
-
-
 static CharPtr SummarizeApplyFeatureAction (ApplyFeatureActionPtr a)
 {
   CharPtr    label = NULL;
@@ -17407,98 +17508,6 @@ static CharPtr SummarizeRemoveFeatureAction (RemoveFeatureActionPtr a)
 }
 
 
-static CharPtr SummarizeRemoveDescriptorAction (RemoveDescriptorActionPtr a)
-{
-  CharPtr    label = NULL;
-  CharPtr    constraint, str;
-  CharPtr    fmt = "Remove %s";
-  CharPtr    constraint_fmt = "Remove %s descriptors %s";
-
-  if (a == NULL) {
-    str = StringSave ("No action");
-  } else {
-    label = GetDescriptorNameFromDescriptorType (a->type);
-    constraint = SummarizeConstraintSet (a->constraint);
-    if (constraint == NULL) {
-      str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (label)));
-      sprintf (str, fmt, label);
-    } else {
-      str = (CharPtr) MemNew (sizeof (Char) * (StringLen (constraint_fmt) + StringLen (label) + StringLen (constraint)));
-      sprintf (str, constraint_fmt, label, constraint);
-      constraint = MemFree (constraint);
-    }
-  }
-
-  return str;
-}
-
-
-static CharPtr SummarizeAutodefClauseListType (Uint2 clause_list_type)
-{
-  CharPtr str = "complete sequence";
-
-  switch (clause_list_type) {
-    case Autodef_list_type_feature_list:
-      str = "list fFeatures";
-      break;
-    case Autodef_list_type_complete_sequence:
-      str = "complete sequence";
-      break;
-    case Autodef_list_type_complete_genome:
-      str = "complete genome";
-      break;
-  }
-  return str;
-}
-
-
-static CharPtr SummarizeAutodefAction (AutodefActionPtr autodef)
-{
-  CharPtr    label = NULL, mod_name;
-  CharPtr    str = NULL;
-  CharPtr    fmt = "Autodef %s";
-  CharPtr    modifiers_fmt = " with modifier";
-  Int4       len;
-  ValNodePtr mod_names = NULL, vnp;
-
-  if (autodef == NULL) {
-    str = StringSave ("No action");
-  } else {
-    label = SummarizeAutodefClauseListType (autodef->clause_list_type);
-    len = StringLen (fmt) + StringLen (label);
-    if (autodef->modifiers != NULL) {
-      len += StringLen (modifiers_fmt) + 2;
-      for (vnp = autodef->modifiers; vnp != NULL; vnp = vnp->next) {
-        mod_name = GetSourceQualName (vnp->data.intvalue);
-        len += StringLen (mod_name) + 3;
-        ValNodeAddPointer (&mod_names, 0, mod_name);
-      }
-    }
-    
-    str = (CharPtr) MemNew (sizeof (Char) * (len + 1));
-    sprintf (str, fmt, label);
-
-    if (autodef->modifiers != NULL) {
-      StringCat (str, modifiers_fmt);
-      if (autodef->modifiers->next != NULL) {
-        StringCat (str, "s");
-      }
-      for (vnp = mod_names; vnp != NULL; vnp = vnp->next) {
-        StringCat (str, " ");
-        StringCat (str, vnp->data.ptrvalue);
-        if (vnp->next != NULL) {
-          StringCat (str, ",");
-        }
-      }
-    }
-
-    mod_names = ValNodeFree (mod_names);
-  }
-
-  return str;
-}
-
-
 static CharPtr SummarizeConvertSourceOptions (ValNodePtr vnp)
 {
   ConvertFromCDSOptionsPtr options;
@@ -17815,6 +17824,12 @@ static CharPtr SummarizeEditFeatureLocationAction (EditFeatureLocationActionPtr
       case LocationEditType_convert:
         action_label = SummarizeConvertLoc (a->action->data.intvalue);
         break;
+      case LocationEditType_extend_5:
+        action_label = StringSave ("Extend 5' end of feature to end of sequence");
+        break;
+      case LocationEditType_extend_3:
+        action_label = StringSave ("Extend 3' end of feature to end of sequence");
+        break;
     }
     if (action_label == NULL) {
       str = StringSave ("Invalid action");
@@ -17835,7 +17850,6 @@ static CharPtr SummarizeEditFeatureLocationAction (EditFeatureLocationActionPtr
 }
 
 
-
 static CharPtr SummarizeMacroAction (ValNodePtr vnp)
 {
   CharPtr str = NULL;
@@ -17868,6 +17882,30 @@ static CharPtr SummarizeMacroAction (ValNodePtr vnp)
     case MacroActionChoice_autodef:
       str = SummarizeAutodefAction (vnp->data.ptrvalue);
       break;
+    case MacroActionChoice_removesets:
+      str = StringSave ("Remove duplicate nested sets");
+      break;
+    case MacroActionChoice_trim_junk_from_primer_seq:
+      str = StringSave ("Trim junk from primer seqs");
+      break;
+    case MacroActionChoice_fix_usa_and_states:
+      str = StringSave ("Fix USA and state abbreviations in publications");
+      break;
+    case MacroActionChoice_trim_stop_from_complete_cds:
+      str = StringSave ("Remove trailing * from complete coding regions");
+      break;
+    case MacroActionChoice_synchronize_cds_partials:
+      str = StringSave ("Synchronize coding region partials");
+      break;
+    case MacroActionChoice_adjust_for_consensus_splice:
+      str = StringSave ("Adjust coding regions for consensus splice sites");
+      break;
+    case MacroActionChoice_fix_pub_caps:
+      str = SummarizeFixPubCapsAction(vnp->data.ptrvalue);
+      break;
+    case MacroActionChoice_remove_seg_gaps:
+      str = StringSave ("Remove seg-gaps");
+      break;
     default:
       str = StringSave ("Invalid action");
       break;
@@ -17893,6 +17931,7 @@ typedef struct tabcolumnconfigdlg {
   DialoG                   cdsgeneprot;
   DialoG                   pub_field;
   DialoG                   molinfo_field;
+  DialoG                   struccomm_field;
 
   ButtoN                   change_mrna;
   GrouP                    apply_options;
@@ -17923,7 +17962,8 @@ typedef enum {
   eTabColumnConfig_Apply_CommentDescriptor,
   eTabColumnConfig_Apply_Defline,
   eTabColumnConfig_Apply_Keyword,
-  eTabColumnConfig_Apply_Molinfo
+  eTabColumnConfig_Apply_Molinfo,
+  eTabColumnConfig_Apply_StructuredCommentField
 } ETabColumnConfig;
 
 typedef enum {
@@ -18136,8 +18176,13 @@ static Pointer TabColumnConfigDialogToChoice (DialoG d)
       f->field = ValNodeNew (NULL);
       f->field->choice = FieldType_molinfo_field;
       f->field->data.ptrvalue = DialogToPointer (dlg->molinfo_field);
+    } else if (val == eTabColumnConfig_Apply_StructuredCommentField) {
+      f->field = ValNodeNew (NULL);
+      f->field->choice = FieldType_struc_comment_field;
+      f->field->data.ptrvalue = DialogToPointer (dlg->struccomm_field);
     }
 
+
     if (dlg->erase_when_blank == NULL) {
       f->skip_blank = TRUE;
     } else {
@@ -18203,6 +18248,7 @@ static void TabColumnActionChange (PopuP p)
       Hide (dlg->cdsgeneprot);
       Hide (dlg->pub_field);
       Hide (dlg->molinfo_field);
+      Hide (dlg->struccomm_field);
       Disable (dlg->change_mrna);
       Enable (dlg->apply_options);
       Hide (dlg->match_grp);
@@ -18216,6 +18262,7 @@ static void TabColumnActionChange (PopuP p)
       Hide (dlg->cdsgeneprot);
       Hide (dlg->pub_field);
       Hide (dlg->molinfo_field);
+      Hide (dlg->struccomm_field);
       config = DialogToPointer (dlg->dialog);
       if (config == NULL || !IsFieldTypeCDSProduct (config->field)) {
         SafeDisable (dlg->change_mrna);
@@ -18235,6 +18282,7 @@ static void TabColumnActionChange (PopuP p)
       Show (dlg->cdsgeneprot);
       Hide (dlg->pub_field);
       Hide (dlg->molinfo_field);
+      Hide (dlg->struccomm_field);
       config = DialogToPointer (dlg->dialog);
       if (config == NULL || !IsFieldTypeCDSProduct (config->field)) {
         SafeDisable (dlg->change_mrna);
@@ -18253,6 +18301,7 @@ static void TabColumnActionChange (PopuP p)
       Hide (dlg->cdsgeneprot);
       Show (dlg->pub_field);
       Hide (dlg->molinfo_field);
+      Hide (dlg->struccomm_field);
       Enable (dlg->apply_options);
       Hide (dlg->match_grp);
       EnableNonTextOptions (dlg->existing_text);
@@ -18266,6 +18315,7 @@ static void TabColumnActionChange (PopuP p)
       Hide (dlg->cdsgeneprot);
       Hide (dlg->pub_field);
       Hide (dlg->molinfo_field);
+      Hide (dlg->struccomm_field);
       Enable (dlg->apply_options);
       Hide (dlg->match_grp);
       Disable (dlg->change_mrna);
@@ -18279,6 +18329,7 @@ static void TabColumnActionChange (PopuP p)
       Hide (dlg->cdsgeneprot);
       Hide (dlg->pub_field);
       Hide (dlg->molinfo_field);
+      Hide (dlg->struccomm_field);
       Enable (dlg->apply_options);
       Hide (dlg->match_grp);
       Disable (dlg->change_mrna);
@@ -18292,12 +18343,27 @@ static void TabColumnActionChange (PopuP p)
       Hide (dlg->cdsgeneprot);
       Hide (dlg->pub_field);
       Show (dlg->molinfo_field);
+      Hide (dlg->struccomm_field);
       Enable (dlg->apply_options);
       Hide (dlg->match_grp);
       Disable (dlg->change_mrna);
       DisableMultiOptions (dlg->existing_text);
       DisableNonTextOptions (dlg->existing_text);
       break;
+    case eTabColumnConfig_Apply_StructuredCommentField:
+      Show (dlg->qual_grp);
+      Hide (dlg->src_qual);
+      Hide (dlg->feature_field_grp);
+      Hide (dlg->cdsgeneprot);
+      Hide (dlg->pub_field);
+      Hide (dlg->molinfo_field);
+      Show (dlg->struccomm_field);
+      Enable (dlg->apply_options);
+      Hide (dlg->match_grp);
+      Disable (dlg->change_mrna);
+      DisableMultiOptions (dlg->existing_text);
+      EnableNonTextOptions (dlg->existing_text);
+      break;
   }
   if (dlg != NULL && dlg->change_notify != NULL) {
     (dlg->change_notify) (dlg->change_userdata);
@@ -18417,6 +18483,9 @@ static void TabColumnConfigToDialog (DialoG d, Pointer data)
       } else if (f->field->choice == FieldType_molinfo_field) {
         SetValue (dlg->column_action, eTabColumnConfig_Apply_Molinfo);
         PointerToDialog (dlg->molinfo_field, f->field->data.ptrvalue);
+      } else if (f->field->choice == FieldType_struc_comment_field) {
+        SetValue (dlg->column_action, eTabColumnConfig_Apply_StructuredCommentField);
+        PointerToDialog (dlg->struccomm_field, f->field->data.ptrvalue);
       }
         
       SafeSetStatus (dlg->change_mrna, f->match_mrna);
@@ -18531,6 +18600,7 @@ NLM_EXTERN DialoG TabColumnConfigDialog
   PopupItem (dlg->column_action, "Apply to Definition Line");
   PopupItem (dlg->column_action, "Apply to Keyword");
   PopupItem (dlg->column_action, "Apply to Molinfo");
+  PopupItem (dlg->column_action, "Apply to Structured Comment Field");
   SetValue (dlg->column_action, 1);
   
   k = HiddenGroup (p, 0, 0, NULL);
@@ -18553,6 +18623,7 @@ NLM_EXTERN DialoG TabColumnConfigDialog
   dlg->cdsgeneprot = CDSGeneProtFieldDialog (dlg->qual_grp, TabColumnConfigFieldChange, dlg);
   dlg->pub_field = PubFieldDialog (dlg->qual_grp, TabColumnConfigFieldChange, dlg);
   dlg->molinfo_field = MolinfoFieldChoiceDialog  (dlg->qual_grp, TabColumnConfigFieldChange, dlg);
+  dlg->struccomm_field = StructuredCommentFieldDialog (dlg->qual_grp, TabColumnConfigFieldChange, dlg);
   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->match_grp, (HANDLE) dlg->qual_grp, NULL);
 
   dlg->change_mrna = CheckBox (p, "Also change mRNA product name", TabColumnConfigButtonChange);
@@ -18798,10 +18869,18 @@ static void PopulateTabConfigListColumnListDoc (DialoG d)
     {0, 0, 1, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, FALSE}, /* action */
     {0, 0, 80, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE}   /* first value */
   };
+  Int4 scroll_pos = 0;
+  BaR  sb_vert;
+
 
   dlg = (TabColumnConfigListDlgPtr) GetObjectExtra (d);
   if (dlg == NULL) return;
 
+  sb_vert = GetSlateVScrollBar ((SlatE) dlg->column_list_doc);
+  if (sb_vert) {
+    scroll_pos = GetBarValue (sb_vert);
+  }
+
   Reset (dlg->column_list_doc);
 
   ObjectRect (dlg->column_list_doc, &r);
@@ -18824,6 +18903,9 @@ static void PopulateTabConfigListColumnListDoc (DialoG d)
     tmp = MemFree (tmp);
   }
   UpdateDocument (dlg->column_list_doc, 0, 0);
+  if (scroll_pos > 0) {
+    CorrectBarValue (sb_vert, scroll_pos);
+  }
 }
 
 
diff --git a/desktop/macrodlg.h b/desktop/macrodlg.h
index b09b7ca..6457484 100755
--- a/desktop/macrodlg.h
+++ b/desktop/macrodlg.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11/23/2007
 *
-* $Revision: 1.15 $
+* $Revision: 1.21 $
 *
 * File Description: 
 *
@@ -48,6 +48,8 @@
 #include <objmacro.h>
 
 NLM_EXTERN void LaunchMacroEditor (IteM i);
+NLM_EXTERN void LaunchMacroEditorBaseForm (BaseFormPtr bfp);
+
 NLM_EXTERN DialoG TabColumnConfigDialog 
 (GrouP                    h,
  CharPtr                  title,
@@ -59,16 +61,36 @@ NLM_EXTERN void ChangeDataForTabColumnConfigListDialog (DialoG d, ValNodePtr fir
 NLM_EXTERN DialoG MatchTypeDialog (GrouP g, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
 
 NLM_EXTERN DialoG FeatureTypeDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+NLM_EXTERN DialoG FeatureTypeDialogMulti (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
 NLM_EXTERN DialoG StringConstraintDialog (GrouP h, CharPtr label, Boolean clear_btn, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
 NLM_EXTERN DialoG ComplexConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+NLM_EXTERN void ChangeComplexConstraintFieldType (DialoG d, Uint2 qual_type, ValNodePtr rna_type, Int2 feat_type);
+NLM_EXTERN DialoG ConstraintSetDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
 NLM_EXTERN DialoG MolInfoBlockDialog (GrouP h, Boolean edit, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
 NLM_EXTERN void SingleAECRMacroAction (Uint2 entityID, Boolean indexer_version, Uint1 AECR_action_type, Uint1 AECR_qual_type);
 NLM_EXTERN void MacroApplyKeyword (Uint2 entityID, Boolean indexer_version);
 
+NLM_EXTERN DialoG LocationConstraintDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+
 NLM_EXTERN Uint2 TwoStepExistingText (Int4 num_found, Boolean non_text, Boolean allow_multi);
 
 NLM_EXTERN ForM SingleParseAction (Uint2 entityID);
 
 NLM_EXTERN DialoG MolinfoFieldChoiceDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
 
+/* for adding features */
+typedef struct applyfeaturedetails {
+  Boolean add_mrna;
+  ValNodePtr fields;
+  ValNodePtr src_fields;
+} ApplyFeatureDetailsData, PNTR ApplyFeatureDetailsPtr;
+
+NLM_EXTERN DialoG ApplyFeatureDetailsDialog (GrouP h, Uint1 featdef_type, ApplyFeatureDetailsPtr details, Boolean indexer_version, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+NLM_EXTERN ApplyFeatureDetailsPtr ApplyFeatureDetailsNew (ApplyFeatureActionPtr action);
+NLM_EXTERN ApplyFeatureDetailsPtr ApplyFeatureDetailsFree (ApplyFeatureDetailsPtr details); 
+NLM_EXTERN DialoG ParseDstDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+NLM_EXTERN DialoG CapChangeDialog (GrouP h, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+NLM_EXTERN DialoG TextPortionDialog (GrouP h, Boolean inside, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata);
+
+
 #endif
diff --git a/desktop/pubdesc.c b/desktop/pubdesc.c
index a606528..5a33762 100644
--- a/desktop/pubdesc.c
+++ b/desktop/pubdesc.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/28/95
 *
-* $Revision: 6.71 $
+* $Revision: 6.81 $
 *
 * File Description:
 *
@@ -48,6 +48,9 @@
 #include <toasn3.h>
 #include <mla2api.h>
 #include <dlogutil.h>
+#ifdef WIN_MOTIF
+#include <netscape.h>
+#endif
 
 #define FIRST_PAGE      0
 
@@ -152,9 +155,7 @@ typedef struct pubdescpage {
   TexT          retractExp;
 
   TexT          comment;
-  /*
   TexT          doi;
-  */
 
 /* year/month - date of issue; cpryear/cprmonth - date of application */
   TexT          pat_country;
@@ -719,9 +720,7 @@ static Pointer PubdescPageToPubdescPtr (DialoG d)
   CitSubPtr             csp;
   AuthListPtr           alp;
   ImprintPtr            imp;
-  /*
   ArticleIdPtr          doi;
-  */
   Char                  str[256];
   Int2                  serial;
   Int2                  val;
@@ -830,7 +829,6 @@ static Pointer PubdescPageToPubdescPtr (DialoG d)
               }
             }
           }
-          /*
           if (! TextHasNoText (ppp->doi)) {
             doi = ArticleIdNew ();
             if (doi != NULL) {
@@ -840,7 +838,6 @@ static Pointer PubdescPageToPubdescPtr (DialoG d)
               cap->ids = doi;
             }
           }
-          */
         }
         break;
 /* note: for Cit-book's there is cbp->otherdata which could be ValNodes */
@@ -1224,10 +1221,8 @@ static void PubdescPtrToPubdescPage (DialoG d, Pointer data)
   CitJourPtr        cjp;
   CitPatPtr         cpp;
   CitSubPtr         csp;
-  /*
   CharPtr           doi;
   ArticleIdPtr      ids;
-  */
   PubStatusDatePtr  history;
   ImprintPtr        imp;
   Uint1             pubstatus;
@@ -1464,14 +1459,12 @@ static void PubdescPtrToPubdescPage (DialoG d, Pointer data)
                 default:
                   break;
               }
-              /*
               for (ids = cap->ids; ids != NULL; ids = ids->next) {
                 if (ids->choice != ARTICLEID_DOI) continue;
                 doi = (CharPtr) ids->data.ptrvalue;
                 if (StringHasNoText (doi)) continue;
                 SetTitle (ppp->doi, doi);
               }
-              */
             }
             break;
           case PUB_Book:
@@ -1983,6 +1976,35 @@ static void LookupByPmidProc (ButtoN b)
   LookupCommonProc (b, TRUE, TRUE);
 }
 
+static void LookupByDOIProc (ButtoN b)
+
+{
+  Char            buf [550], doi [500];
+  PubdescPagePtr  ppp;
+#ifdef WIN_MOTIF
+  NS_Window       window = NULL;
+#endif
+
+  ppp = (PubdescPagePtr) GetObjectExtra (b);
+  if (ppp == NULL) return;
+  GetTitle (ppp->doi, doi, sizeof (doi));
+  if (StringDoesHaveText (doi)) {
+    if (StringNCmp (doi, "10.", 3) == 0) {
+      StringCpy (buf, "http://dx.doi.org/");
+      StringCat (buf, doi);
+#ifdef WIN_MAC
+      Nlm_SendURLAppleEvent (buf, NULL, NULL);
+#endif
+#ifdef WIN_MSWIN
+      Nlm_MSWin_OpenDocument (buf);
+#endif
+#ifdef WIN_MOTIF
+      NS_OpenURL (&window, buf, NULL, TRUE);
+#endif
+    }
+  }
+}
+
 static void LaunchRelaxedQuery PROTO((PubdescPtr pdp, Pointer userdata));
 
 static void LookupRelaxedProc (ButtoN b)
@@ -2001,13 +2023,33 @@ static void LookupRelaxedProc (ButtoN b)
   PubdescFree (pdp);
 }
 
+
+static void MakeJournalReport (ButtoN b)
+{
+  ValNodePtr allTitles, vnp;
+  LogInfoPtr lip;
+  CharPtr str;
+
+  allTitles = (ValNodePtr) GetObjectExtra (b);
+  lip = OpenLog ("Possible Journal Titles");
+  for (vnp = allTitles; vnp != NULL; vnp = vnp->next) {
+    str = (CharPtr) vnp->data.ptrvalue;
+    if (StringHasNoText (str)) continue;
+    fprintf (lip->fp, "%s\n", str);
+  }
+  lip->data_in_log = TRUE;
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
 static Boolean ChooseFromMultipleJournals (CharPtr rsult, size_t max, ValNodePtr allTitles)
 {
   WindoW                 w;
   GrouP                  h, c, q;
   ButtoN                 b;
   PrompT                 p;
-  CharPtr                str;
+  CharPtr                str, cp;
   Int2                   j;
   ValNodePtr             vnp;
   PopuP                  x;
@@ -2039,6 +2081,8 @@ static Boolean ChooseFromMultipleJournals (CharPtr rsult, size_t max, ValNodePtr
   SetObjectExtra (b, &acd, NULL);
   b = PushButton (c, "No", ModalCancelButton);
   SetObjectExtra (b, &acd, NULL);
+  b = PushButton (c, "Make Report", MakeJournalReport);
+  SetObjectExtra (b, allTitles, NULL);
   AlignObjects (ALIGN_CENTER, (HANDLE) p, (HANDLE) q, (HANDLE) c, NULL);
 
   Show (w); 
@@ -2062,6 +2106,10 @@ static Boolean ChooseFromMultipleJournals (CharPtr rsult, size_t max, ValNodePtr
         str = (CharPtr) vnp->data.ptrvalue;
         if (StringDoesHaveText (str)) {
           StringNCpy_0 (rsult, str, max);
+          cp = StringSearch (rsult, "||");
+          if (cp != NULL) {
+            *cp = 0;
+          }
           return TRUE;
         }
       }
@@ -2099,6 +2147,7 @@ static void LookupISOJournalProc (ButtoN b)
         } else {
           Message (MSG_OK, "Unable to match journal");
         }
+        allTitles = ValNodeFreeData (allTitles);
         Update ();
       }
     }
@@ -2209,7 +2258,7 @@ static DialoG CreatePubdescDialog (GrouP h, CharPtr title, GrouP PNTR pages,
   GrouP                 c;
   GrouP                 g1, g2, g3, g4, g5, g6, g7, g8, g9, g10;
   GrouP                 g11, g12, g13, g14, g15;
-  GrouP                 g16, g17, g18, g19, g20, g21, g22, g23;
+  GrouP                 g16, g17, g18, g19, g20, g21, g22, g23, g24;
   ButtoN                lkp;
   GrouP                 m, m2, m3, m4, m5, m6, m7, m8, m9;
   GrouP                 n1, n2, n3, n4;
@@ -2690,12 +2739,13 @@ static DialoG CreatePubdescDialog (GrouP h, CharPtr title, GrouP PNTR pages,
     StaticPrompt (g10, "Remark", (Int2) (25 * stdCharWidth), 0,
                   programFont, 'c');
     ppp->comment = ScrollText (g10, 25, 5, programFont, TRUE, NULL);
-    /*
-    g24 = HiddenGroup (g10, 2, 0, NULL);
-    StaticPrompt (g24, "D.O.I.", 0, dialogTextHeight, programFont, 'l');
+    g24 = HiddenGroup (g10, 4, 0, NULL);
+    SetGroupSpacing (g24, 10, 10);
+    StaticPrompt (g24, "DOI", 0, dialogTextHeight, programFont, 'l');
     ppp->doi = DialogText (g24, "", 12, NULL);
+    b = PushButton (g24, "Lookup By DOI", LookupByDOIProc);
+    SetObjectExtra (b, ppp, NULL);
     AlignObjects (ALIGN_CENTER, (HANDLE) ppp->comment, (HANDLE) g24, NULL);
-    */
 
     g11 = HiddenGroup (g10, -6, 0, NULL);
     if (pub_choice == PUB_UNPUB || pub_choice == PUB_ONLINE || pub_choice == PUB_SUB)
@@ -3553,11 +3603,9 @@ static void PubdescDescFormActnProc (ForM f)
     if (DescFormReplaceWithoutUpdateProc (f)) {
       UpdateRAD (&rad, pfp);
       GetRidOfEmptyFeatsDescStrings (pfp->input_entityID, NULL);
-      if (GetAppProperty ("InternalNcbiSequin") != NULL) {
-        ExtendGeneFeatIfOnMRNA (pfp->input_entityID, NULL);
-      }
-      ObjMgrSendMsg (OM_MSG_UPDATE, pfp->input_entityID,
+      ObjMgrSendMsgNoFeatureChange(OM_MSG_UPDATE, pfp->input_entityID,
                      pfp->input_itemID, pfp->input_itemtype);
+
     }
     CleanupRAD (&rad);
   }
@@ -5549,7 +5597,7 @@ static void PopulateWindow( WindoW w, PubdescPtr pdp)
 		    }
 
 		    alp = (AuthListPtr) cap->authors; 
-		    if (alp != NULL) {		  		 		 			
+		    if (alp != NULL && alp->choice == 1) {		  		 		 			
 		      /*get ptr to both 1st and last author*/	 
 		      auth_vnp = (ValNodePtr) alp->names; /*get the first node */ 
       		
@@ -6071,3 +6119,254 @@ extern void EditPublicationInDialog (DialoG d, Int4 ref_num)
   
   EditPublicationInList (dlg, sdp);
 }
+
+
+static Boolean EditPubdescDataInPlace (SeqDescPtr sdp, PubinitFormPtr pifp)
+{
+  Uint1                 reftype;
+  Uint1                 pub_status;
+  Int2                  pub_choice;
+  PubdescFormPtr        pfp;
+  WindoW                w;
+  ButtoN                b;
+  GrouP                 c;
+  GrouP                 h1;
+  Int2                  initPage;
+  Int2                  j;
+  CharPtr PNTR          labels;
+  Int2                  tabnumber;
+  CharPtr               tabs [NUM_TABS];
+  ModalAcceptCancelData acd;
+  Boolean               rval = FALSE;
+
+  if (pifp == NULL || pifp->form == NULL || sdp == NULL || sdp->choice != Seq_descr_pub) 
+  {
+    return FALSE;
+  }
+
+  pifp->reftype = 0;    /* sequence */
+  reftype = pifp->reftype;
+  pub_status = (Uint1) GetValue (pifp->pub_status);
+  pub_choice = GetValue (pifp->pub_choice);
+  if (pub_status > 2)
+  {
+    pub_status = 0;
+  }
+
+  pfp = (PubdescFormPtr) MemNew (sizeof (PubdescForm));
+  if (pfp == NULL) {
+    return FALSE;
+  }
+  w = FixedWindow (-50, -33, -10, -10, "Publication", StdCloseWindowProc);
+  SetObjectExtra (w, pfp, StdDescFormCleanupProc);
+  pfp->form = (ForM) w;
+  pfp->actproc = NULL /*actproc*/;
+  pfp->toform = NULL;
+  pfp->fromform = NULL;
+  pfp->testform = NULL;
+  pfp->formmessage = PubdescDescFormMessage;
+  pfp->importform = ImportPubdescForm;
+  pfp->exportform = ExportPubdescForm;
+
+#ifndef WIN_MAC
+  CreateStdEditorFormMenus (w);
+#endif
+
+
+  tabnumber = tabcounter[pub_choice];
+  pfp->tabnumber = tabnumber;
+  pfp->pub_choice = pub_choice;
+  pfp->is_feat = FALSE;
+  pfp->replaceAll = FALSE;
+  labels = pubdescFormTabs[pub_choice];
+  for (j = 0; j < NUM_TABS; j++)
+  {
+    tabs [j] = NULL;
+  }
+  for (j = 0; j < NUM_TABS && labels [j] != NULL; j++)
+  {
+    tabs [j] = labels [j];
+  }
+
+  h1 = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h1, 3, 10);
+
+  initPage = FIRST_PAGE;
+  if (GetAppProperty ("InternalNcbiSequin") != NULL) {
+    if (pub_choice == PUB_JOURNAL) {
+      initPage = 2;
+    }
+  }
+  pfp->foldertabs = CreateFolderTabs (h1, tabs, initPage,
+                       descTabsPerLine [pub_choice], 10,
+                       SYSTEM_FOLDER_TAB,
+                       ChangePubdescPage, (Pointer) pfp);
+  pfp->currentPage = initPage;
+  pfp->data = CreatePubdescDialog (h1, NULL, pfp->pages,
+        reftype,
+        pub_status,
+        pub_choice,
+        pifp->flagPubDelta, pifp->flagSerial,
+        NULL, pfp);
+  pfp->Attribute_Page = 0;
+  pfp->Location_Page = 0;
+
+  c = HiddenGroup (h1, 4, 0, NULL);
+  b = PushButton (c, "Accept", ModalAcceptButton);
+  SetObjectExtra (b, &acd, NULL);
+  b = PushButton (c, "Cancel", ModalCancelButton);
+  SetObjectExtra (b, &acd, NULL);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) pfp->foldertabs, (HANDLE) pfp->data,
+             (HANDLE) c, NULL);
+  RealizeWindow (w);
+  SendMessageToDialog (pfp->data, VIB_MSG_INIT);
+  PointerToDialog (pfp->data, (Pointer) pifp->sdp->data.ptrvalue);
+  ChangePubdescPage ((Pointer) pfp, pfp->currentPage, 0);
+  Show (w);
+  acd.accepted = FALSE;
+  acd.cancelled = FALSE;
+
+  while (!acd.accepted && ! acd.cancelled)
+  {
+    while (!acd.accepted && ! acd.cancelled)
+    {
+      ProcessExternalEvent ();
+      Update ();
+    }
+    ProcessAnEvent ();
+    if (!acd.cancelled)
+    {
+      sdp->data.ptrvalue = DialogToPointer (pfp->data);
+      rval = TRUE;
+    }
+  }
+  Remove (w);
+  return rval;
+}
+
+
+NLM_EXTERN Boolean EditPubdescInPlace (SeqDescPtr sdp)
+{
+  ButtoN                b;
+  GrouP                 c;
+  GrouP                 h1;
+  GrouP                 g1, g2, g4, g5;
+  PubdescPtr            pdp;
+  PubinitFormPtr        pifp;
+  WindoW                w;
+  ValNodePtr            vnp;
+  ModalAcceptCancelData acd;
+  Uint1                 st_value;
+  Int2                  pb_value;
+  Boolean               first = TRUE;
+  Boolean               rval = FALSE;
+
+  if (sdp == NULL || sdp->choice != Seq_descr_pub || sdp->data.ptrvalue == NULL) {
+    return FALSE;
+  }
+  w = NULL;
+  pifp = (PubinitFormPtr) MemNew (sizeof (PubinitForm));
+  pifp->flagPubDelta = FALSE;
+  pifp->flagSerial = FALSE;
+  w = ModalWindow (-20, -33, -10, -10, NULL);
+  SetObjectExtra (w, pifp, StdCleanupFormProc);
+  pifp->form = (ForM) w;
+  pifp->actproc = NULL;
+  pifp->toform = PubdescInitPtrToPubdescInitForm;
+  pifp->fromform = NULL;
+  pifp->testform = NULL;
+
+  pifp->sep = NULL;
+  pifp->sdp = sdp;
+  pifp->sfp = NULL;
+
+  pdp = (PubdescPtr) sdp->data.ptrvalue;
+
+  h1 = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h1, 10, 20);
+  g2 = NormalGroup (h1, -1, 0, "Status", programFont, NULL);
+  g4 = HiddenGroup (g2, -4, 0, ChangePubStat);
+  pifp->pub_status = g4;
+  SetObjectExtra (g4, pifp, NULL);
+  RadioButton (g4, "Unpublished");
+  RadioButton (g4, "In Press");
+  RadioButton (g4, "Published");
+  SetValue (g4, 1);           /* unpublished */
+  g1 = NormalGroup (h1, -1, 0, "Class", programFont, NULL);
+  g5 = HiddenGroup (g1, -3, 0, ChangePublication);
+  pifp->pub_choice = g5;
+  SetObjectExtra (g5, pifp, NULL);
+
+  RadioButton (g5, "Journal");
+  RadioButton (g5, "Book Chapter");
+  RadioButton (g5, "Book");
+  RadioButton (g5, "Thesis/Monograph");
+  RadioButton (g5, "Proceedings Chapter");
+  RadioButton (g5, "Proceedings");
+  pifp->patent_btn = RadioButton (g5, "Patent");
+  RadioButton (g5, "Online Publication");
+  vnp = pdp->pub;
+  while (vnp != NULL)
+  {
+    if (vnp->choice == PUB_Sub)
+    {
+      RadioButton (g5, "Submission");
+      break;
+    }
+    vnp = vnp->next;
+  }
+
+  Disable (g5);               /* publications disabled */
+
+  c = HiddenGroup (h1, 2, 0, NULL);
+  b = PushButton (c, "Proceed", ModalAcceptButton);
+  SetObjectExtra (b, &acd, NULL);
+  b = PushButton (c, "Cancel", ModalCancelButton);
+  SetObjectExtra (b, &acd, NULL);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) g2, (HANDLE) g1,
+                (HANDLE) c, NULL);
+  RealizeWindow (w);
+  SendMessageToForm (pifp->form, VIB_MSG_INIT);
+  PointerToForm (pifp->form, (Pointer) sdp->data.ptrvalue);
+  
+  if (pdp->pub != NULL && pdp->pub->choice == PUB_Sub) {
+    /* can't change anything, just proceed to next form */
+    acd.accepted = TRUE;
+  } else {
+    Show (w);
+    acd.accepted = FALSE;
+  }
+
+  acd.cancelled = FALSE;
+  while ((!acd.accepted && ! acd.cancelled) || first)
+  {
+    first = FALSE;
+    while (!acd.accepted && ! acd.cancelled)
+    {
+      ProcessExternalEvent ();
+      Update ();
+    }
+    ProcessAnEvent ();
+    if (!acd.cancelled)
+    {
+      st_value = (Uint1) GetValue (pifp->pub_status);
+      pb_value = GetValue (pifp->pub_choice);
+      if (st_value > 1 && pb_value == 0) 
+      {
+        Message (MSG_ERROR, "Must choose class");
+        acd.accepted = FALSE;
+      }
+      else
+      {
+        /* go on to replace pubdesc */
+        Hide (w);
+        rval = EditPubdescDataInPlace (sdp, pifp);
+      }
+    }
+  }
+  Remove (w);
+  return rval;
+}
+
diff --git a/desktop/pubdesc.h b/desktop/pubdesc.h
index 4780e04..6f2e611 100644
--- a/desktop/pubdesc.h
+++ b/desktop/pubdesc.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/28/95
 *
-* $Revision: 6.6 $
+* $Revision: 6.7 $
 *
 * File Description: 
 *
@@ -102,6 +102,9 @@ extern WindoW EditCitDescDirectly (SeqDescPtr sdp);
 extern DialoG PublicationListDialog (GrouP parent);
 extern void EditPublicationInDialog (DialoG d, Int4 ref_num);
 
+NLM_EXTERN Boolean EditPubdescInPlace (SeqDescPtr sdp);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/desktop/salpanel.c b/desktop/salpanel.c
index a1383d0..aadf722 100644
--- a/desktop/salpanel.c
+++ b/desktop/salpanel.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/27/96
 *
-* $Revision: 6.97 $
+* $Revision: 6.98 $
 *
 * File Description: 
 *
@@ -3040,10 +3040,10 @@ static SeqLocPtr MapSubLoc
               sinp->from = ival->start2;
               sinp->to = ival->stop2;
               sinp->strand = strand;
-              sinp->id = prop_sip;
-              prop_sip = NULL;
+              sinp->id = SeqIdDup (prop_sip);
               ValNodeAddPointer (&prop_loc, SEQLOC_INT, (Pointer) sinp);
             }
+            prop_sip = SeqIdFree (prop_sip);
           } else {
             sinp = SeqIntNew ();
             sinp->from = ival_head->start2;
diff --git a/desktop/salsa.c b/desktop/salsa.c
index a116743..c98d5b3 100644
--- a/desktop/salsa.c
+++ b/desktop/salsa.c
@@ -28,7 +28,7 @@
 *
 * Version Creation Date:   1/27/96
 *
-* $Revision: 6.184 $
+* $Revision: 6.185 $
 *
 * File Description: 
 *
@@ -7516,7 +7516,6 @@ NLM_EXTERN void CalculateAlignmentOffsets (SeqEntryPtr sepnew, SeqEntryPtr sepol
       {
         strand=Seq_strand_plus;
         len = offset;
-        offset = 0;
       }
       SeqAlignStartUpdate (salpnew, sip_temp, abs(offset), len, strand);	    	
     }  	
diff --git a/desktop/seqpanel.c b/desktop/seqpanel.c
index d58918f..2ab798a 100644
--- a/desktop/seqpanel.c
+++ b/desktop/seqpanel.c
@@ -1,4 +1,4 @@
-/* $Id: seqpanel.c,v 6.225 2008/07/07 18:52:31 bollin Exp $
+/* $Id: seqpanel.c,v 6.228 2010/08/02 17:43:05 bollin Exp $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
@@ -178,6 +178,9 @@ typedef struct seqedformdata
                                              * when the alignment panel is removed using
                                              * UnlockFarComponents.
                                              */  
+  Nlm_ChangeNotifyProc on_close_func;       /* This is called when the window is being closed. */
+  Pointer              on_close_data;       /* Argument for on_close_func */
+
 } SeqEdFormData, PNTR SeqEdFormPtr;
 
 typedef struct seqpanpara 
@@ -4305,11 +4308,9 @@ static void ExportSequenceText (SeqEdFormPtr sefp, Int4 from, Int4 to, FILE *fp)
             if (ctr > 0) 
             {
               /* set end to NULL if at end of sequence */
-              if (ctr < bvp->CharsAtLine) MemSet(buf+ctr, '\0', 1);
-              /* convert to lowercase */
-              for (i = SEQ_ED_PRINT_SEQ_OFFSET; i < ctr + SEQ_ED_PRINT_SEQ_OFFSET; i++)
+              if (ctr < bvp->CharsAtLine) 
               {
-              	buf[i] = TO_LOWER (buf[i]);
+                MemSet(file_line + SEQ_ED_PRINT_SEQ_OFFSET + ctr, '\0', 1);
               } 
               
               SeqEdPrintTextLineToFile ((CharPtr)file_line, from, to, seq_pos, fp);
@@ -4351,6 +4352,28 @@ static void ExportSequenceText (SeqEdFormPtr sefp, Int4 from, Int4 to, FILE *fp)
             PrintTranslatedFrame((CharPtr)file_line, splp->bioSeqLine, 6, bvp);
             SeqEdPrintTextLineToFile ((CharPtr)file_line, from, to, seq_pos, fp);
             break;
+          case eTypeSequenceComplement:
+            MemSet (file_line, ' ', bvp->CharsAtLine + SEQ_ED_PRINT_SEQ_OFFSET);
+            seq_pos = (c_n * SEQ_PAN_CHAPTER_SIZE + p_n) * bvp->CharsAtLine;
+            sprintf (label, "complement");
+            StringNCpy ((CharPtr)file_line, label, StringLen (label));
+
+            ctr = 0;
+            SeqPortSeek (spp, seq_pos, SEEK_SET);
+            /* clear last message, might have read to end with last sequence line */
+            spp->lastmsg = 0;
+            ctr = SeqPortRead (spp, file_line + SEQ_ED_PRINT_SEQ_OFFSET, bvp->CharsAtLine);
+            if (ctr > 0) 
+            {
+              /* set end to NULL if at end of sequence */
+              if (ctr < bvp->CharsAtLine) MemSet(file_line + SEQ_ED_PRINT_SEQ_OFFSET + ctr, '\0', 1);
+
+              /* complement */
+              complement_string (file_line + SEQ_ED_PRINT_SEQ_OFFSET);
+              
+              SeqEdPrintTextLineToFile ((CharPtr)file_line, from, to, seq_pos, fp);
+            }  
+            break;
         }
       }
       fprintf (fp, "\n");      
@@ -6786,11 +6809,27 @@ static void CleanupSeqEdForm (GraphiC g, VoidPtr data)
     BioseqUnlock (sefp->bfp->bvd.bsp);
     
     sefp->locked_aln_bioseqs = UnlockFarComponents (sefp->locked_aln_bioseqs);    
+    if (sefp->on_close_func != NULL) {
+      (sefp->on_close_func)(sefp->on_close_data);
+    }
   }
 
   StdCleanupFormProc (g, data);
 }
 
+
+NLM_EXTERN void RemoveSeqEdCloseFunc (WindoW w)
+{
+  SeqEdFormPtr  sefp;
+
+  sefp = (SeqEdFormPtr) GetObjectExtra (w);
+  if (sefp != NULL) {
+    sefp->on_close_func = NULL;
+    sefp->on_close_data = NULL;
+  }
+}
+ 
+
 static void onCloseSeqEdPanel (PaneL p)
 {
   BioseqViewPtr bvp;
@@ -8297,7 +8336,7 @@ static Int4 GetScrollPosForAlnPos (Int4 aln_pos, BioseqViewPtr bvp)
   return display_line;
 }
 
-static void SeqAlnScrollToAlnPos (SeqEdFormPtr sefp, Int4 pos)
+static void SeqAlnScrollToAlnPosEx (SeqEdFormPtr sefp, Int4 pos, Int4 seq_num)
 {
   BaR          sb;
   Int4         scroll_pos, bmax;
@@ -8326,6 +8365,10 @@ static void SeqAlnScrollToAlnPos (SeqEdFormPtr sefp, Int4 pos)
   bmax = GetBarMax (sb);
 
   scroll_pos = GetScrollPosForAlnPos (pos, &(sefp->bfp->bvd));
+  if (seq_num > -1) {
+    /* need to skip two in order to move past header rows for block */
+    scroll_pos += seq_num + 2;
+  }
   if (scroll_pos > bmax)
   {
     scroll_pos = bmax;
@@ -8339,6 +8382,24 @@ static void SeqAlnScrollToAlnPos (SeqEdFormPtr sefp, Int4 pos)
   RestorePort (temport);
 }
 
+
+static void SeqAlnScrollToAlnPos (SeqEdFormPtr sefp, Int4 pos)
+{
+  SeqAlnScrollToAlnPosEx (sefp, pos, -1);
+}
+
+
+NLM_EXTERN void SeqAlnWindowScrollToAlnPos (WindoW w, Int4 aln_pos, Int4 seq_num)
+{
+  SeqEdFormPtr sefp;
+
+  sefp = (SeqEdFormPtr) GetObjectExtra (w);
+  if (sefp != NULL) {
+    SeqAlnScrollToAlnPosEx (sefp, aln_pos, seq_num);
+  }
+}
+    
+
 static void SeqAlnGoToAlnPosBtn (ButtoN b)
 {
   SeqEdFormPtr sefp;
@@ -8353,6 +8414,7 @@ static void SeqAlnGoToAlnPosBtn (ButtoN b)
   {
   	return;
   }
+  aln_pos -= 1;
   
   SeqAlnScrollToAlnPos (sefp, aln_pos);
 }
@@ -9413,7 +9475,9 @@ static void CreateAlnMenus (WindoW w, Boolean enable_feat_prop, Boolean allow_fe
   
 }
 
-extern ForM CreateAlnEditorWindow (Int2 left, Int2 top, CharPtr windowname, SeqAlignPtr salp, Uint2 entityID)
+extern ForM CreateAlnEditorWindowEx 
+(Int2 left, Int2 top, CharPtr windowname, SeqAlignPtr salp, Uint2 entityID,
+ Nlm_ChangeNotifyProc on_close_func, Pointer on_close_data)
 {
   SeqEdFormPtr       sefp;
   WindoW             w;
@@ -9437,6 +9501,9 @@ extern ForM CreateAlnEditorWindow (Int2 left, Int2 top, CharPtr windowname, SeqA
     return NULL;
   }
   
+  sefp->on_close_func = on_close_func;
+  sefp->on_close_data = on_close_data;
+  
   sefp->annot = GetSeqAnnotForAlignment (salp);
   
 #ifdef WIN_MAC
@@ -9558,6 +9625,12 @@ extern ForM CreateAlnEditorWindow (Int2 left, Int2 top, CharPtr windowname, SeqA
 }
 
 
+extern ForM CreateAlnEditorWindow (Int2 left, Int2 top, CharPtr windowname, SeqAlignPtr salp, Uint2 entityID)
+{
+  return CreateAlnEditorWindowEx (left, top, windowname, salp, entityID, NULL, NULL);
+}
+
+
 BioseqPageData seqpnlPageData = {
   "Sequence", TRUE, TRUE, TRUE, FALSE, -1,
   PopulateSeqView, ShowSeqView, SelectSeqView,
diff --git a/desktop/seqpanel.h b/desktop/seqpanel.h
index cab56c0..bcc045a 100644
--- a/desktop/seqpanel.h
+++ b/desktop/seqpanel.h
@@ -1,4 +1,4 @@
-/* $Id: seqpanel.h,v 6.21 2008/07/02 16:39:38 bollin Exp $
+/* $Id: seqpanel.h,v 6.23 2010/05/04 12:23:03 bollin Exp $
 * ===========================================================================
 *
 *                            PUBLIC DOMAIN NOTICE
@@ -56,6 +56,13 @@ extern ForM CreateSeqEditorWindow (Int2 left, Int2 top, CharPtr windowname, Bios
 
 NLM_EXTERN SeqAlignPtr Sequin_GlobalAlign2Seq (BioseqPtr bsp1, BioseqPtr bsp2, BoolPtr revcomp);
 extern ForM CreateAlnEditorWindow (Int2 left, Int2 top, CharPtr windowname, SeqAlignPtr salp, Uint2 entityID);
+extern ForM 
+CreateAlnEditorWindowEx 
+(Int2 left, Int2 top, CharPtr windowname, SeqAlignPtr salp, Uint2 entityID,
+ Nlm_ChangeNotifyProc on_close_func, Pointer on_close_data);
+NLM_EXTERN void RemoveSeqEdCloseFunc (WindoW w);
+NLM_EXTERN void SeqAlnWindowScrollToAlnPos (WindoW w, Int4 aln_pos, Int4 seq_num);
+
 NLM_EXTERN CharPtr FeatureLocationAlignment (SeqFeatPtr sfp, SeqAlignPtr salp, Int4 begin, Int4 fin);
 extern void FlipAlignment (SeqAlignPtr salp);
 
diff --git a/desktop/seqsub.c b/desktop/seqsub.c
index 2c7b44f..6667858 100644
--- a/desktop/seqsub.c
+++ b/desktop/seqsub.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.38 $
+* $Revision: 6.40 $
 *
 * File Description: 
 *
@@ -2534,13 +2534,11 @@ static ENUM_ALIST(molinfo_biomol_nucX_alist)
   {"mRNA [cDNA]",            3},
   {"Ribosomal RNA",          4},
   {"Transfer RNA",           5},
-  {"Small nuclear RNA",      6},
-  {"Small cytoplasmic RNA",  7},
   {"Other-Genetic",          9},
   {"Genomic-mRNA",          10},
   {"cRNA",                  11},
-  {"Small nucleolar RNA",   12},
   {"Transcribed RNA",       13},
+  {"ncRNA",                 14},
   {"Other",                255},
 END_ENUM_ALIST
 
@@ -3703,7 +3701,7 @@ static Boolean GetBioSourceFromSeqEntry (SeqEntryPtr sep, BioSourcePtr PNTR pbio
   BioseqPtr    bsp = NULL;
   BioseqSetPtr bssp = NULL;
   Boolean      rval = TRUE;
-  SeqDescrPtr  sdp;
+  SeqDescrPtr  sdp = NULL;
   
   if (pbiop == NULL)
   {
diff --git a/desktop/valdlg.c b/desktop/valdlg.c
index e10790c..f958d95 100755
--- a/desktop/valdlg.c
+++ b/desktop/valdlg.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/8/2009
 *
-* $Revision: 1.3 $
+* $Revision: 1.4 $
 *
 * File Description: Dialogs for editing structured comment rules
 *
@@ -476,8 +476,7 @@ static Pointer CommentSetFromDialog (DialoG d)
 static void UpdateRuleList (Pointer data)
 {
   CommentSetDlgPtr dlg;
-  CommentRulePtr new_cr, replace_cr, last_cr = NULL;
-  Int4 item;
+  CommentRulePtr new_cr, last_cr = NULL;
 
   dlg = (CommentSetDlgPtr) data;
   if (dlg == NULL) {
diff --git a/desktop/vsmfile.c b/desktop/vsmfile.c
index 7baacfe..6f8ad9a 100644
--- a/desktop/vsmfile.c
+++ b/desktop/vsmfile.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11-29-94
 *
-* $Revision: 6.25 $
+* $Revision: 6.27 $
 *
 * File Description: 
 *
@@ -130,6 +130,9 @@ Boolean LIBCALL VSMFileInit(void)
   ObjMgrProcLoad(OMPROC_SAVE, "Save Entries Within Selected Sets", "ASN.1 text files for each entry in selected sets", 0,0,0,0,NULL,
                            VSMSaveSetsAsFiles, PROC_PRIORITY_DEFAULT);
                            
+    ObjMgrProcLoad(OMPROC_SAVE, "Save As FASTA Protein File With Products","FASTA protein file with products", 0,0,0,0,NULL,
+                           VSMFastaProtSaveWithProduct, PROC_PRIORITY_DEFAULT);
+
 	ObjMgrProcLoad(OMPROC_SAVE, "Save As Sorted FASTA Protein File","Sorted FASTA protein file", 0,0,0,0,NULL,
                            VSMFastaSortedProtSave, PROC_PRIORITY_DEFAULT);
                            
@@ -381,7 +384,7 @@ Int2 LIBCALLBACK VSMFastaNucOpen ( Pointer data )
 }
 
 
-static Int2 LIBCALLBACK VSMGenericFastaSave (OMProcControlPtr ompcp, Boolean is_na )
+static Int2 LIBCALLBACK VSMGenericFastaSave (OMProcControlPtr ompcp, Boolean is_na)
 {
 	Char filename[255];
 	FILE * fp;
@@ -481,6 +484,120 @@ Int2 LIBCALLBACK VSMFastaNucSave ( Pointer data )
 	return VSMGenericFastaSave((OMProcControlPtr)data, TRUE);
 }
 
+typedef struct fastaexportoptions {
+  FILE *fp;
+  StreamFlgType  flags;
+  Int2           linelen;
+  Int2           blocklen;
+  Int2           grouplen;
+} FastaExportOptionsData, PNTR FastaExportOptionsPtr;
+
+static void WriteOneProteinWithProduct (BioseqPtr bsp, Pointer data)
+{
+    FastaExportOptionsPtr fe;
+    SeqFeatPtr            prot;
+    SeqMgrFeatContext     fcontext;
+    Char                  id [128];
+
+    if (bsp != NULL && ISA_aa (bsp->mol) && (fe = (FastaExportOptionsPtr) data) != NULL) {
+        prot = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_PROT, &fcontext);
+        if (prot == NULL) {
+            BioseqFastaStreamEx (bsp, fe->fp, fe->flags, fe->linelen, fe->blocklen, fe->grouplen,
+                                 TRUE, FALSE, FALSE);
+        } else {
+            
+            SeqIdWrite (bsp->id, id, PRINTID_FASTA_LONG, sizeof (id) - 1);
+            fprintf (fe->fp, ">%s [prot=%s]\n", id, fcontext.label);
+            BioseqFastaStreamEx (bsp, fe->fp, fe->flags, fe->linelen, fe->blocklen, fe->grouplen,
+                                 FALSE, FALSE, FALSE);
+        }
+    }
+}
+
+
+Int2 LIBCALLBACK VSMFastaProtSaveWithProduct ( Pointer data )
+{
+
+    Char filename[255];
+    FastaExportOptionsData fe;
+    ValNode vn;
+    SeqEntryPtr sep = NULL;
+    SeqFeatPtr sfp;
+    SeqLocPtr slp;
+    Uint1 code;
+    BioseqPtr bsp;    
+    OMProcControlPtr ompcp;
+
+    if ((ompcp = (OMProcControlPtr) data) == NULL) {
+      return OM_MSG_RET_ERROR;
+    }
+
+    sfp = NULL;
+    switch(ompcp->input_itemtype)
+    {
+        case OBJ_SEQENTRY:
+        case OBJ_BIOSEQ:
+        case OBJ_BIOSEQSET:
+            break;
+        case OBJ_SEQFEAT:
+            sfp = (SeqFeatPtr) ompcp->input_data;
+            if (sfp == NULL || (sfp->data.choice != SEQFEAT_CDREGION && sfp->data.choice != SEQFEAT_PROT)) return OM_MSG_RET_ERROR;
+            break;
+        default:
+            ErrPostEx(SEV_ERROR, 0,0,"ToFasta: Can only write Seq-entry, Bioseq, or Bioseq-set");
+            return OM_MSG_RET_ERROR;
+    }
+    if (sfp != NULL) {
+    } else if (ompcp->input_choicetype == OBJ_SEQENTRY)
+        sep = (SeqEntryPtr)(ompcp->input_choice);
+    else
+    {
+        vn.next = NULL;
+        vn.data.ptrvalue = ompcp->input_data;
+        if (ompcp->input_itemtype == OBJ_BIOSEQ)
+            vn.choice = 1;
+        else
+            vn.choice = 2;
+        sep = &vn;
+    }
+        
+    filename[0] = '\0';
+    if (GetOutputFileName(filename, (size_t)254, NULL))
+    {
+        WatchCursor();
+#ifdef WIN_MAC
+        fe.fp = FileOpen (filename, "r");
+        if (fe.fp != NULL) {
+            FileClose (fe.fp);
+        } else {
+            FileCreate (filename, "TEXT", "ttxt");
+        }
+#endif
+        fe.fp = FileOpen(filename, "w");
+        if (sfp != NULL) {
+            code = Seq_code_ncbieaa;
+            slp = sfp->location;
+            if (sfp->data.choice == SEQFEAT_CDREGION) {
+              slp = sfp->product;
+            }
+            bsp = GetBioseqGivenSeqLoc (slp, ompcp->input_entityID);
+            if (slp != NULL && bsp != NULL) {
+                SeqLocFastaStream (slp, fe.fp, STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL, 70, 0, 0);
+            }
+        } else {
+            fe.flags = STREAM_EXPAND_GAPS | STREAM_CORRECT_INVAL;
+            fe.linelen = 70;
+            fe.blocklen = 0;
+            fe.grouplen = 0;
+            VisitBioseqsInSep (sep, &fe, WriteOneProteinWithProduct);
+        }
+        FileClose(fe.fp);
+        ArrowCursor();
+    }
+    
+    return OM_MSG_RET_DONE;
+}
+
 typedef struct alphaprot
 {
   BioseqPtr bsp;
@@ -790,7 +907,7 @@ static void VSMExportFeatureTableBioseqCallback (BioseqPtr bsp, Pointer userdata
           {
             ExciseProteinIDLine (string);
           }
-          fprintf (ftp->fp, string);
+          fprintf (ftp->fp, "%s", string);
           MemFree (string);
         }
       }
@@ -800,14 +917,14 @@ static void VSMExportFeatureTableBioseqCallback (BioseqPtr bsp, Pointer userdata
             && (!ftp->export_only_selected || IsBaseBlockFeatureSelected (bbp)))
         {
           string = asn2gnbk_format (ajp, (Int4) index);
-          fprintf (ftp->fp, string);
+          fprintf (ftp->fp, "%s", string);
           MemFree (string);
         }
       }
       else
       {
         string = asn2gnbk_format (ajp, (Int4) index);
-        fprintf (ftp->fp, string);
+        fprintf (ftp->fp, "%s", string);
         MemFree (string);
       }
     }
@@ -941,6 +1058,7 @@ VSMExportFeatureTable
   else if (ompcp->input_itemtype == OBJ_SEQANNOT) {
     sep = GetTopSeqEntryForEntityID (ompcp->input_entityID);
     if (sep == NULL) {
+      if (sap != NULL) {
       fake_bsp = BioseqNew();
       first_feat = (SeqFeatPtr) sap->data;
       fake_bsp->id = SeqIdDup (SeqLocId (first_feat->location));
@@ -960,6 +1078,7 @@ VSMExportFeatureTable
       SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) fake_bsp, sep);      
     }
   }
+  }
 	else
 	{
 		vn.next = NULL;
diff --git a/desktop/vsmfile.h b/desktop/vsmfile.h
index 77b04e5..c4ba1ff 100644
--- a/desktop/vsmfile.h
+++ b/desktop/vsmfile.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11-29-94
 *
-* $Revision: 6.8 $
+* $Revision: 6.9 $
 *
 * File Description: 
 *
@@ -85,6 +85,7 @@ Int2 LIBCALLBACK VSMExportNucFeatureTableSelectedFeatures (Pointer data);
 Int2 LIBCALLBACK VSMExportNucFeatureTableSelectedFeaturesSuppressProteinIDs (Pointer data);
 Int2 LIBCALLBACK VSMExportProteinFeatureTable (Pointer data);
 Int2 LIBCALLBACK VSMFastaSortedProtSave (Pointer data);
+Int2 LIBCALLBACK VSMFastaProtSaveWithProduct(Pointer data);
 Int2 LIBCALLBACK VSMDescriptorAsnSave (Pointer data);
 NLM_EXTERN void ViewSortedProteins (SeqEntryPtr sep);
 
diff --git a/desktop/vsmutil.c b/desktop/vsmutil.c
index 3169e09..39cb68b 100644
--- a/desktop/vsmutil.c
+++ b/desktop/vsmutil.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   3/3/95
 *
-* $Revision: 6.66 $
+* $Revision: 6.74 $
 *
 * File Description: 
 *
@@ -114,7 +114,9 @@ typedef struct validextra {
   ValNodePtr     errorfilter;
   BaseFormPtr    bfp;
   FormActnFunc   revalProc;
+  FormActnFunc   revalNoTaxProc;
   ButtoN         revalBtn;
+  ButtoN         skipTaxBtn;
   FormActnFunc   continueProc;
   ButtoN         continueBtn;
   Boolean        okaytosetviewtarget;
@@ -132,6 +134,7 @@ typedef struct validextra {
   Int2           selected_text_anchor_row;
   Int4           selected_text_anchor_offset;
   SequesterProc  sequesterProc;
+  SequesterProc  segregateProc;
 } ValidExtra, PNTR ValidExtraPtr;
 
 static WindoW  validWindow = NULL;
@@ -443,7 +446,7 @@ static void ValDoNotify (ValidExtraPtr vep, Int2 item, Boolean select, Boolean t
       }
       (vep->notify) ((ErrSev) sev, errcode, subcode,
                      (Uint2) entityID, itemID, (Uint2) itemtype,
-                     select, vep->dblClick);
+                     select, vep->dblClick, vep->shftKey);
     }
     MemFree (str);
   }
@@ -829,7 +832,7 @@ static CharPtr FormatConsensusSpliceReport (CharPtr doc_line)
   CharPtr report_str = NULL;
   CharPtr msg_abbrev = NULL;
   Char    ch, ch_2;
-  Int4    pos;
+  long int  pos;
 
   cp = StringChr (doc_line, '\n');
   if (StringSearch (cp, "(AG) not found") != NULL) {
@@ -1068,7 +1071,7 @@ extern Boolean WriteBadSpecificHostTable (ValNodePtr bad_biop_list, FILE *fp)
   BioseqSetPtr bssp;
   SeqFeatPtr   sfp;
   SeqDescrPtr  sdp;
-  BioSourcePtr biop;
+  BioSourcePtr biop = NULL;
   ObjValNodePtr ovp;
   CharPtr       spec_host = NULL;
   OrgModPtr     mod = NULL;
@@ -1663,7 +1666,7 @@ static void MakeValidatorReport (ButtoN b)
   if (consensus_splice_list != NULL) {
     fprintf (fp, "Not Splice Consensus\n");
     for (vnp = consensus_splice_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     fprintf (fp, "\n");
     found_any = TRUE;
@@ -1732,6 +1735,30 @@ static void SequesterByValidatorErrors (ButtoN b)
 }
 
 
+static void SegregateByValidatorErrors (ButtoN b)
+{
+  ValidExtraPtr  vep;
+  ValNodePtr     bsp_list;
+  BioseqPtr      bsp;
+  Uint2          entityID = 0;
+
+  vep = (ValidExtraPtr) GetObjectExtra (b);
+  if (vep == NULL || vep->segregateProc == NULL) return;
+  bsp_list = CollectBioseqsByValidatorReportTypes (vep);
+  if (bsp_list == NULL) {
+    Message (MSG_ERROR, "No Bioseqs selected!");
+    return;
+  }
+  if (bsp_list->choice == OBJ_BIOSEQ && bsp_list->data.ptrvalue != NULL) {
+    bsp = (BioseqPtr) bsp_list->data.ptrvalue;
+    entityID = bsp->idx.entityID;
+  }
+
+  (vep->segregateProc) (entityID, bsp_list);
+  bsp_list = ValNodeFree (bsp_list);
+}
+
+
 static Boolean ValExportProc (ForM f, CharPtr filename)
 
 {
@@ -1915,11 +1942,18 @@ static void RevalidateProc (ButtoN b)
     vep->clicked = 0;
     vep->selected = 0;
     vep->dblClick = FALSE;
+    vep->shftKey = FALSE;
     bfp = vep->bfp;
-    if (bfp != NULL && vep->revalProc != NULL) {
+    if (bfp != NULL) {
+      if (GetStatus (vep->skipTaxBtn)) {
+        if (vep->revalNoTaxProc != NULL) {
+          (vep->revalNoTaxProc)(bfp->form);
+        }
+      } else if (vep->revalProc != NULL) {
       vep->revalProc (bfp->form);
     }
   }
+  }
 }
 
 
@@ -1941,6 +1975,7 @@ static void ContinueProc (ButtoN b)
     vep->clicked = 0;
     vep->selected = 0;
     vep->dblClick = FALSE;
+    vep->shftKey = FALSE;
     bfp = vep->bfp;
     if (bfp != NULL && vep->continueProc != NULL) {
       vep->continueProc (bfp->form);
@@ -1981,6 +2016,7 @@ static void SetVerbosityAndRepopulate (PopuP p)
     vep->clicked = 0;
     vep->selected = 0;
     vep->dblClick = FALSE;
+    vep->shftKey = FALSE;
     RepopVal (p);
     /*
     bfp = vep->bfp;
@@ -2138,8 +2174,12 @@ static CharPtr howToClickText =
 /* CreateValidateWindowEx is hidden, allowing a revalidate button */
 extern WindoW CreateValidateWindowExExEx (ErrNotifyProc notify, CharPtr title,
                                     FonT font, ErrSev sev, Int2 verbose,
-                                    BaseFormPtr bfp, FormActnFunc revalProc, FormActnFunc continueProc,
+                                    BaseFormPtr bfp, 
+                                    FormActnFunc revalProc, 
+                                    FormActnFunc revalNoTaxProc, 
+                                    FormActnFunc continueProc,
                                     SequesterProc sequesterProc,
+                                    SequesterProc segregateProc,
                                     Boolean okaytosetviewtarget)
 
 {
@@ -2245,12 +2285,21 @@ extern WindoW CreateValidateWindowExExEx (ErrNotifyProc notify, CharPtr title,
         */
         Break (w);
 
-        q = HiddenGroup (w, -2, 0, NULL);
+        q = HiddenGroup (w, -4, 0, NULL);
         StaticPrompt (q, "Filter", 0, popupMenuHeight, programFont, 'l');
         vep->filter = PopupList (q, FALSE, RepopVal);
         SetObjectExtra (vep->filter, vep, NULL);
         PopupItem (vep->filter, "ALL");
+        /* note - have to add this line to get the "Skip Tax Validation" checkbox
+         * to appear in the right place - otherwise when vep->filter is resized
+         * after new error categories are added, the checkbox covers/is covered by it.
+         */
+        PopupItem (vep->filter, "LONGEST_EXPECTED: MolInfoConflictsWith");
         SetValue (vep->filter, 1);
+
+        vep->skipTaxBtn = CheckBox (q, "Skip Tax Validation", NULL);
+        Hide (vep->skipTaxBtn);          
+
         Break (w);
 
         f = HiddenGroup (w, 6, 0, NULL);
@@ -2290,6 +2339,7 @@ extern WindoW CreateValidateWindowExExEx (ErrNotifyProc notify, CharPtr title,
         vep->clicked = 0;
         vep->selected = 0;
         vep->dblClick = FALSE;
+        vep->shftKey = FALSE;
 
         valColFmt [0].pixWidth = stdCharWidth * 5;
         valColFmt [1].pixWidth = stdCharWidth * 6;
@@ -2305,7 +2355,7 @@ extern WindoW CreateValidateWindowExExEx (ErrNotifyProc notify, CharPtr title,
 
         vep->summary = StaticPrompt (w, "", stdCharWidth * 30, 0, systemFont, 'c');
 
-        btn_grp = HiddenGroup (w, 3, 0, NULL);
+        btn_grp = HiddenGroup (w, 4, 0, NULL);
         SetGroupSpacing (btn_grp, 10, 10);
         if (indexerVersion) {
           b = PushButton (btn_grp, "Report", MakeValidatorReport);
@@ -2315,6 +2365,11 @@ extern WindoW CreateValidateWindowExExEx (ErrNotifyProc notify, CharPtr title,
             b = PushButton (btn_grp, "Sequester", SequesterByValidatorErrors);
             SetObjectExtra (b, vep, NULL);
           }
+          if (segregateProc != NULL) {
+            vep->segregateProc = segregateProc;
+            b = PushButton (btn_grp, "Segregate", SegregateByValidatorErrors);
+            SetObjectExtra (b, vep, NULL);
+          }
         }
 
         b = PushButton (btn_grp, "Dismiss", CloseValidButton);
@@ -2339,6 +2394,13 @@ extern WindoW CreateValidateWindowExExEx (ErrNotifyProc notify, CharPtr title,
       } else {
         SafeHide (vep->revalBtn);
       }
+      vep->revalNoTaxProc = revalNoTaxProc;
+      if (vep->revalNoTaxProc != NULL) {
+        SafeShow (vep->skipTaxBtn);
+      } else {
+        SafeHide (vep->skipTaxBtn);
+        SetStatus (vep->skipTaxBtn, FALSE);
+      }
       vep->continueProc = continueProc;
       if (vep->continueProc != NULL) {
         SafeShow (vep->continueBtn);
@@ -2358,8 +2420,8 @@ extern WindoW CreateValidateWindowExEx (ErrNotifyProc notify, CharPtr title,
 {
   return CreateValidateWindowExExEx (notify, title,
                                     font, sev, verbose,
-                                    bfp, revalProc, continueProc,
-                                    NULL,
+                                    bfp, revalProc, NULL, continueProc,
+                                    NULL, NULL,
                                     okaytosetviewtarget);
 }
 
@@ -2378,10 +2440,27 @@ extern WindoW CreateValidateWindow (ErrNotifyProc notify, CharPtr title,
   return CreateValidateWindowEx (notify, title, font, sev, verbose, NULL, NULL, FALSE);
 }
 
+extern Boolean IsTaxValidationRequested (WindoW w)
+
+{
+  ValidExtraPtr vep;
+
+  if (w == NULL) {
+    return TRUE;
+  } else if ((vep = (ValidExtraPtr)GetObjectExtra (w)) == NULL) {
+    return TRUE;
+  } else if (vep->skipTaxBtn == NULL) {
+    return TRUE;
+  } else {
+    return !GetStatus (vep->skipTaxBtn);
+  }
+}
+
+
 extern void ShowValidateDoc (void)
 
 {
-  Char           str [64];
+  Char           str [80];
   ValidExtraPtr  vep;
 
   if (validWindow == NULL) return;
@@ -2441,12 +2520,12 @@ extern void ShowValidateWindow (void)
       }
     }
     if (! Visible (validWindow)) {
-      if (vep->totalcount > 0) {
+      if (vep != NULL && vep->totalcount > 0) {
         Show (validWindow);
       }
     }
     if (Visible (validWindow)) {
-      if (Visible (vep->doc)) {
+      if (vep != NULL && Visible (vep->doc)) {
         Select (validWindow);
       }
     }
diff --git a/desktop/vsmutil.h b/desktop/vsmutil.h
index 060fd01..31c2bb5 100644
--- a/desktop/vsmutil.h
+++ b/desktop/vsmutil.h
@@ -29,13 +29,22 @@
 *
 * Version Creation Date:   3/3/95
 *
-* $Revision: 6.13 $
+* $Revision: 6.16 $
 *
 * File Description: 
 *
 * Modifications:  
 * --------------------------------------------------------------------------
 * $Log: vsmutil.h,v $
+* Revision 6.16  2010/06/28 18:03:35  bollin
+* Added checkbox to Validator window to temporarily turn off tax validation.
+*
+* Revision 6.15  2010/02/03 16:56:11  bollin
+* Added Segregate button to Validator.
+*
+* Revision 6.14  2009/09/15 18:48:26  kans
+* pass shftKey to notify callback
+*
 * Revision 6.13  2009/05/01 18:10:51  kans
 * added featureID field to ValidErrorFunc callback type
 *
@@ -90,7 +99,7 @@ extern "C" {
 typedef void (LIBCALLBACK *ErrNotifyProc) PROTO((
               ErrSev sev, int errcode, int subcode,
               Uint2 entityID, Uint4 itemID, Uint2 itemtype,
-              Boolean select, Boolean dblClick));
+              Boolean select, Boolean dblClick, Boolean shftKey));
 
 typedef void (LIBCALLBACK *SequesterProc) PROTO((Uint2 entityID, ValNodePtr bsp_list));
                                                  
@@ -106,9 +115,14 @@ extern WindoW CreateValidateWindowExEx (ErrNotifyProc notify, CharPtr title,
                                       Boolean okaytosetviewtarget);
 extern WindoW CreateValidateWindowExExEx (ErrNotifyProc notify, CharPtr title,
                                       FonT font, ErrSev sev, Int2 verbose,
-                                      BaseFormPtr bfp, FormActnFunc revalProc, FormActnFunc continueProc,
+                                      BaseFormPtr bfp, 
+                                      FormActnFunc revalProc, 
+                                      FormActnFunc revalNoTaxProc, 
+                                      FormActnFunc continueProc,
                                       SequesterProc sequesterProc,
+                                      SequesterProc segregateProc,
                                       Boolean okaytosetviewtarget);
+extern Boolean IsTaxValidationRequested (WindoW w);
 extern void ShowValidateWindow (void);
 extern void ShowValidateDoc (void);
 extern void HideValidateDoc (void);
diff --git a/doc/FAQ.txt b/doc/FAQ.txt
index f4da2cb..ab6f480 100644
--- a/doc/FAQ.txt
+++ b/doc/FAQ.txt
@@ -77,6 +77,37 @@ which can be downloaded at http://www.lesstif.org/
 We didn't check this option yet, so you can use Lesstif for your own risk.
 Besides the Motif/Lesstif the X11R6 development toolkit should be installed.
 
+Q. On Linux I got the following error on compilation of toolkit:
+gcc -pipe -o Psequin -I. -O2 -I../include -L../lib -I/usr/X11R6/include
+-L/usr/X11R6/lib -DWIN_MOTIF -UINTERNAL_NCBI_SEQUIN sequin1.c sequin2.c
+sequin3.c sequin4.c sequin5.c sequin6.c sequin7.c sequin8.c sequin9.c
+sequin10.c sequinx.c -lncbicn3d -lddvlib -lvibnet -lncbidesk -lblastapi
+-lblast -lncbimmdb -lncbitxc2 -lncbiid1 -lnetblast -lncbitool -lblastcompadj
+-lncbimla -lncbiNacc -lnetentr -lnetcli -lncbicdr -lvibrant -lncbiobj -lncbi
+-L/usr/X11R6/lib -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXmu -lXt -lX11 -lXext -lXp
+-lm
+sequin6.c:262: warning: useless storage class specifier in empty declaration
+../lib/libncbi.a(ncbifile.o): In function `Nlm_TmpNam':
+ncbifile.c:(.text+0x2b4): warning: the use of `tempnam' is dangerous, better
+use `mkstemp'
+/usr/lib/libXm.a(TextIn.o): In function `SelfInsert':
+(.text+0x9828): undefined reference to `XftTextExtentsUtf8'
+[...]
+/usr/lib/libXm.a(Png.o): In function `png_load_file':
+(.text+0x4ec): undefined reference to `png_destroy_read_struct'
+collect2: ld returned 1 exit status
+make: *** [Psequin] Error 1
+A. To avoid binary-compatibility concerns in the executables we distribute,
+we normally arrange for the C Toolkit to link Motif statically on Linux.
+This arrangement has the unfortunate side effect that some users run into
+undefined symbol errors because their system's implementation has additional
+library dependencies relative to ours.  The fix is at least straightforward:
+open the relevant .../ncbi/platform/*linux*.ncbi.mk file in your favorite
+text editor and adjust the definition of NCBI_DISTVIBLIBS to omit the -Wl,-B
+flags, most critically -Wl,-Bstatic .  You can determine which file to edit
+by reviewing out.makedis.csh; there should be a line near the beginning of
+the form reading "platform is linux64" or the like.
+
 Q. On RedHat Linux 7.* I got the following error on compilation of toolkit:
 gcc -pipe -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -O2 -c  -I../include objproj.c
 {standard input}: Assembler messages:
diff --git a/doc/blast/blast.html b/doc/blast/blast.html
index e17ea04..27a12a3 100644
--- a/doc/blast/blast.html
+++ b/doc/blast/blast.html
@@ -11,9 +11,19 @@
 
   <body>
 <pre>
+
+WARNING: We now encourage BLAST users to use the BLAST+ applications, that can be downloaded at
+ftp://ftp.ncbi.nlm.nih.gov/blast/executables/LATEST .  There is an extensive user manual about the
+BLAST+ applications at ftp://ftp.ncbi.nlm.nih.gov/blast/executables/blast+/LATEST/user_manual.pdf as well
+as a publication at http://www.ncbi.nlm.nih.gov/pubmed/20003500?dopt=Citation
+
+This document is no longer actively maintained.
+
+
+
 README for stand-alone BLAST
 
-$Date: 2007/10/29 13:30:52 $
+$Date: 2010/03/26 14:52:10 $
 
 Table of contents
 -----------------
@@ -35,11 +45,8 @@ NCBI provides binaries for the following platforms:
 
 Apple MacOS X (ppc32/ia32)
 FreeBSD 4.5 (ia32)
-IBM AIX 5.1 (ppc64)
 Linux (kernel 2.6, glibc 2.3) (ia32, ia64, x64)
 Microsoft Windows 2000 (ia32)
-SGI IRIX 6.5 (mips64)
-Sun Solaris 9 (ia32)
 Sun Solaris 10 (sparc64)
 Sun Solaris 10 (x64)
 
@@ -265,17 +272,6 @@ If you have any questions please send them to the
 blast-help@ncbi.nlm.nih.gov e-mail address.
 
 
-SGI Note:
----------
-
-SGI recommends the following threads patches on IRIX6 systems:
-
-   For 6.2 systems, install SG0001404, SG0001645, SG0002000, SG0002420 and SG0002458 (in that order)
-   For 6.3 systems, install SG0001645, SG0002420 and SG0002458 (in that order)
-   For 6.4 systems, install SG0002194, SG0002420 and SG0002458 (in that order)
-
-These patches can be obtained by calling SGI customer service or from the web: http://support.sgi.com/
-
 System recommendations:
 ----------------------
 
@@ -295,23 +291,3 @@ databases produced from this will probably be about another Gig or so. 4 Gig
 of disk space, to make room for software and output, is probably a pretty
 good bet.
 
-OSF1 and limit
---------------
-
-Some OSF1 users have encountered "out of memory" problems when running searches
-even though there seems to be plenty of memory on the machine and the search
-runs well on other platforms.  The error message would look something like:
-
-[blastall] FATAL ERROR: CoreLib [001.000]  gi|509180|emb|X71670.1|MMP17SAR: Failed to allocate 480 bytes
-
-Often it is sufficient to simply raise the "datasize" limit, which specifies
-the maximum allowed heap size.  The "datasize" limit can be changed by executing:
-
-limit datasize unlimited
-
-Note that this change only applies to the current session, so it is advisable to place
-this command in some file sourced at startup, such as .login or .cshrc.
-</pre>
-  </body>
-</html>
-
diff --git a/doc/blast/blastall.html b/doc/blast/blastall.html
index 264662c..517443a 100644
--- a/doc/blast/blastall.html
+++ b/doc/blast/blastall.html
@@ -83,9 +83,9 @@ blastall   arguments:
         This option specifies that only a subset of the database should be
         searched, determined by the list of gi's (i.e., NCBI identifiers) in a 
         file.  One can obtain a list of gi's for a given Entrez query from
-        http://www.ncbi.nlm.nih.gov/Entrez/batch.html.  This file should
-        be in the same directory as the database, or in the directory that
-        BLAST is called from.
+        http://eutils.ncbi.nlm.nih.gov/corehtml/query/static/eutils_help.html .
+        This file should be in the same directory as the database,
+        or in the directory that BLAST is called from.
 
   -U  Use lower case filtering of FASTA sequence [T/F]  Optional
     default = F
diff --git a/doc/dispatcher.html b/doc/dispatcher.html
index 5f9c38d..213b046 100644
--- a/doc/dispatcher.html
+++ b/doc/dispatcher.html
@@ -388,7 +388,7 @@ your firewall. The ports to open are:
 Firewall Port        IP Address
 --------------------------------
  5860..5870         130.14.29.112
-    5845            130.14.22.12  (no access from outside NCBI!)
+ 5860..5870         165.112.7.12
 </pre>
 
 <p>
@@ -532,10 +532,10 @@ More technical and brief note on dispatcher selection and parameters is in
 located in the C toolkit source tree.
 
 <p>
-Description of the new NCBI dispatcher can be found <a href="http://www.ncbi.nlm.nih.gov/IEB/ToolBox/CPP_DOC/tools/dispatcher/DISPD.html">here</a>.
+Description of the new NCBI dispatcher can be found <a href="http://www.ncbi.nlm.nih.gov/bookshelf/br.fcgi?book=toolkit&amp;part=ch_app#ch_app.DISPD_Network_Dispat">here</a>.
 
 <p>
-Discussion of firewall settings can be found <a href="http://www.ncbi.nlm.nih.gov/IEB/ToolBox/NETWORK/firewall.html">here</a> and also
+Discussion of firewall settings can be found <a href="http://www.ncbi.nlm.nih.gov/IEB/ToolBox/NETWORK/firewall.html#Settings">here</a> and also
 provided in directory <tt>doc</tt> of the <a href="http://www.ncbi.nlm.nih.gov/IEB/ToolBox/C_DOC/lxr/source/doc">C toolkit</a>.
 
 <p>
@@ -547,7 +547,7 @@ you have a question, please contact <a href="mailto:info@ncbi.nlm.nih.gov">
 <p>
 <hr>
 <table border="0" cellspasing="0">
-<tr><td>Source: distrib/doc/dispatcher.html</td><td>$Date: 2006/05/31 18:59:09 $</td><td>$Revision: 6.26 $</td></tr>
+<tr><td>Source: distrib/doc/dispatcher.html</td><td>$Date: 2010/05/27 17:27:54 $</td><td>$Revision: 6.28 $</td></tr>
 </table>
 
 
diff --git a/doc/firewall.html b/doc/firewall.html
index 14f0a52..790a08b 100644
--- a/doc/firewall.html
+++ b/doc/firewall.html
@@ -48,7 +48,7 @@
       <p>&nbsp;</p>
 
 			 <p>
-				<i>Last modified:</i> $Date: 2009/04/10 01:00:09 $<br>
+				<i>Last modified:</i> $Date: 2009/12/29 04:08:40 $<br>
 				<i>Latest version: </i>
 				<a href="http://www.ncbi.nlm.nih.gov/IEB/ToolBox/NETWORK/firewall.html">
 				  http://www.ncbi.nlm.nih.gov/IEB/ToolBox/NETWORK/firewall.html</a>
@@ -81,14 +81,15 @@ If you also have a Domain Name Server (DNS) available, you can now simply press
 <p>
 If DNS is not available, uncheck the <b>Domain Name Server</b> button. If you
 are behind a firewall, set the <b>Connection</b> control to <b>Firewall</b>.
-The <b>Proxy</b> box then becomes active. If you also use a proxy server,
-type in its address. (If you have DNS, it will be of the form
-<tt>www.myproxy.myuniversity.edu</tt>. If you do not have DNS, you should use
-the numerical IP address of the form <tt>127.45.23.6</tt>.) Once you type something
-in the <b>Proxy</b> box, the <b>Port</b> box and <b>Transparent Proxy</b> button
-become active and can be filled in or changed as appropriate. (By default the
-<b>Transparent Proxy</b> button is off, indicating a CERN-like proxy.) Ask your
-network administrator for advice on the proper settings to use.
+Both the <b>HTTP Proxy</b> and the <b>Non-transparent Proxy</b> boxes then become active.
+If your site uses an HTTP proxy server, type in its address. (If you have DNS, it
+can be of the form <tt>www.myproxy.myuniversity.edu</tt>;  if you do not have DNS, you
+should enter the numerical IP address of the form <tt>127.65.43.21</tt>.)
+Once you type something in the <b>HTTP Proxy</b> box, the <b>HTTP Proxy Port</b> box
+becomes active and can be filled in.
+If your site has a non-transparent proxy server (a CERN-like proxy), enter
+its name (or address) in the <b>Non-transparent Proxy</b> box.
+Ask your network administrator for advice on the proper settings to use.
 
 <p>
 If you are in the United States, the default <b>Timeout</b> of 30 seconds should
@@ -117,6 +118,7 @@ ports in your firewall. The ports to open are:
 Firewall Port        IP Address
 --------------------------------
  5860..5870         130.14.29.112
+ 5860..5870         165.112.7.12
 </pre>
 
 <p>
@@ -124,7 +126,7 @@ If your firewall is not transparent, the firewall port number
 should be mapped to the same port number on the external host.
 
 <p>
-Even though port 5860 may not routinely be made accessible to the public,
+Even though port 5860 may not be routinely made accessible to the public,
 and is usually reserved for NCBI internal use only, it is recommended that
 the port is kept open through the firewall just as all other ports from the range,
 in case the public access will eventually be enabled on this port as well.
@@ -167,7 +169,7 @@ response from what is shown above, it indicates that the port is not configured
 
 <p>
 <a href="http://www.ncbi.nlm.nih.gov/sites/entrez?db=Books">NCBI Bookshelf</a> provides more detailed <a
-href="http://www.ncbi.nlm.nih.gov/books/bv.fcgi?rid=toolkit.section.ch_app.Load_Balancing#ch_app.Firewall_Daemon_FWDa">Firewall
+href="http://www.ncbi.nlm.nih.gov/bookshelf/br.fcgi?book=toolkit&part=ch_app#ch_app.Firewall_Daemon_FWDa">Firewall
 Daemon Documentation</a>, and discusses its integration into the overall
 functions of NCBI dispatching facilities.
 
diff --git a/doc/fwd_check.sh b/doc/fwd_check.sh
index 266e7fb..7a046e3 100755
--- a/doc/fwd_check.sh
+++ b/doc/fwd_check.sh
@@ -1,5 +1,5 @@
 #! /bin/sh
-# $Id: fwd_check.sh,v 1.42 2008/02/27 17:19:43 lavr Exp $
+# $Id: fwd_check.sh,v 1.57 2010/06/02 14:57:10 lavr Exp $
 # Author:   Denis Vakatov (vakatov@ncbi,nlm.nih.gov)
 # Modified: Anton Lavrentiev (lavr@ncbi.nlm.nih.gov)
 #
@@ -7,6 +7,10 @@
 
 delay_sec="$1"
 delay_sec=${delay_sec:="10"}
+netcat="`which netcat 2>/dev/null`"
+temp=`mktemp`
+helper="./fwd_failure_helper.exe"
+test -z "$netcat"  &&  netcat="`whereis netcat | sed 's/^[^:]*://;s/ //g'`"
 
 cat <<EOF
 http://www.ncbi.nlm.nih.gov/IEB/ToolBox/NETWORK/firewall.html
@@ -18,6 +22,7 @@ EOF
 cat <<EOF
 ;130.14.25.13	5555	RETIRED
 10.10.150.7	5555	INTERNAL
+130.14.25.26	5555	INTERNAL
 130.14.29.112	5860	RESERVED
 130.14.29.112	5861	RESERVED
 130.14.29.112	5862	RESERVED
@@ -40,36 +45,66 @@ cat <<EOF
 130.14.29.112	4452	OK
 130.14.29.112	4453	OK
 130.14.29.112	4454	RESERVED
+165.112.7.12	5860	RESERVED
+165.112.7.12	5861	RESERVED
+165.112.7.12	5862	OK
+165.112.7.12	5863	OK
+165.112.7.12	5864	RESERVED
+165.112.7.12	5865	RESERVED
+165.112.7.12	5866	OK
+165.112.7.12	5867	RESERVED
+165.112.7.12	5868	RESERVED
+165.112.7.12	5869	RESERVED
+165.112.7.12	5870	RESERVED
+165.112.7.12	4444	RETIRED
+165.112.7.12	4445	RESERVED
+165.112.7.12	4446	OK
+165.112.7.12	4447	OK
+165.112.7.12	4448	RESERVED
+165.112.7.12	4449	RESERVED
+165.112.7.12	4450	OK
+165.112.7.12	4451	RESERVED
+165.112.7.12	4452	RESERVED
+165.112.7.12	4453	RESERVED
+165.112.7.12	4454	RESERVED
 EOF
 } |
 while read x_host x_port x_status ; do
     test "`echo $x_host | grep -c '^[;]'`" != "0"  &&  continue
     if [ "$x_port" -lt "5860" -o "$x_port" -gt "5870" ]; then
-        test -z "$HTTP_CAF" -o -n "$HTTP_CAF_EXTERNAL"  &&  continue
+    test "$x_status" = "RESERVED"  &&  continue
+    if [ _"$HTTP_CAF" = _"" -o _"$HTTP_CAF_EXTERNAL" != _"" ]; then
+      test _"$HTTP_NCBI_RELAY" = _"" &&  continue
     fi
-    if [ "$x_status" = "RETIRED"  -o \
-         "$x_status" = "RESERVED" ]; then
-        echo "${x_host}:${x_port}	$x_status"
+  fi
+  if [ "$x_status" = "RETIRED" -o "$x_status" = "RESERVED" ]; then
+    printf '%s\t%-8s\n'		"${x_host}:${x_port}"	"$x_status"
         continue
     fi
     test "$x_status" = "READYING"  &&  unset x_status
-    tmpfile=`mktemp`
-    ( echo ; sleep $delay_sec ) | telnet $x_host $x_port >$tmpfile 2>&1 &
+  ( echo ; test -z "$netcat" && sleep ${delay_sec} ) | ${netcat:-telnet} $x_host $x_port >$temp 2>&1 &
     pid=$!
-    trap 'rm -f $tmpfile; kill $pid >/dev/null 2>&1' 1 2 15
+  trap 'rm -f $temp; kill $pid >/dev/null 2>&1' 1 2 15
     ( sleep `expr $delay_sec + 2`  &&  kill $pid ) >/dev/null 2>&1 &
     guard=$!
     wait $pid >/dev/null 2>&1
     kill $guard >/dev/null 2>&1
-    test -n "$HTTP_CAF_EXTERNAL"  || \
-        cp="`tail +4 $tmpfile 2>/dev/null | grep -s '^[0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}:[0-9]\{1,5\}'`"
-    grep -qs 'NCBI Firewall Daemon:  Invalid ticket\.  *Connection closed\.' $tmpfile >/dev/null 2>&1
+  test _"$HTTP_CAF_EXTERNAL" != _""  ||  \
+    cp="`tail +3 $temp 2>/dev/null | grep -s '[[]\{0,1\}[0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[.][0-9]\{1,3\}[]]\{0,1\}:[0-9]\{1,5\}'`"
+  grep -qs 'NCBI Firewall Daemon:  Invalid ticket\.  *Connection closed\.' $temp >/dev/null 2>&1
     if   [ $? -eq 0 ]; then
-        echo "${x_host}:${x_port}	${x_status:-OKAY}${cp:+	}${cp}"
+    printf '%s\t%-8s%s\n'	"${x_host}:${x_port}"	"${x_status:-OKAY}"	"${cp:+	}${cp}"
     elif [ -z "$x_status" ]; then
-        echo "${x_host}:${x_port}	READYING"
+    printf '%s\t%-8s\n'		"${x_host}:${x_port}"	"READYING"
+  else
+    x_reason="( telnet $x_host $x_port )"
+    if [ -x "$helper" ]; then
+      x_status="`$helper $x_host $x_port`"
+      test $? -eq 0  &&  x_reason=''
     else
-        echo "${x_host}:${x_port}	FAILED	( telnet $x_host $x_port )"
+      x_status=''
+    fi
+    printf '%s\t%-8s%s\n'	"${x_host}:${x_port}"	"${x_status:-FAILED}"	"${x_reason:+	}${x_reason}"
     fi
-    rm -f $tmpfile
+  rm -f $temp
 done 2>&1 | grep -v 'Terminated'
diff --git a/doc/gene2xml.txt b/doc/gene2xml.txt
index 61361c9..402e88f 100644
--- a/doc/gene2xml.txt
+++ b/doc/gene2xml.txt
@@ -6,6 +6,20 @@ Solaris, and Windows) and is distributed in the asn1-converters area of the
 NCBI public ftp site. From asn1-converters, navigate into by_program and
 then gene2xml, and download and extract the appropriate file.
 
+The following versions of gene2xml have been made available:
+
+  Version 1.3  March 1, 2010
+
+    Report write failures
+
+  Version 1.2  February 1, 2010
+
+    Adds new choices with these values:
+      ncRNA (8)
+      tmRNA (9)
+      miscRNA (10)
+    Adds elements RNA-gen, RNA-qual, RNA-qual-set
+
 Entrez Gene data are stored as compressed binary Entrezgene-Set ASN.1 files
 on the NCBI ftp site, and have the suffix .ags.gz. These are several-fold
 smaller than compressed XML files, resulting in a significant savings of
@@ -14,6 +28,11 @@ text XML files with the same name but with .xgs as the suffix.
 
 The command-line arguments to gene2xml are described below.
 
+  -   Version and Argument Display
+
+Displays the version of the gene2xml program and its arguments and their
+descriptions.
+
   -p  Path to Files [String]  Optional
 
 Use -p if you want to process a entire directory of files. In this case,
diff --git a/doc/man/asn2all.1 b/doc/man/asn2all.1
index a105a5c..1e7ecf1 100644
--- a/doc/man/asn2all.1
+++ b/doc/man/asn2all.1
@@ -1,4 +1,4 @@
-.TH ASN2ALL 1 2009-07-31 NCBI "NCBI Tools User's Manual"
+.TH ASN2ALL 1 2010-09-01 NCBI "NCBI Tools User's Manual"
 .SH NAME
 asn2all \- generate reports from ASN.1 biological data
 .SH SYNOPSIS
@@ -80,6 +80,8 @@ Input ASN.1 type:
 .PD 0
 .IP a
 Automatic (default)
+.IP c
+Catenated
 .IP z
 Any
 .IP e
diff --git a/doc/man/asndisc.1 b/doc/man/asndisc.1
new file mode 100644
index 0000000..f1b9254
--- /dev/null
+++ b/doc/man/asndisc.1
@@ -0,0 +1,188 @@
+.TH ASNDISC 1 2010-09-02 NCBI "NCBI Tools User's Manual"
+.SH NAME
+asndisc \- check ASN.1 biological sequence records for discrepancies
+.SH SYNOPSIS
+.B asndisc
+[\|\fB\-\fP\|]
+[\|\fB\-B\fP\|]
+[\|\fB\-C\fP\ \fIN\fP\|]
+[\|\fB\-I\fP\ \fIpath\fP\|]
+[\|\fB\-N\fP\ \fIfilename\fP\|]
+[\|\fB\-R\fP\|]
+[\|\fB\-S\fP\|]
+[\|\fB\-T\fP\|]
+[\|\fB\-X\fP\ \fItests\fP\|]
+[\|\fB\-Z\fP\|]
+[\|\fB\-a\fP\ \fIstr\fP\|]
+[\|\fB\-b\fP\|]
+[\|\fB\-c\fP\|]
+[\|\fB\-d\fP\ \fItests\fP\|]
+[\|\fB\-e\fP\ \fItests\fP\|]
+[\|\fB\-f\fP\|]
+[\|\fB\-i\fP\ \fIfilename\fP\|]
+[\|\fB\-k\fP\|]
+[\|\fB\-l\fP\|]
+[\|\fB\-o\fP\ \fIfilename\fP\|]
+[\|\fB\-p\fP\ \fIpath\fP\|]
+[\|\fB\-r\fP\ \fIdir\fP\|]
+[\|\fB\-s\fP\ \fIext\fP\|]
+[\|\fB\-u\fP\|]
+[\|\fB\-x\fP\ \fIstr\fP\|]
+.SH DESCRIPTION
+\fBasndisc\fP is a command-line tool to check ASN.1-format biological
+sequence records for discrepancies.
+.SH OPTIONS
+A summary of options is included below.
+.TP
+\fB\-\fP
+Print usage message
+.TP
+\fB\-B\fP
+Big sequence report
+.TP
+\fB\-C\fP\ \fIN\fP
+Max count
+.TP
+\fB\-I\fP\ \fIpath\fP
+Path to Indexed binary ASN.1 data
+.TP
+\fB\-N\fP\ \fIfilename\fP
+File with list of product names to check
+.TP
+\fB\-R\fP
+Remote fetching from ID
+.TP
+\fB\-S\fP
+Summary report
+.TP
+\fB\-T\fP
+Use threads
+.TP
+\fB\-X\fP\ \fItests\fP
+EXpand report categories (comma-delimited list of test names as listed
+below or ALL).
+.TP
+\fB\-Z\fP
+Remote CDS Product Fetch
+.TP
+\fB\-a\fP\ \fIstr\fP
+.RS
+.PD 0
+.IP a
+Any (default)
+.IP e
+seq-Entry
+.IP b
+Bioseq
+.IP s
+bioseq-Set
+.IP m
+seq-subMit
+.IP t
+baTch bioseq-set
+.IP u
+batch seq-sUbmit
+.PD
+.RE
+.TP
+\fB\-b\fP
+Batch file is Binary
+.TP
+\fB\-c\fP
+Batch file is Compressed
+.TP
+\fB\-d\fP\ \fIstr\fP
+Disable tests (comma-delimited list of test names as listed below).
+.TP
+\fB\-e\fP\ \fIstr\fP
+Enable tests (comma-delimited list of test names as listed below).
+.TP
+\fB\-f\fP
+Use Feature table output format
+.TP
+\fB\-i\fP\ \fIfilename\fP
+Single input file (standard input by default)
+.TP
+\fB\-k\fP
+Local fetching
+.TP
+\fB\-l\fP
+Load components in advance
+.TP
+\fB\-o\fP\ \fIfilename\fP
+Single output file
+.TP
+\fB\-p\fP\ \fIpath\fP
+Path to ASN.1 files
+.TP
+\fB\-r\fP\ \fIdir\fP
+Output directory
+.TP
+\fB\-s\fP\ \fIext\fP
+Output file Suffix (\fB.dr\fP by default)
+.TP
+\fB\-u\fP
+Recurse
+.TP
+\fB\-x\fP\ \fIstr\fP
+File selection substring (\fB.sqn\fP by default)
+.SS AVAILABLE TESTS
+.P
+.ad l
+.nh
+MISSING_GENES, EXTRA_GENES, MISSING_LOCUS_TAGS, DUPLICATE_LOCUS_TAGS,
+BAD_LOCUS_TAG_FORMAT, INCONSISTENT_LOCUS_TAG_PREFIX, NON_GENE_LOCUS_TAG,
+DISC_COUNT_NUCLEOTIDES, MISSING_PROTEIN_ID, INCONSISTENT_PROTEIN_ID,
+FEATURE_LOCATION_CONFLICT, GENE_PRODUCT_CONFLICT, DUPLICATE_GENE_LOCUS,
+EC_NUMBER_NOTE, PSEUDO_MISMATCH, JOINED_FEATURES, OVERLAPPING_GENES,
+OVERLAPPING_CDS, CONTAINED_CDS, RNA_CDS_OVERLAP, SHORT_CONTIG,
+INCONSISTENT_BIOSOURCE, SUSPECT_PRODUCT_NAMES, INCONSISTENT_SOURCE_DEFLINE,
+PARTIAL_CDS_COMPLETE_SEQUENCE, EC_NUMBER_ON_UNKNOWN_PROTEIN,
+TAX_LOOKUP_MISSING, TAX_LOOKUP_MISMATCH, SHORT_SEQUENCES, SUSPECT_PHRASES,
+DISC_SUSPICIOUS_NOTE_TEXT, COUNT_TRNAS, FIND_DUP_TRNAS, FIND_BADLEN_TRNAS,
+FIND_STRAND_TRNAS, COUNT_RRNAS, FIND_DUP_RRNAS, RNA_NO_PRODUCT,
+TRANSL_NO_NOTE, NOTE_NO_TRANSL, TRANSL_TOO_LONG, CDS_TRNA_OVERLAP,
+COUNT_PROTEINS, DISC_FEAT_OVERLAP_SRCFEAT, MISSING_GENPRODSET_PROTEIN,
+DUP_GENPRODSET_PROTEIN, MISSING_GENPRODSET_TRANSCRIPT_ID,
+DISC_DUP_GENPRODSET_TRANSCRIPT_ID, DISC_PERCENT_N, N_RUNS, ZERO_BASECOUNT,
+ADJACENT_PSEUDOGENES, NO_ANNOTATION, DISC_INFLUENZA_DATE_MISMATCH,
+DISC_SHORT_INTRON, DISC_MISSING_VIRAL_QUALS, DISC_SRC_QUAL_PROBLEM,
+DISC_MISSING_SRC_QUAL, DISC_DUP_SRC_QUAL, DISC_DUP_SRC_QUAL_DATA,
+DISC_HAPLOTYPE_MISMATCH, DISC_FEATURE_MOLTYPE_MISMATCH,
+DISC_CDS_WITHOUT_MRNA, DISC_EXON_INTRON_CONFLICT, DISC_FEATURE_COUNT,
+DISC_SPECVOUCHER_TAXNAME_MISMATCH, DISC_GENE_PARTIAL_CONFLICT,
+DISC_FLATFILE_FIND_ONCALLER, DISC_CDS_PRODUCT_FIND, DISC_DUP_DEFLINE,
+DUP_DISC_ATCC_CULTURE_CONFLICT, DISC_USA_STATE, DISC_INCONSISTENT_MOLTYPES,
+DISC_SUBMITBLOCK_CONFLICT, DISC_POSSIBLE_LINKER,
+DISC_TITLE_AUTHOR_CONFLICT, DISC_BAD_GENE_STRAND,
+DISC_MAP_CHROMOSOME_CONFLICT, DISC_RBS_WITHOUT_GENE,
+DISC_CITSUBAFFIL_CONFLICT, DISC_REQUIRED_CLONE, DISC_SOURCE_QUALS_ASNDISC,
+DISC_mRNA_ON_WRONG_SEQUENCE_TYPE, DISC_RETROVIRIDAE_DNA,
+DISC_CHECK_AUTH_CAPS, DISC_CHECK_RNA_PRODUCTS_AND_COMMENTS,
+DISC_MICROSATELLITE_REPEAT_TYPE, DISC_MITOCHONDRION_REQUIRED,
+DISC_UNPUB_PUB_WITHOUT_TITLE, DISC_QUALITY_SCORES,
+DISC_INTERNAL_TRANSCRIBED_SPACER_RRNA, DISC_PARTIAL_PROBLEMS,
+DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_PROBLEMS,
+DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_EXCEPTION, DISC_SUSPECT_RRNA_PRODUCTS,
+DISC_SUSPECT_MISC_FEATURES, DISC_BACTERIA_MISSING_STRAIN,
+DISC_MISSING_DEFLINES, DISC_MISSING_AFFIL,
+DISC_BACTERIA_SHOULD_NOT_HAVE_ISOLATE, DISC_BACTERIA_SHOULD_NOT_HAVE_MRNA,
+DISC_CDS_HAS_NEW_EXCEPTION, DISC_TRINOMIAL_SHOULD_HAVE_QUALIFIER,
+DISC_METAGENOMIC, DISC_METAGENOME_SOURCE, ONCALLER_GENE_MISSING,
+ONCALLER_SUPERFLUOUS_GENE, DISC_SHORT_RRNA, ONCALLER_CHECK_AUTHORITY,
+ONCALLER_CONSORTIUM, ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH,
+ONCALLER_MULTISRC, ONCALLER_MULTIPLE_CULTURE_COLLECTION,
+DISC_SEGSETS_PRESENT, DISC_NONWGS_SETS_PRESENT, DISC_FEATURE_LIST,
+DISC_CATEGORY_HEADER, DISC_MISMATCHED_COMMENTS,
+DISC_STRAIN_TAXNAME_MISMATCH, DISC_HUMAN_HOST,
+DISC_BAD_BACTERIAL_GENE_NAME, ONCALLER_ORDERED_LOCATION,
+ONCALLER_COMMENT_PRESENT, ONCALLER_DEFLINE_ON_SET,
+ONCALLER_HIV_RNA_INCONSISTENT, SHORT_PROT_SEQUENCES, TEST_EXON_ON_MRNA,
+TEST_HAS_PROJECT_ID
+.hy
+.ad b
+.SH AUTHOR
+The National Center for Biotechnology Information.
+.SH SEE ALSO
+.BR asnval (1),
+.BR cleanasn (1).
diff --git a/doc/man/asntool.1 b/doc/man/asntool.1
index 0579def..16d54fe 100644
--- a/doc/man/asntool.1
+++ b/doc/man/asntool.1
@@ -1,4 +1,4 @@
-.TH ASNTOOL 1 2005-05-16 NCBI "NCBI Tools User's Manual"
+.TH ASNTOOL 1 2010-09-01 NCBI "NCBI Tools User's Manual"
 .SH NAME
 asntool \- process ASN.1 module specifications
 .SH SYNOPSIS
@@ -13,6 +13,7 @@ asntool \- process ASN.1 module specifications
 [\|\fB\-L\fP\ \fIstr\fP\|]
 [\|\fB\-M\fP\ \fIfilename,...\fP\|]
 [\|\fB\-P\fP\ \fIstr\fP\|]
+[\|\fB\-Q\fP\|]
 [\|\fB\-S\fP\ \fIfilename\fP\|]
 [\|\fB\-T\fP\ \fIfilename\fP\|]
 [\|\fB\-V\fP\|]
@@ -77,6 +78,9 @@ Search the ASN.1 modules in \fIfilename,...\fP for external references
 \fB\-P\fP\ \fIstr\fP
 XML module prefix for \fBDOCTYPE\fP
 .TP
+\fB\-Q\fP
+Use quoted syntax form for generated include files
+.TP
 \fB\-S\fP\ \fIfilename\fP
 Send debugging output to \fIfilename\fP rather than stderr
 .TP
diff --git a/doc/man/asnval.1 b/doc/man/asnval.1
index 2398029..e11ebdd 100644
--- a/doc/man/asnval.1
+++ b/doc/man/asnval.1
@@ -1,4 +1,4 @@
-.TH ASNVAL 1 2009-07-31 NCBI "NCBI Tools User's Manual"
+.TH ASNVAL 1 2010-09-02 NCBI "NCBI Tools User's Manual"
 .SH NAME
 asnval \- validate ASN.1 biological sequence records
 .SH SYNOPSIS
@@ -27,6 +27,7 @@ asnval \- validate ASN.1 biological sequence records
 [\|\fB\-c\fP\|]
 [\|\fB\-d\fP\ \fIpath\fP\|]
 [\|\fB\-e\fP\|]
+[\|\fB\-f\fP\ \fIstr\fP\|]
 [\|\fB\-i\fP\ \fIfilename\fP\|]
 [\|\fB\-k\fP\|]
 [\|\fB\-l\fP\|]
@@ -131,6 +132,8 @@ Input ASN.1 type:
 .PD 0
 .IP a
 Automatic (default)
+.IP c
+Catenated
 .IP z
 Any
 .IP e
@@ -160,6 +163,9 @@ Path to Indexed Binary ASN.1 Data
 \fB\-e\fP
 Ignore transcription/translation Exceptions
 .TP
+\fB\-x\fP\ \fIstr\fP
+Substring filter
+.TP
 \fB\-i\fP\ \fIfilename\fP
 Single input file (standard input by default)
 .TP
@@ -189,5 +195,6 @@ File selection substring (\fB.ent\fP by default)
 .SH AUTHOR
 The National Center for Biotechnology Information.
 .SH SEE ALSO
+.BR asndisc (1),
 .BR cleanasn (1),
 .BR sequin (1).
diff --git a/doc/man/cleanasn.1 b/doc/man/cleanasn.1
index 403e34e..c363696 100644
--- a/doc/man/cleanasn.1
+++ b/doc/man/cleanasn.1
@@ -1,31 +1,38 @@
-.TH CLEANASN 1 2009-07-31 NCBI "NCBI Tools User's Manual"
+.TH CLEANASN 1 2010-09-02 NCBI "NCBI Tools User's Manual"
 .SH NAME
 cleanasn \- clean up irregularities in NCBI ASN.1 objects
 .SH SYNOPSIS
 .B cleanasn
 [\|\fB\-\fP\|]
+[\|\fB\-A\fP\ \fIfilename\fP\|]
 [\|\fB\-D\fP\ \fIstr\fP\|]
 [\|\fB\-F\fP\ \fIstr\fP\|]
 [\|\fB\-K\fP\ \fIstr\fP\|]
 [\|\fB\-L\fP\ \fIfilename\fP\|]
 [\|\fB\-M\fP\ \fIfilename\fP\|]
 [\|\fB\-N\fP\ \fIstr\fP\|]
-[\|\fB\-P\fP\|]
+[\|\fB\-P\fP\ \fIstr\fP\|]
 [\|\fB\-Q\fP\ \fIstr\fP\|]
 [\|\fB\-R\fP\|]
+[\|\fB\-S\fP\ \fIstr\fP\|]
 [\|\fB\-T\fP\|]
 [\|\fB\-U\fP\ \fIstr\fP\|]
 [\|\fB\-X\fP\ \fIstr\fP\|]
 [\|\fB\-a\fP\ \fIstr\fP\|]
 [\|\fB\-b\fP\|]
 [\|\fB\-c\fP\|]
+[\|\fB\-d\fP\ \fIstr\fP\|]
 [\|\fB\-f\fP\ \fIstr\fP\|]
 [\|\fB\-i\fP\ \fIfilename\fP\|]
+[\|\fB\-j\fP\ \fIfilename\fP\|]
+[\|\fB\-k\fP\ \fIfilename\fP\|]
 [\|\fB\-m\fP\ \fIstr\fP\|]
+[\|\fB\-n\fP\ \fIpath\fP\|]
 [\|\fB\-o\fP\ \fIfilename\fP\|]
 [\|\fB\-p\fP\ \fIpath\fP\|]
 [\|\fB\-q\fP\ \fIpath\fP\|]
 [\|\fB\-r\fP\ \fIpath\fP\|]
+[\|\fB\-v\fP\ \fIpath\fP\|]
 [\|\fB\-x\fP\ \fIext\fP\|]
 .SH DESCRIPTION
 \fBcleanasn\fP is a utility program to clean up irregularities in NCBI
@@ -36,12 +43,21 @@ A summary of options is included below.
 \fB\-\fP
 Print usage message
 .TP
+\fB\-A\fP\ \fIfilename\fP
+Accession list file
+.TP
 \fB\-D\fP\ \fIstr\fP
 Clean up descriptors, per the flags in str:
 .RS
 .PD 0
 .IP t
 Remove Title
+.IP n
+Remove Nuc-Prot Set Title
+.IP e
+Remove Pop/Phy/Mut/Eco Set Title
+.IP p
+Remove Protein Title
 .PD
 .RE
 .TP
@@ -74,6 +90,8 @@ GpipeSeqEntryCleanup
 Normalize Descriptor Order
 .IP u
 Remove NcbiCleanup User Objects
+.IP c
+Synchronize Genetic Codes
 .PD
 .RE
 .TP
@@ -99,24 +117,87 @@ ClearFeatureIDs
 .RE
 .TP
 \fB\-P\fP
-Publication Lookup
+Publication lookup:
+.RS
+.PD 0
+.IP u
+Update PMID-only publication
+.IP #
+Replace unpublished with PMID
+.PD
+.RE
 .TP
 \fB\-Q\fP\ \fIstr\fP
 Report:
 .RS
 .PD 0
+.IP c
+Record count
 .IP r
-ASN.1 BSEC/SSEC Report
+ASN.1 BSEC report
+.IP s
+ASN.1 SSEC report
+.IP n
+NORM vs. SSEC report
+.IP e
+PopPhyMutEco AutoDef report
+.IP o
+Overlap report
+.IP d
+Log SSEC differences
 .IP g
-GenBank SSEC Diff
+GenBank SSEC diff
+.IP f
+asn2gb/asn2flat diff
+.IP v
+Validator SSEC diff
 .IP m
-Modernization
+Modernize Gene/RNA/PCR
+.IP u
+Unpublished Pub lookup
+.IP p
+Published Pub lookup
+.IP x
+Custom scan
 .PD
 .RE
 .TP
 \fB\-R\fP
 Remote fetching from ID (NCBI sequence databases)
 .TP
+\fB\-S\fP\ \fIstr\fP
+Selective difference filter (capital letters skip)
+.RS
+.PD 0
+.IP s
+SSEC
+.IP b
+BSEC
+.IP A
+Author
+.IP p
+Publication
+.IP l
+Location
+.IP r
+RNA
+.IP q
+Qualifier sort order
+.IP g
+Genbank block
+.IP k
+Package CdRegion or parts features
+.IP m
+Move publication
+.IP o
+Leave duplicate Bioseq publication
+.IP d
+Automatic definition line
+.IP e
+Pop/Phy/Mut/Eco Set definition line
+.PD
+.RE
+.TP
 \fB\-T\fP
 Taxonomy Lookup
 .TP
@@ -139,6 +220,16 @@ Miscellaneous options, per str:
 .PD 0
 .IP d
 Automatic definition line
+.IP e
+Pop/Phy/Mut/Eco Set Definition Line
+.IP n
+Instantiate NC Title
+.IP m
+Instantiate NM Titles
+.IP x
+Special XM Titles
+.IP p
+Instantiate Protein Titles
 .PD
 .RE
 .TP
@@ -167,12 +258,41 @@ Input ASN.1 is Binary
 \fB\-c\fP
 Input ASN.1 is Compressed
 .TP
+\fB\-d\fP\ \fIstr\fP
+Source database
+.RS
+.PD 0
+.IP a
+Any (default)
+.IP g
+GenBank
+.IP e
+EMBL
+.IP d
+DDBJ
+.IP r
+RefSeq
+.IP n
+NCBI
+.IP x
+Exclude EMBL/DDBJ
+.IP y
+Exclude gbcon, gbest, gbgss, gbhtg, gbpat, gbsts
+.PD
+.RE
+.TP
 \fB\-f\fP\ \fIstr\fP
 Substring filter
 .TP
 \fB\-i\fP\ \fIfilename\fP
 Single input file (defaults to stdin)
 .TP
+\fB\-j\fP\ \fIfilename\fP
+First filename
+.TP
+\fB\-k\fP\ \fIfilename\fP
+Last filename
+.TP
 \fB\-m\fP\ \fIstr\fP
 Flatfile mode:
 .RS
@@ -188,6 +308,9 @@ Dump
 .PD
 .RE
 .TP
+\fB\-n\fP\ \fIpath\fP
+asn2flat executable (default is /netopt/ncbi_tools/bin/asn2flat)
+.TP
 \fB\-o\fP\ \fIfilename\fP
 Single output file (defaults to stdout)
 .TP
@@ -200,10 +323,14 @@ Ffdiff executable (default is /netopt/genbank/subtool/bin/ffdiff)
 \fB\-r\fP\ \fIpath\fP
 Path for results
 .TP
+\fB\-v\fP\ \fIpath\fP
+asnval executable (default is /netopt/ncbi_tools/bin/asnval)
+.TP
 \fB\-x\fP\ \fIext\fP
 File selection suffix for use with \fB\-p\fP (defaults to \fB.ent\fP)
 .SH AUTHOR
 The National Center for Biotechnology Information.
 .SH SEE ALSO
-asnval (1),
-sequin (1).
+.BR asndisc (1),
+.BR asnval (1),
+.BR sequin (1).
diff --git a/doc/man/tbl2asn.1 b/doc/man/tbl2asn.1
index 6b8a3df..0c9b5d3 100644
--- a/doc/man/tbl2asn.1
+++ b/doc/man/tbl2asn.1
@@ -1,4 +1,4 @@
-.TH TBL2ASN 1 2009-07-31 NCBI "NCBI Tools User's Manual"
+.TH TBL2ASN 1 2010-09-01 NCBI "NCBI Tools User's Manual"
 .SH NAME
 tbl2asn \- prepare a GenBank submission using an ASCII feature table
 .SH SYNOPSIS
@@ -13,6 +13,7 @@ tbl2asn \- prepare a GenBank submission using an ASCII feature table
 [\|\fB\-H\fP\ \fIstr\fP\|]
 [\|\fB\-K\fP\|]
 [\|\fB\-L\fP\|]
+[\|\fB\-N\fP\ \fIn\fP\|]
 [\|\fB\-O\fP\|]
 [\|\fB\-P\fP\|]
 [\|\fB\-Q\fP\|]
@@ -43,6 +44,7 @@ tbl2asn \- prepare a GenBank submission using an ASCII feature table
 [\|\fB\-t\fP\ \fIfilename\fP\|]
 [\|\fB\-u\fP\|]
 [\|\fB\-v\fP\|]
+[\|\fB\-w\fP\ \fIfilename\fP\|]
 [\|\fB\-x\fP\ \fIstr\fP\|]
 [\|\fB\-y\fP\ \fIstr\fP\|]
 [\|\fB\-z\fP\|]
@@ -98,6 +100,9 @@ Safe Bioseq-set
 \fB\-L\fP
 Force Local protein_id/transcript_id
 .TP
+\fB\-N\fP\ \fIn\fP
+Project version number
+.TP
 \fB\-O\fP
 Allow run-on ORFs
 .TP
@@ -195,6 +200,8 @@ similar product names and do not contain 'ABC'
 .IP x
 Extend partial ends of features by one or two nucleotides to abut gaps
 or sequence ends
+.IP s
+Add exception to short introns
 .PD
 .RE
 .TP
@@ -255,6 +262,9 @@ Convert GenProdSet to NucProtSet
 \fB\-v\fP
 Validate (deprecated in favor of \fB-V v\fP)
 .TP
+\fB\-w\fP\ \fIfilename\fP
+Single structured comment file
+.TP
 \fB\-x\fP\ \fIstr\fP
 Suffix (default = \fB.fsa\fP)
 .TP
diff --git a/errmsg/flat2asn.msg b/errmsg/flat2asn.msg
deleted file mode 100644
index ee02454..0000000
--- a/errmsg/flat2asn.msg
+++ /dev/null
@@ -1,326 +0,0 @@
-MODULE flat2asn
-$$ FORMAT, 1
-$^   NonAsciiChar, 1, SEV_ERROR
-# This is a comment REJECT(LANL,EMBL,DDBJ,PIR,SP)
-No column of any block of the flat file in any of the formats
-is allowed to have a nonASCII character.  NonASCII is defined
-as anything greater than  decimal value 126 (`~`) or less than
-decimal 32 (space) except decimal 10, which is a newline.
-$^   MissingEnd, 2, SEV_ERROR
-The // line was not found after sequence was found before a line
-with an letter was found.  Likely to be a truncated entry.
-$^   MissingField, 3, SEV_ERROR
- Required field was not found in the flat file
-$^   LocusLinePosition, 4, SEV_ERROR
-The GenBank flat file format requires fixed column positions
-for a variety of fields.  The following are the fields and
-the columns that are expected:
-      bp               31-32  literally, "bp"
-      Strand           34-36
-          This must be blank or ss-, ds-, ms-};
-      Molecule type    37-40
-          This must be blank or DNA , RNA , pre-mRNA, mRNA,
-             rRNA, tRNA, uRNA, or scRNA.
-      Topology          43-52
-             Circular, may be specified or it may be blank
-             ("Tandem???")
-      Division          53-55
-          Legal division codes are: PRI, ROD, MAM, VRT, INV, PLN,
-          BCT, RNA, VRL, PHG, SYN, UNA, or EST.
-        (blank???)
-         New or mispelled Embl divisions will be reported with a
-         DIVISION_NewDivCode error code.  Note that EMBL uses FUN.
-      Date               63-73, and be in dd-mmm-yyyy format.
-$^   DirSubMode, 5, SEV_WARNING
-Not standard EMBL format, used in DirSubMode only
-$^   LineTypeOrder, 6, SEV_WARNING
-$^   MissingSequenceData, 7, SEV_ERROR
-$^   ContigWithSequenceData, 8, SEV_ERROR
-$^   MissingContigFeature, 9, SEV_ERROR
-$^   MissingSourceFeature, 10, SEV_ERROR
-$^   MultipleCopyright, 11, SEV_WARNING
-$^   MissingCopyright, 12, SEV_ERROR
-$^   MultiplePatRefs, 13, SEV_ERROR
-$$ DATACLASS, 2
-$^   UnKnownClass, 1, SEV_WARNING
-Swissprot error, only standard and preliminary are allowed.
-$$ ENTRY, 3
-$^   ParsingComplete, 2, SEV_INFO
-$^   Begin, 3, SEV_ERROR
-Looking for valid begining according to -f arguement in command line:
-LOCUS for GenBank; ID for EMBL; ENTRY for PIR;
-$^   Skipped, 6, SEV_ERROR
-$^   Repeated, 7, SEV_WARNING
-$^   LongSequence, 8, SEV_ERROR
-$^   THC_Sequence, 9, SEV_WARNING
-$^   Parsed, 10, SEV_INFO
-$^   ParsingSetup, 11, SEV_INFO
-$^   GBBlock_not_Empty, 12, SEV_WARNING
-$^   LongHTGSSequence, 13, SEV_WARNING
-$$ DATE, 5
-$^   IllegalDate, 2, SEV_WARNING
-Date not in dd-mmm-yyy format
-$$ SEQUENCE, 7
-$^   UnknownBaseHTG3, 1, SEV_WARNING
-$^   SeqLenNotEq, 2, SEV_WARNING
-The declared length of the sequence in the record was not
-equal to the acutal number of residues found.
-$^   BadResidue, 3, SEV_ERROR
-Depending upon whether nucleic acid or protein, there are
-different single letter legal codes.
-$^   BadData, 4, SEV_WARNING
-Can't parse the entry because of bad sequence data.
-$$ SEGMENT, 8
-$^   MissSegEntry, 1, SEV_ERROR
-The Segmented set (GenBank) that is declared has some
-missing members.  That is, if there 6 members declared,
-The set might only have:
- 1 of 6,
- 2 of 6,
- 4 of 6,
- 5 of 6 and
- 6 of 6, and thus be missing 3 of 6.
-   Another possible problem is there could be a line:
-      "3 of 5", instad of "3 of 6"
-$^   DiffMolType, 2, SEV_WARNING
-A segmented set is supposed to be from the same molecule,
-but with some unknown regions.  It should therefore all be
-of the same type of molecule.  For this error to occur, there
-have to be different molecule types for different segments
-within the set.
-$^   BadLocusName, 3, SEV_ERROR
-For GenBank in a segmented set, it is an error if the segment number
-can not be found at the end of the LOCUS name.  So a LOCUS name
-in SEGMENT 2 of 10 must end in 02, as ABCD02.
-$^   IncompSeg, 4, SEV_ERROR
-There were not three blank-separated token on the SEGMENT line, in
-GenBank Flat File format, the segment line has to look like:
-SEGMENT     4 of 14
- for example.
-$^   PubMatch, 5, SEV_WARNING
-There were matching reference with different serial numbers in
-segments.
-$^   OnlyOneMember, 6, SEV_WARNING
-$^   Rejected, 7, SEV_WARNING
-$$ ACCESSION, 9
-$^   BadAccessNum, 2, SEV_ERROR
-Accession must be upper case letter followed by 5 digits.
-$^   NoAccessNum, 3, SEV_ERROR
-No accession number could be found for this entry. The line number
-given is only approximate.
-$^   MoreAccessLine, 4, SEV_INFO
-More than one accession block was found.  Continuation lines with
-the wrong format can cause this in GenBank format.
-$^   ForeignAccessNum, 5, SEV_WARNING
-$$ LOCUS, 10
-$^   WrongTopology, 2, SEV_WARNING
-This message occurs when looking for either Circular or 'RNA' or 'DNA' in
-embl mode.  Anything other than this will cause this warning.
-$^   NoGIBBModMolType, 3, SEV_WARNING
- In the flat files, the only legal values are blank, RNA, pre-mRNA, mRNA,
- rRNA, tRNA, uRNA, ss-RNA, ds-RNA, ms-RNA, scRNA, DNA, ds-DNA, and ss-DNA
-$^   MayBeNewSpeciesCode, 4, SEV_WARNING
-Swiss-Prot specific error.  The species is not in the list of
-LOCUS name prefix-species pairs.
-$^   NoSpeciesCode, 5, SEV_WARNING
-Swiss-Prot error when no species can be found.
-$^   NoMolType, 6, SEV_WARNING
-Can't find Molecule type
-$^   BadLocusName, 7, SEV_ERROR
-There are multiple possible ways to get this error message.
-In all formats, this identifier must have either digits or
-uppercase letters.
-For Swiss-Prot, the rules are more complicated:
-Locus name consists of up to 10 uppercase alphanumeric characters
-      rule: X_Y format
-         X is a mnemonic code, up to 4 alphanumeric characters to represent
-             the protein name.
-         Y is a mnemonic species identification code of at most 5
-             alphanumeric characters to representing the biological source of
-             the protein
-$^   NoLocusName, 8, SEV_ERROR
-No token after 'LOCUS' found in GenBank format.
-$^   NonViralRNAMoltype, 9, SEV_ERROR
-$$ ORGANISM, 11
-$^   NoOrganism, 1, SEV_WARNING
-EMBL: no OS line found
-GenBank: No ORGANISM line in the SOURCE block.
-This message might repeat which trying to guess genetic code.
-$^  HybridOrganism, 2, SEV_WARNING
-In EMBL format only, can have multiple organisms (OS blocks).
-If the taxonomy changes (OC block), this warning is produced.
-$^   Unclassified, 3, SEV_WARNING
-$^   MissParen, 4, SEV_WARNING
-In EMBL format missing parenthesis after common name
-$^   UnknownReplace, 5, SEV_INFO
-$^   DoesntMatchFeats, 6, SEV_ERROR
-$$ KEYWORD, 12
-$^   MultipleHTGPhases, 1, SEV_ERROR
-$^   ESTSubstring, 2, SEV_WARNING
-$^   STSSubstring, 3, SEV_WARNING
-$^   GSSSubstring, 4, SEV_WARNING
-$$ DIVISION, 13
-$^   NewDivCode, 1, SEV_WARNING
-EMBL only (GenBank format related error is a FORMAT.LocusLinePosition
-error), and the legal codes are:
-    FUN, INV, MAM, ORG, PHG, PLN, PRI, PRO, ROD, SYN,
-    UNA, VRL, VRT, and UNC  (UNA == UNC)
-$^   MappedtoEST, 2, SEV_INFO
-KW line maps one of these words:
-     "EST", "EST PROTO((expressed sequence tag)", "expressed sequence tag",
-     "partial cDNA sequence", "transcribed sequence fragment", "TSR",
-     "putatively transcribed partial sequence", "UK putts" };
-GB-block.div becomes "EST"
-$^   MappedtoPAT, 3, SEV_WARNING
-$^   MappedtoSTS, 4, SEV_WARNING
-$^   Mismatch, 5, SEV_WARNING
-$^   MissingESTKeywords, 6, SEV_WARNING
-$^   MissingSTSKeywords, 7, SEV_WARNING
-$^   MissingPatentRef, 8, SEV_WARNING
-$^   PATHasESTKeywords, 9, SEV_WARNING
-$^   PATHasSTSKeywords, 10, SEV_WARNING
-$^   PATHasCDSFeature, 11, SEV_INFO
-$^   STSHasCDSFeature, 12, SEV_WARNING
-$^   NotMappedtoSTS, 13, SEV_WARNING
-$^   ESTHasSTSKeywords, 14, SEV_INFO
-$^   ESTHasCDSFeature, 15, SEV_WARNING
-$^   NotMappedtoEST, 16, SEV_WARNING
-$^   ShouldBeHTG, 17, SEV_ERROR
-$^   MissingGSSKeywords, 18, SEV_INFO
-$^   GSSHasCDSFeature, 19, SEV_WARNING
-$^   NotMappedtoGSS, 20, SEV_WARNING
-$^   MappedtoGSS, 21, SEV_WARNING
-$^   PATHasGSSKeywords, 22, SEV_WARNING
-$^   LongESTSequence, 23, SEV_WARNING
-$^   LongSTSSequence, 24, SEV_WARNING
-$^   LongGSSSequence, 25, SEV_WARNING
-$^   GBBlockDivision, 26, SEV_WARNING
-$^   MappedtoCON, 27, SEV_WARNING
-$^   MissingHTGKeywords, 28, SEV_WARNING
-$^   ShouldNotBeHTG, 29, SEV_ERROR
-$^   ConDivInSegset, 30, SEV_ERROR
-$^   ConDivLacksContig, 31, SEV_WARNING
-$^   WrongHTGKeyword, 32, SEV_ERROR
-$$ DEFINITION, 15
-$^   HTGNotInProgress, 1, SEV_WARNING
-$^   DifferingRnaTokens, 2, SEV_WARNING
-$^   HTGShouldBeComplete, 3, SEV_ERROR
-$$ REFERENCE, 16
-$^   IllegPageRange, 3, SEV_WARNING
-There are many classes of problems that can give this error message, some
-of which are really warnings to have a human take a closer look.
-$^   UnkRefRcToken, 4, SEV_WARNING
-There are a limited number of valid Swiss-Prot Reference Comment
-   (RC line) tokens.  This one is not one.
-$^   UnkRefSubType, 5, SEV_WARNING
-Illegal Swiss-prot Reference SubType.
-$^   IllegalFormat, 6, SEV_WARNING
-$^   IllegalAuthorName, 7, SEV_WARNING
-$^   YearEquZero, 8, SEV_WARNING
-$^   IllegalDate, 9, SEV_WARNING
-$^   Patent, 10, SEV_WARNING
-$^   Thesis, 12, SEV_WARNING
-$^   Book, 14, SEV_WARNING
-$^   DirectSubmission, 15, SEV_WARNING
-$^   Illegalreference, 16, SEV_ERROR
-$^   Fail_to_parse, 17
-$^   No_references, 18, SEV_ERROR
-$^   Xtratext, 19, SEV_WARNING
-$^   InvalidInPress, 22, SEV_WARNING
-$^   EtAlInAuthors, 24, SEV_WARNING
-$^   NonDigitInPages, 25, SEV_WARNING
-$^   LargePageRange, 26, SEV_WARNING
-  Total pages more than ....   means that the total number in the
-                               article is greater than normal.  This
-                               is usually caused by a typographical error.
-$^   InvertPageRange, 27, SEV_WARNING
-  Page number may invert . . .  it looks like the first page is greater
-                               that the last page.
-$^   SingleTokenPageRange, 28, SEV_WARNING
-$^   MissingBookPages, 29, SEV_WARNING
-$^   MissingBookAuthors, 30, SEV_WARNING
-$^   DateCheck, 31, SEV_WARNING
-$^   GsdbRefDropped, 32, SEV_WARNING
-$^   UnusualBookFormat, 33, SEV_WARNING
-$$ FEATURE, 17
-$^   MultFocusedFeats, 1, SEV_ERROR
-$^   ExpectEmptyComment, 6, SEV_WARNING
-specific Swiss-Prot message for INIT_MET feature
-$^   DiscardData, 7, SEV_WARNING
-includes unbalance double quote
-$^   InValidEndPoint, 9, SEV_WARNING
-$^   MissManQual, 10, SEV_WARNING
-$^   NoFeatData, 11, SEV_WARNING
-$^   NoFragment, 12, SEV_WARNING
-$^   NotSeqEndPoint, 13, SEV_WARNING
-$^   OldNonExp, 15, SEV_WARNING
-$^   PartialNoNonTer, 16, SEV_WARNING
-$^   Pos, 17, SEV_WARNING
-$^   TooManyInitMet, 20, SEV_WARNING
-specific Swiss-Prot error message
-$^   UnEqualEndPoint, 22, SEV_WARNING
-$^   UnknownFeatKey, 23, SEV_WARNING
-$^   UnknownQualSpelling, 24, SEV_WARNING
-$^   LocationParsing, 30, SEV_ERROR
-$^   FeatureKeyReplaced, 32, SEV_WARNING
-$^   Dropped, 33, SEV_ERROR
-$^   UnknownDBName, 36, SEV_WARNING
-$^   Duplicated, 37, SEV_WARNING
-$^   NoSource, 38, SEV_WARNING
-$^   MultipleSource, 39, SEV_WARNING
-$$ LOCATION, 18
-$^   FailedCheck, 1, SEV_WARNING
-$^   MixedStrand, 2, SEV_WARNING
-$$ GENENAME, 19
-$^   IllegalGeneName, 1, SEV_WARNING
-$^   DELineGeneName, 2, SEV_WARNING
-$$ BIOSEQSETCLASS, 20
-$^   NewClass, 1, SEV_INFO
-$$ CDREGION, 21
-$^   FrameNotSet, 1, SEV_WARNING
-$^   InternalStopCodonFound, 2, SEV_WARNING
-$^   NoProteinSeq, 6, SEV_WARNING
-$^   TerminalStopCodonMissing, 7, SEV_WARNING
-$^   TranslationDiff, 8, SEV_WARNING
-$^   TranslationsAgree, 9, SEV_INFO
-$^   IllegalStart, 10, SEV_WARNING
-This error is caused by the start of translation being an unrecognized
-initiation codon when the CDS is not recognized as partial.  Usually,
-one adds '<' or '>' on the locations to accurately reflect the biology
-and remove this error.  On rare occasions, a /partial should be added.
-$^   GeneticCodeDiff, 11, SEV_WARNING
-Genetic code returned by Taxonomy server is different from /transl_table
-$^   UnevenLocation, 12, SEV_WARNING
-$^   ShortProtein, 13, SEV_WARNING
-$^   GeneticCodeAssumed, 14, SEV_WARNING
-$^   NoTranslationCompare, 15, SEV_WARNING
-$^   TranslationAdded, 16, SEV_INFO
-$^   InvalidGcodeTable, 17, SEV_WARNING
-$^   ConvertToImpFeat, 18, SEV_ERROR
-$^   BadLocForTranslation, 19, SEV_ERROR
-$^   LocationLength, 20, SEV_WARNING
-$^   TranslationOverride, 21, SEV_WARNING
-$^   FoundBadPIDType, 22, SEV_ERROR
-$^   FoundBadPIDNumber, 23, SEV_RROR
-$^   InvalidDb_xref, 24, SEV_ERROR
-$^   TooManyDbxref, 25, SEV_ERROR
-$^   Multiple_PID, 28, SEV_WARNING
-$$ GENEREF, 22
-$^   GeneIntervalOverlap, 1, SEV_WARNING
-$^   NoUniqMaploc, 2, SEV_WARNING
-$$ PROTREF, 23
-$^   NoNameForProtein, 1, SEV_WARNING
-$$ SEQID, 24
-$^   NoSeqId, 1, SEV_ERROR
-$$ SERVER, 26
-$^   NotUsed, 1, SEV_WARNING
-No protein translation sequence or organism name has been checked;
-Could not guess the genetic code, standard code used.
-$^   Failed, 2, SEV_ERROR
-Call for Taxonomy or/and Medline service failed.
-$^   GcFromSuppliedLineage, 6, SEV_WARNING
-$^   TaxNameWasFound, 7, SEV_INFO
-$$ NCBI_GI, 27
-$^   BadDataFormat, 1, SEV_ERROR
-$$ SPROT, 28
-$^   DRLine, 1, SEV_WARNING
diff --git a/errmsg/indx_err.msg b/errmsg/indx_err.msg
deleted file mode 100644
index 065ad8b..0000000
--- a/errmsg/indx_err.msg
+++ /dev/null
@@ -1,106 +0,0 @@
-MODULE indx_err
-$$ FORMAT, 1
-$^   NonAsciiChar, 1, SEV_ERROR
-# This is a comment REJECT(LANL,EMBL,DDBJ,PIR,SP)
-No column of any block of the flat file in any of the formats
-is allowed to have a nonASCII character.  NonASCII is defined
-as anything greater than  decimal value 126 (`~`) or less than
-decimal 32 (space) except decimal 10, which is a newline.
-$^   MissingEnd, 2, SEV_ERROR
-The // line was not found after sequence was found before a line
-with an letter was found.  Likely to be a truncated entry.
-$^   MissingField, 3, SEV_ERROR
- Required field was not found in the flat file
-$^   LocusLinePosition, 4, SEV_ERROR
-The GenBank flat file format requires fixed column positions
-for a variety of fields.
-$^   DirSubMode, 5, SEV_WARNING
-Not standard EMBL format, used in DirSubMode only
-$^   LineTypeOrder, 6, SEV_ERROR
-$^   Multiple_NI, 8, SEV_ERROR
-$^   ContigInSegset, 9, SEV_ERROR
-$$ ENTRY, 2
-$^   ParsingSetup, 2, SEV_INFO
-$^   Begin, 3, SEV_ERROR
-Looking for valid begining according to -f arguement in command line:
-LOCUS for GenBank; ID for EMBL; ENTRY for PIR;
-$^   InvalidLineType, 6, SEV_ERROR
-$^   Parsed, 7, SEV_INFO
-$^   ParsingComplete, 8, SEV_INFO
-$$ ACCESSION, 3
-$^   BadAccessNum, 2, SEV_ERROR
-Accession must be upper case letter followed by 5 digits.
-$^   NoAccessNum, 3, SEV_ERROR
-No accession number could be found for this entry. The line number
-given is only approximate.
-$^   MoreAccessLine, 4, SEV_INFO
-More than one accession block was found.  Continuation lines with
-the wrong format can cause this in GenBank format.
-$^   ForeignAccessNum, 5, SEV_WARNING
-$^   DirSubTakeOver, 6, SEV_WARNING
-$$ LOCUS, 4
-$^   WrongTopology, 2, SEV_WARNING
-This message occurs when looking for either Circular or 'RNA' or 'DNA' in
-embl mode.  Anything other than this will cause this warning.
-$^   NoGIBBModMolType, 3, SEV_WARNING
- In the flat files, the only legal values are blank, RNA, pre-mRNA, mRNA,
- rRNA, tRNA, uRNA, ss-RNA, ds-RNA, ms-RNA, scRNA, DNA, ds-DNA, and ss-DNA
-$^   MayBeNewSpeciesCode, 4, SEV_WARNING
-Swiss-Prot specific error.  The species is not in the list of
-LOCUS name prefix-species pairs.
-$^   NoSpeciesCode, 5, SEV_WARNING
-Swiss-Prot error when no species can be found.
-$^   NoMolType, 6, SEV_WARNING
-Can't find Molecule type
-$^   BadLocusName, 7, SEV_ERROR
-There are multiple possible ways to get this error message.
-In all formats, this identifier must have either digits or
-uppercase letters.
-For Swiss-Prot, the rules are more complicated:
-Locus name consists of up to 10 uppercase alphanumeric characters
-      rule: X_Y format
-         X is a mnemonic code, up to 4 alphanumeric characters to represent
-             the protein name.
-         Y is a mnemonic species identification code of at most 5
-             alphanumeric characters to representing the biological source of
-             the protein
-$^   NoLocusName, 8, SEV_ERROR
-No token after 'LOCUS' found in GenBank format.
-$$ SEGMENT, 5
-$^   MissSegEntry, 1, SEV_WARNING
-The Segmented set (GenBank) that is declared has some
-missing members.  That is, if there 6 members declared,
-The set might only have:
- 1 of 6,
- 2 of 6,
- 4 of 6,
- 5 of 6 and
- 6 of 6, and thus be missing 3 of 6.
-   Another possible problem is there could be a line:
-      "3 of 5", instad of "3 of 6"
-$^   DiffMolType, 2, SEV_WARNING
-A segmented set is supposed to be from the same molecule,
-but with some unknown regions.  It should therefore all be
-of the same type of molecule.  For this error to occur, there
-have to be different molecule types for different segments
-within the set.
-$^   BadLocusName, 3, SEV_ERROR
-For GenBank in a segmented set, it is an error if the segment number
-can not be found at the end of the LOCUS name.  So a LOCUS name
-in SEGMENT 2 of 10 must end in 02, as ABCD02.
-$^   IncompSeg, 4, SEV_ERROR
-There were not three blank-separated token on the SEGMENT line, in
-GenBank Flat File format, the segment line has to look like:
-SEGMENT     4 of 14
- for example.
-$^   PubMatch, 5, SEV_WARNING
-There were matching reference with different serial numbers in
-segments.
-$$ REFERENCE, 8
-$^   IllegalDate, 1, SEV_WARNING
-$$ FEATURE, 9
-$^   NoFeatData, 1, SEV_WARNING
-$$ SEQID, 10
-$^   NoSeqId, 1, SEV_ERROR
-$$ ORGANISM, 11
-$^   Multiple, 1, SEV_ERROR
diff --git a/errmsg/medarch.msg b/errmsg/medarch.msg
deleted file mode 100644
index 7cfa0d2..0000000
--- a/errmsg/medarch.msg
+++ /dev/null
@@ -1,13 +0,0 @@
-MODULE medarch
-$$ REFERENCE, 1
-$^   MuidNotFound, 1, SEV_WARNING
-$^   SuccessfulMuidLookup, 2, SEV_INFO
-$^   OldInPress, 3, SEV_WARNING
-$^   No_reference, 4, SEV_WARNING
-$^   Multiple_ref, 5, SEV_WARNING
-$^   Multiple_muid, 6, SEV_WARNING
-$^   MedlineMatchIgnored, 7, SEV_WARNING
-$^   MuidMissmatch, 8, SEV_WARNING
-
-$$ PRINT, 2
-$^   Failed, 1, SEV_WARNING
diff --git a/errmsg/valid.msg b/errmsg/valid.msg
index 844d0c1..d8669dc 100644
--- a/errmsg/valid.msg
+++ b/errmsg/valid.msg
@@ -237,6 +237,11 @@ A SeqLit component of a delta Bioseq must not have 0 length.
 $^   DSmRNA, 67
 This mRNA Bioseq is not single stranded.
 
+$^   HighNContentStretch, 68
+This sequence contains long stretches of Ns.
+
+$^   HighNContentPercent, 69
+This sequence contains a high percentage of Ns.
 
 $$ SEQ_DESCR, 2
 
@@ -471,6 +476,40 @@ The title has (PMID #####) embedded in it.
 $^   BadKeyword, 65
 The keyword is not appropriate in this record.
 
+$^   NoOrganismInTitle, 66
+A RefSeq record should have the organism name at the beginning of a nucleotide
+title and bracketed at the end of a protein title.
+
+$^   MissingChromosome, 67
+An NC or AC RefSeq record should have a chromosome annotated.
+
+$^   LatLonAdjacent, 68
+The lat_lon coordinate may be in an adjacent country or in surrounding waters.
+
+$^   BadStrucCommInvalidFieldName, 69
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommInvalidFieldValue, 70
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommMissingField, 71
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommFieldOutOfOrder, 72
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BadStrucCommMultipleFields, 73
+Structured comment is missing required fields or field values do not conform to correct format.
+
+$^   BioSourceNeedsChromosome, 74
+Chromosome should be set on a BioSource descriptor in non-viral complete genomes.
+
+$^   MolInfoConflictsWithBioSource, 75
+Viral lineage information conflicts with MolInfo.
+
+$^   MissingKeyword, 76
+Expected keyword was not found.
+
 
 $$ GENERIC, 3
 
@@ -520,6 +559,14 @@ Some fields in the publication should not be present with other fields.
 $^ SgmlPresentInText, 13
 SGML markup is embedded in text.
 
+$^ UnexpectedPubStatusComment, 14
+An unexpected publication status exists for a print, online-only,
+or ahead-of-print article : Content-Of-Pubdesc.comment-String.
+
+$^ PastReleaseDate, 15
+The record has is marked as hold-until-published, but the release
+anyway date has already passed.
+
 $$ SEQ_PKG, 4
 
 $^   NoCdRegionPtr, 1
@@ -593,6 +640,22 @@ RefSeq records should not be packaged in a popset.
 $^   BioseqSetClassNotSet, 22
 The BioseqSet class field is not set.
 
+$^   OrphanedProtein, 23
+The Bioseq is an INSD or RefSeq protein erroneously not in a nuc-prot set.
+
+$^   MissingSetTitle, 24
+No title was found on a pop/phy/mut/eco set.
+
+$^   NucProtSetHasTitle, 25
+A title descriptor was found on a nuc-prot set.
+
+$^   ComponentMissingTitle, 26
+A title descriptor should be present on the components of a
+pop/phy/mut/eco set.
+
+$^   SingleItemSet, 27
+Only a single Bioseq was found in this BioseqSet. Is that what was intended?
+
 
 $$ SEQ_FEAT, 5
 
@@ -1268,6 +1331,9 @@ This feature has a gene xref that points to a gene on the wrong strand.
 $^ CDSmRNAXrefLocationProblem, 175
 The CDS is not contained within the cross-referenced mRNA.
 
+$^ LocusCollidesWithLocusTag, 176
+A gene locus is identical with a gene locus_tag.
+
 $$ SEQ_ALIGN, 6
 
 $^   SeqIdProblem, 1
diff --git a/link/mswin/ncbilogo.ico b/link/mswin/ncbilogo.ico
index 247e28f..21dffbe 100644
Binary files a/link/mswin/ncbilogo.ico and b/link/mswin/ncbilogo.ico differ
diff --git a/link/mswin/streamer.rc b/link/mswin/streamer.rc
new file mode 100755
index 0000000..6b2657b
--- /dev/null
+++ b/link/mswin/streamer.rc
@@ -0,0 +1,10 @@
+#include <windows.h>
+#include "ncbirc.h"
+
+STRINGTABLE
+   BEGIN
+   STR_PROGRAM, "Submission Template file Editor"
+   END
+
+ICO_PROGRAM  ICON ncbilogo.ico
+ICO_NCBILOGO ICON ncbilogo.ico
diff --git a/make/makeall.unx b/make/makeall.unx
index 86d2ac6..98a9528 100644
--- a/make/makeall.unx
+++ b/make/makeall.unx
@@ -1,6 +1,6 @@
 #	-*- makefile -*- for asntool and ncbi core routines,
 #
-#	$Id: makeall.unx,v 6.302 2009/07/05 22:11:09 ucko Exp $
+#	$Id: makeall.unx,v 6.306 2010/06/08 15:29:02 lavr Exp $
 #
 #	cdromlib data access functions, vibrant, and entrez
 #	SunOS with unbundled ANSI compiler [ make LCL=acc RAN=ranlib CC=acc ]
@@ -178,10 +178,10 @@ SRC1e =	ncbibs.c wwwutils.c ncbierr.c ncbienv.c ncbifile.c \
 	ncbi_priv.c ncbi_ansi_ext.c ncbi_connection.c ncbi_connector.c \
 	ncbi_connutil.c ncbi_file_connector.c ncbi_heapmgr.c \
 	ncbi_http_connector.c ncbi_memory_connector.c $(NCBI_LBSM_SRC) \
-	ncbi_host_info.c ncbi_server_info.c ncbi_service.c \
+	ncbi_host_info.c ncbi_server_info.c ncbi_service.c ncbi_version.c \
 	ncbi_service_connector.c ncbi_ftp_connector.c ncbi_dispd.c \
 	ncbi_lb.c ncbi_local.c ncbi_socket_connector.c urlquery.c binary.c \
-	ncbi_sendmail.c asn_connection.c raw_scoremat.c \
+	ncbi_sendmail.c ncbi_base64.c asn_connection.c raw_scoremat.c \
 	drwnflpt.c drwnfspc.c drwnmfls.c
 SRC1 =	ncbimain.c $(SRC1e)
 
@@ -323,10 +323,10 @@ OBJ1e =	ncbibs.o wwwutils.o ncbierr.o ncbienv.o ncbifile.o \
 	ncbi_priv.o ncbi_ansi_ext.o ncbi_connection.o ncbi_connector.o \
 	ncbi_connutil.o ncbi_file_connector.o ncbi_heapmgr.o \
 	ncbi_http_connector.o ncbi_memory_connector.o $(NCBI_LBSM_OBJ) \
-	ncbi_host_info.o ncbi_server_info.o ncbi_service.o \
+	ncbi_host_info.o ncbi_server_info.o ncbi_service.o ncbi_version.o \
 	ncbi_service_connector.o ncbi_ftp_connector.o ncbi_dispd.o \
 	ncbi_lb.o ncbi_local.o ncbi_socket_connector.o urlquery.o binary.o \
-	ncbi_sendmail.o asn_connection.o raw_scoremat.o \
+	ncbi_sendmail.o ncbi_base64.o asn_connection.o raw_scoremat.o \
 	drwnflpt.o drwnfspc.o drwnmfls.o
 OBJ1 =	ncbimain.o $(OBJ1e)
 
@@ -713,7 +713,8 @@ copy :
 	$(SRCCOPY) ../connect/ncbi_lbsmd.h .
 	$(SRCCOPY) ../connect/ncbi_local.h .
 	$(SRCCOPY) ../connect/ncbi_lb.h .
-	$(SRCCOPY) ../connect/version.h .
+	$(SRCCOPY) ../connect/ncbi_version.h .
+	$(SRCCOPY) ../connect/ncbi_base64.h .
 	$(SRCCOPY) ../connect/urlquery.h ../include
 	-mkdir ../include/connect
 	-chmod ug+rw,o+r ../include/connect
diff --git a/make/makedis.csh b/make/makedis.csh
index 2037aae..347daf2 100755
--- a/make/makedis.csh
+++ b/make/makedis.csh
@@ -1,6 +1,6 @@
 #!/bin/csh -f
 #
-# $Id: makedis.csh 155379 2009-03-23 17:10:14Z coulouri $
+# $Id: makedis.csh 179886 2010-01-04 17:28:02Z ucko $
 #
 ##                            PUBLIC DOMAIN NOTICE                          
 #               National Center for Biotechnology Information
@@ -54,7 +54,7 @@ if ( "X$tar_file" != "X" && "$tar_file" != "-") then
 	endif
 
 	ls -l $tar_file
-	tar xvf $tar_file
+	tar xf $tar_file
 else
 	# make sure that ncbi/build directory exists
 	if ( ! -d "ncbi/build" ) then
@@ -450,7 +450,7 @@ EoF
 endif
 
 set CMD='make $MFLG -f makedemo.unx CFLAGS1=\"$NCBI_OPTFLAG $NCBI_CFLAGS1\" \
-   LDFLAGS1=\"$NCBI_LDFLAGS1\" SHELL=\"$NCBI_MAKE_SHELL\" \
+   LDFLAGS1=\"$NCBI_LDFLAGS1\" SHELL=\"$NCBI_MAKE_SHELL\" OTHERLIBS=\"$NCBI_OTHERLIBS\" \
    LCL=\"$NCBI_DEFAULT_LCL\" RAN=\"$NCBI_RANLIB\" AR=\"$NCBI_AR\" CC=\"$NCBI_CC\" $DEMO_VIB'
 eval echo $CMD
 eval echo $CMD | sh 
@@ -469,7 +469,7 @@ rm -f $mtapps
 
 
 set CMD='make $MFLG -f makedemo.unx CFLAGS1=\"$NCBI_OPTFLAG $NCBI_CFLAGS1\" \
-   LDFLAGS1=\"$NCBI_LDFLAGS1\" SHELL=\"$NCBI_MAKE_SHELL\" \
+   LDFLAGS1=\"$NCBI_LDFLAGS1\" SHELL=\"$NCBI_MAKE_SHELL\" OTHERLIBS=\"$NCBI_OTHERLIBS\" \
    LCL=\"$NCBI_DEFAULT_LCL\" RAN=\"$NCBI_RANLIB\" AR=\"$NCBI_AR\" CC=\"$NCBI_CC\"  \
    THREAD_OBJ=$NCBI_THREAD_OBJ THREAD_OTHERLIBS=\"$NCBI_MT_OTHERLIBS\" \
    $DEMO_VIB $mtapps'
diff --git a/make/makenet.unx b/make/makenet.unx
index b4ed36a..851eca8 100644
--- a/make/makenet.unx
+++ b/make/makenet.unx
@@ -1,6 +1,6 @@
 #   -*- makefile -*- for network demo programs and network entrez
 #
-#	$Id: makenet.unx,v 6.233 2009/08/05 20:06:36 ucko Exp $
+#	$Id: makenet.unx,v 6.239 2010/08/05 16:13:14 kans Exp $
 #   test, ignore
 #
 #   Sun with unbundled ANSI compiler [ make CC=acc RAN=ranlib ]
@@ -341,6 +341,8 @@ EXEPSEQUIN =	Psequin
 
 EXESBTEDIT =    sbtedit
 
+EXESTREAMER = streamer
+
 SRCDDV = ddvmain.c
 
 SRCUDV = udvmain.c
@@ -360,6 +362,8 @@ SRCSEQUIN = sequin1.c sequin2.c sequin3.c sequin4.c sequin5.c sequin6.c \
 
 SRCSBTEDIT = sbtedit.c
 
+SRCSTREAMER = streamer.c
+
 CLI_SRC = $(SRCDDV) $(SRCUDV)
 
 CLIENTS = suggcli
@@ -367,7 +371,7 @@ CLIENTS =
 
 SERV_SRC = $(SRCENTSRV)
 
-SERVERS = $(EXESUGGSRV) $(EXEQUERY) $(EXESEQUIN) $(EXEPSEQUIN) $(EXESBTEDIT) $(EXENQUERY)
+SERVERS = $(EXESUGGSRV) $(EXEQUERY) $(EXESEQUIN) $(EXEPSEQUIN) $(EXESBTEDIT) $(EXESTREAMER) $(EXENQUERY)
 
 ALL_SRC = $(NET_LIBS_SRC) $(CLI_SRC) $(SERV_SRC)
 
@@ -391,7 +395,7 @@ utilities : $(EXEUTIL)
 
 vibutilities : $(EXEUTILVIB)
 
-.NO_PARALLEL: copy nocopy Tentrez sequin Psequin sbtedit Ssequin elecpcr asn2fast asn2asn cleanasn cspeedtest sugint Nbatch Nbatch3 Nentrcmd seqget idfetch test_nc bi_socket test_ncbi_dsock debug_server rtestval rasn2ff asn2gb asn2gb_psf asn2fsa asn2fsa_psf tbl2asn tbl2asn_psf raw2delt aceread_tst asn2all gene2xml asnval asnval_psf asndisc asndisc_psf demo_aceread_tst asnmacro asnstrip flint gbseqget insdseqget trna2sap trna2tbl testent2 entrez2 spidey dotmatrix ingenue condense bl2seq src_chk src_chk_psf
+.NO_PARALLEL: copy nocopy Tentrez sequin Psequin sbtedit streamer Ssequin elecpcr asn2fast asn2asn cleanasn cleanasn_psf cspeedtest sugint Nbatch Nbatch3 Nentrcmd seqget idfetch test_nc bi_socket test_ncbi_dsock debug_server rtestval rasn2ff asn2gb asn2gb_psf asn2fsa asn2fsa_psf tbl2asn tbl2asn_psf raw2delt aceread_tst asn2all gene2xml asnval asnval_psf asndisc asndisc_psf asnbarval demo_aceread_tst asnmacro asnstrip flint gbseqget insdseqget trna2sap trna2tbl testent2 entrez2 spidey dotmatrix ingenue condense bl2seq src_chk src_chk_psf tbl_chk tbl_chk_psf
 
 .WAIT:
 	echo Waiting...go
@@ -537,6 +541,7 @@ copy :
 	$(SRCCOPY) ../demo/gene2xml.c .
 	$(SRCCOPY) ../demo/asnval.c .
 	$(SRCCOPY) ../demo/asndisc.c .
+	$(SRCCOPY) ../demo/asnbarval.c .
 	$(SRCCOPY) ../demo/aceread_tst.c .
 	$(SRCCOPY) ../demo/asnmacro.c .
 	$(SRCCOPY) ../demo/asnstrip.c .
@@ -558,6 +563,7 @@ copy :
 	$(SRCCOPY) ../demo/blastall.c .
 	$(SRCCOPY) ../demo/blast_driver.c .
 	$(SRCCOPY) ../demo/src_chk.c .
+	$(SRCCOPY) ../demo/tbl_chk.c .
 	$(SRCCOPY) $(SRCUTILCOPY) .
 	-$(SRCCOPY) ../network/entrez/server/*.* .
 	-$(SRCCOPY) ../network/suggest/server/*.* .
@@ -1048,8 +1054,7 @@ asnval_dbx_psf :	asnval.c
 # asndisc program (asndisc)
 asndisc :	asndisc.c
 	$(CC) -g -o asndisc $(LDFLAGS) asndisc.c $(THREAD_OBJ) $(LIB41) \
-		$(NETCLILIB) $(LIB23) $(LIBCOMPADJ) $(LIB2) $(LIB1) \
-		$(OTHERLIBS) $(THREAD_OTHERLIBS)
+		$(LIB23) $(LIB2) $(LIB1) $(THREAD_OTHERLIBS)
 
 # asndisc_psf, uses PUBSEQBioseqFetchEnable instead of PubSeqFetchEnable
 # should be used only internally within NCBI.
@@ -1058,6 +1063,12 @@ asndisc_psf :	asndisc.c
 	$(LIB23) $(LIBCOMPADJ) $(LIB2) $(LIB1) $(NCBI_SYBLIBS_CT_r) \
 	$(OTHERLIBS) $(THREAD_OTHERLIBS)
 
+# asnbarval program (asnbarval)
+asnbarval :	asnbarval.c
+	$(CC) -g -o asnbarval $(LDFLAGS) asnbarval.c $(THREAD_OBJ) $(LIB41) \
+		$(NETCLILIB) $(LIB23) $(LIBCOMPADJ) $(LIB2) $(LIB1) \
+		$(OTHERLIBS) $(THREAD_OTHERLIBS)
+
 # demo_aceread_tst program (demo_aceread_tst)
 demo_aceread_tst :	aceread_tst.c
 	$(CC) -g -o demo_aceread_tst $(LDFLAGS) aceread_tst.c $(THREAD_OBJ) $(LIB41) \
@@ -1102,8 +1113,7 @@ trna2tbl :	trna2tbl.c
 # Entrez2 service test program (testent2)
 testent2 :	testent2.c
 	$(CC) -g -o testent2 $(LDFLAGS) testent2.c $(LIB23) $(LIBCOMPADJ) \
-		$(LIB22) $(LIB20) $(LIB61) $(LIB60) $(LIB2) $(LIB1) \
-		$(OTHERLIBS)
+		$(LIB22) $(LIB61) $(LIB60) $(LIB2) $(LIB1) $(OTHERLIBS)
 
 # network Entrez2 application (entrez2)
 entrez2 :	entrez2.c
@@ -1149,6 +1159,13 @@ asn2asn : asn2asn.c
 cleanasn : cleanasn.c
 	$(CC) -o cleanasn $(LDFLAGS) cleanasn.c $(LIB23) $(LIB2) $(LIB1)
 
+# cleanasn_psf, uses PUBSEQBioseqFetchEnable instead of PubSeqFetchEnable
+# should be used only internally within NCBI.
+cleanasn_psf : cleanasn.c
+	$(CC) -DINTERNAL_NCBI_CLEANASN -g -o cleanasn_psf $(LDFLAGS) cleanasn.c \
+		$(LIB_PS) $(LIB41) $(LIB23) $(LIB6) $(LIBCOMPADJ) $(LIB2) $(LIB1) \
+		$(NCBI_SYBLIBS_CT) $(OTHERLIBS)
+
 # demo program (cspeedtest)
 
 cspeedtest : cspeedtest.c
@@ -1387,6 +1404,18 @@ sbtedit : $(SRCSBTEDIT) $(BENTREZLIBS) $(BLIB61) $(BLIB60) $(BLIB23) \
 	$(LIB20) $(LIB23) $(LIB4) $(LIB2) $(LIB1) $(VIBLIBS)
 	$(VIB_POST_LINK) sbtedit
 
+# 'streamer' Sequinesque Stream Editor
+streamer : $(SRCSTREAMER) $(BENTREZLIBS) $(BLIB61) $(BLIB60) $(BLIB23) \
+	$(BLIBCOMPADJ) $(BLIB45) $(BLIB30) $(BLIB20) \
+	$(BLIB22) $(BLIB40) $(BLIB41) $(BLIB36) \
+	$(BLIB11) $(BLIB8) $(BLIB7) $(NETCLIBLIB) $(BLIB5) $(BLIB4) $(BLIB3) \
+	$(BLIB2) $(BLIB1) $(ULIB31)
+	$(CC) -o streamer -I. $(LDFLAGS) -UINTERNAL_NCBI_SEQUIN $(SRCSTREAMER) \
+	$(LIB30) $(LIB45) $(LIB31) $(LIB20) $(LIB61) $(LIB60) $(LIB22) \
+	$(LIB40) $(LIB41) $(LIB36) $(LIB23) $(LIBCOMPADJ) $(LIB11) \
+	$(ENTREZLIBS) $(LIB4) $(LIB2) $(LIB1) $(VIBLIBS) $(OTHERLIBS)
+	$(VIB_POST_LINK) streamer
+
 salogif.o:	salogif.c
 	$(CC) $(CFLAGS) salogif.c
 
@@ -1462,4 +1491,14 @@ src_chk_psf : src_chk.c
 		$(LIB_PS) $(LIB23) $(LIBCOMPADJ) $(LIB2) $(LIB1) \
 		$(NCBI_SYBLIBS_CT) $(OTHERLIBS)
 
+# tbl_chk
+
+tbl_chk : tbl_chk.c 
+	$(CC) -o tbl_chk $(LDFLAGS) tbl_chk.c $(LIB2) $(LIB1) $(OTHERLIBS) 
+
+tbl_chk_psf : tbl_chk.c 
+	$(CC) -DINTERNAL_NCBI_TBL_CHK -g -o tbl_chk_psf $(LDFLAGS) tbl_chk.c \
+		$(LIB_PS) $(LIB23) $(LIBCOMPADJ) $(LIB2) $(LIB1) \
+		$(NCBI_SYBLIBS_CT) $(OTHERLIBS)
+
 ##
diff --git a/network/id2arch/id2.asn b/network/id2arch/id2.asn
index 1ab48ed..1f51ee3 100644
--- a/network/id2arch/id2.asn
+++ b/network/id2arch/id2.asn
@@ -1,4 +1,4 @@
---$Revision: 1.22 $
+--$Revision: 1.23 $
 --********************************************************************
 --
 --  Network Id server network access
@@ -70,7 +70,10 @@ ID2-Request-Get-Seq-id ::= SEQUENCE {
                 text    (2),    -- text Seq-id (accession etc) is preferred
                 general (4),    -- general Seq-id is preferred
                 all     (127),  -- return all qualified Seq-ids of the sequence
-                label   (128)   -- return a sequence string label as general id
+                label   (128),  -- return a sequence string label as string
+                                -- in general id with db "LABEL"
+                taxid   (256)   -- return a sequence taxonomy ID as integer
+                                -- in general id with db "TAXID"
         } DEFAULT any
 }
 
diff --git a/network/id2arch/id2.c b/network/id2arch/id2.c
index 13fd316..a0f8cbb 100644
--- a/network/id2arch/id2.c
+++ b/network/id2arch/id2.c
@@ -2766,7 +2766,7 @@ ID2ReplyAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> end_of_reply = av.boolvalue;
+      ptr -> end_of_reply = TRUE;
       atp = AsnReadId(aip,amp, atp);
    }
    if (atp == ID2_REPLY_reply) {
@@ -2782,6 +2782,8 @@ ID2ReplyAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       ptr -> discard = av.intvalue;
       atp = AsnReadId(aip,amp, atp);
+   } else {
+      ptr -> discard = -1;
    }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
@@ -2961,15 +2963,19 @@ ID2ReplyAsnWrite(ID2ReplyPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       }
    }
    AsnGenericUserSeqOfAsnWrite(ptr -> error, (AsnWriteFunc) ID2ErrorAsnWrite, aip, ID2_REPLY_error, ID2_REPLY_error_E);
+   if (ptr -> end_of_reply) {
    av.boolvalue = ptr -> end_of_reply;
    retval = AsnWrite(aip, ID2_REPLY_end_of_reply,  &av);
+   }
    if (ptr -> Reply_reply != NULL) {
       if ( ! Reply_replyAsnWrite(ptr -> Reply_reply, aip, ID2_REPLY_reply)) {
          goto erret;
       }
    }
+   if (ptr -> discard != -1) {
    av.intvalue = ptr -> discard;
    retval = AsnWrite(aip, ID2_REPLY_discard,  &av);
+   }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -3517,7 +3523,7 @@ ID2ReplyGetSeqIdAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> end_of_reply = av.boolvalue;
+      ptr -> end_of_reply = TRUE;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -3577,8 +3583,10 @@ ID2ReplyGetSeqIdAsnWrite(ID2ReplyGetSeqIdPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       }
    }
    AsnGenericChoiceSeqOfAsnWrite(ptr -> seq_id, (AsnWriteFunc) SeqIdAsnWrite, aip, ID2_REPLY_GET_SEQ_ID_seq_id, ID2_REPLY_GET_SEQ_ID_seq_id_E);
+   if (ptr -> end_of_reply) {
    av.boolvalue = ptr -> end_of_reply;
    retval = AsnWrite(aip, REPLY_GET_SEQ_ID_end_of_reply,  &av);
+   }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -3707,7 +3715,7 @@ ID2ReplyGetBlobIdAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> end_of_reply = av.boolvalue;
+      ptr -> end_of_reply = TRUE;
       atp = AsnReadId(aip,amp, atp);
    }
    if (atp == REPLY_GET_BLOB_ID_blob_state) {
@@ -3781,8 +3789,10 @@ ID2ReplyGetBlobIdAsnWrite(ID2ReplyGetBlobIdPtr ptr, AsnIoPtr aip, AsnTypePtr ori
    av.intvalue = ptr -> split_version;
    retval = AsnWrite(aip, GET_BLOB_ID_split_version,  &av);
    AsnGenericUserSeqOfAsnWrite(ptr -> annot_info, (AsnWriteFunc) ID2SSeqAnnotInfoAsnWrite, aip, REPLY_GET_BLOB_ID_annot_info, REPLY_GET_BLOB_ID_annot_info_E);
+   if (ptr -> end_of_reply) {
    av.boolvalue = ptr -> end_of_reply;
    retval = AsnWrite(aip, REPLY_GET_BLOB_ID_end_of_reply,  &av);
+   }
    av.intvalue = ptr -> blob_state;
    retval = AsnWrite(aip, REPLY_GET_BLOB_ID_blob_state,  &av);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
diff --git a/network/id2arch/id2.patch b/network/id2arch/id2.patch
new file mode 100644
index 0000000..069fb0e
--- /dev/null
+++ b/network/id2arch/id2.patch
@@ -0,0 +1,143 @@
+*** id2.c	Thu Jan  7 15:08:05 2010
+--- id2.c.new	Thu Jan  7 13:58:12 2010
+*************** ID2ReplyAsnRead(AsnIoPtr aip, AsnTypePtr
+*** 2766,2772 ****
+        if ( AsnReadVal(aip, atp, &av) <= 0) {
+           goto erret;
+        }
+!       ptr -> end_of_reply = av.boolvalue;
+        atp = AsnReadId(aip,amp, atp);
+     }
+     if (atp == ID2_REPLY_reply) {
+--- 2766,2772 ----
+        if ( AsnReadVal(aip, atp, &av) <= 0) {
+           goto erret;
+        }
+!       ptr -> end_of_reply = TRUE;
+        atp = AsnReadId(aip,amp, atp);
+     }
+     if (atp == ID2_REPLY_reply) {
+*************** ID2ReplyAsnRead(AsnIoPtr aip, AsnTypePtr
+*** 2782,2787 ****
+--- 2782,2789 ----
+        }
+        ptr -> discard = av.intvalue;
+        atp = AsnReadId(aip,amp, atp);
++    } else {
++       ptr -> discard = -1;
+     }
+  
+     if (AsnReadVal(aip, atp, &av) <= 0) {
+*************** ID2ReplyAsnWrite(ID2ReplyPtr ptr, AsnIoP
+*** 2961,2975 ****
+        }
+     }
+     AsnGenericUserSeqOfAsnWrite(ptr -> error, (AsnWriteFunc) ID2ErrorAsnWrite, aip, ID2_REPLY_error, ID2_REPLY_error_E);
+!    av.boolvalue = ptr -> end_of_reply;
+!    retval = AsnWrite(aip, ID2_REPLY_end_of_reply,  &av);
+     if (ptr -> Reply_reply != NULL) {
+        if ( ! Reply_replyAsnWrite(ptr -> Reply_reply, aip, ID2_REPLY_reply)) {
+           goto erret;
+        }
+     }
+!    av.intvalue = ptr -> discard;
+!    retval = AsnWrite(aip, ID2_REPLY_discard,  &av);
+     if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+        goto erret;
+     }
+--- 2963,2981 ----
+        }
+     }
+     AsnGenericUserSeqOfAsnWrite(ptr -> error, (AsnWriteFunc) ID2ErrorAsnWrite, aip, ID2_REPLY_error, ID2_REPLY_error_E);
+!    if (ptr -> end_of_reply) {
+!       av.boolvalue = ptr -> end_of_reply;
+!       retval = AsnWrite(aip, ID2_REPLY_end_of_reply,  &av);
+!    }
+     if (ptr -> Reply_reply != NULL) {
+        if ( ! Reply_replyAsnWrite(ptr -> Reply_reply, aip, ID2_REPLY_reply)) {
+           goto erret;
+        }
+     }
+!    if (ptr -> discard != -1) {
+!       av.intvalue = ptr -> discard;
+!       retval = AsnWrite(aip, ID2_REPLY_discard,  &av);
+!    }
+     if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+        goto erret;
+     }
+*************** ID2ReplyGetSeqIdAsnRead(AsnIoPtr aip, As
+*** 3517,3523 ****
+        if ( AsnReadVal(aip, atp, &av) <= 0) {
+           goto erret;
+        }
+!       ptr -> end_of_reply = av.boolvalue;
+        atp = AsnReadId(aip,amp, atp);
+     }
+  
+--- 3523,3529 ----
+        if ( AsnReadVal(aip, atp, &av) <= 0) {
+           goto erret;
+        }
+!       ptr -> end_of_reply = TRUE;
+        atp = AsnReadId(aip,amp, atp);
+     }
+  
+*************** ID2ReplyGetSeqIdAsnWrite(ID2ReplyGetSeqI
+*** 3577,3584 ****
+        }
+     }
+     AsnGenericChoiceSeqOfAsnWrite(ptr -> seq_id, (AsnWriteFunc) SeqIdAsnWrite, aip, ID2_REPLY_GET_SEQ_ID_seq_id, ID2_REPLY_GET_SEQ_ID_seq_id_E);
+!    av.boolvalue = ptr -> end_of_reply;
+!    retval = AsnWrite(aip, REPLY_GET_SEQ_ID_end_of_reply,  &av);
+     if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+        goto erret;
+     }
+--- 3583,3592 ----
+        }
+     }
+     AsnGenericChoiceSeqOfAsnWrite(ptr -> seq_id, (AsnWriteFunc) SeqIdAsnWrite, aip, ID2_REPLY_GET_SEQ_ID_seq_id, ID2_REPLY_GET_SEQ_ID_seq_id_E);
+!    if (ptr -> end_of_reply) {
+!       av.boolvalue = ptr -> end_of_reply;
+!       retval = AsnWrite(aip, REPLY_GET_SEQ_ID_end_of_reply,  &av);
+!    }
+     if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+        goto erret;
+     }
+*************** ID2ReplyGetBlobIdAsnRead(AsnIoPtr aip, A
+*** 3707,3713 ****
+        if ( AsnReadVal(aip, atp, &av) <= 0) {
+           goto erret;
+        }
+!       ptr -> end_of_reply = av.boolvalue;
+        atp = AsnReadId(aip,amp, atp);
+     }
+     if (atp == REPLY_GET_BLOB_ID_blob_state) {
+--- 3715,3721 ----
+        if ( AsnReadVal(aip, atp, &av) <= 0) {
+           goto erret;
+        }
+!       ptr -> end_of_reply = TRUE;
+        atp = AsnReadId(aip,amp, atp);
+     }
+     if (atp == REPLY_GET_BLOB_ID_blob_state) {
+*************** ID2ReplyGetBlobIdAsnWrite(ID2ReplyGetBlo
+*** 3781,3788 ****
+     av.intvalue = ptr -> split_version;
+     retval = AsnWrite(aip, GET_BLOB_ID_split_version,  &av);
+     AsnGenericUserSeqOfAsnWrite(ptr -> annot_info, (AsnWriteFunc) ID2SSeqAnnotInfoAsnWrite, aip, REPLY_GET_BLOB_ID_annot_info, REPLY_GET_BLOB_ID_annot_info_E);
+!    av.boolvalue = ptr -> end_of_reply;
+!    retval = AsnWrite(aip, REPLY_GET_BLOB_ID_end_of_reply,  &av);
+     av.intvalue = ptr -> blob_state;
+     retval = AsnWrite(aip, REPLY_GET_BLOB_ID_blob_state,  &av);
+     if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+--- 3789,3798 ----
+     av.intvalue = ptr -> split_version;
+     retval = AsnWrite(aip, GET_BLOB_ID_split_version,  &av);
+     AsnGenericUserSeqOfAsnWrite(ptr -> annot_info, (AsnWriteFunc) ID2SSeqAnnotInfoAsnWrite, aip, REPLY_GET_BLOB_ID_annot_info, REPLY_GET_BLOB_ID_annot_info_E);
+!    if (ptr -> end_of_reply) {
+!       av.boolvalue = ptr -> end_of_reply;
+!       retval = AsnWrite(aip, REPLY_GET_BLOB_ID_end_of_reply,  &av);
+!    }
+     av.intvalue = ptr -> blob_state;
+     retval = AsnWrite(aip, REPLY_GET_BLOB_ID_blob_state,  &av);
+     if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
diff --git a/network/id2arch/makefile b/network/id2arch/makefile
index 8e095f7..26df232 100644
--- a/network/id2arch/makefile
+++ b/network/id2arch/makefile
@@ -32,6 +32,7 @@ id2.c id2gen.h: id2.l id2.h all.l seqsplit.l
 	$(CODEGEN) -i id2map.h -l id2.l,seqsplit.l,all.l -o id2gen -d .
 	cat id2gen.c | grep -v "^ *\* *Generated" > id2.c && rm -f id2gen.c
 	cat id2gen.h | grep -v "^ *\* *Generated" > x     && mv x id2gen.h
+	@patch id2.c <id2.patch
 
 id2.l : id2.asn
 	$(ASNTOOL) -m id2.asn -l x.h
@@ -52,6 +53,7 @@ all.l :
 id2.h : id2.asn
 	$(ASNTOOL) -m id2.asn -o id2.h
 	cat id2.h | grep -v "^ *\* *Generated" >x && mv x id2.h
+
 seqsplit.h : seqsplit.asn
 	$(ASNTOOL) -m seqsplit.asn -o seqsplit.h
 
diff --git a/network/id2arch/seqsplit.asn b/network/id2arch/seqsplit.asn
index e64745f..d1b2432 100644
--- a/network/id2arch/seqsplit.asn
+++ b/network/id2arch/seqsplit.asn
@@ -1,4 +1,4 @@
---$Revision: 1.9 $
+--$Revision: 1.10 $
 --********************************************************************
 --
 --  Network Id server network access
@@ -114,7 +114,8 @@ ID2S-Seq-annot-place-Info ::= SEQUENCE {
 ID2S-Seq-feat-Ids-Info ::= SEQUENCE {
         feat-types      SET OF ID2S-Feat-type-Info OPTIONAL,
         xref-types      SET OF ID2S-Feat-type-Info OPTIONAL,
-        local-ids       SET OF INTEGER OPTIONAL
+        local-ids       SET OF INTEGER OPTIONAL,
+        local-str-ids   SET OF VisibleString OPTIONAL
 }
 
 
diff --git a/object/objalign.c b/object/objalign.c
index f2a61d4..9615354 100644
--- a/object/objalign.c
+++ b/object/objalign.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 4/1/91
 *
-* $Revision: 6.16 $
+* $Revision: 6.17 $
 *
 * File Description:  Object manager for module NCBI-Seqalign
 *
@@ -333,6 +333,7 @@ NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignFree (SeqAlignPtr sap)
 	DenseDiagPtr ddp, ddpnext;
 	StdSegPtr ssp, sspnext;
 	ValNodePtr anp, next;
+    UserObjectPtr uopa, uopb;
 	
     if (sap == NULL)
         return (SeqAlignPtr)NULL;
@@ -384,7 +385,16 @@ NLM_EXTERN SeqAlignPtr LIBCALL SeqAlignFree (SeqAlignPtr sap)
     /*
     AsnGenericChoiceSeqOfFree(sap -> id, (AsnOptFreeFunc) ObjectIdFree);
     */
+    uopa = (UserObjectPtr) sap->ext;
+    while (uopa != NULL) {
+      uopb = uopa->next;
+      uopa->next = NULL;
+      UserObjectFree (uopa);
+      uopa = uopb;
+    }
+    /*
     AsnGenericUserSeqOfFree(sap -> ext, (AsnOptFreeFunc) UserObjectFree);
+    */
 	SeqLocSetFree(sap->bounds);
     SeqIdFree(sap->master);
 
@@ -408,6 +418,7 @@ NLM_EXTERN Boolean LIBCALL SeqAlignAsnWrite (SeqAlignPtr sap, AsnIoPtr aip, AsnT
     StdSegPtr ssp;
     Boolean retval = FALSE;
     ValNodePtr anp;
+    UserObjectPtr uop;
 
 	if (! loaded)
 	{
@@ -540,8 +551,19 @@ NLM_EXTERN Boolean LIBCALL SeqAlignAsnWrite (SeqAlignPtr sap, AsnIoPtr aip, AsnT
 	   {
 	   	ErrPostEx(SEV_ERROR,0,0,"ASN3: SeqAlign.ext stripped");
 	   }
-	   else
+	   else {
+		uop = (UserObjectPtr) sap->ext;
+        if (! AsnOpenStruct(aip, SEQ_ALIGN_ext, sap->ext)) goto erret;
+        while (uop != NULL)
+            {
+                if (! UserObjectAsnWrite(uop, aip, SEQ_ALIGN_ext_E)) goto erret;
+                uop = uop->next;
+            }
+            if (! AsnCloseStruct(aip, SEQ_ALIGN_ext, sap->ext)) goto erret;
+       }
+	    /*
 	    AsnGenericUserSeqOfAsnWrite(sap -> ext, (AsnWriteFunc) UserObjectAsnWrite, aip, SEQ_ALIGN_ext, SEQ_ALIGN_ext_E);
+        */
 	}
 
 	if (! AsnCloseStruct(aip, atp, (Pointer)sap))
diff --git a/object/objbibli.c b/object/objbibli.c
index 89449d9..e78075f 100644
--- a/object/objbibli.c
+++ b/object/objbibli.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 1/1/91
 *
-* $Revision: 6.7 $
+* $Revision: 6.8 $
 *
 * File Description:  Object manager for module NCBI-Biblio
 *
@@ -41,6 +41,9 @@
 * 07-19-93 Ostell      Support for ASN30 added
 *
 * $Log: objbibli.c,v $
+* Revision 6.8  2009/10/02 19:44:48  kans
+* address clang static analyzer warnings
+*
 * Revision 6.7  2006/02/22 17:31:45  kans
 * fix to AuthListMatch (CB)
 *
@@ -3635,7 +3638,7 @@ NLM_EXTERN PatPriorityPtr LIBCALL PatPrioritySetFree (PatPriorityPtr ppp)
 *****************************************************************************/
 NLM_EXTERN PatPriorityPtr LIBCALL PatPrioritySetAsnRead (AsnIoPtr aip, AsnTypePtr set, AsnTypePtr element)
 {
-	PatPriorityPtr ppp=NULL, head, last;
+	PatPriorityPtr ppp=NULL, head = NULL, last;
 	DataVal av;
 	AsnTypePtr atp;
 
diff --git a/object/objfdef.c b/object/objfdef.c
index de0067c..800fdd2 100644
--- a/object/objfdef.c
+++ b/object/objfdef.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 9/94
 *
-* $Revision: 6.39 $
+* $Revision: 6.41 $
 *
 * File Description:  Object manager for feature definitions
 *
@@ -700,7 +700,8 @@ static CharPtr featDefSetMemStr = "FeatDefGroupSet ::= {\n" \
 "{ typelabel \"oriT\" , menulabel \"Origin of Transcription\" , featdef-key 93 , seqfeat-key 8 , entrygroup 5 , displaygroup 5 , molgroup na } ,\n" \
 "{ typelabel \"ncRNA\" , menulabel \"Non-coding RNA\" , featdef-key 94 , seqfeat-key 5 , entrygroup 3 , displaygroup 3 , molgroup na } ,\n" \
 "{ typelabel \"tmRNA\" , menulabel \"Transfer-messenger RNA\" , featdef-key 95 , seqfeat-key 5 , entrygroup 3 , displaygroup 3 , molgroup na } ,\n" \
-"{ typelabel \"CloneRef\" , menulabel \"Clone Reference\" , featdef-key 96 , seqfeat-key 21 , entrygroup 0 , displaygroup 0 , molgroup na  } } };\n";
+"{ typelabel \"CloneRef\" , menulabel \"Clone Reference\" , featdef-key 96 , seqfeat-key 21 , entrygroup 0 , displaygroup 0 , molgroup na } ,\n" \
+"{ typelabel \"VariationRef\" , menulabel \"Variation Reference\" , featdef-key 97 , seqfeat-key 22 , entrygroup 0 , displaygroup 0 , molgroup na  } } };\n";
 #endif
 
 /*****************************************************************************
@@ -985,6 +986,8 @@ NLM_EXTERN Uint1 LIBCALL FindFeatDefType(SeqFeatPtr sfp)
             return FEATDEF_BIOSRC;
         case SEQFEAT_CLONEREF:
             return FEATDEF_CLONEREF;
+        case SEQFEAT_VARIATIONREF:
+            return FEATDEF_VARIATIONREF;
     }
 
     return FEATDEF_BAD;
@@ -1338,6 +1341,8 @@ protref:    if (prp->name != NULL)
             label = (sfp->data.value.ptrvalue);
             if (StringICmp (label, "Domain") == 0 && sfp->comment != NULL) {
               label = sfp->comment;
+            } else if (StringICmp (label, "Variant") == 0 && sfp->comment != NULL) {
+              label = sfp->comment;
             }
             break;
         case SEQFEAT_COMMENT:
@@ -1397,6 +1402,8 @@ protref:    if (prp->name != NULL)
             goto orgref;
         case SEQFEAT_CLONEREF:
             break;
+        case SEQFEAT_VARIATIONREF:
+            break;
         default:
             break;
     }
@@ -1489,6 +1496,11 @@ NLM_EXTERN Int2 LIBCALL FeatDefLabel (SeqFeatPtr sfp, CharPtr buf, Int2 buflen,
                    sfp->comment != NULL) {
             StringCpy (tbuf, "Domain");
             typelabel = tbuf;
+        } else if (sfp->data.choice == SEQFEAT_REGION &&
+                   StringICmp ((CharPtr) sfp->data.value.ptrvalue, "Variant") == 0 &&
+                   sfp->comment != NULL) {
+            StringCpy (tbuf, "Variant");
+            typelabel = tbuf;
         }
     }
     else
diff --git a/object/objfdef.h b/object/objfdef.h
index 38aca1f..7e114bc 100644
--- a/object/objfdef.h
+++ b/object/objfdef.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 9/94
 *
-* $Revision: 6.7 $
+* $Revision: 6.8 $
 *
 * File Description:  Object manager for feature definitions
 *
@@ -314,8 +314,9 @@ NLM_EXTERN FeatDefPtr LIBCALL FeatDefFindNext PROTO((FeatDefPtr curr, Uint1Ptr k
 #define FEATDEF_ncRNA 94
 #define FEATDEF_tmRNA 95
 #define FEATDEF_CLONEREF 96
+#define FEATDEF_VARIATIONREF 97
 
-#define FEATDEF_MAX 97 /* size of array needed for featdef filter parameters */
+#define FEATDEF_MAX 98 /* size of array needed for featdef filter parameters */
 
 
 #ifdef __cplusplus
diff --git a/object/objfeat.c b/object/objfeat.c
index 2f91c27..0185f4e 100644
--- a/object/objfeat.c
+++ b/object/objfeat.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 4/1/91
 *
-* $Revision: 6.44 $
+* $Revision: 6.55 $
 *
 * File Description:  Object manager for module NCBI-SeqFeat
 *
@@ -54,6 +54,7 @@ static char *this_file = __FILE__;
 #include <asnfeat.h>        /* the AsnTool header */
 #include <objmgr.h>
 #include <objfdef.h>
+#include <objseq.h>
 
 static Boolean loaded = FALSE;
 
@@ -795,6 +796,9 @@ NLM_EXTERN void LIBCALL SeqFeatDataFree(ChoicePtr cp)
         case SEQFEAT_CLONEREF:
             CloneRefFree((CloneRefPtr)pnt);
             break;
+        case SEQFEAT_VARIATIONREF:
+            VariationRefFree((VariationRefPtr)pnt);
+            break;
     }
     return;
 }
@@ -917,6 +921,10 @@ NLM_EXTERN Boolean LIBCALL SeqFeatDataAsnWrite (ChoicePtr cp, AsnIoPtr aip, AsnT
             if (! CloneRefAsnWrite((CloneRefPtr)pnt, aip, SEQFEATDATA_clone))
                 goto erret;
             break;
+        case SEQFEAT_VARIATIONREF:
+            if (! VariationRefAsnWrite((VariationRefPtr)pnt, aip, SEQFEATDATA_variation))
+                goto erret;
+            break;
     }
 
     retval = TRUE;
@@ -1097,6 +1105,13 @@ NLM_EXTERN Boolean LIBCALL SeqFeatDataAsnRead (AsnIoPtr aip, AsnTypePtr orig, Ch
         if (cp->value.ptrvalue == NULL)
             goto erret;
     }
+    else if (atp == SEQFEATDATA_variation)
+    {
+        cp->choice = SEQFEAT_VARIATIONREF ;
+        cp->value.ptrvalue = (Pointer)VariationRefAsnRead(aip, atp);
+        if (cp->value.ptrvalue == NULL)
+            goto erret;
+    }
 
     retval = TRUE;
 erret:
@@ -2525,7 +2540,7 @@ NLM_EXTERN RnaRefPtr LIBCALL RnaRefFree (RnaRefPtr rrp)
 NLM_EXTERN Boolean LIBCALL RnaRefAsnWrite (RnaRefPtr rrp, AsnIoPtr aip, AsnTypePtr orig)
 {
     DataVal av;
-    AsnTypePtr atp, tmp;
+    AsnTypePtr atp, tmp = NULL;
     tRNAPtr trna;
     RNAGenPtr rgp;
     Int2 i;
@@ -4227,6 +4242,19 @@ NLM_EXTERN Boolean LIBCALL OrgNameAsnWrite (OrgNamePtr onp, AsnIoPtr aip, AsnTyp
          }      
     }
 
+    if (onp->pgcode)
+    {
+          if (aip->spec_version == 3)    /* ASN3 strip new value */
+          {
+              ErrPostEx(SEV_ERROR,0,0,"ASN3:  OrgName.pgcode stripped");
+          }
+          else
+          {
+        av.intvalue = (Int4)(onp->pgcode);
+        if (! AsnWrite(aip, ORGNAME_pgcode, &av)) goto erret;
+         }      
+    }
+
 
     if (! AsnCloseStruct(aip, atp, (Pointer)onp))
         goto erret;
@@ -4354,6 +4382,15 @@ NLM_EXTERN OrgNamePtr LIBCALL OrgNameAsnRead (AsnIoPtr aip, AsnTypePtr orig)
               else
                 onp->div = (CharPtr)(av.ptrvalue);
            }
+            else if (atp == ORGNAME_pgcode)
+            {
+               if (aip->spec_version == 3)    /* ASN3 strip new value */
+              {
+                  ErrPostEx(SEV_ERROR,0,0,"ASN3:  OrgName.pgcode stripped");
+              }
+              else
+                onp->pgcode = (Uint1)av.intvalue;
+           }
         }
     }
     if (AsnReadVal(aip, atp, &av) <= 0) goto erret;   /* end struct */
@@ -7791,3 +7828,3030 @@ erret:
    return retval;
 }
 
+
+/**************************************************
+*
+*    VariationRefNew()
+*
+**************************************************/
+NLM_EXTERN 
+VariationRefPtr LIBCALL
+VariationRefNew(void)
+{
+   VariationRefPtr ptr = MemNew((size_t) sizeof(VariationRef));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    Consequence_loss_of_heterozygosityNew()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_loss_of_heterozygosityPtr LIBCALL
+Consequence_loss_of_heterozygosityNew(void)
+{
+   Consequence_loss_of_heterozygosityPtr ptr = MemNew((size_t) sizeof(Consequence_loss_of_heterozygosity));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    VariationRefFree()
+*
+**************************************************/
+NLM_EXTERN 
+VariationRefPtr LIBCALL
+VariationRefFree(VariationRefPtr ptr)
+{
+   if(ptr == NULL) {
+      return NULL;
+   }
+   DbtagFree(ptr -> id);
+   DbtagFree(ptr -> parent_id);
+   ObjectIdFree(ptr -> sample_id);
+   AsnGenericValNodeSetFree(ptr -> other_ids, (AsnOptFreeFunc) DbtagFree);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> other_ids, (AsnOptFreeFunc) DbtagFree);
+   */
+   MemFree(ptr -> name);
+   /*
+   AsnGenericValNodeSetFree(ptr -> synonyms, (AsnOptFreeFunc) MemFree);
+   */
+   AsnGenericBaseSeqOfFree(ptr -> synonyms ,ASNCODE_PTRVAL_SLOT);
+   MemFree(ptr -> description);
+   AsnGenericValNodeSetFree(ptr -> phenotype, (AsnOptFreeFunc) PhenotypeFree);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> phenotype, (AsnOptFreeFunc) PhenotypeFree);
+   */
+   AsnGenericBaseSeqOfFree(ptr -> method ,ASNCODE_INTVAL_SLOT);
+   AsnGenericValNodeSetFree(ptr -> population_data, (AsnOptFreeFunc) PopulationDataFree);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> population_data, (AsnOptFreeFunc) PopulationDataFree);
+   */
+   VariantPropertiesFree(ptr -> variant_prop);
+   AsnGenericValNodeSetFree(ptr -> clinical_test, (AsnOptFreeFunc) DbtagFree);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> clinical_test, (AsnOptFreeFunc) DbtagFree);
+   */
+   PubFree(ptr -> pub);
+   VarRefDataFree(ptr -> data);
+   ConsequenceFree(ptr -> consequence);
+   SeqLocFree(ptr -> location);
+   AsnGenericValNodeSetFree(ptr -> ext_locs, (AsnOptFreeFunc) ExtLocFree);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> ext_locs, (AsnOptFreeFunc) ExtLocFree);
+   */
+   UserObjectFree(ptr -> ext);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    ConsequenceFree()
+*
+**************************************************/
+NLM_EXTERN 
+ConsequencePtr LIBCALL
+ConsequenceFree(ValNodePtr anp)
+{
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   AsnGenericChoiceSeqOfFree(anp, (AsnOptFreeFunc) Consequence_elementFree);    
+   return NULL;
+}
+
+
+/**************************************************
+*
+*    VariationRefAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+VariationRefPtr LIBCALL
+VariationRefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   VariationRefPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* VariationRef ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIATION_REF);
+   } else {
+      atp = AsnLinkType(orig, VARIATION_REF);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = VariationRefNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == VARIATION_REF_id) {
+      ptr -> id = DbtagAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_parent_id) {
+      ptr -> parent_id = DbtagAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_sample_id) {
+      ptr -> sample_id = ObjectIdAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_other_ids) {
+      ptr -> other_ids = AsnGenericValNodeSetAsnRead (aip, amp, atp, &isError, (AsnReadFunc) DbtagAsnRead, (AsnOptFreeFunc) DbtagFree);
+      /*
+      ptr -> other_ids = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) DbtagAsnRead, (AsnOptFreeFunc) DbtagFree);
+      */
+      if (isError && ptr -> other_ids == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_name) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> name = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_synonyms) {
+      /*
+      ptr -> synonyms = AsnGenericValNodeSetAsnRead(aip, amp, atp, &isError, (AsnReadFunc) NULL, (AsnOptFreeFunc) MemFree);
+      */
+      ptr -> synonyms = AsnGenericBaseSeqOfAsnRead(aip, amp, atp, ASNCODE_PTRVAL_SLOT, &isError);
+      if (isError && ptr -> synonyms == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_description) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> description = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_phenotype) {
+      ptr -> phenotype = AsnGenericValNodeSetAsnRead (aip, amp, atp, &isError, (AsnReadFunc) PhenotypeAsnRead, (AsnOptFreeFunc) PhenotypeFree);
+      /*
+      ptr -> phenotype = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) PhenotypeAsnRead, (AsnOptFreeFunc) PhenotypeFree);
+      */
+      if (isError && ptr -> phenotype == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_method) {
+      ptr -> method = AsnGenericBaseSeqOfAsnRead(aip, amp, atp, ASNCODE_INTVAL_SLOT, &isError);
+      if (isError && ptr -> method == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_population_data) {
+      ptr -> population_data = AsnGenericValNodeSetAsnRead (aip, amp, atp, &isError, (AsnReadFunc) PopulationDataAsnRead, (AsnOptFreeFunc) PopulationDataFree);
+      /*
+      ptr -> population_data = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) PopulationDataAsnRead, (AsnOptFreeFunc) PopulationDataFree);
+      */
+      if (isError && ptr -> population_data == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_variant_prop) {
+      ptr -> variant_prop = VariantPropertiesAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_validated) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> validated = av.boolvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_clinical_test) {
+      ptr -> clinical_test = AsnGenericValNodeSetAsnRead(aip, amp, atp, &isError, (AsnReadFunc) DbtagAsnRead, (AsnOptFreeFunc) DbtagFree);
+      /*
+      ptr -> clinical_test = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) DbtagAsnRead, (AsnOptFreeFunc) DbtagFree);
+      */
+      if (isError && ptr -> clinical_test == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_allele_origin) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> allele_origin = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_allele_state) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> allele_state = av.intvalue;
+      ptr -> OBbits__ |= 1<<2;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_allele_frequency) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> allele_frequency = av.realvalue;
+      ptr -> OBbits__ |= 1<<3;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == REF_is_ancestral_allele) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> is_ancestral_allele = av.boolvalue;
+      ptr -> OBbits__ |= 1<<4;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_pub) {
+      ptr -> pub = PubAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_data) {
+      ptr -> data = VarRefDataAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_consequence) {
+      ptr -> consequence =  ConsequenceAsnRead(aip, atp);
+      if (isError && ptr -> consequence == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_location) {
+      ptr -> location = SeqLocAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_ext_locs) {
+      ptr -> ext_locs = AsnGenericValNodeSetAsnRead (aip, amp, atp, &isError, (AsnReadFunc) ExtLocAsnRead, (AsnOptFreeFunc) ExtLocFree);
+      /*
+      ptr -> ext_locs = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) ExtLocAsnRead, (AsnOptFreeFunc) ExtLocFree);
+      */
+      if (isError && ptr -> ext_locs == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_ext) {
+      ptr -> ext = UserObjectAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = VariationRefFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    ConsequenceAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+ConsequencePtr LIBCALL
+ConsequenceAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+
+
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Boolean isError = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* Consequence_element ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIATION_REF_consequence);
+   } else {
+      atp = AsnLinkType(orig, VARIATION_REF_consequence);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp =
+   AsnGenericChoiceSeqOfAsnRead(aip, amp, atp, &isError,
+   (AsnReadFunc) Consequence_elementAsnRead, (AsnOptFreeFunc) Consequence_elementFree);
+   if (isError) 
+   goto erret;
+
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    VariationRefAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+VariationRefAsnWrite(VariationRefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, VARIATION_REF);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> id != NULL) {
+      if ( ! DbtagAsnWrite(ptr -> id, aip, VARIATION_REF_id)) {
+         goto erret;
+      }
+   }
+   if (ptr -> parent_id != NULL) {
+      if ( ! DbtagAsnWrite(ptr -> parent_id, aip, VARIATION_REF_parent_id)) {
+         goto erret;
+      }
+   }
+   if (ptr -> sample_id != NULL) {
+      if ( ! ObjectIdAsnWrite(ptr -> sample_id, aip, VARIATION_REF_sample_id)) {
+         goto erret;
+      }
+   }
+   if (ptr -> other_ids != NULL) {
+     AsnGenericValNodeSetAsnWrite (ptr -> other_ids, (AsnWriteFunc) DbtagAsnWrite, aip, VARIATION_REF_other_ids, VARIATION_REF_other_ids_E);
+     /*
+     AsnGenericUserSeqOfAsnWrite(ptr -> other_ids, (AsnWriteFunc) DbtagAsnWrite, aip, VARIATION_REF_other_ids, VARIATION_REF_other_ids_E);
+     */
+   }
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, VARIATION_REF_name,  &av);
+   }
+   if (ptr -> synonyms != NULL) {
+     retval = AsnGenericBaseSeqOfAsnWrite(ptr -> synonyms ,ASNCODE_PTRVAL_SLOT, aip, VARIATION_REF_synonyms, VARIATION_REF_synonyms_E);
+   }
+   if (ptr -> description != NULL) {
+      av.ptrvalue = ptr -> description;
+      retval = AsnWrite(aip, VARIATION_REF_description,  &av);
+   }
+   if (ptr -> phenotype != NULL) {
+     AsnGenericValNodeSetAsnWrite (ptr -> phenotype, (AsnWriteFunc) PhenotypeAsnWrite, aip, VARIATION_REF_phenotype, VARIATION_REF_phenotype_E);
+     /*
+     AsnGenericUserSeqOfAsnWrite(ptr -> phenotype, (AsnWriteFunc) PhenotypeAsnWrite, aip, VARIATION_REF_phenotype, VARIATION_REF_phenotype_E);
+     */
+   }
+   if (ptr -> method != NULL) {
+     retval = AsnGenericBaseSeqOfAsnWrite(ptr -> method ,ASNCODE_INTVAL_SLOT, aip, VARIATION_REF_method, VARIATION_REF_method_E);
+   }
+   if (ptr -> population_data != NULL) {
+     AsnGenericValNodeSetAsnWrite (ptr -> population_data, (AsnWriteFunc) PopulationDataAsnWrite, aip, VARIATION_REF_population_data, VARIATION_REF_population_data_E);
+     /*
+     AsnGenericUserSeqOfAsnWrite(ptr -> population_data, (AsnWriteFunc) PopulationDataAsnWrite, aip, VARIATION_REF_population_data, VARIATION_REF_population_data_E);
+     */
+   }
+   if (ptr -> variant_prop != NULL) {
+      if ( ! VariantPropertiesAsnWrite(ptr -> variant_prop, aip, VARIATION_REF_variant_prop)) {
+         goto erret;
+      }
+   }
+   if (ptr -> validated || (ptr -> OBbits__ & (1<<0) )){   av.boolvalue = ptr -> validated;
+      retval = AsnWrite(aip, VARIATION_REF_validated,  &av);
+   }
+   if (ptr -> clinical_test != NULL) {
+     AsnGenericValNodeSetAsnWrite (ptr -> clinical_test, (AsnWriteFunc) DbtagAsnWrite, aip, VARIATION_REF_clinical_test, VARIATION_REF_clinical_test_E);
+     /*
+     AsnGenericUserSeqOfAsnWrite(ptr -> clinical_test, (AsnWriteFunc) DbtagAsnWrite, aip, VARIATION_REF_clinical_test, VARIATION_REF_clinical_test_E);
+     */
+   }
+   if (ptr -> allele_origin || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> allele_origin;
+      retval = AsnWrite(aip, VARIATION_REF_allele_origin,  &av);
+   }
+   if (ptr -> allele_state || (ptr -> OBbits__ & (1<<2) )){   av.intvalue = ptr -> allele_state;
+      retval = AsnWrite(aip, VARIATION_REF_allele_state,  &av);
+   }
+   if (ptr -> allele_frequency || (ptr -> OBbits__ & (1<<3) )){   av.realvalue = ptr -> allele_frequency;
+      retval = AsnWrite(aip, VARIATION_REF_allele_frequency,  &av);
+   }
+   if (ptr -> is_ancestral_allele || (ptr -> OBbits__ & (1<<4) )){   av.boolvalue = ptr -> is_ancestral_allele;
+      retval = AsnWrite(aip, REF_is_ancestral_allele,  &av);
+   }
+   if (ptr -> pub != NULL) {
+      if ( ! PubAsnWrite(ptr -> pub, aip, VARIATION_REF_pub)) {
+         goto erret;
+      }
+   }
+   if (ptr -> data != NULL) {
+      if ( ! VarRefDataAsnWrite(ptr -> data, aip, VARIATION_REF_data)) {
+         goto erret;
+      }
+   }
+   if (ptr -> consequence != NULL) {
+     retval = ConsequenceAsnWrite(ptr -> consequence, aip,VARIATION_REF_consequence);
+   }
+   if (ptr -> location != NULL) {
+      if ( ! SeqLocAsnWrite(ptr -> location, aip, VARIATION_REF_location)) {
+         goto erret;
+      }
+   }
+   if (ptr -> ext_locs != NULL) {
+     AsnGenericValNodeSetAsnWrite (ptr -> ext_locs, (AsnWriteFunc) ExtLocAsnWrite, aip, VARIATION_REF_ext_locs, VARIATION_REF_ext_locs_E);
+     /*
+     AsnGenericUserSeqOfAsnWrite(ptr -> ext_locs, (AsnWriteFunc) ExtLocAsnWrite, aip, VARIATION_REF_ext_locs, VARIATION_REF_ext_locs_E);
+     */
+   }
+   if (ptr -> ext != NULL) {
+      if ( ! UserObjectAsnWrite(ptr -> ext, aip, VARIATION_REF_ext)) {
+         goto erret;
+      }
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    ConsequenceAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+ConsequenceAsnWrite(ValNodePtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, VARIATION_REF_consequence);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   retval = AsnGenericChoiceSeqOfAsnWrite(anp, 
+   (AsnWriteFunc) Consequence_elementAsnWrite, aip, atp, VARIATION_REF_consequence_E);
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+/**************************************************
+*
+*    Consequence_elementAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+Consequence_elementAsnWrite(Consequence_elementPtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp, writetype = NULL;
+   Pointer pnt;
+   AsnWriteFunc func = NULL;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, VARIATION_REF_consequence_E);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   if (! AsnWriteChoice(aip, atp, (Int2)anp->choice, &av)) {
+      goto erret;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   case Consequence_unknown:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, REF_consequence_E_unknown, &av);
+      break;
+   case Consequence_splicing:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, REF_consequence_E_splicing, &av);
+      break;
+   case Consequence_note:
+      av.ptrvalue = anp->data.ptrvalue;
+      retval = AsnWrite(aip, REF_consequence_E_note, &av);
+      break;
+   case Consequence_variation:
+      writetype = REF_consequence_E_variation;
+      func = (AsnWriteFunc) VariationRefAsnWrite;
+      break;
+   case Consequence_Consequence_Frameshift:
+      writetype = REF_consequence_E_frameshift;
+      func = (AsnWriteFunc) Consequence_frameshiftAsnWrite;
+      break;
+   case Consequence_Consequence_LossOfHeterozygosity:
+      writetype = E_loss_of_heterozygosity;
+      func = (AsnWriteFunc) Consequence_loss_of_heterozygosityAsnWrite;
+      break;
+   }
+   if (writetype != NULL) {
+      retval = (* func)(pnt, aip, writetype);   /* write it out */
+   }
+   if (!retval) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+/**************************************************
+*
+*    Consequence_loss_of_heterozygosityAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+Consequence_loss_of_heterozygosityAsnWrite(Consequence_loss_of_heterozygosityPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, E_loss_of_heterozygosity);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> reference != NULL) {
+      av.ptrvalue = ptr -> reference;
+      retval = AsnWrite(aip, of_heterozygosity_reference,  &av);
+   }
+   if (ptr -> test != NULL) {
+      av.ptrvalue = ptr -> test;
+      retval = AsnWrite(aip, E_loss_of_heterozygosity_test,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    Consequence_frameshiftAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+Consequence_frameshiftAsnWrite(Consequence_frameshiftPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, REF_consequence_E_frameshift);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> phase || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> phase;
+      retval = AsnWrite(aip, consequence_E_frameshift_phase,  &av);
+   }
+   if (ptr -> x_length || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> x_length;
+      retval = AsnWrite(aip, E_frameshift_x_length,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    Data_setAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+VarRefDataSetAsnWrite(VarRefDataSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, VARIATION_REF_data_set);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   av.intvalue = ptr -> type;
+   retval = AsnWrite(aip, VARIATION_REF_data_set_type,  &av);
+   AsnGenericValNodeSetAsnWrite(ptr -> variations, (AsnWriteFunc) VariationRefAsnWrite, aip, REF_data_set_variations, REF_data_set_variations_E);
+   /*
+   AsnGenericUserSeqOfAsnWrite(ptr -> variations, (AsnWriteFunc) VariationRefAsnWrite, aip, REF_data_set_variations, REF_data_set_variations_E);
+   */
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, VARIATION_REF_data_set_name,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+/**************************************************
+*
+*    VarRefDataAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+VarRefDataAsnWrite( VarRefDataPtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp, writetype = NULL;
+   Pointer pnt;
+   AsnWriteFunc func = NULL;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, VARIATION_REF_data);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   if (! AsnWriteChoice(aip, atp, (Int2)anp->choice, &av)) {
+      goto erret;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   case VarRefData_unknown:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, VARIATION_REF_data_unknown, &av);
+      break;
+   case VarRefData_note:
+      av.ptrvalue = anp->data.ptrvalue;
+      retval = AsnWrite(aip, VARIATION_REF_data_note, &av);
+      break;
+   case VarRefData_uniparental_disomy:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, REF_data_uniparental_disomy, &av);
+      break;
+   case VarRefData_instance:
+      writetype = VARIATION_REF_data_instance;
+      func = (AsnWriteFunc) VariationInstAsnWrite;
+      break;
+   case VarRefData_set:
+      writetype = VARIATION_REF_data_set;
+      func = (AsnWriteFunc) VarRefDataSetAsnWrite;
+      break;
+   }
+   if (writetype != NULL) {
+      retval = (* func)(pnt, aip, writetype);   /* write it out */
+   }
+   if (!retval) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    Consequence_elementAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_elementPtr LIBCALL
+Consequence_elementAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Uint1 choice;
+   Boolean nullIsError = FALSE;
+   AsnReadFunc func;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* Consequence_element ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIATION_REF_consequence_E);
+   } else {
+      atp = AsnLinkType(orig, VARIATION_REF_consequence_E);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp = ValNodeNew(NULL);
+   if (anp == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the CHOICE or OpenStruct value (nothing) */
+      goto erret;
+   }
+
+   func = NULL;
+
+   atp = AsnReadId(aip, amp, atp);  /* find the choice */
+   if (atp == NULL) {
+      goto erret;
+   }
+   if (atp == REF_consequence_E_unknown) {
+      choice = Consequence_unknown;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == REF_consequence_E_splicing) {
+      choice = Consequence_splicing;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == REF_consequence_E_note) {
+      choice = Consequence_note;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.ptrvalue = av.ptrvalue;
+   }
+   else if (atp == REF_consequence_E_variation) {
+      choice = Consequence_variation;
+      func = (AsnReadFunc) VariationRefAsnRead;
+   }
+   else if (atp == REF_consequence_E_frameshift) {
+      choice = Consequence_Consequence_Frameshift;
+      func = (AsnReadFunc) Consequence_frameshiftAsnRead;
+   }
+   else if (atp == E_loss_of_heterozygosity) {
+      choice = Consequence_Consequence_LossOfHeterozygosity;
+      func = (AsnReadFunc) Consequence_loss_of_heterozygosityAsnRead;
+   }
+   anp->choice = choice;
+   if (func != NULL)
+   {
+      anp->data.ptrvalue = (* func)(aip, atp);
+      if (aip -> io_failure) goto erret;
+
+      if (nullIsError && anp->data.ptrvalue == NULL) {
+         goto erret;
+      }
+   }
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   anp = MemFree(anp);
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    Consequence_loss_of_heterozygosityAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_loss_of_heterozygosityPtr LIBCALL
+Consequence_loss_of_heterozygosityAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   Consequence_loss_of_heterozygosityPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* Consequence_loss_of_heterozygosity ::= (self contained) */
+      atp = AsnReadId(aip, amp, E_loss_of_heterozygosity);
+   } else {
+      atp = AsnLinkType(orig, E_loss_of_heterozygosity);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = Consequence_loss_of_heterozygosityNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == of_heterozygosity_reference) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> reference = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == E_loss_of_heterozygosity_test) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> test = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = Consequence_loss_of_heterozygosityFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    Consequence_frameshiftAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_frameshiftPtr LIBCALL
+Consequence_frameshiftAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   Consequence_frameshiftPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* Consequence_frameshift ::= (self contained) */
+      atp = AsnReadId(aip, amp, REF_consequence_E_frameshift);
+   } else {
+      atp = AsnLinkType(orig, REF_consequence_E_frameshift);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = Consequence_frameshiftNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == consequence_E_frameshift_phase) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> phase = av.intvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == E_frameshift_x_length) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> x_length = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = Consequence_frameshiftFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    Data_setFree()
+*
+**************************************************/
+NLM_EXTERN 
+VarRefDataSetPtr LIBCALL
+VarRefDataSetFree(VarRefDataSetPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   AsnGenericValNodeSetFree (ptr -> variations, (AsnOptFreeFunc) VariationRefFree);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> variations, (AsnOptFreeFunc) VariationRefFree);
+   */
+   MemFree(ptr -> name);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    VarRefDataFree()
+*
+**************************************************/
+NLM_EXTERN 
+VarRefDataPtr LIBCALL
+VarRefDataFree(ValNodePtr anp)
+{
+   Pointer pnt;
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   default:
+      break;
+   case VarRefData_note:
+      MemFree(anp -> data.ptrvalue);
+      break;
+   case VarRefData_instance:
+      VariationInstFree(anp -> data.ptrvalue);
+      break;
+   case VarRefData_set:
+      VarRefDataSetFree(anp -> data.ptrvalue);
+      break;
+   }
+   return MemFree(anp);
+}
+
+
+/**************************************************
+*
+*    Data_setNew()
+*
+**************************************************/
+NLM_EXTERN 
+VarRefDataSetPtr LIBCALL
+VarRefDataSetNew(void)
+{
+   VarRefDataSetPtr ptr = MemNew((size_t) sizeof(VarRefData));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    Data_setAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+VarRefDataSetPtr LIBCALL
+VarRefDataSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   VarRefDataSetPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* Data_set ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIATION_REF_data_set);
+   } else {
+      atp = AsnLinkType(orig, VARIATION_REF_data_set);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = VarRefDataSetNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == VARIATION_REF_data_set_type) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> type = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == REF_data_set_variations) {
+      ptr -> variations = AsnGenericValNodeSetAsnRead (aip, amp, atp, &isError, (AsnReadFunc) VariationRefAsnRead, (AsnOptFreeFunc) VariationRefFree);
+      /*
+      ptr -> variations = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) VariationRefAsnRead, (AsnOptFreeFunc) VariationRefFree);
+      */
+      if (isError && ptr -> variations == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_REF_data_set_name) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> name = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = VarRefDataSetFree(ptr);
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    VarRefDataAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+VarRefDataPtr LIBCALL
+VarRefDataAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Uint1 choice;
+   Boolean nullIsError = FALSE;
+   AsnReadFunc func;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* data ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIATION_REF_data);
+   } else {
+      atp = AsnLinkType(orig, VARIATION_REF_data);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp = ValNodeNew(NULL);
+   if (anp == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the CHOICE or OpenStruct value (nothing) */
+      goto erret;
+   }
+
+   func = NULL;
+
+   atp = AsnReadId(aip, amp, atp);  /* find the choice */
+   if (atp == NULL) {
+      goto erret;
+   }
+   if (atp == VARIATION_REF_data_unknown) {
+      choice = VarRefData_unknown;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == VARIATION_REF_data_note) {
+      choice = VarRefData_note;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.ptrvalue = av.ptrvalue;
+   }
+   else if (atp == REF_data_uniparental_disomy) {
+      choice = VarRefData_uniparental_disomy;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == VARIATION_REF_data_instance) {
+      choice = VarRefData_instance;
+      func = (AsnReadFunc) VariationInstAsnRead;
+   }
+   else if (atp == VARIATION_REF_data_set) {
+      choice = VarRefData_set;
+      func = (AsnReadFunc) VarRefDataSetAsnRead;
+   }
+   anp->choice = choice;
+   if (func != NULL)
+   {
+      anp->data.ptrvalue = (* func)(aip, atp);
+      if (aip -> io_failure) goto erret;
+
+      if (nullIsError && anp->data.ptrvalue == NULL) {
+         goto erret;
+      }
+   }
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   anp = MemFree(anp);
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    Consequence_elementFree()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_elementPtr LIBCALL
+Consequence_elementFree(ValNodePtr anp)
+{
+   Pointer pnt;
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   default:
+      break;
+   case Consequence_note:
+      MemFree(anp -> data.ptrvalue);
+      break;
+   case Consequence_variation:
+      VariationRefFree(anp -> data.ptrvalue);
+      break;
+   case Consequence_Consequence_Frameshift:
+      Consequence_frameshiftFree(anp -> data.ptrvalue);
+      break;
+   case Consequence_Consequence_LossOfHeterozygosity:
+      Consequence_loss_of_heterozygosityFree(anp -> data.ptrvalue);
+      break;
+   }
+   return MemFree(anp);
+}
+
+
+/**************************************************
+*
+*    Consequence_loss_of_heterozygosityFree()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_loss_of_heterozygosityPtr LIBCALL
+Consequence_loss_of_heterozygosityFree(Consequence_loss_of_heterozygosityPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> reference);
+   MemFree(ptr -> test);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    Consequence_frameshiftFree()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_frameshiftPtr LIBCALL
+Consequence_frameshiftFree(Consequence_frameshiftPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    Consequence_frameshiftNew()
+*
+**************************************************/
+NLM_EXTERN 
+Consequence_frameshiftPtr LIBCALL
+Consequence_frameshiftNew(void)
+{
+   Consequence_frameshiftPtr ptr = MemNew((size_t) sizeof(Consequence_frameshift));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    VariationInstNew()
+*
+**************************************************/
+NLM_EXTERN 
+VariationInstPtr LIBCALL
+VariationInstNew(void)
+{
+   VariationInstPtr ptr = MemNew((size_t) sizeof(VariationInst));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    VariationInstFree()
+*
+**************************************************/
+NLM_EXTERN 
+VariationInstPtr LIBCALL
+VariationInstFree(VariationInstPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   AsnGenericValNodeSetFree (ptr -> delta, (AsnOptFreeFunc) DeltaItemFree);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> delta, (AsnOptFreeFunc) DeltaItemFree);
+   */
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    VariationInstAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+VariationInstPtr LIBCALL
+VariationInstAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   VariationInstPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* VariationInst ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIATION_INST);
+   } else {
+      atp = AsnLinkType(orig, VARIATION_INST);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = VariationInstNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == VARIATION_INST_type) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> type = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIATION_INST_delta) {
+      ptr -> delta = AsnGenericValNodeSetAsnRead (aip, amp, atp, &isError, (AsnReadFunc) DeltaItemAsnRead, (AsnOptFreeFunc) DeltaItemFree);
+      /*
+      ptr -> delta = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) DeltaItemAsnRead, (AsnOptFreeFunc) DeltaItemFree);
+      */
+      if (isError && ptr -> delta == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = VariationInstFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    VariationInstAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+VariationInstAsnWrite(VariationInstPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, VARIATION_INST);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   av.intvalue = ptr -> type;
+   retval = AsnWrite(aip, VARIATION_INST_type,  &av);
+   AsnGenericValNodeSetAsnWrite (ptr -> delta, (AsnWriteFunc) DeltaItemAsnWrite, aip, VARIATION_INST_delta, VARIATION_INST_delta_E);
+   /*
+   AsnGenericUserSeqOfAsnWrite(ptr -> delta, (AsnWriteFunc) DeltaItemAsnWrite, aip, VARIATION_INST_delta, VARIATION_INST_delta_E);
+   */
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    ProjectDataNew()
+*
+**************************************************/
+NLM_EXTERN 
+ProjectDataPtr LIBCALL
+ProjectDataNew(void)
+{
+   ProjectDataPtr ptr = MemNew((size_t) sizeof(ProjectData));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    VariantPropertiesNew()
+*
+**************************************************/
+NLM_EXTERN 
+VariantPropertiesPtr LIBCALL
+VariantPropertiesNew(void)
+{
+   VariantPropertiesPtr ptr = MemNew((size_t) sizeof(VariantProperties));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    ProjectDataFree()
+*
+**************************************************/
+NLM_EXTERN 
+ProjectDataPtr LIBCALL
+ProjectDataFree(ProjectDataPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   AsnGenericBaseSeqOfFree(ptr -> project_ids ,ASNCODE_INTVAL_SLOT);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+/**************************************************
+*
+*    VariantPropertiesFree()
+*
+**************************************************/
+NLM_EXTERN 
+VariantPropertiesPtr LIBCALL
+VariantPropertiesFree(VariantPropertiesPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   ProjectDataFree(ptr -> project_data);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    ProjectDataAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+ProjectDataPtr LIBCALL
+ProjectDataAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   ProjectDataPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* ProjectData ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIANTPROPERTIES_project_data);
+   } else {
+      atp = AsnLinkType(orig, VARIANTPROPERTIES_project_data);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = ProjectDataNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == project_data_E_project_ids) {
+      ptr -> project_ids = AsnGenericBaseSeqOfAsnRead(aip, amp, atp, ASNCODE_INTVAL_SLOT, &isError);
+      if (isError && ptr -> project_ids == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = ProjectDataFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    VariantPropertiesAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+VariantPropertiesPtr LIBCALL
+VariantPropertiesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   VariantPropertiesPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* VariantProperties ::= (self contained) */
+      atp = AsnReadId(aip, amp, VARIANTPROPERTIES);
+   } else {
+      atp = AsnLinkType(orig, VARIANTPROPERTIES);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = VariantPropertiesNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == VARIANTPROPERTIES_version) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> version = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_resource_link) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> resource_link = av.intvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_gene_location) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gene_location = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_effect) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> effect = av.intvalue;
+      ptr -> OBbits__ |= 1<<2;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_mapping) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> mapping = av.intvalue;
+      ptr -> OBbits__ |= 1<<3;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_map_weight) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> map_weight = av.intvalue;
+      ptr -> OBbits__ |= 1<<4;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == frequency_based_validation) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> freq_based_validation = av.intvalue;
+      ptr -> OBbits__ |= 1<<5;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_genotype) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> genotype = av.intvalue;
+      ptr -> OBbits__ |= 1<<6;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_project_data) {
+      ptr -> project_data =  ProjectDataAsnRead(aip, atp);
+      if (ptr -> project_data == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_quality_check) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> quality_check = av.intvalue;
+      ptr -> OBbits__ |= 1<<7;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == VARIANTPROPERTIES_confidence) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> confidence = av.intvalue;
+      ptr -> OBbits__ |= 1<<8;
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = VariantPropertiesFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    ProjectDataAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+ProjectDataAsnWrite(ProjectDataPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, VARIANTPROPERTIES_project_data);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   retval = AsnGenericBaseSeqOfAsnWrite(ptr -> project_ids ,ASNCODE_INTVAL_SLOT, aip, project_data_E_project_ids, project_data_E_project_ids_E);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    VariantPropertiesAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+VariantPropertiesAsnWrite(VariantPropertiesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, VARIANTPROPERTIES);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   av.intvalue = ptr -> version;
+   retval = AsnWrite(aip, VARIANTPROPERTIES_version,  &av);
+   if (ptr -> resource_link || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> resource_link;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_resource_link,  &av);
+   }
+   if (ptr -> gene_location || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> gene_location;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_gene_location,  &av);
+   }
+   if (ptr -> effect || (ptr -> OBbits__ & (1<<2) )){   av.intvalue = ptr -> effect;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_effect,  &av);
+   }
+   if (ptr -> mapping || (ptr -> OBbits__ & (1<<3) )){   av.intvalue = ptr -> mapping;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_mapping,  &av);
+   }
+   if (ptr -> map_weight || (ptr -> OBbits__ & (1<<4) )){   av.intvalue = ptr -> map_weight;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_map_weight,  &av);
+   }
+   if (ptr -> freq_based_validation || (ptr -> OBbits__ & (1<<5) )){   av.intvalue = ptr -> freq_based_validation;
+      retval = AsnWrite(aip, frequency_based_validation,  &av);
+   }
+   if (ptr -> genotype || (ptr -> OBbits__ & (1<<6) )){   av.intvalue = ptr -> genotype;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_genotype,  &av);
+   }
+   retval = ProjectDataAsnWrite(ptr -> project_data, aip,VARIANTPROPERTIES_project_data);
+   if (ptr -> quality_check || (ptr -> OBbits__ & (1<<7) )){   av.intvalue = ptr -> quality_check;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_quality_check,  &av);
+   }
+   if (ptr -> confidence || (ptr -> OBbits__ & (1<<8) )){   av.intvalue = ptr -> confidence;
+      retval = AsnWrite(aip, VARIANTPROPERTIES_confidence,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    PhenotypeNew()
+*
+**************************************************/
+NLM_EXTERN 
+PhenotypePtr LIBCALL
+PhenotypeNew(void)
+{
+   PhenotypePtr ptr = MemNew((size_t) sizeof(Phenotype));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    PhenotypeFree()
+*
+**************************************************/
+NLM_EXTERN 
+PhenotypePtr LIBCALL
+PhenotypeFree(PhenotypePtr ptr)
+{
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> source);
+   MemFree(ptr -> term);
+   /*
+   AsnGenericUserSeqOfFree(ptr -> xref, (AsnOptFreeFunc) DbtagFree);
+   */
+   AsnGenericValNodeSetFree (ptr->xref, (AsnOptFreeFunc) DbtagFree);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    PhenotypeAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+PhenotypePtr LIBCALL
+PhenotypeAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   PhenotypePtr ptr;
+   Boolean isError = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* Phenotype ::= (self contained) */
+      atp = AsnReadId(aip, amp, PHENOTYPE);
+   } else {
+      atp = AsnLinkType(orig, PHENOTYPE);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = PhenotypeNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == PHENOTYPE_source) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> source = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == PHENOTYPE_term) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> term = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == PHENOTYPE_xref) {
+      ptr->xref = AsnGenericValNodeSetAsnRead (aip, amp, atp, &isError, (AsnReadFunc) DbtagAsnRead, (AsnOptFreeFunc) DbtagFree);
+      /*
+      ptr -> xref = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) DbtagAsnRead, (AsnOptFreeFunc) DbtagFree);
+      */
+      if (isError && ptr -> xref == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == PHENOTYPE_clinical_significance) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> clinical_significance = av.intvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = PhenotypeFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    PhenotypeAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+PhenotypeAsnWrite(PhenotypePtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, PHENOTYPE);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> source != NULL) {
+      av.ptrvalue = ptr -> source;
+      retval = AsnWrite(aip, PHENOTYPE_source,  &av);
+   }
+   if (ptr -> term != NULL) {
+      av.ptrvalue = ptr -> term;
+      retval = AsnWrite(aip, PHENOTYPE_term,  &av);
+   }
+   AsnGenericValNodeSetAsnWrite (ptr->xref, (AsnWriteFunc) DbtagAsnWrite, aip, PHENOTYPE_xref, PHENOTYPE_xref_E);
+   /*
+   AsnGenericUserSeqOfAsnWrite(ptr -> xref, (AsnWriteFunc) DbtagAsnWrite, aip, PHENOTYPE_xref, PHENOTYPE_xref_E);
+   */
+   if (ptr -> clinical_significance || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> clinical_significance;
+      retval = AsnWrite(aip, PHENOTYPE_clinical_significance,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    PopulationDataNew()
+*
+**************************************************/
+NLM_EXTERN 
+PopulationDataPtr LIBCALL
+PopulationDataNew(void)
+{
+   PopulationDataPtr ptr = MemNew((size_t) sizeof(PopulationData));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    PopulationDataFree()
+*
+**************************************************/
+NLM_EXTERN 
+PopulationDataPtr LIBCALL
+PopulationDataFree(PopulationDataPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> population);
+   AsnGenericValNodeSetFree (ptr -> sample_ids, (AsnOptFreeFunc) ObjectIdFree);
+   /*
+   AsnGenericChoiceSeqOfFree(ptr -> sample_ids, (AsnOptFreeFunc) ObjectIdFree);
+   */
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    PopulationDataAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+PopulationDataPtr LIBCALL
+PopulationDataAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   PopulationDataPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* PopulationData ::= (self contained) */
+      atp = AsnReadId(aip, amp, POPULATION_DATA);
+   } else {
+      atp = AsnLinkType(orig, POPULATION_DATA);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = PopulationDataNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == POPULATION_DATA_population) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> population = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == DATA_genotype_frequency) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> genotype_frequency = av.realvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == DATA_chromosomes_tested) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> chromosomes_tested = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == POPULATION_DATA_sample_ids) {
+      ptr -> sample_ids = AsnGenericValNodeSetAsnRead(aip, amp, atp, &isError, (AsnReadFunc) ObjectIdAsnRead, (AsnOptFreeFunc) ObjectIdFree);
+      /*
+      ptr -> sample_ids = AsnGenericChoiceSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) ObjectIdAsnRead, (AsnOptFreeFunc) ObjectIdFree);
+      */
+      if (isError && ptr -> sample_ids == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = PopulationDataFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    PopulationDataAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+PopulationDataAsnWrite(PopulationDataPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, POPULATION_DATA);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> population != NULL) {
+      av.ptrvalue = ptr -> population;
+      retval = AsnWrite(aip, POPULATION_DATA_population,  &av);
+   }
+   if (ptr -> genotype_frequency || (ptr -> OBbits__ & (1<<0) )){   av.realvalue = ptr -> genotype_frequency;
+      retval = AsnWrite(aip, DATA_genotype_frequency,  &av);
+   }
+   if (ptr -> chromosomes_tested || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> chromosomes_tested;
+      retval = AsnWrite(aip, DATA_chromosomes_tested,  &av);
+   }
+   AsnGenericValNodeSetAsnWrite(ptr -> sample_ids, (AsnWriteFunc) ObjectIdAsnWrite, aip, POPULATION_DATA_sample_ids, POPULATION_DATA_sample_ids_E);
+   /*
+   AsnGenericChoiceSeqOfAsnWrite(ptr -> sample_ids, (AsnWriteFunc) ObjectIdAsnWrite, aip, POPULATION_DATA_sample_ids, POPULATION_DATA_sample_ids_E);
+   */
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    ExtLocNew()
+*
+**************************************************/
+NLM_EXTERN 
+ExtLocPtr LIBCALL
+ExtLocNew(void)
+{
+   ExtLocPtr ptr = MemNew((size_t) sizeof(ExtLoc));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    ExtLocFree()
+*
+**************************************************/
+NLM_EXTERN 
+ExtLocPtr LIBCALL
+ExtLocFree(ExtLocPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   ObjectIdFree(ptr -> id);
+   SeqLocFree(ptr -> location);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    ExtLocAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+ExtLocPtr LIBCALL
+ExtLocAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   ExtLocPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* ExtLoc ::= (self contained) */
+      atp = AsnReadId(aip, amp, EXT_LOC);
+   } else {
+      atp = AsnLinkType(orig, EXT_LOC);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = ExtLocNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == EXT_LOC_id) {
+      ptr -> id = ObjectIdAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == EXT_LOC_location) {
+      ptr -> location = SeqLocAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = ExtLocFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    ExtLocAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+ExtLocAsnWrite(ExtLocPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, EXT_LOC);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> id != NULL) {
+      if ( ! ObjectIdAsnWrite(ptr -> id, aip, EXT_LOC_id)) {
+         goto erret;
+      }
+   }
+   if (ptr -> location != NULL) {
+      if ( ! SeqLocAsnWrite(ptr -> location, aip, EXT_LOC_location)) {
+         goto erret;
+      }
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    DeltaItemNew()
+*
+**************************************************/
+NLM_EXTERN 
+DeltaItemPtr LIBCALL
+DeltaItemNew(void)
+{
+   DeltaItemPtr ptr = MemNew((size_t) sizeof(DeltaItem));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    DeltaItemFree()
+*
+**************************************************/
+NLM_EXTERN 
+DeltaItemPtr LIBCALL
+DeltaItemFree(DeltaItemPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   Seq_seqFree(ptr -> Seq_seq);
+   IntFuzzFree(ptr -> multiplier_fuzz);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    Seq_seqFree()
+*
+**************************************************/
+NLM_EXTERN 
+Seq_seqPtr LIBCALL
+Seq_seqFree(ValNodePtr anp)
+{
+   Pointer pnt;
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   default:
+      break;
+   case Seq_seq_literal:
+      SeqLitFree(anp -> data.ptrvalue);
+      break;
+   case Seq_seq_loc:
+      SeqLocFree(anp -> data.ptrvalue);
+      break;
+   }
+   return MemFree(anp);
+}
+
+
+/**************************************************
+*
+*    DeltaItemAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+DeltaItemPtr LIBCALL
+DeltaItemAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   DeltaItemPtr ptr;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* DeltaItem ::= (self contained) */
+      atp = AsnReadId(aip, amp, DELTA_ITEM);
+   } else {
+      atp = AsnLinkType(orig, DELTA_ITEM);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = DeltaItemNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == DELTA_ITEM_seq) {
+      ptr -> Seq_seq = Seq_seqAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == DELTA_ITEM_multiplier) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> multiplier = av.intvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == DELTA_ITEM_multiplier_fuzz) {
+      ptr -> multiplier_fuzz = IntFuzzAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == DELTA_ITEM_action) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> action = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = DeltaItemFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    Seq_seqAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+Seq_seqPtr LIBCALL
+Seq_seqAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Uint1 choice;
+   Boolean nullIsError = FALSE;
+   AsnReadFunc func;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* Seq_seq ::= (self contained) */
+      atp = AsnReadId(aip, amp, DELTA_ITEM_seq);
+   } else {
+      atp = AsnLinkType(orig, DELTA_ITEM_seq);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp = ValNodeNew(NULL);
+   if (anp == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the CHOICE or OpenStruct value (nothing) */
+      goto erret;
+   }
+
+   func = NULL;
+
+   atp = AsnReadId(aip, amp, atp);  /* find the choice */
+   if (atp == NULL) {
+      goto erret;
+   }
+   if (atp == DELTA_ITEM_seq_literal) {
+      choice = Seq_seq_literal;
+      func = (AsnReadFunc) SeqLitAsnRead;
+   }
+   else if (atp == DELTA_ITEM_seq_loc) {
+      choice = Seq_seq_loc;
+      func = (AsnReadFunc) SeqLocAsnRead;
+   }
+   else if (atp == DELTA_ITEM_seq_this) {
+      choice = Seq_seq_this__;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   anp->choice = choice;
+   if (func != NULL)
+   {
+      anp->data.ptrvalue = (* func)(aip, atp);
+      if (aip -> io_failure) goto erret;
+
+      if (nullIsError && anp->data.ptrvalue == NULL) {
+         goto erret;
+      }
+   }
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   anp = MemFree(anp);
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    DeltaItemAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+DeltaItemAsnWrite(DeltaItemPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, DELTA_ITEM);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> Seq_seq != NULL) {
+      if ( ! Seq_seqAsnWrite(ptr -> Seq_seq, aip, DELTA_ITEM_seq)) {
+         goto erret;
+      }
+   }
+   if (ptr -> multiplier || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> multiplier;
+      retval = AsnWrite(aip, DELTA_ITEM_multiplier,  &av);
+   }
+   if (ptr -> multiplier_fuzz != NULL) {
+      if ( ! IntFuzzAsnWrite(ptr -> multiplier_fuzz, aip, DELTA_ITEM_multiplier_fuzz)) {
+         goto erret;
+      }
+   }
+   av.intvalue = ptr -> action;
+   retval = AsnWrite(aip, DELTA_ITEM_action,  &av);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    Seq_seqAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+Seq_seqAsnWrite(Seq_seqPtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp, writetype = NULL;
+   Pointer pnt;
+   AsnWriteFunc func = NULL;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! SeqFeatAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, DELTA_ITEM_seq);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   if (! AsnWriteChoice(aip, atp, (Int2)anp->choice, &av)) {
+      goto erret;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   case Seq_seq_literal:
+      writetype = DELTA_ITEM_seq_literal;
+      func = (AsnWriteFunc) SeqLitAsnWrite;
+      break;
+   case Seq_seq_loc:
+      writetype = DELTA_ITEM_seq_loc;
+      func = (AsnWriteFunc) SeqLocAsnWrite;
+      break;
+   case Seq_seq_this__:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, DELTA_ITEM_seq_this, &av);
+      break;
+   }
+   if (writetype != NULL) {
+      retval = (* func)(pnt, aip, writetype);   /* write it out */
+   }
+   if (!retval) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
diff --git a/object/objfeat.h b/object/objfeat.h
index 8f954bf..b082684 100644
--- a/object/objfeat.h
+++ b/object/objfeat.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 4/1/91
 *
-* $Revision: 6.20 $
+* $Revision: 6.29 $
 *
 * File Description:  Object manager interface for module NCBI-SeqFeat
 *
@@ -157,6 +157,7 @@ NLM_EXTERN SeqFeatXrefPtr LIBCALL SeqFeatXrefFree PROTO((SeqFeatXrefPtr sfxp));
 	19 = het data.value.ptrvalue=CharPtr Heterogen   -- cofactor, prosthetic grp, etc, bound to seq
 	20 = biosrc, data.value.ptrvalue = BioSource
     21 = cloneref, data.value.ptrvalue = CloneRef
+    22 = variation, data.value.ptrvalue = VariationRef
 *   
 *
 *****************************************************************************/
@@ -221,8 +222,9 @@ NLM_EXTERN SeqFeatXrefPtr LIBCALL SeqFeatToXref PROTO((SeqFeatPtr sfp));
 #define SEQFEAT_HET             19
 #define SEQFEAT_BIOSRC          20
 #define SEQFEAT_CLONEREF        21
+#define SEQFEAT_VARIATIONREF    22
 
-#define SEQFEAT_MAX 22 /* size of array needed for seqfeat filter parameters */
+#define SEQFEAT_MAX 23 /* size of array needed for seqfeat filter parameters */
 
 /*****************************************************************************
 *
@@ -545,7 +547,8 @@ typedef struct orgname {
 	OrgModPtr mod;   /* OrgMods */
 	CharPtr lineage;  /* lineage to this org */
 	Uint1 gcode,      /* genetic code using GenBank keys */
-		  mgcode;      /* mitochondrial genetic code using GenBank keys..0=none */
+		  mgcode,      /* mitochondrial genetic code using GenBank keys..0=none */
+		  pgcode;      /* plastid genetic code using GenBank keys..0=none */
 	CharPtr div;       /* GenBank division code */
 	struct orgname PNTR next;   /* for MultiOrgName */
 } OrgName, PNTR OrgNamePtr;
@@ -809,7 +812,335 @@ NLM_EXTERN CloneRefPtr LIBCALL CloneRefAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
 NLM_EXTERN Boolean LIBCALL CloneRefAsnWrite PROTO (( CloneRefPtr , AsnIoPtr, AsnTypePtr));
 
 
+/**************************************************
+*
+*    Phenotype
+*
+**************************************************/
+typedef struct phenotype {
+   struct phenotype PNTR next;
+   Uint4 OBbits__;
+   CharPtr   source;
+   CharPtr   term;
+   ValNodePtr  xref;
+#define OB__Phenotype_clinical_significance 0
+
+   Int4   clinical_significance;
+} Phenotype, PNTR PhenotypePtr;
+
+
+NLM_EXTERN PhenotypePtr LIBCALL PhenotypeFree PROTO ((PhenotypePtr ));
+NLM_EXTERN PhenotypePtr LIBCALL PhenotypeNew PROTO (( void ));
+NLM_EXTERN PhenotypePtr LIBCALL PhenotypeAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL PhenotypeAsnWrite PROTO (( PhenotypePtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    PopulationData
+*
+**************************************************/
+typedef struct population_data {
+   struct population_data PNTR next;
+   Uint4 OBbits__;
+   CharPtr   population;
+#define OB__Population_data_genotype_frequency 0
+
+   FloatHi   genotype_frequency;
+#define OB__Population_data_chromosomes_tested 1
+
+   Int4   chromosomes_tested;
+   ValNodePtr   sample_ids;
+} PopulationData, PNTR PopulationDataPtr;
+
+
+NLM_EXTERN PopulationDataPtr LIBCALL PopulationDataFree PROTO ((PopulationDataPtr ));
+NLM_EXTERN PopulationDataPtr LIBCALL PopulationDataNew PROTO (( void ));
+NLM_EXTERN PopulationDataPtr LIBCALL PopulationDataAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL PopulationDataAsnWrite PROTO (( PopulationDataPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    ProjectData
+*
+**************************************************/
+
+typedef struct struct_ProjectData {
+   Uint4 OBbits__;
+   ValNodePtr   project_ids;
+} ProjectData, PNTR ProjectDataPtr;
+
+
+NLM_EXTERN ProjectDataPtr LIBCALL ProjectDataFree PROTO ((ProjectDataPtr ));
+NLM_EXTERN ProjectDataPtr LIBCALL ProjectDataNew PROTO (( void ));
+NLM_EXTERN ProjectDataPtr LIBCALL ProjectDataAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL ProjectDataAsnWrite PROTO (( ProjectDataPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    VariantProperties
+*
+**************************************************/
+typedef struct struct_VariantProperties {
+   Uint4 OBbits__;
+   Int4   version;
+#define OB__VariantProperties_resource_link 0
+
+   Int4   resource_link;
+#define OB__VariantProperties_gene_location 1
+
+   Int4   gene_location;
+#define OB__VariantProperties_effect 2
+
+   Int4   effect;
+#define OB__VariantProperties_mapping 3
+
+   Int4   mapping;
+#define OB__VariantProperties_map_weight 4
+
+   Int4   map_weight;
+#define OB__frequency_based_validation 5
+
+   Int4   freq_based_validation;
+#define OB__VariantProperties_genotype 6
+
+   Int4   genotype;
+   ProjectDataPtr   project_data;
+#define OB__VariantProperties_quality_check 7
+
+   Int4   quality_check;
+#define OB__VariantProperties_confidence 8
+
+   Int4   confidence;
+} VariantProperties, PNTR VariantPropertiesPtr;
+
+
+NLM_EXTERN VariantPropertiesPtr LIBCALL VariantPropertiesFree PROTO ((VariantPropertiesPtr ));
+NLM_EXTERN VariantPropertiesPtr LIBCALL VariantPropertiesNew PROTO (( void ));
+NLM_EXTERN VariantPropertiesPtr LIBCALL VariantPropertiesAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL VariantPropertiesAsnWrite PROTO (( VariantPropertiesPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    ExtLoc
+*
+**************************************************/
+typedef struct ext_loc {
+   struct ext_loc PNTR next;
+   Uint4 OBbits__;
+   ObjectIdPtr   id;
+   SeqLocPtr   location;
+} ExtLoc, PNTR ExtLocPtr;
+
+
+NLM_EXTERN ExtLocPtr LIBCALL ExtLocFree PROTO ((ExtLocPtr ));
+NLM_EXTERN ExtLocPtr LIBCALL ExtLocNew PROTO (( void ));
+NLM_EXTERN ExtLocPtr LIBCALL ExtLocAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL ExtLocAsnWrite PROTO (( ExtLocPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    VariationRef
+*
+**************************************************/
+typedef struct variation_ref {
+   struct variation_ref PNTR next;
+   Uint4 OBbits__;
+   DbtagPtr   id;
+   DbtagPtr   parent_id;
+   ObjectIdPtr   sample_id;
+   ValNodePtr   other_ids;
+   CharPtr   name;
+   ValNodePtr   synonyms;
+   CharPtr   description;
+   ValNodePtr   phenotype;
+   ValNodePtr   method;
+   ValNodePtr   population_data;
+   VariantPropertiesPtr   variant_prop;
+#define OB__Variation_ref_validated 0
+
+   Uint1   validated;
+   ValNodePtr   clinical_test;
+#define OB__Variation_ref_allele_origin 1
+
+   Int4   allele_origin;
+#define OB__Variation_ref_allele_state 2
+
+   Int4   allele_state;
+#define OB__Variation_ref_allele_frequency 3
+
+   FloatHi   allele_frequency;
+#define OB__Variation_ref_is_ancestral_allele 4
+
+   Uint1   is_ancestral_allele;
+   ValNodePtr   pub;
+   ValNodePtr   data;
+   ValNodePtr   consequence;
+   ValNodePtr   location;
+   ValNodePtr   ext_locs;
+   UserObjectPtr   ext;
+} VariationRef, PNTR VariationRefPtr;
+
+
+NLM_EXTERN VariationRefPtr LIBCALL VariationRefFree PROTO ((VariationRefPtr ));
+NLM_EXTERN VariationRefPtr LIBCALL VariationRefNew PROTO (( void ));
+NLM_EXTERN VariationRefPtr LIBCALL VariationRefAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL VariationRefAsnWrite PROTO (( VariationRefPtr , AsnIoPtr, AsnTypePtr));
+
+typedef ValNodePtr ConsequencePtr;
+typedef ValNode Consequence;
+
+NLM_EXTERN ConsequencePtr LIBCALL ConsequenceFree PROTO ((ConsequencePtr ));
+NLM_EXTERN ConsequencePtr LIBCALL ConsequenceAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL ConsequenceAsnWrite PROTO (( ConsequencePtr , AsnIoPtr, AsnTypePtr));
+
+typedef ValNodePtr Consequence_elementPtr;
+typedef ValNode Consequence_element;
+
+#define Consequence_unknown 1
+#define Consequence_splicing 2
+#define Consequence_note 3
+#define Consequence_variation 4
+#define Consequence_Consequence_Frameshift 5
+#define Consequence_Consequence_LossOfHeterozygosity 6
+
+NLM_EXTERN Consequence_elementPtr LIBCALL Consequence_elementFree PROTO ((Consequence_elementPtr ));
+NLM_EXTERN Consequence_elementPtr LIBCALL Consequence_elementAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL Consequence_elementAsnWrite PROTO (( Consequence_elementPtr , AsnIoPtr, AsnTypePtr));
+
+/**************************************************
+*
+*    Consequence_loss_of_heterozygosity
+*
+**************************************************/
+
+typedef struct consequence_LossOfHeterozygosity {
+   Uint4 OBbits__;
+   CharPtr   reference;
+   CharPtr   test;
+} Consequence_loss_of_heterozygosity, PNTR Consequence_loss_of_heterozygosityPtr;
+
+NLM_EXTERN Consequence_loss_of_heterozygosityPtr LIBCALL Consequence_loss_of_heterozygosityFree PROTO ((Consequence_loss_of_heterozygosityPtr ));
+NLM_EXTERN Consequence_loss_of_heterozygosityPtr LIBCALL Consequence_loss_of_heterozygosityNew PROTO (( void ));
+NLM_EXTERN Consequence_loss_of_heterozygosityPtr LIBCALL Consequence_loss_of_heterozygosityAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL Consequence_loss_of_heterozygosityAsnWrite PROTO (( Consequence_loss_of_heterozygosityPtr , AsnIoPtr, AsnTypePtr));
+
+
+/**************************************************
+*
+*    Consequence_frameshift
+*
+**************************************************/
+
+typedef struct consequence_Frameshift {
+   Uint4 OBbits__;
+#define OB__frameshift_phase 0
+
+   Int4   phase;
+#define OB__frameshift_x_length 1
+
+   Int4   x_length;
+} Consequence_frameshift, PNTR Consequence_frameshiftPtr;
+
+NLM_EXTERN Consequence_frameshiftPtr LIBCALL Consequence_frameshiftFree PROTO ((Consequence_frameshiftPtr ));
+NLM_EXTERN Consequence_frameshiftPtr LIBCALL Consequence_frameshiftNew PROTO (( void ));
+NLM_EXTERN Consequence_frameshiftPtr LIBCALL Consequence_frameshiftAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL Consequence_frameshiftAsnWrite PROTO (( Consequence_frameshiftPtr , AsnIoPtr, AsnTypePtr));
+
+typedef ValNodePtr VarRefDataPtr;
+typedef ValNode VarRefData;
+
+#define VarRefData_unknown 1
+#define VarRefData_note 2
+#define VarRefData_uniparental_disomy 3
+#define VarRefData_instance 4
+#define VarRefData_set 5
+
+NLM_EXTERN VarRefDataPtr LIBCALL VarRefDataFree PROTO ((VarRefDataPtr ));
+NLM_EXTERN VarRefDataPtr LIBCALL VarRefDataAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL VarRefDataAsnWrite PROTO (( VarRefDataPtr , AsnIoPtr, AsnTypePtr));
+
+
+/**************************************************
+*
+*    Data_set
+*
+**************************************************/
+
+typedef struct varRefData_Set {
+   Uint4 OBbits__;
+   Int4   type;
+   ValNodePtr   variations;
+   CharPtr   name;
+} VarRefDataSet, PNTR VarRefDataSetPtr;
+
+NLM_EXTERN VarRefDataSetPtr LIBCALL VarRefDataSetFree PROTO ((VarRefDataSetPtr ));
+NLM_EXTERN VarRefDataSetPtr LIBCALL VarRefDataSetNew PROTO (( void ));
+NLM_EXTERN VarRefDataSetPtr LIBCALL VarRefDataSetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL VarRefDataSetAsnWrite PROTO (( VarRefDataSetPtr , AsnIoPtr, AsnTypePtr));
+
+
+/**************************************************
+*
+*    DeltaItem
+*
+**************************************************/
+typedef struct delta_item {
+   struct delta_item PNTR next;
+   Uint4 OBbits__;
+   ValNodePtr   Seq_seq;
+#define OB__Delta_item_multiplier 0
+
+   Int4   multiplier;
+   IntFuzzPtr   multiplier_fuzz;
+   Int4   action;
+} DeltaItem, PNTR DeltaItemPtr;
+
+
+NLM_EXTERN DeltaItemPtr LIBCALL DeltaItemFree PROTO ((DeltaItemPtr ));
+NLM_EXTERN DeltaItemPtr LIBCALL DeltaItemNew PROTO (( void ));
+NLM_EXTERN DeltaItemPtr LIBCALL DeltaItemAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL DeltaItemAsnWrite PROTO (( DeltaItemPtr , AsnIoPtr, AsnTypePtr));
+
+
+/**************************************************
+*
+*    VariationInst
+*
+**************************************************/
+typedef struct variation_inst {
+   Uint4 OBbits__;
+   Int4   type;
+   ValNodePtr   delta;
+} VariationInst, PNTR VariationInstPtr;
+
+
+NLM_EXTERN VariationInstPtr LIBCALL VariationInstFree PROTO ((VariationInstPtr ));
+NLM_EXTERN VariationInstPtr LIBCALL VariationInstNew PROTO (( void ));
+NLM_EXTERN VariationInstPtr LIBCALL VariationInstAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL VariationInstAsnWrite PROTO (( VariationInstPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+typedef ValNodePtr Seq_seqPtr;
+typedef ValNode Seq_seq;
+
+#define Seq_seq_literal 1
+#define Seq_seq_loc 2
+#define Seq_seq_this__ 3
 
+NLM_EXTERN Seq_seqPtr LIBCALL Seq_seqFree PROTO ((Seq_seqPtr ));
+NLM_EXTERN Seq_seqPtr LIBCALL Seq_seqAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL Seq_seqAsnWrite PROTO (( Seq_seqPtr , AsnIoPtr, AsnTypePtr));
 
 
 
diff --git a/object/objgbseq.c b/object/objgbseq.c
index dc59967..c7171cc 100644
--- a/object/objgbseq.c
+++ b/object/objgbseq.c
@@ -31,7 +31,7 @@ objgbseqAsnLoad(void)
 
 /**************************************************
 *    Generated object loaders for Module NCBI-GBSeq
-*    Generated using ASNCODE Revision: 6.16 at Jan 15, 2009  2:16 PM
+*    Generated using ASNCODE Revision: 6.17 at May 26, 2010 12:37 PM
 *
 **************************************************/
 
@@ -63,7 +63,6 @@ NLM_EXTERN
 GBSetPtr LIBCALL
 GBSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
-   DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
@@ -119,7 +118,6 @@ erret:
 NLM_EXTERN Boolean LIBCALL 
 GBSetAsnWrite(GBSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
-   DataVal av;
    AsnTypePtr atp;
    Boolean retval = FALSE;
 
@@ -202,13 +200,16 @@ GBSeqFree(GBSeqPtr ptr)
    MemFree(ptr -> taxonomy);
    AsnGenericUserSeqOfFree(ptr -> references, (AsnOptFreeFunc) GBReferenceFree);
    MemFree(ptr -> comment);
-   GBTagsetFree(ptr -> tagset);
+   AsnGenericUserSeqOfFree(ptr -> comment_set, (AsnOptFreeFunc) GBCommentFree);
+   AsnGenericUserSeqOfFree(ptr -> struc_comments, (AsnOptFreeFunc) GBStrucCommentFree);
    MemFree(ptr -> primary);
    MemFree(ptr -> source_db);
    MemFree(ptr -> database_reference);
    AsnGenericUserSeqOfFree(ptr -> feature_table, (AsnOptFreeFunc) GBFeatureFree);
+   AsnGenericUserSeqOfFree(ptr -> feature_set, (AsnOptFreeFunc) GBFeatureSetFree);
    MemFree(ptr -> sequence);
    MemFree(ptr -> contig);
+   AsnGenericUserSeqOfFree(ptr -> alt_seq, (AsnOptFreeFunc) GBAltSeqDataFree);
    return MemFree(ptr);
 }
 
@@ -428,9 +429,16 @@ GBSeqAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> comment = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBSEQ_tagset) {
-      ptr -> tagset = GBTagsetAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == GBSEQ_comment_set) {
+      ptr -> comment_set = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBCommentAsnRead, (AsnOptFreeFunc) GBCommentFree);
+      if (isError && ptr -> comment_set == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBSEQ_struc_comments) {
+      ptr -> struc_comments = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBStrucCommentAsnRead, (AsnOptFreeFunc) GBStrucCommentFree);
+      if (isError && ptr -> struc_comments == NULL) {
          goto erret;
       }
       atp = AsnReadId(aip,amp, atp);
@@ -463,6 +471,13 @@ GBSeqAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == GBSEQ_feature_set) {
+      ptr -> feature_set = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBFeatureSetAsnRead, (AsnOptFreeFunc) GBFeatureSetFree);
+      if (isError && ptr -> feature_set == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
    if (atp == GBSEQ_sequence) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
@@ -477,6 +492,13 @@ GBSeqAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> contig = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == GBSEQ_alt_seq) {
+      ptr -> alt_seq = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBAltSeqDataAsnRead, (AsnOptFreeFunc) GBAltSeqDataFree);
+      if (isError && ptr -> alt_seq == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -610,11 +632,8 @@ GBSeqAsnWrite(GBSeqPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       av.ptrvalue = ptr -> comment;
       retval = AsnWrite(aip, GBSEQ_comment,  &av);
    }
-   if (ptr -> tagset != NULL) {
-      if ( ! GBTagsetAsnWrite(ptr -> tagset, aip, GBSEQ_tagset)) {
-         goto erret;
-      }
-   }
+   AsnGenericUserSeqOfAsnWrite(ptr -> comment_set, (AsnWriteFunc) GBCommentAsnWrite, aip, GBSEQ_comment_set, GBSEQ_comment_set_E);
+   AsnGenericUserSeqOfAsnWrite(ptr -> struc_comments, (AsnWriteFunc) GBStrucCommentAsnWrite, aip, GBSEQ_struc_comments, GBSEQ_struc_comments_E);
    if (ptr -> primary != NULL) {
       av.ptrvalue = ptr -> primary;
       retval = AsnWrite(aip, GBSEQ_primary,  &av);
@@ -628,6 +647,7 @@ GBSeqAsnWrite(GBSeqPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       retval = AsnWrite(aip, GBSEQ_database_reference,  &av);
    }
    AsnGenericUserSeqOfAsnWrite(ptr -> feature_table, (AsnWriteFunc) GBFeatureAsnWrite, aip, GBSEQ_feature_table, GBSEQ_feature_table_E);
+   AsnGenericUserSeqOfAsnWrite(ptr -> feature_set, (AsnWriteFunc) GBFeatureSetAsnWrite, aip, GBSEQ_feature_set, GBSEQ_feature_set_E);
    if (ptr -> sequence != NULL) {
       av.ptrvalue = ptr -> sequence;
       retval = AsnWrite(aip, GBSEQ_sequence,  &av);
@@ -636,6 +656,7 @@ GBSeqAsnWrite(GBSeqPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       av.ptrvalue = ptr -> contig;
       retval = AsnWrite(aip, GBSEQ_contig,  &av);
    }
+   AsnGenericUserSeqOfAsnWrite(ptr -> alt_seq, (AsnWriteFunc) GBAltSeqDataAsnWrite, aip, GBSEQ_alt_seq, GBSEQ_alt_seq_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -894,14 +915,14 @@ erret:
 
 /**************************************************
 *
-*    GBTagsetNew()
+*    GBCommentNew()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetPtr LIBCALL
-GBTagsetNew(void)
+GBCommentPtr LIBCALL
+GBCommentNew(void)
 {
-   GBTagsetPtr ptr = MemNew((size_t) sizeof(GBTagset));
+   GBCommentPtr ptr = MemNew((size_t) sizeof(GBComment));
 
    return ptr;
 
@@ -910,39 +931,37 @@ GBTagsetNew(void)
 
 /**************************************************
 *
-*    GBTagsetFree()
+*    GBCommentFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetPtr LIBCALL
-GBTagsetFree(GBTagsetPtr ptr)
+GBCommentPtr LIBCALL
+GBCommentFree(GBCommentPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> authority);
-   MemFree(ptr -> version);
-   MemFree(ptr -> url);
-   GBTagsFree(ptr -> tags);
+   MemFree(ptr -> type);
+   AsnGenericUserSeqOfFree(ptr -> paragraphs, (AsnOptFreeFunc) GBCommentParagraphFree);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBTagsetAsnRead()
+*    GBCommentAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetPtr LIBCALL
-GBTagsetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBCommentPtr LIBCALL
+GBCommentAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   GBTagsetPtr ptr;
+   GBCommentPtr ptr;
 
    if (! loaded)
    {
@@ -955,17 +974,17 @@ GBTagsetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBTagset ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBTAGSET);
+   if (orig == NULL) {         /* GBComment ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBCOMMENT);
    } else {
-      atp = AsnLinkType(orig, GBTAGSET);
+      atp = AsnLinkType(orig, GBCOMMENT);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = GBTagsetNew();
+   ptr = GBCommentNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -976,30 +995,180 @@ GBTagsetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == GBTAGSET_authority) {
+   if (atp == GBCOMMENT_type) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> authority = av.ptrvalue;
+      ptr -> type = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSET_version) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == GBCOMMENT_paragraphs) {
+      ptr -> paragraphs = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBCommentParagraphAsnRead, (AsnOptFreeFunc) GBCommentParagraphFree);
+      if (isError && ptr -> paragraphs == NULL) {
          goto erret;
       }
-      ptr -> version = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSET_url) {
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = GBCommentFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    GBCommentAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+GBCommentAsnWrite(GBCommentPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objgbseqAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, GBCOMMENT);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> type != NULL) {
+      av.ptrvalue = ptr -> type;
+      retval = AsnWrite(aip, GBCOMMENT_type,  &av);
+   }
+   AsnGenericUserSeqOfAsnWrite(ptr -> paragraphs, (AsnWriteFunc) GBCommentParagraphAsnWrite, aip, GBCOMMENT_paragraphs, GBCOMMENT_paragraphs_E);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    GBStrucCommentNew()
+*
+**************************************************/
+NLM_EXTERN 
+GBStrucCommentPtr LIBCALL
+GBStrucCommentNew(void)
+{
+   GBStrucCommentPtr ptr = MemNew((size_t) sizeof(GBStrucComment));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    GBStrucCommentFree()
+*
+**************************************************/
+NLM_EXTERN 
+GBStrucCommentPtr LIBCALL
+GBStrucCommentFree(GBStrucCommentPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> name);
+   AsnGenericUserSeqOfFree(ptr -> items, (AsnOptFreeFunc) GBStrucCommentItemFree);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    GBStrucCommentAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+GBStrucCommentPtr LIBCALL
+GBStrucCommentAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   GBStrucCommentPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objgbseqAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* GBStrucComment ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBSTRUCCOMMENT);
+   } else {
+      atp = AsnLinkType(orig, GBSTRUCCOMMENT);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = GBStrucCommentNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == GBSTRUCCOMMENT_name) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> url = av.ptrvalue;
+      ptr -> name = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSET_tags) {
-      ptr -> tags = GBTagsAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == GBSTRUCCOMMENT_items) {
+      ptr -> items = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBStrucCommentItemAsnRead, (AsnOptFreeFunc) GBStrucCommentItemFree);
+      if (isError && ptr -> items == NULL) {
          goto erret;
       }
       atp = AsnReadId(aip,amp, atp);
@@ -1016,7 +1185,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBTagsetFree(ptr);
+   ptr = GBStrucCommentFree(ptr);
    goto ret;
 }
 
@@ -1024,11 +1193,11 @@ erret:
 
 /**************************************************
 *
-*    GBTagsetAsnWrite()
+*    GBStrucCommentAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBTagsetAsnWrite(GBTagsetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBStrucCommentAsnWrite(GBStrucCommentPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1045,7 +1214,7 @@ GBTagsetAsnWrite(GBTagsetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBTAGSET);   /* link local tree */
+   atp = AsnLinkType(orig, GBSTRUCCOMMENT);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1055,23 +1224,11 @@ GBTagsetAsnWrite(GBTagsetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> authority != NULL) {
-      av.ptrvalue = ptr -> authority;
-      retval = AsnWrite(aip, GBTAGSET_authority,  &av);
-   }
-   if (ptr -> version != NULL) {
-      av.ptrvalue = ptr -> version;
-      retval = AsnWrite(aip, GBTAGSET_version,  &av);
-   }
-   if (ptr -> url != NULL) {
-      av.ptrvalue = ptr -> url;
-      retval = AsnWrite(aip, GBTAGSET_url,  &av);
-   }
-   if (ptr -> tags != NULL) {
-      if ( ! GBTagsAsnWrite(ptr -> tags, aip, GBTAGSET_tags)) {
-         goto erret;
-      }
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, GBSTRUCCOMMENT_name,  &av);
    }
+   AsnGenericUserSeqOfAsnWrite(ptr -> items, (AsnWriteFunc) GBStrucCommentItemAsnWrite, aip, GBSTRUCCOMMENT_items, GBSTRUCCOMMENT_items_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -1118,6 +1275,7 @@ GBFeatureFree(GBFeaturePtr ptr)
    AsnGenericUserSeqOfFree(ptr -> intervals, (AsnOptFreeFunc) GBIntervalFree);
    MemFree(ptr -> operator__);
    AsnGenericUserSeqOfFree(ptr -> quals, (AsnOptFreeFunc) GBQualifierFree);
+   AsnGenericUserSeqOfFree(ptr -> xrefs, (AsnOptFreeFunc) GBXrefFree);
    return MemFree(ptr);
 }
 
@@ -1220,6 +1378,13 @@ GBFeatureAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == GBFEATURE_xrefs) {
+      ptr -> xrefs = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBXrefAsnRead, (AsnOptFreeFunc) GBXrefFree);
+      if (isError && ptr -> xrefs == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -1291,6 +1456,7 @@ GBFeatureAsnWrite(GBFeaturePtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       retval = AsnWrite(aip, GBFEATURE_partial3,  &av);
    }
    AsnGenericUserSeqOfAsnWrite(ptr -> quals, (AsnWriteFunc) GBQualifierAsnWrite, aip, GBFEATURE_quals, GBFEATURE_quals_E);
+   AsnGenericUserSeqOfAsnWrite(ptr -> xrefs, (AsnWriteFunc) GBXrefAsnWrite, aip, GBFEATURE_xrefs, GBFEATURE_xrefs_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -1305,14 +1471,14 @@ erret:
 
 /**************************************************
 *
-*    GBXrefNew()
+*    GBFeatureSetNew()
 *
 **************************************************/
 NLM_EXTERN 
-GBXrefPtr LIBCALL
-GBXrefNew(void)
+GBFeatureSetPtr LIBCALL
+GBFeatureSetNew(void)
 {
-   GBXrefPtr ptr = MemNew((size_t) sizeof(GBXref));
+   GBFeatureSetPtr ptr = MemNew((size_t) sizeof(GBFeatureSet));
 
    return ptr;
 
@@ -1321,37 +1487,37 @@ GBXrefNew(void)
 
 /**************************************************
 *
-*    GBXrefFree()
+*    GBFeatureSetFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBXrefPtr LIBCALL
-GBXrefFree(GBXrefPtr ptr)
+GBFeatureSetPtr LIBCALL
+GBFeatureSetFree(GBFeatureSetPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> dbname);
-   MemFree(ptr -> id);
+   MemFree(ptr -> annot_source);
+   AsnGenericUserSeqOfFree(ptr -> features, (AsnOptFreeFunc) GBFeatureFree);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBXrefAsnRead()
+*    GBFeatureSetAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBXrefPtr LIBCALL
-GBXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBFeatureSetPtr LIBCALL
+GBFeatureSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   GBXrefPtr ptr;
+   GBFeatureSetPtr ptr;
 
    if (! loaded)
    {
@@ -1364,17 +1530,17 @@ GBXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBXref ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBXREF);
+   if (orig == NULL) {         /* GBFeatureSet ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBFEATURESET);
    } else {
-      atp = AsnLinkType(orig, GBXREF);
+      atp = AsnLinkType(orig, GBFEATURESET);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = GBXrefNew();
+   ptr = GBFeatureSetNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -1385,18 +1551,18 @@ GBXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == GBXREF_dbname) {
+   if (atp == GBFEATURESET_annot_source) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> dbname = av.ptrvalue;
+      ptr -> annot_source = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBXREF_id) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == GBFEATURESET_features) {
+      ptr -> features = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBFeatureAsnRead, (AsnOptFreeFunc) GBFeatureFree);
+      if (isError && ptr -> features == NULL) {
          goto erret;
       }
-      ptr -> id = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -1411,7 +1577,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBXrefFree(ptr);
+   ptr = GBFeatureSetFree(ptr);
    goto ret;
 }
 
@@ -1419,11 +1585,11 @@ erret:
 
 /**************************************************
 *
-*    GBXrefAsnWrite()
+*    GBFeatureSetAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBXrefAsnWrite(GBXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBFeatureSetAsnWrite(GBFeatureSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1440,7 +1606,7 @@ GBXrefAsnWrite(GBXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBXREF);   /* link local tree */
+   atp = AsnLinkType(orig, GBFEATURESET);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1450,14 +1616,11 @@ GBXrefAsnWrite(GBXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> dbname != NULL) {
-      av.ptrvalue = ptr -> dbname;
-      retval = AsnWrite(aip, GBXREF_dbname,  &av);
-   }
-   if (ptr -> id != NULL) {
-      av.ptrvalue = ptr -> id;
-      retval = AsnWrite(aip, GBXREF_id,  &av);
+   if (ptr -> annot_source != NULL) {
+      av.ptrvalue = ptr -> annot_source;
+      retval = AsnWrite(aip, GBFEATURESET_annot_source,  &av);
    }
+   AsnGenericUserSeqOfAsnWrite(ptr -> features, (AsnWriteFunc) GBFeatureAsnWrite, aip, GBFEATURESET_features, GBFEATURESET_features_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -1472,36 +1635,53 @@ erret:
 
 /**************************************************
 *
-*    GBTagsFree()
+*    GBAltSeqDataNew()
+*
+**************************************************/
+NLM_EXTERN 
+GBAltSeqDataPtr LIBCALL
+GBAltSeqDataNew(void)
+{
+   GBAltSeqDataPtr ptr = MemNew((size_t) sizeof(GBAltSeqData));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    GBAltSeqDataFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsPtr LIBCALL
-GBTagsFree(GBTagsPtr ptr)
+GBAltSeqDataPtr LIBCALL
+GBAltSeqDataFree(GBAltSeqDataPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   AsnGenericUserSeqOfFree(ptr,  (AsnOptFreeFunc) GBTagFree);
-   return NULL;
+   MemFree(ptr -> name);
+   AsnGenericUserSeqOfFree(ptr -> items, (AsnOptFreeFunc) GBAltSeqItemFree);
+   return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBTagsAsnRead()
+*    GBAltSeqDataAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsPtr LIBCALL
-GBTagsAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBAltSeqDataPtr LIBCALL
+GBAltSeqDataAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   GBTagsPtr ptr;
+   GBAltSeqDataPtr ptr;
 
    if (! loaded)
    {
@@ -1514,24 +1694,46 @@ GBTagsAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBTags ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBTAGS);
+   if (orig == NULL) {         /* GBAltSeqData ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBALTSEQDATA);
    } else {
-      atp = AsnLinkType(orig, GBTAGS);
+      atp = AsnLinkType(orig, GBALTSEQDATA);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
+   ptr = GBAltSeqDataNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   ptr  = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBTagAsnRead, (AsnOptFreeFunc) GBTagFree);
-   if (isError && ptr  == NULL) {
+   if (atp == GBALTSEQDATA_name) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
    }
+      ptr -> name = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQDATA_items) {
+      ptr -> items = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBAltSeqItemAsnRead, (AsnOptFreeFunc) GBAltSeqItemFree);
+      if (isError && ptr -> items == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
-
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
 
 ret:
    AsnUnlinkType(orig);       /* unlink local tree */
@@ -1539,7 +1741,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBTagsFree(ptr);
+   ptr = GBAltSeqDataFree(ptr);
    goto ret;
 }
 
@@ -1547,11 +1749,11 @@ erret:
 
 /**************************************************
 *
-*    GBTagsAsnWrite()
+*    GBAltSeqDataAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBTagsAsnWrite(GBTagsPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBAltSeqDataAsnWrite(GBAltSeqDataPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1568,13 +1770,24 @@ GBTagsAsnWrite(GBTagsPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBTAGS);   /* link local tree */
+   atp = AsnLinkType(orig, GBALTSEQDATA);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
 
    if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
-   retval = AsnGenericUserSeqOfAsnWrite(ptr , (AsnWriteFunc) GBTagAsnWrite, aip, atp, GBTAGS_E);
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, GBALTSEQDATA_name,  &av);
+   }
+   AsnGenericUserSeqOfAsnWrite(ptr -> items, (AsnWriteFunc) GBAltSeqItemAsnWrite, aip, GBALTSEQDATA_items, GBALTSEQDATA_items_E);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
    retval = TRUE;
 
 erret:
@@ -1586,14 +1799,14 @@ erret:
 
 /**************************************************
 *
-*    GBTagNew()
+*    GBXrefNew()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagPtr LIBCALL
-GBTagNew(void)
+GBXrefPtr LIBCALL
+GBXrefNew(void)
 {
-   GBTagPtr ptr = MemNew((size_t) sizeof(GBTag));
+   GBXrefPtr ptr = MemNew((size_t) sizeof(GBXref));
 
    return ptr;
 
@@ -1602,38 +1815,36 @@ GBTagNew(void)
 
 /**************************************************
 *
-*    GBTagFree()
+*    GBXrefFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagPtr LIBCALL
-GBTagFree(GBTagPtr ptr)
+GBXrefPtr LIBCALL
+GBXrefFree(GBXrefPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> name);
-   MemFree(ptr -> value);
-   MemFree(ptr -> unit);
+   MemFree(ptr -> dbname);
+   MemFree(ptr -> id);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBTagAsnRead()
+*    GBXrefAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagPtr LIBCALL
-GBTagAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBXrefPtr LIBCALL
+GBXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   GBTagPtr ptr;
+   GBXrefPtr ptr;
 
    if (! loaded)
    {
@@ -1646,17 +1857,17 @@ GBTagAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBTag ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBTAG);
+   if (orig == NULL) {         /* GBXref ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBXREF);
    } else {
-      atp = AsnLinkType(orig, GBTAG);
+      atp = AsnLinkType(orig, GBXREF);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = GBTagNew();
+   ptr = GBXrefNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -1667,25 +1878,18 @@ GBTagAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == GBTAG_name) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
-         goto erret;
-      }
-      ptr -> name = av.ptrvalue;
-      atp = AsnReadId(aip,amp, atp);
-   }
-   if (atp == GBTAG_value) {
+   if (atp == GBXREF_dbname) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> value = av.ptrvalue;
+      ptr -> dbname = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAG_unit) {
+   if (atp == GBXREF_id) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> unit = av.ptrvalue;
+      ptr -> id = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -1700,7 +1904,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBTagFree(ptr);
+   ptr = GBXrefFree(ptr);
    goto ret;
 }
 
@@ -1708,11 +1912,11 @@ erret:
 
 /**************************************************
 *
-*    GBTagAsnWrite()
+*    GBXrefAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBTagAsnWrite(GBTagPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBXrefAsnWrite(GBXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1729,7 +1933,7 @@ GBTagAsnWrite(GBTagPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBTAG);   /* link local tree */
+   atp = AsnLinkType(orig, GBXREF);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1739,17 +1943,13 @@ GBTagAsnWrite(GBTagPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> name != NULL) {
-      av.ptrvalue = ptr -> name;
-      retval = AsnWrite(aip, GBTAG_name,  &av);
-   }
-   if (ptr -> value != NULL) {
-      av.ptrvalue = ptr -> value;
-      retval = AsnWrite(aip, GBTAG_value,  &av);
+   if (ptr -> dbname != NULL) {
+      av.ptrvalue = ptr -> dbname;
+      retval = AsnWrite(aip, GBXREF_dbname,  &av);
    }
-   if (ptr -> unit != NULL) {
-      av.ptrvalue = ptr -> unit;
-      retval = AsnWrite(aip, GBTAG_unit,  &av);
+   if (ptr -> id != NULL) {
+      av.ptrvalue = ptr -> id;
+      retval = AsnWrite(aip, GBXREF_id,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -1765,14 +1965,14 @@ erret:
 
 /**************************************************
 *
-*    GBIntervalNew()
+*    GBCommentParagraphNew()
 *
 **************************************************/
 NLM_EXTERN 
-GBIntervalPtr LIBCALL
-GBIntervalNew(void)
+GBCommentParagraphPtr LIBCALL
+GBCommentParagraphNew(void)
 {
-   GBIntervalPtr ptr = MemNew((size_t) sizeof(GBInterval));
+   GBCommentParagraphPtr ptr = MemNew((size_t) sizeof(GBCommentParagraph));
 
    return ptr;
 
@@ -1781,36 +1981,36 @@ GBIntervalNew(void)
 
 /**************************************************
 *
-*    GBIntervalFree()
+*    GBCommentParagraphFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBIntervalPtr LIBCALL
-GBIntervalFree(GBIntervalPtr ptr)
+GBCommentParagraphPtr LIBCALL
+GBCommentParagraphFree(GBCommentParagraphPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> accession);
+   AsnGenericUserSeqOfFree(ptr -> items, (AsnOptFreeFunc) GBCommentItemFree);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBIntervalAsnRead()
+*    GBCommentParagraphAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBIntervalPtr LIBCALL
-GBIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBCommentParagraphPtr LIBCALL
+GBCommentParagraphAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   GBIntervalPtr ptr;
+   GBCommentParagraphPtr ptr;
 
    if (! loaded)
    {
@@ -1823,17 +2023,17 @@ GBIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBInterval ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBINTERVAL);
+   if (orig == NULL) {         /* GBCommentParagraph ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBCOMMENTPARAGRAPH);
    } else {
-      atp = AsnLinkType(orig, GBINTERVAL);
+      atp = AsnLinkType(orig, GBCOMMENTPARAGRAPH);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = GBIntervalNew();
+   ptr = GBCommentParagraphNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -1844,51 +2044,169 @@ GBIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == GBINTERVAL_from) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == GBCOMMENTPARAGRAPH_items) {
+      ptr -> items = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBCommentItemAsnRead, (AsnOptFreeFunc) GBCommentItemFree);
+      if (isError && ptr -> items == NULL) {
          goto erret;
       }
-      ptr -> from = av.intvalue;
-      ptr -> OBbits__ |= 1<<0;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBINTERVAL_to) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> to = av.intvalue;
-      ptr -> OBbits__ |= 1<<1;
-      atp = AsnReadId(aip,amp, atp);
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = GBCommentParagraphFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    GBCommentParagraphAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+GBCommentParagraphAsnWrite(GBCommentParagraphPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objgbseqAsnLoad()) {
+         return FALSE;
    }
-   if (atp == GBINTERVAL_point) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, GBCOMMENTPARAGRAPH);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
          goto erret;
       }
-      ptr -> point = av.intvalue;
-      ptr -> OBbits__ |= 1<<2;
-      atp = AsnReadId(aip,amp, atp);
+
+   AsnGenericUserSeqOfAsnWrite(ptr -> items, (AsnWriteFunc) GBCommentItemAsnWrite, aip, GBCOMMENTPARAGRAPH_items, GBCOMMENTPARAGRAPH_items_E);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
    }
-   if (atp == GBINTERVAL_iscomp) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    GBCommentItemNew()
+*
+**************************************************/
+NLM_EXTERN 
+GBCommentItemPtr LIBCALL
+GBCommentItemNew(void)
+{
+   GBCommentItemPtr ptr = MemNew((size_t) sizeof(GBCommentItem));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    GBCommentItemFree()
+*
+**************************************************/
+NLM_EXTERN 
+GBCommentItemPtr LIBCALL
+GBCommentItemFree(GBCommentItemPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> value);
+   MemFree(ptr -> url);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    GBCommentItemAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+GBCommentItemPtr LIBCALL
+GBCommentItemAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   GBCommentItemPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objgbseqAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* GBCommentItem ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBCOMMENTITEM);
+   } else {
+      atp = AsnLinkType(orig, GBCOMMENTITEM);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = GBCommentItemNew();
+   if (ptr == NULL) {
          goto erret;
       }
-      ptr -> iscomp = av.boolvalue;
-      ptr -> OBbits__ |= 1<<3;
-      atp = AsnReadId(aip,amp, atp);
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
    }
-   if (atp == GBINTERVAL_interbp) {
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == GBCOMMENTITEM_value) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> interbp = av.boolvalue;
-      ptr -> OBbits__ |= 1<<4;
+      ptr -> value = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBINTERVAL_accession) {
+   if (atp == GBCOMMENTITEM_url) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> accession = av.ptrvalue;
+      ptr -> url = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -1903,7 +2221,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBIntervalFree(ptr);
+   ptr = GBCommentItemFree(ptr);
    goto ret;
 }
 
@@ -1911,11 +2229,11 @@ erret:
 
 /**************************************************
 *
-*    GBIntervalAsnWrite()
+*    GBCommentItemAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBIntervalAsnWrite(GBIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBCommentItemAsnWrite(GBCommentItemPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1932,7 +2250,7 @@ GBIntervalAsnWrite(GBIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBINTERVAL);   /* link local tree */
+   atp = AsnLinkType(orig, GBCOMMENTITEM);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1942,24 +2260,13 @@ GBIntervalAsnWrite(GBIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> from || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> from;
-      retval = AsnWrite(aip, GBINTERVAL_from,  &av);
-   }
-   if (ptr -> to || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> to;
-      retval = AsnWrite(aip, GBINTERVAL_to,  &av);
-   }
-   if (ptr -> point || (ptr -> OBbits__ & (1<<2) )){   av.intvalue = ptr -> point;
-      retval = AsnWrite(aip, GBINTERVAL_point,  &av);
-   }
-   if (ptr -> iscomp || (ptr -> OBbits__ & (1<<3) )){   av.boolvalue = ptr -> iscomp;
-      retval = AsnWrite(aip, GBINTERVAL_iscomp,  &av);
-   }
-   if (ptr -> interbp || (ptr -> OBbits__ & (1<<4) )){   av.boolvalue = ptr -> interbp;
-      retval = AsnWrite(aip, GBINTERVAL_interbp,  &av);
+   if (ptr -> value != NULL) {
+      av.ptrvalue = ptr -> value;
+      retval = AsnWrite(aip, GBCOMMENTITEM_value,  &av);
    }
-   if (ptr -> accession != NULL) {
-      av.ptrvalue = ptr -> accession;
-      retval = AsnWrite(aip, GBINTERVAL_accession,  &av);
+   if (ptr -> url != NULL) {
+      av.ptrvalue = ptr -> url;
+      retval = AsnWrite(aip, GBCOMMENTITEM_url,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -1975,14 +2282,14 @@ erret:
 
 /**************************************************
 *
-*    GBQualifierNew()
+*    GBStrucCommentItemNew()
 *
 **************************************************/
 NLM_EXTERN 
-GBQualifierPtr LIBCALL
-GBQualifierNew(void)
+GBStrucCommentItemPtr LIBCALL
+GBStrucCommentItemNew(void)
 {
-   GBQualifierPtr ptr = MemNew((size_t) sizeof(GBQualifier));
+   GBStrucCommentItemPtr ptr = MemNew((size_t) sizeof(GBStrucCommentItem));
 
    return ptr;
 
@@ -1991,37 +2298,37 @@ GBQualifierNew(void)
 
 /**************************************************
 *
-*    GBQualifierFree()
+*    GBStrucCommentItemFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBQualifierPtr LIBCALL
-GBQualifierFree(GBQualifierPtr ptr)
+GBStrucCommentItemPtr LIBCALL
+GBStrucCommentItemFree(GBStrucCommentItemPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> name);
+   MemFree(ptr -> tag);
    MemFree(ptr -> value);
+   MemFree(ptr -> url);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBQualifierAsnRead()
+*    GBStrucCommentItemAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBQualifierPtr LIBCALL
-GBQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBStrucCommentItemPtr LIBCALL
+GBStrucCommentItemAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   GBQualifierPtr ptr;
+   GBStrucCommentItemPtr ptr;
 
    if (! loaded)
    {
@@ -2034,17 +2341,17 @@ GBQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBQualifier ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBQUALIFIER);
+   if (orig == NULL) {         /* GBStrucCommentItem ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBSTRUCCOMMENTITEM);
    } else {
-      atp = AsnLinkType(orig, GBQUALIFIER);
+      atp = AsnLinkType(orig, GBSTRUCCOMMENTITEM);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = GBQualifierNew();
+   ptr = GBStrucCommentItemNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -2055,20 +2362,27 @@ GBQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == GBQUALIFIER_name) {
+   if (atp == GBSTRUCCOMMENTITEM_tag) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> name = av.ptrvalue;
+      ptr -> tag = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBQUALIFIER_value) {
+   if (atp == GBSTRUCCOMMENTITEM_value) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
       ptr -> value = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == GBSTRUCCOMMENTITEM_url) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> url = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -2081,7 +2395,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBQualifierFree(ptr);
+   ptr = GBStrucCommentItemFree(ptr);
    goto ret;
 }
 
@@ -2089,11 +2403,11 @@ erret:
 
 /**************************************************
 *
-*    GBQualifierAsnWrite()
+*    GBStrucCommentItemAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBQualifierAsnWrite(GBQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBStrucCommentItemAsnWrite(GBStrucCommentItemPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2110,7 +2424,7 @@ GBQualifierAsnWrite(GBQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBQUALIFIER);   /* link local tree */
+   atp = AsnLinkType(orig, GBSTRUCCOMMENTITEM);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -2120,13 +2434,17 @@ GBQualifierAsnWrite(GBQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> name != NULL) {
-      av.ptrvalue = ptr -> name;
-      retval = AsnWrite(aip, GBQUALIFIER_name,  &av);
+   if (ptr -> tag != NULL) {
+      av.ptrvalue = ptr -> tag;
+      retval = AsnWrite(aip, GBSTRUCCOMMENTITEM_tag,  &av);
    }
    if (ptr -> value != NULL) {
       av.ptrvalue = ptr -> value;
-      retval = AsnWrite(aip, GBQUALIFIER_value,  &av);
+      retval = AsnWrite(aip, GBSTRUCCOMMENTITEM_value,  &av);
+   }
+   if (ptr -> url != NULL) {
+      av.ptrvalue = ptr -> url;
+      retval = AsnWrite(aip, GBSTRUCCOMMENTITEM_url,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -2142,14 +2460,14 @@ erret:
 
 /**************************************************
 *
-*    GBTagsetRulesNew()
+*    GBIntervalNew()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetRulesPtr LIBCALL
-GBTagsetRulesNew(void)
+GBIntervalPtr LIBCALL
+GBIntervalNew(void)
 {
-   GBTagsetRulesPtr ptr = MemNew((size_t) sizeof(GBTagsetRules));
+   GBIntervalPtr ptr = MemNew((size_t) sizeof(GBInterval));
 
    return ptr;
 
@@ -2158,40 +2476,35 @@ GBTagsetRulesNew(void)
 
 /**************************************************
 *
-*    GBTagsetRulesFree()
+*    GBIntervalFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetRulesPtr LIBCALL
-GBTagsetRulesFree(GBTagsetRulesPtr ptr)
+GBIntervalPtr LIBCALL
+GBIntervalFree(GBIntervalPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> authority);
-   MemFree(ptr -> version);
-   GBTagNamesFree(ptr -> mandatorytags);
-   GBTagNamesFree(ptr -> optionaltags);
-   GBTagNamesFree(ptr -> uniquetags);
+   MemFree(ptr -> accession);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBTagsetRulesAsnRead()
+*    GBIntervalAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetRulesPtr LIBCALL
-GBTagsetRulesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBIntervalPtr LIBCALL
+GBIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   GBTagsetRulesPtr ptr;
+   GBIntervalPtr ptr;
 
    if (! loaded)
    {
@@ -2204,17 +2517,17 @@ GBTagsetRulesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBTagsetRules ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBTAGSETRULES);
+   if (orig == NULL) {         /* GBInterval ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBINTERVAL);
    } else {
-      atp = AsnLinkType(orig, GBTAGSETRULES);
+      atp = AsnLinkType(orig, GBINTERVAL);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = GBTagsetRulesNew();
+   ptr = GBIntervalNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -2225,47 +2538,51 @@ GBTagsetRulesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == GBTAGSETRULES_authority) {
+   if (atp == GBINTERVAL_from) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> authority = av.ptrvalue;
+      ptr -> from = av.intvalue;
+      ptr -> OBbits__ |= 1<<0;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSETRULES_version) {
+   if (atp == GBINTERVAL_to) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> version = av.ptrvalue;
+      ptr -> to = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSETRULES_mandatorytags) {
-      ptr -> mandatorytags = GBTagNamesAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == GBINTERVAL_point) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
+      ptr -> point = av.intvalue;
+      ptr -> OBbits__ |= 1<<2;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSETRULES_optionaltags) {
-      ptr -> optionaltags = GBTagNamesAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == GBINTERVAL_iscomp) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
+      ptr -> iscomp = av.boolvalue;
+      ptr -> OBbits__ |= 1<<3;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSETRULES_uniquetags) {
-      ptr -> uniquetags = GBTagNamesAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == GBINTERVAL_interbp) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
+      ptr -> interbp = av.boolvalue;
+      ptr -> OBbits__ |= 1<<4;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == GBTAGSETRULES_extensible) {
+   if (atp == GBINTERVAL_accession) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> extensible = av.boolvalue;
-      ptr -> OBbits__ |= 1<<0;
+      ptr -> accession = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -2280,7 +2597,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBTagsetRulesFree(ptr);
+   ptr = GBIntervalFree(ptr);
    goto ret;
 }
 
@@ -2288,11 +2605,11 @@ erret:
 
 /**************************************************
 *
-*    GBTagsetRulesAsnWrite()
+*    GBIntervalAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBTagsetRulesAsnWrite(GBTagsetRulesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBIntervalAsnWrite(GBIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2309,7 +2626,7 @@ GBTagsetRulesAsnWrite(GBTagsetRulesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBTAGSETRULES);   /* link local tree */
+   atp = AsnLinkType(orig, GBINTERVAL);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -2319,31 +2636,24 @@ GBTagsetRulesAsnWrite(GBTagsetRulesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> authority != NULL) {
-      av.ptrvalue = ptr -> authority;
-      retval = AsnWrite(aip, GBTAGSETRULES_authority,  &av);
-   }
-   if (ptr -> version != NULL) {
-      av.ptrvalue = ptr -> version;
-      retval = AsnWrite(aip, GBTAGSETRULES_version,  &av);
-   }
-   if (ptr -> mandatorytags != NULL) {
-      if ( ! GBTagNamesAsnWrite(ptr -> mandatorytags, aip, GBTAGSETRULES_mandatorytags)) {
-         goto erret;
-      }
+   if (ptr -> from || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> from;
+      retval = AsnWrite(aip, GBINTERVAL_from,  &av);
    }
-   if (ptr -> optionaltags != NULL) {
-      if ( ! GBTagNamesAsnWrite(ptr -> optionaltags, aip, GBTAGSETRULES_optionaltags)) {
-         goto erret;
+   if (ptr -> to || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> to;
+      retval = AsnWrite(aip, GBINTERVAL_to,  &av);
       }
+   if (ptr -> point || (ptr -> OBbits__ & (1<<2) )){   av.intvalue = ptr -> point;
+      retval = AsnWrite(aip, GBINTERVAL_point,  &av);
    }
-   if (ptr -> uniquetags != NULL) {
-      if ( ! GBTagNamesAsnWrite(ptr -> uniquetags, aip, GBTAGSETRULES_uniquetags)) {
-         goto erret;
+   if (ptr -> iscomp || (ptr -> OBbits__ & (1<<3) )){   av.boolvalue = ptr -> iscomp;
+      retval = AsnWrite(aip, GBINTERVAL_iscomp,  &av);
       }
+   if (ptr -> interbp || (ptr -> OBbits__ & (1<<4) )){   av.boolvalue = ptr -> interbp;
+      retval = AsnWrite(aip, GBINTERVAL_interbp,  &av);
    }
-   if (ptr -> extensible || (ptr -> OBbits__ & (1<<0) )){   av.boolvalue = ptr -> extensible;
-      retval = AsnWrite(aip, GBTAGSETRULES_extensible,  &av);
+   if (ptr -> accession != NULL) {
+      av.ptrvalue = ptr -> accession;
+      retval = AsnWrite(aip, GBINTERVAL_accession,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -2359,36 +2669,52 @@ erret:
 
 /**************************************************
 *
-*    GBTagNamesFree()
+*    GBQualifierNew()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagNamesPtr LIBCALL
-GBTagNamesFree(GBTagNamesPtr ptr)
+GBQualifierPtr LIBCALL
+GBQualifierNew(void)
+{
+   GBQualifierPtr ptr = MemNew((size_t) sizeof(GBQualifier));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    GBQualifierFree()
+*
+**************************************************/
+NLM_EXTERN 
+GBQualifierPtr LIBCALL
+GBQualifierFree(GBQualifierPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   AsnGenericBaseSeqOfFree(ptr,ASNCODE_PTRVAL_SLOT);
-   return NULL;
+   MemFree(ptr -> name);
+   MemFree(ptr -> value);
+   return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBTagNamesAsnRead()
+*    GBQualifierAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagNamesPtr LIBCALL
-GBTagNamesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBQualifierPtr LIBCALL
+GBQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   GBTagNamesPtr ptr;
+   GBQualifierPtr ptr;
 
    if (! loaded)
    {
@@ -2401,24 +2727,46 @@ GBTagNamesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBTagNames ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBTAGNAMES);
+   if (orig == NULL) {         /* GBQualifier ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBQUALIFIER);
    } else {
-      atp = AsnLinkType(orig, GBTAGNAMES);
+      atp = AsnLinkType(orig, GBQUALIFIER);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
+   ptr = GBQualifierNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   ptr  = AsnGenericBaseSeqOfAsnRead(aip, amp, atp, ASNCODE_PTRVAL_SLOT, &isError);
-   if (isError && ptr  == NULL) {
+   if (atp == GBQUALIFIER_name) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
    }
+      ptr -> name = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBQUALIFIER_value) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> value = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
 
-
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
 
 ret:
    AsnUnlinkType(orig);       /* unlink local tree */
@@ -2426,7 +2774,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBTagNamesFree(ptr);
+   ptr = GBQualifierFree(ptr);
    goto ret;
 }
 
@@ -2434,11 +2782,11 @@ erret:
 
 /**************************************************
 *
-*    GBTagNamesAsnWrite()
+*    GBQualifierAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBTagNamesAsnWrite(GBTagNamesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBQualifierAsnWrite(GBQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2455,13 +2803,27 @@ GBTagNamesAsnWrite(GBTagNamesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBTAGNAMES);   /* link local tree */
+   atp = AsnLinkType(orig, GBQUALIFIER);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
 
    if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
-   retval = AsnGenericBaseSeqOfAsnWrite(ptr, ASNCODE_PTRVAL_SLOT, aip, atp, GBTAGNAMES_E);
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, GBQUALIFIER_name,  &av);
+   }
+   if (ptr -> value != NULL) {
+      av.ptrvalue = ptr -> value;
+      retval = AsnWrite(aip, GBQUALIFIER_value,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
    retval = TRUE;
 
 erret:
@@ -2473,36 +2835,57 @@ erret:
 
 /**************************************************
 *
-*    GBTagsetRuleSetFree()
+*    GBAltSeqItemNew()
+*
+**************************************************/
+NLM_EXTERN 
+GBAltSeqItemPtr LIBCALL
+GBAltSeqItemNew(void)
+{
+   GBAltSeqItemPtr ptr = MemNew((size_t) sizeof(GBAltSeqItem));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    GBAltSeqItemFree()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetRuleSetPtr LIBCALL
-GBTagsetRuleSetFree(GBTagsetRuleSetPtr ptr)
+GBAltSeqItemPtr LIBCALL
+GBAltSeqItemFree(GBAltSeqItemPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   AsnGenericUserSeqOfFree(ptr,  (AsnOptFreeFunc) GBTagsetRulesFree);
-   return NULL;
+   GBIntervalFree(ptr -> interval);
+   MemFree(ptr -> gap_type);
+   MemFree(ptr -> gap_linkage);
+   MemFree(ptr -> gap_comment);
+   MemFree(ptr -> first_accn);
+   MemFree(ptr -> last_accn);
+   MemFree(ptr -> value);
+   return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    GBTagsetRuleSetAsnRead()
+*    GBAltSeqItemAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-GBTagsetRuleSetPtr LIBCALL
-GBTagsetRuleSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+GBAltSeqItemPtr LIBCALL
+GBAltSeqItemAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   GBTagsetRuleSetPtr ptr;
+   GBAltSeqItemPtr ptr;
 
    if (! loaded)
    {
@@ -2515,24 +2898,97 @@ GBTagsetRuleSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* GBTagsetRuleSet ::= (self contained) */
-      atp = AsnReadId(aip, amp, GBTAGSETRULESET);
+   if (orig == NULL) {         /* GBAltSeqItem ::= (self contained) */
+      atp = AsnReadId(aip, amp, GBALTSEQITEM);
    } else {
-      atp = AsnLinkType(orig, GBTAGSETRULESET);
+      atp = AsnLinkType(orig, GBALTSEQITEM);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
+   ptr = GBAltSeqItemNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   ptr  = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) GBTagsetRulesAsnRead, (AsnOptFreeFunc) GBTagsetRulesFree);
-   if (isError && ptr  == NULL) {
+   if (atp == GBALTSEQITEM_interval) {
+      ptr -> interval = GBIntervalAsnRead(aip, atp);
+      if (aip -> io_failure) {
       goto erret;
    }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_isgap) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> isgap = av.boolvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_gap_length) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_length = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_gap_type) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_type = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_gap_linkage) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_linkage = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_gap_comment) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_comment = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_first_accn) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> first_accn = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_last_accn) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> last_accn = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == GBALTSEQITEM_value) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> value = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
 
-
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
 
 ret:
    AsnUnlinkType(orig);       /* unlink local tree */
@@ -2540,7 +2996,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = GBTagsetRuleSetFree(ptr);
+   ptr = GBAltSeqItemFree(ptr);
    goto ret;
 }
 
@@ -2548,11 +3004,11 @@ erret:
 
 /**************************************************
 *
-*    GBTagsetRuleSetAsnWrite()
+*    GBAltSeqItemAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-GBTagsetRuleSetAsnWrite(GBTagsetRuleSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+GBAltSeqItemAsnWrite(GBAltSeqItemPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2569,13 +3025,54 @@ GBTagsetRuleSetAsnWrite(GBTagsetRuleSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, GBTAGSETRULESET);   /* link local tree */
+   atp = AsnLinkType(orig, GBALTSEQITEM);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
 
    if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
-   retval = AsnGenericUserSeqOfAsnWrite(ptr , (AsnWriteFunc) GBTagsetRulesAsnWrite, aip, atp, GBTAGSETRULESET_E);
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> interval != NULL) {
+      if ( ! GBIntervalAsnWrite(ptr -> interval, aip, GBALTSEQITEM_interval)) {
+         goto erret;
+      }
+   }
+   if (ptr -> isgap || (ptr -> OBbits__ & (1<<0) )){   av.boolvalue = ptr -> isgap;
+      retval = AsnWrite(aip, GBALTSEQITEM_isgap,  &av);
+   }
+   if (ptr -> gap_length || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> gap_length;
+      retval = AsnWrite(aip, GBALTSEQITEM_gap_length,  &av);
+   }
+   if (ptr -> gap_type != NULL) {
+      av.ptrvalue = ptr -> gap_type;
+      retval = AsnWrite(aip, GBALTSEQITEM_gap_type,  &av);
+   }
+   if (ptr -> gap_linkage != NULL) {
+      av.ptrvalue = ptr -> gap_linkage;
+      retval = AsnWrite(aip, GBALTSEQITEM_gap_linkage,  &av);
+   }
+   if (ptr -> gap_comment != NULL) {
+      av.ptrvalue = ptr -> gap_comment;
+      retval = AsnWrite(aip, GBALTSEQITEM_gap_comment,  &av);
+   }
+   if (ptr -> first_accn != NULL) {
+      av.ptrvalue = ptr -> first_accn;
+      retval = AsnWrite(aip, GBALTSEQITEM_first_accn,  &av);
+   }
+   if (ptr -> last_accn != NULL) {
+      av.ptrvalue = ptr -> last_accn;
+      retval = AsnWrite(aip, GBALTSEQITEM_last_accn,  &av);
+   }
+   if (ptr -> value != NULL) {
+      av.ptrvalue = ptr -> value;
+      retval = AsnWrite(aip, GBALTSEQITEM_value,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
    retval = TRUE;
 
 erret:
diff --git a/object/objgbseq.h b/object/objgbseq.h
index b5be0da..11e75a6 100644
--- a/object/objgbseq.h
+++ b/object/objgbseq.h
@@ -17,7 +17,7 @@ extern "C" { /* } */
 /**************************************************
 *
 *    Generated objects for Module NCBI-GBSeq
-*    Generated using ASNCODE Revision: 6.16 at Jan 15, 2009  2:16 PM
+*    Generated using ASNCODE Revision: 6.17 at May 26, 2010 12:37 PM
 *
 **************************************************/
 
@@ -77,13 +77,16 @@ typedef struct struct_GBSeq {
    CharPtr   taxonomy;
    struct struct_GBReference PNTR   references;
    CharPtr   comment;
-   struct struct_GBTagset PNTR   tagset;
+   struct struct_GBComment PNTR   comment_set;
+   struct struct_GBStrucComment PNTR   struc_comments;
    CharPtr   primary;
    CharPtr   source_db;
    CharPtr   database_reference;
    struct struct_GBFeature PNTR   feature_table;
+   struct struct_GBFeatureSet PNTR   feature_set;
    CharPtr   sequence;
    CharPtr   contig;
+   struct struct_GBAltSeqData PNTR   alt_seq;
 } GBSeq, PNTR GBSeqPtr;
 
 
@@ -125,22 +128,41 @@ NLM_EXTERN Boolean LIBCALL GBReferenceAsnWrite PROTO (( GBReferencePtr , AsnIoPt
 
 /**************************************************
 *
-*    GBTagset
+*    GBComment
 *
 **************************************************/
-typedef struct struct_GBTagset {
+typedef struct struct_GBComment {
+   struct struct_GBComment PNTR next;
    Uint4 OBbits__;
-   CharPtr   authority;
-   CharPtr   version;
-   CharPtr   url;
-   struct struct_GBTag PNTR   tags;
-} GBTagset, PNTR GBTagsetPtr;
+   CharPtr   type;
+   struct struct_GBCommentParagraph PNTR   paragraphs;
+} GBComment, PNTR GBCommentPtr;
 
 
-NLM_EXTERN GBTagsetPtr LIBCALL GBTagsetFree PROTO ((GBTagsetPtr ));
-NLM_EXTERN GBTagsetPtr LIBCALL GBTagsetNew PROTO (( void ));
-NLM_EXTERN GBTagsetPtr LIBCALL GBTagsetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL GBTagsetAsnWrite PROTO (( GBTagsetPtr , AsnIoPtr, AsnTypePtr));
+NLM_EXTERN GBCommentPtr LIBCALL GBCommentFree PROTO ((GBCommentPtr ));
+NLM_EXTERN GBCommentPtr LIBCALL GBCommentNew PROTO (( void ));
+NLM_EXTERN GBCommentPtr LIBCALL GBCommentAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBCommentAsnWrite PROTO (( GBCommentPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    GBStrucComment
+*
+**************************************************/
+typedef struct struct_GBStrucComment {
+   struct struct_GBStrucComment PNTR next;
+   Uint4 OBbits__;
+   CharPtr   name;
+   struct struct_GBStrucCommentItem PNTR   items;
+} GBStrucComment, PNTR GBStrucCommentPtr;
+
+
+NLM_EXTERN GBStrucCommentPtr LIBCALL GBStrucCommentFree PROTO ((GBStrucCommentPtr ));
+NLM_EXTERN GBStrucCommentPtr LIBCALL GBStrucCommentNew PROTO (( void ));
+NLM_EXTERN GBStrucCommentPtr LIBCALL GBStrucCommentAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBStrucCommentAsnWrite PROTO (( GBStrucCommentPtr , AsnIoPtr, AsnTypePtr));
 
 
 
@@ -163,6 +185,7 @@ typedef struct struct_GBFeature {
 
    Uint1   partial3;
    struct struct_GBQualifier PNTR   quals;
+   struct struct_GBXref PNTR   xrefs;
 } GBFeature, PNTR GBFeaturePtr;
 
 
@@ -175,6 +198,46 @@ NLM_EXTERN Boolean LIBCALL GBFeatureAsnWrite PROTO (( GBFeaturePtr , AsnIoPtr, A
 
 /**************************************************
 *
+*    GBFeatureSet
+*
+**************************************************/
+typedef struct struct_GBFeatureSet {
+   struct struct_GBFeatureSet PNTR next;
+   Uint4 OBbits__;
+   CharPtr   annot_source;
+   struct struct_GBFeature PNTR   features;
+} GBFeatureSet, PNTR GBFeatureSetPtr;
+
+
+NLM_EXTERN GBFeatureSetPtr LIBCALL GBFeatureSetFree PROTO ((GBFeatureSetPtr ));
+NLM_EXTERN GBFeatureSetPtr LIBCALL GBFeatureSetNew PROTO (( void ));
+NLM_EXTERN GBFeatureSetPtr LIBCALL GBFeatureSetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBFeatureSetAsnWrite PROTO (( GBFeatureSetPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    GBAltSeqData
+*
+**************************************************/
+typedef struct struct_GBAltSeqData {
+   struct struct_GBAltSeqData PNTR next;
+   Uint4 OBbits__;
+   CharPtr   name;
+   struct struct_GBAltSeqItem PNTR   items;
+} GBAltSeqData, PNTR GBAltSeqDataPtr;
+
+
+NLM_EXTERN GBAltSeqDataPtr LIBCALL GBAltSeqDataFree PROTO ((GBAltSeqDataPtr ));
+NLM_EXTERN GBAltSeqDataPtr LIBCALL GBAltSeqDataNew PROTO (( void ));
+NLM_EXTERN GBAltSeqDataPtr LIBCALL GBAltSeqDataAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBAltSeqDataAsnWrite PROTO (( GBAltSeqDataPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
 *    GBXref
 *
 **************************************************/
@@ -195,42 +258,61 @@ NLM_EXTERN Boolean LIBCALL GBXrefAsnWrite PROTO (( GBXrefPtr , AsnIoPtr, AsnType
 
 /**************************************************
 *
-*    GBTags
+*    GBCommentParagraph
 *
 **************************************************/
-typedef struct struct_GBTag GBTags;
-typedef struct struct_GBTag PNTR GBTagsPtr;
-#define GBTagsNew() GBTagNew() 
+typedef struct struct_GBCommentParagraph {
+   struct struct_GBCommentParagraph PNTR next;
+   Uint4 OBbits__;
+   struct struct_GBCommentItem PNTR   items;
+} GBCommentParagraph, PNTR GBCommentParagraphPtr;
 
-#ifdef NLM_GENERATED_CODE_PROTO
 
-NLM_EXTERN GBTagsPtr LIBCALL GBTagsFree PROTO ((GBTagsPtr ));
-NLM_EXTERN GBTagsPtr LIBCALL GBTagsNew PROTO (( void ));
-NLM_EXTERN GBTagsPtr LIBCALL GBTagsAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL GBTagsAsnWrite PROTO (( GBTagsPtr , AsnIoPtr, AsnTypePtr));
+NLM_EXTERN GBCommentParagraphPtr LIBCALL GBCommentParagraphFree PROTO ((GBCommentParagraphPtr ));
+NLM_EXTERN GBCommentParagraphPtr LIBCALL GBCommentParagraphNew PROTO (( void ));
+NLM_EXTERN GBCommentParagraphPtr LIBCALL GBCommentParagraphAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBCommentParagraphAsnWrite PROTO (( GBCommentParagraphPtr , AsnIoPtr, AsnTypePtr));
 
-#endif /* NLM_GENERATED_CODE_PROTO */
+
+
+/**************************************************
+*
+*    GBCommentItem
+*
+**************************************************/
+typedef struct struct_GBCommentItem {
+   struct struct_GBCommentItem PNTR next;
+   Uint4 OBbits__;
+   CharPtr   value;
+   CharPtr   url;
+} GBCommentItem, PNTR GBCommentItemPtr;
+
+
+NLM_EXTERN GBCommentItemPtr LIBCALL GBCommentItemFree PROTO ((GBCommentItemPtr ));
+NLM_EXTERN GBCommentItemPtr LIBCALL GBCommentItemNew PROTO (( void ));
+NLM_EXTERN GBCommentItemPtr LIBCALL GBCommentItemAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBCommentItemAsnWrite PROTO (( GBCommentItemPtr , AsnIoPtr, AsnTypePtr));
 
 
 
 /**************************************************
 *
-*    GBTag
+*    GBStrucCommentItem
 *
 **************************************************/
-typedef struct struct_GBTag {
-   struct struct_GBTag PNTR next;
+typedef struct struct_GBStrucCommentItem {
+   struct struct_GBStrucCommentItem PNTR next;
    Uint4 OBbits__;
-   CharPtr   name;
+   CharPtr   tag;
    CharPtr   value;
-   CharPtr   unit;
-} GBTag, PNTR GBTagPtr;
+   CharPtr   url;
+} GBStrucCommentItem, PNTR GBStrucCommentItemPtr;
 
 
-NLM_EXTERN GBTagPtr LIBCALL GBTagFree PROTO ((GBTagPtr ));
-NLM_EXTERN GBTagPtr LIBCALL GBTagNew PROTO (( void ));
-NLM_EXTERN GBTagPtr LIBCALL GBTagAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL GBTagAsnWrite PROTO (( GBTagPtr , AsnIoPtr, AsnTypePtr));
+NLM_EXTERN GBStrucCommentItemPtr LIBCALL GBStrucCommentItemFree PROTO ((GBStrucCommentItemPtr ));
+NLM_EXTERN GBStrucCommentItemPtr LIBCALL GBStrucCommentItemNew PROTO (( void ));
+NLM_EXTERN GBStrucCommentItemPtr LIBCALL GBStrucCommentItemAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBStrucCommentItemAsnWrite PROTO (( GBStrucCommentItemPtr , AsnIoPtr, AsnTypePtr));
 
 
 
@@ -290,67 +372,32 @@ NLM_EXTERN Boolean LIBCALL GBQualifierAsnWrite PROTO (( GBQualifierPtr , AsnIoPt
 
 /**************************************************
 *
-*    GBTagsetRules
+*    GBAltSeqItem
 *
 **************************************************/
-typedef struct struct_GBTagsetRules {
-   struct struct_GBTagsetRules PNTR next;
+typedef struct struct_GBAltSeqItem {
+   struct struct_GBAltSeqItem PNTR next;
    Uint4 OBbits__;
-   CharPtr   authority;
-   CharPtr   version;
-   ValNodePtr   mandatorytags;
-   ValNodePtr   optionaltags;
-   ValNodePtr   uniquetags;
-#define OB__GBTagsetRules_extensible 0
-
-   Uint1   extensible;
-} GBTagsetRules, PNTR GBTagsetRulesPtr;
-
-
-NLM_EXTERN GBTagsetRulesPtr LIBCALL GBTagsetRulesFree PROTO ((GBTagsetRulesPtr ));
-NLM_EXTERN GBTagsetRulesPtr LIBCALL GBTagsetRulesNew PROTO (( void ));
-NLM_EXTERN GBTagsetRulesPtr LIBCALL GBTagsetRulesAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL GBTagsetRulesAsnWrite PROTO (( GBTagsetRulesPtr , AsnIoPtr, AsnTypePtr));
-
-
-
-/**************************************************
-*
-*    GBTagNames
-*
-**************************************************/
-typedef ValNode GBTagNames;
-typedef ValNodePtr GBTagNamesPtr;
-#define GBTagNamesNew() ValNodeNew(NULL) 
-
-#ifdef NLM_GENERATED_CODE_PROTO
-
-NLM_EXTERN GBTagNamesPtr LIBCALL GBTagNamesFree PROTO ((GBTagNamesPtr ));
-NLM_EXTERN GBTagNamesPtr LIBCALL GBTagNamesNew PROTO (( void ));
-NLM_EXTERN GBTagNamesPtr LIBCALL GBTagNamesAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL GBTagNamesAsnWrite PROTO (( GBTagNamesPtr , AsnIoPtr, AsnTypePtr));
-
-#endif /* NLM_GENERATED_CODE_PROTO */
-
-
-
-/**************************************************
-*
-*    GBTagsetRuleSet
-*
-**************************************************/
-typedef struct struct_GBTagsetRules GBTagsetRuleSet;
-typedef struct struct_GBTagsetRules PNTR GBTagsetRuleSetPtr;
-#define GBTagsetRuleSetNew() GBTagsetRulesNew() 
-
-#ifdef NLM_GENERATED_CODE_PROTO
+   struct struct_GBInterval PNTR   interval;
+#define OB__GBAltSeqItem_isgap 0
+
+   Uint1   isgap;
+#define OB__GBAltSeqItem_gap_length 1
+
+   Int4   gap_length;
+   CharPtr   gap_type;
+   CharPtr   gap_linkage;
+   CharPtr   gap_comment;
+   CharPtr   first_accn;
+   CharPtr   last_accn;
+   CharPtr   value;
+} GBAltSeqItem, PNTR GBAltSeqItemPtr;
 
-NLM_EXTERN GBTagsetRuleSetPtr LIBCALL GBTagsetRuleSetFree PROTO ((GBTagsetRuleSetPtr ));
-NLM_EXTERN GBTagsetRuleSetPtr LIBCALL GBTagsetRuleSetNew PROTO (( void ));
-NLM_EXTERN GBTagsetRuleSetPtr LIBCALL GBTagsetRuleSetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL GBTagsetRuleSetAsnWrite PROTO (( GBTagsetRuleSetPtr , AsnIoPtr, AsnTypePtr));
 
-#endif /* NLM_GENERATED_CODE_PROTO */
+NLM_EXTERN GBAltSeqItemPtr LIBCALL GBAltSeqItemFree PROTO ((GBAltSeqItemPtr ));
+NLM_EXTERN GBAltSeqItemPtr LIBCALL GBAltSeqItemNew PROTO (( void ));
+NLM_EXTERN GBAltSeqItemPtr LIBCALL GBAltSeqItemAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL GBAltSeqItemAsnWrite PROTO (( GBAltSeqItemPtr , AsnIoPtr, AsnTypePtr));
 
 #ifdef __cplusplus
 /* { */ }
diff --git a/object/objgen.c b/object/objgen.c
index 86ef2e9..b02d528 100644
--- a/object/objgen.c
+++ b/object/objgen.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 1/1/91
 *
-* $Revision: 6.16 $
+* $Revision: 6.17 $
 *
 * File Description:  Object manager for module NCBI-General
 *
@@ -42,77 +42,6 @@
 *                      (because it cannot be exported from ncbitime.c when 
 *                      it is linked as a DLL).
 *
-* $Log: objgen.c,v $
-* Revision 6.16  2008/12/30 19:58:39  bollin
-* corrected crash bug in DatePrint when month exceeds 12 (an error condition)
-*
-* Revision 6.15  2008/09/10 15:22:46  bollin
-* Added DbtagMatchEx and ObjectIdMatchEx, which are optionally case sensitive or case insensitive.
-*
-* Revision 6.14  2008/01/25 15:24:21  kans
-* in UserFieldAsnRead, finished implementing ints, reals, oss as list, does not need num in advance
-*
-* Revision 6.13  2008/01/24 23:05:55  kans
-*  User-field.strs stores strings as list, does not need num supplied in advance - have not done ints, reals, oss yet
-*
-* Revision 6.12  2005/05/18 17:30:16  bollin
-* added NameStdMatch and PersonIdMatch functions
-*
-* Revision 6.11  2004/04/01 13:43:08  lavr
-* Spell "occurred", "occurrence", and "occurring"
-*
-* Revision 6.10  2002/07/23 21:47:18  kans
-* label function for pid choice 5 consortium
-*
-* Revision 6.9  2002/07/22 19:56:49  kans
-* added support for PERSON_ID_Consortium
-*
-* Revision 6.8  2000/01/20 17:04:27  beloslyu
-* new function DateClean to properly clean the date was added
-*
-* Revision 6.7  2000/01/20 15:13:16  ostell
-* added hour/minute/second fields to Date
-* added DateTimeCurr()
-*
-* Revision 6.6  1999/11/03 17:58:26  kans
-* added SeqDescrAddPointer
-*
-* Revision 6.5  1999/10/05 17:24:14  kans
-* added SeqDescrAdd
-*
-* Revision 6.4  1999/09/28 14:56:00  kans
-* rename ObjValNodeNew to SeqDescrNew
-*
-* Revision 6.3  1999/09/23 00:07:45  kans
-* ObjValNodeNew implemented
-*
-* Revision 6.2  1998/08/24 18:28:04  kans
-* removed solaris -v -fd warnings
-*
-* Revision 6.1  1998/08/17 23:05:00  kans
-* user object asn read needed to set choices 11 and 12
-*
-* Revision 6.0  1997/08/25 18:49:56  madden
-* Revision changed to 6.0
-*
-* Revision 4.3  1997/06/19 18:41:23  vakatov
-* [WIN32,MSVC++]  Adopted for the "NCBIOBJ.LIB" DLL'ization
-*
-* Revision 4.2  1997/03/18 15:27:53  ostell
-* made DbtagMatch and ObjectIdMatch case insensitive
-*
- * Revision 4.1  1997/01/06  21:38:30  vakatov
- * Removed local(static) NCBI_months[12] -- use that from the "ncbitime.[ch]"
- *
- * Revision 4.0  1995/07/26  13:48:06  ostell
- * force revision to 4.0
- *
- * Revision 3.4  1995/05/15  21:22:00  ostell
- * added Log line
- *
-*
-*
-*
 * ==========================================================================
 */
 #include <asngen.h>        /* the AsnTool header */
@@ -746,6 +675,58 @@ NLM_EXTERN Int2 LIBCALL DateCheck (DatePtr dp)
 	return 0;
 }
 
+NLM_EXTERN DatePtr LIBCALL DateParse (CharPtr str)
+
+{
+  Int4      day = -1, month = -1, year = -1;
+  DatePtr   dp;
+  CharPtr   ptr;
+  Char      tmp [64];
+  long int  val;
+
+  if (StringHasNoText (str)) return NULL;
+
+  StringNCpy_0 (tmp, str, sizeof (tmp));
+  ptr = StringChr (tmp, '/');
+  if (ptr == NULL) {
+    ptr = StringChr (tmp, '-');
+  }
+  if (ptr != NULL) {
+    *ptr = '\0';
+    ptr++;
+    if (sscanf (tmp, "%ld", &val) == 1) {
+      month = (Int4) val;
+    }
+    str = StringChr (ptr, '/');
+    if (str == NULL) {
+      str = StringChr (ptr, '-');
+    }
+    if (str != NULL) {
+      *str = '\0';
+      str++;
+      if (sscanf (ptr, "%ld", &val) == 1) {
+        day = (Int4) val;
+      }
+      if (sscanf (str, "%ld", &val) == 1) {
+        year = (Int4) val;
+     }
+    }
+  }
+
+  if (month < 0 || day < 0 || year < 2000) return NULL;
+  if (month > 12 || day > 31 || year > 2099) return NULL;
+
+  dp = DateNew ();
+  if (dp == NULL) return NULL;
+
+  dp->data [0] = 1;
+  dp->data [1] = (Uint1) (year - 1900);
+  dp->data [2] = (Uint1) month;
+  dp->data [3] = (Uint1) day;
+
+  return dp;
+}
+
 /*****************************************************************************
 *
 *   DbtagNew()
diff --git a/object/objgen.h b/object/objgen.h
index 664296a..8a00f2b 100644
--- a/object/objgen.h
+++ b/object/objgen.h
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 1/1/91
 *
-* $Revision: 6.14 $
+* $Revision: 6.15 $
 *
 * File Description:  Object manager interface for module NCBI-General
 *
@@ -38,65 +38,6 @@
 * Date	   Name        Description of modification
 * -------  ----------  -----------------------------------------------------
 *
-*
-* $Log: objgen.h,v $
-* Revision 6.14  2008/09/10 15:22:46  bollin
-* Added DbtagMatchEx and ObjectIdMatchEx, which are optionally case sensitive or case insensitive.
-*
-* Revision 6.13  2005/07/08 18:18:31  kans
-* added scratch pointer to EXTRA_OBJMGR_FIELDS
-*
-* Revision 6.12  2005/05/18 17:30:16  bollin
-* added NameStdMatch and PersonIdMatch functions
-*
-* Revision 6.11  2002/07/22 20:02:16  kans
-* document person-id.consortium choice
-*
-* Revision 6.10  2002/05/08 18:57:24  kans
-* itemID is Uint4
-*
-* Revision 6.9  2000/01/20 17:04:27  beloslyu
-* new function DateClean to properly clean the date was added
-*
-* Revision 6.8  2000/01/20 15:13:16  ostell
-* added hour/minute/second fields to Date
-* added DateTimeCurr()
-*
-* Revision 6.7  1999/11/03 17:58:26  kans
-* added SeqDescrAddPointer
-*
-* Revision 6.6  1999/10/05 17:24:14  kans
-* added SeqDescrAdd
-*
-* Revision 6.5  1999/09/28 14:56:00  kans
-* rename ObjValNodeNew to SeqDescrNew
-*
-* Revision 6.4  1999/09/27 17:48:38  kans
-* using GatherIndex structure
-*
-* Revision 6.3  1999/09/24 23:09:23  kans
-* adds EXTRA_OBJMGR_FIELDS to several objects
-*
-* Revision 6.2  1999/09/23 00:07:44  kans
-* ObjValNodeNew implemented
-*
-* Revision 6.1  1999/09/22 23:37:18  kans
-* added EXTRA_OBJMGR_FIELDS and ObjValNode
-*
-* Revision 6.0  1997/08/25 18:50:00  madden
-* Revision changed to 6.0
-*
-* Revision 4.1  1997/06/19 18:41:26  vakatov
-* [WIN32,MSVC++]  Adopted for the "NCBIOBJ.LIB" DLL'ization
-*
-* Revision 4.0  1995/07/26 13:48:06  ostell
-* force revision to 4.0
-*
- * Revision 3.3  1995/05/15  21:22:00  ostell
- * added Log line
- *
-*
-*
 * ==========================================================================
 */
 
@@ -199,6 +140,8 @@ NLM_EXTERN NCBI_DatePtr LIBCALL DateDup PROTO((NCBI_DatePtr dp));
 NLM_EXTERN Boolean      LIBCALL DateAsnWrite PROTO((NCBI_DatePtr dp, AsnIoPtr aip, AsnTypePtr atp));
 NLM_EXTERN NCBI_DatePtr LIBCALL DateAsnRead PROTO((AsnIoPtr aip, AsnTypePtr atp));
 NLM_EXTERN Int2         LIBCALL DateMatch PROTO((DatePtr a, DatePtr b, Boolean all));
+NLM_EXTERN DatePtr      LIBCALL DateParse (CharPtr str);
+
 /*****************************************************************************
 *
 *   DateCheck (dp)
diff --git a/object/objinsdseq.c b/object/objinsdseq.c
index b753fcf..b617c8d 100644
--- a/object/objinsdseq.c
+++ b/object/objinsdseq.c
@@ -31,7 +31,7 @@ objinsdseqAsnLoad(void)
 
 /**************************************************
 *    Generated object loaders for Module INSD-INSDSeq
-*    Generated using ASNCODE Revision: 6.16 at Jan 15, 2009  2:16 PM
+*    Generated using ASNCODE Revision: 6.17 at May 26, 2010 12:38 PM
 *
 **************************************************/
 
@@ -63,7 +63,6 @@ NLM_EXTERN
 INSDSetPtr LIBCALL
 INSDSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
-   DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
@@ -119,7 +118,6 @@ erret:
 NLM_EXTERN Boolean LIBCALL 
 INSDSetAsnWrite(INSDSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
-   DataVal av;
    AsnTypePtr atp;
    Boolean retval = FALSE;
 
@@ -202,13 +200,16 @@ INSDSeqFree(INSDSeqPtr ptr)
    MemFree(ptr -> taxonomy);
    AsnGenericUserSeqOfFree(ptr -> references, (AsnOptFreeFunc) INSDReferenceFree);
    MemFree(ptr -> comment);
-   INSDTagsetFree(ptr -> tagset);
+   AsnGenericUserSeqOfFree(ptr -> comment_set, (AsnOptFreeFunc) INSDCommentFree);
+   AsnGenericUserSeqOfFree(ptr -> struc_comments, (AsnOptFreeFunc) INSDStrucCommentFree);
    MemFree(ptr -> primary);
    MemFree(ptr -> source_db);
    MemFree(ptr -> database_reference);
    AsnGenericUserSeqOfFree(ptr -> feature_table, (AsnOptFreeFunc) INSDFeatureFree);
+   AsnGenericUserSeqOfFree(ptr -> feature_set, (AsnOptFreeFunc) INSDFeatureSetFree);
    MemFree(ptr -> sequence);
    MemFree(ptr -> contig);
+   AsnGenericUserSeqOfFree(ptr -> alt_seq, (AsnOptFreeFunc) INSDAltSeqDataFree);
    return MemFree(ptr);
 }
 
@@ -428,9 +429,16 @@ INSDSeqAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> comment = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDSEQ_tagset) {
-      ptr -> tagset = INSDTagsetAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == INSDSEQ_comment_set) {
+      ptr -> comment_set = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDCommentAsnRead, (AsnOptFreeFunc) INSDCommentFree);
+      if (isError && ptr -> comment_set == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDSEQ_struc_comments) {
+      ptr -> struc_comments = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDStrucCommentAsnRead, (AsnOptFreeFunc) INSDStrucCommentFree);
+      if (isError && ptr -> struc_comments == NULL) {
          goto erret;
       }
       atp = AsnReadId(aip,amp, atp);
@@ -463,6 +471,13 @@ INSDSeqAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == INSDSEQ_feature_set) {
+      ptr -> feature_set = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDFeatureSetAsnRead, (AsnOptFreeFunc) INSDFeatureSetFree);
+      if (isError && ptr -> feature_set == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
    if (atp == INSDSEQ_sequence) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
@@ -477,6 +492,13 @@ INSDSeqAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> contig = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == INSDSEQ_alt_seq) {
+      ptr -> alt_seq = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDAltSeqDataAsnRead, (AsnOptFreeFunc) INSDAltSeqDataFree);
+      if (isError && ptr -> alt_seq == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -610,11 +632,8 @@ INSDSeqAsnWrite(INSDSeqPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       av.ptrvalue = ptr -> comment;
       retval = AsnWrite(aip, INSDSEQ_comment,  &av);
    }
-   if (ptr -> tagset != NULL) {
-      if ( ! INSDTagsetAsnWrite(ptr -> tagset, aip, INSDSEQ_tagset)) {
-         goto erret;
-      }
-   }
+   AsnGenericUserSeqOfAsnWrite(ptr -> comment_set, (AsnWriteFunc) INSDCommentAsnWrite, aip, INSDSEQ_comment_set, INSDSEQ_comment_set_E);
+   AsnGenericUserSeqOfAsnWrite(ptr -> struc_comments, (AsnWriteFunc) INSDStrucCommentAsnWrite, aip, INSDSEQ_struc_comments, INSDSEQ_struc_comments_E);
    if (ptr -> primary != NULL) {
       av.ptrvalue = ptr -> primary;
       retval = AsnWrite(aip, INSDSEQ_primary,  &av);
@@ -628,6 +647,7 @@ INSDSeqAsnWrite(INSDSeqPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       retval = AsnWrite(aip, INSDSEQ_database_reference,  &av);
    }
    AsnGenericUserSeqOfAsnWrite(ptr -> feature_table, (AsnWriteFunc) INSDFeatureAsnWrite, aip, INSDSEQ_feature_table, INSDSEQ_feature_table_E);
+   AsnGenericUserSeqOfAsnWrite(ptr -> feature_set, (AsnWriteFunc) INSDFeatureSetAsnWrite, aip, INSDSEQ_feature_set, INSDSEQ_feature_set_E);
    if (ptr -> sequence != NULL) {
       av.ptrvalue = ptr -> sequence;
       retval = AsnWrite(aip, INSDSEQ_sequence,  &av);
@@ -636,6 +656,7 @@ INSDSeqAsnWrite(INSDSeqPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       av.ptrvalue = ptr -> contig;
       retval = AsnWrite(aip, INSDSEQ_contig,  &av);
    }
+   AsnGenericUserSeqOfAsnWrite(ptr -> alt_seq, (AsnWriteFunc) INSDAltSeqDataAsnWrite, aip, INSDSEQ_alt_seq, INSDSEQ_alt_seq_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -894,14 +915,14 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsetNew()
+*    INSDCommentNew()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetPtr LIBCALL
-INSDTagsetNew(void)
+INSDCommentPtr LIBCALL
+INSDCommentNew(void)
 {
-   INSDTagsetPtr ptr = MemNew((size_t) sizeof(INSDTagset));
+   INSDCommentPtr ptr = MemNew((size_t) sizeof(INSDComment));
 
    return ptr;
 
@@ -910,39 +931,37 @@ INSDTagsetNew(void)
 
 /**************************************************
 *
-*    INSDTagsetFree()
+*    INSDCommentFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetPtr LIBCALL
-INSDTagsetFree(INSDTagsetPtr ptr)
+INSDCommentPtr LIBCALL
+INSDCommentFree(INSDCommentPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> authority);
-   MemFree(ptr -> version);
-   MemFree(ptr -> url);
-   INSDTagsFree(ptr -> tags);
+   MemFree(ptr -> type);
+   AsnGenericUserSeqOfFree(ptr -> paragraphs, (AsnOptFreeFunc) INSDCommentParagraphFree);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDTagsetAsnRead()
+*    INSDCommentAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetPtr LIBCALL
-INSDTagsetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDCommentPtr LIBCALL
+INSDCommentAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDTagsetPtr ptr;
+   INSDCommentPtr ptr;
 
    if (! loaded)
    {
@@ -955,17 +974,17 @@ INSDTagsetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDTagset ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDTAGSET);
+   if (orig == NULL) {         /* INSDComment ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDCOMMENT);
    } else {
-      atp = AsnLinkType(orig, INSDTAGSET);
+      atp = AsnLinkType(orig, INSDCOMMENT);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = INSDTagsetNew();
+   ptr = INSDCommentNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -976,30 +995,180 @@ INSDTagsetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == INSDTAGSET_authority) {
+   if (atp == INSDCOMMENT_type) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> authority = av.ptrvalue;
+      ptr -> type = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSET_version) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == INSDCOMMENT_paragraphs) {
+      ptr -> paragraphs = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDCommentParagraphAsnRead, (AsnOptFreeFunc) INSDCommentParagraphFree);
+      if (isError && ptr -> paragraphs == NULL) {
          goto erret;
       }
-      ptr -> version = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSET_url) {
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = INSDCommentFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    INSDCommentAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+INSDCommentAsnWrite(INSDCommentPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objinsdseqAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, INSDCOMMENT);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> type != NULL) {
+      av.ptrvalue = ptr -> type;
+      retval = AsnWrite(aip, INSDCOMMENT_type,  &av);
+   }
+   AsnGenericUserSeqOfAsnWrite(ptr -> paragraphs, (AsnWriteFunc) INSDCommentParagraphAsnWrite, aip, INSDCOMMENT_paragraphs, INSDCOMMENT_paragraphs_E);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    INSDStrucCommentNew()
+*
+**************************************************/
+NLM_EXTERN 
+INSDStrucCommentPtr LIBCALL
+INSDStrucCommentNew(void)
+{
+   INSDStrucCommentPtr ptr = MemNew((size_t) sizeof(INSDStrucComment));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    INSDStrucCommentFree()
+*
+**************************************************/
+NLM_EXTERN 
+INSDStrucCommentPtr LIBCALL
+INSDStrucCommentFree(INSDStrucCommentPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> name);
+   AsnGenericUserSeqOfFree(ptr -> items, (AsnOptFreeFunc) INSDStrucCommentItemFree);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    INSDStrucCommentAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+INSDStrucCommentPtr LIBCALL
+INSDStrucCommentAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   INSDStrucCommentPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objinsdseqAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* INSDStrucComment ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDSTRUCCOMMENT);
+   } else {
+      atp = AsnLinkType(orig, INSDSTRUCCOMMENT);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = INSDStrucCommentNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == INSDSTRUCCOMMENT_name) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> url = av.ptrvalue;
+      ptr -> name = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSET_tags) {
-      ptr -> tags = INSDTagsAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == INSDSTRUCCOMMENT_items) {
+      ptr -> items = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDStrucCommentItemAsnRead, (AsnOptFreeFunc) INSDStrucCommentItemFree);
+      if (isError && ptr -> items == NULL) {
          goto erret;
       }
       atp = AsnReadId(aip,amp, atp);
@@ -1016,7 +1185,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDTagsetFree(ptr);
+   ptr = INSDStrucCommentFree(ptr);
    goto ret;
 }
 
@@ -1024,11 +1193,11 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsetAsnWrite()
+*    INSDStrucCommentAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDTagsetAsnWrite(INSDTagsetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDStrucCommentAsnWrite(INSDStrucCommentPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1045,7 +1214,7 @@ INSDTagsetAsnWrite(INSDTagsetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDTAGSET);   /* link local tree */
+   atp = AsnLinkType(orig, INSDSTRUCCOMMENT);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1055,23 +1224,11 @@ INSDTagsetAsnWrite(INSDTagsetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> authority != NULL) {
-      av.ptrvalue = ptr -> authority;
-      retval = AsnWrite(aip, INSDTAGSET_authority,  &av);
-   }
-   if (ptr -> version != NULL) {
-      av.ptrvalue = ptr -> version;
-      retval = AsnWrite(aip, INSDTAGSET_version,  &av);
-   }
-   if (ptr -> url != NULL) {
-      av.ptrvalue = ptr -> url;
-      retval = AsnWrite(aip, INSDTAGSET_url,  &av);
-   }
-   if (ptr -> tags != NULL) {
-      if ( ! INSDTagsAsnWrite(ptr -> tags, aip, INSDTAGSET_tags)) {
-         goto erret;
-      }
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, INSDSTRUCCOMMENT_name,  &av);
    }
+   AsnGenericUserSeqOfAsnWrite(ptr -> items, (AsnWriteFunc) INSDStrucCommentItemAsnWrite, aip, INSDSTRUCCOMMENT_items, INSDSTRUCCOMMENT_items_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -1118,6 +1275,7 @@ INSDFeatureFree(INSDFeaturePtr ptr)
    AsnGenericUserSeqOfFree(ptr -> intervals, (AsnOptFreeFunc) INSDIntervalFree);
    MemFree(ptr -> operator__);
    AsnGenericUserSeqOfFree(ptr -> quals, (AsnOptFreeFunc) INSDQualifierFree);
+   AsnGenericUserSeqOfFree(ptr -> xrefs, (AsnOptFreeFunc) INSDXrefFree);
    return MemFree(ptr);
 }
 
@@ -1220,6 +1378,13 @@ INSDFeatureAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == INSDFEATURE_xrefs) {
+      ptr -> xrefs = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDXrefAsnRead, (AsnOptFreeFunc) INSDXrefFree);
+      if (isError && ptr -> xrefs == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -1291,6 +1456,7 @@ INSDFeatureAsnWrite(INSDFeaturePtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       retval = AsnWrite(aip, INSDFEATURE_partial3,  &av);
    }
    AsnGenericUserSeqOfAsnWrite(ptr -> quals, (AsnWriteFunc) INSDQualifierAsnWrite, aip, INSDFEATURE_quals, INSDFEATURE_quals_E);
+   AsnGenericUserSeqOfAsnWrite(ptr -> xrefs, (AsnWriteFunc) INSDXrefAsnWrite, aip, INSDFEATURE_xrefs, INSDFEATURE_xrefs_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -1305,14 +1471,14 @@ erret:
 
 /**************************************************
 *
-*    INSDXrefNew()
+*    INSDFeatureSetNew()
 *
 **************************************************/
 NLM_EXTERN 
-INSDXrefPtr LIBCALL
-INSDXrefNew(void)
+INSDFeatureSetPtr LIBCALL
+INSDFeatureSetNew(void)
 {
-   INSDXrefPtr ptr = MemNew((size_t) sizeof(INSDXref));
+   INSDFeatureSetPtr ptr = MemNew((size_t) sizeof(INSDFeatureSet));
 
    return ptr;
 
@@ -1321,37 +1487,37 @@ INSDXrefNew(void)
 
 /**************************************************
 *
-*    INSDXrefFree()
+*    INSDFeatureSetFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDXrefPtr LIBCALL
-INSDXrefFree(INSDXrefPtr ptr)
+INSDFeatureSetPtr LIBCALL
+INSDFeatureSetFree(INSDFeatureSetPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> dbname);
-   MemFree(ptr -> id);
+   MemFree(ptr -> annot_source);
+   AsnGenericUserSeqOfFree(ptr -> features, (AsnOptFreeFunc) INSDFeatureFree);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDXrefAsnRead()
+*    INSDFeatureSetAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDXrefPtr LIBCALL
-INSDXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDFeatureSetPtr LIBCALL
+INSDFeatureSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDXrefPtr ptr;
+   INSDFeatureSetPtr ptr;
 
    if (! loaded)
    {
@@ -1364,17 +1530,17 @@ INSDXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDXref ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDXREF);
+   if (orig == NULL) {         /* INSDFeatureSet ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDFEATURESET);
    } else {
-      atp = AsnLinkType(orig, INSDXREF);
+      atp = AsnLinkType(orig, INSDFEATURESET);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = INSDXrefNew();
+   ptr = INSDFeatureSetNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -1385,18 +1551,18 @@ INSDXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == INSDXREF_dbname) {
+   if (atp == INSDFEATURESET_annot_source) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> dbname = av.ptrvalue;
+      ptr -> annot_source = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDXREF_id) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == INSDFEATURESET_features) {
+      ptr -> features = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDFeatureAsnRead, (AsnOptFreeFunc) INSDFeatureFree);
+      if (isError && ptr -> features == NULL) {
          goto erret;
       }
-      ptr -> id = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -1411,7 +1577,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDXrefFree(ptr);
+   ptr = INSDFeatureSetFree(ptr);
    goto ret;
 }
 
@@ -1419,11 +1585,11 @@ erret:
 
 /**************************************************
 *
-*    INSDXrefAsnWrite()
+*    INSDFeatureSetAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDXrefAsnWrite(INSDXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDFeatureSetAsnWrite(INSDFeatureSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1440,7 +1606,7 @@ INSDXrefAsnWrite(INSDXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDXREF);   /* link local tree */
+   atp = AsnLinkType(orig, INSDFEATURESET);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1450,14 +1616,11 @@ INSDXrefAsnWrite(INSDXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> dbname != NULL) {
-      av.ptrvalue = ptr -> dbname;
-      retval = AsnWrite(aip, INSDXREF_dbname,  &av);
-   }
-   if (ptr -> id != NULL) {
-      av.ptrvalue = ptr -> id;
-      retval = AsnWrite(aip, INSDXREF_id,  &av);
+   if (ptr -> annot_source != NULL) {
+      av.ptrvalue = ptr -> annot_source;
+      retval = AsnWrite(aip, INSDFEATURESET_annot_source,  &av);
    }
+   AsnGenericUserSeqOfAsnWrite(ptr -> features, (AsnWriteFunc) INSDFeatureAsnWrite, aip, INSDFEATURESET_features, INSDFEATURESET_features_E);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -1472,36 +1635,53 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsFree()
+*    INSDAltSeqDataNew()
+*
+**************************************************/
+NLM_EXTERN 
+INSDAltSeqDataPtr LIBCALL
+INSDAltSeqDataNew(void)
+{
+   INSDAltSeqDataPtr ptr = MemNew((size_t) sizeof(INSDAltSeqData));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    INSDAltSeqDataFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsPtr LIBCALL
-INSDTagsFree(INSDTagsPtr ptr)
+INSDAltSeqDataPtr LIBCALL
+INSDAltSeqDataFree(INSDAltSeqDataPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   AsnGenericUserSeqOfFree(ptr,  (AsnOptFreeFunc) INSDTagFree);
-   return NULL;
+   MemFree(ptr -> name);
+   AsnGenericUserSeqOfFree(ptr -> items, (AsnOptFreeFunc) INSDAltSeqItemFree);
+   return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDTagsAsnRead()
+*    INSDAltSeqDataAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsPtr LIBCALL
-INSDTagsAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDAltSeqDataPtr LIBCALL
+INSDAltSeqDataAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDTagsPtr ptr;
+   INSDAltSeqDataPtr ptr;
 
    if (! loaded)
    {
@@ -1514,24 +1694,46 @@ INSDTagsAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDTags ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDTAGS);
+   if (orig == NULL) {         /* INSDAltSeqData ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDALTSEQDATA);
    } else {
-      atp = AsnLinkType(orig, INSDTAGS);
+      atp = AsnLinkType(orig, INSDALTSEQDATA);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
+   ptr = INSDAltSeqDataNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   ptr  = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDTagAsnRead, (AsnOptFreeFunc) INSDTagFree);
-   if (isError && ptr  == NULL) {
+   if (atp == INSDALTSEQDATA_name) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
    }
+      ptr -> name = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQDATA_items) {
+      ptr -> items = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDAltSeqItemAsnRead, (AsnOptFreeFunc) INSDAltSeqItemFree);
+      if (isError && ptr -> items == NULL) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
-
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
 
 ret:
    AsnUnlinkType(orig);       /* unlink local tree */
@@ -1539,7 +1741,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDTagsFree(ptr);
+   ptr = INSDAltSeqDataFree(ptr);
    goto ret;
 }
 
@@ -1547,11 +1749,11 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsAsnWrite()
+*    INSDAltSeqDataAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDTagsAsnWrite(INSDTagsPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDAltSeqDataAsnWrite(INSDAltSeqDataPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1568,13 +1770,24 @@ INSDTagsAsnWrite(INSDTagsPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDTAGS);   /* link local tree */
+   atp = AsnLinkType(orig, INSDALTSEQDATA);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
 
    if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
-   retval = AsnGenericUserSeqOfAsnWrite(ptr , (AsnWriteFunc) INSDTagAsnWrite, aip, atp, INSDTAGS_E);
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, INSDALTSEQDATA_name,  &av);
+   }
+   AsnGenericUserSeqOfAsnWrite(ptr -> items, (AsnWriteFunc) INSDAltSeqItemAsnWrite, aip, INSDALTSEQDATA_items, INSDALTSEQDATA_items_E);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
    retval = TRUE;
 
 erret:
@@ -1586,14 +1799,14 @@ erret:
 
 /**************************************************
 *
-*    INSDTagNew()
+*    INSDXrefNew()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagPtr LIBCALL
-INSDTagNew(void)
+INSDXrefPtr LIBCALL
+INSDXrefNew(void)
 {
-   INSDTagPtr ptr = MemNew((size_t) sizeof(INSDTag));
+   INSDXrefPtr ptr = MemNew((size_t) sizeof(INSDXref));
 
    return ptr;
 
@@ -1602,38 +1815,36 @@ INSDTagNew(void)
 
 /**************************************************
 *
-*    INSDTagFree()
+*    INSDXrefFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagPtr LIBCALL
-INSDTagFree(INSDTagPtr ptr)
+INSDXrefPtr LIBCALL
+INSDXrefFree(INSDXrefPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> name);
-   MemFree(ptr -> value);
-   MemFree(ptr -> unit);
+   MemFree(ptr -> dbname);
+   MemFree(ptr -> id);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDTagAsnRead()
+*    INSDXrefAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagPtr LIBCALL
-INSDTagAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDXrefPtr LIBCALL
+INSDXrefAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDTagPtr ptr;
+   INSDXrefPtr ptr;
 
    if (! loaded)
    {
@@ -1646,17 +1857,17 @@ INSDTagAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDTag ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDTAG);
+   if (orig == NULL) {         /* INSDXref ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDXREF);
    } else {
-      atp = AsnLinkType(orig, INSDTAG);
+      atp = AsnLinkType(orig, INSDXREF);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = INSDTagNew();
+   ptr = INSDXrefNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -1667,25 +1878,18 @@ INSDTagAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == INSDTAG_name) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
-         goto erret;
-      }
-      ptr -> name = av.ptrvalue;
-      atp = AsnReadId(aip,amp, atp);
-   }
-   if (atp == INSDTAG_value) {
+   if (atp == INSDXREF_dbname) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> value = av.ptrvalue;
+      ptr -> dbname = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAG_unit) {
+   if (atp == INSDXREF_id) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> unit = av.ptrvalue;
+      ptr -> id = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -1700,7 +1904,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDTagFree(ptr);
+   ptr = INSDXrefFree(ptr);
    goto ret;
 }
 
@@ -1708,11 +1912,11 @@ erret:
 
 /**************************************************
 *
-*    INSDTagAsnWrite()
+*    INSDXrefAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDTagAsnWrite(INSDTagPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDXrefAsnWrite(INSDXrefPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1729,7 +1933,7 @@ INSDTagAsnWrite(INSDTagPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDTAG);   /* link local tree */
+   atp = AsnLinkType(orig, INSDXREF);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1739,17 +1943,13 @@ INSDTagAsnWrite(INSDTagPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> name != NULL) {
-      av.ptrvalue = ptr -> name;
-      retval = AsnWrite(aip, INSDTAG_name,  &av);
-   }
-   if (ptr -> value != NULL) {
-      av.ptrvalue = ptr -> value;
-      retval = AsnWrite(aip, INSDTAG_value,  &av);
+   if (ptr -> dbname != NULL) {
+      av.ptrvalue = ptr -> dbname;
+      retval = AsnWrite(aip, INSDXREF_dbname,  &av);
    }
-   if (ptr -> unit != NULL) {
-      av.ptrvalue = ptr -> unit;
-      retval = AsnWrite(aip, INSDTAG_unit,  &av);
+   if (ptr -> id != NULL) {
+      av.ptrvalue = ptr -> id;
+      retval = AsnWrite(aip, INSDXREF_id,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -1765,14 +1965,14 @@ erret:
 
 /**************************************************
 *
-*    INSDIntervalNew()
+*    INSDCommentParagraphNew()
 *
 **************************************************/
 NLM_EXTERN 
-INSDIntervalPtr LIBCALL
-INSDIntervalNew(void)
+INSDCommentParagraphPtr LIBCALL
+INSDCommentParagraphNew(void)
 {
-   INSDIntervalPtr ptr = MemNew((size_t) sizeof(INSDInterval));
+   INSDCommentParagraphPtr ptr = MemNew((size_t) sizeof(INSDCommentParagraph));
 
    return ptr;
 
@@ -1781,36 +1981,36 @@ INSDIntervalNew(void)
 
 /**************************************************
 *
-*    INSDIntervalFree()
+*    INSDCommentParagraphFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDIntervalPtr LIBCALL
-INSDIntervalFree(INSDIntervalPtr ptr)
+INSDCommentParagraphPtr LIBCALL
+INSDCommentParagraphFree(INSDCommentParagraphPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> accession);
+   AsnGenericUserSeqOfFree(ptr -> items, (AsnOptFreeFunc) INSDCommentItemFree);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDIntervalAsnRead()
+*    INSDCommentParagraphAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDIntervalPtr LIBCALL
-INSDIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDCommentParagraphPtr LIBCALL
+INSDCommentParagraphAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
    Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDIntervalPtr ptr;
+   INSDCommentParagraphPtr ptr;
 
    if (! loaded)
    {
@@ -1823,17 +2023,17 @@ INSDIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDInterval ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDINTERVAL);
+   if (orig == NULL) {         /* INSDCommentParagraph ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDCOMMENTPARAGRAPH);
    } else {
-      atp = AsnLinkType(orig, INSDINTERVAL);
+      atp = AsnLinkType(orig, INSDCOMMENTPARAGRAPH);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = INSDIntervalNew();
+   ptr = INSDCommentParagraphNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -1844,51 +2044,169 @@ INSDIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == INSDINTERVAL_from) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == INSDCOMMENTPARAGRAPH_items) {
+      ptr -> items = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDCommentItemAsnRead, (AsnOptFreeFunc) INSDCommentItemFree);
+      if (isError && ptr -> items == NULL) {
          goto erret;
       }
-      ptr -> from = av.intvalue;
-      ptr -> OBbits__ |= 1<<0;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDINTERVAL_to) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> to = av.intvalue;
-      ptr -> OBbits__ |= 1<<1;
-      atp = AsnReadId(aip,amp, atp);
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = INSDCommentParagraphFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    INSDCommentParagraphAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+INSDCommentParagraphAsnWrite(INSDCommentParagraphPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objinsdseqAsnLoad()) {
+         return FALSE;
    }
-   if (atp == INSDINTERVAL_point) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, INSDCOMMENTPARAGRAPH);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
          goto erret;
       }
-      ptr -> point = av.intvalue;
-      ptr -> OBbits__ |= 1<<2;
-      atp = AsnReadId(aip,amp, atp);
+
+   AsnGenericUserSeqOfAsnWrite(ptr -> items, (AsnWriteFunc) INSDCommentItemAsnWrite, aip, INSDCOMMENTPARAGRAPH_items, INSDCOMMENTPARAGRAPH_items_E);
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
    }
-   if (atp == INSDINTERVAL_iscomp) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    INSDCommentItemNew()
+*
+**************************************************/
+NLM_EXTERN 
+INSDCommentItemPtr LIBCALL
+INSDCommentItemNew(void)
+{
+   INSDCommentItemPtr ptr = MemNew((size_t) sizeof(INSDCommentItem));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    INSDCommentItemFree()
+*
+**************************************************/
+NLM_EXTERN 
+INSDCommentItemPtr LIBCALL
+INSDCommentItemFree(INSDCommentItemPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> value);
+   MemFree(ptr -> url);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    INSDCommentItemAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+INSDCommentItemPtr LIBCALL
+INSDCommentItemAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   AsnReadFunc func;
+   INSDCommentItemPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objinsdseqAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* INSDCommentItem ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDCOMMENTITEM);
+   } else {
+      atp = AsnLinkType(orig, INSDCOMMENTITEM);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = INSDCommentItemNew();
+   if (ptr == NULL) {
          goto erret;
       }
-      ptr -> iscomp = av.boolvalue;
-      ptr -> OBbits__ |= 1<<3;
-      atp = AsnReadId(aip,amp, atp);
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
    }
-   if (atp == INSDINTERVAL_interbp) {
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == INSDCOMMENTITEM_value) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> interbp = av.boolvalue;
-      ptr -> OBbits__ |= 1<<4;
+      ptr -> value = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDINTERVAL_accession) {
+   if (atp == INSDCOMMENTITEM_url) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> accession = av.ptrvalue;
+      ptr -> url = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -1903,7 +2221,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDIntervalFree(ptr);
+   ptr = INSDCommentItemFree(ptr);
    goto ret;
 }
 
@@ -1911,11 +2229,11 @@ erret:
 
 /**************************************************
 *
-*    INSDIntervalAsnWrite()
+*    INSDCommentItemAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDIntervalAsnWrite(INSDIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDCommentItemAsnWrite(INSDCommentItemPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -1932,7 +2250,7 @@ INSDIntervalAsnWrite(INSDIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDINTERVAL);   /* link local tree */
+   atp = AsnLinkType(orig, INSDCOMMENTITEM);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -1942,24 +2260,13 @@ INSDIntervalAsnWrite(INSDIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> from || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> from;
-      retval = AsnWrite(aip, INSDINTERVAL_from,  &av);
-   }
-   if (ptr -> to || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> to;
-      retval = AsnWrite(aip, INSDINTERVAL_to,  &av);
-   }
-   if (ptr -> point || (ptr -> OBbits__ & (1<<2) )){   av.intvalue = ptr -> point;
-      retval = AsnWrite(aip, INSDINTERVAL_point,  &av);
-   }
-   if (ptr -> iscomp || (ptr -> OBbits__ & (1<<3) )){   av.boolvalue = ptr -> iscomp;
-      retval = AsnWrite(aip, INSDINTERVAL_iscomp,  &av);
-   }
-   if (ptr -> interbp || (ptr -> OBbits__ & (1<<4) )){   av.boolvalue = ptr -> interbp;
-      retval = AsnWrite(aip, INSDINTERVAL_interbp,  &av);
+   if (ptr -> value != NULL) {
+      av.ptrvalue = ptr -> value;
+      retval = AsnWrite(aip, INSDCOMMENTITEM_value,  &av);
    }
-   if (ptr -> accession != NULL) {
-      av.ptrvalue = ptr -> accession;
-      retval = AsnWrite(aip, INSDINTERVAL_accession,  &av);
+   if (ptr -> url != NULL) {
+      av.ptrvalue = ptr -> url;
+      retval = AsnWrite(aip, INSDCOMMENTITEM_url,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -1975,14 +2282,14 @@ erret:
 
 /**************************************************
 *
-*    INSDQualifierNew()
+*    INSDStrucCommentItemNew()
 *
 **************************************************/
 NLM_EXTERN 
-INSDQualifierPtr LIBCALL
-INSDQualifierNew(void)
+INSDStrucCommentItemPtr LIBCALL
+INSDStrucCommentItemNew(void)
 {
-   INSDQualifierPtr ptr = MemNew((size_t) sizeof(INSDQualifier));
+   INSDStrucCommentItemPtr ptr = MemNew((size_t) sizeof(INSDStrucCommentItem));
 
    return ptr;
 
@@ -1991,37 +2298,37 @@ INSDQualifierNew(void)
 
 /**************************************************
 *
-*    INSDQualifierFree()
+*    INSDStrucCommentItemFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDQualifierPtr LIBCALL
-INSDQualifierFree(INSDQualifierPtr ptr)
+INSDStrucCommentItemPtr LIBCALL
+INSDStrucCommentItemFree(INSDStrucCommentItemPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> name);
+   MemFree(ptr -> tag);
    MemFree(ptr -> value);
+   MemFree(ptr -> url);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDQualifierAsnRead()
+*    INSDStrucCommentItemAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDQualifierPtr LIBCALL
-INSDQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDStrucCommentItemPtr LIBCALL
+INSDStrucCommentItemAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDQualifierPtr ptr;
+   INSDStrucCommentItemPtr ptr;
 
    if (! loaded)
    {
@@ -2034,17 +2341,17 @@ INSDQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDQualifier ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDQUALIFIER);
+   if (orig == NULL) {         /* INSDStrucCommentItem ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDSTRUCCOMMENTITEM);
    } else {
-      atp = AsnLinkType(orig, INSDQUALIFIER);
+      atp = AsnLinkType(orig, INSDSTRUCCOMMENTITEM);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = INSDQualifierNew();
+   ptr = INSDStrucCommentItemNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -2055,20 +2362,27 @@ INSDQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == INSDQUALIFIER_name) {
+   if (atp == INSDSTRUCCOMMENTITEM_tag) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> name = av.ptrvalue;
+      ptr -> tag = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDQUALIFIER_value) {
+   if (atp == INSDSTRUCCOMMENTITEM_value) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
       ptr -> value = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == INSDSTRUCCOMMENTITEM_url) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> url = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -2081,7 +2395,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDQualifierFree(ptr);
+   ptr = INSDStrucCommentItemFree(ptr);
    goto ret;
 }
 
@@ -2089,11 +2403,11 @@ erret:
 
 /**************************************************
 *
-*    INSDQualifierAsnWrite()
+*    INSDStrucCommentItemAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDQualifierAsnWrite(INSDQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDStrucCommentItemAsnWrite(INSDStrucCommentItemPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2110,7 +2424,7 @@ INSDQualifierAsnWrite(INSDQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDQUALIFIER);   /* link local tree */
+   atp = AsnLinkType(orig, INSDSTRUCCOMMENTITEM);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -2120,13 +2434,17 @@ INSDQualifierAsnWrite(INSDQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> name != NULL) {
-      av.ptrvalue = ptr -> name;
-      retval = AsnWrite(aip, INSDQUALIFIER_name,  &av);
+   if (ptr -> tag != NULL) {
+      av.ptrvalue = ptr -> tag;
+      retval = AsnWrite(aip, INSDSTRUCCOMMENTITEM_tag,  &av);
    }
    if (ptr -> value != NULL) {
       av.ptrvalue = ptr -> value;
-      retval = AsnWrite(aip, INSDQUALIFIER_value,  &av);
+      retval = AsnWrite(aip, INSDSTRUCCOMMENTITEM_value,  &av);
+   }
+   if (ptr -> url != NULL) {
+      av.ptrvalue = ptr -> url;
+      retval = AsnWrite(aip, INSDSTRUCCOMMENTITEM_url,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -2142,14 +2460,14 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsetRulesNew()
+*    INSDIntervalNew()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetRulesPtr LIBCALL
-INSDTagsetRulesNew(void)
+INSDIntervalPtr LIBCALL
+INSDIntervalNew(void)
 {
-   INSDTagsetRulesPtr ptr = MemNew((size_t) sizeof(INSDTagsetRules));
+   INSDIntervalPtr ptr = MemNew((size_t) sizeof(INSDInterval));
 
    return ptr;
 
@@ -2158,40 +2476,35 @@ INSDTagsetRulesNew(void)
 
 /**************************************************
 *
-*    INSDTagsetRulesFree()
+*    INSDIntervalFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetRulesPtr LIBCALL
-INSDTagsetRulesFree(INSDTagsetRulesPtr ptr)
+INSDIntervalPtr LIBCALL
+INSDIntervalFree(INSDIntervalPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> authority);
-   MemFree(ptr -> version);
-   INSDTagNamesFree(ptr -> mandatorytags);
-   INSDTagNamesFree(ptr -> optionaltags);
-   INSDTagNamesFree(ptr -> uniquetags);
+   MemFree(ptr -> accession);
    return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDTagsetRulesAsnRead()
+*    INSDIntervalAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetRulesPtr LIBCALL
-INSDTagsetRulesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDIntervalPtr LIBCALL
+INSDIntervalAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDTagsetRulesPtr ptr;
+   INSDIntervalPtr ptr;
 
    if (! loaded)
    {
@@ -2204,17 +2517,17 @@ INSDTagsetRulesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDTagsetRules ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDTAGSETRULES);
+   if (orig == NULL) {         /* INSDInterval ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDINTERVAL);
    } else {
-      atp = AsnLinkType(orig, INSDTAGSETRULES);
+      atp = AsnLinkType(orig, INSDINTERVAL);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
-   ptr = INSDTagsetRulesNew();
+   ptr = INSDIntervalNew();
    if (ptr == NULL) {
       goto erret;
    }
@@ -2225,47 +2538,51 @@ INSDTagsetRulesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == INSDTAGSETRULES_authority) {
+   if (atp == INSDINTERVAL_from) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> authority = av.ptrvalue;
+      ptr -> from = av.intvalue;
+      ptr -> OBbits__ |= 1<<0;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSETRULES_version) {
+   if (atp == INSDINTERVAL_to) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> version = av.ptrvalue;
+      ptr -> to = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSETRULES_mandatorytags) {
-      ptr -> mandatorytags = INSDTagNamesAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == INSDINTERVAL_point) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
+      ptr -> point = av.intvalue;
+      ptr -> OBbits__ |= 1<<2;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSETRULES_optionaltags) {
-      ptr -> optionaltags = INSDTagNamesAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == INSDINTERVAL_iscomp) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
+      ptr -> iscomp = av.boolvalue;
+      ptr -> OBbits__ |= 1<<3;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSETRULES_uniquetags) {
-      ptr -> uniquetags = INSDTagNamesAsnRead(aip, atp);
-      if (aip -> io_failure) {
+   if (atp == INSDINTERVAL_interbp) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
+      ptr -> interbp = av.boolvalue;
+      ptr -> OBbits__ |= 1<<4;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == INSDTAGSETRULES_extensible) {
+   if (atp == INSDINTERVAL_accession) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
       }
-      ptr -> extensible = av.boolvalue;
-      ptr -> OBbits__ |= 1<<0;
+      ptr -> accession = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
 
@@ -2280,7 +2597,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDTagsetRulesFree(ptr);
+   ptr = INSDIntervalFree(ptr);
    goto ret;
 }
 
@@ -2288,11 +2605,11 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsetRulesAsnWrite()
+*    INSDIntervalAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDTagsetRulesAsnWrite(INSDTagsetRulesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDIntervalAsnWrite(INSDIntervalPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2309,7 +2626,7 @@ INSDTagsetRulesAsnWrite(INSDTagsetRulesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDTAGSETRULES);   /* link local tree */
+   atp = AsnLinkType(orig, INSDINTERVAL);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
@@ -2319,31 +2636,24 @@ INSDTagsetRulesAsnWrite(INSDTagsetRulesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> authority != NULL) {
-      av.ptrvalue = ptr -> authority;
-      retval = AsnWrite(aip, INSDTAGSETRULES_authority,  &av);
-   }
-   if (ptr -> version != NULL) {
-      av.ptrvalue = ptr -> version;
-      retval = AsnWrite(aip, INSDTAGSETRULES_version,  &av);
-   }
-   if (ptr -> mandatorytags != NULL) {
-      if ( ! INSDTagNamesAsnWrite(ptr -> mandatorytags, aip, INSDTAGSETRULES_mandatorytags)) {
-         goto erret;
-      }
+   if (ptr -> from || (ptr -> OBbits__ & (1<<0) )){   av.intvalue = ptr -> from;
+      retval = AsnWrite(aip, INSDINTERVAL_from,  &av);
    }
-   if (ptr -> optionaltags != NULL) {
-      if ( ! INSDTagNamesAsnWrite(ptr -> optionaltags, aip, INSDTAGSETRULES_optionaltags)) {
-         goto erret;
+   if (ptr -> to || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> to;
+      retval = AsnWrite(aip, INSDINTERVAL_to,  &av);
       }
+   if (ptr -> point || (ptr -> OBbits__ & (1<<2) )){   av.intvalue = ptr -> point;
+      retval = AsnWrite(aip, INSDINTERVAL_point,  &av);
    }
-   if (ptr -> uniquetags != NULL) {
-      if ( ! INSDTagNamesAsnWrite(ptr -> uniquetags, aip, INSDTAGSETRULES_uniquetags)) {
-         goto erret;
+   if (ptr -> iscomp || (ptr -> OBbits__ & (1<<3) )){   av.boolvalue = ptr -> iscomp;
+      retval = AsnWrite(aip, INSDINTERVAL_iscomp,  &av);
       }
+   if (ptr -> interbp || (ptr -> OBbits__ & (1<<4) )){   av.boolvalue = ptr -> interbp;
+      retval = AsnWrite(aip, INSDINTERVAL_interbp,  &av);
    }
-   if (ptr -> extensible || (ptr -> OBbits__ & (1<<0) )){   av.boolvalue = ptr -> extensible;
-      retval = AsnWrite(aip, INSDTAGSETRULES_extensible,  &av);
+   if (ptr -> accession != NULL) {
+      av.ptrvalue = ptr -> accession;
+      retval = AsnWrite(aip, INSDINTERVAL_accession,  &av);
    }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
@@ -2359,36 +2669,52 @@ erret:
 
 /**************************************************
 *
-*    INSDTagNamesFree()
+*    INSDQualifierNew()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagNamesPtr LIBCALL
-INSDTagNamesFree(INSDTagNamesPtr ptr)
+INSDQualifierPtr LIBCALL
+INSDQualifierNew(void)
+{
+   INSDQualifierPtr ptr = MemNew((size_t) sizeof(INSDQualifier));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    INSDQualifierFree()
+*
+**************************************************/
+NLM_EXTERN 
+INSDQualifierPtr LIBCALL
+INSDQualifierFree(INSDQualifierPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   AsnGenericBaseSeqOfFree(ptr,ASNCODE_PTRVAL_SLOT);
-   return NULL;
+   MemFree(ptr -> name);
+   MemFree(ptr -> value);
+   return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDTagNamesAsnRead()
+*    INSDQualifierAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagNamesPtr LIBCALL
-INSDTagNamesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDQualifierPtr LIBCALL
+INSDQualifierAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDTagNamesPtr ptr;
+   INSDQualifierPtr ptr;
 
    if (! loaded)
    {
@@ -2401,24 +2727,46 @@ INSDTagNamesAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDTagNames ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDTAGNAMES);
+   if (orig == NULL) {         /* INSDQualifier ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDQUALIFIER);
    } else {
-      atp = AsnLinkType(orig, INSDTAGNAMES);
+      atp = AsnLinkType(orig, INSDQUALIFIER);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
+   ptr = INSDQualifierNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   ptr  = AsnGenericBaseSeqOfAsnRead(aip, amp, atp, ASNCODE_PTRVAL_SLOT, &isError);
-   if (isError && ptr  == NULL) {
+   if (atp == INSDQUALIFIER_name) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
    }
+      ptr -> name = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDQUALIFIER_value) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> value = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
 
-
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
 
 ret:
    AsnUnlinkType(orig);       /* unlink local tree */
@@ -2426,7 +2774,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDTagNamesFree(ptr);
+   ptr = INSDQualifierFree(ptr);
    goto ret;
 }
 
@@ -2434,11 +2782,11 @@ erret:
 
 /**************************************************
 *
-*    INSDTagNamesAsnWrite()
+*    INSDQualifierAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDTagNamesAsnWrite(INSDTagNamesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDQualifierAsnWrite(INSDQualifierPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2455,13 +2803,27 @@ INSDTagNamesAsnWrite(INSDTagNamesPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDTAGNAMES);   /* link local tree */
+   atp = AsnLinkType(orig, INSDQUALIFIER);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
 
    if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
-   retval = AsnGenericBaseSeqOfAsnWrite(ptr, ASNCODE_PTRVAL_SLOT, aip, atp, INSDTAGNAMES_E);
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> name != NULL) {
+      av.ptrvalue = ptr -> name;
+      retval = AsnWrite(aip, INSDQUALIFIER_name,  &av);
+   }
+   if (ptr -> value != NULL) {
+      av.ptrvalue = ptr -> value;
+      retval = AsnWrite(aip, INSDQUALIFIER_value,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
    retval = TRUE;
 
 erret:
@@ -2473,36 +2835,57 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsetRuleSetFree()
+*    INSDAltSeqItemNew()
+*
+**************************************************/
+NLM_EXTERN 
+INSDAltSeqItemPtr LIBCALL
+INSDAltSeqItemNew(void)
+{
+   INSDAltSeqItemPtr ptr = MemNew((size_t) sizeof(INSDAltSeqItem));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    INSDAltSeqItemFree()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetRuleSetPtr LIBCALL
-INSDTagsetRuleSetFree(INSDTagsetRuleSetPtr ptr)
+INSDAltSeqItemPtr LIBCALL
+INSDAltSeqItemFree(INSDAltSeqItemPtr ptr)
 {
 
    if(ptr == NULL) {
       return NULL;
    }
-   AsnGenericUserSeqOfFree(ptr,  (AsnOptFreeFunc) INSDTagsetRulesFree);
-   return NULL;
+   INSDIntervalFree(ptr -> interval);
+   MemFree(ptr -> gap_type);
+   MemFree(ptr -> gap_linkage);
+   MemFree(ptr -> gap_comment);
+   MemFree(ptr -> first_accn);
+   MemFree(ptr -> last_accn);
+   MemFree(ptr -> value);
+   return MemFree(ptr);
 }
 
 
 /**************************************************
 *
-*    INSDTagsetRuleSetAsnRead()
+*    INSDAltSeqItemAsnRead()
 *
 **************************************************/
 NLM_EXTERN 
-INSDTagsetRuleSetPtr LIBCALL
-INSDTagsetRuleSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+INSDAltSeqItemPtr LIBCALL
+INSDAltSeqItemAsnRead(AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
-   Boolean isError = FALSE;
    AsnReadFunc func;
-   INSDTagsetRuleSetPtr ptr;
+   INSDAltSeqItemPtr ptr;
 
    if (! loaded)
    {
@@ -2515,24 +2898,97 @@ INSDTagsetRuleSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       return NULL;
    }
 
-   if (orig == NULL) {         /* INSDTagsetRuleSet ::= (self contained) */
-      atp = AsnReadId(aip, amp, INSDTAGSETRULESET);
+   if (orig == NULL) {         /* INSDAltSeqItem ::= (self contained) */
+      atp = AsnReadId(aip, amp, INSDALTSEQITEM);
    } else {
-      atp = AsnLinkType(orig, INSDTAGSETRULESET);
+      atp = AsnLinkType(orig, INSDALTSEQITEM);
    }
    /* link in local tree */
    if (atp == NULL) {
       return NULL;
    }
 
+   ptr = INSDAltSeqItemNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   ptr  = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) INSDTagsetRulesAsnRead, (AsnOptFreeFunc) INSDTagsetRulesFree);
-   if (isError && ptr  == NULL) {
+   if (atp == INSDALTSEQITEM_interval) {
+      ptr -> interval = INSDIntervalAsnRead(aip, atp);
+      if (aip -> io_failure) {
       goto erret;
    }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_isgap) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> isgap = av.boolvalue;
+      ptr -> OBbits__ |= 1<<0;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_gap_length) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_length = av.intvalue;
+      ptr -> OBbits__ |= 1<<1;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_gap_type) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_type = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_gap_linkage) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_linkage = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_gap_comment) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> gap_comment = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_first_accn) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> first_accn = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_last_accn) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> last_accn = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == INSDALTSEQITEM_value) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> value = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
 
-
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
 
 ret:
    AsnUnlinkType(orig);       /* unlink local tree */
@@ -2540,7 +2996,7 @@ ret:
 
 erret:
    aip -> io_failure = TRUE;
-   ptr = INSDTagsetRuleSetFree(ptr);
+   ptr = INSDAltSeqItemFree(ptr);
    goto ret;
 }
 
@@ -2548,11 +3004,11 @@ erret:
 
 /**************************************************
 *
-*    INSDTagsetRuleSetAsnWrite()
+*    INSDAltSeqItemAsnWrite()
 *
 **************************************************/
 NLM_EXTERN Boolean LIBCALL 
-INSDTagsetRuleSetAsnWrite(INSDTagsetRuleSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+INSDAltSeqItemAsnWrite(INSDAltSeqItemPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
 {
    DataVal av;
    AsnTypePtr atp;
@@ -2569,13 +3025,54 @@ INSDTagsetRuleSetAsnWrite(INSDTagsetRuleSetPtr ptr, AsnIoPtr aip, AsnTypePtr ori
       return FALSE;
    }
 
-   atp = AsnLinkType(orig, INSDTAGSETRULESET);   /* link local tree */
+   atp = AsnLinkType(orig, INSDALTSEQITEM);   /* link local tree */
    if (atp == NULL) {
       return FALSE;
    }
 
    if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
-   retval = AsnGenericUserSeqOfAsnWrite(ptr , (AsnWriteFunc) INSDTagsetRulesAsnWrite, aip, atp, INSDTAGSETRULESET_E);
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> interval != NULL) {
+      if ( ! INSDIntervalAsnWrite(ptr -> interval, aip, INSDALTSEQITEM_interval)) {
+         goto erret;
+      }
+   }
+   if (ptr -> isgap || (ptr -> OBbits__ & (1<<0) )){   av.boolvalue = ptr -> isgap;
+      retval = AsnWrite(aip, INSDALTSEQITEM_isgap,  &av);
+   }
+   if (ptr -> gap_length || (ptr -> OBbits__ & (1<<1) )){   av.intvalue = ptr -> gap_length;
+      retval = AsnWrite(aip, INSDALTSEQITEM_gap_length,  &av);
+   }
+   if (ptr -> gap_type != NULL) {
+      av.ptrvalue = ptr -> gap_type;
+      retval = AsnWrite(aip, INSDALTSEQITEM_gap_type,  &av);
+   }
+   if (ptr -> gap_linkage != NULL) {
+      av.ptrvalue = ptr -> gap_linkage;
+      retval = AsnWrite(aip, INSDALTSEQITEM_gap_linkage,  &av);
+   }
+   if (ptr -> gap_comment != NULL) {
+      av.ptrvalue = ptr -> gap_comment;
+      retval = AsnWrite(aip, INSDALTSEQITEM_gap_comment,  &av);
+   }
+   if (ptr -> first_accn != NULL) {
+      av.ptrvalue = ptr -> first_accn;
+      retval = AsnWrite(aip, INSDALTSEQITEM_first_accn,  &av);
+   }
+   if (ptr -> last_accn != NULL) {
+      av.ptrvalue = ptr -> last_accn;
+      retval = AsnWrite(aip, INSDALTSEQITEM_last_accn,  &av);
+   }
+   if (ptr -> value != NULL) {
+      av.ptrvalue = ptr -> value;
+      retval = AsnWrite(aip, INSDALTSEQITEM_value,  &av);
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
    retval = TRUE;
 
 erret:
diff --git a/object/objinsdseq.h b/object/objinsdseq.h
index f7e3b1e..f35ab76 100644
--- a/object/objinsdseq.h
+++ b/object/objinsdseq.h
@@ -17,7 +17,7 @@ extern "C" { /* } */
 /**************************************************
 *
 *    Generated objects for Module INSD-INSDSeq
-*    Generated using ASNCODE Revision: 6.16 at Jan 15, 2009  2:16 PM
+*    Generated using ASNCODE Revision: 6.17 at May 26, 2010 12:38 PM
 *
 **************************************************/
 
@@ -77,13 +77,16 @@ typedef struct struct_INSDSeq {
    CharPtr   taxonomy;
    struct struct_INSDReference PNTR   references;
    CharPtr   comment;
-   struct struct_INSDTagset PNTR   tagset;
+   struct struct_INSDComment PNTR   comment_set;
+   struct struct_INSDStrucComment PNTR   struc_comments;
    CharPtr   primary;
    CharPtr   source_db;
    CharPtr   database_reference;
    struct struct_INSDFeature PNTR   feature_table;
+   struct struct_INSDFeatureSet PNTR   feature_set;
    CharPtr   sequence;
    CharPtr   contig;
+   struct struct_INSDAltSeqData PNTR   alt_seq;
 } INSDSeq, PNTR INSDSeqPtr;
 
 
@@ -125,22 +128,41 @@ NLM_EXTERN Boolean LIBCALL INSDReferenceAsnWrite PROTO (( INSDReferencePtr , Asn
 
 /**************************************************
 *
-*    INSDTagset
+*    INSDComment
 *
 **************************************************/
-typedef struct struct_INSDTagset {
+typedef struct struct_INSDComment {
+   struct struct_INSDComment PNTR next;
    Uint4 OBbits__;
-   CharPtr   authority;
-   CharPtr   version;
-   CharPtr   url;
-   struct struct_INSDTag PNTR   tags;
-} INSDTagset, PNTR INSDTagsetPtr;
+   CharPtr   type;
+   struct struct_INSDCommentParagraph PNTR   paragraphs;
+} INSDComment, PNTR INSDCommentPtr;
 
 
-NLM_EXTERN INSDTagsetPtr LIBCALL INSDTagsetFree PROTO ((INSDTagsetPtr ));
-NLM_EXTERN INSDTagsetPtr LIBCALL INSDTagsetNew PROTO (( void ));
-NLM_EXTERN INSDTagsetPtr LIBCALL INSDTagsetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL INSDTagsetAsnWrite PROTO (( INSDTagsetPtr , AsnIoPtr, AsnTypePtr));
+NLM_EXTERN INSDCommentPtr LIBCALL INSDCommentFree PROTO ((INSDCommentPtr ));
+NLM_EXTERN INSDCommentPtr LIBCALL INSDCommentNew PROTO (( void ));
+NLM_EXTERN INSDCommentPtr LIBCALL INSDCommentAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDCommentAsnWrite PROTO (( INSDCommentPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    INSDStrucComment
+*
+**************************************************/
+typedef struct struct_INSDStrucComment {
+   struct struct_INSDStrucComment PNTR next;
+   Uint4 OBbits__;
+   CharPtr   name;
+   struct struct_INSDStrucCommentItem PNTR   items;
+} INSDStrucComment, PNTR INSDStrucCommentPtr;
+
+
+NLM_EXTERN INSDStrucCommentPtr LIBCALL INSDStrucCommentFree PROTO ((INSDStrucCommentPtr ));
+NLM_EXTERN INSDStrucCommentPtr LIBCALL INSDStrucCommentNew PROTO (( void ));
+NLM_EXTERN INSDStrucCommentPtr LIBCALL INSDStrucCommentAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDStrucCommentAsnWrite PROTO (( INSDStrucCommentPtr , AsnIoPtr, AsnTypePtr));
 
 
 
@@ -163,6 +185,7 @@ typedef struct struct_INSDFeature {
 
    Uint1   partial3;
    struct struct_INSDQualifier PNTR   quals;
+   struct struct_INSDXref PNTR   xrefs;
 } INSDFeature, PNTR INSDFeaturePtr;
 
 
@@ -175,6 +198,46 @@ NLM_EXTERN Boolean LIBCALL INSDFeatureAsnWrite PROTO (( INSDFeaturePtr , AsnIoPt
 
 /**************************************************
 *
+*    INSDFeatureSet
+*
+**************************************************/
+typedef struct struct_INSDFeatureSet {
+   struct struct_INSDFeatureSet PNTR next;
+   Uint4 OBbits__;
+   CharPtr   annot_source;
+   struct struct_INSDFeature PNTR   features;
+} INSDFeatureSet, PNTR INSDFeatureSetPtr;
+
+
+NLM_EXTERN INSDFeatureSetPtr LIBCALL INSDFeatureSetFree PROTO ((INSDFeatureSetPtr ));
+NLM_EXTERN INSDFeatureSetPtr LIBCALL INSDFeatureSetNew PROTO (( void ));
+NLM_EXTERN INSDFeatureSetPtr LIBCALL INSDFeatureSetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDFeatureSetAsnWrite PROTO (( INSDFeatureSetPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    INSDAltSeqData
+*
+**************************************************/
+typedef struct struct_INSDAltSeqData {
+   struct struct_INSDAltSeqData PNTR next;
+   Uint4 OBbits__;
+   CharPtr   name;
+   struct struct_INSDAltSeqItem PNTR   items;
+} INSDAltSeqData, PNTR INSDAltSeqDataPtr;
+
+
+NLM_EXTERN INSDAltSeqDataPtr LIBCALL INSDAltSeqDataFree PROTO ((INSDAltSeqDataPtr ));
+NLM_EXTERN INSDAltSeqDataPtr LIBCALL INSDAltSeqDataNew PROTO (( void ));
+NLM_EXTERN INSDAltSeqDataPtr LIBCALL INSDAltSeqDataAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDAltSeqDataAsnWrite PROTO (( INSDAltSeqDataPtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
 *    INSDXref
 *
 **************************************************/
@@ -195,42 +258,61 @@ NLM_EXTERN Boolean LIBCALL INSDXrefAsnWrite PROTO (( INSDXrefPtr , AsnIoPtr, Asn
 
 /**************************************************
 *
-*    INSDTags
+*    INSDCommentParagraph
 *
 **************************************************/
-typedef struct struct_INSDTag INSDTags;
-typedef struct struct_INSDTag PNTR INSDTagsPtr;
-#define INSDTagsNew() INSDTagNew() 
+typedef struct struct_INSDCommentParagraph {
+   struct struct_INSDCommentParagraph PNTR next;
+   Uint4 OBbits__;
+   struct struct_INSDCommentItem PNTR   items;
+} INSDCommentParagraph, PNTR INSDCommentParagraphPtr;
 
-#ifdef NLM_GENERATED_CODE_PROTO
 
-NLM_EXTERN INSDTagsPtr LIBCALL INSDTagsFree PROTO ((INSDTagsPtr ));
-NLM_EXTERN INSDTagsPtr LIBCALL INSDTagsNew PROTO (( void ));
-NLM_EXTERN INSDTagsPtr LIBCALL INSDTagsAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL INSDTagsAsnWrite PROTO (( INSDTagsPtr , AsnIoPtr, AsnTypePtr));
+NLM_EXTERN INSDCommentParagraphPtr LIBCALL INSDCommentParagraphFree PROTO ((INSDCommentParagraphPtr ));
+NLM_EXTERN INSDCommentParagraphPtr LIBCALL INSDCommentParagraphNew PROTO (( void ));
+NLM_EXTERN INSDCommentParagraphPtr LIBCALL INSDCommentParagraphAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDCommentParagraphAsnWrite PROTO (( INSDCommentParagraphPtr , AsnIoPtr, AsnTypePtr));
 
-#endif /* NLM_GENERATED_CODE_PROTO */
+
+
+/**************************************************
+*
+*    INSDCommentItem
+*
+**************************************************/
+typedef struct struct_INSDCommentItem {
+   struct struct_INSDCommentItem PNTR next;
+   Uint4 OBbits__;
+   CharPtr   value;
+   CharPtr   url;
+} INSDCommentItem, PNTR INSDCommentItemPtr;
+
+
+NLM_EXTERN INSDCommentItemPtr LIBCALL INSDCommentItemFree PROTO ((INSDCommentItemPtr ));
+NLM_EXTERN INSDCommentItemPtr LIBCALL INSDCommentItemNew PROTO (( void ));
+NLM_EXTERN INSDCommentItemPtr LIBCALL INSDCommentItemAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDCommentItemAsnWrite PROTO (( INSDCommentItemPtr , AsnIoPtr, AsnTypePtr));
 
 
 
 /**************************************************
 *
-*    INSDTag
+*    INSDStrucCommentItem
 *
 **************************************************/
-typedef struct struct_INSDTag {
-   struct struct_INSDTag PNTR next;
+typedef struct struct_INSDStrucCommentItem {
+   struct struct_INSDStrucCommentItem PNTR next;
    Uint4 OBbits__;
-   CharPtr   name;
+   CharPtr   tag;
    CharPtr   value;
-   CharPtr   unit;
-} INSDTag, PNTR INSDTagPtr;
+   CharPtr   url;
+} INSDStrucCommentItem, PNTR INSDStrucCommentItemPtr;
 
 
-NLM_EXTERN INSDTagPtr LIBCALL INSDTagFree PROTO ((INSDTagPtr ));
-NLM_EXTERN INSDTagPtr LIBCALL INSDTagNew PROTO (( void ));
-NLM_EXTERN INSDTagPtr LIBCALL INSDTagAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL INSDTagAsnWrite PROTO (( INSDTagPtr , AsnIoPtr, AsnTypePtr));
+NLM_EXTERN INSDStrucCommentItemPtr LIBCALL INSDStrucCommentItemFree PROTO ((INSDStrucCommentItemPtr ));
+NLM_EXTERN INSDStrucCommentItemPtr LIBCALL INSDStrucCommentItemNew PROTO (( void ));
+NLM_EXTERN INSDStrucCommentItemPtr LIBCALL INSDStrucCommentItemAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDStrucCommentItemAsnWrite PROTO (( INSDStrucCommentItemPtr , AsnIoPtr, AsnTypePtr));
 
 
 
@@ -290,67 +372,32 @@ NLM_EXTERN Boolean LIBCALL INSDQualifierAsnWrite PROTO (( INSDQualifierPtr , Asn
 
 /**************************************************
 *
-*    INSDTagsetRules
+*    INSDAltSeqItem
 *
 **************************************************/
-typedef struct struct_INSDTagsetRules {
-   struct struct_INSDTagsetRules PNTR next;
+typedef struct struct_INSDAltSeqItem {
+   struct struct_INSDAltSeqItem PNTR next;
    Uint4 OBbits__;
-   CharPtr   authority;
-   CharPtr   version;
-   ValNodePtr   mandatorytags;
-   ValNodePtr   optionaltags;
-   ValNodePtr   uniquetags;
-#define OB__INSDTagsetRules_extensible 0
-
-   Uint1   extensible;
-} INSDTagsetRules, PNTR INSDTagsetRulesPtr;
-
-
-NLM_EXTERN INSDTagsetRulesPtr LIBCALL INSDTagsetRulesFree PROTO ((INSDTagsetRulesPtr ));
-NLM_EXTERN INSDTagsetRulesPtr LIBCALL INSDTagsetRulesNew PROTO (( void ));
-NLM_EXTERN INSDTagsetRulesPtr LIBCALL INSDTagsetRulesAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL INSDTagsetRulesAsnWrite PROTO (( INSDTagsetRulesPtr , AsnIoPtr, AsnTypePtr));
-
-
-
-/**************************************************
-*
-*    INSDTagNames
-*
-**************************************************/
-typedef ValNode INSDTagNames;
-typedef ValNodePtr INSDTagNamesPtr;
-#define INSDTagNamesNew() ValNodeNew(NULL) 
-
-#ifdef NLM_GENERATED_CODE_PROTO
-
-NLM_EXTERN INSDTagNamesPtr LIBCALL INSDTagNamesFree PROTO ((INSDTagNamesPtr ));
-NLM_EXTERN INSDTagNamesPtr LIBCALL INSDTagNamesNew PROTO (( void ));
-NLM_EXTERN INSDTagNamesPtr LIBCALL INSDTagNamesAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL INSDTagNamesAsnWrite PROTO (( INSDTagNamesPtr , AsnIoPtr, AsnTypePtr));
-
-#endif /* NLM_GENERATED_CODE_PROTO */
-
-
-
-/**************************************************
-*
-*    INSDTagsetRuleSet
-*
-**************************************************/
-typedef struct struct_INSDTagsetRules INSDTagsetRuleSet;
-typedef struct struct_INSDTagsetRules PNTR INSDTagsetRuleSetPtr;
-#define INSDTagsetRuleSetNew() INSDTagsetRulesNew() 
-
-#ifdef NLM_GENERATED_CODE_PROTO
+   struct struct_INSDInterval PNTR   interval;
+#define OB__INSDAltSeqItem_isgap 0
+
+   Uint1   isgap;
+#define OB__INSDAltSeqItem_gap_length 1
+
+   Int4   gap_length;
+   CharPtr   gap_type;
+   CharPtr   gap_linkage;
+   CharPtr   gap_comment;
+   CharPtr   first_accn;
+   CharPtr   last_accn;
+   CharPtr   value;
+} INSDAltSeqItem, PNTR INSDAltSeqItemPtr;
 
-NLM_EXTERN INSDTagsetRuleSetPtr LIBCALL INSDTagsetRuleSetFree PROTO ((INSDTagsetRuleSetPtr ));
-NLM_EXTERN INSDTagsetRuleSetPtr LIBCALL INSDTagsetRuleSetNew PROTO (( void ));
-NLM_EXTERN INSDTagsetRuleSetPtr LIBCALL INSDTagsetRuleSetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
-NLM_EXTERN Boolean LIBCALL INSDTagsetRuleSetAsnWrite PROTO (( INSDTagsetRuleSetPtr , AsnIoPtr, AsnTypePtr));
 
-#endif /* NLM_GENERATED_CODE_PROTO */
+NLM_EXTERN INSDAltSeqItemPtr LIBCALL INSDAltSeqItemFree PROTO ((INSDAltSeqItemPtr ));
+NLM_EXTERN INSDAltSeqItemPtr LIBCALL INSDAltSeqItemNew PROTO (( void ));
+NLM_EXTERN INSDAltSeqItemPtr LIBCALL INSDAltSeqItemAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL INSDAltSeqItemAsnWrite PROTO (( INSDAltSeqItemPtr , AsnIoPtr, AsnTypePtr));
 
 #ifdef __cplusplus
 /* { */ }
diff --git a/object/objmacro.c b/object/objmacro.c
index b2c23b8..e7dd29f 100755
--- a/object/objmacro.c
+++ b/object/objmacro.c
@@ -31,7 +31,7 @@ objmacroAsnLoad(void)
 
 /**************************************************
 *    Generated object loaders for Module NCBI-Macro
-*    Generated using ASNCODE Revision: 6.16 at May 12, 2009  9:09 AM
+*    Generated using ASNCODE Revision: 6.17 at Jul 26, 2010  2:39 PM
 *
 **************************************************/
 
@@ -737,6 +737,191 @@ erret:
 
 /**************************************************
 *
+*    LocationPosConstraintFree()
+*
+**************************************************/
+NLM_EXTERN 
+LocationPosConstraintPtr LIBCALL
+LocationPosConstraintFree(ValNodePtr anp)
+{
+   Pointer pnt;
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   default:
+      break;
+   }
+   return MemFree(anp);
+}
+
+
+/**************************************************
+*
+*    LocationPosConstraintAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+LocationPosConstraintPtr LIBCALL
+LocationPosConstraintAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Uint1 choice;
+   Boolean isError = FALSE;
+   Boolean nullIsError = FALSE;
+   AsnReadFunc func;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* LocationPosConstraint ::= (self contained) */
+      atp = AsnReadId(aip, amp, LOCATION_POS_CONSTRAINT);
+   } else {
+      atp = AsnLinkType(orig, LOCATION_POS_CONSTRAINT);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp = ValNodeNew(NULL);
+   if (anp == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the CHOICE or OpenStruct value (nothing) */
+      goto erret;
+   }
+
+   func = NULL;
+
+   atp = AsnReadId(aip, amp, atp);  /* find the choice */
+   if (atp == NULL) {
+      goto erret;
+   }
+   if (atp == POS_CONSTRAINT_dist_from_end) {
+      choice = LocationPosConstraint_dist_from_end;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.intvalue = av.intvalue;
+   }
+   else if (atp == CONSTRAINT_max_dist_from_end) {
+      choice = LocationPosConstraint_max_dist_from_end;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.intvalue = av.intvalue;
+   }
+   else if (atp == CONSTRAINT_min_dist_from_end) {
+      choice = LocationPosConstraint_min_dist_from_end;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.intvalue = av.intvalue;
+   }
+   anp->choice = choice;
+   if (func != NULL)
+   {
+      anp->data.ptrvalue = (* func)(aip, atp);
+      if (aip -> io_failure) goto erret;
+
+      if (nullIsError && anp->data.ptrvalue == NULL) {
+         goto erret;
+      }
+   }
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   anp = MemFree(anp);
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    LocationPosConstraintAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+LocationPosConstraintAsnWrite(LocationPosConstraintPtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp, writetype = NULL;
+   Pointer pnt;
+   AsnWriteFunc func = NULL;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, LOCATION_POS_CONSTRAINT);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   if (! AsnWriteChoice(aip, atp, (Int2)anp->choice, &av)) {
+      goto erret;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   case LocationPosConstraint_dist_from_end:
+      av.intvalue = anp->data.intvalue;
+      retval = AsnWrite(aip, POS_CONSTRAINT_dist_from_end, &av);
+      break;
+   case LocationPosConstraint_max_dist_from_end:
+      av.intvalue = anp->data.intvalue;
+      retval = AsnWrite(aip, CONSTRAINT_max_dist_from_end, &av);
+      break;
+   case LocationPosConstraint_min_dist_from_end:
+      av.intvalue = anp->data.intvalue;
+      retval = AsnWrite(aip, CONSTRAINT_min_dist_from_end, &av);
+      break;
+   }
+   if (writetype != NULL) {
+      retval = (* func)(pnt, aip, writetype);   /* write it out */
+   }
+   if (!retval) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+/**************************************************
+*
 *    LocationConstraintNew()
 *
 **************************************************/
@@ -750,6 +935,7 @@ LocationConstraintNew(void)
    ptr -> seq_type = 0;
    ptr -> partial5 = 0;
    ptr -> partial3 = 0;
+   ptr -> location_type = 0;
    return ptr;
 
 }
@@ -768,6 +954,8 @@ LocationConstraintFree(LocationConstraintPtr ptr)
    if(ptr == NULL) {
       return NULL;
    }
+   LocationPosConstraintFree(ptr -> end5);
+   LocationPosConstraintFree(ptr -> end3);
    return MemFree(ptr);
 }
 
@@ -847,6 +1035,27 @@ LocationConstraintAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> partial3 = av.intvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == CONSTRAINT_location_type) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> location_type = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == LOCATION_CONSTRAINT_end5) {
+      ptr -> end5 = LocationPosConstraintAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == LOCATION_CONSTRAINT_end3) {
+      ptr -> end3 = LocationPosConstraintAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -906,6 +1115,18 @@ LocationConstraintAsnWrite(LocationConstraintPtr ptr, AsnIoPtr aip, AsnTypePtr o
    retval = AsnWrite(aip, LOCATION_CONSTRAINT_partial5,  &av);
    av.intvalue = ptr -> partial3;
    retval = AsnWrite(aip, LOCATION_CONSTRAINT_partial3,  &av);
+   av.intvalue = ptr -> location_type;
+   retval = AsnWrite(aip, CONSTRAINT_location_type,  &av);
+   if (ptr -> end5 != NULL) {
+      if ( ! LocationPosConstraintAsnWrite(ptr -> end5, aip, LOCATION_CONSTRAINT_end5)) {
+         goto erret;
+      }
+   }
+   if (ptr -> end3 != NULL) {
+      if ( ! LocationPosConstraintAsnWrite(ptr -> end3, aip, LOCATION_CONSTRAINT_end3)) {
+         goto erret;
+      }
+   }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -5662,6 +5883,356 @@ erret:
 
 /**************************************************
 *
+*    PubFieldSpecialConstraintTypeFree()
+*
+**************************************************/
+NLM_EXTERN 
+PubFieldSpecialConstraintTypePtr LIBCALL
+PubFieldSpecialConstraintTypeFree(ValNodePtr anp)
+{
+   Pointer pnt;
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   default:
+      break;
+   }
+   return MemFree(anp);
+}
+
+
+/**************************************************
+*
+*    PubFieldSpecialConstraintTypeAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+PubFieldSpecialConstraintTypePtr LIBCALL
+PubFieldSpecialConstraintTypeAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Uint1 choice;
+   Boolean isError = FALSE;
+   Boolean nullIsError = FALSE;
+   AsnReadFunc func;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* PubFieldSpecialConstraintType ::= (self contained) */
+      atp = AsnReadId(aip, amp, FIELD_SPECIAL_CONSTRAINT_TYPE);
+   } else {
+      atp = AsnLinkType(orig, FIELD_SPECIAL_CONSTRAINT_TYPE);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp = ValNodeNew(NULL);
+   if (anp == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the CHOICE or OpenStruct value (nothing) */
+      goto erret;
+   }
+
+   func = NULL;
+
+   atp = AsnReadId(aip, amp, atp);  /* find the choice */
+   if (atp == NULL) {
+      goto erret;
+   }
+   if (atp == CONSTRAINT_TYPE_is_present) {
+      choice = PubFieldSpecialConstraintType_is_present;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == CONSTRAINT_TYPE_is_not_present) {
+      choice = PubFieldSpecialConstraintType_is_not_present;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == CONSTRAINT_TYPE_is_all_caps) {
+      choice = PubFieldSpecialConstraintType_is_all_caps;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   anp->choice = choice;
+   if (func != NULL)
+   {
+      anp->data.ptrvalue = (* func)(aip, atp);
+      if (aip -> io_failure) goto erret;
+
+      if (nullIsError && anp->data.ptrvalue == NULL) {
+         goto erret;
+      }
+   }
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   anp = MemFree(anp);
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    PubFieldSpecialConstraintTypeAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+PubFieldSpecialConstraintTypeAsnWrite(PubFieldSpecialConstraintTypePtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp, writetype = NULL;
+   Pointer pnt;
+   AsnWriteFunc func = NULL;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, FIELD_SPECIAL_CONSTRAINT_TYPE);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   if (! AsnWriteChoice(aip, atp, (Int2)anp->choice, &av)) {
+      goto erret;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   case PubFieldSpecialConstraintType_is_present:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, CONSTRAINT_TYPE_is_present, &av);
+      break;
+   case PubFieldSpecialConstraintType_is_not_present:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, CONSTRAINT_TYPE_is_not_present, &av);
+      break;
+   case PubFieldSpecialConstraintType_is_all_caps:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, CONSTRAINT_TYPE_is_all_caps, &av);
+      break;
+   }
+   if (writetype != NULL) {
+      retval = (* func)(pnt, aip, writetype);   /* write it out */
+   }
+   if (!retval) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+/**************************************************
+*
+*    PubFieldSpecialConstraintNew()
+*
+**************************************************/
+NLM_EXTERN 
+PubFieldSpecialConstraintPtr LIBCALL
+PubFieldSpecialConstraintNew(void)
+{
+   PubFieldSpecialConstraintPtr ptr = MemNew((size_t) sizeof(PubFieldSpecialConstraint));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    PubFieldSpecialConstraintFree()
+*
+**************************************************/
+NLM_EXTERN 
+PubFieldSpecialConstraintPtr LIBCALL
+PubFieldSpecialConstraintFree(PubFieldSpecialConstraintPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   PubFieldSpecialConstraintTypeFree(ptr -> constraint);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    PubFieldSpecialConstraintAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+PubFieldSpecialConstraintPtr LIBCALL
+PubFieldSpecialConstraintAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   PubFieldSpecialConstraintPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* PubFieldSpecialConstraint ::= (self contained) */
+      atp = AsnReadId(aip, amp, PUB_FIELD_SPECIAL_CONSTRAINT);
+   } else {
+      atp = AsnLinkType(orig, PUB_FIELD_SPECIAL_CONSTRAINT);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = PubFieldSpecialConstraintNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == FIELD_SPECIAL_CONSTRAINT_field) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> field = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == SPECIAL_CONSTRAINT_constraint) {
+      ptr -> constraint = PubFieldSpecialConstraintTypeAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = PubFieldSpecialConstraintFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    PubFieldSpecialConstraintAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+PubFieldSpecialConstraintAsnWrite(PubFieldSpecialConstraintPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, PUB_FIELD_SPECIAL_CONSTRAINT);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   av.intvalue = ptr -> field;
+   retval = AsnWrite(aip, FIELD_SPECIAL_CONSTRAINT_field,  &av);
+   if (ptr -> constraint != NULL) {
+      if ( ! PubFieldSpecialConstraintTypeAsnWrite(ptr -> constraint, aip, SPECIAL_CONSTRAINT_constraint)) {
+         goto erret;
+      }
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
 *    PublicationConstraintNew()
 *
 **************************************************/
@@ -5690,6 +6261,7 @@ PublicationConstraintFree(PublicationConstraintPtr ptr)
       return NULL;
    }
    PubFieldConstraintFree(ptr -> field);
+   PubFieldSpecialConstraintFree(ptr -> special_field);
    return MemFree(ptr);
 }
 
@@ -5755,6 +6327,13 @@ PublicationConstraintAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == CONSTRAINT_special_field) {
+      ptr -> special_field = PubFieldSpecialConstraintAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -5813,6 +6392,11 @@ PublicationConstraintAsnWrite(PublicationConstraintPtr ptr, AsnIoPtr aip, AsnTyp
          goto erret;
       }
    }
+   if (ptr -> special_field != NULL) {
+      if ( ! PubFieldSpecialConstraintAsnWrite(ptr -> special_field, aip, CONSTRAINT_special_field)) {
+         goto erret;
+      }
+   }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -7141,6 +7725,191 @@ erret:
 
 /**************************************************
 *
+*    QuantityConstraintFree()
+*
+**************************************************/
+NLM_EXTERN 
+QuantityConstraintPtr LIBCALL
+QuantityConstraintFree(ValNodePtr anp)
+{
+   Pointer pnt;
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   default:
+      break;
+   }
+   return MemFree(anp);
+}
+
+
+/**************************************************
+*
+*    QuantityConstraintAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+QuantityConstraintPtr LIBCALL
+QuantityConstraintAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Uint1 choice;
+   Boolean isError = FALSE;
+   Boolean nullIsError = FALSE;
+   AsnReadFunc func;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* QuantityConstraint ::= (self contained) */
+      atp = AsnReadId(aip, amp, QUANTITY_CONSTRAINT);
+   } else {
+      atp = AsnLinkType(orig, QUANTITY_CONSTRAINT);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp = ValNodeNew(NULL);
+   if (anp == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the CHOICE or OpenStruct value (nothing) */
+      goto erret;
+   }
+
+   func = NULL;
+
+   atp = AsnReadId(aip, amp, atp);  /* find the choice */
+   if (atp == NULL) {
+      goto erret;
+   }
+   if (atp == QUANTITY_CONSTRAINT_equals) {
+      choice = QuantityConstraint_equals;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.intvalue = av.intvalue;
+   }
+   else if (atp == CONSTRAINT_greater_than) {
+      choice = QuantityConstraint_greater_than;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.intvalue = av.intvalue;
+   }
+   else if (atp == QUANTITY_CONSTRAINT_less_than) {
+      choice = QuantityConstraint_less_than;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.intvalue = av.intvalue;
+   }
+   anp->choice = choice;
+   if (func != NULL)
+   {
+      anp->data.ptrvalue = (* func)(aip, atp);
+      if (aip -> io_failure) goto erret;
+
+      if (nullIsError && anp->data.ptrvalue == NULL) {
+         goto erret;
+      }
+   }
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   anp = MemFree(anp);
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    QuantityConstraintAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+QuantityConstraintAsnWrite(QuantityConstraintPtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp, writetype = NULL;
+   Pointer pnt;
+   AsnWriteFunc func = NULL;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, QUANTITY_CONSTRAINT);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   if (! AsnWriteChoice(aip, atp, (Int2)anp->choice, &av)) {
+      goto erret;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   case QuantityConstraint_equals:
+      av.intvalue = anp->data.intvalue;
+      retval = AsnWrite(aip, QUANTITY_CONSTRAINT_equals, &av);
+      break;
+   case QuantityConstraint_greater_than:
+      av.intvalue = anp->data.intvalue;
+      retval = AsnWrite(aip, CONSTRAINT_greater_than, &av);
+      break;
+   case QuantityConstraint_less_than:
+      av.intvalue = anp->data.intvalue;
+      retval = AsnWrite(aip, QUANTITY_CONSTRAINT_less_than, &av);
+      break;
+   }
+   if (writetype != NULL) {
+      retval = (* func)(pnt, aip, writetype);   /* write it out */
+   }
+   if (!retval) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+/**************************************************
+*
 *    SequenceConstraintNew()
 *
 **************************************************/
@@ -7170,6 +7939,7 @@ SequenceConstraintFree(SequenceConstraintPtr ptr)
    }
    SequenceConstraintMolTypeConstraintFree(ptr -> seqtype);
    StringConstraintFree(ptr -> id);
+   QuantityConstraintFree(ptr -> num_features);
    return MemFree(ptr);
 }
 
@@ -7242,6 +8012,13 @@ SequenceConstraintAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> feature = av.intvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == CONSTRAINT_num_features) {
+      ptr -> num_features = QuantityConstraintAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -7305,6 +8082,11 @@ SequenceConstraintAsnWrite(SequenceConstraintPtr ptr, AsnIoPtr aip, AsnTypePtr o
    }
    av.intvalue = ptr -> feature;
    retval = AsnWrite(aip, SEQUENCE_CONSTRAINT_feature,  &av);
+   if (ptr -> num_features != NULL) {
+      if ( ! QuantityConstraintAsnWrite(ptr -> num_features, aip, CONSTRAINT_num_features)) {
+         goto erret;
+      }
+   }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -7673,6 +8455,194 @@ erret:
 
 /**************************************************
 *
+*    TextMarkerFree()
+*
+**************************************************/
+NLM_EXTERN 
+TextMarkerPtr LIBCALL
+TextMarkerFree(ValNodePtr anp)
+{
+   Pointer pnt;
+
+   if (anp == NULL) {
+      return NULL;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   default:
+      break;
+   case TextMarker_free_text:
+      MemFree(anp -> data.ptrvalue);
+      break;
+   }
+   return MemFree(anp);
+}
+
+
+/**************************************************
+*
+*    TextMarkerAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+TextMarkerPtr LIBCALL
+TextMarkerAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   ValNodePtr anp;
+   Uint1 choice;
+   Boolean isError = FALSE;
+   Boolean nullIsError = FALSE;
+   AsnReadFunc func;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* TextMarker ::= (self contained) */
+      atp = AsnReadId(aip, amp, TEXT_MARKER);
+   } else {
+      atp = AsnLinkType(orig, TEXT_MARKER);    /* link in local tree */
+   }
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   anp = ValNodeNew(NULL);
+   if (anp == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the CHOICE or OpenStruct value (nothing) */
+      goto erret;
+   }
+
+   func = NULL;
+
+   atp = AsnReadId(aip, amp, atp);  /* find the choice */
+   if (atp == NULL) {
+      goto erret;
+   }
+   if (atp == TEXT_MARKER_free_text) {
+      choice = TextMarker_free_text;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.ptrvalue = av.ptrvalue;
+   }
+   else if (atp == TEXT_MARKER_digits) {
+      choice = TextMarker_digits;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == TEXT_MARKER_letters) {
+      choice = TextMarker_letters;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   anp->choice = choice;
+   if (func != NULL)
+   {
+      anp->data.ptrvalue = (* func)(aip, atp);
+      if (aip -> io_failure) goto erret;
+
+      if (nullIsError && anp->data.ptrvalue == NULL) {
+         goto erret;
+      }
+   }
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return anp;
+
+erret:
+   anp = MemFree(anp);
+   aip -> io_failure = TRUE;
+   goto ret;
+}
+
+
+/**************************************************
+*
+*    TextMarkerAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+TextMarkerAsnWrite(TextMarkerPtr anp, AsnIoPtr aip, AsnTypePtr orig)
+
+{
+   DataVal av;
+   AsnTypePtr atp, writetype = NULL;
+   Pointer pnt;
+   AsnWriteFunc func = NULL;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad())
+      return FALSE;
+   }
+
+   if (aip == NULL)
+   return FALSE;
+
+   atp = AsnLinkType(orig, TEXT_MARKER);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (anp == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+
+   av.ptrvalue = (Pointer)anp;
+   if (! AsnWriteChoice(aip, atp, (Int2)anp->choice, &av)) {
+      goto erret;
+   }
+
+   pnt = anp->data.ptrvalue;
+   switch (anp->choice)
+   {
+   case TextMarker_free_text:
+      av.ptrvalue = anp->data.ptrvalue;
+      retval = AsnWrite(aip, TEXT_MARKER_free_text, &av);
+      break;
+   case TextMarker_digits:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, TEXT_MARKER_digits, &av);
+      break;
+   case TextMarker_letters:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, TEXT_MARKER_letters, &av);
+      break;
+   }
+   if (writetype != NULL) {
+      retval = (* func)(pnt, aip, writetype);   /* write it out */
+   }
+   if (!retval) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+/**************************************************
+*
 *    TextPortionNew()
 *
 **************************************************/
@@ -7702,8 +8672,8 @@ TextPortionFree(TextPortionPtr ptr)
    if(ptr == NULL) {
       return NULL;
    }
-   MemFree(ptr -> left_text);
-   MemFree(ptr -> right_text);
+   TextMarkerFree(ptr -> left_marker);
+   TextMarkerFree(ptr -> right_marker);
    return MemFree(ptr);
 }
 
@@ -7755,11 +8725,11 @@ TextPortionAsnRead(AsnIoPtr aip, AsnTypePtr orig)
    atp = AsnReadId(aip,amp, atp);
    func = NULL;
 
-   if (atp == TEXT_PORTION_left_text) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == TEXT_PORTION_left_marker) {
+      ptr -> left_marker = TextMarkerAsnRead(aip, atp);
+      if (aip -> io_failure) {
          goto erret;
       }
-      ptr -> left_text = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
    if (atp == TEXT_PORTION_include_left) {
@@ -7769,11 +8739,11 @@ TextPortionAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> include_left = av.boolvalue;
       atp = AsnReadId(aip,amp, atp);
    }
-   if (atp == TEXT_PORTION_right_text) {
-      if ( AsnReadVal(aip, atp, &av) <= 0) {
+   if (atp == TEXT_PORTION_right_marker) {
+      ptr -> right_marker = TextMarkerAsnRead(aip, atp);
+      if (aip -> io_failure) {
          goto erret;
       }
-      ptr -> right_text = av.ptrvalue;
       atp = AsnReadId(aip,amp, atp);
    }
    if (atp == TEXT_PORTION_include_right) {
@@ -7855,15 +8825,17 @@ TextPortionAsnWrite(TextPortionPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
       goto erret;
    }
 
-   if (ptr -> left_text != NULL) {
-      av.ptrvalue = ptr -> left_text;
-      retval = AsnWrite(aip, TEXT_PORTION_left_text,  &av);
+   if (ptr -> left_marker != NULL) {
+      if ( ! TextMarkerAsnWrite(ptr -> left_marker, aip, TEXT_PORTION_left_marker)) {
+         goto erret;
+      }
    }
    av.boolvalue = ptr -> include_left;
    retval = AsnWrite(aip, TEXT_PORTION_include_left,  &av);
-   if (ptr -> right_text != NULL) {
-      av.ptrvalue = ptr -> right_text;
-      retval = AsnWrite(aip, TEXT_PORTION_right_text,  &av);
+   if (ptr -> right_marker != NULL) {
+      if ( ! TextMarkerAsnWrite(ptr -> right_marker, aip, TEXT_PORTION_right_marker)) {
+         goto erret;
+      }
    }
    av.boolvalue = ptr -> include_right;
    retval = AsnWrite(aip, TEXT_PORTION_include_right,  &av);
@@ -8639,6 +9611,7 @@ ConvertActionNew(void)
 
    ptr -> strip_name = 0;
    ptr -> keep_original = 0;
+   ptr -> capitalization = 0;
    return ptr;
 
 }
@@ -8730,6 +9703,13 @@ ConvertActionAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> keep_original = av.boolvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == CONVERT_ACTION_capitalization) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> capitalization = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
    if (atp == CONVERT_ACTION_existing_text) {
       if ( AsnReadVal(aip, atp, &av) <= 0) {
          goto erret;
@@ -8797,6 +9777,8 @@ ConvertActionAsnWrite(ConvertActionPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
    retval = AsnWrite(aip, CONVERT_ACTION_strip_name,  &av);
    av.boolvalue = ptr -> keep_original;
    retval = AsnWrite(aip, CONVERT_ACTION_keep_original,  &av);
+   av.intvalue = ptr -> capitalization;
+   retval = AsnWrite(aip, CONVERT_ACTION_capitalization,  &av);
    av.intvalue = ptr -> existing_text;
    retval = AsnWrite(aip, CONVERT_ACTION_existing_text,  &av);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
@@ -10948,6 +11930,13 @@ LocationChoiceAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       anp->data.boolvalue = av.boolvalue;
    }
+   else if (atp == LOCATION_CHOICE_point) {
+      choice = LocationChoice_point;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.intvalue = av.intvalue;
+   }
    anp->choice = choice;
    if (func != NULL)
    {
@@ -11017,6 +12006,10 @@ LocationChoiceAsnWrite(LocationChoicePtr anp, AsnIoPtr aip, AsnTypePtr orig)
       av.boolvalue = anp->data.boolvalue;
       retval = AsnWrite(aip, LOCATION_CHOICE_whole_sequence, &av);
       break;
+   case LocationChoice_point:
+      av.intvalue = anp->data.intvalue;
+      retval = AsnWrite(aip, LOCATION_CHOICE_point, &av);
+      break;
    }
    if (writetype != NULL) {
       retval = (* func)(pnt, aip, writetype);   /* write it out */
@@ -13264,6 +14257,20 @@ LocationEditTypeAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       anp->data.intvalue = av.intvalue;
    }
+   else if (atp == LOCATION_EDIT_TYPE_extend_5) {
+      choice = LocationEditType_extend_5;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == LOCATION_EDIT_TYPE_extend_3) {
+      choice = LocationEditType_extend_3;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
    anp->choice = choice;
    if (func != NULL)
    {
@@ -13349,6 +14356,14 @@ LocationEditTypeAsnWrite(LocationEditTypePtr anp, AsnIoPtr aip, AsnTypePtr orig)
       av.intvalue = anp->data.intvalue;
       retval = AsnWrite(aip, LOCATION_EDIT_TYPE_convert, &av);
       break;
+   case LocationEditType_extend_5:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, LOCATION_EDIT_TYPE_extend_5, &av);
+      break;
+   case LocationEditType_extend_3:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, LOCATION_EDIT_TYPE_extend_3, &av);
+      break;
    }
    if (writetype != NULL) {
       retval = (* func)(pnt, aip, writetype);   /* write it out */
@@ -14052,6 +15067,189 @@ erret:
 
 /**************************************************
 *
+*    FixPubCapsActionNew()
+*
+**************************************************/
+NLM_EXTERN 
+FixPubCapsActionPtr LIBCALL
+FixPubCapsActionNew(void)
+{
+   FixPubCapsActionPtr ptr = MemNew((size_t) sizeof(FixPubCapsAction));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    FixPubCapsActionFree()
+*
+**************************************************/
+NLM_EXTERN 
+FixPubCapsActionPtr LIBCALL
+FixPubCapsActionFree(FixPubCapsActionPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   ConstraintChoiceSetFree(ptr -> constraint);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    FixPubCapsActionAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+FixPubCapsActionPtr LIBCALL
+FixPubCapsActionAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   FixPubCapsActionPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* FixPubCapsAction ::= (self contained) */
+      atp = AsnReadId(aip, amp, FIX_PUB_CAPS_ACTION);
+   } else {
+      atp = AsnLinkType(orig, FIX_PUB_CAPS_ACTION);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = FixPubCapsActionNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == FIX_PUB_CAPS_ACTION_title) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> title = av.boolvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == FIX_PUB_CAPS_ACTION_authors) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> authors = av.boolvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == FIX_PUB_CAPS_ACTION_affiliation) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> affiliation = av.boolvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == FIX_PUB_CAPS_ACTION_constraint) {
+      ptr -> constraint = ConstraintChoiceSetAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = FixPubCapsActionFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    FixPubCapsActionAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+FixPubCapsActionAsnWrite(FixPubCapsActionPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objmacroAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, FIX_PUB_CAPS_ACTION);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   av.boolvalue = ptr -> title;
+   retval = AsnWrite(aip, FIX_PUB_CAPS_ACTION_title,  &av);
+   av.boolvalue = ptr -> authors;
+   retval = AsnWrite(aip, FIX_PUB_CAPS_ACTION_authors,  &av);
+   av.boolvalue = ptr -> affiliation;
+   retval = AsnWrite(aip, FIX_PUB_CAPS_ACTION_affiliation,  &av);
+   if (ptr -> constraint != NULL) {
+      if ( ! ConstraintChoiceSetAsnWrite(ptr -> constraint, aip, FIX_PUB_CAPS_ACTION_constraint)) {
+         goto erret;
+      }
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
 *    MacroActionChoiceFree()
 *
 **************************************************/
@@ -14094,6 +15292,9 @@ MacroActionChoiceFree(ValNodePtr anp)
    case MacroActionChoice_autodef:
       AutodefActionFree(anp -> data.ptrvalue);
       break;
+   case MacroActionChoice_fix_pub_caps:
+      FixPubCapsActionFree(anp -> data.ptrvalue);
+      break;
    }
    return MemFree(anp);
 }
@@ -14182,6 +15383,59 @@ MacroActionChoiceAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       choice = MacroActionChoice_autodef;
       func = (AsnReadFunc) AutodefActionAsnRead;
    }
+   else if (atp == MACRO_ACTION_CHOICE_removesets) {
+      choice = MacroActionChoice_removesets;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == trim_junk_from_primer_seq) {
+      choice = MacroActionChoice_trim_junk_from_primer_seq;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == trim_stop_from_complete_cds) {
+      choice = MacroActionChoice_trim_stop_from_complete_cds;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == CHOICE_fix_usa_and_states) {
+      choice = MacroActionChoice_fix_usa_and_states;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == synchronize_cds_partials) {
+      choice = MacroActionChoice_synchronize_cds_partials;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == adjust_for_consensus_splice) {
+      choice = MacroActionChoice_adjust_for_consensus_splice;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
+   else if (atp == ACTION_CHOICE_fix_pub_caps) {
+      choice = MacroActionChoice_fix_pub_caps;
+      func = (AsnReadFunc) FixPubCapsActionAsnRead;
+   }
+   else if (atp == ACTION_CHOICE_remove_seg_gaps) {
+      choice = MacroActionChoice_remove_seg_gaps;
+      if (AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      anp->data.boolvalue = av.boolvalue;
+   }
    anp->choice = choice;
    if (func != NULL)
    {
@@ -14275,6 +15529,38 @@ MacroActionChoiceAsnWrite(MacroActionChoicePtr anp, AsnIoPtr aip, AsnTypePtr ori
       writetype = MACRO_ACTION_CHOICE_autodef;
       func = (AsnWriteFunc) AutodefActionAsnWrite;
       break;
+   case MacroActionChoice_removesets:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, MACRO_ACTION_CHOICE_removesets, &av);
+      break;
+   case MacroActionChoice_trim_junk_from_primer_seq:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, trim_junk_from_primer_seq, &av);
+      break;
+   case MacroActionChoice_trim_stop_from_complete_cds:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, trim_stop_from_complete_cds, &av);
+      break;
+   case MacroActionChoice_fix_usa_and_states:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, CHOICE_fix_usa_and_states, &av);
+      break;
+   case MacroActionChoice_synchronize_cds_partials:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, synchronize_cds_partials, &av);
+      break;
+   case MacroActionChoice_adjust_for_consensus_splice:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, adjust_for_consensus_splice, &av);
+      break;
+   case MacroActionChoice_fix_pub_caps:
+      writetype = ACTION_CHOICE_fix_pub_caps;
+      func = (AsnWriteFunc) FixPubCapsActionAsnWrite;
+      break;
+   case MacroActionChoice_remove_seg_gaps:
+      av.boolvalue = anp->data.boolvalue;
+      retval = AsnWrite(aip, ACTION_CHOICE_remove_seg_gaps, &av);
+      break;
    }
    if (writetype != NULL) {
       retval = (* func)(pnt, aip, writetype);   /* write it out */
diff --git a/object/objmacro.h b/object/objmacro.h
index 0888ba6..44d4b4f 100755
--- a/object/objmacro.h
+++ b/object/objmacro.h
@@ -17,7 +17,7 @@ extern "C" { /* } */
 /**************************************************
 *
 *    Generated objects for Module NCBI-Macro
-*    Generated using ASNCODE Revision: 6.16 at May 12, 2009  9:09 AM
+*    Generated using ASNCODE Revision: 6.17 at Jul 26, 2010  2:39 PM
 *
 **************************************************/
 
@@ -127,6 +127,23 @@ NLM_EXTERN Boolean LIBCALL StringConstraintAsnWrite PROTO (( StringConstraintPtr
 #define Partial_constraint_partial 1
 #define Partial_constraint_complete 2
 
+/* following #defines are for enumerated type, not used by object loaders */
+#define Location_type_constraint_any 0
+#define Location_type_constraint_single_interval 1
+#define Location_type_constraint_joined 2
+#define Location_type_constraint_ordered 3
+
+typedef ValNodePtr LocationPosConstraintPtr;
+typedef ValNode LocationPosConstraint;
+#define LocationPosConstraint_dist_from_end 1
+#define LocationPosConstraint_max_dist_from_end 2
+#define LocationPosConstraint_min_dist_from_end 3
+
+
+NLM_EXTERN LocationPosConstraintPtr LIBCALL LocationPosConstraintFree PROTO ((LocationPosConstraintPtr ));
+NLM_EXTERN LocationPosConstraintPtr LIBCALL LocationPosConstraintAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL LocationPosConstraintAsnWrite PROTO (( LocationPosConstraintPtr , AsnIoPtr, AsnTypePtr));
+
 
 
 /**************************************************
@@ -139,6 +156,9 @@ typedef struct struct_Location_constraint {
    Uint2   seq_type;
    Uint2   partial5;
    Uint2   partial3;
+   Uint2   location_type;
+   ValNodePtr   end5;
+   ValNodePtr   end3;
 } LocationConstraint, PNTR LocationConstraintPtr;
 
 
@@ -316,6 +336,8 @@ NLM_EXTERN Boolean LIBCALL LocationConstraintAsnWrite PROTO (( LocationConstrain
 #define Feat_qual_legal_satellite 65
 #define Feat_qual_legal_satellite_type 66
 #define Feat_qual_legal_satellite_name 67
+#define Feat_qual_legal_location 68
+#define Feat_qual_legal_tag_peptide 69
 
 
 
@@ -457,6 +479,7 @@ NLM_EXTERN Boolean LIBCALL RnaFeatTypeAsnWrite PROTO (( RnaFeatTypePtr , AsnIoPt
 #define Rna_field_gene_locus_tag 10
 #define Rna_field_gene_synonym 11
 #define Rna_field_gene_comment 12
+#define Rna_field_tag_peptide 13
 
 
 
@@ -1066,6 +1089,35 @@ NLM_EXTERN PubFieldConstraintPtr LIBCALL PubFieldConstraintNew PROTO (( void ));
 NLM_EXTERN PubFieldConstraintPtr LIBCALL PubFieldConstraintAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
 NLM_EXTERN Boolean LIBCALL PubFieldConstraintAsnWrite PROTO (( PubFieldConstraintPtr , AsnIoPtr, AsnTypePtr));
 
+typedef ValNodePtr PubFieldSpecialConstraintTypePtr;
+typedef ValNode PubFieldSpecialConstraintType;
+#define PubFieldSpecialConstraintType_is_present 1
+#define PubFieldSpecialConstraintType_is_not_present 2
+#define PubFieldSpecialConstraintType_is_all_caps 3
+
+
+NLM_EXTERN PubFieldSpecialConstraintTypePtr LIBCALL PubFieldSpecialConstraintTypeFree PROTO ((PubFieldSpecialConstraintTypePtr ));
+NLM_EXTERN PubFieldSpecialConstraintTypePtr LIBCALL PubFieldSpecialConstraintTypeAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL PubFieldSpecialConstraintTypeAsnWrite PROTO (( PubFieldSpecialConstraintTypePtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    PubFieldSpecialConstraint
+*
+**************************************************/
+typedef struct struct_Pub_field_special_constraint {
+   Uint2   field;
+   ValNodePtr   constraint;
+} PubFieldSpecialConstraint, PNTR PubFieldSpecialConstraintPtr;
+
+
+NLM_EXTERN PubFieldSpecialConstraintPtr LIBCALL PubFieldSpecialConstraintFree PROTO ((PubFieldSpecialConstraintPtr ));
+NLM_EXTERN PubFieldSpecialConstraintPtr LIBCALL PubFieldSpecialConstraintNew PROTO (( void ));
+NLM_EXTERN PubFieldSpecialConstraintPtr LIBCALL PubFieldSpecialConstraintAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL PubFieldSpecialConstraintAsnWrite PROTO (( PubFieldSpecialConstraintPtr , AsnIoPtr, AsnTypePtr));
+
 
 
 /**************************************************
@@ -1076,6 +1128,7 @@ NLM_EXTERN Boolean LIBCALL PubFieldConstraintAsnWrite PROTO (( PubFieldConstrain
 typedef struct struct_Publication_constraint {
    Uint2   type;
    struct struct_Pub_field_constraint PNTR   field;
+   struct struct_Pub_field_special_constraint PNTR   special_field;
 } PublicationConstraint, PNTR PublicationConstraintPtr;
 
 
@@ -1218,6 +1271,17 @@ NLM_EXTERN SequenceConstraintMolTypeConstraintPtr LIBCALL SequenceConstraintMolT
 NLM_EXTERN SequenceConstraintMolTypeConstraintPtr LIBCALL SequenceConstraintMolTypeConstraintAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
 NLM_EXTERN Boolean LIBCALL SequenceConstraintMolTypeConstraintAsnWrite PROTO (( SequenceConstraintMolTypeConstraintPtr , AsnIoPtr, AsnTypePtr));
 
+typedef ValNodePtr QuantityConstraintPtr;
+typedef ValNode QuantityConstraint;
+#define QuantityConstraint_equals 1
+#define QuantityConstraint_greater_than 2
+#define QuantityConstraint_less_than 3
+
+
+NLM_EXTERN QuantityConstraintPtr LIBCALL QuantityConstraintFree PROTO ((QuantityConstraintPtr ));
+NLM_EXTERN QuantityConstraintPtr LIBCALL QuantityConstraintAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL QuantityConstraintAsnWrite PROTO (( QuantityConstraintPtr , AsnIoPtr, AsnTypePtr));
+
 
 
 /**************************************************
@@ -1229,6 +1293,7 @@ typedef struct struct_Sequence_constraint {
    ValNodePtr   seqtype;
    struct struct_String_constraint PNTR   id;
    Uint2   feature;
+   ValNodePtr   num_features;
 } SequenceConstraint, PNTR SequenceConstraintPtr;
 
 
@@ -1273,6 +1338,17 @@ NLM_EXTERN Boolean LIBCALL ConstraintChoiceSetAsnWrite PROTO (( ConstraintChoice
 
 #endif /* NLM_GENERATED_CODE_PROTO */
 
+typedef ValNodePtr TextMarkerPtr;
+typedef ValNode TextMarker;
+#define TextMarker_free_text 1
+#define TextMarker_digits 2
+#define TextMarker_letters 3
+
+
+NLM_EXTERN TextMarkerPtr LIBCALL TextMarkerFree PROTO ((TextMarkerPtr ));
+NLM_EXTERN TextMarkerPtr LIBCALL TextMarkerAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL TextMarkerAsnWrite PROTO (( TextMarkerPtr , AsnIoPtr, AsnTypePtr));
+
 
 
 /**************************************************
@@ -1281,9 +1357,9 @@ NLM_EXTERN Boolean LIBCALL ConstraintChoiceSetAsnWrite PROTO (( ConstraintChoice
 *
 **************************************************/
 typedef struct struct_Text_portion {
-   CharPtr   left_text;
+   ValNodePtr   left_marker;
    Uint1   include_left;
-   CharPtr   right_text;
+   ValNodePtr   right_marker;
    Uint1   include_right;
    Uint1   inside;
    Uint1   case_sensitive;
@@ -1386,6 +1462,13 @@ NLM_EXTERN EditActionPtr LIBCALL EditActionNew PROTO (( void ));
 NLM_EXTERN EditActionPtr LIBCALL EditActionAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
 NLM_EXTERN Boolean LIBCALL EditActionAsnWrite PROTO (( EditActionPtr , AsnIoPtr, AsnTypePtr));
 
+/* following #defines are for enumerated type, not used by object loaders */
+#define Cap_change_none 0
+#define Cap_change_tolower 1
+#define Cap_change_toupper 2
+#define Cap_change_firstcap 3
+#define Cap_change_firstcaprestnochange 4
+
 
 
 /**************************************************
@@ -1397,6 +1480,7 @@ typedef struct struct_Convert_action {
    ValNodePtr   fields;
    Uint1   strip_name;
    Uint1   keep_original;
+   Uint2   capitalization;
    Uint2   existing_text;
 } ConvertAction, PNTR ConvertActionPtr;
 
@@ -1496,12 +1580,6 @@ NLM_EXTERN ActionChoicePtr LIBCALL ActionChoiceFree PROTO ((ActionChoicePtr ));
 NLM_EXTERN ActionChoicePtr LIBCALL ActionChoiceAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
 NLM_EXTERN Boolean LIBCALL ActionChoiceAsnWrite PROTO (( ActionChoicePtr , AsnIoPtr, AsnTypePtr));
 
-/* following #defines are for enumerated type, not used by object loaders */
-#define Cap_change_none 0
-#define Cap_change_tolower 1
-#define Cap_change_toupper 2
-#define Cap_change_firstcap 3
-
 typedef ValNodePtr ParseSrcOrgChoicePtr;
 typedef ValNode ParseSrcOrgChoice;
 #define ParseSrcOrgChoice_source_qual 1
@@ -1599,6 +1677,7 @@ typedef ValNodePtr LocationChoicePtr;
 typedef ValNode LocationChoice;
 #define LocationChoice_interval 1
 #define LocationChoice_whole_sequence 2
+#define LocationChoice_point 3
 
 
 NLM_EXTERN LocationChoicePtr LIBCALL LocationChoiceFree PROTO ((LocationChoicePtr ));
@@ -1899,6 +1978,8 @@ typedef ValNode LocationEditType;
 #define LocationEditType_set_3_partial 4
 #define LocationEditType_clear_3_partial 5
 #define LocationEditType_convert 6
+#define LocationEditType_extend_5 7
+#define LocationEditType_extend_3 8
 
 
 NLM_EXTERN LocationEditTypePtr LIBCALL LocationEditTypeFree PROTO ((LocationEditTypePtr ));
@@ -1998,6 +2079,26 @@ NLM_EXTERN AutodefActionPtr LIBCALL AutodefActionNew PROTO (( void ));
 NLM_EXTERN AutodefActionPtr LIBCALL AutodefActionAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
 NLM_EXTERN Boolean LIBCALL AutodefActionAsnWrite PROTO (( AutodefActionPtr , AsnIoPtr, AsnTypePtr));
 
+
+
+/**************************************************
+*
+*    FixPubCapsAction
+*
+**************************************************/
+typedef struct struct_Fix_pub_caps_action {
+   Uint1   title;
+   Uint1   authors;
+   Uint1   affiliation;
+   ValNodePtr   constraint;
+} FixPubCapsAction, PNTR FixPubCapsActionPtr;
+
+
+NLM_EXTERN FixPubCapsActionPtr LIBCALL FixPubCapsActionFree PROTO ((FixPubCapsActionPtr ));
+NLM_EXTERN FixPubCapsActionPtr LIBCALL FixPubCapsActionNew PROTO (( void ));
+NLM_EXTERN FixPubCapsActionPtr LIBCALL FixPubCapsActionAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL FixPubCapsActionAsnWrite PROTO (( FixPubCapsActionPtr , AsnIoPtr, AsnTypePtr));
+
 typedef ValNodePtr MacroActionChoicePtr;
 typedef ValNode MacroActionChoice;
 #define MacroActionChoice_aecr 1
@@ -2008,6 +2109,14 @@ typedef ValNode MacroActionChoice;
 #define MacroActionChoice_edit_location 6
 #define MacroActionChoice_remove_descriptor 7
 #define MacroActionChoice_autodef 8
+#define MacroActionChoice_removesets 9
+#define MacroActionChoice_trim_junk_from_primer_seq 10
+#define MacroActionChoice_trim_stop_from_complete_cds 11
+#define MacroActionChoice_fix_usa_and_states 12
+#define MacroActionChoice_synchronize_cds_partials 13
+#define MacroActionChoice_adjust_for_consensus_splice 14
+#define MacroActionChoice_fix_pub_caps 15
+#define MacroActionChoice_remove_seg_gaps 16
 
 
 NLM_EXTERN MacroActionChoicePtr LIBCALL MacroActionChoiceFree PROTO ((MacroActionChoicePtr ));
diff --git a/object/objmedli.c b/object/objmedli.c
index 3f085a2..0333dfa 100644
--- a/object/objmedli.c
+++ b/object/objmedli.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 1/1/91
 *
-* $Revision: 6.4 $
+* $Revision: 6.5 $
 *
 * File Description:  Object manager for module NCBI-Medline
 *
@@ -41,6 +41,9 @@
 *
 *
 * $Log: objmedli.c,v $
+* Revision 6.5  2009/10/02 19:44:49  kans
+* address clang static analyzer warnings
+*
 * Revision 6.4  1998/08/26 17:43:17  kans
 * fixed -v -fd warnings in label functions
 *
@@ -223,7 +226,7 @@ NLM_EXTERN MedlineMeshPtr LIBCALL MedlineMeshAsnRead (AsnIoPtr aip, AsnTypePtr o
 	MedlineMeshPtr mmp=NULL;
 	DataVal av;
 	AsnTypePtr atp, oldatp;
-    ValNodePtr first, anp;
+    ValNodePtr first, anp = NULL;
 
 	if (! loaded)
 	{
@@ -740,7 +743,7 @@ NLM_EXTERN MedlineEntryPtr LIBCALL MedlineEntryAsnRead (AsnIoPtr aip, AsnTypePtr
                 if (anp == NULL) goto erret;
                 if (mep->xref == NULL)
                     mep->xref = anp;
-                else
+                else if (anplast != NULL)
                     anplast->next = anp;
                 anplast = anp;
             }
diff --git a/object/objpub.c b/object/objpub.c
index e6ad239..0831528 100644
--- a/object/objpub.c
+++ b/object/objpub.c
@@ -29,7 +29,7 @@
 *   
 * Version Creation Date: 4/1/91
 *
-* $Revision: 6.7 $
+* $Revision: 6.9 $
 *
 * File Description:  Object manager for module NCBI-Pub
 *
@@ -41,6 +41,12 @@
 *
 *
 * $Log: objpub.c,v $
+* Revision 6.9  2010/03/09 16:56:39  bollin
+* Include Medline/PMID in Medline article formatting.
+*
+* Revision 6.8  2009/10/02 19:44:49  kans
+* address clang static analyzer warnings
+*
 * Revision 6.7  2005/12/29 13:46:18  bollin
 * added PubdescContentMatch function
 *
@@ -536,8 +542,8 @@ NLM_EXTERN ValNodePtr LIBCALL PubAsnRead (AsnIoPtr aip, AsnTypePtr orig)
 	DataVal av;
 	AsnTypePtr atp;
     ValNodePtr anp=NULL;
-    Uint1 choice;
-    AsnReadFunc func;
+    Uint1 choice = 0;
+    AsnReadFunc func = NULL;
 
 	if (! loaded)
 	{
@@ -628,7 +634,7 @@ NLM_EXTERN ValNodePtr LIBCALL PubAsnRead (AsnIoPtr aip, AsnTypePtr orig)
     }
 
     anp->choice = choice;
-    if ((choice != 4) && (choice != 13))
+    if ((choice != 4) && (choice != 13) && func != NULL)
     {
         anp->data.ptrvalue = (* func)(aip, atp);
         if (anp->data.ptrvalue == NULL) goto erret;
@@ -685,10 +691,10 @@ NLM_EXTERN ValNodePtr LIBCALL PubSetFree (ValNodePtr anp)
 NLM_EXTERN Boolean LIBCALL PubSetAsnWrite (ValNodePtr anp, AsnIoPtr aip, AsnTypePtr orig)
 {
 	DataVal av;
-	AsnTypePtr atp, settype, elementtype;
+	AsnTypePtr atp, settype = NULL, elementtype;
     Pointer pnt;
     Uint1 choice;
-    AsnWriteFunc func;
+    AsnWriteFunc func = NULL;
 	ValNodePtr oldanp;
     Boolean retval = FALSE;
 
@@ -760,7 +766,9 @@ NLM_EXTERN Boolean LIBCALL PubSetAsnWrite (ValNodePtr anp, AsnIoPtr aip, AsnType
             pnt = (Pointer)anp;
         else
             pnt = anp->data.ptrvalue;
+        if (func != NULL) {
         if (! (*func)(pnt, aip, elementtype)) goto erret;
+        }
         anp = anp->next;
     }
     
@@ -1458,7 +1466,7 @@ NLM_EXTERN Int2 LIBCALL PubLabelUnique (ValNodePtr pub, CharPtr buf, Int2 buflen
 			else
 				sprintf(tbuf, "NLM%ld", (long)(mep->uid));
 			diff = LabelCopyExtra(buf, tbuf, buflen, NULL, " ");
-			buflen -= diff;
+		  buflen -= diff; buf += diff;
 			cap = mep->cit;
 			goto cit_art;
 		case PUB_Article:
diff --git a/object/objvalid.c b/object/objvalid.c
index 76ab137..8428a51 100644
--- a/object/objvalid.c
+++ b/object/objvalid.c
@@ -31,7 +31,7 @@ objvalidAsnLoad(void)
 
 /**************************************************
 *    Generated object loaders for Module NCBI-Structured-comment-validation
-*    Generated using ASNCODE Revision: 6.16 at Apr 7, 2009  1:38 PM
+*    Generated using ASNCODE Revision: 6.16 at Dec 11, 2009  7:16 AM
 *
 **************************************************/
 
@@ -48,6 +48,7 @@ FieldRuleNew(void)
    FieldRulePtr ptr = MemNew((size_t) sizeof(FieldRule));
 
    ptr -> required = 0;
+   ptr -> severity = 2;
    return ptr;
 
 }
@@ -140,6 +141,13 @@ FieldRuleAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       ptr -> required = av.boolvalue;
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == FIELD_RULE_severity) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> severity = av.intvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -201,6 +209,8 @@ FieldRuleAsnWrite(FieldRulePtr ptr, AsnIoPtr aip, AsnTypePtr orig)
    }
    av.boolvalue = ptr -> required;
    retval = AsnWrite(aip, FIELD_RULE_required,  &av);
+   av.intvalue = ptr -> severity;
+   retval = AsnWrite(aip, FIELD_RULE_severity,  &av);
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
@@ -329,6 +339,313 @@ erret:
 
 /**************************************************
 *
+*    DependentFieldRuleNew()
+*
+**************************************************/
+NLM_EXTERN 
+DependentFieldRulePtr LIBCALL
+DependentFieldRuleNew(void)
+{
+   DependentFieldRulePtr ptr = MemNew((size_t) sizeof(DependentFieldRule));
+
+   return ptr;
+
+}
+
+
+/**************************************************
+*
+*    DependentFieldRuleFree()
+*
+**************************************************/
+NLM_EXTERN 
+DependentFieldRulePtr LIBCALL
+DependentFieldRuleFree(DependentFieldRulePtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   MemFree(ptr -> match_name);
+   MemFree(ptr -> value_constraint);
+   FieldSetFree(ptr -> other_fields);
+   FieldSetFree(ptr -> disallowed_fields);
+   return MemFree(ptr);
+}
+
+
+/**************************************************
+*
+*    DependentFieldRuleAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+DependentFieldRulePtr LIBCALL
+DependentFieldRuleAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   DependentFieldRulePtr ptr;
+
+   if (! loaded)
+   {
+      if (! objvalidAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* DependentFieldRule ::= (self contained) */
+      atp = AsnReadId(aip, amp, DEPENDENT_FIELD_RULE);
+   } else {
+      atp = AsnLinkType(orig, DEPENDENT_FIELD_RULE);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   ptr = DependentFieldRuleNew();
+   if (ptr == NULL) {
+      goto erret;
+   }
+   if (AsnReadVal(aip, atp, &av) <= 0) { /* read the start struct */
+      goto erret;
+   }
+
+   atp = AsnReadId(aip,amp, atp);
+   func = NULL;
+
+   if (atp == DEPENDENT_FIELD_RULE_match_name) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> match_name = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == FIELD_RULE_value_constraint) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> value_constraint = av.ptrvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == FIELD_RULE_other_fields) {
+      ptr -> other_fields = FieldSetAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == FIELD_RULE_disallowed_fields) {
+      ptr -> disallowed_fields = FieldSetAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
+
+   if (AsnReadVal(aip, atp, &av) <= 0) {
+      goto erret;
+   }
+   /* end struct */
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = DependentFieldRuleFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    DependentFieldRuleAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+DependentFieldRuleAsnWrite(DependentFieldRulePtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objvalidAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, DEPENDENT_FIELD_RULE);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   if (! AsnOpenStruct(aip, atp, (Pointer) ptr)) {
+      goto erret;
+   }
+
+   if (ptr -> match_name != NULL) {
+      av.ptrvalue = ptr -> match_name;
+      retval = AsnWrite(aip, DEPENDENT_FIELD_RULE_match_name,  &av);
+   }
+   if (ptr -> value_constraint != NULL) {
+      av.ptrvalue = ptr -> value_constraint;
+      retval = AsnWrite(aip, FIELD_RULE_value_constraint,  &av);
+   }
+   if (ptr -> other_fields != NULL) {
+      if ( ! FieldSetAsnWrite(ptr -> other_fields, aip, FIELD_RULE_other_fields)) {
+         goto erret;
+      }
+   }
+   if (ptr -> disallowed_fields != NULL) {
+      if ( ! FieldSetAsnWrite(ptr -> disallowed_fields, aip, FIELD_RULE_disallowed_fields)) {
+         goto erret;
+      }
+   }
+   if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
+      goto erret;
+   }
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
+*    DependentFieldSetFree()
+*
+**************************************************/
+NLM_EXTERN 
+DependentFieldSetPtr LIBCALL
+DependentFieldSetFree(DependentFieldSetPtr ptr)
+{
+
+   if(ptr == NULL) {
+      return NULL;
+   }
+   AsnGenericUserSeqOfFree(ptr,  (AsnOptFreeFunc) DependentFieldRuleFree);
+   return NULL;
+}
+
+
+/**************************************************
+*
+*    DependentFieldSetAsnRead()
+*
+**************************************************/
+NLM_EXTERN 
+DependentFieldSetPtr LIBCALL
+DependentFieldSetAsnRead(AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean isError = FALSE;
+   AsnReadFunc func;
+   DependentFieldSetPtr ptr;
+
+   if (! loaded)
+   {
+      if (! objvalidAsnLoad()) {
+         return NULL;
+      }
+   }
+
+   if (aip == NULL) {
+      return NULL;
+   }
+
+   if (orig == NULL) {         /* DependentFieldSet ::= (self contained) */
+      atp = AsnReadId(aip, amp, DEPENDENT_FIELD_SET);
+   } else {
+      atp = AsnLinkType(orig, DEPENDENT_FIELD_SET);
+   }
+   /* link in local tree */
+   if (atp == NULL) {
+      return NULL;
+   }
+
+   func = NULL;
+
+   ptr  = AsnGenericUserSeqOfAsnRead(aip, amp, atp, &isError, (AsnReadFunc) DependentFieldRuleAsnRead, (AsnOptFreeFunc) DependentFieldRuleFree);
+   if (isError && ptr  == NULL) {
+      goto erret;
+   }
+
+
+
+ret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return ptr;
+
+erret:
+   aip -> io_failure = TRUE;
+   ptr = DependentFieldSetFree(ptr);
+   goto ret;
+}
+
+
+
+/**************************************************
+*
+*    DependentFieldSetAsnWrite()
+*
+**************************************************/
+NLM_EXTERN Boolean LIBCALL 
+DependentFieldSetAsnWrite(DependentFieldSetPtr ptr, AsnIoPtr aip, AsnTypePtr orig)
+{
+   DataVal av;
+   AsnTypePtr atp;
+   Boolean retval = FALSE;
+
+   if (! loaded)
+   {
+      if (! objvalidAsnLoad()) {
+         return FALSE;
+      }
+   }
+
+   if (aip == NULL) {
+      return FALSE;
+   }
+
+   atp = AsnLinkType(orig, DEPENDENT_FIELD_SET);   /* link local tree */
+   if (atp == NULL) {
+      return FALSE;
+   }
+
+   if (ptr == NULL) { AsnNullValueMsg(aip, atp); goto erret; }
+   retval = AsnGenericUserSeqOfAsnWrite(ptr , (AsnWriteFunc) DependentFieldRuleAsnWrite, aip, atp, DEPENDENT_FIELD_SET_E);
+   retval = TRUE;
+
+erret:
+   AsnUnlinkType(orig);       /* unlink local tree */
+   return retval;
+}
+
+
+
+/**************************************************
+*
 *    CommentRuleNew()
 *
 **************************************************/
@@ -339,6 +656,8 @@ CommentRuleNew(void)
    CommentRulePtr ptr = MemNew((size_t) sizeof(CommentRule));
 
    ptr -> updated = 0;
+   ptr -> require_order = 1;
+   ptr -> allow_unlisted = 0;
    return ptr;
 
 }
@@ -359,6 +678,7 @@ CommentRuleFree(CommentRulePtr ptr)
    }
    MemFree(ptr -> prefix);
    FieldSetFree(ptr -> fields);
+   DependentFieldSetFree(ptr -> dependent_rules);
    return MemFree(ptr);
 }
 
@@ -431,6 +751,27 @@ CommentRuleAsnRead(AsnIoPtr aip, AsnTypePtr orig)
       }
       atp = AsnReadId(aip,amp, atp);
    }
+   if (atp == COMMENT_RULE_require_order) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> require_order = av.boolvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == COMMENT_RULE_allow_unlisted) {
+      if ( AsnReadVal(aip, atp, &av) <= 0) {
+         goto erret;
+      }
+      ptr -> allow_unlisted = av.boolvalue;
+      atp = AsnReadId(aip,amp, atp);
+   }
+   if (atp == COMMENT_RULE_dependent_rules) {
+      ptr -> dependent_rules = DependentFieldSetAsnRead(aip, atp);
+      if (aip -> io_failure) {
+         goto erret;
+      }
+      atp = AsnReadId(aip,amp, atp);
+   }
 
    if (AsnReadVal(aip, atp, &av) <= 0) {
       goto erret;
@@ -493,6 +834,15 @@ CommentRuleAsnWrite(CommentRulePtr ptr, AsnIoPtr aip, AsnTypePtr orig)
          goto erret;
       }
    }
+   av.boolvalue = ptr -> require_order;
+   retval = AsnWrite(aip, COMMENT_RULE_require_order,  &av);
+   av.boolvalue = ptr -> allow_unlisted;
+   retval = AsnWrite(aip, COMMENT_RULE_allow_unlisted,  &av);
+   if (ptr -> dependent_rules != NULL) {
+      if ( ! DependentFieldSetAsnWrite(ptr -> dependent_rules, aip, COMMENT_RULE_dependent_rules)) {
+         goto erret;
+      }
+   }
    if (! AsnCloseStruct(aip, atp, (Pointer)ptr)) {
       goto erret;
    }
diff --git a/object/objvalid.h b/object/objvalid.h
index 49b9ff6..d8160b9 100644
--- a/object/objvalid.h
+++ b/object/objvalid.h
@@ -17,12 +17,20 @@ extern "C" { /* } */
 /**************************************************
 *
 *    Generated objects for Module NCBI-Structured-comment-validation
-*    Generated using ASNCODE Revision: 6.16 at Apr 7, 2009  1:38 PM
+*    Generated using ASNCODE Revision: 6.16 at Dec 11, 2009  7:16 AM
 *
 **************************************************/
 
 NLM_EXTERN Boolean LIBCALL
 objvalidAsnLoad PROTO((void));
+/* following #defines are for enumerated type, not used by object loaders */
+#define Severity_level_none 0
+#define Severity_level_info 1
+#define Severity_level_warning 2
+#define Severity_level_error 3
+#define Severity_level_reject 4
+#define Severity_level_fatal 5
+
 
 
 /**************************************************
@@ -35,6 +43,7 @@ typedef struct struct_Field_rule {
    CharPtr   field_name;
    CharPtr   match_expression;
    Uint1   required;
+   Uint2   severity;
 } FieldRule, PNTR FieldRulePtr;
 
 
@@ -67,6 +76,47 @@ NLM_EXTERN Boolean LIBCALL FieldSetAsnWrite PROTO (( FieldSetPtr , AsnIoPtr, Asn
 
 /**************************************************
 *
+*    DependentFieldRule
+*
+**************************************************/
+typedef struct struct_Dependent_field_rule {
+   struct struct_Dependent_field_rule PNTR next;
+   CharPtr   match_name;
+   CharPtr   value_constraint;
+   struct struct_Field_rule PNTR   other_fields;
+   struct struct_Field_rule PNTR   disallowed_fields;
+} DependentFieldRule, PNTR DependentFieldRulePtr;
+
+
+NLM_EXTERN DependentFieldRulePtr LIBCALL DependentFieldRuleFree PROTO ((DependentFieldRulePtr ));
+NLM_EXTERN DependentFieldRulePtr LIBCALL DependentFieldRuleNew PROTO (( void ));
+NLM_EXTERN DependentFieldRulePtr LIBCALL DependentFieldRuleAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL DependentFieldRuleAsnWrite PROTO (( DependentFieldRulePtr , AsnIoPtr, AsnTypePtr));
+
+
+
+/**************************************************
+*
+*    DependentFieldSet
+*
+**************************************************/
+typedef struct struct_Dependent_field_rule DependentFieldSet;
+typedef struct struct_Dependent_field_rule PNTR DependentFieldSetPtr;
+#define DependentFieldSetNew() Dependent_field_ruleNew() 
+
+#ifdef NLM_GENERATED_CODE_PROTO
+
+NLM_EXTERN DependentFieldSetPtr LIBCALL DependentFieldSetFree PROTO ((DependentFieldSetPtr ));
+NLM_EXTERN DependentFieldSetPtr LIBCALL DependentFieldSetNew PROTO (( void ));
+NLM_EXTERN DependentFieldSetPtr LIBCALL DependentFieldSetAsnRead PROTO (( AsnIoPtr, AsnTypePtr));
+NLM_EXTERN Boolean LIBCALL DependentFieldSetAsnWrite PROTO (( DependentFieldSetPtr , AsnIoPtr, AsnTypePtr));
+
+#endif /* NLM_GENERATED_CODE_PROTO */
+
+
+
+/**************************************************
+*
 *    CommentRule
 *
 **************************************************/
@@ -75,6 +125,9 @@ typedef struct struct_Comment_rule {
    CharPtr   prefix;
    Uint1   updated;
    struct struct_Field_rule PNTR   fields;
+   Uint1   require_order;
+   Uint1   allow_unlisted;
+   struct struct_Dependent_field_rule PNTR   dependent_rules;
 } CommentRule, PNTR CommentRulePtr;
 
 
diff --git a/platform/darwin-univ.ncbi.mk b/platform/darwin-univ.ncbi.mk
index 9dc032d..cf46c43 100644
--- a/platform/darwin-univ.ncbi.mk
+++ b/platform/darwin-univ.ncbi.mk
@@ -1,5 +1,5 @@
 #
-# $Id: darwin-univ.ncbi.mk,v 1.16 2008/07/14 14:26:03 ucko Exp $
+# $Id: darwin-univ.ncbi.mk,v 1.18 2010/07/18 14:24:24 ucko Exp $
 #
 # Tested on Darwin localhost 1.2 Darwin Kernel Version 1.2: Wed Aug 30 23:32:53 PDT 2000;
 # root:xnu/xnu-103.obj~1/RELEASE_PPC  Power Macintosh powerpc
@@ -8,9 +8,10 @@
 NCBI_DEFAULT_LCL = dwn
 NCBI_MAKE_SHELL = /bin/sh
 NCBI_AR=ar
-NCBI_CC = gcc -pipe -isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4 -arch ppc -arch i386
+NCBI_CC = gcc -pipe -mmacosx-version-min=10.4 -arch ppc -arch i386
 #NCBI_CFLAGS1 = -c -g -no-cpp-precomp
-NCBI_CFLAGS1 = -c -no-cpp-precomp -Wno-long-double
+#NCBI_CFLAGS1 = -c -no-cpp-precomp -Wno-long-double
+NCBI_CFLAGS1 = -c
 NCBI_LDFLAGS1 = -framework CoreServices -O2
 NCBI_OPTFLAG = -O2
 NCBI_BIN_MASTER = /home/coremake/ncbi/bin
diff --git a/platform/darwin.ncbi.mk b/platform/darwin.ncbi.mk
index 864d563..2cdf47b 100644
--- a/platform/darwin.ncbi.mk
+++ b/platform/darwin.ncbi.mk
@@ -1,5 +1,5 @@
 #
-# $Id: darwin.ncbi.mk,v 1.14 2005/12/01 19:52:56 rsmith Exp $
+# $Id: darwin.ncbi.mk,v 1.15 2010/07/18 14:24:23 ucko Exp $
 #
 # Tested on Darwin localhost 1.2 Darwin Kernel Version 1.2: Wed Aug 30 23:32:53 PDT 2000;
 # root:xnu/xnu-103.obj~1/RELEASE_PPC  Power Macintosh powerpc
@@ -10,7 +10,8 @@ NCBI_MAKE_SHELL = /bin/sh
 NCBI_AR=ar
 NCBI_CC = cc -pipe
 #NCBI_CFLAGS1 = -c -g -no-cpp-precomp
-NCBI_CFLAGS1 = -c -no-cpp-precomp -Wno-long-double
+#NCBI_CFLAGS1 = -c -no-cpp-precomp -Wno-long-double
+NCBI_CFLAGS1 = -c
 NCBI_LDFLAGS1 = -framework CoreServices -O2
 NCBI_OPTFLAG = -O2
 NCBI_BIN_MASTER = /home/coremake/ncbi/bin
diff --git a/platform/linux.ncbi.mk b/platform/linux.ncbi.mk
index a89bde9..58f2547 100644
--- a/platform/linux.ncbi.mk
+++ b/platform/linux.ncbi.mk
@@ -1,5 +1,5 @@
 #
-# $Id: linux.ncbi.mk,v 1.34 2009/02/04 14:24:03 lavr Exp $
+# $Id: linux.ncbi.mk,v 1.35 2010/02/05 19:46:19 ucko Exp $
 #
 NCBI_DEFAULT_LCL = lnx
 NCBI_MAKE_SHELL = /bin/sh
@@ -23,7 +23,7 @@ NCBI_VIBFLAG = -I/usr/X11R6/include -L/usr/X11R6/lib -DWIN_MOTIF
 NCBI_VIBLIBS = -lXmu -lXm -lXt -lSM -lICE -lXext -lXp -lX11 -ldl
 #warning! If you have only dynamic version of Motif or Lesstif
 #you should delete -Wl,-Bstatic sentence from the next line:
-NCBI_DISTVIBLIBS = -L/usr/X11R6/lib -lXmu -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXt -lSM -lICE -lXext -lXp -lX11 -ldl
+NCBI_DISTVIBLIBS = -L/usr/X11R6/lib -lXmu -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXft -lfontconfig -ljpeg -lpng -lXt -lSM -lICE -lXext -lXp -lX11 -ldl
 NCBI_OTHERLIBS = -lm
 NCBI_RANLIB = ranlib
 # Used by makedis.csh
diff --git a/platform/linux64.ncbi.mk b/platform/linux64.ncbi.mk
index 5ce1125..d4bf88f 100644
--- a/platform/linux64.ncbi.mk
+++ b/platform/linux64.ncbi.mk
@@ -1,5 +1,5 @@
 #
-# $Id: linux64.ncbi.mk,v 1.2 2009/02/04 14:24:03 lavr Exp $
+# $Id: linux64.ncbi.mk,v 1.3 2010/02/05 19:46:19 ucko Exp $
 #
 NCBI_DEFAULT_LCL = lnx
 NCBI_MAKE_SHELL = /bin/sh
@@ -18,7 +18,7 @@ NCBI_VIBFLAG = -I/usr/X11R6/include -L/usr/X11R6/lib64 -L/usr/X11R6/lib -DWIN_MO
 NCBI_VIBLIBS = -lXmu -lXm -lXt -lSM -lICE -lXext -lXp -lX11 -ldl
 #warning! If you have only dynamic version of Motif or Lesstif
 #you should delete -Wl,-Bstatic sentence from the next line:
-NCBI_DISTVIBLIBS = -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lXmu -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXt -lSM -lICE -lXext -lXp -lX11 -ldl
+NCBI_DISTVIBLIBS = -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lXmu -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXft -lfontconfig -ljpeg -lpng -lXt -lSM -lICE -lXext -lXp -lX11 -ldl
 NCBI_OTHERLIBS = -lm
 NCBI_RANLIB = ranlib
 # Used by makedis.csh
diff --git a/platform/linux64_icc9.ncbi.mk b/platform/linux64_icc9.ncbi.mk
index 136cc65..1efe918 100644
--- a/platform/linux64_icc9.ncbi.mk
+++ b/platform/linux64_icc9.ncbi.mk
@@ -1,5 +1,5 @@
 #
-# $Id: linux64_icc9.ncbi.mk,v 1.10 2009/02/04 14:24:03 lavr Exp $
+# $Id: linux64_icc9.ncbi.mk,v 1.11 2010/02/05 19:46:19 ucko Exp $
 #
 # ICC 9.0 on 64-bit Linux
 
@@ -27,7 +27,7 @@ NCBI_VIBFLAG = -I/usr/X11R6/include -L/usr/X11R6/lib64 -DWIN_MOTIF
 NCBI_VIBLIBS = -lXm -lXmu -lXt -lX11 -lXext
 #warning! If you have only dynamic version of Motif or Lesstif
 #you should delete -Wl,-Bstatic sentence from the next line:
-NCBI_DISTVIBLIBS = -L/usr/X11R6/lib64 -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXmu -lXt -lX11 -lXext -lXp
+NCBI_DISTVIBLIBS = -L/usr/X11R6/lib64 -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXft -lfontconfig -ljpeg -lpng -lXmu -lXt -lX11 -lXext -lXp
 NCBI_OTHERLIBS = -lm
 NCBI_RANLIB = ranlib
 # Used by makedis.csh
diff --git a/platform/linux_icc.ncbi.mk b/platform/linux_icc.ncbi.mk
index 904b432..a8bb32f 100644
--- a/platform/linux_icc.ncbi.mk
+++ b/platform/linux_icc.ncbi.mk
@@ -1,5 +1,5 @@
 #
-# $Id: linux_icc.ncbi.mk,v 1.8 2009/02/04 14:24:03 lavr Exp $
+# $Id: linux_icc.ncbi.mk,v 1.9 2010/02/05 19:46:19 ucko Exp $
 #
 # ICC 8.x with optimization options for Pentium 4 processor
 
@@ -25,7 +25,7 @@ NCBI_VIBFLAG = -I/usr/X11R6/include -L/usr/X11R6/lib -DWIN_MOTIF
 NCBI_VIBLIBS = -lXm -lXmu -lXt -lX11 -lXext
 #warning! If you have only dynamic version of Motif or Lesstif
 #you should delete -Wl,-Bstatic sentence from the next line:
-NCBI_DISTVIBLIBS = -L/usr/X11R6/lib -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXmu -lXt -lX11 -lXext -lXp
+NCBI_DISTVIBLIBS = -L/usr/X11R6/lib -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXft -lfontconfig -ljpeg -lpng -lXmu -lXt -lX11 -lXext -lXp
 NCBI_OTHERLIBS = -lm
 NCBI_RANLIB = ranlib
 # Used by makedis.csh
diff --git a/platform/linux_icc9.ncbi.mk b/platform/linux_icc9.ncbi.mk
index 26f510d..508ca06 100644
--- a/platform/linux_icc9.ncbi.mk
+++ b/platform/linux_icc9.ncbi.mk
@@ -1,5 +1,5 @@
 #
-# $Id: linux_icc9.ncbi.mk,v 1.10 2009/04/02 17:38:09 ucko Exp $
+# $Id: linux_icc9.ncbi.mk,v 1.11 2010/02/05 19:46:19 ucko Exp $
 #
 # ICC 9.0 with optimization options for Pentium 4 processor
 
@@ -27,7 +27,7 @@ NCBI_VIBFLAG = -I/usr/X11R6/include -L/usr/X11R6/lib -DWIN_MOTIF
 NCBI_VIBLIBS = -lXm -lXmu -lXt -lX11 -lXext
 #warning! If you have only dynamic version of Motif or Lesstif
 #you should delete -Wl,-Bstatic sentence from the next line:
-NCBI_DISTVIBLIBS = -L/usr/X11R6/lib -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXmu -lXt -lX11 -lXext -lXp
+NCBI_DISTVIBLIBS = -L/usr/X11R6/lib -Wl,-Bstatic -lXm -Wl,-Bdynamic -lXft -lfontconfig -ljpeg -lpng -lXmu -lXt -lX11 -lXext -lXp
 NCBI_OTHERLIBS = -lm
 NCBI_RANLIB = ranlib
 # Used by makedis.csh
diff --git a/sequin/macro.asn b/sequin/macro.asn
index 36632f5..aadc720 100755
--- a/sequin/macro.asn
+++ b/sequin/macro.asn
@@ -1,4 +1,4 @@
---$Revision: 1.54 $
+--$Revision: 1.68 $
 --**********************************************************************
 --
 --  NCBI ASN.1 macro editing language specifications
@@ -43,11 +43,25 @@ Partial-constraint ::= ENUMERATED {
     partial (1) ,
     complete (2) }
 
+Location-type-constraint ::= ENUMERATED {
+    any (0) ,
+    single-interval (1) ,
+    joined (2) ,
+    ordered (3) }
+
+Location-pos-constraint ::= CHOICE {
+    dist-from-end INTEGER ,
+    max-dist-from-end INTEGER ,
+    min-dist-from-end INTEGER }
+
 Location-constraint ::= SEQUENCE {
     strand Strand-constraint DEFAULT any ,
     seq-type Seqtype-constraint DEFAULT any ,
     partial5 Partial-constraint DEFAULT either ,
-    partial3 Partial-constraint DEFAULT either }
+    partial3 Partial-constraint DEFAULT either ,
+    location-type Location-type-constraint DEFAULT any ,
+    end5 Location-pos-constraint OPTIONAL ,
+    end3 Location-pos-constraint OPTIONAL }
 
 Object-type-constraint ::= ENUMERATED {
     any (0) ,
@@ -220,7 +234,9 @@ Feat-qual-legal ::= ENUMERATED {
     gene-comment (64) ,
     satellite (65) ,
     satellite-type (66) ,
-    satellite-name (67) }
+    satellite-name (67) ,
+    location (68) ,
+    tag-peptide (69) }
 
 Feat-qual-legal-val ::= SEQUENCE {
     qual Feat-qual-legal ,
@@ -269,7 +285,8 @@ Rna-field ::= ENUMERATED {
     gene-maploc (9) ,
     gene-locus-tag (10) ,
     gene-synonym (11) ,
-    gene-comment (12) }
+    gene-comment (12) ,
+    tag-peptide (13) }
     
 
 Rna-qual ::= SEQUENCE {
@@ -645,9 +662,19 @@ Pub-field-constraint ::= SEQUENCE {
   field Publication-field ,
   constraint String-constraint }
   
+Pub-field-special-constraint-type ::= CHOICE {
+  is-present NULL ,
+  is-not-present NULL ,
+  is-all-caps NULL }
+
+Pub-field-special-constraint ::= SEQUENCE {
+  field Publication-field ,
+  constraint Pub-field-special-constraint-type }
+  
 Publication-constraint ::= SEQUENCE {
   type Pub-type ,
-  field Pub-field-constraint OPTIONAL }
+  field Pub-field-constraint OPTIONAL ,
+  special-field Pub-field-special-constraint OPTIONAL }
 
 Source-constraint ::= SEQUENCE {
   field1 Source-qual-choice OPTIONAL ,
@@ -699,10 +726,16 @@ Sequence-constraint-mol-type-constraint ::= CHOICE {
   rna Sequence-constraint-rnamol ,
   protein NULL }
 
+Quantity-constraint ::= CHOICE {
+  equals INTEGER ,
+  greater-than INTEGER ,
+  less-than INTEGER }
+
 Sequence-constraint ::= SEQUENCE {
     seqtype Sequence-constraint-mol-type-constraint OPTIONAL ,
     id String-constraint OPTIONAL ,
-    feature Feature-type }
+    feature Feature-type ,
+    num-features Quantity-constraint OPTIONAL }
 
 Constraint-choice ::= CHOICE {
     string String-constraint ,
@@ -716,10 +749,15 @@ Constraint-choice ::= CHOICE {
 
 Constraint-choice-set ::= SET OF Constraint-choice
 
+Text-marker ::= CHOICE {
+    free-text VisibleString ,
+    digits NULL ,
+    letters NULL }
+
 Text-portion ::= SEQUENCE {
-    left-text VisibleString OPTIONAL ,
+    left-marker Text-marker  OPTIONAL ,
     include-left BOOLEAN ,
-    right-text VisibleString OPTIONAL ,
+    right-marker Text-marker  OPTIONAL ,
     include-right BOOLEAN ,
     inside BOOLEAN ,
     case-sensitive BOOLEAN DEFAULT FALSE ,
@@ -778,10 +816,18 @@ Edit-action ::= SEQUENCE {
     edit Field-edit ,
     field Field-type }
 
+Cap-change ::= ENUMERATED {
+    none (0) ,
+    tolower (1) ,
+    toupper (2) ,
+    firstcap (3) ,
+    firstcaprestnochange (4) }
+
 Convert-action ::= SEQUENCE {
     fields Field-pair-type ,
     strip-name BOOLEAN DEFAULT FALSE ,
     keep-original BOOLEAN DEFAULT FALSE ,
+    capitalization Cap-change DEFAULT none ,
     existing-text ExistingTextOption }
 
 Copy-action ::= SEQUENCE {
@@ -817,12 +863,6 @@ AECR-action ::= SEQUENCE {
     also-change-mrna BOOLEAN DEFAULT FALSE ,
     constraint Constraint-choice-set OPTIONAL }
 
-Cap-change ::= ENUMERATED {
-    none (0) ,
-    tolower (1) ,
-    toupper (2) ,
-    firstcap (3) }
-
 Parse-src-org-choice ::= CHOICE {
     source-qual Source-qual ,
     taxname-after-binomial NULL }
@@ -867,7 +907,8 @@ Location-interval ::= SEQUENCE {
 
 Location-choice ::= CHOICE {
     interval Location-interval ,
-    whole-sequence NULL }
+    whole-sequence NULL ,
+    point INTEGER }
 
 Sequence-list ::= SET OF VisibleString
 Sequence-list-choice ::= CHOICE {
@@ -1017,7 +1058,9 @@ Location-edit-type ::= CHOICE {
   clear-5-partial Partial-5-clear-constraint ,
   set-3-partial Partial-3-set-action ,
   clear-3-partial Partial-3-clear-constraint ,
-  convert Convert-location-type }
+  convert Convert-location-type ,
+  extend-5 NULL ,
+  extend-3 NULL }
 
 Edit-feature-location-action ::= SEQUENCE {
   type Feature-type ,
@@ -1056,6 +1099,12 @@ Autodef-action ::= SEQUENCE {
   modifiers SET OF Source-qual OPTIONAL ,
   clause-list-type Autodef-list-type }
 
+Fix-pub-caps-action ::= SEQUENCE {
+  title BOOLEAN OPTIONAL ,
+  authors BOOLEAN OPTIONAL ,
+  affiliation BOOLEAN OPTIONAL ,
+  constraint Constraint-choice-set OPTIONAL }
+
 Macro-action-choice ::= CHOICE {
   aecr AECR-action ,
   parse Parse-action ,
@@ -1064,7 +1113,15 @@ Macro-action-choice ::= CHOICE {
   convert-feature Convert-feature-action ,
   edit-location Edit-feature-location-action ,
   remove-descriptor Remove-descriptor-action ,
-  autodef Autodef-action }
+  autodef Autodef-action ,
+  removesets NULL ,
+  trim-junk-from-primer-seq NULL ,
+  trim-stop-from-complete-cds NULL ,
+  fix-usa-and-states NULL ,
+  synchronize-cds-partials NULL ,
+  adjust-for-consensus-splice NULL ,
+  fix-pub-caps Fix-pub-caps-action ,
+  remove-seg-gaps NULL }
 
 
 Macro-action-list ::= SET OF Macro-action-choice
diff --git a/sequin/sbtedit.c b/sequin/sbtedit.c
old mode 100755
new mode 100644
index 8de0089..f13870c
--- a/sequin/sbtedit.c
+++ b/sequin/sbtedit.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   5/17/2005
 *
-* $Revision: 1.5 $
+* $Revision: 1.6 $
 *
 * File Description: 
 * This file provides the Main function for the standalone Submission Template
@@ -590,7 +590,7 @@ static Int4 TaxLookup (SeqEntryPtr sep, Boolean strip, Boolean correct,
   }
 
   oldscope = SeqEntrySetScope (sep);
-  rsult = SeqEntryToAsn3Ex (sep, strip, correct, TRUE, NULL, Tax3MergeSourceDescr, FALSE);
+  rsult = SeqEntryToAsn3Ex (sep, strip, correct, TRUE, NULL, Tax3MergeSourceDescr, FALSE, FALSE);
   DeleteMarkedObjects (0, OBJ_SEQENTRY, sep);
   SeqEntrySetScope (oldscope);
   return rsult;
diff --git a/sequin/sequin.h b/sequin/sequin.h
index 2b757fb..3814c5c 100644
--- a/sequin/sequin.h
+++ b/sequin/sequin.h
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.579 $
+* $Revision: 6.620 $
 *
 * File Description: 
 *
@@ -94,15 +94,14 @@ extern "C" {
 
 
 #define SEQ_PKG_SINGLE        1
-#define SEQ_PKG_SEGMENTED     2
-#define SEQ_PKG_GAPPED        3
-#define SEQ_PKG_GENOMICCDNA   4
-#define SEQ_PKG_POPULATION    5
-#define SEQ_PKG_PHYLOGENETIC  6
-#define SEQ_PKG_MUTATION      7
-#define SEQ_PKG_ENVIRONMENT   8
-#define SEQ_PKG_GENBANK       9
-#define NUM_SEQ_PKG           9
+#define SEQ_PKG_GAPPED        2
+#define SEQ_PKG_GENOMICCDNA   3
+#define SEQ_PKG_POPULATION    4
+#define SEQ_PKG_PHYLOGENETIC  5
+#define SEQ_PKG_MUTATION      6
+#define SEQ_PKG_ENVIRONMENT   7
+#define SEQ_PKG_GENBANK       8
+#define NUM_SEQ_PKG           8
 
 #define SEQ_FMT_FASTA         1
 #define SEQ_FMT_ALIGNMENT     2 
@@ -392,7 +391,6 @@ extern Boolean PropagateFromGenBankBioseqSet (SeqEntryPtr sep, Boolean ask);
 extern Uint2 SmartAttachSeqAnnotToSeqEntry (Uint2 entityID, SeqAnnotPtr sap, ValNodePtr PNTR err_list);
 extern void HandleProjectAsn (ProjectPtr proj, Uint2 entityID);
 
-extern CharPtr CompressSpaces (CharPtr str);
 extern CharPtr SearchForString (CharPtr str, CharPtr sub, Boolean case_counts, Boolean whole_word);
 extern void AddAboutAndHelpMenuItems (MenU m);
 extern void NetConfigureProc (IteM i);
@@ -408,6 +406,7 @@ extern void CommonAddOrgOrModsToDefLines (IteM i, Int2 orgmod, Int2 subsource, B
 extern void PrefixDefLines (IteM i);
 extern void MRnaFromCdsProc (Uint2 entityID);
 extern void BioseqViewFormToolBar (GrouP h);
+extern void BioseqViewFormWGSToolBar (GrouP h);
 extern Boolean DoBuildContig (void);
 extern void SetGenome (PopuP p);
 extern PopuP ReplaceBioSourceGencodePopup (DialoG d, PopuP gencode);
@@ -415,7 +414,6 @@ extern CharPtr NameStdPtrToAuthorSpreadsheetString (NameStdPtr nsp);
 extern NameStdPtr AuthorSpreadsheetStringToNameStdPtr (CharPtr txt);
 extern Boolean ExtendGene (GeneRefPtr grp, SeqEntryPtr nsep, SeqLocPtr slp);
 extern void CommonAddOrgOrModsToDefLines (IteM i, Int2 orgmod, Int2 subsource, ButtoN b);
-extern void CorrectGenCodes (SeqEntryPtr sep, Uint2 entityID);
 extern void PrepareToConvertToCDS (SeqEntryPtr sep, Uint2 entityID,
                                    Uint2 subtype, CharPtr findthis);
 extern void EditGenbankElements (Handle i);
@@ -470,6 +468,9 @@ extern void RemoveSequencesFromRecord (IteM i);
 
 extern void ParseFileToSource (IteM i);
 extern void AddModToOrg (IteM i);
+extern void AddModToOrgBaseForm (BaseFormPtr bfp);
+extern void ChangeTargetBaseForm (BaseFormPtr bfp);
+
 
 extern void ParseInMoreProteins (IteM i);
 extern void ParseInNucUpdates (IteM i);
@@ -496,7 +497,7 @@ extern void UpdateProteinsFromCDS (IteM i);
 extern void AutoDef (IteM i);
 extern void AutoDefWithOptions (IteM i);
 extern void AutoDefWithoutModifiers (IteM i);
-extern void AutoDefBaseFormCommon (BaseFormPtr bfp, Boolean use_form, Boolean use_modifiers);
+extern void AutoDefBaseFormCommon (BaseFormPtr bfp, Boolean use_form, Boolean use_modifiers, Boolean popset_only);
 extern void AutoDefStrain (BaseFormPtr bfp);
 extern void AutoDefMiscFeat (BaseFormPtr bfp);
 extern void AutoDefToolBtn (ButtoN b);
@@ -504,6 +505,9 @@ extern void AutoDefOptionsToolBtn (ButtoN b);
 extern void AutoDefStrainToolBtn (ButtoN b);
 extern void AutoDefMiscFeatToolBtn (ButtoN b);
 extern void AutoDefEntityIDNoOptions (Uint2 entityID, Boolean use_modifiers);
+extern void AutoDefId (Uint2 entityID);
+extern void AutoDefIdEx (Uint2 entityID, DefLineType feature_list_type);
+extern void AddPopsetTitlesItem (IteM i);
 
 extern void RemoveDefLinesToolBtn (ButtoN b);
 extern void FindStringProcToolBtn (ButtoN b);
@@ -511,6 +515,8 @@ extern void FindFlatfileProcToolBtn (ButtoN b);
 extern void ResolveExistingLocalIDsToolBtn (ButtoN b);
 extern void GroupExplodeToolBtn (ButtoN b);
 
+extern void PromoteAlignIDsProc (SeqAnnotPtr sp, Pointer data);
+
 extern Int2 LIBCALLBACK MakeGroupsOf200 (Pointer data);
 
 extern void SetBestFrame (SeqFeatPtr sfp);
@@ -707,8 +713,6 @@ typedef struct sequencesform {
 
 extern ValNodePtr InsertMostUsedFeatureValNodes (ValNodePtr old_list);
 
-extern ValNodePtr FindExactStringInStrings ( ValNodePtr strings, CharPtr value);
-
 extern EnumFieldAssocPtr InsertMostUsedFeatureEnumFieldAssoc (
   EnumFieldAssocPtr alist
 );
@@ -875,6 +879,9 @@ extern void MacroApplyStructuredComment (IteM i);
 extern void MacroEditStructuredComment (IteM i);
 extern void MacroRemoveStructuredComment (IteM i);
 
+extern void PublicMacroApplyStructuredComment (IteM i);
+extern void PublicMacroEditStructuredComment (IteM i);
+
 
 /* constraint values */
 #define LOCATION_CONSTRAINT_WHOLE_INTERVAL  1
@@ -1598,8 +1605,6 @@ extern void ApplyLargeRNA (IteM i);
 
 /* capitalization */
 extern void GetOrgNamesInRecordCallback (BioSourcePtr biop, Pointer userdata);
-extern void FixCapitalizationInTitle (CharPtr PNTR pTitle, Boolean first_is_upper, ValNodePtr org_names);
-extern void FixCaseByField (IteM i);
 
 extern void ApplyRNA_ITS (IteM i);
 
@@ -1715,6 +1720,7 @@ extern void AbbreviateCitSubAffilStates (IteM i);
 extern void RemoveQualityScores (BioseqPtr bsp, FILE *log_fp, BoolPtr data_in_log);
 extern void NewLoadFeatureQualifierTable (IteM i);
 extern void NewLoadSourceQualifierTable (IteM i);
+NLM_EXTERN void CreateTableReaderWindowWithStructuredComments (IteM i);
 extern void ListAllSequences (BioseqPtr bsp, Pointer userdata);
 extern void ChooseCategories (ValNodePtr value_list, Boolean do_choose);
 extern void ChooseCategoriesByStringConstraint (ValNodePtr value_list, StringConstraintXPtr scp, Boolean do_choose);
@@ -1815,6 +1821,9 @@ extern void RemoveContigFromScaffoldMenuItem (IteM i);
 
 NLM_EXTERN void LIBCALLBACK SequesterSequenceList (Uint2 entityID, ValNodePtr bsp_list);
 NLM_EXTERN Boolean OkToSequester (void);
+NLM_EXTERN void LIBCALLBACK SegregateSequenceList (Uint2 entityID, ValNodePtr bsp_list);
+NLM_EXTERN Uint2 SequesterClickableItem (Uint2 entityID, ClickableItemPtr cip);
+NLM_EXTERN void SetDoReportAfterUnsequester (Int4 report_type);
 
 extern void ConvertRptUnitRangeToLocation (IteM i);
 extern void RetranscribemRNA (IteM i);
@@ -1830,6 +1839,57 @@ NLM_EXTERN void CleanupCDD (IteM i);
 
 NLM_EXTERN void ReportNonTSABioseqs (BioseqPtr bsp, Pointer userdata);
 
+NLM_EXTERN void FindBestNTrimSites (IteM i);
+extern void ScrollToTrimSequenceItem (ValNodePtr vnp, Pointer userdata);
+extern DialoG TrimSequenceResultsDisplay (GrouP h);
+extern DialoG TrimSequenceEndDisplay (GrouP h);
+extern Pointer GetCurrentPercentN (Uint1 data_choice, Pointer data, Pointer metadata);
+extern Pointer GetTrimInterval (Uint1 data_choice, Pointer data, Pointer metadata);
+extern Pointer GetTrimRemaining (Uint1 data_choice, Pointer data, Pointer metadata);
+extern Pointer GetTrimRemove (Uint1 data_choice, Pointer data, Pointer metadata);
+extern Boolean TrimShouldDelete (Uint1 data_choice, Pointer data, Pointer metadata);
+extern Pointer GetTrimAccession (Uint1 data_choice, Pointer data, Pointer metadata);
+extern Pointer GetTrim5 (Uint1 data_choice, Pointer data, Pointer metadata);
+extern Pointer GetTrim3 (Uint1 data_choice, Pointer data, Pointer metadata);
+extern void DefaultCheckTrimSequenceResultsDisplay (DialoG d);
+
+extern void MakeSpecialProjectsMenu (MenU m, BaseFormPtr bfp);
+
+NLM_EXTERN void TrimSequencesByAlignment (IteM i);
+extern void RemoveGenomeProjectIdsBaseForm (BaseFormPtr bfp);
+
+NLM_EXTERN void MakeCommonFeatureMicrosatellite (IteM i);
+NLM_EXTERN void MakeCommonFeatureControlRegion (IteM i);
+
+NLM_EXTERN void RemoveNonNIslands (IteM i);
+NLM_EXTERN void RemoveUTRsFromCDSs (IteM i);
+NLM_EXTERN void AddFeatureBetween (IteM i);
+NLM_EXTERN void ChangeQualifierCase (IteM i);
+NLM_EXTERN void ExternalApplyMoleculeType (IteM i);
+NLM_EXTERN void ApplyGenomeAssemblyComment (IteM i);
+NLM_EXTERN void SetReleaseDate(IteM i);
+NLM_EXTERN void NewRemoveTextOutsideString (IteM i);
+
+NLM_EXTERN void ImportTpaAlignment (IteM i);
+NLM_EXTERN Boolean ValidateTPAHistAlign (BioseqPtr bsp, ValNodePtr PNTR errors);
+NLM_EXTERN void RemoveOldTPAAccessions (UserObjectPtr uop);
+NLM_EXTERN UserObjectPtr GetTPAAssembly (BioseqPtr bsp);
+NLM_EXTERN void SortTPAAssembly (SeqAlignPtr PNTR salp);
+
+NLM_EXTERN void TruncateByProtAlign (IteM i);
+NLM_EXTERN void FrameShiftFinder (IteM i);
+
+NLM_EXTERN void ApplySetType (IteM i);
+NLM_EXTERN void ApplySetTypeToSeqEntry (SeqEntryPtr sep, Uint1 new_class, Boolean is_top);
+NLM_EXTERN void ApplySetTypeToInnerSets (BioseqSetPtr bssp, Uint2 entityID);
+
+NLM_EXTERN void ApplyArticles (IteM i);
+NLM_EXTERN void AdjustForConsensusSplice (IteM i);
+
+NLM_EXTERN void ExplodeRNA (IteM i);
+NLM_EXTERN void RemoveFeaturesLikeGaps (IteM i);
+
+
 #ifdef OS_MSWIN
 NLM_EXTERN Int4 RunSilent(const char *cmdline);
 #endif
diff --git a/sequin/sequin1.c b/sequin/sequin1.c
index 36616fd..4ef7ffa 100644
--- a/sequin/sequin1.c
+++ b/sequin/sequin1.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.709 $
+* $Revision: 6.735 $
 *
 * File Description: 
 *
@@ -131,7 +131,7 @@ static char *time_of_compilation = "now";
 #include <Gestalt.h>
 #endif
 
-#define SEQ_APP_VER "9.55"
+#define SEQ_APP_VER "10.25"
 
 CharPtr SEQUIN_APPLICATION = SEQ_APP_VER;
 CharPtr SEQUIN_SERVICES = NULL;
@@ -285,6 +285,7 @@ static MenU     newPubMenu = NULL;
 static MenU     batchApplyMenu = NULL;
 static MenU     batchEditMenu = NULL;
 static MenU     specialMenu = NULL;
+static MenU     projectsMenu = NULL;
 static MenU     analysisMenu = NULL;
 static Boolean  initialFormsActive = FALSE;
 #endif
@@ -318,6 +319,7 @@ static CharPtr validFailMsg =
 "Submission failed validation test.  Continue?\n\
 (Choose Validate in the Search menu to see errors.)";
 
+
 extern Int2 GetSequinAppParam (CharPtr section, CharPtr type, CharPtr dflt, CharPtr buf, Int2 buflen)
 
 {
@@ -1334,14 +1336,123 @@ static void SaveBinSeqEntry (IteM i)
   }
 }
 
+static CharPtr google_earth_1 =
+  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \
+  "<kml xmlns=\"http://earth.google.com/kml/2.2\">\n" \
+  "<Document>\n" \
+  "  <name>KmlFile</name>\n" \
+  "  <StyleMap id=\"default_copy0+nicon=http://maps.google.com/mapfiles/kml/pal3/icon60.png+hicon=http://maps.google.com/mapfiles/kml/pal3/icon52.png\">\n" \
+  "    <Pair>\n" \
+  "      <key>normal</key>\n" \
+  "      <styleUrl>#default_copy0+icon=http://maps.google.com/mapfiles/kml/pal3/icon60.png</styleUrl>\n" \
+  "    </Pair>\n" \
+  "    <Pair>\n" \
+  "      <key>highlight</key>\n" \
+  "      <styleUrl>#default_copy0+icon=http://maps.google.com/mapfiles/kml/pal3/icon52.png</styleUrl>\n" \
+  "    </Pair>\n" \
+  "  </StyleMap>\n" \
+  "  <Style id=\"default_copy0+icon=http://maps.google.com/mapfiles/kml/pal3/icon60.png\">\n" \
+  "    <IconStyle>\n" \
+  "      <Icon>\n" \
+  "        <href>http://maps.google.com/mapfiles/kml/pal3/icon60.png</href>\n" \
+  "      </Icon>\n" \
+  "    </IconStyle>\n" \
+  "  </Style>\n" \
+  "  <Placemark>\n";
+
+static CharPtr google_earth_2 =
+  "    <styleUrl>#default_copy0+nicon=http://maps.google.com/mapfiles/kml/pal3/icon60.png+hicon=http://maps.google.com/mapfiles/kml/pal3/icon52.png</styleUrl>\n" \
+  "    <Point>\n";
+
+static CharPtr google_earth_3 =
+  "    </Point>\n" \
+  "  </Placemark>\n" \
+  "</Document>\n" \
+  "</kml>\n";
+
+static Boolean LaunchedGoogleEarth (
+  Uint2 entityID, Uint4 itemID, Uint2 itemtype
+)
+
+{
+  BioSourcePtr       biop;
+  SeqMgrDescContext  context;
+  Boolean            format_ok = FALSE;
+  FILE               *fp;
+  FloatHi            lat = 0.0;
+  FloatHi            lon = 0.0;
+  CharPtr            lat_lon = NULL;
+  Boolean            lat_in_range = FALSE;
+  Boolean            lon_in_range = FALSE;
+  Char               path [PATH_MAX];
+  SeqDescPtr         sdp;
+  SubSourcePtr       ssp;
+#ifdef OS_UNIX
+  Char               cmmd [256];
+#endif
+
+  if (itemtype != OBJ_SEQDESC) return FALSE;
+
+  sdp = SeqMgrGetDesiredDescriptor (entityID, NULL, itemID, 0, NULL, &context);
+  if (sdp != NULL && sdp->choice == Seq_descr_source) {
+    biop = (BioSourcePtr) sdp->data.ptrvalue;
+    if (biop != NULL) {
+      for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
+        if (ssp->subtype != SUBSRC_lat_lon) continue;
+        lat_lon = ssp->name;
+        if (StringHasNoText (lat_lon)) continue;
+        IsCorrectLatLonFormat (lat_lon, &format_ok, &lat_in_range, &lon_in_range);
+        if (! format_ok) continue;
+        if (! lat_in_range) continue;
+        if (! lon_in_range) continue;
+        if (! ParseLatLon (lat_lon, &lat, &lon)) continue;
+        TmpNam (path);
+        /* write to original temp file, so next temp file name will not collide */
+        fp = FileOpen (path, "w");
+        if (fp != NULL) {
+          fprintf (fp, "\n");
+          FileClose (fp);
+          RememberSqnTempFile (path);
+        }
+        /* now append .kml extension so proper application is launched */
+        StringCat (path, ".kml");
+        fp = FileOpen (path, "w");
+        if (fp != NULL) {
+          fprintf (fp, "%s", google_earth_1);
+          fprintf (fp, "    <name>%s</name>\n", lat_lon);
+          fprintf (fp, "%s", google_earth_2);
+          fprintf (fp, "      <coordinates>%lf,%lf</coordinates>\n", (double) lon, (double) lat);
+          fprintf (fp, "%s", google_earth_3);
+          FileClose (fp);
+          RememberSqnTempFile (path);
+#ifdef OS_UNIX
+          sprintf (cmmd, "open %s", path);
+          system (cmmd);
+#endif
+#ifdef WIN_MSWIN
+          Nlm_MSWin_OpenDocument (path);
+#endif
+        }
+        return TRUE;
+      }
+    }
+  }
+
+  return FALSE;
+}
+
 static void LIBCALLBACK ValidNotify (ErrSev sev, int errcode, int subcode,
                                      Uint2 entityID, Uint4 itemID, Uint2 itemtype,
-                                     Boolean select, Boolean dblClick)
+                                     Boolean select, Boolean dblClick, Boolean shftKey)
 
 {
   Int2  handled;
 
   if (dblClick && entityID > 0 && itemID > 0 && itemtype > 0) {
+    if (itemtype == OBJ_SEQDESC && shftKey) {
+      if (LaunchedGoogleEarth (entityID, itemID, itemtype)) return;
+    }
+
     WatchCursor ();
     handled = GatherProcLaunch (OMPROC_EDIT, FALSE, entityID, itemID,
                                 itemtype, 0, 0, itemtype, 0);
@@ -1420,7 +1531,7 @@ static void SmartResetProc (IteM i)
 
 static void LaunchValidatorForDone (BaseFormPtr bfp, SeqEntryPtr sep, FormActnFunc revalProc, FormActnFunc continueProc);
 static Boolean SmallInferenceAccnVer (ForM f);
-static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck, FormActnFunc revalProc, FormActnFunc doneProc);
+static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck, FormActnFunc revalProc, FormActnFunc revalNoTaxProc, FormActnFunc doneProc);
 
 #ifdef USE_SMARTNET
 static Boolean LIBCALLBACK AllGenBankOrRefSeq (BioseqPtr bsp, SeqMgrBioseqContextPtr bcontext)
@@ -1503,7 +1614,7 @@ static void SmartnetDoneValidateFunc (ForM f)
   Boolean  inferenceAccnCheck;
 
   inferenceAccnCheck = SmallInferenceAccnVer (f);
-  ValSeqEntryFormExEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck, SmartnetDoneValidateFunc, SmartnetDoneNoValidateFunc);
+  ValSeqEntryFormExEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck, SmartnetDoneValidateFunc, NULL, SmartnetDoneNoValidateFunc);
 }
 
 static void SmartnetDoneNoValidateFunc (ForM f)
@@ -1515,6 +1626,19 @@ static void SmartnetDoneNoValidateFunc (ForM f)
   SmartnetDoneFuncEx (bfp, FALSE);
 }
 
+static void RemovePgcode (BioSourcePtr biop, Pointer userdata)
+
+{
+  OrgNamePtr  onp;
+  OrgRefPtr   orp;
+
+  if (biop == NULL) return;
+  orp = biop->org;
+  if (orp == NULL) return;
+  onp = orp->orgname;
+  if (onp == NULL) return;
+  onp->pgcode = 0;
+}
 
 static void SmartnetDoneFuncEx (BaseFormPtr bfp, Boolean validate)
 
@@ -1527,6 +1651,7 @@ static void SmartnetDoneFuncEx (BaseFormPtr bfp, Boolean validate)
     Boolean       update;
     
     ObjMgrDataPtr omdp;  
+    ObjMgrPtr     omp;
     OMUserDataPtr omudp;
     SMUserDataPtr sm_usr_data;
 /*    Uint2         entityID; */
@@ -1561,6 +1686,14 @@ static void SmartnetDoneFuncEx (BaseFormPtr bfp, Boolean validate)
             /* ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0); */
             ObjMgrFree(omdp->datatype, omdp->dataptr);
             
+            omp = ObjMgrGet ();
+            ObjMgrReapOne (omp);
+            SeqMgrClearBioseqIndex ();
+            ObjMgrFreeCache (0);
+            FreeSeqIdGiCache ();
+
+            SeqEntrySetScope (NULL);
+
             return;
         }
 
@@ -1635,6 +1768,7 @@ static void SmartnetDoneFuncEx (BaseFormPtr bfp, Boolean validate)
             }
             SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
 
+            VisitBioSourcesInSep (sep, NULL, RemovePgcode);
         }
 
         if(sm_usr_data->header->format == OBJ_SEQENTRY) {
@@ -1654,9 +1788,19 @@ static void SmartnetDoneFuncEx (BaseFormPtr bfp, Boolean validate)
         ObjMgrFreeUserData(entityID, 0, 0, SMART_KEY); 
         */
 
+        HideBioseqView ((WindoW) bfp->form);  
+
         /* ObjMgrSendMsg (OM_MSG_DEL, entityID, 0, 0); */
         ObjMgrFree(omdp->datatype, omdp->dataptr);
 
+        omp = ObjMgrGet ();
+        ObjMgrReapOne (omp);
+        SeqMgrClearBioseqIndex ();
+        ObjMgrFreeCache (0);
+        FreeSeqIdGiCache ();
+
+        SeqEntrySetScope (NULL);
+
         subtoolRecordDirty = FALSE;
         FileRemove (SEQUIN_EDIT_TEMP_FILE);
         FileRemove (SEQUIN_EDIT_PREV_FILE);
@@ -1697,7 +1841,7 @@ static void SubtoolDoneValidateFunc (ForM f)
   Boolean  inferenceAccnCheck;
 
   inferenceAccnCheck = SmallInferenceAccnVer (f);
-  ValSeqEntryFormExEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck, SubtoolDoneValidateFunc, SubtoolDoneNoValidateFunc);
+  ValSeqEntryFormExEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck, SubtoolDoneValidateFunc, NULL, SubtoolDoneNoValidateFunc);
 }
 
 
@@ -2292,6 +2436,7 @@ static void TaxonValidate (SeqEntryPtr sep, ValidStructPtr vsp)
   Boolean           is_species_level;
   Boolean           force_tax_consult;
   ValNodePtr        last = NULL;
+  OrgNamePtr        onp;
   OrgRefPtr         orp;
   ErrSev            sev;
   TaxLst            srclist;
@@ -2327,6 +2472,12 @@ static void TaxonValidate (SeqEntryPtr sep, ValidStructPtr vsp)
                         (AsnReadFunc) OrgRefAsnRead,
                         (AsnWriteFunc) OrgRefAsnWrite);
     vnp2 = ValNodeAddPointer (&last, 3, (Pointer) orp);
+    if (orp != NULL) {
+      onp = orp->orgname;
+      if (onp != NULL) {
+        onp->pgcode = 0;
+      }
+    }
     if (t3rq->request == NULL) {
       t3rq->request = vnp2;
     }
@@ -2459,7 +2610,7 @@ static void TaxonValidate (SeqEntryPtr sep, ValidStructPtr vsp)
   ReportBadSpecificHostValues (sep, vsp);
 }
 
-static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck, FormActnFunc revalProc, FormActnFunc doneProc)
+static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck, FormActnFunc revalProc, FormActnFunc revalNoTaxProc, FormActnFunc doneProc)
 
 {
   Boolean         allRawOrSeg = TRUE;
@@ -2499,8 +2650,9 @@ static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean i
 
         validatorWindow = CreateValidateWindowExExEx (ValidNotify, "Sequin Validation Errors",
                                                   programFont, SEV_INFO, verbosity, bfp,
-                                                  revalProc, doneProc, 
+                                                  revalProc, revalNoTaxProc, doneProc, 
                                                   doneProc == NULL && OkToSequester () ? SequesterSequenceList : NULL,
+                                                  doneProc == NULL ? SegregateSequenceList : NULL,
                                                   TRUE);
         ClearValidateWindow ();
         SeqEntryExplore (sep, (Pointer) (&allRawOrSeg), CheckForCookedBioseqs);
@@ -2541,7 +2693,7 @@ static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean i
         }
         vsp->errfunc = ValidErrCallback;
         ValidateSeqEntry (sep, vsp);
-        if (indexerVersion && useEntrez) {
+        if (indexerVersion && useEntrez && IsTaxValidationRequested(validatorWindow)) {
           SetTitle (validatorWindow, "Validating Taxonomy");
           Update ();
           TaxonValidate (sep, vsp);
@@ -2576,7 +2728,7 @@ static void ValSeqEntryFormExEx (ForM f, Boolean doAligns, Int2 limit, Boolean i
 static void ValSeqEntryFormEx (ForM f, Boolean doAligns, Int2 limit, Boolean inferenceAccnCheck)
 
 {
-  ValSeqEntryFormExEx (f, doAligns, limit, inferenceAccnCheck, ValSeqEntryForm, NULL);
+  ValSeqEntryFormExEx (f, doAligns, limit, inferenceAccnCheck, ValSeqEntryForm, ValSeqEntryForm, NULL);
 }
 
 static void CountInfAccnVer (SeqFeatPtr sfp, Pointer userdata)
@@ -2629,6 +2781,7 @@ extern void ValSeqEntryForm (ForM f)
   ValSeqEntryFormEx (f, TRUE, VALIDATE_ALL, inferenceAccnCheck);
 }
 
+
 static void ValSeqEntryProc (IteM i)
 
 {
@@ -3698,7 +3851,7 @@ static Boolean DoReadAnythingLoop (BaseFormPtr bfp, CharPtr filename, CharPtr pa
       each = HandleOneNewAsnProcEx (bfp, removeold, askForSubmit, path, dataptr, datatype, entityID, &updateEntityID, &err_list);
       if (err_list != NULL) {
         for (vnp_err = err_list; vnp_err != NULL; vnp_err = vnp_err->next) {
-          fprintf (lip->fp, "%s\n", vnp_err->data.ptrvalue);
+          fprintf (lip->fp, "%s\n", (CharPtr) vnp_err->data.ptrvalue);
           lip->data_in_log = TRUE;
         }
         err_list = ValNodeFreeData (err_list);
@@ -5228,6 +5381,7 @@ static void BioseqViewFormActivated (WindoW w)
   Enable (aluItem);
   Enable (submitItem);
   Enable (specialMenu);
+  Enable (projectsMenu);
   Enable (analysisMenu);
   Enable (vectorScreenItem);
   Enable (cddBlastItem);
@@ -5534,6 +5688,7 @@ static void MacDeactProc (WindoW w)
   Disable (printItem);
   Disable (restoreItem);
   Disable (specialMenu);
+  Disable (projectsMenu);
   Disable (analysisMenu);
   Disable (loadUidItem);
   Disable (saveUidItem);
@@ -5797,6 +5952,64 @@ static ValNodePtr LookupAnArticleFunc (ValNodePtr oldpep, BoolPtr success)
   return pub;
 }
 
+
+static Boolean HasMoreThanOneISOJTA (TitleMsgPtr titles)
+{
+  TitleMsgPtr tmp;
+  ValNodePtr  ttl;
+  Int4 num_found = 0;
+
+  for (tmp = titles; tmp != NULL; tmp = tmp->next) {
+    for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
+      if (ttl->choice == Cit_title_iso_jta) {
+        if (num_found > 0) {
+          return TRUE;
+        }
+        num_found++;
+        break;
+      }
+    }
+  }
+  return FALSE;
+}
+
+
+static CharPtr GetExtendedDescription (TitleMsgPtr tmp) 
+{
+  CharPtr iso_jta = NULL, name = NULL, issn = NULL, extended = NULL;
+  ValNodePtr ttl;
+
+  if (tmp == NULL) {
+    return NULL;
+  }
+  
+  for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
+    if (ttl->choice == Cit_title_iso_jta) {
+      iso_jta = ttl->data.ptrvalue;
+    } else if (ttl->choice == Cit_title_name) {
+      name = ttl->data.ptrvalue;
+    } else if (ttl->choice == Cit_title_issn) {
+      issn = ttl->data.ptrvalue;
+    }
+  }
+  if (iso_jta == NULL) {
+    return NULL;
+  }
+  if (name == NULL && issn == NULL) {
+    extended = StringSave (iso_jta);
+  } else if (name == NULL) {
+    extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (issn) + 5));
+    sprintf (extended, "%s||(%s)", iso_jta, issn);
+  } else if (issn == NULL) {
+    extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (name) + 5));
+    sprintf (extended, "%s||(%s)", iso_jta, name);
+  } else {
+    extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (name) + StringLen (issn) + 6));
+    sprintf (extended, "%s||(%s:%s)", iso_jta, name, issn);
+  }
+  return extended;
+}
+
 static Boolean LookupJournalFuncNew (CharPtr title, size_t maxsize, Int1Ptr jtaType, ValNodePtr PNTR all_titlesP)
 
 {
@@ -5804,7 +6017,7 @@ static Boolean LookupJournalFuncNew (CharPtr title, size_t maxsize, Int1Ptr jtaT
   ValNodePtr       last = NULL;
   MlaBackPtr       mbp;
   MlaRequestPtr    mrp;
-  CharPtr          str;
+  CharPtr          str, end;
   TitleMsgListPtr  tlp;
   TitleMsgPtr      tmp;
   ValNodePtr       ttl;
@@ -5846,6 +6059,14 @@ static Boolean LookupJournalFuncNew (CharPtr title, size_t maxsize, Int1Ptr jtaT
       }
       tlp = Mla2ExtractJournalTitleReply (mbp);
       if (tlp != NULL) {
+        if (HasMoreThanOneISOJTA (tlp->titles)) {
+          for (tmp = tlp->titles; tmp != NULL; tmp = tmp->next) {
+            str = GetExtendedDescription (tmp);
+            if (str != NULL) {
+              ValNodeAddPointer (&first, 0, str);
+            }
+          }
+        } else {
         for (tmp = tlp->titles; tmp != NULL; tmp = tmp->next) {
           for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
             if (ttl->choice != Cit_title_iso_jta) continue;
@@ -5858,15 +6079,22 @@ static Boolean LookupJournalFuncNew (CharPtr title, size_t maxsize, Int1Ptr jtaT
             last = vnp;
           }
         }
-        if (all_titlesP != NULL) {
-          *all_titlesP = first;
         }
         if (first != NULL) {
           str = (CharPtr) first->data.ptrvalue;
           StringNCpy_0 (title, str, maxsize);
+          end = StringSearch (title, "||");
+          if (end != NULL) {
+            *end = 0;
+          }
           if (jtaType != NULL) {
-            *jtaType = (Int1) first->choice;
+            *jtaType = Cit_title_iso_jta;
+          }
           }
+        if (all_titlesP == NULL) {
+          first = ValNodeFreeData (first);
+        } else {
+          *all_titlesP = first;
         }
         tlp = TitleMsgListFree (tlp);
       }
@@ -6415,22 +6643,15 @@ static void ChangeTargetMessageProc (ForM f, Int2 mssg)
   }
 }
 
-static void DoChangeTarget (IteM i)
-
+extern void ChangeTargetBaseForm (BaseFormPtr bfp)
 {
   ButtoN               b;
-  BaseFormPtr          bfp;
   GrouP                c;
   ChangeTargetFormPtr  cfp;
   GrouP                g;
   StdEditorProcsPtr    sepp;
   WindoW               w;
 
-#ifdef WIN_MAC
-  bfp = currentFormDataPtr;
-#else
-  bfp = GetObjectExtra (i);
-#endif
   if (bfp == NULL) return;
 
   cfp = (ChangeTargetFormPtr) MemNew (sizeof (ChangeTargetForm));
@@ -6463,6 +6684,19 @@ static void DoChangeTarget (IteM i)
   Select (w);
 }
 
+static void DoChangeTarget (IteM i)
+
+{
+  BaseFormPtr          bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  ChangeTargetBaseForm (bfp);
+}
+
 static void ConfigFormMessage (ForM f, Int2 mssg)
 
 {
@@ -7330,6 +7564,8 @@ static void BioseqViewFormMenus (WindoW w)
     if (extraServices) {
       m = PulldownMenu (w, "Special/ S");
       SetupSpecialMenu (m, bfp);
+      m = PulldownMenu (w, "Projects");
+      MakeSpecialProjectsMenu (m, bfp);
     }
 /*#endif*/
 
@@ -7367,6 +7603,15 @@ static void BioseqViewFormMenus (WindoW w)
     SetupBatchApplyMenu (sub, bfp);
     sub = SubMenu (m, "Batch Feature Edit");
     SetupBatchEditMenu (sub, bfp);
+    i = CommandItem (m, "Batch Apply Molecule Type", ExternalApplyMoleculeType);
+    SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (m, "Set Release Date", SetReleaseDate);
+    SetObjectExtra (i, bfp, NULL);
+    SeparatorItem (m);
+    i = CommandItem (m, "ORF Finder", FindOrf);
+    SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (m, "Import Source Table", ParseFileToSource);
+    SetObjectExtra (i, bfp, NULL);
     SeparatorItem (m);
     sub = SubMenu (m, "Publications");
     SetupNewPublicationsMenu (sub, bfp);
@@ -7374,8 +7619,6 @@ static void BioseqViewFormMenus (WindoW w)
     sub = SubMenu (m, "Descriptors");
     SetupNewDescriptorsMenu (sub, bfp);
     SeparatorItem (m);
-    i = CommandItem (m, "Generate Definition Line", AutoDef);
-    SetObjectExtra (i, bfp, NULL);
     sub = SubMenu (m, "Advanced Table Readers");
     i = CommandItem (sub, "Load Structured Comments from Table", SubmitterCreateStructuredComments);
     SetObjectExtra (i, bfp, NULL);
@@ -8849,12 +9092,22 @@ static void SetupDesktop (void)
 #endif
 #ifdef WIN_MOTIF
   if (indexerVersion) {
-    seqviewprocs.createToolBar = BioseqViewFormToolBar; /* now in separate window */
+    if (GetSequinAppParam ("SETTINGS", "WGS", NULL, str, sizeof (str))
+        && StringICmp (str, "TRUE") == 0) {
+      seqviewprocs.createToolBar = BioseqViewFormWGSToolBar;
+    } else {
+      seqviewprocs.createToolBar = BioseqViewFormToolBar;
+    }
   }
 #endif
 #ifdef WIN_MSWIN
   if (indexerVersion) {
-    seqviewprocs.createToolBar = BioseqViewFormToolBar; /* now in separate window */
+    if (GetSequinAppParam ("SETTINGS", "WGS", NULL, str, sizeof (str))
+        && StringICmp (str, "TRUE") == 0) {
+      seqviewprocs.createToolBar = BioseqViewFormWGSToolBar;
+    } else {
+      seqviewprocs.createToolBar = BioseqViewFormToolBar;
+    }
   }
 #endif
 /*#ifdef INTERNAL_NCBI_SEQUIN*/
@@ -9739,6 +9992,9 @@ static void SetupMacMenus (void)
   if (extraServices) {
     specialMenu = PulldownMenu (NULL, "Special");
     SetupSpecialMenu (specialMenu, NULL);
+    projectsMenu = PulldownMenu (NULL, "Projects");
+    MakeSpecialProjectsMenu (projectsMenu, NULL);
+
   }
 /*#endif*/
 
@@ -9783,6 +10039,11 @@ static void SetupMacMenus (void)
   SetupBatchApplyMenu (batchApplyMenu, NULL);
   batchEditMenu = SubMenu (newFeatMenu, "Batch Feature Edit");
   SetupBatchEditMenu (batchEditMenu, NULL);
+  CommandItem (newFeatMenu, "Batch Apply Molecule Type", ExternalApplyMoleculeType);
+  CommandItem (newFeatMenu, "Set Release Date", SetReleaseDate);
+  SeparatorItem (newFeatMenu);
+  CommandItem (newFeatMenu, "ORF Finder", FindOrf);
+  CommandItem (newFeatMenu, "Import Source Table", ParseFileToSource);
   SeparatorItem (newFeatMenu);
   newPubMenu = SubMenu (newFeatMenu, "Publications");
   SetupNewPublicationsMenu (newPubMenu, NULL);
@@ -9790,7 +10051,6 @@ static void SetupMacMenus (void)
   newDescMenu = SubMenu (newFeatMenu, "Descriptors");
   SetupNewDescriptorsMenu (newDescMenu, NULL);
   SeparatorItem (newFeatMenu);
-  CommandItem (newFeatMenu, "Generate Definition Line", AutoDef);
   advTableMenu = SubMenu (newFeatMenu, "Advanced Table Readers");
   CommandItem (advTableMenu, "Load Structured Comments from Table", SubmitterCreateStructuredComments);
   sucItem = CommandItem (newFeatMenu, "Sort Unique Count By Group", SUCSubmitterProc);
@@ -11096,7 +11356,7 @@ static Int2 LIBCALLBACK HUPBioseqFetchFunc (Pointer data)
   TmpNam (path);
 
 #ifdef OS_UNIX
-  sprintf (cmmd, "csh %s %s > %s", hupfetchcmd, tsip->accession, path);
+  sprintf (cmmd, "csh %s %s > %s 2>&1", hupfetchcmd, tsip->accession, path);
   system (cmmd);
 #endif
 #ifdef OS_MSWIN
@@ -12836,4 +13096,3 @@ extern void UpdateFeatures (IteM i)
   Show (w);
   Select (w);
 }
-
diff --git a/sequin/sequin10.c b/sequin/sequin10.c
index 3015d03..58460be 100644
--- a/sequin/sequin10.c
+++ b/sequin/sequin10.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   9/3/2003
 *
-* $Revision: 1.450 $
+* $Revision: 1.504 $
 *
 * File Description: 
 *
@@ -54,9 +54,18 @@
 #include <findrepl.h>
 #include <asnenbin.h>
 #include <cdrgn.h>
+#define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
 #include <macrodlg.h>
 #include <macroapi.h>
 #include <seqpanel.h>
+#include <salpanel.h>
+#include <alignmgr2.h>
+#include <salpedit.h>
+#include <objvalid.h>
+#include <valapi.h>
+#include <seqsub.h>
+#include <tax3api.h>
 
 typedef struct deflineformdata {
   FEATURE_FORM_BLOCK
@@ -73,6 +82,7 @@ typedef struct deflineformdata {
   ButtoN    exclude_cf;
   ButtoN    exclude_aff;
   ButtoN    exclude_nr;
+  ButtoN    allow_mod_at_end_of_taxname;
   ButtoN    include_country_extra;
   ButtoN    allow_semicolon_in_modifier;
   GrouP     clone_isolate_HIV_rule_num;
@@ -93,6 +103,7 @@ typedef struct deflineformdata {
   ButtoN    gene_cluster_opp_strand;
   DialoG    suppressed_feature_list;
   GrouP     suppressed_feature_grp;
+  Boolean   popset_only;
 } DefLineFormData, PNTR DefLineFormPtr;
 
 static void DefLineFormMessageProc (ForM f, Int2 mssg)
@@ -180,7 +191,6 @@ static void DoAutoDefLine (ButtoN b)
   OrganismDescriptionModifiers odmp;
   Int2 product_flag, feature_list_type;
   Int4 i;
-  ValNodePtr defline_clauses = NULL;
   Boolean alternate_splice_flag;
   Boolean gene_cluster_opp_strand;
 
@@ -190,6 +200,8 @@ static void DoAutoDefLine (ButtoN b)
   WatchCursor ();
   Update ();
 
+  if (!dlfp->popset_only) {
+    InitOrganismDescriptionModifiers (&odmp, NULL);
   odmp.use_labels = GetStatus (dlfp->use_labels);
   odmp.keep_paren = GetStatus (dlfp->keep_paren);
   odmp.exclude_sp = GetStatus (dlfp->exclude_sp);
@@ -199,6 +211,7 @@ static void DoAutoDefLine (ButtoN b)
   odmp.include_country_extra = GetStatus (dlfp->include_country_extra);
   odmp.use_modifiers = TRUE;
   odmp.allow_semicolon_in_modifier = GetStatus (dlfp->allow_semicolon_in_modifier);
+    odmp.allow_mod_at_end_of_taxname = !GetStatus (dlfp->allow_mod_at_end_of_taxname);
 
   if (dlfp->clone_isolate_HIV_rule_num == NULL)
   {
@@ -209,6 +222,18 @@ static void DoAutoDefLine (ButtoN b)
     odmp.clone_isolate_HIV_rule_num = GetValue (dlfp->clone_isolate_HIV_rule_num);
   }
 
+    odmp.max_mods = GetValue (dlfp->modLimit);
+    if (odmp.max_mods > 1)
+    {
+      odmp.max_mods = odmp.max_mods - 1;
+    }
+    else
+    {
+      odmp.max_mods = -99;
+    }
+
+  }
+
   if (GetValue (dlfp->customGrp) == 1)
   {
     /* take all features */
@@ -244,6 +269,12 @@ static void DoAutoDefLine (ButtoN b)
     case DEFLINE_COMPLETE_GENOME :
       dlfp->feature_requests.feature_list_type = DEFLINE_COMPLETE_GENOME;
       break;
+    case DEFLINE_PARTIAL_GENOME :
+      dlfp->feature_requests.feature_list_type = DEFLINE_PARTIAL_GENOME;
+      break;
+    case DEFLINE_SEQUENCE :
+      dlfp->feature_requests.feature_list_type = DEFLINE_SEQUENCE;
+      break;
     default:
       dlfp->feature_requests.feature_list_type = DEFLINE_USE_FEATURES;
       break;
@@ -280,16 +311,6 @@ static void DoAutoDefLine (ButtoN b)
                  
   dlfp->feature_requests.suppressed_feature_list = DialogToPointer (dlfp->suppressed_feature_list);                 
 
-  odmp.max_mods = GetValue (dlfp->modLimit);
-  if (odmp.max_mods > 1)
-  {
-    odmp.max_mods = odmp.max_mods - 1;
-  }
-  else
-  {
-    odmp.max_mods = -99;
-  }
-
   product_flag = GetValue (dlfp->organelle_popup) - 1;
   alternate_splice_flag = GetStatus (dlfp->alternate_splice_flag);
   gene_cluster_opp_strand = GetStatus (dlfp->gene_cluster_opp_strand);
@@ -304,8 +325,13 @@ static void DoAutoDefLine (ButtoN b)
   }
   if (sep == NULL) return;
 
+  RemovePopsetTitles (sep);
+  if (dlfp->popset_only) {
+    AddPopsetTitles (sep, &dlfp->feature_requests, product_flag, alternate_splice_flag, gene_cluster_opp_strand);
+  } else {
   AutoDefForSeqEntry (sep, dlfp->input_entityID, &odmp, dlfp->modList, modifier_indices,
                       &dlfp->feature_requests, product_flag, alternate_splice_flag, gene_cluster_opp_strand);
+  }
                               
   dlfp->feature_requests.suppressed_feature_list = ValNodeFree (dlfp->feature_requests.suppressed_feature_list);
   modifier_indices = ValNodeFree (modifier_indices);
@@ -387,47 +413,6 @@ static Boolean HasTrickyHIVRecords (
 }
 
 
-static void AddSpTaxnameToList (SeqDescrPtr sdp, Pointer userdata)
-{
-  BioSourcePtr biop;
-
-  if (sdp == NULL || sdp->choice != Seq_descr_source || userdata == NULL) return;
-
-  biop = (BioSourcePtr) sdp->data.ptrvalue;
-  if (biop == NULL || biop->org == NULL || !IsSpName (biop->org->taxname)) return;
-
-  ValNodeAddPointer ((ValNodePtr PNTR) userdata, 0, biop->org->taxname);
-}
-
-
-static Boolean ShouldExcludeSp (SeqEntryPtr sep)
-{
-  ValNodePtr name_list = NULL, vnp1, vnp2;
-  Boolean    all_diff = TRUE;
-
-  if (sep == NULL) return TRUE;
-  VisitDescriptorsInSep (sep, &name_list, AddSpTaxnameToList);
-
-  name_list = ValNodeSort (name_list, SortVnpByString);
-
-  if (name_list != NULL && name_list->next != NULL)
-  {
-    for (vnp1 = name_list; vnp1 != NULL && vnp1->next != NULL && all_diff; vnp1 = vnp1->next)
-    {
-      for (vnp2 = vnp1->next; vnp2 != NULL && all_diff; vnp2 = vnp2->next)
-      {
-        if (StringCmp (vnp1->data.ptrvalue, vnp2->data.ptrvalue) == 0)
-        {
-          all_diff = FALSE;
-        }
-      }
-    }
-  }
-  name_list = ValNodeFree (name_list);
-  return all_diff;
-}
-
-
 static GrouP CreateDefLineFormHIVRule (
   GrouP h
 )
@@ -637,6 +622,9 @@ static GrouP CreateDefLineFormSourceGroup (
   dlfp->exclude_nr = CheckBox (r, "Do not apply modifier to 'nr.' organisms", NULL);
   SetStatus (dlfp->exclude_nr, FALSE);
   
+  dlfp->allow_mod_at_end_of_taxname = CheckBox (r, "Do not apply modifier to organisms with matching tax name value", NULL);
+  SetStatus (dlfp->allow_mod_at_end_of_taxname, TRUE);
+
   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) dlfp->use_labels,
                               (HANDLE) dlfp->sourceListGrp,
                               (HANDLE) r,
@@ -681,6 +669,8 @@ static GrouP CreateDefLineFormFeatureListPopuP (
   PopupItem (dlfp->featurePopup, "List Features");
   PopupItem (dlfp->featurePopup, "Complete Sequence");
   PopupItem (dlfp->featurePopup, "Complete Genome");
+  PopupItem (dlfp->featurePopup, "Partial Genome");
+  PopupItem (dlfp->featurePopup, "Sequence");
   SetValue (dlfp->featurePopup, 1);
   
   return q;
@@ -805,12 +795,13 @@ static GrouP CreateDefLineFormFeatureOptionsGroup (
 static void CreateDefLineForm (
   BaseFormPtr bfp,
   ModifierItemLocalPtr modList,
-  DeflineFeatureRequestList *feature_requests
+  DeflineFeatureRequestList *feature_requests,
+  Boolean popset_only
 )
 {
   DefLineFormPtr dlfp;
   WindoW         w;
-  GrouP          h, k, g1, c, feat_opts;
+  GrouP          h, k, g1 = NULL, c, feat_opts;
   ButtoN         b;
   SeqEntryPtr    sep;
 
@@ -819,6 +810,7 @@ static void CreateDefLineForm (
   dlfp->input_entityID = bfp->input_entityID;
   dlfp->input_itemID = bfp->input_itemID;
   dlfp->input_itemtype = bfp->input_itemtype;
+  dlfp->popset_only = popset_only;
 
   dlfp->modifier_btns = (ButtoN PNTR) MemNew (sizeof (ButtoN) * NumDefLineModifiers());
 
@@ -838,10 +830,12 @@ static void CreateDefLineForm (
 
   k = HiddenGroup (h, -1, 0, NULL);
   SetGroupSpacing (k, 10, 10);
+  if (!popset_only) {
   g1 = CreateDefLineFormSourceGroup (k, dlfp, sep);
+  }
 
   feat_opts = CreateDefLineFormFeatureOptionsGroup (k, dlfp);
-  AlignObjects (ALIGN_CENTER, (HANDLE) g1, (HANDLE) feat_opts, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) feat_opts, (HANDLE) g1, NULL);
 
   c = HiddenGroup (h, 4, 0, NULL);
   b = DefaultButton (c, "Accept", DoAutoDefLine);
@@ -902,17 +896,9 @@ extern void AutoDefEntityIDNoOptions (Uint2 entityID, Boolean use_modifiers)
   if (modList == NULL) return;
   SetRequiredModifiers (modList);
   CountModifiers (modList, sep);
-    odmp.use_labels = TRUE;
-    odmp.max_mods = -99;
-    odmp.keep_paren = TRUE;
-    odmp.exclude_sp = ShouldExcludeSp (sep);
-    odmp.exclude_cf = FALSE;
-    odmp.exclude_aff = FALSE;
-    odmp.exclude_nr = FALSE;
-    odmp.include_country_extra = FALSE;
-    odmp.clone_isolate_HIV_rule_num = clone_isolate_HIV_rule_want_both;
+
+  InitOrganismDescriptionModifiers (&odmp, sep);
     odmp.use_modifiers = use_modifiers;
-    odmp.allow_semicolon_in_modifier = FALSE;
 
     RemoveNucProtSetTitles (sep);  
     SeqEntrySetScope (sep);
@@ -945,13 +931,16 @@ extern void AutoDefEntityIDNoOptions (Uint2 entityID, Boolean use_modifiers)
 
     ClearProteinTitlesInNucProts (entityID, NULL);
     InstantiateProteinTitles (entityID, NULL);
+  RemovePopsetTitles (sep);
+  AddPopsetTitles (sep, &feature_requests, DEFAULT_ORGANELLE_CLAUSE, FALSE, FALSE);
 }
 
 
 extern void AutoDefBaseFormCommon (
   BaseFormPtr bfp,
   Boolean use_form,
-  Boolean use_modifiers
+  Boolean use_modifiers,
+  Boolean popset_only
 )
 {
   SeqEntryPtr sep;
@@ -977,23 +966,14 @@ extern void AutoDefBaseFormCommon (
     modifier_indices = FindBestModifiersEx (sep, modList, TRUE);
     AddBestModifiersToModList ( modifier_indices, modList);
     modifier_indices = ValNodeFree (modifier_indices);
-    CreateDefLineForm (bfp, modList, &feature_requests);
+    CreateDefLineForm (bfp, modList, &feature_requests, popset_only);
   }
   else
   {
     WatchCursor ();
     Update ();
-    odmp.use_labels = TRUE;
-    odmp.max_mods = -99;
-    odmp.keep_paren = TRUE;
-    odmp.exclude_sp = ShouldExcludeSp (sep);
-    odmp.exclude_cf = FALSE;
-    odmp.exclude_aff = FALSE;
-    odmp.exclude_nr = FALSE;
-    odmp.include_country_extra = FALSE;
-    odmp.clone_isolate_HIV_rule_num = clone_isolate_HIV_rule_want_both;
+    InitOrganismDescriptionModifiers (&odmp, sep);
     odmp.use_modifiers = use_modifiers;
-    odmp.allow_semicolon_in_modifier = FALSE;
 
     RemoveNucProtSetTitles (sep);  
     SeqEntrySetScope (sep);
@@ -1010,8 +990,10 @@ extern void AutoDefBaseFormCommon (
       modifier_indices = FindBestModifiersForDeflineClauseList (defline_clauses, modList);
     }
 
+    if (!popset_only) {
     BuildDefinitionLinesFromFeatureClauseLists (defline_clauses, modList,
                                                 modifier_indices, &odmp);
+    }
 
     DefLineFeatClauseListFree (defline_clauses);
     if (modList != NULL)
@@ -1024,8 +1006,12 @@ extern void AutoDefBaseFormCommon (
     }
     modifier_indices = ValNodeFree (modifier_indices);
 
+    if (!popset_only) {
     ClearProteinTitlesInNucProts (bfp->input_entityID, NULL);
     InstantiateProteinTitles (bfp->input_entityID, NULL);
+    }
+    RemovePopsetTitles (sep);
+    AddPopsetTitles (sep, &feature_requests, DEFAULT_ORGANELLE_CLAUSE, FALSE, FALSE);
 
     ArrowCursor ();
     Update ();
@@ -1036,9 +1022,17 @@ extern void AutoDefBaseFormCommon (
 }
 
 
-extern void AutoDefStrain (
-  BaseFormPtr bfp
-)
+static const Int4 s_auto_def_id_preferred_quals[] = {
+  DEFLINE_POS_Strain,
+  DEFLINE_POS_Clone,
+  DEFLINE_POS_Isolate,
+  DEFLINE_POS_Cultivar,
+  DEFLINE_POS_Specimen_voucher,
+};
+
+static const Int4 k_num_auto_def_id_preferred_quals = sizeof (s_auto_def_id_preferred_quals) / sizeof (Int4);
+
+extern void AutoDefIdEx (Uint2 entityID, DefLineType feature_list_type)
 {
   SeqEntryPtr sep;
   DeflineFeatureRequestList feature_requests;
@@ -1046,58 +1040,43 @@ extern void AutoDefStrain (
   ValNodePtr modifier_indices = NULL;
   OrganismDescriptionModifiers odmp;
   Int4 index;
+  Boolean added_required = FALSE;
   ValNodePtr defline_clauses = NULL;
 
-  if (bfp == NULL) return;
-  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  sep = GetTopSeqEntryForEntityID (entityID);
   if (sep == NULL) return;
 
   InitFeatureRequests (&feature_requests);
+  feature_requests.feature_list_type = feature_list_type;
 
   modList = MemNew (NumDefLineModifiers () * sizeof (ModifierItemLocalData));
   if (modList == NULL) return;
   SetRequiredModifiers (modList);
   CountModifiers (modList, sep);
-  if (modList[DEFLINE_POS_Strain].all_present) {
-    modList[DEFLINE_POS_Strain].required = TRUE;
-  } else if (modList[DEFLINE_POS_Clone].all_present) {
-    modList[DEFLINE_POS_Clone].required = TRUE;
-  } else if (modList[DEFLINE_POS_Isolate].all_present) {
-    modList[DEFLINE_POS_Isolate].required = TRUE;
-  } else if (modList[DEFLINE_POS_Cultivar].all_present) {
-    modList[DEFLINE_POS_Cultivar].required = TRUE;
-  } else if (modList[DEFLINE_POS_Specimen_voucher].all_present) {
-    modList[DEFLINE_POS_Specimen_voucher].required = TRUE;
-  } else if (modList[DEFLINE_POS_Strain].any_present) {
-    modList[DEFLINE_POS_Strain].required = TRUE;
-  } else if (modList[DEFLINE_POS_Clone].any_present) {
-    modList[DEFLINE_POS_Clone].required = TRUE;
-  } else if (modList[DEFLINE_POS_Isolate].any_present) {
-    modList[DEFLINE_POS_Isolate].required = TRUE;
-  } else if (modList[DEFLINE_POS_Cultivar].any_present) {
-    modList[DEFLINE_POS_Cultivar].required = TRUE;
-  } else if (modList[DEFLINE_POS_Specimen_voucher].any_present) {
-    modList[DEFLINE_POS_Specimen_voucher].required = TRUE;
+  /* first look for first modifier in list that is present on all sources */
+  for (index = 0; index < k_num_auto_def_id_preferred_quals && !added_required; index++) {
+    if (modList[s_auto_def_id_preferred_quals[index]].all_present) {
+      modList[s_auto_def_id_preferred_quals[index]].required = TRUE;
+      added_required = TRUE;
+    }
+  }
+  /* if not found, then look for first modifier in list that is present on any sources */
+  for (index = 0; index < k_num_auto_def_id_preferred_quals && !added_required; index++) {
+    if (modList[s_auto_def_id_preferred_quals[index]].any_present) {
+      modList[s_auto_def_id_preferred_quals[index]].required = TRUE;
+      added_required = TRUE;
+    }
   }
 
   WatchCursor ();
   Update ();
-  odmp.use_labels = TRUE;
-  odmp.max_mods = -99;
-  odmp.keep_paren = TRUE;
-  odmp.exclude_sp = ShouldExcludeSp (sep);
-  odmp.exclude_cf = FALSE;
-  odmp.exclude_aff = FALSE;
-  odmp.exclude_nr = FALSE;
-  odmp.include_country_extra = FALSE;
-  odmp.clone_isolate_HIV_rule_num = clone_isolate_HIV_rule_want_both;
+  InitOrganismDescriptionModifiers (&odmp, sep);
   odmp.use_modifiers = TRUE;
-  odmp.allow_semicolon_in_modifier = FALSE;
 
   RemoveNucProtSetTitles (sep);  
   SeqEntrySetScope (sep);
 
-  BuildDefLineFeatClauseList (sep, bfp->input_entityID, &feature_requests,
+  BuildDefLineFeatClauseList (sep, entityID, &feature_requests,
                               DEFAULT_ORGANELLE_CLAUSE, FALSE, FALSE,
                               &defline_clauses);
   if ( AreFeatureClausesUnique (defline_clauses))
@@ -1123,8 +1102,30 @@ extern void AutoDefStrain (
   }
   modifier_indices = ValNodeFree (modifier_indices);
 
-  ClearProteinTitlesInNucProts (bfp->input_entityID, NULL);
-  InstantiateProteinTitles (bfp->input_entityID, NULL);
+  ClearProteinTitlesInNucProts (entityID, NULL);
+  InstantiateProteinTitles (entityID, NULL);
+  RemovePopsetTitles (sep);
+  AddPopsetTitles (sep, &feature_requests, DEFAULT_ORGANELLE_CLAUSE, FALSE, FALSE);
+
+}
+
+
+extern void AutoDefId (Uint2 entityID)
+{
+  AutoDefIdEx (entityID, DEFLINE_USE_FEATURES);
+}
+
+
+extern void AutoDefStrain (
+  BaseFormPtr bfp
+)
+{
+
+  if (bfp == NULL) return;
+
+  WatchCursor ();
+  Update ();
+  AutoDefId (bfp->input_entityID);
 
   ArrowCursor ();
   Update ();
@@ -1160,17 +1161,8 @@ extern void AutoDefMiscFeat (
 
   WatchCursor ();
   Update ();
-  odmp.use_labels = TRUE;
-  odmp.max_mods = -99;
-  odmp.keep_paren = TRUE;
-  odmp.exclude_sp = ShouldExcludeSp (sep);
-  odmp.exclude_cf = FALSE;
-  odmp.exclude_aff = FALSE;
-  odmp.exclude_nr = FALSE;
-  odmp.include_country_extra = FALSE;
-  odmp.clone_isolate_HIV_rule_num = clone_isolate_HIV_rule_want_both;
+  InitOrganismDescriptionModifiers (&odmp, sep);
   odmp.use_modifiers = TRUE;
-  odmp.allow_semicolon_in_modifier = FALSE;
 
   RemoveNucProtSetTitles (sep);  
   SeqEntrySetScope (sep);
@@ -1203,6 +1195,8 @@ extern void AutoDefMiscFeat (
 
   ClearProteinTitlesInNucProts (bfp->input_entityID, NULL);
   InstantiateProteinTitles (bfp->input_entityID, NULL);
+  RemovePopsetTitles (sep);
+  AddPopsetTitles (sep, &feature_requests, DEFAULT_ORGANELLE_CLAUSE, FALSE, FALSE);
 
   ArrowCursor ();
   Update ();
@@ -1222,7 +1216,7 @@ static void AutoDefCommon (IteM i, Boolean use_form, Boolean use_modifiers)
   bfp = GetObjectExtra (i);
 #endif
   if (bfp == NULL || bfp->input_entityID == 0) return;
-  AutoDefBaseFormCommon (bfp, use_form, use_modifiers);
+  AutoDefBaseFormCommon (bfp, use_form, use_modifiers, FALSE);
 }
 
 extern void AutoDef (IteM i)
@@ -1247,7 +1241,7 @@ extern void AutoDefToolBtn (ButtoN b)
 
   bfp = (BaseFormPtr) GetObjectExtra (b);
   if (bfp == NULL) return;
-  AutoDefBaseFormCommon (bfp, FALSE, TRUE);
+  AutoDefBaseFormCommon (bfp, FALSE, TRUE, FALSE);
 }
 
 extern void AutoDefOptionsToolBtn (ButtoN b)
@@ -1256,7 +1250,7 @@ extern void AutoDefOptionsToolBtn (ButtoN b)
 
   bfp = (BaseFormPtr) GetObjectExtra (b);
   if (bfp == NULL) return;
-  AutoDefBaseFormCommon (bfp, TRUE, TRUE);
+  AutoDefBaseFormCommon (bfp, TRUE, TRUE, FALSE);
 }
 
 
@@ -1280,6 +1274,16 @@ extern void AutoDefMiscFeatToolBtn (ButtoN b)
 }
 
 
+extern void AddPopsetTitlesItem (IteM i)
+{
+  BaseFormPtr  bfp;
+
+  bfp = (BaseFormPtr) GetObjectExtra (i);
+  if (bfp == NULL) return;
+  AutoDefBaseFormCommon (bfp, TRUE, TRUE, TRUE);
+}
+
+
 static void TrimQuotesAroundString (CharPtr str)
 {
   Int4 len;
@@ -2160,7 +2164,6 @@ static ValNodePtr OrgModLoadFormToApplyList (OrgModLoadFormPtr f)
 {
   ValNodePtr line;
   ValNodePtr apply_list = NULL;
-  ValNodePtr column_options = NULL;
   Int4       column_index;
   OrgModTableColumnPtr PNTR o_list;
 
@@ -2361,20 +2364,20 @@ static Boolean ListOrganismsWithMultipleRows (ValNodePtr apply_list)
             {
               if (StringCmp (t->identifiers->data.ptrvalue, t2->identifiers->data.ptrvalue) == 0)
               {
-                fprintf (lip->fp, " (both are %s).\n", t->identifiers->data.ptrvalue);
+                fprintf (lip->fp, " (both are %s).\n", (CharPtr) t->identifiers->data.ptrvalue);
               }
               else
               {
-                fprintf (lip->fp, " (%s and %s).\n", t->identifiers->data.ptrvalue, t2->identifiers->data.ptrvalue);
+                fprintf (lip->fp, " (%s and %s).\n", (CharPtr) t->identifiers->data.ptrvalue, (CharPtr) t2->identifiers->data.ptrvalue);
               }
             }
             else if (t->identifiers != NULL && t->identifiers->data.ptrvalue != NULL)
             {
-              fprintf (lip->fp, " (%s).\n", t->identifiers->data.ptrvalue);
+              fprintf (lip->fp, " (%s).\n", (CharPtr) t->identifiers->data.ptrvalue);
             }
             else if (t2->identifiers != NULL && t2->identifiers->data.ptrvalue != NULL)
             {
-              fprintf (lip->fp, " (%s).\n", t2->identifiers->data.ptrvalue);
+              fprintf (lip->fp, " (%s).\n", (CharPtr) t2->identifiers->data.ptrvalue);
             }
             else
             {
@@ -2409,7 +2412,7 @@ static Boolean ListRowsWithMultipleOrganisms (ValNodePtr apply_list)
     fprintf (lip->fp, "Row with the following match columns applies to %d organisms\n", ValNodeLen (t->biop_list));
     for (vnp_id = t->identifiers; vnp_id != NULL; vnp_id = vnp_id->next) 
     {
-      fprintf (lip->fp, "\t%s\n", vnp_id->data.ptrvalue);
+      fprintf (lip->fp, "\t%s\n", (CharPtr) vnp_id->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
   }
@@ -2434,7 +2437,7 @@ static void ListRowsWithoutOrganisms (ValNodePtr apply_list)
     if (t == NULL || t->biop_list != NULL || t->identifiers == NULL) continue;
     for (vnp_id = t->identifiers; vnp_id != NULL; vnp_id = vnp_id->next) 
     {
-      fprintf (lip->fp, "No match found for %s\n", vnp_id->data.ptrvalue);
+      fprintf (lip->fp, "No match found for %s\n", (CharPtr) vnp_id->data.ptrvalue);
       lip->data_in_log = TRUE;
     }
   }
@@ -3100,7 +3103,7 @@ static void ExportOneOrganism (BioSourcePtr biop, Pointer userdata)
     {
       sip = gen_sip->next;
       gen_sip->next = NULL;
-      SeqIdWrite (gen_sip, acc_str, PRINTID_TEXTID_ACCESSION, sizeof (acc_str));
+      SeqIdWrite (gen_sip, acc_str, PRINTID_FASTA_GENERAL, sizeof (acc_str));
       gen_sip->next = sip;
       fprintf (eotp->fp, "%s", acc_str);
     }
@@ -4476,7 +4479,7 @@ static void ApplyTableQuals (BioseqPtr bsp, Pointer userdata)
   Int4                   column_index;
   ValNodePtr             line;
   TableLinePtr           tlp;
-  Boolean                use_local_id;
+  Boolean                use_local_id = FALSE;
   FeatureQualTableData   fqtd;
   Int2                   seq_match_choice;
   CharPtr                idval;
@@ -4760,6 +4763,7 @@ typedef struct qualloadformdata {
   Int4                   num_columns;
   ButtoN                 remove_quotes;
   ButtoN                 accept_button;
+  ButtoN                 mail_button;
 } QualLoadFormData, PNTR QualLoadFormPtr;
 
 static void CleanupQualLoadForm (
@@ -4796,6 +4800,7 @@ static void ChangeTabColumnChoice (Pointer data)
         if (t->match_type != NULL) {
           if (have_match) {
             Disable (form_data->accept_button);
+            Disable (form_data->mail_button);
             return;
           } else {
             have_match = TRUE;
@@ -4808,15 +4813,19 @@ static void ChangeTabColumnChoice (Pointer data)
     }
     if (have_match && have_apply) {
       Enable (form_data->accept_button);
+      Enable (form_data->mail_button);
     } else {
       Disable (form_data->accept_button);
+      Disable (form_data->mail_button);
     }
   } else {
     err_list = TestDialog (form_data->list_dlg);
     if (err_list == NULL) {
       Enable (form_data->accept_button);
+      Enable (form_data->mail_button);
     } else {
       Disable (form_data->accept_button);
+      Disable (form_data->mail_button);
       err_list = ValNodeFree (err_list);
     }
   }
@@ -4834,7 +4843,7 @@ static Boolean ApplyTableValues (SeqEntryPtr sep, ValNodePtr table, ValNodePtr c
 
   err_list = ValidateTabTableValues (table, columns);
   for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-    fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+    fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     lip->data_in_log = TRUE;
   }
   err_list = ValNodeFreeData (err_list);
@@ -4844,7 +4853,7 @@ static Boolean ApplyTableValues (SeqEntryPtr sep, ValNodePtr table, ValNodePtr c
   dup_dest_errs = CheckObjTableForRowsThatApplyToTheSameDestination (obj_table);
   if (dup_dest_errs != NULL) {
     for (vnp = dup_dest_errs; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
       lip->data_in_log = TRUE;
     }
     CloseLog (lip);
@@ -4863,7 +4872,7 @@ static Boolean ApplyTableValues (SeqEntryPtr sep, ValNodePtr table, ValNodePtr c
   /* cycle through errors twice - first time, just print the ones with choice 1 (and sum lengths) */
   for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
     if (vnp->choice == 1) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
       lip->data_in_log = TRUE;
       msg_len += StringLen (vnp->data.ptrvalue) + 2;
     }
@@ -4871,7 +4880,7 @@ static Boolean ApplyTableValues (SeqEntryPtr sep, ValNodePtr table, ValNodePtr c
   /* then cycle again, printing 0s */
   for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
     if (vnp->choice == 0) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
       lip->data_in_log = TRUE;
     }
   }
@@ -4906,7 +4915,7 @@ static Boolean ApplyTableValues (SeqEntryPtr sep, ValNodePtr table, ValNodePtr c
 
   lip = OpenLog ("Table Problems");
   for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-    fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+    fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     lip->data_in_log = TRUE;
   }
   err_list = ValNodeFreeData (err_list);
@@ -4957,6 +4966,230 @@ static void DoAcceptQuals (ButtoN b)
 }
 
 
+typedef struct mailreport {
+  BioseqPtr    bsp;
+  BioSourcePtr biop;
+  CharPtr      old_name;
+} MailReportData, PNTR MailReportPtr;
+
+
+static MailReportPtr MailReportNew (BioseqPtr bsp, CharPtr old_name, BioSourcePtr biop)
+{
+  MailReportPtr m;
+
+  m = (MailReportPtr) MemNew (sizeof (MailReportData));
+  m->bsp = bsp;
+  m->old_name = StringSave (old_name);
+  m->biop = biop;
+  return m;
+}
+
+
+static MailReportPtr MailReportFree (MailReportPtr m)
+{
+  if (m != NULL) {
+    m->old_name = MemFree (m->old_name);
+    m = MemFree (m);
+  }
+  return m;
+}
+
+
+static ValNodePtr MailReportListFree (ValNodePtr vnp)
+{
+  ValNodePtr vnp_next;
+
+  while (vnp != NULL) {
+    vnp_next = vnp->next;
+    vnp->next = NULL;
+    vnp->data.ptrvalue = MailReportFree (vnp->data.ptrvalue);
+    vnp = ValNodeFree (vnp);
+    vnp = vnp_next;
+  }
+  return vnp;
+}
+
+
+static void MailReportCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqDescrPtr       sdp;
+  SeqMgrDescContext context;
+  BioSourcePtr      biop;
+
+  if (bsp == NULL || data == NULL || ISA_aa (bsp->mol)) {
+    return;
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_source, &context);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_source, &context)) {
+    if ((biop = (BioSourcePtr) sdp->data.ptrvalue) != NULL
+        && biop->org != NULL
+        && !StringHasNoText (biop->org->taxname)) {
+      ValNodeAddPointer ((ValNodePtr PNTR) data, 0, MailReportNew (bsp, biop->org->taxname, biop));
+    }
+  }
+}
+
+
+static Boolean HasTaxonomyID (BioSourcePtr biop)
+{
+  ValNodePtr  db;
+  DbtagPtr    dbt;
+  Boolean     rval = FALSE;
+
+  if (biop == NULL || biop->org == NULL) {
+    return FALSE;
+  }
+  for (db = biop->org->db; db != NULL && !rval; db = db->next) {
+    dbt = (DbtagPtr) db->data.ptrvalue;
+    if (dbt != NULL && dbt->db != NULL &&
+      StringICmp (dbt->db, "taxon") == 0) {
+      rval = TRUE;
+    }
+  }
+  return rval;
+}
+
+
+static void ReportOneMailReport (MailReportPtr m, BioSourcePtr biop, LogInfoPtr lip)
+{
+  Char              id_str[100];
+
+  SeqIdWrite (SeqIdFindBest (m->bsp->id, SEQID_GENBANK), id_str, PRINTID_REPORT, sizeof (id_str) - 1);
+  fprintf (lip->fp, "%s\t%s\t%s\n", id_str, m->old_name == NULL ? "" : m->old_name, 
+                 biop->org == NULL || biop->org->taxname == NULL ? "" : biop->org->taxname);
+  lip->data_in_log = TRUE;
+}
+
+
+static void ReportOneMailReportNoTaxId (MailReportPtr m, LogInfoPtr lip)
+{
+  SeqDescrPtr       sdp;
+  SeqMgrDescContext context;
+  BioSourcePtr      biop;
+
+  if (m == NULL || m->bsp == NULL) {
+    return;
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (m->bsp, NULL, Seq_descr_source, &context);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (m->bsp, sdp, Seq_descr_source, &context)) {
+    if ((biop = (BioSourcePtr) sdp->data.ptrvalue) != NULL 
+        && biop == m->biop
+        &&!HasTaxonomyID(biop)) {
+      ReportOneMailReport (m, biop, lip);
+      lip->data_in_log = TRUE;
+      break;
+    }
+  }
+}
+
+
+static void ReportOneMailReportSpToNoSp (MailReportPtr m, LogInfoPtr lip)
+{
+  SeqDescrPtr       sdp;
+  SeqMgrDescContext context;
+  BioSourcePtr      biop;
+
+  if (m == NULL || m->bsp == NULL || StringStr (m->old_name, " sp.") == NULL) {
+    return;
+  }
+
+  for (sdp = SeqMgrGetNextDescriptor (m->bsp, NULL, Seq_descr_source, &context);
+       sdp != NULL;
+       sdp = SeqMgrGetNextDescriptor (m->bsp, sdp, Seq_descr_source, &context)) {
+    if ((biop = (BioSourcePtr) sdp->data.ptrvalue) != NULL 
+        && biop == m->biop
+        && biop->org != NULL && biop->org->taxname != NULL
+        && StringStr (biop->org->taxname, " sp.") == NULL) {
+      ReportOneMailReport (m, biop, lip);
+      lip->data_in_log = TRUE;
+    }
+  }
+}
+
+
+static void ReportUnpublishedTaxnames (ValNodePtr list, LogInfoPtr lip)
+{
+  ValNodePtr request_list = NULL, response_list;
+  ValNodePtr vnp_m, vnp_r;
+  MailReportPtr m;
+
+  for (vnp_m = list; vnp_m != NULL; vnp_m = vnp_m->next) {
+    m = (MailReportPtr) vnp_m->data.ptrvalue;
+    ValNodeAddPointer (&request_list, 3, m->biop->org);
+  }
+  response_list = Taxon3GetOrgRefList (request_list);
+  ValNodeFree (request_list);
+
+  fprintf (lip->fp, "\n\nUnpublished Names\n");
+  fprintf (lip->fp, "Accession\tOld Name\tNew Name\n");
+  for (vnp_m = list, vnp_r = response_list;
+       vnp_m != NULL && vnp_r != NULL;
+       vnp_m = vnp_m->next, vnp_r = vnp_r->next) {
+    if (vnp_r->choice & eReturnedOrgFlag_unpublished) {
+      m = (MailReportPtr) vnp_m->data.ptrvalue;
+      ReportOneMailReport (m, m->biop, lip);
+    }
+  }
+
+  ValNodeFree (response_list);
+}
+
+
+static void SpecialMailReport (ButtoN b)
+{
+  QualLoadFormPtr form_data;
+  ValNodePtr      list = NULL, vnp;
+  ValNodePtr      columns = NULL;
+  SeqEntryPtr     sep;
+  LogInfoPtr      lip;
+  MailReportPtr   m;
+
+  form_data = (QualLoadFormPtr) GetObjectExtra (b);
+  if (form_data == NULL) return;
+
+  /* first, get list of accessions and current names */
+  sep = GetTopSeqEntryForEntityID (form_data->input_entityID);
+  VisitBioseqsInSep (sep, &list, MailReportCallback);
+
+  /* now apply table */
+  DoAcceptQuals (b);
+
+  /* now do taxfix */
+  Taxon3ReplaceOrgInSeqEntryEx (sep, FALSE, FALSE);
+  ObjMgrSetDirtyFlag (form_data->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, form_data->input_entityID, 0, 0);
+  Update();
+
+  /* now create report for organisms without IDs */
+  lip = OpenLog ("Organism Change Report");
+  fprintf (lip->fp, "Failed Lookups\n");
+  fprintf (lip->fp, "Accession\tOld Name\tNew Name\n");
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    m = (MailReportPtr) vnp->data.ptrvalue;
+    ReportOneMailReportNoTaxId(m, lip);
+  }
+  fprintf (lip->fp, "\n\nSp. Replaced with Real\n");
+
+  fprintf (lip->fp, "Accession\tOld Name\tNew Name\n");
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    m = (MailReportPtr) vnp->data.ptrvalue;
+    ReportOneMailReportSpToNoSp(m, lip);
+  }
+
+  ReportUnpublishedTaxnames (list, lip);
+
+  CloseLog (lip);
+  lip = FreeLog (lip);
+        
+  MailReportListFree(list);
+
+}
+
+
 static void AutoMatchQuals (ButtoN b)
 {
   QualLoadFormPtr form_data;
@@ -5083,6 +5316,223 @@ static void LoadNewTable (ButtoN b)
 
 }
 
+typedef void (*Nlm_ReparseTabTable) PROTO ((ValNodePtr));
+
+
+static void ReDrawWindowAfterTableReload(QualLoadFormPtr form_data)
+{
+  QualLoadFormPtr new_form_data;
+  ValNodePtr      blank_list, columns = NULL, c_vnp, table;
+  Int4            i;
+  WindoW          w;
+  TabColumnConfigPtr t;
+
+  if (form_data->list_dlg != NULL) {
+    /* it's ok, can just repopulate dialogs */
+    blank_list = CountTabTableBlanks (form_data->table);
+    ChangeDataForTabColumnConfigListDialog (form_data->list_dlg, form_data->table->data.ptrvalue, blank_list);
+    blank_list = ValNodeFree (blank_list);
+  } else {
+    /* build a new window */
+    table = form_data->table;
+    form_data->table = NULL;
+
+    w = CreateTableReaderWindowWithTable (form_data->input_entityID, table);
+    /* get old configurations */
+    if (form_data->list_dlg == NULL) {
+      for (i = 0; i < form_data->num_columns; i++) {
+        t = DialogToPointer (form_data->column_list[i]);
+        ValNodeAddPointer (&columns, 0, t);
+      }
+    } else {
+      columns = DialogToPointer (form_data->list_dlg);
+    }
+
+    /* apply to new window */
+    new_form_data = (QualLoadFormPtr) GetObjectExtra (w);
+    if (new_form_data->list_dlg == NULL) {
+      for (i = 0, c_vnp = columns; i < new_form_data->num_columns && c_vnp != NULL; i++, c_vnp = c_vnp->next) {
+        PointerToDialog (new_form_data->column_list[i], c_vnp->data.ptrvalue);
+      }
+    } else {
+      PointerToDialog (new_form_data->list_dlg, columns);
+    }
+    columns = ValNodeFree (columns);
+    SetStatus (new_form_data->remove_quotes, GetStatus (form_data->remove_quotes));
+    SetStatus (new_form_data->leave_dlg_up, GetStatus (form_data->leave_dlg_up));
+
+    /* remove old window */
+    Remove ((WindoW) form_data->form);
+    
+    RealizeWindow (w);
+    Show (w);
+    Update ();
+  }
+}
+
+
+static void ReLoadTable (ButtoN b, Nlm_ReparseTabTable reparse_func)
+{
+  QualLoadFormPtr form_data;
+
+  form_data = (QualLoadFormPtr) GetObjectExtra (b);
+  if (form_data == NULL || reparse_func == NULL) return;
+
+  reparse_func (form_data->table);
+
+  ReDrawWindowAfterTableReload (form_data);
+}
+
+
+static void ReloadFirstSpace (ButtoN b)
+{
+  ReLoadTable (b, ReparseTabTableConvertFirstSpaceToTab);
+}
+
+
+static void ReloadMultiSpace (ButtoN b)
+{
+  ReLoadTable (b, ReparseTabTableConvertMultiSpaceToTab);
+}
+
+
+static void ReparseTabTableAddDummySeqId (ValNodePtr row_list)
+{
+  AddTextToTabTableColumn (row_list, 0, "_Seq1", ExistingTextOption_append_none);
+}
+
+
+static void ReloadNewBankitNoId (ButtoN b)
+{
+  ReLoadTable (b, ReparseTabTableAddDummySeqId);
+}
+
+
+static void ReparseForFileId (ValNodePtr table)
+{
+  ValNodePtr column_list = NULL;
+  ValNodeAddInt (&column_list, 0, 0);
+  ValNodeAddInt (&column_list, 0, 1);
+  CombineTabTableColumns (table, column_list, "/");
+}
+
+
+static void ReloadFileId (ButtoN b)
+{
+  ReLoadTable (b, ReparseForFileId);
+}
+
+
+static void ReparseForNewBankitId (ValNodePtr table)
+{
+  ValNodePtr column_list = NULL;
+  ValNodeAddInt (&column_list, 0, 0);
+  ValNodeAddInt (&column_list, 0, 1);
+  CombineTabTableColumns (table, column_list, "_");
+}
+
+
+static void ReloadNewBankitId (ButtoN b)
+{
+  ReLoadTable (b, ReparseForNewBankitId);
+}
+
+
+static int LIBCALLBACK SortVnpByInt (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+
+  if (ptr1 == NULL || ptr2 == NULL) return 0;
+  vnp1 = *((ValNodePtr PNTR) ptr1);
+  vnp2 = *((ValNodePtr PNTR) ptr2);
+  if (vnp1 == NULL || vnp2 == NULL) return 0;
+
+  if (vnp1->data.intvalue > vnp2->data.intvalue) {
+    return 1;
+  } else if (vnp1->data.intvalue < vnp2->data.intvalue) {
+    return -1;
+  }
+
+  return 0;
+}
+
+
+static void CombineColumns (ButtoN b_in)
+{
+  WindoW w;
+  GrouP  h, c;
+  DialoG dlg;
+  ValNodePtr options = NULL, vnp, combine_list = NULL;
+  Int4       i;
+  ButtoN b;
+  ModalAcceptCancelData acd;
+  QualLoadFormPtr form_data;
+  CharPtr         label;
+
+  form_data = (QualLoadFormPtr) GetObjectExtra (b_in);
+  if (form_data == NULL || form_data->table == NULL || form_data->table->data.ptrvalue == NULL) return;
+  
+  acd.accepted = FALSE;
+  acd.cancelled = FALSE;
+  acd.third_option = FALSE;
+  
+  w = ModalWindow(-20, -13, -10, -10, NULL);
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  for (i = 0, vnp = form_data->table->data.ptrvalue;
+       i < form_data->num_columns && vnp != NULL; 
+       i++, vnp = vnp->next) 
+  {
+    label = (CharPtr) MemNew (sizeof (Char) * (StringLen (vnp->data.ptrvalue) + 15));
+    sprintf (label, "%5d   %s", i + 1, vnp->data.ptrvalue);
+    ValNodeAddPointer (&options, i, label);
+  }
+
+  dlg = ValNodeSelectionDialog (h, options, TALL_SELECTION_LIST, ValNodeStringName,
+                                              ValNodeSimpleDataFree, ValNodeStringCopy,
+                                              ValNodeStringMatch, "column", 
+                                              NULL, NULL, TRUE);
+
+  c = HiddenGroup (h, 3, 0, NULL);
+  SetGroupSpacing (c, 10, 10);
+  b = PushButton (c, "Combine", ModalAcceptButton);
+  SetObjectExtra (b, &acd, NULL);
+  b = PushButton (c, "Cancel", ModalCancelButton);
+  SetObjectExtra (b, &acd, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) dlg, (HANDLE) c, NULL);
+  
+  Show(w); 
+  Select (w);
+  while (!acd.accepted && ! acd.cancelled)
+  {
+    ProcessExternalEvent ();
+    Update ();
+    ProcessAnEvent ();
+    if (acd.accepted)
+    {
+      /* combine here */
+      options = DialogToPointer (dlg);
+      if (options == NULL || options->next == NULL) {
+        Message (MSG_ERROR, "Must choose at least two columns!");
+        acd.accepted = FALSE;
+      } else {
+        for (vnp = options; vnp != NULL; vnp = vnp->next) {
+          ValNodeAddInt (&combine_list, 0, vnp->choice);
+        }
+        combine_list = ValNodeSort (combine_list, SortVnpByInt);
+        CombineTabTableColumns (form_data->table, combine_list, ",");
+        combine_list = ValNodeFree (combine_list);
+        ReDrawWindowAfterTableReload (form_data);
+      }
+      options = ValNodeFree (options);
+    }
+  }
+  Remove (w);
+}
+
 
 static WindoW CreateTableReaderWindowWithTable (Uint2 entityID, ValNodePtr table)
 {
@@ -5090,7 +5540,7 @@ static WindoW CreateTableReaderWindowWithTable (Uint2 entityID, ValNodePtr table
   ValNodePtr   col_vnp, blank_vnp;
   Int4         index;
   WindoW        w;
-  GrouP         h, g, g2, c;
+  GrouP         h, g, g2, g3, c;
   QualLoadFormPtr form_data;
   CharPtr         title;
   Int4            col_for_list = 3;
@@ -5150,18 +5600,37 @@ static WindoW CreateTableReaderWindowWithTable (Uint2 entityID, ValNodePtr table
   form_data->remove_quotes = CheckBox (g2, "Remove quotes around values", NULL);
   SetStatus (form_data->remove_quotes, TRUE);
 
-  c = HiddenGroup (h, 4, 0, NULL);
+  g3 = HiddenGroup (h, 7, 0, NULL);
+  b = PushButton (g3, "Load New Table", LoadNewTable);
+  SetObjectExtra (b, form_data, NULL);
+  b = PushButton (g3, "Reload, 1st Space=Tab", ReloadFirstSpace);
+  SetObjectExtra (b, form_data, NULL);
+  b = PushButton (g3, "Reload, Mult Space=Tab", ReloadMultiSpace);
+  SetObjectExtra (b, form_data, NULL);
+  b = PushButton (g3, "Reload, First Two are File ID", ReloadFileId);
+  SetObjectExtra (b, form_data, NULL);
+  b = PushButton (g3, "New BankIt With SeqId", ReloadNewBankitId);
+  SetObjectExtra (b, form_data, NULL);
+  b = PushButton (g3, "New BankIt No SeqId", ReloadNewBankitNoId);
+  SetObjectExtra (b, form_data, NULL);
+  b = PushButton (g3, "Combine Columns", CombineColumns);
+  SetObjectExtra (b, form_data, NULL);
+
+  c = HiddenGroup (h, 7, 0, NULL);
   form_data->accept_button = DefaultButton (c, "Accept", DoAcceptQuals);
   SetObjectExtra (form_data->accept_button, form_data, NULL);
   Disable (form_data->accept_button);
-  b = PushButton (c, "Load New Table", LoadNewTable);
-  SetObjectExtra (b, form_data, NULL);
+  form_data->mail_button = DefaultButton (c, "Accept and Make Mail Report", SpecialMailReport);
+  SetObjectExtra (form_data->mail_button, form_data, NULL);
+  Disable (form_data->mail_button);
+  
   PushButton (c, "Cancel", StdCancelButtonProc);
   form_data->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
 
   AlignObjects (ALIGN_CENTER,
                 (HANDLE) g, 
                 (HANDLE) g2,
+                (HANDLE) g3,
                 (HANDLE) c, NULL);
 
   blank_list = ValNodeFree (blank_list);
@@ -5240,6 +5709,48 @@ extern void NewLoadFeatureQualifierTable (IteM i)
 }
 
 
+NLM_EXTERN void CreateTableReaderWindowWithStructuredComments (IteM i)
+{
+  BaseFormPtr  bfp;
+  WindoW        w;
+  QualLoadFormPtr form_data;
+  TabColumnConfigPtr t;
+  ValNodePtr         table, column_list = NULL;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  table = CreateStructuredCommentTableFromSeqEntry(GetTopSeqEntryForEntityID(bfp->input_entityID));
+  w = CreateTableReaderWindowWithTable (bfp->input_entityID, table);
+
+  if (w != NULL) {
+    /* populate */
+    form_data = (QualLoadFormPtr) GetObjectExtra (w);
+    if (form_data != NULL) {
+      t = TabColumnConfigNew ();
+      t->match_type = MatchTypeNew ();
+      t->match_type->match_location = eTableMatchNucID;
+      if (form_data->list_dlg == NULL) {
+        PointerToDialog (form_data->column_list[0], t);
+      } else {
+        ValNodeAddPointer (&column_list, 0, t);
+        PointerToDialog (form_data->list_dlg, column_list);
+        column_list = ValNodeFree (column_list);
+      }
+      t = TabColumnConfigFree (t);
+    } 
+
+    RealizeWindow (w);
+    Show (w);
+    Update ();
+  }
+}  
+  
+
 extern void LoadTaxTableReader (IteM i)
 {
   BaseFormPtr  bfp;
@@ -5416,7 +5927,7 @@ extern void ExternalSourceQualifierTableReader (IteM i)
       t->field = FieldTypeFromString (val->data.ptrvalue);
       if (t->field == NULL) {
         t = TabColumnConfigFree (t);
-        fprintf (lip->fp, "%s\n", val->data.ptrvalue);
+        fprintf (lip->fp, "%s\n", (CharPtr) val->data.ptrvalue);
         lip->data_in_log = TRUE;
       } else {
         any_valid = TRUE;
@@ -5573,7 +6084,7 @@ static void AddPrefixesToOneDefLine (
         {
           mod = mod->next;
         }
-        if ( UseOrgModifier (mod, taxName))
+        if ( UseOrgModifier (mod, taxName, FALSE))
         {
           no_semicolon_len = StringCSpn (mod->subname, ";");
           if (mod->subtype == ORGMOD_nat_host)
@@ -6436,7 +6947,6 @@ CheckTableDataAssociation
   BioseqTableDataAssocPtr bap1, bap2;
   ValNodePtr duplicated_bioseqs = NULL, already_has_list = NULL, err_list = NULL;
   ValNodePtr blanks = NULL;
-  MsgAnswer ans = ANS_YES;
   ClickableItemPtr cip;
   TableLinePtr     tlp;
   Boolean          found;
@@ -6662,7 +7172,7 @@ static void ApplyGenomeProjectIDs (ButtoN b)
   SeqEntryPtr        sep;
   MatchBioseqToTableData match_func = NULL;
   Int4                   match_pos, project_id_col, col_num;
-  Boolean                ok = FALSE, do_replace = FALSE;
+  Boolean                ok = FALSE;
   Boolean                skip_already_has = FALSE, blanks_erase = FALSE;
   ValNodePtr             err_list = NULL;
   SeqEntryPtr            oldscope;
@@ -6935,6 +7445,7 @@ static ValNodePtr GetFeatureListForProteinBioseq (Uint1 featdef, BioseqPtr bsp)
     cds = SeqMgrGetCDSgivenProduct (bsp, NULL);
     if (cds != NULL) 
     {
+      sfp = NULL;
       if (featdef == FEATDEF_CDS)
       {
         sfp = cds;
@@ -7005,8 +7516,6 @@ static SeqFeatPtr GetFeatureForFieldByMatchList (ValNodePtr field, ValNodePtr ma
 {
   Uint1 featdef;
   ValNodePtr vnp;
-  BioseqPtr  bsp = NULL;
-  SeqFeatPtr gene = NULL;
   ValNodePtr tmp;
   CharPtr    msg;
   CharPtr    no_match_fmt = "No feature found for %s";
@@ -7471,7 +7980,7 @@ FindMatchListForRow
   Int4       index;
   ValNodePtr match_list = NULL, vnp_match;
   SeqIdPtr   sip;
-  BioseqPtr  bsp, nbsp = NULL;
+  BioseqPtr  bsp;
   FindGeneLocusTagData fd;
 
   if (f_list == NULL || tlp == NULL || tlp->parts == NULL || sep == NULL) return NULL;
@@ -7526,7 +8035,6 @@ static void DoLoadFeatureFieldTable (ButtoN b)
   ValNodePtr            vnp;
   FeatureFieldColumnChoicePtr PNTR f_list;  
   Int4                             index;
-  Boolean                          missing = FALSE;
   Int4                             num_rows;
   ValNodePtr PNTR                  match_lists;
   ValNodePtr                       missing_ids = NULL, missing_genes = NULL;
@@ -7585,7 +8093,7 @@ static void DoLoadFeatureFieldTable (ButtoN b)
   
   lip = OpenLog ("Table Problems");
   for (vnp = errors; vnp != NULL; vnp = vnp->next) {
-    fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+    fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     lip->data_in_log = TRUE;
   }
   errors = ValNodeFreeData (errors);
@@ -7816,10 +8324,12 @@ static Pointer GetRevSectionInterval (Uint1 data_choice, Pointer data, Pointer m
 }
 
 
+/*
 static BulkEdFieldData revsection_fields[] = {
   { "Sequence", NULL, NULL, GetRevSectionSequence, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
   { "Interval", NULL, NULL, GetRevSectionInterval, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
   { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
+*/
 
 
 typedef struct deltaseqint {
@@ -8033,7 +8543,7 @@ static void RevCompSeqPntForFlippedInterval (SeqPntPtr spp, BioseqPtr bsp, Int4
 
 static void RevCompLocationForFlippedInterval (SeqLocPtr head, BioseqPtr bsp, Int4 start, Int4 stop)
 {
-	SeqLocPtr newhead = NULL, slp;
+	SeqLocPtr slp;
 	SeqIntPtr sip;
 	SeqPntPtr spp;
 	PackSeqPntPtr pspp, pspp2;
@@ -8703,6 +9213,40 @@ static void CleanupStructuredCommentsForm (GraphiC g, VoidPtr data)
 }
 
 
+static CharPtr DbnameFromString (CharPtr string)
+{
+  CharPtr tmp;
+  Int4    len;
+
+  if (StringHasNoText (string)) {
+    return NULL;
+  }
+
+  tmp = StringSave (string + StringSpn (string, "##"));
+  len = StringLen (tmp);
+  if (len > 2 && StringCmp (tmp + len - 2, "##") == 0) {
+    tmp[len - 2] = 0;
+    len -= 2;
+  }
+  if (len > 6 && StringCmp (tmp + len - 6, "-START") == 0) {
+    tmp[len - 6] = 0;
+    len -= 6;
+  }
+  if (len > 6 && StringCmp (tmp + len - 4, "-END") == 0) {
+    tmp[len - 4] = 0;
+    len -= 4;
+  }
+  if (len > 4 && StringCmp (tmp + len - 4, "Data") == 0) {
+    tmp[len - 4] = 0;
+    len -= 4;
+  }
+  if (StringCmp (tmp, "HIV-Database") == 0) {
+    StringCpy (tmp, "HIVDatabase");
+  }
+  return tmp;
+}
+
+
 static UserObjectPtr UserObjectFromRow (ValNodePtr header, ValNodePtr line, Int4 col, CharPtr dbname, ValNodePtr PNTR err_list)
 {
   ValNodePtr vnp_h, vnp_l;
@@ -8714,6 +9258,8 @@ static UserObjectPtr UserObjectFromRow (ValNodePtr header, ValNodePtr line, Int4
   CharPtr       prefix = NULL, suffix = NULL;
   CharPtr       prefix_fmt = "##%sData-START##";
   CharPtr       suffix_fmt = "##%sData-END##";
+  CharPtr       tmp_dbname = NULL;
+  Boolean       prefix_from_row = FALSE;
 
   if (header == NULL || line == NULL) {
     return NULL;
@@ -8735,19 +9281,33 @@ static UserObjectPtr UserObjectFromRow (ValNodePtr header, ValNodePtr line, Int4
     id_str = vnp_l->data.ptrvalue;
   }
 
+  
+  /* look for dbname in table if not supplied */
+  if (StringHasNoText (dbname)) {
+    for (vnp_h = header, vnp_l = line->data.ptrvalue;
+         vnp_h != NULL && vnp_l != NULL && StringHasNoText (dbname);
+         vnp_h = vnp_h->next, vnp_l = vnp_l->next) {
+      if (StringICmp (vnp_h->data.ptrvalue, "StructuredCommentPrefix") == 0
+          || StringICmp (vnp_h->data.ptrvalue, "StructuredCommentSuffix") == 0) {
+        tmp_dbname = DbnameFromString(vnp_l->data.ptrvalue);
+        dbname = tmp_dbname;
+        prefix_from_row = TRUE;
+      }
+    }
+  }
+
+
   /* build user object */
   vnp_h = header;
   vnp_l = line->data.ptrvalue;
   num = 0;
 
-  if (StringHasNoText (dbname)) {
-    dbname = "Meta";
-  }
-
+  if (!StringHasNoText (dbname)) {
   prefix = (CharPtr) MemNew (sizeof (Char) * (StringLen (prefix_fmt) + StringLen (dbname)));
   sprintf (prefix, prefix_fmt, dbname);
   suffix = (CharPtr) MemNew (sizeof (Char) * (StringLen (suffix_fmt) + StringLen (dbname)));
   sprintf (suffix, suffix_fmt, dbname);
+  }
 
   uop = CreateStructuredCommentUserObject (prefix, suffix);
 
@@ -8756,8 +9316,12 @@ static UserObjectPtr UserObjectFromRow (ValNodePtr header, ValNodePtr line, Int4
 
   while (vnp_h != NULL && vnp_l != NULL) {
     if (num != col && !StringHasNoText (vnp_l->data.ptrvalue)) {
+      if (!prefix_from_row 
+          || (StringCmp (vnp_h->data.ptrvalue, "StructuredCommentPrefix") != 0
+              && StringCmp (vnp_h->data.ptrvalue, "StructuredCommentSuffix") != 0)) {
       AddItemStructuredCommentUserObject (uop, vnp_h->data.ptrvalue, vnp_l->data.ptrvalue);
     }
+    }
     vnp_h = vnp_h->next;
     vnp_l = vnp_l->next;
     num++;
@@ -8770,6 +9334,7 @@ static UserObjectPtr UserObjectFromRow (ValNodePtr header, ValNodePtr line, Int4
     sprintf (msg, extra_data_fmt, id_str);
     ValNodeAddPointer (err_list, 0, msg);
   }
+  tmp_dbname = MemFree (tmp_dbname);
   return uop;
 }
 
@@ -8803,7 +9368,7 @@ static void DoParseStructuredComments (ButtoN b)
   if (err_list != NULL) {
     lip = OpenLog ("Table Problems");
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     CloseLog (lip);
@@ -8822,11 +9387,13 @@ static void DoParseStructuredComments (ButtoN b)
   line = frm->table->next;
   s_row = sequence_lists;
 
+  if (frm->database_name != NULL) {
   database_name = SaveStringFromText (frm->database_name);
   len = StringLen (database_name);
   if (len >= 4 && StringCmp (database_name + len - 4, "data") == 0) {
     database_name[len - 4] = 0;
   }
+  }
 
   while (line != NULL && s_row != NULL) {
     vnp_s = s_row->data.ptrvalue;
@@ -8850,7 +9417,7 @@ static void DoParseStructuredComments (ButtoN b)
   if (err_list != NULL) {
     lip = OpenLog ("Data Problems");
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     CloseLog (lip);
@@ -8972,7 +9539,7 @@ NLM_EXTERN void CreateStructuredCommentsItem (IteM i)
   } 
 }
 
-
+#if 0
 static void DoSubmitterParseStructuredComments (ButtoN b)
 {
   StructuredCommentsFormPtr frm;
@@ -9003,7 +9570,7 @@ static void DoSubmitterParseStructuredComments (ButtoN b)
   if (err_list != NULL) {
     lip = OpenLog ("Table Problems");
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     CloseLog (lip);
@@ -9021,7 +9588,9 @@ static void DoSubmitterParseStructuredComments (ButtoN b)
   header = frm->table->data.ptrvalue;
   line = frm->table->next;
   s_row = sequence_lists;
+  if (frm->database_name != NULL) {
   database_name = SaveStringFromText (frm->database_name);
+  }
 
   while (line != NULL && s_row != NULL) {
     vnp_s = s_row->data.ptrvalue;
@@ -9045,7 +9614,7 @@ static void DoSubmitterParseStructuredComments (ButtoN b)
   if (err_list != NULL) {
     lip = OpenLog ("Data Problems");
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     CloseLog (lip);
@@ -9062,19 +9631,24 @@ static void DoSubmitterParseStructuredComments (ButtoN b)
   Update ();
   
 }
-
+#endif
 
 NLM_EXTERN void SubmitterCreateStructuredComments (IteM i)
 {
   BaseFormPtr        bfp;
-  SeqEntryPtr        sep;
   Char               path [PATH_MAX];
   FILE *fp;
-  StructuredCommentsFormPtr frm;
-  WindoW                    w;
-  GrouP                     h, c;
-  PrompT                    ppt1;
-  ButtoN                    b;
+  Int4                      col;
+  MatchTypeData             match_type;
+  CharPtr                   database_name = NULL;
+  ValNodePtr                sequence_lists;
+  SeqEntryPtr               sep;
+  ValNodePtr                err_list = NULL, vnp, header, line, s_row, vnp_s;
+  LogInfoPtr                lip;
+  BioseqPtr                 bsp;
+  UserObjectPtr             uop, uop_cpy;
+  SeqDescrPtr               sdp;
+  ValNodePtr                table;
 
 #ifdef WIN_MAC
   bfp = currentFormDataPtr;
@@ -9088,48 +9662,88 @@ NLM_EXTERN void SubmitterCreateStructuredComments (IteM i)
   if (sep == NULL)
     return;
 
-  if (GetInputFileName (path, sizeof (path), "", "TEXT")) {
+  if (!GetInputFileName (path, sizeof (path), "", "TEXT")) {
+    return;
+  }
     fp = FileOpen (path, "r");
     if (fp == NULL) {
       Message (MSG_ERROR, "Unable to open %s");
-    } else {
-      frm = (StructuredCommentsFormPtr) MemNew (sizeof (StructuredCommentsFormData));
-      if (frm == NULL) {
-        FileClose (fp);
         return;
       }
-      frm->table = ReadTabTableFromFile(fp);
+  table = ReadTabTableFromFile(fp);
       FileClose (fp);
-      if (frm->table == NULL || frm->table->data.ptrvalue == NULL || frm->table->next == NULL) {
+  if (table == NULL || table->data.ptrvalue == NULL || table->next == NULL) {
         Message (MSG_ERROR, "Unable to read table from file");
-        frm = MemFree (frm);
         return;
       }
 
-      w = FixedWindow (-50, -33, -10, -10, "Parse Structured Comment From File", StdCloseWindowProc);
-      SetObjectExtra (w, frm, CleanupStructuredCommentsForm);
-      frm->form = (ForM) w;
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  col = 0;
+  match_type.choice = eTableMatchNucID;
+  match_type.match_location = String_location_equals;
+  match_type.data = NULL;
 
-      frm->input_entityID = bfp->input_entityID;
+  sequence_lists = GetSequenceListsForMatchTypeInTabTable (sep, table->next, col, &match_type, &err_list);
 
-      h = HiddenGroup (w, -1, 0, NULL);
+  if (err_list != NULL) {
+    lip = OpenLog ("Table Problems");
+    for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
+    }
+    lip->data_in_log = TRUE;
+    CloseLog (lip);
+    lip = FreeLog (lip);
+    err_list = ValNodeFreeData (err_list);
+    if (ANS_YES != Message (MSG_YN, "Continue with table problems")) {
+      sequence_lists = FreeSequenceLists(sequence_lists);
+      return;
+    }
+  }
 
-      ppt1 = StaticPrompt (h, "Choose database name", 0, dialogTextHeight,
-		                       programFont, 'l');
+  WatchCursor ();
+  Update();
 
-      frm->database_name = DialogText (h, "", 10, NULL);
+  header = table->data.ptrvalue;
+  line = table->next;
+  s_row = sequence_lists;
 
-      c = HiddenGroup (h, 2, 0, NULL);
-      b = PushButton (c, "Accept", DoSubmitterParseStructuredComments);
-      SetObjectExtra (b, frm, NULL);
-      PushButton (c, "Cancel", StdCancelButtonProc);
+  while (line != NULL && s_row != NULL) {
+    vnp_s = s_row->data.ptrvalue;
+    if (vnp_s != NULL) {
+      uop = UserObjectFromRow (header, line, col, NULL, &err_list);
+      while (vnp_s != NULL) {
+        bsp = vnp_s->data.ptrvalue;
+        uop_cpy = (UserObjectPtr) AsnIoMemCopy (uop, (AsnReadFunc) UserObjectAsnRead, (AsnWriteFunc) UserObjectAsnWrite);
+        sdp = CreateNewDescriptorOnBioseq (bsp, Seq_descr_user);
+        sdp->data.ptrvalue = uop_cpy;
+        vnp_s = vnp_s->next;
+      }
+      uop = UserObjectFree (uop);
+    }
+    line = line->next;
+    s_row = s_row->next;
+  }
 
-      AlignObjects (ALIGN_CENTER, (HANDLE) ppt1, (HANDLE) frm->database_name, (HANDLE) c, NULL);
-      RealizeWindow (w);
-      Show (w);
-      Update();
+
+  if (err_list != NULL) {
+    lip = OpenLog ("Data Problems");
+    for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
+    lip->data_in_log = TRUE;
+    CloseLog (lip);
+    lip = FreeLog (lip);
+    err_list = ValNodeFreeData (err_list);
   } 
+
+  table = FreeTabTable (table);
+  sequence_lists = FreeSequenceLists(sequence_lists);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+
+  ArrowCursor ();
+  Update ();
+
 }
 
 
@@ -9165,7 +9779,10 @@ static ValNodePtr OrgModListsMatch (OrgModPtr mod1, OrgModPtr mod2)
   ValNodePtr rval = NULL;
   OrgModPtr cmp1, cmp2;
   Boolean    found;
-  CharPtr    str, qual, mismatch_fmt = "Mismatched values for %s", missing_fmt = "Only one has %s";
+  CharPtr    str, qual, mismatch_fmt = "Mismatched values for %s";
+#if 0
+  CharPtr    missing_fmt = "Only one has %s";
+#endif
 
   /* look for missing and mismatch */
   for (cmp1 = mod1; cmp1 != NULL; cmp1 = cmp1->next) {
@@ -9355,7 +9972,10 @@ static ValNodePtr SubtypeListsMatch (SubSourcePtr ssp1, SubSourcePtr ssp2)
   ValNodePtr rval = NULL;
   SubSourcePtr cmp1, cmp2;
   Boolean    found;
-  CharPtr    str, qual, mismatch_fmt = "Mismatched values for %s", missing_fmt = "Only one has %s";
+  CharPtr    str, qual, mismatch_fmt = "Mismatched values for %s";
+#if 0
+  CharPtr    missing_fmt = "Only one has %s";
+#endif
 
   /* look for missing and mismatch */
   for (cmp1 = ssp1; cmp1 != NULL; cmp1 = cmp1->next) {
@@ -9739,7 +10359,7 @@ static void DoExportQualifiers (ButtoN b)
     field_list = DialogToPointer (frm->src_qual_selection);
   }
   val = GetValue (frm->qual_choice);
-  if ((val < 2 || val > 4) && field_list == NULL) {
+  if ((val < 2 || val > 6) && field_list == NULL) {
     Message (MSG_ERROR, "Must select qualifiers to export!");
     return;
   }
@@ -9766,6 +10386,10 @@ static void DoExportQualifiers (ButtoN b)
 
   if (GetOutputFileName (path, sizeof (path), NULL)) {
     fp = FileOpen (path, "w");
+    if (fp == NULL) {
+      Message (MSG_ERROR, "Unable to open %s", path);
+      return;
+    }
     ExportFieldTable (field_type, field_list, GetTopSeqEntryForEntityID (frm->input_entityID), fp);
     FileClose (fp);
   }
@@ -9962,77 +10586,6 @@ extern void ExportBankitComments (IteM i)
 }
 
 
-static void TrimPrimerSeqJunkFromString (CharPtr str)
-{
-  Int4 len;
-  CharPtr src, dst;
-  
-  if (StringHasNoText (str)) {
-    return;
-  }
-  len = StringLen (str);
-
-  if (len >= 7 && StringNCmp (str, "5'-", 3) == 0 && StringCmp (str + len - 3, "-3'") == 0) {
-    src = str + 3;
-    dst = str;
-    len -= 6;
-
-    while (len > 0) {
-      *dst = *src;
-      src++;
-      dst++;
-      len--;
-    }
-    *dst = 0;
-  } else if ((len >= 5 && StringNCmp (str, "5-", 2) == 0 && StringCmp (str + len - 2, "-3") == 0)
-             || (len >= 5 && StringNCmp (str, "5'", 2) == 0 && StringCmp (str + len - 2, "3'") == 0)) {
-    src = str + 2;
-    dst = str;
-    len -= 4;
-    while (len > 0) {
-      *dst = *src;
-      src++;
-      dst++;
-      len--;
-    }
-    *dst = 0;
-  }
-
-}
-
-
-static void TrimPrimerSeqJunkOnBioSource (BioSourcePtr biop)
-{
-  SubSourcePtr ssp;
-
-  if (biop == NULL) {
-    return;
-  }
-
-  for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
-    if (ssp->subtype == SUBSRC_fwd_primer_seq
-      || ssp->subtype == SUBSRC_rev_primer_seq) {
-      TrimPrimerSeqJunkFromString (ssp->name);
-    }
-  }
-}
-
-
-static void TrimPrimerSeqJunkDescrCallback (SeqDescrPtr sdp, Pointer data)
-{
-  if (sdp != NULL && sdp->choice == Seq_descr_source) {
-    TrimPrimerSeqJunkOnBioSource (sdp->data.ptrvalue);
-  }
-}
-
-
-static void TrimPrimerSeqJunkFeatCallback (SeqFeatPtr sfp, Pointer data)
-{
-  if (sfp != NULL && sfp->data.choice == SEQFEAT_BIOSRC) {
-    TrimPrimerSeqJunkOnBioSource (sfp->data.value.ptrvalue);
-  }
-}
-
 extern void TrimPrimerSeqJunk (IteM i)
 {
   BaseFormPtr    bfp;
@@ -10050,8 +10603,7 @@ extern void TrimPrimerSeqJunk (IteM i)
 
   WatchCursor ();
   Update();
-  VisitDescriptorsInSep (sep, NULL, TrimPrimerSeqJunkDescrCallback);
-  VisitFeaturesInSep (sep, NULL, TrimPrimerSeqJunkFeatCallback);
+  TrimPrimerSeqJunkInSeqEntry (sep, NULL);
   ArrowCursor ();
   Update ();
   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
@@ -10928,3 +11480,2240 @@ NLM_EXTERN void CleanupCDD (IteM i)
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 }
 
+
+typedef struct trimseqbyalignform {
+  FORM_MESSAGE_BLOCK
+
+  ButtoN trim_before_btn;
+  TexT trim_before_coord_txt;
+  ButtoN trim_after_btn;
+  TexT trim_after_coord_txt;
+  ButtoN accept_btn;
+
+  SeqAlignPtr salp;
+} TrimSeqByAlignFormData, PNTR TrimSeqByAlignFormPtr;
+
+
+static void CleanupTrimSeqByAlignForm (GraphiC g, VoidPtr data)
+
+{
+  TrimSeqByAlignFormPtr frm;
+
+  frm = (TrimSeqByAlignFormPtr) data;
+  if (frm != NULL) {
+    frm->salp = SeqAlignFree (frm->salp);
+  }
+  StdCleanupFormProc (g, data);
+}
+
+
+
+static void ChangeTrimSeqByAln(TrimSeqByAlignFormPtr frm)
+{
+  Boolean is_ok = FALSE;
+  CharPtr str;
+  Int4 val1 = 0, val2 = 0;
+
+  if (frm == NULL) {
+    return;
+  }
+
+  if (GetStatus (frm->trim_before_btn)) {
+    Enable (frm->trim_before_coord_txt);
+    str = SaveStringFromText (frm->trim_before_coord_txt);
+    if (!StringHasNoText (str)) {
+      val1 = atoi (str); 
+      if (val1 > 0) {
+        is_ok = TRUE;
+      }
+    }
+    str = MemFree (str);
+  }
+
+  if (GetStatus (frm->trim_after_btn)) {
+    Enable (frm->trim_after_coord_txt);
+    str = SaveStringFromText (frm->trim_after_coord_txt);
+    if (!StringHasNoText (str)) {
+      val2 = atoi (str); 
+      if (val2 > 0) {
+        is_ok = TRUE;
+      } else {
+        is_ok = FALSE;
+      }
+    }
+    str = MemFree (str);
+  }
+
+  if (val1 > 0 && val2 > 0 && val2 <= val1) {
+    is_ok = FALSE;
+  }
+
+  if (is_ok) {
+    Enable (frm->accept_btn);
+  } else {
+    Disable (frm->accept_btn);
+  }
+
+}
+
+
+static void ChangeTrimSeqByAlnBtn(ButtoN b)
+{
+  TrimSeqByAlignFormPtr frm;
+  frm = (TrimSeqByAlignFormPtr) GetObjectExtra (b);
+  ChangeTrimSeqByAln (frm);
+}
+  
+
+static void ChangeTrimSeqByAlnTxt(TexT t)
+{
+  TrimSeqByAlignFormPtr frm;
+  frm = (TrimSeqByAlignFormPtr) GetObjectExtra (t);
+  ChangeTrimSeqByAln (frm);
+}
+
+
+static void DoTrimSeqsByAln (ButtoN b)
+{
+  TrimSeqByAlignFormPtr frm;
+  CharPtr str;
+  Int4 val_start = -1, val_stop = -1, num_rows, row, pos, val;
+  SeqIdPtr sip;
+  BioseqPtr bsp;
+  SeqLocPtr slp;
+  SeqEntryPtr sep;
+  SeqAnnotPtr sap;
+  LogInfoPtr  lip;
+
+  frm = (TrimSeqByAlignFormPtr) GetObjectExtra (b);
+
+  lip = OpenLog ("Trimmed Locations");
+  if (GetStatus (frm->trim_before_btn)) {
+    str = SaveStringFromText (frm->trim_before_coord_txt);
+    val_start = atoi (str) - 1;
+    str = MemFree (str);
+  }
+  if (GetStatus (frm->trim_after_btn)) {
+    str = SaveStringFromText (frm->trim_after_coord_txt);
+    val_stop = atoi (str) - 1;
+    str = MemFree (str);
+  }
+
+  num_rows = AlnMgr2GetNumRows(frm->salp);
+
+  /* for each sequence in alignment*/
+  for (row = 1; row <= num_rows; row++) {
+    sip = AlnMgr2GetNthSeqIdPtr (frm->salp, row);
+    bsp = BioseqLockById (sip);
+    if (bsp != NULL) {
+      if (AlnMgr2GetNthStrand(frm->salp, row) == Seq_strand_minus) {
+        /* trim 3' ends first */
+        if (val_start > -1) {
+          /* get sequence position for alignment coordinate */
+          pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val_start, row);
+          if (pos < 0) {
+            val = val_start + 1;
+            while (pos < 0 && val > -1) {
+              pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val, row);
+              val ++;
+            }
+          }
+
+          if (pos > -1 && pos < bsp->length - 1) {
+            /* remove sequence after position */
+            slp = SeqLocIntNew (pos + 1, bsp->length - 1, Seq_strand_plus, sip);
+            SeqDeleteByLoc (slp, TRUE, FALSE);
+            LogTrimmedLocation (lip, slp);
+            TrimQualityScores (bsp, bsp->length - 1 - pos, FALSE);
+          }
+        }
+        /* now trim 5' end */
+        if (val_stop > -1) {
+          /* get sequence position for alignment coordinate */
+          pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val_stop, row);
+          if (pos < 0) {
+            val = val_stop - 1;
+            while (pos < 0 && val > -1) {
+              pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val, row);
+              val --;
+            }
+          }
+
+          if (pos > 0) {
+            /* remove sequence before position */
+            slp = SeqLocIntNew (0, pos - 1, Seq_strand_plus, sip);
+            SeqDeleteByLoc (slp, TRUE, FALSE);
+            LogTrimmedLocation (lip, slp);
+            TrimQualityScores (bsp, pos, TRUE);
+          }
+        }
+      } else {
+        /* trim 3' ends first */
+        if (val_stop > -1) {
+          /* get sequence position for alignment coordinate */
+          pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val_stop, row);
+          if (pos < 0) {
+            val = val_stop - 1;
+            while (pos < 0 && val > -1) {
+              pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val, row);
+              val --;
+            }
+          }
+
+          if (pos > -1 && pos < bsp->length - 1) {
+            /* remove sequence after position */
+            slp = SeqLocIntNew (pos + 1, bsp->length - 1, Seq_strand_plus, sip);
+            SeqDeleteByLoc (slp, TRUE, FALSE);
+            LogTrimmedLocation (lip, slp);
+            TrimQualityScores (bsp, bsp->length - 1 - pos, FALSE);
+          }
+        }
+        /* now trim 5' end */
+        if (val_start > -1) {
+          /* get sequence position for alignment coordinate */
+          pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val_start, row);
+          if (pos < 0) {
+            val = val_start + 1;
+            while (pos < 0 && val > -1) {
+              pos = AlnMgr2MapSeqAlignToBioseq (frm->salp, val, row);
+              val ++;
+            }
+          }
+
+          if (pos > -1) {
+            /* remove sequence before position */
+            slp = SeqLocIntNew (0, pos - 1, Seq_strand_plus, sip);
+            SeqDeleteByLoc (slp, TRUE, FALSE);
+            LogTrimmedLocation (lip, slp);
+            TrimQualityScores (bsp, pos, TRUE);
+          }
+        }
+      }
+      BioseqUnlock (bsp);
+    }
+  }
+
+  sep = GetTopSeqEntryForEntityID (frm->input_entityID);
+  sap = (SeqAnnotPtr) FindSeqAlignInSeqEntry (sep, OBJ_SEQANNOT);
+  if (sap != NULL) {
+    sap->idx.deleteme = TRUE;
+    DeleteMarkedObjects (frm->input_entityID, 0, NULL);
+    fprintf (lip->fp, "Removed Alignment\n");
+    lip->data_in_log = TRUE;
+  }
+
+  CloseLog (lip);
+  lip = FreeLog (lip);
+
+  ObjMgrSetDirtyFlag (frm->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, frm->input_entityID, 0, 0);
+  Remove (frm->form);
+}
+
+
+NLM_EXTERN void TrimSequencesByAlignment (IteM i)
+{
+  BaseFormPtr       bfp;
+  SeqEntryPtr       sep;
+  TrimSeqByAlignFormPtr frm;
+  WindoW                w;
+  ButtoN                b;
+  GrouP                 h, g, c;
+  SeqAlignPtr           salp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+
+  salp  = (SeqAlignPtr)FindSeqAlignInSeqEntry (sep, OBJ_SEQALIGN);
+  if (!salp) {
+    Message (MSG_ERROR, "No alignments found!");
+    return;
+  }
+
+  frm = (TrimSeqByAlignFormPtr) MemNew (sizeof (TrimSeqByAlignFormData));
+  if (frm == NULL)
+  {
+    return;
+  }
+
+  frm->salp = SeqAlignDup (salp);
+  AlnMgr2IndexSingleChildSeqAlign(frm->salp);
+
+  frm->input_entityID = bfp->input_entityID;
+  w = FixedWindow (-50, -33, -10, -10, "Trim Sequences by Alignment Coordinates", StdCloseWindowProc);
+  SetObjectExtra (w, frm, CleanupTrimSeqByAlignForm);
+  frm->form = (ForM) w;
+
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  g = HiddenGroup (h, 2, 0, NULL);
+  frm->trim_before_btn = CheckBox (g, "Trim before alignment coordinate", ChangeTrimSeqByAlnBtn);
+  SetObjectExtra (frm->trim_before_btn, frm, NULL);
+  SetStatus (frm->trim_before_btn, FALSE);
+  frm->trim_before_coord_txt = DialogText (g, "", 10, ChangeTrimSeqByAlnTxt);
+  SetObjectExtra (frm->trim_before_coord_txt, frm, NULL);
+  Disable (frm->trim_before_coord_txt);
+
+  frm->trim_after_btn = CheckBox (g, "Trim after alignment coordinate", ChangeTrimSeqByAlnBtn);
+  SetObjectExtra (frm->trim_after_btn, frm, NULL);
+  SetStatus (frm->trim_after_btn, FALSE);
+  frm->trim_after_coord_txt = DialogText (g, "", 10, ChangeTrimSeqByAlnTxt);
+  SetObjectExtra (frm->trim_after_coord_txt, frm, NULL);
+  Disable (frm->trim_after_coord_txt);
+
+  c = HiddenGroup (h, 4, 0, NULL);
+  frm->accept_btn = PushButton (c, "Accept", DoTrimSeqsByAln);
+  SetObjectExtra (frm->accept_btn, frm, NULL);
+
+  b = PushButton (c, "Close", StdCancelButtonProc);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
+
+  Show (w);
+}
+
+/* add a repeat-region with satellite-type of microsatellite and repeat-type of tandem.  
+* Make the feature complete over the entire span of the sequence.
+*/
+static void MakeCommonFeatureMicrosatelliteCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqFeatPtr sfp;
+  ImpFeatPtr ifp;
+  GBQualPtr  gbq;
+
+  if (bsp == NULL || ISA_aa (bsp->mol)) {
+    return;
+  }
+
+  sfp = CreateNewFeatureOnBioseq (bsp, SEQFEAT_IMP, NULL);
+  ifp = ImpFeatNew ();
+  ifp->key = StringSave ("repeat_region");
+  sfp->data.value.ptrvalue = ifp;
+  gbq = GBQualNew ();
+  gbq->qual = StringSave ("rpt_type");
+  gbq->val = StringSave ("tandem");
+  sfp->qual = gbq;
+  gbq = GBQualNew ();
+  gbq->qual = StringSave ("satellite");
+  gbq->val = StringSave ("microsatellite");
+  gbq->next = sfp->qual;
+  sfp->qual = gbq;
+}
+
+
+NLM_EXTERN void MakeCommonFeatureMicrosatellite (IteM i)
+{
+  BaseFormPtr       bfp;
+  SeqEntryPtr       sep;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  VisitBioseqsInSep (sep, NULL, MakeCommonFeatureMicrosatelliteCallback);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+}
+
+
+static void MakeCommonFeatureControlRegionCallback (BioseqPtr bsp, Pointer data)
+{
+  SeqFeatPtr sfp;
+  ImpFeatPtr ifp;
+
+  if (bsp == NULL || ISA_aa (bsp->mol)) {
+    return;
+  }
+
+  sfp = CreateNewFeatureOnBioseq (bsp, SEQFEAT_IMP, NULL);
+  ifp = ImpFeatNew ();
+  ifp->key = StringSave ("misc_feature");
+  sfp->data.value.ptrvalue = ifp;
+  sfp->comment = StringSave ("control region");
+  SetSeqLocPartial (sfp->location, TRUE, TRUE);
+  sfp->partial = TRUE;
+}
+
+
+NLM_EXTERN void MakeCommonFeatureControlRegion (IteM i)
+{
+  BaseFormPtr       bfp;
+  SeqEntryPtr       sep;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  VisitBioseqsInSep (sep, NULL, MakeCommonFeatureControlRegionCallback);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+}
+
+
+static void RemoveNonNIslandsCallback (BioseqPtr bsp, Pointer data)
+{
+  CharPtr     bases, cp;
+  Int4        pos = 0, island_start = 0, island_len = 0, i;
+  SeqDataPtr  seq_data;
+
+  if (bsp == NULL || ISA_aa (bsp->mol)) {
+    return;
+  }
+
+  bases = GetSequenceByBsp (bsp);
+  if (bases == NULL) return;
+
+  for (cp = bases; *cp != 0; cp++) {
+    if (*cp == 'N') {
+      if (island_len < 3 && island_len > 0) {
+        for (i = island_start; i < pos; i++) {
+          *(bases + i) = 'N';
+        }
+      }
+      island_len = 0;
+    } else {
+      if (island_len == 0) {
+        island_start = pos;
+      }
+      island_len++;
+    }
+    pos++;
+  }
+  if (island_len < 3 && island_len > 0) {
+    for (i = island_start; i < pos; i++) {
+      *(bases + i) = 'N';
+    }
+  }
+
+  seq_data = (SeqDataPtr) BSNew (bsp->length);
+  AddBasesToByteStore ((ByteStorePtr) seq_data, bases);
+  bsp->seq_data = SeqDataFree (bsp->seq_data, bsp->seq_data_type);
+  bsp->seq_data_type = Seq_code_iupacna;
+  bsp->seq_data = seq_data;
+  bases = MemFree (bases);
+  BioseqPack (bsp);
+}
+
+NLM_EXTERN void RemoveNonNIslands (IteM i)
+{
+  BaseFormPtr       bfp;
+  SeqEntryPtr       sep;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  VisitBioseqsInSep (sep, NULL, RemoveNonNIslandsCallback);
+  DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+}
+
+
+static Boolean StrandOk (Uint1 strand1, Uint1 strand2)
+{
+  if (strand1 == Seq_strand_minus && strand2 != Seq_strand_minus) {
+    return FALSE;
+  } else if (strand1 != Seq_strand_minus && strand2 == Seq_strand_minus) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+static void RemoveUTRsFromCDSCallback (SeqFeatPtr sfp, Pointer data)
+{
+  BioseqPtr bsp;
+  SeqFeatPtr utr;
+  SeqMgrFeatContext fcontext;
+  Int4              start, stop, right;
+  Uint1             cds_strand;
+  Boolean           changed, partial5, partial3, retranslate = FALSE;
+  CdRegionPtr       crp;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION) {
+    return;
+  }
+
+  bsp = BioseqFindFromSeqLoc (sfp->location);
+  if (bsp == NULL) {
+    return;
+  }
+
+  start = SeqLocStart (sfp->location);
+  stop = SeqLocStop (sfp->location);
+  if (start < stop) {
+    right = stop;
+  } else {
+    right = start;
+  }
+  cds_strand = SeqLocStrand (sfp->location);
+
+  for (utr = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_5UTR, &fcontext);
+       utr != NULL;
+       utr = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_5UTR, &fcontext)) {
+    if (fcontext.left > right) {
+      break;
+    } else if (!StrandOk (cds_strand, SeqLocStrand (utr->location))) {
+      continue;
+    }
+    if ((cds_strand == Seq_strand_minus && fcontext.right == start) 
+        || (cds_strand != Seq_strand_minus && fcontext.left == start)) {
+      sfp->location = SeqLocDelete (sfp->location, SeqLocId (sfp->location), fcontext.left, fcontext.right, FALSE, &changed);
+      crp = (CdRegionPtr) sfp->data.value.ptrvalue;
+      if (crp != NULL) {
+        crp->frame = 1;
+      }
+      CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
+      SetSeqLocPartial (sfp->location, FALSE, partial3);
+      retranslate = TRUE;
+      break;
+    } 
+  }
+
+  for (utr = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_3UTR, &fcontext);
+       utr != NULL;
+       utr = SeqMgrGetNextFeature (bsp, NULL, 0, FEATDEF_3UTR, &fcontext)) {
+    if (fcontext.left > right) {
+      break;
+    } else if (!StrandOk (cds_strand, SeqLocStrand (utr->location))) {
+      continue;
+    }
+    if ((cds_strand == Seq_strand_minus && fcontext.left == stop) 
+        || (cds_strand != Seq_strand_minus && fcontext.right == stop)) {
+      sfp->location = SeqLocDelete (sfp->location, SeqLocId (sfp->location), fcontext.left, fcontext.right, FALSE, &changed);
+      CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
+      SetSeqLocPartial (sfp->location, partial5, FALSE);
+      retranslate = TRUE;
+      break;
+    } 
+  }
+  
+  if (retranslate) {
+    RetranslateOneCDS (sfp, sfp->idx.entityID, FALSE, FALSE);
+  }
+}
+
+
+NLM_EXTERN void RemoveUTRsFromCDSs (IteM i)
+{
+  BaseFormPtr       bfp;
+  SeqEntryPtr       sep;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  VisitFeaturesInSep (sep, NULL, RemoveUTRsFromCDSCallback);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+}
+
+
+typedef enum {
+  eFeatureBetweenPolicy_NoFeatPartial = 1,
+  eFeatureBetweenPolicy_NoFeatNoFeat,
+  eFeatureBetweenPolicy_ExtendComplete,
+  eFeatureBetweenPolicy_ExtendPartial
+} EFeatureBetweenPolicy;
+
+typedef struct featurebetweenendpolicy {
+  Uint1 policy;
+  ValNodePtr feat_type;
+  ConstraintChoiceSetPtr constraint;
+} FeatureBetweenEndPolicyData, PNTR FeatureBetweenEndPolicyPtr;
+
+
+static FeatureBetweenEndPolicyPtr FeatureBetweenEndPolicyNew (void)
+{
+  FeatureBetweenEndPolicyPtr pol;
+
+  pol = (FeatureBetweenEndPolicyPtr) MemNew (sizeof (FeatureBetweenEndPolicyData));
+  pol->policy = eFeatureBetweenPolicy_ExtendPartial;
+  return pol;
+}
+
+
+static FeatureBetweenEndPolicyPtr FeatureBetweenEndPolicyFree (FeatureBetweenEndPolicyPtr pol)
+{
+  if (pol != NULL) {
+    pol->feat_type = ValNodeFree (pol->feat_type);
+    pol = MemFree (pol);
+  }
+  return pol;
+}
+
+
+typedef struct addfeaturebetween {
+  FeatureBetweenEndPolicyPtr left_policy;
+  ValNodePtr feat_type_add;
+  ApplyFeatureDetailsPtr details;
+  FeatureBetweenEndPolicyPtr right_policy;
+} AddFeatureBetweenData, PNTR AddFeatureBetweenPtr;
+
+static AddFeatureBetweenPtr AddFeatureBetweenNew (void)
+{
+  AddFeatureBetweenPtr add;
+
+  add = (AddFeatureBetweenPtr) MemNew (sizeof (AddFeatureBetweenData));
+  return add;
+}
+
+
+static AddFeatureBetweenPtr AddFeatureBetweenFree (AddFeatureBetweenPtr add)
+{
+  if (add != NULL) {
+    add->left_policy = FeatureBetweenEndPolicyFree (add->left_policy);
+    add->feat_type_add = ValNodeFree (add->feat_type_add);
+    add->details = ApplyFeatureDetailsFree (add->details);
+    add->right_policy = FeatureBetweenEndPolicyFree (add->right_policy);
+    add = MemFree (add);
+  }
+  return add;
+}
+
+
+static void 
+AddOneFeatureBetween 
+(BioseqPtr bsp,
+ Int4 feat_left,
+ Boolean partial_left,
+ Int4 feat_right,
+ Boolean partial_right,
+ Uint1   strand,
+ Uint1   featdef,
+ ApplyFeatureDetailsPtr details)
+{
+  Int4       seqfeattype;
+  SeqLocPtr  slp;
+
+  seqfeattype = FindFeatFromFeatDefType (featdef);
+
+  slp = SeqLocIntNew (feat_left, feat_right, strand, SeqIdFindWorst (bsp->id));
+  SetSeqLocPartial (slp, partial_left, partial_right);
+  
+  ApplyOneFeatureToBioseq (bsp, featdef, slp, details == NULL ? NULL : details->fields, details == NULL ? NULL : details->src_fields, details->add_mrna);
+}
+
+
+static void AddFeaturesBetweenCallback (BioseqPtr bsp, Pointer data)
+{
+  AddFeatureBetweenPtr add;
+  SeqFeatPtr           feat_before, feat_after;
+  SeqMgrFeatContext    context_before, context_after;
+  Boolean              found = FALSE, partial_left = TRUE, partial_right = TRUE;
+  Uint1                featdef_before = FEATDEF_BAD, featdef_after = FEATDEF_BAD, featdef_new;
+  Int4                 seqfeattype;
+  Int4                 feat_left, feat_right;
+
+  if (bsp == NULL || (add = (AddFeatureBetweenPtr) data) == NULL || add->left_policy == NULL || add->right_policy == NULL) {
+    return;
+  }
+  if (add->feat_type_add == NULL) {
+    return;
+  }
+
+  featdef_new = GetFeatdefFromFeatureType (add->feat_type_add->choice);
+  seqfeattype = FindFeatFromFeatDefType (featdef_new);
+  if (seqfeattype == SEQFEAT_PROT) {
+    if (!ISA_aa (bsp->mol)) {
+      return;
+    }
+  } else {
+    if (ISA_aa (bsp->mol)) {
+      return;
+    }
+  }
+
+  if ((add->left_policy->policy == eFeatureBetweenPolicy_NoFeatPartial 
+          || add->left_policy->policy == eFeatureBetweenPolicy_NoFeatNoFeat)
+      && add->left_policy->feat_type != NULL) {
+    featdef_before = GetFeatdefFromFeatureType (add->left_policy->feat_type->choice);
+  }
+  if ((add->right_policy->policy == eFeatureBetweenPolicy_NoFeatPartial 
+          || add->right_policy->policy == eFeatureBetweenPolicy_NoFeatNoFeat)
+      && add->right_policy->feat_type != NULL) {
+    featdef_after = GetFeatdefFromFeatureType (add->right_policy->feat_type->choice);
+  }
+
+  if (featdef_before != FEATDEF_BAD) {
+    for (feat_before = SeqMgrGetNextFeature (bsp, NULL, 0, featdef_before, &context_before);
+         feat_before != NULL;
+         feat_before = SeqMgrGetNextFeature (bsp, feat_before, 0, featdef_before, &context_before)) {
+      if (DoesObjectMatchConstraintChoiceSet (OBJ_SEQFEAT, feat_before, add->left_policy->constraint)) {
+        /* add feature starting at context_before.right + 1, ending with first feature matching right constraint */
+        feat_left = context_before.right + 1;
+        partial_left = FALSE;
+        feat_right = bsp->length - 1;
+        if (featdef_after != FEATDEF_BAD) {
+          for (feat_after = SeqMgrGetNextFeature (bsp, NULL, 0, featdef_after, &context_after);
+               feat_after != NULL && feat_right == bsp->length - 1;
+               feat_after = SeqMgrGetNextFeature (bsp, feat_after, 0, featdef_after, &context_after)) {
+            if (context_after.left > feat_left && DoesObjectMatchConstraintChoiceSet (OBJ_SEQFEAT, feat_after, add->right_policy->constraint)) {
+              feat_right = context_after.left - 1;
+              partial_right = FALSE;
+            }
+          }
+        }
+        if (feat_right > -1
+            && feat_right > feat_left
+            && (feat_right < bsp->length - 1 
+                || add->right_policy->policy != eFeatureBetweenPolicy_NoFeatNoFeat)) {
+          if (add->right_policy->policy == eFeatureBetweenPolicy_ExtendComplete) {
+            partial_right = FALSE;
+          }
+          AddOneFeatureBetween (bsp, feat_left, partial_left, feat_right, partial_right, context_before.strand, featdef_new, add->details);
+        }
+        found = TRUE;
+      }
+    }
+    if (!found && add->left_policy->policy == eFeatureBetweenPolicy_NoFeatPartial) {
+      /* add feature starting at 0 and partial on this end, ending with first feature matching right constraint */
+      feat_left = 0;
+      feat_right = bsp->length - 1;
+      if (featdef_after != FEATDEF_BAD) {
+        for (feat_after = SeqMgrGetNextFeature (bsp, NULL, 0, featdef_after, &context_after);
+              feat_after != NULL && feat_right == bsp->length - 1;
+              feat_after = SeqMgrGetNextFeature (bsp, feat_after, 0, featdef_after, &context_after)) {
+          if (context_after.left > feat_left && DoesObjectMatchConstraintChoiceSet (OBJ_SEQFEAT, feat_after, add->right_policy->constraint)) {
+            feat_right = context_after.left - 1;
+            partial_right = FALSE;
+            AddOneFeatureBetween (bsp, feat_left, partial_left, feat_right, partial_right, context_after.strand, featdef_new, add->details);
+            found = TRUE;
+          }
+        }
+      }
+      if (!found && add->right_policy->policy != eFeatureBetweenPolicy_NoFeatNoFeat) {
+        if (add->right_policy->policy == eFeatureBetweenPolicy_ExtendComplete) {
+          partial_right = FALSE;
+        }
+        if (feat_right > feat_left && feat_right > -1) {
+          AddOneFeatureBetween (bsp, feat_left, partial_left, feat_right, partial_right, Seq_strand_plus, featdef_new, add->details);
+        }
+      }
+    }
+  } else if (featdef_after != FEATDEF_BAD) {
+    feat_left = 0;
+    if (add->left_policy->policy == eFeatureBetweenPolicy_ExtendComplete) {
+      partial_left = FALSE;
+    }
+    for (feat_after = SeqMgrGetNextFeature (bsp, NULL, 0, featdef_after, &context_after);
+         feat_after != NULL && !found;
+         feat_after = SeqMgrGetNextFeature (bsp, feat_after, 0, featdef_after, &context_after)) {
+      if (DoesObjectMatchConstraintChoiceSet (OBJ_SEQFEAT, feat_after, add->right_policy->constraint)) {
+        /* add feature starting at 0 and partial on this end, ending with context_after.left - 1 */
+        partial_right = FALSE;
+        feat_right = context_after.left - 1;
+        if (feat_right > feat_left && feat_right > -1) {
+          AddOneFeatureBetween (bsp, feat_left, partial_left, feat_right, partial_right, context_after.strand, featdef_new, add->details);
+        }
+        found = TRUE;
+      }
+    }
+    if (!found && add->right_policy->policy != eFeatureBetweenPolicy_NoFeatNoFeat) {
+      AddOneFeatureBetween (bsp, feat_left, partial_left, bsp->length - 1, partial_right, Seq_strand_plus, featdef_new, add->details);      
+    }
+  } else {
+    feat_left = 0;
+    feat_right = bsp->length - 1;
+    if (add->left_policy->policy == eFeatureBetweenPolicy_ExtendComplete) {
+      partial_left = FALSE;
+    }
+    if (add->right_policy->policy == eFeatureBetweenPolicy_ExtendComplete) {
+      partial_right = FALSE;
+    }
+    if (feat_right > feat_left && feat_right > -1) {
+      AddOneFeatureBetween (bsp, feat_left, partial_left, feat_right, partial_right, Seq_strand_plus, featdef_new, add->details);          
+    }
+  }
+}
+
+typedef struct featurebetweenendpolicydlg {
+  DIALOG_MESSAGE_BLOCK
+
+  GrouP          missing_feat_policy;
+  DialoG         feat_type_dlg;
+  DialoG         constraint_dlg;
+
+  Nlm_ChangeNotifyProc     change_notify;
+  Pointer                  change_userdata;
+} FeatureBetweenEndPolicyDlgData, PNTR FeatureBetweenEndPolicyDlgPtr;
+
+
+static void EnableDialogFeatureBetweenEndPolicy (FeatureBetweenEndPolicyDlgPtr dlg)
+{
+  Int4 val;
+
+  if (dlg != NULL) {
+    val = GetValue (dlg->missing_feat_policy);
+    if (val == eFeatureBetweenPolicy_NoFeatPartial || val == eFeatureBetweenPolicy_NoFeatNoFeat) {
+      Enable (dlg->feat_type_dlg);
+      Enable (dlg->constraint_dlg);
+    } else {
+      Disable (dlg->feat_type_dlg);
+      Disable (dlg->constraint_dlg);
+    }
+  }
+}
+
+
+static void FeatureBetweenEndPolicyToDialog (DialoG d, Pointer data)
+{
+  FeatureBetweenEndPolicyDlgPtr dlg;
+  FeatureBetweenEndPolicyPtr    pol;
+  ValNode                       vn;
+
+  dlg = (FeatureBetweenEndPolicyDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return;
+  }
+  pol = (FeatureBetweenEndPolicyPtr) data;
+  if (data == NULL) {
+    SetValue (dlg->missing_feat_policy, eFeatureBetweenPolicy_NoFeatPartial);
+    MemSet (&vn, 0, sizeof (ValNode));
+    vn.choice = Feature_type_cds;
+    PointerToDialog (dlg->feat_type_dlg, &vn);
+    PointerToDialog (dlg->constraint_dlg, NULL);
+  } else {
+    SetValue (dlg->missing_feat_policy, pol->policy);
+    PointerToDialog (dlg->feat_type_dlg, pol->feat_type);
+    PointerToDialog (dlg->constraint_dlg, pol->constraint);
+  }
+  EnableDialogFeatureBetweenEndPolicy (dlg);
+}
+
+
+static Pointer DialogToFeatureBetweenEndPolicy (DialoG d)
+{
+  FeatureBetweenEndPolicyDlgPtr dlg;
+  FeatureBetweenEndPolicyPtr    pol;
+
+  dlg = (FeatureBetweenEndPolicyDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return NULL;
+  }
+
+  pol = FeatureBetweenEndPolicyNew();
+  pol->policy = GetValue (dlg->missing_feat_policy);
+  pol->feat_type = DialogToPointer (dlg->feat_type_dlg);
+  pol->constraint = DialogToPointer (dlg->constraint_dlg);
+
+  return pol;
+}
+
+
+static void ChangeFeatureBetweenPolicy (GrouP g)
+{
+  EnableDialogFeatureBetweenEndPolicy (GetObjectExtra (g));
+}
+
+
+static DialoG FeatureBetweenEndPolicyDialog (GrouP h, CharPtr label, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+{  
+  FeatureBetweenEndPolicyDlgPtr dlg;
+  GrouP                    p;
+  PrompT                   ppt;
+
+  dlg = (FeatureBetweenEndPolicyDlgPtr) MemNew (sizeof (FeatureBetweenEndPolicyDlgData));
+  p = HiddenGroup (h, -1, 0, NULL);
+  SetGroupSpacing (p, 10, 10);
+  SetObjectExtra (p, dlg, StdCleanupExtraProc);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = FeatureBetweenEndPolicyToDialog;
+  dlg->fromdialog = DialogToFeatureBetweenEndPolicy;
+  dlg->dialogmessage = NULL;
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  ppt = StaticPrompt (p, label, 0, popupMenuHeight, programFont, 'l');
+  dlg->missing_feat_policy = HiddenGroup (p, 0, 4, ChangeFeatureBetweenPolicy);
+  SetObjectExtra (dlg->missing_feat_policy, dlg, NULL);
+  RadioButton (dlg->missing_feat_policy, "If selected feature missing, extend to partial end");
+  RadioButton (dlg->missing_feat_policy, "If selected feature missing, do not create feature");
+  RadioButton (dlg->missing_feat_policy, "Extend to complete end");
+  RadioButton (dlg->missing_feat_policy, "Extend to partial end");
+
+  dlg->feat_type_dlg = FeatureTypeDialog (p, NULL, NULL);
+  dlg->constraint_dlg = ConstraintSetDialog (p, NULL, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) dlg->missing_feat_policy, 
+                              (HANDLE) dlg->feat_type_dlg, (HANDLE) dlg->constraint_dlg, NULL);
+
+  return (DialoG) p;
+}
+
+
+typedef struct addfeaturebetweendlg {
+  DIALOG_MESSAGE_BLOCK
+
+  DialoG         left_policy_dlg;
+
+  DialoG         feat_type_add_dlg;
+  DialoG         details_dlg;
+
+  DialoG         right_policy_dlg;
+
+  Nlm_ChangeNotifyProc     change_notify;
+  Pointer                  change_userdata;
+} AddFeatureBetweenDlgData, PNTR AddFeatureBetweenDlgPtr;
+
+
+static Pointer DialogToAddFeatureBetween (DialoG d)
+{
+  AddFeatureBetweenDlgPtr dlg;
+  AddFeatureBetweenPtr add;
+
+  dlg = (AddFeatureBetweenDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return NULL;
+  }
+  add = AddFeatureBetweenNew ();
+  add->left_policy = DialogToPointer (dlg->left_policy_dlg);
+  add->feat_type_add = DialogToPointer (dlg->feat_type_add_dlg);
+  add->details = DialogToPointer (dlg->details_dlg);
+  add->right_policy = DialogToPointer (dlg->right_policy_dlg);
+
+  return add;
+}
+
+
+static void AddFeatureBetweenToDialog (DialoG d, Pointer data)
+{
+  AddFeatureBetweenDlgPtr dlg;
+  AddFeatureBetweenPtr add;
+  ValNode              vn;
+
+  dlg = (AddFeatureBetweenDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) {
+    return;
+  }
+
+  add = (AddFeatureBetweenPtr) data;
+  if (add == NULL) {
+    PointerToDialog (dlg->left_policy_dlg, NULL);
+    MemSet (&vn, 0, sizeof (ValNode));
+    vn.choice = Feature_type_misc_feature;
+    PointerToDialog (dlg->feat_type_add_dlg, &vn);
+    PointerToDialog (dlg->details_dlg, NULL);
+    PointerToDialog (dlg->right_policy_dlg, NULL);
+  } else {
+    PointerToDialog (dlg->left_policy_dlg, add->left_policy);
+    PointerToDialog (dlg->feat_type_add_dlg, add->feat_type_add);
+    PointerToDialog (dlg->details_dlg, add->details);
+    PointerToDialog (dlg->right_policy_dlg, add->right_policy);
+  }
+
+}
+
+
+static DialoG AddFeatureBetweenDialog (GrouP h, Uint1 add_type, ApplyFeatureDetailsPtr details, Nlm_ChangeNotifyProc change_notify, Pointer change_userdata)
+{
+  AddFeatureBetweenDlgPtr dlg;
+  GrouP                    p, k2;
+  PrompT                   ppt;
+
+  dlg = (AddFeatureBetweenDlgPtr) MemNew (sizeof (AddFeatureBetweenDlgData));
+  p = HiddenGroup (h, 3, 0, NULL);
+  SetGroupSpacing (p, 10, 10);
+  SetObjectExtra (p, dlg, StdCleanupExtraProc);
+
+  dlg->dialog = (DialoG) p;
+  dlg->todialog = AddFeatureBetweenToDialog;
+  dlg->fromdialog = DialogToAddFeatureBetween;
+  dlg->dialogmessage = NULL;
+  dlg->change_notify = change_notify;
+  dlg->change_userdata = change_userdata;
+
+  dlg->left_policy_dlg = FeatureBetweenEndPolicyDialog (p, "Left Feature", NULL, NULL);
+
+  k2 = HiddenGroup (p, -1, 0, NULL);
+  ppt = StaticPrompt (k2, "Feature to Add", 0, popupMenuHeight, programFont, 'l');
+  dlg->feat_type_add_dlg = FeatureTypeDialog (k2, change_notify, change_userdata);
+  dlg->details_dlg = ApplyFeatureDetailsDialog (k2, add_type, details, TRUE, NULL, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) dlg->feat_type_add_dlg, (HANDLE) dlg->details_dlg, NULL);
+
+  dlg->right_policy_dlg = FeatureBetweenEndPolicyDialog (p, "Right Feature", NULL, NULL);
+
+  return (DialoG) p;
+}
+
+
+typedef struct addfeaturebetweenform {
+  FORM_MESSAGE_BLOCK
+
+  DialoG add_between_dlg;
+  ButtoN leave_dlg_up;
+
+  Boolean changing;
+} AddFeatureBetweenFormData, PNTR AddFeatureBetweenFormPtr;
+
+
+static void ChangeAddFeatureFunc (Pointer data);
+
+static void DoAddFeatureBetween (ButtoN b)
+{
+  AddFeatureBetweenFormPtr dlg;
+  AddFeatureBetweenPtr     add;
+  SeqEntryPtr              sep;
+
+  dlg = (AddFeatureBetweenFormPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  WatchCursor();
+  Update();
+  add = DialogToPointer (dlg->add_between_dlg);
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+
+  VisitBioseqsInSep (sep, add, AddFeaturesBetweenCallback);
+
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+  
+  if (!GetStatus (dlg->leave_dlg_up)) {
+    Remove (dlg->form);
+  }
+  ArrowCursor();
+  Update();
+}
+
+
+static WindoW AddFeatureBetweenForm (Uint2 entityID, AddFeatureBetweenPtr add)
+{
+  WindoW            w;
+  GrouP             h, c;
+  ButtoN            b;
+  AddFeatureBetweenFormPtr dlg;
+
+  dlg = (AddFeatureBetweenFormPtr) MemNew (sizeof (AddFeatureBetweenFormData));
+  if (dlg == NULL) return NULL;
+    
+  w = FixedWindow (-50, -33, -10, -10, "Add Feature Between", StdCloseWindowProc);
+  SetObjectExtra (w, dlg, StdCleanupFormProc);
+  dlg->form = (ForM) w;
+  dlg->input_entityID = entityID;
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  dlg->changing = TRUE;
+  dlg->add_between_dlg = AddFeatureBetweenDialog (h, (add == NULL || add->feat_type_add == NULL) ? FEATDEF_misc_feature : GetFeatdefFromFeatureType (add->feat_type_add->choice),
+                                                  add == NULL ? NULL : add->details,
+                                                  ChangeAddFeatureFunc, dlg);
+  PointerToDialog (dlg->add_between_dlg, add);
+  dlg->changing = FALSE;
+
+  c = HiddenGroup (h, 4, 0, NULL);
+  b = DefaultButton (c, "Accept", DoAddFeatureBetween);
+  SetObjectExtra (b, dlg, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+  dlg->leave_dlg_up = CheckBox (c, "Leave dialog up", NULL);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) dlg->add_between_dlg, (HANDLE) c, NULL);
+
+  return w;
+}
+
+
+static void ChangeAddFeatureFunc (Pointer data)
+{
+  AddFeatureBetweenFormPtr dlg;
+  AddFeatureBetweenPtr add;
+  WindoW               w;
+
+  dlg = (AddFeatureBetweenFormPtr) data;
+  if (dlg == NULL || dlg->changing) {
+    return;
+  }
+
+  add = DialogToPointer (dlg->add_between_dlg);
+  Hide (dlg->form);
+  /* build new form */
+  w = AddFeatureBetweenForm (dlg->input_entityID, add);
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+
+  /* remove old form */
+  dlg->changing = TRUE;
+  Remove (dlg->form);
+  
+  add = AddFeatureBetweenFree (add);
+
+}
+
+
+NLM_EXTERN void AddFeatureBetween (IteM i)
+{
+  BaseFormPtr       bfp;
+  WindoW            w;
+  AddFeatureBetweenFormPtr dlg;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  dlg = (AddFeatureBetweenFormPtr) MemNew (sizeof (AddFeatureBetweenFormData));
+  if (dlg == NULL) return;
+
+  w = AddFeatureBetweenForm (bfp->input_entityID, NULL);
+    
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+}
+
+
+typedef struct changequalcaseform {
+  FORM_MESSAGE_BLOCK
+
+  DialoG qual_dlg;
+  DialoG cap_dlg;
+  ButtoN leave_dlg_up;
+
+} ChangeQualCaseFormData, PNTR ChangeQualCaseFormPtr;
+
+
+typedef struct changecase {
+  ValNodePtr dst_field;
+  Int4       change_cap;
+  ValNodePtr orgnames;
+} ChangeCaseData, PNTR ChangeCasePtr;
+
+static void ChangeQualCaseCallbackDesc (SeqDescrPtr sdp, Pointer data)
+{
+  ChangeCasePtr ccp;
+  ParseDstOrgPtr o;
+  CharPtr        str;
+
+  ccp = (ChangeCasePtr) data;
+  if (sdp == NULL || ccp == NULL || ccp->dst_field == NULL || ccp->change_cap < 1) {
+    return;
+  }
+
+  switch (ccp->dst_field->choice) {
+    case ParseDest_defline:
+      if (sdp->choice == Seq_descr_title) {
+        FixCapitalizationInString ((CharPtr PNTR)&(sdp->data.ptrvalue), ccp->change_cap, ccp->orgnames);
+      }
+      break;
+    case ParseDest_org:
+      if ((o = (ParseDstOrgPtr) ccp->dst_field->data.ptrvalue) != NULL
+          && o->type != Object_type_constraint_feature
+          && sdp->choice == Seq_descr_source) {
+        str = GetSourceQualFromBioSource (sdp->data.ptrvalue, o->field, NULL);
+        FixCapitalizationInString(&str, ccp->change_cap, NULL);
+        SetSourceQualInBioSource(sdp->data.ptrvalue, o->field, NULL, str, ExistingTextOption_replace_old);
+        str = MemFree (str);
+      }
+      break;
+    case ParseDest_comment_descriptor:
+      if (sdp->choice == Seq_descr_comment) {
+        FixCapitalizationInString ((CharPtr PNTR)&(sdp->data.ptrvalue), ccp->change_cap, ccp->orgnames);
+      }
+      break;
+    case ParseDest_dbxref:
+      if (sdp->choice == Seq_descr_source) {
+        str = GetDBxrefFromBioSource (sdp->data.ptrvalue, ccp->dst_field->data.ptrvalue);
+        if (str != NULL) {
+          FixCapitalizationInString(&str, ccp->change_cap, ccp->orgnames);
+          SetDBxrefForBioSource (sdp->data.ptrvalue, ccp->dst_field->data.ptrvalue, str, ExistingTextOption_replace_old);
+          str = MemFree (str);
+        }
+      }
+      break;
+  }
+}
+
+
+static void ChangeQualCaseCallbackFeat (SeqFeatPtr sfp, Pointer data)
+{
+  ChangeCasePtr ccp;
+  ParseDstOrgPtr o;
+  CharPtr        str;
+  FeatureFieldLegalPtr fl;
+  FeatureField f;
+
+  ccp = (ChangeCasePtr) data;
+  if (sfp == NULL || ccp == NULL || ccp->dst_field == NULL || ccp->change_cap < 1) {
+    return;
+  }
+
+  switch (ccp->dst_field->choice) {
+    case ParseDest_org:
+      if ((o = (ParseDstOrgPtr) ccp->dst_field->data.ptrvalue) != NULL
+          && o->type != Object_type_constraint_descriptor
+          && sfp->data.choice == SEQFEAT_BIOSRC) {
+        str = GetSourceQualFromBioSource (sfp->data.value.ptrvalue, o->field, NULL);
+        FixCapitalizationInString(&str, ccp->change_cap, NULL);
+        SetSourceQualInBioSource(sfp->data.value.ptrvalue, o->field, NULL, str, ExistingTextOption_replace_old);
+        str = MemFree (str);
+      }
+      break;
+    case ParseDest_featqual:
+      fl = (FeatureFieldLegalPtr) ccp->dst_field->data.ptrvalue;
+      if (fl != NULL) {
+        f.type = fl->type;
+        f.field = ValNodeNew(NULL);
+        f.field->next = NULL;
+        f.field->choice = FeatQualChoice_legal_qual;
+        f.field->data.intvalue = fl->field;        
+        str = GetQualFromFeature (sfp, &f, NULL);
+        if (str != NULL) {
+          FixCapitalizationInString(&str, ccp->change_cap, ccp->orgnames);
+          SetQualOnFeature (sfp, &f, NULL, str, ExistingTextOption_replace_old);
+          f.field = ValNodeFree (f.field);
+          str = MemFree (str);
+        }
+      }
+      break;
+    case ParseDest_dbxref:
+      if (sfp->data.choice == SEQFEAT_BIOSRC) {
+        str = GetDBxrefFromBioSource (sfp->data.value.ptrvalue, ccp->dst_field->data.ptrvalue);
+        if (str != NULL) {
+          FixCapitalizationInString(&str, ccp->change_cap, ccp->orgnames);
+          SetDBxrefForBioSource (sfp->data.value.ptrvalue, ccp->dst_field->data.ptrvalue, str, ExistingTextOption_replace_old);
+          str = MemFree (str);
+        }
+      }
+      break;
+  }
+}
+
+
+static void DoChangeQualCase(ButtoN b)
+{
+  ChangeQualCaseFormPtr dlg;
+  ChangeCaseData        ccd;
+  SeqEntryPtr           sep;
+  ParseDstOrgPtr        o;
+
+  dlg = (ChangeQualCaseFormPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  ccd.dst_field = DialogToPointer (dlg->qual_dlg);
+  if (ccd.dst_field == NULL) {
+    return;
+  }
+
+  ccd.change_cap = (Int4) DialogToPointer (dlg->cap_dlg);
+
+  ccd.orgnames = NULL;
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+  VisitBioSourcesInSep (sep, &ccd.orgnames, GetOrgNamesInRecordCallback);
+
+
+  switch (ccd.dst_field->choice) {
+    case ParseDest_defline :
+      VisitDescriptorsInSep (sep, &ccd, ChangeQualCaseCallbackDesc);
+      break;
+    case ParseDest_org :
+      o = (ParseDstOrgPtr) ccd.dst_field->data.ptrvalue;
+      if (o->type == Object_type_constraint_any || o->type == Object_type_constraint_descriptor) {
+        VisitDescriptorsInSep (sep, &ccd, ChangeQualCaseCallbackDesc);
+      }
+      if (o->type == Object_type_constraint_any || o->type == Object_type_constraint_feature) {
+        VisitFeaturesInSep (sep, &ccd, ChangeQualCaseCallbackFeat);
+      }
+      break;
+    case ParseDest_featqual :
+      VisitFeaturesInSep (sep, &ccd, ChangeQualCaseCallbackFeat);
+      break;
+    case ParseDest_comment_descriptor :
+      VisitDescriptorsInSep (sep, &ccd, ChangeQualCaseCallbackDesc);
+      break;
+    case ParseDest_dbxref :
+      VisitDescriptorsInSep (sep, &ccd, ChangeQualCaseCallbackDesc);
+      VisitFeaturesInSep (sep, &ccd, ChangeQualCaseCallbackFeat);
+      break;
+  }
+
+  ccd.orgnames = ValNodeFree (ccd.orgnames);
+  ccd.dst_field = ParseDestFree (ccd.dst_field);
+
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+
+  if (!GetStatus (dlg->leave_dlg_up)) {
+    Remove (dlg->form);
+  }
+  ArrowCursor();
+  Update();
+}
+
+
+NLM_EXTERN void ChangeQualifierCase (IteM i)
+{
+  BaseFormPtr       bfp;
+  WindoW            w;
+  GrouP             h, c;
+  ButtoN            b;
+  ChangeQualCaseFormPtr dlg;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  dlg = (ChangeQualCaseFormPtr) MemNew (sizeof (ChangeQualCaseFormData));
+  if (dlg == NULL) return;
+
+  w = FixedWindow (-50, -33, -10, -10, "Lowercase Qualifiers", StdCloseWindowProc);
+  SetObjectExtra (w, dlg, StdCleanupFormProc);
+  dlg->form = (ForM) w;
+  dlg->input_entityID = bfp->input_entityID;
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  dlg->qual_dlg = ParseDstDialog (h, NULL, NULL);
+  dlg->cap_dlg = CapChangeDialog (h, NULL, NULL);
+  PointerToDialog (dlg->cap_dlg, (Pointer) 1);
+
+  c = HiddenGroup (h, 4, 0, NULL);
+  b = DefaultButton (c, "Accept", DoChangeQualCase);
+  SetObjectExtra (b, dlg, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+  dlg->leave_dlg_up = CheckBox (c, "Leave dialog up", NULL);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) dlg->qual_dlg, (HANDLE) dlg->cap_dlg, (HANDLE) c, NULL);
+    
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+}
+
+
+typedef struct applymoltypeform {
+  FORM_MESSAGE_BLOCK
+
+  DialoG mol_type_dlg;
+
+  Uint1 mol_type;
+  Uint1 mol_class;
+
+} ApplyMolTypeFormData, PNTR ApplyMolTypeFormPtr;
+
+
+static void ApplyMoleculeTypeCallback (BioseqPtr bsp, Pointer data)
+{
+  ApplyMolTypeFormPtr dlg;
+  SeqDescrPtr         sdp;
+  SeqMgrDescContext   context;
+  MolInfoPtr          mip;
+
+  if (bsp == NULL || ISA_aa(bsp->mol) || (dlg = (ApplyMolTypeFormPtr) data) == NULL) {
+    return;
+  }
+
+  bsp->mol = dlg->mol_class;
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
+  if (sdp == NULL) {
+    sdp = CreateNewDescriptorOnBioseq (bsp, Seq_descr_molinfo);
+  }
+
+  mip = (MolInfoPtr) sdp->data.ptrvalue;
+  if (mip == NULL) {
+    mip = MolInfoNew ();
+    sdp->data.ptrvalue = mip;
+  }
+  mip->biomol = dlg->mol_type;
+}
+
+
+static void DoApplyMoleculeType(ButtoN b)
+{
+  ApplyMolTypeFormPtr dlg;
+  ValNodePtr          vnp;
+  SeqEntryPtr         sep;
+
+  dlg = (ApplyMolTypeFormPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+
+  vnp = DialogToPointer (dlg->mol_type_dlg);
+  if (vnp == NULL) {
+    return;
+  }
+
+  dlg->mol_type = BiomolFromMoleculeType (vnp->choice);
+  if (StringSearch (vnp->data.ptrvalue, "RNA") == NULL) {
+    dlg->mol_class = MOLECULE_CLASS_DNA;
+  } else {
+    dlg->mol_class = MOLECULE_CLASS_RNA;
+  }
+
+  VisitBioseqsInSep (sep, dlg, ApplyMoleculeTypeCallback);
+
+  vnp = ValNodeFree (vnp);
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+  Remove (dlg->form);
+  ArrowCursor();
+  Update();
+}
+
+
+NLM_EXTERN void ExternalApplyMoleculeType (IteM i)
+{
+  BaseFormPtr       bfp;
+  WindoW            w;
+  GrouP             h, c;
+  ButtoN            b;
+  ApplyMolTypeFormPtr dlg;
+  ValNodePtr          moltype_list, vnp, vnp_new;
+
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  dlg = (ApplyMolTypeFormPtr) MemNew (sizeof (ApplyMolTypeFormData));
+  if (dlg == NULL) return;
+
+  w = FixedWindow (-50, -33, -10, -10, "Apply Molecule Type", StdCloseWindowProc);
+  SetObjectExtra (w, dlg, StdCleanupFormProc);
+  dlg->form = (ForM) w;
+  dlg->input_entityID = bfp->input_entityID;
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  moltype_list = GetMoleculeTypeList ();
+  /* edit list - split genomic into genomic DNA and genomic RNA */
+  for (vnp = moltype_list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == Molecule_type_unknown) {
+      vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
+      vnp->data.ptrvalue = StringSave ("unknown");
+    } else if (vnp->choice == Molecule_type_genomic) {
+      vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
+      vnp->data.ptrvalue = StringSave ("genomic DNA");
+      vnp_new = ValNodeNew (NULL);
+      vnp_new->choice = Molecule_type_genomic;
+      vnp_new->data.ptrvalue = StringSave ("genomic RNA");
+      vnp_new->next = vnp->next;
+      vnp->next = vnp_new;
+      vnp = vnp_new;
+    }
+  }
+
+  dlg->mol_type_dlg = ValNodeSelectionDialog (h, moltype_list, SHORT_SELECTION_LIST, ValNodeStringName,
+                                              ValNodeSimpleDataFree, ValNodeStringCopy,
+                                              ValNodeStringMatch, "molecule type", 
+                                              NULL, NULL, FALSE);
+  vnp = ValNodeNew (NULL);
+  vnp->choice = Molecule_type_unknown;
+  vnp->data.ptrvalue = StringSave ("unknown");
+  PointerToDialog (dlg->mol_type_dlg, vnp);
+  vnp = ValNodeFree (vnp);
+                                              
+  c = HiddenGroup (h, 4, 0, NULL);
+  b = DefaultButton (c, "Accept", DoApplyMoleculeType);
+  SetObjectExtra (b, dlg, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) dlg->mol_type_dlg, (HANDLE) c, NULL);
+    
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+}
+
+
+typedef struct formattedstruccomform {
+  FORM_MESSAGE_BLOCK
+
+  TexT * values;
+  Int4   num_fields;
+
+  CommentRulePtr    comment_rule;
+
+} FormattedStrucComFormData, PNTR FormattedStrucComFormPtr;
+
+
+static void CleanupFormattedStrucComFormProc (GraphiC g, VoidPtr data)
+
+{
+  FormattedStrucComFormPtr  dlg;
+
+  if (data) {
+    dlg = (FormattedStrucComFormPtr) data;
+    dlg->values = MemFree (dlg->values);
+  }
+  StdCleanupFormProc (g, data);
+}
+
+
+static void DoApplyFormattedStructuredComment (ButtoN b)
+{
+  FormattedStrucComFormPtr dlg;
+  UserObjectPtr            uop;
+  CharPtr                  suffix, value;
+  Int4                     len;
+  SeqDescrPtr              sdp;
+  SeqEntryPtr              sep;
+  FieldRulePtr             field;
+  Int4                     n;
+
+  dlg = (FormattedStrucComFormPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  uop = UserObjectNew ();
+  uop->type = ObjectIdNew ();
+  uop->type->str = StringSave ("StructuredComment");
+
+  AddItemStructuredCommentUserObject (uop, "StructuredCommentPrefix", dlg->comment_rule->prefix);
+
+  for (field = dlg->comment_rule->fields, n = 0; field != NULL; field = field->next, n++) {
+    if (!TextHasNoText (dlg->values[n])) {
+      value = SaveStringFromText (dlg->values[n]);
+      AddItemStructuredCommentUserObject (uop, field->field_name, value);
+      value = MemFree (value);
+    }
+  }
+
+  if ((len = StringLen (dlg->comment_rule->prefix)) > 7 
+    && StringCmp (dlg->comment_rule->prefix + len - 7, "START##") == 0) {      
+    suffix = StringSave (dlg->comment_rule->prefix);
+    sprintf (suffix + len - 7, "%s", "END##");
+    AddItemStructuredCommentUserObject (uop, "StructuredCommentSuffix", suffix);
+    suffix = MemFree (suffix);
+  }
+
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+  sdp = CreateNewDescriptor (sep, Seq_descr_user);
+  sdp->data.ptrvalue = uop;
+
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+  Remove (dlg->form);
+  Update ();
+}
+
+static void ApplyFormattedStructuredComment (IteM i, CharPtr prefix)
+{
+  BaseFormPtr       bfp;
+  CharPtr           prefix_fmt = "##%s-Data-START##";
+  CharPtr           title_fmt = "Apply %s Structured Comment";
+  CharPtr           tmp;
+  WindoW            w;
+  GrouP             h, g, c;
+  ButtoN            b;
+  CommentRulePtr    comment_rule;
+  FieldRulePtr      field;
+  Int4              n;
+  FormattedStrucComFormPtr dlg;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (prefix) + StringLen (prefix_fmt)));
+  sprintf (tmp, prefix_fmt, prefix);
+
+  comment_rule = GetCommentRuleFromRuleSet (tmp);
+  tmp = MemFree (tmp);
+  if (comment_rule == NULL) {
+    return;
+  }
+
+  dlg = (FormattedStrucComFormPtr) MemNew (sizeof (FormattedStrucComFormData));
+  if (dlg == NULL) return;
+
+  dlg->comment_rule = comment_rule;
+  n = 0;
+  for (field = comment_rule->fields; field != NULL; field = field->next) {
+    n++;
+  }
+  dlg->num_fields = n;
+  dlg->values = (TexT *) MemNew (sizeof (TexT) * dlg->num_fields);
+
+  tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (title_fmt) + StringLen(prefix)));
+  sprintf (tmp, title_fmt, prefix);
+  w = FixedWindow (-50, -33, -10, -10, tmp, StdCloseWindowProc);
+  tmp = MemFree (tmp);
+  SetObjectExtra (w, dlg, CleanupFormattedStrucComFormProc);
+  dlg->form = (ForM) w;
+  dlg->input_entityID = bfp->input_entityID;
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  g = HiddenGroup (h, 2, 0, NULL);
+  for (field = dlg->comment_rule->fields, n = 0; field != NULL; field = field->next, n++) {
+    StaticPrompt (g, field->field_name, 0, dialogTextHeight, programFont, 'l');
+    dlg->values[n] = DialogText (g, "", 10, NULL);
+  }
+
+  c = HiddenGroup (h, 4, 0, NULL);
+  b = DefaultButton (c, "Accept", DoApplyFormattedStructuredComment);
+  SetObjectExtra (b, dlg, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE)g, (HANDLE) c, NULL);
+    
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+}
+
+
+NLM_EXTERN void ApplyGenomeAssemblyComment (IteM i)
+{
+  ApplyFormattedStructuredComment (i, "Genome-Assembly");
+}
+
+
+typedef struct releasedateform {
+  FORM_MESSAGE_BLOCK
+
+  DialoG dlg;
+} ReleaseDateFormData, PNTR ReleaseDateFormPtr;
+
+
+static void DoApplyReleaseDate (ButtoN b)
+{
+  ReleaseDateFormPtr dlg;
+  SeqEntryPtr        sep;
+  SeqSubmitPtr       ssp;
+
+  dlg = (ReleaseDateFormPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+  if (sep == NULL) return;
+
+  ssp = FindSeqSubmitForSeqEntry (sep);
+  if (ssp == NULL) {
+    return;
+  }
+
+  ssp->sub = SubmitBlockFree (ssp->sub);
+  ssp->sub = DialogToPointer (dlg->dlg);
+
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+  Remove (dlg->form);
+  Update ();
+}
+
+
+NLM_EXTERN void SetReleaseDate(IteM i)
+{
+  BaseFormPtr  bfp;
+  SeqEntryPtr  sep;
+  SeqSubmitPtr ssp;
+  ReleaseDateFormPtr dlg;
+  WindoW             w;
+  GrouP              h, c;
+  ButtoN             b;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) return;
+
+  ssp = FindSeqSubmitForSeqEntry (sep);
+  if (ssp == NULL) {
+    return;
+  }
+
+  dlg = (ReleaseDateFormPtr) MemNew (sizeof (ReleaseDateFormData));
+  if (dlg == NULL) return;
+
+  w = FixedWindow (-50, -33, -10, -10, "Set Release Date", StdCloseWindowProc);
+  SetObjectExtra (w, dlg, StdCleanupFormProc);
+  dlg->form = (ForM) w;
+  dlg->input_entityID = bfp->input_entityID;
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  dlg->dlg = CreateSubmitDataDialog (h, "", ssp->sub == NULL, ssp->sub == NULL || ssp->sub->hup);
+  PointerToDialog (dlg->dlg, ssp->sub);
+
+  c = HiddenGroup (h, 4, 0, NULL);
+  b = DefaultButton (c, "Accept", DoApplyReleaseDate);
+  SetObjectExtra (b, dlg, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE)dlg->dlg, (HANDLE) c, NULL);
+    
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+}
+
+
+typedef struct removetextform {
+  FORM_MESSAGE_BLOCK
+  DialoG text_portion;
+  GrouP  not_found;
+  DialoG field;
+  DialoG constraint;
+  ButtoN leave_dlg_up;
+  ButtoN accept_btn;
+
+} RemoveTextFormData, PNTR RemoveTextFormPtr;
+
+typedef struct removetext {
+  TextPortionPtr text_portion;
+  Boolean    remove_if_not_found;
+  ValNodePtr field;
+  ValNodePtr constraint;
+} RemoveTextData, PNTR RemoveTextPtr;
+
+
+static RemoveTextPtr RemoveTextFree (RemoveTextPtr data)
+{
+  if (data != NULL) {
+    data->text_portion = TextPortionFree (data->text_portion);
+    data->field = ParseDestFree (data->field);
+    data->constraint = ConstraintChoiceSetFree (data->constraint);
+    data = MemFree (data);
+  }
+  return data;
+}
+
+
+static void RemoveTextCallbackDesc (SeqDescPtr sdp, Pointer data)
+{
+  RemoveTextPtr     rt;
+  ParseDstOrgPtr    o;
+  CharPtr           str;
+  ObjValNodePtr     ovn;
+  StringConstraint  sc;
+
+  if (sdp == NULL || (rt = (RemoveTextPtr) data) == NULL
+      || !DoesObjectMatchConstraintChoiceSet(OBJ_SEQDESC, sdp, rt->constraint)) {
+    return;
+  }
+  switch (rt->field->choice) {
+    case ParseDest_defline:
+      if (sdp->choice == Seq_descr_title) {
+        if (!RemoveTextPortionFromString ((CharPtr)(sdp->data.ptrvalue), rt->text_portion)
+            && rt->remove_if_not_found) {
+          if (sdp->extended) {
+            ovn = (ObjValNodePtr) sdp;
+            ovn->idx.deleteme = TRUE;
+          }
+        }
+      }
+      break;
+    case ParseDest_org:
+      if ((o = (ParseDstOrgPtr) rt->field->data.ptrvalue) != NULL
+          && o->type != Object_type_constraint_feature
+          && sdp->choice == Seq_descr_source) {
+        str = GetSourceQualFromBioSource (sdp->data.ptrvalue, o->field, NULL);
+        if (RemoveTextPortionFromString(str, rt->text_portion)) {
+          SetSourceQualInBioSource(sdp->data.ptrvalue, o->field, NULL, str, ExistingTextOption_replace_old);
+        } else if (rt->remove_if_not_found) {
+          MemSet (&sc, 0, sizeof (StringConstraint));
+          sc.case_sensitive = TRUE;
+          sc.match_location = String_location_equals;
+          sc.match_text = str;
+          RemoveSourceQualFromBioSource (sdp->data.ptrvalue, o->field, &sc);
+        }
+        str = MemFree (str);
+      }
+      break;
+    case ParseDest_comment_descriptor:
+      if (sdp->choice == Seq_descr_comment) {
+        if (!RemoveTextPortionFromString ((CharPtr)(sdp->data.ptrvalue), rt->text_portion)
+          && rt->remove_if_not_found) {
+          if (sdp->extended) {
+            ovn = (ObjValNodePtr) sdp;
+            ovn->idx.deleteme = TRUE;
+          }
+        }
+      }
+      break;
+    case ParseDest_dbxref:
+      if (sdp->choice == Seq_descr_source) {
+        str = GetDBxrefFromBioSource (sdp->data.ptrvalue, rt->field->data.ptrvalue);
+        if (str != NULL) {
+          if (RemoveTextPortionFromString(str, rt->text_portion)) {
+            SetDBxrefForBioSource (sdp->data.ptrvalue, rt->field->data.ptrvalue, str, ExistingTextOption_replace_old);
+          } else if (rt->remove_if_not_found) {
+            MemSet (&sc, 0, sizeof (StringConstraint));
+            sc.case_sensitive = TRUE;
+            sc.match_location = String_location_equals;
+            sc.match_text = str;
+            RemoveDBxrefForBioSource (sdp->data.ptrvalue, rt->field->data.ptrvalue, &sc);
+          }
+          str = MemFree (str);
+        }
+      }
+      break;
+  }
+}
+
+
+static void RemoveTextCallbackFeat (SeqFeatPtr sfp, Pointer data)
+{
+  RemoveTextPtr     rt;
+  ParseDstOrgPtr    o;
+  CharPtr           str;
+  StringConstraint  sc;
+  FeatureFieldLegalPtr fl;
+  FeatureField         f;
+
+  if (sfp == NULL || (rt = (RemoveTextPtr) data) == NULL
+      || !DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, rt->constraint)) {
+    return;
+  }
+
+  switch (rt->field->choice) {
+    case ParseDest_org:
+      if ((o = (ParseDstOrgPtr) rt->field->data.ptrvalue) != NULL
+          && o->type != Object_type_constraint_descriptor
+          && sfp->data.choice == SEQFEAT_BIOSRC) {
+        str = GetSourceQualFromBioSource (sfp->data.value.ptrvalue, o->field, NULL);
+        if (RemoveTextPortionFromString(str, rt->text_portion)) {
+          SetSourceQualInBioSource(sfp->data.value.ptrvalue, o->field, NULL, str, ExistingTextOption_replace_old);
+        } else if (rt->remove_if_not_found) {
+          MemSet (&sc, 0, sizeof (StringConstraint));
+          sc.case_sensitive = TRUE;
+          sc.match_location = String_location_equals;
+          sc.match_text = str;
+          RemoveSourceQualFromBioSource (sfp->data.value.ptrvalue, o->field, &sc);
+        }          
+        str = MemFree (str);
+      }
+      break;
+    case ParseDest_featqual:
+      fl = (FeatureFieldLegalPtr) rt->field->data.ptrvalue;
+      if (fl != NULL) {
+        f.type = fl->type;
+        f.field = ValNodeNew(NULL);
+        f.field->next = NULL;
+        f.field->choice = FeatQualChoice_legal_qual;
+        f.field->data.intvalue = fl->field;        
+        str = GetQualFromFeature (sfp, &f, NULL);
+        if (str != NULL) {
+          if (RemoveTextPortionFromString(str, rt->text_portion)) {
+            SetQualOnFeature (sfp, &f, NULL, str, ExistingTextOption_replace_old);
+          } else if (rt->remove_if_not_found) {
+            MemSet (&sc, 0, sizeof (StringConstraint));
+            sc.case_sensitive = TRUE;
+            sc.match_location = String_location_equals;
+            sc.match_text = str;
+            RemoveQualFromFeature (sfp, &f, &sc);
+          }
+          f.field = ValNodeFree (f.field);
+          str = MemFree (str);
+        }
+      }
+      break;
+    case ParseDest_dbxref:
+      if (sfp->data.choice == SEQFEAT_BIOSRC) {
+        str = GetDBxrefFromBioSource (sfp->data.value.ptrvalue, rt->field->data.ptrvalue);
+        if (str != NULL) {
+          if (RemoveTextPortionFromString (str, rt->text_portion)) {
+            SetDBxrefForBioSource (sfp->data.value.ptrvalue, rt->field->data.ptrvalue, str, ExistingTextOption_replace_old);
+          } else if (rt->remove_if_not_found) {
+            MemSet (&sc, 0, sizeof (StringConstraint));
+            sc.case_sensitive = TRUE;
+            sc.match_location = String_location_equals;
+            sc.match_text = str;
+            RemoveDBxrefForBioSource (sfp->data.value.ptrvalue, rt->field->data.ptrvalue, &sc);
+          }
+          str = MemFree (str);
+        }
+      }
+      break;
+  }
+
+}
+
+
+static void DoRemoveText (ButtoN b)
+{
+  RemoveTextFormPtr dlg;
+  RemoveTextPtr     data;
+  SeqEntryPtr       sep;
+  ParseDstOrgPtr    o;
+
+  dlg = (RemoveTextFormPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  data = (RemoveTextPtr) MemNew (sizeof (RemoveTextData));
+
+  data->text_portion = DialogToPointer (dlg->text_portion);
+  data->field = DialogToPointer (dlg->field);
+  data->remove_if_not_found = (GetValue (dlg->not_found) == 2);
+  data->constraint = DialogToPointer (dlg->constraint);
+  
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+
+
+  switch (data->field->choice) {
+    case ParseDest_defline :
+      VisitDescriptorsInSep (sep, data, RemoveTextCallbackDesc);
+      break;
+    case ParseDest_org :
+      o = (ParseDstOrgPtr) data->field->data.ptrvalue;
+      if (o->type == Object_type_constraint_any || o->type == Object_type_constraint_descriptor) {
+        VisitDescriptorsInSep (sep, data, RemoveTextCallbackDesc);
+      }
+      if (o->type == Object_type_constraint_any || o->type == Object_type_constraint_feature) {
+        VisitFeaturesInSep (sep, data, RemoveTextCallbackFeat);
+      }
+      break;
+    case ParseDest_featqual :
+      VisitFeaturesInSep (sep, data, RemoveTextCallbackFeat);
+      break;
+    case ParseDest_comment_descriptor :
+      VisitDescriptorsInSep (sep, data, RemoveTextCallbackDesc);
+      break;
+    case ParseDest_dbxref :
+      VisitDescriptorsInSep (sep, data, RemoveTextCallbackDesc);
+      VisitFeaturesInSep (sep, data, RemoveTextCallbackFeat);
+      break;
+  }
+
+  data = RemoveTextFree (data);
+
+  DeleteMarkedObjects (dlg->input_entityID, 0, NULL);
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+  if (GetStatus (dlg->leave_dlg_up)) {
+  } else {
+    Remove (dlg->form);
+  }
+  Update();
+}
+
+
+static void EnableRemoveTextAccept (Pointer data)
+{
+  RemoveTextFormPtr dlg;
+  ValNodePtr        field;
+
+  dlg = (RemoveTextFormPtr) data;
+  if (dlg == NULL) {
+    return;
+  }
+
+  field = DialogToPointer (dlg->field);
+  if (field == NULL) {
+    Disable (dlg->accept_btn);
+  } else {
+    Enable (dlg->accept_btn);
+  }
+  field = ParseDestFree (field);
+}
+
+
+static void ClearRemoveText(ButtoN b)
+{
+  RemoveTextFormPtr dlg;
+
+  dlg = (RemoveTextFormPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  PointerToDialog (dlg->text_portion, NULL);
+  PointerToDialog (dlg->field, NULL);
+  EnableRemoveTextAccept(dlg);
+}
+
+
+static void NewRemoveText (IteM i, Boolean inside)
+{
+  BaseFormPtr  bfp;
+  RemoveTextFormPtr dlg;
+  WindoW             w;
+  GrouP              h, g1, c;
+  PrompT             p1;
+  ButtoN             clear_btn;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  dlg = (RemoveTextFormPtr) MemNew (sizeof (RemoveTextFormData));
+  if (dlg == NULL) return;
+
+  w = FixedWindow (-50, -33, -10, -10, inside ? "Remove Text Inside String" : "Remove Text Outside String", StdCloseWindowProc);
+  SetObjectExtra (w, dlg, StdCleanupFormProc);
+  dlg->form = (ForM) w;
+  dlg->input_entityID = bfp->input_entityID;
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  dlg->text_portion = TextPortionDialog (h, inside, NULL, NULL);
+
+  g1 = HiddenGroup (h, 0, 2, NULL);
+  StaticPrompt (g1, "If field doesn't contain searched for text:", 0, 0, programFont, 'l');
+
+  dlg->not_found = HiddenGroup (g1, 0, 3, NULL);
+
+  RadioButton (dlg->not_found, "     Do nothing to field");
+  RadioButton (dlg->not_found, "     Remove entire field text");
+  SetValue (dlg->not_found, 1);
+
+  p1 = StaticPrompt (h, "Perform excision in", 0, popupMenuHeight, programFont, 'l');
+
+  dlg->field = ParseDstDialog (h, EnableRemoveTextAccept, dlg);
+
+  /* clear button */
+  clear_btn = PushButton (h, "Clear", ClearRemoveText);
+  SetObjectExtra (clear_btn, dlg, NULL);
+
+  dlg->constraint = ConstraintSetDialog (h, NULL, NULL);
+
+
+  c = HiddenGroup (h, 4, 0, NULL);
+  dlg->accept_btn = DefaultButton (c, "Accept", DoRemoveText);
+  SetObjectExtra (dlg->accept_btn, dlg, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+  dlg->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE)dlg->text_portion, 
+                              (HANDLE) g1, 
+                              (HANDLE) p1, 
+                              (HANDLE) dlg->field, 
+                              (HANDLE) dlg->constraint,
+                              (HANDLE) clear_btn, 
+                              (HANDLE) c, NULL);
+  EnableRemoveTextAccept (dlg);
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+}
+
+
+NLM_EXTERN void NewRemoveTextOutsideString (IteM i)
+{
+  NewRemoveText (i, FALSE);
+}
+
+
+static void PrintTPAHistErrors (LogInfoPtr lip, ValNodePtr errors)
+{
+  ValNodePtr vnp;
+
+  if (lip == NULL || lip->fp == NULL || errors == NULL) return;
+
+  for (vnp = errors; vnp != NULL; vnp = vnp->next)
+  {
+    fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
+    lip->data_in_log = TRUE;
+  }
+  fprintf (lip->fp, "\n\n");
+}
+
+
+NLM_EXTERN void ImportTpaAlignment (IteM i)
+{
+  BaseFormPtr  bfp;
+  SeqEntryPtr  sep;
+  BioseqPtr    bsp, bsp_tmp;
+  Char         path [PATH_MAX];
+  AsnIoPtr     aip;
+  SeqAlignPtr  align, last_align, next_align;
+  SeqAnnotPtr  sap;
+  SeqHistPtr   shp;
+  ValNodePtr   err_list = NULL;
+  LogInfoPtr   lip;
+  UserObjectPtr uop;
+  SeqDescPtr   sdp;
+  Char         id_buf[255];
+  SeqIdPtr     sip;
+  Int4         primary_start, primary_stop;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) {
+    return;
+  }
+
+  bsp = GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
+  if (bsp == NULL) {
+    Message (MSG_ERROR, "Need to select sequence to attach alignment to");
+    return;
+  }
+
+  if (! GetInputFileName (path, sizeof (path), NULL, "TEXT")) return;
+
+  aip = AsnIoOpen (path, "rb");
+  align = SeqAlignAsnRead (aip, NULL);
+
+  if (align == NULL) {
+    AsnIoClose (aip);
+    aip = AsnIoOpen (path, "rb");
+    sap = SeqAnnotAsnRead (aip, NULL);
+    if (sap == NULL) {
+      Message (MSG_ERROR, "Unable to read alignment");
+      return;
+    } else if (sap->type != 2 || sap->data == NULL) {
+      Message (MSG_ERROR, "Unable to read alignment");
+      sap = SeqAnnotFree (sap);
+      return;
+    } else {
+      align = sap->data;
+      sap->data = NULL;
+      sap = SeqAnnotFree (sap);
+    }
+  } else {
+    last_align = align;
+    while ((next_align = SeqAlignAsnRead (aip, NULL)) != NULL) {
+      last_align->next = next_align;
+      last_align = next_align;
+    }
+  }
+  AsnIoClose (aip);
+
+  SortTPAAssembly (&align);
+
+  uop = GetTPAAssembly(bsp);
+  if (uop != NULL || (bsp->hist != NULL && bsp->hist->assembly != NULL)) {
+    if (Message (MSG_OKC, "Sequence already has assembly - remove and replace with the new?") != ANS_OK) {
+      while (align != NULL) {
+        next_align = align->next;
+        align->next = NULL;
+        align = SeqAlignFree (align);
+        align = next_align;
+      }
+      return;
+    }
+  }    
+
+  if (bsp->hist != NULL) {
+	  shp = bsp->hist;
+	  if (shp->assembly != NULL)
+	    SeqAlignSetFree(shp->assembly);
+	  shp->assembly = align;
+	}
+  else
+	{
+	  shp = SeqHistNew();
+	  shp->assembly = align;
+	  bsp->hist = shp;
+	}
+
+  ValidateTPAHistAlign (bsp, &err_list);
+  if (err_list != NULL) {
+    lip = OpenLog ("TPA Problems");
+    PrintTPAHistErrors (lip, err_list);
+    lip->data_in_log = TRUE;
+    err_list = ValNodeFreeData (err_list);
+    CloseLog (lip);
+    FreeLog (lip);
+  }
+
+  if (uop == NULL) 
+  {
+    sdp = CreateNewDescriptor (SeqMgrGetSeqEntryForData (bsp), Seq_descr_user);
+    uop = CreateTpaAssemblyUserObject ();
+    sdp->data.ptrvalue = uop;
+  }
+
+  RemoveOldTPAAccessions (uop);
+
+  for (align = shp->assembly; align != NULL; align = align->next)
+  {
+    sip = AlnMgr2GetNthSeqIdPtr (align, 2);
+    bsp_tmp = BioseqLockById (sip);
+    if (bsp_tmp == NULL) {
+      SeqIdWrite (sip, id_buf, PRINTID_REPORT, sizeof (id_buf) - 1);
+    } else {
+      SeqIdWrite (SeqIdFindBest (bsp_tmp->id, SEQID_GENBANK), id_buf, PRINTID_REPORT, sizeof (id_buf) - 1);
+      BioseqUnlock (bsp_tmp);
+    }
+    sip = SeqIdFree (sip);
+    AlnMgr2GetNthSeqRangeInSA (align, 1, &primary_start, &primary_stop);
+    if (AlnMgr2GetNthStrand (align, 2) == Seq_strand_minus) {
+      AddAccessionToTpaAssemblyUserObject (uop, id_buf, primary_stop, primary_start);
+    } else {
+      AddAccessionToTpaAssemblyUserObject (uop, id_buf, primary_start, primary_stop);
+    }
+  }
+
+
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);  
+  Update ();
+}
+
+
+NLM_EXTERN void AdjustForConsensusSplice (IteM i)
+{
+  BaseFormPtr  bfp;
+  SeqEntryPtr  sep;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) {
+    return;
+  }
+
+  AdjustSeqEntryForConsensusSplice (sep);
+
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);  
+  Update ();
+}
diff --git a/sequin/sequin2.c b/sequin/sequin2.c
index 9e641b0..11d7244 100644
--- a/sequin/sequin2.c
+++ b/sequin/sequin2.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.667 $
+* $Revision: 6.682 $
 *
 * File Description: 
 *
@@ -84,13 +84,11 @@ static ENUM_ALIST(biomol_nucX_alist)
   {"mRNA [cDNA]",              3},
   {"Ribosomal RNA",            4},
   {"Transfer RNA",             5},
-  {"Small nuclear RNA",        6},
-  {"Small cytoplasmic RNA",    7},
   {"Other-Genetic",            9},
   {"cRNA",                    11},
-  {"Small nucleolar RNA",     12},
   {"Transcribed RNA",         13}, 
   {"Transfer-messenger RNA", MOLECULE_TYPE_TMRNA },
+  {"ncRNA",                  MOLECULE_TYPE_NCRNA},
 END_ENUM_ALIST
 
 static ENUM_ALIST(biomol_nucGen_alist)
@@ -874,7 +872,6 @@ static Boolean PackageTypeIsSet (Int2 seqPackage)
 static Boolean PackageTypeIsSingle (Int2 seqPackage)
 {
   if (seqPackage == SEQ_PKG_SINGLE
-      || seqPackage == SEQ_PKG_SEGMENTED
       || seqPackage == SEQ_PKG_GAPPED)
   {
     return TRUE;
@@ -3405,7 +3402,7 @@ static void FormatFastaDoc (FastaPagePtr fpp)
   CharPtr            label;
   Int4               len;
   CharPtr            measure;
-  SeqEntryPtr        nsep;
+  SeqEntryPtr        nsep = NULL;
   Int2               num;
   CharPtr            plural;
   CharPtr            ptr;
@@ -4191,6 +4188,28 @@ static void CleanTitles (SeqEntryPtr sep, ValNodePtr PNTR special_list)
 }
 
 
+static void StripStopCodons (SeqEntryPtr sep_list)
+{
+  BioseqPtr pbsp;
+  Char      prot_str[2];
+
+  prot_str[1] = 0;
+  while (sep_list != NULL) {
+    if (IS_Bioseq (sep_list) && (pbsp = (BioseqPtr) sep_list->data.ptrvalue) != NULL
+        && ISA_aa(pbsp->mol) && pbsp->repr == Seq_repr_raw) {     
+      SeqPortStreamInt (pbsp, pbsp->length - 1, pbsp->length - 1, Seq_strand_plus, EXPAND_GAPS_TO_DASHES, (Pointer) (prot_str), NULL);
+      if (prot_str[0] == '*') {
+        /* trim trailing stop codon */
+        BSSeek (pbsp->seq_data, -1, SEEK_END);
+        BSDelete (pbsp->seq_data, 1);
+        pbsp->length -= 1;
+      }
+    }
+    sep_list = sep_list->next;
+  }
+}
+
+
 static SeqEntryPtr ImportOnlyProteinSequences 
 (FILE            *fp,
  SeqEntryPtr     sep_list,
@@ -4291,6 +4310,8 @@ static SeqEntryPtr ImportOnlyProteinSequences
     lastsep->next = new_list;
   }
 
+  StripStopCodons (sep_list);
+
   SeqEntrySetScope (oldscope);
 
   return sep_list;
@@ -4867,6 +4888,7 @@ static Boolean ImportedSequenceTypeOk (SeqEntryPtr list, Int2 seqPackage)
   return rval;
 }
 
+
 static Boolean ImportFastaDialog (DialoG d, CharPtr filename)
 
 {
@@ -4960,13 +4982,6 @@ static Boolean ImportFastaDialog (DialoG d, CharPtr filename)
           }
         }
         supplied_id_txt = MemFree (supplied_id_txt);                                              
-        if (fpp->seqPackagePtr != NULL 
-            && *(fpp->seqPackagePtr) == SEQ_PKG_SEGMENTED
-            && new_sep_list != NULL
-            && IS_Bioseq (new_sep_list))
-        {
-          new_sep_list = SegsetFromSeqEntryList (new_sep_list);
-        }
         FileClose (f);
         
         if (new_sep_list != NULL
@@ -6126,15 +6141,7 @@ static SeqEntryPtr GetSeqEntryFromSequencesForm (SequencesFormPtr sqfp)
   
   if (sqfp == NULL) return NULL;
 
-  if (sqfp->seqPackage == SEQ_PKG_SEGMENTED) 
-  {
-    fpp = (FastaPagePtr) GetObjectExtra (sqfp->dnaseq);
-    if (fpp != NULL) 
-    {
-      list = fpp->list;
-    }
-  }
-  else if (sqfp->seqFormat == SEQ_FMT_FASTA) {
+  if (sqfp->seqFormat == SEQ_FMT_FASTA) {
     fpp = (FastaPagePtr) GetObjectExtra (sqfp->dnaseq);
     if (fpp != NULL) 
     {
@@ -6592,6 +6599,10 @@ SetMoleculeAndMolTypeFromTitle
     {
       molecule = Seq_mol_dna;
     }
+    else if (biomol == MOLECULE_TYPE_NCRNA)
+    {
+      molecule = Seq_mol_rna;
+    }
     else if (biomol == 253)
     {
       molecule = Seq_mol_dna;
@@ -7735,9 +7746,6 @@ static void OnlyOneComponentWarning (SequencesFormPtr sqfp)
       return;
     }
     switch (sqfp->seqPackage) {
-      case SEQ_PKG_SEGMENTED :
-        type = "segmented sequence";
-        break;
       case SEQ_PKG_POPULATION :
         type = "population set";
         break;
@@ -8636,7 +8644,7 @@ static SeqLocPtr DefaultPairInterval (BioseqPtr nbsp, BioseqPtr pbsp, Int2 code)
   /* if no location, use entire sequence */
   if (slp == NULL)
   {
-    slp = SeqLocIntNew (0, nbsp->length - 1, Seq_strand_plus, nbsp->id); 
+    return slp; 
   }
 
   /* check for start and stop codons */  
@@ -8776,6 +8784,16 @@ PickCodingRegionLocationsForProteinNucleotidePairs
       } else {
         code = GetGeneticCodeFromBioseq (nbsp);
         slp = DefaultPairInterval (nbsp, pbsp, code);
+        if (slp == NULL) {
+          errors_found = TRUE;
+          if (fp != NULL) {
+            SeqIdWrite (SeqIdFindWorst (nbsp->id), n_idstr, PRINTID_REPORT,
+                        sizeof (n_idstr));
+            SeqIdWrite (SeqIdFindWorst (pbsp->id), p_idstr, PRINTID_REPORT,
+                        sizeof (p_idstr));
+            fprintf (fp, "Unable to determine coding region location on %s for %s\n", n_idstr, p_idstr); 
+          }
+        }
       }
     }
     else
@@ -9151,7 +9169,7 @@ static void PopulateNucProtEdit (NucProtEditPtr npep)
   CharPtr               data_string, gene_locus, prot_name;
   Int4                  data_len;
   Int4                  prot_num;
-  Int4                  old_scroll_pos;
+  Int4                  old_scroll_pos = 0;
   
   if (npep == NULL)
   {
@@ -9611,7 +9629,7 @@ CollectNucleotideProteinAssociations
                                                                  nuc_list,
                                                                  prot_list)) 
         {
-          if (ANS_NO == Message (MSG_YN, "Some nucleotides are too short to encode the selected proteins.  These proteins will be discarded.  Do you wish to continue?")) 
+          if (ANS_NO == Message (MSG_YN, "Unable to determine coding region location for some proteins.  These proteins will be discarded.  Do you wish to continue?")) 
           {
             acd.accepted = FALSE;
             PopulateNucProtEdit (&nped);
@@ -9874,6 +9892,14 @@ static void BuildNucProtSets
   sqfp->nuc_prot_assoc_list = FreeAssociationList (sqfp->nuc_prot_assoc_list);
 }
 
+typedef enum {
+  eSubmitAnnotType_CDS = 1,
+  eSubmitAnnotType_rRNA,
+  eSubmitAnnotType_Gene,
+  eSubmitAnnotType_None 
+} ESubmitAnnotTypen;
+
+
 static Pointer FastaSequencesFormToSeqEntryPtr (ForM f)
 
 {
@@ -10002,29 +10028,7 @@ static Pointer FastaSequencesFormToSeqEntryPtr (ForM f)
         }
       }
     }
-    if (sep != NULL && sqfp->seqPackage == SEQ_PKG_SEGMENTED) {
-      nsep = FindNucSeqEntry (sep);
-      if (nsep != NULL && nsep->choice == 1) {
-        segseq = (BioseqPtr) nsep->data.ptrvalue;
-        if (segseq != NULL && segseq->repr == Seq_repr_seg && segseq->seq_ext_type == 1) {
-          vnp = (ValNodePtr) segseq->seq_ext;
-          while (vnp != NULL) {
-            nxtvnp = vnp->next;
-            if (nxtvnp != NULL && vnp->choice != SEQLOC_NULL) {
-              nulvnp = ValNodeNew (NULL);
-              if (nulvnp != NULL) {
-                nulvnp->choice = SEQLOC_NULL;
-                nulvnp->next = nxtvnp;
-                vnp->next = nulvnp;
-              }
-            }
-            vnp = nxtvnp;
-          }
-        }
-      }
-    }
-    if (sqfp->seqPackage != SEQ_PKG_SEGMENTED &&
-        sqfp->seqPackage != SEQ_PKG_GENOMICCDNA &&
+    if (sqfp->seqPackage != SEQ_PKG_GENOMICCDNA &&
         sqfp->seqPackage != SEQ_PKG_GAPPED) {
       if (! TextHasNoText (sqfp->defline)) {
         ApplyAnnotationToAll (ADD_TITLE, sep, sqfp->partialLft, sqfp->partialRgt,
@@ -10091,24 +10095,29 @@ static Pointer FastaSequencesFormToSeqEntryPtr (ForM f)
         AddSeqAlignForSeqEntry (sep, ObjMgrGetEntityIDForChoice (sep), FALSE, TRUE);
       }
     }
-    if (sqfp->seqPackage != SEQ_PKG_SEGMENTED &&
-        sqfp->seqPackage != SEQ_PKG_GENOMICCDNA &&
+    if (sqfp->seqPackage != SEQ_PKG_GENOMICCDNA &&
         sqfp->seqPackage != SEQ_PKG_GAPPED) {
       annotType = GetValue (sqfp->annotType);
       if (annotType > 0) {
         oldscope = SeqEntrySetScope (sep);
+        if (annotType == eSubmitAnnotType_CDS
+            && TextHasNoText (sqfp->protOrRnaName)
+            && TextHasNoText (sqfp->protDesc)
+            && TextHasNoText (sqfp->featcomment)) {
+          annotType = eSubmitAnnotType_Gene;
+        }
         switch (annotType) {
-          case 1 :
+          case eSubmitAnnotType_Gene :
             ApplyAnnotationToAll (ADD_IMP, sep, sqfp->partialLft, sqfp->partialRgt,
                                   sqfp->geneName, NULL, NULL, NULL,
                                   sqfp->featcomment, NULL);
             break;
-          case 2 :
+          case eSubmitAnnotType_rRNA :
             ApplyAnnotationToAll (ADD_RRNA, sep, sqfp->partialLft, sqfp->partialRgt,
                                   sqfp->geneName, NULL, NULL, sqfp->protOrRnaName,
                                   sqfp->featcomment, NULL);
             break;
-          case 3 :
+          case eSubmitAnnotType_CDS :
             ambig = ApplyAnnotationToAll (ADD_CDS, sep, sqfp->partialLft, sqfp->partialRgt,
                                           sqfp->geneName, sqfp->protOrRnaName, sqfp->protDesc, NULL,
                                           sqfp->featcomment, NULL);
@@ -10317,17 +10326,17 @@ static Pointer PhylipSequencesFormToSeqEntryPtr (ForM f)
     annotType = GetValue (sqfp->annotType);
     if (annotType > 0) {
       switch (annotType) {
-        case 1 :
+        case eSubmitAnnotType_Gene :
           ApplyAnnotationToAll (ADD_IMP, sep, sqfp->partialLft, sqfp->partialRgt,
                                 sqfp->geneName, NULL, NULL, NULL,
                                 sqfp->featcomment, NULL);
           break;
-        case 2 :
+        case eSubmitAnnotType_rRNA :
           ApplyAnnotationToAll (ADD_RRNA, sep, sqfp->partialLft, sqfp->partialRgt,
                                 sqfp->geneName, NULL, NULL, sqfp->protOrRnaName,
                                 sqfp->featcomment, NULL);
           break;
-        case 3 :
+        case eSubmitAnnotType_CDS :
           ambig = ApplyAnnotationToAll (ADD_CDS, sep, sqfp->partialLft, sqfp->partialRgt,
                                         sqfp->geneName, sqfp->protOrRnaName, sqfp->protDesc, NULL,
                                         sqfp->featcomment, NULL);
@@ -10486,7 +10495,7 @@ ReportMissingOrganismNames
     fprintf (fp, "The following sequences have no organism names.  You must supply one for each sequence listed.\n");
     for (vnp = no_org_list; vnp != NULL; vnp = vnp->next)
     {
-      fprintf (fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
   }
 
@@ -10574,11 +10583,11 @@ static Boolean IsAnnotTabEmpty (SequencesFormPtr sqfp)
   {
     return FALSE;
   }
-  else if (annot_type > 1 && ! TextHasNoText (sqfp->protOrRnaName))
+  else if (annot_type != eSubmitAnnotType_Gene && ! TextHasNoText (sqfp->protOrRnaName))
   {
     return FALSE;
   }
-  else if (annot_type == 3 && ! TextHasNoText (sqfp->protDesc))
+  else if (annot_type == eSubmitAnnotType_CDS  && ! TextHasNoText (sqfp->protDesc))
   {
     return FALSE;
   }
@@ -10598,7 +10607,7 @@ static void ChangeAnnotType (GrouP g)
   if (sqfp == NULL) return;
   val = GetValue (g);
   switch (val) {
-    case 1 :
+    case eSubmitAnnotType_Gene :
       SafeHide (sqfp->protOrRnaPpt);
       SafeHide (sqfp->protOrRnaName);
       SafeHide (sqfp->protDescPpt);
@@ -10606,7 +10615,7 @@ static void ChangeAnnotType (GrouP g)
       SafeShow (sqfp->annotGrp);
       Select (sqfp->geneName);
       break;
-    case 2 :
+    case eSubmitAnnotType_rRNA :
       SafeSetTitle (sqfp->protOrRnaPpt, "rRNA Name");
       SafeShow (sqfp->protOrRnaPpt);
       SafeShow (sqfp->protOrRnaName);
@@ -10615,7 +10624,7 @@ static void ChangeAnnotType (GrouP g)
       SafeShow (sqfp->annotGrp);
       Select (sqfp->protOrRnaName);
       break;
-    case 3 :
+    case eSubmitAnnotType_CDS :
       SafeSetTitle (sqfp->protOrRnaPpt, "Protein Name");
       SafeShow (sqfp->protOrRnaPpt);
       SafeShow (sqfp->protOrRnaName);
@@ -10656,7 +10665,7 @@ static Boolean ImportSequencesForm (ForM f, CharPtr filename)
         rval = ImportDialog (sqfp->protseq, "");
         if (rval && IsAnnotTabEmpty (sqfp))
         {
-          SetValue (sqfp->annotType, 4);
+          SetValue (sqfp->annotType, eSubmitAnnotType_None);
           ChangeAnnotType (sqfp->annotType);
         }
         break;
@@ -12673,7 +12682,7 @@ static void SummarizeModifiers (ValNodePtr row_list, DialoG summary_dlg)
             is_unique = FALSE;
           }
           
-          if ( FindExactStringInStrings (values_seen, column_vnp->data.ptrvalue)
+          if ( FindExactStringListMatch (values_seen, column_vnp->data.ptrvalue)
               == NULL)
           {
             ValNodeAddStr (&values_seen, 0, column_vnp->data.ptrvalue);
@@ -17462,12 +17471,6 @@ static void SpecifyModValueButton (ButtoN b, CharPtr mod_name)
     mod_label = MemFree (mod_label);
     return;
   }
-  if (seq_list->next == NULL || sqfp->seqPackage == SEQ_PKG_SEGMENTED)
-  {
-    ApplyOneValueToAllSequencesDialog (b, mod_name);
-    mod_label = MemFree (mod_label);
-    return;
-  }
 
   sprintf (title, "Edit %s Information", mod_label);
   title [5] = TO_UPPER (title [5]);
@@ -23501,6 +23504,7 @@ static void ReplaceFakeIDWithIDFromTitle (BioseqPtr bsp)
   }  
 }
 
+
 static SeqEntryPtr GetSequencesFromFile (CharPtr path, SeqEntryPtr current_list) 
 {
   FILE         *fp;
@@ -24702,7 +24706,7 @@ SequenceAssistantValidateOneBioseqContentAndLength
 
   if (CountSeqChars (seqbuf) < 50)
   {
-    ValNodeAddPointer (too_short_list, seq_num, id_str);
+    ValNodeAddPointer (too_short_list, seq_num, StringSave (id_str));
     rval = FALSE;
   }
   if (IsSequenceAllNs (seqbuf))
@@ -25183,9 +25187,9 @@ static GrouP CreateNucleotideTab (GrouP h, SequencesFormPtr sqfp)
 {
   GrouP              q, g, x, y, k;
   ButtoN             b = NULL;
-  Handle             h1, h2;
+  Handle             h1 = NULL, h2 = NULL;
   Boolean            single;
-  GrouP              import_btn_grp;
+  GrouP              import_btn_grp = NULL;
   FastaPagePtr       fpp;
   
   q = HiddenGroup (h, -1, 0, NULL);
@@ -25234,8 +25238,7 @@ static GrouP CreateNucleotideTab (GrouP h, SequencesFormPtr sqfp)
     SetObjectExtra (fpp->import_btn, sqfp, NULL);
     
     if (sqfp->seqPackage != SEQ_PKG_GAPPED 
-        && sqfp->seqPackage != SEQ_PKG_GENOMICCDNA
-        && sqfp->seqPackage != SEQ_PKG_SEGMENTED)
+        && sqfp->seqPackage != SEQ_PKG_GENOMICCDNA)
     {
       b = PushButton (import_btn_grp, "Add/Modify Sequences", SequenceAssistant);
       SetObjectExtra (b, sqfp, NULL);
@@ -25362,11 +25365,11 @@ static GrouP CreateAnnotTab (GrouP h, SequencesFormPtr sqfp)
                        0, 0, programFont, 'l');
   sqfp->annotType = HiddenGroup (q, 5, 0, ChangeAnnotType);
   SetObjectExtra (sqfp->annotType, sqfp, NULL);
-  RadioButton (sqfp->annotType, "Gene");
-  RadioButton (sqfp->annotType, "rRNA");
   RadioButton (sqfp->annotType, "CDS");
+  RadioButton (sqfp->annotType, "rRNA");
+  RadioButton (sqfp->annotType, "Gene");
   RadioButton (sqfp->annotType, "None");
-  SetValue (sqfp->annotType, 1);
+  SetValue (sqfp->annotType, eSubmitAnnotType_CDS);
   sqfp->annotGrp = HiddenGroup (q, -1, 0, NULL);
   SetGroupSpacing (sqfp->annotGrp, 10, 10);
   x = HiddenGroup (sqfp->annotGrp, 2, 0, NULL);
@@ -25404,11 +25407,6 @@ static GrouP CreateAnnotTab (GrouP h, SequencesFormPtr sqfp)
 
   SetPosition (sqfp->defline, &defline_rect);
   
-  Hide (sqfp->protOrRnaPpt);
-  Hide (sqfp->protOrRnaName);
-  Hide (sqfp->protDescPpt);
-  Hide (sqfp->protDesc);
-  /* Hide (sqfp->annotGrp); */
   return q;
 }
 
@@ -25487,7 +25485,7 @@ extern ForM CreateInitOrgNucProtForm (Int2 left, Int2 top, CharPtr title,
       sqfp->tbs = CreateFolderTabs (j, cdnaGenFormTabs, NUCLEOTIDE_PAGE,
                                     0, 0, SYSTEM_FOLDER_TAB,
                                     ChangeSequencesPage, (Pointer) sqfp);
-    } else if (sqfp->seqPackage == SEQ_PKG_SEGMENTED || sqfp->seqPackage == SEQ_PKG_GAPPED) {
+    } else if (sqfp->seqPackage == SEQ_PKG_GAPPED) {
       sqfp->tbs = CreateFolderTabs (j, seqSegFormTabs, NUCLEOTIDE_PAGE,
                                     0, 0, SYSTEM_FOLDER_TAB,
                                     ChangeSequencesPage, (Pointer) sqfp);
@@ -25525,7 +25523,6 @@ extern ForM CreateInitOrgNucProtForm (Int2 left, Int2 top, CharPtr title,
     page++;
 
     if (sqfp->seqPackage != SEQ_PKG_GENOMICCDNA 
-        && sqfp->seqPackage != SEQ_PKG_SEGMENTED
         && sqfp->seqPackage != SEQ_PKG_GAPPED)
     {
       sqfp->pages [page] = CreateAnnotTab (h, sqfp);
@@ -26366,13 +26363,18 @@ static void DownloadProc (ButtoN b)
   CharPtr       dbname;
   Uint2         entityID;
   FetchFormPtr  ffp;
+  Int4          flags = 0;
   Int2          handled;
   Boolean       idTypes [NUM_SEQID];
   Boolean       isReplaced = FALSE;
+  Int2          retcode = 0;
   SeqEntryPtr   sep;
-  Char          str [32];
+  Char          str [64];
   Uint4         tid;
+  CharPtr       tmp1 = NULL;
+  CharPtr       tmp2 = NULL;
   Int4          uid;
+  long int      val;
   ForM          w;
 
   ffp = (FetchFormPtr) GetObjectExtra (b);
@@ -26390,6 +26392,24 @@ static void DownloadProc (ButtoN b)
     Select (ffp->accession);
     return;
   }
+
+  tmp1 = StringChr (str, ',');
+  if (tmp1 != NULL) {
+    *tmp1 = '\0';
+    tmp1++;
+    tmp2 = StringChr (tmp1, ',');
+    if (tmp2 != NULL) {
+      *tmp2 = '\0';
+      tmp2++;
+      if (StringDoesHaveText (tmp2) && sscanf (tmp2, "%ld", &val) == 1) {
+        flags = (Int4) val;
+      }
+    }
+    if (StringDoesHaveText (tmp1) && sscanf (tmp1, "%ld", &val) == 1) {
+      retcode = (Int2) val;
+    }
+  }
+
   sep = NULL;
   uid = 0;
   tid = 0;
@@ -26443,7 +26463,7 @@ static void DownloadProc (ButtoN b)
     }
   }
   if (uid > 0) {
-    sep = PubSeqSynchronousQuery (uid, 0, /* -1 */ 0);
+    sep = PubSeqSynchronousQuery (uid, retcode, flags);
   }
   if (uid > 0 || tid > 0) {
     /* EntrezFini (); */
@@ -26724,7 +26744,8 @@ static void FetchTextProc (TexT t)
 {
   Boolean       alldigits;
   FetchFormPtr  ffp;
-  Char          str [32];
+  CharPtr       ptr;
+  Char          str [64];
 
   ffp = (FetchFormPtr) GetObjectExtra (t);
   if (ffp == NULL) return;
@@ -26733,6 +26754,10 @@ static void FetchTextProc (TexT t)
     SafeDisable (ffp->accept);
   } else {
     SafeEnable (ffp->accept);
+    ptr = StringChr (str, ',');
+    if (ptr != NULL) {
+      *ptr = '\0';
+    }
     TrimSpacesAroundString (str);
     alldigits = IsAllDigits (str);
     if (alldigits) {
@@ -27127,7 +27152,7 @@ static ValNodePtr TPAFromFileListFree (ValNodePtr vnp)
 }
 
 
-static UserObjectPtr GetTPAAssembly (BioseqPtr bsp)
+NLM_EXTERN UserObjectPtr GetTPAAssembly (BioseqPtr bsp)
 {
   SeqDescrPtr       sdp;
   SeqMgrDescContext context;
@@ -27190,6 +27215,7 @@ static ValNodePtr ReadTPAAccessionNumbersFile (FILE *fp, SeqEntryPtr sep, BoolPt
   ValNodePtr    acc_list;
   Boolean       found_other_acc = FALSE;
   MsgAnswer     ans;
+  SeqIdPtr      sip;
 
   notfound_lip = OpenLog ("Accessions in Table Not Found in Record");
   alreadyhas_lip = OpenLog ("Accessions that Already Have TPA Acccesion Numbers");
@@ -27262,7 +27288,12 @@ static ValNodePtr ReadTPAAccessionNumbersFile (FILE *fp, SeqEntryPtr sep, BoolPt
 
     if (need_seqid == TRUE)
     {
+      sip = CreateSeqIdFromText (seqid, sep);
+      bsp = BioseqFind (sip);
+      sip = SeqIdFree (sip);
+      if (bsp == NULL) {
       bsp = FindBioseqByIDString (seqid, sep);
+      }
       if (bsp == NULL) 
       {
         fprintf (notfound_lip->fp, 
@@ -27350,7 +27381,7 @@ static ValNodePtr ReadTPAAccessionNumbersFile (FILE *fp, SeqEntryPtr sep, BoolPt
 }
 
 
-static void RemoveOldTPAAccessions (UserObjectPtr uop)
+NLM_EXTERN void RemoveOldTPAAccessions (UserObjectPtr uop)
 {
   UserFieldPtr  ufp, ufp_next, ufp_prev = NULL;
   ObjectIdPtr   oip;
@@ -27820,16 +27851,10 @@ static void RemoveAllGenomeProjectIDCallback (SeqDescrPtr sdp, Pointer userdata)
 }
 
 
-extern void RemoveGenomeProjectIDs  (IteM i)
+extern void RemoveGenomeProjectIdsBaseForm (BaseFormPtr bfp)
 {
-  BaseFormPtr   bfp;
   SeqEntryPtr   sep;
 
-#ifdef WIN_MAC
-  bfp = currentFormDataPtr;
-#else
-  bfp = GetObjectExtra (i);
-#endif
   if (bfp == NULL) return;
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
@@ -27844,6 +27869,19 @@ extern void RemoveGenomeProjectIDs  (IteM i)
   return;
 }
 
+extern void RemoveGenomeProjectIDs  (IteM i)
+{
+  BaseFormPtr   bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+
+  RemoveGenomeProjectIdsBaseForm (bfp);
+}
+
 
 CharPtr MostUsedFeatureList[] = { 
   "CDS",
@@ -27865,7 +27903,7 @@ extern ValNodePtr InsertMostUsedFeatureValNodes (ValNodePtr old_list)
        index < sizeof (MostUsedFeatureList) / sizeof (CharPtr);
        index ++)
   {
-    old_item = FindExactStringInStrings ( old_list, MostUsedFeatureList [index])
+    old_item = FindExactStringListMatch ( old_list, MostUsedFeatureList [index])
 ;
     if (old_item == NULL) continue;
     new_item = ValNodeNew ( new_list);
diff --git a/sequin/sequin3.c b/sequin/sequin3.c
index d05dc00..251c207 100644
--- a/sequin/sequin3.c
+++ b/sequin/sequin3.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/22/95
 *
-* $Revision: 6.978 $
+* $Revision: 6.1043 $
 *
 * File Description: 
 *
@@ -239,7 +239,7 @@ static void AddTSATableToBioseq (IteM i)
   if (err_list != NULL) {
     lip = OpenLog ("Problems Reading TSA Table File");
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     CloseLog (lip);
@@ -275,7 +275,7 @@ static void AddTSATableToBioseq (IteM i)
   lip = OpenLog ("TSA Table Problems");
   if (err_list != NULL) {
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     err_list = ValNodeFreeData (err_list);
@@ -325,7 +325,7 @@ static void RefreshTSATables (IteM i)
   lip = OpenLog ("TSA Table Problems");
   if (err_list != NULL) {
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     err_list = ValNodeFreeData (err_list);
@@ -353,13 +353,84 @@ static void CreateTSAIDsFromLocalIDs (IteM i)
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
 
-  ConvertLocalIdsToTSAIds (sep);
+  ConvertLocalIdsToTSAIds (sep, NULL);
 
   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 }
 
 
+typedef struct createtsaidswithsuffixform {
+  FORM_MESSAGE_BLOCK
+  TexT suffix;
+  DialoG text_portion;
+} CreateTsaIDsWithSuffixFormData, PNTR CreateTsaIDsWithSuffixFormPtr;
+
+static void DoCreateTSAIDsFromLocalIDsWithSuffix (ButtoN b)
+{
+  CreateTsaIDsWithSuffixFormPtr t;
+  SeqEntryPtr                   sep;
+  CharPtr                       suffix = NULL;
+
+  t = (CreateTsaIDsWithSuffixFormPtr) GetObjectExtra (b);
+  if (b == NULL) {
+    return;
+  }
+
+  sep = GetTopSeqEntryForEntityID (t->input_entityID);
+  if (sep == NULL) return;
+
+  if (!TextHasNoText (t->suffix)) {
+    suffix = SaveStringFromText (t->suffix);
+  }
+  ConvertLocalIdsToTSAIds (sep, suffix);
+  suffix = MemFree (suffix);
+
+  ObjMgrSetDirtyFlag (t->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, t->input_entityID, 0, 0);
+  Remove (t->form);
+  Update();
+}
+
+static void CreateTSAIDsFromLocalIDsWithSuffix (IteM i)
+{
+  BaseFormPtr  bfp;
+  CreateTsaIDsWithSuffixFormPtr t;
+  WindoW       w;
+  GrouP        h, g, c;
+  ButtoN       b;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  t = (CreateTsaIDsWithSuffixFormPtr) MemNew (sizeof (CreateTsaIDsWithSuffixFormData));
+
+  w = FixedWindow (-50, -33, -10, -10, "Create TSA IDs With Suffix", StdCloseWindowProc);
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+  t->form = (ForM) w;
+  t->input_entityID = bfp->input_entityID;
+
+  g = HiddenGroup (h, 2, 0, NULL);
+  StaticPrompt (g, "Suffix", 0, dialogTextHeight, programFont, 'c');
+  t->suffix = DialogText (g, "", 14, NULL);
+
+  c = HiddenGroup (h, 2, 0, NULL);
+  b = DefaultButton (c, "Accept", DoCreateTSAIDsFromLocalIDsWithSuffix);
+  SetObjectExtra (b, t, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
+
+  Show (w);
+
+}
+
+
+
 static void CreateTSAIDsFromTable (IteM i)
 {
   BaseFormPtr  bfp;
@@ -399,7 +470,7 @@ static void CreateTSAIDsFromTable (IteM i)
   if (err_list != NULL) {
     lip = OpenLog ("Table Problems");
     for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-      fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+      fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     }
     lip->data_in_log = TRUE;
     CloseLog (lip);
@@ -455,6 +526,127 @@ static void CreateTSAIDsFromTable (IteM i)
 }
 
 
+typedef struct tsaidfromdefline {
+  TextPortionPtr text_portion;
+  CharPtr suffix;
+} TSAIdFromDeflineData, PNTR TSAIdFromDeflinePtr;
+
+
+static void CreateTSAIDsFromDeflineCallback (BioseqPtr bsp, Pointer data)
+{
+  TSAIdFromDeflinePtr t;
+  Int4         gpid = 0;
+  SeqDescrPtr  sdp;
+  SeqMgrDescContext dcontext;
+  CharPtr      str;
+  SeqIdPtr     sip_new;
+  DbtagPtr     dbtag;
+  CharPtr      id_fmt = "gpid:%d";
+
+  if (bsp == NULL || ISA_aa (bsp->mol) 
+      || (t = (TSAIdFromDeflinePtr) data) == NULL
+      || (gpid = GetGenomeProjectID(bsp)) <= 0) {
+    return;
+  }
+
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_title, &dcontext);
+  if (sdp == NULL 
+      || (str = GetTextPortionFromString ((CharPtr) sdp->data.ptrvalue, t->text_portion)) == NULL) {
+    return;
+  }
+
+  dbtag = DbtagNew ();
+  dbtag->db = MemNew (sizeof (Char) * (StringLen (id_fmt) + 15));
+  sprintf (dbtag->db, id_fmt, gpid);
+  dbtag->tag = ObjectIdNew ();
+  if (t->suffix == NULL) {
+    dbtag->tag->str = str;
+    str = NULL;
+  } else {
+    dbtag->tag->str = (CharPtr) MemNew (sizeof (Char) * (StringLen (str) + StringLen (t->suffix) + 2));
+    sprintf (dbtag->tag->str, "%s.%s", str, t->suffix);
+    str = MemFree (str);
+  }
+  sip_new = ValNodeNew (NULL);
+  sip_new->choice = SEQID_GENERAL;
+  sip_new->data.ptrvalue = dbtag;
+  sip_new->next = bsp->id;
+  bsp->id = sip_new;
+  SeqMgrReplaceInBioseqIndex (bsp);
+}
+
+
+static void DoCreateTSAIDsFromDefline (ButtoN b)
+{
+  CreateTsaIDsWithSuffixFormPtr t;
+  SeqEntryPtr                   sep;
+  TSAIdFromDeflineData          data;
+
+  t = (CreateTsaIDsWithSuffixFormPtr) GetObjectExtra (b);
+  if (b == NULL) {
+    return;
+  }
+
+  MemSet (&data, 0, sizeof (TSAIdFromDeflineData));
+
+  sep = GetTopSeqEntryForEntityID (t->input_entityID);
+  if (sep == NULL) return;
+
+  if (!TextHasNoText (t->suffix)) {
+    data.suffix = SaveStringFromText (t->suffix);
+  }
+  data.text_portion = DialogToPointer (t->text_portion);
+  VisitBioseqsInSep (sep, &data, CreateTSAIDsFromDeflineCallback);
+  data.suffix = MemFree (data.suffix);
+  data.text_portion = TextPortionFree (data.text_portion);
+
+  ObjMgrSetDirtyFlag (t->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, t->input_entityID, 0, 0);
+  Remove (t->form);
+  Update();
+}
+
+
+static void CreateTSAIDsFromDefline (IteM i)
+{
+  BaseFormPtr  bfp;
+  CreateTsaIDsWithSuffixFormPtr t;
+  WindoW       w;
+  GrouP        h, g, c;
+  ButtoN       b;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  t = (CreateTsaIDsWithSuffixFormPtr) MemNew (sizeof (CreateTsaIDsWithSuffixFormData));
+
+  w = FixedWindow (-50, -33, -10, -10, "Create TSA IDs from Defline", StdCloseWindowProc);
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+  t->form = (ForM) w;
+  t->input_entityID = bfp->input_entityID;
+
+  t->text_portion = TextPortionDialog (h, TRUE, NULL, NULL);
+
+  g = HiddenGroup (h, 2, 0, NULL);
+  StaticPrompt (g, "Suffix", 0, dialogTextHeight, programFont, 'c');
+  t->suffix = DialogText (g, "", 14, NULL);
+
+  c = HiddenGroup (h, 2, 0, NULL);
+  b = DefaultButton (c, "Accept", DoCreateTSAIDsFromDefline);
+  SetObjectExtra (b, t, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+  AlignObjects (ALIGN_CENTER, (HANDLE) t->text_portion, (HANDLE) g, (HANDLE) c, NULL);
+
+  Show (w);
+
+}
+
+
 static void CreateBarcodeIDsFromLocalIDs (IteM i)
 {
   BaseFormPtr  bfp;
@@ -476,29 +668,6 @@ static void CreateBarcodeIDsFromLocalIDs (IteM i)
 }
 
 
-static void AddmRNASequenceCallback (SeqDescrPtr sdp, Pointer data)
-{
-  Int4 len, len_add;
-  CharPtr add = ", mRNA sequence.", tmp, title;
-
-  if (sdp != NULL && sdp->choice == Seq_descr_title) {
-    title = (CharPtr) sdp->data.ptrvalue;
-    len_add = StringLen (add);
-    len = StringLen (title);
-    if (len < len_add || StringCmp (title + (len - len_add), add) != 0) {
-      /* remove trailing period if present */
-      if (title[len - 1] == '.') {
-        title[len - 1] = 0;
-      }
-      tmp = (CharPtr) MemNew (sizeof (Char) * (len + len_add + 1));
-      sprintf (tmp, "%s%s", title, add);
-      sdp->data.ptrvalue = MemFree (sdp->data.ptrvalue);
-      sdp->data.ptrvalue = tmp;
-    }
-  }
-}
-
-
 static void AddmRNASequenceToDeflines (IteM i)
 {
   BaseFormPtr  bfp;
@@ -513,8 +682,12 @@ static void AddmRNASequenceToDeflines (IteM i)
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
 
-  AutoDefEntityIDNoOptions (bfp->input_entityID, TRUE);
-  VisitDescriptorsInSep (sep, NULL, AddmRNASequenceCallback);
+  WatchCursor ();
+  Update ();
+
+  AutoDefIdEx (bfp->input_entityID, DEFLINE_SEQUENCE);
+  ArrowCursor();
+  Update();
 
   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
@@ -821,63 +994,15 @@ static void ParseCommentIntoStructuredObject (IteM i)
   Update ();
 }
 
-static void DoHivOrFluTag (SeqDescrPtr sdp, Pointer userdata, CharPtr prefix, CharPtr suffix)
+static void DoStructuredTag (SeqDescrPtr sdp, Pointer userdata)
 
 {
-  UserFieldPtr   curr;
-  Boolean        hasPrefix = FALSE;
-  Boolean        hasSuffix = FALSE;
-  ObjectIdPtr    oip;
-  UserObjectPtr  uop;
-
-  if (sdp == NULL || sdp->choice != Seq_descr_user) return;
-  uop = (UserObjectPtr) sdp->data.ptrvalue;
-  if (uop == NULL) return;
-  oip = uop->type;
-  if (oip == NULL || StringICmp (oip->str, "StructuredComment") != 0) return;
-
-  for (curr = uop->data; curr != NULL; curr = curr->next) {
-    oip = curr->label;
-    if (oip != NULL && StringICmp (oip->str, "StructuredCommentPrefix") == 0) {
-      hasPrefix = TRUE;
-      if (curr->choice == 1) {
-        MemFree (curr->data.ptrvalue);
-        curr->data.ptrvalue = (Pointer) StringSave (prefix);
-      }
+  if (sdp->choice == Seq_descr_user) {
+    AddDatabaseNameToStructuredComment ((UserObjectPtr) sdp->data.ptrvalue, (CharPtr)userdata);
     }
-  }
-  if (! hasPrefix) {
-    AddItemStructuredCommentUserObject (uop, "StructuredCommentPrefix", prefix);
-  }
-
-  for (curr = uop->data; curr != NULL; curr = curr->next) {
-    oip = curr->label;
-    if (oip != NULL && StringICmp (oip->str, "StructuredCommentSuffix") == 0) {
-      hasSuffix = TRUE;
-      if (curr->choice == 1) {
-        MemFree (curr->data.ptrvalue);
-        curr->data.ptrvalue = (Pointer) StringSave (suffix);
-      }
-    }
-  }
-  if (! hasSuffix) {
-    AddItemStructuredCommentUserObject (uop, "StructuredCommentSuffix", suffix);
-  }
-}
-
-static void DoHivTag (SeqDescrPtr sdp, Pointer userdata)
-
-{
-  DoHivOrFluTag (sdp, userdata, "##HIVData-START##", "##HIVData-END##");
 }
 
-static void DoFluTag (SeqDescrPtr sdp, Pointer userdata)
-
-{
-  DoHivOrFluTag (sdp, userdata, "##FluData-START##", "##FluData-END##");
-}
-
-static void AddStructuredCommentHivTag (IteM i)
+static void AddStructuredCommentTag (IteM i, CharPtr dbname)
 
 {
   BaseFormPtr  bfp;
@@ -892,18 +1017,55 @@ static void AddStructuredCommentHivTag (IteM i)
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
 
-  VisitDescriptorsInSep (sep, NULL, DoHivTag);
+  VisitDescriptorsInSep (sep, dbname, DoStructuredTag);
 
   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
   Update ();
 }
 
+static void AddStructuredCommentHivTag (IteM i)
+{
+  AddStructuredCommentTag (i, "HIV");
+}
+
+
 static void AddStructuredCommentFluTag (IteM i)
 
 {
+  AddStructuredCommentTag (i, "Flu");
+}
+
+
+static void AddStructuredCommentMIGSTag (IteM i)
+
+{
+  AddStructuredCommentTag (i, "MIGS");
+}
+
+
+static void AddStructuredCommentMIMSTag (IteM i)
+
+{
+  AddStructuredCommentTag (i, "MIMS");
+}
+
+
+static void AddStructuredCommentMIENSTag (IteM i)
+
+{
+  AddStructuredCommentTag (i, "MIENS");
+}
+
+
+static void ExportStructuredCommentTable (IteM i)
+
+{
   BaseFormPtr  bfp;
   SeqEntryPtr  sep;
+  ValNodePtr   table;
+  Char         path [PATH_MAX];
+  FILE         *fp;
 
 #ifdef WIN_MAC
   bfp = currentFormDataPtr;
@@ -911,16 +1073,31 @@ static void AddStructuredCommentFluTag (IteM i)
   bfp = GetObjectExtra (i);
 #endif
   if (bfp == NULL) return;
+
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
-  if (sep == NULL) return;
 
-  VisitDescriptorsInSep (sep, NULL, DoFluTag);
+  table = CreateStructuredCommentTableFromSeqEntry (sep);
+
+  if (table == NULL) {
+    Message (MSG_ERROR, "No structured comments found!");
+    return;
+  }
+
+  path [0] = '\0';
+  if (path [0] != '\0' || GetOutputFileName (path, sizeof (path), NULL)) {
+    fp = FileOpen (path, "w");
+    if (!fp) {
+      Message (MSG_ERROR, "Unable to open %s", path);
+    } else {
+      WriteTabTableToFile (table, fp);
+      FileClose (fp);
+    }
+  }
+  table = FreeTabTable(table);
 
-  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
-  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
-  Update ();
 }
 
+
 static void ConvertBadInfProc (SeqFeatPtr sfp, Pointer userdata)
 
 {
@@ -6540,6 +6717,7 @@ typedef struct featuretocdsform
   ButtoN  accept_btn;
   ButtoN  fuse_multiple_btn;
   ButtoN  include_utr_btn;
+  DialoG  constraint_dlg;
   
   Int4       featdef_choice;
   ValNodePtr gene_field_list;
@@ -6552,6 +6730,7 @@ typedef struct featuretocdsform
   Boolean    include_utr;
   SeqEntryPtr sep;
   LogInfoData lid;
+  ConstraintChoiceSetPtr constraint;
   
 } FeatureToCDSFormData, PNTR FeatureToCDSFormPtr;
 
@@ -7050,7 +7229,7 @@ static void FeatureToCDSBioseqCheckCallback (BioseqPtr bsp, Pointer userdata)
   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &feature_context);
   while (sfp != NULL)
   {
-    if (sfp->idx.subtype == fp->featdef_choice)
+    if (sfp->idx.subtype == fp->featdef_choice && DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, fp->constraint))
     {
       if (fp->makemRNA) {
         cds = SeqMgrGetOverlappingmRNA (sfp->location, &cds_context);
@@ -7123,7 +7302,7 @@ static void FeatureToCDSBioseqActCallback (BioseqPtr bsp, Pointer userdata)
   sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &feature_context);
   while (sfp != NULL)
   {
-    if (sfp->idx.subtype == fp->featdef_choice)
+    if (sfp->idx.subtype == fp->featdef_choice && DoesObjectMatchConstraintChoiceSet (OBJ_SEQFEAT, sfp, fp->constraint))
     {
       if (fp->makemRNA) {
         cds = SeqMgrGetOverlappingmRNA (sfp->location, &cds_context);
@@ -7252,6 +7431,7 @@ static void FeatureToCDSAccept (ButtoN b)
     fp->include_utr = GetStatus (fp->include_utr_btn);
   }
 
+  fp->constraint = DialogToPointer (fp->constraint_dlg);
   VisitBioseqsInSep (fp->sep, (Pointer) fp, FeatureToCDSBioseqCheckCallback);
 
   if (ans == ANS_YES)
@@ -7259,6 +7439,7 @@ static void FeatureToCDSAccept (ButtoN b)
     fp->sep = GetTopSeqEntryForEntityID (fp->input_entityID);
     VisitBioseqsInSep (fp->sep, (Pointer) fp, FeatureToCDSBioseqActCallback);
   }
+  fp->constraint = ConstraintChoiceSetFree(fp->constraint);
   
   CloseLog (&(fp->lid));
     
@@ -7360,6 +7541,9 @@ static void FeatureToCDSormRNA (IteM i, Boolean makemRNA)
     fp->include_utr_btn = NULL;
   }
    
+  fp->constraint_dlg = ComplexConstraintDialog(h, NULL, NULL);
+  ChangeComplexConstraintFieldType (fp->constraint_dlg, FieldType_cds_gene_prot, NULL, Feature_type_gene);
+   
   c = HiddenGroup (h, 4, 0, NULL); 
   fp->accept_btn = PushButton (c, "Accept", FeatureToCDSAccept);
   SetObjectExtra (fp->accept_btn, fp, NULL);
@@ -7373,6 +7557,7 @@ static void FeatureToCDSormRNA (IteM i, Boolean makemRNA)
                               (HANDLE) fp->qual_caps_grp,
                               (HANDLE) m, 
                               (HANDLE) fp->fuse_multiple_btn, 
+                              (HANDLE) fp->constraint_dlg,
                               (HANDLE) c, 
                               (HANDLE) fp->include_utr_btn,
                               NULL);
@@ -8571,17 +8756,10 @@ static void UpdateProtEC (SeqFeatPtr sfp, Pointer userdata)
   }
 }
 
-static void UpdateECnumbers (IteM i)
-
+static void UpdateECNumbersBaseForm (BaseFormPtr bfp)
 {
-  BaseFormPtr  bfp;
   SeqEntryPtr  sep;
 
-#ifdef WIN_MAC
-  bfp = currentFormDataPtr;
-#else
-  bfp = GetObjectExtra (i);
-#endif
   if (bfp == NULL) return;
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
@@ -8593,6 +8771,20 @@ static void UpdateECnumbers (IteM i)
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 }
 
+static void UpdateECnumbers (IteM i)
+
+{
+  BaseFormPtr  bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+
+  UpdateECNumbersBaseForm (bfp);
+}
+
 
 typedef struct icrepdata {
   CharPtr  code;
@@ -9091,7 +9283,7 @@ ConvertOneCDSToMiscFeat
 
 extern void ConvertCDSToMiscFeat (SeqFeatPtr sfp, Pointer userdata)
 {
-  CDStoMiscFeatPtr     cmfp;
+  CDStoMiscFeatPtr     cmfp = NULL;
   Boolean              viral = FALSE;
   Boolean              must_have_stops = TRUE;
 
@@ -12166,70 +12358,6 @@ static void CheckForExistingMolInfo (SeqEntryPtr sep, MolInfoCheckPtr micp)
 }
 
 
-static Int4 
-ThreeOptionsDlg
-(CharPtr title_txt,
- CharPtr explain_txt,
- CharPtr opt1,
- CharPtr opt2,
- CharPtr opt3)
-{
-  WindoW w;
-  GrouP  h, c;
-  ButtoN b;
-  GrouP  p;
-  ModalAcceptCancelData acd;
-  
-  
-  w = MovableModalWindow (-20, -13, -10, -10, title_txt, NULL);
-  h = HiddenGroup(w, -1, 0, NULL);
-  SetGroupSpacing (h, 10, 10);
-
-  p = MultiLinePrompt (h, explain_txt, 300, programFont);
-    
-  c = HiddenGroup (h, 3, 0, NULL);
-  b = PushButton (c, opt1, ModalAcceptButton);
-  SetObjectExtra (b, &acd, NULL);
-  b = PushButton (c, opt2, ModalCancelButton);
-  SetObjectExtra (b, &acd, NULL);
-  
-  if (!StringHasNoText (opt3)) {
-    b = PushButton (c, opt3, ModalThirdOptionButton);
-    SetObjectExtra (b, &acd, NULL);
-  }
-  
-  AlignObjects (ALIGN_CENTER, (HANDLE) p,
-                              (HANDLE) c, 
-                              NULL);
-
-  Show (w);
-  Select (w);
-  
-  acd.cancelled = FALSE;
-  acd.third_option = FALSE;
-  acd.accepted = FALSE;
-  while (!acd.accepted && ! acd.cancelled && !acd.third_option)
-  {
-    ProcessExternalEvent ();
-    Update ();
-  }
-  ProcessAnEvent ();
-  Remove (w);
-  
-  if (acd.accepted)
-  {
-    return 1;
-  }
-  else if (acd.cancelled)
-  {
-    return 2;
-  }
-  else
-  {
-    return 3;
-  }
-}
-
 static void DoProcessApplyMolInfo (ButtoN b)
 
 {
@@ -12592,6 +12720,7 @@ static void GenePseudoOff (SeqFeatPtr sfp, Pointer userdata)
   grp = (GeneRefPtr) sfp->data.value.ptrvalue;
   if (grp == NULL) return;
   grp->pseudo = FALSE;
+  sfp->pseudo = FALSE;
 }
 
 typedef struct genepseudodata 
@@ -12964,7 +13093,7 @@ static ForM CreateBioseqSetEditForm (BioseqSetPtr bssp, Uint2 entityID)
   BioseqSetFormPtr  bsfp;
   GrouP             c;
   GrouP             h;
-  WindoW            w;
+  WindoW            w = NULL;
 
   bsfp = (BioseqSetFormPtr) MemNew (sizeof (BioseqSetForm));
   if (bsfp != NULL) {
@@ -12995,6 +13124,74 @@ static ForM CreateBioseqSetEditForm (BioseqSetPtr bssp, Uint2 entityID)
   return (ForM) w;
 }
 
+
+static void DoApplySetType (ButtoN b)
+{
+  BioseqSetFormPtr  bsfp;
+  BioseqSetPtr      bssp;
+  UIEnum            val;
+  SeqEntryPtr       sep;
+
+  bsfp = (BioseqSetFormPtr) GetObjectExtra (b);
+  if (bsfp != NULL) {
+    Hide (bsfp->form);
+    bssp = bsfp->bssp;
+    if (bssp == NULL && bsfp->entityID == 0) {
+      bssp = BioseqSetNew ();
+    }
+    if (bssp != NULL) {
+      GetEnumPopup (bsfp->class_control, bioseqset_class_alist, &val);
+      sep = SeqMgrGetSeqEntryForData (bssp);
+      ApplySetTypeToSeqEntry (sep, val, TRUE);
+
+    }
+    Remove (bsfp->form);
+    ObjMgrSetDirtyFlag (bsfp->entityID, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, bsfp->entityID, 0, 0);
+  }
+}
+
+
+NLM_EXTERN void ApplySetTypeToInnerSets (BioseqSetPtr bssp, Uint2 entityID)
+{
+  ButtoN            b;
+  BioseqSetFormPtr  bsfp;
+  GrouP             c;
+  GrouP             h;
+  WindoW            w = NULL;
+
+  bsfp = (BioseqSetFormPtr) MemNew (sizeof (BioseqSetForm));
+  if (bsfp != NULL) {
+    w = FixedWindow (-50, -33, -10, -10, "Apply Set Type", NULL);
+    SetObjectExtra (w, bsfp, StdCleanupFormProc);
+    bsfp->form = (ForM) w;
+    bsfp->formmessage = CreateBioseqSetMessageProc;
+
+    bsfp->bssp = bssp;
+    bsfp->entityID = entityID;
+
+    h = HiddenGroup (w, -2, 0, NULL);
+    StaticPrompt (h, "Class", 0, popupMenuHeight, programFont, 'l');
+    bsfp->class_control = PopupList (h, TRUE, NULL);
+    SetObjectExtra (bsfp->class_control, bsfp, NULL);
+    InitEnumPopup (bsfp->class_control, bioseqset_class_alist, NULL);
+    if (bssp != NULL) {
+      SetEnumPopup (bsfp->class_control, bioseqset_class_alist, (UIEnum) bssp->_class);
+    }
+
+    c = HiddenGroup (w, 2, 0, NULL);
+    b = DefaultButton (c, "Accept", DoApplySetType);
+    SetObjectExtra (b, bsfp, NULL);
+    PushButton (c, "Cancel", StdCancelButtonProc);
+    AlignObjects (ALIGN_CENTER, (HANDLE) h, (HANDLE) c, NULL);
+    RealizeWindow (w);
+    Show (w);
+    Select (w);
+  }
+}
+
+
+
 extern Int2 LIBCALLBACK BioseqSetEditFunc (Pointer data)
 
 {
@@ -13195,6 +13392,7 @@ static CharPtr StartsWithQualOrFeat (CharPtr str)
     if (space_before_qual == 5
         && qual_len + space_after_feat == 16
         && (isdigit(str[space_before_qual + qual_len + space_after_feat])
+        || str[space_before_qual + qual_len + space_after_feat] == '<'
         || StringNCmp (str + space_before_qual + qual_len + space_after_feat, "complement", 10) == 0)) {
       qual_name = (CharPtr) MemNew ((qual_len + 1) * sizeof(Char));
       StringNCpy (qual_name, str + space_before_qual, qual_len);
@@ -13256,10 +13454,14 @@ static void CaptureFFLineEx (
       } else if (itemtype == OBJ_SEQFEAT) {
         sfp = SeqMgrGetDesiredFeature (entityID, NULL, itemID, 0, NULL, &fcontext);
         if (sfp != NULL) {
+          if (sfp->idx.subtype == FEATDEF_gap) {
+            /* can't add gap features, they are temporary */
+          } else {
           item_list = ValNodeNew (NULL);
           item_list->choice = OBJ_SEQFEAT;
           item_list->data.ptrvalue = sfp;
         }
+        }
       } else if (itemtype == OBJ_SEQDESC) {
         sdp = SeqMgrGetDesiredDescriptor (entityID, NULL, itemID, 0, NULL, &dcontext);
         item_list = ValNodeNew (NULL);
@@ -13333,7 +13535,9 @@ static void CaptureFFLine (
   BlockType blocktype,
   Uint2 entityID,
   Uint2 itemtype,
-  Uint4 itemID
+  Uint4 itemID,
+  Int4 left,
+  Int4 right
 )
 
 {
@@ -13346,7 +13550,9 @@ static void CaptureFFLineNoSequence (
   BlockType blocktype,
   Uint2 entityID,
   Uint2 itemtype,
-  Uint4 itemID
+  Uint4 itemID,
+  Int4 left,
+  Int4 right
 )
 
 {
@@ -13359,7 +13565,9 @@ static void CaptureFFLineNoSequenceByQual (
   BlockType blocktype,
   Uint2 entityID,
   Uint2 itemtype,
-  Uint4 itemID
+  Uint4 itemID,
+  Int4 left,
+  Int4 right
 )
 
 {
@@ -13372,7 +13580,9 @@ static void CaptureFFLineByQual (
   BlockType blocktype,
   Uint2 entityID,
   Uint2 itemtype,
-  Uint4 itemID
+  Uint4 itemID,
+  Int4 left,
+  Int4 right
 )
 
 {
@@ -13566,11 +13776,9 @@ static CharPtr ReSUCCallback (Pointer userdata)
   return NULL;
 }
 
-static void SUCCommonProcEx (IteM i, Boolean reverse, Boolean byblock, 
-                             Boolean showsequence, ButtoN b, Boolean use_new_suc)
-
+static void SUCBaseForm (BaseFormPtr bfp, Boolean reverse, Boolean byblock, 
+                             Boolean showsequence, Boolean use_new_suc)
 {
-  BaseFormPtr  bfp;
   FILE         *fp;
   ValNodePtr   head = NULL;
   Char         path [PATH_MAX];
@@ -13580,15 +13788,6 @@ static void SUCCommonProcEx (IteM i, Boolean reverse, Boolean byblock,
   ReSUCOptionsPtr rp = NULL;
   ClickableItemPtr cip;
 
-  if (b != NULL) {
-    bfp = GetObjectExtra (b);
-  } else {
-#ifdef WIN_MAC
-    bfp = currentFormDataPtr;
-#else
-    bfp = GetObjectExtra (i);
-#endif
-  }
   if (bfp == NULL) return;
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
@@ -13634,6 +13833,25 @@ static void SUCCommonProcEx (IteM i, Boolean reverse, Boolean byblock,
   Update ();
 }
 
+static void SUCCommonProcEx (IteM i, Boolean reverse, Boolean byblock, 
+                             Boolean showsequence, ButtoN b, Boolean use_new_suc)
+
+{
+  BaseFormPtr  bfp;
+
+  if (b != NULL) {
+    bfp = GetObjectExtra (b);
+  } else {
+#ifdef WIN_MAC
+    bfp = currentFormDataPtr;
+#else
+    bfp = GetObjectExtra (i);
+#endif
+  }
+
+  SUCBaseForm (bfp, reverse, byblock, showsequence, use_new_suc);
+}
+
 static void SUCCommonProc (IteM i, Boolean reverse, Boolean byblock, 
                            Boolean showsequence, ButtoN b)
 {
@@ -14556,6 +14774,78 @@ static void RemovePrtLocalIDs (IteM i)
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 }
 
+
+static Boolean IsTSAId (SeqIdPtr sip)
+{
+  DbtagPtr dbtag;
+
+  if (sip != NULL && sip->choice == SEQID_GENERAL
+      && (dbtag = (DbtagPtr) sip->data.ptrvalue) != NULL
+      && StringNCmp (dbtag->db, "gpid:", 5) == 0) 
+  {
+    return TRUE;
+  }
+  else
+  {
+    return FALSE;
+  }
+}
+
+
+static void RemoveTSAIdsProc (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+  BioseqPtr     bsp;
+  SeqIdPtr      nextsip;
+  Pointer PNTR  prevsip;
+  Boolean       replaced;
+  SeqIdPtr      sip;
+
+  if (sep == NULL) return;
+  if (! IS_Bioseq (sep)) return;
+  bsp = (BioseqPtr) sep->data.ptrvalue;
+  if (bsp == NULL) return;
+  sip = bsp->id;
+  prevsip = (Pointer PNTR) &(bsp->id);
+  replaced = FALSE;
+  while (sip != NULL) {
+    nextsip = sip->next;
+    if (IsTSAId(sip)) {
+      (*prevsip) = sip->next;
+      sip->next = NULL;
+      SeqIdFree (sip);
+      replaced = TRUE;
+    } else {
+      prevsip = (Pointer PNTR) &(sip->next);
+    }
+    sip = nextsip;
+  }
+  if (replaced) {
+    SeqMgrReplaceInBioseqIndex (bsp);
+  }
+}
+
+
+static void RemoveTSAIdsFromBioseqs (IteM i)
+
+{
+  BaseFormPtr  bfp;
+  SeqEntryPtr  sep;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) return;
+  SeqEntryExplore (sep, NULL, RemoveTSAIdsProc);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+}
+
+
 static void RemoveLocusProc (BioseqPtr bsp, Pointer userdata)
 
 {
@@ -15477,9 +15767,9 @@ static void DeleteDeltaEndGaps (IteM i)
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 }
 
-static void AtccStrainToCultureCollection (IteM i)
+
+static void AtccStrainToCultureCollectionBaseForm (BaseFormPtr bfp)
 {
-  BaseFormPtr  bfp;
   SeqEntryPtr  sep;
   ValNodePtr   object_list, vnp;
   AECRSamplePtr       sample;
@@ -15489,11 +15779,6 @@ static void AtccStrainToCultureCollection (IteM i)
   AECRActionPtr       action;
   CharPtr             str1, str2, cp, new_str;
 
-#ifdef WIN_MAC
-  bfp = currentFormDataPtr;
-#else
-  bfp = GetObjectExtra (i);
-#endif
   if (bfp == NULL) return;
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
@@ -15508,9 +15793,9 @@ static void AtccStrainToCultureCollection (IteM i)
   parse->fields->data.ptrvalue = pair;
 
   parse->portion = TextPortionNew ();
-  parse->portion->left_text = StringSave ("ATCC ");
+  parse->portion->left_marker = MakeTextTextMarker ("ATCC ");
   parse->portion->include_left = FALSE;
-  parse->portion->right_text = StringSave ("");
+  parse->portion->right_marker = NULL;
   parse->portion->include_right = FALSE;
   parse->portion->inside = TRUE;
   parse->portion->case_sensitive = FALSE;
@@ -15567,6 +15852,20 @@ static void AtccStrainToCultureCollection (IteM i)
 }
 
 
+static void AtccStrainToCultureCollection (IteM i)
+{
+  BaseFormPtr  bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+
+  AtccStrainToCultureCollectionBaseForm (bfp);
+}
+
+
 typedef struct extendgeneformglobalitemdata {
   Int4		iFeatDef;
   Boolean	item_value;
@@ -17937,7 +18236,7 @@ static void ToolBtn2 (ButtoN b)
   bfp = (BaseFormPtr) GetObjectExtra (b);
   if (bfp == NULL) return;
 
-  AutoDefBaseFormCommon (bfp, FALSE, TRUE);
+  AutoDefBaseFormCommon (bfp, FALSE, TRUE, FALSE);
 }
 
 /*
@@ -18448,6 +18747,11 @@ static void RemoveInconsistentProteinTitles (IteM i)
   Update ();
 }
 
+static void ToolBtnOncallerTool (ButtoN b)
+{
+  CreateReportWindow (eReportTypeOnCaller);
+}
+
 static ButtoN SqnPushButton (GrouP prnt, CharPtr title, BtnActnProc actn, BaseFormPtr bfp)
 
 {
@@ -18464,8 +18768,8 @@ extern void BioseqViewFormToolBar (GrouP h)
 
 {
   BaseFormPtr  bfp;
-  GrouP        g, g2;
-  ButtoN       b1, b2, b3, b4, b5, b_top;
+  GrouP        g, g2, g3;
+  ButtoN       b1, b2, b3, b4, b5, b6, b_top;
 
   bfp = (BaseFormPtr) GetObjectExtra (h);
   if (bfp == NULL) return;
@@ -18505,8 +18809,10 @@ extern void BioseqViewFormToolBar (GrouP h)
     b5 = SqnPushButton (g2, "Edit Pubs", ToolBtn13, bfp);
     SqnPushButton (g, "rem_prot_titles", ToolBtn17, bfp);
     SqnPushButton (g, "Validate", ToolBtn14, bfp);
-    SqnPushButton (g, "Desktop", ToolBtn15, bfp);
-    AlignObjects (ALIGN_RIGHT, (HANDLE) b1, (HANDLE) b2, (HANDLE) b3, (HANDLE) b4, (HANDLE) b5, (HANDLE) b_top, NULL);
+    g3 = HiddenGroup (g, 2, 0, NULL);
+    SqnPushButton (g3, "Desktop", ToolBtn15, bfp);
+    b6 = SqnPushButton (g3, "On-Caller Tool", ToolBtnOncallerTool, bfp);
+    AlignObjects (ALIGN_RIGHT, (HANDLE) b1, (HANDLE) b2, (HANDLE) b3, (HANDLE) b4, (HANDLE) b5, (HANDLE) b6, (HANDLE) b_top, NULL);
 
   }
   else
@@ -18538,7 +18844,247 @@ static void MakeToolBarWindow (IteM i)
 
 {
   BaseFormPtr  bfp;
+  SeqViewProcsPtr svpp;
+  ForM         f;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  svpp = (SeqViewProcsPtr) GetAppProperty ("SeqDisplayForm");
+  if (svpp != NULL) {
+    svpp->createToolBar = BioseqViewFormToolBar;
+  }
+
+  f = ReplaceToolFormForBioseqView (bfp, BioseqViewFormToolBar);
+  Show (f);
+  Select (f);
+}
+
+
+static void WGSBtnRemoveGenomeProjectIds (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  RemoveGenomeProjectIdsBaseForm (bfp);
+}
+
+
+static void WGSBtnAtccStrainToCultureCollection (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  AtccStrainToCultureCollectionBaseForm (bfp);
+}
+
+
+static void WGSBtnAddModToOrg (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  AddModToOrgBaseForm (bfp);
+}
+
+static void WGSBtnUpdateECNumbers (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  UpdateECNumbersBaseForm (bfp);
+}
+
+static void WGSBtnMegaReport (ButtoN b)
+{
+  CreateReportWindow (eReportTypeMegaReport);
+}
+
+static void WGSBtnOriginalSUC (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  SUCBaseForm (bfp, FALSE, TRUE, TRUE, FALSE);
+}
+
+static void WGSBtnClickableSUC (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  SUCBaseForm (bfp, FALSE, TRUE, FALSE, TRUE);
+}
+
+static void WGSBtnPT_Cleanup (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  SeqEntryPtr  sep;
+
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+  if (bfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) return;
+
+  InstantiateProteinTitles (bfp->input_entityID, NULL);
+
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+  Update ();
+}
+
+static void WBSBtnLaunchMacroEditor (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  LaunchMacroEditorBaseForm (bfp);
+}
+
+static void WGSBtnChangeTarget (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  ChangeTargetBaseForm (bfp);
+}
+
+static void WBSBtnRetranslateCodingRegions (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+
+  RetranslateCdRegionsEx (bfp->input_entityID, TRUE, TRUE);
+}
+
+static void WGSBtnAddComment (ButtoN b)
+{
+  BaseFormPtr  bfp;
+  ObjMgrPtr      omp;
+  ObjMgrTypePtr  omtp = NULL;
+  ObjMgrProcPtr  ompp;
+
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+  if (bfp == NULL) {
+    return;
+  }
+
+  omp = ObjMgrGet ();
+  if (omp == NULL) return;
+  while ((omtp = ObjMgrTypeFindNext (omp, omtp)) != NULL) {
+    if (omtp->datatype == OBJ_SEQDESC) {
+      ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, omtp->datatype, 0, NULL);
+      if (ompp != NULL) {
+        ompp = NULL;
+        while ((ompp = ObjMgrProcFindNext (omp, OMPROC_EDIT, omtp->datatype, 0, ompp)) != NULL) {
+          if (ompp->subinputtype == Seq_descr_comment) {
+            NewDescriptorMenuFunc (ompp, bfp, Seq_descr_comment);
+            return;
+          }
+        }
+      }
+    }
+  }
+}
+
+
+static void RemoveAllFeaturesCallback (SeqFeatPtr sfp, Pointer data)
+{
+  BioseqPtr bsp;
+
+  if (sfp != NULL) {
+    sfp->idx.deleteme = TRUE;
+    if (sfp->product != NULL) {
+      bsp = BioseqFindFromSeqLoc (sfp->product);
+      if (bsp != NULL) {
+        bsp->idx.deleteme = TRUE;
+      }
+    }
+  }
+}
+
+
+static void WGSBtnRemoveAllFeatures (ButtoN b)
+{
+  BaseFormPtr bfp;
+  SeqEntryPtr sep;
+
+  bfp = (BaseFormPtr) GetObjectExtra (b);
+  if (bfp == NULL) {
+    return;
+  }
+
+  if (Message (MSG_OKC, "Are you sure?  This will remove all features, all protein sequences, and all mRNA product sequences.") != ANS_OK) {
+    return;
+  }
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  VisitFeaturesInSep (sep, NULL, RemoveAllFeaturesCallback);
+
+  DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
+  RemoveOrphanProteins (bfp->input_entityID, sep);
+  RenormalizeNucProtSets (sep, TRUE);   	
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+  Update ();
+}
+
+extern void BioseqViewFormWGSToolBar (GrouP h)
+
+{
+  BaseFormPtr  bfp;
+  GrouP        g, g2, g3;
+  ButtoN       b1, b2, b_top;
+
+  bfp = (BaseFormPtr) GetObjectExtra (h);
+  if (bfp == NULL) return;
+  g = HiddenGroup (h, 1, 0, NULL);
+
+  b_top = SqnPushButton (g, "Remove GPID", WGSBtnRemoveGenomeProjectIds, bfp);
+  SqnPushButton (g, "Parse ATCC Strain", WGSBtnAtccStrainToCultureCollection, bfp);
+  SqnPushButton (g, "Append to Organism", WGSBtnAddModToOrg, bfp);
+  if (useTaxon) {
+    SqnPushButton (g, "Tax_Fix/Clean_Up", ToolBtn3, bfp);
+  }
+  SqnPushButton (g, "EC Number Cleanup", WGSBtnUpdateECNumbers, bfp);
+  SqnPushButton (g, "Add Comment", WGSBtnAddComment, bfp);
+
+  g3 = HiddenGroup (g, 2, 0, NULL);
+  SqnPushButton (g3, "SUC", WGSBtnOriginalSUC, bfp);
+  b2 = SqnPushButton (g3, "cSUC", WGSBtnClickableSUC, bfp);
+
+  SqnPushButton (g, "Macro Editor", WBSBtnLaunchMacroEditor, bfp);
+  SqnPushButton (g, "Retranslate CDS", WBSBtnRetranslateCodingRegions, bfp);
+  SqnPushButton (g, "Remove DefLines", RemoveDefLinesToolBtn, bfp);
+  SqnPushButton (g, "Trim Ns", TrimNsFromNucsToolBtn, bfp);
+  g2 = HiddenGroup (g, 2, 0, NULL);
+  SqnPushButton (g2, "Find ASN.1", FindStringProcToolBtn, bfp);
+  b1 = SqnPushButton (g2, "Find FF", FindFlatfileProcToolBtn, bfp);
+  AlignObjects (ALIGN_RIGHT, (HANDLE) b_top, (HANDLE) b1, (HANDLE) b2, NULL);
+
+  SqnPushButton (g, "Select Target", WGSBtnChangeTarget, bfp);
+  SqnPushButton (g, "Remove All Features", WGSBtnRemoveAllFeatures, bfp);
+  SqnPushButton (g, "Group Explode", GroupExplodeToolBtn, bfp);
+  SqnPushButton (g, "cit-sub-upd", ToolBtn16, bfp);
+  SqnPushButton (g, "PT_Cleanup", WGSBtnPT_Cleanup, bfp);
+  SqnPushButton (g, "rem_prot_titles", ToolBtn17, bfp);
+  SqnPushButton (g, "MegaReport", WGSBtnMegaReport, bfp);
+  SqnPushButton (g, "Validate", ToolBtn14, bfp);
+  SqnPushButton (g, "Desktop", ToolBtn15, bfp);
+
+}
+
+static void MakeWGSToolBar (IteM i)
+
+{
+  BaseFormPtr  bfp;
   ForM         f;
+  SeqViewProcsPtr svpp;
 
 #ifdef WIN_MAC
   bfp = currentFormDataPtr;
@@ -18546,7 +19092,11 @@ static void MakeToolBarWindow (IteM i)
   bfp = GetObjectExtra (i);
 #endif
   if (bfp == NULL) return;
-  f = MakeToolFormForBioseqView (bfp, BioseqViewFormToolBar);
+  svpp = (SeqViewProcsPtr) GetAppProperty ("SeqDisplayForm");
+  if (svpp != NULL) {
+    svpp->createToolBar = BioseqViewFormWGSToolBar;
+  }
+  f = ReplaceToolFormForBioseqView (bfp, BioseqViewFormWGSToolBar);
   Show (f);
   Select (f);
 }
@@ -20157,41 +20707,6 @@ static void ReverseNameOrderInAuthor (AuthorPtr pAuthor)
 
 }
 
-extern void 
-FixCapitalizationInTitle 
-(CharPtr PNTR pTitle,
- Boolean      first_is_upper,
- ValNodePtr   org_names)
-{
-  if (pTitle == NULL) return;
-  ResetCapitalization (first_is_upper, *pTitle);
-  FixAbbreviationsInElement (pTitle);
-  FixOrgNamesInString (*pTitle, org_names);
-}
-
-
-static void FixCapitalizationInAuthor (AuthorPtr pAuthor)
-{
-  NameStdPtr pNameStandard;
-  CharPtr    cp;
-  
-  if (pAuthor == NULL)
-    return;
-  else if(pAuthor->name->choice != 2)
-    return;
-  pNameStandard = pAuthor->name->data;
-  if (pNameStandard != NULL)
-  {
-    FixCapitalizationInElement (&(pNameStandard->names[0]), FALSE, FALSE, TRUE);
-    FixCapitalizationInElement (&(pNameStandard->names[1]), FALSE, FALSE, FALSE);
-    /* Set initials to all caps */
-    for (cp = pNameStandard->names[4]; cp != NULL && *cp != 0; cp++)
-    {
-      *cp = toupper (*cp);
-    }
-  }
-}
-
 static void StripSuffixFromAuthor (AuthorPtr pAuthor)
 {
   NameStdPtr pNameStandard;
@@ -20388,28 +20903,7 @@ static void FixPubdesc (PubdescPtr pdp, Pointer userdata)
     }
 
     if (iType & FIX_PUB_AFFIL_CAPITALIZATION ) {
-      affil = alp->affil;
-      if (affil == NULL) continue;
-      FixCapitalizationInElement (&(affil->affil), TRUE, TRUE, FALSE);
-      FixAffiliationShortWordsInElement (&(affil->affil));
-      FixCapitalizationInElement (&(affil->div), TRUE, TRUE, FALSE);
-      FixAffiliationShortWordsInElement (&(affil->div));
-      FixCapitalizationInElement (&(affil->city), FALSE, TRUE, FALSE);
-      FixAffiliationShortWordsInElement (&(affil->city));
-
-      /* special handling for states */
-      if (affil->sub != NULL && StringLen (affil->sub) == 2
-	      && isalpha((Int4)(affil->sub[0]))	&& isalpha((Int4)(affil->sub[1])))
-      {
-        affil->sub[0] = toupper(affil->sub[0]);
-        affil->sub[1] = toupper(affil->sub[1]);
-      } else {
-        FixCapitalizationInElement (&(affil->sub), FALSE, TRUE, FALSE);
-        FixAffiliationShortWordsInElement (&(affil->sub));
-      }
-      FixCapitalizationInElement (&(affil->country), TRUE, TRUE, FALSE);
-      FixCapitalizationInElement (&(affil->street), FALSE, TRUE, FALSE);
-      FixAffiliationShortWordsInElement (&(affil->street));
+      FixCapsInPubAffil (alp->affil);
     }
   }
 }
@@ -20464,6 +20958,7 @@ static void FixPubs (Uint2 entityID, Int4 iType, StringConstraintXPtr author_scp
   
   if(sel == NULL)
   {
+    fpd.iType |= FIX_ALL;
     VisitPubdescsInSep (sep, (Pointer)&fpd, FixPubdesc);
   }
   else
@@ -20676,12 +21171,69 @@ static void ChangeAuthorNameToConsortiumWithConstraint (IteM i)
   Show (w);  
 }
 
+
+typedef struct fixproductcap {
+  Boolean keep_cap_before_punct;
+  Boolean keep_cap_before_cap;
+  CharPtr remove_list;
+} FixProductCapData, PNTR FixProductCapPtr;
+
+
+static void FixProductCapitalizationInString (CharPtr PNTR pStr, FixProductCapPtr fc)
+{
+  CharPtr cp, cp2;
+
+  if (pStr == NULL || (cp = *pStr) == NULL || fc == NULL) {
+    return;
+  }
+
+  /* first remove punctuation */
+  if (fc->remove_list != NULL) {
+    cp2 = cp + StringSpn (cp, fc->remove_list);
+    while (*cp2 != 0) {
+      if (cp2 != cp) {
+        *cp = *cp2;
+      }
+      cp++;
+      cp2 = cp2 + 1 + StringSpn (cp2 + 1, fc->remove_list);
+    }
+    *cp = 0;
+  }
+
+  /* now adjust capitalization */
+  cp = *pStr;
+  while (*cp != 0) {
+    if (*cp == 'S' && cp > *pStr && IS_DIGIT (*(cp - 1))) {
+      /* leave S after digits capitalized */
+    } else if (*cp == 's' && cp > *pStr && IS_DIGIT (*(cp - 1))) {
+      /* capitalize S after digits */
+      *cp = 'S';
+    } else if (IS_UPPER (*cp)) {
+      if (fc->keep_cap_before_punct && ispunct (*(cp + 1))) {
+        /* ok to leave as upper */
+      } else if (fc->keep_cap_before_cap && IS_UPPER (*(cp + 1))) {
+        /* ok to leave as upper, skip upper */
+        while (IS_UPPER (*(cp + 1))) {
+          cp++;
+        }
+      } else {
+        *cp = tolower (*cp);
+      }
+    }
+    cp++;
+  }
+
+  FixAbbreviationsInElement (pStr);
+}
+
+
 static void FixProductCapitalizationCallback (SeqFeatPtr sfp, Pointer userdata)
 {
   ProtRefPtr prp;
   RnaRefPtr  rrp;
   ValNodePtr vnp;
   CharPtr    product_name;
+  RNAGenPtr  rgp;
   
   if (sfp == NULL) return;
   if (sfp->data.choice != SEQFEAT_PROT && sfp->data.choice != SEQFEAT_RNA) return;
@@ -20694,7 +21246,7 @@ static void FixProductCapitalizationCallback (SeqFeatPtr sfp, Pointer userdata)
       for (vnp = prp->name; vnp != NULL; vnp = vnp->next)
       {
         product_name = (CharPtr)(vnp->data.ptrvalue);
-        FixCapitalizationInTitle (&product_name, FALSE, NULL);
+        FixProductCapitalizationInString (&product_name, (FixProductCapPtr) userdata);
         vnp->data.ptrvalue = product_name;
       }
     }
@@ -20702,18 +21254,160 @@ static void FixProductCapitalizationCallback (SeqFeatPtr sfp, Pointer userdata)
   else if (sfp->data.choice == SEQFEAT_RNA)
   {
     rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-    if (rrp != NULL && rrp->ext.choice == 1)
+    if (rrp != NULL) 
+    {
+      if (rrp->ext.choice == 1)
     {
       product_name = (CharPtr)(rrp->ext.value.ptrvalue);
-      FixCapitalizationInTitle (&product_name, FALSE, NULL);
+        FixProductCapitalizationInString (&product_name, (FixProductCapPtr) userdata);
       rrp->ext.value.ptrvalue = product_name;
     }
+      else if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL) 
+      {
+        product_name = rgp->product;
+        FixProductCapitalizationInString (&product_name, (FixProductCapPtr) userdata);
+        rgp->product = product_name;
+      }
+    }
+  }
+}
+
+typedef struct fixproductcapdlg {
+  FORM_MESSAGE_BLOCK
+  ButtoN keep_cap_before_punct;
+  ButtoN keep_cap_before_cap;
+  ButtoN remove_comma;
+} FixProductCapDlgData, PNTR FixProductCapDlgPtr;
+
+
+static void DoFixProductCapitalization (ButtoN b)
+{
+  FixProductCapDlgPtr dlg;
+  FixProductCapData   data;
+  SeqEntryPtr       sep;
+  SelStructPtr      sel;
+  Boolean           any_found = FALSE;
+  SeqMgrFeatContext fcontext;
+  SeqFeatPtr        sfp;
+  RnaRefPtr         rrp;
+
+  dlg = (FixProductCapDlgPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+
+  MemSet (&data, 0, sizeof (FixProductCapData));
+  data.keep_cap_before_cap = GetStatus (dlg->keep_cap_before_cap);
+  data.keep_cap_before_punct = GetStatus (dlg->keep_cap_before_punct);
+  if (GetStatus (dlg->remove_comma)) {
+    data.remove_list = (CharPtr) MemNew (sizeof (Char) * 2);
+    sprintf (data.remove_list, ",");
+  }
+
+  sel = ObjMgrGetSelected ();
+  if(sel == NULL)
+  {
+    VisitFeaturesInSep (sep, &data, FixProductCapitalizationCallback);
+  }
+  else
+  {
+    while( sel != NULL )
+    {
+      if(sel->entityID == dlg->input_entityID && sel->itemtype == OBJ_SEQFEAT)
+      {
+        sfp = SeqMgrGetDesiredFeature (dlg->input_entityID, NULL, sel->itemID, 0, NULL, &fcontext);
+        if(sfp != NULL)
+        {
+          if (sfp->data.choice == SEQFEAT_PROT)
+          {
+          	FixProductCapitalizationCallback (sfp, &data);
+          	any_found = TRUE;
+          }
+          else if (sfp->data.choice == SEQFEAT_RNA)
+          {
+            rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
+          	if (rrp != NULL && rrp->ext.choice == 1)
+          	{
+          	  FixProductCapitalizationCallback (sfp, &data);
+          	  any_found = TRUE;
+          	}
+          }
+        }
+      } 
+      sel = sel->next;      
+    }
+    if (!any_found)
+    {
+      VisitFeaturesInSep (sep, &data, FixProductCapitalizationCallback);      
+    }
   }
+
+  data.remove_list = MemFree (data.remove_list);
+  
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+  Remove (dlg->form);
+  Update ();
 }
 
+
 static void FixProductCapitalization (IteM i)
 {
   BaseFormPtr       bfp;
+  FixProductCapDlgPtr dlg;
+  WindoW      w;
+  GrouP       h, g, c;
+  ButtoN      b;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+
+  if (bfp == NULL) return;
+  
+  dlg = (FixProductCapDlgPtr) MemNew (sizeof (FixProductCapDlgData));
+  if (dlg == NULL)
+  {
+    return;
+  }
+  
+  w = FixedWindow (-50, -33, -10, -10, "Fix Product Name Capitalization", StdCloseWindowProc);
+  SetObjectExtra (w, dlg, StdCleanupExtraProc);
+  dlg->form = (ForM) w;
+  dlg->input_entityID = bfp->input_entityID;
+  
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+
+  g = HiddenGroup (h, 0, 3, NULL);
+  SetGroupSpacing (g, 10, 10);
+  dlg->keep_cap_before_punct = CheckBox (g, "Keep caps before punctuation", NULL);
+  dlg->keep_cap_before_cap = CheckBox (g, "Keep caps before caps", NULL);
+  dlg->remove_comma = CheckBox (g, "Remove comma", NULL);
+
+  c = HiddenGroup (h, 2, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+  
+  b = PushButton (c, "Accept", DoFixProductCapitalization);
+  SetObjectExtra (b, dlg, NULL);
+  
+  b = PushButton (c, "Cancel", StdCancelButtonProc);
+  
+  AlignObjects (ALIGN_CENTER, (HANDLE) g,
+                              (HANDLE) c, 
+                              NULL);
+                                
+  Show (w);   
+}
+
+static void FixProductCapitalizationDefault (IteM i)
+{
+  BaseFormPtr         bfp;
+  FixProductCapData   data;
   SeqEntryPtr       sep;
   SelStructPtr      sel;
   Boolean           any_found = FALSE;
@@ -20728,13 +21422,14 @@ static void FixProductCapitalization (IteM i)
 #endif
 
   if (bfp == NULL) return;
+  
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
-  if (sep == NULL) return;
+  MemSet (&data, 0, sizeof (FixProductCapData));
   
   sel = ObjMgrGetSelected ();
   if(sel == NULL)
   {
-    VisitFeaturesInSep (sep, NULL, FixProductCapitalizationCallback);
+    VisitFeaturesInSep (sep, &data, FixProductCapitalizationCallback);
   }
   else
   {
@@ -20747,7 +21442,7 @@ static void FixProductCapitalization (IteM i)
         {
           if (sfp->data.choice == SEQFEAT_PROT)
           {
-          	FixProductCapitalizationCallback (sfp, NULL);
+          	FixProductCapitalizationCallback (sfp, &data);
           	any_found = TRUE;
           }
           else if (sfp->data.choice == SEQFEAT_RNA)
@@ -20755,7 +21450,7 @@ static void FixProductCapitalization (IteM i)
             rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
           	if (rrp != NULL && rrp->ext.choice == 1)
           	{
-          	  FixProductCapitalizationCallback (sfp, NULL);
+          	  FixProductCapitalizationCallback (sfp, &data);
           	  any_found = TRUE;
           	}
           }
@@ -20765,15 +21460,18 @@ static void FixProductCapitalization (IteM i)
     }
     if (!any_found)
     {
-      VisitFeaturesInSep (sep, NULL, FixProductCapitalizationCallback);      
+      VisitFeaturesInSep (sep, &data, FixProductCapitalizationCallback);      
     }
   }
   
+  data.remove_list = MemFree (data.remove_list);
+  
   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
   Update ();	
 }
 
+
 static void FixDeltaSeqDataLenCallback (BioseqPtr bsp, Pointer userdata)
 {
   DeltaSeqPtr dsp;
@@ -21087,6 +21785,20 @@ static void ShowOnCallerTool (IteM i)
   CreateReportWindow (eReportTypeOnCaller);
 }
 
+static void ShowMegaReport (IteM i)
+{
+  BaseFormPtr  bfp;
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+
+  if (bfp == NULL) return;
+  
+  CreateReportWindow (eReportTypeMegaReport);
+}
+
 static void TestTax3 (IteM i, Int4 taxid, CharPtr name)
 
 {
@@ -21355,6 +22067,104 @@ static void ApplyBarcodeDbxrefs (IteM i)
   Update();
 }
 
+static void BarcodeHupDateProc (
+  SeqDescrPtr sdp,
+  Pointer userdata
+)
+
+{
+  Char            buf [64];
+  DatePtr         dp = NULL;
+  size_t          len;
+  ObjValNodePtr   ovp;
+  SubmitBlockPtr  sbp;
+  CharPtr         ttl;
+
+  if (sdp == NULL || sdp->choice != Seq_descr_title) return;
+  sbp = (SubmitBlockPtr) userdata;
+  if (sbp == NULL) return;
+
+  ttl = (CharPtr) sdp->data.ptrvalue;
+  if (StringHasNoText (ttl)) return;
+
+  len = StringLen (ttl);
+  if (len < 5) return;
+  if (ttl [0] != '[') return;
+  if (ttl [len - 1] != ']') return;
+
+  if (StringNICmp (ttl, "[hup=", 5) != 0) return;
+  StringNCpy_0 (buf, ttl + 5, sizeof (buf));
+  len = StringLen (buf);
+  if (len < 3) return;
+  if (buf [len - 1] == ']') {
+    buf [len - 1] = '\0';
+  }
+  if (StringChr (buf, '[') != NULL) return;
+  if (StringChr (buf, ']') != NULL) return;
+
+  if (StringICmp (buf, "y") == 0) {
+    dp = DateCurr ();
+    if (dp != NULL) {
+      if (dp->data [0] == 1) {
+        (dp->data [1])++;
+      }
+    }
+  } else {
+    dp = DateParse (buf);
+  }
+  if (dp == NULL) return;
+
+  if (sbp->hup && sbp->reldate != NULL) {
+    if (DateMatch (dp, sbp->reldate, TRUE) == -1) {
+      sbp->reldate = DateFree (sbp->reldate);
+      sbp->reldate = dp;
+    }
+  } else {
+    sbp->hup = TRUE;
+    sbp->reldate = DateFree (sbp->reldate);
+    sbp->reldate = dp;
+  }
+
+  if (sdp->extended == 1) {
+    ovp = (ObjValNodePtr) sdp;
+    ovp->idx.deleteme = TRUE;
+  }
+}
+
+static void ParseBarcodeHupDate (IteM i)
+
+{
+  BaseFormPtr     bfp;
+  ObjMgrDataPtr   omdp;
+  SubmitBlockPtr  sbp;
+  SeqEntryPtr     sep;
+  SeqSubmitPtr    ssp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) return;
+
+  omdp = ObjMgrGetData (bfp->input_entityID);
+  if (omdp == NULL) return;
+  if (omdp->datatype != OBJ_SEQSUB) return;
+  ssp = (SeqSubmitPtr) omdp->dataptr;
+  if (ssp == NULL || ssp->datatype != 1) return;
+  sbp = ssp->sub;
+  if (sbp == NULL) return;
+
+  VisitDescriptorsInSep (sep, (Pointer) sbp, BarcodeHupDateProc);
+
+  DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+  Update();
+}
+
 
 static void InstantiateMatPeptideProductsMenuItem (IteM i)
 {
@@ -21624,6 +22434,37 @@ static void ApplyKeywordWithStringConstraint (IteM i)
 }
 
 
+static void AddStructuredCommentKeywordsMenuItem (IteM i)
+{
+  BaseFormPtr    bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  AddStructuredCommentKeywords (bfp->input_entityID);
+}
+
+
+static void RemoveStructuredCommentKeywordsMenuItem (IteM i)
+{
+  BaseFormPtr    bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  RemoveStructuredCommentKeywords (bfp->input_entityID);
+}
+
+
+
 static void TestNewParse (IteM i)
 {
   BaseFormPtr  bfp;
@@ -21643,6 +22484,129 @@ static void TestNewParse (IteM i)
 }
 
 
+static void RemoveDuplicateNestedSetsMenuItem (IteM i)
+{
+  BaseFormPtr  bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  RemoveDuplicateNestedSetsForEntityID (bfp->input_entityID);
+}
+
+
+
+
+static void RunAutoFixScript (IteM i)
+{
+  BaseFormPtr  bfp;
+  AsnIoPtr     aip;
+  Char         buf [PATH_MAX];
+  SeqEntryPtr  sep;
+  ValNodePtr   sep_list, vnp, action_list;
+  Uint2        entityID;
+  Int4         num_fields = 0, num_features = 0;
+  Int4         tmp_fields, tmp_features;
+  LogInfoPtr   lip;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  if (! FindPath("ncbi", "ncbi", "data", buf, sizeof (buf)))
+  {
+    Message (MSG_ERROR, "Failed to find Auto-fix script");
+    return;
+  }
+
+  StringCat(buf, "autofix.prt");
+
+  aip = AsnIoOpen (buf, "r");
+  if (aip == NULL) {
+    Message (MSG_ERROR, "Unable to open %s", buf);
+    return;
+  }
+
+  action_list = MacroActionListAsnRead (aip, NULL);
+  AsnIoClose (aip);
+
+  if (action_list == NULL) {
+    Message (MSG_ERROR, "Unable to read action list from %s.", buf);
+    return;
+  }
+
+  sep_list = GetViewedSeqEntryList ();
+  if (sep_list == NULL) {
+    Message (MSG_ERROR, "No records open!");
+  } else if (sep_list->next != NULL 
+    && ANS_CANCEL == Message (MSG_OKC, "You have more than one record open - run macro for all open records?")) {
+    /* do nothing */
+  } else {
+    WatchCursor();
+    Update();
+    lip = OpenLog ("Macro Actions");
+    for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+      sep = vnp->data.ptrvalue;
+      entityID = ObjMgrGetEntityIDForChoice(sep);
+      tmp_fields = 0;
+      tmp_features = 0;
+      lip->data_in_log |= ApplyMacroToSeqEntryEx (sep, action_list, &tmp_fields, &tmp_features, lip->fp);
+      num_fields += tmp_fields;
+      num_features += tmp_features;
+      ObjMgrSetDirtyFlag (entityID, TRUE);
+      ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+    }
+    sep_list = ValNodeFree (sep_list);
+    ArrowCursor ();
+    Update ();   
+    Message (MSG_OK, "Macro script affected %d fields and created %d features", num_fields, num_features);
+    if (!lip->data_in_log) {
+      fprintf (lip->fp, "Macro had no effect\n");
+      lip->data_in_log = TRUE;
+    }
+    CloseLog (lip);
+    lip = FreeLog (lip);
+  }
+  action_list = MacroActionListFree (action_list);
+}
+
+
+static void ConvertCommentsWithSpacesToStructuredComments (IteM i)
+{
+  BaseFormPtr  bfp;
+  SeqEntryPtr  sep;
+  Int4         n;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) {
+    return;
+  }
+
+  n = ConvertCommentsWithSpacesToStructuredCommentsForSeqEntry (sep);
+  if (n > 0) {
+    Message (MSG_ERROR, "Unable to convert %d comments\n", n);
+  }
+
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
+  Update();
+}
+
+
 static void MakeSpecialOrganismMenu (MenU m, BaseFormPtr bfp)
 {
   IteM  i;
@@ -21768,13 +22732,44 @@ static void MakeSpecialOrganismMenu (MenU m, BaseFormPtr bfp)
   SetObjectExtra (i, bfp, NULL);
 }
 
-static void MakeSpecialProjectsMenu (MenU m, BaseFormPtr bfp)
+
+static void MakeStructuredCommentsMenu (MenU s, BaseFormPtr bfp)
+{
+  IteM  i;
+  MenU  x;
+
+  i = CommandItem (s, "Parse Structured Comment into User Object", ParseCommentIntoStructuredObject);
+  SetObjectExtra (i, bfp, NULL);
+  x = SubMenu (s, "Add Structured Comment Prefix-Suffix");
+  i = CommandItem (x, "HIVData", AddStructuredCommentHivTag);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "FluData", AddStructuredCommentFluTag);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "MIGSData", AddStructuredCommentMIGSTag);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "MIMSData", AddStructuredCommentMIMSTag);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "MIENSData", AddStructuredCommentMIENSTag);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (s, "Add Genome Assembly Structured Comment", ApplyGenomeAssemblyComment);
+  SetObjectExtra (i, bfp, NULL); 
+  i = CommandItem (s, "Export Structured Comment Table", ExportStructuredCommentTable);
+  SetObjectExtra (i, bfp, NULL); 
+  i = CommandItem (s, "Parse from Structured Comments", CreateTableReaderWindowWithStructuredComments);
+  SetObjectExtra (i, bfp, NULL); 
+
+  i = CommandItem (s, "Convert Comments with Spaces to Structured Comments", ConvertCommentsWithSpacesToStructuredComments);
+  SetObjectExtra (i, bfp, NULL); 
+
+  i = CommandItem (s, "Create Structured Comments from Table", CreateStructuredCommentsItem);
+  SetObjectExtra (i, bfp, NULL); 
+}
+
+extern void MakeSpecialProjectsMenu (MenU s, BaseFormPtr bfp)
 {
   IteM  i;
-  MenU  s;
   MenU  x;
 
-  s = SubMenu (m, "Projects/ J");
   if (indexerVersion) {
     i = CommandItem (s, "Create Seq-Hist for TPA", CreateSeqHistTPA);
     SetObjectExtra (i, bfp, NULL);
@@ -21784,6 +22779,9 @@ static void MakeSpecialProjectsMenu (MenU m, BaseFormPtr bfp)
     i = CommandItem (s, "Load TPA Accession Numbers From File",
                      LoadTPAAccessionNumbersFromFile);
     SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (s, "Import TPA Alignment ASN.1 from File",
+                     ImportTpaAlignment);
+    SetObjectExtra (i, bfp, NULL);
     i = CommandItem (s, "Import Single Interval Alignment for TPA Seq-hist", ImportAlignmentForSeqHistInterval);
     SetObjectExtra (i, bfp, NULL);
     i = CommandItem (s, "Advanced Assembly Alignment Editor", AdvancedAssemblyAlignmentEditor);
@@ -21815,13 +22813,8 @@ static void MakeSpecialProjectsMenu (MenU m, BaseFormPtr bfp)
     i = CommandItem (s, "Remove Gaps at ends of HTGS Deltas", DeleteDeltaEndGaps);
     SetObjectExtra (i, bfp, NULL);
     SeparatorItem (s);
-    i = CommandItem (s, "Parse Structured Comment into User Object", ParseCommentIntoStructuredObject);
-    SetObjectExtra (i, bfp, NULL);
-    x = SubMenu (s, "Add Structured Comment Prefix-Suffix");
-    i = CommandItem (x, "HIVData", AddStructuredCommentHivTag);
-    SetObjectExtra (i, bfp, NULL);
-    i = CommandItem (x, "FluData", AddStructuredCommentFluTag);
-    SetObjectExtra (i, bfp, NULL);
+    x = SubMenu (s, "Structured Comments");
+    MakeStructuredCommentsMenu (x, bfp);
     SeparatorItem (s);
     i = CommandItem (s, "BARCODE Discrepancy Tool", BarcodeTestTool);
     SetObjectExtra (i, bfp, NULL);
@@ -21829,6 +22822,8 @@ static void MakeSpecialProjectsMenu (MenU m, BaseFormPtr bfp)
     SetObjectExtra (i, bfp, NULL);
     i = CommandItem (s, "Apply BARCODE Dbxrefs", ApplyBarcodeDbxrefs);
     SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (s, "Parse BARCODE HUP Date in Titles", ParseBarcodeHupDate);
+    SetObjectExtra (i, bfp, NULL);
     SeparatorItem (s);
     i = CommandItem (s, "Add Note to Coding Regions in Source Features", ApplyTagToCodingRegionsInSourceFeatures);
     SetObjectExtra (i, bfp, NULL);
@@ -21839,15 +22834,21 @@ static void MakeSpecialProjectsMenu (MenU m, BaseFormPtr bfp)
     SetObjectExtra (i, bfp, NULL);
 
     x = SubMenu (s, "Create TSA IDs");
-    i = CommandItem (x, "From Local IDs", CreateTSAIDsFromLocalIDs); 
+    i = CommandItem (x, "From Existing IDs", CreateTSAIDsFromLocalIDs); 
     SetObjectExtra (i, bfp, NULL);
     i = CommandItem (x, "From Table", CreateTSAIDsFromTable);
     SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (x, "From Existing IDs with Suffix", CreateTSAIDsFromLocalIDsWithSuffix);
+    SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (x, "From Defline", CreateTSAIDsFromDefline);
+    SetObjectExtra (i, bfp, NULL);
 
     i = CommandItem (s, "Edit TSA Assembly", EditTSAAssembly);
     SetObjectExtra (i, bfp, NULL);
     i = CommandItem (s, "Add mRNA sequence to deflines", AddmRNASequenceToDeflines);
     SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (s, "Trim for N Pct", FindBestNTrimSites);
+    SetObjectExtra (i, bfp, NULL);
     SeparatorItem (s);
     i = CommandItem (s, "Create RefSeq Protein IDs", CreateRefSeqProteinIDs);
     SetObjectExtra (i, bfp, NULL); 
@@ -21855,10 +22856,11 @@ static void MakeSpecialProjectsMenu (MenU m, BaseFormPtr bfp)
     i = CommandItem (s, "Add Flu Comments", AddFluComments);
     SetObjectExtra (i, bfp, NULL); 
     SeparatorItem (s);
-    i = CommandItem (s, "Create Structured Comments from Table", CreateStructuredCommentsItem);
+    i = CommandItem (s, "Retranscribe mRNAs", RetranscribemRNA);
     SetObjectExtra (i, bfp, NULL); 
+
     SeparatorItem (s);
-    i = CommandItem (s, "Retranscribe mRNAs", RetranscribemRNA);
+    i = CommandItem (s, "Apply Articles", ApplyArticles);
     SetObjectExtra (i, bfp, NULL); 
 
     /* remove after retro */
@@ -21923,6 +22925,14 @@ static void MakeSpecialApplyMenu (MenU m, BaseFormPtr bfp)
 
   i = CommandItem (s, "Add other Feature", ApplyImpFeat);
   SetObjectExtra (i, bfp, NULL);
+  x = SubMenu (s, "Add Common Feature");
+  i = CommandItem (x, "Microsatellite", MakeCommonFeatureMicrosatellite);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "Control Region", MakeCommonFeatureControlRegion);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (s, "Add Feature Between", AddFeatureBetween);
+  SetObjectExtra (i, bfp, NULL);
+  
   i = CommandItem (s, "Add Qualifier", MacroApplyGBQual);
   SetObjectExtra (i, bfp, NULL);
   SeparatorItem (s);
@@ -21958,6 +22968,8 @@ static void MakeSpecialApplyMenu (MenU m, BaseFormPtr bfp)
     SetObjectExtra (i, bfp, NULL);
     i = CommandItem (x, "With Constraint", ApplyKeywordWithStringConstraint);
     SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (x, "Structured Comment", AddStructuredCommentKeywordsMenuItem);
+    SetObjectExtra (i, bfp, NULL);
   }
   else
   {
@@ -22075,6 +23087,8 @@ static void MakeSpecialRemoveMenu (MenU m, BaseFormPtr bfp)
   SetObjectExtra (i, bfp, NULL);
   i = CommandItem (x, "Outside String", RemoveTextOutsideString);
   SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "New Outside String", NewRemoveTextOutsideString);
+  SetObjectExtra (i, bfp, NULL);
 
   SeparatorItem (s);
   
@@ -22192,6 +23206,9 @@ static void MakeSpecialRemoveMenu (MenU m, BaseFormPtr bfp)
     i = CommandItem (y, "LOCUS from Parts", RemoveLocusFromParts);
     SetObjectExtra (i, bfp, NULL);    
 
+    i = CommandItem (y, "TSA IDs", RemoveTSAIdsFromBioseqs);
+    SetObjectExtra (i, bfp, NULL);    
+
     SeparatorItem (s);
   }
   
@@ -22304,6 +23321,11 @@ static void MakeSpecialConvertMenu (MenU m, BaseFormPtr bfp)
   i = CommandItem (x, "Protein Description to Second Name", ProtDescToSecondName);
   SetObjectExtra (i, bfp, NULL);
   SeparatorItem (s);
+  if (indexerVersion) {
+    i = CommandItem (s, "Convert repeat_region rpt_unit_range to location", ConvertRptUnitRangeToLocation);
+    SetObjectExtra (i, bfp, NULL);
+    SeparatorItem (s);
+  }
   i = CommandItem (s, "Whole Location to Interval", ConvertWholeToInterval);
   SetObjectExtra (i, bfp, NULL);
   i = CommandItem (s, "Both Strands to Proper Strand", ConvertBothStrands);
@@ -22398,7 +23420,7 @@ static void MakeSpecialEditMenu (MenU m, BaseFormPtr bfp)
 
 
   SeparatorItem (s);
-  i = CommandItem (s, "Lowercase Qualifiers", FixCaseByField);
+  i = CommandItem (s, "Lowercase Qualifiers", ChangeQualifierCase);
   SetObjectExtra (i, bfp, NULL);
 
   SeparatorItem (s);
@@ -22423,6 +23445,9 @@ static void MakeSpecialEditMenu (MenU m, BaseFormPtr bfp)
     SeparatorItem (s);
     i = CommandItem (s, "Edit Sequence Ends", EditSeqEndsProc);
     SetObjectExtra (i, bfp, NULL);
+
+    i = CommandItem (s, "Edit Sequence Ends with Alignment", TrimSequencesByAlignment);
+    SetObjectExtra (i, bfp, NULL);
   }
 
   i = CommandItem (s, "Trim Ns from Bioseqs", TrimNsFromNucs);
@@ -22436,6 +23461,7 @@ static void MakeSpecialEditMenu (MenU m, BaseFormPtr bfp)
     i = CommandItem (x, "All", VecScreenToNsWeak);
     SetObjectExtra (i, bfp, NULL);
   }
+
 }
 
 static void MakeSpecialClearMenu (MenU m, BaseFormPtr bfp)
@@ -22469,6 +23495,11 @@ static void MakeSpecialClearMenu (MenU m, BaseFormPtr bfp)
   {
     i = CommandItem (s, "Clear Keywords", RemoveKeywordWithStringConstraint);
     SetObjectExtra (i, bfp, NULL);
+    if (indexerVersion) {
+      i = CommandItem (s, "Remove Structured Comment Keywords", RemoveStructuredCommentKeywordsMenuItem);
+      SetObjectExtra (i, bfp, NULL);
+    }
+
     i = CommandItem (s, "Clear Nomenclature", RemoveNomenclature);
     SetObjectExtra (i, bfp, NULL);    
   }
@@ -22532,12 +23563,17 @@ static void MakeSpecialGapSequencesMenu (MenU m, BaseFormPtr bfp)
   SetObjectExtra (i, bfp, NULL);
   i = CommandItem (s, "Remove Unnecessary Gap Features", RemoveUnnecessaryGapFeatures);
   SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (s, "Convert Features with Gap Locations to Instantiated Gaps", RemoveFeaturesLikeGaps);
+  SetObjectExtra (i, bfp, NULL);
   SeparatorItem (s);
   i = CommandItem (s, "Flip Intervals Between Gaps", FlipSequenceIntervals);
   SetObjectExtra (i, bfp, NULL);
   SeparatorItem (s);
   i = CommandItem (s, "Remove Contigs from Scaffolds", RemoveContigFromScaffoldMenuItem);
   SetObjectExtra (i, bfp, NULL);
+  SeparatorItem (s);
+  i = CommandItem (s, "Replace Non-N Islands", RemoveNonNIslands);
+  SetObjectExtra (i, bfp, NULL);
 }
 
 static void MakeSpecialSelectMenu (MenU m, BaseFormPtr bfp)
@@ -22626,8 +23662,10 @@ static void MakeSpecialDesktopMenu (MenU m, BaseFormPtr bfp)
   SetObjectExtra (i, bfp, NULL);
   i = CommandItem (s, "Remove Sets in Set", RemoveSetsInSetMenuItem);
   SetObjectExtra (i, bfp, NULL);
-
-
+  i = CommandItem (s, "Remove Duplicate Nested Sets", RemoveDuplicateNestedSetsMenuItem);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (s, "Apply Set Type", ApplySetType);
+  SetObjectExtra (i, bfp, NULL);
 }
 
 
@@ -22646,6 +23684,8 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   SetObjectExtra (i, bfp, NULL);
   i = CommandItem (x, "Select Options...", AutoDefWithOptions);
   SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "Add Popset Titles", AddPopsetTitlesItem);
+  SetObjectExtra (i, bfp, NULL);
   SeparatorItem (s);
   i = CommandItem (s, "Add Definition Line", ApplyTitle);
   SetObjectExtra (i, bfp, NULL);
@@ -22683,7 +23723,10 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   MakeSpecialClearMenu (m, bfp);
 
   s = SubMenu (m, "CDS, Protein, and RNA");
-  i = CommandItem (s, "Fix Product Name Capitalization", FixProductCapitalization);
+  x = SubMenu (s, "Fix Product Name Capitalization");
+  i = CommandItem (x, "Default", FixProductCapitalizationDefault);
+  SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (x, "With Options", FixProductCapitalization);
   SetObjectExtra (i, bfp, NULL);
   SeparatorItem (s);
   x = SubMenu (s, "Retranslate Coding Regions");
@@ -22738,6 +23781,11 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   SetObjectExtra (i, bfp, NULL);
   i = CommandItem (x, "Make Last Exon 3' Partial", FixLastExonLocMakePartial);
   SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (s, "Remove UTR locations from CDS location", RemoveUTRsFromCDSs);
+  SetObjectExtra (i, bfp, NULL);    
+  i = CommandItem (s, "Adjust CDS for Consensus Splice Sites", AdjustForConsensusSplice);
+  SetObjectExtra (i, bfp, NULL);    
+
   SeparatorItem (s);
   i = CommandItem (s, "Convert CDS to mat_peptide", CombineMultipleCDS);
   SetObjectExtra (i, bfp, NULL);
@@ -22752,6 +23800,8 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   SeparatorItem (s);
   i = CommandItem (s, "Instantiate Mat-peptide Products", InstantiateMatPeptideProductsMenuItem);
   SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (s, "Mark Truncated Products by Protein Alignment", TruncateByProtAlign);
+  SetObjectExtra (i, bfp, NULL);
     
   /* Authors and Publications */
   s = SubMenu (m, "Authors and Publications");
@@ -22837,6 +23887,10 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   i = CommandItem (s, "Combine Selected Genes into Pseudogene", CombineToCreatePseudoGene);
   SetObjectExtra (i, bfp, NULL);
   
+  SeparatorItem (s);
+  i = CommandItem (s, "Explode RNA Features", ExplodeRNA);
+  SetObjectExtra (i, bfp, NULL);
+  
   s = SubMenu (m, "Normalize, Map, Package");
   i = CommandItem (s, "Renormalize Nuc-Prot Sets", RenormalizeNucProtSetsMenuItem);
   SetObjectExtra (i, bfp, NULL);
@@ -22884,8 +23938,8 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   i = CommandItem (s, "Suppress genes inside mobile elements", SuppressGenesOnFeaturesInsideMobileElements);
   SetObjectExtra (i, bfp, NULL);
 
-
-  MakeSpecialProjectsMenu (m, bfp);
+  s = SubMenu (m, "Projects/ J");
+  MakeSpecialProjectsMenu (s, bfp);
 
   s = SubMenu (m, "GenProdSets and SeqAnnots");
   if (indexerVersion) {
@@ -23008,12 +24062,14 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   i = CommandItem (s, "Process Scanned tRNA Anticodons", tRNAScanUpdate);
   SetObjectExtra (i, bfp, NULL);
     
-  s = SubMenu (m, "Display");
+  s = SubMenu (m, "Display/ I");
   i = CommandItem (s, "View Sorted Protein FASTA", ViewSortedProteinMenuItem);
   SetObjectExtra (i, bfp, NULL);
   if (extraServices) {
     i = CommandItem (s, "Make ToolBar Window/ T", MakeToolBarWindow);
     SetObjectExtra (i, bfp, NULL);
+    i = CommandItem (s, "Make WGS Toolbar/ W", MakeWGSToolBar);
+    SetObjectExtra (i, bfp, NULL);
   }
   i = CommandItem (s, "Alignment Summary", ViewAlignmentSummary);
   SetObjectExtra (i, bfp, NULL);
@@ -23025,13 +24081,15 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
   SetObjectExtra (i, bfp, NULL);
   i = CommandItem (s, "Print Test List", PrintDiscrepancyTestListMenuItem);
   SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (s, "Find Frame Shifts", FrameShiftFinder);
+  SetObjectExtra (i, bfp, NULL);
+
+  MakeSpecialDesktopMenu (m, bfp);
 
   MakeSpecialLinkMenu (m, bfp);
 
   MakeSpecialSelectMenu (m, bfp);
 
-  MakeSpecialDesktopMenu (m, bfp);
-
   SeparatorItem (m);
   s = SubMenu (m, "Sort Unique Count/ U");
   x = SubMenu (s, "By Group");
@@ -23077,11 +24135,16 @@ extern void SetupSpecialMenu (MenU m, BaseFormPtr bfp)
     
   }
   SeparatorItem (m);
+  i = CommandItem (m, "Mega Report", ShowMegaReport);
+  SetObjectExtra (i, bfp, NULL);
   i = CommandItem (m, "Discrepancy Report", ShowDiscrepancyReport);
   SetObjectExtra (i, bfp, NULL);
   SeparatorItem (m);
   i = CommandItem (m, "Macro Editor", LaunchMacroEditor);
   SetObjectExtra (i, bfp, NULL);
+  i = CommandItem (m, "AutoFix", RunAutoFixScript);
+  SetObjectExtra (i, bfp, NULL);
+
 #ifdef TEST_VALIDAPI
   i = CommandItem (m, "Rules Editor", LaunchCommentRulesEditor);
   SetObjectExtra (i, bfp, NULL);
diff --git a/sequin/sequin4.c b/sequin/sequin4.c
index b88225d..f835760 100644
--- a/sequin/sequin4.c
+++ b/sequin/sequin4.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   6/28/96
 *
-* $Revision: 6.436 $
+* $Revision: 6.462 $
 *
 * File Description: 
 *
@@ -87,6 +87,8 @@ static Int2 LIBCALLBACK ConvertToDeltaSequence (Pointer data);
 static Int2 LIBCALLBACK FeatToDeltaSeq (Pointer data);
 static Int2 LIBCALLBACK CopyMasterSourceToSegments (Pointer data);
 
+#define REGISTER_APPLY_SET_TYPE ObjMgrProcLoadEx (OMPROC_FILTER,"Apply Set Type","ApplySetType",0,0,0,0,NULL,ApplySetTypeDesktop,PROC_PRIORITY_DEFAULT, "Indexer")
+
 #define REGISTER_REMOVESET ObjMgrProcLoadEx (OMPROC_FILTER,"Remove Set","RemoveSet",0,0,0,0,NULL,RemoveSet,PROC_PRIORITY_DEFAULT, "Indexer")
 
 #define REGISTER_REMOVESETSINSET ObjMgrProcLoadEx (OMPROC_FILTER,"Remove Sets in Selected Set","RemoveSetsInSelectedSet",0,0,0,0,NULL,RemoveSetsInSelectedSet,PROC_PRIORITY_DEFAULT, "Indexer")
@@ -158,6 +160,7 @@ static Int2 LIBCALLBACK CopyMasterSourceToSegments (Pointer data);
 #define REGISTER_BIOSEQ_REVERSE ObjMgrProcLoadEx (OMPROC_FILTER, "Bioseq Reverse", "BioseqReverse", OBJ_BIOSEQ, 0, OBJ_BIOSEQ, 0, NULL, RevFunc, PROC_PRIORITY_DEFAULT, "Utilities")
 #define REGISTER_BIOSEQ_COMPLEMENT ObjMgrProcLoadEx (OMPROC_FILTER, "Bioseq Complement", "BioseqComplement", OBJ_BIOSEQ, 0, OBJ_BIOSEQ, 0, NULL, CompFunc, PROC_PRIORITY_DEFAULT, "Utilities")
 #define REGISTER_BIOSEQ_REVCOMP_BYID ObjMgrProcLoadEx (OMPROC_FILTER, "Bioseq and Features RevComp By ID", "RevCompByID", OBJ_BIOSEQ, 0, OBJ_BIOSEQ, 0, NULL, BioseqRevCompByID, PROC_PRIORITY_DEFAULT, "Utilities")
+#define REGISTER_BIOSEQ_REVERSE_QUALITY_SCORES ObjMgrProcLoadEx (OMPROC_FILTER, "Reverse Quality Scores", "RevQualScores", OBJ_BIOSEQ, 0, OBJ_BIOSEQ, 0, NULL, BioseqRevQualScores, PROC_PRIORITY_DEFAULT, "Utilities")
 
 #define REGISTER_BIOSEQ_SEG_REPORT ObjMgrProcLoadEx (OMPROC_FILTER, "Bioseq Seg Report", "BioseqSegReport", OBJ_BIOSEQ, 0, OBJ_BIOSEQ, 0, NULL, ReportDeltaSegments, PROC_PRIORITY_DEFAULT, "Misc")
 
@@ -2546,6 +2549,7 @@ static Int2 LIBCALLBACK RemoveSet (Pointer data)
   Pointer           parentptr, top_parentptr;
   SeqEntryPtr       top_sep, this_sep;
   BioseqSetPtr      target_bssp, parent_bssp;
+  ValNodePtr        titles;
 
   ompcp = (OMProcControlPtr) data;
   if (ompcp == NULL 
@@ -2604,6 +2608,9 @@ static Int2 LIBCALLBACK RemoveSet (Pointer data)
   }
   else
   {
+    /* first, remove set title if any */
+    titles = ValNodeExtractList (&(target_bssp->descr), Seq_descr_title);
+    titles = SeqDescrFree (titles);
     /* propagate the descriptors on the set to the sequences in the set */
     SetDescriptorPropagate (target_bssp);
      
@@ -2672,7 +2679,7 @@ static Int2 LIBCALLBACK RemoveSetsInBioseqSet (BioseqSetPtr parent_bssp, Uint2 e
   SeqEntryPtr       top_sep, this_sep, next_sep;
   BioseqSetPtr      target_bssp;
   Boolean           need_locus_fixup = FALSE;
-
+  SeqDescrPtr       titles;
 
   if (parent_bssp == NULL) {
     return OM_MSG_RET_ERROR;
@@ -2723,6 +2730,10 @@ static Int2 LIBCALLBACK RemoveSetsInBioseqSet (BioseqSetPtr parent_bssp, Uint2 e
       else if (target_bssp->_class != BioseqseqSet_class_not_set
                && target_bssp->_class != BioseqseqSet_class_parts)
       {
+        /* first, remove set title if any */
+        titles = ValNodeExtractList (&(target_bssp->descr), Seq_descr_title);
+        titles = SeqDescrFree (titles);
+
         /* propagate the descriptors on the set to the sequences in the set */
         SetDescriptorPropagate (target_bssp);
      
@@ -2798,6 +2809,65 @@ extern void RemoveSetsInSetMenuItem (IteM i)
 }
 
 
+NLM_EXTERN void ApplySetTypeToSeqEntry (SeqEntryPtr sep, Uint1 new_class, Boolean is_top)
+{
+  BioseqSetPtr bssp;
+
+  if (sep == NULL || !IS_Bioseq_set (sep) 
+      || (bssp = (BioseqSetPtr) sep->data.ptrvalue) == NULL
+      || bssp->_class == BioseqseqSet_class_nuc_prot
+      || bssp->_class == BioseqseqSet_class_segset) {
+    return;
+  }
+
+  if (is_top) {
+    for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
+      ApplySetTypeToSeqEntry (sep, new_class, FALSE);
+    }
+  } else {
+    bssp->_class = new_class;
+  }
+}
+
+
+NLM_EXTERN void ApplySetType (IteM i)
+{
+  BaseFormPtr  bfp;
+  SeqEntryPtr  sep;
+  BioseqSetPtr bssp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) {
+    return;
+  }
+  bssp = FindTopLevelSetForDesktopFunction((BioseqSetPtr) sep->data.ptrvalue);
+  ApplySetTypeToInnerSets (bssp, bfp->input_entityID);
+}
+
+
+static Int2 LIBCALLBACK ApplySetTypeDesktop (Pointer data)
+{
+  OMProcControlPtr  ompcp;
+
+  ompcp = (OMProcControlPtr) data;
+  if (ompcp == NULL 
+      || ompcp->input_itemtype != OBJ_BIOSEQSET
+      || ompcp->input_data == NULL)
+  {
+    return OM_MSG_RET_ERROR;
+  }
+  ApplySetTypeToInnerSets (ompcp->input_data, ompcp->input_entityID);
+  return OM_MSG_RET_DONE;
+}
+
+
 static void DoPartSeqAlignToParent (DenseSegPtr dsp)
 
 {
@@ -3370,7 +3440,7 @@ static Boolean ReplaceAlignmentIDsFromFile (TAlignmentFilePtr afp, Int4 index)
     err_msg = (CharPtr) MemNew (err_msg_len * sizeof (Char));
     if (err_msg != NULL)
     {
-      sprintf (err_msg, err_msg_prefix);
+      sprintf (err_msg, "%s", err_msg_prefix);
       vnp = err_list;
       while (vnp != NULL && vnp->next != NULL)
       {
@@ -4537,7 +4607,7 @@ typedef struct sqn_bsp {
 
 static void SQNGetBioseqsProt(SeqEntryPtr sep, Pointer userdata, Int4 index, Int2 indent)
 {
-   BioseqPtr  bsp;
+   BioseqPtr  bsp = NULL;
    SQNBspPtr  sbp;
 
    if (sep == NULL || sep->data.ptrvalue == NULL || userdata == NULL)
@@ -5730,7 +5800,6 @@ extern Int2 AddSeqAlignForSeqEntry (SeqEntryPtr sep, Uint2 entityID, Boolean cho
 extern void GenerateSeqAlignMenuItem (IteM i)
 {
   BaseFormPtr   bfp;
-  BioseqSetPtr  bssp;
   SeqEntryPtr   sep;
 
 #ifdef WIN_MAC
@@ -5744,8 +5813,6 @@ extern void GenerateSeqAlignMenuItem (IteM i)
   if (sep == NULL || !IS_Bioseq_set (sep)) {
     Message (MSG_ERROR, "This record does not have a top-levelset!");
   } else {
-    bssp = FindTopLevelSetForDesktopFunction((BioseqSetPtr) sep->data.ptrvalue);
-    sep = SeqMgrGetSeqEntryForData (bssp);
     AddSeqAlignForSeqEntry (sep, bfp->input_entityID, FALSE, TRUE);
   }
 }
@@ -6697,12 +6764,14 @@ typedef struct makeexondata {
 
   ButtoN      make_introns_button;
   TexT        exon_number_field;
+  DialoG      constraint_dlg;
   ButtoN      accept;
 
   SeqEntryPtr sep;
   Boolean     make_introns;
   ObjectIdPtr first_exon_number;
   Uint1       feature_type;
+  ConstraintChoiceSetPtr constraint;
 } MakeExonData, PNTR MakeExonPtr;
 
 static void MakeExonsFromFeatureIntervalsVisitFunc (SeqFeatPtr sfp, Pointer userdata)
@@ -6710,7 +6779,9 @@ static void MakeExonsFromFeatureIntervalsVisitFunc (SeqFeatPtr sfp, Pointer user
   MakeExonPtr mep;
   BioseqPtr   bsp;
 
-  if (sfp == NULL || (mep = (MakeExonPtr) userdata) == NULL || sfp->idx.subtype != mep->feature_type)
+  if (sfp == NULL || (mep = (MakeExonPtr) userdata) == NULL 
+      || sfp->idx.subtype != mep->feature_type
+      || !DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, mep->constraint))
   {
     return;
   }
@@ -6743,10 +6814,12 @@ static void DoMakeExonsFromFeatureIntervals (ButtoN b)
             sizeof (exon_number_str) - 1 );
 
   mep->first_exon_number = ObjectIdFromString (exon_number_str);
+  mep->constraint = DialogToPointer (mep->constraint_dlg);
 
   VisitFeaturesInSep (mep->sep, mep, 
                       MakeExonsFromFeatureIntervalsVisitFunc);
   mep->first_exon_number = ObjectIdFree (mep->first_exon_number);
+  mep->constraint = ConstraintChoiceSetFree (mep->constraint);
   ObjMgrSetDirtyFlag (mep->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, mep->input_entityID, 0, 0);
   ArrowCursor ();
@@ -6814,12 +6887,14 @@ static void CommonMakeExonsFromFeatureIntervals (
   mep->exon_number_field = DialogText (p, "1", 3, CheckExonNumberText);
   SetObjectExtra (mep->exon_number_field, mep, NULL);
   mep->make_introns_button = CheckBox (p, "Make Introns", NULL);
+  mep->constraint_dlg = ComplexConstraintDialog(h, NULL, NULL);
+  ChangeComplexConstraintFieldType(mep->constraint_dlg, FieldType_cds_gene_prot, NULL, Feature_type_any);
 
   c = HiddenGroup (h, 4, 0, NULL);
   mep->accept = DefaultButton (c, "Accept", DoMakeExonsFromFeatureIntervals);
   SetObjectExtra (mep->accept, mep, NULL);
   PushButton (c, "Cancel", StdCancelButtonProc);
-  AlignObjects (ALIGN_CENTER, (HANDLE) p, (HANDLE) c, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) p, (HANDLE) mep->constraint_dlg, (HANDLE) c, NULL);
   RealizeWindow (w);
   Show (w);
   Update ();
@@ -9581,6 +9656,100 @@ extern void BioseqRevCompByIDMenuItem (IteM i)
 }
 
 
+static void DoRevQualScores (ButtoN b)
+{
+  RevCompByIdFrmPtr f;
+  SequenceConstraintXPtr scp;
+  ValNodePtr            bsp_list, vnp;
+  SeqEntryPtr           sep;
+
+  f = (RevCompByIdFrmPtr) GetObjectExtra (b);
+  if (f == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (f->input_entityID);
+  scp = DialogToPointer (f->sequence_constraint);
+  bsp_list = CollectBioseqsWithConstraint (sep, scp);
+  scp = SequenceConstraintXFree (scp);
+
+  if (bsp_list == NULL) 
+  {
+    Message (MSG_ERROR, "No sequences match constraint!");
+  }
+  else
+  {
+    for (vnp = bsp_list; vnp != NULL; vnp = vnp->next) 
+    {
+      ReverseQualityScores ((BioseqPtr) vnp->data.ptrvalue);
+    }
+    ObjMgrSetDirtyFlag (f->input_entityID, TRUE);
+    ObjMgrSendMsg (OM_MSG_UPDATE, f->input_entityID, 0, 0);
+    Remove (f->form);
+    Update();
+  }
+  bsp_list = ValNodeFree (bsp_list);
+}
+
+static Int2 LIBCALLBACK BioseqRevQualScoresForEntityID (Uint2 entityID)
+
+{
+  GrouP            c;
+  GrouP            h;
+  RevCompByIdFrmPtr f;
+  WindoW           w;
+
+  f = (RevCompByIdFrmPtr) MemNew (sizeof (RevCompByIdFrmData));
+  if (f == NULL) return OM_MSG_RET_ERROR;
+  w = FixedWindow (-50, -33, -10, -10, "Reverse Quality Scores", StdCloseWindowProc);
+  SetObjectExtra (w, f, StdCleanupFormProc);
+  f->form = (ForM) w;
+  f->formmessage = NULL;
+
+  f->input_entityID = entityID;
+
+  h = HiddenGroup (w, -1, 0, NULL);
+
+  f->sequence_constraint = SequenceConstraintXDialog (h);
+
+  c = HiddenGroup (h, 2, 0, NULL);
+  f->accept = DefaultButton (c, "Accept", DoRevQualScores);
+  SetObjectExtra (f->accept, f, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+  AlignObjects (ALIGN_CENTER, (HANDLE) f->sequence_constraint,
+                              (HANDLE) c, NULL);
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+  return OM_MSG_RET_DONE;
+}
+
+
+static Int2 LIBCALLBACK BioseqRevQualScores (Pointer data)
+
+{
+  OMProcControlPtr ompcp;
+
+  ompcp = (OMProcControlPtr) data;
+  if (ompcp == NULL) return OM_MSG_RET_ERROR;
+
+  return BioseqRevQualScoresForEntityID (ompcp->input_entityID);
+}
+
+
+extern void BioseqRevQualScoresMenuItem (IteM i)
+{
+  BaseFormPtr   bfp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  BioseqRevQualScoresForEntityID (bfp->input_entityID);
+}
+
+
 extern void ReverseComplementBioseqAndFeats (BioseqPtr bsp, Uint2 entityID)
 {
   SeqEntryPtr sep;
@@ -11221,6 +11390,7 @@ extern void SetupSequinFilters (void)
   REGISTER_STRUCTUREDCOMMENTUSER_DESC_EDIT;
   REGISTER_TPAASSEMBLYUSER_DESC_EDIT;
 
+  REGISTER_BIOSEQ_REVERSE_QUALITY_SCORES;
   REGISTER_BIOSEQ_COMPLEMENT;
   REGISTER_BIOSEQ_REVERSE;
   REGISTER_BIOSEQ_REVCOMP_WITHFEAT;
@@ -11265,6 +11435,7 @@ extern void SetupSequinFilters (void)
     REGISTER_INTERVAL_COMBINE_AND_FUSE;
     REGISTER_INTERVAL_COMBINE;
     REGISTER_REPACKAGE_PARTS;
+    REGISTER_APPLY_SET_TYPE;
     REGISTER_REMOVESET;
     REGISTER_REMOVESETSINSET;
     REGISTER_UNDOSEGSET;
@@ -11445,9 +11616,6 @@ static void CheckFeatForNuclID_callback (SeqFeatPtr sfp, Pointer userdata)
   if (NULL == sfp)
     return;
 
-  if ((sfp->data.choice == SEQFEAT_CDREGION) &&
-      (sfp->location != NULL)) {
-
     /* Get the old Seq Id and the new */
     /* one that it was changed to.    */
     
@@ -11474,7 +11642,6 @@ static void CheckFeatForNuclID_callback (SeqFeatPtr sfp, Pointer userdata)
     } else if (StringCmp (oip->str, idsPtr->oldStr) == 0){
       ReplaceIdForFeature (sfp, idsPtr->newSip);
     }
-  }
 }
 
 static void CheckFeatForProductID_callback (SeqFeatPtr sfp, Pointer userdata)
@@ -11527,7 +11694,7 @@ static void ReplaceLocalID (BioseqPtr bsp,
   ObjectIdPtr      oip;
   Char             str [64];
   Char             tmp [70];
-  BioseqSetPtr     bssp;
+  BioseqSetPtr     bssp = NULL;
   ReplaceIDStruct  ids;
   BioseqPtr        siblingBsp;
   SeqEntryPtr      sep;
@@ -11764,18 +11931,141 @@ static Boolean GetReconstructSegSetAnswer (void)
   return rd.ans;
 }
 
-static void SeqEntryHasAlignmentsCallback (SeqAnnotPtr sap, Pointer userdata)
+
+static Boolean DoesIdListHaveLocal (SeqIdPtr sip)
+{
+  while (sip != NULL) {
+    if (sip->choice == SEQID_LOCAL) {
+      return TRUE;
+    }
+    sip = sip->next;
+  }
+  return FALSE;
+}
+
+
+static Boolean DoesSeqLocListHaveLocalId (SeqLocPtr slp)
+{
+  SeqLocPtr      loc;
+  PackSeqPntPtr  psp;
+  SeqBondPtr     sbp;
+  SeqIntPtr      sinp;
+  SeqIdPtr       sip;
+  SeqPntPtr      spp;
+  Boolean        has_local = FALSE;
+
+  while (slp != NULL) {
+    switch (slp->choice) {
+      case SEQLOC_NULL :
+        break;
+      case SEQLOC_EMPTY :
+      case SEQLOC_WHOLE :
+        sip = (SeqIdPtr) slp->data.ptrvalue;
+        has_local = DoesIdListHaveLocal (sip);
+        break;
+      case SEQLOC_INT :
+        sinp = (SeqIntPtr) slp->data.ptrvalue;
+        if (sinp != NULL) {
+          sip = sinp->id;
+          has_local = DoesIdListHaveLocal (sip);
+        }
+        break;
+      case SEQLOC_PNT :
+        spp = (SeqPntPtr) slp->data.ptrvalue;
+        if (spp != NULL) {
+          sip = spp->id;
+          has_local = DoesIdListHaveLocal (sip);
+        }
+        break;
+      case SEQLOC_PACKED_PNT :
+        psp = (PackSeqPntPtr) slp->data.ptrvalue;
+        if (psp != NULL) {
+          sip = psp->id;
+          has_local = DoesIdListHaveLocal (sip);
+        }
+        break;
+      case SEQLOC_PACKED_INT :
+      case SEQLOC_MIX :
+      case SEQLOC_EQUIV :
+        loc = (SeqLocPtr) slp->data.ptrvalue;
+        while (loc != NULL && !has_local) {
+          has_local = DoesSeqLocListHaveLocalId(loc);
+          loc = loc->next;
+        }
+        break;
+      case SEQLOC_BOND :
+        sbp = (SeqBondPtr) slp->data.ptrvalue;
+        if (sbp != NULL) {
+          spp = (SeqPntPtr) sbp->a;
+          if (spp != NULL) {
+            sip = spp->id;
+            has_local = DoesIdListHaveLocal (sip);
+          }
+          spp = (SeqPntPtr) sbp->b;
+          if (spp != NULL) {
+            sip = spp->id;
+            has_local = DoesIdListHaveLocal (sip);
+          }
+        }
+        break;
+      case SEQLOC_FEAT :
+        break;
+      default :
+        break;
+    }
+    slp = slp->next;
+  }
+  return FALSE;
+}
+
+
+static void SeqEntryHasAlignmentsWithLocalIDsCallback (SeqAnnotPtr sap, Pointer userdata)
 {
+  DenseDiagPtr  ddp;
+  DenseSegPtr   dsp;
+  PackSegPtr    psp;
   SeqAlignPtr salp;
+  StdSegPtr     ssp;
+  Boolean       has_local = FALSE;
   BoolPtr     bp;
 
   if (sap == NULL || sap->type != 2 || userdata == NULL) return;
   salp = (SeqAlignPtr) sap->data;
   if (salp != NULL) 
   {
-    bp = (BoolPtr) userdata;
-    *bp = TRUE;
+    switch (salp->segtype) {
+      case SAS_DENDIAG :
+        for (ddp = salp->segs; ddp != NULL && !has_local; ddp = ddp->next) {
+          has_local = DoesIdListHaveLocal (ddp->id);
   }
+        break;
+      case SAS_DENSEG :
+        dsp = salp->segs;
+        if (dsp != NULL) {
+          has_local = DoesIdListHaveLocal (dsp->ids);
+        }
+        break;
+      case SAS_STD :
+        for (ssp = salp->segs; ssp != NULL && !has_local; ssp = ssp->next) {
+          has_local = DoesIdListHaveLocal (ssp->ids);
+          if (!has_local) {
+            has_local = DoesSeqLocListHaveLocalId (ssp->loc);
+          }
+        }
+        break;
+      case SAS_PACKED :
+        psp = (PackSegPtr) salp->segs;
+        if (psp != NULL) {
+          has_local = DoesIdListHaveLocal (psp->ids);
+        }
+        break;
+      default :
+        break;
+    }
+  }
+
+  bp = (BoolPtr) userdata;
+  *bp |= has_local;
 }
 
 static Boolean SeqEntryHasSegSets (SeqEntryPtr sep)
@@ -11809,16 +12099,21 @@ static void ResolveExistingLocalIDsBaseForm (BaseFormPtr bfp)
 {
   Boolean       doParts = FALSE, has_alignments = FALSE, has_segsets = FALSE;
   LclIdListPtr  head = NULL;
-  SeqEntryPtr   sep;
+  SeqEntryPtr   sep, oldscope;
 
   if (bfp == NULL) return;
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL) return;
   
-  VisitAnnotsInSep (sep, (Pointer) &has_alignments, SeqEntryHasAlignmentsCallback);
+  /* first, promote local IDs in alignments (if possible) */
+  oldscope = SeqEntrySetScope (sep);
+  VisitAnnotsInSep (sep, NULL, PromoteAlignIDsProc);
+  SeqEntrySetScope (oldscope);
+
+  VisitAnnotsInSep (sep, (Pointer) &has_alignments, SeqEntryHasAlignmentsWithLocalIDsCallback);
   if (has_alignments)
   {
-    if (ANS_CANCEL == Message (MSG_OKC, "This record has alignments.  You will need to repair the alignments manually if you resolve colliding IDs.  Do you want to continue?"))
+    if (ANS_CANCEL == Message (MSG_OKC, "This record has alignments with local IDs.  You will need to repair the alignments manually if you resolve colliding IDs.  Do you want to continue?"))
     {
       return;
     }
@@ -14262,11 +14557,10 @@ static Int4 GetPubStatus (PubPtr the_pub)
   ImprintPtr imp = NULL;
   Int4       status = PUB_STAT_ANY;
   
-  if (the_pub == NULL || the_pub->data.ptrvalue == NULL)
+  while (the_pub != NULL && status == PUB_STAT_ANY) 
+  {
+    if (the_pub->data.ptrvalue != NULL)
   {
-    return PUB_STAT_ANY;
-  }
-  
   switch (the_pub->choice)
   {
     case PUB_Gen :
@@ -14335,7 +14629,9 @@ static Int4 GetPubStatus (PubPtr the_pub)
     {
       status = PUB_STAT_UNPUBLISHED;
     }
-    
+      }
+    }
+    the_pub = the_pub->next;
   }
   return status;
 }
@@ -17619,3 +17915,1384 @@ static Int2 LIBCALLBACK CopyMasterSourceToSegments (Pointer data)
   return OM_MSG_RET_DONE;
 }
 
+
+static void RemoveSequenceFromAlignmentFile (TAlignmentFilePtr afp, CharPtr str)
+{
+  int pos, k;
+
+  if (afp == NULL) {
+    return;
+  }
+  for (pos = 0; pos < afp->num_sequences; pos++) {
+    if (StringCmp (str, afp->ids[pos]) == 0) {
+      free (afp->ids[pos]);
+      for (k = pos + 1; k < afp->num_sequences; k++) {
+        afp->ids[k - 1] = afp->ids[k];
+      }
+      free (afp->sequences[pos]);
+      for (k = pos + 1; k < afp->num_sequences; k++) {
+        afp->sequences[k - 1] = afp->sequences[k];
+      }
+      afp->num_sequences--;
+      if (pos < afp->num_organisms) {
+        free (afp->organisms[pos]);
+        for (k = pos + 1; k < afp->num_organisms; k++) {
+          afp->organisms[k - 1] = afp->organisms[k];
+        }
+        afp->num_organisms--;
+      }
+      if (pos < afp->num_deflines) {
+        free (afp->deflines[pos]);
+        for (k = pos + 1; k < afp->num_deflines; k++) {
+          afp->deflines[k - 1] = afp->deflines[k];
+        }
+        afp->num_deflines--;
+      }
+    }
+  }
+}
+
+
+static SeqAlignPtr ReadAlignmentForSeqEntry (SeqEntryPtr sep, Boolean is_nuc, Boolean allow_options)
+{
+  Char              path [PATH_MAX];
+  FILE              *fp;
+  SeqAlignPtr       salp=NULL,
+                    salpnew, salp_return = NULL;
+  SeqEntryPtr       sepnew=NULL;
+  Boolean           ok = TRUE, 
+                    dirty = FALSE;
+  TSequenceInfoPtr  default_info, sequence_info;
+  ReadBufferData    rbd;
+  TErrorInfoPtr     error_list;
+  TAlignmentFilePtr afp;
+  Uint1             moltype;
+  ErrSev            sev;
+  SeqEntryPtr       scope;
+
+  if (sep == NULL) return NULL;
+
+  if (GetInputFileName (path, sizeof (path), NULL, "TEXT")) {
+    fp = FileOpen (path, "r");
+    if (fp != NULL) {      
+      default_info = SequenceInfoNew ();
+      if (is_nuc) {
+        default_info->alphabet = nucleotide_alphabet;
+      } else {
+        default_info->alphabet = protein_alphabet;
+      }
+      default_info->beginning_gap = MemFree (default_info->beginning_gap);
+      default_info->beginning_gap = StringSave ("-.Nn?");
+      default_info->middle_gap = MemFree (default_info->middle_gap);
+      default_info->middle_gap = StringSave ("-.#");
+      default_info->end_gap = MemFree (default_info->end_gap);
+      default_info->end_gap = StringSave ("-.Nn?");
+      default_info->match = MemFree (default_info->match);
+      default_info->match = StringSave (":");
+      default_info->missing = MemFree (default_info->missing);
+      default_info->missing = StringSave ("?Nn");
+
+      if (allow_options) {
+        sequence_info = GetAlignmentOptions (&moltype, default_info);
+        SequenceInfoFree (default_info);
+        if (sequence_info == NULL) return NULL;
+        default_info = sequence_info;
+      }
+
+      WatchCursor();
+      error_list = NULL;
+
+      rbd.fp = fp;
+      rbd.current_data = NULL;
+      afp = ReadAlignmentFile ( AbstractReadFunction,
+                                (Pointer) &rbd,
+                                AbstractReportError,
+                                (Pointer) &error_list,
+                                default_info);
+      SequenceInfoFree (default_info);
+      default_info = NULL;
+      if (afp != NULL) 
+      {
+        RemoveSequenceFromAlignmentFile (afp, "Consensus");
+        SeqEntrySetScope (sep);
+        if (CorrectAlignmentIDs (afp, moltype))
+        {
+          sepnew = MakeSequinDataFromAlignmentEx (afp, moltype, TRUE); 
+        }
+      }
+      if (sepnew == NULL) {
+        ProduceAlignmentNotes (afp, error_list);
+      }
+      ErrorInfoFree (error_list);
+      AlignmentFileFree (afp);
+      if (sepnew) 
+      {
+        salpnew = (SeqAlignPtr) FindSeqAlignInSeqEntry (sepnew, OBJ_SEQALIGN);
+        if (salpnew) {
+          sev = ErrSetMessageLevel (SEV_FATAL);
+
+          scope = SeqEntrySetScope (NULL);
+          /* adjust the start positions for the sequences read in from the alignments. */
+          CalculateAlignmentOffsets (sepnew, sep);
+          /* ValidateSeqAlignandACCInSeqEntry will readjust the start positions for
+           * the alignments for far pointer sequences.
+           */
+          SeqEntrySetScope (scope);
+          ok = ValidateSeqAlignandACCInSeqEntry (sepnew, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE);
+          
+          ErrSetMessageLevel (sev);
+          
+          if (ok) {
+            AlnMgr2IndexSeqAlignEx(salpnew, FALSE);
+            ok = CheckAlignmentSequenceLengths (salpnew);
+          }
+          
+          if (ok) {
+            /* make copy, otherwise it will be removed when we delete sep_new */
+            salp_return = (SeqAlignPtr) AsnIoMemCopy (salpnew, (AsnReadFunc) SeqAlignAsnRead,
+                                                       (AsnWriteFunc) SeqAlignAsnWrite);
+          }
+        }
+        /* this statement will free salpnew as part of sepnew */
+        ObjMgrFree (OBJ_SEQENTRY, (Pointer)sepnew);
+        sepnew=NULL;
+      }
+      ArrowCursor();
+      Update ();
+    }
+  }
+  return salp_return;
+}
+
+
+static void GetNonPartialProteinsCallback (BioseqPtr bsp, Pointer userdata)
+{
+  SeqDescPtr        sdp;
+  SeqMgrDescContext context;
+  MolInfoPtr        mip;
+
+  if (bsp != NULL && ISA_aa(bsp->mol) && userdata != NULL) {
+    sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
+    /* we don't want to consider the ones that are 3' partial */
+    if (sdp != NULL && (mip = (MolInfoPtr) sdp->data.ptrvalue) != NULL
+        && mip->completeness != 4 /* no right */
+        && mip->completeness != 5 /* no ends */) {
+      ValNodeAddPointer ((ValNodePtr PNTR) userdata, OBJ_BIOSEQ, bsp);
+    }
+  }
+}
+
+
+static SeqAlignPtr GetNonPartialProtAlign (SeqEntryPtr sep)
+{
+  ValNodePtr protein_list = NULL;
+  ValNodePtr vnp;
+  SeqAlignPtr salp_head = NULL, salp_prev = NULL, salp, salp_tmp, salp_mult = NULL;
+  BioseqPtr   master_bsp;
+
+  if (sep == NULL) 
+  {
+    return NULL;
+  }
+
+  /* get list of protein sequences */
+  VisitBioseqsInSep (sep, &protein_list, GetNonPartialProteinsCallback);
+  if (protein_list == NULL || protein_list->next == NULL) 
+  {
+    protein_list = ValNodeFree (protein_list);
+    return NULL;
+  }
+
+  /* now get protein alignment */
+  master_bsp = protein_list->data.ptrvalue;
+  for (vnp = protein_list->next; vnp != NULL; vnp = vnp->next) 
+  {
+    salp = Sequin_GlobalAlign2Seq(master_bsp, vnp->data.ptrvalue, FALSE);
+    if (salp_head != NULL && salp != NULL)
+    {
+      salp_prev->next = salp;
+      salp_prev = salp;
+    } 
+    else if (salp != NULL)
+    {
+      salp_head = salp_prev = salp;
+    }
+  }
+  /* clean up protein list now that we are done with it */
+  protein_list = ValNodeFree (protein_list);
+
+  if (salp_head != NULL)
+  {
+    salp_tmp = salp_head;
+    while (salp_tmp != NULL)
+    {
+       if (salp_tmp->saip != NULL)
+       {
+          SeqAlignIndexFree(salp_tmp->saip);
+          salp_tmp->saip = NULL;
+       }
+       salp_tmp = salp_tmp->next;
+    }
+    AlnMgr2IndexSeqAlign(salp_head);
+    salp_mult = AlnMgr2GetSubAlign(salp_head, 0, -1, 0, TRUE);
+    salp_mult->dim = AlnMgr2GetNumRows(salp_head);
+    salp_mult->type = SAT_PARTIAL;
+    FixAlignmentEndStubs (salp_mult);
+  }
+
+  return salp_mult;
+}
+
+
+/* returns list of SeqIds that must be freed */
+static ValNodePtr GetAccessionListForTruncateFromAlign (SeqAlignPtr salp, Int4 num_missing)
+{
+  ValNodePtr        trunc_list = NULL;
+  Int4              aln_len, i, start_seq, stop_seq, aln_pos;
+  SeqIdPtr          sip;
+  BioseqPtr         bsp;
+  MolInfoPtr        mip;
+  SeqDescPtr        sdp;
+  SeqMgrDescContext context;
+
+  if (salp == NULL || num_missing < 1) {
+    return NULL;
+  }
+  AlnMgr2IndexSeqAlign(salp);
+  aln_len = AlnMgr2GetAlnLength (salp, TRUE);
+  for (i = 0; i < salp->dim; i++) {
+    sip = AlnMgr2GetNthSeqIdPtr (salp, i + 1);
+    bsp = BioseqFind (sip);
+    if (bsp) {
+      sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
+      /* we don't want to consider the ones that are 3' partial */
+      if (sdp != NULL && (mip = (MolInfoPtr) sdp->data.ptrvalue) != NULL
+          && mip->completeness != 4 /* no right */
+          && mip->completeness != 5 /* no ends */) {      
+        AlnMgr2GetNthSeqRangeInSA(salp, i + 1, &start_seq, &stop_seq);
+        aln_pos = AlnMgr2MapBioseqToSeqAlign(salp, stop_seq, i + 1);
+        if (aln_len - aln_pos >= num_missing) {
+          ValNodeAddPointer (&trunc_list, 0, sip);
+          sip = NULL;
+        }
+      }
+    }
+    sip = SeqIdFree (sip);
+  }
+  return trunc_list;
+}
+
+
+typedef struct truncatebyprotalign {
+  FORM_MESSAGE_BLOCK
+
+  TexT num_missing;
+
+  SeqAlignPtr salp;
+} TruncateByProtAlignData, PNTR TruncateByProtAlignPtr;
+
+
+static void CleanupTruncateByProtAlignForm (GraphiC g, VoidPtr data)
+{
+  TruncateByProtAlignPtr dlg;
+
+  dlg = (TruncateByProtAlignPtr) data;
+  if (dlg != NULL) {
+    dlg->salp = SeqAlignFree (dlg->salp);
+  }
+  StdCleanupFormProc (g, data);
+}
+
+
+
+static void ShowTruncateList (ButtoN b)
+{
+  TruncateByProtAlignPtr dlg;
+  SeqEntryPtr            sep;
+  SeqAlignPtr            salp;
+  ValNodePtr             trunc_list, vnp;
+  CharPtr                val;
+  Int4                   num_missing;
+  LogInfoPtr             lip;
+  Char                   id_str[200];
+
+  dlg = (TruncateByProtAlignPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  val = SaveStringFromText (dlg->num_missing);
+  if (StringHasNoText (val)) {
+    val = MemFree (val);
+    return;
+  }
+  num_missing = atoi (val);
+  val = MemFree (val);
+
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+  if (dlg->salp == NULL) {
+    salp = GetNonPartialProtAlign (sep);
+  } else {
+    salp = dlg->salp;
+  }
+  trunc_list = GetAccessionListForTruncateFromAlign(salp, num_missing);
+  if (dlg->salp == NULL) {
+    salp = SeqAlignFree (salp);
+  }
+
+  lip = OpenLog ("Accessions");
+  for (vnp = trunc_list; vnp != NULL; vnp = vnp->next) {
+    SeqIdWrite (vnp->data.ptrvalue, id_str, PRINTID_FASTA_LONG, sizeof (id_str) - 1);
+    fprintf (lip->fp, "%s\n", id_str);
+    lip->data_in_log = TRUE;
+  }
+  if (!lip->data_in_log) {
+    fprintf (lip->fp, "No accessions found\n");
+    lip->data_in_log = TRUE;
+  }
+  CloseLog (lip);
+  lip = FreeLog (lip);
+
+  for (vnp = trunc_list; vnp != NULL; vnp = vnp->next) {
+    vnp->data.ptrvalue = SeqIdFree (vnp->data.ptrvalue);
+  }
+  trunc_list = ValNodeFree (trunc_list);
+}
+
+
+static void MarkTruncateList (ButtoN b)
+{
+  TruncateByProtAlignPtr dlg;
+  SeqEntryPtr            sep;
+  SeqAlignPtr            salp;
+  ValNodePtr             trunc_list, vnp;
+  CharPtr                val;
+  Int4                   num_missing;
+  BioseqPtr              prot_bsp;
+  SeqFeatPtr             sfp, cds, mrna;
+  SeqMgrFeatContext      context;
+  ProtRefPtr             prp;
+  CharPtr                orig_val, new_val;
+  RnaRefPtr              rrp;
+
+  dlg = (TruncateByProtAlignPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  val = SaveStringFromText (dlg->num_missing);
+  if (StringHasNoText (val)) {
+    val = MemFree (val);
+    return;
+  }
+  num_missing = atoi (val);
+  val = MemFree (val);
+
+  sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
+  if (dlg->salp == NULL) {
+    salp = GetNonPartialProtAlign (sep);
+  } else {
+    salp = dlg->salp;
+  }
+  trunc_list = GetAccessionListForTruncateFromAlign(salp, num_missing);
+  if (dlg->salp == NULL) {
+    salp = SeqAlignFree (salp);
+  }
+
+  for (vnp = trunc_list; vnp != NULL; vnp = vnp->next) {
+    prot_bsp = BioseqFind (vnp->data.ptrvalue);
+    sfp = SeqMgrGetNextFeature (prot_bsp, NULL, 0, FEATDEF_PROT, &context);
+    if (sfp != NULL && (prp = (ProtRefPtr) sfp->data.value.ptrvalue) != NULL) {
+      if (prp->name == NULL) {
+        ValNodeAddPointer (&(prp->name), 0, StringSave ("truncated"));
+      } else {
+        orig_val = prp->name->data.ptrvalue;
+        if (StringNCmp (orig_val, "truncated ", 10) != 0) {
+          new_val = (CharPtr) MemNew (sizeof (Char) * (StringLen (orig_val) + 11));
+          sprintf (new_val, "truncated %s", orig_val);
+          orig_val = MemFree (orig_val);
+          prp->name->data.ptrvalue = new_val;
+          cds = SeqMgrGetCDSgivenProduct (prot_bsp, NULL);
+          if (cds != NULL) {
+            mrna = SeqMgrGetOverlappingmRNA (cds->location, &context);
+            if (mrna != NULL) {
+              rrp = (RnaRefPtr) mrna->data.value.ptrvalue;
+              if (rrp->ext.choice == 1) {
+                rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
+                rrp->ext.value.ptrvalue = StringSave (new_val);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+        
+  for (vnp = trunc_list; vnp != NULL; vnp = vnp->next) {
+    vnp->data.ptrvalue = SeqIdFree (vnp->data.ptrvalue);
+  }
+  trunc_list = ValNodeFree (trunc_list);
+
+  ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
+  Update ();
+}
+
+
+NLM_EXTERN void TruncateByProtAlign (IteM i)
+{
+  BaseFormPtr  bfp;
+  TruncateByProtAlignPtr dlg;
+  WindoW       w;
+  GrouP        h, g, c;
+  ButtoN       b;
+  SeqEntryPtr  sep;
+  SeqAlignPtr  salp;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) return;
+  salp = ReadAlignmentForSeqEntry (sep, FALSE, TRUE);
+  if (salp == NULL) {
+    return;
+  }
+
+  dlg = (TruncateByProtAlignPtr) MemNew (sizeof (TruncateByProtAlignData));
+  dlg->input_entityID = bfp->input_entityID;
+
+  dlg->salp = salp;
+
+  w = FixedWindow (-50, -33, -10, -10, "Mark Truncated Products by Protein Alignment", StdCloseWindowProc);
+  SetObjectExtra (w, dlg, StdCleanupExtraProc);
+  dlg->form = (ForM) w;
+    
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+  
+  g = HiddenGroup (h, 2, 0, NULL);
+  StaticPrompt (g, "Missing amino acids for truncation:", 0, dialogTextHeight, programFont, 'r');
+  dlg->num_missing = DialogText (g, "10", 0, NULL);
+  c = HiddenGroup (h, 4, 0, NULL);
+  SetGroupSpacing (c, 10, 10);
+
+  b = PushButton (c, "Make List", ShowTruncateList);
+  SetObjectExtra (b, dlg, NULL);
+  b = PushButton (c, "Mark List", MarkTruncateList);
+  SetObjectExtra (b, dlg, NULL);
+  
+  b = PushButton (c, "Dismiss", StdCancelButtonProc);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+}
+
+typedef struct exoninterval {
+  Int4 start;
+  Int4 stop;
+} ExonIntervalData, PNTR ExonIntervalPtr;
+
+
+static ExonIntervalPtr ExonIntervalNew (Int4 start, Int4 stop)
+{
+  ExonIntervalPtr p = (ExonIntervalPtr) MemNew (sizeof (ExonIntervalData));
+  if (start < stop) {
+    p->start = start;
+    p->stop = stop;
+  } else {
+    p->start = stop;
+    p->stop = start;
+  }
+  return p;
+}
+
+
+static int LIBCALLBACK SortExonIntervals (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr      vnp1, vnp2;
+  ExonIntervalPtr p1, p2;
+  
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      p1 = (ExonIntervalPtr) vnp1->data.ptrvalue;
+      p2 = (ExonIntervalPtr) vnp2->data.ptrvalue;
+      if (p1 != NULL && p2 != NULL) {
+        if (p1->start < p2->start)
+        {
+          return -1;
+        }
+        else if (p1->start > p2->start)
+        {
+          return 1;
+        }
+        else if (p1->stop < p2->stop)
+        {
+          return -1;
+        }
+        else if (p1->stop > p2->stop)
+        {
+          return 1;
+        }
+        else
+        {
+          return 0;
+        }
+      }
+    }
+  }
+  return 0;
+}
+
+
+typedef struct exonintervallist {
+  ExonIntervalPtr intervals;
+  Int4            num_intervals;
+} ExonIntervalListData, PNTR ExonIntervalListPtr;
+
+
+static ExonIntervalListPtr ExonIntervalListFree (ExonIntervalListPtr list)
+{
+  if (list != NULL) {
+    list->intervals = MemFree (list->intervals);
+    list = MemFree (list);
+  }
+  return list;
+}
+
+
+static ExonIntervalListPtr ExonIntervalListNew (ValNodePtr interval_list)
+{
+  ExonIntervalListPtr list = NULL;
+  ExonIntervalPtr     exint;
+  ValNodePtr          vnp;
+  Int4                i;
+
+  list = (ExonIntervalListPtr) MemNew (sizeof (ExonIntervalListData));
+  list->num_intervals = ValNodeLen (interval_list);
+  if (list->num_intervals == 0) {
+    list->intervals = NULL;
+  } else {
+    list->intervals = (ExonIntervalPtr) MemNew (sizeof (ExonIntervalData) * list->num_intervals);
+    for (vnp = interval_list, i = 0; vnp != NULL; vnp = vnp->next, i++) {
+      exint = (ExonIntervalPtr) vnp->data.ptrvalue;
+      list->intervals[i].start = exint->start;
+      list->intervals[i].stop = exint->stop;
+    }
+  }
+  return list; 
+}
+
+
+static ExonIntervalListPtr GetExonIntervalsForBioseq (BioseqPtr bsp)
+{
+  SeqFeatPtr sfp;
+  SeqMgrFeatContext fcontext;
+  ExonIntervalListPtr list = NULL;
+  ValNodePtr unsorted_list = NULL;
+  SeqLocPtr  slp;
+  Int4       num_intervals = 0;
+
+  if (bsp == NULL || ISA_aa (bsp->mol)) {
+    return NULL;
+  }
+
+  for (sfp = SeqMgrGetNextFeature(bsp, NULL, 0, FEATDEF_CDS, &fcontext);
+       sfp != NULL;
+       sfp = SeqMgrGetNextFeature(bsp, sfp, 0, FEATDEF_CDS, &fcontext)) {
+    for (slp = SeqLocFindNext (sfp->location, NULL);
+         slp != NULL;
+         slp = SeqLocFindNext (sfp->location, slp)) {
+      ValNodeAddPointer (&unsorted_list, 0, ExonIntervalNew (SeqLocStart (slp), SeqLocStop (slp)));
+      num_intervals++;
+    }
+  }
+
+  for (sfp = SeqMgrGetNextFeature(bsp, NULL, 0, FEATDEF_exon, &fcontext);
+       sfp != NULL;
+       sfp = SeqMgrGetNextFeature(bsp, sfp, 0, FEATDEF_exon, &fcontext)) {
+    for (slp = SeqLocFindNext (sfp->location, NULL);
+         slp != NULL;
+         slp = SeqLocFindNext (sfp->location, slp)) {
+      ValNodeAddPointer (&unsorted_list, 0, ExonIntervalNew (SeqLocStart (slp), SeqLocStop (slp)));
+      num_intervals++;
+    }
+  }
+
+  if (num_intervals > 0) {
+    unsorted_list = ValNodeSort (unsorted_list, SortExonIntervals);
+    ValNodeUnique (&unsorted_list, SortExonIntervals, ValNodeFreeData);
+    list = ExonIntervalListNew(unsorted_list);
+    unsorted_list = ValNodeFreeData (unsorted_list);
+  }
+  return list;
+}
+
+
+static Boolean IsPointInExon (Int4 pos, ExonIntervalListPtr list)
+{
+  Int4 i = 0;
+  Boolean found = FALSE;
+
+  if (list == NULL) {
+    return FALSE;
+  }
+
+  /* looking for interval that contains pos */
+  while (i < list->num_intervals && !found && list->intervals[i].start <= pos) {
+    if (list->intervals[i].stop >= pos) {
+      found = TRUE;
+    }
+    i++;
+  }
+  return found;
+}
+
+
+static ExonIntervalListPtr GetAlignedExons
+(DenseSegPtr              dsp, 
+ Int4                     examine_dim)
+{
+  Int4 seg, i, j;
+  Int4 aln_pos = 1, start = -1;
+  Boolean in_exon = FALSE;
+  ValNodePtr align_intervals = NULL;
+  ExonIntervalListPtr list = NULL;
+  ExonIntervalListPtr PNTR exon_lists;
+  SeqIdPtr sip;
+  BioseqPtr bsp;
+
+  /* create lists of exons for individual sequences */
+  exon_lists = (ExonIntervalListPtr PNTR) MemNew (sizeof (ExonIntervalListPtr) * examine_dim);
+  for (sip = dsp->ids, i = 0; sip != NULL && i < examine_dim; sip = sip->next, i++) {
+    bsp = BioseqLockById (sip);
+    exon_lists[i] = GetExonIntervalsForBioseq(bsp);
+    BioseqUnlock (bsp);
+  }
+
+  for (seg = 0; seg < dsp->numseg; seg++) {
+    for (j = 0; j < dsp->lens[seg]; j++) {
+      in_exon = FALSE;
+      for (i = 0; i < examine_dim && !in_exon; i++) {
+        if (dsp->starts[seg * dsp->dim + i] != -1
+            && IsPointInExon(dsp->starts[seg * dsp->dim + i] + j, exon_lists[i])) {
+          in_exon = TRUE;
+        }
+      }
+      if (in_exon) {
+        if (start < 0) {
+          /* found the beginning of an interval */
+          start = aln_pos;
+        }
+      } else {
+        if (start > -1) {
+          /* found the end of an interval */
+          ValNodeAddPointer (&align_intervals, 0, ExonIntervalNew(start, aln_pos - 1));
+          start = -1;
+        }
+      }
+      aln_pos++;
+    }
+  }
+
+  /* free individual sequence exon lists */
+  for (i = 0; i < examine_dim; i++) {
+    exon_lists[i] = ExonIntervalListFree(exon_lists[i]);
+  }
+  exon_lists = MemFree (exon_lists);
+
+  if (align_intervals != NULL) {
+    list = ExonIntervalListNew (align_intervals);
+    align_intervals = ValNodeFreeData (align_intervals);
+  }
+    
+  return list;
+}
+
+
+typedef enum {
+  eFrameShiftReport_NoReport = 0,
+  eFrameShiftReport_Intron = 1,
+  eFrameShiftReport_Exon = 2,
+  eFrameShiftReport_ExonMult3 = 3
+} EFrameShiftReport;
+
+
+static CharPtr FrameShiftReportString (EFrameShiftReport flag, Int4 aln_pos, Int4 gap, Int4 non_gap, Int4Ptr report, Int4 len, CharPtr fmt, CharPtr ids)
+{
+  CharPtr msg = NULL;
+  Int4    num_items = 0, i, msg_len;
+  Boolean first = TRUE;
+  CharPtr gap_fmt = "Gap: %d Non-gap: %d\n";
+
+  for (i = 0; i < len; i++) {
+    if (report[i] == flag) {
+      num_items++;
+    }
+  }
+
+  if (num_items == 0) {
+    return NULL;
+  }
+
+  msg_len = StringLen (fmt) + StringLen (gap_fmt) + 30 + (num_items * 204);
+  msg = (CharPtr) MemNew (sizeof (CharPtr) * msg_len);
+  sprintf (msg, fmt, aln_pos);
+  sprintf (msg + StringLen (msg), gap_fmt, gap, non_gap);
+  num_items = 0;
+  for (i = 0; i < len; i++) {
+    if (report[i] == flag) {
+      if (!first) {
+        StringCat (msg, ", ");
+        if (num_items % 10 == 0) {
+          StringCat (msg, "\n");
+        }
+      }
+      StringCat (msg, ids + (200 * i));
+      first = FALSE;
+      num_items++;
+    }
+  }
+  return msg;
+}
+
+
+static CharPtr FrameShiftReportMult (Int4 aln_pos, Int4Ptr report, Int4 len, CharPtr fmt, CharPtr ids)
+{
+  CharPtr msg = NULL;
+  Int4    num_items = 0, i, msg_len;
+  Boolean first = TRUE;
+
+  for (i = 0; i < len; i++) {
+    if (report[i] == eFrameShiftReport_ExonMult3) {
+      num_items++;
+    }
+  }
+
+  if (num_items == 0) {
+    return NULL;
+  }
+
+  msg_len = StringLen (fmt) + (num_items * 204);
+  msg = (CharPtr) MemNew (sizeof (CharPtr) * msg_len);
+  sprintf (msg, fmt, aln_pos);
+  num_items = 0;
+  for (i = 0; i < len; i++) {
+    if (report[i] == eFrameShiftReport_ExonMult3) {
+      if (!first) {
+        StringCat (msg, ", ");
+        if (num_items % 10 == 0) {
+          StringCat (msg, "\n");
+        }
+      }
+      StringCat (msg, ids + (200 * i));
+      first = FALSE;
+      num_items++;
+    }
+  }
+  return msg;
+}
+
+
+typedef struct frameshiftreport {
+  CharPtr msg;
+  Int4    aln_pos;
+  Int4    first_related_seq;
+} FrameShiftReportData, PNTR FrameShiftReportPtr;
+
+
+static FrameShiftReportPtr FrameShiftReportNew (CharPtr msg, Int4 aln_pos, Int4 first_related_seq)
+{
+  FrameShiftReportPtr r = (FrameShiftReportPtr) MemNew (sizeof (FrameShiftReportData));
+  r->msg = msg;
+  r->aln_pos = aln_pos;
+  r->first_related_seq = first_related_seq;
+  return r;
+}
+
+
+static FrameShiftReportPtr FrameShiftReportFree (FrameShiftReportPtr r)
+{
+  if (r != NULL) {
+    r->msg = MemFree (r->msg);
+    r = MemFree (r);
+  }
+  return r;
+}
+
+
+static ValNodePtr FrameShiftReportListFree (ValNodePtr vnp)
+{
+  ValNodePtr tmp;
+
+  while (vnp != NULL) {
+    tmp = vnp->next;
+    vnp->next = NULL;
+    vnp->data.ptrvalue = FrameShiftReportFree (vnp->data.ptrvalue);
+    vnp = ValNodeFree (vnp);
+    vnp = tmp;
+  }
+  return vnp;
+}
+
+
+static int FrameShiftReportCompare (FrameShiftReportPtr r1, FrameShiftReportPtr r2)
+{
+  if (r1 == NULL && r2 == NULL) {
+    return 0;
+  } else if (r1 == NULL) {
+    return -1;
+  } else if (r2 == NULL) {
+    return 1;
+  } else if (r1->aln_pos < r2->aln_pos) {
+    return -1;
+  } else if (r1->aln_pos > r2->aln_pos) {
+    return 1;
+  } else {
+    return StringCmp (r1->msg, r2->msg);
+  }
+}
+
+
+static int LIBCALLBACK SortFrameShiftReports (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr      vnp1, vnp2;
+  
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      if (vnp1->choice == vnp2->choice) {
+        return FrameShiftReportCompare(vnp1->data.ptrvalue, vnp2->data.ptrvalue);
+      } else if (vnp1->choice == eFrameShiftReport_Exon) {
+        return -1;
+      } else if (vnp2->choice == eFrameShiftReport_Exon) {
+        return 1;
+      } else if (vnp1->choice == eFrameShiftReport_Intron) {
+        return -1;
+      } else if (vnp2->choice == eFrameShiftReport_Intron) {
+        return 1;
+      } else if (vnp1->choice == eFrameShiftReport_ExonMult3) {
+        return -1;
+      } else if (vnp2->choice == eFrameShiftReport_ExonMult3) {
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+
+static void PrintFrameShiftReportList (ValNodePtr list, Boolean has_exons, LogInfoPtr lip)
+{
+  ValNodePtr          vnp;
+  FrameShiftReportPtr r;
+  EFrameShiftReport section = eFrameShiftReport_NoReport;
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice != section) {
+      if (vnp->choice == eFrameShiftReport_Exon) {
+        fprintf (lip->fp, "FRAMESHIFTS IN EXONS\n\n");
+      } else if (vnp->choice == eFrameShiftReport_Intron) {
+        if (has_exons) {
+          fprintf (lip->fp, "FRAMESHIFTS IN INTRONS\n\n");
+        } else {
+          fprintf (lip->fp, "FRAMESHIFTS\n\n");
+        }
+      } else if (vnp->choice == eFrameShiftReport_ExonMult3) {
+        fprintf (lip->fp, "MULTIPLES OF THREE ARE IGNORED\n\n");
+      }
+      section = vnp->choice;
+    }
+    if ((r = (FrameShiftReportPtr) vnp->data.ptrvalue) != NULL) {
+      fprintf (lip->fp, "%s\n\n", r->msg);
+      lip->data_in_log = TRUE;
+    }
+  }
+}
+
+
+static Int4 LenBeforeBoundary (Int4 i, Int4 seg, Int4 offset, Int4 aln_pos,
+                               DenseSegPtr dsp, ExonIntervalListPtr exon_intervals)
+{
+  Int4    len = 1;
+  Boolean is_gap;
+  Boolean is_exon;
+  Boolean found_boundary = FALSE;
+
+  if (dsp == NULL) {
+    return 1;
+  }
+
+  if (dsp->starts[dsp->dim * seg + i] == -1) {
+    is_gap = TRUE;
+  } else {
+    is_gap = FALSE;
+  }
+
+  is_exon = IsPointInExon (aln_pos, exon_intervals);
+
+  offset++;
+  aln_pos++;
+  while (seg < dsp->numseg && !found_boundary) {
+    while (offset < dsp->lens[seg] && !found_boundary) {
+      if (IsPointInExon(aln_pos, exon_intervals) != is_exon) {
+        found_boundary = TRUE;
+      } else {
+        len++;
+        offset++;
+        aln_pos++;
+      }
+    }
+
+    if (!found_boundary) {
+      seg++;
+      offset = 0;
+      if (seg < dsp->numseg) {
+        if (dsp->starts[dsp->dim * seg + i] == -1 && !is_gap) {
+          found_boundary = TRUE;
+        } else if (dsp->starts[dsp->dim * seg + i] != -1 && is_gap) {
+          found_boundary = TRUE;
+        }
+      }
+    }
+  }
+
+  return len;
+}
+
+
+static Int4 
+FindFirstSeqWithProblem 
+(Int4Ptr report, BoolPtr current_gap_ignore, Int4 num,
+ EFrameShiftReport report_type, Int4 num_gap, Int4 num_non_gap)
+{
+  Int4 i;
+
+  if (num_non_gap >= num_gap) {
+    for (i = 0; i < num; i++) {
+      if (current_gap_ignore[i]) {
+        /* don't report this one */
+      } else if (report[i] == report_type) {
+        return i;
+      }
+    }
+  } else {
+    /* look for transition between problem/not-problem */
+    for (i = 0; i < num; i++) {
+      if (report[i] == report_type) {
+        if (i < num - 1 && report[i + 1] != report_type) {
+          return i;
+        } else if (i > 0 && report[i - 1] != report_type) {
+          return i;
+        }
+      }
+    }
+  }
+
+  return -1;
+}
+
+
+static ValNodePtr FindFrameShiftsInAlignment (SeqAlignPtr salp, BoolPtr has_exons)
+{
+  DenseSegPtr dsp;
+  Int4        seg, i, j, aln_pos = 1, len_gap, extend;
+  Int4        num_gap, num_non_gap;
+  BoolPtr     current_gap_ignore = NULL;
+  Int4Ptr     current_gap_examined = NULL, gap_mult3 = NULL;
+  Int4Ptr     report = NULL;
+  Boolean     any_report;
+  Int4        num_mult;
+  CharPtr     ids = NULL;
+  ValNodePtr  exon_list = NULL, report_list = NULL;
+  SeqIdPtr    sip;
+  Int4        examine_dim;
+  CharPtr     msg;
+  CharPtr     exon_insert_fmt = "Insertion in exon at position %d:\n";
+  CharPtr     exon_delete_fmt = "Deletion in exon at position %d:\n";
+  CharPtr     intron_insert_fmt = "Insertion at position %d:\n";
+  CharPtr     intron_delete_fmt = "Deletion at position %d:\n";
+  CharPtr     mult_fmt = "Ignored multiple of 3 at %d:\n";
+  ExonIntervalListPtr exon_intervals;
+  Int4        first_related_seq;
+
+  if (salp == NULL) {
+    return NULL;
+  }
+
+  if (salp->segtype != SAS_DENSEG || (dsp = (DenseSegPtr) salp->segs) == NULL) {
+    return NULL;
+  }
+  ids = (CharPtr) MemNew (sizeof (Char) * dsp->dim * 200);
+  for (sip = dsp->ids, i = 0; sip != NULL; sip = sip->next, i++) {
+    SeqIdWrite (sip, ids + (200 * i), PRINTID_REPORT, 199);
+  }
+  if (StringCmp (ids + (200 * (dsp->dim - 1)), "Consensus") == 0) {
+    examine_dim = dsp->dim - 1;
+  } else {
+    examine_dim = dsp->dim;
+  }
+
+  current_gap_examined = (Int4Ptr) MemNew (sizeof (Int4) * examine_dim);
+  gap_mult3 = (Int4Ptr) MemNew (sizeof (Int4Ptr) * examine_dim);
+  current_gap_ignore = (BoolPtr) MemNew (sizeof (Boolean) * examine_dim);
+  report = (Int4Ptr) MemNew (sizeof (Int4) * examine_dim);
+  for (i = 0; i < examine_dim; i++) {
+    current_gap_examined[i] = 0;
+    gap_mult3[i] = 0;
+    current_gap_ignore[i] = FALSE;
+  }
+
+  exon_intervals = GetAlignedExons (dsp, examine_dim);
+  if (has_exons != NULL) {
+    if (exon_intervals == NULL) {
+      *has_exons = FALSE;
+    } else {
+      *has_exons = TRUE;
+    }
+  }
+
+  for (seg = 0; seg < dsp->numseg; seg++) {
+    num_gap = 0;
+    num_non_gap = 0;
+    for (i = 0; i < examine_dim; i++) {
+      if (dsp->starts[seg * dsp->dim + i] == -1) {
+        if (!current_gap_ignore[i] && gap_mult3[i] == 0) {
+          if (seg == 0) {
+            /* ignore - beginning gap */
+            current_gap_ignore[i] = TRUE;
+          } else {
+            /* check to see if gap goes to end */
+            extend = seg + 1;
+            while (extend < dsp->numseg && dsp->starts[extend * dsp->dim + i] == -1) {
+              extend++;
+            }
+            if (extend == dsp->numseg) {
+              /* ignore - gap extends to end of alignment */
+              current_gap_ignore[i] = TRUE;
+            }              
+          }
+          if (!current_gap_ignore[i]) {
+            num_gap ++;
+          }
+        }
+      } else {
+        current_gap_ignore[i] = FALSE;
+        num_non_gap++;
+      }
+    }
+
+    if (num_gap > 0) {
+      /* report for each position in seg */
+      for (j = 0; j < dsp->lens[seg]; j++) {
+        MemSet (report, eFrameShiftReport_NoReport, sizeof (Int4) * examine_dim);
+        num_mult = 0;
+        any_report = FALSE;
+        if (IsPointInExon (aln_pos + j, exon_intervals)) {          
+          for (i = 0; i < examine_dim; i++) {
+            if (gap_mult3[i] > 0) {
+              gap_mult3[i]--;
+              current_gap_examined[i] --;
+            } else if (!current_gap_ignore[i] && dsp->starts[dsp->dim * seg + i] == -1) {
+              len_gap = 1;
+              if (current_gap_examined[i] > 0) {
+                current_gap_examined[i] --;
+              } else {
+                /* check for multiple of 3 */
+                len_gap = LenBeforeBoundary (i, seg, j, aln_pos + j, dsp, exon_intervals);
+                current_gap_examined[i] = len_gap - 1;
+              }
+              if (len_gap % 3 == 0) {
+                report[i] = eFrameShiftReport_ExonMult3;
+                gap_mult3[i] = len_gap - 1;
+                num_mult++;
+                num_gap--;
+              } else {
+                report[i] = eFrameShiftReport_Exon;
+                any_report = TRUE;
+              }
+            }
+          }
+          if (any_report) {
+            msg = FrameShiftReportString(eFrameShiftReport_Exon, aln_pos + j, num_gap, num_non_gap, report, examine_dim,
+                                     num_gap > num_non_gap ? exon_insert_fmt : exon_delete_fmt, ids);
+            first_related_seq = FindFirstSeqWithProblem(report, current_gap_ignore, examine_dim, eFrameShiftReport_Exon, num_gap, num_non_gap);
+            ValNodeAddPointer (&report_list, eFrameShiftReport_Exon, FrameShiftReportNew (msg, aln_pos + j, first_related_seq));
+          }
+        } else {
+          /* point is not in exon */
+          for (i = 0; i < examine_dim; i++) {
+            if (gap_mult3[i] > 0) {
+              gap_mult3[i]--;
+              current_gap_examined[i] --;
+            } else if (!current_gap_ignore[i] && dsp->starts[dsp->dim * seg + i] == -1) {
+              len_gap = 1;
+              if (current_gap_examined[i] > 0) {
+                current_gap_examined[i] --;
+              } else {
+                /* check for multiple of 3 */
+                len_gap = LenBeforeBoundary (i, seg, j, aln_pos + j, dsp, exon_intervals);
+                current_gap_examined[i] = len_gap - 1;
+              }
+              if (len_gap % 3 == 0) {
+                report[i] = eFrameShiftReport_ExonMult3;
+                gap_mult3[i] = len_gap - 1;
+                num_mult++;
+                num_gap--;
+              } else {
+                report[i] = eFrameShiftReport_Intron;
+              }
+            }
+          }
+          /* report introns later */
+          msg = FrameShiftReportString(eFrameShiftReport_Intron, aln_pos + j, num_gap, num_non_gap, report, examine_dim,
+                                     num_gap > num_non_gap ? intron_insert_fmt : intron_delete_fmt, ids);
+          if (msg != NULL) {
+            first_related_seq = FindFirstSeqWithProblem(report, current_gap_ignore, examine_dim, eFrameShiftReport_Intron, num_gap, num_non_gap);
+            ValNodeAddPointer (&report_list, eFrameShiftReport_Intron, FrameShiftReportNew(msg, aln_pos + j, first_related_seq));
+          }
+        }
+        /* report multiples of 3 later */
+        if (num_mult > 0) {
+          msg = FrameShiftReportMult (aln_pos + j, report, examine_dim, mult_fmt, ids);
+          first_related_seq = FindFirstSeqWithProblem(report, current_gap_ignore, examine_dim, eFrameShiftReport_ExonMult3, num_gap, num_non_gap);
+          ValNodeAddPointer (&report_list, eFrameShiftReport_ExonMult3, FrameShiftReportNew(msg, aln_pos + j, first_related_seq));
+        }
+      }
+      /* finished reporting for each position in seg */
+    }
+    aln_pos += dsp->lens[seg];
+  }
+
+  report_list = ValNodeSort (report_list, SortFrameShiftReports);
+
+  ids = MemFree (ids);
+  current_gap_examined = MemFree (current_gap_examined);
+  current_gap_ignore = MemFree (current_gap_ignore);
+  report = MemFree (report);
+  return report_list;
+}
+
+
+typedef struct frameshiftdlg {
+  FORM_MESSAGE_BLOCK
+
+  WindoW aln_window;
+  DoC    doc;
+
+  SeqAlignPtr salp;
+  ValNodePtr  report_list;
+  Boolean     any_exons;
+
+  FonT        title_font;
+} FrameShiftDlgData, PNTR FrameShiftDlgPtr;
+
+
+static void CleanupFrameShiftDlg (GraphiC g, VoidPtr data)
+
+{
+  FrameShiftDlgPtr dlg;
+
+  dlg = (FrameShiftDlgPtr) data;
+  if (dlg != NULL)
+  {
+    if (dlg->aln_window != NULL) {
+      RemoveSeqEdCloseFunc (dlg->aln_window);
+      Remove (dlg->aln_window);
+    }
+    dlg->salp = SeqAlignFree (dlg->salp);
+    dlg->report_list = FrameShiftReportListFree (dlg->report_list);
+  }
+  StdCleanupFormProc (g, data);
+}
+
+
+static void ResetFrameshiftWindow (Pointer data)
+{
+  FrameShiftDlgPtr  dlg;
+
+  if ((dlg = (FrameShiftDlgPtr) data) != NULL) {
+    dlg->aln_window = NULL;
+  }
+}
+
+
+static void ClickFrameShiftList (DoC d, PoinT pt)
+
+{
+  Int2             item;
+  Int2             row, i;
+  FrameShiftDlgPtr dlg;
+  ValNodePtr       vnp;
+  FrameShiftReportPtr fr;
+  Uint1               last_choice = eFrameShiftReport_NoReport;
+
+  /* TODO - skip headers after headers are added */
+
+  dlg = GetObjectExtra (d);
+  if (dlg != NULL) {
+    MapDocPoint (d, pt, &item, &row, NULL, NULL);
+    if (item > 0 && row > 0) {
+      if (item == 1 || item == 2) {
+        vnp = dlg->report_list;
+      } else {
+        i = 1;
+        vnp = dlg->report_list;
+        while (i < item && vnp != NULL) {
+          i++;
+          vnp = vnp->next;
+          if (vnp->choice != last_choice) {
+            i++;
+            last_choice = vnp->choice;
+          }
+        }
+      }
+      if (vnp != NULL && (fr = (FrameShiftReportPtr) vnp->data.ptrvalue) != NULL) {
+        /* navigage alignment window to coordinate */
+        if (dlg->aln_window == NULL) {
+          dlg->aln_window = (WindoW) CreateAlnEditorWindowEx (33, 50, "Frameshift Alignment", dlg->salp, dlg->input_entityID, ResetFrameshiftWindow, dlg);
+          Show (dlg->aln_window);
+        }          
+        SeqAlnWindowScrollToAlnPos (dlg->aln_window, fr->aln_pos - 1, fr->first_related_seq);
+      }
+    }
+  }
+}
+
+
+static Nlm_ParData frameshiftParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
+static Nlm_ColData frameshiftColFmt = {500, 0, 0, 0, NULL, 'l', 0,0,0,0, TRUE};
+
+static void PopulateFrameShiftList (FrameShiftDlgPtr dlg, ValNodePtr list)
+{
+  FrameShiftReportPtr fr;
+  Int2                numItems;
+  RecT                r;
+  Uint1               last_choice = eFrameShiftReport_NoReport;
+  
+  if (dlg == NULL || dlg->doc == NULL) 
+  {
+    return;
+  }
+  
+  Reset (dlg->doc);
+  
+  ObjectRect (dlg->doc, &r);
+  InsetRect (&r, 4, 4);
+  frameshiftColFmt.pixWidth = r.right - r.left;
+
+  while (list != NULL)
+  {    
+    if (list->choice != last_choice) {
+      if (list->choice == eFrameShiftReport_Exon) {
+        AppendText (dlg->doc, "FRAMESHIFTS IN EXONS", &frameshiftParFmt, &frameshiftColFmt, dlg->title_font);
+      } else if (list->choice == eFrameShiftReport_Intron) {
+        if (dlg->any_exons) {
+          AppendText (dlg->doc, "FRAMESHIFTS IN INTRONS", &frameshiftParFmt, &frameshiftColFmt, dlg->title_font);
+        } else {
+          AppendText (dlg->doc, "FRAMESHIFTS", &frameshiftParFmt, &frameshiftColFmt, dlg->title_font);
+        }
+      } else if (list->choice == eFrameShiftReport_ExonMult3) {
+        AppendText (dlg->doc, "MULTIPLES OF THREE ARE IGNORED", &frameshiftParFmt, &frameshiftColFmt, dlg->title_font);
+      }
+      last_choice = list->choice;
+    }      
+    fr = (FrameShiftReportPtr) list->data.ptrvalue;
+    AppendText (dlg->doc, fr->msg, &frameshiftParFmt, &frameshiftColFmt, programFont);
+    list = list->next;
+  }
+  GetDocParams (dlg->doc, &numItems, NULL);
+  UpdateDocument (dlg->doc, 0, numItems);
+
+}
+
+
+static void MakeFrameShiftReport (ButtoN b)
+{
+  FrameShiftDlgPtr  dlg;
+  LogInfoPtr        lip;
+
+  dlg = (FrameShiftDlgPtr) GetObjectExtra (b);
+  if (dlg == NULL) {
+    return;
+  }
+
+  lip = OpenLog ("Frame Shift Report");
+  PrintFrameShiftReportList (dlg->report_list, dlg->any_exons, lip);
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
+NLM_EXTERN void FrameShiftFinder (IteM i)
+{
+  SeqEntryPtr       sep;
+  BaseFormPtr       bfp;
+  SeqAlignPtr       salp=NULL;
+  ValNodePtr        report_list;
+  Boolean           has_exons = FALSE;
+  FrameShiftDlgPtr  dlg;
+  WindoW            w;
+  GrouP             h, c;
+  ButtoN            b;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL) return;
+
+  salp = ReadAlignmentForSeqEntry (sep, TRUE, FALSE);
+  if (salp == NULL) {
+    return;
+  }
+  /* now look for frame shifts */
+  report_list = FindFrameShiftsInAlignment (salp, &has_exons);
+
+  dlg = (FrameShiftDlgPtr) MemNew (sizeof (FrameShiftDlgData));
+
+  w = FixedWindow (-50, -33, -10, -10, "FrameShift Finder", StdCloseWindowProc);
+  dlg->form = (ForM) w;
+  SetObjectExtra (w, dlg, CleanupFrameShiftDlg);
+  dlg->input_entityID = bfp->input_entityID;
+  dlg->salp = salp;
+  dlg->report_list = report_list;
+  dlg->any_exons = has_exons;
+  dlg->aln_window = NULL;
+
+  dlg->title_font = GetFont ("Arial", 12, TRUE, FALSE, FALSE, "");
+
+  h = HiddenGroup (w, -1, 0, NULL);
+  dlg->doc = DocumentPanel (h, 900, stdLineHeight * 20);
+  SetObjectExtra (dlg->doc, dlg, NULL);
+  SetDocAutoAdjust (dlg->doc, FALSE);
+  SetDocProcs (dlg->doc, ClickFrameShiftList, NULL, NULL, NULL);
+  PopulateFrameShiftList (dlg, dlg->report_list);
+
+  c = HiddenGroup (h, 4, 0, NULL);
+  b = PushButton (c, "Make Report", MakeFrameShiftReport);
+  SetObjectExtra (b, dlg, NULL);
+  PushButton (c, "Cancel", StdCancelButtonProc);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) dlg->doc, (HANDLE) c, NULL);
+  RealizeWindow (w);
+  Show (w);
+  Update ();
+
+}
+
diff --git a/sequin/sequin5.c b/sequin/sequin5.c
index 28490f9..cb46965 100644
--- a/sequin/sequin5.c
+++ b/sequin/sequin5.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   8/26/97
 *
-* $Revision: 6.675 $
+* $Revision: 6.704 $
 *
 * File Description:
 *
@@ -1454,7 +1454,23 @@ void ChangeGenBankNameToLocal (IteM i)
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 }
 
-static Boolean PromoteAlignIDsProc (GatherObjectPtr gop)
+
+static SeqEntryPtr GetParentForSeqAnnot (SeqAnnotPtr sap)
+{
+  if (sap == NULL || sap->idx.parentptr == NULL) {
+    return NULL;
+  }
+  if (sap->idx.parenttype == OBJ_BIOSEQSET) {
+    return SeqMgrGetSeqEntryForData (sap->idx.parentptr);
+  } else if (sap->idx.parenttype == OBJ_BIOSEQ) {
+    return SeqMgrGetSeqEntryForData (sap->idx.parentptr);
+  } else {
+    return NULL;
+  }
+}
+
+
+extern void PromoteAlignIDsProc (SeqAnnotPtr sp, Pointer data)
 
 {
   DenseDiagPtr  ddp;
@@ -1463,10 +1479,17 @@ static Boolean PromoteAlignIDsProc (GatherObjectPtr gop)
   SeqAlignPtr   sap;
   SeqLocPtr     slp;
   StdSegPtr     ssp;
+  SeqEntryPtr   orig_scope, new_scope = NULL;
+
+  if (sp == NULL || sp->type != 2) {
+    return;
+  }
+  sap = (SeqAlignPtr) sp->data;
+  if (sap == NULL) return;
 
-  if (gop->itemtype != OBJ_SEQALIGN) return TRUE;
-  sap = (SeqAlignPtr) gop->dataptr;
-  if (sap == NULL) return TRUE;
+  new_scope = GetParentForSeqAnnot(sp);
+ 
+  orig_scope = SeqEntrySetScope (new_scope);
 
   switch (sap->segtype) {
     case SAS_DENDIAG :
@@ -1498,9 +1521,10 @@ static Boolean PromoteAlignIDsProc (GatherObjectPtr gop)
       break;
   }
 
-  return TRUE;
+  SeqEntrySetScope (orig_scope);
 }
 
+
 extern void PromoteAlignsToBestIDProc (IteM i);
 void PromoteAlignsToBestIDProc (IteM i)
 
@@ -1518,8 +1542,7 @@ void PromoteAlignsToBestIDProc (IteM i)
   if (sep == NULL) return;
 
   oldscope = SeqEntrySetScope (sep);
-
-  GatherObjectsInEntity (bfp->input_entityID, 0, NULL, PromoteAlignIDsProc, NULL, NULL);
+  VisitAnnotsInSep (sep, NULL, PromoteAlignIDsProc);
 
   SeqEntrySetScope (oldscope);
 
@@ -2128,17 +2151,48 @@ static Boolean ConvertRegionToRNA
   return TRUE;
 }
 
+
+static Boolean CommentShouldBeProduct (CharPtr comment)
+{
+  CharPtr search1 = "internal transcribed spacer ";
+  CharPtr search2 = "ITS";
+  CharPtr found;
+  Int4 len;
+
+  if (StringHasNoText (comment)) {
+    return FALSE;
+  }
+  if ((found = StringISearch (comment, search1)) != NULL
+      && (len = StringLen (search1)) < StringLen (found)
+      && (*(found + len) == '1' || *(found + len) == '2' || *(found + len) == '3')) {
+    return TRUE;
+  }
+
+  if ((found = StringISearch (comment, search2)) != NULL
+      && (len = StringLen (search2)) < StringLen (found)
+      && (*(found + len) == '1' || *(found + len) == '2' || *(found + len) == '3')) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
 static Boolean ConvertImpToRNA 
 (SeqFeatPtr sfp,
  Uint2      featdef_to,
  Pointer    extradata)
 {
   RnaRefPtr  rrp;
+  RNAGenPtr  rgp;
+  Boolean    was_misc_feat = FALSE;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_IMP)
   {
     return FALSE;
   }
+  if (sfp->idx.subtype == FEATDEF_misc_feature) {
+    was_misc_feat = TRUE;
+  }
 
   rrp = RnaRefNew ();
   if (NULL == rrp)
@@ -2172,12 +2226,38 @@ static Boolean ConvertImpToRNA
     rrp->type = 7;
     break;
   case FEATDEF_ncRNA :
-    rrp->type = 255;
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave ("ncRNA");
+    rrp->type = 8;
+    rrp->ext.choice = 3;
+    rrp->ext.value.ptrvalue = RNAGenNew ();
+    break;
+  case FEATDEF_tmRNA :
+    rrp->type = 9;
+    rrp->ext.choice = 3;
+    rrp->ext.value.ptrvalue = RNAGenNew ();
+    break;
+  case FEATDEF_misc_RNA:
+    rrp->type = 10;
+    rrp->ext.choice = 3;
+    rgp = RNAGenNew ();
+    rrp->ext.value.ptrvalue = rgp;
+    if (was_misc_feat && CommentShouldBeProduct(sfp->comment)) {
+      rgp->product = sfp->comment;
+      sfp->comment = NULL;
+    }
     break;
   case FEATDEF_otherRNA :
+    if (was_misc_feat && CommentShouldBeProduct(sfp->comment)) {
+      rrp->type = 10;
+      rrp->ext.choice = 3;
+      rgp = RNAGenNew ();
+      rrp->ext.value.ptrvalue = rgp;
+      rgp->product = sfp->comment;
+      sfp->comment = NULL;
+    } else {      
     rrp->type = 255;
+      rrp->ext.choice = 1;
+      rrp->ext.value.ptrvalue = StringSave ("misc_RNA");
+    }
     break;
   default :
     break;
@@ -2379,8 +2459,8 @@ static Boolean ConvertRNAToNcRNA
 (SeqFeatPtr sfp)
 {
   RnaRefPtr  rrp;
-  GBQualPtr  gbq;
   tRNAPtr    trp; 
+  RNAGenPtr  rgp = NULL;
   
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return FALSE;
   
@@ -2402,49 +2482,33 @@ static Boolean ConvertRNAToNcRNA
 
   /* might be converting from other ncRNA, tmRNA, or misc_RNA */
   if (rrp->ext.choice == 1) {
-    if (StringCmp (rrp->ext.value.ptrvalue, "ncRNA") == 0) {
-      /* already ncRNA */
-    } else if (StringCmp (rrp->ext.value.ptrvalue, "tmRNA") == 0) {
-      rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-      rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-    } else if (StringCmp (rrp->ext.value.ptrvalue, "misc_RNA") == 0) {
-      rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-      rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-    } else {
-      /* not one of the specified types, copy to product gbqual */
-      gbq = GBQualNew ();
-      gbq->qual = StringSave ("product");
-      gbq->val = rrp->ext.value.ptrvalue;
-      gbq->next = sfp->qual;
-      sfp->qual = gbq;
-      rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-    }
-  } else {
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave ("ncRNA");
-  }
-  
+    rgp = RNAGenNew ();
+    rgp->product = rrp->ext.value.ptrvalue;
+    rrp->ext.choice = 3;
+    rrp->ext.value.ptrvalue = rgp;
+  } else if (rrp->ext.choice == 0) {
+    rgp = RNAGenNew ();
+    rrp->ext.choice = 3;
+    rrp->ext.value.ptrvalue = rgp;
+  } else if (rrp->ext.choice == 3) {
+    rgp = rrp->ext.value.ptrvalue;
+    if (rgp == NULL) {
+      rgp = RNAGenNew ();
+      rrp->ext.value.ptrvalue = rgp;
+    }
+  }
+
+  if (rgp != NULL) {
   if (rrp->type == 5) {
-    gbq = GBQualNew ();
-    gbq->qual = StringSave ("ncRNA_class");
-    gbq->val = StringSave ("snRNA");
-    gbq->next = sfp->qual;
-    sfp->qual = gbq;
+      rgp->_class = StringSave ("snRNA");
   } else if (rrp->type == 6) {
-    gbq = GBQualNew ();
-    gbq->qual = StringSave ("ncRNA_class");
-    gbq->val = StringSave ("scRNA");
-    gbq->next = sfp->qual;
-    sfp->qual = gbq;
+      rgp->_class = StringSave ("scRNA");
   } else if (rrp->type == 7) {
-    gbq = GBQualNew ();
-    gbq->qual = StringSave ("ncRNA_class");
-    gbq->val = StringSave ("snoRNA");
-    gbq->next = sfp->qual;
-    sfp->qual = gbq;
+      rgp->_class = StringSave ("snoRNA");
+    }
   }
 
-  rrp->type = 255;
+  rrp->type = 8;
   return TRUE;
 }
 
@@ -2452,72 +2516,46 @@ static Boolean ConvertRNAToNcRNA
 static void ConvertFromncRNAtoMiscRNA (SeqFeatPtr sfp)
 {
   RnaRefPtr rrp;
-  GBQualPtr gbq, gbq_prev = NULL;
+  RNAGenPtr rgp;
   CharPtr tmp;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA) return;
   rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
-  if (rrp == NULL || rrp->ext.choice != 1 || StringCmp (rrp->ext.value.ptrvalue, "ncRNA") != 0) {
+  if (rrp == NULL || rrp->ext.choice != 3) {
     return;
   }
-  rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
-  rrp->ext.choice = 0;
-  /* find new value for product */
-  gbq = sfp->qual;
-  while (gbq != NULL && StringCmp (gbq->qual, "product") != 0) {
-    gbq_prev = gbq;
-    gbq = gbq->next;
-  }
 
-  if (gbq != NULL) {
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave (gbq->val);
-    if (gbq_prev == NULL) {
-      sfp->qual = gbq->next;
-    } else {
-      gbq_prev->next = gbq->next;
-    }
-    gbq->next = NULL;
-    gbq = GBQualFree (gbq);
-  } else if (!StringHasNoText (sfp->comment)) {
-    rrp->ext.choice = 1;
-    rrp->ext.value.ptrvalue = StringSave (sfp->comment);
-    sfp->comment = MemFree (sfp->comment);
+  rgp = (RNAGenPtr) rrp->ext.value.ptrvalue;
+  if (rgp == NULL) {
+    return;
   }
 
-  /* move ncRNA_class elsewhere */
-  gbq = sfp->qual;
-  gbq_prev = NULL;
-  while (gbq != NULL && StringCmp (gbq->qual, "ncRNA_class") != 0) {
-    gbq_prev = gbq;
-    gbq = gbq->next;
+  /* if no product but has comment, promote comment to product */
+  if (rgp->product == NULL && !StringHasNoText (sfp->comment)) {
+    rgp->product = sfp->comment;
+    sfp->comment = NULL;
   }
 
-  if (gbq != NULL) {
-    if (StringCmp (gbq->val, "other") != 0) {
-      if (rrp->ext.choice == 0) {
-        rrp->ext.choice = 1;
-        rrp->ext.value.ptrvalue = StringSave (gbq->val);
+  /* move ncRNA_class elsewhere */
+  if (!StringHasNoText (rgp->_class)) {
+    if (StringCmp (rgp->_class, "other") == 0) {
+      rgp->_class = MemFree (rgp->_class);
+    } else if (rgp->product == NULL) {
+      rgp->product = rgp->_class;
+      rgp->_class = NULL;
       } else {
         if (StringHasNoText (sfp->comment)) {
           sfp->comment = MemFree (sfp->comment);
-          sfp->comment = StringSave (gbq->val);
+        sfp->comment = StringSave (rgp->_class);
         } else {
-          tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (sfp->comment) + StringLen (gbq->val) + 3));
-          sprintf (tmp, "%s; %s", sfp->comment, gbq->val);
+        tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (sfp->comment) + StringLen (rgp->_class) + 3));
+        sprintf (tmp, "%s; %s", sfp->comment, rgp->_class);
           sfp->comment = MemFree (sfp->comment);
           sfp->comment = tmp;
         }
+      rgp->_class = MemFree (rgp->_class);
       }
     }
-    if (gbq_prev == NULL) {
-      sfp->qual = gbq->next;
-    } else {
-      gbq_prev->next = gbq->next;
-    }
-    gbq->next = NULL;
-    gbq = GBQualFree (gbq);
-  }    
 }
 
 
@@ -9179,7 +9217,7 @@ static void ApplyBioSourceDbxrefBioSourceCallback (BioSourcePtr biop, Pointer us
     /* if it was a number before, make it a string now */
     if (dbtag->tag->id > 0 && dbtag->tag->str == NULL)
     {
-      sprintf (buf, "%s", dbtag->tag->id);
+      sprintf (buf, "%ld", (long) dbtag->tag->id);
       dbtag->tag->id = 0;
       dbtag->tag->str = StringSave (buf);
     }
@@ -16588,7 +16626,7 @@ ParseToOneFeature
 {
   SetFeatureFieldString set_string_func = NULL;
   ApplyValuePtr         avp;
-  BioseqPtr             prot_bsp, bsp;
+  BioseqPtr             prot_bsp, bsp = NULL;
   SeqMgrFeatContext     context;
   ProtRefPtr            prp;
   
@@ -17263,7 +17301,7 @@ static void FeatureRemoveClear (Pointer data)
 static void FeatureRemoveChangeNotify (Pointer userdata)
 {
   FeatureSelRemConvFormPtr mrfp;
-  ValNodePtr          err_list, vnp_from, vnp_to;
+  ValNodePtr          err_list = NULL, vnp_from, vnp_to;
   Int4                table_line;
   RecT                r;
   Boolean             need_original = FALSE;
@@ -20254,11 +20292,13 @@ typedef struct feated
   ButtoN extend5_btn;
   PopuP  partial3_choice;
   ButtoN extend3_btn;
+  ButtoN retranslate_btn;
   Int4   orderjoinpolicy;
   Int4   leftpolicy;
   Int4   rightpolicy;
   Boolean extend5;
   Boolean extend3;
+  Boolean retranslate;
   
   /* for strand */
   PopuP  from_strand;
@@ -20389,6 +20429,10 @@ static void FeatEdClear (Pointer data)
   {
     SetStatus (mp->extend3_btn, FALSE);
   }
+  if (mp->retranslate_btn != NULL)
+  {
+    SetStatus (mp->retranslate_btn, FALSE);
+  }
 
   /* for strand */
   if (mp->from_strand != NULL)
@@ -20627,20 +20671,20 @@ static GrouP FeatureEditorCitationGroup (GrouP h, FeatEdPtr mp)
 
 static GrouP FeatureEditorPartialGroup (GrouP h, FeatEdPtr mp)
 {
-  GrouP g, g1, g2,k1, k2;
-  PrompT p1, p2;
+  GrouP g, g1, g2,k1, k2, top;
   
   if (mp == NULL)
   {
     return NULL;
   }
   
-  g = HiddenGroup (h, 2, 0, NULL);
+  top = HiddenGroup (h, -1, 0, NULL);
+  SetGroupSpacing (top, 10, 10);
+
+  g = HiddenGroup (top, 2, 0, NULL);
   SetGroupSpacing (g, 10, 10);
-  StaticPrompt (g, "", 0, dialogTextHeight, systemFont, 'l');
-  StaticPrompt (g, "", 0, dialogTextHeight, systemFont, 'l');
   
-  p1 = StaticPrompt (g, "Partials:", 0, dialogTextHeight, systemFont, 'l');
+  StaticPrompt (g, "Partials:", 0, dialogTextHeight, systemFont, 'l');
   g1 = NormalGroup (g, 1, 0, "", programFont, NULL);
   k1 = HiddenGroup (g1, 2, 0, NULL);
 
@@ -20676,7 +20720,7 @@ static GrouP FeatureEditorPartialGroup (GrouP h, FeatEdPtr mp)
   
   mp->extend3_btn = CheckBox (g1, "Extend to 3' end of sequence if setting 3' partial", NULL);
 
-  p2 = StaticPrompt (g, "Join/Order/Merge:", 0, dialogTextHeight, systemFont, 'l');
+  StaticPrompt (g, "Join/Order/Merge:", 0, dialogTextHeight, systemFont, 'l');
   g2 = NormalGroup (g, 1, 0, "", programFont, NULL);
   mp->convert_choice = PopupList (g2, TRUE, NULL);
   PopupItem (mp->convert_choice, "Do not convert location");
@@ -20685,7 +20729,11 @@ static GrouP FeatureEditorPartialGroup (GrouP h, FeatEdPtr mp)
   PopupItem (mp->convert_choice, "Convert location to single interval");
   SetValue (mp->convert_choice, 1);
   
-  return g;
+  mp->retranslate_btn = CheckBox (top, "Retranslate coding regions", NULL);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) mp->retranslate_btn, NULL);
+  
+  return top;
 }
 
 #define FEATED_STRAND_ANY_REVERSE 1
@@ -21074,7 +21122,7 @@ static void DoPartialFeatureProc (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr
   ByteStorePtr bs;
   CharPtr      prot;
   CharPtr      ptr;
-  Char         first_char, ch;
+  Char         first_char = '\0', ch;
   Boolean      hasNulls;
   SeqLocPtr    slp, firstSlp = NULL, lastSlp = NULL;
   Uint1        strand;
@@ -21343,6 +21391,10 @@ static void DoPartialFeatureProc (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr
   {
     ResynchCDSPartials (sfp, NULL);
   }
+
+  if (mp->retranslate) {
+    RetranslateOneCDS (sfp, sfp->idx.entityID, TRUE, TRUE);
+  }
 }
 
 static Boolean DoesStrandMatch (Int4 strand_choice, Uint1 strand_val)
@@ -21716,6 +21768,7 @@ FeatureEditorDoOneAction
         mp->rightpolicy = GetValue (mp->partial3_choice);
         mp->extend5 = GetStatus (mp->extend5_btn);
         mp->extend3 = GetStatus (mp->extend3_btn);
+        mp->retranslate = GetStatus (mp->retranslate_btn);
 
         OperateOnSeqEntryConstrainedObjects (sep, fsp, 
                                              DoPartialFeatureProc,
@@ -30454,38 +30507,6 @@ GetUniqueValueListForSeqEntry
 }
 
 
-static SeqEntryPtr GetBestSeqEntryForItem (ValNodePtr vnp)
-{
-  SeqFeatPtr       sfp;
-  SeqDescrPtr      sdp;
-  ObjValNodePtr    ovp;
-  SeqEntryPtr      sep = NULL;
-  BioseqPtr        bsp;
-
-  if (vnp == NULL || vnp->data.ptrvalue == NULL) return NULL;
-
-  if (vnp->choice == OBJ_SEQFEAT) {
-    sfp = vnp->data.ptrvalue;
-    sep = GetBestTopParentForData (sfp->idx.entityID, BioseqFindFromSeqLoc (sfp->location));
-  } else if (vnp->choice == OBJ_SEQDESC) {
-    sdp = vnp->data.ptrvalue;
-    if (sdp->extended != 0) {
-      ovp = (ObjValNodePtr) sdp;
-      if (ovp->idx.parenttype == OBJ_BIOSEQSET) {
-        sep = SeqMgrGetSeqEntryForData (ovp->idx.parentptr);
-      } else if (ovp->idx.parenttype == OBJ_BIOSEQ) {
-        sep = GetBestTopParentForData (ovp->idx.entityID, ovp->idx.parentptr);
-      }
-    }
-  } else if (vnp->choice == OBJ_BIOSEQ) {
-    bsp = (BioseqPtr) vnp->data.ptrvalue;
-    sep = GetBestTopParentForData (bsp->idx.entityID, bsp);
-  } else if (vnp->choice == OBJ_SEQENTRY) {
-    sep = vnp->data.ptrvalue;
-  }
-  return sep;
-}
-
 static ValNodePtr GetSeqEntryListForItem (ValNodePtr vnp)
 {
   SeqFeatPtr       sfp;
@@ -30968,358 +30989,6 @@ static ValNodePtr GetTextSeqEntryListForSeqEntry (SeqEntryPtr sep, Uint2 entityI
   return value_lists;
 }
 
-static void AddNewUniqueDescriptors (SeqDescrPtr PNTR new_set, SeqDescrPtr parent_set)
-{
-  SeqDescrPtr sdp, sdp_next, sdp_tmp, sdp_tmp_next;
-  Boolean     found_match;
-
-  if (new_set == NULL || parent_set == NULL) return;
-
-  if (*new_set == NULL) {
-    ValNodeLink (new_set,
-                 AsnIoMemCopy ((Pointer) parent_set,
-                               (AsnReadFunc) SeqDescrAsnRead,
-                               (AsnWriteFunc) SeqDescrAsnWrite));
-  } else {
-    sdp = parent_set;
-    while (sdp != NULL) {
-      sdp_next = sdp->next;
-      sdp->next = NULL;
-      for (sdp_tmp = *new_set, found_match = FALSE;
-           sdp_tmp != NULL && !found_match; 
-           sdp_tmp = sdp_tmp->next) {
-        sdp_tmp_next = sdp_tmp->next;
-        sdp_tmp->next = NULL;
-        if (AsnIoMemComp (sdp, sdp_tmp, (AsnWriteFunc) SeqDescrAsnWrite)) {
-          found_match = TRUE;
-        }
-        sdp_tmp->next = sdp_tmp_next;
-      }
-      if (!found_match) {
-        ValNodeLink (new_set,
-                     AsnIoMemCopy ((Pointer) sdp,
-                                   (AsnReadFunc) SeqDescrAsnRead,
-                                   (AsnWriteFunc) SeqDescrAsnWrite));
-      }
-      sdp->next = sdp_next;
-      sdp = sdp->next;
-    }
-  }
-}
-
-static void AddNewUniqueDescriptorsToSeqEntry (SeqEntryPtr sep, SeqDescrPtr parent_set)
-{
-  BioseqPtr    bsp;
-  BioseqSetPtr bssp;
-
-  if (IS_Bioseq(sep)) {
-    bsp = (BioseqPtr) sep->data.ptrvalue;
-    if (bsp != NULL) {
-      AddNewUniqueDescriptors (&(bsp->descr), parent_set);
-    }
-  } else if (IS_Bioseq_set (sep)) {
-    bssp = (BioseqSetPtr) sep->data.ptrvalue;
-    if (bssp != NULL) {
-      AddNewUniqueDescriptors (&(bssp->descr), parent_set);
-    }
-  }
-}
-
-static void AddNewUniqueAnnotations (SeqAnnotPtr PNTR new_set, SeqAnnotPtr parent_set)
-{
-  SeqAnnotPtr sap, sap_next, sap_tmp, sap_tmp_next, sap_copy, last_sap;
-  Boolean     found_match;
-
-  if (new_set == NULL || parent_set == NULL) return;
-
-  sap = parent_set;
-  while (sap != NULL) {
-    sap_next = sap->next;
-    sap->next = NULL;
-    last_sap = NULL;
-    for (sap_tmp = *new_set, found_match = FALSE;
-         sap_tmp != NULL && !found_match;
-         sap_tmp = sap_tmp->next) {
-      sap_tmp_next = sap_tmp->next;
-      sap_tmp->next = NULL;
-      if (AsnIoMemComp (sap, sap_tmp, (AsnWriteFunc) SeqAnnotAsnWrite)) {
-        found_match = TRUE;
-      }
-      sap_tmp->next = sap_tmp->next;
-      last_sap = sap_tmp;
-    }
-    if (!found_match) {        
-      sap_copy = (SeqAnnotPtr) AsnIoMemCopy ((Pointer) sap, (AsnReadFunc) SeqAnnotAsnRead, (AsnWriteFunc) SeqAnnotAsnWrite); 
-      if (last_sap == NULL) {
-        *new_set = sap_copy;
-      } else {
-        last_sap->next = sap_copy;
-      }
-    }
-    sap->next = sap_next;
-    sap = sap->next;
-  }
-}
-
-
-static void AddNewUniqueAnnotationsToSeqEntry (SeqEntryPtr sep, SeqAnnotPtr parent_set)
-{
-  BioseqPtr    bsp;
-  BioseqSetPtr bssp;
-
-  if (IS_Bioseq(sep)) {
-    bsp = (BioseqPtr) sep->data.ptrvalue;
-    if (bsp != NULL) {
-      AddNewUniqueAnnotations (&(bsp->annot), parent_set);
-    }
-  } else if (IS_Bioseq_set (sep)) {
-    bssp = (BioseqSetPtr) sep->data.ptrvalue;
-    if (bssp != NULL) {
-      AddNewUniqueAnnotations (&(bssp->annot), parent_set);
-    }
-  }
-}
-
-
-static void AddCategorySeqEntriesToSet (BioseqSetPtr newset, ClickableItemPtr category)
-{
-  ValNodePtr vnp_item;
-  SeqEntryPtr sep, last_sep, prev_sep, remove_sep;
-  BioseqSetPtr bssp, orig_parent;
-  BioseqPtr bsp;
-
-  if (newset == NULL || category == NULL || category->item_list == NULL) return;
-
-  if (category->chosen) {
-    last_sep = newset->seq_set;
-    while (last_sep != NULL && last_sep->next != NULL) {
-      last_sep = last_sep->next;
-    }
-
-    for (vnp_item = category->item_list; vnp_item != NULL; vnp_item = vnp_item->next) {
-      sep = GetBestSeqEntryForItem (vnp_item);
-      if (sep == NULL || sep->data.ptrvalue == NULL) continue;
-      orig_parent = NULL;
-      if (IS_Bioseq (sep)) {
-        bsp = sep->data.ptrvalue;
-        if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
-          orig_parent = bsp->idx.parentptr;
-          bsp->idx.parentptr = NULL;
-        }
-      } else if (IS_Bioseq_set (sep)) {
-        bssp = sep->data.ptrvalue;
-        if (bssp->idx.parenttype == OBJ_BIOSEQSET) {
-          orig_parent = bssp->idx.parentptr;
-          bssp->idx.parentptr = NULL;
-        }
-      } else {
-        continue;
-      }
-         
-      if (orig_parent != NULL) {
-        /* remove this seq-entry from the original parent */
-        prev_sep = NULL;
-        for (remove_sep = orig_parent->seq_set;
-             remove_sep != NULL && remove_sep != sep;
-             remove_sep = remove_sep->next) {
-          prev_sep = remove_sep;
-        }
-        if (remove_sep == sep) {
-          if (prev_sep == NULL) {
-            orig_parent->seq_set = orig_parent->seq_set->next;
-            if (orig_parent->seq_set == NULL) {
-              orig_parent->idx.deleteme = TRUE; 
-            }
-          } else {
-            prev_sep->next = sep->next;
-          }
-        }
-        /* set class type if not already set */
-        if (newset->_class == BioseqseqSet_class_genbank) {
-          newset->_class = orig_parent->_class;
-        }
-      }
-      /* add descriptors from the orig_parent to the new parent */
-      AddNewUniqueDescriptors (&(newset->descr), orig_parent->descr);
-
-      /* add annotations from the orig_parent to the new parent */
-      AddNewUniqueAnnotations (&(newset->annot), orig_parent->annot);
-
-      /* add to new parent */
-      sep->next = NULL;
-      if (last_sep == NULL) {
-        newset->seq_set = sep;
-      } else {
-        last_sep->next = sep;
-      }
-      last_sep = sep;
-      SeqMgrLinkSeqEntry (sep, OBJ_BIOSEQSET, newset);
-    }
-  } else {
-    for (vnp_item = category->subcategories; vnp_item != NULL; vnp_item = vnp_item->next) {
-      AddCategorySeqEntriesToSet (newset, vnp_item->data.ptrvalue);
-    }
-  }
-}
-
-static Boolean AnyDiscrepanciesChosen (ValNodePtr cip_list)
-{
-  ClickableItemPtr cip;
-  Boolean          any_chosen = FALSE;
-
-  while (cip_list != NULL && !any_chosen) {
-    cip = (ClickableItemPtr) cip_list->data.ptrvalue;
-    if (cip != NULL
-        && (cip->chosen 
-            || (cip->expanded && AnyDiscrepanciesChosen (cip->subcategories)))) {
-      any_chosen = TRUE;
-    }
-    cip_list = cip_list->next;
-  }
-  return any_chosen;
-}
-
-static Boolean NeedsNewSet (SeqEntryPtr sep)
-{
-  BioseqSetPtr bssp;
-  while (sep != NULL) {
-    if (IS_Bioseq (sep)) {
-      return TRUE;
-    } else if (IS_Bioseq_set (sep)) {
-      bssp = (BioseqSetPtr) sep->data.ptrvalue;
-      if (bssp != NULL 
-          && (bssp->_class == BioseqseqSet_class_nuc_prot
-          || bssp->_class == BioseqseqSet_class_segset)) {
-        return TRUE;
-      }
-    }
-    sep = sep->next;
-  }
-  return FALSE;
-}
-
-static BioseqSetPtr MakeGroupsForUniqueValues
-(BioseqSetPtr bssp, 
- ValNodePtr   value_lists)
-{
-  ObjMgrDataPtr     omdptop;
-  ObjMgrData        omdata;
-  Uint2             parenttype;
-  Pointer           parentptr;
-  BioseqSetPtr parent_set;
-  SeqEntryPtr  sep, first_new_sep = NULL;
-  SeqEntryPtr  tmp;
-  BioseqSetPtr newset;
-  ValNodePtr   vnp;
-  ClickableItemPtr cip;
-  Uint1        child_class;
-  Uint2        entityID;
-  Boolean      child_became_parent = FALSE;
-
-  if (bssp == NULL) return NULL;
-  entityID = bssp->idx.entityID;
-  
-  sep = SeqMgrGetSeqEntryForData (bssp);
-
-  WatchCursor ();
-  Update ();
-  SaveSeqEntryObjMgrData (sep, &omdptop, &omdata);
-  GetSeqEntryParent (sep, &parentptr, &parenttype);
-
-  parent_set = (BioseqSetPtr)(bssp->idx.parentptr);
-
-  if (parent_set == NULL || parent_set->seq_set == NULL) {
-    /* this set has no parent, so make it the parent set, class GenBank,
-     * and create two new sets using the original set class as members of this set
-     */
-    parent_set = bssp;
-    child_class = parent_set->_class;
-    child_became_parent = TRUE;
-  } else {
-    /* we already have a parent set. */
-    child_class = bssp->_class;
-  }
-
-  for (vnp = value_lists; vnp != NULL; vnp = vnp->next) {      
-    cip = (ClickableItemPtr) vnp->data.ptrvalue;
-    if (cip == NULL || (!cip->chosen && ! AnyDiscrepanciesChosen (cip->subcategories))) {
-      continue;
-    }
-
-    newset = BioseqSetNew ();
-    newset->_class = child_class;
-    /* add SeqEntries for this category here */
-    AddCategorySeqEntriesToSet (newset, cip);
-
-    /* check - is any member of the newset also a set? */
-    tmp = newset->seq_set;
-    while (tmp != NULL && IS_Bioseq (tmp)) {
-      tmp = tmp->next;
-    }
-
-    /* add to members for parent_set */
-    tmp = SeqEntryNew ();
-    tmp->choice = 2;
-    tmp->data.ptrvalue = (Pointer) newset;
-
-    tmp->next = parent_set->seq_set;
-    parent_set->seq_set = tmp;
-
-    if (parent_set->idx.deleteme) {
-      parent_set->idx.deleteme = FALSE;
-    }
-    if (first_new_sep == NULL) {
-      first_new_sep = tmp;
-    }
-
-    SeqMgrLinkSeqEntry (tmp, OBJ_BIOSEQSET, parent_set);
-  }
-
-  RestoreSeqEntryObjMgrData (sep, omdptop, &omdata); 
-  DeleteMarkedObjects (entityID, 0, NULL);
-
-  if (child_became_parent) {
-    if (NeedsNewSet (first_new_sep->next)) {
-      /* make new set to hold what wasn't moved */
-      newset = BioseqSetNew ();
-      /* contents of set are unmoved sequences */
-      newset->seq_set = first_new_sep->next;
-      /* set class type */
-      newset->_class = parent_set->_class;
-      /* add descriptors from the parent */
-      ValNodeLink (&(newset->descr),
-                   AsnIoMemCopy ((Pointer) parent_set->descr,
-                                 (AsnReadFunc) SeqDescrAsnRead,
-                                 (AsnWriteFunc) SeqDescrAsnWrite));
-
-
-      tmp = SeqEntryNew();
-      tmp->choice = 2;
-      tmp->data.ptrvalue = (Pointer) newset;
-      tmp->next = NULL;
-      first_new_sep->next = tmp;
-      SeqMgrLinkSeqEntry (tmp, OBJ_BIOSEQSET, parent_set);
-    } else {
-      sep = first_new_sep->next;
-      while (sep != NULL) {
-        AddNewUniqueDescriptorsToSeqEntry (sep, parent_set->descr);
-        sep = sep->next;
-      }
-    }
-    /* set parent class to GenBank set */
-    parent_set->_class = BioseqseqSet_class_genbank;
-    /* remove descriptors on parent, they will all have been copied down */
-    parent_set->descr = SeqDescrFree (parent_set->descr);
-  }
-
-  ObjMgrSetDirtyFlag (entityID, TRUE);
-  ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
-
-  ArrowCursor ();
-  Update ();
-  return parent_set;
-}
-
 typedef enum vectorhitlevel {
   eVectorHitLevelSuspect = 1,
   eVectorHitLevelWeak,
@@ -31651,6 +31320,8 @@ typedef enum {
   eSegPageDescriptorType,
   eSegPageLength,
   eSegPageVectorContamination,
+  eSegPageNumFinalSets,
+  eSegPageFile,
   eNumSegPages
 } ESegPage;
 
@@ -31686,25 +31357,15 @@ typedef struct segbyfield {
   /* for segregating by vector contamination */
   DialoG       vector_options;
 
+  /* for segregating into a specific number of sets */
+  TexT         num_sets;
+
   ButtoN       accept;
   ButtoN       leave_dlg_up;
   BioseqSetPtr target_set;
   ValNodePtr   value_lists;
 } SegByFieldData, PNTR SegByFieldPtr;
 
-static void ChooseAllDiscrepancies (ValNodePtr cip_list)
-{
-  ClickableItemPtr cip;
-
-  while (cip_list != NULL) {
-    cip = cip_list->data.ptrvalue;
-    if (cip != NULL) {
-      cip->chosen = TRUE;
-    }
-    cip_list = cip_list->next;
-  }
-}
-
 static void ChangeSegChoice (GrouP g);
 
 
@@ -32306,6 +31967,150 @@ static void SegDescriptorChangeNotify (Pointer data)
 
 }
 
+static void ChooseSeqsForNumSets (Pointer data)
+{
+  SegByFieldPtr      sfp;
+  SeqEntryPtr        sep;
+  Int4               num_sets;
+  CharPtr            str;
+
+  sfp = (SegByFieldPtr) data;
+  if (sfp == NULL) return;
+
+  str = SaveStringFromText (sfp->num_sets);
+  if (str == NULL) {
+    Disable (sfp->accept);
+    return;
+  }
+
+  num_sets = atoi (str);
+  str = MemFree (str);
+  if (num_sets < 1) {
+    Disable (sfp->accept);
+    return;
+  }
+
+  WatchCursor ();
+  Update();
+  sep = SeqMgrGetSeqEntryForData (sfp->target_set);
+
+  PointerToDialog (sfp->group_list_dlg, NULL);
+  sfp->value_lists = FreeClickableList (sfp->value_lists);
+
+  sfp->value_lists = PrepareSequenceListForSegregateByNumberOfSets (num_sets, sep);
+
+  PointerToDialog (sfp->group_list_dlg, sfp->value_lists);
+
+  if (sfp->value_lists == NULL) {
+    Disable (sfp->accept);
+  } else {
+    Enable (sfp->accept);
+  }
+  ArrowCursor();
+  Update();
+}
+
+static void SegNumSetsChange (TexT t)
+{
+  SegByFieldPtr sfp;
+
+  sfp = (SegByFieldPtr) GetObjectExtra (t);
+
+  ChooseSeqsForNumSets (sfp);
+}
+
+
+static Boolean IsNcbiFileId(SeqIdPtr sip)
+{
+  DbtagPtr dbtag;
+
+  if (sip == NULL || sip->choice != SEQID_GENERAL || (dbtag = sip->data.ptrvalue) == NULL) {
+    return FALSE;
+  }
+  if (StringCmp (dbtag->db, "NCBIFILE") == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+static void GroupSeqByFileCallback (BioseqPtr bsp, Pointer data)
+{
+  ValNodePtr PNTR list;
+  ValNodePtr vnp;
+  SeqIdPtr   sip;
+  DbtagPtr   dbtag;
+  Char       id_buf[15];
+  CharPtr    id = NULL, last_slash;
+  ClickableItemPtr cip;
+  Boolean          found = FALSE;
+
+  if (bsp == NULL || ISA_aa (bsp->mol) || (list = (ValNodePtr PNTR) data) == NULL) {
+    return;
+  }
+
+  sip = bsp->id; 
+  while (sip != NULL && !IsNcbiFileId(sip)) {
+    sip = sip->next;
+  }
+
+  if (sip != NULL && (dbtag = (DbtagPtr) sip->data.ptrvalue) != NULL) {
+    if (dbtag->tag->id > 0) {
+      sprintf (id_buf, "%d", dbtag->tag->id);
+      id = id_buf;
+    } else {
+      id = dbtag->tag->str;
+    }
+    id = StringSave (id);
+    if ((last_slash = StringRChr (id, '/')) != NULL) {
+      *last_slash = 0;
+    }
+    for (vnp = *list; vnp != NULL && !found; vnp = vnp->next) {
+      cip = (ClickableItemPtr) vnp->data.ptrvalue;
+      if (cip != NULL && StringCmp (id, cip->description) == 0) {
+        ValNodeAddPointer (&cip->item_list, OBJ_BIOSEQ, bsp);
+        found = TRUE;
+        id = MemFree (id);
+      }
+    }
+    if (!found) {
+      cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+      cip->description = id;
+      ValNodeAddPointer (&cip->item_list, OBJ_BIOSEQ, bsp);
+      ValNodeAddPointer (list, 0, cip);
+    }
+  }
+}
+
+
+static void ChooseFile (SegByFieldPtr sfp)
+{
+  SeqEntryPtr        sep;
+
+  if (sfp == NULL) return;
+
+  WatchCursor ();
+  Update();
+  sep = SeqMgrGetSeqEntryForData (sfp->target_set);
+
+  PointerToDialog (sfp->group_list_dlg, NULL);
+  sfp->value_lists = FreeClickableList (sfp->value_lists);
+
+  VisitBioseqsInSep (sep, &(sfp->value_lists), GroupSeqByFileCallback);
+
+  PointerToDialog (sfp->group_list_dlg, sfp->value_lists);
+
+  if (sfp->value_lists == NULL) {
+    Disable (sfp->accept);
+  } else {
+    Enable (sfp->accept);
+  }
+  ArrowCursor();
+  Update();
+}
+
+
 static void ChangeSegChoice (GrouP g)
 {
   SegByFieldPtr sfp;
@@ -32318,9 +32123,9 @@ static void ChangeSegChoice (GrouP g)
 
     for (i = 0; i < eNumSegPages; i++) {
     if (i == seg_choice - 1) {
-        Show (sfp->pages[i]);
+        SafeShow (sfp->pages[i]);
       } else {
-        Hide (sfp->pages[i]);
+        SafeHide (sfp->pages[i]);
       }
     }
     switch (seg_choice) {
@@ -32348,6 +32153,12 @@ static void ChangeSegChoice (GrouP g)
     case eSegPageLength:
         ChooseSeqsByLen (sfp);
         break;
+    case eSegPageNumFinalSets:
+        ChooseSeqsForNumSets (sfp);
+        break;
+    case eSegPageFile:
+        ChooseFile(sfp);
+        break;
   }
   if (seg_choice == eSegPageId || seg_choice == eSegPageVectorContamination || seg_choice == eSegPageLength) {
     SetClickableListDialogTitles (sfp->group_list_dlg, "Sequences for New Set", "",
@@ -32532,6 +32343,8 @@ static Int2 NewSegregateBioseqSet (BioseqSetPtr bssp, Nlm_BtnActnProc actn, ESeg
   RadioButton (cfp->seg_choice_grp, "Descriptor Type");
   RadioButton (cfp->seg_choice_grp, "Nucleotide Sequence Length");
   RadioButton (cfp->seg_choice_grp, "Vector Contamination");
+  RadioButton (cfp->seg_choice_grp, "Number of Sets");
+  RadioButton (cfp->seg_choice_grp, "File Name");
 
   page_grp = HiddenGroup (h, 0, 0, NULL);
   /* identical fields */
@@ -32601,6 +32414,16 @@ static Int2 NewSegregateBioseqSet (BioseqSetPtr bssp, Nlm_BtnActnProc actn, ESeg
   SetGroupSpacing (cfp->pages[eSegPageVectorContamination - 1], 10, 10);
   cfp->vector_options = VectorContaminationOptionsDialog (cfp->pages[eSegPageVectorContamination - 1], ChooseVectorSeqs, cfp);
 
+  /* number of sets */
+  cfp->pages[eSegPageNumFinalSets - 1] = HiddenGroup (page_grp, 2, 0, NULL);
+  SetGroupSpacing (cfp->pages[eSegPageNumFinalSets - 1], 10, 10);
+  StaticPrompt (cfp->pages[eSegPageNumFinalSets - 1], "Number of sets to create", 0, dialogTextHeight, programFont, 'l');
+  cfp->num_sets = DialogText (cfp->pages[eSegPageNumFinalSets - 1], "", 10, SegNumSetsChange);
+  SetObjectExtra (cfp->num_sets, cfp, NULL);
+
+  /* don't need controls for File */
+  cfp->pages[eSegPageFile - 1] = NULL;
+
   b = PushButton (g2, "Mark", SelectSequenceIDsForSegregate);
   SetObjectExtra (b, cfp, NULL);
   AlignObjects (ALIGN_CENTER, (HANDLE) p2, (HANDLE) g1, (HANDLE) g2, NULL);
@@ -32612,6 +32435,7 @@ static Int2 NewSegregateBioseqSet (BioseqSetPtr bssp, Nlm_BtnActnProc actn, ESeg
                               (HANDLE) cfp->pages[4],
                               (HANDLE) cfp->pages[5],
                               (HANDLE) cfp->pages[6],
+                              (HANDLE) cfp->pages[7],
                               NULL);
 
   SetValue (cfp->seg_choice_grp, default_type);
@@ -32736,6 +32560,13 @@ static ValNodePtr unsequester_list = NULL;
 
 static BioseqSetPtr sequester_set = NULL;
 static const CharPtr SEQUESTER_BACKUP_FILE = "sequestr.bkp";
+static Boolean doReportAfterUnsequester = 0;
+
+NLM_EXTERN void SetDoReportAfterUnsequester (Int4 report_type)
+{
+  doReportAfterUnsequester = report_type;
+}
+
 
 static const CharPtr placeholder_id_string = "ABCDEFGHIJKLMNOPQRSTUVWXYZMagicCookiePlaceHolderABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
@@ -32780,7 +32611,7 @@ static void SequesterCategorySeqEntries (BioseqSetPtr newset, ClickableItemPtr c
   BioseqPtr bsp;
   Int4      set_pos;
 
-  if (newset == NULL || category == NULL || category->item_list == NULL) return;
+  if (newset == NULL || category == NULL || (category->item_list == NULL && category->subcategories == NULL)) return;
 
   if (category->chosen) {
     last_sep = newset->seq_set;
@@ -32960,7 +32791,7 @@ static void AddSepBackToSet (SeqEntryPtr add_back_sep, BioseqSetPtr bssp, SeqDes
   Uint2          parenttype;
   Pointer        parentptr;
   SeqEntryPtr    sep, prev, tmp;
-  SeqDescrPtr    sdp, new_sdp;
+  SeqDescrPtr    sdp, new_sdp, sdp_tmp;
   ObjValNodePtr  ovp, new_ovp;
   Boolean        found;
   Int4           pos;
@@ -32972,6 +32803,10 @@ static void AddSepBackToSet (SeqEntryPtr add_back_sep, BioseqSetPtr bssp, SeqDes
     if (sdp->extended == 0) {
       continue;
     }
+    /* don't copy set titles */
+    if (sdp->choice == Seq_descr_title) {
+      continue;
+    }
     ovp = (ObjValNodePtr) sdp;
     found = FALSE;
     for (new_sdp = parent_descriptors; new_sdp != NULL && !found; new_sdp = new_sdp->next) {
@@ -32989,9 +32824,12 @@ static void AddSepBackToSet (SeqEntryPtr add_back_sep, BioseqSetPtr bssp, SeqDes
     }
     if (!found) {
       /* propagate descriptor to members of bssp */
+      sdp_tmp = sdp->next;
+      sdp->next = NULL;
       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
         PropagateToSeqEntryIfNotDup (sep, sdp);
       }
+      sdp->next = sdp_tmp;
       ovp->idx.deleteme = TRUE;
     }
   }
@@ -33055,6 +32893,9 @@ static void ReintegrateSequesteredSets (Uint2 entityID)
   bfp = GetBaseFormForEntityID (entityID);
   RemoveSeqEntryViewer (bfp->form);
 
+  /* remove any popset titles created */
+  RemovePopsetTitles (add_back_sep);
+
   /* we created a genbank set to hold the actual parent sets */
   top_bssp = (BioseqSetPtr) add_back_sep->data.ptrvalue;
 
@@ -33088,6 +32929,8 @@ static void ReintegrateSequesteredSets (Uint2 entityID)
   top_bssp->idx.deleteme = TRUE;
   DeleteMarkedObjects (entityID, 0, NULL);
 
+  sep = GetTopSeqEntryForEntityID (sequester_set->idx.entityID);
+  RemovePopsetTitles (sep);
   DeleteMarkedObjects (sequester_set->idx.entityID, 0, NULL);
   ObjMgrSetDirtyFlag (sequester_set->idx.entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, sequester_set->idx.entityID, 0, 0);
@@ -33107,6 +32950,10 @@ static void FinishedSequester (void)
   sequester_set = NULL;
   unsequester_list = ValNodeFreeData (unsequester_list);
   FileRemove(SEQUESTER_BACKUP_FILE);
+  if (doReportAfterUnsequester > 0) {
+    CreateReportWindow (doReportAfterUnsequester);
+    doReportAfterUnsequester = 0;
+  }
 }
 
 
@@ -33265,11 +33112,10 @@ NLM_EXTERN Boolean OkToSequester (void)
 }
 
 
-NLM_EXTERN void LIBCALLBACK SequesterSequenceList (Uint2 entityID, ValNodePtr bsp_list)
+NLM_EXTERN Uint2 SequesterClickableItem (Uint2 entityID, ClickableItemPtr cip)
 {
   SeqEntryPtr sep;
   BioseqSetPtr bssp, new_set;
-  ClickableItemData cid;
   ObjMgrDataPtr  omdptop;
   ObjMgrData     omdata;
   Uint2          parenttype;
@@ -33280,25 +33126,21 @@ NLM_EXTERN void LIBCALLBACK SequesterSequenceList (Uint2 entityID, ValNodePtr bs
   BioseqViewFormPtr vfp;
   SeqEntryPtr       pulled_sep;
 
-  if (bsp_list == NULL) {
-    return;
-  }
-
   if (unsequester_list != NULL || sequester_set != NULL) {
     Message (MSG_ERROR, "You are already sequestering a set.  You cannot sequester until you have restored these sequences to the original set.");
-    return;
+    return 0;
   }
 
   sep = GetTopSeqEntryForEntityID (entityID);
   if (sep == NULL || !IS_Bioseq_set (sep)) {
     Message (MSG_ERROR, "This record does not have a top-levelset!");
-    return;
+    return 0;
   }
 
   bssp = FindTopLevelSetForDesktopFunction((BioseqSetPtr) sep->data.ptrvalue);
   if (bssp == NULL) {
     Message (MSG_ERROR, "Unable to find top level set");
-    return;
+    return 0;
   }
 
   WriteTheEntityID (entityID, SEQUESTER_BACKUP_FILE, FALSE);
@@ -33311,10 +33153,7 @@ NLM_EXTERN void LIBCALLBACK SequesterSequenceList (Uint2 entityID, ValNodePtr bs
   new_set = BioseqSetNew ();
   new_set->_class = BioseqseqSet_class_genbank;
 
-  MemSet (&cid, 0, sizeof (ClickableItemData));
-  cid.chosen = TRUE;
-  cid.item_list = bsp_list;
-  SequesterCategorySeqEntries (new_set, &cid);
+  SequesterCategorySeqEntries (new_set, cip);
 
   RestoreSeqEntryObjMgrData (sep, omdptop, &omdata); 
   DeleteMarkedObjects (entityID, 0, NULL);
@@ -33346,11 +33185,29 @@ NLM_EXTERN void LIBCALLBACK SequesterSequenceList (Uint2 entityID, ValNodePtr bs
     vfp = (BioseqViewFormPtr) bfp;
     Hide (vfp->toolForm);
   }
+  return new_entityID;
+}
+  
+
+NLM_EXTERN void LIBCALLBACK SequesterSequenceList (Uint2 entityID, ValNodePtr bsp_list)
+{
+  ClickableItemData cid;
+  Uint2          new_entityID;
+  BaseFormPtr     bfp;
+
+  if (bsp_list == NULL) {
+    return;
+  }
 
+  MemSet (&cid, 0, sizeof (ClickableItemData));
+  cid.chosen = TRUE;
+  cid.item_list = bsp_list;
+  if ((new_entityID = SequesterClickableItem (entityID, &cid)) > 0) {
   /* get rid of existing validator window, replace with validator for new sequences */
   FreeValidateWindow ();
   bfp = GetBaseFormForEntityID (new_entityID);
   ValSeqEntryForm (bfp->form);
+  }
 }
 
 
@@ -33375,361 +33232,45 @@ extern void SequesterSequencesMenuItem (IteM i)
 
   sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
   if (sep == NULL || !IS_Bioseq_set (sep)) {
-    Message (MSG_ERROR, "This record does not have a top-levelset!");
+    Message (MSG_ERROR, "This record does not have a top-level set!");
   } else {
     NewSegregateBioseqSet (FindTopLevelSetForDesktopFunction((BioseqSetPtr) sep->data.ptrvalue), SequesterSets, eSegPageId);
   }
 }
 
 
-typedef struct fixcase {
-  FORM_MESSAGE_BLOCK
-  DialoG       field_dlg;
-  DialoG       case_dlg;  
-  ButtoN       accept;
-  ButtoN       leave_dlg_up;
-
-  ValNodePtr               requested_field;
-  GetFeatureFieldString    fieldstring_func;
-  GetDescriptorFieldString descrstring_func;
-  SetFeatureFieldString    feature_apply_action;
-  SetDescriptorFieldString descriptor_apply_action;
-  FreeValNodeProc          free_vn_proc;
-  CopyValNodeDataProc      copy_vn_proc;
-  ChangeCasePtr            ccp;
-  ValNodePtr               orgnames;
-} FixCaseData, PNTR FixCasePtr;
-
-
-static void FixCaseFeatureCallback (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr fsp)
-{
-  FixCasePtr     fcp;
-  CharPtr        str;
-  ApplyValueData avd;
-
-  if (sfp == NULL || userdata == NULL) return;
-  fcp = (FixCasePtr) userdata;
-  if (fcp->fieldstring_func == NULL || fcp->feature_apply_action == NULL
-      || fcp->ccp == NULL || fcp->ccp->change == eChangeCaseNone) 
-  {
-    return;
-  }
-  
-  str = fcp->fieldstring_func (sfp, fcp->requested_field, fsp);
-  if (StringHasNoText (str)) {
-    str = MemFree (str);
-    return;
-  } else {
-    avd.text_to_replace = NULL;
-    avd.where_to_replace = EditApplyFindLocation_anywhere;
-    avd.etp = NULL;
-    avd.field_list = fcp->requested_field;
-    ChangeCase (&str, fcp->ccp, fcp->orgnames);
-    avd.new_text = str;
-    (fcp->feature_apply_action) (sfp, &avd, fsp);
-  }
-}
-
-static void FixCaseDescriptorCallback (SeqDescrPtr sdp, Pointer userdata, FilterSetPtr fsp)
+NLM_EXTERN void LIBCALLBACK SegregateSequenceList (Uint2 entityID, ValNodePtr bsp_list)
 {
-  FixCasePtr     fcp;
-  CharPtr        str;
-  ApplyValueData avd;
+  SeqEntryPtr sep;
+  BioseqSetPtr bssp;
+  ClickableItemData cid;
+  ValNodePtr list = NULL;
 
-  if (sdp == NULL || userdata == NULL) return;
-  fcp = (FixCasePtr) userdata;
-  if (fcp->descrstring_func == NULL || fcp->descriptor_apply_action == NULL
-      || fcp->ccp == NULL || fcp->ccp->change == eChangeCaseNone) 
-  {
+  if (bsp_list == NULL) {
     return;
   }
   
-  str = fcp->descrstring_func (sdp, fcp->requested_field, fsp);
-  if (StringHasNoText (str)) {
-    str = MemFree (str);
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL || !IS_Bioseq_set (sep)) {
+    Message (MSG_ERROR, "This record does not have a top-level set!");
     return;
-  } else {
-    avd.text_to_replace = NULL;
-    avd.where_to_replace = EditApplyFindLocation_anywhere;
-    avd.etp = NULL;
-    avd.field_list = fcp->requested_field;
-    ChangeCase (&str, fcp->ccp, fcp->orgnames);
-    avd.new_text = str;
-    (fcp->descriptor_apply_action) (sdp, &avd, fsp);
   }
-}
-
-
-static void FixCaseByFieldCallback (ButtoN b)
-{
-  FixCasePtr  fcp;
-  SeqEntryPtr sep;
-  ParseFieldPtr dst_field_data;
-  FilterSetPtr fsp = NULL;
-  ValNodePtr   vnp;
-
-  fcp = (FixCasePtr) GetObjectExtra (b);
-  if (fcp == NULL) return;
-
-  sep = GetTopSeqEntryForEntityID (fcp->input_entityID);
-
-  if (sep == NULL) return;
   
-  dst_field_data = DialogToPointer (fcp->field_dlg);
-  if (dst_field_data == NULL) return;
-  fcp->ccp = DialogToPointer (fcp->case_dlg);
-  if (fcp->ccp == NULL || fcp->ccp->change == eChangeCaseNone) {
-    dst_field_data = ParseFieldFree (dst_field_data);
-    fcp->ccp = MemFree (fcp->ccp);
+  bssp = FindTopLevelSetForDesktopFunction((BioseqSetPtr) sep->data.ptrvalue);
+  if (bssp == NULL) {
+    Message (MSG_ERROR, "Unable to find top level set");
     return;
   }
 
-  WatchCursor();
-  Update();
-
-  /* if we will be fixing capitalization, get org names to use in fixes */
-  if (dst_field_data->parse_field_type != PARSE_FIELD_BIOSRC_STRING
-      || dst_field_data->feature_field == NULL
-      || dst_field_data->feature_field->data.intvalue != PARSE_FIELD_BIOSRC_TAXNAME) {
-    VisitBioSourcesInSep (sep, &(fcp->orgnames), GetOrgNamesInRecordCallback);
-  }
-
-  switch (dst_field_data->parse_field_type)
-  {
-    case PARSE_FIELD_SOURCE_QUAL :
-      fcp->fieldstring_func = GetSourceQualFeatureString;
-      fcp->descrstring_func = GetSourceQualDescrString;
-      fcp->feature_apply_action = ApplySourceQualFeatureCallback;
-      fcp->descriptor_apply_action = ApplySourceQualDescriptorCallback,
-      fcp->free_vn_proc = ValNodeSimpleDataFree;
-      fcp->copy_vn_proc = SourceQualValNodeDataCopy;
-      fcp->requested_field = dst_field_data->feature_field;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                           FixCaseDescriptorCallback,
-                                           SEQFEAT_BIOSRC, 0,
-                                           Seq_descr_source, fcp);
-
-      break;
-    case PARSE_FIELD_DEFLINE:
-      fcp->fieldstring_func = NULL;
-      fcp->descrstring_func = GetStringFromStringDescriptor;
-      fcp->feature_apply_action = NULL;
-      fcp->descriptor_apply_action = ApplyTitleDescriptorCallback;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-      fcp->requested_field = ValNodeNew (NULL);
-      fcp->requested_field->data.intvalue = Seq_descr_title;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, NULL, 
-                                           FixCaseDescriptorCallback,
-                                           0, 0,
-                                           Seq_descr_title, fcp);
-      fcp->requested_field = ValNodeFree (fcp->requested_field);
-
-      break;
-    case PARSE_FIELD_BIOSRC_STRING:
-      fcp->fieldstring_func = GetSourceFeatureString;
-      fcp->descrstring_func = GetSourceDescriptorString;
-      fcp->feature_apply_action = ApplySourceStringFeatureCallback;
-      fcp->descriptor_apply_action = ApplySourceStringDescriptorCallback;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-      fcp->requested_field = dst_field_data->feature_field;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                           FixCaseDescriptorCallback,
-                                           SEQFEAT_BIOSRC, 0,
-                                           Seq_descr_source, fcp);
-      break;
-    case PARSE_FIELD_DBXREF:
-      fcp->fieldstring_func = GetBioSourceFeatureDbxrefString;
-      fcp->descrstring_func = GetBioSourceDescriptorDbxrefString;
-      fcp->feature_apply_action = ApplyBioSourceDbxrefFeatureCallback;
-      fcp->descriptor_apply_action = ApplyBioSourceDbxrefDescriptorCallback;
-      fcp->free_vn_proc = ValNodeSimpleDataFree;
-      fcp->copy_vn_proc = ValNodeStringCopy;
-      fcp->requested_field = dst_field_data->feature_field;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                           FixCaseDescriptorCallback,
-                                           SEQFEAT_BIOSRC, 0,
-                                           Seq_descr_source, fcp);
-      break;
-    case PARSE_FIELD_GENE_FIELD:
-      fcp->fieldstring_func = GetGeneFieldString;
-      fcp->descrstring_func = NULL;
-      fcp->feature_apply_action = SetGeneFieldString;
-      fcp->descriptor_apply_action = NULL;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-      fcp->requested_field = dst_field_data->feature_field;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                           NULL,
-                                           SEQFEAT_GENE, 0,
-                                           0, fcp);
-      break;
-    case PARSE_FIELD_RNA_FIELD:
-      fcp->fieldstring_func = GetRNAFieldString;
-      fcp->descrstring_func = NULL;
-      fcp->feature_apply_action = SetRNAFieldString;
-      fcp->descriptor_apply_action = NULL;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-      fcp->requested_field = dst_field_data->feature_field;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                           NULL,
-                                           SEQFEAT_RNA,
-                                           dst_field_data->feature_subtype == NULL ? 0 : dst_field_data->feature_subtype->data.intvalue,
-                                           0, fcp);
-      break;
-    case PARSE_FIELD_CDS_COMMENT:
-      fcp->fieldstring_func = GetCDSComment;
-      fcp->descrstring_func = NULL;
-      fcp->feature_apply_action = SetCDSComment;
-      fcp->descriptor_apply_action = NULL;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-      fcp->requested_field = dst_field_data->feature_field;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                           NULL,
-                                           SEQFEAT_CDREGION, FEATDEF_CDS,
-                                           0, fcp);
-      break;
-    case PARSE_FIELD_COMMENT_DESC:
-      fcp->requested_field = ValNodeNew (NULL);
-      fcp->requested_field->data.intvalue = Seq_descr_comment;
-      fcp->fieldstring_func = NULL;
-      fcp->descrstring_func = GetStringFromStringDescriptor;
-      fcp->feature_apply_action = NULL;
-      fcp->descriptor_apply_action = ApplyTitleDescriptorCallback;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, NULL, 
-                                           FixCaseDescriptorCallback,
-                                           0, 0,
-                                           Seq_descr_comment, fcp);
-      fcp->requested_field = ValNodeFree (fcp->requested_field);
-      break;
-    case PARSE_FIELD_PROTEIN_FIELD:
-      fcp->fieldstring_func = GetProteinFieldString;
-      fcp->descrstring_func = NULL;
-      fcp->feature_apply_action = SetProteinFieldString;
-      fcp->descriptor_apply_action = NULL;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-      fcp->requested_field = dst_field_data->feature_field;
-      OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                           NULL,
-                                           SEQFEAT_PROT, 0,
-                                           0, fcp);
-      break;
-    case PARSE_FIELD_IMPORT_QUAL:
-      fcp->requested_field = dst_field_data->feature_field;
-      fcp->fieldstring_func = GetGBQualString;
-      fcp->descrstring_func = NULL;
-      fcp->feature_apply_action = SetGBQualString;
-      fcp->descriptor_apply_action = NULL;
-      fcp->free_vn_proc = NULL;
-      fcp->copy_vn_proc = IntValNodeCopy;
-
-      for (vnp = dst_field_data->feature_subtype; vnp != NULL; vnp = vnp->next)
-      {
-        OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                             NULL,
-                                             0, vnp->choice,
-                                             0, fcp);
-      }
-      break;
-    case PARSE_FIELD_FEATURE_NOTE:
-      fcp->fieldstring_func = GetFeatureNote;
-      fcp->descrstring_func = NULL;
-      fcp->feature_apply_action = SetFeatureNote;
-      fcp->descriptor_apply_action = NULL;
-      fcp->free_vn_proc = ValNodeSimpleDataFree;
-      fcp->copy_vn_proc = ValNodeStringCopy;
-
-      for (vnp = dst_field_data->feature_field; vnp != NULL; vnp = vnp->next)
-      {
-        fcp->requested_field = vnp;
-        OperateOnSeqEntryConstrainedObjects (sep, fsp, FixCaseFeatureCallback, 
-                                             NULL,
-                                             0, vnp->choice,
-                                             0, fcp);
-      }
-      break;
-  }
-  fcp->orgnames = ValNodeFree (fcp->orgnames);
-  dst_field_data = ParseFieldFree (dst_field_data);
-  fcp->ccp = MemFree (fcp->ccp);
-
-  ObjMgrSetDirtyFlag (fcp->input_entityID, TRUE);
-  ObjMgrSendMsg (OM_MSG_UPDATE, fcp->input_entityID, 0, 0);
-  ArrowCursor ();
-  Update ();
+  MemSet (&cid, 0, sizeof (ClickableItemData));
+  cid.item_list = bsp_list;
+  cid.chosen = TRUE;
+  ValNodeAddPointer (&list, 0, &cid);
 
-  if (!GetStatus (fcp->leave_dlg_up)) {
-    Remove (fcp->form);
-  }
+  MakeGroupsForUniqueValues (bssp, list);
+  list = ValNodeFree (list);
 }
 
-extern void FixCaseByField (IteM i)
-{
-  GrouP              c;
-  FixCasePtr         cfp;
-  ChangeCaseData     ccd;
-  GrouP              h;
-  WindoW             w;
-  BaseFormPtr  bfp;
-
-#ifdef WIN_MAC
-  bfp = currentFormDataPtr;
-#else
-  bfp = GetObjectExtra (i);
-#endif
-  if (bfp == NULL) return;
-
-  /* Create a new window, and a struct */
-  /* to pass around the data in.       */
-
-  cfp = (FixCasePtr) MemNew (sizeof (FixCaseData));
-  if (cfp == NULL)
-    return;
-
-  w = FixedWindow (-50, -33, -10, -10, "Fix Case By Field",
-           StdCloseWindowProc);
-  SetObjectExtra (w, cfp, StdCleanupFormProc);
-  cfp->form = (ForM) w;
-  cfp->input_entityID = bfp->input_entityID;
-
-  h = HiddenGroup (w, -1, 0, NULL);
-  SetGroupSpacing (h, 10, 10);
-
-  cfp->field_dlg = ParseFieldDestDialogEx (h, NULL, NULL, FALSE, TRUE);
-
-  cfp->case_dlg = ChangeCaseDialog (h);
-  ccd.change = eChangeCaseAllLower;
-  PointerToDialog (cfp->case_dlg, &ccd);
-
-  /* Add Accept and Cancel buttons */
-
-  c = HiddenGroup (h, 3, 0, NULL);
-  cfp->accept = DefaultButton (c, "Accept", FixCaseByFieldCallback);
-  SetObjectExtra (cfp->accept, cfp, NULL);
-  PushButton (c, "Cancel", StdCancelButtonProc);
-  cfp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
-
-  /* Line things up nicely */
-
-  AlignObjects (ALIGN_CENTER, (HANDLE) cfp->field_dlg,
-                              (HANDLE) cfp->case_dlg,
-                              (HANDLE) c, NULL);
-
-
-  /* Display the window now */
-
-  RealizeWindow (w);
-  Show (w);
-  Select (w);
-  Select (cfp->accept);
-  Update ();
-}
 
 static void FormatBoxColumn (ColPtr col)
 {
@@ -35794,6 +35335,7 @@ static void ApplyBulkEdit (ButtoN b)
   ApplyValueData   avd;
   OneFieldBulkEditPtr ofp = NULL;
   TwoFieldBulkEditPtr tfp = NULL;
+  Int4                bulk_row_num, bulk_sub_num, i;
 
   dlg = (BulkEditorDlgPtr) GetObjectExtra (b);
   if (dlg == NULL) return;
@@ -35866,6 +35408,20 @@ static void ApplyBulkEdit (ButtoN b)
   gsp = GetSampleFree (gsp);
   etp = MemFree (etp);
 
+  /* update individual field editor */
+  if (dlg->last_viewed_row > 0) {
+    /* show appropriate editor for highlighted item */
+    if (DataPosFromBulkEdDlgRow (dlg->last_viewed_row, dlg->row_list, &bulk_row_num, &bulk_sub_num)) {
+      ShowBulkFieldEditor (dlg, bulk_row_num, bulk_sub_num, dlg->last_sorted_col);
+    } else {
+      dlg->last_viewed_row = 0;
+      dlg->last_viewed_col = 0;
+      for (i = 0; i < dlg->num_columns; i++) {
+        SafeHide (dlg->editor_list[i]);
+      }
+    }
+  }
+
   UpdateBulkEdDisplay (dlg);
   ObjectRect (dlg->doc, &r);
   InvalRect (&r);  
@@ -37463,6 +37019,50 @@ static Pointer GetBarcodeTestSpecimenVoucherResult (Uint1 data_choice, Pointer d
 }
 
 
+static Pointer GetBarcodeTestCollectionDateResult (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  BarcodeTestResultsPtr res = (BarcodeTestResultsPtr) data;
+  if (res == NULL || !res->failed_tests[eBarcodeTest_CollectionDate]) {
+    return NULL;
+  } else {
+    return StringSave ("TRUE");
+  }
+}
+
+
+static Pointer GetBarcodeTestOrderAssignmentResult (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  BarcodeTestResultsPtr res = (BarcodeTestResultsPtr) data;
+  if (res == NULL || !res->failed_tests[eBarcodeTest_OrderAssignment]) {
+    return NULL;
+  } else {
+    return StringSave ("TRUE");
+  }
+}
+
+
+static Pointer GetBarcodeTestLowTraceResult (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  BarcodeTestResultsPtr res = (BarcodeTestResultsPtr) data;
+  if (res == NULL || !res->failed_tests[eBarcodeTest_LowTrace]) {
+    return NULL;
+  } else {
+    return StringSave ("TRUE");
+  }
+}
+
+
+static Pointer GetBarcodeTestFrameShiftResult (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  BarcodeTestResultsPtr res = (BarcodeTestResultsPtr) data;
+  if (res == NULL || !res->failed_tests[eBarcodeTest_FrameShift]) {
+    return NULL;
+  } else {
+    return StringSave ("TRUE");
+  }
+}
+
+
 static Pointer GetBarcodeTestPercentNsResult (Uint1 data_choice, Pointer data, Pointer metadata)
 {
   BarcodeTestResultsPtr res = (BarcodeTestResultsPtr) data;
@@ -37478,26 +37078,11 @@ static Pointer GetBarcodeTestPercentNsResult (Uint1 data_choice, Pointer data, P
 
 static Pointer HasBarcodeKeyword (Uint1 data_choice, Pointer data, Pointer metadata)
 {
-  SeqDescrPtr sdp;
-  SeqMgrDescContext context;
-  GBBlockPtr gb;
-  ValNodePtr vnp;
   Boolean rval = FALSE;
 
   BarcodeTestResultsPtr res = (BarcodeTestResultsPtr) data;
   if (res != NULL && res->bsp != NULL) {
-    for (sdp = SeqMgrGetNextDescriptor (res->bsp, NULL, Seq_descr_genbank, &context);
-         sdp != NULL && !rval;
-         sdp = SeqMgrGetNextDescriptor (res->bsp, sdp, Seq_descr_genbank, &context)) {
-      gb = (GBBlockPtr) sdp->data.ptrvalue;
-      if (gb != NULL) {
-        for (vnp = gb->keywords; vnp != NULL && !rval; vnp = vnp->next) {
-          if (StringCmp (vnp->data.ptrvalue, "BARCODE") == 0) {
-            rval = TRUE;
-          }
-        }
-      }
-    }
+    rval = BioseqHasBarcodeKeyword(res->bsp);
   }
   if (rval) {
     return StringSave ("TRUE");
@@ -37570,6 +37155,10 @@ static BulkEdFieldData barcode_test_fields[] = {
   { "Country", NULL, NULL, GetBarcodeTestCountryResult, NULL, BulkFreeSimpleText, NULL, BulkFormatTrueFalse, BulkDrawTrueFalse, NULL, BulkSimpleTextCopy }, 
   { "Voucher", NULL, NULL, GetBarcodeTestSpecimenVoucherResult, NULL, BulkFreeSimpleText, NULL, BulkFormatTrueFalse, BulkDrawTrueFalse, NULL, BulkSimpleTextCopy }, 
   { "Percent Ns", NULL, NULL, GetBarcodeTestPercentNsResult, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BarcodeFormatPercentN, NULL, NULL, BulkSimpleTextCopy }, 
+  { "Collection Date", NULL, NULL, GetBarcodeTestCollectionDateResult, NULL, BulkFreeSimpleText, NULL, BulkFormatTrueFalse, BulkDrawTrueFalse, NULL, BulkSimpleTextCopy }, 
+  { "Order Assignment", NULL, NULL, GetBarcodeTestOrderAssignmentResult, NULL, BulkFreeSimpleText, NULL, BulkFormatTrueFalse, BulkDrawTrueFalse, NULL, BulkSimpleTextCopy }, 
+  { "Low Trace", NULL, NULL, GetBarcodeTestLowTraceResult, NULL, BulkFreeSimpleText, NULL, BulkFormatTrueFalse, BulkDrawTrueFalse, NULL, BulkSimpleTextCopy }, 
+  { "Frame Shift", NULL, NULL, GetBarcodeTestFrameShiftResult, NULL, BulkFreeSimpleText, NULL, BulkFormatTrueFalse, BulkDrawTrueFalse, NULL, BulkSimpleTextCopy }, 
   { "Has BARCODE Keyword", NULL, NULL, HasBarcodeKeyword, NULL, BulkFreeSimpleText, NULL, BulkFormatTrueFalse, BulkDrawTrueFalse, NULL, BulkSimpleTextCopy }, 
   { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
 
@@ -37681,6 +37270,76 @@ extern DialoG LatLonTestResultsDisplay (GrouP h)
 }
 
 
+static BulkEdFieldData trim_sequence_fields[] = {
+  { "Current PercentN", NULL, NULL, GetCurrentPercentN, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
+  { "Bases to Remove", NULL, NULL, GetTrimRemove, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
+  { "Remaining Bases", NULL, NULL, GetTrimRemaining, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
+  { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
+
+extern DialoG TrimSequenceResultsDisplay (GrouP h)
+{
+  return CreateBulkEditorDialog (h, trim_sequence_fields, NULL, NULL, FALSE, ScrollToTrimSequenceItem, NULL);
+}
+
+
+static void DefaultCheckTrimSequenceResults (BulkEditorRowPtr berp)
+{
+  ValNodePtr vnp;
+
+  if (berp == NULL) {
+    return;
+  }
+  while (berp->object_list != NULL) {
+    if (berp->subrows == NULL) {
+      vnp = berp->object_list;
+      if (vnp != NULL) {
+        if (TrimShouldDelete (vnp->choice, vnp->data.ptrvalue, NULL)) {
+          berp->selected = FALSE;
+        } else {
+          berp->selected = TRUE;
+        }
+      }
+    } else {
+      DefaultCheckTrimSequenceResults (berp->subrows);
+      berp->selected = AllBulkEditorRowsSelected (berp->subrows);
+    }
+
+    berp++;
+  }
+}
+
+
+extern void DefaultCheckTrimSequenceResultsDisplay (DialoG d)
+{
+  BulkEditorDlgPtr    dlg;
+  RecT                r;
+
+  dlg = (BulkEditorDlgPtr) GetObjectExtra (d);
+  if (dlg == NULL) return;
+
+  DefaultCheckTrimSequenceResults (dlg->row_list);
+    
+  UpdateCheckStatus (dlg);
+
+  ObjectRect (dlg->doc, &r);
+  InvalRect (&r);  
+  Update ();
+}
+
+
+static BulkEdFieldData trim_sequence_end_fields[] = {
+  { "Accession", NULL, NULL, GetTrimAccession, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
+  { "Remove from 5'", NULL, NULL, GetTrim5, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
+  { "Remove from 3'", NULL, NULL, GetTrim3, BulkDisplaySimpleText, BulkFreeSimpleText, NULL, BulkFormatSimpleText, NULL, NULL, BulkSimpleTextCopy },
+  { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}};
+
+extern DialoG TrimSequenceEndDisplay (GrouP h)
+{
+  return CreateBulkEditorDialog (h, trim_sequence_end_fields, NULL, NULL, FALSE, ScrollToTrimSequenceItem, NULL);
+}
+
+
+
 static Pointer GetTaxName (Uint1 data_choice, Pointer data, Pointer metadata)
 {
   TaxFixItemPtr t;
diff --git a/sequin/sequin6.c b/sequin/sequin6.c
index 4459543..4eedd85 100644
--- a/sequin/sequin6.c
+++ b/sequin/sequin6.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   11/12/97
 *
-* $Revision: 6.342 $
+* $Revision: 6.355 $
 *
 * File Description: 
 *
@@ -59,6 +59,10 @@
 #include <vsm.h>
 #include <actutils.h>
 #include <findrepl.h>
+#define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
+#include <macrodlg.h>
+#include <macroapi.h>
 
 #define NUMBER_OF_SUFFIXES    7
 
@@ -260,8 +264,8 @@ typedef enum {
   eFieldTypeCommentDescriptor,
   eFieldTypeFeatureNote,
   eFieldTypePublication,
-  eNumFieldType
-} FieldType;
+  eFieldType_Max
+} SegregateFieldType;
 
 static CharPtr field_type_names[] = {
   "Gene",
@@ -299,9 +303,9 @@ static FieldSubfieldPtr FieldSubfieldFree (FieldSubfieldPtr f)
 typedef struct fieldsubfielddlg {
   DIALOG_MESSAGE_BLOCK
   PopuP field_list;
-  DialoG subfield_dlg[eNumFieldType];
+  DialoG subfield_dlg[eFieldType_Max];
   DialoG impfeat_type;
-  Boolean allowed_fields[eNumFieldType];
+  Boolean allowed_fields[eFieldType_Max];
   Nlm_ChangeNotifyProc     change_notify;
   Pointer                  change_userdata;
 } FieldSubfieldDlgData, PNTR FieldSubfieldDlgPtr;
@@ -314,7 +318,7 @@ static Int4 FieldNumFromListVal (Int4 list_val, BoolPtr allowed_fields)
 
   if (list_val < 1) return -1;
 
-  for (i = 0; i < eNumFieldType && field_num < 0; i++) {
+  for (i = 0; i < eFieldType_Max && field_num < 0; i++) {
     if (allowed_fields[i]) {
       if (list_val - 1 == i) {
         field_num = i;
@@ -354,7 +358,7 @@ static void ChangeFieldType (PopuP p)
   list_val = GetValue (dlg->field_list);
   field_num = FieldNumFromListVal (list_val, dlg->allowed_fields);
 
-  for (i = 0; i < eNumFieldType; i++) {
+  for (i = 0; i < eFieldType_Max; i++) {
     if (dlg->subfield_dlg[i] == NULL) continue;
     if (i == field_num) {
       Show (dlg->subfield_dlg[i]);
@@ -512,14 +516,14 @@ CreateFieldSubfieldDlg
   if (allowed_fields == NULL) {
     MemSet (dlg->allowed_fields, TRUE, sizeof (dlg->allowed_fields));
   } else {
-    for (i = 0; i < eNumFieldType; i++) {      
+    for (i = 0; i < eFieldType_Max; i++) {      
       dlg->allowed_fields[i] = allowed_fields[i];
     }
   }
 
   dlg->field_list = PopupList (p, TRUE, ChangeFieldType);
   SetObjectExtra (dlg->field_list, dlg, NULL);
-  for (i = 0; i < eNumFieldType; i++) {
+  for (i = 0; i < eFieldType_Max; i++) {
     if (dlg->allowed_fields[i]) {
       PopupItem (dlg->field_list, field_type_names[i]);
     }
@@ -578,7 +582,7 @@ CreateFieldSubfieldDlg
                               (HANDLE) g2,
                               NULL);
 
-  for (i = 0; i < eNumFieldType; i++) {
+  for (i = 0; i < eFieldType_Max; i++) {
     Hide (dlg->subfield_dlg[i]);
   }
   return (DialoG) p;
@@ -1022,14 +1026,14 @@ static void DeleteFeaturesByText_Callback (SeqEntryPtr sep,
 					   Int2        indent)
 {
   ConvertFormPtr cfp;
-  BioseqPtr      bsp;
-  BioseqSetPtr   bssp;
+  BioseqPtr      bsp = NULL;
+  BioseqSetPtr   bssp = NULL;
   SeqAnnotPtr    sap;
   SeqFeatPtr     sfp;
   GeneRefPtr     grp;
   ProtRefPtr     prp;
   RnaRefPtr      rrp;
-  Boolean        found;
+  Boolean        found = FALSE;
 
   /* Check parameters */
 
@@ -1101,13 +1105,13 @@ static void DeleteFeaturesByText_Callback (SeqEntryPtr sep,
       sfp->idx.deleteme = TRUE;
       break;
     case 2 :
-      if (IS_Bioseq (sep))
+      if (bsp != NULL)
 	bsp->idx.deleteme = TRUE;
       break;
     case 3 :
-      if (IS_Bioseq_set (sep))
+      if (bssp != NULL)
 	bssp->idx.deleteme = TRUE;
-      else {
+      else if (bsp != NULL) {
 	if (bsp->idx.parenttype == OBJ_BIOSEQSET) {
 	  bssp = (BioseqSetPtr) bsp->idx.parentptr;
 	  bssp->idx.deleteme = TRUE;
@@ -1241,7 +1245,7 @@ static void DeleteSourceByText (SeqDescrPtr    sdp,
 				ConvertFormPtr cfp)
 
 {
-  Boolean       found;
+  Boolean       found = FALSE;
   BioseqSetPtr  bssp;
   BioSourcePtr  biop;
 
@@ -1506,7 +1510,7 @@ extern Int2 LIBCALLBACK CreateDeleteByTextWindow (Pointer data)
   GrouP              p;
   StdEditorProcsPtr  sepp;
   WindoW             w;
-  Boolean            allowed[eNumFieldType];
+  Boolean            allowed[eFieldType_Max];
 
   /* Check parameters and get a pointer to the current data */
 
@@ -1567,7 +1571,7 @@ extern Int2 LIBCALLBACK CreateDeleteByTextWindow (Pointer data)
 
   p = HiddenGroup (h, 6, 0, NULL);
   StaticPrompt (p, "Find string in", 0, popupMenuHeight, programFont, 'l');
-  MemSet (allowed, TRUE, sizeof (Boolean) * eNumFieldType);
+  MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
   allowed[eFieldTypeCommentDescriptor] = FALSE;
   allowed[eFieldTypeFeatureNote] = FALSE;
   allowed[eFieldTypePublication] = FALSE;
@@ -2434,7 +2438,7 @@ static void CleanupSegregatePage (GraphiC g, VoidPtr data)
 
 extern Int2 LIBCALLBACK CreateSegregateByTextWindow (Pointer data)
 {
-  Boolean            allowed[eNumFieldType];
+  Boolean            allowed[eFieldType_Max];
   GrouP              c;
   ConvertFormPtr     cfp;
   GrouP              g;
@@ -2495,7 +2499,7 @@ extern Int2 LIBCALLBACK CreateSegregateByTextWindow (Pointer data)
 
   p = HiddenGroup (h, 6, 0, NULL);
   StaticPrompt (p, "Find string in", 0, popupMenuHeight, programFont, 'l');
-  MemSet (allowed, TRUE, sizeof (Boolean) * eNumFieldType);
+  MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
   allowed[eFieldTypeCommentDescriptor] = TRUE;
 
   cfp->target_dlg = CreateFieldSubfieldDlg (p, allowed, ChangeTargetFields, cfp);
@@ -4010,7 +4014,7 @@ static void ClearRemoveOutsideText (ButtoN b)
 
 extern void RemoveTextOutsideString (IteM i)
 {
-  Boolean            allowed[eNumFieldType];
+  Boolean            allowed[eFieldType_Max];
   BaseFormPtr        bfp;
   GrouP              buttonGroup;
   ConvertFormPtr     cfp;
@@ -4088,7 +4092,7 @@ extern void RemoveTextOutsideString (IteM i)
   p2 = StaticPrompt (mainGroup, "Perform excision in", 0, popupMenuHeight, programFont, 'l');
 
   /* selecting the target field */
-  MemSet (allowed, TRUE, sizeof (Boolean) * eNumFieldType);
+  MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
   allowed[eFieldTypeFeatureNote] = FALSE;
   allowed[eFieldTypePublication] = FALSE;
   cfp->target_dlg = CreateFieldSubfieldDlg (mainGroup, allowed, ChangeTargetFields, cfp);
@@ -4134,7 +4138,7 @@ extern void RemoveTextInsideString (IteM i)
   SeqEntryPtr        sep;
   StdEditorProcsPtr  sepp;
   WindoW             w;
-  Boolean            allowed[eNumFieldType];
+  Boolean            allowed[eFieldType_Max];
 
 #ifdef WIN_MAC
   bfp = currentFormDataPtr;
@@ -4178,7 +4182,7 @@ extern void RemoveTextInsideString (IteM i)
 
   ppt2 = StaticPrompt (h, "Perform excision in", 0, popupMenuHeight, programFont, 'c');
   
-  MemSet (allowed, TRUE, sizeof (Boolean) * eNumFieldType);
+  MemSet (allowed, TRUE, sizeof (Boolean) * eFieldType_Max);
   allowed[eFieldTypeCommentDescriptor] = TRUE;
   allowed[eFieldTypeFeatureNote] = FALSE;
   allowed[eFieldTypePublication] = FALSE;
@@ -4528,7 +4532,12 @@ static void AdjustSeqLocForApply (SeqFeatPtr sfp, ApplyFormPtr afp)
   num_str = MemFree (num_str);
   num_str = SaveStringFromText (afp->right_end);
   if (num_str == NULL) return;
+  if (num_str[0] == '^') {
+    is_caret = TRUE;
+    to = atoi (num_str + 1);
+  } else {
   to = atoi (num_str);
+  }
   num_str = MemFree (num_str);
   if (from > to)
   {
@@ -4752,6 +4761,7 @@ typedef struct adjustfeatforgapdialog {
   GrouP  partial_grp;
   ButtoN trim_ends;
   ButtoN split_internal;
+  ButtoN split_in_intron;
 
   Nlm_ChangeNotifyProc     change_notify;
   Pointer                  change_userdata;
@@ -4774,17 +4784,23 @@ static void AdjustFeaturesForGapToDialog (DialoG d, Pointer udata)
     SetStatus (dlg->known_gaps, FALSE);
     SetStatus (dlg->trim_ends, FALSE);
     SetStatus (dlg->split_internal, FALSE);
+    SetStatus (dlg->split_in_intron, FALSE);
+    Disable (dlg->split_in_intron);
     SetValue (dlg->partial_grp, 2);
   } else {
     PointerToDialog (dlg->feature_select, data->feature_list);
-    SetStatus (dlg->unknown_gaps, data->unknown_gaps);
-    SetStatus (dlg->known_gaps, data->known_gaps);
-    SetStatus (dlg->split_internal, data->split_internal);
-    SetStatus (dlg->trim_ends, data->trim_ends);
+    SetStatus (dlg->unknown_gaps, data->options & eAdjustFeatForGap_unknown_gaps);
+    SetStatus (dlg->known_gaps, data->options & eAdjustFeatForGap_known_gaps);
+    SetStatus (dlg->split_internal, data->options & eAdjustFeatForGap_split_internal);
+    SetStatus (dlg->split_in_intron, data->options & eAdjustFeatForGap_split_in_intron);
+    if (!(data->options & eAdjustFeatForGap_split_internal)) {
+      Disable (dlg->split_in_intron);
+    }
+    SetStatus (dlg->trim_ends, data->options & eAdjustFeatForGap_trim_ends);
 
-    if (data->make_partial && data->partial_for_pseudo) {
+    if ((data->options & eAdjustFeatForGap_make_partial) && (data->options & eAdjustFeatForGap_partial_for_pseudo)) {
       SetValue (dlg->partial_grp, 1);
-    } else if (data->make_partial && !data->partial_for_pseudo) {
+    } else if ((data->options & eAdjustFeatForGap_make_partial) && !(data->options & eAdjustFeatForGap_partial_for_pseudo)) {
       SetValue (dlg->partial_grp, 2);
     } else {
       SetValue (dlg->partial_grp, 3);
@@ -4809,27 +4825,35 @@ static Pointer AdjustFeaturesForGapToPointer (DialoG d)
   data->feature_list = (ValNodePtr) DialogToPointer (dlg->feature_select);
   data->features_in_gap = NULL;
 
-  data->unknown_gaps = GetStatus (dlg->unknown_gaps);
-  data->known_gaps = GetStatus (dlg->known_gaps);
+  if (GetStatus (dlg->unknown_gaps)) {
+    data->options |= eAdjustFeatForGap_unknown_gaps;
+  }
+  if (GetStatus (dlg->known_gaps)) {
+    data->options |= eAdjustFeatForGap_known_gaps;
+  }
 
   grp_val = GetValue (dlg->partial_grp);
   switch (grp_val) {
     case 1:
-      data->make_partial = TRUE;
-      data->partial_for_pseudo = TRUE;
+      data->options |= eAdjustFeatForGap_make_partial | eAdjustFeatForGap_partial_for_pseudo;
       break;
     case 2:
-      data->make_partial = TRUE;
-      data->partial_for_pseudo = FALSE;
+      data->options |= eAdjustFeatForGap_make_partial;
       break;
     case 3:
-      data->make_partial = FALSE;
-      data->partial_for_pseudo = FALSE;
+      /* both false */
       break;
   }
   
-  data->split_internal = GetStatus (dlg->split_internal);
-  data->trim_ends = GetStatus (dlg->trim_ends);
+  if (GetStatus (dlg->split_internal)) {
+    data->options |= eAdjustFeatForGap_split_internal;
+    if (GetStatus (dlg->split_in_intron)) {
+      data->options |= eAdjustFeatForGap_split_in_intron;
+    }
+  }
+  if (GetStatus (dlg->trim_ends)) {
+    data->options |= eAdjustFeatForGap_trim_ends;
+  }
 
   return (Pointer) data;
 }
@@ -4860,12 +4884,12 @@ static ValNodePtr TestAdjustForGapsDialog (DialoG d)
     ValNodeAddPointer (&err_list, 0, "No features");
   }
 
-  if (!data->unknown_gaps && !data->known_gaps)
+  if (!(data->options & eAdjustFeatForGap_unknown_gaps) && !(data->options & eAdjustFeatForGap_known_gaps))
   {
     ValNodeAddPointer (&err_list, 0, "No gaps");
   }
 
-  if (!data->split_internal && !data->trim_ends)
+  if (!(data->options & eAdjustFeatForGap_split_internal) && !(data->options & eAdjustFeatForGap_trim_ends))
   {
     ValNodeAddPointer (&err_list, 0, "No action");
   }
@@ -4881,6 +4905,11 @@ static void AdjustFeaturesForGapsChangeNotifyButton (ButtoN b)
   AdjustFeatForGapDialogPtr dlg;
 
   dlg = (AdjustFeatForGapDialogPtr) GetObjectExtra (b);
+  if (GetStatus (dlg->split_internal)) {
+    Enable (dlg->split_in_intron);
+  } else {
+    Disable (dlg->split_in_intron);
+  }
   if (dlg != NULL && dlg->change_notify != NULL) {
     (dlg->change_notify) (dlg->change_userdata);
   }
@@ -4937,11 +4966,14 @@ static DialoG AdjustFeaturesForGapDialog (GrouP h, Uint2 entityID, Nlm_ChangeNot
   RadioButton (dlg->partial_grp, "Never");
   SetValue (dlg->partial_grp, 2);
 
-  g2 = HiddenGroup (p, 2, 0, NULL);
+  g2 = HiddenGroup (p, 3, 0, NULL);
   dlg->trim_ends = CheckBox (g2, "Trim ends in gaps", AdjustFeaturesForGapsChangeNotifyButton);
   SetObjectExtra (dlg->trim_ends, dlg, NULL);
   dlg->split_internal = CheckBox (g2, "Split for internal gaps", AdjustFeaturesForGapsChangeNotifyButton);
   SetObjectExtra (dlg->split_internal, dlg, NULL);
+  dlg->split_in_intron = CheckBox (g2, "(Even when gaps are in introns)", AdjustFeaturesForGapsChangeNotifyButton);
+  SetObjectExtra (dlg->split_in_intron, dlg, NULL);
+  Disable (dlg->split_in_intron);
 
   AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_select, (HANDLE) g, (HANDLE) dlg->partial_grp, (HANDLE) g2, NULL);
   return (DialoG) p;
@@ -4983,7 +5015,7 @@ static void FindFeaturesToBeAdjustedForGapsCallback (SeqFeatPtr sfp, Pointer dat
 
   gapped_bioseq = BioseqFind (SeqLocId (sfp->location));
 
-  LocationContainsGaps (sfp->location, gapped_bioseq, faap->afgp->unknown_gaps, faap->afgp->known_gaps, &terminal_gaps, &internal_gaps, &entirely_in_gap);
+  LocationContainsGaps (sfp->location, gapped_bioseq, faap->afgp->options, &terminal_gaps, &internal_gaps, &entirely_in_gap);
   if (entirely_in_gap)
   {
     ValNodeAddPointer (&(faap->features_in_gap), OBJ_SEQFEAT, sfp);
@@ -4994,8 +5026,8 @@ static void FindFeaturesToBeAdjustedForGapsCallback (SeqFeatPtr sfp, Pointer dat
     ValNodeAddPointer (&(faap->features_contain_gap), OBJ_SEQFEAT, sfp);
   }
 
-  if ((faap->afgp->split_internal && internal_gaps) 
-      || (faap->afgp->trim_ends && terminal_gaps)) 
+  if (((faap->afgp->options & eAdjustFeatForGap_split_internal) && internal_gaps) 
+      || ((faap->afgp->options & eAdjustFeatForGap_trim_ends) && terminal_gaps)) 
   {
     ValNodeAddPointer (&(faap->features_to_adjust), OBJ_SEQFEAT, sfp);
   }
@@ -5421,7 +5453,7 @@ static void AdjustCodingRegionLocationsForGapLocations (BioseqPtr bsp, ValNodePt
 {
   SeqFeatPtr        sfp;
   SeqMgrFeatContext fcontext;
-  BioseqPtr         protbsp = NULL, new_protbsp;
+  BioseqPtr         protbsp = NULL, new_protbsp = NULL;
   SeqFeatPtr        new_sfp;
   CdRegionPtr       crp;
   Boolean           partial5, partial3;
@@ -6435,7 +6467,6 @@ static void RealApplyBioFeatToAll (Uint2        entityID,
     
     SetApplyFeatureLocation (sfp, afp);      
     AddToComment (sfp, afp->feature_details_data->featcomment);
-    ConvertToOldRNAFormat (sfp);
 
     if (! StringHasNoText (afp->feature_details_data->geneName)) {
       if (entityID > 0 
@@ -9558,7 +9589,7 @@ static void ParseDefOrLocalIDToSource (BaseFormPtr bfp, Boolean parsedef, CharPt
   if (sep == NULL) return;
   pfp = (ParseFormPtr) MemNew (sizeof (ParseFormData));
   if (pfp == NULL) return;
-  w = FixedWindow (-50, -33, -10, -10, "Parse Def Line", StdCloseWindowProc);
+  w = FixedWindow (-50, -33, -10, -10, "Parse file to source", StdCloseWindowProc);
   SetObjectExtra (w, pfp, StdCleanupFormProc);
   pfp->form = (ForM) w;
   pfp->formmessage = ParseDeflineMessageProc;
@@ -10023,9 +10054,9 @@ static void ChangeModPopup (PopuP p)
   }
 }
 
-extern void AddModToOrg (IteM i)
+
+extern void AddModToOrgBaseForm (BaseFormPtr bfp)
 {
-  BaseFormPtr  bfp;
   AddModFormPtr amfp;
   WindoW w;
   GrouP	g;
@@ -10034,11 +10065,6 @@ extern void AddModToOrg (IteM i)
   Int2 index;
   ButtoN b;
 
-#ifdef WIN_MAC
-  bfp = currentFormDataPtr;
-#else
-  bfp = GetObjectExtra (i);
-#endif
   if (bfp == NULL) return;
 
   amfp = (AddModFormPtr) MemNew (sizeof (AddModFormData));
@@ -10086,7 +10112,20 @@ extern void AddModToOrg (IteM i)
   RealizeWindow(w);
   Show(w);
   Update();
+}
+
+
+extern void AddModToOrg (IteM i)
+{
+  BaseFormPtr  bfp;
   
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+
+  AddModToOrgBaseForm (bfp);
 }
 
 typedef struct descformdata {
@@ -10109,8 +10148,24 @@ typedef struct descformdata {
   Int2           segSetCount;
   Uint2          descsubtype;
   ButtoN         createNewBtn;
+  CharPtr        user_object_tag;
 } DescFormData, PNTR DescFormPtr;
 
+
+static Boolean IsUserObjectCorrectTag (UserObjectPtr uop, CharPtr user_object_tag)
+{
+  if (uop == NULL) {
+    return FALSE;
+  } else if (user_object_tag == NULL) {
+    return TRUE;
+  } else if (StringCmp (uop->type->str, user_object_tag) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
 static Boolean FindDescrFunc (GatherContextPtr gcp)
 
 {
@@ -10122,7 +10177,8 @@ static Boolean FindDescrFunc (GatherContextPtr gcp)
   if (dfp == NULL) return TRUE;
   if (gcp->thistype == OBJ_SEQDESC) {
     vnp = (ValNodePtr) gcp->thisitem;
-    if (vnp != NULL && vnp->choice == dfp->lookfor) {
+    if (vnp != NULL && vnp->choice == dfp->lookfor 
+        && (vnp->choice != Seq_descr_user || IsUserObjectCorrectTag(vnp->data.ptrvalue, dfp->user_object_tag))) {
       dfp->oldEntityID = gcp->entityID;
       dfp->oldItemID = gcp->itemID;
       dfp->oldItemtype = gcp->thistype;
@@ -10423,7 +10479,7 @@ static void NewDescriptorMessageProc (ForM f, Int2 mssg)
   }
 }
 
-extern void NewDescriptorMenuFunc (ObjMgrProcPtr ompp, BaseFormPtr bfp, Uint2 descsubtype)
+extern void NewDescriptorMenuFuncEx (ObjMgrProcPtr ompp, BaseFormPtr bfp, Uint2 descsubtype, CharPtr user_object_tag)
 
 {
   ButtoN             b;
@@ -10454,6 +10510,9 @@ extern void NewDescriptorMenuFunc (ObjMgrProcPtr ompp, BaseFormPtr bfp, Uint2 de
   if (dfp == NULL) return;
   dfp->ompp = ompp;
   dfp->lookfor = ompp->subinputtype;
+  if (dfp->lookfor == Seq_descr_user) {
+    dfp->user_object_tag = user_object_tag;
+  }
   dfp->found = FALSE;
   dfp->descsubtype = descsubtype;
   bsp =  GetBioseqGivenIDs (bfp->input_entityID, bfp->input_itemID, bfp->input_itemtype);
@@ -10544,6 +10603,12 @@ extern void NewDescriptorMenuFunc (ObjMgrProcPtr ompp, BaseFormPtr bfp, Uint2 de
   Update ();
 }
 
+extern void NewDescriptorMenuFunc (ObjMgrProcPtr ompp, BaseFormPtr bfp, Uint2 descsubtype)
+{
+  NewDescriptorMenuFuncEx (ompp, bfp, descsubtype, NULL);
+}
+
+
 static void NewDescriptorMenuProc (IteM i)
 
 {
@@ -10554,6 +10619,22 @@ static void NewDescriptorMenuProc (IteM i)
   NewDescriptorMenuFunc (nop->ompp, nop->bfp, nop->descsubtype);
 }
 
+
+static void NewDescriptorMenuProcExtra (IteM i)
+
+{
+  NewObjectPtr  nop;
+
+  nop = (NewObjectPtr) GetObjectExtra (i);
+  if (nop == NULL) return;
+  if (nop->blurb == NULL) {
+    NewDescriptorMenuFunc (nop->ompp, nop->bfp, nop->descsubtype);
+  } else {
+    NewDescriptorMenuFuncEx (nop->ompp, nop->bfp, nop->descsubtype, nop->blurb);
+  }
+}
+
+
 extern void SetupNewDescriptorsMenu (MenU m, BaseFormPtr bfp)
 
 {
@@ -10593,6 +10674,26 @@ extern void SetupNewDescriptorsMenu (MenU m, BaseFormPtr bfp)
                 /* skip */
               } else if (!allow_structured_comment && ompp->subinputtype == Seq_descr_user && StringCmp (ompp->proclabel, "Structured Comment") == 0) {
                 /* skip */
+              } else if (ompp->subinputtype == Seq_descr_user) {
+                i = CommandItem (m, ompp->proclabel, NewDescriptorMenuProcExtra);
+                nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
+                if (nop != NULL) {
+                  nop->ompp = ompp;
+                  nop->bfp = bfp;
+                  nop->descsubtype = ompp->subinputtype;
+                  if (StringCmp (ompp->proclabel, "DBLink") == 0) {
+                    nop->blurb = "DBLink"; 
+                  } else if (StringCmp (ompp->proclabel, "GenomeProjectsDB") == 0) {
+                    nop->blurb = "GenomeProjectsDB";
+                  } else if (StringCmp (ompp->proclabel, "Structured Comment") == 0) {
+                    nop->blurb = "StructuredComment";
+                  } else if (StringCmp (ompp->proclabel, "TPA Assembly") == 0) {
+                    nop->blurb = "TpaAssembly";
+                  } else if (StringCmp (ompp->proclabel, "RefGene Tracking") == 0) {
+                    nop->blurb = "RefGeneTracking";
+                  }
+                }
+                SetObjectExtra (i, (Pointer) nop, StdCleanupExtraProc);               
               } else {
                 i = CommandItem (m, ompp->proclabel, NewDescriptorMenuProc);
                 nop = (NewObjectPtr) MemNew (sizeof (NewObjectData));
@@ -12674,7 +12775,9 @@ extern void tRNAScanUpdate (IteM i)
 
 typedef struct resolvefeatureoverlaps {
   Uint1 trim_type;
+  ValNodePtr trim_constraint;
   Uint1 intersect_type;
+  ValNodePtr intersect_constraint;
   LogInfoPtr lip;
 } ResolveFeatureOverlapsData, PNTR ResolveFeatureOverlapsPtr;
 
@@ -12770,6 +12873,7 @@ static void ResolveFeatureOverlapsBioseqCallback (BioseqPtr bsp, Pointer data)
   r = (ResolveFeatureOverlapsPtr) data;
   if (bsp == NULL || r == NULL) return;
 
+  MemSet (&vn, 0, sizeof (ValNode));
   vn.next = NULL;
   vn.choice = OBJ_SEQFEAT;
 
@@ -12778,8 +12882,11 @@ static void ResolveFeatureOverlapsBioseqCallback (BioseqPtr bsp, Pointer data)
        sfp = SeqMgrGetNextFeature (bsp, sfp, 0, r->trim_type, &fcontext))
   {
     vn.data.ptrvalue = sfp;
+    if (!DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, r->trim_constraint)) {
+      continue;
+    }
     feat_desc = GetDiscrepancyItemText (&vn);
-    overlap_list = ListFeaturesOverlappingLocation (bsp, sfp->location, 0, r->intersect_type);
+    overlap_list = ListFeaturesOverlappingLocationEx (bsp, sfp->location, 0, r->intersect_type, r->intersect_constraint);
     if (TrimLocationForIntersectingFeatures (&(sfp->location), overlap_list))
     {
       if (sfp->location == NULL)
@@ -12804,7 +12911,9 @@ static void ResolveFeatureOverlapsBioseqCallback (BioseqPtr bsp, Pointer data)
 typedef struct resolvefeatureoverlapsform {
   FORM_MESSAGE_BLOCK
   DialoG trim_type;
+  DialoG trim_constraint;
   DialoG intersect_type;
+  DialoG intersect_constraint;
   DialoG accept_cancel;
 
 } ResolveFeatureOverlapsFormData, PNTR ResolveFeatureOverlapsFormPtr;
@@ -12828,11 +12937,46 @@ static void SetResolveFeatureOverlapsFormAccept (Pointer data)
   {
     EnableAcceptCancelDialogAccept (dlg->accept_cancel);
   }
+
   vnp1 = ValNodeFree (vnp1);
   vnp2 = ValNodeFree (vnp2);
 }
 
 
+static void ChangeTrimFeatureType (Pointer data)
+{
+  ResolveFeatureOverlapsFormPtr dlg;
+  ValNodePtr                    vnp;
+
+  dlg = (ResolveFeatureOverlapsFormPtr) data;
+  if (dlg == NULL) return;
+
+  vnp = DialogToPointer (dlg->trim_type);
+  if (vnp != NULL) {
+    ChangeComplexConstraintFieldType (dlg->trim_constraint, FieldType_feature_field, NULL, vnp->choice);
+  }
+  vnp = ValNodeFree (vnp);
+  SetResolveFeatureOverlapsFormAccept (data);
+}
+
+
+static void ChangeIntersectFeatureType (Pointer data)
+{
+  ResolveFeatureOverlapsFormPtr dlg;
+  ValNodePtr                    vnp;
+
+  dlg = (ResolveFeatureOverlapsFormPtr) data;
+  if (dlg == NULL) return;
+
+  vnp = DialogToPointer (dlg->intersect_type);
+  if (vnp != NULL) {
+    ChangeComplexConstraintFieldType (dlg->intersect_constraint, FieldType_feature_field, NULL, vnp->choice);
+  }
+  vnp = ValNodeFree (vnp);
+  SetResolveFeatureOverlapsFormAccept (data);
+}
+
+
 static Boolean ResolveFeatureOverlapAction (Pointer data)
 {
   ResolveFeatureOverlapsFormPtr dlg;
@@ -12849,7 +12993,9 @@ static Boolean ResolveFeatureOverlapAction (Pointer data)
   WatchCursor();
   Update();
   r.trim_type = vnp1->choice;
+  r.trim_constraint = DialogToPointer (dlg->trim_constraint);
   r.intersect_type = vnp2->choice;
+  r.intersect_constraint = DialogToPointer (dlg->intersect_constraint);
   r.lip = OpenLog ("Trimmed Features");
 
   sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
@@ -12858,6 +13004,9 @@ static Boolean ResolveFeatureOverlapAction (Pointer data)
   CloseLog (r.lip);
   FreeLog (r.lip);
 
+  r.trim_constraint = ConstraintChoiceSetFree (r.trim_constraint);
+  r.intersect_constraint = ConstraintChoiceSetFree (r.intersect_constraint);
+
   DeleteMarkedObjects (dlg->input_entityID, 0, NULL);
   ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
@@ -12901,12 +13050,16 @@ extern void ResolveFeatureOverlaps (IteM i)
   h = HiddenGroup (w, -1, 0, NULL);
   SetGroupSpacing (h, 10, 10);
 
-  g = HiddenGroup (h, 2, 0, NULL);
+  g = HiddenGroup (h, 3, 0, NULL);
   StaticPrompt (g, "Trim features of type", 0, popupMenuHeight, programFont, 'c');
-  dlg->trim_type = FeatureSelectionDialogEx (g, FALSE, sep, SetResolveFeatureOverlapsFormAccept, dlg);
+  dlg->trim_type = FeatureSelectionDialogEx (g, FALSE, sep, ChangeTrimFeatureType, dlg);
+  dlg->trim_constraint = ComplexConstraintDialog (g, NULL, NULL);
+  ChangeComplexConstraintFieldType (dlg->trim_constraint, FieldType_feature_field, NULL, Feature_type_any);
 
   StaticPrompt (g, "Where they overlap features of type", 0, popupMenuHeight, programFont, 'c');
-  dlg->intersect_type = FeatureSelectionDialogEx (g, FALSE, sep, SetResolveFeatureOverlapsFormAccept, dlg);
+  dlg->intersect_type = FeatureSelectionDialogEx (g, FALSE, sep, ChangeIntersectFeatureType, dlg);
+  dlg->intersect_constraint = ComplexConstraintDialog (g, NULL, NULL);
+  ChangeComplexConstraintFieldType (dlg->intersect_constraint, FieldType_feature_field, NULL, Feature_type_any);
 
   /* Accept and Cancel buttons */
 
@@ -13054,52 +13207,9 @@ extern void ConvertGeneralIdToLocalID (IteM i)
 }
 
 
-static Boolean IsUSA (CharPtr country)
-{
-  if (StringICmp (country, "USA") == 0
-      || StringICmp (country, "United States of America") == 0
-      || StringICmp (country, "U.S.A.") == 0
-      || StringICmp (country, "U S A") == 0) {
-    return TRUE;
-  } else {
-    return FALSE;
-  }
-}
-
-
-static void AbbreviateCitSubAffilStatesCallback (PubdescPtr pdp, Pointer data)
-{
-  ValNodePtr vnp;
-  CitSubPtr  csp;
-  CharPtr    abbrev;
-
-  if (pdp == NULL) return;
-  for (vnp = pdp->pub; vnp != NULL; vnp = vnp->next) {
-    if (vnp->choice == PUB_Sub) {
-      csp = (CitSubPtr) vnp->data.ptrvalue;     
-      if (csp != NULL && csp->authors != NULL 
-          && csp->authors->affil != NULL
-          && IsUSA(csp->authors->affil->country)) {
-        if (StringCmp (csp->authors->affil->country, "USA") != 0) {
-          csp->authors->affil->country = MemFree (csp->authors->affil->country);
-          csp->authors->affil->country = StringSave ("USA");
-        }
-        abbrev = GetStateAbbreviation (csp->authors->affil->sub);
-        if (abbrev != NULL) {
-          csp->authors->affil->sub = MemFree (csp->authors->affil->sub);
-          csp->authors->affil->sub = StringSave (abbrev);
-        }
-      }
-    }
-  }
-  
-}
-
-
 extern void AbbreviateCitSubAffilStates (IteM i)
 {
   BaseFormPtr        bfp;
-  SeqEntryPtr        sep;
 
 #ifdef WIN_MAC
   bfp = currentFormDataPtr;
@@ -13109,12 +13219,7 @@ extern void AbbreviateCitSubAffilStates (IteM i)
   if (bfp == NULL)
     return;
 
-  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
-  if (sep == NULL)
-    return;
-
-  VisitPubdescsInSep (sep, NULL, AbbreviateCitSubAffilStatesCallback);
-
+  FixUsaAndStateAbbreviations(bfp->input_entityID, NULL);
   ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
 }
@@ -13391,3 +13496,323 @@ NLM_EXTERN void AddFluComments (IteM i)
 }
 
 
+static CharPtr RNA_words[] = {
+  "ITS1",
+  "ITS2",
+  "5.8S",
+  "16S",
+  "18S",
+  "28S"
+};
+
+static const k_num_RNA_words = sizeof (RNA_words) / sizeof (CharPtr);
+
+
+static ValNodePtr RNAWordsFromString (CharPtr str, TextFsaPtr tags)
+{
+  Int4        state;
+  Char        ch;
+  CharPtr     ptr;
+  ValNodePtr  matches;
+  CharPtr     last_hit = NULL, last_pos = NULL;
+  Int4        match_len;
+  ValNodePtr  tokens = NULL;
+
+  if (StringHasNoText (str) || tags == NULL) {
+    return NULL;
+  }
+
+  state = 0;
+  ptr = str;
+  ch = *ptr;
+  while (ch != '\0') {
+    matches = NULL;
+    state = TextFsaNext (tags, state, ch, &matches);
+    if (matches != NULL && (isspace (*(ptr + 1)) || ispunct (*(ptr + 1)) || *(ptr + 1) == 0) && (match_len = StringLen (matches->data.ptrvalue)) > 0
+        && (ptr - match_len + 1 == str || isspace (*(ptr - match_len)) || ispunct (*(ptr - match_len)))) {
+      ValNodeAddPointer (&tokens, 0, ptr - match_len + 1);
+      last_pos = ptr;
+      last_hit = (CharPtr) matches->data.ptrvalue;
+    }
+    ptr++;
+    ch = *ptr;
+  }
+  return tokens;
+}
+
+
+static void ExpandFeatureForIntervals (SeqFeatPtr sfp)
+{
+  SeqLocPtr   slp, slp_next, orig;
+  SeqFeatPtr  sfp_new;
+  Boolean     part5, part3;
+
+  orig = sfp->location;
+  sfp->location = orig->data.ptrvalue;
+  orig->data.ptrvalue = NULL;
+  orig = SeqLocFree (orig);
+  slp = sfp->location->next;
+  sfp->location->next = NULL;
+  sfp->partial = CheckSeqLocForPartial (sfp->location, &part5, &part3);
+  while (slp != NULL) {
+    sfp_new = SeqFeatCopy (sfp);
+    sfp_new->next = sfp->next;
+    sfp->next = sfp_new;
+    sfp_new->location = SeqLocFree (sfp_new->location);
+    slp_next = slp->next;
+    slp->next = NULL;
+    sfp_new->location = slp;
+    sfp_new->partial = CheckSeqLocForPartial (sfp_new->location, &part5, &part3);
+    slp = slp_next;
+    sfp = sfp_new;
+  }
+} 
+    
+
+/* TODO - for each string, remove trailing delimiters and spaces, replace abbreviations */
+
+static void FixExplodedRNAProduct (CharPtr PNTR pProduct)
+{
+  CharPtr cp;
+  Int4    len, i;
+  Char    repl_buf[200];
+  CharPtr repl_fmt = "%s ribosomal RNA";
+
+  if (pProduct == NULL || *pProduct == NULL) {
+    return;
+  }
+
+  FindReplaceString (pProduct, " and ", "", FALSE, FALSE);
+
+  len = StringLen (*pProduct);
+  cp = *pProduct + len - 1;
+
+  while (ispunct (*cp) || isspace (*cp)) {
+    *cp = 0;
+    cp--;
+  }
+   
+  if (StringStr (*pProduct, " ribosomal RNA") != NULL) {
+    return;
+  }
+  for (i = 2; i < k_num_RNA_words; i++) {
+    sprintf (repl_buf, repl_fmt, RNA_words[i]);
+    FindReplaceString (pProduct, RNA_words[i], repl_buf, FALSE, TRUE);
+  }
+}
+
+
+static void ExplodeRNACallback (SeqFeatPtr sfp, Pointer data)
+{
+  TextFsaPtr  tags;
+  Int4        num_interval = 0, len;
+  SeqLocPtr   tmp;
+  ValNodePtr  tokens = NULL, vnp;
+  RnaRefPtr   rrp, rrp_new;
+  RNAGenPtr   rgp, rgp_new;
+  SeqFeatPtr  sfp_new;
+  CharPtr     new_product;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_RNA || (tags = (TextFsaPtr) data) == NULL
+      || sfp->location == NULL
+      || (sfp->location->choice != SEQLOC_MIX && sfp->location->choice != SEQLOC_PACKED_INT)) {
+    return;
+  }
+
+  for (tmp = sfp->location->data.ptrvalue; tmp != NULL; tmp = tmp->next) {
+    num_interval++;
+  }
+
+  if (!StringHasNoText (sfp->comment)
+      && (tokens = RNAWordsFromString (sfp->comment, tags)) != NULL
+      && (num_interval == ValNodeLen (tokens))) {
+    ExpandFeatureForIntervals (sfp);
+    for (vnp = tokens->next, sfp_new = sfp->next; vnp != NULL && sfp_new != NULL; vnp = vnp->next, sfp_new = sfp_new->next) {
+      sfp_new->comment = MemFree (sfp_new->comment);
+      sfp_new->comment = StringSave (vnp->data.ptrvalue);
+      if (vnp->next != NULL) {
+        len = (CharPtr) vnp->next->data.ptrvalue - (CharPtr)vnp->data.ptrvalue;
+        sfp_new->comment[len] = 0;
+      }
+      FixExplodedRNAProduct(&(sfp_new->comment));
+    }
+    /* now truncate original */
+    *((CharPtr) tokens->next->data.ptrvalue) = 0;
+    FixExplodedRNAProduct(&(sfp->comment));
+    tokens = ValNodeFree (tokens);
+  } else if ((rrp = (RnaRefPtr) sfp->data.value.ptrvalue) != NULL) {
+    if (rrp->ext.choice == 1) {
+      tokens = RNAWordsFromString (rrp->ext.value.ptrvalue, tags);
+      if (num_interval == ValNodeLen (tokens)) {
+        ExpandFeatureForIntervals (sfp);
+        for (vnp = tokens->next, sfp_new = sfp->next; vnp != NULL && sfp_new != NULL; vnp = vnp->next, sfp_new = sfp_new->next) {
+          rrp_new = sfp_new->data.value.ptrvalue;
+          rrp_new->ext.value.ptrvalue = MemFree (rrp_new->ext.value.ptrvalue);
+          new_product = StringSave (vnp->data.ptrvalue);
+          if (vnp->next != NULL) {
+            len = (CharPtr) vnp->next->data.ptrvalue - (CharPtr)vnp->data.ptrvalue;
+            new_product[len] = 0;
+          }
+          FixExplodedRNAProduct (&new_product);
+          rrp_new->ext.value.ptrvalue = new_product;
+        }  
+        *((CharPtr) tokens->next->data.ptrvalue) = 0;
+        new_product = rrp->ext.value.ptrvalue;
+        FixExplodedRNAProduct (&new_product);
+        rrp->ext.value.ptrvalue = new_product;
+      }
+      tokens = ValNodeFree (tokens);
+    } else if (rrp->ext.choice == 3 && (rgp = (RNAGenPtr) rrp->ext.value.ptrvalue) != NULL) {
+      tokens = RNAWordsFromString (rgp->product, tags);
+      if (num_interval == ValNodeLen (tokens)) {
+        ExpandFeatureForIntervals (sfp);
+        for (vnp = tokens->next, sfp_new = sfp->next; vnp != NULL && sfp_new != NULL; vnp = vnp->next, sfp_new = sfp_new->next) {
+          rrp_new = sfp_new->data.value.ptrvalue;
+          rgp_new = rrp_new->ext.value.ptrvalue;
+          rgp_new->product = MemFree (rgp_new->product);
+          rgp_new->product = StringSave (vnp->data.ptrvalue);
+          if (vnp->next != NULL) {
+            len = (CharPtr) vnp->next->data.ptrvalue - (CharPtr)vnp->data.ptrvalue;
+            rgp_new->product[len] = 0;
+          }
+          FixExplodedRNAProduct(&(rgp_new->product));
+        }      
+        *((CharPtr) tokens->next->data.ptrvalue) = 0;
+        FixExplodedRNAProduct (&(rgp->product));
+      }
+      tokens = ValNodeFree (tokens);
+    }
+  }
+}
+
+
+NLM_EXTERN void ExplodeRNA (IteM i)
+{
+  BaseFormPtr        bfp;
+  SeqEntryPtr        sep;
+  TextFsaPtr         tags;
+  Int4               j;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL)
+    return;
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  if (sep == NULL)
+    return;
+
+  
+  tags = TextFsaNew();
+
+  for (j = 0; j < k_num_RNA_words; j++) {
+    TextFsaAdd (tags, RNA_words[j]);
+  }
+
+  VisitFeaturesInSep (sep, tags, ExplodeRNACallback);
+
+  tags = TextFsaFree (tags);
+
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);  
+}
+
+
+static void RemoveFeaturesLikeGapsCallback (BioseqPtr bsp, Pointer userdata)
+{
+  SeqFeatPtr           sfp, gap_feat;
+  SeqMgrFeatContext    context;
+  DeltaSeqPtr          dsp;
+  SeqLocPtr            slp;
+  Int4                 pos = 0, len;
+  CharPtr              new_note;
+  ImpFeatPtr           imp;
+
+  if (bsp == NULL || bsp->repr != Seq_repr_delta) {
+    return;
+  }
+
+  dsp = (DeltaSeqPtr)(bsp->seq_ext);
+  sfp = SeqMgrGetNextFeature(bsp, NULL, 0, 0, &context);
+  while (dsp != NULL && sfp != NULL) {
+    while (dsp != NULL && !IsDeltaSeqGap(dsp)) {
+      if (dsp->choice == 1) {
+        pos += SeqLocLen (dsp->data.ptrvalue);
+      } else if (dsp->choice == 2) {
+        pos += ((SeqLitPtr)dsp->data.ptrvalue)->length;
+      }
+      dsp = dsp->next;
+    }
+    if (dsp != NULL) {
+      len = ((SeqLitPtr)dsp->data.ptrvalue)->length;
+      while (context.left < pos && sfp != NULL) {
+        sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
+      }
+      if (sfp != NULL) {
+        gap_feat = NULL;
+        new_note = NULL;
+        while (context.left == pos && sfp != NULL) {
+          if (context.right == pos + len - 1) {
+            if (sfp->idx.subtype == FEATDEF_gap) {
+              gap_feat = sfp;
+            } else {
+              if (sfp->comment != NULL) {
+                SetStringValue(&new_note, sfp->comment, ExistingTextOption_append_semi);
+              }
+              sfp->idx.deleteme = TRUE;
+            }
+          }
+          sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
+        }
+        /* only need to instantiate gap if there is a note to add */
+        if (new_note != NULL) {
+          if (gap_feat == NULL) {
+            slp = SeqLocIntNew (pos, pos + len - 1, Seq_strand_plus, SeqIdFindWorst (bsp->id));
+            gap_feat = CreateNewFeatureOnBioseq (bsp, SEQFEAT_IMP, slp);
+            imp = ImpFeatNew ();
+            imp->key = StringSave ("gap");
+            gap_feat->data.value.ptrvalue = imp;
+          }
+          if (gap_feat->comment == NULL) {
+            gap_feat->comment = new_note;
+          } else {
+            SetStringValue (&(gap_feat->comment), new_note, ExistingTextOption_append_semi);
+            new_note = MemFree (new_note);
+          }
+        }
+      }
+      pos += len;
+      dsp = dsp->next;
+    }
+  }
+}
+
+
+NLM_EXTERN void RemoveFeaturesLikeGaps (IteM i)
+{
+  BaseFormPtr          bfp;
+  SeqEntryPtr          sep;
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL) {
+    return;
+  }
+
+  sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
+  VisitBioseqsInSep (sep, NULL, RemoveFeaturesLikeGapsCallback);
+
+  DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
+  ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);  
+}
+
+
+
+
diff --git a/sequin/sequin7.c b/sequin/sequin7.c
index b3fe188..6a3e7c5 100644
--- a/sequin/sequin7.c
+++ b/sequin/sequin7.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/3/98
 *
-* $Revision: 6.360 $
+* $Revision: 6.388 $
 *
 * File Description: 
 *
@@ -79,6 +79,10 @@ static char *time_of_compilation = "now";
 #include <algo/blast/api/blast_api.h>
 #include <salstruc.h>
 #include <valid.h> /* added for latloncountry conflict checking */
+#define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
+#include <macrodlg.h>
+#include <macroapi.h>
 
 #define CONVERT_TO_JOIN  1
 #define CONVERT_TO_ORDER 2
@@ -508,6 +512,7 @@ extern ForM CreateStartupForm (Int2 left, Int2 top, CharPtr title,
   return (ForM) w;
 }
 
+
 typedef struct formatform {
   FORM_MESSAGE_BLOCK
 
@@ -835,7 +840,6 @@ extern ForM CreateFormatForm (Int2 left, Int2 top, CharPtr title,
     ffp->package = HiddenGroup (g1, 2, 0, EnableOrDisableFormats);
     SetObjectExtra (ffp->package, ffp, NULL);
     RadioButton (ffp->package, "Single Sequence");
-    RadioButton (ffp->package, "Segmented Sequence");
     RadioButton (ffp->package, "Gapped Sequence");
     if (allowGenomicPlusCDNA) {
       RadioButton (ffp->package, "Genomic + Transcripts");
@@ -3599,57 +3603,6 @@ typedef struct findform {
   Int4            last_paragraph_found;
 } FindForm, PNTR FindFormPtr;
 
-extern CharPtr CompressSpaces (CharPtr str)
-
-{
-  Char     ch;
-  CharPtr  dst;
-  Char     last;
-  CharPtr  ptr;
-
-  if (str != NULL && str [0] != '\0') {
-    dst = str;
-    ptr = str;
-    ch = *ptr;
-    while (ch != '\0' && ch <= ' ') {
-      ptr++;
-      ch = *ptr;
-    }
-    while (ch != '\0') {
-      *dst = ch;
-      dst++;
-      ptr++;
-      last = ch;
-      ch = *ptr;
-      if (ch != '\0' && ch < ' ') {
-        *ptr = ' ';
-        ch = *ptr;
-      }
-      while (ch != '\0' && last <= ' ' && ch <= ' ') {
-        ptr++;
-        ch = *ptr;
-      }
-    }
-    *dst = '\0';
-    dst = NULL;
-    ptr = str;
-    ch = *ptr;
-    while (ch != '\0') {
-      if (ch != ' ') {
-        dst = NULL;
-      } else if (dst == NULL) {
-        dst = ptr;
-      }
-      ptr++;
-      ch = *ptr;
-    }
-    if (dst != NULL) {
-      *dst = '\0';
-    }
-  }
-  return str;
-}
-
 extern CharPtr SearchForString (CharPtr str, CharPtr sub, Boolean case_counts, Boolean whole_word)
 
 {
@@ -3736,8 +3689,8 @@ FindInFlatFile
  Int4 start_index)
 
 {
-  Asn2gbJobPtr     ajp;
-  BioseqPtr        bsp;
+  Asn2gbJobPtr     ajp = NULL;
+  BioseqPtr        bsp = NULL;
   BioseqSetPtr     bssp;
   ErrSev           level;
   SeqEntryPtr      oldsep;
@@ -3773,7 +3726,7 @@ FindInFlatFile
   if (usethetop != NULL && IS_Bioseq_set (usethetop)) {
     bssp = (BioseqSetPtr) usethetop->data.ptrvalue;
     ajp = asn2gnbk_setup (NULL, bssp, NULL, (FmtType) format, (ModType) mode, NORMAL_STYLE, flags, (LckType) 0, (CstType) 0, NULL);
-  } else {
+  } else if (bsp != NULL) {
     ajp = asn2gnbk_setup (bsp, NULL, NULL, (FmtType) format, (ModType) mode, NORMAL_STYLE, flags, (LckType) 0, (CstType) 0, NULL);
   }
   if (ajp != NULL) {
@@ -4113,7 +4066,7 @@ static void FindByLabelOrPosProc (ButtoN b)
 
 {
   Boolean            already;
-  BioseqPtr          bsp;
+  BioseqPtr          bsp = NULL;
   SeqMgrFeatContext  context;
   FindFormPtr        ffp;
   CharPtr            findme;
@@ -4993,7 +4946,7 @@ static void ConvertAccInDefToLocalIdProc (SeqEntryPtr sep)
 static Int2  taxonCount;
 
 static Int4 DoSeqEntryToAsn3 (SeqEntryPtr sep, Boolean strip, Boolean correct,
-                              Boolean force, Boolean dotaxon, MonitorPtr mon)
+                              Boolean force, Boolean dotaxon, MonitorPtr mon, Boolean isEmblOrDdbj)
 
 {
   BioseqSetPtr  bssp;
@@ -5007,7 +4960,7 @@ static Int4 DoSeqEntryToAsn3 (SeqEntryPtr sep, Boolean strip, Boolean correct,
     if (bssp != NULL && (bssp->_class == 7 ||
                          (IsPopPhyEtcSet (bssp->_class)))) {
       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
-        rsult += DoSeqEntryToAsn3 (sep, strip, correct, force, dotaxon, mon);
+        rsult += DoSeqEntryToAsn3 (sep, strip, correct, force, dotaxon, mon, isEmblOrDdbj);
       }
       return rsult;
     }
@@ -5029,10 +4982,10 @@ static Int4 DoSeqEntryToAsn3 (SeqEntryPtr sep, Boolean strip, Boolean correct,
 /*#endif*/
   oldscope = SeqEntrySetScope (sep);
   if (dotaxon) {
-    rsult = SeqEntryToAsn3Ex (sep, strip, correct, TRUE, NULL, Tax3MergeSourceDescr, FALSE);
+    rsult = SeqEntryToAsn3Ex (sep, strip, correct, TRUE, NULL, Tax3MergeSourceDescr, FALSE, isEmblOrDdbj);
     DeleteMarkedObjects (0, OBJ_SEQENTRY, sep);
   } else {
-    rsult = SeqEntryToAsn3Ex (sep, strip, correct, FALSE, NULL, NULL, FALSE);
+    rsult = SeqEntryToAsn3Ex (sep, strip, correct, FALSE, NULL, NULL, FALSE, isEmblOrDdbj);
   }
   SeqEntrySetScope (oldscope);
   return rsult;
@@ -5179,11 +5132,39 @@ static void MakeSequinCleanupObject (SeqEntryPtr sep)
   sdp->data.ptrvalue = uop;
 }
 
+static void SqnCheckForEmblDdbjID (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
+
+{
+  BioseqPtr  bsp;
+  BoolPtr    isEmblOrDdbj;
+  SeqIdPtr   sip;
+
+  if (sep == NULL) return;
+  if (IS_Bioseq (sep)) {
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    if (bsp == NULL) return;
+    isEmblOrDdbj = (BoolPtr) mydata;
+    if (isEmblOrDdbj == NULL) return;
+    for (sip = bsp->id; sip != NULL; sip = sip->next) {
+      switch (sip->choice) {
+        case SEQID_EMBL :
+        case SEQID_DDBJ :
+          *isEmblOrDdbj = TRUE;
+          break;
+          break;
+        default :
+          break;
+      }
+    }
+  }
+}
+
 extern Int4 MySeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip, Boolean correct, Boolean force, Boolean dotaxon);
 extern Int4 MySeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip, Boolean correct, Boolean force, Boolean dotaxon)
 
 {
   Uint2       entityID;
+  Boolean     isEmblOrDdbj = FALSE;
   MonitorPtr  mon;
   Boolean     needstaxfix;
   Int4        rsult;
@@ -5214,6 +5195,8 @@ extern Int4 MySeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip, Boolean correct,
   VisitBioseqsInSep (sep, NULL, ExtendSingleGeneOnMRNA);
   RemoveBioSourceOnPopSet (sep, NULL);
   /* SeqEntryExplore (sep, NULL, CleanupEmptyFeatCallback); */
+  /* before deleting titles, promote common set titles up */
+  PromoteCommonTitlesToSet (sep);
   SeqEntryExplore (sep, NULL, DeleteMultipleTitles); /* do it old way in Sequin */
   /*
   SeqEntryExplore (sep, NULL, RemoveMultipleTitles);
@@ -5227,6 +5210,7 @@ extern Int4 MySeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip, Boolean correct,
     ValidateSeqAlignandACCInSeqEntry (sep, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE); /* remove components with seqID accXNNNNN */
   }
   SeqEntryExplore (sep, NULL, CheckSeqAlignCallback); /* remove alignments with single dimension */
+  SeqEntryExplore (sep, (Pointer) &isEmblOrDdbj, SqnCheckForEmblDdbjID);
   needstaxfix = FALSE;
   if (! force) {
     needstaxfix = NoBiosourceOrTaxonId (sep);
@@ -5276,7 +5260,7 @@ extern Int4 MySeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip, Boolean correct,
   if (dotaxon) {
     Taxon3ReplaceOrgInSeqEntry (sep, FALSE);
   }
-  rsult = DoSeqEntryToAsn3 (sep, strip, correct, force, FALSE, mon);
+  rsult = DoSeqEntryToAsn3 (sep, strip, correct, force, FALSE, mon, isEmblOrDdbj);
 /*#ifdef USE_TAXON*/
   if (dotaxon) {
     MonitorStrValue (mon, "Closing Taxon");
@@ -7272,13 +7256,13 @@ extern Boolean DoBioseqFeaturesMatchSequenceConstraintX (BioseqPtr bsp, ValNodeP
 typedef struct keywordform 
 {
   FORM_MESSAGE_BLOCK
-  DialoG string_src_dlg;
-  DialoG string_constraint_dlg;
+  DialoG constraint_dlg;
   TexT   keyword_txt;
   
   ParseFieldPtr pfp;
   FilterSetPtr  fsp;
   CharPtr       keyword;
+  ValNodePtr    constraint;
 } KeywordFormData, PNTR KeywordFormPtr;
 
 
@@ -7288,8 +7272,6 @@ static void ApplyKeywordCallback (BioseqPtr bsp, Pointer userdata)
   ValNodePtr              vnp;
   KeywordFormPtr scfp;
   GBBlockPtr              gbp;
-  GetSamplePtr            gsp;
-  Boolean                 ok_to_add = TRUE;
   
   sep = SeqMgrGetSeqEntryForData (bsp);
   if (sep == NULL)
@@ -7299,18 +7281,7 @@ static void ApplyKeywordCallback (BioseqPtr bsp, Pointer userdata)
   
   scfp = (KeywordFormPtr) userdata;
   
-  if (scfp->pfp != NULL && scfp->fsp != NULL)
-  {
-    gsp = GetSampleForSeqEntry (sep, bsp->idx.entityID, scfp->pfp, scfp->fsp);
-    if (gsp == NULL || gsp->num_found == 0)
-    {
-      ok_to_add = FALSE;
-    }
-    gsp = GetSampleFree (gsp);
-  }
-  
-  if (!ok_to_add)
-  {
+  if (!DoesObjectMatchConstraintChoiceSet (OBJ_BIOSEQ, bsp, scfp->constraint)) {
     return;
   }
       
@@ -7344,8 +7315,8 @@ static void RemoveKeywordCallback (BioseqPtr bsp, Pointer userdata)
   ValNodePtr              vnp, prev_keyword, next_keyword;
   KeywordFormPtr scfp;
   GBBlockPtr              gbp;
-  GetSamplePtr            gsp;
-  Boolean                 ok_to_remove = TRUE;
+  SeqDescPtr              sdp;
+  SeqMgrDescContext       context;
   
   sep = SeqMgrGetSeqEntryForData (bsp);
   if (sep == NULL)
@@ -7355,29 +7326,15 @@ static void RemoveKeywordCallback (BioseqPtr bsp, Pointer userdata)
   
   scfp = (KeywordFormPtr) userdata;
   
-  if (scfp->pfp != NULL && scfp->fsp != NULL)
-  {
-    gsp = GetSampleForSeqEntry (sep, bsp->idx.entityID, scfp->pfp, scfp->fsp);
-    if (gsp == NULL || gsp->num_found == 0)
-    {
-      ok_to_remove = FALSE;
-    }
-    gsp = GetSampleFree (gsp);
-  }
-  
-  if (!ok_to_remove)
-  {
+  if (!DoesObjectMatchConstraintChoiceSet (OBJ_BIOSEQ, bsp, scfp->constraint)) {
     return;
   }
       
-	vnp = GetDescrOnSeqEntry (sep, Seq_descr_genbank);
-  /* no GenBank descriptor, no keywords to remove */
-	if (vnp == NULL) return;
-	
-	gbp = (GBBlockPtr) vnp->data.ptrvalue;
+  sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_genbank, &context);
+  while (sdp != NULL) {	
+	gbp = (GBBlockPtr) sdp->data.ptrvalue;
 	/* No GBBlock, no keywords to remove */
-	if (gbp == NULL) return;
-  	
+    if (gbp != NULL) {  	
   prev_keyword = NULL;
 	for (vnp = gbp->keywords; vnp; vnp = next_keyword) {
 	  next_keyword = vnp->next;
@@ -7398,6 +7355,9 @@ static void RemoveKeywordCallback (BioseqPtr bsp, Pointer userdata)
 		  prev_keyword = vnp;
 		}
 	}
+    }
+    sdp = SeqMgrGetNextDescriptor (bsp, sdp, Seq_descr_genbank, &context);
+  }
 }
 
 static void ApplyKeyword (IteM i, CharPtr keyword)
@@ -7418,6 +7378,7 @@ static void ApplyKeyword (IteM i, CharPtr keyword)
   kfd.pfp = NULL;
   kfd.fsp = NULL;
   kfd.keyword = keyword;
+  kfd.constraint = NULL;
   
   VisitBioseqsInSep (sep, &kfd, ApplyKeywordCallback);
 
@@ -7458,9 +7419,8 @@ static void DoRemoveKeywords (ButtoN b)
     return;
   }
   
-  scfp->pfp = (ParseFieldPtr) DialogToPointer (scfp->string_src_dlg);
-  scfp->fsp = FilterSetNew ();
-  scfp->fsp->scp = (StringConstraintXPtr) DialogToPointer (scfp->string_constraint_dlg);
+  scfp->constraint = DialogToPointer (scfp->constraint_dlg);
+  
   scfp->keyword = SaveStringFromText (scfp->keyword_txt);
   
   sep = GetTopSeqEntryForEntityID (scfp->input_entityID);
@@ -7468,8 +7428,8 @@ static void DoRemoveKeywords (ButtoN b)
   
   VisitBioseqsInSep (sep, scfp, RemoveKeywordCallback);
 
-  scfp->fsp = FilterSetFree (scfp->fsp);
-  scfp->pfp = ParseFieldFree (scfp->pfp);
+  scfp->keyword = MemFree (scfp->keyword);
+  scfp->constraint = ConstraintChoiceSetFree (scfp->constraint);
 
   ObjMgrSetDirtyFlag (scfp->input_entityID, TRUE);
   ObjMgrSendMsg (OM_MSG_UPDATE, scfp->input_entityID, 0, 0);
@@ -7483,7 +7443,6 @@ extern void RemoveKeywordWithStringConstraint (IteM i)
   BaseFormPtr    bfp;
   KeywordFormPtr scfp;
   WindoW         w;
-  PrompT         ppt;
   GrouP          h, g, c;
   ButtoN         b;
 
@@ -7510,10 +7469,8 @@ extern void RemoveKeywordWithStringConstraint (IteM i)
   StaticPrompt (g, "Remove Keyword", 0, 0, programFont, 'l');
   scfp->keyword_txt = DialogText (g, "", 30, NULL);
   
-  ppt = StaticPrompt (h, "Where", 0, 0, programFont, 'l');
-  scfp->string_src_dlg = ParseFieldDestDialogEx (h, NULL, NULL, FALSE, TRUE);
-
-  scfp->string_constraint_dlg = StringConstraintDialogX (h, NULL, FALSE);
+  scfp->constraint_dlg = ComplexConstraintDialog (h, NULL, NULL);
+  ChangeComplexConstraintFieldType (scfp->constraint_dlg, FieldType_molinfo_field, NULL, 0);
   
   c = HiddenGroup (h, 2, 0, NULL);
   b = PushButton (c, "Accept", DoRemoveKeywords);
@@ -7521,9 +7478,7 @@ extern void RemoveKeywordWithStringConstraint (IteM i)
   b = PushButton (c, "Cancel", StdCancelButtonProc);
   
   AlignObjects (ALIGN_CENTER, (HANDLE) g,
-                              (HANDLE) ppt,
-                              (HANDLE) scfp->string_src_dlg,
-                              (HANDLE) scfp->string_constraint_dlg,
+                              (HANDLE) scfp->constraint_dlg,
                               (HANDLE) c,
                               NULL);
   RealizeWindow (w);
@@ -8271,7 +8226,7 @@ static void CleanupRNAStrandFormProc (GraphiC g, Pointer data)
 
 static Int4 GetSeqNumFromListPos (Int4 list_pos, ValNodePtr sequence_list)
 {
-  Int4       seq_num, list_offset;
+  Int4       seq_num = 0, list_offset;
   ValNodePtr vnp;
   ERNAstrand_group_num group;
   
@@ -10179,12 +10134,16 @@ static void RefreshClickableList (ButtoN b)
 
   drfp = (ClickableItemListWindowPtr) GetObjectExtra (b);
   if (drfp == NULL || drfp->refresh_func == NULL) return;
+  WatchCursor();
+  Update();
   
   PointerToDialog (drfp->clickable_list, NULL);
   drfp->item_list = FreeClickableList (drfp->item_list);
 
   drfp->item_list = (drfp->refresh_func)(drfp->input_entityID);
   PointerToDialog (drfp->clickable_list, drfp->item_list);  
+  ArrowCursor();
+  Update();
 }
 
 
@@ -10479,6 +10438,7 @@ typedef struct vecscreentool {
   ValNodePtr      item_list;
   DialoG          clickable_list;
   BaseFormPtr     bfp;
+  GrouP           sort_grp;
   GrouP           trim_options_grp;
   ButtoN          add_citsub_btn;  
 
@@ -10607,7 +10567,7 @@ static CharPtr GetMatchType (SeqFeatPtr sfp)
 static SeqLocPtr GetFeatureListLoc (ValNodePtr feat_list, VecScreenToolPtr vstp)
 {
   ValNodePtr vnp;
-  BioseqPtr  bsp;
+  BioseqPtr  bsp = NULL;
   SeqFeatPtr sfp;
   Int4       loc_left = -1, loc_right = -1, tmp, start, stop;
     
@@ -10888,6 +10848,41 @@ static void VecScreenToolUnselectInternalBtn (ButtoN b)
 }
 
 
+static void VecScreenToolSelectStrongAndModerate (ValNodePtr vnp)
+{
+  ClickableItemPtr cip;
+  
+  while (vnp != NULL)
+  {
+    cip = (ClickableItemPtr) vnp->data.ptrvalue;
+    if (cip != NULL)
+    {
+      if (StringISearch (cip->description, "strong") != NULL 
+          || StringISearch (cip->description, "moderate") != NULL) {
+        cip->chosen = TRUE;
+      } 
+      else 
+      {
+        cip->chosen = FALSE;
+      }
+      VecScreenToolSelectStrongAndModerate (cip->subcategories);
+    }
+    vnp = vnp->next;
+  }  
+}
+
+
+static void VecScreenToolSelectStrongAndModerateBtn (ButtoN b)
+{
+  VecScreenToolPtr vstp;
+
+  vstp = (VecScreenToolPtr) GetObjectExtra (b);
+  if (vstp == NULL) return;
+  VecScreenToolSelectStrongAndModerate (vstp->item_list);
+  RedrawVecScreenTool (vstp);  
+}
+
+
 static void TrimFeatureList (ValNodePtr feat_list, VecScreenToolPtr vstp)
 {
   BioseqPtr  bsp = NULL;
@@ -10900,6 +10895,9 @@ static void TrimFeatureList (ValNodePtr feat_list, VecScreenToolPtr vstp)
   bsp = BioseqFindFromSeqLoc (delete_loc);
   loc_left = SeqLocStart (delete_loc);
   loc_right = SeqLocStop (delete_loc);
+  if (loc_left == 0 && loc_right >= bsp->length - 1) {
+    bsp->idx.deleteme = TRUE;
+  } else {
   len = SeqLocLen (delete_loc);
       
   if (loc_left == 0) {
@@ -10911,7 +10909,8 @@ static void TrimFeatureList (ValNodePtr feat_list, VecScreenToolPtr vstp)
   if (vstp->top_sep != NULL) {
     SeqEntryExplore (vstp->top_sep, (Pointer) delete_loc, SeqAlignDeleteByLocCallback);
   }
-  SeqDeleteByLoc (delete_loc, TRUE, FALSE);  
+    SeqDeleteByLocEx (delete_loc, TRUE, FALSE, TRUE);  
+  }
   delete_loc = SeqLocFree (delete_loc);  
   ValNodeAddPointer (&(vstp->trimmed_bsps), OBJ_BIOSEQ, bsp);
 }
@@ -11155,6 +11154,127 @@ static ValNodePtr SortVecScreenList (ValNodePtr item_list)
 }
 
 
+static ValNodePtr SortVecScreenListByStrength (ValNodePtr item_list)
+{
+  ClickableItemPtr cip;
+  ValNodePtr list_strong = NULL, list_moderate = NULL, list_weak = NULL, list_suspect = NULL, list_other = NULL;
+  ValNodePtr list_strong_last = NULL, list_moderate_last = NULL, list_weak_last = NULL, list_suspect_last = NULL, list_other_last = NULL;
+  ValNodePtr next_item, last_item;
+  
+  while (item_list != NULL) {
+    next_item = item_list->next;
+    item_list->next = NULL;
+    cip = (ClickableItemPtr) item_list->data.ptrvalue;
+    if (StringISearch (cip->description, "strong") != NULL) {
+      if (list_strong_last == NULL) {
+        list_strong = item_list;
+      } else {
+        list_strong_last->next = item_list;
+      }
+      list_strong_last = item_list;
+    } else if (StringISearch (cip->description, "moderate") != NULL) {
+      if (list_moderate_last == NULL) {
+        list_moderate = item_list;
+      } else {
+        list_moderate_last->next = item_list;
+      }
+      list_moderate_last = item_list;
+    } else if (StringISearch (cip->description, "weak") != NULL) {
+      if (list_weak_last == NULL) {
+        list_weak = item_list;
+      } else {
+        list_weak_last->next = item_list;
+      }
+      list_weak_last = item_list;
+    } else if (StringISearch (cip->description, "suspect") != NULL) {
+      if (list_suspect_last == NULL) {
+        list_suspect = item_list;
+      } else {
+        list_suspect_last->next = item_list;
+      }
+      list_suspect_last = item_list;
+    } else {
+      if (list_other_last == NULL) {
+        list_other = item_list;
+      } else {
+        list_other_last->next = item_list;
+      }
+      list_other_last = item_list;
+    }
+    item_list = next_item;
+  }
+  
+  item_list = list_strong;
+  last_item = list_strong_last;
+  
+  if (list_moderate != NULL) {
+    if (item_list == NULL) {
+      item_list = list_moderate;
+    } else {
+      last_item->next = list_moderate;
+    }
+    last_item = list_moderate_last;
+  }
+  
+  if (list_weak != NULL) {
+    if (item_list == NULL) {
+      item_list = list_weak;
+    } else {
+      last_item->next = list_weak;
+    }
+    last_item = list_weak_last;
+  }
+
+  if (list_suspect != NULL) {
+    if (item_list == NULL) {
+      item_list = list_suspect;
+    } else {
+      last_item->next = list_suspect;
+    }
+    last_item = list_suspect_last;
+  }
+
+  if (list_other != NULL) {
+    if (item_list == NULL) {
+      item_list = list_other;
+    } else {
+      last_item->next = list_other;
+    }
+    last_item = list_other_last;
+  }
+
+  return item_list;  
+}
+
+
+static void RearrangeVecScreenList (GrouP g)
+{
+  VecScreenToolPtr vstp;
+  Int2 val;
+
+  vstp = (VecScreenToolPtr) GetObjectExtra (g);
+  if (vstp == NULL) return;
+  
+  val = GetValue (g);
+  switch (val) {
+    case 1:
+      vstp->item_list = SortVecScreenList (vstp->item_list);
+      break;
+    case 2:
+      vstp->item_list = SortVecScreenListByStrength (vstp->item_list);
+      break;
+    case 3:
+      vstp->item_list = ValNodeSort (vstp->item_list, SortVnpByClickableItemChosen);
+      break;
+    case 4:
+    default:
+      vstp->item_list = ValNodeSort (vstp->item_list, SortClickableItemLoc);
+      break;
+  }
+  PointerToDialog (vstp->clickable_list, vstp->item_list);
+}
+
+
 static void RefreshVecScreenList (VecScreenToolPtr vstp)
 {
   if (vstp == NULL) return;
@@ -11163,10 +11283,57 @@ static void RefreshVecScreenList (VecScreenToolPtr vstp)
   vstp->item_list = FreeClickableList (vstp->item_list);
 
   VisitBioseqsInSep (vstp->top_sep, &(vstp->item_list), GetVectorContaminationList);
-  vstp->item_list = SortVecScreenList (vstp->item_list);
   VecScreenToolSelectAll (vstp->item_list);
   VecScreenToolUnselectInternal (vstp->item_list);
-  PointerToDialog (vstp->clickable_list, vstp->item_list);  
+  RearrangeVecScreenList(vstp->sort_grp);
+}
+
+
+static ValNodePtr FindCompleteDeletions (ValNodePtr item_list, Boolean do_all, VecScreenToolPtr vstp)
+{
+  ClickableItemPtr cip;
+  ValNodePtr       list = NULL, vnp;
+  BioseqPtr        bsp = NULL;
+  SeqLocPtr        delete_loc;
+  Int4             len, loc_left = -1, loc_right = -1;
+  
+  vnp = item_list;
+  while (vnp != NULL)
+  {
+    cip = (ClickableItemPtr) vnp->data.ptrvalue;
+    if (cip != NULL)
+    {
+      if (cip->chosen || do_all)
+      {
+        if (cip->expanded)
+        {
+          ValNodeLink (&list, FindCompleteDeletions (cip->subcategories, TRUE, vstp));
+        }
+        else
+        {
+          /* find location to trim */
+          delete_loc = GetFeatureListLoc (cip->item_list, vstp);
+          if (delete_loc != NULL) {
+            bsp = BioseqFindFromSeqLoc (delete_loc);
+            if (bsp != NULL) {
+              loc_left = SeqLocStart (delete_loc);
+              loc_right = SeqLocStop (delete_loc);
+              delete_loc = SeqLocFree (delete_loc); 
+              if (loc_left == 0 && loc_right >= bsp->length - 1) {
+                ValNodeAddPointer (&list, OBJ_BIOSEQ, bsp);
+              }
+            }
+          }
+        }
+      }
+      else if (cip->expanded)
+      {
+        ValNodeLink (&list, FindCompleteDeletions (cip->subcategories, FALSE, vstp));
+      }
+    }
+    vnp = vnp->next;
+  }
+  return list;
 }
 
 
@@ -11174,11 +11341,35 @@ static void TrimSelectedBtn (ButtoN b)
 {
   VecScreenToolPtr vstp;
   ValNodePtr       vnp;
+  ValNodePtr       complete_deletion = NULL;
+  MsgAnswer        ans = ANS_OK;
+  LogInfoPtr       lip;
+  CharPtr          str;
 
   vstp = (VecScreenToolPtr) GetObjectExtra (b);
   if (vstp == NULL) return;
+
+  complete_deletion = FindCompleteDeletions (vstp->item_list, FALSE, vstp);
+  if (complete_deletion != NULL) {
+    lip = OpenLog ("Sequences to be deleted");
+    for (vnp = complete_deletion; vnp != NULL; vnp = vnp->next) {
+      str = GetDiscrepancyItemText (vnp);
+      fprintf (lip->fp, "%s", str);
+      lip->data_in_log = TRUE;
+    }
+    CloseLog (lip);
+    lip = FreeLog (lip);
+    ans = Message (MSG_OKC, "%d sequences will be completely deleted - do you want to continue?",
+                   ValNodeLen (complete_deletion));
+    complete_deletion = ValNodeFree (complete_deletion);
+  }
+  if (ans == ANS_CANCEL) {
+    return;
+  }
+
   WatchCursor();
   Update();
+
   vstp->trimmed_bsps = NULL;
   vstp->trim_option = GetValue (vstp->trim_options_grp);
   vstp->lip = OpenLog ("Trimmed Locations");
@@ -11279,22 +11470,6 @@ static void RemoveSelectedBtn (ButtoN b)
   Update();
 }
 
-static void RearrangeVecScreenList (GrouP g)
-{
-  VecScreenToolPtr vstp;
-
-  vstp = (VecScreenToolPtr) GetObjectExtra (g);
-  if (vstp == NULL) return;
-  
-  if (GetValue (g) == 1) {
-    vstp->item_list = SortVecScreenList (vstp->item_list);
-  } else {
-    vstp->item_list = ValNodeSort (vstp->item_list, SortClickableItemLoc);
-  }
-  PointerToDialog (vstp->clickable_list, vstp->item_list);
-}
-
-
 static void ReportVecScreenDiscrepancies (LogInfoPtr lip, ValNodePtr item_list)
 {
   ClickableItemPtr cip;
@@ -11338,7 +11513,7 @@ extern void VecScreenTool (IteM i)
   VecScreenToolPtr         drfp;
   SeqEntryPtr              sep;
   GrouP                    h, g;
-  GrouP                    c, c2, sort_grp;
+  GrouP                    c, c2;
   ButtoN                   b, b1;
   WindoW                   w;
   OMUserDataPtr            omudp;
@@ -11390,14 +11565,16 @@ extern void VecScreenTool (IteM i)
                                                     ScrollToDiscrepancyItem, EditDiscrepancyItem, bfp,
                                                     GetDiscrepancyItemText);
 
-  RefreshVecScreenList(drfp);
+  drfp->sort_grp = NormalGroup (h, 4, 0, "Order By", programFont, RearrangeVecScreenList);
+  SetObjectExtra (drfp->sort_grp, drfp, NULL);
+  SetGroupSpacing (drfp->sort_grp, 10, 10);
+  RadioButton (drfp->sort_grp, "Internal, 5', 3'");
+  RadioButton (drfp->sort_grp, "Strength");
+  RadioButton (drfp->sort_grp, "Marked");
+  RadioButton (drfp->sort_grp, "Accession");
+  SetValue (drfp->sort_grp, 1);
   
-  sort_grp = NormalGroup (h, 2, 0, "Order By", programFont, RearrangeVecScreenList);
-  SetObjectExtra (sort_grp, drfp, NULL);
-  SetGroupSpacing (sort_grp, 10, 10);
-  RadioButton (sort_grp, "Internal, 5', 3'");
-  RadioButton (sort_grp, "Accession");
-  SetValue (sort_grp, 1);
+  RefreshVecScreenList(drfp);
   
   drfp->trim_options_grp = NormalGroup (h, 3, 0, "Internal Trim Options", programFont, NULL);
   SetGroupSpacing (drfp->trim_options_grp, 10, 10);
@@ -11406,7 +11583,7 @@ extern void VecScreenTool (IteM i)
   RadioButton (drfp->trim_options_grp, "Trim to 3' end");
   SetValue (drfp->trim_options_grp, 1);
   
-  c2 = HiddenGroup (h, 3, 0, NULL);
+  c2 = HiddenGroup (h, 4, 0, NULL);
   SetGroupSpacing (c2, 10, 10);
   b = PushButton (c2, "Select All", VecScreenToolSelectAllBtn);
   SetObjectExtra (b, drfp, NULL);
@@ -11414,6 +11591,8 @@ extern void VecScreenTool (IteM i)
   SetObjectExtra (b, drfp, NULL);
   b = PushButton (c2, "Unselect Internal", VecScreenToolUnselectInternalBtn);
   SetObjectExtra (b, drfp, NULL);
+  b = PushButton (c2, "Select Only Strong and Moderate", VecScreenToolSelectStrongAndModerateBtn);
+  SetObjectExtra (b, drfp, NULL);
 
   g = HiddenGroup (h, 2, 0, NULL);
   SetGroupSpacing (g, 10, 10);
@@ -11433,7 +11612,7 @@ extern void VecScreenTool (IteM i)
   PushButton (c, "Dismiss", StdCancelButtonProc);
 
   AlignObjects (ALIGN_CENTER, (HANDLE) drfp->clickable_list,
-                              (HANDLE) sort_grp,
+                              (HANDLE) drfp->sort_grp,
                               (HANDLE) drfp->trim_options_grp,
                               (HANDLE) c2,
                               (HANDLE) g,
@@ -12065,6 +12244,43 @@ static void RemoveSelectedKeywordsBtn (ButtoN b)
 }
 
 
+static void RemoveBarcodeKeywordsFromLowTrace (ButtoN b)
+{
+  BarcodeToolPtr vstp;
+  LogInfoPtr     lip;
+  ValNodePtr     object_list;
+  SeqEntryPtr    sep;
+
+  vstp = (BarcodeToolPtr) GetObjectExtra (b);
+  if (vstp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (vstp->input_entityID);
+  object_list = GetBarcodeLowTraceList(sep);
+
+  if (object_list == NULL)
+  {
+    Message (MSG_ERROR, "No low-trace entries found");
+    return;
+  }
+  
+  lip = OpenLog ("BARCODE Keywords Removed");
+  RemoveBarcodeKeywordsFromObjectList (lip->fp, object_list);
+  object_list = ValNodeFree (object_list);
+
+  RefreshBarcodeList (vstp);
+  RedrawBarcodeTool (vstp);  
+
+  DeleteMarkedObjects (vstp->input_entityID, 0, NULL);
+  ObjMgrSetDirtyFlag (vstp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, vstp->input_entityID, 0, 0);
+  Update();
+
+  lip->data_in_log = TRUE;
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
 static void ApplyBarcodeKeywordCallback (BioseqPtr bsp, Pointer data)
 {
   LogInfoPtr lip;
@@ -12117,11 +12333,15 @@ extern void BarcodeRefreshButton (ButtoN b)
   vstp = (BarcodeToolPtr) GetObjectExtra (b);
   if (vstp == NULL) return;
 
+  WatchCursor();
+  Update();
   if (vstp->refresh_func != NULL) 
   {
     (vstp->refresh_func) (vstp);
   }
   RedrawBarcodeTool (vstp);  
+  ArrowCursor();
+  Update();
 }
 
 
@@ -12148,7 +12368,7 @@ extern void BarcodeReportButton (ButtoN b)
   }
 
   lip = OpenLog ("BARCODE Discrepancies");
-  WriteBarcodeDiscrepancies (lip->fp, object_list);
+  WriteBarcodeFailureReport (lip->fp, object_list);
   lip->data_in_log = TRUE;
   CloseLog (lip);
   lip = FreeLog (lip);
@@ -12163,11 +12383,21 @@ extern void BarcodeTestComplianceReport (ButtoN b)
   BarcodeToolPtr vstp;
   ValNodePtr     object_list;
   LogInfoPtr     lip;
+  Boolean        free_config = FALSE;
 
   vstp = (BarcodeToolPtr) GetObjectExtra (b);
   if (vstp == NULL) return;
 
+  if (vstp->cfg == NULL) {
+    vstp->cfg = BarcodeTestConfigNew ();
+    free_config = TRUE;
+  }
+  vstp->cfg->conf_list[eBarcodeTest_OrderAssignment] = FALSE;
   object_list = GetBarcodePassFail (vstp->top_sep, vstp->cfg);
+  vstp->cfg->conf_list[eBarcodeTest_OrderAssignment] = TRUE;
+  if (free_config) {
+    vstp->cfg = BarcodeTestConfigFree (vstp->cfg);
+  }
   lip = OpenLog ("BARCODE Compliance");
   WriteBarcodeTestCompliance (lip->fp, object_list);
   lip->data_in_log = TRUE;
@@ -12177,6 +12407,25 @@ extern void BarcodeTestComplianceReport (ButtoN b)
 }
 
 
+extern void BarcodeTestIbolComplianceReport (ButtoN b)
+{
+  BarcodeToolPtr vstp;
+  ValNodePtr     object_list;
+  LogInfoPtr     lip;
+
+  vstp = (BarcodeToolPtr) GetObjectExtra (b);
+  if (vstp == NULL) return;
+
+  object_list = GetBarcodePassFail (vstp->top_sep, vstp->cfg);
+  lip = OpenLog ("BARCODE Compliance");
+  WriteBarcodeTestComplianceEx (lip->fp, object_list, TRUE);
+  lip->data_in_log = TRUE;
+  CloseLog (lip);
+  lip = FreeLog (lip);
+  object_list = BarcodeTestResultsListFree (object_list);
+}
+
+
 extern DialoG BarcodeTestResultsDisplay (GrouP h, BarcodeTestConfigPtr cfg);
 
 static void BarcodeTestMakeTagTable (ButtoN b)
@@ -12667,12 +12916,22 @@ static void BarcodeComprehensiveReportButton (ButtoN b)
   BarcodeToolPtr         drfp;
   LogInfoPtr             lip;
   ValNodePtr             object_list;
+  Boolean                free_config = FALSE;
 
   drfp = (BarcodeToolPtr) GetObjectExtra (b);
   if (drfp == NULL) return;
 
   lip = OpenLog ("BARCODE Discrepancies");
+  if (drfp->cfg == NULL) {
+    drfp->cfg = BarcodeTestConfigNew ();
+    free_config = TRUE;
+  }
+  drfp->cfg->conf_list[eBarcodeTest_OrderAssignment] = FALSE;
   object_list = GetBarcodePassFail (drfp->top_sep, drfp->cfg);
+  drfp->cfg->conf_list[eBarcodeTest_OrderAssignment] = TRUE;
+  if (free_config) {
+    drfp->cfg = BarcodeTestConfigFree (drfp->cfg);
+  }
   WriteBarcodeTestComprehensive (lip->fp, object_list);
   lip->data_in_log = TRUE;
   CloseLog (lip);
@@ -12735,6 +12994,268 @@ static void ApplyBarcodeDbxrefsBtn (ButtoN b)
 }
 
 
+typedef struct stripreport {
+  CharPtr id;
+  CharPtr reasons;
+} StripReportData, PNTR StripReportPtr;
+
+static StripReportPtr StripReportNew (CharPtr id, CharPtr reasons)
+{
+  StripReportPtr s = (StripReportPtr) MemNew (sizeof (StripReportData));
+  s->id = StringSave (id);
+  s->reasons = StringSave (reasons);
+  return s;
+}
+
+
+static StripReportPtr StripReportFree (StripReportPtr s)
+{
+  if (s != NULL) {
+    s->id = MemFree (s->id);
+    s->reasons = MemFree (s->reasons);
+    s = MemFree (s);
+  }
+  return s;
+}
+
+
+static StripReportPtr StripReportCopy (StripReportPtr s)
+{
+  StripReportPtr cpy = NULL;
+
+  if (s != NULL) {
+    cpy = StripReportNew (s->id, s->reasons);
+  }
+  return cpy;
+}
+
+
+static StripReportPtr CombineStripReports (StripReportPtr s1, StripReportPtr s2)
+{
+  StripReportPtr sum = NULL;
+  CharPtr        tmp;
+
+  if (s1 == NULL || StringHasNoText (s1->reasons)) {
+    sum = StripReportCopy (s2);
+  } else if (s2 == NULL || StringHasNoText (s2->reasons)) {
+    sum = StripReportCopy (s1);
+  } else if (StringCmp (s1->reasons, s2->reasons) == 0) {
+    sum = StripReportCopy (s1);
+  } else {
+    sum = StripReportNew (s1->id, NULL);
+    tmp = (CharPtr) MemNew (sizeof (Char) * (StringLen (s1->reasons) + StringLen (s2->reasons) + 3));
+    if (StringICmp (s1->reasons, "frameshift") == 0) {
+      sprintf (tmp, "%s, %s", s2->reasons, s1->reasons);
+    } else {
+      sprintf (tmp, "%s, %s", s1->reasons, s2->reasons);
+    }
+    sum->reasons = tmp;
+  }
+  return sum;
+}
+
+
+static int LIBCALLBACK SortVnpByStripReport(VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  StripReportPtr str1;
+  StripReportPtr str2;
+  ValNodePtr     vnp1;
+  ValNodePtr     vnp2;
+  int            rval = 0;
+
+  if (ptr1 != NULL && ptr2 != NULL) {
+    vnp1 = *((ValNodePtr PNTR) ptr1);
+    vnp2 = *((ValNodePtr PNTR) ptr2);
+    if (vnp1 != NULL && vnp2 != NULL) {
+      str1 = (StripReportPtr) vnp1->data.ptrvalue;
+      str2 = (StripReportPtr) vnp2->data.ptrvalue;
+      if (str1 != NULL && str2 != NULL) {
+        rval = StringICmp (str1->id, str2->id);
+        if (rval == 0) {
+          if (str1->reasons == NULL) {
+            if (str2->reasons == NULL) {
+              rval = 0;
+            } else {
+              rval = -1;
+            }
+          } else if (str2->reasons == NULL) {
+            rval = 1;
+          } else {
+            rval = StringICmp (str1->reasons, str2->reasons);
+          }
+        }
+      }
+    }
+  }
+  return rval;
+}
+
+
+typedef struct stripreportcollect {
+  ValNodePtr strip_report_list;
+  BarcodeTestConfigPtr cfg;
+} StripReportCollectData, PNTR StripReportCollectPtr;
+
+
+static void FindMissingKeywordsCallback (BioseqPtr bsp, Pointer data)
+{
+  Char             id_buf[255];
+  StripReportCollectPtr  s;
+  BarcodeTestResultsPtr  res;
+  CharPtr                reasons, tmp;
+
+  if (bsp == NULL || !HasBARCODETech (bsp) || (s = (StripReportCollectPtr) data) == NULL || BioseqHasBarcodeKeyword(bsp)) {
+    return;
+  } else {
+    res = BarcodeTestResultsForBioseq(bsp, s->cfg);
+    reasons = GetBarcodeTestFailureReasons (res);
+    res = BarcodeTestResultsFree (res);
+
+    SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_buf, PRINTID_TEXTID_ACC_ONLY, sizeof (id_buf) - 1);
+
+    ValNodeAddPointer (&(s->strip_report_list), 0, StripReportNew(id_buf, reasons));
+    reasons = MemFree (reasons);
+  }
+}
+
+
+static void ProcessOneFrameFindFile (CharPtr filename, Pointer userdata)
+
+{
+  ReadBufferData rbd;
+  CharPtr line, id, comma;
+  StripReportCollectPtr  s;
+
+  if (StringHasNoText (filename) || (s = (StripReportCollectPtr) userdata) == NULL) {
+    return;
+  }
+
+  rbd.fp = FileOpen (filename, "r");
+  if (rbd.fp == NULL) {
+    Message (MSG_POSTERR, "Failed to open '%s'", filename);
+    return;
+  }
+
+  rbd.current_data = NULL;
+
+  line = AbstractReadFunction (&rbd);
+  while (line != NULL) 
+  {
+    if (StringNCmp (line, "Gap: ", 5) == 0) {
+      line = MemFree (line);
+      line = AbstractReadFunction (&rbd);
+      id = line;
+      comma = StringChr(id, ',');
+      while (comma != NULL) {
+        *comma = 0;
+        ValNodeAddPointer (&(s->strip_report_list), 0, StripReportNew(id, "frameshift"));
+        id = comma + 1;
+        comma = StringChr(id, ',');
+      }
+      if (*id != 0) {
+        ValNodeAddPointer (&(s->strip_report_list), 0, StripReportNew(id, "frameshift"));
+      }
+    }
+    line = MemFree (line);
+    line = AbstractReadFunction (&rbd);
+  }
+  FileClose (rbd.fp);
+}
+
+
+static void CollapseStripReportList (ValNodePtr list)
+{
+  ValNodePtr vnp, prev, vnp_next;
+  StripReportPtr s1, s2, sum;
+
+  if (list == NULL || list->next == NULL) {
+    return;
+  }
+  prev = list;
+  vnp = prev->next;
+  while (vnp != NULL) {
+    vnp_next = vnp->next;
+    s1 = prev->data.ptrvalue;
+    s2 = vnp->data.ptrvalue;
+    if (StringICmp (s1->id, s2->id) == 0) {
+      sum = CombineStripReports (s1, s2);
+      s1 = StripReportFree (s1);
+      s2 = StripReportFree (s2);
+      prev->data.ptrvalue = sum;
+      prev->next = vnp->next;
+      vnp->next = NULL;
+      vnp = ValNodeFree (vnp);
+    } else {
+      prev = vnp;
+    }
+    vnp = vnp_next;
+  }
+}
+
+
+static void MakeBarcodeStripReport (ButtoN b)
+{
+  BarcodeToolPtr drfp;
+  StripReportCollectData sd;
+  ValNodePtr     vnp;
+  SeqEntryPtr    sep;
+  LogInfoPtr     lip;
+  Char           path [PATH_MAX];
+  CharPtr        cp;
+  StripReportPtr sp;
+  Boolean        require_keyword;
+
+  drfp = (BarcodeToolPtr) GetObjectExtra (b);
+  if (drfp == NULL) return;
+
+  sep = GetTopSeqEntryForEntityID (drfp->input_entityID);
+
+  MemSet (&sd, 0, sizeof (StripReportCollectData));
+  sd.cfg = drfp->cfg;
+  if (sd.cfg == NULL) {
+    sd.cfg = BarcodeTestConfigNew();
+  }
+  require_keyword = sd.cfg->require_keyword;
+  sd.cfg->require_keyword = FALSE;
+  VisitBioseqsInSep (sep, &sd, FindMissingKeywordsCallback);
+  sd.cfg->require_keyword = require_keyword;
+  if (drfp->cfg == NULL) {
+    sd.cfg = BarcodeTestConfigFree (sd.cfg);
+  }
+
+  path [0] = '\0';
+  if (GetInputFileName (path, sizeof (path), NULL, "TEXT")) {    
+    cp = StringRChr (path, '\\');
+    if (cp == NULL) {
+      cp = StringRChr (path, '/');
+    }
+    if (cp != NULL) {
+      *cp = 0;
+    }
+    DirExplore (path, "", "", FALSE, ProcessOneFrameFindFile, (Pointer) &sd);
+  }
+
+  sd.strip_report_list = ValNodeSort (sd.strip_report_list, SortVnpByStripReport);
+  CollapseStripReportList (sd.strip_report_list);
+
+  lip = OpenLog ("Stripped Sequences");
+
+  fprintf (lip->fp, "Total Sequences: %d\n\n", ValNodeLen (sd.strip_report_list));
+  lip->data_in_log = TRUE;
+  for (vnp = sd.strip_report_list; vnp != NULL; vnp = vnp->next) {
+    if ((sp = (StripReportPtr)vnp->data.ptrvalue) != NULL) {
+      fprintf (lip->fp, "%s: %s\n", sp->id, sp->reasons == NULL ? "Reason unknown" : sp->reasons);
+      sp = StripReportFree (sp);
+      vnp->data.ptrvalue = NULL;
+    }
+  }
+  CloseLog(lip);
+  lip = FreeLog (lip);
+  sd.strip_report_list = ValNodeFree (sd.strip_report_list);
+}
+
+
 extern void BarcodeTestTool (IteM i)
 {
   BaseFormPtr              bfp;
@@ -12797,17 +13318,23 @@ extern void BarcodeTestTool (IteM i)
   drfp->pass_fail_summary = StaticPrompt (h, "0 Pass, 0 Fail", 20 * stdCharWidth, dialogTextHeight, programFont, 'l');
   RefreshBarcodeList(drfp);
 
-  c4 = HiddenGroup (h, 5, 0, NULL);
+  c4 = HiddenGroup (h, 6, 0, NULL);
   SetGroupSpacing (c4, 10, 10);
 
   b = PushButton (c4, "Compliance Report", BarcodeTestComplianceReport);
   SetObjectExtra (b, drfp, NULL);
+  b = PushButton (c4, "iBOL Compliance Report", BarcodeTestIbolComplianceReport);
+  SetObjectExtra (b, drfp, NULL);  
   b = PushButton (c4, "Failure Report", BarcodeReportButton);
   SetObjectExtra (b, drfp, NULL);
   b = PushButton (c4, "Comprehensive Report", BarcodeComprehensiveReportButton);
   SetObjectExtra (b, drfp, NULL);
   b = PushButton (c4, "Report Polymorphism", BarcodeReportPolymorphism);
   SetObjectExtra (b, drfp, NULL);
+  b = PushButton (c4, "Barcode Strip Report", MakeBarcodeStripReport);
+  SetObjectExtra (b, drfp, NULL);
+
+
 
   c5 = HiddenGroup (h, 5, 0, NULL);
   SetGroupSpacing (c5, 10, 10);
@@ -12830,6 +13357,8 @@ extern void BarcodeTestTool (IteM i)
   SetObjectExtra (b, drfp, NULL);
   b = PushButton (c3, "Remove BARCODE Tech from Selected", RemoveSelectedTechBtn);
   SetObjectExtra (b, drfp, NULL);
+  b = PushButton (c3, "Remove BARCODE Keyword from Low Trace", RemoveBarcodeKeywordsFromLowTrace);
+  SetObjectExtra (b, drfp, NULL);
 
   c = HiddenGroup (h, 4, 0, NULL);
   SetGroupSpacing (c, 10, 10);
@@ -12846,7 +13375,13 @@ extern void BarcodeTestTool (IteM i)
 
   PushButton (c, "Dismiss", StdCancelButtonProc);
 
-  AlignObjects (ALIGN_CENTER, (HANDLE) drfp->clickable_list, (HANDLE) drfp->pass_fail_summary, (HANDLE) c4, (HANDLE) c5, (HANDLE) c3, (HANDLE) c, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) drfp->clickable_list,
+                              (HANDLE) drfp->pass_fail_summary, 
+                              (HANDLE) c4, 
+                              (HANDLE) c5, 
+                              (HANDLE) c3, 
+                              (HANDLE) c, 
+                              NULL);
 
   RealizeWindow (w);
   
@@ -15222,3 +15757,905 @@ extern void TaxFixTool (IteM i)
 
 }
 
+
+/* Begin section of code for trimming sequences to contain correct percentage of Ns */
+typedef struct ntriminterval {
+  Int4 start;
+  Int4 stop;
+  Int4 internal_ns;
+  Int4 pct;
+  BioseqPtr bsp;
+} NTrimIntervalData, PNTR NTrimIntervalPtr;
+
+
+static NTrimIntervalPtr NTrimIntervalNew (Int4 start, BioseqPtr bsp)
+{
+  NTrimIntervalPtr n;
+
+  n = (NTrimIntervalPtr) MemNew (sizeof (NTrimIntervalData));
+  n->start = start;
+  n->stop = -1;
+  n->internal_ns = 0;
+  n->pct = 0;
+  n->bsp = bsp;
+  return n;
+}
+
+
+static NTrimIntervalPtr NTrimIntervalCopy (NTrimIntervalPtr orig)
+{
+  NTrimIntervalPtr n;
+
+  if (orig == NULL) {
+    return NULL;
+  }
+  n = (NTrimIntervalPtr) MemNew (sizeof (NTrimIntervalData));
+  n->start = orig->start;
+  n->stop = orig->stop;
+  n->internal_ns = orig->internal_ns;
+  n->pct = orig->pct;
+  n->bsp = orig->bsp;
+  return n;
+}
+
+
+static void NTrimIntervalSetStop (NTrimIntervalPtr n, Int4 stop)
+{
+  if (n != NULL) {
+    n->stop = stop;
+    n->pct = (1000 * n->internal_ns) / (n->stop - n->start + 1);
+  }
+}
+
+
+static NTrimIntervalPtr NTrimIntervalFree (NTrimIntervalPtr n)
+{
+  n = MemFree (n);
+  return n;
+}
+
+
+static int s_MaxPct = 100;
+static int s_MinLen = 10;
+
+NLM_EXTERN int LIBCALLBACK SortVnpByNTrimInterval (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+  NTrimIntervalPtr n1, n2;
+  Int4        rval = 0, len1, len2;
+
+  if (ptr1 == NULL || ptr2 == NULL) return 0;
+  vnp1 = *((ValNodePtr PNTR) ptr1);
+  vnp2 = *((ValNodePtr PNTR) ptr2);
+  if (vnp1 == NULL || vnp2 == NULL) return 0;
+  if (vnp1->data.ptrvalue == NULL || vnp2->data.ptrvalue == NULL) return 0;
+  
+  n1 = vnp1->data.ptrvalue;
+  n2 = vnp2->data.ptrvalue;
+
+  len1 = n1->stop - n1->start + 1;
+  len2 = n2->stop - n2->start + 1;
+  if (n1->pct < s_MaxPct && n2->pct < s_MaxPct) {
+    if (len1 > len2) {
+      rval = -1;
+    } else if (len1 < len2) {
+      rval = 1;
+    } else if (n1->pct < n2->pct) {
+      rval = -1;
+    } else if (n1->pct > n2->pct) {
+      rval = 1;
+    }
+  } else if (n1->pct < n2->pct) {
+    rval = -1;
+  } else if (n1->pct > n2->pct) {
+    rval = 1;
+  } else {
+    if (len1 > len2) {
+      rval = -1;
+    } else if (len1 < len2) {
+      rval = 1;
+    } else {
+      rval = 0;
+    }
+  }
+
+  return rval;
+}
+
+
+extern Pointer GetTrimInterval (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  CharPtr          fmt = "%d-%d (%.1f%%)";
+  CharPtr          buffer;
+
+  n_trim = (NTrimIntervalPtr) data;
+  if (n_trim == NULL || n_trim->bsp == NULL) return NULL;
+
+  if (n_trim->stop - n_trim->start + 1 < s_MinLen) {
+    buffer = StringSave ("Delete");
+  } else {
+    buffer = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + 100));
+    sprintf (buffer, fmt, n_trim->start + 1, n_trim->stop + 1, (float) n_trim->pct / 10.0);
+  }
+  return buffer;
+}
+
+
+extern Pointer GetTrimRemove (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  CharPtr          fmt = "%6d";
+  CharPtr          buffer;
+  Int4             len;
+
+  n_trim = (NTrimIntervalPtr) data;
+  if (n_trim == NULL || n_trim->bsp == NULL) return NULL;
+
+  len = n_trim->stop - n_trim->start + 1;
+
+  if (len < s_MinLen) {
+    buffer = StringSave ("Delete");
+  } else {
+    buffer = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + 100));
+    sprintf (buffer, fmt, n_trim->bsp->length - len);
+  }
+  return buffer;
+}
+
+
+extern Pointer GetTrimRemaining (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  CharPtr          fmt = "%6d";
+  CharPtr          buffer;
+  Int4             len;
+
+  n_trim = (NTrimIntervalPtr) data;
+  if (n_trim == NULL || n_trim->bsp == NULL) return NULL;
+
+  len = n_trim->stop - n_trim->start + 1;
+  buffer = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + 100));
+  sprintf (buffer, fmt, len);
+
+  return buffer;
+}
+
+
+extern Boolean TrimShouldDelete (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  Int4             len;
+
+  n_trim = (NTrimIntervalPtr) data;
+
+  if (n_trim == NULL) {
+    return TRUE;
+  }
+  len = n_trim->stop - n_trim->start + 1;
+  if (len < s_MinLen) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+
+extern Pointer GetCurrentPercentN (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  CharPtr          fmt = "%s:%.1f%%";
+  CharPtr          buffer;
+  Char             id_buf[255];
+
+  n_trim = (NTrimIntervalPtr) data;
+  if (n_trim == NULL || n_trim->bsp == NULL) return NULL;
+
+  SeqIdWrite (SeqIdFindBest (n_trim->bsp->id, SEQID_GENBANK), id_buf, PRINTID_REPORT, sizeof (id_buf) - 1);
+
+  buffer = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt) + StringLen (id_buf) + 100));
+  sprintf (buffer, fmt, id_buf, PercentNInBioseq(n_trim->bsp, FALSE));
+  return buffer;
+}
+
+
+extern Pointer GetTrimAccession (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  Char             id_buf[255];
+
+  n_trim = (NTrimIntervalPtr) data;
+  if (n_trim == NULL || n_trim->bsp == NULL) return NULL;
+
+  SeqIdWrite (SeqIdFindBest (n_trim->bsp->id, SEQID_GENBANK), id_buf, PRINTID_REPORT, sizeof (id_buf) - 1);
+
+  return StringSave (id_buf);
+}
+
+
+extern Pointer GetTrim5 (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  Char             buffer[255];
+
+  n_trim = (NTrimIntervalPtr) data;
+  if (n_trim == NULL || n_trim->bsp == NULL) return NULL;
+  sprintf (buffer, "%14d", n_trim->start);
+
+  return StringSave (buffer);
+}
+
+
+extern Pointer GetTrim3 (Uint1 data_choice, Pointer data, Pointer metadata)
+{
+  NTrimIntervalPtr n_trim;
+  Char             buffer[255];
+
+  n_trim = (NTrimIntervalPtr) data;
+  if (n_trim == NULL || n_trim->bsp == NULL) return NULL;
+  sprintf (buffer, "%14d", n_trim->bsp->length - n_trim->stop - 1);
+
+  return StringSave (buffer);
+}
+
+
+extern void ScrollToTrimSequenceItem (ValNodePtr vnp, Pointer userdata)
+{
+  NTrimIntervalPtr n_trim;
+  BaseFormPtr   bfp;
+    
+  if (vnp == NULL || (n_trim = vnp->data.ptrvalue) == NULL || n_trim->bsp == NULL)
+  {
+    return;
+  }
+
+  bfp = GetBaseFormForEntityID (n_trim->bsp->idx.entityID);
+  if (bfp != NULL) {
+    Select (bfp->form);
+    SetBioseqViewTargetByBioseq (bfp, n_trim->bsp);
+  }
+}
+
+
+typedef struct ntrimlist {
+  ValNodePtr open_intervals;
+  ValNodePtr closed_intervals;
+  ValNodePtr start_list;
+  Boolean last_was_n;
+  Int4    pos;
+  Int4    total_ns;
+  BioseqPtr bsp;
+} NTrimListData, PNTR NTrimListPtr;
+
+static void LIBCALLBACK FindTrimEndpoints (CharPtr sequence, Pointer userdata)
+{
+  Char          ch;
+  NTrimListPtr  interval_list;
+  CharPtr       ptr;
+  ValNodePtr    vnp;
+  NTrimIntervalPtr n_open, n_closed;
+
+  if (sequence == NULL || userdata == NULL) return;
+  interval_list = (NTrimListPtr) userdata;
+
+  ptr = sequence;
+  ch = *ptr;
+
+  while (ch != '\0') {
+    if (ch == 'N') {
+      if (!interval_list->last_was_n) {
+        /* add new stop */
+        for (vnp = interval_list->open_intervals; vnp != NULL; vnp = vnp->next) {
+          n_open = vnp->data.ptrvalue;
+          n_closed = NTrimIntervalCopy (n_open);
+          NTrimIntervalSetStop(n_closed, interval_list->pos - 1);
+          ValNodeAddPointer (&(interval_list->closed_intervals), 0, n_closed);
+        }
+      }
+      /* add Ns to all open intervals */
+      for (vnp = interval_list->open_intervals; vnp != NULL; vnp = vnp->next) {
+        n_open = vnp->data.ptrvalue;
+        n_open->internal_ns ++;
+      }
+      interval_list->last_was_n = TRUE;
+      interval_list->total_ns ++;
+    } else {
+      if (interval_list->last_was_n) {
+        /* add new start */
+        n_open = NTrimIntervalNew (interval_list->pos, interval_list->bsp);
+        ValNodeAddPointer (&(interval_list->open_intervals), 0, n_open);
+        interval_list->last_was_n = FALSE;
+      }
+    }
+    interval_list->pos ++;
+    ptr++;
+    ch = *ptr;
+  }
+}
+
+
+static ValNodePtr FindTrimIntervalsForBioseq (BioseqPtr bsp)
+{
+  NTrimListData interval_list;
+  ValNodePtr    vnp;
+  NTrimIntervalPtr n_open;
+  int              orig_pct;
+
+  if (bsp == NULL) return NULL;
+  MemSet ((Pointer) &interval_list, 0, sizeof (NTrimListData));
+
+  interval_list.bsp = bsp;
+  interval_list.last_was_n = TRUE; /* need this to start interval at beginning (if sequence not starting with N) */
+
+  SeqPortStream (bsp, EXPAND_GAPS_TO_DASHES | KNOWN_GAP_AS_PLUS, (Pointer) &interval_list, FindTrimEndpoints);
+
+  /* finish up end of sequence intervals */
+  if (!interval_list.last_was_n) {
+    for (vnp = interval_list.open_intervals; vnp != NULL; vnp = vnp->next) {
+      n_open = (NTrimIntervalPtr) vnp->data.ptrvalue;
+      NTrimIntervalSetStop(n_open, interval_list.pos - 1);
+    }
+    ValNodeLink (&(interval_list.closed_intervals), interval_list.open_intervals);
+    interval_list.open_intervals = NULL;
+  } else {
+    interval_list.open_intervals = ValNodeFreeData (interval_list.open_intervals);
+  }
+
+  interval_list.closed_intervals = ValNodeSort (interval_list.closed_intervals, SortVnpByNTrimInterval);
+
+  orig_pct = (1000 * interval_list.total_ns) / bsp->length;
+
+  if (orig_pct < s_MaxPct) {
+    interval_list.closed_intervals = MemFree (interval_list.closed_intervals);
+  }
+
+  return interval_list.closed_intervals;
+}
+
+
+static void GetBestTrimIntervalForBioseq (BioseqPtr bsp, Pointer userdata)
+{
+  ValNodePtr PNTR best_list;
+  ValNodePtr intervals;
+
+  if (bsp == NULL || (best_list = (ValNodePtr PNTR) userdata) == NULL) {
+    return;
+  }
+
+  intervals = FindTrimIntervalsForBioseq(bsp);
+
+  if (intervals != NULL) {
+    ValNodeAddPointer (best_list, 0, intervals->data.ptrvalue);
+    intervals->data.ptrvalue = NULL;
+    intervals = ValNodeFreeData (intervals);
+  }
+}
+
+
+static void GetTrimIntervalWithoutNStretchesAtEnds (BioseqPtr bsp, Pointer userdata)
+{
+  ValNodePtr PNTR best_list;
+  Int2       ctr, pos, i, begin = 0, chop5 = -1, chop3 = -1;
+  Char       buf1[51];
+  Int4       len = 50, this_stretch = 0;
+  StreamFlgType flags = STREAM_CORRECT_INVAL | STREAM_EXPAND_GAPS;
+  NTrimIntervalPtr ntrim;
+
+  if (bsp == NULL || (best_list = (ValNodePtr PNTR) userdata) == NULL) {
+    return;
+  }
+
+  pos = 0;
+  while (pos < bsp->length) {
+    ctr = SeqPortStreamInt (bsp, pos, MIN(pos + len - 1, bsp->length - 1), Seq_strand_plus,
+                            flags, (Pointer) buf1, NULL);
+    for (i = 0; i < ctr; i++) {
+      if (buf1[i] == 'N') {
+        if (this_stretch == 0) {
+          begin = pos + i;
+        }
+        this_stretch++;
+      } else {
+        if (begin < 20 && this_stretch >= 5) {
+          chop5 = pos + i;
+        }
+        if (pos + i > bsp->length - 20 && this_stretch >= 5) {
+          chop3 = begin - 1;
+        }
+        this_stretch = 0;
+      }
+    }
+    pos += len;
+  }
+  if (chop5 > -1 || chop3 > -1) {
+    ntrim = NTrimIntervalNew (chop5 > -1 ? chop5 : 0, bsp);
+    NTrimIntervalSetStop (ntrim, chop3 > -1 ? chop3 : bsp->length - 1);
+    ValNodeAddPointer (best_list, 0, ntrim);
+  }
+}
+
+
+typedef struct seqtrimtool {
+  BARCODE_TOOL_BLOCK
+  GrouP pages[2];
+  GrouP page_choice;
+  /* controls for percentage trimming */
+  DialoG pct_display;
+  TexT max_pct;
+  TexT min_len;
+  /* controls for end trimming */
+  DialoG end_display;
+} SeqTrimToolData, PNTR SeqTrimToolPtr;
+
+
+static void CleanupSequenceTrimTool (GraphiC g, VoidPtr data)
+
+{
+  SeqTrimToolPtr drfp;
+
+  drfp = (SeqTrimToolPtr) data;
+  if (drfp != NULL) {
+    drfp->item_list = ValNodeFreeData (drfp->item_list);
+    ObjMgrFreeUserData (drfp->input_entityID, drfp->procid, drfp->proctype, drfp->userkey);
+  }
+  StdCleanupFormProc (g, data);
+}
+
+
+static void RefreshSequenceTrimTool (Pointer data)
+{  
+  FloatHi val;
+  CharPtr str;
+  Char    buf[50];
+  Int2    page;
+
+  SeqTrimToolPtr vstp = (SeqTrimToolPtr) data;
+
+  if (vstp == NULL) return;
+  
+  page = GetValue (vstp->page_choice);
+  if (page == 1) {
+    str = SaveStringFromText (vstp->max_pct);
+    val = atof (str);
+    str = MemFree (str);
+    s_MaxPct = (Int4) (val * 10);
+    sprintf (buf, "%.1f", (FloatHi) s_MaxPct / 10.0);
+    SetTitle (vstp->max_pct, buf);
+    
+    str = SaveStringFromText (vstp->min_len);
+    s_MinLen = atoi (str);
+    str = MemFree (str);
+    sprintf (buf, "%d", s_MinLen);
+    SetTitle (vstp->min_len, buf);
+
+    PointerToDialog (vstp->clickable_list, NULL);
+    vstp->item_list = ValNodeFreeData (vstp->item_list);
+
+    VisitBioseqsInSep (vstp->top_sep, &(vstp->item_list), GetBestTrimIntervalForBioseq);
+
+    PointerToDialog (vstp->clickable_list, vstp->item_list);  
+
+    DefaultCheckTrimSequenceResultsDisplay (vstp->clickable_list);
+  } else {
+    PointerToDialog (vstp->clickable_list, NULL);
+    vstp->item_list = ValNodeFreeData (vstp->item_list);
+
+    VisitBioseqsInSep (vstp->top_sep, &(vstp->item_list), GetTrimIntervalWithoutNStretchesAtEnds);
+
+    PointerToDialog (vstp->clickable_list, vstp->item_list);
+
+    DefaultCheckTrimSequenceResultsDisplay (vstp->clickable_list);
+  }
+}
+
+
+static void TrimSequence (BioseqPtr bsp, Int4 start, Int4 stop, LogInfoPtr lip)
+{
+  SeqIdPtr       sip;
+  SeqLocPtr      slp1 = NULL,
+                 slp2 = NULL;
+  SeqEntryPtr    sep;    
+  
+  if (bsp == NULL || stop < start) {
+    return;
+  }
+
+  sep = GetTopSeqEntryForEntityID (bsp->idx.entityID);
+  sip = SeqIdFindBest (bsp->id, 0);
+  /* trim 3' end first */
+  if (stop < bsp->length) {
+    slp1 = SeqLocIntNew (stop + 1, bsp->length - 1, Seq_strand_plus, sip);
+    SeqDeleteByLoc (slp1, TRUE, FALSE);
+    TrimQualityScores (bsp, bsp->length - 1 - stop, FALSE);        
+  }
+  /* now trim 5' end */
+  if (start > 0) {
+    slp2 = SeqLocIntNew (0, start - 1, Seq_strand_plus, sip);
+    SeqDeleteByLoc (slp2, TRUE, FALSE);
+    TrimQualityScores (bsp, start, TRUE);        
+  }
+  /* also trim alignments and log */
+  if (slp1!=NULL) {
+    LogTrimmedLocation (lip, slp1);
+    if (sep!=NULL) {
+      SeqEntryExplore (sep, (Pointer)slp1, SeqAlignDeleteByLocCallback);
+    }
+    slp1 = SeqLocFree (slp1);
+  }
+  if (slp2!=NULL) {
+    LogTrimmedLocation (lip, slp2);
+    if (sep!=NULL) {
+      SeqEntryExplore (sep, (Pointer)slp2, SeqAlignDeleteByLocCallback);
+    }
+    slp2 = SeqLocFree (slp2);
+  }
+}
+
+
+static void AutoTrimList (LogInfoPtr lip, ValNodePtr list)
+{
+  ValNodePtr vnp;
+  NTrimIntervalPtr n_trim;
+  Char             id_buf[255];
+
+  if (list == NULL) {
+    return;
+  }
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    n_trim = (NTrimIntervalPtr) vnp->data.ptrvalue;
+    if (n_trim->stop - n_trim->start + 1 < s_MinLen) {
+      /* delete it */
+      n_trim->bsp->idx.deleteme = TRUE;
+      if (lip != NULL && lip->fp != NULL) {
+        SeqIdWrite (SeqIdFindBest (n_trim->bsp->id, SEQID_GENBANK), id_buf, PRINTID_REPORT, sizeof (id_buf) - 1);
+        fprintf (lip->fp, "Deleted %s\n", id_buf);
+        lip->data_in_log = TRUE;
+      }
+    } else {
+      /* trim it */
+      TrimSequence (n_trim->bsp, n_trim->start, n_trim->stop, lip);
+    }
+  }
+}
+
+
+static void AutoTrim (ButtoN b)
+{
+  SeqTrimToolPtr    drfp;
+  ValNodePtr        object_list;
+  LogInfoPtr        lip;
+
+  drfp = (SeqTrimToolPtr) GetObjectExtra (b);
+  if (drfp == NULL) return;
+  object_list = DialogToPointer (drfp->clickable_list);
+
+  if (object_list == NULL)
+  {
+    if (ANS_YES == Message (MSG_YN, "You have not selected any sequences - correct all?"))
+    {
+      object_list = drfp->item_list;
+    }
+    else
+    {
+      return;
+    }
+  }
+  
+  WatchCursor();
+  Update();
+  lip = OpenLog ("Sequences Trimmed");
+  AutoTrimList (lip, object_list);
+
+  if (object_list != drfp->item_list) 
+  {
+    object_list = ValNodeFree (object_list);
+  }
+
+  DeleteMarkedObjects (drfp->input_entityID, 0, NULL);
+  ObjMgrSetDirtyFlag (drfp->input_entityID, TRUE);
+  ObjMgrSendMsg (OM_MSG_UPDATE, drfp->input_entityID, 0, 0);
+
+  RefreshSequenceTrimTool (drfp);
+  RedrawBarcodeTool ((BarcodeToolPtr)drfp);  
+
+  ArrowCursor();
+  Update();
+
+  lip->data_in_log = TRUE;
+  CloseLog (lip);
+  lip = FreeLog (lip);
+
+}
+
+
+static void ReportTrimNDelete (ButtoN b)
+{
+  SeqTrimToolPtr   drfp;
+  ValNodePtr       vnp;
+  LogInfoPtr       lip;
+  NTrimIntervalPtr n_trim;
+  Char             id_buf[255];
+
+  drfp = (SeqTrimToolPtr) GetObjectExtra (b);
+  if (drfp == NULL) return;
+  
+  lip = OpenLog ("Sequences that Should Be Deleted");
+  for (vnp = drfp->item_list; vnp != NULL; vnp = vnp->next) {
+    if (TrimShouldDelete (vnp->choice, vnp->data.ptrvalue, NULL)) {
+      n_trim = (NTrimIntervalPtr)(vnp->data.ptrvalue);
+      if (lip != NULL && lip->fp != NULL) {
+        SeqIdWrite (SeqIdFindBest (n_trim->bsp->id, SEQID_GENBANK), id_buf, PRINTID_REPORT, sizeof (id_buf) - 1);
+        fprintf (lip->fp, "%s\n", id_buf);
+        lip->data_in_log = TRUE;
+      }
+    }
+  }
+  if (!lip->data_in_log) {
+    fprintf (lip->fp, "No sequences were found for deletion\n");
+    lip->data_in_log = TRUE;
+  }
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
+static void ChangeTrimToolChoice (GrouP g)
+{
+  SeqTrimToolPtr   drfp;
+
+  drfp = (SeqTrimToolPtr) GetObjectExtra (g);
+  if (drfp == NULL) return;
+  WatchCursor();
+  Update();
+  
+  if (GetValue (g) == 1) {
+    Show (drfp->pages[0]);
+    Hide (drfp->pages[1]);
+    drfp->clickable_list = drfp->pct_display;
+  } else {
+    Show (drfp->pages[1]);
+    Hide (drfp->pages[0]);
+    drfp->clickable_list = drfp->end_display;
+  }
+  RefreshSequenceTrimTool (drfp);
+  ArrowCursor();
+  Update();
+}
+
+
+NLM_EXTERN void FindBestNTrimSites (IteM i)
+{
+  BaseFormPtr       bfp;
+  ValNodePtr        trim_list = NULL;
+  SeqTrimToolPtr    drfp;
+  WindoW            w;
+  GrouP             h, page_grp, c, opts;
+  ButtoN            b;
+  OMUserDataPtr     omudp;
+  Char              buf[50];
+
+#ifdef WIN_MAC
+  bfp = currentFormDataPtr;
+#else
+  bfp = GetObjectExtra (i);
+#endif
+  if (bfp == NULL || bfp->input_entityID == 0) return;
+
+  drfp = (SeqTrimToolPtr) MemNew (sizeof (SeqTrimToolData));
+  if (drfp == NULL)
+  {
+    return;
+  }
+  
+  drfp->bfp = bfp;
+  drfp->input_entityID = bfp->input_entityID;
+  drfp->top_sep = GetTopSeqEntryForEntityID (drfp->input_entityID);
+  w = FixedWindow (-50, -33, -10, -10, "Sequence Trim Tool", StdCloseWindowProc);
+  SetObjectExtra (w, drfp, CleanupSequenceTrimTool);
+  drfp->form = (ForM) w;
+  drfp->formmessage = BarcodeToolMessage;
+
+  drfp->refresh_func = RefreshSequenceTrimTool;    
+  /* register to receive update messages */
+  drfp->userkey = OMGetNextUserKey ();
+  drfp->procid = 0;
+  drfp->proctype = OMPROC_EDIT;
+  omudp = ObjMgrAddUserData (drfp->input_entityID, drfp->procid, drfp->proctype, drfp->userkey);
+  if (omudp != NULL) {
+    omudp->userdata.ptrvalue = (Pointer) drfp;
+    omudp->messagefunc = BarcodeToolMsgFunc;
+  }
+
+
+#ifndef WIN_MAC
+  CreateStdValidatorFormMenus (w);
+#endif
+  
+  drfp->item_list = NULL;
+  drfp->cfg = NULL;
+  drfp->undo_list = NULL;
+  
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+  
+  page_grp = HiddenGroup (h, 0, 0, NULL);
+  drfp->pages[0] = HiddenGroup (page_grp, -1, 0, NULL);
+  /* page for trimming for percentage */
+  drfp->pct_display = TrimSequenceResultsDisplay (drfp->pages[0]);
+
+  opts = HiddenGroup (drfp->pages[0], 2, 0, NULL);
+  SetGroupSpacing (opts, 10, 10);
+  StaticPrompt (opts, "Maximum N Percent", 0, dialogTextHeight, programFont, 'l');
+  sprintf (buf, "%.1f", (FloatHi) s_MaxPct / 10.0);
+  drfp->max_pct = DialogText (opts, buf, 10, NULL);
+
+  StaticPrompt (opts, "Minimum Length", 0, dialogTextHeight, programFont, 'l');
+  sprintf (buf, "%d", s_MinLen);
+  drfp->min_len = DialogText (opts, buf, 10, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) drfp->pct_display, (HANDLE) opts, NULL);
+
+  drfp->pages[1] = HiddenGroup (page_grp, -1, 0, NULL);
+  /* page for trimming ends with stretches */
+  drfp->end_display = TrimSequenceEndDisplay(drfp->pages[1]);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) drfp->pages[0], (HANDLE) drfp->pages[1], NULL);
+
+  drfp->page_choice = HiddenGroup (h, 2, 0, ChangeTrimToolChoice);
+  SetObjectExtra (drfp->page_choice, drfp, NULL);
+  RadioButton (drfp->page_choice, "Trim to interval with lower percentage");
+  RadioButton (drfp->page_choice, "Trim ends with stretches of Ns");
+  SetValue (drfp->page_choice, 1);
+  ChangeTrimToolChoice (drfp->page_choice);
+
+  c = HiddenGroup (h, 5, 0, NULL);
+  SetGroupSpacing (c, 10, 10);
+
+  b = PushButton (c, "Autotrim/Delete", AutoTrim);
+  SetObjectExtra (b, drfp, NULL);
+  b = PushButton (c, "Report Sequences for Deletion", ReportTrimNDelete);
+  SetObjectExtra (b, drfp, NULL);
+  b = PushButton (c, "Refresh List", BarcodeRefreshButton);
+  SetObjectExtra (b, drfp, NULL);
+
+  PushButton (c, "Dismiss", StdCancelButtonProc);
+
+  AlignObjects (ALIGN_CENTER, (HANDLE) page_grp, (HANDLE) drfp->page_choice, (HANDLE) c, NULL);
+
+  RealizeWindow (w);
+  
+  Show (w);
+
+}
+
+
+typedef struct articleupload {
+  CharPtr dir;
+  ValNodePtr table;
+} ArticleUploadData, PNTR ArticleUploadPtr;
+
+
+static void ArticleUploadBioseqCallback (BioseqPtr bsp, Pointer data)
+{
+  ArticleUploadPtr    up;
+  ValNodePtr          vnp, line;
+  CharPtr             article_id;
+  StringConstraintPtr scp;
+  Char                path[PATH_MAX];
+  SeqEntryPtr         sep;
+  AsnIoPtr            aip;
+  SeqDescPtr          sdp, sdp_last;
+  BioseqPtr           add_bsp = NULL;
+  BioseqSetPtr        add_bssp = NULL;
+
+  if (bsp == NULL || (up = (ArticleUploadPtr) data) == NULL || ISA_aa (bsp->mol)) {
+    return;
+  }
+
+  sep = GetBestTopParentForData (bsp->idx.entityID, bsp);
+  if (sep == NULL) {
+    return;
+  }
+  if (IS_Bioseq (sep)) {
+    add_bsp = sep->data.ptrvalue;
+  } else if (IS_Bioseq_set (sep)) {
+    add_bssp = sep->data.ptrvalue;
+  } else {
+    return;
+  }
+
+  scp = StringConstraintNew ();
+  scp->match_location = String_location_equals;
+
+  for (vnp = up->table; vnp != NULL; vnp = vnp->next) {
+    line = vnp->data.ptrvalue;
+    if (line != NULL && line->next != NULL && line->data.ptrvalue != NULL && line->next->data.ptrvalue != NULL) {
+      article_id = line->data.ptrvalue;
+      scp->match_text = line->next->data.ptrvalue;
+      if (DoesSeqIDListMeetStringConstraint (bsp->id, scp)) {
+        sprintf (path, "%s%s.descr", up->dir, article_id);
+        if (FileLength (path) < 1) {
+          Message (MSG_ERROR, "Article file %s does not exist", path);
+        } else {
+          /* add article from this file */
+          aip = AsnIoOpen (path, "r");
+          sdp = SeqDescAsnRead (aip, NULL);
+          aip = AsnIoClose (aip);
+          if (sdp == NULL) {
+            Message (MSG_ERROR, "Unable to read article from %s", path);
+          } else {
+            if (add_bsp != NULL) {
+              if (add_bsp->descr == NULL) {
+                add_bsp->descr = sdp;
+              } else {
+                sdp_last = add_bsp->descr;
+                while (sdp_last->next != NULL) {
+                  sdp_last = sdp_last->next;
+                }
+                sdp_last->next = sdp;
+              }
+            } else {
+              if (add_bssp->descr == NULL) {
+                add_bssp->descr = sdp;
+              } else {
+                sdp_last = add_bssp->descr;
+                while (sdp_last->next != NULL) {
+                  sdp_last = sdp_last->next;
+                }
+                sdp_last->next = sdp;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  scp->match_text = NULL;
+  scp = StringConstraintFree (scp);
+}
+
+
+NLM_EXTERN void ApplyArticles (IteM i)
+{
+  ValNodePtr  sep_list, vnp;
+  Char        path [PATH_MAX];
+  FILE        *fp;
+  SeqEntryPtr sep;
+  ArticleUploadData aud;
+  CharPtr           cp;
+  Uint2             entityID;
+
+  sep_list = GetViewedSeqEntryList ();
+  if (sep_list == NULL) {
+    Message (MSG_ERROR, "No records open!");
+  }
+
+  if (GetInputFileName (path, sizeof (path), "", "TEXT")) {
+    fp = FileOpen (path, "r");
+    aud.table = ReadTabTableFromFile (fp);
+    FileClose (fp);
+    cp = StringRChr (path, '\\');
+    if (cp == NULL) {
+      cp = StringRChr (path, '//');
+    }
+    if (cp != NULL) {
+      *(cp +1) = 0;
+    }
+    aud.dir = path;
+
+    for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
+      sep = vnp->data.ptrvalue;
+      VisitBioseqsInSep (sep, &aud, ArticleUploadBioseqCallback);
+      entityID = ObjMgrGetEntityIDForChoice (sep);
+      ObjMgrSetDirtyFlag (entityID, TRUE);
+      ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
+    }
+    aud.table = FreeTabTable (aud.table);
+  }
+  sep_list = ValNodeFree (sep_list);
+  ArrowCursor ();
+  Update ();   
+}
+
diff --git a/sequin/sequin8.c b/sequin/sequin8.c
index 4b3d401..2f160ed 100644
--- a/sequin/sequin8.c
+++ b/sequin/sequin8.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   2/3/98
 *
-* $Revision: 6.540 $
+* $Revision: 6.590 $
 *
 * File Description: 
 *
@@ -747,6 +747,9 @@ extern void RecomputeSuggestedIntervalsForCDS
 
       /* correct for partial conditions */
       CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
+      if (!partial5) {
+        crp->frame = 0;
+      }
 
       sfp->location = SeqLocFree (sfp->location);
       sfp->location = slp;
@@ -1801,171 +1804,6 @@ extern void ParseCodonQualToCodeBreak (IteM i)
   Update ();
 }
 
-static void CorrectGenCodeIndexedCallback (SeqFeatPtr sfp, Pointer userdata)
-{
-  CdRegionPtr     crp;
-  GeneticCodePtr  gc;
-  Int2Ptr         pGenCode;
-  ValNodePtr      vnp;
-  Boolean         need_replacement = FALSE;
-
-  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION 
-      || sfp->data.value.ptrvalue == NULL
-      || userdata == NULL) return;
- 
-  pGenCode = (Int2Ptr) userdata;
-  crp = (CdRegionPtr) sfp->data.value.ptrvalue;
-  if (crp->genetic_code != NULL
-      && crp->genetic_code->choice == 254) {
-    if (crp->genetic_code->data.ptrvalue == NULL) {
-      vnp = ValNodeNew (NULL);
-      vnp->choice = 2;
-      vnp->data.intvalue = (Int4) *pGenCode;
-    } else {
-      vnp = crp->genetic_code->data.ptrvalue;
-      if (vnp->next == NULL && vnp->choice == 2) {
-        vnp->data.intvalue = (Int4) *pGenCode;
-      } else {
-        need_replacement = TRUE;
-      }
-    }
-  } else {
-    need_replacement = TRUE;
-  }
-  if (need_replacement) {
-    gc = GeneticCodeNew ();
-    if (gc == NULL) return;
-    crp->genetic_code = GeneticCodeFree (crp->genetic_code);
-    vnp = ValNodeNew (NULL);
-    gc->data.ptrvalue = vnp;
-    if (vnp != NULL) {
-      vnp->choice = 2;
-      vnp->data.intvalue = (Int4) *pGenCode;
-    }
-    crp->genetic_code = gc;
-  }
-}
-
-static void CorrectGenCodesBioseqCallback (BioseqPtr bsp, Pointer userdata)
-{
-  SeqMgrFeatContext fcontext;
-  SeqFeatPtr        sfp;
-
-  if (bsp == NULL || userdata == NULL) return;
-  for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext);
-       sfp != NULL;
-       sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext)) {
-    CorrectGenCodeIndexedCallback (sfp, userdata);
-  }
-
-}
-
-typedef struct gencodescan {
-  Boolean mito;
-  Boolean plastid;
-  Int2    nuclCode;
-  Int2    mitoCode;
-  Boolean already_found;
-} GenCodeScanData, PNTR GenCodeScanPtr;
-
-static void JustGetGenCodeFromOrgRef (OrgRefPtr orp, GenCodeScanPtr gp)
-{
-  if (orp == NULL || orp->orgname == NULL || gp == NULL || gp->already_found) return;
-
-  gp->nuclCode = orp->orgname->gcode;
-  gp->mitoCode = orp->orgname->mgcode;
-}
-
-static void JustGetGenCodeFromBiop (BioSourcePtr biop, GenCodeScanPtr gp)
-{
-  if (biop == NULL || gp == NULL) return;
-  if (gp->already_found && !biop->is_focus) return;
-
-  gp->mito = (Boolean) (biop->genome == GENOME_kinetoplast ||
-                        biop->genome == GENOME_mitochondrion ||
-                        biop->genome == GENOME_hydrogenosome);
-
-  gp->plastid = (Boolean) (biop->genome == GENOME_chloroplast ||
-                                biop->genome == GENOME_chromoplast ||
-                                biop->genome == GENOME_plastid ||
-                                biop->genome == GENOME_cyanelle ||
-                                biop->genome == GENOME_apicoplast ||
-                                biop->genome == GENOME_leucoplast ||
-                                biop->genome == GENOME_proplastid);
-
-  JustGetGenCodeFromOrgRef (biop->org, gp);
-  gp->already_found = TRUE;
-}
-
-
-static void JustGetGenCodeFromFeat (SeqFeatPtr sfp, Pointer userdata) 
-{
-  GenCodeScanPtr gp;
-
-  if (sfp == NULL || userdata == NULL || sfp->data.choice != SEQFEAT_BIOSRC) return;
-
-  gp = (GenCodeScanPtr) userdata;
-
-  JustGetGenCodeFromBiop (sfp->data.value.ptrvalue, gp);
-}
-
-static void JustGetGenCodeFromDesc (SeqDescrPtr sdp, Pointer userdata)
-{
-  GenCodeScanPtr gp;
-
-  if (sdp == NULL || userdata == NULL || sdp->choice != Seq_descr_source) return;
-
-  gp = (GenCodeScanPtr) userdata;
-
-  JustGetGenCodeFromBiop (sdp->data.ptrvalue, gp);
-}
-
-static Int2 JustGetGenCodeForSeqEntry (SeqEntryPtr sep) 
-{
-  GenCodeScanData gd;
-
-  gd.already_found = FALSE;
-  gd.mito = FALSE;
-  gd.mitoCode = 0;
-  gd.nuclCode = 0;
-  gd.plastid = FALSE;
-
-  VisitDescriptorsInSep (sep, &gd, JustGetGenCodeFromDesc);
-  VisitFeaturesInSep (sep, &gd, JustGetGenCodeFromFeat);
-
-  if (gd.plastid) {
-    return 11;
-  } else if (gd.mito) {
-    return gd.mitoCode;
-  } else {
-    return gd.nuclCode;
-  }
-}
-
-
-extern void CorrectGenCodes (SeqEntryPtr sep, Uint2 entityID)
-
-{
-  BioseqSetPtr  bssp;
-  Int2          genCode;
-
-  if (sep == NULL) return;
-  if (IS_Bioseq_set (sep)) {
-    bssp = (BioseqSetPtr) sep->data.ptrvalue;
-    if (bssp != NULL && (bssp->_class == 7 ||
-                         (IsPopPhyEtcSet (bssp->_class)))) {
-      for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
-        CorrectGenCodes (sep, entityID);
-      }
-      return;
-    }
-  }
-
-  genCode = JustGetGenCodeForSeqEntry(sep);
-  VisitFeaturesInSep (sep, &genCode, CorrectGenCodeIndexedCallback);
-  VisitBioseqsInSep (sep, &genCode, CorrectGenCodesBioseqCallback);
-}
-
 extern void CorrectCDSGenCodes (IteM i)
 
 {
@@ -3361,7 +3199,7 @@ static void SelectAsnObject (IteM i, Int2 type)
   GrouP              c;
   GrouP              g;
   GrouP              h;
-  GrouP              k, m;
+  GrouP              k = NULL, m;
   ValNodePtr         head;
   Uint1              j;
   Int2               listHeight;
@@ -3488,7 +3326,7 @@ static void SelectAsnObject (IteM i, Int2 type)
 
   if (selfp->type == SLCT_FEAT || selfp->type == SLCT_DESC)
   {
-    AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) k, (HANDLE) c, NULL);
+    AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) k, NULL);
   }
   else
   {
@@ -3526,8 +3364,10 @@ typedef struct fuseformdata {
   FEATURE_FORM_BLOCK
 
   LisT           objlist;
+  DialoG         constraint_dlg;
   Uint2          subtype;
   ValNodePtr     head;
+  ConstraintChoiceSetPtr constraint;
 } FuseFormData, PNTR FuseFormPtr;
 
 static SeqLocPtr FuseTwoLocations (Uint2 entityID, SeqLocPtr slp1, SeqLocPtr slp2)
@@ -3843,9 +3683,10 @@ static void FuseFeatureCallback (BioseqPtr bsp, Pointer userdata)
   sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &context);
   while (sfp != NULL)
   {
-    if (sfp->idx.subtype == ffp->subtype ||
+    if ((sfp->idx.subtype == ffp->subtype ||
            (ffp->subtype == FEATDEF_IMP &&
             IsRealImpFeat (sfp->idx.subtype))) 
+        && DoesObjectMatchConstraintChoiceSet(OBJ_SEQFEAT, sfp, ffp->constraint))
     {
       if (first == NULL)
       {
@@ -3896,7 +3737,9 @@ static void DoFuseFeature (ButtoN b)
   }
   if (vnp != NULL) {
     ffp->subtype = vnp->choice;
+    ffp->constraint = DialogToPointer (ffp->constraint_dlg);
     VisitBioseqsInSep (sep, ffp, FuseFeatureCallback);
+    ffp->constraint = ConstraintChoiceSetFree(ffp->constraint);
     DeleteMarkedObjects (ffp->input_entityID, 0, NULL);
   }
 
@@ -4021,12 +3864,15 @@ extern void FuseFeature (IteM i)
   }
   ffp->head = head;
 
+  ffp->constraint_dlg = ComplexConstraintDialog(h, NULL, NULL);
+  ChangeComplexConstraintFieldType (ffp->constraint_dlg, FieldType_feature_field, NULL, Feature_type_any);
+
   c = HiddenGroup (h, 4, 0, NULL);
   b = DefaultButton (c, "Accept", DoFuseFeature);
   SetObjectExtra (b, ffp, NULL);
   PushButton (c, "Cancel", StdCancelButtonProc);
 
-  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) ffp->constraint_dlg, (HANDLE) c, NULL);
   RealizeWindow (w);
   Show (w);
   Update ();
@@ -4445,6 +4291,7 @@ typedef struct dblinkdialog {
   DialoG  traceassm;
   DialoG  biosample;
   DialoG  probedb;
+  DialoG  seqreadarch;
 } DblinkDialog, PNTR DblinkDialogPtr;
 
 typedef struct dblinkform {
@@ -4478,6 +4325,7 @@ static void UserObjectPtrToDblinkDialog (
     PointerToDialog (ddp->traceassm, NULL);
     PointerToDialog (ddp->biosample, NULL);
     PointerToDialog (ddp->probedb, NULL);
+    PointerToDialog (ddp->seqreadarch, NULL);
     return;
   }
 
@@ -4539,6 +4387,24 @@ static void UserObjectPtrToDblinkDialog (
           head = ValNodeFreeData (head);
         }
       }
+    } else if (StringICmp (oip->str, "Sequence Read Archive") == 0) {
+      if (curr->choice == 7) {
+        num = curr->num;
+        cpp = (CharPtr PNTR) curr->data.ptrvalue;
+        if (num > 0 && cpp != NULL) {
+          head = NULL;
+          for (i = 0; i < num; i++) {
+            str = cpp [i];
+            if (StringDoesHaveText (str)) {
+              ValNodeCopyStr (&head, 0, str);
+            }
+          }
+          if (head != NULL) {
+            PointerToDialog (ddp->seqreadarch, (Pointer) head);
+          }
+          head = ValNodeFreeData (head);
+        }
+      }
     }
   }
 }
@@ -4647,6 +4513,33 @@ static Pointer DblinkDialogToUserObjectPtr (
   }
   ValNodeFreeData (head);
 
+  head = (ValNodePtr) DialogToPointer (ddp->seqreadarch);
+  if (head != NULL) {
+    num = 0;
+    for (vnp = head; vnp != NULL; vnp = vnp->next) {
+      str = (CharPtr) vnp->data.ptrvalue;
+      if (StringHasNoText (str)) continue;
+      num++;
+    }
+    if (num > 0) {
+      cpp = (CharPtr PNTR) MemNew (sizeof (CharPtr) * num);
+      if (cpp != NULL) {
+        i = 0;
+        for (vnp = head; vnp != NULL; vnp = vnp->next) {
+          str = (CharPtr) vnp->data.ptrvalue;
+          if (StringHasNoText (str)) continue;
+          cpp [i] = str;
+          i++;
+        }
+        if (i > 0) {
+          AddSeqReadArchiveIDsToDBLinkUserObject (uop, i, cpp);
+          okay = TRUE;
+        }
+      }
+    }
+  }
+  ValNodeFreeData (head);
+
   if (! okay) {
     uop = UserObjectFree (uop);
   }
@@ -4684,6 +4577,9 @@ static DialoG CreateDblinkDialog (
   StaticPrompt (x, "ProbeDB", 10 * stdCharWidth, 0, programFont, 'c');
   ddp->probedb = CreateVisibleStringDialog (x, 3, -1, 15);
 
+  StaticPrompt (x, "Sequence Read Archive", 10 * stdCharWidth, 0, programFont, 'c');
+  ddp->seqreadarch = CreateVisibleStringDialog (x, 3, -1, 15);
+
   return (DialoG) p;
 }
 
@@ -5833,12 +5729,56 @@ static Boolean ExportStructuredCommentForm (ForM f, CharPtr filename)
 }
 
 
+static UserObjectPtr StructuredCommentFromTabFile (CharPtr path)
+{
+  FILE *fp;
+  ValNodePtr table, tmp, header, line;
+  UserObjectPtr uop = NULL;
+
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    return NULL;
+  }
+
+  table = ReadTabTableFromFile (fp);
+  FileClose (fp);
+  if (table == NULL || table->next == NULL 
+      || table->data.ptrvalue == NULL
+      || table->next->data.ptrvalue == NULL) {
+    table = FreeTabTable (table);
+    return NULL;
+  }
+  tmp = FlipTabTableAxes (table);
+  table = FreeTabTable (table);
+  table = tmp;
+
+  header = table->data.ptrvalue;
+  if (header == NULL || header->data.ptrvalue == NULL || header->next == NULL) {
+    table = FreeTabTable (table);
+    return NULL;
+  }
+  line = table->next;
+
+  tmp = CreateStructuredCommentsFromRow (header, line->data.ptrvalue, NULL, NULL);
+  table = FreeTabTable (table);
+  if (tmp != NULL) {
+    uop = (UserObjectPtr) tmp->data.ptrvalue;
+    tmp->data.ptrvalue = NULL;
+    for (line = tmp->next; line != NULL; line = line->next) {
+      line->data.ptrvalue = UserObjectFree (line->data.ptrvalue);
+    }
+    tmp = ValNodeFree (tmp);
+  }
+  return uop;
+}
+
+
 static Boolean ImportStructuredCommentForm  (ForM f, CharPtr filename)
 {
   StruCommUserFormPtr  sfp;
   Char            path [PATH_MAX];
-  UserObjectPtr   uop;
-  AsnIoPtr        aip;
+  UserObjectPtr   uop = NULL;
+  AsnIoPtr        aip = NULL;
   Boolean         rval = FALSE;
 
   sfp = (StruCommUserFormPtr) GetObjectExtra (f);
@@ -5859,15 +5799,20 @@ static Boolean ImportStructuredCommentForm  (ForM f, CharPtr filename)
     Message (MSG_ERROR, "Unable to read file %s", path);
   } else {
     uop = UserObjectAsnRead (aip, NULL);
+    AsnIoClose (aip);
+    if (uop == NULL) {
+      /* try reading as though it were a table */
+      uop = StructuredCommentFromTabFile(path);
+    }
     if (uop == NULL) {
       Message (MSG_ERROR, "Unable to read structured comment ASN.1 from file");
-    } else {
+    }
+  }
+  if (uop != NULL) {
       PointerToDialog (sfp->data, uop);
       uop = UserObjectFree (uop);
       rval = TRUE;
     }
-    AsnIoClose (aip);
-  }
   return rval;
 }
 
@@ -6016,10 +5961,10 @@ static ForM CreateStruCommDescForm (Int2 left, Int2 top, Int2 width,
       b = DefaultButton (c, "Accept", StdAcceptFormButtonProc);
       SetObjectExtra (b, sfp, NULL);
     } else {
-      b = DefaultButton (c, "Replace This", StdAcceptFormButtonProc);
-      SetObjectExtra (b, sfp, NULL);
       b = PushButton (c, "Replace All", ReplaceAllStructuredCommentsButtonProc);
       SetObjectExtra (b, sfp, NULL);
+      b = DefaultButton (c, "Replace This", StdAcceptFormButtonProc);
+      SetObjectExtra (b, sfp, NULL);
     }
 
     PushButton (c, "Cancel", StdCancelButtonProc);
@@ -6334,7 +6279,7 @@ static SeqIdPtr SqnSeqIdFindBestAccession (SeqIdPtr sip)
 }
 
 
-static Boolean ValidateTPAHistAlign (BioseqPtr bsp, ValNodePtr PNTR errors)
+NLM_EXTERN Boolean ValidateTPAHistAlign (BioseqPtr bsp, ValNodePtr PNTR errors)
 {
   ValNodePtr new_errors;
   Boolean    retval = TRUE;
@@ -6653,7 +6598,7 @@ static void PrintTPAHistErrors (LogInfoPtr lip, ValNodePtr errors)
 
   for (vnp = errors; vnp != NULL; vnp = vnp->next)
   {
-    fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+    fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
     lip->data_in_log = TRUE;
   }
   fprintf (lip->fp, "\n\n");
@@ -7052,8 +6997,20 @@ static Uint1 SeqAlignSortRowStrand (SeqAlignSortPtr s, Int4 row)
 static Uint1 SeqAlignSortListFindBestStrand (ValNodePtr vnp, Int4 row)
 {
   Int4 num_plus = 0, num_minus = 0, num_align, num = 0;
+  Uint4 plus_len = 0, minus_len = 0;
   SeqAlignSortPtr s;
 
+  if (vnp == NULL) {
+    return Seq_strand_plus;
+  } else if (vnp->next == NULL) {
+    s = (SeqAlignSortPtr) vnp->data.ptrvalue;
+    if (s == NULL) {
+      return Seq_strand_plus;
+    } else {
+      return SeqAlignSortRowStrand(s, row);
+    }
+  }
+
   /* count the alignments */
   num_align = ValNodeLen (vnp);
 
@@ -7065,15 +7022,29 @@ static Uint1 SeqAlignSortListFindBestStrand (ValNodePtr vnp, Int4 row)
     if (s != NULL) {
       if (SeqAlignSortRowStrand(s, row) == Seq_strand_minus) {
         num_minus++;
+        if (row == 1) {
+          minus_len += SeqAlignRowLen (s->row1);
+        } else {
+          minus_len += SeqAlignRowLen (s->row2);
+        }
       } else {
         num_plus++;
+        if (row == 1) {
+          plus_len += SeqAlignRowLen (s->row1);
+        } else {
+          plus_len += SeqAlignRowLen (s->row2);
+        }
       }
     }
     vnp = vnp->next;
     num++;
   }
 
-  if (num_minus > num_plus) {
+  if (num_minus == 0) {
+    return Seq_strand_plus;
+  } else if (num_plus == 0) {
+    return Seq_strand_minus;
+  } else if (minus_len / num_minus > plus_len / num_plus) {
     return Seq_strand_minus;
   } else {
     return Seq_strand_plus;
@@ -7295,6 +7266,10 @@ static ValNodePtr SeqAlignSortListMarkRepeats (ValNodePtr PNTR list, Int4 row, I
           ValNodeAddPointer (&tmp_list, 0, SeqAlignSortCopy (vnp_mark->data.ptrvalue));
           /* mark as repeat for this row */
           vnp_mark->choice = row;
+          s2 = vnp_mark->data.ptrvalue;
+          if (SeqAlignRowLen(s2->row1) == 2300) {
+            vnp_mark->choice = row;
+          }
         }
         ValNodeAddPointer (&repeat_list, 0, tmp_list);
       }
@@ -7312,6 +7287,7 @@ static ValNodePtr SeqAlignSortListMarkRepeats (ValNodePtr PNTR list, Int4 row, I
       ValNodeAddPointer (&tmp_list, 0, SeqAlignSortCopy (vnp_mark->data.ptrvalue));
       /* mark as repeat for this row */
       vnp_mark->choice = row;
+      s2 = vnp_mark->data.ptrvalue;
     }
     ValNodeAddPointer (&repeat_list, 0, tmp_list);
   }
@@ -7463,6 +7439,25 @@ static Boolean FindSeqAlignSortWithPoint (ValNodePtr list, Int4 point, Int4 row)
 }
 
 
+static Int4 LengthOfLongestInterval (ValNodePtr list, Int4 row)
+{
+  Int4 max = 0, len;
+  ValNodePtr vnp;
+  SeqAlignRowPtr r;
+  SeqAlignSortPtr s;
+
+  for (vnp = list; vnp != NULL; vnp = vnp->next) {
+    s = vnp->data.ptrvalue;
+    r = SeqAlignRowFromSeqAlignSort (s, row);
+    len = r->stop - r->start + 1;
+    if (len > max) {
+      max = len;
+    }
+  }
+  return max;  
+}
+
+
 static ValNodePtr FindBestRepeat (ValNodePtr PNTR repeat_list, SeqAlignSortPtr s_before, SeqAlignSortPtr s_after, Int4 row, Int4 fuzz)
 {
   Int4       best_diff = -1, diff;
@@ -7721,6 +7716,58 @@ static int LIBCALLBACK SortVnpByRepeatList (VoidPtr ptr1, VoidPtr ptr2)
 }
 
 
+static void FindCompleteCoverageAlign (ValNodePtr PNTR list, Int4 row)
+{
+  SeqAlignSortPtr s;
+  ValNodePtr      vnp, prev = NULL;
+  Boolean         found = FALSE;
+  SeqIdPtr        sip;
+  BioseqPtr       bsp;
+  Int4            length;
+
+  if (list == NULL || *list == NULL) {
+    return;
+  }
+
+  vnp = *list;
+  s = (SeqAlignSortPtr) vnp->data.ptrvalue;
+  sip = AlnMgr2GetNthSeqIdPtr (s->salp, row);
+  bsp = BioseqLockById (sip);
+  if (bsp == NULL) {
+    return;
+  }
+
+  length = bsp->length;
+  BioseqUnlock(bsp);
+
+  while (vnp != NULL && !found) {
+    s = (SeqAlignSortPtr) vnp->data.ptrvalue;
+    if (s != NULL) {
+      if (row == 1) {
+        if (SeqAlignRowLen (s->row1) == length) {
+          found = TRUE;
+        }
+      } else {
+        if (SeqAlignRowLen (s->row2) == length) {
+          found = TRUE;
+        }
+      }
+    }
+    if (!found) {
+      prev = vnp;
+      vnp = vnp->next;
+    }
+  }
+
+  if (found) {
+    vnp->next = SeqAlignSortListFree (vnp->next);
+    if (prev != NULL) {
+      prev->next = NULL;
+      *list = SeqAlignSortListFree (*list);
+      *list = vnp;
+    }
+  }
+}
 
 
 static void SelectBestRepeatsFromList (SeqAlignPtr PNTR salp)
@@ -7732,6 +7779,7 @@ static void SelectBestRepeatsFromList (SeqAlignPtr PNTR salp)
   Int4           fuzz = 15;
   Int4           missing = 600;
   Int4           len1, len2;
+  Int4           best_len;
 
   if (salp == NULL || *salp == NULL || (*salp)->next == NULL) {
     return;
@@ -7741,11 +7789,16 @@ static void SelectBestRepeatsFromList (SeqAlignPtr PNTR salp)
 
   FindSeqAlignSortWithPoint (list, missing, 1);
 
+  FindCompleteCoverageAlign (&list, 2);
+  FindCompleteCoverageAlign (&list, 1);
+
   /* remove conflicting strands for row 1 */
   strand1 = SeqAlignSortListRemoveConflictingStrands (&list, 1);
+  best_len = LengthOfLongestInterval (list, 1);
 
   /* remove conflicting strands for row 1 */
   strand2 = SeqAlignSortListRemoveConflictingStrands (&list, 2);
+  best_len = LengthOfLongestInterval (list, 1);
 
   FindSeqAlignSortWithPoint (list, missing, 1);
 
@@ -7755,17 +7808,23 @@ static void SelectBestRepeatsFromList (SeqAlignPtr PNTR salp)
     row2_repeats = SeqAlignSortListMarkRepeats (&list, 2, fuzz);
     row2_repeats = ValNodeSort (row2_repeats, SortVnpByRepeatList);
     vnp = ValNodeExtractList (&list, 1);
+    best_len = LengthOfLongestInterval (vnp, 1);
     vnp = SeqAlignSortListFree (vnp);
+    best_len = LengthOfLongestInterval (list, 1);
     vnp = ValNodeExtractList (&list, 2);
+    best_len = LengthOfLongestInterval (vnp, 1);
     vnp = SeqAlignSortListFree (vnp);
+    best_len = LengthOfLongestInterval (list, 1);
 
     FindSeqAlignSortWithPoint (list, missing, 1);
 
     /* remove scaffold intervals that are out of order */
     list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
     SeqAlignSortListRemoveIntervalsOutOfOrder (&list, 1, fuzz);
+    best_len = LengthOfLongestInterval (list, 1);
     list = ValNodeSort (list, SortVnpBySeqAlignSortRow2);
     SeqAlignSortListRemoveIntervalsOutOfOrder (&list, 2, fuzz);
+    best_len = LengthOfLongestInterval (list, 1);
 
     FindSeqAlignSortWithPoint (list, missing, 1);
 
@@ -7819,6 +7878,21 @@ static void SelectBestRepeatsFromList (SeqAlignPtr PNTR salp)
 }
 
 
+NLM_EXTERN void SortTPAAssembly (SeqAlignPtr PNTR salp)
+{
+  ValNodePtr list;
+
+  if (salp == NULL || *salp == NULL || (*salp)->next == NULL) {
+    return;
+  }
+
+  list = SeqAlignSortListNew (*salp);
+  list = ValNodeSort (list, SortVnpBySeqAlignSortRow1);
+  *salp = SeqAlignFromSeqAlignSortList (list);
+  list = SeqAlignSortListFree (list);
+}
+
+
 static void amconssetfree(AMConsSetPtr acp)
 {
    AMConsSetPtr  acp_next;
@@ -7887,6 +7961,9 @@ static void CKA_RemoveInconsistentAlnsFromSet(SeqAlignPtr sap_head, Int4 fuzz)
    SeqIdPtr      sip_head;
    Uint1         strand;
 
+   if (sap_head == NULL) {
+     return;
+   }
    lfuzz = fuzz;
    if (fuzz < 0)
       fuzz = 1;
@@ -8076,11 +8153,11 @@ static BioseqPtr ReadFromTraceDb (CharPtr number)
   SeqEntryPtr  sep = NULL;
   EIO_Status   status;
   STimeout     timeout;
-  long int     val;
+  unsigned long int     val;
 
   if (StringHasNoText (number)) return NULL;
-  if (sscanf (number, "%ld", &val) != 1) return NULL;
-  sprintf (query, "cmd=raw&query=retrieve+fasta+%ld", (long) val);
+  if (sscanf (number, "%lu", &val) != 1) return NULL;
+  sprintf (query, "cmd=raw&query=retrieve+fasta+%lu", (long) val);
   conn = QUERY_OpenUrlQuery ("www.ncbi.nlm.nih.gov", 80, "/Traces/trace.cgi",
                              query, "Sequin", 30, eMIME_T_NcbiData,
                              eMIME_Fasta, eENCOD_None, 0);
@@ -8210,6 +8287,60 @@ static Boolean IsHUPIDAccession (BioseqPtr bsp)
 }
 
 
+static void ExamineAln (SeqAlignPtr sap)
+{
+  Int4 len, num_aln = 0;
+
+  while (sap != NULL) {
+    len = SeqAlignLength (sap);
+    num_aln++;
+    sap = sap->next;
+  }
+
+}
+
+
+static void RemoveShortAlignments (SeqAlignPtr PNTR p_salp, Int4 min_len)
+{
+  SeqAlignPtr this_aln, prev = NULL, next_aln;
+  Int4        len;
+
+  if (p_salp == NULL || (this_aln = *p_salp) == NULL) {
+    return;
+  }
+
+  len = SeqAlignLength (this_aln);
+  if (len < min_len) {
+    /* free after the first */
+    next_aln = this_aln->next;
+    this_aln->next = NULL;
+    this_aln = next_aln;
+    while (this_aln != NULL) {
+      next_aln = this_aln->next;
+      this_aln = SeqAlignFree (this_aln);
+      this_aln = next_aln;
+    }
+  } else {
+    /* free only if shorter than min_len */
+    while (this_aln != NULL) {
+      next_aln = this_aln->next;
+      if ((len = SeqAlignLength (this_aln)) < min_len) {
+        if (prev == NULL) {
+          *p_salp = next_aln;
+        } else {
+          prev->next = next_aln;
+        }
+        this_aln->next = NULL;
+        this_aln = SeqAlignFree (this_aln);
+      } else {
+        prev = this_aln;
+      }
+      this_aln = next_aln;
+    }
+  }
+}
+
+
 static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr lip)
 {
    CKA_AccPtr           acc;
@@ -8261,6 +8392,7 @@ static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr
       } else {
         sip = SeqIdFromAccessionDotVersion(acc->accession);
         bsp_tmp = BioseqLockById(sip);
+        sip = SeqIdFree (sip);
         if (bsp_tmp != NULL) {
           need_to_unlock = TRUE;
           if (lip != NULL && lip->fp != NULL && IsHUPIDAccession (bsp_tmp)) {
@@ -8272,7 +8404,8 @@ static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr
       if (bsp_tmp == NULL) {
         fprintf (lip->fp, "Unable to load %s", acc->accession);
         lip->data_in_log = TRUE;
-        break;
+        acc = acc->next;
+        continue;
       }
       if (bsp_tmp->id->next) {
         /* find the best accession */
@@ -8291,18 +8424,18 @@ static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr
          break;
       }
       WatchCursor();
-      if (acc->start_acc >=0 && acc->stop_acc >=0 &&
-          acc->start_acc < bsp_tmp->length &&
-          acc->start_acc < bsp_tmp->length) {
+      if (acc->start_acc >= 0 && acc->stop_acc >= 0 &&
+          acc->start_acc < bsp->length &&
+          acc->start_acc < bsp->length) {
         SeqLocPtr slp1, slp2;
         if (acc->start_acc <= acc->stop_acc) {
-          slp1 = SeqLocIntNew
-            (acc->start_acc, acc->stop_acc, Seq_strand_plus, bsp_tmp->id);
+          slp2 = SeqLocIntNew
+            (acc->start_acc, acc->stop_acc, Seq_strand_plus, bsp->id);
         } else {
-          slp1 = SeqLocIntNew
-            (acc->stop_acc, acc->start_acc, Seq_strand_minus, bsp_tmp->id);
+          slp2 = SeqLocIntNew
+            (acc->stop_acc, acc->start_acc, Seq_strand_minus, bsp->id);
         }
-        slp2 = SeqLocIntNew(0, bsp->length-1, Seq_strand_plus, bsp->id);
+        slp1 = SeqLocIntNew(0, bsp_tmp->length-1, Seq_strand_plus, bsp_tmp->id);
         acc->sap = NULL;
         seqalign_arr = NULL;
         BLAST_TwoSeqLocSets (options, slp1, slp2, NULL, &seqalign_arr, NULL, NULL, NULL);
@@ -8323,6 +8456,12 @@ static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr
       if (acc->sap != NULL)
          SPI_flip_sa_list(acc->sap);
       acc_new_head = NULL;
+      if (StringStr (acc->accession, "1742833740") != NULL) {
+        acc_new_head = NULL;
+      }
+      if (acc->sap != NULL && acc->sap->next != NULL && CKA_blast_allow_repeats) {
+        RemoveShortAlignments (&(acc->sap), .8 * bsp_tmp->length);
+      }
       if (acc->sap != NULL && acc->sap->next != NULL)
       {
          if (!CKA_blast_allow_repeats) {
@@ -8332,6 +8471,7 @@ static SeqAlignPtr CKA_MakeAlign(BioseqPtr bsp, CKA_AccPtr acc_head, LogInfoPtr
          if (!CKA_blast_allow_repeats) {
            CKA_RemoveInconsistentAlnsFromSet(acc->sap, -1);
          }
+
          sap_tmp = acc->sap;
          acc->sap = (SeqAlignPtr)(acc->sap->segs);
          sap_tmp->segs = NULL;
@@ -9098,8 +9238,12 @@ static void PopulateAssemblyIntervals (ButtoN b)
       AlnMgr2IndexSingleChildSeqAlign (salp); 
       sip = AlnMgr2GetNthSeqIdPtr (salp, 2);
       SeqIdWrite (sip, id_txt, PRINTID_REPORT, sizeof (id_txt) - 1);
-      AlnMgr2GetNthSeqRangeInSA (salp, 2, &primary_start, &primary_stop);
+      AlnMgr2GetNthSeqRangeInSA (salp, 1, &primary_start, &primary_stop);
+      if (AlnMgr2GetNthStrand (salp, 2) == Seq_strand_minus) {
+        AddAccessionToTpaAssemblyUserObject (uop, id_txt, primary_stop, primary_start);
+      } else {
       AddAccessionToTpaAssemblyUserObject (uop, id_txt, primary_start, primary_stop);
+      }
       sip = SeqIdFree (sip);
     }
 
@@ -9108,6 +9252,201 @@ static void PopulateAssemblyIntervals (ButtoN b)
   }
 }
 
+static void ExportTpaAccessionList (ButtoN b)
+{
+  AssemblyUserFormPtr  afp;
+  UserObjectPtr        uop;
+  Char                 path[PATH_MAX];
+  Boolean              first = TRUE;
+  UserFieldPtr         curr, ufp;
+  CharPtr              str;
+  ObjectIdPtr          oip;
+  FILE *fp;
+
+  afp = (AssemblyUserFormPtr) GetObjectExtra (b);
+  if (afp == NULL) {
+    return;
+  }
+
+  uop = (UserObjectPtr) DialogToPointer (afp->data);
+  if (uop == NULL) 
+  {
+    return;
+  }
+
+  path[0] = 0;
+  if (GetOutputFileName (path, sizeof (path), NULL)) {
+#ifdef WIN_MAC
+    fp = FileOpen (path, "r");
+    if (fp != NULL) {
+      FileClose (fp);
+    } else {
+      FileCreate (path, "TEXT", "ttxt");
+    }
+#endif
+    fp = FileOpen (path, "w");
+    if (fp == NULL) {
+      Message (MSG_ERROR, "Unable to open %s", path);
+    } else {
+      for (curr = uop->data; curr != NULL; curr = curr->next) {
+        if (curr->choice != 11) continue;
+        str = NULL;
+        for (ufp = curr->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
+          oip = ufp->label;
+          if (oip == NULL) continue;
+          if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
+            str = (CharPtr) ufp->data.ptrvalue;
+            fprintf (fp, "%s%s", first ? "" : ", ", str);
+            first = FALSE;
+          }
+        }
+      }
+      fprintf (fp, "\n");
+      FileClose (fp);
+    }
+  }
+}
+
+
+static void ExportTpaAccessionTable (ButtoN b)
+{
+  AssemblyUserFormPtr  afp;
+  UserObjectPtr        uop;
+  Char                 path[PATH_MAX];
+  Boolean              first = TRUE;
+  UserFieldPtr         curr, ufp;
+  CharPtr              str;
+  Int4                 from, to;
+  ObjectIdPtr          oip;
+  FILE *fp;
+
+  afp = (AssemblyUserFormPtr) GetObjectExtra (b);
+  if (afp == NULL) {
+    return;
+  }
+
+  uop = (UserObjectPtr) DialogToPointer (afp->data);
+  if (uop == NULL) 
+  {
+    return;
+  }
+
+  path[0] = 0;
+  if (GetOutputFileName (path, sizeof (path), NULL)) {
+#ifdef WIN_MAC
+    fp = FileOpen (path, "r");
+    if (fp != NULL) {
+      FileClose (fp);
+    } else {
+      FileCreate (path, "TEXT", "ttxt");
+    }
+#endif
+    fp = FileOpen (path, "w");
+    if (fp == NULL) {
+      Message (MSG_ERROR, "Unable to open %s", path);
+    } else {
+      str = NULL;
+      from = -1;
+      to = -1;
+      for (curr = uop->data; curr != NULL; curr = curr->next) {
+        if (curr->choice != 11) continue;
+        for (ufp = curr->data.ptrvalue; ufp != NULL; ufp = ufp->next) {
+          oip = ufp->label;
+          if (oip == NULL) continue;
+          if (StringICmp (oip->str, "accession") == 0 && ufp->choice == 1) {
+            if (!first) {
+              fprintf (fp, "%s", str);
+              if (from > -1 && to > -1) {
+                fprintf (fp, "\t%d\t%d", from + 1, to + 1);
+              }
+              fprintf (fp, "\n");
+            }
+            str = (CharPtr) ufp->data.ptrvalue;
+            from = -1;
+            to = -1;
+            first = FALSE;
+          } else if (StringICmp (oip->str, "from") == 0) {
+            from = ufp->data.intvalue;
+          } else if (StringICmp (oip->str, "to") == 0) {
+            to = ufp->data.intvalue;
+          }
+        }
+      }
+      if (str != NULL) {
+        fprintf (fp, "%s", str);
+        if (from > -1 && to > -1) {
+          fprintf (fp, "\t%d\t%d", from + 1, to + 1);
+        }
+        fprintf (fp, "\n");
+      }
+
+      FileClose (fp);
+    }
+  }
+}
+
+
+static void ImportTPATable (ButtoN b)
+{
+  AssemblyUserFormPtr  afp;
+  FILE *fp;
+  UserObjectPtr        uop;
+  Char                 path[PATH_MAX];
+  ReadBufferData rbd;
+  CharPtr        line;
+  ValNodePtr     column_list;
+  UserFieldPtr   last = NULL, row, ufp;
+
+  afp = (AssemblyUserFormPtr) GetObjectExtra (b);
+  if (afp == NULL) {
+    return;
+  }
+
+  path[0] = 0;
+  if (!GetInputFileName (path, sizeof (path), "", "TEXT")) {
+    return;
+  }
+  fp = FileOpen (path, "r");
+  if (fp == NULL) {
+    Message (MSG_ERROR, "Unable to open %s", path);
+    return;
+  }
+
+  uop = CreateTpaAssemblyUserObject  ();
+
+  rbd.fp = fp;
+  rbd.current_data = NULL;
+
+  line = AbstractReadFunction (&rbd);
+  while (line != NULL) 
+  {
+    column_list = ReadOneColumnList(line);
+    if (column_list != NULL) {
+      row = UserFieldNew ();
+      row->choice = 11;  
+      row->label = ObjectIdNew();
+      ufp = CreateTPAAssemblyAccessionField (column_list->data.ptrvalue);
+      row->data.ptrvalue = ufp;
+      if (column_list->next != NULL && column_list->next->next != NULL) {
+        ufp->next = CreateTPAAssemblyFromField (atoi (column_list->next->data.ptrvalue) - 1);
+        ufp->next->next = CreateTPAAssemblyToField (atoi (column_list->next->next->data.ptrvalue) - 1);
+      }
+      column_list = ValNodeFreeData (column_list);
+      if (last == NULL) {
+        uop->data = row;
+      } else {
+        last->next = row;
+      }
+      last = row;
+    }
+    line = AbstractReadFunction (&rbd);
+  }
+  FileClose (rbd.fp);
+  
+  PointerToDialog (afp->data, uop);
+  uop = UserObjectFree (uop);
+}
+
 
 static ForM CreateAssemblyDescForm (Int2 left, Int2 top, Int2 width,
                                    Int2 height, CharPtr title, ValNodePtr sdp,
@@ -9117,7 +9456,7 @@ static ForM CreateAssemblyDescForm (Int2 left, Int2 top, Int2 width,
   AssemblyUserFormPtr  afp;
   ButtoN               b, pop_btn = NULL;
   GrouP                c;
-  GrouP                g;
+  GrouP                g, g2;
   StdEditorProcsPtr    sepp;
   WindoW               w;
   BioseqPtr            bsp;
@@ -9145,19 +9484,26 @@ static ForM CreateAssemblyDescForm (Int2 left, Int2 top, Int2 width,
     g = HiddenGroup (w, -1, 0, NULL);
     afp->data = CreateAssemblyDialog (g);
 
+    g2 = HiddenGroup (g, 2, 0, NULL);
     if (sdp != NULL) {
       bsp = GetSequenceForObject (OBJ_SEQDESC, sdp);
       if (bsp != NULL && bsp->hist != NULL && bsp->hist->assembly != NULL) {
-        pop_btn = PushButton (g, "Populate Intervals from Assembly Alignment", PopulateAssemblyIntervals);
+        pop_btn = PushButton (g2, "Populate Intervals from Assembly Alignment", PopulateAssemblyIntervals);
         SetObjectExtra (pop_btn, afp, NULL);
       }
     }
+    b = PushButton (g2, "Export TPA Accession List", ExportTpaAccessionList);
+    SetObjectExtra (b, afp, NULL);
+    b = PushButton (g2, "Export Interval Table", ExportTpaAccessionTable);
+    SetObjectExtra (b, afp, NULL);
+    b = PushButton (g2, "Import Interval Table", ImportTPATable);
+    SetObjectExtra (b, afp, NULL);
 
     c = HiddenGroup (w, 2, 0, NULL);
     b = DefaultButton (c, "Accept", TPAAssemblyFormAccept);
     SetObjectExtra (b, afp, NULL);
     PushButton (c, "Cancel", StdCancelButtonProc);
-    AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) pop_btn, NULL);
+    AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) g2, NULL);
     RealizeWindow (w);
   }
   return (ForM) w;
@@ -12301,7 +12647,7 @@ static void AcceptTSAAssembly (ButtoN b)
     lip = OpenLog ("TSA Table Problems");
     if (err_list != NULL) {
       for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
-        fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
+        fprintf (lip->fp, "%s\n", (CharPtr) vnp->data.ptrvalue);
       }
       lip->data_in_log = TRUE;
       err_list = ValNodeFreeData (err_list);
@@ -13308,7 +13654,7 @@ FindAndConvertGapFeat
   ValNodePtr vnp;
   SeqLocPtr  slp;
   SeqLitPtr  litp;
-  Int4       currpos = 0, len_diff;
+  Int4       currpos = 0, len_diff = 0;
   
   if (bsp == NULL || bsp->repr != Seq_repr_delta
       || start < 0)
@@ -14324,6 +14670,7 @@ extern void CopyLocusToLocusTag (IteM i)
 
 /* data structure and functions for a generic form displaying a clickable list */
 typedef  void  (*Nlm_AddClickableListEntityIDProc) PROTO ((ButtoN, Uint2));
+typedef  void  (*Nlm_ReorderResultsProc) PROTO ((ValNodePtr PNTR));
 
 #define CLICKABLE_LIST_FORM_BLOCK   \
   FORM_MESSAGE_BLOCK                \
@@ -14332,6 +14679,7 @@ typedef  void  (*Nlm_AddClickableListEntityIDProc) PROTO ((ButtoN, Uint2));
   ButtoN          recheck_btn;         \
   CharPtr         log_name;            \
   Nlm_AddClickableListEntityIDProc add_entity_proc;        \
+  Nlm_ReorderResultsProc reorder_results_proc;
   
 typedef struct clickablelistform {
   CLICKABLE_LIST_FORM_BLOCK
@@ -14443,6 +14791,7 @@ static void ClickableListFormMessage (ForM f, Int2 mssg)
 /* There will only be one Discrepancy Report window at a time */
 static WindoW discrepancyReportWindow = NULL;
 static WindoW oncallerReportWindow = NULL;
+static WindoW megaReportWindow = NULL;
 
 static WindoW GetWindowForReportType (EDiscrepancyReportType report_type)
 {
@@ -14455,6 +14804,9 @@ static WindoW GetWindowForReportType (EDiscrepancyReportType report_type)
     case eReportTypeOnCaller:
       w = oncallerReportWindow;
       break;
+    case eReportTypeMegaReport:
+      w = megaReportWindow;
+      break;
   }
   return w;
 }
@@ -14468,6 +14820,9 @@ static void ClearWindowForReportType (WindoW w)
   if (oncallerReportWindow == w) {
     oncallerReportWindow = NULL;
   }
+  if (megaReportWindow == w) {
+    megaReportWindow = NULL;
+  }
 }
 
 
@@ -14480,7 +14835,29 @@ static void SetWindowForReportType (WindoW w, EDiscrepancyReportType report_type
     case eReportTypeOnCaller:
       oncallerReportWindow = w;
       break;
+    case eReportTypeMegaReport:
+      megaReportWindow = w;
+      break;
+  }
+}
+
+
+static CharPtr GetReportConfigName (EDiscrepancyReportType report_type)
+{
+  CharPtr report_name = "";
+
+  switch (report_type) {
+    case eReportTypeDiscrepancy:
+      report_name = "DISCREPANCY_REPORT";
+      break;
+    case eReportTypeOnCaller:
+      report_name = "ON_CALLER_TOOL";
+      break;
+    case eReportTypeMegaReport:
+      report_name = "MEGA_REPORT";
+      break;
   }
+  return report_name;
 }
 
 
@@ -14495,6 +14872,7 @@ typedef struct discrepancyreportform
   CLICKABLE_LIST_FORM_BLOCK
 
   DiscrepancyConfigPtr dcp;
+  Int4 report_type;
 } DiscrepancyReportFormData, PNTR DiscrepancyReportFormPtr;
 
 static void CleanupDiscrepancyReportForm (GraphiC g, VoidPtr data)
@@ -14509,13 +14887,20 @@ static void CleanupDiscrepancyReportForm (GraphiC g, VoidPtr data)
     /* find whether source qual report is open or closed */
     for (vnp = drfp->clickable_list_data; vnp != NULL; vnp = vnp->next) {
       cip = vnp->data.ptrvalue;
-      if (cip != NULL && cip->clickable_item_type == DISC_SRC_QUAL_PROBLEM) {
+      if (cip != NULL) {
+        if (cip->clickable_item_type == DISC_SRC_QUAL_PROBLEM) {
         if (cip->expanded) {
           SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_SRCQUAL_REPORT", "TRUE");
         } else {
           SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_SRCQUAL_REPORT", "FALSE");
         }
-        break;
+        } else if (cip->clickable_item_type == ONCALLER_DEFLINE_ON_SET) {
+          if (cip->expanded) {
+            SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_DEFLINE_ON_SET", "TRUE");
+          } else {
+            SetAppParam ("SEQUINCUSTOM", "ONCALLERTOOL", "EXPAND_DEFLINE_ON_SET", "FALSE");
+          }
+        }
       }
     }
     drfp->clickable_list_data = FreeClickableList (drfp->clickable_list_data);
@@ -14559,6 +14944,31 @@ static void SelectDiscrepancyList(ButtoN b)
 }
 
 
+typedef struct discrepancyconfigpage {
+  GrouP PNTR            grp_list;
+  Int4                  num_pages;
+} DiscrepancyConfigPageData, PNTR DiscrepancyConfigPagePtr;
+
+static void ChangeDiscrepancyConfigPage (VoidPtr data, Int2 newval, Int2 oldval)
+
+{
+  DiscrepancyConfigPagePtr cfg_page;
+
+  cfg_page = (DiscrepancyConfigPagePtr) data;
+  if (cfg_page == NULL || cfg_page->grp_list == NULL) {
+    return;
+  }
+
+  if (oldval > -1 && oldval < cfg_page->num_pages) {
+    Hide (cfg_page->grp_list[oldval]);
+  }
+  if (newval > -1 && newval < cfg_page->num_pages) {
+    Show (cfg_page->grp_list[newval]);
+  }
+
+}
+
+
 /* This function returns TRUE if there was a change to the discrepancy config,
  * FALSE otherwise.
  */
@@ -14571,6 +14981,15 @@ static Boolean EditDiscrepancyConfig (DiscrepancyConfigPtr dcp, EDiscrepancyRepo
   Int4                  i;
   ButtoN                test_options[MAX_DISC_TYPE];
   Boolean               rval = FALSE;
+  DialoG                tbs = NULL;
+  CharPtr PNTR          page_name_list = NULL;
+  Char                  page_name[50];
+  DiscrepancyConfigPageData cfg_page;
+  Int4                  num_rows = 25;
+  Int4                  num_columns = 3;
+  Int4                  num_per_page = num_rows * num_columns;
+  Int4                  num_appropriate = 0;
+  Int4                  num_on_page = 0, page_num = 0;
   
   if (dcp == NULL)
   {
@@ -14584,33 +15003,81 @@ static Boolean EditDiscrepancyConfig (DiscrepancyConfigPtr dcp, EDiscrepancyRepo
   h = HiddenGroup (w, -1, 0, NULL);
   SetGroupSpacing (h, 10, 10);
   
-  g = NormalGroup (h, 0, 14, "Discrepancy Tests to Run", programFont, NULL);
+  for (i = 0; i < MAX_DISC_TYPE; i++)
+  {
+    if (IsTestTypeAppropriateForReportType (i, report_type) && i != DISC_CATEGORY_HEADER) {
+      num_appropriate ++;
+    }
+  }
+
+  if (num_appropriate > num_per_page) {
+    /* set up page headers */
+    cfg_page.num_pages = num_appropriate / num_per_page;
+    if (num_appropriate % num_per_page > 0) {
+      cfg_page.num_pages ++;
+    }
+    page_name_list = (CharPtr PNTR) MemNew (sizeof (CharPtr) * (cfg_page.num_pages + 1));
+    for (i = 0; i < cfg_page.num_pages; i++) {
+      sprintf (page_name, "Page %d", i + 1);
+      page_name_list[i] = StringSave (page_name);
+    }
+    page_name_list[i] = NULL;
+    tbs = CreateFolderTabs (h, page_name_list, 0,
+                                    0, 0, SYSTEM_FOLDER_TAB,
+                                    ChangeDiscrepancyConfigPage, &cfg_page);
+
+    g = NormalGroup (h, 0, 0, "Discrepancy Tests to Run", programFont, NULL);
+    cfg_page.grp_list = (GrouP PNTR) MemNew (sizeof (GrouP) * cfg_page.num_pages );
+    cfg_page.grp_list[page_num] = HiddenGroup (g, 0, num_rows, NULL);
+    SetGroupSpacing (cfg_page.grp_list[page_num], 10, 10);
+    for (i = 0; i < MAX_DISC_TYPE; i++)
+    {
+      if (IsTestTypeAppropriateForReportType (i, report_type) && i != DISC_CATEGORY_HEADER) {
+        if (num_on_page == num_per_page) {
+          page_num++;
+          cfg_page.grp_list[page_num] = HiddenGroup (g, 0, num_rows, NULL);
+          SetGroupSpacing (cfg_page.grp_list[page_num], 10, 10);
+        }
+        test_options[i] = CheckBox (cfg_page.grp_list[page_num], GetDiscrepancyTestConfName ((DiscrepancyType) i), NULL);
+        SetStatus (test_options[i], dcp->conf_list[i]);
+        num_on_page++;
+      } else {
+        test_options[i] = NULL;
+      }
+    }
+    for (i = 1; i < cfg_page.num_pages; i++) {
+      Hide (cfg_page.grp_list[i]);
+    }    
+  } else {
+    g = NormalGroup (h, 0, num_rows, "Discrepancy Tests to Run", programFont, NULL);
   SetGroupSpacing (g, 10, 10);
+
   for (i = 0; i < MAX_DISC_TYPE; i++)
   {
-    if (IsTestTypeAppropriateForReportType (i, report_type)) {
+      if (IsTestTypeAppropriateForReportType (i, report_type) && i != DISC_CATEGORY_HEADER) {
       test_options[i] = CheckBox (g, GetDiscrepancyTestConfName ((DiscrepancyType) i), NULL);
       SetStatus (test_options[i], dcp->conf_list[i]);
     } else {
       test_options[i] = NULL;
     }
   }
+  }
   
-  use_feature_table_format_btn = CheckBox (h, "Use feature table format for features in report", NULL);
-  SetStatus (use_feature_table_format_btn, dcp->use_feature_table_format);
-  
-  k = HiddenGroup (h, 2, 0, NULL);
+  k = HiddenGroup (h, 3, 0, NULL);
   b = PushButton (k, "Select All", SelectDiscrepancyList);
   SetObjectExtra (b, test_options, NULL);
   b = PushButton (k, "Unselect All", UnselectDiscrepancyList);
   SetObjectExtra (b, test_options, NULL);  
+  use_feature_table_format_btn = CheckBox (k, "Use feature table format for features in report", NULL);
+  SetStatus (use_feature_table_format_btn, dcp->use_feature_table_format);
+  
   
   c = HiddenGroup (h, 3, 0, NULL);
   b = PushButton (c, "Accept", ModalAcceptButton);
   SetObjectExtra (b, &acd, NULL);
   b = PushButton (c, "Cancel", ModalCancelButton);
   SetObjectExtra (b, &acd, NULL);
-  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) use_feature_table_format_btn, (HANDLE) k, (HANDLE) c, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) k, (HANDLE) c, (HANDLE) tbs, NULL);
   
   Show(w); 
   Select (w);
@@ -14628,7 +15095,7 @@ static Boolean EditDiscrepancyConfig (DiscrepancyConfigPtr dcp, EDiscrepancyRepo
     }
     dcp->use_feature_table_format = GetStatus (use_feature_table_format_btn);
     rval = TRUE;
-    SaveDiscrepancyConfig (dcp);
+    SaveDiscrepancyConfigEx (dcp, GetReportConfigName (report_type));
   }
 
   Remove (w);
@@ -14877,7 +15344,7 @@ static void ExtendPartialsToEndOrGapCallback (ValNodePtr list, Pointer userdata)
   Update();
   lip = OpenLog ("Extended Features");
 
-  FixBacterialExtendablePartials (list, userdata, lip);
+  FixExtendablePartials (list, userdata, lip);
 
   sep_list = GetViewedSeqEntryList ();
   for (vnp = sep_list; vnp != NULL; vnp = vnp->next) {
@@ -14952,6 +15419,114 @@ static void MarkOverlappingCDSCallback (ValNodePtr list, Pointer userdata)
 }
 
 
+static void FixNonWGSSetsCallback (ValNodePtr list, Pointer userdata)
+{
+  LogInfoPtr lip;
+
+  if (Message (MSG_OKC, "Change non-WGS sets to GenBank?") == ANS_CANCEL) {
+    return;
+  }
+  WatchCursor();
+  Update();
+  lip = OpenLog ("Changed Sets");
+  FixNonWGSSets (list, userdata, lip);
+
+  ArrowCursor();
+  Update();
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
+static void FixMismatchedCommentsCallback (ValNodePtr list, Pointer userdata)
+{
+  LogInfoPtr lip;
+  SeqDescrPtr sdp;
+
+  if (list == NULL || (sdp = (list->data.ptrvalue)) == NULL) {
+    return;
+  }
+  if (Message (MSG_OKC, "Make comments match %s?", sdp->data.ptrvalue) == ANS_CANCEL) {
+    return;
+  }
+  WatchCursor();
+  Update();
+  lip = OpenLog ("Changed Comments");
+  FixMismatchedComments (list, userdata, lip);
+
+  ArrowCursor();
+  Update();
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
+static void FixHumanHostsCallback (ValNodePtr list, Pointer userdata)
+{
+  LogInfoPtr lip;
+
+  if (list == NULL) {
+    return;
+  }
+  if (Message (MSG_OKC, "Change 'human' host to 'Homo sapiens'") == ANS_CANCEL) {
+    return;
+  }
+  WatchCursor();
+  Update();
+  lip = OpenLog ("Changed Hosts");
+  FixHumanHosts (list, userdata, lip);
+
+  ArrowCursor();
+  Update();
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
+static void FixOrderedLocationsCallback (ValNodePtr list, Pointer userdata)
+{
+  LogInfoPtr lip;
+
+  if (list == NULL) {
+    return;
+  }
+  if (Message (MSG_OKC, "Change ordered locations to join?") == ANS_CANCEL) {
+    return;
+  }
+  WatchCursor();
+  Update();
+  lip = OpenLog ("Changed Locations");
+  FixOrderedLocations (list, userdata, lip);
+
+  ArrowCursor();
+  Update();
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
+static void FixPseudoDiscrepanciesCallback (ValNodePtr list, Pointer userdata)
+{
+  LogInfoPtr lip;
+
+  if (list == NULL) {
+    return;
+  }
+  if (Message (MSG_OKC, "Make overlapping genes and mRNAs pseudo?") == ANS_CANCEL) {
+    return;
+  }
+  WatchCursor();
+  Update();
+  lip = OpenLog ("Set Pseudo");
+  OncallerToolPseudoDiscrepanciesFix (list, userdata, lip);
+
+  ArrowCursor();
+  Update();
+  CloseLog (lip);
+  lip = FreeLog (lip);
+}
+
+
 extern void SetBioseqViewTargetByBioseq (BaseFormPtr bfp, BioseqPtr bsp)
 {
   Char       id_text [41];
@@ -15152,12 +15727,22 @@ static void AddBulkEditing (ValNodePtr clickable_list)
         cip->callback_func = EditCDStRNAOverlapCallback;    
       } else if (cip->clickable_item_type == DISC_INCONSISTENT_BIOSRC_DEFLINE) {
         cip->callback_func = ApplyTagToCodingRegionsCallback; 
-      } else if (cip->clickable_item_type == DISC_BACTERIAL_PARTIAL_PROBLEMS) {
+      } else if (cip->clickable_item_type == DISC_PARTIAL_PROBLEMS) {
         cip->callback_func = ExtendPartialsToEndOrGapCallback;
       } else if (cip->clickable_item_type == DISC_BACTERIAL_PARTIAL_NONEXTENDABLE_PROBLEMS) {
         cip->callback_func = AddNonExtendableExceptionsCallback;
       } else if (cip->clickable_item_type == DISC_OVERLAPPING_CDS) {
         cip->callback_func = MarkOverlappingCDSCallback;
+      } else if (cip->clickable_item_type == DISC_NONWGS_SETS_PRESENT) {
+        cip->callback_func = FixNonWGSSetsCallback;
+      } else if (cip->clickable_item_type == DISC_MISMATCHED_COMMENTS) {
+        cip->callback_func = FixMismatchedCommentsCallback;
+      } else if (cip->clickable_item_type == DISC_HUMAN_HOST) {
+        cip->callback_func = FixHumanHostsCallback;
+      } else if (cip->clickable_item_type == ONCALLER_ORDERED_LOCATION) {
+        cip->callback_func = FixOrderedLocationsCallback;
+      } else if (cip->clickable_item_type == DISC_PSEUDO_MISMATCH) {
+        cip->callback_func = FixPseudoDiscrepanciesCallback;
       } else {
         subtype = GetSubtypeForBulkEdit (cip->item_list);
         /* Note - using FEATDEF_rRNA to represent all editable RNA features */
@@ -15171,6 +15756,279 @@ static void AddBulkEditing (ValNodePtr clickable_list)
   }
 }
 
+
+static Uint4 sOnCallerToolPriorities[] = {
+DISC_COUNT_NUCLEOTIDES,
+DISC_DUP_DEFLINE,
+DISC_MISSING_DEFLINES,
+TEST_HAS_PROJECT_ID,
+ONCALLER_DEFLINE_ON_SET,
+DISC_SRC_QUAL_PROBLEM,
+DISC_FEATURE_COUNT,
+DISC_FEATURE_MOLTYPE_MISMATCH,
+DISC_INCONSISTENT_MOLTYPES,
+DISC_CHECK_AUTH_CAPS,
+ONCALLER_CONSORTIUM,
+DISC_UNPUB_PUB_WITHOUT_TITLE,
+DISC_TITLE_AUTHOR_CONFLICT,
+DISC_SUBMITBLOCK_CONFLICT,
+DISC_CITSUBAFFIL_CONFLICT,
+DISC_MISSING_AFFIL,
+DISC_USA_STATE,
+DISC_DUP_SRC_QUAL,
+DISC_MISSING_SRC_QUAL,
+DISC_DUP_SRC_QUAL_DATA,
+DISC_MISSING_VIRAL_QUALS,
+DISC_INFLUENZA_DATE_MISMATCH,
+DISC_HUMAN_HOST,
+DISC_SPECVOUCHER_TAXNAME_MISMATCH,
+DISC_STRAIN_TAXNAME_MISMATCH,
+DISC_BACTERIA_SHOULD_NOT_HAVE_ISOLATE,
+DISC_BACTERIA_MISSING_STRAIN,
+DISC_REQUIRED_CLONE,
+ONCALLER_MULTISRC,
+DUP_DISC_ATCC_CULTURE_CONFLICT,
+ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH,
+ONCALLER_MULTIPLE_CULTURE_COLLECTION,
+DISC_TRINOMIAL_SHOULD_HAVE_QUALIFIER,
+ONCALLER_CHECK_AUTHORITY,
+DISC_MAP_CHROMOSOME_CONFLICT,
+DISC_METAGENOMIC,
+DISC_METAGENOME_SOURCE,
+DISC_RETROVIRIDAE_DNA,
+DISC_MITOCHONDRION_REQUIRED,
+ONCALLER_SUPERFLUOUS_GENE,
+ONCALLER_GENE_MISSING,
+DISC_GENE_PARTIAL_CONFLICT,
+DISC_BAD_GENE_STRAND,
+DISC_NON_GENE_LOCUS_TAG,
+DISC_RBS_WITHOUT_GENE,
+ONCALLER_ORDERED_LOCATION,
+DISC_CDS_WITHOUT_MRNA,
+DISC_mRNA_ON_WRONG_SEQUENCE_TYPE,
+DISC_BACTERIA_SHOULD_NOT_HAVE_MRNA,
+TEST_EXON_ON_MRNA,
+DISC_CDS_HAS_NEW_EXCEPTION,
+DISC_SHORT_INTRON,
+DISC_EXON_INTRON_CONFLICT,
+DISC_PSEUDO_MISMATCH,
+DISC_RNA_NO_PRODUCT,
+DISC_BADLEN_TRNA,
+DISC_MICROSATELLITE_REPEAT_TYPE,
+DISC_POSSIBLE_LINKER,
+DISC_HAPLOTYPE_MISMATCH,
+DISC_FLATFILE_FIND_ONCALLER,
+DISC_CDS_PRODUCT_FIND,
+DISC_SUSPICIOUS_NOTE_TEXT,
+DISC_CHECK_RNA_PRODUCTS_AND_COMMENTS,
+DISC_INTERNAL_TRANSCRIBED_SPACER_RRNA,
+ONCALLER_COMMENT_PRESENT
+};
+
+static const Uint4 kNumOnCallerToolPriority = sizeof (sOnCallerToolPriorities) / sizeof (Uint4);
+
+static Uint4 GetOnCallerToolPriority (Uint4 clickable_item_type)
+{
+  Uint4 priority = kNumOnCallerToolPriority + clickable_item_type;
+  Uint4 i;
+
+  for (i = 0; i < kNumOnCallerToolPriority; i++) {
+    if (sOnCallerToolPriorities[i] == clickable_item_type) {
+      priority = i;
+      break;
+    }
+  }
+  return priority;
+}
+
+
+static int LIBCALLBACK SortVnpByOnCallerToolPriority (VoidPtr ptr1, VoidPtr ptr2)
+
+{
+  ValNodePtr  vnp1;
+  ValNodePtr  vnp2;
+  ClickableItemPtr cip1, cip2;
+  Uint4            priority1, priority2;
+  int rval = 0;
+
+  if (ptr1 == NULL || ptr2 == NULL) return 0;
+  vnp1 = *((ValNodePtr PNTR) ptr1);
+  vnp2 = *((ValNodePtr PNTR) ptr2);
+  if (vnp1 == NULL || vnp2 == NULL) return 0;
+  if (vnp1->data.ptrvalue == NULL || vnp2->data.ptrvalue == NULL) return 0;
+  
+  cip1 = vnp1->data.ptrvalue;
+  cip2 = vnp2->data.ptrvalue;
+
+  priority1 = GetOnCallerToolPriority (cip1->clickable_item_type);
+  priority2 = GetOnCallerToolPriority (cip2->clickable_item_type);
+
+  if (priority1 < priority2) {
+    rval = -1;
+  } else if (priority1 == priority2) {
+    rval = 0;
+  } else {
+    rval = 1;
+  }
+
+  return rval;
+}
+
+
+static ClickableItemPtr CreateTopLevelCategory (ValNodePtr orig, CharPtr cat_name)
+{
+  ClickableItemPtr cip, cat_cip = NULL;
+
+  if (orig == NULL || (cip = (ClickableItemPtr)orig->data.ptrvalue) == NULL) {
+    return NULL;
+  }
+
+  cat_cip = (ClickableItemPtr) MemNew (sizeof (ClickableItemData));
+  MemSet (cat_cip, 0, sizeof (ClickableItemData));
+  cat_cip->clickable_item_type = DISC_CATEGORY_HEADER;
+  cat_cip->description = StringSave (cat_name);
+  cat_cip->expanded = TRUE;
+  ValNodeAddPointer (&(cat_cip->subcategories), 0, cip);
+  orig->data.ptrvalue = cat_cip;
+
+  return cat_cip;  
+}
+
+
+static void ReorderOnCallerResults (ValNodePtr PNTR p_clickable_list)
+{
+  ClickableItemPtr cip_mol_type = NULL, cip_cit_sub = NULL, cip_src = NULL;
+  ClickableItemPtr cip_feat = NULL, cip_suspect_text = NULL;
+  ValNodePtr vnp, v_prev = NULL, v_next;
+  ClickableItemPtr cip;
+
+  if (p_clickable_list == NULL || *p_clickable_list == NULL) {
+    return;
+  }
+
+  /* first, sort */
+  *p_clickable_list = ValNodeSort (*p_clickable_list, SortVnpByOnCallerToolPriority);
+
+  /* now accumulate results into groups */
+  for (vnp = *p_clickable_list; vnp != NULL; vnp = v_next) {
+    v_next = vnp->next;
+    cip = (vnp->data.ptrvalue);
+    switch (cip->clickable_item_type) {
+      case DISC_FEATURE_MOLTYPE_MISMATCH:
+      case DISC_INCONSISTENT_MOLTYPES:
+        if (cip_mol_type == NULL) {
+          cip_mol_type = CreateTopLevelCategory (vnp, "Molecule type tests");
+          v_prev = vnp;
+        } else {
+          ValNodeAddPointer (&(cip_mol_type->subcategories), 0, cip);
+          v_prev->next = vnp->next;
+          vnp->next = NULL;
+          vnp = ValNodeFree (vnp);
+        }
+        break;
+      case DISC_CHECK_AUTH_CAPS:
+      case ONCALLER_CONSORTIUM:
+      case DISC_UNPUB_PUB_WITHOUT_TITLE:
+      case DISC_TITLE_AUTHOR_CONFLICT:
+      case DISC_SUBMITBLOCK_CONFLICT:
+      case DISC_CITSUBAFFIL_CONFLICT:
+      case DISC_MISSING_AFFIL:
+      case DISC_USA_STATE:
+        if (cip_cit_sub == NULL) {
+          cip_cit_sub = CreateTopLevelCategory (vnp, "Cit-sub type tests");
+          v_prev = vnp;
+        } else {
+          ValNodeAddPointer (&(cip_cit_sub->subcategories), 0, cip);
+          v_prev->next = vnp->next;
+          vnp->next = NULL;
+          vnp = ValNodeFree (vnp);
+        }
+        break;
+      case DISC_DUP_SRC_QUAL:
+      case DISC_MISSING_SRC_QUAL:
+      case DISC_DUP_SRC_QUAL_DATA:
+      case DISC_MISSING_VIRAL_QUALS:
+      case DISC_INFLUENZA_DATE_MISMATCH:
+      case DISC_HUMAN_HOST:
+      case DISC_SPECVOUCHER_TAXNAME_MISMATCH:
+      case DISC_STRAIN_TAXNAME_MISMATCH:
+      case DISC_BACTERIA_SHOULD_NOT_HAVE_ISOLATE:
+      case DISC_BACTERIA_MISSING_STRAIN:
+      case DISC_REQUIRED_CLONE:
+      case ONCALLER_MULTISRC:
+      case DUP_DISC_ATCC_CULTURE_CONFLICT:
+      case ONCALLER_STRAIN_CULTURE_COLLECTION_MISMATCH:
+      case ONCALLER_MULTIPLE_CULTURE_COLLECTION:
+      case DISC_TRINOMIAL_SHOULD_HAVE_QUALIFIER:
+      case ONCALLER_CHECK_AUTHORITY:
+      case DISC_MAP_CHROMOSOME_CONFLICT:
+      case DISC_METAGENOMIC:
+      case DISC_METAGENOME_SOURCE:
+      case DISC_RETROVIRIDAE_DNA:
+      case DISC_MITOCHONDRION_REQUIRED:
+        if (cip_src == NULL) {
+          cip_src = CreateTopLevelCategory (vnp, "Source tests");
+          v_prev = vnp;
+        } else {
+          ValNodeAddPointer (&(cip_src->subcategories), 0, cip);
+          v_prev->next = vnp->next;
+          vnp->next = NULL;
+          vnp = ValNodeFree (vnp);
+        }
+        break;
+      case ONCALLER_SUPERFLUOUS_GENE:
+      case ONCALLER_GENE_MISSING:
+      case DISC_GENE_PARTIAL_CONFLICT:
+      case DISC_BAD_GENE_STRAND:
+      case DISC_NON_GENE_LOCUS_TAG:
+      case DISC_RBS_WITHOUT_GENE:
+      case ONCALLER_ORDERED_LOCATION:
+      case DISC_CDS_WITHOUT_MRNA:
+      case DISC_mRNA_ON_WRONG_SEQUENCE_TYPE:
+      case DISC_BACTERIA_SHOULD_NOT_HAVE_MRNA:
+      case TEST_EXON_ON_MRNA:
+      case DISC_CDS_HAS_NEW_EXCEPTION:
+      case DISC_SHORT_INTRON:
+      case DISC_EXON_INTRON_CONFLICT:
+      case DISC_PSEUDO_MISMATCH:
+      case DISC_RNA_NO_PRODUCT:
+      case DISC_BADLEN_TRNA:
+      case DISC_MICROSATELLITE_REPEAT_TYPE:
+        if (cip_feat == NULL) {
+          cip_feat = CreateTopLevelCategory (vnp, "Feature tests");
+          v_prev = vnp;
+        } else {
+          ValNodeAddPointer (&(cip_feat->subcategories), 0, cip);
+          v_prev->next = vnp->next;
+          vnp->next = NULL;
+          vnp = ValNodeFree (vnp);
+        }
+        break;
+      case DISC_FLATFILE_FIND_ONCALLER:
+      case DISC_CDS_PRODUCT_FIND:
+      case DISC_SUSPICIOUS_NOTE_TEXT:
+      case DISC_CHECK_RNA_PRODUCTS_AND_COMMENTS:
+      case DISC_INTERNAL_TRANSCRIBED_SPACER_RRNA:
+      case ONCALLER_COMMENT_PRESENT:
+        if (cip_suspect_text == NULL) {
+          cip_suspect_text = CreateTopLevelCategory (vnp, "Suspect text tests");
+          v_prev = vnp;
+        } else {
+          ValNodeAddPointer (&(cip_suspect_text->subcategories), 0, cip);
+          v_prev->next = vnp->next;
+          vnp->next = NULL;
+          vnp = ValNodeFree (vnp);
+        }
+        break;
+      default:
+        v_prev = vnp;
+        break;
+    }
+  }
+  SetDiscrepancyLevels (*p_clickable_list, 0);
+}
+
+
 static void RecheckDiscrepancyProc (ButtoN b)
 {
   DiscrepancyReportFormPtr drfp;
@@ -15193,6 +16051,11 @@ static void RecheckDiscrepancyProc (ButtoN b)
 
     drfp->clickable_list_data = CollectDiscrepancies (drfp->dcp, sep_list, CheckTaxNamesAgainstTaxDatabase);
 
+    /* reorder as necessary */
+    if (drfp->reorder_results_proc != NULL) {
+      (drfp->reorder_results_proc) (&(drfp->clickable_list_data));
+    }
+
     /* add bulk editing where appropriate */
     AddBulkEditing (drfp->clickable_list_data);
     
@@ -15235,6 +16098,11 @@ static void AddNewEntityDiscrepancyProc (ButtoN b, Uint2 new_entityID )
     drfp->clickable_list_data = CollectDiscrepancies (drfp->dcp, sep_list, CheckTaxNamesAgainstTaxDatabase);
     sep_list = ValNodeFree (sep_list);
 
+    /* reorder as necessary */
+    if (drfp->reorder_results_proc != NULL) {
+      (drfp->reorder_results_proc) (&(drfp->clickable_list_data));
+    }
+
     /* add bulk editing where appropriate */
     AddBulkEditing (drfp->clickable_list_data);
     
@@ -15414,6 +16282,12 @@ static void EditOnCallerConfigBtn (ButtoN b)
 }
 
 
+static void EditMegaReportConfigBtn (ButtoN b)
+{
+  EditReportConfigBtn (eReportTypeMegaReport);
+}
+
+
 static Nlm_BtnActnProc GetReportEditButtonProc (EDiscrepancyReportType report_type)
 {
   Nlm_BtnActnProc proc = NULL;
@@ -15425,6 +16299,9 @@ static Nlm_BtnActnProc GetReportEditButtonProc (EDiscrepancyReportType report_ty
     case eReportTypeOnCaller:
       proc = EditOnCallerConfigBtn;
       break;
+    case eReportTypeMegaReport:
+      proc = EditMegaReportConfigBtn;
+      break;
   }
   return proc;
 }
@@ -15446,21 +16323,8 @@ static CharPtr GetReportName (EDiscrepancyReportType report_type)
     case eReportTypeOnCaller:
       report_name = "On Caller Tool";
       break;
-  }
-  return report_name;
-}
-
-
-static CharPtr GetReportConfigName (EDiscrepancyReportType report_type)
-{
-  CharPtr report_name = "";
-
-  switch (report_type) {
-    case eReportTypeDiscrepancy:
-      report_name = "DISCREPANCY_REPORT";
-      break;
-    case eReportTypeOnCaller:
-      report_name = "ON_CALLER_TOOL";
+    case eReportTypeMegaReport:
+      report_name = "Mega Report";
       break;
   }
   return report_name;
@@ -15513,6 +16377,20 @@ static void ContractAllDiscReportItems (ButtoN b)
 }
 
 
+static void UnmarkAllBtn (ButtoN b)
+{
+  DiscrepancyReportFormPtr d;
+
+  d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
+  if (d == NULL) {
+    return;
+  }
+  ChooseCategories (d->clickable_list_data, FALSE);
+
+  PointerToDialog (d->clickable_list_dlg, d->clickable_list_data);
+}
+
+
 static void FixMarkedDiscrepanciesBtn (ButtoN b)
 {
   DiscrepancyReportFormPtr d;
@@ -15543,6 +16421,11 @@ static void FixMarkedDiscrepanciesBtn (ButtoN b)
   d->clickable_list_data = CollectDiscrepancies (d->dcp, sep_list, CheckTaxNamesAgainstTaxDatabase);
   sep_list = ValNodeFree (sep_list);
 
+  /* reorder as necessary */
+  if (d->reorder_results_proc != NULL) {
+    (d->reorder_results_proc) (&(d->clickable_list_data));
+  }
+
   /* add bulk editing where appropriate */
   AddBulkEditing (d->clickable_list_data);
   
@@ -15567,6 +16450,52 @@ static void MarkFixableDiscrepancies (ButtoN b)
 }
 
 
+/* Sequester by test */
+static void ReportSequesterButton (ButtoN b)
+{
+  ClickableItemData cid;
+  Uint2          entityID;
+  Int4              num_disc;
+  ValNodePtr        sep_list;
+
+  DiscrepancyReportFormPtr d;
+
+  d = (DiscrepancyReportFormPtr) GetObjectExtra (b);
+  if (d == NULL) {
+    return;
+  }
+
+  sep_list = GetViewedSeqEntryList ();
+  if (sep_list == NULL) {
+    return;
+  } else if (sep_list->next != NULL) {
+    Message (MSG_ERROR, "Can't sequester when viewing more than one record");
+    return;
+  } else {
+    entityID = ObjMgrGetEntityIDForChoice (sep_list->data.ptrvalue);
+  }
+  sep_list = ValNodeFree (sep_list);
+
+
+  num_disc = CountChosenDiscrepancies (d->clickable_list_data, FALSE);
+
+  if (num_disc == 0) 
+  {
+    Message (MSG_ERROR, "No discrepancies selected!");
+    return;
+  }
+
+  MemSet (&cid, 0, sizeof (ClickableItemData));
+  cid.chosen = FALSE;
+  cid.item_list = NULL;
+  cid.subcategories = d->clickable_list_data;
+
+  if (SequesterClickableItem (entityID, &cid)) {
+    SetDoReportAfterUnsequester (d->report_type);
+  }
+}
+
+
 extern void CreateReportWindow (EDiscrepancyReportType report_type)
 {
   DiscrepancyReportFormPtr drfp;
@@ -15597,15 +16526,21 @@ extern void CreateReportWindow (EDiscrepancyReportType report_type)
   
   /* read in config file */
   drfp->dcp = ReadDiscrepancyConfigEx(GetReportConfigName (report_type));
+  drfp->report_type = report_type;
 
   /* adjust for report type */
   AdjustConfigForReportType (report_type, drfp->dcp);
 
-  /* Discrepancy Report uses log file for autofix */
-  if (report_type == eReportTypeDiscrepancy) {
+  /* Discrepancy Report and MegaReport use log file for autofix */
+  if (report_type == eReportTypeDiscrepancy || report_type == eReportTypeMegaReport) {
     drfp->log_name = StringSave ("Autofix Changes");
   }
   
+  /* On-caller Tool uses special order */
+  if (report_type == eReportTypeOnCaller) {
+    drfp->reorder_results_proc = ReorderOnCallerResults;
+  }
+  
   /* register to receive update messages */
   drfp->userkey = OMGetNextUserKey ();
   drfp->procid = 0;
@@ -15635,7 +16570,7 @@ extern void CreateReportWindow (EDiscrepancyReportType report_type)
   b = PushButton (c1, "Contract All", ContractAllDiscReportItems);
   SetObjectExtra (b, drfp, NULL);
 
-  c = HiddenGroup (h, 6, 0, NULL);
+  c = HiddenGroup (h, 8, 0, NULL);
   SetGroupSpacing (c, 10, 10);
   b = PushButton (c, "Generate Report", GenerateDiscrepancyReport);
   SetObjectExtra (b, drfp, NULL);
@@ -15643,6 +16578,8 @@ extern void CreateReportWindow (EDiscrepancyReportType report_type)
   SetObjectExtra (drfp->recheck_btn, drfp, NULL);
   if (report_type == eReportTypeOnCaller) {
     drfp->add_entity_proc = AddNewEntityDiscrepancyProc;
+  } else {
+    drfp->add_entity_proc = NULL;
   }
   b = PushButton (c, "Mark Fixable", MarkFixableDiscrepancies);
   SetObjectExtra (b, drfp, NULL);
@@ -15650,9 +16587,15 @@ extern void CreateReportWindow (EDiscrepancyReportType report_type)
   b = PushButton (c, "Fix Marked", FixMarkedDiscrepanciesBtn);
   SetObjectExtra (b, drfp, NULL);
   
+  b = PushButton (c, "Unmark All", UnmarkAllBtn);
+  SetObjectExtra (b, drfp, NULL);
+
   b = PushButton (c, "Configure", GetReportEditButtonProc (report_type));
   SetObjectExtra (b, drfp, NULL);
   
+  b = PushButton (c, "Sequester", ReportSequesterButton);
+  SetObjectExtra (b, drfp, NULL);
+
   PushButton (c, "Dismiss", StdCancelButtonProc);
 
   AlignObjects (ALIGN_CENTER, (HANDLE) drfp->clickable_list_dlg, (HANDLE) c1, (HANDLE) c, NULL);
@@ -16165,6 +17108,7 @@ typedef struct rnaits {
   /* for alignment coordinates */
   ButtoN       use_aln;
   PopuP        this_aln;
+  GrouP        gap_handling;
 
   BaseFormPtr       bfp;
   TaglistCallback   callbacks[3];
@@ -16322,12 +17266,12 @@ static CharPtr RNAITSItemToTagListString (RNA_ITS_ItemPtr rip)
   if (rip->left > -1) {
     sprintf (left_str, "%d", rip->left);
   } else {
-    sprintf (left_str, "");
+    sprintf (left_str, "%s", "");
   }
   if (rip->right > -1) {
     sprintf (right_str, "%d", rip->right);
   } else {
-    sprintf (right_str, "");
+    sprintf (right_str, "%s", "");
   }
   sprintf (new_line, "%d\t%s\t%s\n", rip->rna_type, left_str, right_str);
   return StringSave (new_line);
@@ -16727,16 +17671,15 @@ static void MakeRNA_ITSChainForBioseq (BioseqPtr bsp, Pointer userdata)
 
     rrp = RnaRefNew ();
     if (rip->rna_type == eRNA_ITS_ITS1 || rip->rna_type == eRNA_ITS_ITS2) {
-      rrp->type = RNA_TYPE_other;
+      rrp->type = RNA_TYPE_misc_RNA;
     } else {
       rrp->type = RNA_TYPE_rRNA;
     }
-    rrp->ext.choice = 1;
-
-    rrp->ext.value.ptrvalue = StringSave (RNANameFromRNAType(rip->rna_type));
     sfp = SeqFeatNew ();
     sfp->data.choice = SEQFEAT_RNA;
     sfp->data.value.ptrvalue = rrp;
+    SetRNAProductString (sfp, NULL, RNANameFromRNAType(rip->rna_type), ExistingTextOption_replace_old);
+
     /* if last endpoint not set, use end of sequence.
      * if last endpoint past end of sequence, use end of sequence.
      */
@@ -16756,7 +17699,7 @@ static void MakeRNA_ITSChainForBioseq (BioseqPtr bsp, Pointer userdata)
 /* This function will propagate the RNA features pointed to by feature_list
  * from aln_row in salp to the other rows in salp. 
 */
-static void PropagateRNAList (ValNodePtr feature_list, Int4 aln_row, SeqAlignPtr salp)
+static void PropagateRNAList (ValNodePtr feature_list, Int4 aln_row, SeqAlignPtr salp, Boolean split_at_gaps)
 {
   ValNodePtr seq_for_prop = NULL, vnp;
   Int4       i;
@@ -16774,7 +17717,7 @@ static void PropagateRNAList (ValNodePtr feature_list, Int4 aln_row, SeqAlignPtr
 
   /* propagate each feature */
   for (vnp = feature_list; vnp != NULL; vnp = vnp->next) {
-    PropagateOneFeat (vnp->data.ptrvalue, TRUE, FALSE, FALSE, FALSE, FALSE, seq_for_prop, &warned_about_master);
+    PropagateOneFeat (vnp->data.ptrvalue, split_at_gaps, FALSE, FALSE, FALSE, FALSE, seq_for_prop, &warned_about_master);
   }
 
   /* free sequence IDs in seq_for_prop */
@@ -16795,6 +17738,7 @@ static void MakeRNA_ITSChain (ButtoN b)
   Boolean            apply_to_all = FALSE, propagate = FALSE;
   SeqAlignPtr        next_salp, propagate_salp = NULL;
   Int4               salp_index, aln_row = -1;
+  Boolean            split_at_gaps = FALSE;
 
   rp = (RNAITSPtr) GetObjectExtra (b);
   if (rp == NULL) return;
@@ -16866,7 +17810,10 @@ static void MakeRNA_ITSChain (ButtoN b)
   } else {
     MakeRNA_ITSChainForBioseq (bsp, rp);
     if (propagate) {
-      PropagateRNAList (rp->feature_list, aln_row, propagate_salp);
+      if (GetValue (rp->gap_handling) == 2) {
+        split_at_gaps = TRUE;
+      }
+      PropagateRNAList (rp->feature_list, aln_row, propagate_salp, split_at_gaps);
     }
   }
   rp->feature_list = ValNodeFree (rp->feature_list);
@@ -17072,6 +18019,13 @@ extern void ApplyRNA_ITS (IteM i)
                                           rp->callbacks, rp, FALSE);
 
   rp->prev_list = NULL;
+
+  /* control for handling alignment coordinates over gaps */
+  rp->gap_handling = HiddenGroup (h, 2, 0, NULL);
+  RadioButton (rp->gap_handling, "Extend over gaps");
+  RadioButton (rp->gap_handling, "Split at gaps");
+  SetValue (rp->gap_handling, 1);
+
   /* Add Accept and Cancel buttons */
 
   c = HiddenGroup (h, 3, 0, NULL);
@@ -17084,6 +18038,7 @@ extern void ApplyRNA_ITS (IteM i)
 
   AlignObjects (ALIGN_CENTER, (HANDLE) g,
                               (HANDLE) rp->rna_list,
+                              (HANDLE) rp->gap_handling,
                               (HANDLE) c, NULL);
 
 
@@ -17352,7 +18307,7 @@ static void PopulateLinkLeftDoc (CDSmRNALinkToolPtr tp)
   ValNodePtr vnp;
   CharPtr    desc;
   Int4       col_width;
-  Int2       i = 1, item_num;
+  Int2       i = 1, item_num = 0;
   Int4       startsAt;
 
   if (tp == NULL) return;
@@ -18477,9 +19432,7 @@ static ValNodePtr DivideClickableItemListByEntityID (ValNodePtr clickable_list)
 
 
 typedef struct cdstrnatool {
-  FORM_MESSAGE_BLOCK
-  DialoG clickable_list_dlg;
-  ValNodePtr clickable_list;
+  CLICKABLE_LIST_FORM_BLOCK
   ValNodePtr overlap_list;
 } CDStRNAToolData, PNTR CDStRNAToolPtr;
 
@@ -18490,7 +19443,7 @@ static void CleanupCDStRNAToolForm (GraphiC g, VoidPtr data)
 
   dlg = (CDStRNAToolPtr) data;
   if (dlg != NULL) {
-    dlg->clickable_list = FreeClickableList (dlg->clickable_list);
+    dlg->clickable_list_data = FreeClickableList (dlg->clickable_list_data);
     dlg->overlap_list = FreeCDStRNAOverlapList (dlg->overlap_list);
     ObjMgrFreeUserData (dlg->input_entityID, dlg->procid, dlg->proctype, dlg->userkey);
   }
@@ -18527,13 +19480,13 @@ static void TrimSelectedCDS (ButtoN b)
   dlg = (CDStRNAToolPtr) GetObjectExtra (b);
   if (dlg == NULL) return;
 
-  tmp_list = GetSelectedClickableItems (dlg->clickable_list);
+  tmp_list = GetSelectedClickableItems (dlg->clickable_list_data);
 
   if (tmp_list == NULL) {
     if (ANS_CANCEL == Message (MSG_OKC, "No features selected!  Trim all?")) {
       return;
     } else {
-      tmp_list = dlg->clickable_list;
+      tmp_list = dlg->clickable_list_data;
     }
   }
 
@@ -18571,7 +19524,7 @@ static void TrimSelectedCDS (ButtoN b)
   overlap_list = FreeCDStRNAOverlapList (overlap_list);
   SendUpdatesForClickableList (tmp_list);
 
-  if (tmp_list != dlg->clickable_list) {
+  if (tmp_list != dlg->clickable_list_data) {
     tmp_list = ValNodeFree (tmp_list);
   }
 
@@ -18581,9 +19534,9 @@ static void TrimSelectedCDS (ButtoN b)
   } else {
     /* update list of overlaps (remove the trimmed ones) */
     PointerToDialog (dlg->clickable_list_dlg, NULL);
-    dlg->clickable_list = FreeClickableList (dlg->clickable_list);
-    dlg->clickable_list = ClickableListFromCDStRNAOverlapList (dlg->overlap_list);
-    PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list);
+    dlg->clickable_list_data = FreeClickableList (dlg->clickable_list_data);
+    dlg->clickable_list_data = ClickableListFromCDStRNAOverlapList (dlg->overlap_list);
+    PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list_data);
   }
 }
 
@@ -18595,8 +19548,8 @@ static void SelectAllCDS (ButtoN b)
   dlg = (CDStRNAToolPtr) GetObjectExtra (b);
   if (dlg == NULL) return;
 
-  ChooseCategories (dlg->clickable_list, TRUE);
-  PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list);
+  ChooseCategories (dlg->clickable_list_data, TRUE);
+  PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list_data);
 
 }
 
@@ -18618,7 +19571,7 @@ static void EditCDStRNAOverlap (ValNodePtr item_list)
 
   /* create window to display and correct overlaps */
   dlg = (CDStRNAToolPtr) MemNew (sizeof (CDStRNAToolData));
-  dlg->clickable_list = ClickableListFromCDStRNAOverlapList (overlap_list);
+  dlg->clickable_list_data = ClickableListFromCDStRNAOverlapList (overlap_list);
   dlg->overlap_list = overlap_list;
 
   w = FixedWindow (-50, -33, -10, -10, "CDS tRNA Overlaps", StdCloseWindowProc);
@@ -18646,7 +19599,7 @@ static void EditCDStRNAOverlap (ValNodePtr item_list)
   dlg->clickable_list_dlg = CreateClickableListDialog (h, "CDS-tRNA Overlaps", "Features",
                                                         ScrollToDiscrepancyItem, EditDiscrepancyItem, NULL,
                                                         GetDiscrepancyItemText);
-  PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list);
+  PointerToDialog (dlg->clickable_list_dlg, dlg->clickable_list_data);
 
   c = HiddenGroup (h, 4, 0, NULL);
   SetGroupSpacing (c, 10, 10);
diff --git a/sequin/sequin9.c b/sequin/sequin9.c
index 344d827..0f8c92f 100644
--- a/sequin/sequin9.c
+++ b/sequin/sequin9.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   4/20/99
 *
-* $Revision: 6.479 $
+* $Revision: 6.484 $
 *
 * File Description: 
 *
@@ -62,6 +62,10 @@
 #include <assert.h>
 #include <pmfapi.h>
 #include <vsm.h>
+#define NLM_GENERATED_CODE_PROTO
+#include <objmacro.h>
+#include <macrodlg.h>
+#include <macroapi.h>
 
 /*-------------------*/
 /* Defined Constants */
@@ -3035,7 +3039,7 @@ extern void RemoveQualityScores
 static Boolean ExpandSeqGraph (SeqGraphPtr sgp)
 {
   Int4    oldpos = 0, newpos = 0, i;
-  Pointer new_values;
+  Pointer new_values = NULL;
   Int4    new_numval;
   Int2    cur_byte;
 
@@ -3064,6 +3068,7 @@ static Boolean ExpandSeqGraph (SeqGraphPtr sgp)
 
   /* copy and expand */
   while (oldpos < sgp->numval) {
+    cur_byte = 0;
     if (sgp->flags[2] == SEQGRAPH_BS) {
       cur_byte = BSGetByte ((ByteStorePtr) sgp->values);
     }
@@ -3099,10 +3104,10 @@ static Boolean ExpandSeqGraph (SeqGraphPtr sgp)
 static Boolean TruncateSeqGraphValues (SeqGraphPtr sgp, Int4 len, Boolean onleft)
 {
   Int4    oldpos, newpos = 0;
-  Pointer new_values;
+  Pointer new_values = NULL;
   Int4    new_numval;
   Int2    cur_byte;
-  Int4    imin, imax;
+  Int4    imin = 0, imax = 0;
   FloatHi fmin, fmax;
 
   if (sgp == NULL) return TRUE;
@@ -7225,7 +7230,7 @@ AddVariationFeaturesToLog
     total_buf = PrepareVariationFeatureLogEntry (sfp, salp);
     if (!StringHasNoText (total_buf))
     {
-      fprintf (fp, total_buf);
+      fprintf (fp, "%s", total_buf);
       if (data_in_log != NULL)
       {
         *data_in_log = TRUE;
@@ -7301,7 +7306,7 @@ static void AcceptRMCOrExtend (ButtoN b)
 
 static void DoAcceptRMCOrExtendSet (UpsDataPtr udp)
 {
-  Int2         sfbval;
+  Int2         sfbval = 0;
   Boolean      log_is_local = FALSE;
   Boolean      update_proteins = FALSE;
   Boolean      do_update = TRUE;
@@ -9726,7 +9731,7 @@ extern void ExtendAllSequencesInSet (IteM i)
   Char               path [PATH_MAX];
   Pointer            dataptr;
   Uint2              datatype;
-  SeqEntryPtr        nwsep, topsep;
+  SeqEntryPtr        nwsep = NULL, topsep;
   SeqSubmitPtr       ssp;
   BioseqPtr          nbsp;
   BioseqPtr          bsp;
@@ -9887,7 +9892,7 @@ static void NewUpdateOrExtendSequence (IteM i, Boolean do_update)
   MsgAnswer     ans;
   BaseFormPtr   bfp;
   BioseqPtr     bsp, nbsp;
-  Pointer       dataptr;
+  Pointer       dataptr = NULL;
   Uint2         datatype;
   FILE          *fp;
   Char          path [PATH_MAX];
@@ -11141,6 +11146,7 @@ extern void AddTranslExceptWithComment (IteM i)
   clear_btn = PushButton (h, "Clear Comment", ClearComment);
   SetObjectExtra (clear_btn, ap, NULL);
   ap->strict_checking_btn = CheckBox (h, "Overhang must be T or TA", NULL);
+  SetStatus (ap->strict_checking_btn, TRUE);
   ap->extend_btn = CheckBox (h, "Extend for T/TA overhang", NULL);
   ap->adjust_gene_btn = CheckBox (h, "Adjust gene to match coding region location", NULL);
   SetStatus (ap->adjust_gene_btn, TRUE);
@@ -12087,9 +12093,11 @@ UpdateSequencePatchRaw
                              flags, (Pointer) (str + ctr), NULL);
   }
 
-  /* take old 3' */
+  /* take old 3' (if any) */
+  if (ualp->old5 + ualp->olda < upp->orig_bsp->length) {
   ctr += SeqPortStreamInt (upp->orig_bsp, ualp->old5 + ualp->olda, upp->orig_bsp->length - 1, Seq_strand_plus,
                     flags, (Pointer) (str + ctr), NULL);
+  }
   
   str[ctr] = '\0';
   
@@ -14342,13 +14350,13 @@ static void UpdatePairToUpdateTitlesDialog (DialoG d, Pointer data)
     {
       sprintf (ppt_txt, "No update sequence for %s", id_txt);
       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
-      sprintf (ppt_txt, "Length %ld", upp->orig_bsp->length);
+      sprintf (ppt_txt, "Length %ld", (long) upp->orig_bsp->length);
       SetTitle (dlg->new_sequence_length_ppt, ppt_txt);
     }
     else
     {
       sprintf (ppt_txt, "No update sequence for %s (length %ld)", 
-               id_txt, upp->orig_bsp->length);
+               id_txt, (long) upp->orig_bsp->length);
       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
     }
     SafeHide (dlg->old_sequence_id_ppt);    
@@ -14363,12 +14371,12 @@ static void UpdatePairToUpdateTitlesDialog (DialoG d, Pointer data)
     {
       sprintf (ppt_txt, "No alignment for %s", id_txt);
       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
-      sprintf (ppt_txt, "Length: %ld", dlg->orig_bsp->length);
+      sprintf (ppt_txt, "Length: %ld", (long) dlg->orig_bsp->length);
       SetTitle (dlg->new_sequence_length_ppt, ppt_txt);
     }
     else
     {
-      sprintf (ppt_txt, "No alignment for %s Length: %ld", id_txt, dlg->orig_bsp->length);
+      sprintf (ppt_txt, "No alignment for %s Length: %ld", id_txt, (long) dlg->orig_bsp->length);
       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
     }
     SafeHide (dlg->old_sequence_id_ppt);    
@@ -14383,12 +14391,12 @@ static void UpdatePairToUpdateTitlesDialog (DialoG d, Pointer data)
     {
       sprintf (ppt_txt, "New sequence: %s", id_txt);
       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
-      sprintf (ppt_txt, "Length: %ld", dlg->update_bsp->length);
+      sprintf (ppt_txt, "Length: %ld", (long) dlg->update_bsp->length);
       SetTitle (dlg->new_sequence_length_ppt, ppt_txt);
     }
     else
     {
-      sprintf (ppt_txt, "New sequence: %s Length: %ld", id_txt, dlg->update_bsp->length);
+      sprintf (ppt_txt, "New sequence: %s Length: %ld", id_txt, (long) dlg->update_bsp->length);
       SetTitle (dlg->new_sequence_id_ppt, ppt_txt);
     }
   
@@ -14398,12 +14406,12 @@ static void UpdatePairToUpdateTitlesDialog (DialoG d, Pointer data)
     {
       sprintf (ppt_txt, "Old sequence: %s", id_txt);
       SetTitle (dlg->old_sequence_id_ppt, ppt_txt);
-      sprintf (ppt_txt, "Length: %ld", dlg->orig_bsp->length);
+      sprintf (ppt_txt, "Length: %ld", (long) dlg->orig_bsp->length);
       SetTitle (dlg->old_sequence_length_ppt, ppt_txt);
     }
     else
     {
-      sprintf (ppt_txt, "Old sequence: %s Length: %ld", id_txt, dlg->orig_bsp->length);
+      sprintf (ppt_txt, "Old sequence: %s Length: %ld", id_txt, (long) dlg->orig_bsp->length);
       SetTitle (dlg->old_sequence_id_ppt, ppt_txt);
     }
   
@@ -16648,11 +16656,23 @@ static void AddUniqueUpdateSequenceIDs (SeqEntryPtr sep)
   AddUniqueUpdateSequenceIDs (sep->next);
 }
 
+
+static Boolean MatchToBankIt (SeqIdPtr sip1, SeqIdPtr sip2)
+{
+  if (sip1 == NULL || sip1->choice != SEQID_LOCAL) {
+    return FALSE;
+  }
+}
+
+
 static Boolean SeqIdListsOverlap (SeqIdPtr sip1, SeqIdPtr sip2)
 { 
-  SeqIdPtr sip_tmp, sip_next;
+  SeqIdPtr sip_next;
   Char     tmp_id_str [MAX_ID_LEN + 5];
   Boolean  rval = FALSE;
+  StringConstraint scd;
+
+  MemSet (&scd, 0, sizeof (StringConstraint));
   
   while (sip1 != NULL && !rval)
   {
@@ -16662,18 +16682,13 @@ static Boolean SeqIdListsOverlap (SeqIdPtr sip1, SeqIdPtr sip2)
     }
     else if (sip1->choice == SEQID_LOCAL)
     {
-      /* check to see if user just forgot to put "gb|" at the front of the IDs */
       sip_next = sip1->next;
       sip1->next = NULL;
-      StringCpy (tmp_id_str, "gb|");
-      SeqIdWrite (sip1, tmp_id_str + 3, PRINTID_REPORT, sizeof (tmp_id_str) - 4);     
-      sip_tmp = MakeSeqID (tmp_id_str);
-      if (SeqIdIn (sip_tmp, sip2))
-      {
-        rval = TRUE;
-      }
-      sip_tmp = SeqIdFree (sip_tmp);
+      SeqIdWrite (sip1, tmp_id_str, PRINTID_REPORT, sizeof (tmp_id_str) - 1);     
       sip1->next = sip_next;
+      scd.match_text = tmp_id_str;
+      scd.match_location = String_location_equals;
+      rval = DoesSeqIDListMeetStringConstraint (sip2, &scd);
     }
     sip1 = sip1->next;
   }
@@ -16917,7 +16932,7 @@ static SeqEntryPtr ReadASNUpdateSequences (FILE *fp, BoolPtr chars_stripped)
 {
   Pointer      dataptr;
   Uint2        datatype;
-  SeqEntryPtr  sep;
+  SeqEntryPtr  sep = NULL;
   SeqSubmitPtr ssp;
   
   /* Read in one sequence from the file */
diff --git a/sequin/sequiny.c b/sequin/sequiny.c
index c42b65c..86d83c0 100644
--- a/sequin/sequiny.c
+++ b/sequin/sequiny.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   5/24/96
 *
-* $Revision: 6.1 $
+* $Revision: 6.2 $
 *
 * File Description:
 *    This is a companion file to sequinx.c. In order to register additional proceedures
@@ -144,7 +144,7 @@ Int2 LIBCALLBACK MyBioseqEditFunc (Pointer data)
 
 
 	                                      /* now we can send a message to ourselves */
-	                                      /* just to prove it works. The message could just
+	                                      /* just to prove it works. The message could just */
 										  /* as well be from another proceedure though */
 
 	ObjMgrSendMsg (OM_MSG_SELECT, ompcp->input_entityID, 0, 0);
diff --git a/sequin/streamer.c b/sequin/streamer.c
new file mode 100644
index 0000000..7cf9237
--- /dev/null
+++ b/sequin/streamer.c
@@ -0,0 +1,1240 @@
+/*   streamer.c
+* ===========================================================================
+*
+*                            PUBLIC DOMAIN NOTICE
+*            National Center for Biotechnology Information (NCBI)
+*
+*  This software/database is a "United States Government Work" under the
+*  terms of the United States Copyright Act.  It was written as part of
+*  the author's official duties as a United States Government employee and
+*  thus cannot be copyrighted.  This software/database is freely available
+*  to the public for use. The National Library of Medicine and the U.S.
+*  Government do not place any restriction on its use or reproduction.
+*  We would, however, appreciate having the NCBI and the author cited in
+*  any work or product based on this material
+*
+*  Although all reasonable efforts have been taken to ensure the accuracy
+*  and reliability of the software and data, the NLM and the U.S.
+*  Government do not and cannot warrant the performance or results that
+*  may be obtained by using this software or data. The NLM and the U.S.
+*  Government disclaim all warranties, express or implied, including
+*  warranties of performance, merchantability or fitness for any particular
+*  purpose.
+*
+* ===========================================================================
+*
+* File Name:  streamer.c
+*
+* Author:  Colleen Bollin
+*
+* Version Creation Date:   5/17/2005
+*
+* $Revision: 1.4 $
+*
+* File Description: 
+* This file provides the Main function for the standalone Streaming Editor.
+*
+* Modifications:  
+* --------------------------------------------------------------------------
+* Date     Name        Description of modification
+* -------  ----------  -----------------------------------------------------
+*
+*
+* ==========================================================================
+*/
+
+#ifndef CODECENTER
+static char *date_of_compilation = __DATE__;
+static char *time_of_compilation = __TIME__;
+#else
+static char *date_of_compilation = "today";
+static char *time_of_compilation = "now";
+#endif
+
+#include <vibrant.h>
+#include <biosrc.h>
+#include <pubdesc.h>
+#include <explore.h>
+#include <toasn3.h>
+#include <tax3api.h>
+/* includes for pub lookup */
+#include <pmfapi.h>
+#include <utilpub.h>
+#include <medarch.h>
+#include <medutil.h>
+#include <mla2api.h>
+
+
+
+#ifndef WIN16
+CharPtr objPrtMemStr = "PrintTemplateSet ::= {\n" \
+"{ name \"StdSeqDesc\" ,\n" \
+"format { asn1 \"Seqdesc\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Seqdesc.mol-type\" , label \"Molecule type\" , prefix \"\\n\" , form enum { } } ,\n" \
+"{ asn1 \"Seqdesc.modif\" , label \"Modifiers\" , prefix \"\\n\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Seqdesc.modif.E\" , form enum { } } } } } ,\n" \
+"{ asn1 \"Seqdesc.method\" , label \"Method\" , prefix \"\\n\" , form enum { } } ,\n" \
+"{ asn1 \"Seqdesc.name\" , label \"Name\" , prefix \"\\n\" , form text { } } ,\n" \
+"{ asn1 \"Seqdesc.title\" , label \"Title\" , prefix \"\\n\" , form text { } } ,\n" \
+"{ asn1 \"Seqdesc.org\" , label \"Organism\" , prefix \"\\n\" , form use-template \"StdOrgRef\" } ,\n" \
+"{ asn1 \"Seqdesc.comment\" , label \"Comment\" , prefix \"\\n\" , form text { } } ,\n" \
+"{ asn1 \"Seqdesc.num\" , label \"Numbering\" , prefix \"\\n\" , form use-template \"StdNumbering\" } ,\n" \
+"{ asn1 \"Seqdesc.maploc\" , label \"Map location\" , prefix \"\\n\" , form use-template \"StdDbtag\" } ,\n" \
+"{ asn1 \"Seqdesc.pir\" , label \"PIR block\" , prefix \"\\n\" , form null NULL } ,\n" \
+"{ asn1 \"Seqdesc.genbank\" , label \"GenBank block\" , prefix \"\\n\" , form use-template \"StdGBBlock\" } ,\n" \
+"{ asn1 \"Seqdesc.pub\" , label \"Citation\" , prefix \"\\n\" , form use-template \"StdPubdesc\" } ,\n" \
+"{ asn1 \"Seqdesc.region\" , label \"Region\" , prefix \"\\n\" , form text { } } ,\n" \
+"{ asn1 \"Seqdesc.user\" , label \"User Type\" , prefix \"\\n\" , form use-template \"StdUserObj\" } ,\n" \
+"{ asn1 \"Seqdesc.sp\" , label \"SWISS-PROT block\" , prefix \"\\n\" , form null NULL } ,\n" \
+"{ asn1 \"Seqdesc.dbxref\" , label \"Cross reference\" , prefix \"\\n\" , form use-template \"StdDbtag\"  } ,\n" \
+"{ asn1 \"Seqdesc.embl\" , label \"EMBL block\" , prefix \"\\n\" , form null NULL } ,\n" \
+"{ asn1 \"Seqdesc.create-date\" , label \"Create date\" , prefix \"\\n\" , form user { printfunc \"StdDatePrint\" } } ,\n" \
+"{ asn1 \"Seqdesc.update-date\" , label \"Update date\" , prefix \"\\n\" , form user { printfunc \"StdDatePrint\" } } ,\n" \
+"{ asn1 \"Seqdesc.prf\" , label \"PRF block\" , prefix \"\\n\" , form null NULL } ,\n" \
+"{ asn1 \"Seqdesc.pdb\" , label \"PDB block\" , prefix \"\\n\" , form null NULL } ,\n" \
+"{ asn1 \"Seqdesc.het\" , label \"Heterogen\" , prefix \"\\n\" , form text { } } ,\n" \
+"{ asn1 \"Seqdesc.source\" , label \"Biological Source\" , prefix \"\\n\" , form use-template \"StdBioSource\" } ,\n" \
+"{ asn1 \"Seqdesc.molinfo\" , label \"Molecule Information\" , prefix \"\\n\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"MolInfo.biomol\" , form enum { } } ,\n" \
+"{ asn1 \"MolInfo.tech\" , form enum { } } ,\n" \
+"{ asn1 \"MolInfo.completeness\" , form enum { } } } } } } } } } ,\n" \
+"{ name \"StdSeqFeatLocation\" ,\n" \
+"format { asn1 \"Seq-feat.location\" , label \"Location\" , prefix \"\\t\" , form user { printfunc \"StdSeqLocPrint\" } } } ,\n" \
+"{ name \"StdSeqFeatProduct\" ,\n" \
+"format { asn1 \"Seq-feat.product\" , label \"Product\" , prefix \"\\t\" , form user { printfunc \"StdSeqLocPrint\" } } } ,\n" \
+"{ name \"EntrySeqFeatData\" ,\n" \
+"labelfrom \"Seq-feat.data\" ,\n" \
+"format { asn1 \"Seq-feat.data\" , prefix \"\\t\" , form use-template \"StdSeqFeatData\" } } ,\n" \
+"{ name \"StdSeqFeat\" ,\n" \
+"labelfrom \"Seq-feat.data\" ,\n" \
+"format { asn1 \"Seq-feat\" , prefix \"\\n\" , suffix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Seq-feat.data\" , form use-template \"StdSeqFeatData\" } ,\n" \
+"{ asn1 \"Seq-feat\" , form use-template \"StdSeqFeatCommon\" } ,\n" \
+"{ asn1 \"Seq-feat.product\" , label \"Product\" , prefix \" \" , form user { printfunc \"StdSeqLocPrint\" } } ,\n" \
+"{ asn1 \"Seq-feat.location\" , label \"Location\" , prefix \" \" , form user { printfunc \"StdSeqLocPrint\" } } ,\n" \
+"{ asn1 \"Seq-feat.cit\" , label \"Citations\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Seq-feat.cit.pub.E\" , form use-template \"StdPub\" } } } } ,\n" \
+"{ asn1 \"Seq-feat.xref\" , label \"Cross-reference\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Seq-feat.xref.E\" , form use-template \"StdSeqFeatXref\" } } } } } } } } ,\n" \
+"{ name \"StdSeqFeatData\" ,\n" \
+"format { asn1 \"SeqFeatData\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"SeqFeatData.gene\" , label \"Gene\" , form use-template \"StdGeneRef\" } ,\n" \
+"{ asn1 \"SeqFeatData.org\" , label \"Organism\" , form use-template \"StdOrgRef\" } ,\n" \
+"{ asn1 \"SeqFeatData.cdregion\" , label \"Coding Region\" , form use-template \"StdCdRegion\" } ,\n" \
+"{ asn1 \"SeqFeatData.prot\" , label \"Protein\" , form use-template \"StdProtRef\" } ,\n" \
+"{ asn1 \"SeqFeatData.rna\" , label \"RNA\" , form use-template \"StdRNARef\" } ,\n" \
+"{ asn1 \"SeqFeatData.pub\" , label \"Citation\" , form use-template \"StdPubdesc\" } ,\n" \
+"{ asn1 \"SeqFeatData.seq\" , label \"Sequence\" , form user { printfunc \"StdSeqLocPrint\" } } ,\n" \
+"{ asn1 \"SeqFeatData.imp.key\" , label \"Import\" , form use-template \"StdImpFeat\" } ,\n" \
+"{ asn1 \"SeqFeatData.region\" , label \"Region\" , form text { } } ,\n" \
+"{ asn1 \"SeqFeatData.comment\" , label \"Comment\" , form null NULL } ,\n" \
+"{ asn1 \"SeqFeatData.bond\" , label \"Bond\" , form enum { } } ,\n" \
+"{ asn1 \"SeqFeatData.site\" , label \"Site\" , form enum { } } ,\n" \
+"{ asn1 \"SeqFeatData.rsite\" , label \"Rest. Site\" , form use-template \"StdRsiteRef\" } ,\n" \
+"{ asn1 \"SeqFeatData.user\" , label \"User Type\" , form use-template \"StdUserObj\" } ,\n" \
+"{ asn1 \"SeqFeatData.txinit\" , label \"TxInit\" , form use-template \"StdTxInit\" } ,\n" \
+"{ asn1 \"SeqFeatData.num\" , label \"Numbering\" , form use-template \"StdNumbering\" } ,\n" \
+"{ asn1 \"SeqFeatData.psec-str\" , label \"Sec. Struct\" , form enum { } } ,\n" \
+"{ asn1 \"SeqFeatData.non-std-residue\" , label \"NonStd Residue\" , form text { } } ,\n" \
+"{ asn1 \"SeqFeatData.het\" , label \"Heterogen\" , form text { } } ,\n" \
+"{ asn1 \"SeqFeatData.biosrc\" , label \"Biological Source\" , prefix \"\\n\" , form use-template \"StdBioSource\" } } } } } ,\n" \
+"{ name \"StdGeneRef\" ,\n" \
+"format { asn1 \"Gene-ref\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Gene-ref\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Gene-ref.locus\" , form text { } } ,\n" \
+"{ asn1 \"Gene-ref.allele\" , prefix \" \" , form text { } } } } } ,\n" \
+"{ asn1 \"Gene-ref.desc\" , prefix \"[\" , suffix \"]\" , form text { } } ,\n" \
+"{ asn1 \"Gene-ref.pseudo\" , form boolean {\n" \
+"true \"This is a pseudogene.\" } } ,\n" \
+"{ asn1 \"Gene-ref.syn\" , label \"Synonyms\" , prefix \" (\" , suffix \")\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Gene-ref.syn.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"Gene-ref.maploc\" , label \"Map Location\" , prefix \" \" , form text { } } ,\n" \
+"{ asn1 \"Gene-ref.db\" , label \"Cross Reference\" , prefix \" \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Gene-ref.db.E\" , prefix \"(\" , suffix \")\" , form use-template \"StdDbtag\" } } } } } } } } ,\n" \
+"{ name \"StdUserObj\" ,\n" \
+"format { asn1 \"User-object\" , label \"User-object\" , prefix \"\\n\" , form block {\n" \
+"separator \": \" ,\n" \
+"components {\n" \
+"{ asn1 \"User-object.class\" , form text { } } ,\n" \
+"{ asn1 \"User-object.type\" , form use-template \"StdObjectId\" } } } } } ,\n" \
+"{ name \"StdPubOnFeat\" ,\n" \
+"format { asn1 \"Pub\" , label \"Citation\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Pub\" , form use-template \"StdPub\" } } } } } ,\n" \
+"{ name \"StdPub\" ,\n" \
+"format { asn1 \"Pub\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Pub.gen\" , form use-template \"StdCitGen\" } ,\n" \
+"{ asn1 \"Pub.sub\" , form use-template \"StdCitSub\" } ,\n" \
+"{ asn1 \"Pub.medline\" , form use-template \"StdMedlineEntry\" } ,\n" \
+"{ asn1 \"Pub.muid\" , label \"MEDLINE uid: \" , form text { } } ,\n" \
+"{ asn1 \"Pub.pmid\" , label \"PubMed id: \" , form text { } } ,\n" \
+"{ asn1 \"Pub.article\" , form use-template \"StdCitArt\" } ,\n" \
+"{ asn1 \"Pub.journal\" , form use-template \"StdCitJour\" } ,\n" \
+"{ asn1 \"Pub.book\" , form use-template \"StdCitBook\" } ,\n" \
+"{ asn1 \"Pub.proc\" , form use-template \"StdCitProc\" } ,\n" \
+"{ asn1 \"Pub.patent\" , form use-template \"StdCitPat\" } ,\n" \
+"{ asn1 \"Pub.pat-id\" , form use-template \"StdIdPat\" } ,\n" \
+"{ asn1 \"Pub.man\" , form use-template \"StdCitLet\" } ,\n" \
+"{ asn1 \"Pub.equiv\" , form use-template \"StdPubEquiv\" } } } } } ,\n" \
+"{ name \"StdCitGen\" ,\n" \
+"format { asn1 \"Cit-gen\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-gen.serial-number\" , prefix \"[\" , suffix \"]\" , form text { } } ,\n" \
+"{ asn1 \"Cit-gen.authors\" , form use-template \"StdAuthList\" } ,\n" \
+"{ asn1 \"Cit-gen.date\" , prefix \"(\" , suffix \")\" , form user { printfunc \"StdDatePrint\" } } ,\n" \
+"{ asn1 \"Cit-gen.title\" , form text { } } ,\n" \
+"{ asn1 \"Cit-gen.cit\" , form text { } } ,\n" \
+"{ asn1 \"Cit-gen\" , form block {\n" \
+"separator \" \" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-gen.journal\" , suffix \":\" , form use-template \"StdTitle\" } ,\n" \
+"{ asn1 \"Cit-gen.issue\" , suffix \";\" , form text { } } ,\n" \
+"{ asn1 \"Cit-gen.pages\" , form text { } } } } } } } } } ,\n" \
+"{ name \"StdCitSub\" ,\n" \
+"format { asn1 \"Cit-sub\" , prefix \"Data Submission \" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Cit-sub.medium\" , prefix \"on \" , suffix \" \" , form enum { } } ,\n" \
+"{ asn1 \"Cit-sub.imp.date\" , prefix \"(\" , suffix \")\" , form user { printfunc \"StdDatePrint\" } } ,\n" \
+"{ asn1 \"Cit-sub.authors\" , prefix \"\\n\" , form use-template \"StdAuthList\" } } } } } ,\n" \
+"{ name \"StdMedlineEntry\" ,\n" \
+"format { asn1 \"Medline-entry\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-entry\" , form block {\n" \
+"separator \"   \" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-entry.uid\" , label \"uid\" , prefix \": \" , form text { } } ,\n" \
+"{ asn1 \"Medline-entry.em\" , label \"entry month\" , prefix \": \" , form user { printfunc \"StdDatePrint\" } } } } } ,\n" \
+"{ asn1 \"Medline-entry.cit\" , form use-template \"StdCitArt\" } ,\n" \
+"{ asn1 \"Medline-entry.abstract\" , label \"abstract\" , prefix \": \" , form text { } } ,\n" \
+"{ asn1 \"Medline-entry.mesh\" , label \"Mesh Terms\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-entry.mesh.E\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Medline-mesh.term\" , form text { } } ,\n" \
+"{ asn1 \"Medline-mesh.mp\" , form boolean {\n" \
+"true \" (Main Point)\" } } ,\n" \
+"{ asn1 \"Medline-mesh.qual\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-mesh.qual.E\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Medline-qual.subh\" , form text { } } ,\n" \
+"{ asn1 \"Medline-qual.mp\" , form boolean {\n" \
+"true \" (Main Point)\" } } } } } } } } } } } } } } ,\n" \
+"{ asn1 \"Medline-entry.substance\" , label \"Substance\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-entry.substance.E\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Medline-rn.name\" , form text { } } ,\n" \
+"{ asn1 \"Medline-rn.type\" , form enum {\n" \
+"values {\n" \
+"\"\" ,\n" \
+"\" CAS: \" ,\n" \
+"\"EC \" } } } ,\n" \
+"{ asn1 \"Medline-rn.cit\" , form text { } } } } } } } } ,\n" \
+"{ asn1 \"Medline-entry.xref\" , label \"Cross Reference\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-entry.xref.E\" , form block {\n" \
+"separator \": \" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-si.type\" , form enum { } } ,\n" \
+"{ asn1 \"Medline-si.cit\" , form text { } } } } } } } } ,\n" \
+"{ asn1 \"Medline-entry.gene\" , label \"Possible Gene Symbols\" , prefix \": \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-entry.gene.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"Medline-entry.idnum\" , label \"Support\" , prefix \": \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Medline-entry.idnum.E\" , form text { } } } } } } } } } ,\n" \
+"{ name \"StdCitArt\" ,\n" \
+"format { asn1 \"Cit-art\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-art.title\" , form use-template \"StdTitle\" } ,\n" \
+"{ asn1 \"Cit-art.authors\" , form use-template \"StdAuthList\" } ,\n" \
+"{ asn1 \"Cit-art.from.journal\" , form use-template \"StdCitJour\" } ,\n" \
+"{ asn1 \"Cit-art.from.book\" , prefix \"(in) \" , form use-template \"StdCitBook\" } ,\n" \
+"{ asn1 \"Cit-art.from.proc\" , prefix \"(in) \" , form use-template \"StdCitProc\" } } } } } ,\n" \
+"{ name \"StdCitJour\" ,\n" \
+"format { asn1 \"Cit-jour\" , form block {\n" \
+"separator \" \" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-jour.title\" , form use-template \"StdTitle\" } ,\n" \
+"{ asn1 \"Cit-jour.imp\" , form use-template \"StdImprint\" } } } } } ,\n" \
+"{ name \"StdCitBook\" ,\n" \
+"format { asn1 \"Cit-book\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-book.title\" , form use-template \"StdTitle\" } ,\n" \
+"{ asn1 \"Cit-book.coll\" , prefix \"Collection: \" , form use-template \"StdTitle\" } ,\n" \
+"{ asn1 \"Cit-book.authors\" , form use-template \"StdAuthList\" } ,\n" \
+"{ asn1 \"Cit-book.imp\" , form use-template \"StdImprint\" } } } } } ,\n" \
+"{ name \"StdCitProc\" ,\n" \
+"format { asn1 \"Cit-proc\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-proc.book\" , form use-template \"StdCitBook\" } ,\n" \
+"{ asn1 \"Cit-proc.meet\" , label \"Meeting \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Meeting.number\" , form text { } } ,\n" \
+"{ asn1 \"Meeting.date\" , form user { printfunc \"StdDatePrint\" } } ,\n" \
+"{ asn1 \"Meeting.place\" , form use-template \"StdAffil\" } } } } } } } } ,\n" \
+"{ name \"StdCitPat\" ,\n" \
+"format { asn1 \"Cit-pat\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-pat.title\" , form text { } } ,\n" \
+"{ asn1 \"Cit-pat.authors\" , form use-template \"StdAuthList\" } ,\n" \
+"{ asn1 \"Cit-pat\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Cit-pat.country\" , suffix \" \" , form text { } } ,\n" \
+"{ asn1 \"Cit-pat.doc-type\" , form text { } } ,\n" \
+"{ asn1 \"Cit-pat.number\" , form text { } } ,\n" \
+"{ asn1 \"Cit-pat.date-issue\" , prefix \" (\" , suffix \")\" , form user { printfunc \"StdDatePrint\" } } ,\n" \
+"{ asn1 \"Cit-pat.app-number\" , prefix \" Appl: \" , form text { } } ,\n" \
+"{ asn1 \"Cit-pat.app-date\" , prefix \" (\" , suffix \")\" , form user { printfunc \"StdDatePrint\" } } } } } } } } } ,\n" \
+"{ name \"StdIdPat\" ,\n" \
+"format { asn1 \"Id-pat\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Id-pat.country\" , suffix \" \" , form text { } } ,\n" \
+"{ asn1 \"Id-pat.id.number\" , form text { } } ,\n" \
+"{ asn1 \"Id-pat.id.app-number\" , prefix \"Appl: \" , form text { } } } } } } ,\n" \
+"{ name \"StdCitLet\" ,\n" \
+"format { asn1 \"Cit-let\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Cit-let.type\" , prefix \"[\" , suffix \"]\" , form enum { } } ,\n" \
+"{ asn1 \"Cit-let.man-id\" , form text { } } ,\n" \
+"{ asn1 \"Cit-let.cit\" , form use-template \"StdCitBook\" } } } } } ,\n" \
+"{ name \"StdPubEquiv\" ,\n" \
+"format { asn1 \"Pub-equiv\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Pub-equiv.E\" , form use-template \"StdPub\" } } } } } ,\n" \
+"{ name \"StdTitle\" ,\n" \
+"format { asn1 \"Title\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Title.E.trans\" , prefix \"[\" , suffix \"]\" , form text { } } ,\n" \
+"{ asn1 \"Title.E.name\" , form text { } } ,\n" \
+"{ asn1 \"Title.E.tsub\" , form text { } } ,\n" \
+"{ asn1 \"Title.E.abr\" , form text { } } ,\n" \
+"{ asn1 \"Title.E.iso-jta\" , form text { } } ,\n" \
+"{ asn1 \"Title.E.ml-jta\" , label \"MEDLINE\" , prefix \": \" , form text { } } ,\n" \
+"{ asn1 \"Title.E.jta\" , label \"jta\" , prefix \": \" , form text { } } ,\n" \
+"{ asn1 \"Title.E.issn\" , label \"ISSN\" , prefix \": \" , form text { } } ,\n" \
+"{ asn1 \"Title.E.coden\" , label \"CODEN\" , prefix \": \" , form text { } } ,\n" \
+"{ asn1 \"Title.E.isbn\" , label \"ISBN\" , prefix \": \" , form text { } } } } } } ,\n" \
+"{ name \"StdAuthList\" ,\n" \
+"format { asn1 \"Auth-list\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Auth-list\" , form user { printfunc \"StdAuthListNamesPrint\" } } ,\n" \
+"{ asn1 \"Auth-list.affil\" , form use-template \"StdAffil\" } } } } } ,\n" \
+"{ name \"StdAffil\" ,\n" \
+"format { asn1 \"Affil\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Affil.str\" , form text { } } ,\n" \
+"{ asn1 \"Affil.std.affil\" , form text { } } ,\n" \
+"{ asn1 \"Affil.std.div\" , form text { } } ,\n" \
+"{ asn1 \"Affil.std.street\" , form text { } } ,\n" \
+"{ asn1 \"Affil.std\" , form block {\n" \
+"separator \" \" ,\n" \
+"components {\n" \
+"{ asn1 \"Affil.std.city\" , form text { } } ,\n" \
+"{ asn1 \"Affil.std.sub\" , form text { } } ,\n" \
+"{ asn1 \"Affil.std.country\" , form text { } } } } } } } } } ,\n" \
+"{ name \"StdImprint\" ,\n" \
+"format { asn1 \"Imprint\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Imprint.date\" , prefix \"(\" , suffix \") \" , form user { printfunc \"StdDatePrint\" } } ,\n" \
+"{ asn1 \"Imprint.volume\" , form text { } } ,\n" \
+"{ asn1 \"Imprint.issue\" , prefix \" (\" , suffix \")\" , form text { } } ,\n" \
+"{ asn1 \"Imprint.section\" , prefix \" (\" , suffix \")\" , form text { } } ,\n" \
+"{ asn1 \"Imprint.part-sup\" , prefix \" (\" , suffix \")\" , form text { } } ,\n" \
+"{ asn1 \"Imprint.pages\" , prefix \": \" , form text { } } ,\n" \
+"{ asn1 \"Imprint.prepub\" , prefix \" (\" , suffix \")\" , form enum { } } ,\n" \
+"{ asn1 \"Imprint.pub\" , label \"\nPublisher: \" , form use-template \"StdAffil\" } ,\n" \
+"{ asn1 \"Imprint.cprt\" , label \" Copyright: \" , form user { printfunc \"StdDatePrint\" } } } } } } ,\n" \
+"{ name \"StdSeqFeatXref\" ,\n" \
+"format { asn1 \"SeqFeatXref\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"SeqFeatXref.id\" , label \"Id=\" , form use-template \"StdFeatId\" } ,\n" \
+"{ asn1 \"SeqFeatXref.data\" , form use-template \"StdSeqFeatData\" } } } } } ,\n" \
+"{ name \"StdOrgRef\" ,\n" \
+"format { asn1 \"Org-ref\" , label \"Org-ref\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Org-ref\" , form block {\n" \
+"separator \" \" ,\n" \
+"components {\n" \
+"{ asn1 \"Org-ref.taxname\" , form text { } } ,\n" \
+"{ asn1 \"Org-ref.common\" , prefix \"(\" , suffix \")\" , form text { } } } } } ,\n" \
+"{ asn1 \"Org-ref.mod\" , label \"Modifiers\" , prefix \" (\" , suffix \")\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Org-ref.mod.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"Org-ref.db\" , label \"Cross Reference\" , prefix \" \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Org-ref.db.E\" , prefix \"(\" , suffix \")\" , form use-template \"StdDbtag\" } } } } ,\n" \
+"{ asn1 \"Org-ref.syn\" , label \"Synonyms\" , prefix \" (\" , suffix \")\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Org-ref.syn.E\" , form text { } } } } } } } } } ,\n" \
+"{ name \"StdBioSource\" ,\n" \
+"format { asn1 \"BioSource\" , label \"BioSource\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"BioSource.genome\" , form enum { } } ,\n" \
+"{ asn1 \"BioSource.org\" , label \"Organism\" , form use-template \"StdOrgRef\" } } } } } ,\n" \
+"{ name \"StdCdRegion\" ,\n" \
+"format { asn1 \"Cdregion\" , label \"Cdregion\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Cdregion.orf\" , form boolean {\n" \
+"true \"Uncharacterized Open Reading Frame\" } } ,\n" \
+"{ asn1 \"Cdregion.frame\" , label \"Reading Frame = \" , form enum { } } ,\n" \
+"{ asn1 \"Cdregion.code\" , label \"Genetic Code: \" , suffix \";\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Genetic-code.E.name\" , form text { } } ,\n" \
+"{ asn1 \"Genetic-code.E.id\" , label \"id= \" , form text { } } } } } ,\n" \
+"{ asn1 \"Cdregion.conflict\" , form boolean {\n" \
+"true \"Translation conflicts with protein sequence\" } } ,\n" \
+"{ asn1 \"Cdregion.stops\" , prefix \"Translation contains \" , suffix \" stop codons\" , form text { } } ,\n" \
+"{ asn1 \"Cdregion.gaps\" , prefix \"Translation contains \" , suffix \" gaps when aligned to protein\" , form text { } } ,\n" \
+"{ asn1 \"Cdregion.mismatch\" , prefix \"Translation contains \" , suffix \" mismatches when aligned to protein\" , form text { } } } } } } ,\n" \
+"{ name \"StdProtRef\" ,\n" \
+"format { asn1 \"Prot-ref\" , label \"Prot-ref\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Prot-ref.name\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Prot-ref.name.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"Prot-ref.desc\" , prefix \"[\" , suffix \"]\" , form text { } } ,\n" \
+"{ asn1 \"Prot-ref.processed\" , form enum { } } ,\n" \
+"{ asn1 \"Prot-ref.ec\" , label \"ec\" , prefix \": \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Prot-ref.ec.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"Prot-ref.activity\" , label \"activity\" , prefix \": \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Prot-ref.activity.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"Prot-ref.db\" , label \"Cross Reference\" , prefix \" \" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Prot-ref.db.E\" , prefix \"(\" , suffix \")\" , form use-template \"StdDbtag\" } } } } } } } } ,\n" \
+"{ name \"StdRNARef\" ,\n" \
+"format { asn1 \"RNA-ref\" , label \"RNA-ref\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"RNA-ref.type\" , form enum { } } ,\n" \
+"{ asn1 \"RNA-ref.pseudo\" , form boolean {\n" \
+"true \"This is an RNA pseudogene.\" } } ,\n" \
+"{ asn1 \"RNA-ref.ext.name\" , form text { } } } } } } ,\n" \
+"{ name \"StdPubdesc\" ,\n" \
+"format { asn1 \"Pubdesc\" , label \"Pubdesc\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Pubdesc.pub\" , form use-template \"StdPubEquiv\" } ,\n" \
+"{ asn1 \"Pubdesc\" , prefix \"In this article:\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Pubdesc.name\" , label \"name=\" , form text { } } ,\n" \
+"{ asn1 \"Pubdesc.fig\" , label \"figure=\" , form text { } } ,\n" \
+"{ asn1 \"Pubdesc.poly-a\" , form boolean {\n" \
+"true \"poly(A) shown\" } } ,\n" \
+"{ asn1 \"Pubdesc.maploc\" , label \"map location=\" , form text { } } ,\n" \
+"{ asn1 \"Pubdesc.num\" , form use-template \"StdNumbering\" } ,\n" \
+"{ asn1 \"Pubdesc.numexc\" , form boolean {\n" \
+"true \"numbering inconsistent\" } } } } } ,\n" \
+"{ asn1 \"Pubdesc.comment\" , form text { } } } } } } ,\n" \
+"{ name \"StdImpFeat\" ,\n" \
+"format { asn1 \"Imp-feat.key\" , label \"Imp-feat\" , form text { } } } ,\n" \
+"{ name \"StdRsiteRef\" ,\n" \
+"format { asn1 \"Rsite-ref\" , label \"Rsite-ref\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Rsite-ref.str\" , form text { } } ,\n" \
+"{ asn1 \"Rsite-ref.std\" , form use-template \"StdDbtag\" } } } } } ,\n" \
+"{ name \"StdTxInit\" ,\n" \
+"format { asn1 \"Txinit\" , label \"TxInit\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Txinit.name\" , form text { } } } } } } ,\n" \
+"{ name \"StdNumbering\" ,\n" \
+"format { asn1 \"Numbering\" , label \"Numbering\" , form null NULL } } ,\n" \
+"{ name \"StdGBBlock\" ,\n" \
+"format { asn1 \"GB-block\" , label \"GenBank-block\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"GB-block.extra-accessions\" , label \"Extra accessions\" , prefix \" (\" , suffix \")\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"GB-block.extra-accessions.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"GB-block.keywords\" , label \"Keywords\" , prefix \" (\" , suffix \")\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"GB-block.keywords.E\" , form text { } } } } } ,\n" \
+"{ asn1 \"GB-block.source\" , label \"Source: \" , form text { } } ,\n" \
+"{ asn1 \"GB-block.origin\" , label \"Origin: \" , form text { } } ,\n" \
+"{ asn1 \"GB-block.div\" , label \"Division: \" , form text { } } ,\n" \
+"{ asn1 \"GB-block.taxonomy\" , label \"Taxonomy: \" , form text { } } ,\n" \
+"{ asn1 \"GB-block.date\" , label \"Date: \" , form text { } } ,\n" \
+"{ asn1 \"GB-block.entry-date\" , label \"Entry date: \" , form user { printfunc \"StdDatePrint\" } } } } } } ,\n" \
+"{ name \"StdFeatId\" ,\n" \
+"format { asn1 \"Feat-id\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Feat-id.gibb\" , label \"GenInfo Backbone: \" , form text { } } ,\n" \
+"{ asn1 \"Feat-id.giim.id\" , label \"GenInfo Import Id: \" , form text { } } ,\n" \
+"{ asn1 \"Feat-id.local\" , label \"Local: \" , form use-template \"StdObjectId\" } ,\n" \
+"{ asn1 \"Feat-id.general\" , form use-template \"StdDbtag\" } } } } } ,\n" \
+"{ name \"StdSeqFeatCommon\" ,\n" \
+"format { asn1 \"Seq-feat\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Seq-feat.id\" , label \"Id=\" , form use-template \"StdFeatId\" } ,\n" \
+"{ asn1 \"Seq-feat.title\" , form text { } } ,\n" \
+"{ asn1 \"Seq-feat\" , suffix \";\" , form block {\n" \
+"separator \", \" ,\n" \
+"components {\n" \
+"{ asn1 \"Seq-feat.partial\" , form boolean {\n" \
+"true \"Partial\" } } ,\n" \
+"{ asn1 \"Seq-feat.except\" , form boolean {\n" \
+"true \"Biological Exception\" } } ,\n" \
+"{ asn1 \"Seq-feat.exp-ev\" , label \"Evidence\" , prefix \" is \" , form enum { } } } } } ,\n" \
+"{ asn1 \"Seq-feat.comment\" , form text { } } ,\n" \
+"{ asn1 \"Seq-feat.ext\" , form use-template \"StdUserObj\" } ,\n" \
+"{ asn1 \"Seq-feat.qual\" , label \"Qualifiers\" , prefix \"\\n\" , form block {\n" \
+"separator \"\\n\" ,\n" \
+"components {\n" \
+"{ asn1 \"Seq-feat.qual.E\" , prefix \"/\" , form block {\n" \
+"separator \"= \" ,\n" \
+"components {\n" \
+"{ asn1 \"Gb-qual.qual\" , form text { } } ,\n" \
+"{ asn1 \"Gb-qual.val\" , form text { } } } } } } } } } } } } ,\n" \
+"{ name \"StdDbtag\" ,\n" \
+"format { asn1 \"Dbtag\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Dbtag.db\" , suffix \": \" , form text { } } ,\n" \
+"{ asn1 \"Dbtag.tag\" , form use-template \"StdObjectId\" } } } } } ,\n" \
+"{ name \"StdObjectId\" ,\n" \
+"format { asn1 \"Object-id\" , form block {\n" \
+"components {\n" \
+"{ asn1 \"Object-id.id\" , form text { } } ,\n" \
+"{ asn1 \"Object-id.str\" , form text { } } } } } } };\n";
+#else
+CharPtr objPrtMemStr = "";
+#endif
+
+Boolean  useTaxon = FALSE;
+
+static PubdescEditProcs    pubedprocs;
+static BioSourceEditProcs  biosrcedprocs;
+Boolean  useEntrez = FALSE;
+Boolean  indexerVersion = FALSE;
+
+
+static Int2  taxonCount;
+
+static Int4 TaxLookup (SeqEntryPtr sep, Boolean strip, Boolean correct,
+                              MonitorPtr mon)
+
+{
+  BioseqSetPtr  bssp;
+  SeqEntryPtr   oldscope;
+  Int4          rsult;
+  Char          str [32];
+
+  rsult = 0;
+  if (IS_Bioseq_set (sep)) {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    if (bssp != NULL && (bssp->_class == 7 ||
+                         (IsPopPhyEtcSet (bssp->_class)))) {
+      for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
+        rsult += TaxLookup (sep, strip, correct, mon);
+      }
+      return rsult;
+    }
+  }
+  if (mon != NULL) {
+    taxonCount++;
+    sprintf (str, "Processing Component %d", (int) taxonCount);
+    MonitorStrValue (mon, str);
+  }
+
+  oldscope = SeqEntrySetScope (sep);
+  rsult = SeqEntryToAsn3Ex (sep, strip, correct, TRUE, NULL, Tax3MergeSourceDescr, FALSE, FALSE);
+  DeleteMarkedObjects (0, OBJ_SEQENTRY, sep);
+  SeqEntrySetScope (oldscope);
+  return rsult;
+}
+
+static Boolean LookupTaxonomyFunc (Uint2 entityID)
+
+{
+  SeqEntryPtr  sep;
+  MonitorPtr   mon;
+  Int4        rsult;
+  ErrSev      sev;
+
+  if (entityID < 1) return FALSE;
+  sep = GetTopSeqEntryForEntityID (entityID);
+  if (sep == NULL) return FALSE;
+  
+  rsult = 0;
+  sev = ErrSetMessageLevel (SEV_FATAL);
+
+  taxonCount = 0;
+  WatchCursor ();
+  mon = MonitorStrNewEx ("Taxonomy Lookup", 40, FALSE);
+  MonitorStrValue (mon, "Processing Organism Info");
+  Update ();
+
+  ObjMgrSetDirtyFlag (entityID, TRUE);
+
+  EntryMergeDupBioSources (sep); /* do before and after SE2A3 */
+
+  Taxon3ReplaceOrgInSeqEntry (sep, FALSE);
+  rsult = TaxLookup (sep, TRUE, FALSE, mon);
+  MonitorStrValue (mon, "Closing Taxon");
+  Update ();
+  MonitorFree (mon);
+  ArrowCursor ();
+  Update ();
+
+  ErrSetMessageLevel (sev);
+  ErrClear ();
+  ErrShow ();
+
+  return TRUE;
+}
+
+static Int2 LclGetSequinAppParam (CharPtr section, CharPtr type, CharPtr dflt, CharPtr buf, Int2 buflen)
+
+{
+  Int2  rsult;
+
+  rsult = GetAppParam ("SEQUINCUSTOM", section, type, NULL, buf, buflen);
+  if (rsult) return rsult;
+  rsult = GetAppParam ("SEQUIN", section, type, dflt, buf, buflen);
+  return rsult;
+}
+
+/* section for enabling pubmed lookups */
+static Boolean log_mla_asn = FALSE;
+static Boolean log_mla_set = FALSE;
+
+static ValNodePtr LookupAnArticleFuncNew (ValNodePtr oldpep, BoolPtr success)
+
+{
+  CitArtPtr      cap = NULL;
+  ArticleIdPtr   ids;
+  MlaBackPtr     mbp;
+  MlaRequestPtr  mrp;
+  Int4           pmid = 0;
+  ValNodePtr     pub = NULL;
+  ValNodePtr     vnp;
+#ifdef OS_UNIX
+  CharPtr        str;
+#endif
+
+  if (success != NULL) {
+    *success = FALSE;
+  }
+  if (oldpep == NULL) return NULL;
+
+#ifdef OS_UNIX
+  if (! log_mla_set) {
+    str = (CharPtr) getenv ("LOG_MLA_ASN");
+    if (StringDoesHaveText (str)) {
+      if (StringICmp (str, "TRUE") == 0) {
+        log_mla_asn = TRUE;
+      }
+    }
+    log_mla_set = TRUE;
+  }
+#endif
+
+  for (vnp = oldpep; vnp != NULL; vnp = vnp->next) {
+    if (vnp->choice == PUB_Article) {
+      cap = (CitArtPtr) vnp->data.ptrvalue;
+    } else if (vnp->choice == PUB_PMid) {
+      pmid = (Int4) vnp->data.intvalue;
+    }
+  }
+
+  if (cap != NULL) {
+    mrp = Mla2CreateCitArtMatchRequest (cap);
+    if (mrp != NULL) {
+      if (log_mla_asn) {
+        LaunchAsnTextViewer ((Pointer) mrp, (AsnWriteFunc) MlaRequestAsnWrite, "citart match request");
+      }
+      mbp = Mla2SynchronousQuery (mrp);
+      mrp = MlaRequestFree (mrp);
+      if (mbp != NULL) {
+        if (log_mla_asn) {
+          LaunchAsnTextViewer ((Pointer) mbp, (AsnWriteFunc) MlaBackAsnWrite, "citart match result");
+        }
+        pmid = Mla2ExtractCitMatchReply (mbp);
+        mbp = MlaBackFree (mbp);
+      }
+    }
+  }
+
+  if (pmid > 0) {
+    mrp = Mla2CreatePubFetchRequest (pmid);
+    if (mrp != NULL) {
+      if (log_mla_asn) {
+        LaunchAsnTextViewer ((Pointer) mrp, (AsnWriteFunc) MlaRequestAsnWrite, "get pub request");
+      }
+      mbp = Mla2SynchronousQuery (mrp);
+      mrp = MlaRequestFree (mrp);
+      if (mbp != NULL) {
+        if (log_mla_asn) {
+          LaunchAsnTextViewer ((Pointer) mbp, (AsnWriteFunc) MlaBackAsnWrite, "get pub result");
+        }
+        cap = Mla2ExtractPubFetchReply (mbp);
+        if (cap != NULL) {
+          if (log_mla_asn) {
+            LaunchAsnTextViewer ((Pointer) cap, (AsnWriteFunc) CitArtAsnWrite, "before");
+          }
+          ChangeCitArtMLAuthorsToSTD (cap);
+          if (log_mla_asn) {
+            LaunchAsnTextViewer ((Pointer) cap, (AsnWriteFunc) CitArtAsnWrite, "after");
+          }
+          for (ids = cap->ids; ids != NULL; ids = ids->next) {
+            if (ids->choice != ARTICLEID_PUBMED) continue;
+            if (ids->data.intvalue != pmid) {
+              Message (MSG_POSTERR, "CitArt ID %ld does not match PMID %ld",
+                       (long) ids->data.intvalue, (long) pmid);
+            }
+          }
+          pub = ValNodeAddPointer (NULL, PUB_Article, (Pointer) cap);
+          ValNodeAddInt (&pub, PUB_PMid, pmid);
+          if (success != NULL) {
+            *success = TRUE;
+          }
+        }
+        mbp = MlaBackFree (mbp);
+      }
+    }
+  }
+
+  return pub;
+}
+
+
+static Boolean HasMoreThanOneISOJTA (TitleMsgPtr titles)
+{
+  TitleMsgPtr tmp;
+  ValNodePtr  ttl;
+  Int4 num_found = 0;
+
+  for (tmp = titles; tmp != NULL; tmp = tmp->next) {
+    for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
+      if (ttl->choice == Cit_title_iso_jta) {
+        if (num_found > 0) {
+          return TRUE;
+        }
+        num_found++;
+        break;
+      }
+    }
+  }
+  return FALSE;
+}
+
+
+static CharPtr GetExtendedDescription (TitleMsgPtr tmp) 
+{
+  CharPtr iso_jta = NULL, name = NULL, issn = NULL, extended = NULL;
+  ValNodePtr ttl;
+
+  if (tmp == NULL) {
+    return NULL;
+  }
+  
+  for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
+    if (ttl->choice == Cit_title_iso_jta) {
+      iso_jta = ttl->data.ptrvalue;
+    } else if (ttl->choice == Cit_title_name) {
+      name = ttl->data.ptrvalue;
+    } else if (ttl->choice == Cit_title_issn) {
+      issn = ttl->data.ptrvalue;
+    }
+  }
+  if (iso_jta == NULL) {
+    return NULL;
+  }
+  if (name == NULL && issn == NULL) {
+    extended = StringSave (iso_jta);
+  } else if (name == NULL) {
+    extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (issn) + 5));
+    sprintf (extended, "%s||(%s)", iso_jta, issn);
+  } else if (issn == NULL) {
+    extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (name) + 5));
+    sprintf (extended, "%s||(%s)", iso_jta, name);
+  } else {
+    extended = (CharPtr) MemNew (sizeof (Char) * (StringLen (iso_jta) + StringLen (name) + StringLen (issn) + 6));
+    sprintf (extended, "%s||(%s:%s)", iso_jta, name, issn);
+  }
+  return extended;
+}
+
+
+static Boolean LookupJournalFuncNew (CharPtr title, size_t maxsize, Int1Ptr jtaType, ValNodePtr PNTR all_titlesP)
+
+{
+  ValNodePtr       first = NULL;
+  ValNodePtr       last = NULL;
+  MlaBackPtr       mbp;
+  MlaRequestPtr    mrp;
+  CharPtr          str, end;
+  TitleMsgListPtr  tlp;
+  TitleMsgPtr      tmp;
+  ValNodePtr       ttl;
+  ValNodePtr       vnp;
+
+  if (all_titlesP != NULL) {
+    *all_titlesP = NULL;
+  }
+  if (jtaType != NULL) {
+    *jtaType = 0;
+  }
+  if (StringHasNoText (title)) return FALSE;
+
+#ifdef OS_UNIX
+  if (! log_mla_set) {
+    str = (CharPtr) getenv ("LOG_MLA_ASN");
+    if (StringDoesHaveText (str)) {
+      if (StringICmp (str, "TRUE") == 0) {
+        log_mla_asn = TRUE;
+      }
+    }
+    log_mla_set = TRUE;
+  }
+#endif
+
+  WatchCursor ();
+  Update ();
+
+  mrp = Mla2CreateJournalTitleRequest (title);
+  if (mrp != NULL) {
+  if (log_mla_asn) {
+    LaunchAsnTextViewer ((Pointer) mrp, (AsnWriteFunc) MlaRequestAsnWrite, "lookup journal request");
+  }
+    mbp = Mla2SynchronousQuery (mrp);
+    mrp = MlaRequestFree (mrp);
+    if (mbp != NULL) {
+      if (log_mla_asn) {
+        LaunchAsnTextViewer ((Pointer) mbp, (AsnWriteFunc) MlaBackAsnWrite, "lookup journal result");
+      }
+      tlp = Mla2ExtractJournalTitleReply (mbp);
+      if (tlp != NULL) {
+        if (HasMoreThanOneISOJTA (tlp->titles)) {
+          for (tmp = tlp->titles; tmp != NULL; tmp = tmp->next) {
+            str = GetExtendedDescription (tmp);
+            if (str != NULL) {
+              ValNodeAddPointer (&first, 0, str);
+            }
+          }
+        } else {
+          for (tmp = tlp->titles; tmp != NULL; tmp = tmp->next) {
+            for (ttl = tmp->title; ttl != NULL; ttl = ttl->next) {
+              if (ttl->choice != Cit_title_iso_jta) continue;
+              str = (CharPtr) ttl->data.ptrvalue;
+              if (StringHasNoText (str)) continue;
+              vnp = ValNodeCopyStr (&last, ttl->choice, str);
+              if (first == NULL) {
+                first = vnp;
+              }
+              last = vnp;
+            }
+          }
+        }
+        if (first != NULL) {
+          str = (CharPtr) first->data.ptrvalue;
+          StringNCpy_0 (title, str, maxsize);
+          end = StringSearch (title, "||");
+          if (end != NULL) {
+            *end = 0;
+          }
+          if (jtaType != NULL) {
+            *jtaType = Cit_title_iso_jta;
+          }
+        }
+        if (all_titlesP == NULL) {
+          first = ValNodeFreeData (first);
+        } else {
+          *all_titlesP = first;
+        }
+        tlp = TitleMsgListFree (tlp);
+      }
+      mbp = MlaBackFree (mbp);
+    }
+  }
+
+  ArrowCursor ();
+  Update ();
+
+  return TRUE;
+}
+
+
+static Boolean LoadReaderData ()
+{
+  Char  str [64];
+
+  if (! AllObjLoad ()) {
+    Message (MSG_FATAL, "AllObjLoad failed");
+    return FALSE;
+  }
+  if (! SubmitAsnLoad ()) {
+    Message (MSG_FATAL, "SubmitAsnLoad failed");
+    return FALSE;
+  }
+  if (! FeatDefSetLoad ()) {
+    Message (MSG_FATAL, "FeatDefSetLoad failed");
+    return FALSE;
+  }
+  if (! SeqCodeSetLoad ()) {
+    Message (MSG_FATAL, "SeqCodeSetLoad failed");
+    return FALSE;
+  }
+  if (! GeneticCodeTableLoad ()) {
+    Message (MSG_FATAL, "GeneticCodeTableLoad failed");
+    return FALSE;
+  }
+  
+  if (! PrintTemplateSetLoadEx ("objprt.prt", objPrtMemStr)) {
+    ArrowCursor ();
+    Message (MSG_FATAL, "PrintTemplateSetLoad objprt.prt failed");
+    return 0;
+  }
+
+  
+  SetupGeneticCodes ();
+
+  if (! LoadOrganismTable ()) {
+    ArrowCursor ();
+    Message (MSG_POSTERR, "LoadOrganismTable failed");
+  }
+  
+  MemSet ((Pointer) (&pubedprocs), 0, sizeof (PubdescEditProcs));
+  pubedprocs.lookupArticle = LookupAnArticleFuncNew;
+  pubedprocs.lookupJournal = LookupJournalFuncNew;
+  SetAppProperty ("PubdescEditForm", &pubedprocs);
+
+  useTaxon = FALSE;
+ #ifdef USE_TAXON
+  useTaxon = TRUE;
+#endif
+  if (LclGetSequinAppParam ("SETTINGS", "USETAXON", NULL, str, sizeof (str))) {
+    if (StringICmp (str, "TRUE") == 0) {
+      useTaxon = TRUE;
+    }
+  }
+  
+  if (LclGetSequinAppParam ("SETTINGS", "INDEXERVERSION", NULL, str, sizeof (str))) {
+      SetAppProperty ("InternalNcbiSequin", (void *) 1024);
+  }
+#ifdef INTERNAL_NCBI_SEQUIN
+  SetAppProperty ("InternalNcbiSequin", (void *) 1024);
+#endif
+
+ 
+  MemSet ((Pointer) (&biosrcedprocs), 0, sizeof (BioSourceEditProcs));
+  if (useTaxon) {
+    biosrcedprocs.lookupTaxonomy = LookupTaxonomyFunc;
+  }
+  SetAppProperty ("BioSourcEditForm", &biosrcedprocs);
+
+  return TRUE;
+}
+
+static void CloseStreamEditorForm (WindoW w)
+{
+  if (Message (MSG_OKC, "Are you sure you want to quit?") == ANS_CANCEL) {
+    return;
+  }
+  Remove (w);
+  QuitProgram ();
+}
+
+
+typedef struct streamfilterform {
+  FORM_MESSAGE_BLOCK
+
+  DialoG pub_dlg;
+
+  CharPtr    input_file;
+  CharPtr    output_file;
+  ValNodePtr desc_stream_list;
+  SeqIdPtr   sip_list;
+  Boolean    is_binary;
+  Boolean    is_batch;
+  Boolean    is_submit;
+} StreamFilterFormData, PNTR StreamFilterFormPtr;
+
+
+static void AcceptFilteringChanges (ButtoN b)
+{
+  StreamFilterFormPtr frm;
+  FILE                *fp;
+  FILE                *outfp;
+  Char                buf[PATH_MAX];
+  Boolean             move_output = FALSE;
+
+  frm = (StreamFilterFormPtr) GetObjectExtra (b);
+  if (frm == NULL) 
+  {
+    return;
+  }
+
+  fp = FileOpen (frm->input_file, "r");
+  if (fp == NULL) {
+    Message (MSG_ERROR, "Unable to open %s", frm->input_file);
+    return;
+  }
+  if (StringHasNoText (frm->output_file) || StringCmp (frm->input_file, frm->output_file) == 0) {
+    sprintf (buf, "%s.filter_tmp", frm->input_file);
+    outfp = FileOpen (buf, "w");       
+    move_output = TRUE;
+  } else {
+    outfp = FileOpen (frm->output_file, "w");
+  }
+  WriteAsnWithReplacedDescriptors (frm->desc_stream_list, fp, outfp, frm->is_binary, frm->is_batch, frm->is_submit);
+  FileClose (fp);
+  FileClose (outfp);  
+
+  if (move_output) {
+    FileRemove (frm->input_file);
+    FileRename (buf, frm->input_file);
+  }
+
+  Remove ((WindoW) frm->form);
+  QuitProgram ();
+}
+
+
+static void CancelStreamEditor (ButtoN b)
+{
+  StreamFilterFormPtr frm;
+
+  frm = (StreamFilterFormPtr) GetObjectExtra (b);
+  if (frm == NULL) 
+  {
+    return;
+  }
+
+  if (Message (MSG_OKC, "Are you sure you want to quit?") == ANS_CANCEL) {
+    return;
+  }
+
+  Remove ((WindoW) frm->form);
+  QuitProgram ();
+}
+
+
+static void CleanupStreamFilteringForm (GraphiC g, VoidPtr data)
+
+{
+  StreamFilterFormPtr  frm;
+
+  frm = (StreamFilterFormPtr) data;
+  if (frm != NULL) {
+    frm->desc_stream_list = DescStreamListFree(frm->desc_stream_list);
+  }
+  MemFree (data);
+}
+
+
+static WindoW MakeStreamFilteringWindow (CharPtr input_file, CharPtr output_file, Boolean is_binary, Boolean is_batch, Boolean is_submit)
+{
+  FILE         *fp;
+  ValNodePtr   tmp;
+  WindoW       w;
+  GrouP        h, g, c;
+  ButtoN       b;
+  StreamFilterFormPtr frm;
+  SeqIdPtr     sip_list = NULL;
+
+  fp = FileOpen (input_file, "r");
+  if (fp == NULL) {
+    Message (MSG_ERROR, "Unable to open %s", input_file);
+    return NULL;
+  }
+
+  tmp = StreamAsnForDescriptors(fp, is_binary, is_batch, is_submit, &sip_list);
+  FileClose (fp);
+
+  frm = (StreamFilterFormPtr) MemNew (sizeof (StreamFilterFormData));
+
+  w = FixedWindow (-50, -33, -10, -10, "Pub Editing", CloseStreamEditorForm);
+  h = HiddenGroup (w, -1, 0, NULL);
+  SetGroupSpacing (h, 10, 10);
+  frm->form = (ForM) w;
+  SetObjectExtra (w, frm, CleanupStreamFilteringForm);
+  
+  frm->input_file = input_file;
+  frm->output_file = output_file;
+  frm->desc_stream_list = tmp;
+  frm->sip_list = sip_list;
+  frm->is_binary = is_binary;
+  frm->is_batch = is_batch;
+  frm->is_submit = is_submit;
+
+  g = HiddenGroup (h, -1, 0, NULL);
+  frm->pub_dlg = DescriptorStreamEditor (g, NULL, NULL);
+  SetDescriptorStreamEditorIdList(frm->pub_dlg, frm->sip_list);
+  PointerToDialog (frm->pub_dlg, frm->desc_stream_list);
+
+  c = HiddenGroup (h, 2, 0, NULL);
+  b = DefaultButton (c, "Accept", AcceptFilteringChanges);
+  SetObjectExtra (b, frm, NULL);
+  b = PushButton (c, "Cancel", CancelStreamEditor);
+  SetObjectExtra (b, frm, NULL);
+  AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
+
+  return w;
+}
+
+
+#define STREAMER_APP_VER "1.0"
+
+CharPtr STREAMER_APPLICATION = STREAMER_APP_VER;
+
+
+Int2 Main (void)
+
+{
+
+  WindoW       w;
+  Char         app [64];
+  CharPtr      input_file = NULL;
+  CharPtr      output_file = NULL;
+  Boolean      is_binary = FALSE, is_batch = FALSE, is_submit = FALSE;
+  Int2         i;
+  Int4         argc = GetArgc();
+  CharPtr PNTR argv = GetArgv();
+  CharPtr      type = NULL;
+
+#if defined(OS_MAC) && !defined(OS_UNIX_DARWIN)
+  long           sysVer;
+#endif
+
+  ErrSetFatalLevel (SEV_MAX);
+  ErrClearOptFlags (EO_SHOW_USERSTR);
+  ProcessUpdatesFirst (FALSE);
+  
+  UseLocalAsnloadDataAndErrMsg ();
+  ErrPathReset ();
+
+#if defined(OS_MAC) && !defined(OS_UNIX_DARWIN)
+  if ( Gestalt (gestaltSystemVersion, &sysVer) == noErr) {
+    /* system version in low order word is hexadecimal */
+    if (sysVer >= 4096) {
+      Message (MSG_OK, "You are running on MacOS X and should use the native version of Sequin, not SequinOS9");
+    }
+  }
+#endif
+
+  if (! LoadReaderData ())
+  {
+    QuitProgram ();
+  }  
+
+  sprintf (app, "streamer %s", STREAMER_APPLICATION);
+  for (i = 1;  i < argc;  i++)
+  {
+    if (StringCmp (argv[i], "-i") == 0)
+    {
+      input_file = argv[i + 1];
+      i++;
+    }
+    else if (StringCmp (argv[i], "-o") == 0)
+    {
+      output_file = argv[i + 1];
+      i++;
+    }
+    else if (StringCmp (argv[i], "-b") == 0) 
+    {
+      is_binary = TRUE;
+    }
+    else if (StringCmp (argv[i], "-a") == 0)
+    {
+      if (i + 1 < argc) 
+      {
+        type = argv[i + 1];
+        i++;
+        if (StringCmp (type, "n") == 0) 
+        {
+          is_batch = TRUE;
+        }
+        else if (StringCmp (type, "m") == 0)
+        {
+          is_submit = TRUE;
+        }
+      }
+    }
+    else
+    {
+      Message (MSG_ERROR, "Unrecognized argument for %s", app);
+      QuitProgram();
+    }
+  }
+
+  if (StringHasNoText (input_file)) {
+    Message (MSG_ERROR, "No input file specified.");
+    QuitProgram();
+  }
+
+  w = (WindoW) MakeStreamFilteringWindow (input_file, output_file, is_binary, is_batch, is_submit);
+  
+  Show (w);
+  Update ();
+
+  ProcessEvents ();
+
+
+  ArrowCursor ();
+  Update ();
+
+
+  return 0;
+}
+
+
diff --git a/tools/blfmtutl.c b/tools/blfmtutl.c
index d03aa77..8431054 100644
--- a/tools/blfmtutl.c
+++ b/tools/blfmtutl.c
@@ -1,4 +1,4 @@
-static char const rcsid[] = "$Id: blfmtutl.c,v 1.38 2009/06/12 18:34:11 coulouri Exp $";
+static char const rcsid[] = "$Id: blfmtutl.c,v 1.41 2010/08/06 16:23:16 coulouri Exp $";
 
 /* ===========================================================================
 *
@@ -36,6 +36,15 @@ Contents: Utilities for BLAST formatting
 /*
 * $Revision: 
 * $Log: blfmtutl.c,v $
+* Revision 1.41  2010/08/06 16:23:16  coulouri
+* bump to 2.2.24
+*
+* Revision 1.40  2010/02/19 19:16:50  coulouri
+* bump version
+*
+* Revision 1.39  2009/09/25 17:41:31  coulouri
+* bump to 2.2.22
+*
 * Revision 1.38  2009/06/12 18:34:11  coulouri
 * bump version
 *
@@ -165,8 +174,8 @@ Contents: Utilities for BLAST formatting
 #include <jzcoll.h>
 
 /* the version of BLAST. */
-#define BLAST_ENGINE_VERSION "2.2.21"
-#define BLAST_RELEASE_DATE "Jun-14-2009"
+#define BLAST_ENGINE_VERSION "2.2.24"
+#define BLAST_RELEASE_DATE "Aug-08-2010"
 
 #define BUFFER_LENGTH 255
 
diff --git a/tools/readdb.c b/tools/readdb.c
index cf37d41..c8c371f 100644
--- a/tools/readdb.c
+++ b/tools/readdb.c
@@ -1,6 +1,6 @@
-static char const rcsid[] = "$Id: readdb.c,v 6.541 2009/02/24 18:19:36 coulouri Exp $";
+static char const rcsid[] = "$Id: readdb.c,v 6.544 2009/12/22 12:54:28 madden Exp $";
 
-/* $Id: readdb.c,v 6.541 2009/02/24 18:19:36 coulouri Exp $ */
+/* $Id: readdb.c,v 6.544 2009/12/22 12:54:28 madden Exp $ */
 /*
 * ===========================================================================
 *
@@ -50,7 +50,7 @@ Detailed Contents:
 *
 * Version Creation Date:   3/22/95
 *
-* $Revision: 6.541 $
+* $Revision: 6.544 $
 *
 * File Description: 
 *       Functions to rapidly read databases from files produced by formatdb.
@@ -65,6 +65,15 @@ Detailed Contents:
 *
 * RCS Modification History:
 * $Log: readdb.c,v $
+* Revision 6.544  2009/12/22 12:54:28  madden
+* Try stripped off path for microbial db, JIRA WB-313
+*
+* Revision 6.543  2009/09/17 15:41:43  madden
+* Consolidate checking of paths, JIRA SB-368
+*
+* Revision 6.542  2009/08/25 13:45:23  madden
+* Work with database with no GI ISAM, JIRA SB-367
+*
 * Revision 6.541  2009/02/24 18:19:36  coulouri
 * correct Nlm_StringTokMT invocation; fixes JIRA SB-181
 *
@@ -2700,25 +2709,37 @@ Int4ListReadFromFileEx (CharPtr lookup_dir,CharPtr fname)
     return listp;
 }
 
-Int4ListPtr LIBCALL
-Int4ListReadFromFile PROTO((CharPtr fname))
+/* read configuration and check file in all places */
+static void s_GetBlastDirInfo(char *blast_dir, char *path_delim)
 {
-    Int4ListPtr listp = NULL;
-    Char *wrk_buf,  blast_dir[PATH_MAX];
-    Char *one_blast_dir ;
-    Char path_delim[2];
     CharPtr envp = NULL;
-
     /* read configuration... */
-    memset(blast_dir,0,sizeof(blast_dir));
+    memset(blast_dir, 0, sizeof(blast_dir));
     if ((envp = getenv("BLASTDB")) == NULL) {
+      /* This checks current directory, user home directory, then path pointed to by $NCBI. */ 
       Nlm_GetAppParam ("NCBI", "BLAST", "BLASTDB", NULL, blast_dir, PATH_MAX);
     }
     else {
       StringCpy(blast_dir, envp);
     }
-    /* parse pathes and check files*/
+
     StringCpy(path_delim,":");
+
+    return;
+} 
+
+Int4ListPtr LIBCALL
+Int4ListReadFromFile PROTO((CharPtr fname))
+{
+    Int4ListPtr listp = NULL;
+    Char *wrk_buf;  
+    char blast_dir[PATH_MAX];
+    Char *one_blast_dir ;
+    char path_delim[2];
+
+    s_GetBlastDirInfo(blast_dir, path_delim);
+
+    /* parse paths and check files*/
     for( one_blast_dir = Nlm_StringTokMT(blast_dir,(char*)path_delim, (char **)&wrk_buf);
 	 one_blast_dir != NULL;
 	 one_blast_dir = Nlm_StringTokMT (NULL,(char*)path_delim, (char **)&wrk_buf) )
@@ -3480,21 +3501,15 @@ return NULL;
 
 CharPtr    FindBlastDBFile (CharPtr filename)
 {
-    Char *wrk_buf,  blast_dir[PATH_MAX];
+    Char *wrk_buf;  
+    char blast_dir[PATH_MAX];
     Char *one_blast_dir ;
-    Char path_delim[2];
-    CharPtr envp = NULL, found_name = NULL;
+    char path_delim[2];
+    CharPtr found_name = NULL;
 
-    /* read configuration and find file in all places */
-    memset(blast_dir,0,sizeof(blast_dir));
-    if ((envp = getenv("BLASTDB")) == NULL) {
-      Nlm_GetAppParam ("NCBI", "BLAST", "BLASTDB", NULL, blast_dir, PATH_MAX);
-    }
-    else {
-      StringCpy(blast_dir, envp);
-    }
-    /* parse pathes and lookup filename */
-    StringCpy(path_delim,":");
+    s_GetBlastDirInfo(blast_dir, path_delim);
+
+    /* parse paths and lookup filename */
     for( one_blast_dir = Nlm_StringTokMT (blast_dir,(char*)path_delim, (char **)&wrk_buf);
 	 one_blast_dir != NULL;
 	 one_blast_dir = Nlm_StringTokMT (NULL,(char*)path_delim, (char **)&wrk_buf) )
@@ -3869,24 +3884,15 @@ static ReadDBFILEPtr
 readdb_new_internal(CharPtr filename, Uint1 is_prot, Uint1 init_state, CommonIndexHeadPtr cih)
 {
     ReadDBFILEPtr ret_rdfp = NULL;
-    Char *wrk_buf,  blast_dir[PATH_MAX];
+    Char *wrk_buf;  
+    char blast_dir[PATH_MAX];
     Char *one_blast_dir;
-    Char path_delim[2];
-    CharPtr envp = NULL;
+    char path_delim[2];
     if( (ret_rdfp = readdb_new_internalEx(NULL,filename,is_prot,init_state,cih)) ){
 	return ret_rdfp;
     }
 
-    /* read configuration and check file in all places */
-    memset(blast_dir,0,sizeof(blast_dir));
-    if ((envp = getenv("BLASTDB")) == NULL) {
-      Nlm_GetAppParam ("NCBI", "BLAST", "BLASTDB", NULL, blast_dir, PATH_MAX);
-    }
-    else {
-      StringCpy(blast_dir, envp);
-    }
-    /* put all passes to ValNode list */
-    StringCpy(path_delim,":");
+    s_GetBlastDirInfo(blast_dir, path_delim);
 
     for( one_blast_dir = Nlm_StringTokMT (blast_dir,(char*)path_delim, (char **)&wrk_buf);
 	 one_blast_dir != NULL;
@@ -3895,6 +3901,9 @@ readdb_new_internal(CharPtr filename, Uint1 is_prot, Uint1 init_state, CommonInd
 	ret_rdfp = readdb_new_internalEx( one_blast_dir,filename,is_prot,init_state,cih);
 	if( ret_rdfp )  return ret_rdfp;
 
+        /* Try it again, stripping any path off the filename. */
+        ret_rdfp = readdb_new_internalEx( one_blast_dir, Nlm_FileNameFind(filename),is_prot,init_state,cih);
+	if( ret_rdfp )  return ret_rdfp;
     }
     return NULL;
 }
@@ -5132,6 +5141,7 @@ static Boolean readdb_find_best_id(SeqIdPtr sip, Int4Ptr gi, CharPtr tmpbuf)
     return TRUE;
 }
 
+#define READDB_TMPBUFF_SIZE 81
 /*
   Returnes Int4 sequence_number by SeqIdPtr using SISAM indexes:
   
@@ -5147,7 +5157,6 @@ readdb_seqid2fasta(ReadDBFILEPtr rdfp, SeqIdPtr sip)
 {
     ISAMErrorCode error;
     Int4 Value;
-    Char tmpbuff[81];
     CharPtr key_out = NULL, data = NULL;
     Uint4 index;
     Int4 gi = 0;
@@ -5155,6 +5164,9 @@ readdb_seqid2fasta(ReadDBFILEPtr rdfp, SeqIdPtr sip)
     SeqIdPtr bestid;
     TextSeqIdPtr tsip = NULL;
 
+    Char tmpbuff[READDB_TMPBUFF_SIZE];
+    CharPtr seqid_buff_ptr = tmpbuff;
+
     if(rdfp->sisam_opt == NULL || sip == NULL)
         return -1;
     
@@ -5178,11 +5190,12 @@ readdb_seqid2fasta(ReadDBFILEPtr rdfp, SeqIdPtr sip)
         }
 
         if(rdfp->sparse_idx) {
-            readdb_find_best_id(sip, &gi, tmpbuff);
+            readdb_find_best_id(sip, &gi, seqid_buff_ptr);
             if(gi != 0) {
                     return readdb_gi2seq(rdfp, gi, NULL);
             }
         } else {
+            Int4 i;
 
                switch (sip->choice) {
             case SEQID_EMBL:      /* embl */
@@ -5202,25 +5215,21 @@ readdb_seqid2fasta(ReadDBFILEPtr rdfp, SeqIdPtr sip)
                 break;
             }
 
-        /* We have to clear name if both accession and name exists */
-        if(tsip != NULL && tsip->accession != NULL && tsip->name != NULL) {
-            chptr = tsip->name;
-            tsip->name = NULL;
-        }
-        
-        if((SeqIdWrite(sip, tmpbuff, 
-                       PRINTID_FASTA_SHORT, sizeof(tmpbuff))) == NULL) {
+            if(tsip != NULL) {
+                Int4 dummy_gi = 0; /* Not used, should have been handled above. */
+                GetAccessionVersionFromSeqId(sip, &gi, &seqid_buff_ptr, TRUE);
+            } else {
+                if((SeqIdWrite(sip, seqid_buff_ptr, 
+                       PRINTID_FASTA_SHORT, READDB_TMPBUFF_SIZE-1)) == NULL)
             return -1;
         }
         
-        /* Returning back name */
-        if(chptr != NULL) {
-            tsip->name = chptr;
-        }
+            for(i = 0; seqid_buff_ptr[i] != '\0'; i++)
+                seqid_buff_ptr[i] = TO_LOWER(seqid_buff_ptr[i]);
     }
 
     NlmMutexLockEx(&isamsearch_mutex);
-        if((error = SISAMSearch(rdfp->sisam_opt, tmpbuff, 0, &key_out,
+        if((error = SISAMSearch(rdfp->sisam_opt, seqid_buff_ptr, 0, &key_out,
                                 &data, &index)) < 0) {
             ErrPostEx(SEV_WARNING, 0, 0, "Failed to search string index "
                       "ISAM Error code is %d\n", error);
@@ -5228,6 +5237,9 @@ readdb_seqid2fasta(ReadDBFILEPtr rdfp, SeqIdPtr sip)
         }
     NlmMutexUnlock(isamsearch_mutex);
         
+        if (tmpbuff != seqid_buff_ptr)
+          MemFree(seqid_buff_ptr); /* seqid_buff_ptr allocated in GetAccessionVersionFromSeqId. */
+        
         MemFree(key_out); /* We need no this for now */
         
         if(data && error != ISAMNotFound) {
diff --git a/tools/toasn3.c b/tools/toasn3.c
index a7297f3..3238204 100644
--- a/tools/toasn3.c
+++ b/tools/toasn3.c
@@ -1,4 +1,4 @@
-static char const rcsid[] = "$Id: toasn3.c,v 6.112 2009/06/04 16:14:29 kans Exp $";
+static char const rcsid[] = "$Id: toasn3.c,v 6.120 2010/07/15 20:09:00 kans Exp $";
 
 /*****************************************************************************
 *
@@ -133,15 +133,15 @@ static Int2 FindStr(CharPtr PNTR array, Int2 array_num, CharPtr str) {
 
 /*****************************************************************************
 *
-*   ToAsn4(sep)
+*   ToAsn4(sep, isEmblOrDdbj)
 *       Converts pubs to asn.1 spec 4.0 within SeqEntryPtr - SeqEntryPubsAsn4
 *        move tax lineage from GBblock to BioSource
 *****************************************************************************/
-Int4 ToAsn4 (SeqEntryPtr sep)
+Int4 ToAsn4 (SeqEntryPtr sep, Boolean isEmblOrDdbj)
 {
     CharPtr lineage = NULL;
     
-    SeqEntryPubsAsn4(sep);
+    SeqEntryPubsAsn4(sep, isEmblOrDdbj);
     SeqEntryExplore(sep, (Pointer) (&lineage), FindOldLineage);
     if (lineage) {
         SeqEntryExplore(sep, (Pointer) (&lineage), NewLineage);
@@ -698,14 +698,17 @@ static void HasSiteRef (SeqFeatPtr sfp, Pointer userdata)
 *   SeqEntryPubsAsn4(sep)
 *       Converts pubs to asn.1 spec 4.0 within SeqEntryPtr
 *****************************************************************************/
-Int4 SeqEntryPubsAsn4 (SeqEntryPtr sep)
+Int4 SeqEntryPubsAsn4Ex (SeqEntryPtr sep, Boolean isEmblOrDdbj, Boolean uniqueOnBioseq)
 {
+    BioseqPtr bsp = NULL;
     BioseqSetPtr bioset = NULL;
-    ValNodePtr vnp = NULL, publist= NULL, tmp, v;
+    ValNodePtr vnp = NULL, publist, tmp, v;
     PubdescPtr        pubdesc;
     Boolean foundSitRef = FALSE;
     
-    if (!IS_Bioseq(sep)) {
+    if (IS_Bioseq(sep)) {
+        bsp = (BioseqPtr) (sep->data.ptrvalue);
+    } else if (IS_Bioseq_set(sep)) {
         bioset = (BioseqSetPtr) (sep->data.ptrvalue); /* top level set */
     } 
     SeqEntryExplore(sep, &vnp, FindCit);
@@ -719,7 +722,8 @@ Int4 SeqEntryPubsAsn4 (SeqEntryPtr sep)
     SeqEntryExplore(sep, NULL, DeleteSites);
 
 /* move pubs in set to the top level */
-    if (bioset && bioset->_class != 9) {
+    if (bioset && bioset->_class != 9 && (! isEmblOrDdbj)) {
+        publist = NULL;
         SeqEntryExplore(sep, (Pointer) NULL, MoveSegmPubs);
         SeqEntryExplore(sep, (Pointer) NULL, MoveNPPubs);
 /*   unique pubs on the set level*/
@@ -736,10 +740,26 @@ Int4 SeqEntryPubsAsn4 (SeqEntryPtr sep)
         }
         vnp_list_free(tmp); 
     }
+    if (uniqueOnBioseq && bsp != NULL && (! isEmblOrDdbj)) {
+/*   unique pubs on the bioseq level*/
+        publist = NULL;
+        tmp = ValNodeExtractList(&bsp->descr, Seq_descr_pub);
+        for (v = tmp; v; v = v->next) {
+            pubdesc = v->data.ptrvalue;
+            publist = AddToList(publist, NULL, pubdesc);
+        }
+        bsp->descr = ValNodeLink(&(bsp->descr), publist);
+        vnp_list_free(tmp); 
+    }
     SeqEntryExplore(sep, NULL, ChangeCitSub);
     return 0;        
 }
 
+Int4 SeqEntryPubsAsn4 (SeqEntryPtr sep, Boolean isEmblOrDdbj)
+{
+    return SeqEntryPubsAsn4Ex(sep, isEmblOrDdbj, TRUE);
+}
+
 /*****************************************************************************
 *
 *  Remove old (ver 2.0)  asn.1 (with check for the new ver 3.0)
@@ -752,7 +772,7 @@ void StripOld (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
     OrgRefPtr    orp;
     SeqAnnotPtr    sap, ap, apnext;
     BioseqPtr    bsp = NULL;
-    BioseqSetPtr    bssp;
+    BioseqSetPtr    bssp = NULL;
     
     if (IS_Bioseq(sep)) {
         bsp = (BioseqPtr)(sep->data.ptrvalue);
@@ -787,9 +807,9 @@ void StripOld (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
             OrgRefFree(orp);
             MemFree(tmp);
         }
-        if (IS_Bioseq(sep)) {
+        if (bsp != NULL) {
             bsp->descr = vnp;
-        } else {
+        } else if (bssp != NULL) {
             bssp->descr = vnp;
         }
     }
@@ -811,9 +831,9 @@ void StripOld (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
             sap = remove_annot(sap, ap);
         }
     }
-    if (IS_Bioseq(sep)) {
+    if (bsp != NULL) {
         bsp->annot = sap;
-    } else {
+    } else if (bssp != NULL) {
         bssp->annot = sap;
     }
 }
@@ -826,8 +846,8 @@ void StripOld (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 ValNodePtr GetMultBiosource(SeqEntryPtr sep)
 {
     ValNodePtr bvnp, vnp, retval;
-    BioseqPtr bsp;
-    BioseqSetPtr bssp;
+    BioseqPtr bsp = NULL;
+    BioseqSetPtr bssp = NULL;
     
     if (sep == NULL)
         return NULL;
@@ -849,9 +869,9 @@ ValNodePtr GetMultBiosource(SeqEntryPtr sep)
         retval = NULL;
     }
     vnp = tie_next(vnp, bvnp);    
-    if (IS_Bioseq(sep)) {
+    if (bsp != NULL) {
         bsp->descr = vnp;    
-    } else {
+    } else if (bssp != NULL) {
         bssp->descr = vnp;    
     }
     return retval;    
@@ -956,7 +976,7 @@ static void RemoveEmptyTitleAndPubGenAsOnlyPub (SeqEntryPtr sep)
 Int4 SeqEntryToAsn3 (SeqEntryPtr sep, Boolean strip_old, Boolean source_correct, Boolean taxserver, SeqEntryFunc taxfun)
 {
     return SeqEntryToAsn3Ex(sep, strip_old, source_correct, 
-            taxserver, taxfun, NULL, FALSE);
+            taxserver, taxfun, NULL, FALSE, FALSE);
 }
 static Boolean is_equiv(SeqEntryPtr sep)
 {
@@ -1038,7 +1058,16 @@ static Int2 GetUpdateDatePos (SeqEntryPtr sep)
 *        txfun - Taxon3ReplaceOrgInSeqEntry
 *        taxmerge - Tax3MergeSourceDescr
 *****************************************************************************/
-Int4 SeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip_old, Boolean source_correct, Boolean taxserver, SeqEntryFunc taxfun, SeqEntryFunc taxmerge, Boolean gpipeMode)
+Int4 SeqEntryToAsn3Ex (
+SeqEntryPtr sep,
+Boolean strip_old,
+Boolean source_correct,
+Boolean taxserver,
+SeqEntryFunc taxfun,
+SeqEntryFunc taxmerge,
+Boolean gpipeMode,
+Boolean isEmblOrDdbj
+)
 {
     ToAsn3 ta;
     OrgFixPtr ofp = NULL;
@@ -1079,7 +1108,7 @@ Int4 SeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip_old, Boolean source_correc
         if(strip_old) {
             SeqEntryExplore(sep, NULL, StripOld);
         }
-        ToAsn4(sep);               /* move pubs and lineage */
+        ToAsn4(sep, isEmblOrDdbj);               /* move pubs and lineage */
         CombineBSFeat(sep);
         if (taxserver && taxfun != NULL) {
             SeqEntryExplore(sep, NULL, taxfun);
@@ -1117,7 +1146,9 @@ Int4 SeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip_old, Boolean source_correc
             SeqEntryExplore(sep, NULL, MapsToGenref);
         }
         */
+        if (! isEmblOrDdbj) {
         SeqEntryExplore(sep, NULL, MapsToGenref);
+        }
         CheckGeneticCode(sep);
         NormalizeSegSeqMolInfo (sep);
         toasn3_free(&ta);
@@ -1152,7 +1183,7 @@ Int4 SeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip_old, Boolean source_correc
     if(ta.had_biosource && strip_old) {
         SeqEntryExplore(sep, NULL, StripOld);
     }
-    ToAsn4(sep);          /* move pubs and lineage */
+    ToAsn4(sep, isEmblOrDdbj);          /* move pubs and lineage */
     if (taxserver && taxfun != NULL) {
         SeqEntryExplore(sep, NULL, taxfun);
     }
@@ -1189,7 +1220,9 @@ Int4 SeqEntryToAsn3Ex (SeqEntryPtr sep, Boolean strip_old, Boolean source_correc
         SeqEntryExplore(sep, NULL, MapsToGenref);
     }
     */
+    if (! isEmblOrDdbj) {
     SeqEntryExplore(sep, NULL, MapsToGenref);
+    }
     CheckGeneticCode(sep);
     NormalizeSegSeqMolInfo (sep);
     toasn3_free(&ta);
@@ -1498,7 +1531,7 @@ Int4 BSComparisonEx(BioSourcePtr one, BioSourcePtr two, Boolean clone)
 static CharPtr GetQualValue(GBQualPtr gbqual, CharPtr qual)
 {
     GBQualPtr    q;
-    CharPtr     value;
+    CharPtr     value = NULL;
     
         for(q = gbqual; q != NULL; q = q->next) {
             if (StringCmp(q->qual, qual) == 0) {
@@ -1745,7 +1778,7 @@ void CkOrg (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
     SeqFeatPtr    sfp, tmp_sfp = NULL;
     SeqAnnotPtr    sap;
     BioseqPtr    bsp = NULL;
-    BioseqSetPtr    bssp;
+    BioseqSetPtr    bssp = NULL;
     
     tap = (ToAsn3Ptr)data;
     if (!tap->had_biosource)
@@ -1783,9 +1816,9 @@ void CkOrg (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
     }
     sap->data = tmp_sfp;
     if (tmp_sfp == NULL) {
-        if (IS_Bioseq(sep)) {
+        if (bsp != NULL) {
             bsp->annot = NULL;
-        } else {
+        } else if (bssp != NULL) {
             bssp->annot = NULL;
         }
     }
@@ -1901,7 +1934,9 @@ Int4 FixNucProtSet(SeqEntryPtr sep)
 /*   quick fix of core dump in segmented sets with multiple organisms 
     BIOSOURCE feature is created on main segmeted bioseq (not parts) !*/
         s = bseg->seq_set;
+        if (s != NULL) {
         bsp = (BioseqPtr) s->data.ptrvalue;
+        }
         descr = bseg->descr;
         sap = bseg->annot;
     }
@@ -2468,17 +2503,17 @@ void CountSourceFeat (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 *****************************************************************************/
 void CorrectSourceFeat (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 {
-    Boolean        whole = FALSE, new;
+    Boolean        whole = FALSE, new = FALSE;
     Int2        count=0;
     Int4        len;
     ValNodePtr    vnp0, vnp;
-    SeqFeatPtr    sfp = NULL, tmp_sfp, f, ff, fnext;
+    SeqFeatPtr    sfp = NULL, tmp_sfp = NULL, f, ff, fnext;
     SeqAnnotPtr    sap;
     BioseqPtr    bsp = NULL;
     BioseqSetPtr    bssp;
     ImpFeatPtr    imp;
     OrgRefPtr    orp;
-    CharPtr        name, org_name, f_org, ff_org;
+    CharPtr        name, org_name, f_org = NULL, ff_org = NULL;
     GBQualPtr    q;
     SeqLocPtr     slp;
     static Char        msg[51];
@@ -2629,6 +2664,7 @@ Int2 BioSourceToGeneticCode (BioSourcePtr biop)
 {
   OrgNamePtr  onp;
   OrgRefPtr   orp;
+  Uint1       pgcode;
 
   if (biop != NULL) {
     orp = biop->org;
@@ -2646,7 +2682,15 @@ Int2 BioSourceToGeneticCode (BioSourcePtr biop)
                    biop->genome == GENOME_apicoplast ||
                    biop->genome == GENOME_leucoplast ||
                    biop->genome == GENOME_proplastid) {
+          if (onp->pgcode > 0) {
+            return onp->pgcode;
+          } else {
+            pgcode = GetSpecialPlastidGenCode (orp->taxname, onp->lineage);
+            if (pgcode > 0) {
+              return pgcode;
+            }
           return 11;
+          }
         } else {
           return onp->gcode;
         }
@@ -2867,7 +2911,7 @@ static void CheckGCode (SeqFeatPtr sfp, Pointer userdata)
     Uint1    code;
     SeqFeatPtr      f;
     CdRegionPtr     cds;
-    BioseqPtr         bsp;
+    BioseqPtr         bsp = NULL;
     SeqAnnotPtr     ap;
     ValNodePtr         vnp, vnpnext;
     DbtagPtr         db;
@@ -3081,8 +3125,8 @@ static CharPtr GetQualValuePos(CharPtr qval)
 
 static Uint1 GetQualValueAa(CharPtr qval)
 {
-   CharPtr  str, eptr, ptr;
-   Uint1    aa;
+   CharPtr  str, eptr = NULL, ptr;
+   Uint1    aa = 0;
 
     str = StringStr(qval, "aa:");
     if (str != NULL) {
@@ -3092,9 +3136,11 @@ static Uint1 GetQualValueAa(CharPtr qval)
            for (eptr = str; *eptr != ')' && *eptr != ' ' && *eptr != '\0'; eptr++) continue;
     }
 
+    if (eptr != NULL && str != NULL) {
     ptr = TextSave(str, eptr-str);
     aa = ValidAminoAcid(ptr);
     MemFree(ptr);  
+    }
 
     return (aa);
 
@@ -3115,7 +3161,7 @@ Boolean ImpFeatToCdregion(SeqFeatPtr sfp)
     SeqIntPtr        sip;
     SeqLocPtr         loc;
     BioseqPtr       bsp;
-    SeqIdPtr        sidp;
+    SeqIdPtr        sidp = NULL;
     
     if (sfp == NULL)
         return FALSE;
@@ -4089,7 +4135,7 @@ static void CdEndCheck(SeqFeatPtr sfp, FILE *fp)
 {
     ByteStorePtr newprot = NULL;
     BioseqPtr protseq, nucseq;
-    SeqLocPtr last=NULL, curr = NULL;
+    SeqLocPtr last= NULL, curr = NULL;
     Int4 len, remainder, aas, oldfrom, oldto, protlen, i, oldnum;
     CdRegionPtr crp;
     SeqIdPtr protid, tmp;
@@ -4101,7 +4147,7 @@ static void CdEndCheck(SeqFeatPtr sfp, FILE *fp)
     SeqLocPtr tmpslp;
     Int4 len2;
     SeqFeatPtr gene = NULL;
-    GeneRefPtr grp;
+    GeneRefPtr grp ;
     BioseqPtr bsp;
     SeqLocPtr slp;
   Boolean        hasNulls;
@@ -4176,10 +4222,11 @@ static void CdEndCheck(SeqFeatPtr sfp, FILE *fp)
         last = curr;
     }
 
-    if (last->choice != SEQLOC_INT)  /* this is too weird */
+    if (last != NULL && last->choice != SEQLOC_INT)  /* this is too weird */
     {
         return;
     }
+    if (last == NULL || last->data.ptrvalue == NULL) return;
     sip = (SeqIntPtr)(last->data.ptrvalue);
     nucseq = BioseqFind(sip->id);
     if (nucseq == NULL)
@@ -4799,7 +4846,7 @@ static void ProtFeatOnNucToImpFeat (SeqFeatPtr sfp, Pointer userdata)
   ImpFeatPtr  ifp;
   CharPtr     key = NULL;
   ProtRefPtr  prp;
-  CharPtr     str;
+  CharPtr     str = NULL;
   ValNodePtr  vnp;
 
   if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT) return;
diff --git a/tools/toasn3.h b/tools/toasn3.h
index a135038..b54685e 100644
--- a/tools/toasn3.h
+++ b/tools/toasn3.h
@@ -1,7 +1,7 @@
 #ifndef _TOASN3_
 #define _TOASN3_
 
-/*  $Id: toasn3.h,v 6.14 2009/06/03 20:13:16 kans Exp $
+/*  $Id: toasn3.h,v 6.19 2010/07/21 21:56:28 kans Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -109,10 +109,11 @@ typedef struct toasn3 {
 	Boolean had_molinfo;
 } ToAsn3, PNTR ToAsn3Ptr;
 
-Int4 ToAsn4(SeqEntryPtr sep);
-Int4 SeqEntryPubsAsn4(SeqEntryPtr sep);
+Int4 ToAsn4(SeqEntryPtr sep, Boolean isEmblOrDdbj);
+Int4 SeqEntryPubsAsn4(SeqEntryPtr sep, Boolean isEmblOrDdbj);
+Int4 SeqEntryPubsAsn4Ex(SeqEntryPtr sep, Boolean isEmblOrDdbj, Boolean uniqueOnBioseq);
 Int4 SeqEntryToAsn3(SeqEntryPtr sep, Boolean strip, Boolean correct, Boolean taxserver, SeqEntryFunc taxfun);
-Int4 SeqEntryToAsn3Ex(SeqEntryPtr sep, Boolean strip, Boolean correct, Boolean taxserver, SeqEntryFunc taxfun, SeqEntryFunc taxmerge, Boolean gpipeMode);
+Int4 SeqEntryToAsn3Ex(SeqEntryPtr sep, Boolean strip, Boolean correct, Boolean taxserver, SeqEntryFunc taxfun, SeqEntryFunc taxmerge, Boolean gpipeMode, Boolean isEmblOrDdbj);
 Int2 seq_loc_compare( SeqLocPtr a, SeqLocPtr b);
 void compare_quals(GBQualPtr PNTR qual1, GBQualPtr PNTR qual2);
 Boolean feat_join(SeqFeatPtr f1, SeqFeatPtr f2, SeqFeatPtr head);
@@ -214,6 +215,7 @@ extern Boolean NoBiosourceOrTaxonId (SeqEntryPtr sep);
 extern void ExtendGeneFeatIfOnMRNA (Uint2 entityID, SeqEntryPtr sep);
 extern void ConvertFullLenSourceFeatToDesc (SeqEntryPtr sep);
 extern void ConvertFullLenPubFeatToDesc (SeqEntryPtr sep);
+extern void CorrectGenCodes (SeqEntryPtr sep, Uint2 entityID);
 
 /* SeriousSeqEntryCleanup combines many of the above cleanups */
 
@@ -227,6 +229,10 @@ extern void SeriousSeqEntryCleanupBulk (SeqEntryPtr sep);
 
 extern void GpipeSeqEntryCleanup (SeqEntryPtr sep);
 
+/* SeriousSeqAnnotCleanup calls BasicSeqAnnotCleanup and adds a cleanup user object to annot-desc */
+
+extern void SeriousSeqAnnotCleanup (SeqAnnotPtr sap);
+
 
 #ifdef __cplusplus
 }
diff --git a/tools/toporg.c b/tools/toporg.c
index bd47d82..6a9cfea 100644
--- a/tools/toporg.c
+++ b/tools/toporg.c
@@ -1,4 +1,4 @@
-static char const rcsid[] = "$Id: toporg.c,v 6.118 2009/06/03 20:13:16 kans Exp $";
+static char const rcsid[] = "$Id: toporg.c,v 6.145 2010/07/21 21:56:28 kans Exp $";
 
 #include <stdio.h>
 #include <ncbi.h>
@@ -14,6 +14,7 @@ static char const rcsid[] = "$Id: toporg.c,v 6.118 2009/06/03 20:13:16 kans Exp
 #include <explore.h>
 #include <subutil.h>
 #include <tofasta.h>
+#include <objfdef.h>
 
 static ValNodePtr GetDescrNoTitles (ValNodePtr PNTR descr);
 
@@ -47,7 +48,7 @@ void ChkSegset (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 
   BioseqSetPtr  bssp, tmp;
   BioseqPtr     bsp;
-  SeqEntryPtr   segsep, parts;
+  SeqEntryPtr   segsep, parts = NULL;
   ValNodePtr    vnp = NULL, set_vnp = NULL, upd_date_vnp = NULL;
   ValNodePtr    org, modif, mol, date, v /*, title */;
   SeqAnnotPtr   sap = NULL;
@@ -94,6 +95,9 @@ void ChkSegset (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
         case SEQID_OTHER:      /* other */
         case SEQID_DDBJ:
         case SEQID_PRF:
+        case SEQID_TPG:
+        case SEQID_TPE:
+        case SEQID_TPD:
           continue;
         case SEQID_GIBBSQ:     /* gibbseq */
         case SEQID_GIBBMT:     /* gibbmt */
@@ -481,7 +485,7 @@ void MoveSegmPubs (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 {
 
   BioseqSetPtr  bssp, tmp;
-  SeqEntryPtr   segsep, parts;
+  SeqEntryPtr   segsep, parts = NULL;
   ValNodePtr    v, pub, vv, next;
   PubdescPtr    pdp, pdpv;
 
@@ -528,37 +532,91 @@ void MoveSegmPubs (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
   return;
 }
 
-void ChkNucProt (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
-{
+static Boolean AllPartsHaveTitles (BioseqSetPtr bssp)
 
-  BioseqSetPtr  bssp, tmp;
+{
   BioseqPtr     bsp;
-  SeqEntryPtr   seqsep;
-  ValNodePtr    descr = NULL, vnp;
+  SeqEntryPtr  sep;
+  CharPtr      str;
+
+  if (bssp == NULL) return FALSE;
+  for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
+    if (sep->choice != 1) return FALSE;
+    bsp = (BioseqPtr) sep->data.ptrvalue;
+    if (bsp == NULL) return FALSE;
+    str = BioseqGetTitle (bsp);
+    if (StringHasNoText (str)) return FALSE;
+  }
+
+  return TRUE;
+}
+
+void ChkNucProt (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
+{
+  BioseqSetPtr  bssp, tmp, bssp2, bssp3;
+  BioseqPtr     bsp = NULL, bsp2, bsp3, bsp4;
+  SeqEntryPtr   seqsep, sep2, sep3, sep4;
+  ValNodePtr    descr = NULL, head = NULL, vnp, next;
+  Int2Ptr       ip;
   Boolean       is_org = FALSE, is_modif = FALSE, is_title = FALSE;
-  Boolean       is_date = FALSE /* , is_pub = FALSE */;
+  Boolean       is_date = FALSE, is_nuc /* , is_pub = FALSE */;
   CharPtr       npstitle = NULL, seqtitle = NULL;
+  ValNodePtr    PNTR prev;
   Char          ch;
 
   if (IS_Bioseq(sep)) {
     return;
   }
   bssp = (BioseqSetPtr)(sep->data.ptrvalue);
-  if (bssp->_class != 1) {    /*  do the rest for nuc-prot only */
+  if (bssp->_class != BioseqseqSet_class_nuc_prot) {    /*  do the rest for nuc-prot only */
     return;
   }
   seqsep = bssp->seq_set;
-  if (seqsep == NULL) {
-    return;
+  if (seqsep == NULL || seqsep->data.ptrvalue == NULL) return;
+
+  /* if protein first, extract nucleotide, put first */
+  if (seqsep->choice == 1) {
+    bsp3 = seqsep->data.ptrvalue;
+    if (bsp3 != NULL && ISA_aa (bsp3->mol)) {
+      prev = (ValNodePtr PNTR) &(bssp->seq_set);
+      vnp = bssp->seq_set;
+      while (vnp != NULL) {
+        next = vnp->next;
+        is_nuc = FALSE;
+        if (IS_Bioseq (vnp)) {
+          bsp4 = (BioseqPtr) vnp->data.ptrvalue;
+          if (bsp4 != NULL && ISA_na (bsp4->mol)) {
+            is_nuc = TRUE;
+          }
+        }
+        if (is_nuc) {
+          *prev = vnp->next;
+          ValNodeLink (&head, vnp);
+          vnp->next = NULL;
+        } else {
+          prev = (ValNodePtr PNTR) &(vnp->next);
+        }
+        vnp = next;
   }
+      if (head != NULL) {
+        vnp = bssp->seq_set;
+        bssp->seq_set = head;
+        ValNodeLink (&(bssp->seq_set), vnp);
+      }
+    }
+
+    seqsep = bssp->seq_set;
+    if (seqsep == NULL || seqsep->data.ptrvalue == NULL) return;
+  }
+
   if (seqsep->choice == 1) {
     bsp = seqsep->data.ptrvalue;
     descr = bsp->descr;
-  }
-  if (seqsep->choice == 2) {
+  } else if (seqsep->choice == 2) {
     tmp = seqsep->data.ptrvalue;
     descr = tmp->descr;
   }
+  ip = (Int2Ptr) data;
   if (bssp->descr == NULL) {
     bssp->descr = GetDescrNoTitles(&descr);
   } else {
@@ -594,6 +652,63 @@ void ChkNucProt (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
         if (ch == '\0' || StringCmp (npstitle, ", and translated products") == 0) {
           vnp = ValNodeExtractList (&(bssp->descr), Seq_descr_title);
           ValNodeFreeData (vnp);
+          if (ip != NULL) {
+            *ip = 1;
+          }
+        } else {
+          /* now removing any unrelated title */
+          vnp = ValNodeExtractList (&(bssp->descr), Seq_descr_title);
+          ValNodeFreeData (vnp);
+          if (ip != NULL) {
+            *ip = 2;
+          }
+        }
+      } else if (bsp != NULL) {
+        /* if no nucleotide title, move nps title to it */
+        vnp = ValNodeExtractList (&(bssp->descr), Seq_descr_title);
+        bsp->descr = ValNodeLink (&(bsp->descr), vnp);
+        descr = bsp->descr;
+        if (ip != NULL) {
+          *ip = 3;
+        }
+      } else if (seqsep->choice == 2) {
+        if (ip != NULL) {
+          *ip = 4;
+        }
+        /* get segmented sequence in segset */
+        sep2 = bssp->seq_set;
+        if (sep2 != NULL && sep2->choice == 2 && SeqEntryGetTitle (sep2) == NULL) {
+          bssp2 = sep2->data.ptrvalue;
+          if (bssp2 != NULL && bssp2->_class == BioseqseqSet_class_segset) {
+            sep3 = bssp2->seq_set;
+            if (sep3 != NULL && sep3->choice == 1) {
+              bsp2 = sep3->data.ptrvalue;
+              if (bsp2 != NULL && BioseqGetTitle (bsp2) == NULL) {
+                sep4 = sep3->next;
+                if (sep4 != NULL && sep4->choice == 2) {
+                  bssp3 = sep4->data.ptrvalue;
+                  if (bssp3 != NULL && bssp3->_class == BioseqseqSet_class_parts) {
+                    if (AllPartsHaveTitles (bssp3)) {
+                      /* if no segmented nucleotide bioseq title, move nps title to it */
+                      vnp = ValNodeExtractList (&(bssp->descr), Seq_descr_title);
+                      bsp2->descr = ValNodeLink (&(bsp2->descr), vnp);
+                      if (ip != NULL) {
+                        *ip = 5;
+                      }
+                    } else {
+                      if (ip != NULL) {
+                        *ip = 6;
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      } else {
+        if (ip != NULL) {
+          *ip = 7;
         }
       }
     }
@@ -636,6 +751,7 @@ void ChkNucProt (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
   }
   return;
 }
+
 void MoveNPPubs (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 {
 
@@ -726,19 +842,21 @@ static SeqDescrPtr CheckSegsForPopPhyMut (SeqEntryPtr sep)
 {
   SeqDescrPtr    descr;
   ValNodePtr     head;
+  ValNodePtr     last;
   SeqDescrPtr    list = NULL;
   ObjValNodePtr  ovp;
   PubdescPtr     pdp1, pdp2;
   Boolean        same;
   SeqDescrPtr    sdp1, sdp2;
   SeqEntryPtr    tmp;
-  ValNodePtr     vnp1, vnp2;
+  ValNodePtr     vnp, vnp1, vnp2;
 
   for (sdp1 = GetSeqDescFromSeqEntry (sep); sdp1 != NULL; sdp1 = sdp1->next) {
     if (sdp1->choice != Seq_descr_pub) continue;
     pdp1 = (PubdescPtr) sdp1->data.ptrvalue;
     if (pdp1 == NULL) continue;
     head = NULL;
+    last = NULL;
     for (tmp = sep->next, same = FALSE; tmp != NULL; tmp = tmp->next) {
       for (sdp2 = GetSeqDescFromSeqEntry (tmp); sdp2 != NULL; sdp2 = sdp2->next) {
         if (sdp2->choice != Seq_descr_pub) continue;
@@ -747,7 +865,11 @@ static SeqDescrPtr CheckSegsForPopPhyMut (SeqEntryPtr sep)
         if (PubLabelMatchEx (pdp1->pub, pdp2->pub) == 0) {
           if (PubdescMatch (pdp1, pdp2)) {
             same = TRUE;
-            ValNodeAddPointer (&head, 0, (Pointer) sdp2);
+            vnp = ValNodeAddPointer (&last, 0, (Pointer) sdp2);
+            if (head == NULL) {
+              head = vnp;
+            }
+            last = vnp;
             break;
           }
         }
@@ -881,7 +1003,8 @@ static void MoveFeatsOnPartsProc (BioseqSetPtr bssp, Pointer userdata)
       prevsfp = (Pointer PNTR) &(sap->data);
       while (sfp != NULL) {
         nextsfp = sfp->next;
-        target = GetBioseqGivenSeqLoc (sfp->location, sfp->idx.entityID);
+        /* target = GetBioseqGivenSeqLoc (sfp->location, sfp->idx.entityID); */
+        target = BioseqFindFromSeqLoc (sfp->location);
         if (target != NULL) {
           *(prevsfp) = sfp->next;
           sfp->next = NULL;
@@ -1442,25 +1565,35 @@ void StripProtXref (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
   SeqFeatXrefPtr  xrp, xrpnext;
   SeqIdPtr        sid;
   SeqLocPtr       slp;
+  TextSeqIdPtr    tsip;
 
   if (IS_Bioseq(sep)) {
     bsp = (BioseqPtr)(sep->data.ptrvalue);
     sap = bsp->annot;
+    if (bsp != NULL) {
+      for (sid = bsp->id; sid != NULL; sid = sid->next) {
+        if (sid->choice != SEQID_OTHER) continue;
+        tsip = (TextSeqIdPtr) sid->data.ptrvalue;
+        if (tsip == NULL) continue;
+        if (StringNCmp (tsip->accession, "NG_", 3) == 0) return;
+      }
+    }
   }
   else {
     bssp = (BioseqSetPtr)(sep->data.ptrvalue);
     sap = bssp->annot;
   }
   for (ap = sap; ap != NULL; ap = ap->next) {
-    if (ap->type != 1) {
-      continue;
-    }
+    if (ap->type != 1) continue;
     head = (SeqFeatPtr)(ap->data);
     for (sfp = head; sfp; sfp = sfp->next) {
-      if (sfp->data.choice != SEQFEAT_CDREGION) {
-        continue;
-      }
-      if ((vnp = sfp->product) != NULL) {
+      if (sfp->data.choice != SEQFEAT_CDREGION) continue;
+      prot = NULL;
+      pap = NULL;
+      psfp = NULL;
+      pprp = NULL;
+      vnp = sfp->product;
+      if (vnp != NULL) {
         if (vnp->choice == SEQLOC_WHOLE) {
           sid = vnp->data.ptrvalue;
           prot = BioseqFind(sid);
@@ -1477,7 +1610,7 @@ void StripProtXref (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
           }
         }
       }
-      if (vnp) {         /* sfp->product != NULL */
+      if (vnp != NULL) {         /* sfp->product != NULL */
         for (xrp = sfp->xref; xrp != NULL; xrp = xrpnext) {
           xrpnext = xrp->next;
           if (xrp->data.choice == SEQFEAT_PROT) {
@@ -1867,6 +2000,16 @@ static Boolean CheckMinPub(ValNodePtr pub, Boolean is_ref_seq_prot)
   return FALSE;
 }
 
+static Boolean OkayToFuseRemarks (CharPtr com1, CharPtr com2)
+
+{
+  if (com1 != NULL && com2 != NULL) {
+    if (StringICmp (com1, com2) != 0) return FALSE;
+  }
+
+  return TRUE;
+}
+
 static ValNodePtr AddToListEx (ValNodePtr list, ValNodePtr check, PubdescPtr pdp, Boolean is_ref_seq_prot)
 {
   ValNodePtr    v, vnext;
@@ -1911,13 +2054,18 @@ static ValNodePtr AddToListEx (ValNodePtr list, ValNodePtr check, PubdescPtr pdp
     } else {
       pubequ2 = pdp->pub;
     }
-    if (PubLabelMatchEx (pubequ1, pubequ2) == 0) {
+    if (PubLabelMatchEx (pubequ1, pubequ2) == 0 && OkayToFuseRemarks (pdp->comment, vpdp->comment)) {
       if (pdp->reftype == 2 && vpdp->reftype == 1) {
         vpdp->reftype = 2;
       }
       if (pdp->reftype == 1 && vpdp->reftype == 2) {
         pdp->reftype = 2;
       }
+      if (vpdp->comment != NULL && pdp->comment == NULL) {
+        pdp->comment = StringSave (vpdp->comment);
+      } else if (vpdp->comment == NULL && pdp->comment != NULL) {
+        vpdp->comment = StringSave (pdp->comment);
+      }
       if (SelectBestPub(pubequ1, pubequ2) >= 0) {
         if (is_1) {
           ValNodeFree(pubequ1);
@@ -2717,6 +2865,8 @@ static void CheckForEmblDdbjID (SeqEntryPtr sep, Pointer mydata, Int4 index, Int
       switch (sip->choice) {
         case SEQID_EMBL :
         case SEQID_DDBJ :
+        case SEQID_TPE :
+        case SEQID_TPD :
           *isEmblOrDdbj = TRUE;
           break;
           break;
@@ -2994,6 +3144,7 @@ extern void CleanupEmptyFeatCallback (SeqEntryPtr sep, Pointer mydata, Int4 inde
                 ifp->key = StringSave ("misc_feature");
                 sfp->data.choice = SEQFEAT_IMP;
                 sfp->data.value.ptrvalue = (Pointer) ifp;
+                sfp->idx.subtype = 0;
                 GeneRefFree (grp);
                 empty = FALSE;
               }
@@ -3366,7 +3517,15 @@ extern void ConvertFullLenSourceFeatToDesc (SeqEntryPtr sep)
   DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
 }
 
-static Int4 LoopSeqEntryToAsn3 (SeqEntryPtr sep, Boolean strip, Boolean correct, SeqEntryFunc taxfun, SeqEntryFunc taxmerge, Boolean gpipeMode)
+static Int4 LoopSeqEntryToAsn3 (
+  SeqEntryPtr sep,
+  Boolean strip,
+  Boolean correct,
+  SeqEntryFunc taxfun,
+  SeqEntryFunc taxmerge,
+  Boolean gpipeMode,
+  Boolean isEmblOrDdbj
+)
 
 {
   BioseqSetPtr  bssp;
@@ -3381,14 +3540,14 @@ static Int4 LoopSeqEntryToAsn3 (SeqEntryPtr sep, Boolean strip, Boolean correct,
                          (bssp->_class >= 13 && bssp->_class <= 16) ||
                          bssp->_class == BioseqseqSet_class_wgs_set)) {
       for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
-        rsult += LoopSeqEntryToAsn3 (sep, strip, correct, taxfun, taxmerge, gpipeMode);
+        rsult += LoopSeqEntryToAsn3 (sep, strip, correct, taxfun, taxmerge, gpipeMode, isEmblOrDdbj);
       }
       return rsult;
     }
   }
   oldscope = SeqEntrySetScope (sep);
   taxserver = (Boolean) (taxfun != NULL || taxmerge != NULL);
-  rsult = SeqEntryToAsn3Ex (sep, strip, correct, taxserver, taxfun, taxmerge, gpipeMode);
+  rsult = SeqEntryToAsn3Ex (sep, strip, correct, taxserver, taxfun, taxmerge, gpipeMode, isEmblOrDdbj);
   SeqEntrySetScope (oldscope);
   return rsult;
 }
@@ -3554,6 +3713,7 @@ static void MergeEquivCitSubs (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2
   CitSubPtr      csp1, csp2;
   SeqDescrPtr    descr = NULL;
   SeqDescrPtr    lastcit;
+  PubdescPtr     lastpdp;
   ObjValNodePtr  ovp;
   PubdescPtr     pdp;
   SeqDescrPtr    sdp;
@@ -3569,14 +3729,16 @@ static void MergeEquivCitSubs (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2
   } else return;
 
   lastcit = NULL;
+  lastpdp = NULL;
   for (sdp = descr; sdp != NULL; sdp = sdp->next) {
     if (sdp->choice != Seq_descr_pub) continue;
     pdp = (PubdescPtr) sdp->data.ptrvalue;
     if (pdp == NULL) continue;
-    if (lastcit != NULL) {
+    if (lastcit != NULL && lastpdp != NULL) {
       csp2 = GetCspFromPdp (pdp);
       if (csp2 != NULL) {
-        if (CitSubsMatch (csp1, csp2)) {
+        if (CitSubsMatch (csp1, csp2) &&
+            OkayToFuseRemarks (pdp->comment, lastpdp->comment)) {
           alp1 = csp1->authors;
           alp2 = csp2->authors;
           if (alp1 != NULL && alp2 != NULL) {
@@ -3585,6 +3747,10 @@ static void MergeEquivCitSubs (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2
               alp2->affil = NULL;
             }
           }
+          if (lastpdp->comment == NULL && pdp->comment != NULL) {
+            lastpdp->comment = pdp->comment;
+            pdp->comment = NULL;
+          }
           if (sdp->extended != 0) {
             ovp = (ObjValNodePtr) sdp;
             ovp->idx.deleteme = TRUE;
@@ -3600,6 +3766,7 @@ static void MergeEquivCitSubs (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2
         lastcit = sdp;
       }
     }
+    lastpdp = pdp;
   }
 }
 
@@ -4512,7 +4679,7 @@ static void CleanupOldName (BioSourcePtr biop, Pointer userdata)
   omp = *prev;
   while (omp != NULL) {
     next = omp->next;
-    if (omp->subtype == ORGMOD_old_name && StringCmp (orp->taxname, omp->subname) == 0) {
+    if (omp->subtype == ORGMOD_old_name && StringCmp (orp->taxname, omp->subname) == 0 && StringHasNoText (omp->attrib)) {
       *prev = omp->next;
       omp->next = NULL;
       OrgModFree (omp);
@@ -4759,11 +4926,12 @@ static void MarkBadProtTitlesInNucProts (SeqEntryPtr sep)
   if (! IS_Bioseq_set (sep)) return;
   bssp = (BioseqSetPtr) sep->data.ptrvalue;
   if (bssp == NULL) return;
-  if (bssp->_class == 7 ||
-      (bssp->_class >= 13 && bssp->_class <= 16) ||
+  if (bssp->_class == BioseqseqSet_class_genbank ||
+      (bssp->_class >= BioseqseqSet_class_mut_set && bssp->_class <= BioseqseqSet_class_eco_set) ||
       bssp->_class == BioseqseqSet_class_wgs_set) {
     for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
-      StripTitleFromProtsInNucProts (sep);
+      /* StripTitleFromProtsInNucProts (sep); */
+      MarkBadProtTitlesInNucProts (sep);
     }
     return;
   }
@@ -4824,6 +4992,7 @@ static void SeriousSeqEntryCleanupEx (SeqEntryPtr sep, SeqEntryFunc taxfun, SeqE
   entityID = SeqMgrGetEntityIDForSeqEntry (sep);
   /* clear indexes, since CleanupEmptyFeatCallback removes genes, etc. */
   SeqMgrClearFeatureIndexes (entityID, NULL);
+  RemoveAllNcbiCleanupUserObjects (sep);
   MemSet ((Pointer) objMgrFilter, FALSE, sizeof (objMgrFilter));
   objMgrFilter [OBJ_SEQFEAT] = TRUE;
   GatherObjectsInEntity (entityID, 0, NULL, MarkMovedGeneGbquals, (Pointer) &hasMarkedGenes, objMgrFilter);
@@ -4858,10 +5027,12 @@ static void SeriousSeqEntryCleanupEx (SeqEntryPtr sep, SeqEntryFunc taxfun, SeqE
   VisitFeaturesInSep (sep, (Pointer) &muid, RemoveBadPubFeat);
   SeqEntryExplore (sep, (Pointer) &muid, MergePubFigInChain);
   VisitFeaturesInSep (sep, NULL, CorrectSfpExceptText);
+  if (! isEmblOrDdbj) {
   SeqEntryExplore (sep, NULL, MergeEquivCitSubs);
+  }
   DeleteMarkedObjects (0, OBJ_SEQENTRY, (Pointer) sep);
   EntryMergeDupBioSources (sep); /* do before and after SE2A3 */
-  LoopSeqEntryToAsn3 (sep, TRUE, FALSE, taxfun, taxmerge, gpipeMode);
+  LoopSeqEntryToAsn3 (sep, TRUE, FALSE, taxfun, taxmerge, gpipeMode, isEmblOrDdbj);
   /* EntryStripSerialNumber(sep); */ /* strip citation serial numbers */
   MovePopPhyMutPubs (sep);
   EntryChangeGBSource (sep);   /* at least remove redundant information in GBBlocks */
@@ -4910,6 +5081,8 @@ static void SeriousSeqEntryCleanupEx (SeqEntryPtr sep, SeqEntryFunc taxfun, SeqE
   VisitBioSourcesInSep (sep, NULL, CleanupOldName);
   VisitBioSourcesInSep (sep, NULL, CleanupOrgModNote);
   CdCheck (sep, NULL);
+  /* do again to catch occasional duplicate pub on some set components */
+  SeqEntryPubsAsn4 (sep, isEmblOrDdbj);
   SeqMgrIndexFeatures (entityID, NULL);
   if (hasMarkedGenes) {
     MemSet ((Pointer) objMgrFilter, FALSE, sizeof (objMgrFilter));
@@ -4952,3 +5125,222 @@ extern void GpipeSeqEntryCleanup (SeqEntryPtr sep)
   SeriousSeqEntryCleanupEx (sep, NULL, NULL, TRUE, TRUE);
 }
 
+extern void SeriousSeqAnnotCleanup (SeqAnnotPtr sap)
+
+{
+  AnnotDescrPtr  adp;
+  DatePtr        dp;
+  AnnotDescrPtr  last;
+  UserObjectPtr  uop;
+
+  if (sap == NULL) return;
+
+  RemoveAllSeqAnnotCleanupUserObjs (sap);
+
+  BasicSeqAnnotCleanup (sap);
+
+  dp = DateCurr ();
+  if (dp == NULL) return;
+
+  uop = CreateNcbiCleanupUserObject ();
+  if (uop == NULL) return;
+
+  AddStringToNcbiCleanupUserObject (uop, "method", "SeriousSeqAnnotCleanup");
+  AddIntegerToNcbiCleanupUserObject (uop, "version", NCBI_CLEANUP_VERSION);
+
+  AddIntegerToNcbiCleanupUserObject (uop, "month", dp->data [2]);
+  AddIntegerToNcbiCleanupUserObject (uop, "day", dp->data [3]);
+  AddIntegerToNcbiCleanupUserObject (uop, "year", dp->data [1] + 1900);
+
+  adp = AnnotDescrNew (NULL);
+  if (adp == NULL) return;
+
+  adp->choice = Annot_descr_user;
+  adp->data.ptrvalue = uop;
+
+  if (sap->desc == NULL) {
+    sap->desc = adp;
+  } else {
+    last = sap->desc;
+    while (last->next != NULL) {
+      last = last->next;
+    }
+    last->next = adp;
+  }
+}
+
+static void CorrectGenCodeIndexedCallback (SeqFeatPtr sfp, Pointer userdata)
+{
+  CdRegionPtr     crp;
+  GeneticCodePtr  gc;
+  Int2Ptr         pGenCode;
+  ValNodePtr      vnp;
+  Boolean         need_replacement = FALSE;
+
+  if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION 
+      || sfp->data.value.ptrvalue == NULL
+      || userdata == NULL) return;
+ 
+  pGenCode = (Int2Ptr) userdata;
+  crp = (CdRegionPtr) sfp->data.value.ptrvalue;
+  if (crp->genetic_code != NULL
+      && crp->genetic_code->choice == 254) {
+    if (crp->genetic_code->data.ptrvalue == NULL) {
+      vnp = ValNodeNew (NULL);
+      vnp->choice = 2;
+      vnp->data.intvalue = (Int4) *pGenCode;
+    } else {
+      vnp = crp->genetic_code->data.ptrvalue;
+      if (vnp->next == NULL && vnp->choice == 2) {
+        vnp->data.intvalue = (Int4) *pGenCode;
+      } else {
+        need_replacement = TRUE;
+      }
+    }
+  } else {
+    need_replacement = TRUE;
+  }
+  if (need_replacement) {
+    gc = GeneticCodeNew ();
+    if (gc == NULL) return;
+    crp->genetic_code = GeneticCodeFree (crp->genetic_code);
+    vnp = ValNodeNew (NULL);
+    gc->data.ptrvalue = vnp;
+    if (vnp != NULL) {
+      vnp->choice = 2;
+      vnp->data.intvalue = (Int4) *pGenCode;
+    }
+    crp->genetic_code = gc;
+  }
+}
+
+static void CorrectGenCodesBioseqCallback (BioseqPtr bsp, Pointer userdata)
+{
+  SeqMgrFeatContext fcontext;
+  SeqFeatPtr        sfp;
+
+  if (bsp == NULL || userdata == NULL) return;
+  for (sfp = SeqMgrGetNextFeature (bsp, NULL, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext);
+       sfp != NULL;
+       sfp = SeqMgrGetNextFeature (bsp, sfp, SEQFEAT_CDREGION, FEATDEF_CDS, &fcontext)) {
+    CorrectGenCodeIndexedCallback (sfp, userdata);
+  }
+
+}
+
+typedef struct gencodescan {
+  Boolean mito;
+  Boolean plastid;
+  Int2    nuclCode;
+  Int2    mitoCode;
+  Int2    pstdCode;
+  Boolean already_found;
+} GenCodeScanData, PNTR GenCodeScanPtr;
+
+static void JustGetGenCodeFromOrgRef (OrgRefPtr orp, GenCodeScanPtr gp)
+{
+  OrgNamePtr onp;
+
+  if (orp == NULL || orp->orgname == NULL || gp == NULL || gp->already_found) return;
+  onp = orp->orgname;
+
+  gp->nuclCode = onp->gcode;
+  gp->mitoCode = onp->mgcode;
+  gp->pstdCode = onp->pgcode;
+}
+
+static void JustGetGenCodeFromBiop (BioSourcePtr biop, GenCodeScanPtr gp)
+{
+  if (biop == NULL || gp == NULL) return;
+  if (gp->already_found && !biop->is_focus) return;
+
+  gp->mito = (Boolean) (biop->genome == GENOME_kinetoplast ||
+                        biop->genome == GENOME_mitochondrion ||
+                        biop->genome == GENOME_hydrogenosome);
+
+  gp->plastid = (Boolean) (biop->genome == GENOME_chloroplast ||
+                                biop->genome == GENOME_chromoplast ||
+                                biop->genome == GENOME_plastid ||
+                                biop->genome == GENOME_cyanelle ||
+                                biop->genome == GENOME_apicoplast ||
+                                biop->genome == GENOME_leucoplast ||
+                                biop->genome == GENOME_proplastid ||
+                                biop->genome == GENOME_chromatophore);
+
+  JustGetGenCodeFromOrgRef (biop->org, gp);
+  gp->already_found = TRUE;
+}
+
+
+static void JustGetGenCodeFromFeat (SeqFeatPtr sfp, Pointer userdata) 
+{
+  GenCodeScanPtr gp;
+
+  if (sfp == NULL || userdata == NULL || sfp->data.choice != SEQFEAT_BIOSRC) return;
+
+  gp = (GenCodeScanPtr) userdata;
+
+  JustGetGenCodeFromBiop (sfp->data.value.ptrvalue, gp);
+}
+
+static void JustGetGenCodeFromDesc (SeqDescrPtr sdp, Pointer userdata)
+{
+  GenCodeScanPtr gp;
+
+  if (sdp == NULL || userdata == NULL || sdp->choice != Seq_descr_source) return;
+
+  gp = (GenCodeScanPtr) userdata;
+
+  JustGetGenCodeFromBiop (sdp->data.ptrvalue, gp);
+}
+
+static Int2 JustGetGenCodeForSeqEntry (SeqEntryPtr sep) 
+{
+  GenCodeScanData gd;
+
+  gd.already_found = FALSE;
+  gd.mito = FALSE;
+  gd.mitoCode = 0;
+  gd.nuclCode = 0;
+  gd.pstdCode = 0;
+  gd.plastid = FALSE;
+
+  VisitDescriptorsInSep (sep, &gd, JustGetGenCodeFromDesc);
+  VisitFeaturesInSep (sep, &gd, JustGetGenCodeFromFeat);
+
+  if (gd.plastid) {
+    if (gd.pstdCode > 0) {
+      return gd.pstdCode;
+    } else {
+      return 11;
+    }
+  } else if (gd.mito) {
+    return gd.mitoCode;
+  } else {
+    return gd.nuclCode;
+  }
+}
+
+extern void CorrectGenCodes (SeqEntryPtr sep, Uint2 entityID)
+
+{
+  BioseqSetPtr  bssp;
+  Int2          genCode;
+
+  if (sep == NULL) return;
+  if (IS_Bioseq_set (sep)) {
+    bssp = (BioseqSetPtr) sep->data.ptrvalue;
+    if (bssp != NULL && (bssp->_class == 7 ||
+                         (IsPopPhyEtcSet (bssp->_class)))) {
+      for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
+        CorrectGenCodes (sep, entityID);
+      }
+      return;
+    }
+  }
+
+  genCode = JustGetGenCodeForSeqEntry(sep);
+  VisitFeaturesInSep (sep, &genCode, CorrectGenCodeIndexedCallback);
+  VisitBioseqsInSep (sep, &genCode, CorrectGenCodesBioseqCallback);
+}
+
diff --git a/tools/toporg.h b/tools/toporg.h
index decde68..2063c93 100644
--- a/tools/toporg.h
+++ b/tools/toporg.h
@@ -1,7 +1,7 @@
 #ifndef _TOPORG_
 #define _TOPORG_
 
-/*  $Id: toporg.h,v 6.7 2009/06/03 18:30:57 kans Exp $
+/*  $Id: toporg.h,v 6.10 2010/01/27 19:02:40 kans Exp $
  * ===========================================================================
  *
  *                            PUBLIC DOMAIN NOTICE
@@ -45,7 +45,7 @@ extern "C" {
 
 /* increment NCBI_CLEANUP_VERSION on every BSEC or SSEC change */
 
-#define NCBI_CLEANUP_VERSION 4
+#define NCBI_CLEANUP_VERSION 7
 
 #define Seq_descr_GIBB_mod_dna         0
 #define Seq_descr_GIBB_mod_rna         1
diff --git a/util/creaders/alnread.c b/util/creaders/alnread.c
index 302dbe8..2cc099c 100644
--- a/util/creaders/alnread.c
+++ b/util/creaders/alnread.c
@@ -1,5 +1,5 @@
 /*
- * $Id: alnread.c,v 1.33 2009/05/06 14:49:32 kazimird Exp $
+ * $Id: alnread.c,v 1.37 2010/04/22 15:24:36 kazimird Exp $
  *
  * ===========================================================================
  *
@@ -295,76 +295,6 @@ s_ReportInconsistentBlockLine
 }
 
 
-#if 0
-/* this section was removed by indexer request */
-/* This function creates and sends an error message regarding mismatched
- * definition lines
- */
-static void
-s_ReportDefinitionLineMismatch
-(FReportErrorFunction report_error,
- void *              report_error_userdata)
-{
-    TErrorInfoPtr eip;
-
-    if (report_error == NULL) {
-        return;
-    }
-    eip = ErrorInfoNew (NULL);
-    if (eip == NULL) {
-        return;
-    }
-
-    eip->category = eAlnErr_BadData;
-    eip->message = strdup ("Mismatched definition lines");
-    report_error (eip, report_error_userdata);
-}
-#endif
-
-
-/* This function recursively creates and sends an error message 
- * regarding the number of times items in list appear.
- */
-static void 
-s_ReportDefinitionLines 
-(TStringCountPtr      list,
- FReportErrorFunction report_error,
- void *              report_error_userdata)
-{
-    TErrorInfoPtr eip;
-    const char *  err_null_format = "Null definition line occurs %d times";
-    const char *  err_format = "Definition line %s occurs %d times";
-
-    if (list == NULL  ||  report_error == NULL) {
-        return;
-    }
-    eip = ErrorInfoNew (NULL);
-    if (eip == NULL) {
-        return;
-    }
-
-    eip->category = eAlnErr_BadData;
-    if (list->string == NULL) {
-        eip->message = (char*)malloc (strlen (err_null_format)
-                                      + kMaxPrintedIntLen + 1);
-        if (eip->message != NULL) {
-            sprintf (eip->message, err_null_format, list->num_appearances);
-        }
-    } else {
-        eip->message = (char*)malloc (strlen (err_format)
-                                      + strlen (list->string)
-                                      + kMaxPrintedIntLen + 1);
-        if (eip->message != NULL) {
-            sprintf (eip->message, err_format, list->string,
-                     list->num_appearances);
-        }
-    }
-    report_error (eip, report_error_userdata);
-  
-    s_ReportDefinitionLines (list->next, report_error, report_error_userdata);
-}
-
-  
 /* This function creates and sends an error message regarding a line of
  * sequence data that was expected to be a different length.
  */
@@ -714,7 +644,7 @@ s_ReportASN1Error
         eip->category = eAlnErr_BadData;
         eip->message = (char *) malloc (strlen (msg) + 1);
         if (eip->message != NULL) {
-            sprintf (eip->message, msg);
+            sprintf (eip->message, "%s", msg);
         }
         errfunc (eip, errdata);
     }
@@ -2517,6 +2447,22 @@ static EBool s_SkippableNexusComment (char *str)
 }
 
 
+static EBool s_IsOnlyNumbersAndSpaces (char *str)
+{
+    if (str == NULL) {
+        return eFalse;
+    }
+
+    while (*str != 0) {
+        if (!isspace (*str) && !isdigit(*str)) {
+            return eFalse;
+        }
+        ++str;
+    }
+    return eTrue;
+}
+
+
 /* This function determines whether the contents of str are "skippable"
  * in that they do not contain sequence data and therefore should not be
  * considered part of any block patterns or sequence data.
@@ -2529,6 +2475,7 @@ static EBool s_SkippableString (char * str)
         ||  s_StringNICmp (str, "CLUSTAL W", 8) == 0
         ||  s_SkippableNexusComment (str)
         ||  s_IsTwoNumbersSeparatedBySpace (str)
+        ||  s_IsOnlyNumbersAndSpaces (str)
         ||  s_IsConsensusLine (str)
         ||  str [0] == ';') {
         return eTrue;
@@ -5737,38 +5684,6 @@ static EBool s_AreOrganismsUnique (SAlignRawFilePtr afrp)
 }
 
 
-#if 0 /* this step was removed by indexer request */
-/* This function reports whether the definition lines are identical for
- * each sequence or not.
- */
-static EBool s_AreDeflinesIdentical (SAlignRawFilePtr afrp)
-{
-    TLineInfoPtr    lip;
-    TStringCountPtr list;
-    EBool           rval;
-
-    if (afrp == NULL) {
-        return eFalse;
-    }
-
-    list = NULL;
-    for (lip = afrp->deflines;  lip != NULL;  lip = lip->next) {
-        list = s_AddStringCount (lip->data, lip->line_num, list);
-    }
-    rval = eTrue;
-    if (list != NULL  &&  list->next != NULL) {
-        rval = eFalse; 
-        s_ReportDefinitionLineMismatch (afrp->report_error,
-                                      afrp->report_error_userdata);
-        s_ReportDefinitionLines (list, afrp->report_error,
-                               afrp->report_error_userdata);
-    }
-    s_StringCountFree (list);
-    return rval;
-}
-#endif
-
-
 /* This function uses the contents of an SAlignRawFileData structure to
  * create an SAlignmentFile structure with the appropriate information.
  */
@@ -6001,11 +5916,6 @@ ReadAlignmentFileEx
 
     s_ReprocessIds (afrp);
 
-#if 0 /* this step was removed by indexer request */
-    /* Note - have to check deflines after reprocessing IDs */
-    s_AreDeflinesIdentical (afrp);
-#endif
-
     if (s_s_FindBadDataCharsInSequenceList (afrp, sequence_info)) {
         s_AlignFileRawFree (afrp);
         return NULL;
diff --git a/vibrant/mapping.c b/vibrant/mapping.c
index 70724b2..9d305ae 100644
--- a/vibrant/mapping.c
+++ b/vibrant/mapping.c
@@ -29,24 +29,13 @@
 *
 * Version Creation Date:   1/19/93
 *
-* $Revision: 6.4 $
+* $Revision: 6.5 $
 *
 * File Description: 
 *
 * Modifications:  
 * --------------------------------------------------------------------------
-* $Log: mapping.c,v $
-* Revision 6.4  1999/10/04 17:16:31  kans
-* include ncbidraw.h instead of vibrant.h, a couple Nlm_ prefixes
 *
-* Revision 6.3  1999/08/06 19:29:45  vakatov
-* "NormalizeBox()":  bottom >= top!
-*
-* Revision 6.2  1999/08/06 18:42:32  vakatov
-* Moved "NormalizeBox()" from "viewer.c" to "mappingp.[ch]" & made it public
-*
-* Revision 6.1  1998/06/12 16:40:24  kans
-* fixed warnings detected by unix compiler
 * ==========================================================================
 */
 
@@ -168,6 +157,7 @@ extern void Nlm_MapRectToWorldBox
 
 static Int4 MapX (Int4 pntX, VScalePtr scale)
 {
+  if (scale == NULL || scale->scaleX == 0) return 0;
   return (Int4) scale->view.left + (pntX - scale->port.left) / scale->scaleX;
 }
 
@@ -180,6 +170,7 @@ static Int4 MapX (Int4 pntX, VScalePtr scale)
 
 static Int4 MapY (Int4 pntY, VScalePtr scale)
 {
+  if (scale == NULL || scale->scaleY == 0) return 0;
   return (Int4)scale->view.bottom - (pntY - scale->port.bottom)/scale->scaleY;
 }
 
diff --git a/vibrant/ncbidraw.c b/vibrant/ncbidraw.c
index 5d673de..c1afe3a 100644
--- a/vibrant/ncbidraw.c
+++ b/vibrant/ncbidraw.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   1/1/91
 *
-* $Revision: 6.45 $
+* $Revision: 6.46 $
 *
 * File Description: 
 *       Vibrant drawing functions.
@@ -67,6 +67,12 @@
 #  endif
 #  ifdef WIN_MAC
 #    undef WIN_MAC
+#    ifdef WIN_MAC_ATSUI
+#      undef WIN_MAC_ATSUI
+#    endif
+#    ifdef WIN_MAC_QUARTZ
+#      undef WIN_MAC_QUARTZ
+#    endif
 #    define Nlm_RgnTool Handle
 #  endif
 #  ifdef WIN_MSWIN
diff --git a/vibrant/vibutils.c b/vibrant/vibutils.c
index 89160ae..8dce248 100644
--- a/vibrant/vibutils.c
+++ b/vibrant/vibutils.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/1/91
 *
-* $Revision: 6.78 $
+* $Revision: 6.80 $
 *
 * File Description:
 *       Vibrant miscellaneous functions
@@ -608,10 +608,10 @@ static MsgAnswer LIBCALLBACK Nlm_VibMessageHook (MsgKey key, ErrSev severity,
                                                  const char * caption,
                                                  const char * message)
 {
+  Nlm_CharPtr  buf = NULL;
   Nlm_Int2     rsult = 0;
 #if defined(WIN_MAC) || defined(WIN_MOTIF)
   size_t       len;
-  Nlm_CharPtr  buf = NULL;
   Nlm_ButtoN   b[3];
   Nlm_Char     ch;
   Nlm_Int2     delta;
@@ -647,7 +647,7 @@ static MsgAnswer LIBCALLBACK Nlm_VibMessageHook (MsgKey key, ErrSev severity,
       size_t curr_len = Nlm_TextLength(postText);
       size_t add_len  = Nlm_StringLen( message );
       if (curr_len < 1000000 && add_len < 1000000) {
-        char*  buf    = (char*) Nlm_MemNew(add_len+1 + curr_len + 1);
+        buf = (char*) Nlm_MemNew(add_len+1 + curr_len + 1);
         Nlm_MemCpy(buf, add_mess, add_len);
         buf[add_len++] = '\n';
         Nlm_GetTitle(postText, buf+add_len, curr_len+1);
@@ -3655,7 +3655,6 @@ extern Nlm_Boolean Nlm_ClipboardHasString (void)
 # if TARGET_API_MAC_CARBON
   OSStatus status;
   ScrapRef scrap;
-  ScrapFlavorFlags flags = 0;
   status = GetCurrentScrap(&scrap);
   
   err = TEFromScrap();
@@ -3715,7 +3714,7 @@ extern Nlm_CharPtr Nlm_ClipboardToString (void)
   return str;
 #else
   long         len;
-  Nlm_CharPtr  str;
+  Nlm_CharPtr  str = NULL;
   Handle hdl;
 
 # if TARGET_API_MAC_CARBON
diff --git a/vibrant/vibwndws.c b/vibrant/vibwndws.c
index ccec78a..0d7be6c 100644
--- a/vibrant/vibwndws.c
+++ b/vibrant/vibwndws.c
@@ -29,7 +29,7 @@
 *
 * Version Creation Date:   7/1/91
 *
-* $Revision: 6.84 $
+* $Revision: 6.87 $
 *
 * File Description:
 *       Vibrant main, event loop, and window functions
@@ -2498,7 +2498,7 @@ static Nlm_WindoW Nlm_NextVisWindow (Nlm_WindoW w)
 
 {
   WindowPtr  p;
-  WindowPtr  q;
+  WindowPtr  q = NULL;
 
   if (w == Nlm_desktopWindow) {
     return Nlm_desktopWindow;
@@ -6306,7 +6306,7 @@ static void ParseSetupArguments(HINSTANCE hInstance, Nlm_CharPtr lpszCmdLine)
     p++;
   else
     p = winfile;
-  SetAppProperty("ProgramName", p);
+  SetProgramName(p);
 
   if (!lpszCmdLine  ||  !*lpszCmdLine)
     {
@@ -7751,6 +7751,27 @@ static Nlm_Boolean FetchArg(Nlm_ArgPtr arg, const char *str,
 }
 
 
+static Nlm_Int2 NumReturnsIn (Nlm_CharPtr prompt)
+
+{
+  Nlm_Char  ch;
+  Nlm_Int2  count = 0;
+
+  if (StringHasNoText (prompt)) return 0;
+
+  ch = *prompt;
+  while (ch != '\0') {
+    if (ch == '\r' || ch == '\n') {
+      count++;
+    }
+    prompt++;
+    ch = *prompt;
+  }
+
+  return count;
+}
+
+
 static Nlm_Boolean GetArgs_ST(const char* progname,
                               Nlm_Int2 numargs, Nlm_ArgPtr ap,
                               Nlm_Boolean silent)
@@ -7791,6 +7812,8 @@ static const char* s_ValueStrings[] = {
   Nlm_HandlePtr  hp;
   Nlm_RecT       r1;
   Nlm_RecT       r2;
+  Nlm_Boolean    new_line;
+  Nlm_Boolean    largeScreen;
   Nlm_Boolean    smallScreen;
   Nlm_Char       tag [16];
   Nlm_WindoW     w;
@@ -7939,25 +7962,50 @@ static const char* s_ValueStrings[] = {
   /* Arg-Query Dialog Box */ 
   w = Nlm_FixedWindow (-50, -33, -10, -10, (Nlm_CharPtr) progname, NULL);
   smallScreen = FALSE;
+  largeScreen = FALSE;
 #ifdef WIN_MAC
-  if (Nlm_screenRect.right < 513  ||  Nlm_screenRect.bottom < 343)
+  if (Nlm_screenRect.right < 513  ||  Nlm_screenRect.bottom < 343) {
     smallScreen = TRUE;
+  }
+  if (Nlm_screenRect.right > 1200  &&  Nlm_screenRect.bottom > 800) {
+    largeScreen = TRUE;
+  }
 #endif
 #ifdef WIN_MSWIN
-  if (Nlm_screenRect.bottom < 352)
+  if (Nlm_screenRect.bottom < 352) {
     smallScreen = TRUE;
+  }
+  if (Nlm_screenRect.bottom > 800) {
+    largeScreen = TRUE;
+  }
 #endif
   g = Nlm_HiddenGroup (w, 5, 0, NULL);
   hp = (Nlm_HandlePtr) Nlm_MemNew (numargs * sizeof (Nlm_Handle));
 
   firstText = NULL;
   curarg = ap;
-  for (i = 0, j = 0; i < numargs; i++, j++, curarg++) {
-    if ((smallScreen && j >= 10) || j >= 15) {
+  for (i = 0, j = 0; i < numargs; i++, curarg++) {
+    new_line = FALSE;
+    if (smallScreen) {
+      if (j >= 10) {
+        new_line = TRUE;
+      }
+    } else if (largeScreen) {
+      if (j >= 30) {
+        new_line = TRUE;
+      }
+    } else {
+      if (j >= 15) {
+        new_line = TRUE;
+      }
+    }
+    if (new_line) {
       j = 0;
       Nlm_Advance (w);
       g = Nlm_HiddenGroup (w, 5, 0, NULL);
     }
+    j++;
+    j += NumReturnsIn ((Nlm_CharPtr) curarg->prompt);
 
     Nlm_StaticPrompt(g, (char*)s_TypeStrings[curarg->type], 0,
                      Nlm_dialogTextHeight, Nlm_systemFont, 'l');
