1 /* $Id: wwwblast.c,v 1.16 2011/12/19 18:41:34 gouriano Exp $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name:  $RCSfile: wwwblast.c,v $
27 *
28 * Author:  Sergei Shavirin
29 *
30 * Initial Creation Date: 03/15/2000
31 *
32 * $Revision: 1.16 $
33 *
34 * File Description:
35 *        Standalone WWW Blast CGI program.
36 *
37 * $Log: wwwblast.c,v $
38 * Revision 1.16  2011/12/19 18:41:34  gouriano
39 * Corrected printf formatting. NOJIRA
40 *
41 * Revision 1.15  2004/05/03 15:11:46  dondosha
42 * Added support for masking query in XML output
43 *
44 * Revision 1.14  2004/03/02 16:44:11  dondosha
45 * Do not print closing </form> for XML output
46 *
47 * Revision 1.13  2004/01/16 17:35:20  dondosha
48 * Fixed mouseover problems
49 *
50 * Revision 1.12  2003/11/20 22:19:35  dondosha
51 * Pass www_root_path to the PrintDefLines... function
52 *
53 * Revision 1.11  2003/11/20 20:10:52  dondosha
54 * Decide whether to print header only after the output type is determined
55 *
56 * Revision 1.10  2003/11/20 19:10:33  dondosha
57 * Do not print progress messages if XML output requested
58 *
59 * Revision 1.9  2003/11/05 22:40:28  dondosha
60 * Do not shift coordinates for tabular output if query is a subsequence - they are already shifted in the seqalign
61 *
62 * Revision 1.8  2003/06/04 16:12:51  dondosha
63 * Set db genetic code for formatting
64 *
65 * Revision 1.7  2003/05/13 22:00:37  dondosha
66 * More changes to make alternative links work
67 *
68 * Revision 1.6  2003/05/13 21:17:01  dondosha
69 * Pass www_blast_type to txalign in all cases
70 *
71 * Revision 1.5  2003/05/09 21:09:05  dondosha
72 * Removed unused variables
73 *
74 * Revision 1.4  2003/05/02 23:04:03  dondosha
75 * Fixed paths for non-standard setups, removed blast_form.map
76 *
77 * Revision 1.3  2003/04/29 15:55:56  dondosha
78 * Always use root path in links
79 *
80 * Revision 1.2  2003/02/10 21:48:53  dondosha
81 * Added support for multi-query XML output
82 *
83 * Revision 1.1  2002/12/02 18:05:53  dondosha
84 * Moved from different locations to a common one
85 *
86 * Revision 6.32  2002/06/19 22:50:17  dondosha
87 * Added all queries information for tabular output with multiple queries
88 *
89 * Revision 6.31  2002/06/18 21:14:28  dondosha
90 * Added return statement in the end of AppendMegaBlastHit
91 *
92 * Revision 6.30  2002/01/08 22:36:25  dondosha
93 * Added tabular output functionality
94 *
95 * Revision 6.29  2000/11/29 16:11:31  dondosha
96 * If multiple queries, send proper lower case mask to the search engine
97 *
98 * Revision 6.28  2000/11/17 14:40:04  dondosha
99 * Changed MegaBlastResultsNew call to MemNew
100 *
101 * Revision 6.27  2000/11/16 22:37:07  dondosha
102 * Added endpoint Mega BLAST results handling
103 *
104 * Revision 6.26  2000/10/31 20:18:52  shavirin
105 * Added printing of correct XML output when no hits found
106 * Added printing progeress messages to avoid browser timeout.
107 *
108 * Revision 6.25  2000/10/23 20:19:57  dondosha
109 * Open and close AsnIo outside calls to BXMLPrintOutput function
110 *
111 * Revision 6.24  2000/10/18 20:19:31  shavirin
112 * Added title for OOF Blastx.
113 *
114 * Revision 6.23  2000/10/16 22:18:17  shavirin
115 * Added possibility to perform OOF blastx
116 *
117 * Revision 6.22  2000/10/16 20:27:03  shavirin
118 * Added possibility to run RPS Blast.
119 *
120 * Revision 6.21  2000/09/28 16:48:20  dondosha
121 * Changed MegaBlast related code to get a single SeqAlignPtr from server
122 *
123 * Revision 6.20  2000/09/28 15:16:55  shavirin
124 * Added message if request was limited to results of Entrez query.
125 *
126 * Revision 6.19  2000/09/27 22:17:04  shavirin
127 * Added possibility to limit search to results of entrez query.
128 *
129 * Revision 6.18  2000/09/13 22:28:10  dondosha
130 * Removed extra </PRE> that is now printed in PrintDefLinesFromSeqAlign
131 *
132 * Revision 6.17  2000/09/13 20:47:51  dondosha
133 * Small cleanup with closures of html blocks
134 *
135 * Revision 6.16  2000/09/12 21:57:28  dondosha
136 * Pass the correct scoring matrix to ShowTextAlignFromAnnot
137 *
138 * Revision 6.15  2000/09/11 17:51:07  shavirin
139 * Removed redundant <PRE> tag.
140 *
141 * Revision 6.14  2000/09/08 20:18:12  dondosha
142 * Print the title, background and GIF image before creating options
143 *
144 * Revision 6.13  2000/09/08 14:49:28  dondosha
145 * Allow graphical overview with multiple queries
146 *
147 * Revision 6.12  2000/09/07 18:01:38  dondosha
148 * Pass a callback to the server from TraditionalBlastReportEngineWithImage; allow multiple queries for all BLAST searches
149 *
150 * Revision 6.11  2000/09/05 18:00:25  dondosha
151 * Added query acknowledgement for each query in WWWBlastDoSearch for megablast
152 *
153 * Revision 6.10  2000/09/01 17:55:14  dondosha
154 * Call SeqEntryLoad at the beginning; corrections for megablast page
155 *
156 * Revision 6.9  2000/08/30 22:22:35  dondosha
157 * Enhance function WWWBlastDoSearch to handle megablast search
158 *
159 * Revision 6.8  2000/08/28 20:20:59  dondosha
160 * Added functionality for megablast web page
161 *
162 * Revision 6.7  2000/08/09 20:30:30  shavirin
163 * Added possibility to print XML output.
164 *
165 * Revision 6.6  2000/07/31 20:44:12  shavirin
166 * Minor change (initialized variable) from Haruna Cofer (haruna@detroit.sgi.com)
167 *
168 * Revision 6.5  2000/05/17 15:50:51  shavirin
169 * Moved many functions to the wwwbutl.c file.
170 *
171 * Revision 6.4  2000/04/21 18:10:59  shavirin
172 * Added possibility to print Patrick's alignment.
173 *
174 * Revision 6.3  2000/03/28 14:44:20  shavirin
175 * Changed function ctime_r to ctime() for compatibility.
176 *
177 * Revision 6.2  2000/03/24 16:05:37  shavirin
178 * Added option to be used as NCBI client/server.
179 *
180 * Revision 6.1  2000/03/20 19:01:00  shavirin
181 * Initial revision.
182 *
183 *
184 * ==========================================================================
185 */
186 
187 #include <wwwblast.h>
188 #include <xmlblast.h>
189 
WWWTickCallback(Int4 sequence_number,Int4 number_of_positive_hits)190 static int LIBCALLBACK WWWTickCallback(Int4 sequence_number,
191                                        Int4 number_of_positive_hits)
192 {
193     if(!TestSTDOut()) {
194 	return -1;
195     }
196 
197     /*    fprintf(stdout, "."); */
198 
199     printf("<!-- Progress msg from the server %d %d-->\n",
200            sequence_number, number_of_positive_hits);
201 
202     fflush(stdout);
203 
204     return 1;
205 }
206 
207 /* Callback in case of XML output should not print anything to the stdout */
WWWXMLTickCallback(Int4 sequence_number,Int4 number_of_positive_hits)208 static int LIBCALLBACK WWWXMLTickCallback(Int4 sequence_number,
209                                           Int4 number_of_positive_hits)
210 {
211    if(!TestSTDOut()) {
212       return -1;
213    }
214    fflush(stdout);
215 
216    return 1;
217 }
218 
get_number_alignment(SeqAlignPtr align)219 static Int4 get_number_alignment(SeqAlignPtr align)
220 {
221     Int4 num = 0;
222 
223     while(align)
224     {
225 	++num;
226 	align = align->next;
227     }
228 
229     return num;
230 }
231 static void
PrintMotd(CharPtr string,FILE * fp,Boolean html_format)232 PrintMotd(CharPtr string, FILE *fp, Boolean html_format)
233 
234 {
235     Char buffer[100];
236     CharPtr ptr;
237 
238     if (string == NULL)
239         return;
240 
241     buffer[0] = NULLB;
242     ptr = buffer;
243 
244     if (html_format) {
245         fprintf(fp, "<PRE>\n");
246     }
247 
248     while (*string != NULLB) {
249         if (*string == '~') {
250             *ptr = NULLB;
251             fprintf(fp, "%s\n", buffer);
252             buffer[0] = NULLB;
253             ptr = buffer;
254             string++;
255             if (*string == NULLB)
256                 break;
257         } else {
258             *ptr=*string;
259             ptr++;  string++;
260         }
261     }
262     *ptr = NULLB;
263     fprintf(fp, "%s\n", buffer);
264 
265     if (html_format) {
266         fprintf(fp, "</PRE>\n");
267     }
268 
269     fflush(fp);
270 
271     return;
272 }
273 #ifdef NCBI_CLIENT_SERVER
274 
275 static  Boolean LIBCALLBACK
callback(BlastResponsePtr brp,Boolean PNTR cancel)276 callback (BlastResponsePtr brp, Boolean PNTR cancel)
277 
278 {
279         fprintf(stdout, "</PRE>\n<PRE>");
280 	return TRUE;
281 }
282 
283 static Boolean
TraditionalBlastReportEngineWithImage(SeqLocPtr slp,BioseqPtr bsp,BlastNet3Hptr bl3hp,WWWBlastInfoPtr theInfo)284 TraditionalBlastReportEngineWithImage(SeqLocPtr slp, BioseqPtr bsp, BlastNet3Hptr bl3hp, WWWBlastInfoPtr theInfo)
285 
286 {
287     BlastDbinfoPtr dbinfo;
288     BlastKABlkPtr ka_params=NULL, ka_params_gap=NULL;
289     BlastPruneSapStructPtr prune;
290     BLAST_MatrixPtr matrix;
291     Int4Ptr PNTR txmatrix;
292     Boolean query_is_na, db_is_na;
293     Boolean status;
294     CharPtr params_buffer=NULL;
295     Int4 number_of_hits_private=0, length;
296     SeqAlignPtr seqalign = NULL, sap, next_seqalign;
297     SeqAnnotPtr seqannot=NULL;
298     TxDfDbInfoPtr tx_dbinfo=NULL, tx_dbinfo_head;
299     ValNodePtr mask_loc = NULL, mask_loc_start, next_mask_loc = NULL;
300     SeqLocPtr mask_slp = NULL;
301     ValNodePtr other_returns, error_returns, vnp, vnp1=NULL;
302     Uint1 align_type;
303     Uint1 f_order[FEATDEF_ANY], g_order[FEATDEF_ANY];
304     /* Variables for multiple query output */
305     SeqLocPtr tmp_slp;
306     Boolean done = TRUE;
307     BLAST_OptionsBlkPtr options = theInfo->options;
308     CharPtr program = theInfo->program, database = theInfo->database;
309     Uint4 align_options = theInfo->align_options;
310     DenseSegPtr dsp, next_dsp;
311     AsnIoPtr xml_aip;
312     MegaBlastResultsPtr mb_results = NULL;
313     Boolean tabular_output = (theInfo->align_view == HitTable ||
314                               theInfo->align_view == HitTableWithHeader);
315 
316     MemSet((Pointer)(g_order), 0, (size_t)(FEATDEF_ANY* sizeof(Uint1)));
317     MemSet((Pointer)(f_order), 0, (size_t)(FEATDEF_ANY* sizeof(Uint1)));
318 
319     if (bsp == NULL && slp == NULL)
320         return FALSE;
321 
322     if (bl3hp == NULL || program == NULL || database == NULL)
323         return FALSE;
324 
325     align_type = BlastGetTypes(program, &query_is_na, &db_is_na);
326 
327     init_buff_ex(85);
328     dbinfo = BlastRequestDbInfo(bl3hp, database, !db_is_na);
329 
330     if (dbinfo && !tabular_output &&
331         !(options->is_megablast_search && options->no_traceback))
332         PrintDbInformationBasic(database, !db_is_na, 70, dbinfo->definition, dbinfo->number_seqs, dbinfo->total_length, stdout, TRUE);
333     dbinfo = BlastDbinfoFree(dbinfo);
334     free_buff();
335 
336     if (bsp)
337         seqalign = BlastBioseqNetCore(bl3hp, bsp, program, database, options, &other_returns, &error_returns, callback, NULL, &status);
338     else if (options->is_megablast_search) {
339         seqalign = MegaBlastSeqLocNetCore(bl3hp, slp, program, database, options, &other_returns, &error_returns, callback, &status);
340     } else
341         seqalign = BlastSeqLocNetCore(bl3hp, slp, program, database, options, &other_returns, &error_returns, callback, NULL, &status);
342 
343 
344     BlastErrorPrintExtra(error_returns, TRUE, stdout);
345 
346     mask_loc = next_mask_loc = NULL;
347     matrix = NULL;
348     txmatrix = NULL;
349     for (vnp=other_returns; vnp; vnp = vnp->next) {
350         switch (vnp->choice) {
351            case BlastResponse_mbalign:
352            mb_results = (MegaBlastResultsPtr) vnp->data.ptrvalue;
353            break;
354         case TXDBINFO:
355 	    tx_dbinfo = (TxDfDbInfoPtr) vnp->data.ptrvalue;
356             break;
357         case TXKABLK_NOGAP:
358             ka_params = (BlastKABlkPtr) vnp->data.ptrvalue;
359             break;
360         case TXKABLK_GAP:
361 	    ka_params_gap = (BlastKABlkPtr) vnp->data.ptrvalue;
362             break;
363         case TXPARAMETERS:
364 	    params_buffer = (CharPtr) vnp->data.ptrvalue;
365             break;
366         case TXMATRIX:
367             matrix = (BLAST_MatrixPtr) vnp->data.ptrvalue;
368             if (matrix)
369                 txmatrix = BlastMatrixToTxMatrix(matrix);
370             /*BLAST_MatrixDestruct(matrix);*/
371             break;
372         case SEQLOC_MASKING_NOTSET:
373         case SEQLOC_MASKING_PLUS1:
374         case SEQLOC_MASKING_PLUS2:
375         case SEQLOC_MASKING_PLUS3:
376         case SEQLOC_MASKING_MINUS1:
377         case SEQLOC_MASKING_MINUS2:
378         case SEQLOC_MASKING_MINUS3:
379             ValNodeAddPointer(&mask_loc, vnp->choice, vnp->data.ptrvalue);
380 	    break;
381         default:
382             break;
383         }
384     }
385 
386     mask_loc_start = mask_loc;
387 
388     /* If results come as alignment endpoints only from Mega BLAST */
389     if (mb_results) {
390        MegaBlastHitPtr mb_hit = mb_results->mbhits, next_hit;
391 
392        while (mb_hit) {
393           fprintf(stdout, "%s\t%s\t%d\t%d\t%d\t%d\t%d\n", mb_hit->id1,
394                   mb_hit->id2, mb_hit->query_offset, mb_hit->subject_offset,
395                   mb_hit->query_end, mb_hit->subject_end, mb_hit->score);
396           mb_hit = mb_hit->next;
397        }
398        MegaBlastResultsFree(mb_results);
399     } else if (!seqalign) {
400        done = FALSE;
401     }
402 
403     ReadDBBioseqFetchEnable ("blastall", database, db_is_na, TRUE);
404     ReadDBBioseqSetDbGeneticCode(theInfo->options->db_genetic_code);
405 
406     tmp_slp = slp;
407 
408     if(theInfo->xml_output)
409         xml_aip = AsnIoOpen("stdout", "wx");
410 
411     if (tabular_output) {
412        if (theInfo->align_view == HitTableWithHeader)
413           PrintTabularOutputHeader(database, bsp, slp,
414               (options->is_megablast_search ? "megablast" : program),
415               0, FALSE, stdout);
416 
417        BlastPrintTabulatedResults(seqalign, bsp, slp,
418                                   theInfo->number_of_alignments,
419                                   program,
420                                   !theInfo->options->gapped_calculation,
421                                   FALSE, 0, 0, stdout,
422                                   (theInfo->align_view == HitTableWithHeader));
423        SeqAlignSetFree(seqalign);
424     } else {
425     Int4 query_number = 1;
426     while (seqalign) {
427         if (!options->is_megablast_search)
428             next_seqalign = NULL;
429         else {
430             SeqIdPtr seqid = TxGetQueryIdFromSeqAlign(seqalign);
431             sap = seqalign;
432             while (sap != NULL) {
433                 if (sap->next != NULL) {
434                     if (SeqIdComp(seqid, TxGetQueryIdFromSeqAlign(sap->next)
435                                   != SIC_YES)) {
436                         next_seqalign = sap->next;
437                         sap->next = NULL;
438                     }
439                 } else {
440                     next_seqalign = NULL;
441                 }
442                 sap = sap->next;
443             }
444             /* Find this query's SeqLoc and Bioseq */
445             while (tmp_slp && SeqIdComp(seqid, SeqLocId(tmp_slp)) != SIC_YES)
446                 tmp_slp = tmp_slp->next;
447             if (tmp_slp == NULL) /* Should never happen */
448                 break;
449             bsp = BioseqLockById(SeqLocId(tmp_slp));
450             init_buff_ex(85);
451             fprintf(stdout, "<HR><BR>");
452             AcknowledgeBlastQuery(bsp, 70, stdout, FALSE, TRUE);
453             free_buff();
454             BioseqUnlock(bsp);
455 
456             /* Separate the mask locations list for this query. */
457             if (mask_loc) {
458                 mask_slp = (SeqLocPtr) mask_loc->data.ptrvalue;
459                 while (SeqIdComp(SeqLocId(mask_slp), seqid) != SIC_YES) {
460                     mask_loc = mask_loc->next;
461                     if (!mask_loc)
462                         break;
463                     mask_slp = (SeqLocPtr) mask_loc->data.ptrvalue;
464                 }
465                 if (mask_loc) {
466                     next_mask_loc = mask_loc->next;
467                     mask_loc->next = NULL;
468                 }
469             }
470         }
471 
472         if(theInfo->xml_output) {
473             printf("<PRE>");
474             BXMLPrintOutput(xml_aip, seqalign, options,
475                             program, database,
476                             bsp, other_returns, 0, NULL, mask_loc);
477             AsnIoReset(xml_aip);
478             printf("</PRE>");
479 
480         } else {
481 
482             seqannot = SeqAnnotNew();
483             seqannot->type = 2;
484             AddAlignInfoToSeqAnnot(seqannot, align_type);
485             seqannot->data = seqalign;
486 
487             if(theInfo->show_overview) {
488                 Char f_name[64], title[1024], href[64], form_name[16];
489                 Int4 align_num;
490 
491                 sprintf(f_name, "%ld%ld.gif", (long)random(), (long)getpid());
492                 sprintf(href, "nph-viewgif.cgi?");
493 
494                 align_num = get_number_alignment(seqalign);
495                 sprintf(title,
496                         "<H3><a href=\"%s/blast/docs/newoptions.html#graphical-overview\"> "
497                         "Distribution of %ld Blast Hits on the Query Sequence</a> "
498                         "</H3>\n", theInfo->www_root_path, (long)align_num);
499 
500                 /* Open HTML form */
501                 sprintf(form_name, "BLASTFORM%ld", query_number);
502                 fprintf(stdout, "<FORM NAME=\"%s\">\n", form_name);
503                 fflush(stdout);
504 
505                 PrintOneAlignmentOverview(seqannot, stdout, form_name, href, f_name,
506                                           title, query_number);
507                 ++query_number;
508             }
509 
510             prune = BlastPruneHitsFromSeqAlign(seqalign, theInfo->number_of_descriptions, NULL);
511             ObjMgrSetHold();
512             init_buff_ex(85);
513 
514             PrintDefLinesFromSeqAlignWithPath(prune->sap, 80, stdout,
515                theInfo->print_options, FIRST_PASS, NULL,
516                theInfo->number_of_descriptions, database,
517                theInfo->www_blast_type, theInfo->www_root_path);
518             free_buff();
519 
520             prune = BlastPruneHitsFromSeqAlign(seqalign, theInfo->number_of_alignments, prune);
521             seqannot->data = prune->sap;
522 
523             if(theInfo->color_schema != 0 &&
524                (!StringICmp(program, "blastn") ||
525                 !StringICmp(program, "blastp"))) {
526 
527                 if(!DDV_DisplayBlastPairList(prune->sap, mask_loc, stdout,
528                                              query_is_na, align_options,
529                                              theInfo->color_schema)) {
530                     fprintf(stdout,
531                             "\n\n!!!\n   "
532                             "    --------  Failure to print alignment...  --------"
533                             "\n!!!\n\n");
534                     fflush(stdout);
535                 }
536             } else {
537 
538                 if(options->is_ooframe) {
539                     printf("<PRE>");
540                     OOFShowBlastAlignment(seqalign, /*mask*/ NULL,
541                                           stdout, align_options, txmatrix);
542                 } else {
543                     if (align_options & TXALIGN_MASTER) {
544                         ShowTextAlignFromAnnot2(seqannot, 60, stdout, f_order,
545                            g_order, align_options, txmatrix, mask_loc, NULL,
546                            NULL, theInfo->www_blast_type);
547                     } else {
548                         ShowTextAlignFromAnnot2(seqannot, 60, stdout, f_order,
549                            g_order, align_options, txmatrix, mask_loc,
550                            FormatScoreFunc, NULL, theInfo->www_blast_type);
551                     }
552                 }
553             }
554 
555             seqannot->data = seqalign;
556             number_of_hits_private = prune->original_number;
557             prune = BlastPruneSapStructDestruct(prune);
558             ObjMgrClearHold();
559             ObjMgrFreeCache(0);
560         } /* If else xml_output */
561 
562         if (options->is_megablast_search) {
563             tmp_slp = tmp_slp->next;
564 
565             /* Reconnect the mask locations */
566             if (next_mask_loc) {
567                 mask_loc->next = next_mask_loc;
568                 mask_loc = next_mask_loc;
569             }
570         }
571 
572         if (seqannot)
573             seqannot = SeqAnnotFree(seqannot);
574         seqalign = next_seqalign;
575         fprintf(stdout, "<PRE>\n</form>\n");
576     }
577     } /* End if not hit table */
578     if (!done) { /* seqalign == NULL */
579     if(theInfo->xml_output && !options->is_ooframe) {
580        BlastErrorMsgPtr error_msg;
581        CharPtr message;
582 
583        if (error_returns == NULL) {
584                 message = "No hits found";
585        } else {
586           error_msg = error_returns->data.ptrvalue;
587           message = error_msg->msg;
588        }
589 
590        BXMLPrintOutput(xml_aip, NULL,
591                        options, program, database,
592                        bsp, other_returns, 0, message, NULL);
593 
594        if (error_returns != NULL) {
595           MemFree(error_msg->msg);
596           MemFree(error_msg);
597           MemFree(error_returns);
598        }
599 
600        AsnIoReset(xml_aip);
601     } else if (!tabular_output) {
602        fprintf(stdout, "\n\n ***** No hits found ******\n\n");
603     }
604     }
605     if(theInfo->xml_output)
606         xml_aip = AsnIoClose(xml_aip);
607 
608     BLAST_MatrixDestruct(matrix);
609     if (txmatrix)
610         txmatrix = TxMatrixDestruct(txmatrix);
611 
612     for (mask_loc = mask_loc_start; mask_loc; mask_loc = mask_loc->next) {
613         SeqLocSetFree(mask_loc->data.ptrvalue);
614     }
615     ValNodeFree(mask_loc_start);
616 
617     init_buff_ex(85);
618     tx_dbinfo_head = tx_dbinfo;
619     if (!tabular_output &&
620         !(options->is_megablast_search && options->no_traceback)) {
621         while (tx_dbinfo) {
622             PrintDbReport(tx_dbinfo, 70, stdout);
623             tx_dbinfo = tx_dbinfo->next;
624         }
625     }
626     tx_dbinfo_head = TxDfDbInfoDestruct(tx_dbinfo_head);
627 
628     if (ka_params) {
629         if (!tabular_output &&
630             !(options->is_megablast_search && options->no_traceback))
631             PrintKAParameters(ka_params->lambda, ka_params->k, ka_params->h,
632                               70, stdout, FALSE);
633             MemFree(ka_params);
634     }
635     if (ka_params_gap) {
636         if (!tabular_output &&
637             !(options->is_megablast_search && options->no_traceback))
638             PrintKAParameters(ka_params_gap->lambda, ka_params_gap->k, ka_params_gap->h, 70, stdout, TRUE);
639         MemFree(ka_params_gap);
640     }
641 
642     if (!tabular_output &&
643         !(options->is_megablast_search && options->no_traceback))
644         PrintTildeSepLines(params_buffer, 70, stdout);
645 
646     printf("</PRE></BODY></HTML>\n");
647     MemFree(params_buffer);
648     free_buff();
649 
650     other_returns = ValNodeFree(other_returns);
651 
652     return status;
653 }
654 
655 static Boolean
TraditionalBlastReportWithImage(BioseqPtr bsp,BlastNet3Hptr bl3hp,WWWBlastInfoPtr theInfo)656 TraditionalBlastReportWithImage(BioseqPtr bsp, BlastNet3Hptr bl3hp,
657                                 WWWBlastInfoPtr theInfo)
658 {
659    return TraditionalBlastReportEngineWithImage(NULL, bsp, bl3hp, theInfo);
660 }
661 static Boolean
TraditionalBlastReportLocWithImage(SeqLocPtr slp,BlastNet3Hptr bl3hp,WWWBlastInfoPtr theInfo)662 TraditionalBlastReportLocWithImage(SeqLocPtr slp, BlastNet3Hptr bl3hp,
663                                    WWWBlastInfoPtr theInfo)
664 {
665    return TraditionalBlastReportEngineWithImage(slp, NULL, bl3hp, theInfo);
666 }
667 
WWWBlastDoClientSearch(WWWBlastInfoPtr theInfo)668 Boolean WWWBlastDoClientSearch(WWWBlastInfoPtr theInfo)
669 {
670     BlastNet3Hptr	bl3hp;
671     BlastResponsePtr	response;
672     BlastVersionPtr	blast_version;
673     CharPtr		date, motd, version;
674     Boolean status;
675 
676     if(theInfo == NULL)
677 	return FALSE;
678 
679     if (!BlastInit("blastcl3", &bl3hp, &response)) {
680         WWWBlastErrMessage(BLASTErrClient, NULL);
681         return FALSE;
682     }
683 
684     if (response && response->choice == BlastResponse_init) {
685         blast_version = response->data.ptrvalue;
686         version = blast_version->version;
687         date = blast_version->date;
688     } else {
689         WWWBlastErrMessage(BLASTErrClient, NULL);
690         return FALSE;
691     }
692 
693     BlastNetBioseqFetchEnable(bl3hp, theInfo->database,
694                               theInfo->db_is_na, TRUE);
695 
696 #ifdef BLAST_PRINT_MOTD
697     motd = Blast3GetMotd(bl3hp);
698     PrintMotd(motd, stdout, TRUE);
699     motd = MemFree(motd);
700 #endif
701 
702     if (!theInfo->options->is_megablast_search)
703        status = TraditionalBlastReportWithImage(theInfo->fake_bsp, bl3hp, theInfo);
704     else
705        status = TraditionalBlastReportLocWithImage(theInfo->query_slp, bl3hp, theInfo);
706     if (status == FALSE) {
707         WWWBlastErrMessage(BLASTErrServer, NULL);
708         return FALSE;
709     }
710 
711     return TRUE;
712 }
713 #endif
714 
715 #define BUFFER_LENGTH 255
716 
717 static int LIBCALLBACK
AppendMegaBlastHit(VoidPtr ptr)718 AppendMegaBlastHit(VoidPtr ptr)
719 {
720    BlastSearchBlkPtr search = (BlastSearchBlkPtr) ptr;
721    SeqIdPtr subject_id, query_id;
722    CharPtr subject_descr, subject_buffer;
723    Int4 index, query_length;
724    Int2 context;
725    BLAST_HSPPtr hsp;
726    MegaBlastResultsPtr mb_results;
727    MegaBlastHitPtr new_hit, last_hit = NULL;
728 
729    if (search->current_hitlist == NULL || search->current_hitlist->hspcnt <= 0) {
730       search->subject_info = BLASTSubjectInfoDestruct(search->subject_info);
731       return 0;
732    }
733 
734    mb_results = (MegaBlastResultsPtr)
735       search->mb_endpoint_results->data.ptrvalue;
736    if (mb_results) {
737        for (last_hit = mb_results->mbhits; last_hit->next;
738             last_hit = last_hit->next);
739    }
740    readdb_get_descriptor(search->rdfp, search->subject_id, &subject_id,
741 			 &subject_descr);
742    if (subject_id->choice != SEQID_GENERAL) {
743       subject_buffer = (CharPtr) Malloc(BUFFER_LENGTH + 1);
744       SeqIdWrite(SeqIdFindBestAccession(subject_id), subject_buffer,
745                  PRINTID_TEXTID_ACC_VER, BUFFER_LENGTH);
746    } else {
747       subject_buffer = StringTokMT(subject_descr, " ", &subject_descr);
748       subject_descr = subject_buffer;
749    }
750 
751    for (index=0; index<search->current_hitlist->hspcnt; index++) {
752       hsp = search->current_hitlist->hsp_array[index];
753       if (hsp==NULL || (search->pbp->cutoff_e > 0 &&
754 	  hsp->evalue > search->pbp->cutoff_e))
755 	 continue;
756       new_hit = Malloc(sizeof(MegaBlastHit));
757       new_hit->next = NULL;
758       context = hsp->context;
759       query_id = search->qid_array[context/2];
760 
761       new_hit->id2 = StringSave(subject_buffer);
762       if (query_id->choice == SEQID_LOCAL) {
763          BioseqPtr query_bsp = BioseqLockById(query_id);
764          CharPtr title = StringSave(BioseqGetTitle(query_bsp));
765          if (title) {
766             new_hit->id1 = StringTokMT(title, " ", &title);
767          } else {
768             Int4 query_gi;
769             Boolean numeric_query_id =
770                 GetAccessionFromSeqId(query_bsp->id, &query_gi,
771                                       &new_hit->id1);
772             if (numeric_query_id) {
773                 new_hit->id1 = Malloc(10);
774                 sprintf(new_hit->id1, "%d", query_gi);
775             }
776          }
777          BioseqUnlock(query_bsp);
778       } else {
779           new_hit->id1 = (CharPtr) Malloc(BUFFER_LENGTH + 1);
780           SeqIdWrite(SeqIdFindBestAccession(query_id), new_hit->id1,
781                      PRINTID_TEXTID_ACC_VER, BUFFER_LENGTH);
782       }
783       query_length = search->query_context_offsets[context+1] -
784          search->query_context_offsets[context] - 1;
785       if (context & 1) {
786 	 new_hit->query_end = query_length - hsp->query.offset;
787 	 new_hit->query_offset =
788 	    new_hit->query_end - hsp->query.length + 1;
789       } else {
790          new_hit->query_offset = hsp->query.offset + 1;
791 	 new_hit->query_end = new_hit->query_offset + hsp->query.length - 1;
792       }
793 
794       new_hit->subject_offset = hsp->subject.offset + 1;
795       new_hit->subject_end = hsp->subject.end;
796 
797       if (search->pbp->gap_open==0 && search->pbp->gap_extend==0)
798 	 new_hit->score = ((hsp->subject.length + hsp->query.length)*
799 		   search->sbp->reward / 2 - hsp->score) /
800 	    (search->sbp->reward - search->sbp->penalty);
801       else
802 	 new_hit->score = hsp->score;
803       if (last_hit == NULL) {
804          last_hit = new_hit;
805          mb_results = MemNew(sizeof(MegaBlastResults));
806          mb_results->mbhits = last_hit;
807          search->mb_endpoint_results->data.ptrvalue = mb_results;
808       } else {
809          last_hit->next = new_hit;
810          last_hit = last_hit->next;
811       }
812    }
813    return 0;
814 }
815 
WWWBlastDoSearch(WWWBlastInfoPtr theInfo)816 Boolean WWWBlastDoSearch(WWWBlastInfoPtr theInfo)
817 {
818     SeqAlignPtr  seqalign = NULL;
819     ValNodePtr mask_loc = NULL, mask_loc_start, next_mask_loc = NULL;
820     SeqLocPtr mask_slp = NULL;
821     ValNodePtr vnp, other_returns, error_returns;
822     TxDfDbInfoPtr dbinfo=NULL, dbinfo_head;
823     BLAST_KarlinBlkPtr ka_params=NULL, ka_params_gap=NULL;
824     BLAST_MatrixPtr matrix;
825     Int4Ptr PNTR txmatrix;
826     CharPtr params_buffer=NULL;
827     SeqAnnotPtr seqannot = NULL;
828     BlastPruneSapStructPtr prune;
829     SeqAlignPtr PNTR seqalignp = NULL;
830     Boolean is_megablast, done = FALSE, all_done = FALSE;
831     SeqLocPtr query_slp, query_lcase_mask, lcase_mask;
832     Int4 index;
833     AsnIoPtr xml_aip;
834     MegaBlastResultsPtr mb_results = NULL;
835     BLAST_OptionsBlkPtr options = theInfo->options;
836     Boolean tabular_output = (theInfo->align_view == HitTable ||
837                               theInfo->align_view == HitTableWithHeader);
838     MBXmlPtr mbxp = NULL;
839     int LIBCALLBACK (*callback)(Int4, Int4);
840     Int4 query_number;
841 
842     if(theInfo == NULL)
843 	return FALSE;
844 
845     is_megablast = options->is_megablast_search;
846 
847     query_slp = theInfo->query_slp;
848     lcase_mask = query_lcase_mask = options->query_lcase_mask;
849 
850     if(!theInfo->xml_output && !tabular_output &&
851        !(is_megablast && options->no_traceback)) {
852         PrintDbInformation(theInfo->database, !theInfo->db_is_na,
853                            70, stdout, TRUE);
854     }
855 
856     if(!tabular_output && options->entrez_query != NULL &&
857        theInfo->gi_list_total > 0) {
858 
859         printf("Your search was limited by an Entrez query: '%s'\n"
860                "<!-- %d sequences-->\n<P>\n",
861                options->entrez_query,
862                theInfo->gi_list_total);
863     }
864 
865     ReadDBBioseqFetchEnable ("blastall", theInfo->database,
866                              theInfo->db_is_na, TRUE);
867 
868     if(theInfo->xml_output)
869        xml_aip = AsnIoOpen("stdout", "wx");
870 
871     while (!all_done) { /* Loop on complete BLAST searches */
872         if (!query_slp || is_megablast)
873             all_done = TRUE;
874 
875         other_returns = NULL;
876         error_returns = NULL;
877 
878         if(!theInfo->xml_output) {
879             printf("</PRE>\n");
880             callback = WWWTickCallback;
881         } else {
882             callback = WWWXMLTickCallback;
883         }
884 
885         if (!is_megablast) {
886             if (SeqIdComp(SeqLocId(lcase_mask), SeqLocId(query_slp)) ==
887                 SIC_YES) {
888                 options->query_lcase_mask = (SeqLocPtr) ValNodeNew(NULL);
889                 MemCpy(options->query_lcase_mask, lcase_mask, sizeof(SeqLoc));
890                 options->query_lcase_mask->next = NULL;
891                 lcase_mask = lcase_mask->next;
892             }
893             if (query_slp) {
894                 seqalign = BioseqBlastEngineByLocEx(query_slp, theInfo->program, theInfo->database, options, &other_returns, &error_returns, callback, NULL, theInfo->gi_list, theInfo->gi_list_total);
895             } else {
896                 seqalign = BioseqBlastEngineEx(theInfo->fake_bsp, theInfo->program, theInfo->database, options, &other_returns, &error_returns, callback, NULL, theInfo->gi_list, theInfo->gi_list_total);
897             }
898         } else {
899            if (options->no_traceback)
900             seqalignp = BioseqMegaBlastEngineByLoc(query_slp, theInfo->program, theInfo->database, options, &other_returns, &error_returns, callback, NULL, theInfo->gi_list, theInfo->gi_list_total, AppendMegaBlastHit);
901            else
902             seqalignp = BioseqMegaBlastEngineByLoc(query_slp, theInfo->program, theInfo->database, options, &other_returns, &error_returns, callback, NULL, theInfo->gi_list, theInfo->gi_list_total, NULL);
903         }
904 
905         if(!theInfo->xml_output)
906             printf("<PRE>");
907 
908         BlastErrorPrint(error_returns);
909 
910         dbinfo = NULL;
911         ka_params = NULL;
912         ka_params_gap = NULL;
913         params_buffer = NULL;
914         mask_loc = NULL;
915         matrix = NULL;
916         txmatrix = NULL;
917         for (vnp=other_returns; vnp; vnp = vnp->next) {
918             switch (vnp->choice) {
919             case TXDBINFO:
920                 dbinfo = vnp->data.ptrvalue;
921                 break;
922             case TXKABLK_NOGAP:
923                 ka_params = vnp->data.ptrvalue;
924                 break;
925             case TXKABLK_GAP:
926                 ka_params_gap = vnp->data.ptrvalue;
927                 break;
928             case TXPARAMETERS:
929                 params_buffer = vnp->data.ptrvalue;
930                 break;
931             case TXMATRIX:
932                 matrix = vnp->data.ptrvalue;
933                 if (matrix)
934                     txmatrix = (Int4Ptr PNTR) BlastMatrixToTxMatrix(matrix);
935                 break;
936             case SEQLOC_MASKING_NOTSET:
937             case SEQLOC_MASKING_PLUS1:
938             case SEQLOC_MASKING_PLUS2:
939             case SEQLOC_MASKING_PLUS3:
940             case SEQLOC_MASKING_MINUS1:
941             case SEQLOC_MASKING_MINUS2:
942             case SEQLOC_MASKING_MINUS3:
943                 ValNodeAddPointer(&mask_loc, vnp->choice, vnp->data.ptrvalue);
944                 break;
945             case BlastResponse_mbalign:
946                mb_results = (MegaBlastResultsPtr) vnp->data.ptrvalue;
947                break;
948             default:
949                 break;
950             }
951         }
952 
953         fflush(stdout);
954 
955         if (mb_results) {
956            /* Results come as alignment endpoints only from Mega BLAST */
957            MegaBlastHitPtr mb_hit = mb_results->mbhits, next_hit;
958 
959            while (mb_hit) {
960               fprintf(stdout, "%s\t%s\t%d\t%d\t%d\t%d\t%d\n", mb_hit->id1,
961                       mb_hit->id2, mb_hit->query_offset, mb_hit->subject_offset,
962                       mb_hit->query_end, mb_hit->subject_end, mb_hit->score);
963               next_hit = mb_hit->next;
964               MemFree(mb_hit->id1);
965               MemFree(mb_hit->id2);
966               MemFree(mb_hit);
967               mb_hit = next_hit;
968            }
969            MemFree(mb_results);
970            done = TRUE;
971         } else
972            done = FALSE;
973 
974         if (theInfo->xml_output && is_megablast) {
975            mbxp = PSIXmlInit(xml_aip, "megablast", theInfo->database,
976                              options, theInfo->fake_bsp, 0);
977         }
978 
979         ReadDBBioseqSetDbGeneticCode(theInfo->options->db_genetic_code);
980         query_number = 1;
981 
982         mask_loc_start = mask_loc;
983 
984         for (index=0; !done; index++) {
985             if (is_megablast)
986                 seqalign = seqalignp[index];
987             else
988                 done = TRUE;
989             if (seqalign) {
990                 /* Separate the mask locations list for this query, if there
991                    are multiple queries. */
992                 if (mask_loc) {
993                     SeqIdPtr seqid = TxGetQueryIdFromSeqAlign(seqalign);
994                     mask_slp = (SeqLocPtr) mask_loc->data.ptrvalue;
995                     while (SeqIdComp(SeqLocId(mask_slp), seqid) != SIC_YES) {
996                         mask_loc = mask_loc->next;
997                         if (!mask_loc)
998                             break;
999                         mask_slp = (SeqLocPtr) mask_loc->data.ptrvalue;
1000                     }
1001                     if (mask_loc) {
1002                         next_mask_loc = mask_loc->next;
1003                         mask_loc->next = NULL;
1004                     }
1005                 }
1006                 if(theInfo->xml_output) {
1007                    if (!is_megablast) {
1008                       BXMLPrintOutput(xml_aip, seqalign, options,
1009                          theInfo->program, theInfo->database,
1010                          theInfo->fake_bsp, other_returns, 0, NULL, mask_loc);
1011                       AsnIoReset(xml_aip);
1012                    } else {
1013                        IterationPtr iterp;
1014                        BioseqPtr bsp = BioseqLockById(SeqLocId(query_slp));
1015 
1016                        iterp = BXMLBuildOneQueryIteration(seqalign,
1017                                   NULL, FALSE,
1018                                   !options->gapped_calculation, index,
1019                                   NULL, bsp, mask_loc);
1020                        IterationAsnWrite(iterp, mbxp->aip, mbxp->atp);
1021                        AsnIoFlush(mbxp->aip);
1022                        IterationFree(iterp);
1023 
1024                        BioseqUnlock(bsp);
1025                    }
1026                 } else if (tabular_output) {
1027                    if (theInfo->align_view == HitTableWithHeader)
1028                       PrintTabularOutputHeader(theInfo->database,
1029                           theInfo->fake_bsp, query_slp,
1030                           (options->is_megablast_search ?
1031                            "megablast" : theInfo->program),
1032                           0, FALSE, stdout);
1033 
1034                    BlastPrintTabulatedResults(seqalign, theInfo->fake_bsp,
1035                         query_slp, theInfo->number_of_alignments,
1036                         theInfo->program,
1037                         !theInfo->options->gapped_calculation, FALSE,
1038                         0, 0, stdout,
1039                         (theInfo->align_view == HitTableWithHeader));
1040                 } else {
1041                     seqannot = SeqAnnotNew();
1042                     seqannot->type = 2;
1043                     AddAlignInfoToSeqAnnot(seqannot, theInfo->align_type);
1044                     seqannot->data = seqalign;
1045 
1046 #if !defined(NCBI_CLIENT_SERVER) && defined (NCBI_ENTREZ_CLIENT)
1047                     if(theInfo->show_tax_blast) {
1048                         fprintf(stdout, "<a href=#taxblast>Taxonomy reports</a><BR>");
1049                     }
1050 #endif
1051 
1052                     if (is_megablast || query_slp) {
1053                         BioseqPtr bsp = BioseqLockById(SeqLocId(query_slp));
1054                         init_buff_ex(85);
1055                         fprintf(stdout, "<HR><BR>");
1056                         AcknowledgeBlastQuery(bsp, 70, stdout, FALSE, TRUE);
1057                         free_buff();
1058                         BioseqUnlock(bsp);
1059                     }
1060 
1061                     /* Now printing nice gif with alignment overview */
1062 
1063                     if(theInfo->show_overview) {
1064                         Char f_name[64], title[1024], href[64], form_name[16];
1065                         Int4 align_num;
1066 
1067                         sprintf(f_name, "%ld%ld.gif", (long)random(), (long)getpid());
1068                         sprintf(href, "nph-viewgif.cgi?");
1069 
1070                         align_num = get_number_alignment(seqalign);
1071                         sprintf(title,
1072                                 "<H3><a href=\"%s/blast/docs/newoptions.html#graphical-overview\"> "
1073                                 "Distribution of %ld Blast Hits on the Query Sequence</a> "
1074                                 "</H3>\n",
1075                                 theInfo->www_root_path, (long)align_num);
1076 
1077 
1078                         /* Open HTML form */
1079                         sprintf(form_name, "BLASTFORM%d", query_number);
1080                         fprintf(stdout, "<FORM NAME=\"%s\">\n", form_name);
1081                         fflush(stdout);
1082 
1083                         PrintOneAlignmentOverview(seqannot, stdout, form_name, href,
1084                                                   f_name, title, query_number);
1085                         ++query_number;
1086                     }
1087 
1088                     prune = BlastPruneHitsFromSeqAlign(seqalign, theInfo->number_of_descriptions, NULL);
1089                     ObjMgrSetHold();
1090                     init_buff_ex(85);
1091                     PrintDefLinesFromSeqAlignWithPath(prune->sap, 80, stdout,
1092                        theInfo->print_options, FIRST_PASS, NULL, -1,
1093                        NULL, theInfo->www_blast_type, theInfo->www_root_path);
1094                     free_buff();
1095 
1096                     prune = BlastPruneHitsFromSeqAlign(seqalign, theInfo->number_of_alignments, prune);
1097                     seqannot->data = prune->sap;
1098 
1099                     if(theInfo->color_schema != 0 &&
1100                        (!StringICmp(theInfo->program, "blastn") ||
1101                         !StringICmp(theInfo->program, "blastp"))) {
1102 
1103                         if(!DDV_DisplayBlastPairList(prune->sap, mask_loc, stdout,
1104                                                      theInfo->query_is_na,
1105                                                      theInfo->align_options,
1106                                                      theInfo->color_schema)) {
1107                             fprintf(stdout,
1108                                     "\n\n!!!\n   "
1109                                     "    --------  Failure to print alignment...  --------"
1110                                     "\n!!!\n\n");
1111                             fflush(stdout);
1112                         }
1113                     } else {
1114 
1115                         if(options->is_ooframe) {
1116                             printf("<PRE>");
1117                             OOFShowBlastAlignment(seqalign, /*mask*/ NULL,
1118                                                   stdout, theInfo->align_options, txmatrix);
1119                         } else {
1120                             if (theInfo->align_view != 0) {
1121                                 ShowTextAlignFromAnnot2(seqannot, 60, stdout,
1122                                    NULL, NULL, theInfo->align_options,
1123                                    txmatrix, mask_loc, NULL, NULL,
1124                                    theInfo->www_blast_type);
1125                             } else {
1126                                 ShowTextAlignFromAnnot2(seqannot, 60, stdout,
1127                                    NULL, NULL, theInfo->align_options,
1128                                    txmatrix, mask_loc, FormatScoreFunc,
1129                                    NULL, theInfo->www_blast_type);
1130                             }
1131                         }
1132                     }
1133                     seqannot->data = NULL; /* Don't want to delete seqalign yet */
1134                     prune = BlastPruneSapStructDestruct(prune);
1135                     ObjMgrClearHold();
1136                     ObjMgrFreeCache(0);
1137                 }
1138                 /* Reconnect the mask locations, in case of multiple queries */
1139                 if (next_mask_loc) {
1140                     mask_loc->next = next_mask_loc;
1141                     mask_loc = next_mask_loc;
1142                 }
1143             } else if (!is_megablast) { /* while(seqalign) */
1144                 /* seqalign == NULL */
1145 
1146                 if(theInfo->xml_output && !options->is_ooframe) {
1147                     BlastErrorMsgPtr error_msg;
1148                     CharPtr message;
1149 
1150                     if (error_returns == NULL) {
1151                         message = "No hits found";
1152                     } else {
1153                         error_msg = error_returns->data.ptrvalue;
1154                         message = error_msg->msg;
1155                     }
1156 
1157                     BXMLPrintOutput(xml_aip, NULL,
1158                                     options, theInfo->program,
1159                                     theInfo->database,
1160                                     theInfo->fake_bsp, other_returns,
1161                                     0, message, NULL);
1162 
1163                     if (error_returns != NULL) {
1164                         MemFree(error_msg->msg);
1165                         MemFree(error_msg);
1166                         MemFree(error_returns);
1167                     }
1168 
1169                     AsnIoReset(xml_aip);
1170                 } else {
1171                     fprintf(stdout, "\n\n ***** No hits found ******\n\n");
1172                 }
1173             }
1174 
1175             if (is_megablast) {
1176                 query_slp = query_slp->next;
1177                 if (!query_slp)
1178                     done = TRUE;
1179             }
1180             if(!theInfo->xml_output) {
1181                 seqannot = SeqAnnotFree(seqannot);
1182                 fprintf(stdout, "</form>\n");
1183             }
1184         }
1185 
1186         matrix = BLAST_MatrixDestruct(matrix);
1187         if (txmatrix)
1188             txmatrix = (Int4Ptr PNTR) TxMatrixDestruct(txmatrix);
1189 
1190         dbinfo_head = dbinfo;
1191         if(!theInfo->xml_output && !tabular_output &&
1192            !(is_megablast && options->no_traceback)) {
1193             fprintf(stdout, "<PRE>");
1194             init_buff_ex(85);
1195             while (dbinfo) {
1196                 PrintDbReport(dbinfo, 70, stdout);
1197                 dbinfo = dbinfo->next;
1198             }
1199         }
1200 
1201         dbinfo_head = TxDfDbInfoDestruct(dbinfo_head);
1202 
1203         if (ka_params) {
1204             if(!theInfo->xml_output && !tabular_output &&
1205                !(is_megablast && options->no_traceback)) {
1206                 PrintKAParameters(ka_params->Lambda, ka_params->K,
1207                                   ka_params->H, 70, stdout, FALSE);
1208             }
1209             MemFree(ka_params);
1210         }
1211 
1212         if (ka_params_gap) {
1213             if(!theInfo->xml_output && !tabular_output &&
1214                !(is_megablast && options->no_traceback)) {
1215                 PrintKAParameters(ka_params_gap->Lambda, ka_params_gap->K,
1216                                   ka_params_gap->H, 70, stdout, TRUE);
1217             }
1218             MemFree(ka_params_gap);
1219         }
1220 
1221         if(!theInfo->xml_output && !tabular_output &&
1222            !(is_megablast && options->no_traceback)) {
1223 
1224             PrintTildeSepLines(params_buffer, 70, stdout);
1225 
1226 #if !defined(NCBI_CLIENT_SERVER) && defined (NCBI_ENTREZ_CLIENT)
1227 
1228             fprintf(stdout, "<HR>\n");
1229 
1230             if( !tabular_output && theInfo->show_tax_blast) {
1231                 TXBHtmlReport(seqalign, stdout, theInfo->query_is_na,
1232                               theInfo->db_is_na, theInfo->database,
1233                               NULL, NULL, theInfo->show_gi);
1234             }
1235 
1236 #endif
1237         }
1238 
1239         if (is_megablast) {
1240             Int4 i;
1241             for (i=0; i<index; i++)
1242                 SeqAlignSetFree(seqalignp[i]);
1243             MemFree(seqalignp);
1244         } else if(seqalign != NULL)
1245             seqalign = SeqAlignSetFree(seqalign);
1246 
1247         MemFree(params_buffer);
1248         free_buff();
1249 
1250         for (mask_loc = mask_loc_start; mask_loc; mask_loc = mask_loc->next) {
1251             SeqLocSetFree(mask_loc->data.ptrvalue);
1252         }
1253         ValNodeFree(mask_loc_start);
1254 
1255         other_returns = ValNodeFree(other_returns);
1256 
1257         if (!is_megablast && query_slp) {
1258             query_slp = query_slp->next;
1259             if (!query_slp)
1260                 all_done = TRUE;
1261         }
1262     } /* End of loop over all searches */
1263 
1264     SeqLocSetFree(query_lcase_mask);
1265 
1266     if (theInfo->xml_output) {
1267        if (is_megablast && mbxp != NULL)
1268           MBXmlClose(mbxp, other_returns, !options->gapped_calculation);
1269     }
1270     ReadDBBioseqFetchDisable();
1271 
1272     if (!theInfo->xml_output)
1273        fprintf(stdout, "</PRE>\n</BODY>\n</HTML>\n");
1274 
1275     return TRUE;
1276 }
1277 
WWWBlastPrintTopHeader(WWWBlastInfoPtr theInfo)1278 static void WWWBlastPrintTopHeader(WWWBlastInfoPtr theInfo)
1279 {
1280     fprintf(stdout, "<HTML>\n");
1281     fprintf(stdout, "<TITLE>BLAST Search Results</TITLE>\n");
1282     fflush(stdout);
1283 
1284     fprintf(stdout, "<BODY BGCOLOR=\"#FFFFFF\" LINK=\"#0000FF\" "
1285             "VLINK=\"#660099\" ALINK=\"#660099\">\n");
1286     fprintf(stdout, "<map name=img_map0>\n");
1287     fprintf(stdout, "<area shape=rect coords=2,1,48,21 "
1288             "href=\"http://www.ncbi.nlm.nih.gov\">\n");
1289     fprintf(stdout, "<area shape=rect coords=385,1,435,21 "
1290             "href=\"%s/blast/index.html\">\n", theInfo->www_root_path);
1291     fprintf(stdout, "<area shape=rect coords=436,1,486,21 "
1292             "href=\"http://www.ncbi.nlm.nih.gov/Entrez/\">\n");
1293     fprintf(stdout, "<area shape=rect coords=487,1,508,21 "
1294             "href=\"%s/blast/docs/blast_help.html\">\n", theInfo->www_root_path);
1295     fprintf(stdout, "</map>\n");
1296     fprintf(stdout, "<IMG USEMAP=#img_map0 WIDTH=509 HEIGHT=22 "
1297             "SRC=\"%s/blast/images/blast_results.gif\" ISMAP> \n",
1298             theInfo->www_root_path);
1299 }
1300 
WWWBlastPrintHeader(WWWBlastInfoPtr theInfo)1301 void WWWBlastPrintHeader(WWWBlastInfoPtr theInfo)
1302 {
1303 
1304     fprintf(stdout, "<PRE>\n");
1305     init_buff_ex(90);
1306     if (theInfo->options->is_megablast_search) {
1307         BlastPrintVersionInfo("megablast", TRUE, stdout);
1308     } else if (theInfo->options->is_rps_blast){
1309         BlastPrintVersionInfo("rps-blast", TRUE, stdout);
1310     } else if (theInfo->options->is_ooframe){
1311         BlastPrintVersionInfo("OOF BLASTX", TRUE, stdout);
1312     } else {
1313         BlastPrintVersionInfo(theInfo->program, TRUE, stdout);
1314         fprintf(stdout, "\n");
1315         BlastPrintReference(TRUE, 90, stdout);
1316     }
1317     fprintf(stdout, "\n");
1318     if (!theInfo->options->is_megablast_search && !theInfo->query_slp)
1319        AcknowledgeBlastQuery(theInfo->query_bsp, 70, stdout,
1320                              theInfo->believe_query, TRUE);
1321     free_buff();
1322 
1323     return;
1324 }
1325 
Main(void)1326 Int2 Main(void)
1327 {
1328     WWWBlastInfoPtr theInfo;
1329 
1330     UseLocalAsnloadDataAndErrMsg ();
1331 
1332     if (! SeqEntryLoad())
1333         return 1;
1334 
1335     ErrSetMessageLevel(SEV_WARNING);
1336 
1337     /* This function will read posting data, set-up config file and
1338        write small message into logfile (if it exists) */
1339 
1340     if((theInfo = WWWBlastReadArgs(NULL)) == NULL)
1341         return 1;
1342 
1343     /* Read options into structure */
1344     if(!WWWCreateSearchOptions(theInfo)) {
1345         return 1;
1346     }
1347 
1348     if (!theInfo->xml_output)
1349        WWWBlastPrintTopHeader(theInfo);
1350 
1351     /* validate them */
1352     if(!WWWValidateOptions(theInfo)) {
1353         return 1;
1354     }
1355 
1356     /* Print BLAST Header */
1357 
1358     if(!theInfo->xml_output &&
1359        theInfo->align_view != HitTableWithHeader) {
1360         WWWBlastPrintHeader(theInfo);
1361     }
1362 
1363     /* Do the search and Format output */
1364 
1365 #ifdef NCBI_CLIENT_SERVER
1366     WWWBlastDoClientSearch(theInfo);
1367 #else
1368     WWWBlastDoSearch(theInfo);
1369 #endif
1370 
1371     WWWBlastInfoFree(theInfo);
1372 
1373     return 0;
1374 }
1375