|
NCBI Home IEB Home C Toolkit docs C++ Toolkit source browser C Toolkit source browser (2) |
NCBI C Toolkit Cross ReferenceC/sequin/sequin3.c |
source navigation diff markup identifier search freetext search file search |
1 /* sequin3.c
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information (NCBI)
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government do not place any restriction on its use or reproduction.
13 * We would, however, appreciate having the NCBI and the author cited in
14 * any work or product based on this material
15 *
16 * Although all reasonable efforts have been taken to ensure the accuracy
17 * and reliability of the software and data, the NLM and the U.S.
18 * Government do not and cannot warrant the performance or results that
19 * may be obtained by using this software or data. The NLM and the U.S.
20 * Government disclaim all warranties, express or implied, including
21 * warranties of performance, merchantability or fitness for any particular
22 * purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name: sequin3.c
27 *
28 * Author: Jonathan Kans
29 *
30 * Version Creation Date: 1/22/95
31 *
32 * $Revision: 6.1002 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date Name Description of modification
39 * ------- ---------- -----------------------------------------------------
40 *
41 *
42 * ==========================================================================
43 */
44
45 #include "sequin.h"
46 #include <document.h>
47 #include <sequtil.h>
48 #include <biosrc.h>
49 #include <import.h>
50 #include <gather.h>
51 #include <asn2gnbk.h>
52 #include <asn2gnbp.h>
53 #include <edutil.h>
54 #include <gbfeat.h>
55 #include <gbftdef.h>
56 #include <subutil.h> /* TOPOLOGY_xxx definitions */
57 #include <salutil.h>
58 #include <valid.h>
59 #include <vsm.h>
60 #include <bspview.h>
61 #include <toasn3.h>
62 #include <salstruc.h>
63 #include <explore.h>
64 #include <utilpub.h>
65 #include <tofasta.h>
66 #include <rpsutil.h>
67 #include <findrepl.h>
68 #include <explore.h>
69 #include <seqpanel.h>
70 #include <tax3api.h>
71 #include <saledit.h>
72 #include <alignmgr2.h>
73 #include <suggslp.h>
74 #include <asn2gnbi.h>
75 #include <alignval.h>
76 #include <cdrgn.h>
77 #define NLM_GENERATED_CODE_PROTO
78 #include <objmacro.h>
79 #include <macrodlg.h>
80 #include <macroapi.h>
81 #include <valdlg.h>
82
83 /* For converting primer names to primer seqs and vice versa */
84 static void PrimerSeqToPrimerNameCallback (BioSourcePtr biop, Pointer userdata)
85 {
86 SubSourcePtr ssp;
87
88 if (biop == NULL) return;
89 for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
90 if (ssp->subtype == SUBSRC_fwd_primer_seq) {
91 ssp->subtype = SUBSRC_fwd_primer_name;
92 } else if (ssp->subtype == SUBSRC_rev_primer_seq) {
93 ssp->subtype = SUBSRC_rev_primer_name;
94 }
95 }
96 }
97
98
99 static void PrimerNameToPrimerSeqCallback (BioSourcePtr biop, Pointer userdata)
100 {
101 SubSourcePtr ssp;
102
103 if (biop == NULL) return;
104 for (ssp = biop->subtype; ssp != NULL; ssp = ssp->next) {
105 if (ssp->subtype == SUBSRC_fwd_primer_name) {
106 ssp->subtype = SUBSRC_fwd_primer_seq;
107 } else if (ssp->subtype == SUBSRC_rev_primer_name) {
108 ssp->subtype = SUBSRC_rev_primer_seq;
109 }
110 }
111 }
112
113
114 static void SwapPrimerNamesAndSeq (IteM i, Boolean seq_to_name)
115 {
116 BaseFormPtr bfp;
117 SeqEntryPtr sep;
118
119 #ifdef WIN_MAC
120 bfp = currentFormDataPtr;
121 #else
122 bfp = GetObjectExtra (i);
123 #endif
124 if (bfp == NULL) return;
125 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
126 if (sep == NULL) return;
127 if (seq_to_name) {
128 VisitBioSourcesInSep (sep, NULL, PrimerSeqToPrimerNameCallback);
129 } else {
130 VisitBioSourcesInSep (sep, NULL, PrimerNameToPrimerSeqCallback);
131 }
132 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
133 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
134 }
135
136
137 static void ConvertPrimerSeqToName (IteM i)
138 {
139 SwapPrimerNamesAndSeq (i, TRUE);
140 }
141
142
143 static void ConvertPrimerNameToSeq (IteM i)
144 {
145 SwapPrimerNamesAndSeq (i, FALSE);
146 }
147
148
149 static void TSATableCallback (Pointer data)
150 {
151 ProcessExternalEvent ();
152 }
153
154 static ValNodePtr ApplyTranscriptomeIdListWithProgress (ValNodePtr ids_list, LocalAlignFunc aln_func)
155 {
156 WindoW w;
157 GrouP h;
158 PrompT ppt;
159 CharPtr prompt_fmt = "%d out of %d";
160 Char prompt_str[40];
161 Int4 max, num = 1;
162 ValNodePtr err_list = NULL, vnp;
163
164 if (ids_list == NULL || aln_func == NULL) return NULL;
165
166 WatchCursor();
167 Update();
168 w = ModalWindow(-20, -13, -10, -10, NULL);
169 h = HiddenGroup (w, -1, 0, NULL);
170 SetGroupSpacing (h, 10, 10);
171
172 max = ValNodeLen (ids_list);
173 sprintf (prompt_str, prompt_fmt, max, max);
174 ppt = StaticPrompt (h, prompt_str, 0, dialogTextHeight, programFont, 'c');
175 sprintf (prompt_str, prompt_fmt, 1, max);
176 SetTitle (ppt, prompt_str);
177
178 Show(w);
179 Select (w);
180 for (num = 1, vnp = ids_list; vnp != NULL; vnp = vnp->next, num++) {
181 sprintf (prompt_str, prompt_fmt, num, max);
182 SetTitle (ppt, prompt_str);
183 ValNodeLink (&err_list, MakeTranscriptomeAssemblySeqHist (vnp->data.ptrvalue, aln_func, TSATableCallback, NULL));
184 }
185
186 Remove (w);
187 ArrowCursor();
188 Update();
189 return err_list;
190 }
191
192
193 NLM_EXTERN void ReportNonTSABioseqs (BioseqPtr bsp, Pointer userdata)
194 {
195 LogInfoPtr lip;
196 Char id_str[255];
197
198 if (bsp == NULL || (lip = (LogInfoPtr) userdata) == NULL || lip->fp == NULL || ISA_aa (bsp->mol)) {
199 return;
200 }
201 if (bsp->hist == NULL || bsp->hist->assembly == NULL) {
202 SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_str, PRINTID_REPORT, sizeof (id_str) - 1);
203 fprintf (lip->fp, "%s has no TSA table\n", id_str);
204 lip->data_in_log = TRUE;
205 }
206 }
207
208
209 static void AddTSATableToBioseq (IteM i)
210 {
211 BaseFormPtr bfp;
212 SeqEntryPtr sep;
213 ValNodePtr err_list = NULL, ids_list, vnp;
214 LogInfoPtr lip;
215 Char path [PATH_MAX];
216 FILE *fp;
217 MsgAnswer ans;
218 ValNodePtr coverage_report;
219
220 #ifdef WIN_MAC
221 bfp = currentFormDataPtr;
222 #else
223 bfp = GetObjectExtra (i);
224 #endif
225 if (bfp == NULL) return;
226 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
227 if (sep == NULL) return;
228
229 if (! GetInputFileName (path, sizeof (path), "", "TEXT")) return;
230 fp = FileOpen (path, "r");
231 if (fp == NULL) {
232 Message (MSG_ERROR, "Unable to open %s", path);
233 return;
234 }
235
236 ids_list = GetTranscriptomeIdsList (fp, sep, &err_list);
237 FileClose (fp);
238
239 if (err_list != NULL) {
240 lip = OpenLog ("Problems Reading TSA Table File");
241 for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
242 fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
243 }
244 lip->data_in_log = TRUE;
245 CloseLog (lip);
246 lip = FreeLog (lip);
247 err_list = ValNodeFreeData (err_list);
248 if (ANS_NO == Message (MSG_YN, "Problems reading input file - continue creating TSA tables?")) {
249 ids_list = TranscriptomeIdsListFree (ids_list);
250 return;
251 }
252 }
253
254 if (HasExistingSeqHistAssembly(ids_list)) {
255 ans = Message (MSG_YNC, "Some of the bioseqs listed in the file already have Seq-Hist assemblies. Should these be replaced?");
256 if (ans == ANS_YES) {
257 DeleteSeqHistAssembliesForList(ids_list);
258 } else if (ans == ANS_CANCEL) {
259 ids_list = TranscriptomeIdsListFree (ids_list);
260 return;
261 }
262 }
263
264
265 ValNodeLink (&err_list, ApplyTranscriptomeIdListWithProgress (ids_list, GetSeqAlignTSA));
266
267 coverage_report = ReportCoverageForTranscriptomeIdsListSeqHist (ids_list);
268 ValNodeLink (&coverage_report, ReportGapsInSeqHistAlignmentsForIdsList (ids_list));
269
270 ids_list = TranscriptomeIdsListFree (ids_list);
271
272 ValNodeLink (&coverage_report, err_list);
273 err_list = coverage_report;
274
275 lip = OpenLog ("TSA Table Problems");
276 if (err_list != NULL) {
277 for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
278 fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
279 }
280 lip->data_in_log = TRUE;
281 err_list = ValNodeFreeData (err_list);
282 }
283 VisitBioseqsInSep (sep, lip, ReportNonTSABioseqs);
284 CloseLog (lip);
285 lip = FreeLog (lip);
286
287 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
288 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
289 }
290
291
292 static void RefreshTSATables (IteM i)
293 {
294 BaseFormPtr bfp;
295 SeqEntryPtr sep;
296 ValNodePtr err_list = NULL, ids_list, vnp;
297 LogInfoPtr lip;
298 ValNodePtr coverage_report;
299
300 #ifdef WIN_MAC
301 bfp = currentFormDataPtr;
302 #else
303 bfp = GetObjectExtra (i);
304 #endif
305 if (bfp == NULL) return;
306 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
307 if (sep == NULL) return;
308
309
310 ids_list = GetExistingTSATableIds (sep);
311
312 DeleteSeqHistAssembliesForList(ids_list);
313
314 ValNodeLink (&err_list, ApplyTranscriptomeIdListWithProgress (ids_list, GetSeqAlignTSA));
315
316 coverage_report = ReportCoverageForTranscriptomeIdsListSeqHist (ids_list);
317 ValNodeLink (&coverage_report, ReportGapsInSeqHistAlignmentsForIdsList (ids_list));
318
319 ids_list = TranscriptomeIdsListFree (ids_list);
320
321 ValNodeLink (&coverage_report, err_list);
322 err_list = coverage_report;
323
324
325 lip = OpenLog ("TSA Table Problems");
326 if (err_list != NULL) {
327 for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
328 fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
329 }
330 lip->data_in_log = TRUE;
331 err_list = ValNodeFreeData (err_list);
332 }
333 VisitBioseqsInSep (sep, lip, ReportNonTSABioseqs);
334 CloseLog (lip);
335 lip = FreeLog (lip);
336
337 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
338 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
339 }
340
341
342 static void CreateTSAIDsFromLocalIDs (IteM i)
343 {
344 BaseFormPtr bfp;
345 SeqEntryPtr sep;
346
347 #ifdef WIN_MAC
348 bfp = currentFormDataPtr;
349 #else
350 bfp = GetObjectExtra (i);
351 #endif
352 if (bfp == NULL) return;
353 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
354 if (sep == NULL) return;
355
356 ConvertLocalIdsToTSAIds (sep, NULL);
357
358 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
359 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
360 }
361
362
363 typedef struct createtsaidswithsuffixform {
364 FORM_MESSAGE_BLOCK
365 TexT suffix;
366 } CreateTsaIDsWithSuffixFormData, PNTR CreateTsaIDsWithSuffixFormPtr;
367
368 static void DoCreateTSAIDsFromLocalIDsWithSuffix (ButtoN b)
369 {
370 CreateTsaIDsWithSuffixFormPtr t;
371 SeqEntryPtr sep;
372 CharPtr suffix = NULL;
373
374 t = (CreateTsaIDsWithSuffixFormPtr) GetObjectExtra (b);
375 if (b == NULL) {
376 return;
377 }
378
379 sep = GetTopSeqEntryForEntityID (t->input_entityID);
380 if (sep == NULL) return;
381
382 if (!TextHasNoText (t->suffix)) {
383 suffix = SaveStringFromText (t->suffix);
384 }
385 ConvertLocalIdsToTSAIds (sep, suffix);
386 suffix = MemFree (suffix);
387
388 ObjMgrSetDirtyFlag (t->input_entityID, TRUE);
389 ObjMgrSendMsg (OM_MSG_UPDATE, t->input_entityID, 0, 0);
390 Remove (t->form);
391 Update();
392 }
393
394 static void CreateTSAIDsFromLocalIDsWithSuffix (IteM i)
395 {
396 BaseFormPtr bfp;
397 CreateTsaIDsWithSuffixFormPtr t;
398 WindoW w;
399 GrouP h, g, c;
400 ButtoN b;
401
402 #ifdef WIN_MAC
403 bfp = currentFormDataPtr;
404 #else
405 bfp = GetObjectExtra (i);
406 #endif
407 if (bfp == NULL) return;
408
409 t = (CreateTsaIDsWithSuffixFormPtr) MemNew (sizeof (CreateTsaIDsWithSuffixFormData));
410
411 w = FixedWindow (-50, -33, -10, -10, "Create TSA IDs With Suffix", StdCloseWindowProc);
412 h = HiddenGroup (w, -1, 0, NULL);
413 SetGroupSpacing (h, 10, 10);
414 t->form = (ForM) w;
415 t->input_entityID = bfp->input_entityID;
416
417 g = HiddenGroup (h, 2, 0, NULL);
418 StaticPrompt (g, "Suffix", 0, dialogTextHeight, programFont, 'c');
419 t->suffix = DialogText (g, "", 14, NULL);
420
421 c = HiddenGroup (h, 2, 0, NULL);
422 b = DefaultButton (c, "Accept", DoCreateTSAIDsFromLocalIDsWithSuffix);
423 SetObjectExtra (b, t, NULL);
424 PushButton (c, "Cancel", StdCancelButtonProc);
425 AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
426
427 Show (w);
428
429 }
430
431
432
433 static void CreateTSAIDsFromTable (IteM i)
434 {
435 BaseFormPtr bfp;
436 SeqEntryPtr sep;
437 Char path [PATH_MAX];
438 FILE *fp;
439 ValNodePtr table, sequence_lists, err_list = NULL, vnp, vnp_rs, vnp_s, vnp_rt, vnp_t;
440 MatchTypeData match;
441 LogInfoPtr lip;
442 BioseqPtr bsp;
443 Int4 gpid = 0;
444 SeqIdPtr sip_new;
445 DbtagPtr dbtag;
446 CharPtr id_fmt = "gpid:%d";
447
448 #ifdef WIN_MAC
449 bfp = currentFormDataPtr;
450 #else
451 bfp = GetObjectExtra (i);
452 #endif
453 if (bfp == NULL) return;
454 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
455 if (sep == NULL) return;
456
457 if (! GetInputFileName (path, sizeof (path), "", "TEXT")) return;
458 fp = FileOpen (path, "r");
459 if (fp == NULL) return;
460 table = ReadTabTableFromFile (fp);
461 FileClose (fp);
462
463 match.choice = eTableMatchNucID;
464 match.data = NULL;
465 match.match_location = String_location_equals;
466
467 sequence_lists = GetSequenceListsForMatchTypeInTabTable (sep, table, 0, &match, &err_list);
468
469 if (err_list != NULL) {
470 lip = OpenLog ("Table Problems");
471 for (vnp = err_list; vnp != NULL; vnp = vnp->next) {
472 fprintf (lip->fp, "%s\n", vnp->data.ptrvalue);
473 }
474 lip->data_in_log = TRUE;
475 CloseLog (lip);
476 lip = FreeLog (lip);
477 err_list = ValNodeFreeData (err_list);
478 if (ANS_YES != Message (MSG_YN, "Continue with table problems")) {
479 sequence_lists = FreeSequenceLists(sequence_lists);
480 table = FreeTabTable (table);
481 return;
482 }
483 }
484
485 WatchCursor();
486 Update();
487 for (vnp_rs = sequence_lists, vnp_rt = table;
488 vnp_rs != NULL && vnp_rt != NULL;
489 vnp_rs = vnp_rs->next, vnp_rt = vnp_rt->next) {
490 vnp_s = vnp_rs->data.ptrvalue;
491 vnp_t = vnp_rt->data.ptrvalue;
492 if (vnp_s == NULL || vnp_t == NULL) {
493 continue;
494 }
495 vnp_t = vnp_t->next;
496 if (vnp_t == NULL || StringHasNoText (vnp_t->data.ptrvalue)) {
497 continue;
498 }
499 while (vnp_s != NULL) {
500 bsp = (BioseqPtr) vnp_s->data.ptrvalue;
501 gpid = GetGenomeProjectID (bsp);
502 if (gpid > 0) {
503 dbtag = DbtagNew ();
504 dbtag->db = MemNew (sizeof (Char) * (StringLen (id_fmt) + 15));
505 sprintf (dbtag->db, id_fmt, gpid);
506 dbtag->tag = ObjectIdNew ();
507 dbtag->tag->str = StringSave (vnp_t->data.ptrvalue);
508 sip_new = ValNodeNew (NULL);
509 sip_new->choice = SEQID_GENERAL;
510 sip_new->data.ptrvalue = dbtag;
511 sip_new->next = bsp->id;
512 bsp->id = sip_new;
513 SeqMgrReplaceInBioseqIndex (bsp);
514 }
515 vnp_s = vnp_s->next;
516 }
517 }
518 sequence_lists = FreeSequenceLists(sequence_lists);
519 table = FreeTabTable (table);
520 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
521 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
522 ArrowCursor();
523 Update();
524
525 }
526
527
528 static void CreateBarcodeIDsFromLocalIDs (IteM i)
529 {
530 BaseFormPtr bfp;
531 SeqEntryPtr sep;
532
533 #ifdef WIN_MAC
534 bfp = currentFormDataPtr;
535 #else
536 bfp = GetObjectExtra (i);
537 #endif
538 if (bfp == NULL) return;
539 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
540 if (sep == NULL) return;
541
542 ConvertLocalIdsToBarcodeIds (sep);
543
544 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
545 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
546 }
547
548
549 static void AddmRNASequenceCallback (SeqDescrPtr sdp, Pointer data)
550 {
551 Int4 len, len_add;
552 CharPtr add = ", mRNA sequence.", tmp, title;
553
554 if (sdp != NULL && sdp->choice == Seq_descr_title) {
555 title = (CharPtr) sdp->data.ptrvalue;
556 len_add = StringLen (add);
557 len = StringLen (title);
558 if (len < len_add || StringCmp (title + (len - len_add), add) != 0) {
559 /* remove trailing period if present */
560 if (title[len - 1] == '.') {
561 title[len - 1] = 0;
562 }
563 tmp = (CharPtr) MemNew (sizeof (Char) * (len + len_add + 1));
564 sprintf (tmp, "%s%s", title, add);
565 sdp->data.ptrvalue = MemFree (sdp->data.ptrvalue);
566 sdp->data.ptrvalue = tmp;
567 }
568 }
569 }
570
571
572 static void AddmRNASequenceToDeflines (IteM i)
573 {
574 BaseFormPtr bfp;
575 SeqEntryPtr sep;
576
577 #ifdef WIN_MAC
578 bfp = currentFormDataPtr;
579 #else
580 bfp = GetObjectExtra (i);
581 #endif
582 if (bfp == NULL) return;
583 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
584 if (sep == NULL) return;
585
586 WatchCursor ();
587 Update ();
588
589 AutoDefId (bfp->input_entityID);
590 SeqEntrySetScope (NULL);
591 VisitDescriptorsInSep (sep, NULL, AddmRNASequenceCallback);
592 ArrowCursor();
593 Update();
594
595 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
596 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
597 }
598
599
600 static void SplitPubsByTable (IteM i)
601 {
602 BaseFormPtr bfp;
603 SeqEntryPtr sep;
604 FILE *fp;
605 ValNodePtr tab_table, split_list;
606 ValNodePtr err_list = NULL;
607 Char path [PATH_MAX];
608
609 #ifdef WIN_MAC
610 bfp = currentFormDataPtr;
611 #else
612 bfp = GetObjectExtra (i);
613 #endif
614 if (bfp == NULL) return;
615 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
616 if (sep == NULL) return;
617
618 if (! GetInputFileName (path, sizeof (path), "", "TEXT")) return;
619 fp = FileOpen (path, "r");
620 if (fp == NULL) return;
621 tab_table = ReadTabTableFromFile (fp);
622 FileClose (fp);
623 split_list = MakeSplitPubListFromTabList (&tab_table, sep, &err_list);
624 tab_table = FreeTabTable (tab_table);
625 SplitPubsByList (split_list);
626 SplitPubListFree (split_list);
627 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
628 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
629 Update();
630 }
631
632
633 #define DDBUFFERMAX 32768
634
635 typedef struct fndeldata {
636 CharPtr buffer;
637 CharPtr curr;
638 Int4 seqlen;
639 Int4 gap_count;
640 Int4 bsp_length;
641 Boolean in_gap;
642 Boolean unk_gap;
643 ValNodePtr head;
644 ValNodePtr last;
645 } DelData, PNTR DelDataPtr;
646
647 static void AddNextBlock (
648 DelDataPtr ddp
649 )
650
651 {
652 ByteStorePtr bs;
653 IntFuzzPtr ifp;
654 SeqLitPtr slitp;
655 CharPtr str;
656 ValNodePtr vnp;
657
658 if (ddp == NULL) return;
659 if (ddp->in_gap) {
660 slitp = (SeqLitPtr) MemNew (sizeof (SeqLit));
661 if (slitp != NULL) {
662 slitp->length = ddp->gap_count;
663 ddp->bsp_length += slitp->length;
664 if (ddp->unk_gap) {
665 ifp = IntFuzzNew ();
666 if (ifp != NULL) {
667 ifp->choice = 4;
668 slitp->fuzz = ifp;
669 }
670 }
671 vnp = ValNodeAddPointer (&(ddp->last), 2, (Pointer) slitp);
672 if (ddp->head == NULL) {
673 ddp->head = vnp;
674 }
675 ddp->last = vnp;
676 }
677 } else if (ddp->seqlen > 0) {
678 str = ddp->curr;
679 if (str != NULL) {
680 *str = '\0';
681 }
682 bs = BSNew (ddp->seqlen);
683 if (bs != NULL) {
684 BSWrite (bs, (VoidPtr) ddp->buffer, ddp->seqlen);
685 slitp = (SeqLitPtr) MemNew (sizeof (SeqLit));
686 if (slitp != NULL) {
687 slitp->length = ddp->seqlen;
688 slitp->seq_data_type = Seq_code_iupacna;
689 slitp->seq_data = (SeqDataPtr) bs;
690 ddp->bsp_length += slitp->length;
691 vnp = ValNodeAddPointer (&(ddp->last), 2, (Pointer) slitp);
692 if (ddp->head == NULL) {
693 ddp->head = vnp;
694 }
695 ddp->last = vnp;
696 }
697 }
698 }
699 }
700
701 static void LIBCALLBACK FarToNearCallback (
702 CharPtr sequence,
703 Pointer userdata
704 )
705
706 {
707 Char ch;
708 DelDataPtr ddp;
709 CharPtr ptr;
710 CharPtr str;
711
712 if (sequence == NULL || userdata == NULL) return;
713 ddp = (DelDataPtr) userdata;
714
715 ptr = sequence;
716 ch = *ptr;
717 str = ddp->curr;
718
719 while (ch != '\0') {
720 if (ch != '-' && ch != '+') {
721 if (ddp->in_gap) {
722 AddNextBlock (ddp);
723 ddp->in_gap = FALSE;
724 ddp->unk_gap = FALSE;
725 ddp->gap_count = 0;
726 ddp->curr = ddp->buffer;
727 ddp->seqlen = 0;
728 str = ddp->curr;
729 }
730 *str = ch;
731 str++;
732 (ddp->seqlen)++;
733 if (ddp->seqlen >= DDBUFFERMAX) {
734 *str = '\0';
735 ddp->curr = str;
736 AddNextBlock (ddp);
737 ddp->curr = ddp->buffer;
738 ddp->seqlen = 0;
739 str = ddp->curr;
740 }
741 } else {
742 if (! ddp->in_gap) {
743 AddNextBlock (ddp);
744 ddp->in_gap = TRUE;
745 ddp->unk_gap = (Boolean) (ch == '-');
746 ddp->gap_count = 0;
747 ddp->curr = ddp->buffer;
748 ddp->seqlen = 0;
749 str = ddp->curr;
750 }
751 (ddp->gap_count)++;
752 }
753
754 ptr++;
755 ch = *ptr;
756 }
757 ddp->curr = str;
758 }
759
760 static void FarToNearProc (BioseqPtr bsp, Pointer userdata)
761
762 {
763 DelData dd;
764 Pointer olddelta;
765
766 if (bsp == NULL || bsp->repr != Seq_repr_delta || bsp->seq_ext_type != 4) return;
767 MemSet ((Pointer) &dd, 0, sizeof (DelData));
768 dd.buffer = MemNew (sizeof (Char) * (DDBUFFERMAX + 2));
769 if (dd.buffer == NULL) return;
770 dd.curr = dd.buffer;
771 dd.seqlen = 0;
772 SeqPortStream (bsp, EXPAND_GAPS_TO_DASHES | KNOWN_GAP_AS_PLUS, (Pointer) &dd, FarToNearCallback);
773 AddNextBlock (&dd);
774 MemFree (dd.buffer);
775 olddelta = bsp->seq_ext;
776 bsp->seq_ext = (Pointer) dd.head;
777 if (dd.bsp_length != bsp->length) {
778 Message (MSG_OK, "Old length %ld differs from new length %ld",
779 (long) bsp->length, (long) dd.bsp_length);
780 }
781 }
782
783 static void FarDeltaToNear (IteM i)
784
785 {
786 BaseFormPtr bfp;
787 SeqEntryPtr sep;
788
789 #ifdef WIN_MAC
790 bfp = currentFormDataPtr;
791 #else
792 bfp = GetObjectExtra (i);
793 #endif
794 if (bfp == NULL) return;
795 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
796 if (sep == NULL) return;
797 VisitBioseqsInSep (sep, NULL, FarToNearProc);
798 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
799 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
800 Message (MSG_OK, "Some manual desktop manipulations remain");
801 }
802
803 static CharPtr HIVDBStart = "##HIVDataBaseData-START##";
804 static CharPtr HIVDBEnd = "##HIVDataBaseData-END##";
805
806 static CharPtr HIVStart = "##HIVData-START##";
807 static CharPtr HIVEnd = "##HIVData-END##";
808
809 static CharPtr FluStart = "##FluData-START##";
810 static CharPtr FluEnd = "##FluData-END##";
811
812
813 static void RemoveStructuredCommentFromString (CharPtr str, CharPtr prefix, CharPtr suffix)
814 {
815 CharPtr pPrefix, pSuffix, pAfter;
816
817 if (StringHasNoText (str) || StringHasNoText (prefix) || StringHasNoText (suffix)) return;
818
819 pPrefix = StringSearch (str, prefix);
820 pSuffix = StringSearch (str, suffix);
821 if (pPrefix == NULL || pSuffix == NULL || pPrefix >= pSuffix) return;
822
823 pAfter = pSuffix + StringLen (suffix);
824 StringCpy (pPrefix, pAfter);
825 }
826
827
828 static void FindStructComment (SeqDescrPtr sdp, Pointer userdata)
829
830 {
831 CharPtr str;
832 UserObjectPtr uop = NULL;
833 UserObjectPtr PNTR uopp;
834 CharPtr prefix = "", suffix = "";
835
836 if (sdp == NULL || sdp->choice != Seq_descr_comment) return;
837 str = (CharPtr) sdp->data.ptrvalue;
838 if (StringHasNoText (str)) return;
839 uopp = (UserObjectPtr PNTR) userdata;
840 if (uopp == NULL) return;
841
842 if (StringStr (str, HIVDBStart) != NULL) {
843 prefix = HIVDBStart;
844 suffix = HIVDBEnd;
845 } else if (StringStr (str, HIVStart) != NULL) {
846 prefix = HIVStart;
847 suffix = HIVEnd;
848 } else if (StringStr (str, FluStart) != NULL) {
849 prefix = FluStart;
850 prefix = FluEnd;
851 }
852
853 uop = ParseStringIntoStructuredComment (NULL, str, prefix, suffix);
854
855 if (uop != NULL) {
856 *uopp = uop;
857 RemoveStructuredCommentFromString (str, prefix, suffix);
858 if (StringHasNoText (str) && sdp->extended != 0) {
859 ((ObjValNodePtr)sdp)->idx.deleteme = TRUE;
860 }
861 }
862 }
863
864 static void DoStructCommentBsp (BioseqPtr bsp, Pointer userdata)
865
866 {
867 SeqDescrPtr sdp;
868 UserObjectPtr uop = NULL;
869
870 VisitDescriptorsOnBsp (bsp, (Pointer) &uop, FindStructComment);
871 if (uop == NULL) return;
872 sdp = CreateNewDescriptorOnBioseq (bsp, Seq_descr_user);
873 if (sdp == NULL) return;
874 sdp->data.ptrvalue = uop;
875 }
876
877 static void ParseCommentIntoStructuredObject (IteM i)
878
879 {
880 BaseFormPtr bfp;
881 SeqEntryPtr sep;
882
883 #ifdef WIN_MAC
884 bfp = currentFormDataPtr;
885 #else
886 bfp = GetObjectExtra (i);
887 #endif
888 if (bfp == NULL) return;
889 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
890 if (sep == NULL) return;
891
892 VisitBioseqsInSep (sep, NULL, DoStructCommentBsp);
893
894 DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
895 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
896 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
897 Update ();
898 }
899
900 static void DoHivOrFluTag (SeqDescrPtr sdp, Pointer userdata, CharPtr prefix, CharPtr suffix)
901
902 {
903 UserFieldPtr curr;
904 Boolean hasPrefix = FALSE;
905 Boolean hasSuffix = FALSE;
906 ObjectIdPtr oip;
907 UserObjectPtr uop;
908
909 if (sdp == NULL || sdp->choice != Seq_descr_user) return;
910 uop = (UserObjectPtr) sdp->data.ptrvalue;
911 if (uop == NULL) return;
912 oip = uop->type;
913 if (oip == NULL || StringICmp (oip->str, "StructuredComment") != 0) return;
914
915 for (curr = uop->data; curr != NULL; curr = curr->next) {
916 oip = curr->label;
917 if (oip != NULL && StringICmp (oip->str, "StructuredCommentPrefix") == 0) {
918 hasPrefix = TRUE;
919 if (curr->choice == 1) {
920 MemFree (curr->data.ptrvalue);
921 curr->data.ptrvalue = (Pointer) StringSave (prefix);
922 }
923 }
924 }
925 if (! hasPrefix) {
926 AddItemStructuredCommentUserObject (uop, "StructuredCommentPrefix", prefix);
927 }
928
929 for (curr = uop->data; curr != NULL; curr = curr->next) {
930 oip = curr->label;
931 if (oip != NULL && StringICmp (oip->str, "StructuredCommentSuffix") == 0) {
932 hasSuffix = TRUE;
933 if (curr->choice == 1) {
934 MemFree (curr->data.ptrvalue);
935 curr->data.ptrvalue = (Pointer) StringSave (suffix);
936 }
937 }
938 }
939 if (! hasSuffix) {
940 AddItemStructuredCommentUserObject (uop, "StructuredCommentSuffix", suffix);
941 }
942 }
943
944 static void DoHivTag (SeqDescrPtr sdp, Pointer userdata)
945
946 {
947 DoHivOrFluTag (sdp, userdata, "##HIVData-START##", "##HIVData-END##");
948 }
949
950 static void DoFluTag (SeqDescrPtr sdp, Pointer userdata)
951
952 {
953 DoHivOrFluTag (sdp, userdata, "##FluData-START##", "##FluData-END##");
954 }
955
956 static void AddStructuredCommentHivTag (IteM i)
957
958 {
959 BaseFormPtr bfp;
960 SeqEntryPtr sep;
961
962 #ifdef WIN_MAC
963 bfp = currentFormDataPtr;
964 #else
965 bfp = GetObjectExtra (i);
966 #endif
967 if (bfp == NULL) return;
968 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
969 if (sep == NULL) return;
970
971 VisitDescriptorsInSep (sep, NULL, DoHivTag);
972
973 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
974 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
975 Update ();
976 }
977
978 static void AddStructuredCommentFluTag (IteM i)
979
980 {
981 BaseFormPtr bfp;
982 SeqEntryPtr sep;
983
984 #ifdef WIN_MAC
985 bfp = currentFormDataPtr;
986 #else
987 bfp = GetObjectExtra (i);
988 #endif
989 if (bfp == NULL) return;
990 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
991 if (sep == NULL) return;
992
993 VisitDescriptorsInSep (sep, NULL, DoFluTag);
994
995 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
996 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
997 Update ();
998 }
999
1000 static void ConvertBadInfProc (SeqFeatPtr sfp, Pointer userdata)
1001
1002 {
1003 GBQualPtr gbq;
1004 size_t len;
1005 CharPtr ptr, str;
1006
1007 if (sfp == NULL) return;
1008 for (gbq = sfp->qual; gbq != NULL; gbq = gbq->next) {
1009 if (StringICmp (gbq->qual, "inference") != 0) continue;
1010 if (ValidateInferenceQualifier (gbq->val, FALSE) != VALID_INFERENCE) {
1011 if (StringNICmp (gbq->val, "similar to ", 11) == 0) {
1012 ptr = StringChr (gbq->val, ':');
1013 if (ptr != NULL) {
1014 ptr++;
1015 if (StringDoesHaveText (ptr)) {
1016 len = StringLen ("similar to ") + StringLen (ptr);
1017 str = MemNew (len + 5);
1018 if (str != NULL) {
1019 StringCpy (str, "similar to ");
1020 StringCat (str, ptr);
1021 gbq->val = MemFree (gbq->val);
1022 gbq->val = StringSave (str);
1023 MemFree (str);
1024 }
1025 }
1026 }
1027 }
1028 gbq->qual = MemFree (gbq->qual);
1029 gbq->qual = StringSave ("note");
1030 }
1031 }
1032 }
1033
1034 static void ConvertBadInferenceToNote (IteM i)
1035
1036 {
1037 BaseFormPtr bfp;
1038 SeqEntryPtr sep;
1039
1040 #ifdef WIN_MAC
1041 bfp = currentFormDataPtr;
1042 #else
1043 bfp = GetObjectExtra (i);
1044 #endif
1045 if (bfp == NULL) return;
1046
1047 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1048
1049 VisitFeaturesInSep (sep, NULL, ConvertBadInfProc);
1050
1051 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1052 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1053 Update ();
1054 }
1055
1056 typedef struct {
1057 Int2 level;
1058 Boolean prevWasModified;
1059 } VecToNData, PNTR VecToNDataPtr;
1060
1061 typedef struct {
1062 Boolean dirtyFlag;
1063 Int2 number;
1064 } CdsDelStruct, PNTR CdsDelStructPtr;
1065
1066 typedef struct {
1067 FORM_MESSAGE_BLOCK
1068 Int2 number;
1069 } CdsDelForm, PNTR CdsDelFormPtr;
1070
1071 static void AddOrgNameToDefLines (IteM i)
1072
1073 {
1074 CommonAddOrgOrModsToDefLines (i, 0, 0, NULL);
1075 }
1076
1077 static void AddStrainToDefLines (IteM i)
1078
1079 {
1080 CommonAddOrgOrModsToDefLines (i, ORGMOD_strain, 0, NULL);
1081 }
1082
1083 static void AddCloneToDefLines (IteM i)
1084
1085 {
1086 CommonAddOrgOrModsToDefLines (i, 0, SUBSRC_clone, NULL);
1087 }
1088
1089 static void AddIsolateToDefLines (IteM i)
1090
1091 {
1092 CommonAddOrgOrModsToDefLines (i, ORGMOD_isolate, 0, NULL);
1093 }
1094
1095 static void AddHaplotypeToDefLines (IteM i)
1096
1097 {
1098 CommonAddOrgOrModsToDefLines (i, 0, SUBSRC_haplotype, NULL);
1099 }
1100
1101 static void AddCultivarToDefLines (IteM i)
1102
1103 {
1104 CommonAddOrgOrModsToDefLines (i, ORGMOD_cultivar, 0, NULL);
1105 }
1106
1107 static Boolean FindBestCitSubCallback (GatherContextPtr gcp)
1108
1109 {
1110 CitSubPtr best;
1111 CitSubPtr PNTR bestp;
1112 CitSubPtr csp;
1113 PubdescPtr pdp;
1114 ValNodePtr sdp;
1115 ValNodePtr vnp;
1116
1117 if (gcp == NULL) return TRUE;
1118 bestp = (CitSubPtr PNTR) gcp->userdata;
1119 if (bestp == NULL) return TRUE;
1120 if (gcp->thistype != OBJ_SEQDESC) return TRUE;
1121 sdp = (ValNodePtr) gcp->thisitem;
1122 if (sdp == NULL || sdp->choice != Seq_descr_pub) return TRUE;
1123 pdp = (PubdescPtr) sdp->data.ptrvalue;
1124 if (pdp == NULL) return TRUE;
1125 vnp = pdp->pub;
1126 if (vnp == NULL || vnp->choice != PUB_Sub) return TRUE;
1127 csp = (CitSubPtr) vnp->data.ptrvalue;
1128 if (csp == NULL) return TRUE;
1129 if (*bestp == NULL) {
1130 *bestp = csp;
1131 return TRUE;
1132 }
1133 best = *bestp;
1134 if (DateMatch (best->date, csp->date, FALSE) == -1) {
1135 *bestp = csp;
1136 return TRUE;
1137 }
1138 return TRUE;
1139 }
1140
1141 CharPtr kSubmitterUpdateText = "Sequence update by submitter";
1142 CharPtr kIndexerUpdateVecScreenText = "Sequence update by database staff to remove vector contamination";
1143
1144 extern Boolean CreateUpdateCitSubFromBestTemplate (
1145 SeqEntryPtr top_sep,
1146 SeqEntryPtr upd_sep,
1147 CharPtr update_txt
1148 )
1149 {
1150 CitSubPtr best;
1151 CitSubPtr csp;
1152 DatePtr dp;
1153 GatherScope gs;
1154 PubdescPtr pdp;
1155 ValNodePtr sdp;
1156 ValNodePtr vnp;
1157
1158 best = NULL;
1159 MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
1160 gs.seglevels = 1;
1161 gs.get_feats_location = FALSE;
1162 MemSet ((Pointer) (gs.ignore), (int)(TRUE), (size_t) (OBJ_MAX * sizeof(Boolean)));
1163 gs.ignore[OBJ_BIOSEQ] = FALSE;
1164 gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
1165 gs.ignore[OBJ_SEQDESC] = FALSE;
1166 gs.scope = top_sep;
1167 GatherSeqEntry (top_sep, (Pointer) (&best), FindBestCitSubCallback, &gs);
1168 if (best == NULL) {
1169 Message (MSG_OK, "There is no earlier cit-sub template");
1170 return FALSE;
1171 }
1172 dp = DateCurr ();
1173 if (dp != NULL) {
1174 if (DateMatch (best->date, dp, FALSE) == 0) {
1175 DateFree (dp);
1176 dp = NULL;
1177 if (upd_sep == top_sep
1178 && StringICmp (best->descr, update_txt) == 0)
1179 {
1180 Message (MSG_OK, "There already exists an update on today's date");
1181 Update ();
1182 return FALSE;
1183 } else if (best->descr == NULL) {
1184 best->descr = StringSave (update_txt);
1185 Message (MSG_OK, "Adding update indication to existing cit-sub");
1186 return TRUE;
1187 }
1188 }
1189 DateFree (dp);
1190 }
1191 sdp = CreateNewDescriptor (upd_sep, Seq_descr_pub);
1192 if (sdp == NULL) return FALSE;
1193 pdp = PubdescNew ();
1194 if (pdp == NULL) return FALSE;
1195 sdp->data.ptrvalue = (Pointer) pdp;
1196 vnp = ValNodeNew (NULL);
1197 csp = AsnIoMemCopy ((Pointer) best,
1198 (AsnReadFunc) CitSubAsnRead,
1199 (AsnWriteFunc) CitSubAsnWrite);
1200 pdp->pub = vnp;
1201 vnp->choice = PUB_Sub;
1202 vnp->data.ptrvalue = csp;
1203 csp->date = DateFree (csp->date);
1204 csp->date = DateCurr ();
1205 if (!StringHasNoText (update_txt)) {
1206 csp->descr = MemFree (csp->descr);
1207 csp->descr = StringSave (update_txt);
1208 }
1209
1210 if (top_sep == upd_sep)
1211 {
1212 Message (MSG_OK, "The update Cit-sub has been placed on the top Seq-entry");
1213 }
1214 return TRUE;
1215 }
1216
1217 static void AddCitSubForUpdateProc (BaseFormPtr bfp)
1218
1219 {
1220 SeqEntryPtr sep;
1221
1222 if (bfp == NULL) return;
1223 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1224 if (sep == NULL) return;
1225
1226 if ( CreateUpdateCitSubFromBestTemplate (sep, sep, kSubmitterUpdateText))
1227 {
1228 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1229 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1230 Update ();
1231 }
1232 return;
1233 }
1234
1235 static void AddCitSubForUpdate (IteM i)
1236
1237 {
1238 BaseFormPtr bfp;
1239
1240 #ifdef WIN_MAC
1241 bfp = currentFormDataPtr;
1242 #else
1243 bfp = GetObjectExtra (i);
1244 #endif
1245 AddCitSubForUpdateProc (bfp);
1246 }
1247
1248 /* FixLocus is copied from taxutil, then modified to remove embl_code use */
1249 static void FixLocus (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
1250 {
1251 BioseqPtr bsp;
1252 ValNodePtr vnp;
1253 TextSeqIdPtr tsip;
1254 Char tbuf[40];
1255 CharPtr ptr, embl_code;
1256
1257 if (! IS_Bioseq(sep))
1258 return;
1259
1260 bsp = (BioseqPtr)(sep->data.ptrvalue);
1261 embl_code = (CharPtr) data;
1262 /* if (! embl_code) return; */
1263
1264 for (vnp = bsp->id; vnp != NULL; vnp = vnp->next) {
1265 if ((vnp->choice == SEQID_GENBANK || vnp->choice == SEQID_TPG) && vnp->data.ptrvalue != NULL) {
1266 tsip = (TextSeqIdPtr) (vnp->data.ptrvalue);
1267 if (tsip->accession != NULL)
1268 {
1269 tsip->name = MemFree (tsip->name);
1270 if (bsp->repr != Seq_repr_seg) {
1271 /* ptr = StringMove (tbuf, embl_code); */
1272 ptr = tbuf;
1273 StringMove (ptr, tsip->accession);
1274 tsip->name = StringSave (tbuf);
1275 SeqMgrReplaceInBioseqIndex (bsp);
1276 }
1277 return;
1278 }
1279 }
1280 }
1281
1282 return;
1283 }
1284
1285 extern void DoFixupLocus (SeqEntryPtr sep);
1286 extern void DoFixupLocus (SeqEntryPtr sep)
1287
1288 {
1289 BioSourcePtr biop;
1290 BioseqSetPtr bssp;
1291 CharPtr embl_code;
1292 OrgRefPtr orp;
1293 ValNodePtr sdp;
1294
1295 if (IS_Bioseq_set (sep)) {
1296 bssp = (BioseqSetPtr) sep->data.ptrvalue;
1297 if (bssp != NULL && (bssp->_class == 7 ||
1298 (IsPopPhyEtcSet (bssp->_class)))) {
1299 for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
1300 DoFixupLocus (sep);
1301 }
1302 return;
1303 }
1304 }
1305 sdp = SeqEntryGetSeqDescr (sep, Seq_descr_source, NULL);
1306 if (sdp == NULL) return;
1307 biop = (BioSourcePtr) sdp->data.ptrvalue;
1308 if (biop == NULL) return;
1309 orp = biop->org;
1310 if (orp == NULL) return;
1311 /* embl_code = get_embl_code (orp); */
1312 embl_code = NULL;
1313 SeqEntryExplore (sep, (Pointer) embl_code, FixLocus);
1314 MemFree (embl_code);
1315 }
1316
1317 static TextSeqIdPtr GetTSIPforBSP (BioseqPtr bsp)
1318
1319 {
1320 SeqIdPtr sip;
1321 TextSeqIdPtr tsip = NULL;
1322
1323 if (bsp == NULL) return NULL;
1324
1325 for (sip = bsp->id; sip != NULL; sip = sip->next) {
1326 if (sip->choice == SEQID_GENBANK || sip->choice == SEQID_TPG) {
1327 tsip = (TextSeqIdPtr) sip->data.ptrvalue;
1328 }
1329 }
1330
1331 return tsip;
1332 }
1333
1334 static void DoFixPartLocus (SeqEntryPtr sep, CharPtr prefix, Int2 segment, Int2 digits)
1335
1336 {
1337 BioseqPtr bsp;
1338 Char ch;
1339 Char digs [16];
1340 CharPtr ptr;
1341 Char str [32];
1342 TextSeqIdPtr tsip;
1343
1344 if (sep == NULL || prefix == NULL) return;
1345 if (! IS_Bioseq (sep)) return;
1346 bsp = (BioseqPtr) sep->data.ptrvalue;
1347 if (bsp == NULL) return;
1348 if (bsp->repr != Seq_repr_raw && bsp->repr != Seq_repr_const) return;
1349 tsip = GetTSIPforBSP (bsp);
1350 if (tsip == NULL) return;
1351 tsip->name = MemFree (tsip->name);
1352 sprintf (digs, "%*d", (int) digits, (int) segment);
1353 ptr = digs;
1354 ch = *ptr;
1355 while (ch != '\0') {
1356 if (ch == ' ') {
1357 *ptr = '0';
1358 }
1359 ptr++;
1360 ch = *ptr;
1361 }
1362 sprintf (str, "%sS%s", prefix, digs);
1363 tsip->name = StringSave (str);
1364 }
1365
1366 extern void DoFixupSegSet (SeqEntryPtr sep);
1367 extern void DoFixupSegSet (SeqEntryPtr sep)
1368
1369 {
1370 CharPtr accn;
1371 Uint1 chs;
1372 Int2 digits;
1373 BioseqPtr nbsp;
1374 BioseqSetPtr bssp;
1375 size_t len;
1376 SeqEntryPtr nsep;
1377 Int2 numsegs;
1378 BioseqSetPtr pbssp;
1379 CharPtr prefix;
1380 SeqEntryPtr psep;
1381 BioseqPtr sbsp;
1382 Int2 segment;
1383 SeqIdPtr sip;
1384 Char str [32];
1385 Char tmp [128];
1386 TextSeqIdPtr tsip;
1387
1388 if (! IS_Bioseq_set (sep)) return;
1389 bssp = (BioseqSetPtr) sep->data.ptrvalue;
1390 if (bssp == NULL) return;
1391 if (bssp->_class != BioseqseqSet_class_segset) {
1392 for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
1393 DoFixupSegSet (sep);
1394 }
1395 return;
1396 }
1397 nsep = FindNucSeqEntry (sep);
1398 if (nsep == NULL) return;
1399 if (! IS_Bioseq (nsep)) return;
1400 nbsp = (BioseqPtr) nsep->data.ptrvalue;
1401 if (nbsp == NULL) return;
1402 if (nbsp->repr != Seq_repr_seg) return;
1403 sbsp = NULL;
1404 tsip = GetTSIPforBSP (nbsp);
1405 if (tsip == NULL || StringHasNoText (tsip->accession)) {
1406 sbsp = nbsp;
1407 nsep = FindNthSeqEntry (sep, 4);
1408 if (nsep == NULL) return;
1409 if (! IS_Bioseq (nsep)) return;
1410 nbsp = (BioseqPtr) nsep->data.ptrvalue;
1411 if (nbsp == NULL) return;
1412 if (nbsp->repr != Seq_repr_raw && nbsp->repr != Seq_repr_const) return;
1413 tsip = GetTSIPforBSP (nbsp);
1414 }
1415 if (tsip == NULL) return;
1416 chs = SEQID_GENBANK;
1417 for (sip = nbsp->id; sip != NULL; sip = sip->next) {
1418 if (sip->choice == SEQID_GENBANK || sip->choice == SEQID_TPG) {
1419 chs = sip->choice;
1420 }
1421 }
1422 accn = tsip->accession;
1423 if (StringHasNoText (accn)) return;
1424 psep = FindBioseqSetByClass (sep, BioseqseqSet_class_parts);
1425 if (psep == NULL) return;
1426 pbssp = (BioseqSetPtr) psep->data.ptrvalue;
1427 if (pbssp == NULL) return;
1428 for (sep = pbssp->seq_set, numsegs = 0; sep != NULL; sep = sep->next, numsegs++) continue;
1429 StringNCpy_0 (tmp, accn, sizeof (tmp));
1430 prefix = tmp;
1431 len = StringLen (prefix);
1432 if (numsegs > 999) {
1433 digits = 4;
1434 } else if (numsegs > 99) {
1435 digits = 3;
1436 } else if (numsegs > 9) {
1437 digits = 2;
1438 } else {
1439 digits = 1;
1440 }
1441 if (digits + 1 + len > 16) {
1442 prefix += digits + 1 + len - 16;
1443 }
1444
1445 for (sep = pbssp->seq_set, segment = 1; sep != NULL; sep = sep->next, segment++) {
1446 DoFixPartLocus (sep, prefix, segment, digits);
1447 }
1448
1449 if (sbsp == NULL) return;
1450 tsip = NULL;
1451 for (sip = sbsp->id; sip != NULL; sip = sip->next) {
1452 if (sip->choice == SEQID_GENBANK || sip->choice == SEQID_TPG) {
1453 tsip = (TextSeqIdPtr) sip->data.ptrvalue;
1454 }
1455 }
1456 if (tsip == NULL) {
1457 tsip = TextSeqIdNew ();
1458 if (tsip == NULL) return;
1459 ValNodeAddPointer (&(sbsp->id), chs, (Pointer) tsip);
1460 }
1461 tsip->name = MemFree (tsip->name);
1462 sprintf (str, "SEG_%sS", prefix);
1463 tsip->name = StringSave (str);
1464 SeqMgrReplaceInBioseqIndex (sbsp);
1465 }
1466
1467 static void ForceLocusFixup (IteM i)
1468
1469 {
1470 BaseFormPtr bfp;
1471 SeqEntryPtr sep;
1472 ErrSev sev;
1473
1474 #ifdef WIN_MAC
1475 bfp = currentFormDataPtr;
1476 #else
1477 bfp = GetObjectExtra (i);
1478 #endif
1479 if (bfp == NULL) return;
1480 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1481 if (sep == NULL) return;
1482 sev = ErrSetMessageLevel (SEV_FATAL);
1483 WatchCursor ();
1484 Update ();
1485 DoFixupLocus (sep);
1486 DoFixupSegSet (sep);
1487 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1488 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1489 ArrowCursor ();
1490 Update ();
1491 ErrSetMessageLevel (sev);
1492 ErrClear ();
1493 ErrShow ();
1494 }
1495
1496 extern void GetRidOfRedundantSourceNotes (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent);
1497
1498 static void CleanupGenbankBlockCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
1499
1500 {
1501 BioseqPtr bsp;
1502 BioseqSetPtr bssp;
1503 Boolean empty;
1504 GBBlockPtr gbp;
1505 ValNodePtr nextsdp;
1506 Pointer PNTR prevsdp;
1507 ValNodePtr sdp;
1508
1509 if (sep == NULL || sep->data.ptrvalue == NULL) return;
1510 if (IS_Bioseq (sep)) {
1511 bsp = (BioseqPtr) sep->data.ptrvalue;
1512 sdp = bsp->descr;
1513 prevsdp = (Pointer PNTR) &(bsp->descr);
1514 } else if (IS_Bioseq_set (sep)) {
1515 bssp = (BioseqSetPtr) sep->data.ptrvalue;
1516 sdp = bssp->descr;
1517 prevsdp = (Pointer PNTR) &(bssp->descr);
1518 } else return;
1519 while (sdp != NULL) {
1520 nextsdp = sdp->next;
1521 empty = FALSE;
1522 if (sdp->choice == Seq_descr_genbank && sdp->data.ptrvalue == NULL) {
1523 empty = TRUE;
1524 } else if (sdp->choice == Seq_descr_genbank && sdp->data.ptrvalue != NULL) {
1525 gbp = (GBBlockPtr) sdp->data.ptrvalue;
1526 gbp->source = MemFree (gbp->source); /* remove within Sequin */
1527 gbp->origin = MemFree (gbp->origin);
1528 gbp->taxonomy = MemFree (gbp->taxonomy);
1529 if (gbp->extra_accessions == NULL && gbp->source == NULL &&
1530 gbp->keywords == NULL && gbp->origin == NULL &&
1531 gbp->date == NULL && gbp->entry_date == NULL &&
1532 gbp->div == NULL && gbp->taxonomy == NULL) {
1533 empty = TRUE;
1534 }
1535 }
1536 if (empty) {
1537 *(prevsdp) = sdp->next;
1538 sdp->next = NULL;
1539 SeqDescFree (sdp);
1540 } else {
1541 prevsdp = (Pointer PNTR) &(sdp->next);
1542 }
1543 sdp = nextsdp;
1544 }
1545 }
1546
1547 static void CheckBioSourceForEnvironmentalSample (BioSourcePtr biop, Pointer userdata)
1548 {
1549 BoolPtr bp;
1550
1551 if (biop == NULL || userdata == NULL) return;
1552
1553 bp = (BoolPtr) userdata;
1554 if (! *bp) return;
1555
1556 if (biop->org == NULL || biop->org->orgname == NULL)
1557 {
1558 *bp = FALSE;
1559 return;
1560 }
1561 if (StringSearch (biop->org->orgname->lineage, "environmental sample") == NULL)
1562 {
1563 *bp = FALSE;
1564 }
1565 }
1566
1567 static Boolean CheckForEnvironmentalSample (BioseqSetPtr bssp)
1568 {
1569 Boolean all_enviro = TRUE;
1570
1571 if (bssp == NULL) return FALSE;
1572
1573 VisitBioSourcesInSet (bssp, (Pointer) &all_enviro, CheckBioSourceForEnvironmentalSample);
1574
1575 return all_enviro;
1576 }
1577
1578
1579 static void ConvertToEcoSets (SeqEntryPtr sep)
1580 {
1581 BioseqSetPtr bssp;
1582 SeqEntryPtr sep_entry;
1583
1584 if (sep == NULL) return;
1585
1586 if (!IS_Bioseq_set (sep)) return;
1587 bssp = (BioseqSetPtr) sep->data.ptrvalue;
1588 if (bssp == NULL) return;
1589
1590 if (bssp->_class == BioseqseqSet_class_mut_set
1591 || bssp->_class == BioseqseqSet_class_pop_set
1592 || bssp->_class == BioseqseqSet_class_phy_set)
1593 {
1594 if (CheckForEnvironmentalSample (bssp))
1595 {
1596 bssp->_class = BioseqseqSet_class_eco_set;
1597 }
1598 }
1599 for (sep_entry = bssp->seq_set; sep_entry != NULL; sep_entry = sep_entry->next)
1600 {
1601 if (IS_Bioseq_set (sep_entry))
1602 {
1603 ConvertToEcoSets (sep_entry);
1604 }
1605 }
1606 }
1607
1608 static void AddQualsFromLineageAndDiv (BioSourcePtr biop, Pointer userdata)
1609 {
1610 ValNode vn;
1611
1612 if (biop == NULL || biop->org == NULL || biop->org->orgname == NULL) return;
1613
1614 if (StringISearch (biop->org->orgname->lineage, "environmental sample") != NULL
1615 || StringCmp (biop->org->orgname->div, "ENV") == 0)
1616 {
1617 vn.choice = SourceQualChoice_textqual;
1618 vn.data.intvalue = Source_qual_environmental_sample;
1619 vn.next = NULL;
1620 SetSourceQualInBioSource (biop, &vn, NULL, "", ExistingTextOption_replace_old);
1621 }
1622 if (StringISearch (biop->org->orgname->lineage, "metagenomes") != NULL) {
1623 vn.choice = SourceQualChoice_textqual;
1624 vn.data.intvalue = Source_qual_metagenomic;
1625 vn.next = NULL;
1626 SetSourceQualInBioSource (biop, &vn, NULL, "", ExistingTextOption_replace_old);
1627 }
1628 }
1629
1630 extern void ForceCleanupEntityID (Uint2 entityID)
1631
1632 {
1633 SeqEntryPtr sep;
1634 ModTextFixPtr tfp;
1635
1636 sep = GetTopSeqEntryForEntityID (entityID);
1637 if (sep == NULL) return;
1638 SeqMgrClearFeatureIndexes (entityID, NULL);
1639 SeqEntryExplore (sep, NULL, CleanupGenbankBlockCallback);
1640 SeqEntryExplore (sep, NULL, CleanupEmptyFeatCallback);
1641 SeqEntryExplore (sep, NULL, MergeAdjacentAnnotsCallback);
1642 MySeqEntryToAsn3 (sep, TRUE, FALSE, TRUE);
1643 CorrectGenCodes (sep, entityID);
1644 CleanUpPseudoProducts (entityID, sep);
1645 SeqEntryExplore (sep, NULL, GetRidOfRedundantSourceNotes);
1646 RenormalizeNucProtSets (sep, TRUE);
1647 CdCheck (sep, NULL);
1648 ConvertToEcoSets (sep);
1649 VisitBioSourcesInSep (sep, NULL, AddQualsFromLineageAndDiv);
1650 tfp = ModTextFixNew ();
1651 VisitBioSourcesInSep (sep, tfp, RemoveTextFromTextFreeSubSourceModifiers);
1652 MemFree (tfp);
1653 ObjMgrSetDirtyFlag (entityID, TRUE);
1654 ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
1655 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1656 }
1657
1658 static void ForceCleanupBtn (IteM i, ButtoN b, Boolean validate)
1659
1660 {
1661 BaseFormPtr bfp;
1662
1663 if (b != NULL) {
1664 bfp = GetObjectExtra (b);
1665 } else {
1666 #ifdef WIN_MAC
1667 bfp = currentFormDataPtr;
1668 #else
1669 bfp = GetObjectExtra (i);
1670 #endif
1671 }
1672 if (bfp == NULL) return;
1673 ForceCleanupEntityID (bfp->input_entityID);
1674 if (validate) {
1675 ValSeqEntryForm (bfp->form);
1676 }
1677 }
1678
1679
1680 static void ForceCleanup (IteM i)
1681
1682 {
1683 ForceCleanupBtn (i, NULL, TRUE);
1684 }
1685
1686 static void MapWholeToInt (SeqFeatPtr sfp, Pointer userdata)
1687
1688 {
1689 BioseqPtr bsp;
1690 SeqLocPtr location;
1691 SeqIntPtr sint;
1692 SeqIdPtr sip;
1693
1694 if (sfp == NULL) return;
1695 location = sfp->location;
1696 if (location == NULL) return;
1697 if (location->choice != SEQLOC_WHOLE) return;
1698 sip = SeqLocId (location);
1699 if (sip == NULL) return;
1700 bsp = BioseqFind (sip);
1701 if (bsp == NULL) return;
1702 sint = SeqIntNew ();
1703 if (sint == NULL) return;
1704 sint->from = 0;
1705 sint->to = bsp->length - 1;
1706 sint->id = SeqIdDup (sip);
1707 location = ValNodeAddPointer (NULL, SEQLOC_INT, (Pointer) sint);
1708 sfp->location = SeqLocFree (sfp->location);
1709 sfp->location = location;
1710 }
1711
1712 static void ConvertWholeToInterval (IteM i)
1713
1714 {
1715 BaseFormPtr bfp;
1716 SeqEntryPtr sep;
1717
1718 #ifdef WIN_MAC
1719 bfp = currentFormDataPtr;
1720 #else
1721 bfp = GetObjectExtra (i);
1722 #endif
1723 if (bfp == NULL) return;
1724 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1725 if (sep == NULL) return;
1726 VisitFeaturesInSep (sep, NULL, MapWholeToInt);
1727 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1728 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1729 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1730 }
1731
1732 static void CorrectBothStrands (SeqFeatPtr sfp, Pointer userdata)
1733
1734 {
1735 SeqLocPtr location, slp = NULL;
1736 SeqIntPtr sint;
1737 SeqPntPtr spp;
1738
1739 if (sfp == NULL) return;
1740 location = sfp->location;
1741 if (location == NULL) return;
1742
1743 while ((slp = SeqLocFindNext (location, slp)) != NULL) {
1744 switch (slp->choice) {
1745 case SEQLOC_INT :
1746 sint = (SeqIntPtr) slp->data.ptrvalue;
1747 if (sint != NULL) {
1748 if (sint->strand == Seq_strand_both) {
1749 sint->strand = Seq_strand_plus;
1750 } else if (sint->strand == Seq_strand_both_rev) {
1751 sint->strand = Seq_strand_minus;
1752 }
1753 }
1754 break;
1755 case SEQLOC_PNT :
1756 spp = (SeqPntPtr) slp->data.ptrvalue;
1757 if (spp != NULL) {
1758 if (spp->strand == Seq_strand_both) {
1759 spp->strand = Seq_strand_plus;
1760 } else if (spp->strand == Seq_strand_both_rev) {
1761 spp->strand = Seq_strand_minus;
1762 }
1763 }
1764 break;
1765 default :
1766 break;
1767 }
1768 }
1769 }
1770
1771 static void ConvertBothStrands (IteM i)
1772
1773 {
1774 BaseFormPtr bfp;
1775 SeqEntryPtr sep;
1776
1777 #ifdef WIN_MAC
1778 bfp = currentFormDataPtr;
1779 #else
1780 bfp = GetObjectExtra (i);
1781 #endif
1782 if (bfp == NULL) return;
1783 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1784 if (sep == NULL) return;
1785 VisitFeaturesInSep (sep, NULL, CorrectBothStrands);
1786 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1787 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1788 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1789 }
1790
1791 static void AssignFeatIDs (IteM i)
1792
1793 {
1794 BaseFormPtr bfp;
1795 SeqEntryPtr sep;
1796
1797 #ifdef WIN_MAC
1798 bfp = currentFormDataPtr;
1799 #else
1800 bfp = GetObjectExtra (i);
1801 #endif
1802 if (bfp == NULL) return;
1803 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1804 if (sep == NULL) return;
1805
1806 AssignFeatureIDs (sep);
1807
1808 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1809 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1810 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1811 Update ();
1812 }
1813
1814 static void ReassignFeatIDs (IteM i)
1815
1816 {
1817 MsgAnswer ans;
1818 BaseFormPtr bfp;
1819 SeqEntryPtr sep;
1820
1821 #ifdef WIN_MAC
1822 bfp = currentFormDataPtr;
1823 #else
1824 bfp = GetObjectExtra (i);
1825 #endif
1826 if (bfp == NULL) return;
1827 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1828 if (sep == NULL) return;
1829
1830 ans = Message (MSG_OKC, "Are you sure you want to reassign feature identifiers?");
1831 if (ans == ANS_CANCEL) return;
1832
1833 ReassignFeatureIDs (sep);
1834
1835 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1836 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1837 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1838 Update ();
1839 }
1840
1841 static void UniqifyFeatIDs (IteM i)
1842
1843 {
1844 MsgAnswer ans;
1845 BaseFormPtr bfp;
1846 BioseqSetPtr bssp;
1847 Int4 count;
1848 Int4 offset = 0;
1849 SeqEntryPtr sep;
1850
1851 #ifdef WIN_MAC
1852 bfp = currentFormDataPtr;
1853 #else
1854 bfp = GetObjectExtra (i);
1855 #endif
1856 if (bfp == NULL) return;
1857 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1858 if (sep == NULL) return;
1859
1860 if (! IS_Bioseq_set (sep)) return;
1861 bssp = (BioseqSetPtr) sep->data.ptrvalue;
1862 if (bssp == NULL || bssp->_class != BioseqseqSet_class_genbank) return;
1863
1864 ans = Message (MSG_OKC, "Are you sure you want to make merged feature identifiers unique?");
1865 if (ans == ANS_CANCEL) return;
1866
1867 for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
1868 count = FindHighestFeatureID (sep);
1869 OffsetFeatureIDs (sep, offset);
1870 OffsetFeatureIDXrefs (sep, offset);
1871 offset += count;
1872 }
1873
1874 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1875 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1876 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1877 Update ();
1878 }
1879
1880 static void ClearFeatIDsAndLinks (IteM i)
1881
1882 {
1883 MsgAnswer ans;
1884 BaseFormPtr bfp;
1885 SeqEntryPtr sep;
1886
1887 #ifdef WIN_MAC
1888 bfp = currentFormDataPtr;
1889 #else
1890 bfp = GetObjectExtra (i);
1891 #endif
1892 if (bfp == NULL) return;
1893 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1894 if (sep == NULL) return;
1895
1896 ans = Message (MSG_YN, "Are you sure you want to remove feature IDs and links?");
1897 if (ans == ANS_NO) return;
1898
1899 ClearFeatureIDs (sep);
1900
1901 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1902 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1903 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1904 Update ();
1905 }
1906
1907 static void LinkByOverlap (IteM i)
1908
1909 {
1910 BaseFormPtr bfp;
1911 SeqEntryPtr sep;
1912
1913 #ifdef WIN_MAC
1914 bfp = currentFormDataPtr;
1915 #else
1916 bfp = GetObjectExtra (i);
1917 #endif
1918 if (bfp == NULL) return;
1919 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1920 if (sep == NULL) return;
1921
1922 LinkCDSmRNAbyOverlap (sep);
1923
1924 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1925 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1926 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1927 Update ();
1928 }
1929
1930 static void LinkByProduct (IteM i)
1931
1932 {
1933 BaseFormPtr bfp;
1934 ValNodePtr bsplist;
1935 SeqEntryPtr sep;
1936
1937 #ifdef WIN_MAC
1938 bfp = currentFormDataPtr;
1939 #else
1940 bfp = GetObjectExtra (i);
1941 #endif
1942 if (bfp == NULL) return;
1943 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1944 if (sep == NULL) return;
1945
1946 bsplist = LockFarComponentsEx (sep, FALSE, TRUE, TRUE, NULL);
1947 LinkCDSmRNAbyProduct (sep);
1948 bsplist = UnlockFarComponents (bsplist);
1949
1950 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1951 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1952 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1953 Update ();
1954 }
1955
1956 static void LinkByLabel (IteM i)
1957
1958 {
1959 BaseFormPtr bfp;
1960 ValNodePtr bsplist;
1961 SeqEntryPtr sep;
1962
1963 #ifdef WIN_MAC
1964 bfp = currentFormDataPtr;
1965 #else
1966 bfp = GetObjectExtra (i);
1967 #endif
1968 if (bfp == NULL) return;
1969 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
1970 if (sep == NULL) return;
1971
1972 bsplist = LockFarComponentsEx (sep, FALSE, TRUE, TRUE, NULL);
1973 LinkCDSmRNAbyLabel (sep);
1974 bsplist = UnlockFarComponents (bsplist);
1975
1976 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
1977 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
1978 ObjMgrDeSelect (0, 0, 0, 0, NULL);
1979 Update ();
1980 }
1981
1982
1983 extern void RemoveFeatureLink (SeqFeatPtr sfp1, SeqFeatPtr sfp2)
1984 {
1985 SeqFeatXrefPtr xref, next, PNTR prevlink;
1986 ObjectIdPtr oip;
1987 SeqFeatPtr link_sfp;
1988 Char buf [32];
1989 CharPtr str = NULL;
1990
1991 if (sfp1 == NULL) return;
1992
1993 prevlink = (SeqFeatXrefPtr PNTR) &(sfp1->xref);
1994 xref = sfp1->xref;
1995 while (xref != NULL) {
1996 next = xref->next;
1997 link_sfp = NULL;
1998
1999 if (xref->id.choice == 3) {
2000 oip = (ObjectIdPtr) xref->id.value.ptrvalue;
2001 if (oip != NULL) {
2002 if (StringDoesHaveText (oip->str)) {
2003 str = oip->str;
2004 } else {
2005 sprintf (buf, "%ld", (long) oip->id);
2006 str = buf;
2007 }
2008 link_sfp = SeqMgrGetFeatureByFeatID (sfp1->idx.entityID, NULL, str, NULL, NULL);
2009 }
2010 }
2011 if (link_sfp == sfp2) {
2012 *prevlink = xref->next;
2013 xref->next = NULL;
2014 MemFree (xref);
2015 } else {
2016 prevlink = (SeqFeatXrefPtr PNTR) &(xref->next);
2017 }
2018
2019 xref = next;
2020 }
2021 }
2022
2023
2024 extern void LinkTwoFeatures (SeqFeatPtr dst, SeqFeatPtr sfp)
2025
2026 {
2027 ChoicePtr cp;
2028 ObjectIdPtr oip;
2029 SeqFeatXrefPtr xref, prev_xref, next_xref;
2030 SeqFeatPtr old_match;
2031
2032 if (dst == NULL || sfp == NULL) return;
2033
2034 cp = &(dst->id);
2035 if (cp == NULL) return;
2036 if (cp->choice == 3) {
2037 /* don't create a duplicate xref, remove links to other features */
2038 xref = sfp->xref;
2039 prev_xref = NULL;
2040 while (xref != NULL) {
2041 next_xref = xref->next;
2042 if (xref->id.choice == 3 && xref->id.value.ptrvalue != NULL) {
2043 if (ObjectIdMatch (cp->value.ptrvalue, xref->id.value.ptrvalue)) {
2044 /* already have this xref */
2045 return;
2046 } else {
2047 old_match = SeqMgrGetFeatureByFeatID (sfp->idx.entityID, NULL, NULL, xref, NULL);
2048 RemoveFeatureLink (sfp, old_match);
2049 RemoveFeatureLink (old_match, sfp);
2050 }
2051 } else {
2052 prev_xref = xref;
2053 }
2054 xref = next_xref;
2055 }
2056
2057 oip = (ObjectIdPtr) cp->value.ptrvalue;
2058 if (oip != NULL) {
2059 oip = AsnIoMemCopy (oip, (AsnReadFunc) ObjectIdAsnRead,
2060 (AsnWriteFunc) ObjectIdAsnWrite);
2061 if (oip != NULL) {
2062 xref = SeqFeatXrefNew ();
2063 if (xref != NULL) {
2064 xref->id.choice = 3;
2065 xref->id.value.ptrvalue = (Pointer) oip;
2066 xref->next = sfp->xref;
2067 sfp->xref = xref;
2068 }
2069 }
2070 }
2071 }
2072 }
2073
2074 static void LinkSelected (IteM i)
2075
2076 {
2077 BaseFormPtr bfp;
2078 SeqEntryPtr sep;
2079 SeqFeatPtr sfp1, sfp2;
2080 SelStructPtr ssp;
2081
2082 #ifdef WIN_MAC
2083 bfp = currentFormDataPtr;
2084 #else
2085 bfp = GetObjectExtra (i);
2086 #endif
2087 if (bfp == NULL) return;
2088 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2089 if (sep == NULL) return;
2090
2091 AssignFeatureIDs (sep);
2092
2093 ssp = ObjMgrGetSelected ();
2094 if (ssp == NULL) {
2095 Message (MSG_OK, "No features selected");
2096 return;
2097 }
2098 if (ssp->itemtype != OBJ_SEQFEAT) {
2099 Message (MSG_OK, "Something other than a feature is selected");
2100 return;
2101 }
2102 sfp1 = SeqMgrGetDesiredFeature (ssp->entityID, NULL, ssp->itemID, 0, NULL, NULL);
2103 if (sfp1 == NULL) {
2104 Message (MSG_OK, "Unable to find selected feature");
2105 return;
2106 }
2107 ssp = ssp->next;
2108 if (ssp == NULL) {
2109 Message (MSG_OK, "Only one feature was selected, two must be selected");
2110 return;
2111 }
2112 if (ssp->itemtype != OBJ_SEQFEAT) {
2113 Message (MSG_OK, "Something other than a feature is selected");
2114 return;
2115 }
2116 sfp2 = SeqMgrGetDesiredFeature (ssp->entityID, NULL, ssp->itemID, 0, NULL, NULL);
2117 if (ssp->next != NULL) {
2118 Message (MSG_OK, "Only two features must be selected");
2119 return;
2120 }
2121 if (sfp2 == NULL) {
2122 Message (MSG_OK, "Unable to find selected feature");
2123 return;
2124 }
2125
2126 LinkTwoFeatures (sfp1, sfp2);
2127 LinkTwoFeatures (sfp2, sfp1);
2128
2129 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2130 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2131 ObjMgrDeSelect (0, 0, 0, 0, NULL);
2132 Update ();
2133 }
2134
2135 static void SelCDSmRNALink (IteM i)
2136
2137 {
2138 Char buf [32];
2139 ObjectIdPtr oip;
2140 SeqFeatPtr sfp;
2141 SelStructPtr ssp;
2142 CharPtr str = NULL;
2143 SeqFeatXrefPtr xref;
2144
2145 ssp = ObjMgrGetSelected ();
2146 if (ssp == NULL) {
2147 Message (MSG_OK, "No feature selected");
2148 return;
2149 }
2150 if (ssp->next != NULL) {
2151 Message (MSG_OK, "Only one feature must be selected");
2152 return;
2153 }
2154 if (ssp->itemtype != OBJ_SEQFEAT) {
2155 Message (MSG_OK, "Something other than a feature is selected");
2156 return;
2157 }
2158
2159 sfp = SeqMgrGetDesiredFeature (ssp->entityID, NULL, ssp->itemID, 0, NULL, NULL);
2160 if (sfp == NULL) {
2161 Message (MSG_OK, "Unable to find selected feature");
2162 return;
2163 }
2164
2165 for (xref = sfp->xref; xref != NULL; xref = xref->next) {
2166 if (xref->id.choice != 3) continue;
2167 oip = (ObjectIdPtr) xref->id.value.ptrvalue;
2168 if (oip != NULL) {
2169 if (StringDoesHaveText (oip->str)) {
2170 str = oip->str;
2171 } else {
2172 sprintf (buf, "%ld", (long) oip->id);
2173 str = buf;
2174 }
2175 }
2176 }
2177
2178 if (str == NULL) {
2179 Message (MSG_OK, "Unable to extract feature ID xref");
2180 return;
2181 }
2182
2183 sfp = SeqMgrGetFeatureByFeatID (ssp->entityID, NULL, str, NULL, NULL);
2184 if (sfp == NULL) {
2185 Message (MSG_OK, "Unable to find referenced feature");
2186 return;
2187 }
2188
2189 ObjMgrAlsoSelect (sfp->idx.entityID, sfp->idx.itemID, OBJ_SEQFEAT, 0, NULL);
2190 ObjMgrSendMsg (OM_MSG_UPDATE, sfp->idx.entityID, 0, 0);
2191 Update ();
2192 }
2193
2194 extern void ForceTaxonFixupBtn (IteM i, ButtoN b)
2195
2196 {
2197 BaseFormPtr bfp;
2198 SeqEntryPtr sep;
2199
2200 if (b != NULL) {
2201 bfp = GetObjectExtra (b);
2202 } else {
2203 #ifdef WIN_MAC
2204 bfp = currentFormDataPtr;
2205 #else
2206 bfp = GetObjectExtra (i);
2207 #endif
2208 }
2209 if (bfp == NULL) return;
2210 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2211 if (sep == NULL) return;
2212 /* SeqEntryExplore (sep, (Pointer) bfp, CleanupGenbankBlockCallback); */
2213 SeqEntryExplore (sep, NULL, CleanupEmptyFeatCallback);
2214 SeqEntryExplore (sep, NULL, MergeAdjacentAnnotsCallback);
2215 MySeqEntryToAsn3 (sep, TRUE, FALSE, TRUE);
2216 CorrectGenCodes (sep, bfp->input_entityID);
2217 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2218 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2219 }
2220
2221 static void ForceTaxonFixup (IteM i)
2222
2223 {
2224 ForceTaxonFixupBtn (i, NULL);
2225 }
2226
2227 static void JustTaxonFixup (IteM i)
2228
2229 {
2230 BaseFormPtr bfp;
2231 SeqEntryPtr sep;
2232
2233 #ifdef WIN_MAC
2234 bfp = currentFormDataPtr;
2235 #else
2236 bfp = GetObjectExtra (i);
2237 #endif
2238 if (bfp == NULL) return;
2239 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2240 if (sep == NULL) return;
2241 Taxon3ReplaceOrgInSeqEntry (sep, FALSE);
2242 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2243 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2244 }
2245
2246
2247 typedef struct hasdupfeatsdata {
2248 Uint1 featdef;
2249 Int4 num_feat;
2250 Int4 num_cds_with_product;
2251 ValNodePtr delete_list;
2252 Boolean case_sensitive;
2253 Boolean ignore_partials;
2254 } HasDupFeatsData, PNTR HasDupFeatsPtr;
2255
2256 typedef struct dupfeatsdlg {
2257 DIALOG_MESSAGE_BLOCK
2258 DialoG feat_type;
2259 ButtoN ignore_partials;
2260 Uint2 entityID;
2261 WindoW window;
2262 } DupFeatsDlgData, PNTR DupFeatsDlgPtr;
2263
2264 static Pointer DupFeatsDlgToData (DialoG d)
2265 {
2266 DupFeatsDlgPtr dlg;
2267 HasDupFeatsPtr data;
2268 ValNodePtr vnp;
2269
2270 dlg = (DupFeatsDlgPtr) GetObjectExtra (d);
2271 if (dlg == NULL) {
2272 return NULL;
2273 }
2274
2275 data = (HasDupFeatsPtr) MemNew (sizeof (HasDupFeatsData));
2276 data->num_feat = 0;
2277 data->num_cds_with_product = 0;
2278 data->delete_list = NULL;
2279 data->case_sensitive = TRUE;
2280
2281 vnp = DialogToPointer (dlg->feat_type);
2282 if (vnp == NULL) {
2283 data->featdef = 0;
2284 } else {
2285 if (vnp->choice == Feature_type_any) {
2286 data->featdef = 0;
2287 } else {
2288 data->featdef = GetFeatdefFromFeatureType (vnp->choice);
2289 }
2290 vnp = ValNodeFreeData (vnp);
2291 }
2292
2293 data->ignore_partials = GetStatus (dlg->ignore_partials);
2294
2295 return data;
2296 }
2297
2298
2299 static DialoG DupFeatsDialog (GrouP g, Uint2 entityID, WindoW w)
2300 {
2301 DupFeatsDlgPtr dlg;
2302 GrouP p;
2303 ValNode vn;
2304 ValNodePtr feature_list = NULL;
2305
2306 dlg = (DupFeatsDlgPtr) MemNew (sizeof (DupFeatsDlgData));
2307
2308 p = HiddenGroup (g, -1, 0, NULL);
2309 SetObjectExtra (p, dlg, StdCleanupExtraProc);
2310
2311 dlg->dialog = (DialoG) p;
2312 dlg->fromdialog = DupFeatsDlgToData;
2313
2314 dlg->entityID = entityID;
2315 dlg->window = w;
2316
2317 feature_list = ValNodeNew (NULL);
2318 feature_list->choice = Feature_type_any;
2319 feature_list->data.ptrvalue = StringSave ("All");
2320 AddAllFeaturesToChoiceList (&feature_list);
2321 dlg->feat_type = ValNodeSelectionDialog (p, feature_list, TALL_SELECTION_LIST, ValNodeStringName,
2322 ValNodeSimpleDataFree, ValNodeStringCopy,
2323 ValNodeChoiceMatch, "feature type",
2324 NULL, NULL, FALSE);
2325
2326 vn.choice = Feature_type_any;
2327 vn.data.ptrvalue = NULL;
2328 vn.next = NULL;
2329 PointerToDialog (dlg->feat_type, &vn);
2330 dlg->ignore_partials = CheckBox (p, "Ignore partials", NULL);
2331
2332 AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feat_type, (HANDLE) dlg->ignore_partials, NULL);
2333
2334 return (DialoG) p;
2335 }
2336
2337
2338 static void HasDupFeatsBioseqCallback (BioseqPtr bsp, Pointer data)
2339 {
2340 HasDupFeatsPtr h;
2341 SeqFeatPtr sfp1, sfp2;
2342 SeqMgrFeatContext fcontext;
2343
2344 if (bsp == NULL || data == NULL) {
2345 return;
2346 }
2347
2348 h = (HasDupFeatsPtr) data;
2349
2350 sfp1 = SeqMgrGetNextFeature (bsp, NULL, 0,h->featdef, &fcontext);
2351 while (sfp1 != NULL) {
2352 sfp2 = SeqMgrGetNextFeature (bsp, sfp1, 0, h->featdef, &fcontext);
2353 if (sfp1 == sfp2) {
2354 break;
2355 }
2356 if (DoFeaturesMatch (sfp1, sfp2, FALSE, h->case_sensitive, h->ignore_partials)) {
2357 h->num_feat++;
2358 if (sfp2->data.choice == SEQFEAT_CDREGION && sfp2->product != NULL) {
2359 h->num_cds_with_product++;
2360 }
2361 ValNodeAddPointer (&(h->delete_list), OBJ_SEQFEAT, sfp2);
2362 }
2363 sfp1 = sfp2;
2364 }
2365 }
2366
2367
2368 static Boolean RemoveDuplicateFeatsAction (Uint2 entityID, HasDupFeatsPtr data)
2369 {
2370 SeqEntryPtr sep;
2371 Boolean rval = FALSE;
2372 MsgAnswer ans;
2373 Boolean remove_proteins = FALSE;
2374 ValNodePtr vnp;
2375 SeqFeatPtr sfp;
2376 BioseqPtr protbsp;
2377
2378 sep = GetTopSeqEntryForEntityID (entityID);
2379
2380 VisitBioseqsInSep (sep, data, HasDupFeatsBioseqCallback);
2381 if (data->num_feat == 0) {
2382 Message (MSG_ERROR, "No duplicates found");
2383 return rval;
2384 }
2385
2386 if (data->num_cds_with_product > 0) {
2387 ans = Message (MSG_YNC, "%d duplicate features found. %d coding regions have protein products. Remove protein products?",
2388 data->num_feat, data->num_cds_with_product);
2389 if (ans == ANS_CANCEL) {
2390 data->delete_list = ValNodeFree (data->delete_list);
2391 return rval;
2392 } else if (ans == ANS_YES) {
2393 remove_proteins = TRUE;
2394 }
2395 }
2396
2397 for (vnp = data->delete_list; vnp != NULL; vnp = vnp->next) {
2398 sfp = (SeqFeatPtr) vnp->data.ptrvalue;
2399 if (sfp != NULL) {
2400 if (remove_proteins && sfp->data.choice == SEQFEAT_CDREGION && sfp->product != NULL) {
2401 protbsp = BioseqFindFromSeqLoc (sfp->product);
2402 if (protbsp != NULL) {
2403 protbsp->idx.deleteme = TRUE;
2404 }
2405 }
2406 sfp->idx.deleteme = TRUE;
2407 }
2408 }
2409
2410 DeleteMarkedObjects (entityID, 0, NULL);
2411 if (remove_proteins) {
2412 RenormalizeNucProtSets (sep, TRUE);
2413 }
2414
2415 ObjMgrSetDirtyFlag (entityID, TRUE);
2416 ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
2417 rval = TRUE;
2418 return rval;
2419 }
2420
2421
2422 static void DoRemoveDuplicateFeats (ButtoN b)
2423 {
2424 DialoG d;
2425 DupFeatsDlgPtr dlg;
2426 HasDupFeatsPtr data;
2427
2428 d = (DialoG) GetObjectExtra (b);
2429 dlg = (DupFeatsDlgPtr) GetObjectExtra (d);
2430
2431 if (dlg == NULL) {
2432 return;
2433 }
2434
2435 data = (HasDupFeatsPtr) DialogToPointer (dlg->dialog);
2436
2437 if (RemoveDuplicateFeatsAction (dlg->entityID, data)) {
2438 Remove (dlg->window);
2439 }
2440 data = MemFree (data);
2441 }
2442
2443
2444 static void RemoveDuplicateFeatsWithOptions (IteM i)
2445 {
2446 BaseFormPtr bfp;
2447 WindoW w;
2448 GrouP h, c;
2449 ButtoN b;
2450 DialoG d;
2451
2452 #ifdef WIN_MAC
2453 bfp = currentFormDataPtr;
2454 #else
2455 bfp = GetObjectExtra (i);
2456 #endif
2457 if (bfp == NULL) return;
2458
2459 w = FixedWindow (-50, -33, -10, -10, "Remove Duplicate Features", StdCloseWindowProc);
2460 h = HiddenGroup (w, -1, 0, NULL);
2461 SetGroupSpacing (h, 10, 10);
2462
2463 d = DupFeatsDialog (h, bfp->input_entityID, w);
2464 c = HiddenGroup (h, 2, 0, NULL);
2465 b = DefaultButton (c, "Accept", DoRemoveDuplicateFeats);
2466 SetObjectExtra (b, d, NULL);
2467 PushButton (c, "Cancel", StdCancelButtonProc);
2468 AlignObjects (ALIGN_CENTER, (HANDLE) d, (HANDLE) c, NULL);
2469
2470 Show (w);
2471 }
2472
2473
2474 static void NewRemoveDuplicateFeats (IteM i, Uint2 featdef)
2475 {
2476 BaseFormPtr bfp;
2477 HasDupFeatsData h;
2478
2479 #ifdef WIN_MAC
2480 bfp = currentFormDataPtr;
2481 #else
2482 bfp = GetObjectExtra (i);
2483 #endif
2484 if (bfp == NULL) return;
2485
2486 h.featdef = (Uint1) featdef;
2487 h.num_cds_with_product = 0;
2488 h.num_feat = 0;
2489 h.delete_list = NULL;
2490 h.case_sensitive = TRUE;
2491 h.ignore_partials = FALSE;
2492
2493 RemoveDuplicateFeatsAction (bfp->input_entityID, &h);
2494 }
2495
2496
2497 static void NewRemoveDuplicateFeatsAll (IteM i)
2498 {
2499 NewRemoveDuplicateFeats (i, 0);
2500 }
2501
2502
2503 static void NewRemoveDuplicateFeatsGenes (IteM i)
2504 {
2505 NewRemoveDuplicateFeats (i, FEATDEF_GENE);
2506 }
2507
2508
2509
2510 /*
2511 static Boolean LIBCALLBACK RemoveGeneXrefsOnBioseqs (BioseqPtr bsp, SeqMgrBioseqContextPtr bcontext)
2512
2513 {
2514 SeqFeatXrefPtr curr;
2515 SeqMgrFeatContext fcontext;
2516 GeneRefPtr grp;
2517 GeneRefPtr grpx;
2518 SeqFeatXrefPtr PNTR last;
2519 SeqFeatXrefPtr next;
2520 Boolean redundantgenexref;
2521 SeqFeatPtr sfp;
2522 SeqFeatPtr sfpx;
2523 CharPtr syn1;
2524 CharPtr syn2;
2525
2526 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
2527 while (sfp != NULL) {
2528 if (sfp->data.choice != SEQFEAT_GENE) {
2529 grp = SeqMgrGetGeneXref (sfp);
2530 if (grp != NULL && (! SeqMgrGeneIsSuppressed (grp))) {
2531 sfpx = SeqMgrGetOverlappingGene (sfp->location, NULL);
2532 if (sfpx != NULL && sfpx->data.choice == SEQFEAT_GENE) {
2533 grpx = (GeneRefPtr) sfpx->data.value.ptrvalue;
2534 if (grpx != NULL) {
2535 redundantgenexref = FALSE;
2536 if ((! StringHasNoText (grp->locus)) && (! StringHasNoText (grpx->locus))) {
2537 if ((StringICmp (grp->locus, grpx->locus) == 0)) {
2538 redundantgenexref = TRUE;
2539 }
2540 } else if ((! StringHasNoText (grp->locus_tag)) && (! StringHasNoText (grpx->locus_tag))) {
2541 if ((StringICmp (grp->locus_tag, grpx->locus_tag) == 0)) {
2542 redundantgenexref = TRUE;
2543 }
2544 } else if (grp->syn != NULL && grpx->syn != NULL) {
2545 syn1 = (CharPtr) grp->syn->data.ptrvalue;
2546 syn2 = (CharPtr) grpx->syn->data.ptrvalue;
2547 if ((! StringHasNoText (syn1)) && (! StringHasNoText (syn2))) {
2548 if ((StringICmp (syn1, syn2) == 0)) {
2549 redundantgenexref = TRUE;
2550 }
2551 }
2552 }
2553 if (redundantgenexref) {
2554 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
2555 curr = sfp->xref;
2556 while (curr != NULL) {
2557 next = curr->next;
2558 if (curr->data.choice == SEQFEAT_GENE) {
2559 *last = next;
2560 curr->next = NULL;
2561 SeqFeatXrefFree (curr);
2562 } else {
2563 last = &(curr->next);
2564 }
2565 curr = next;
2566 }
2567 }
2568 }
2569 }
2570 }
2571 }
2572 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
2573 }
2574
2575 return TRUE;
2576 }
2577 */
2578
2579 typedef struct dummysmfedata {
2580 Int4 max;
2581 Int4 num_at_max;
2582 } DummySmfeData, PNTR DummySmfePtr;
2583
2584 static Boolean LIBCALLBACK SQNDummySMFEProc (
2585 SeqFeatPtr sfp,
2586 SeqMgrFeatContextPtr context
2587 )
2588
2589
2590 {
2591 DummySmfePtr dsp;
2592 Int4 len;
2593
2594 if (sfp == NULL || context == NULL) return TRUE;
2595 dsp = context->userdata;
2596 if (dsp == NULL) return TRUE;
2597
2598 len = SeqLocLen (sfp->location);
2599 if (len < dsp->max) {
2600 dsp->max = len;
2601 dsp->num_at_max = 1;
2602 } else if (len == dsp->max) {
2603 (dsp->num_at_max)++;
2604 }
2605
2606 return TRUE;
2607 }
2608
2609 static Boolean LIBCALLBACK RemoveGeneXrefsOnBioseqs (BioseqPtr bsp, SeqMgrBioseqContextPtr bcontext)
2610
2611 {
2612 Int2 count;
2613 SeqFeatXrefPtr curr;
2614 DummySmfeData dsd;
2615 SeqMgrFeatContext fcontext;
2616 GeneRefPtr grp;
2617 GeneRefPtr grpx;
2618 SeqFeatXrefPtr PNTR last;
2619 SeqFeatXrefPtr next;
2620 Boolean redundantgenexref;
2621 SeqFeatPtr sfp;
2622 SeqFeatPtr sfpx;
2623 CharPtr syn1, syn2;
2624
2625 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
2626 while (sfp != NULL) {
2627 grp = SeqMgrGetGeneXref (sfp);
2628 if (grp != NULL && (! SeqMgrGeneIsSuppressed (grp))) {
2629 sfpx = SeqMgrGetOverlappingGene (sfp->location, NULL);
2630 if (sfpx != NULL && sfpx->data.choice == SEQFEAT_GENE) {
2631 grpx = (GeneRefPtr) sfpx->data.value.ptrvalue;
2632 if (grpx != NULL) {
2633
2634 redundantgenexref = TRUE;
2635 if ((!StringHasNoText (grp->locus)) && (!StringHasNoText (grpx->locus))) {
2636 if ((StringICmp (grp->locus, grpx->locus) != 0)) {
2637 redundantgenexref = FALSE;
2638 }
2639 } else if (StringDoesHaveText (grp->locus_tag) && StringDoesHaveText (grp->locus_tag)) {
2640 if ((StringICmp (grp->locus_tag, grpx->locus_tag) != 0)) {
2641 redundantgenexref = FALSE;
2642 }
2643 } else if (grp->syn != NULL && grpx->syn != NULL) {
2644 syn1 = (CharPtr) grp->syn->data.ptrvalue;
2645 syn2 = (CharPtr) grpx->syn->data.ptrvalue;
2646 if ((!StringHasNoText (syn1)) && (!StringHasNoText (syn2))) {
2647 if ((StringICmp (syn1, syn2) != 0)) {
2648 redundantgenexref = FALSE;
2649 }
2650 }
2651 }
2652
2653 if (redundantgenexref) {
2654 MemSet ((Pointer) &dsd, 0, sizeof (DummySmfeData));
2655 dsd.max = INT4_MAX;
2656 dsd.num_at_max = 0;
2657 count = SeqMgrGetAllOverlappingFeatures (sfp->location, FEATDEF_GENE, NULL, 0,
2658 LOCATION_SUBSET, (Pointer) &dsd, SQNDummySMFEProc);
2659
2660 if (dsd.num_at_max < 2) {
2661 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
2662 curr = sfp->xref;
2663 while (curr != NULL) {
2664 next = curr->next;
2665 if (curr->data.choice == SEQFEAT_GENE) {
2666 *last = next;
2667 curr->next = NULL;
2668 SeqFeatXrefFree (curr);
2669 } else {
2670 last = &(curr->next);
2671 }
2672 curr = next;
2673 }
2674 }
2675 }
2676 }
2677 }
2678 }
2679 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
2680 }
2681
2682 return TRUE;
2683 }
2684
2685 static void RemoveGeneXrefs (IteM i)
2686
2687 {
2688 BaseFormPtr bfp;
2689 Uint2 entityID;
2690 SeqEntryPtr sep;
2691
2692 #ifdef WIN_MAC
2693 bfp = currentFormDataPtr;
2694 #else
2695 bfp = GetObjectExtra (i);
2696 #endif
2697 if (bfp == NULL) return;
2698 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2699 if (sep == NULL) return;
2700 entityID = SeqMgrIndexFeatures (bfp->input_entityID, NULL);
2701 if (entityID < 1) return;
2702 SeqMgrExploreBioseqs (entityID, 0, NULL, RemoveGeneXrefsOnBioseqs, TRUE, TRUE, TRUE);
2703 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2704 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2705 }
2706
2707 static void RemoveGeneXNoLC (SeqFeatPtr sfp, Pointer userdata)
2708
2709 {
2710 BioseqPtr bsp;
2711 GeneRefPtr grp;
2712 SeqFeatXrefPtr curr;
2713 SeqFeatXrefPtr PNTR last;
2714 SeqFeatXrefPtr next;
2715
2716 grp = SeqMgrGetGeneXref (sfp);
2717 if (grp == NULL || SeqMgrGeneIsSuppressed (grp)) return;
2718 if (StringHasNoText (grp->locus_tag)) return;
2719 bsp = BioseqFindFromSeqLoc (sfp->location);
2720 if (bsp == NULL) return;
2721 if (SeqMgrGetFeatureByLabel (bsp, grp->locus, SEQFEAT_GENE, 0, NULL) != NULL) return;
2722 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
2723 curr = sfp->xref;
2724 while (curr != NULL) {
2725 next = curr->next;
2726 if (curr->data.choice == SEQFEAT_GENE) {
2727 *last = next;
2728 curr->next = NULL;
2729 SeqFeatXrefFree (curr);
2730 } else {
2731 last = &(curr->next);
2732 }
2733 curr = next;
2734 }
2735 }
2736
2737 static void RemoveGeneXrefsNoGene (IteM i)
2738
2739 {
2740 BaseFormPtr bfp;
2741 SeqEntryPtr sep;
2742
2743 #ifdef WIN_MAC
2744 bfp = currentFormDataPtr;
2745 #else
2746 bfp = GetObjectExtra (i);
2747 #endif
2748 if (bfp == NULL) return;
2749 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2750 if (sep == NULL) return;
2751 VisitFeaturesInSep (sep, NULL, RemoveGeneXNoLC);
2752 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2753 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2754 }
2755
2756 static void RemoveGeneXNoLT (SeqFeatPtr sfp, Pointer userdata)
2757
2758 {
2759 BioseqPtr bsp;
2760 GeneRefPtr grp;
2761 SeqFeatXrefPtr curr;
2762 SeqFeatXrefPtr PNTR last;
2763 SeqFeatXrefPtr next;
2764
2765 grp = SeqMgrGetGeneXref (sfp);
2766 if (grp == NULL || SeqMgrGeneIsSuppressed (grp)) return;
2767 if (StringHasNoText (grp->locus_tag)) return;
2768 bsp = BioseqFindFromSeqLoc (sfp->location);
2769 if (bsp == NULL) return;
2770 if (SeqMgrGetGeneByLocusTag (bsp, grp->locus_tag, NULL) != NULL) return;
2771 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
2772 curr = sfp->xref;
2773 while (curr != NULL) {
2774 next = curr->next;
2775 if (curr->data.choice == SEQFEAT_GENE) {
2776 *last = next;
2777 curr->next = NULL;
2778 SeqFeatXrefFree (curr);
2779 } else {
2780 last = &(curr->next);
2781 }
2782 curr = next;
2783 }
2784 }
2785
2786 static void RemoveGeneXrefsNoLocTag (IteM i)
2787
2788 {
2789 BaseFormPtr bfp;
2790 SeqEntryPtr sep;
2791
2792 #ifdef WIN_MAC
2793 bfp = currentFormDataPtr;
2794 #else
2795 bfp = GetObjectExtra (i);
2796 #endif
2797 if (bfp == NULL) return;
2798 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2799 if (sep == NULL) return;
2800 VisitFeaturesInSep (sep, NULL, RemoveGeneXNoLT);
2801 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2802 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2803 }
2804
2805 static void DoRemoveNSGeneXrefs (SeqFeatPtr sfp, Pointer userdata)
2806
2807 {
2808 SeqFeatXrefPtr curr;
2809 GeneRefPtr grp;
2810 SeqFeatXrefPtr PNTR last;
2811 SeqFeatXrefPtr next;
2812
2813 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
2814 curr = sfp->xref;
2815 while (curr != NULL) {
2816 next = curr->next;
2817 if (curr->data.choice == SEQFEAT_GENE) {
2818 grp = (GeneRefPtr) curr->data.value.ptrvalue;
2819 if (SeqMgrGeneIsSuppressed (grp)) {
2820 last = &(curr->next);
2821 } else {
2822 *last = next;
2823 curr->next = NULL;
2824 SeqFeatXrefFree (curr);
2825 }
2826 } else {
2827 last = &(curr->next);
2828 }
2829 curr = next;
2830 }
2831 }
2832
2833 static void RemoveNSGeneXrefs (IteM i)
2834
2835 {
2836 BaseFormPtr bfp;
2837 SeqEntryPtr sep;
2838
2839 #ifdef WIN_MAC
2840 bfp = currentFormDataPtr;
2841 #else
2842 bfp = GetObjectExtra (i);
2843 #endif
2844 if (bfp == NULL) return;
2845 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2846 if (sep == NULL) return;
2847 VisitFeaturesInSep (sep, NULL, DoRemoveNSGeneXrefs);
2848 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2849 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2850 }
2851
2852 static void DoRemoveGeneXrefs (SeqFeatPtr sfp, Pointer userdata)
2853
2854 {
2855 SeqFeatXrefPtr curr;
2856 SeqFeatXrefPtr PNTR last;
2857 SeqFeatXrefPtr next;
2858
2859 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
2860 curr = sfp->xref;
2861 while (curr != NULL) {
2862 next = curr->next;
2863 if (curr->data.choice == SEQFEAT_GENE) {
2864 *last = next;
2865 curr->next = NULL;
2866 SeqFeatXrefFree (curr);
2867 } else {
2868 last = &(curr->next);
2869 }
2870 curr = next;
2871 }
2872 }
2873
2874 static void RemoveAllGeneXrefs (IteM i)
2875
2876 {
2877 BaseFormPtr bfp;
2878 SeqEntryPtr sep;
2879
2880 #ifdef WIN_MAC
2881 bfp = currentFormDataPtr;
2882 #else
2883 bfp = GetObjectExtra (i);
2884 #endif
2885 if (bfp == NULL) return;
2886 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
2887 if (sep == NULL) return;
2888 VisitFeaturesInSep (sep, NULL, DoRemoveGeneXrefs);
2889 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
2890 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
2891 }
2892
2893 typedef struct removegenexref
2894 {
2895 FORM_MESSAGE_BLOCK
2896 DialoG feature_select;
2897 DialoG constraints;
2898 DialoG accept_cancel;
2899
2900 ButtoN suppressing;
2901 ButtoN nonsuppressing;
2902 ButtoN unnecessary;
2903
2904 Boolean do_suppressing;
2905 Boolean do_nonsuppressing;
2906 Boolean do_unnecessary;
2907 } RemoveGeneXrefData, PNTR RemoveGeneXrefPtr;
2908
2909 static void RemoveGeneXrefsChangeNotify (Pointer userdata)
2910 {
2911 RemoveGeneXrefPtr dlg;
2912 ValNodePtr vnp;
2913 Boolean do_enable = FALSE;
2914
2915 dlg = (RemoveGeneXrefPtr) userdata;
2916 if (dlg == NULL)
2917 {
2918 return;
2919 }
2920
2921 vnp = (ValNodePtr) DialogToPointer (dlg->feature_select);
2922 if (vnp != NULL)
2923 {
2924 ValNodeFree (vnp);
2925 if (GetStatus (dlg->suppressing)
2926 || GetStatus (dlg->nonsuppressing)
2927 || GetStatus (dlg->unnecessary))
2928 {
2929 do_enable = TRUE;
2930 }
2931 }
2932 if (do_enable)
2933 {
2934 EnableAcceptCancelDialogAccept (dlg->accept_cancel);
2935 }
2936 else
2937 {
2938 DisableAcceptCancelDialogAccept (dlg->accept_cancel);
2939 }
2940 }
2941
2942 static void RemoveGeneXrefsChangeBtn (ButtoN b)
2943 {
2944 RemoveGeneXrefPtr dlg;
2945
2946 dlg = (RemoveGeneXrefPtr) GetObjectExtra (b);
2947 RemoveGeneXrefsChangeNotify (dlg);
2948 }
2949
2950 static void RemoveGeneXrefsClear (Pointer data)
2951 {
2952 RemoveGeneXrefPtr dlg;
2953
2954 dlg = (RemoveGeneXrefPtr) data;
2955 if (dlg == NULL) return;
2956
2957 PointerToDialog (dlg->feature_select, NULL);
2958 PointerToDialog (dlg->constraints, NULL);
2959 }
2960
2961 static void RemoveGeneXrefsClearText (Pointer data)
2962 {
2963 RemoveGeneXrefPtr dlg;
2964 FilterSetPtr fsp;
2965
2966 dlg = (RemoveGeneXrefPtr) data;
2967 if (dlg == NULL) return;
2968
2969 fsp = DialogToPointer (dlg->constraints);
2970 FilterSetClearText (fsp);
2971 PointerToDialog (dlg->constraints, fsp);
2972 FilterSetFree (fsp);
2973 }
2974
2975 static Boolean IsUnnecessaryGeneXref (SeqFeatPtr sfp, GeneRefPtr grp)
2976 {
2977 SeqFeatPtr sfpx;
2978 GeneRefPtr grpx;
2979 Boolean redundantgenexref = FALSE;
2980 CharPtr syn1;
2981 CharPtr syn2;
2982
2983 if (sfp == NULL || grp == NULL || SeqMgrGeneIsSuppressed (grp))
2984 {
2985 return FALSE;
2986 }
2987
2988 sfpx = SeqMgrGetOverlappingGene (sfp->location, NULL);
2989 if (sfpx == NULL || sfpx->data.choice != SEQFEAT_GENE)
2990 {
2991 return FALSE;
2992 }
2993
2994 grpx = (GeneRefPtr) sfpx->data.value.ptrvalue;
2995 if (grpx == NULL)
2996 {
2997 return FALSE;
2998 }
2999
3000 if (StringDoesHaveText (grp->locus_tag) && StringDoesHaveText (grpx->locus_tag)) {
3001 if (StringICmp (grp->locus_tag, grpx->locus_tag) == 0) {
3002 redundantgenexref = TRUE;
3003 }
3004 } else if (StringDoesHaveText (grp->locus) && StringDoesHaveText (grpx->locus)) {
3005 if (StringICmp (grp->locus, grpx->locus) == 0) {
3006 redundantgenexref = TRUE;
3007 }
3008 } else if (grp->syn != NULL && grpx->syn != NULL) {
3009 syn1 = (CharPtr) grp->syn->data.ptrvalue;
3010 syn2 = (CharPtr) grpx->syn->data.ptrvalue;
3011 if (StringDoesHaveText (syn1) && StringDoesHaveText (syn2)) {
3012 if (StringICmp (syn1, syn2) == 0) {
3013 redundantgenexref = TRUE;
3014 }
3015 }
3016 }
3017 return redundantgenexref;
3018 }
3019
3020 static void RemoveGeneXrefsCallback (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr fsp)
3021 {
3022 RemoveGeneXrefPtr dlg;
3023 SeqFeatXrefPtr curr;
3024 GeneRefPtr grp;
3025 SeqFeatXrefPtr PNTR last;
3026 SeqFeatXrefPtr next;
3027 Boolean is_suppressed;
3028
3029 if (sfp == NULL || userdata == NULL)
3030 {
3031 return;
3032 }
3033
3034 dlg = (RemoveGeneXrefPtr) userdata;
3035
3036 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
3037 curr = sfp->xref;
3038 while (curr != NULL) {
3039 next = curr->next;
3040 if (curr->data.choice == SEQFEAT_GENE) {
3041 grp = (GeneRefPtr) curr->data.value.ptrvalue;
3042 is_suppressed = SeqMgrGeneIsSuppressed (grp);
3043
3044 if ((dlg->do_suppressing && is_suppressed)
3045 || (dlg->do_nonsuppressing && !is_suppressed)
3046 || (dlg->do_unnecessary && IsUnnecessaryGeneXref (sfp, grp)))
3047 {
3048 *last = next;
3049 curr->next = NULL;
3050 SeqFeatXrefFree (curr);
3051 }
3052 else
3053 {
3054 last = &(curr->next);
3055 }
3056 } else {
3057 last = &(curr->next);
3058 }
3059 curr = next;
3060 }
3061
3062 }
3063
3064 static Boolean RemoveGeneXrefsAction (Pointer userdata)
3065 {
3066 RemoveGeneXrefPtr dlg;
3067 FilterSetPtr fsp;
3068 SeqEntryPtr sep;
3069 ValNodePtr feature_type_list, vnp;
3070 Uint1 feat_def_choice;
3071
3072 if (userdata == NULL) return FALSE;
3073
3074 dlg = (RemoveGeneXrefPtr) userdata;
3075
3076 sep = GetTopSeqEntryForEntityID (dlg->input_entityID);
3077 if (sep == NULL) return FALSE;
3078
3079 feature_type_list = (ValNodePtr) DialogToPointer (dlg->feature_select);
3080
3081 if (feature_type_list == NULL)
3082 {
3083 return FALSE;
3084 }
3085
3086 fsp = (FilterSetPtr) DialogToPointer (dlg->constraints);
3087
3088 dlg->do_suppressing = GetStatus (dlg->suppressing);
3089 dlg->do_nonsuppressing = GetStatus (dlg->nonsuppressing);
3090 dlg->do_unnecessary = GetStatus (dlg->unnecessary);
3091
3092 for (vnp = feature_type_list; vnp != NULL; vnp = vnp->next)
3093 {
3094 feat_def_choice = vnp->choice;
3095 if (feat_def_choice == 255)
3096 {
3097 feat_def_choice = 0;
3098 }
3099 OperateOnSeqEntryConstrainedObjects (sep, fsp,
3100 RemoveGeneXrefsCallback,
3101 NULL, 0, feat_def_choice, 0, dlg);
3102 }
3103
3104 ValNodeFree (feature_type_list);
3105 FilterSetFree (fsp);
3106
3107 ObjMgrSetDirtyFlag (dlg->input_entityID, TRUE);
3108 ObjMgrSendMsg (OM_MSG_UPDATE, dlg->input_entityID, 0, 0);
3109 Update ();
3110 return TRUE;
3111 }
3112
3113 static void NewRemoveGeneXrefs (IteM i)
3114
3115 {
3116 BaseFormPtr bfp;
3117 RemoveGeneXrefPtr dlg;
3118 WindoW w;
3119 GrouP h, k;
3120 SeqEntryPtr sep;
3121
3122 #ifdef WIN_MAC
3123 bfp = currentFormDataPtr;
3124 #else
3125 bfp = GetObjectExtra (i);
3126 #endif
3127 if (bfp == NULL) return;
3128
3129 dlg = (RemoveGeneXrefPtr) MemNew (sizeof (RemoveGeneXrefData));
3130 if (dlg == NULL) return;
3131
3132 w = FixedWindow (-50, -33, -10, -10, "Remove Gene Xrefs", StdCloseWindowProc);
3133 SetObjectExtra (w, dlg, StdCleanupExtraProc);
3134 dlg->form = (ForM) w;
3135 dlg->input_entityID = bfp->input_entityID;
3136
3137 h = HiddenGroup (w, -1, 0, NULL);
3138 SetGroupSpacing (h, 10, 10);
3139
3140 sep = GetTopSeqEntryForEntityID(bfp->input_entityID);
3141 dlg->feature_select = FeatureSelectionDialogEx (h, TRUE, sep,
3142 RemoveGeneXrefsChangeNotify,
3143 dlg);
3144
3145 k = NormalGroup (h, 0, 3, "Remove Gene Xrefs that are", programFont, NULL);
3146 dlg->suppressing = CheckBox (k, "Suppressing", RemoveGeneXrefsChangeBtn);
3147 SetObjectExtra (dlg->suppressing, dlg, NULL);
3148 dlg->nonsuppressing = CheckBox (k, "Non-Suppressing", RemoveGeneXrefsChangeBtn);
3149 SetObjectExtra (dlg->nonsuppressing, dlg, NULL);
3150 dlg->unnecessary = CheckBox (k, "Unnecessary", RemoveGeneXrefsChangeBtn);
3151 SetObjectExtra (dlg->unnecessary, dlg, NULL);
3152
3153 dlg->constraints = FilterGroup (h, TRUE, FALSE, TRUE, FALSE, FALSE, "Where feature text");
3154 dlg->accept_cancel = AcceptCancelDialog (h, RemoveGeneXrefsAction, NULL, RemoveGeneXrefsClear, RemoveGeneXrefsClearText, (Pointer)dlg, w);
3155 AlignObjects (ALIGN_CENTER, (HANDLE) dlg->feature_select,
3156 (HANDLE) k,
3157 (HANDLE) dlg->constraints,
3158 (HANDLE) dlg->accept_cancel, NULL);
3159
3160 Show (w);
3161 }
3162
3163 static void DoRefreshGeneXrefs (SeqFeatPtr sfp, Pointer userdata)
3164
3165 {
3166 SeqFeatXrefPtr curr;
3167 GeneRefPtr grp, grpfeat;
3168 SeqFeatPtr gene;
3169 SeqMgrFeatContext fcontext;
3170 BioseqPtr bsp;
3171
3172 if (sfp == NULL) return;
3173
3174 for (curr = sfp->xref; curr != NULL; curr = curr->next)
3175 {
3176 if (curr->data.choice == SEQFEAT_GENE) {
3177 grp = (GeneRefPtr) curr->data.value.ptrvalue;
3178 if (grp != NULL)
3179 {
3180 bsp = BioseqFindFromSeqLoc (sfp->location);
3181 gene = SeqMgrGetFeatureByLabel (bsp, grp->locus, SEQFEAT_GENE, 0, &fcontext);
3182 if (gene != NULL && gene->data.choice == SEQFEAT_GENE) {
3183 grpfeat = (GeneRefPtr) gene->data.value.ptrvalue;
3184 if (grpfeat != NULL) {
3185 GeneRefFree (grp);
3186 grp = GeneRefDup (grpfeat);
3187 curr->data.value.ptrvalue = grp;
3188 }
3189 }
3190 }
3191 }
3192 }
3193 }
3194
3195 static void RefreshGeneXRefs (IteM i)
3196
3197 {
3198 BaseFormPtr bfp;
3199 SeqEntryPtr sep;
3200
3201 #ifdef WIN_MAC
3202 bfp = currentFormDataPtr;
3203 #else
3204 bfp = GetObjectExtra (i);
3205 #endif
3206 if (bfp == NULL) return;
3207 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3208 if (sep == NULL) return;
3209 VisitFeaturesInSep (sep, NULL, DoRefreshGeneXrefs);
3210 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3211 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3212 }
3213
3214 static ValNodePtr RemoveDbxrefList (ValNodePtr vnp)
3215
3216 {
3217 ValNodePtr next;
3218
3219 while (vnp != NULL) {
3220 next = vnp->next;
3221 DbtagFree ((DbtagPtr) vnp->data.ptrvalue);
3222 MemFree (vnp);
3223 vnp = next;
3224 }
3225 return NULL;
3226 }
3227
3228 static void DoRemoveDbxrefs (SeqFeatPtr sfp, Pointer userdata)
3229
3230 {
3231 GeneRefPtr grp;
3232 Uint1 feattype;
3233
3234 if (sfp == NULL) return;
3235
3236 if (userdata != NULL && (feattype = *(Uint1 PNTR)userdata) != sfp->data.choice) return;
3237 sfp->dbxref = RemoveDbxrefList (sfp->dbxref);
3238 if (sfp->data.choice != SEQFEAT_GENE) return;
3239 grp = (GeneRefPtr) sfp->data.value.ptrvalue;
3240 if (grp == NULL) return;
3241 grp->db = RemoveDbxrefList (grp->db);
3242 }
3243
3244 static void DoRemoveBioSourceDbxrefs (BioSourcePtr biop, Pointer userdata)
3245 {
3246 if (biop == NULL || biop->org == NULL) return;
3247
3248 biop->org->db = RemoveDbxrefList (biop->org->db);
3249 }
3250
3251 static void RemoveDbxrefsCommon (IteM i, Uint1 PNTR subtype, Boolean remove_source, Boolean remove_features)
3252
3253 {
3254 BaseFormPtr bfp;
3255 SeqEntryPtr sep;
3256
3257 #ifdef WIN_MAC
3258 bfp = currentFormDataPtr;
3259 #else
3260 bfp = GetObjectExtra (i);
3261 #endif
3262 if (bfp == NULL) return;
3263 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3264 if (sep == NULL) return;
3265 if (remove_features) {
3266 VisitFeaturesInSep (sep, subtype, DoRemoveDbxrefs);
3267 }
3268 if (subtype == NULL && remove_source)
3269 {
3270 VisitBioSourcesInSep (sep, NULL, DoRemoveBioSourceDbxrefs);
3271 }
3272 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3273 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3274 }
3275
3276 static void RemoveGeneDbxrefs (IteM i)
3277 {
3278 Uint1 subtype = SEQFEAT_GENE;
3279 RemoveDbxrefsCommon (i, &subtype, FALSE, TRUE);
3280 }
3281
3282 static void RemoveRNADbxrefs (IteM i)
3283
3284 {
3285 Uint1 subtype = SEQFEAT_RNA;
3286
3287 RemoveDbxrefsCommon (i, &subtype, FALSE, TRUE);
3288 }
3289
3290 static void RemoveCDSDbxrefs (IteM i)
3291
3292 {
3293 Uint1 subtype = FEATDEF_CDS;
3294 RemoveDbxrefsCommon (i, &subtype, FALSE, TRUE);
3295 }
3296
3297 static void RemoveAllFeatureDbxrefs (IteM i)
3298 {
3299 RemoveDbxrefsCommon (i, NULL, FALSE, TRUE);
3300 }
3301
3302 static void RemoveAllDbxrefs (IteM i)
3303
3304 {
3305 RemoveDbxrefsCommon (i, NULL, TRUE, TRUE);
3306 }
3307
3308
3309 static void RemoveAllBioSourceDbxrefs (IteM i)
3310
3311 {
3312 RemoveDbxrefsCommon (i, NULL, TRUE, FALSE);
3313 }
3314
3315
3316 static void RemoveMissingFeatureXrefsCallback (SeqFeatPtr sfp, Pointer data)
3317
3318 {
3319 SeqFeatXrefPtr xref, xref_next, xref_prev = NULL;
3320 SeqFeatPtr matchsfp;
3321
3322 if (sfp == NULL) {
3323 return;
3324 }
3325
3326 for (xref = sfp->xref; xref != NULL; xref = xref_next) {
3327 xref_next = xref->next;
3328 if (xref->id.choice != 0
3329 && (matchsfp = SeqMgrGetFeatureByFeatID (sfp->idx.entityID, NULL, NULL, xref, NULL)) == NULL) {
3330 if (xref_prev == NULL) {
3331 sfp->xref = xref->next;
3332 } else {
3333 xref_prev->next = xref->next;
3334 }
3335 xref->next = NULL;
3336 xref = SeqFeatXrefFree (xref);
3337 } else {
3338 xref_prev = xref;
3339 }
3340 }
3341 }
3342
3343
3344 static void RemoveMissingFeatureXrefs (IteM i)
3345
3346 {
3347 BaseFormPtr bfp;
3348 SeqEntryPtr sep;
3349
3350 #ifdef WIN_MAC
3351 bfp = currentFormDataPtr;
3352 #else
3353 bfp = GetObjectExtra (i);
3354 #endif
3355 if (bfp == NULL) return;
3356 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3357 if (sep == NULL) return;
3358 WatchCursor();
3359 Update();
3360 VisitFeaturesInSep (sep, NULL, RemoveMissingFeatureXrefsCallback);
3361 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3362 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3363 ArrowCursor();
3364 Update();
3365 }
3366
3367
3368 static void ClearPubFig (PubdescPtr pdp, Pointer userdata)
3369
3370 {
3371 if (pdp == NULL) return;
3372 pdp->fig = MemFree (pdp->fig);
3373 pdp->num = NumberingFree (pdp->num);
3374 }
3375
3376 static void RemovePubFig (IteM i)
3377
3378 {
3379 BaseFormPtr bfp;
3380 SeqEntryPtr sep;
3381
3382 #ifdef WIN_MAC
3383 bfp = currentFormDataPtr;
3384 #else
3385 bfp = GetObjectExtra (i);
3386 #endif
3387 if (bfp == NULL) return;
3388 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3389 if (sep == NULL) return;
3390 VisitPubdescsInSep (sep, NULL, ClearPubFig);
3391 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3392 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3393 }
3394
3395 static void RemoveSelFeats (IteM i)
3396
3397 {
3398 MsgAnswer ans;
3399 BaseFormPtr bfp;
3400 BioseqPtr cdna;
3401 SeqMgrFeatContext fcontext;
3402 BioseqPtr prot;
3403 Boolean remove_asked;
3404 Boolean remove_mrnas = FALSE;
3405 Boolean remove_prots = FALSE;
3406 SelStructPtr sel;
3407 SeqEntryPtr sep;
3408 SeqFeatPtr sfp;
3409 SelStructPtr ssp;
3410 Boolean unremoved_feats = FALSE;
3411
3412 #ifdef WIN_MAC
3413 bfp = currentFormDataPtr;
3414 #else
3415 bfp = GetObjectExtra (i);
3416 #endif
3417 if (bfp == NULL) return;
3418 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3419 if (sep == NULL) return;
3420
3421 ssp = ObjMgrGetSelected ();
3422 if (ssp == NULL) return;
3423
3424 remove_asked = FALSE;
3425 for (sel = ssp; sel != NULL; sel = sel->next) {
3426 if (sel->entityID != bfp->input_entityID)
3427 {
3428 unremoved_feats = TRUE;
3429 continue;
3430 }
3431 if (sel->itemtype == OBJ_SEQFEAT) {
3432 sfp = SeqMgrGetDesiredFeature (sel->entityID, NULL, sel->itemID, 0, NULL, &fcontext);
3433 if (sfp != NULL) {
3434 sfp->idx.deleteme = TRUE;
3435 if (sfp->data.choice == SEQFEAT_CDREGION && sfp->product != NULL) {
3436 prot = BioseqFindFromSeqLoc (sfp->product);
3437 if (prot != NULL) {
3438 if (! remove_asked) {
3439 ans = Message (MSG_YN, "Remove protein products?");
3440 if (ans == ANS_YES) {
3441 remove_prots = TRUE;
3442 }
3443 remove_asked = TRUE;
3444 }
3445 if (remove_prots) {
3446 prot->idx.deleteme = TRUE;
3447 }
3448 }
3449 }
3450 }
3451 }
3452 }
3453
3454 remove_asked = FALSE;
3455 for (sel = ssp; sel != NULL; sel = sel->next) {
3456 if (sel->entityID != bfp->input_entityID)
3457 {
3458 unremoved_feats = TRUE;
3459 continue;
3460 }
3461 if (sel->itemtype == OBJ_SEQFEAT) {
3462 sfp = SeqMgrGetDesiredFeature (sel->entityID, NULL, sel->itemID, 0, NULL, &fcontext);
3463 if (sfp != NULL) {
3464 sfp->idx.deleteme = TRUE;
3465 if (sfp->data.choice == SEQFEAT_RNA && sfp->product != NULL) {
3466 cdna = BioseqFindFromSeqLoc (sfp->product);
3467 if (cdna != NULL) {
3468 if (! remove_asked) {
3469 ans = Message (MSG_YN, "Remove mRNA products?");
3470 if (ans == ANS_YES) {
3471 remove_mrnas = TRUE;
3472 }
3473 remove_asked = TRUE;
3474 }
3475 if (remove_mrnas) {
3476 cdna->idx.deleteme = TRUE;
3477 }
3478 }
3479 }
3480 }
3481 }
3482 }
3483
3484 ObjMgrSelect (0, 0, 0, 0, NULL);
3485
3486 DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
3487
3488 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3489 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3490 if (unremoved_feats)
3491 {
3492 Message (MSG_ERROR, "Warning! Features mapped to far sequences cannot be deleted!");
3493 }
3494 }
3495
3496 static void RemoveUnselFeats (IteM i)
3497
3498 {
3499 MsgAnswer ans;
3500 BaseFormPtr bfp;
3501 BioseqPtr bsp;
3502 BioseqPtr cdna;
3503 SeqMgrFeatContext fcontext;
3504 BioseqPtr prot;
3505 Boolean remove_asked;
3506 Boolean remove_mrnas = FALSE;
3507 Boolean remove_prots = FALSE;
3508 SelStructPtr sel;
3509 SeqEntryPtr sep;
3510 SeqFeatPtr sfp;
3511 SelStructPtr ssp;
3512 SeqEntryPtr scope;
3513 Boolean sel_on_local = FALSE;
3514 Boolean sel_on_far = FALSE;
3515
3516 #ifdef WIN_MAC
3517 bfp = currentFormDataPtr;
3518 #else
3519 bfp = GetObjectExtra (i);
3520 #endif
3521 if (bfp == NULL) return;
3522 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3523 if (sep == NULL) return;
3524
3525 ssp = ObjMgrGetSelected ();
3526 if (ssp == NULL) return;
3527
3528 scope = SeqEntrySetScope (NULL);
3529 bsp = NULL;
3530 for (sel = ssp; sel != NULL && bsp == NULL; sel = sel->next) {
3531 if (sel->entityID != bfp->input_entityID)
3532 {
3533 if (sel->itemtype == OBJ_SEQFEAT)
3534 {
3535 sel_on_far = TRUE;
3536 }
3537 continue;
3538 }
3539 if (sel->itemtype == OBJ_SEQFEAT) {
3540 sel_on_local = TRUE;
3541 sfp = SeqMgrGetDesiredFeature (sel->entityID, NULL, sel->itemID, 0, NULL, &fcontext);
3542 if (sfp != NULL) {
3543 bsp = BioseqFindFromSeqLoc (sfp->location);
3544 }
3545 }
3546 }
3547 SeqEntrySetScope (scope);
3548 if (bsp == NULL)
3549 {
3550 if (sel_on_far && ! sel_on_local)
3551 {
3552 Message (MSG_ERROR, "Warning! Features mapped to far sequences cannot be deleted!");
3553 }
3554 return;
3555 }
3556
3557 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
3558 while (sfp != NULL) {
3559 sfp->idx.deleteme = TRUE;
3560 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
3561 }
3562
3563 for (sel = ssp; sel != NULL; sel = sel->next) {
3564 if (sel->entityID != bfp->input_entityID) continue;
3565 if (sel->itemtype == OBJ_SEQFEAT) {
3566 sfp = SeqMgrGetDesiredFeature (0, bsp, sel->itemID, 0, NULL, &fcontext);
3567 if (sfp != NULL) {
3568 sfp->idx.deleteme = FALSE;
3569 }
3570 }
3571 }
3572
3573 remove_asked = FALSE;
3574 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
3575 while (sfp != NULL) {
3576 if (sfp->idx.deleteme) {
3577 if (sfp->data.choice == SEQFEAT_CDREGION && sfp->product != NULL) {
3578 prot = BioseqFindFromSeqLoc (sfp->product);
3579 if (prot != NULL) {
3580 if (! remove_asked) {
3581 ans = Message (MSG_YN, "Remove protein products?");
3582 if (ans == ANS_YES) {
3583 remove_prots = TRUE;
3584 }
3585 remove_asked = TRUE;
3586 }
3587 if (remove_prots) {
3588 prot->idx.deleteme = TRUE;
3589 }
3590 }
3591 }
3592 }
3593 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
3594 }
3595
3596 remove_asked = FALSE;
3597 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
3598 while (sfp != NULL) {
3599 if (sfp->idx.deleteme) {
3600 if (sfp->data.choice == SEQFEAT_RNA && sfp->product != NULL) {
3601 cdna = BioseqFindFromSeqLoc (sfp->product);
3602 if (cdna != NULL) {
3603 if (! remove_asked) {
3604 ans = Message (MSG_YN, "Remove mRNA products?");
3605 if (ans == ANS_YES) {
3606 remove_mrnas = TRUE;
3607 }
3608 remove_asked = TRUE;
3609 }
3610 if (remove_mrnas) {
3611 cdna->idx.deleteme = TRUE;
3612 }
3613 }
3614 }
3615 }
3616 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
3617 }
3618
3619 ObjMgrSelect (0, 0, 0, 0, NULL);
3620
3621 DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
3622
3623 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3624 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3625 }
3626
3627 static void RemoveFeatsOutOfSelRange (IteM i)
3628
3629 {
3630 MsgAnswer ans;
3631 BaseFormPtr bfp;
3632 BioseqPtr bsp;
3633 BioseqPtr cdna;
3634 SeqMgrFeatContext fcontext;
3635 BioseqPtr prot;
3636 Boolean remove_asked;
3637 Boolean remove_mrnas = FALSE;
3638 Boolean remove_prots = FALSE;
3639 SelStructPtr sel;
3640 SeqEntryPtr sep;
3641 SeqFeatPtr sfp;
3642 SeqLocPtr slp = NULL;
3643 SelStructPtr ssp;
3644 SeqEntryPtr scope;
3645 Boolean sel_on_local = FALSE;
3646 Boolean sel_on_far = FALSE;
3647
3648 #ifdef WIN_MAC
3649 bfp = currentFormDataPtr;
3650 #else
3651 bfp = GetObjectExtra (i);
3652 #endif
3653 if (bfp == NULL) return;
3654 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3655 if (sep == NULL) return;
3656
3657 ssp = ObjMgrGetSelected ();
3658 if (ssp == NULL) {
3659 Message (MSG_ERROR, "Warning! No features are selected - please select one");
3660 return;
3661 }
3662 if (ssp->next != NULL) {
3663 Message (MSG_ERROR, "Warning! Multiple features are selected - please select only one");
3664 return;
3665 }
3666
3667 scope = SeqEntrySetScope (NULL);
3668 bsp = NULL;
3669 for (sel = ssp; sel != NULL && bsp == NULL; sel = sel->next) {
3670 if (sel->entityID != bfp->input_entityID)
3671 {
3672 if (sel->itemtype == OBJ_SEQFEAT)
3673 {
3674 sel_on_far = TRUE;
3675 }
3676 continue;
3677 }
3678 if (sel->itemtype == OBJ_SEQFEAT) {
3679 sel_on_local = TRUE;
3680 sfp = SeqMgrGetDesiredFeature (sel->entityID, NULL, sel->itemID, 0, NULL, &fcontext);
3681 if (sfp != NULL) {
3682 slp = sfp->location;
3683 bsp = BioseqFindFromSeqLoc (slp);
3684 }
3685 }
3686 }
3687 SeqEntrySetScope (scope);
3688 if (bsp == NULL)
3689 {
3690 if (sel_on_far && ! sel_on_local)
3691 {
3692 Message (MSG_ERROR, "Warning! Please select only a feature on a near sequence");
3693 }
3694 return;
3695 }
3696 if (slp == NULL) {
3697 Message (MSG_ERROR, "Warning! Failure to get location from selected feature");
3698 return;
3699 }
3700
3701 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
3702 while (sfp != NULL) {
3703 if (SeqLocAinB (sfp->location, slp) >= 0) {
3704 sfp->idx.deleteme = FALSE;
3705 } else {
3706 sfp->idx.deleteme = TRUE;
3707 }
3708 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
3709 }
3710
3711 remove_asked = FALSE;
3712 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
3713 while (sfp != NULL) {
3714 if (sfp->idx.deleteme) {
3715 if (sfp->data.choice == SEQFEAT_CDREGION && sfp->product != NULL) {
3716 prot = BioseqFindFromSeqLoc (sfp->product);
3717 if (prot != NULL) {
3718 if (! remove_asked) {
3719 ans = Message (MSG_YN, "Remove protein products?");
3720 if (ans == ANS_YES) {
3721 remove_prots = TRUE;
3722 }
3723 remove_asked = TRUE;
3724 }
3725 if (remove_prots) {
3726 prot->idx.deleteme = TRUE;
3727 }
3728 }
3729 }
3730 }
3731 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
3732 }
3733
3734 remove_asked = FALSE;
3735 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &fcontext);
3736 while (sfp != NULL) {
3737 if (sfp->idx.deleteme) {
3738 if (sfp->data.choice == SEQFEAT_RNA && sfp->product != NULL) {
3739 cdna = BioseqFindFromSeqLoc (sfp->product);
3740 if (cdna != NULL) {
3741 if (! remove_asked) {
3742 ans = Message (MSG_YN, "Remove mRNA products?");
3743 if (ans == ANS_YES) {
3744 remove_mrnas = TRUE;
3745 }
3746 remove_asked = TRUE;
3747 }
3748 if (remove_mrnas) {
3749 cdna->idx.deleteme = TRUE;
3750 }
3751 }
3752 }
3753 }
3754 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, 0, &fcontext);
3755 }
3756
3757 ObjMgrSelect (0, 0, 0, 0, NULL);
3758
3759 DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
3760
3761 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3762 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3763 }
3764
3765 static void RemoveCDDRegions (IteM i)
3766
3767 {
3768 BaseFormPtr bfp;
3769 SeqEntryPtr sep;
3770
3771 #ifdef WIN_MAC
3772 bfp = currentFormDataPtr;
3773 #else
3774 bfp = GetObjectExtra (i);
3775 #endif
3776 if (bfp == NULL) return;
3777 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3778 if (sep == NULL) return;
3779 FreeCDDRegions (sep);
3780 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3781 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3782 }
3783
3784 static void RemoveCDDAligns (IteM i)
3785
3786 {
3787 BaseFormPtr bfp;
3788 SeqEntryPtr sep;
3789
3790 #ifdef WIN_MAC
3791 bfp = currentFormDataPtr;
3792 #else
3793 bfp = GetObjectExtra (i);
3794 #endif
3795 if (bfp == NULL) return;
3796 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3797 if (sep == NULL) return;
3798 FreeCDDAligns (sep);
3799 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3800 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3801 }
3802
3803 static void RemoveCDDDups (IteM i)
3804
3805 {
3806 BaseFormPtr bfp;
3807 SeqEntryPtr sep;
3808
3809 #ifdef WIN_MAC
3810 bfp = currentFormDataPtr;
3811 #else
3812 bfp = GetObjectExtra (i);
3813 #endif
3814 if (bfp == NULL) return;
3815 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3816 if (sep == NULL) return;
3817 RemoveDuplicateCDDs (sep);
3818 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3819 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3820 }
3821
3822 static void RetainBestCDD (IteM i)
3823
3824 {
3825 BaseFormPtr bfp;
3826 SeqEntryPtr sep;
3827
3828 #ifdef WIN_MAC
3829 bfp = currentFormDataPtr;
3830 #else
3831 bfp = GetObjectExtra (i);
3832 #endif
3833 if (bfp == NULL) return;
3834 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3835 if (sep == NULL) return;
3836 LeaveBestCDD (sep);
3837 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
3838 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
3839 }
3840
3841 static void LastDitchLookup (BioSourcePtr biop)
3842
3843 {
3844 DbtagPtr dbt;
3845 Char orgname [256];
3846 OrgRefPtr orp;
3847 CharPtr ptr;
3848 CharPtr binomial_end = NULL, trinomial_end = NULL;
3849 SubSourcePtr ssp;
3850 Int4 taxID;
3851 ValNodePtr vnp;
3852
3853 if (biop == NULL) return;
3854 orp = biop->org;
3855 if (orp == NULL) return;
3856 /* if this organism has already been assigned a taxon ID, skip it */
3857 if (orp->db != NULL) {
3858 for (vnp = orp->db; vnp != NULL; vnp = vnp->next) {
3859 dbt = (DbtagPtr) vnp->data.ptrvalue;
3860 if (dbt != NULL) {
3861 if (StringICmp (dbt->db, "taxon") == 0) return;
3862 }
3863 }
3864 }
3865 /* we are looking for a name that might become a recognizable name if we
3866 * truncated it after the first four words (if the third word is subsp.),
3867 * after the first three words (if the third word is not subsp.),
3868 * or after the first two words if the above two attempts failed.
3869 */
3870
3871 StringNCpy_0 (orgname, orp->taxname, sizeof (orgname));
3872 if (StringHasNoText (orgname)) return;
3873 ptr = StringChr (orgname, ' ');
3874 if (ptr == NULL) return;
3875 /* skip over the first word and the spaces after it. */
3876 while (*ptr == ' ')
3877 {
3878 ptr++;
3879 }
3880 ptr = StringChr (ptr, ' ');
3881 /* if there are only two words, give up. */
3882 if (ptr == NULL)
3883 {
3884 return;
3885 }
3886 binomial_end = ptr;
3887 while (*ptr == ' ')
3888 {
3889 ptr++;
3890 }
3891 if (StringNCmp (ptr, "subsp.", 6) == 0)
3892 {
3893 ptr += 6;
3894 while (*ptr == ' ' )
3895 {
3896 ptr++;
3897 }
3898 }
3899
3900 ptr = StringChr (ptr, ' ');
3901 if (ptr != NULL)
3902 {
3903 trinomial_end = ptr;
3904 }
3905
3906 /* see if trinomial produces a tax server hit */
3907 taxID = 0;
3908 if (trinomial_end != NULL)
3909 {
3910 *trinomial_end = '\0';
3911 taxID = Taxon3GetTaxIdByName (orgname);
3912 }
3913 if (taxID < 1)
3914 {
3915 /* see if binomial produces a tax server hit */
3916 *binomial_end = '\0';
3917 taxID = Taxon3GetTaxIdByName (orgname);
3918 }
3919
3920 if (taxID < 1) return;
3921
3922 /* create a note that contains the original name of the organism, and truncate
3923 * the actual organism after the binomial or trinomial.
3924 */
3925 ssp = SubSourceNew ();
3926 if (ssp != NULL) {
3927 ssp->subtype = 255;
3928 ssp->name = orp->taxname;
3929 orp->taxname = NULL;
3930 ssp->next = biop->subtype;
3931 biop->subtype = ssp;
3932 SetTaxNameAndRemoveTaxRef (orp, StringSave (orgname));
3933 }
3934 }
3935
3936 static void LastDitchTaxonFixup (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
3937
3938 {
3939 BioseqPtr bsp = NULL;
3940 BioseqSetPtr bssp = NULL;
3941 ValNodePtr descr, vnp;
3942 BioSourcePtr biosp = NULL;
3943 SeqAnnotPtr annot, sap;
3944 SeqFeatPtr sfp;
3945
3946 if (IS_Bioseq(sep)) {
3947 bsp = sep->data.ptrvalue;
3948 descr = bsp->descr;
3949 annot = bsp->annot;
3950 } else {
3951 bssp = sep->data.ptrvalue;
3952 descr = bssp->descr;
3953 annot = bssp->annot;
3954 }
3955 for (vnp = descr; vnp; vnp = vnp->next) {
3956 if (vnp->choice == Seq_descr_source) {
3957 biosp = vnp->data.ptrvalue;
3958 LastDitchLookup (biosp);
3959 }
3960 }
3961 for (sap = annot; sap != NULL; sap = sap->next) {
3962 if (sap->type == 1) {
3963 for (sfp = (SeqFeatPtr) sap->data; sfp != NULL; sfp = sfp->next) {
3964 if (sfp->data.choice == SEQFEAT_BIOSRC) {
3965 biosp = sfp->data.value.ptrvalue;
3966 LastDitchLookup (biosp);
3967 }
3968 }
3969 }
3970 }
3971 }
3972
3973 static void GenSpecTaxonFixup (IteM i)
3974
3975 {
3976 BaseFormPtr bfp;
3977 SeqEntryPtr sep;
3978
3979 #ifdef WIN_MAC
3980 bfp = currentFormDataPtr;
3981 #else
3982 bfp = GetObjectExtra (i);
3983 #endif
3984 if (bfp == NULL) return;
3985 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
3986 if (sep == NULL) return;
3987 SeqEntryExplore (sep, NULL, LastDitchTaxonFixup);
3988 ForceTaxonFixupBtn (i, NULL);
3989 }
3990
3991
3992 static void MergeToPartsCallback (SeqFeatPtr sfp, Pointer userdata)
3993 {
3994 BoolPtr ordered;
3995
3996 if (sfp == NULL) return;
3997 ordered = (BoolPtr) userdata;
3998
3999 MergeFeatureIntervalsToParts (sfp, *ordered);
4000 }
4001
4002 static void MergeToParts (IteM i, Boolean ordered)
4003 {
4004 BaseFormPtr bfp;
4005 SelStructPtr ssp;
4006 Boolean some_sel_not_feat = FALSE;
4007 Boolean some_sel_feat = FALSE;
4008 SeqFeatPtr sfp;
4009 SeqMgrFeatContext fcontext;
4010 SeqEntryPtr sep;
4011
4012 ssp = ObjMgrGetSelected ();
4013 if (ssp == NULL) {
4014 #ifdef WIN_MAC
4015 bfp = currentFormDataPtr;
4016 #else
4017 bfp = GetObjectExtra (i);
4018 #endif
4019 if (bfp == NULL) {
4020 Message (MSG_ERROR, "MergeToParts error");
4021 return;
4022 }
4023 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4024 if (sep == NULL) return;
4025 VisitFeaturesInSep (sep, (Pointer) &ordered, MergeToPartsCallback);
4026 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
4027 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
4028 }
4029 else
4030 {
4031 while (ssp != NULL)
4032 {
4033 if (ssp->itemtype == OBJ_SEQFEAT)
4034 {
4035 sfp = SeqMgrGetDesiredFeature (ssp->entityID, NULL, ssp->itemID, 0, NULL, &fcontext);
4036 if (sfp != NULL)
4037 {
4038 MergeFeatureIntervalsToParts (sfp, ordered);
4039 some_sel_feat = TRUE;
4040 ObjMgrSetDirtyFlag (ssp->entityID, TRUE);
4041 ObjMgrSendMsg (OM_MSG_UPDATE, ssp->entityID, 0, 0);
4042 }
4043 }
4044 else
4045 {
4046 some_sel_not_feat = TRUE;
4047 }
4048 ssp = ssp->next;
4049 }
4050 if (!some_sel_feat)
4051 {
4052 Message (MSG_ERROR, "No features selected!");
4053 }
4054 else if (some_sel_not_feat)
4055 {
4056 Message (MSG_ERROR, "Some selected items were not features!");
4057 }
4058 }
4059 Update ();
4060 }
4061
4062 extern void MergeToPartsJoin (IteM i)
4063 {
4064 MergeToParts (i, FALSE);
4065 }
4066
4067 extern void MergeToPartsOrdered (IteM i)
4068 {
4069 MergeToParts (i, TRUE);
4070 }
4071
4072
4073 static Boolean MergeSegSeqCallback (GatherContextPtr gcp)
4074
4075 {
4076 BioseqPtr bsp;
4077 CodeBreakPtr cbp;
4078 CdRegionPtr crp;
4079 Boolean noLeft;
4080 Boolean noRight;
4081 RnaRefPtr rrp;
4082 SeqEntryPtr sep;
4083 SeqFeatPtr sfp;
4084 SeqLocPtr slp;
4085 tRNAPtr trna;
4086
4087 if (gcp->thistype != OBJ_SEQFEAT) return TRUE;
4088 sfp = (SeqFeatPtr) gcp->thisitem;
4089 if (sfp == NULL || sfp->location == NULL) return TRUE;
4090 bsp = GetBioseqGivenSeqLoc (sfp->location, gcp->entityID);
4091 if (bsp == NULL) return TRUE;
4092 if (ISA_aa (bsp->mol)) return TRUE;
4093 if (bsp->repr != Seq_repr_seg) {
4094 sep = GetBestTopParentForData (gcp->entityID, bsp);
4095 if (sep == NULL) return TRUE;
4096 sep = FindNucSeqEntry (sep);
4097 if (sep == NULL || sep->choice != 1) return TRUE;
4098 bsp = (BioseqPtr) sep->data.ptrvalue;
4099 if (bsp == NULL) return TRUE;
4100 }
4101 CheckSeqLocForPartial (sfp->location, &noLeft, &noRight);
4102 slp = SeqLocMerge (bsp, sfp->location, NULL, FALSE, TRUE, FALSE);
4103 if (slp == NULL) return TRUE;
4104 sfp->location = SeqLocFree (sfp->location);
4105 sfp->location = slp;
4106 FreeAllFuzz (sfp->location);
4107 SetSeqLocPartial (sfp->location, noLeft, noRight);
4108 sfp->partial = (sfp->partial || noLeft || noRight);
4109 switch (sfp->data.choice) {
4110 case SEQFEAT_CDREGION :
4111 crp = (CdRegionPtr) sfp->data.value.ptrvalue;
4112 if (crp != NULL && crp->code_break != NULL) {
4113 for (cbp = crp->code_break; cbp != NULL; cbp = cbp->next) {
4114 slp = SeqLocMerge (bsp, cbp->loc, NULL, FALSE, TRUE, FALSE);
4115 if (slp != NULL) {
4116 cbp->loc = SeqLocFree (cbp->loc);
4117 cbp->loc = slp;
4118 FreeAllFuzz (cbp->loc);
4119 }
4120 }
4121 }
4122 break;
4123 case SEQFEAT_RNA :
4124 rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
4125 if (rrp != NULL && rrp->type == 3 && rrp->ext.choice == 2) {
4126 trna = rrp->ext.value.ptrvalue;
4127 if (trna != NULL && trna->anticodon != NULL) {
4128 slp = SeqLocMerge (bsp, trna->anticodon, NULL, FALSE, TRUE, FALSE);
4129 if (slp != NULL) {
4130 trna->anticodon = SeqLocFree (trna->anticodon);
4131 trna->anticodon = slp;
4132 FreeAllFuzz (trna->anticodon);
4133 }
4134 }
4135 }
4136 break;
4137 default :
4138 break;
4139 }
4140 return TRUE;
4141 }
4142
4143 static void MergeToSegSeq (IteM i)
4144
4145 {
4146 BaseFormPtr bfp;
4147 GatherScope gs;
4148 SelStructPtr ssp;
4149
4150 ssp = ObjMgrGetSelected ();
4151 if (ssp == NULL) {
4152 #ifdef WIN_MAC
4153 bfp = currentFormDataPtr;
4154 #else
4155 bfp = GetObjectExtra (i);
4156 #endif
4157 if (bfp == NULL) {
4158 Message (MSG_ERROR, "MergeToSegSeq error");
4159 return;
4160 }
4161 MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
4162 gs.seglevels = 1;
4163 MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
4164 gs.ignore[OBJ_BIOSEQ] = FALSE;
4165 gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
4166 gs.ignore[OBJ_SEQANNOT] = FALSE;
4167 gs.ignore[OBJ_SEQFEAT] = FALSE;
4168 GatherEntity (bfp->input_entityID, NULL, MergeSegSeqCallback, &gs);
4169 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
4170 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
4171 /*
4172 Message (MSG_ERROR, "No item selected");
4173 */
4174 return;
4175 }
4176 if (ssp->itemtype != OBJ_SEQFEAT) {
4177 Message (MSG_ERROR, "Feature must be selected");
4178 return;
4179 }
4180 GatherItem (ssp->entityID, ssp->itemID, ssp->itemtype, NULL, MergeSegSeqCallback);
4181 ObjMgrSetDirtyFlag (ssp->entityID, TRUE);
4182 ObjMgrSendMsg (OM_MSG_UPDATE, ssp->entityID, 0, 0);
4183 }
4184
4185 static void SegToRawCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
4186
4187 {
4188 BioseqPtr bsp;
4189
4190 if (sep == NULL) return;
4191 if (! IS_Bioseq (sep)) return;
4192 bsp = (BioseqPtr) sep->data.ptrvalue;
4193 if (bsp == NULL || (bsp->repr != Seq_repr_seg && bsp->repr != Seq_repr_delta)) return;
4194 SegOrDeltaBioseqToRaw (bsp);
4195 }
4196
4197 static void SegSeqToRawSeq (IteM i)
4198
4199 {
4200 BaseFormPtr bfp;
4201 SeqEntryPtr sep;
4202
4203 #ifdef WIN_MAC
4204 bfp = currentFormDataPtr;
4205 #else
4206 bfp = GetObjectExtra (i);
4207 #endif
4208 if (bfp == NULL) return;
4209 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4210 if (sep == NULL) return;
4211 SeqEntryExplore (sep, (Pointer) bfp, SegToRawCallback);
4212 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
4213 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
4214 Message (MSG_OK, "Some manual desktop manipulations remain");
4215 }
4216
4217 static void CollectBioseqsForConversion (BioseqPtr bsp, Pointer userdata)
4218 {
4219 ValNodePtr PNTR list;
4220
4221 if (bsp == NULL || bsp->repr != Seq_repr_raw || ISA_aa (bsp->mol)) return;
4222 if (userdata == NULL)
4223 {
4224 return;
4225 }
4226 list = (ValNodePtr PNTR) userdata;
4227
4228 ValNodeAddPointer (list, 0, bsp);
4229 }
4230
4231 static ValNodePtr GetAnnotListForBspList (ValNodePtr bsp_list)
4232 {
4233 BioseqPtr bsp;
4234 SeqAnnotPtr sanp;
4235 ValNodePtr complete_annot_list = NULL, align_annot_list;
4236 ValNodePtr annot_vnp, vnp, bsp_vnp;
4237 Boolean found;
4238
4239 for (bsp_vnp = bsp_list; bsp_vnp != NULL; bsp_vnp = bsp_vnp->next)
4240 {
4241 bsp = (BioseqPtr)(bsp_vnp->data.ptrvalue);
4242 align_annot_list = FindAlignSeqAnnotsForBioseq (bsp);
4243 for (annot_vnp = align_annot_list; annot_vnp != NULL; annot_vnp = annot_vnp->next)
4244 {
4245 sanp = (SeqAnnotPtr) annot_vnp->data.ptrvalue;
4246 if (sanp->type == 2 && sanp->data != NULL)
4247 {
4248 for (vnp = complete_annot_list, found = FALSE;
4249 vnp != NULL && !found;
4250 vnp = vnp->next)
4251 {
4252 if (vnp->data.ptrvalue == sanp)
4253 {
4254 found = TRUE;
4255 }
4256 }
4257 if (!found)
4258 {
4259 ValNodeAddPointer (&complete_annot_list, 0, sanp);
4260 }
4261 }
4262 }
4263 align_annot_list = ValNodeFree (align_annot_list);
4264 }
4265 return complete_annot_list;
4266 }
4267
4268
4269 static void
4270 CleanupAlignmentsAfterConversion
4271 (ValNodePtr adjusted_bsp_list,
4272 Uint2 entityID)
4273 {
4274 ValNodePtr align_annot_list, annot_vnp;
4275 SeqAnnotPtr sanp;
4276
4277 align_annot_list = GetAnnotListForBspList (adjusted_bsp_list);
4278 for (annot_vnp = align_annot_list;
4279 annot_vnp != NULL;
4280 annot_vnp = annot_vnp->next)
4281 {
4282 sanp = annot_vnp->data.ptrvalue;
4283 if (sanp != NULL && sanp->type == 2)
4284 {
4285 ConsolidateSegmentsOverKnownLengthGaps (sanp->data);
4286 FixOneAlignmentOverGaps (sanp->data, entityID);
4287 }
4288 }
4289 align_annot_list = ValNodeFree (align_annot_list);
4290 DeleteMarkedObjects (entityID, 0, NULL);
4291
4292 }
4293
4294 static void CorrectAlignmentsAfterNToGapConversion (SeqEntryPtr sep, Uint2 entityID)
4295 {
4296 ValNodePtr adjusted_bsp_list = NULL;
4297
4298 VisitBioseqsInSep (sep, &adjusted_bsp_list, CollectBioseqsForConversion);
4299 CleanupAlignmentsAfterConversion (adjusted_bsp_list, entityID);
4300 adjusted_bsp_list = ValNodeFree (adjusted_bsp_list);
4301 }
4302
4303 static void ConvertNsToGapsWithSizeList (Uint2 entityID, Int4Ptr gap_sizes, Boolean adjust_cds)
4304 {
4305 ValNodePtr adjusted_bsp_list = NULL;
4306 SeqEntryPtr sep;
4307
4308 sep = GetTopSeqEntryForEntityID (entityID);
4309 if (sep == NULL) return;
4310 VisitBioseqsInSep (sep, &adjusted_bsp_list, CollectBioseqsForConversion);
4311
4312 if (adjust_cds)
4313 {
4314 /* remove the gap locations from the coding regions first */
4315 VisitBioseqsInSep (sep, gap_sizes, PrepareCodingRegionLocationsForDeltaConversionCallback);
4316 }
4317
4318 VisitBioseqsInSep (sep, gap_sizes, ConvertNsToGaps);
4319 CleanupAlignmentsAfterConversion (adjusted_bsp_list, entityID);
4320 adjusted_bsp_list = ValNodeFree (adjusted_bsp_list);
4321 ObjMgrSetDirtyFlag (entityID, TRUE);
4322 ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
4323 }
4324
4325
4326 static void RawSeqToDeltaSeq (IteM i)
4327
4328 {
4329 BaseFormPtr bfp;
4330
4331 #ifdef WIN_MAC
4332 bfp = currentFormDataPtr;
4333 #else
4334 bfp = GetObjectExtra (i);
4335 #endif
4336 if (bfp == NULL) return;
4337 ConvertNsToGapsWithSizeList (bfp->input_entityID, NULL, FALSE);
4338 }
4339
4340 static void RawSeqToDeltaSeqUnknownLengthGaps (IteM i)
4341
4342 {
4343 BaseFormPtr bfp;
4344 Int4 gap_sizes[2];
4345
4346 #ifdef WIN_MAC
4347 bfp = currentFormDataPtr;
4348 #else
4349 bfp = GetObjectExtra (i);
4350 #endif
4351 if (bfp == NULL) return;
4352 gap_sizes [0] = 100;
4353 gap_sizes [1] = -1;
4354 ConvertNsToGapsWithSizeList (bfp->input_entityID, gap_sizes, FALSE);
4355 }
4356
4357 static void RawSeqToDeltaSeqUnknown100LengthGaps (IteM i)
4358
4359 {
4360 BaseFormPtr bfp;
4361 Int4 gap_sizes[2];
4362
4363 #ifdef WIN_MAC
4364 bfp = currentFormDataPtr;
4365 #else
4366 bfp = GetObjectExtra (i);
4367 #endif
4368 if (bfp == NULL) return;
4369 gap_sizes [0] = -1;
4370 gap_sizes [1] = 0;
4371 ConvertNsToGapsWithSizeList (bfp->input_entityID, gap_sizes, FALSE);
4372 }
4373
4374 #if 0
4375 static void ConvertSegSetToDeltaItem (IteM i)
4376 {
4377 BaseFormPtr bfp;
4378 SeqEntryPtr sep;
4379 Int4 gap_sizes[2];
4380
4381 #ifdef WIN_MAC
4382 bfp = currentFormDataPtr;
4383 #else
4384 bfp = GetObjectExtra (i);
4385 #endif
4386 if (bfp == NULL) return;
4387 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4388 if (sep == NULL) return;
4389 ConvertSegSetsToDeltaSequences (sep);
4390 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
4391 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
4392 }
4393 #endif
4394
4395
4396 typedef struct gapconversiondata
4397 {
4398 FEATURE_FORM_BLOCK
4399
4400 GrouP unknown_op;
4401 TexT unknown_val_txt;
4402 GrouP known_op;
4403 TexT known_val_txt;
4404 ButtoN acceptBtn;
4405 DoC explanation;
4406 ButtoN adjust_CDS_locations;
4407
4408 } GapConversionData, PNTR GapConversionPtr;
4409
4410 static ParData faParFmt = {FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0};
4411 static ColData faColFmt = {0, 0, 80, 0, NULL, 'l', TRUE, FALSE, FALSE, FALSE, TRUE};
4412
4413 static void SetConvertGapsAcceptAndText (GapConversionPtr gcp)
4414 {
4415 Char str[15];
4416 Int4 unknown_val, known_val;
4417 Int4 unknown_op, known_op;
4418 Char explanation[300];
4419
4420 if (gcp == NULL || gcp->explanation == NULL) return;
4421 GetTitle (gcp->unknown_val_txt, str, sizeof (str));
4422 unknown_val = atoi (str);
4423 unknown_op = GetValue (gcp->unknown_op);
4424 GetTitle (gcp->known_val_txt, str, sizeof (str));
4425 known_val = atoi (str);
4426 known_op = GetValue (gcp->known_op);
4427
4428 Reset (gcp->explanation);
4429 explanation [0] = 0;
4430
4431 if (unknown_val < 0 || known_val < 0)
4432 {
4433 sprintf (explanation, "%s", "Negative values are not permitted.");
4434 Disable (gcp->acceptBtn);
4435 }
4436 else if (known_val == unknown_val)
4437 {
4438 sprintf (explanation,
4439 "You must specify different values for known and unknown gap conversion sizes.");
4440 Disable (gcp->acceptBtn);
4441 }
4442 else if (unknown_val == 0 && unknown_op == 1 && known_val == 0 && known_op == 1)
4443 {
4444 sprintf (explanation, "%s", "This combination will have no effect.");
4445 Disable (gcp->acceptBtn);
4446 }
4447 else if (unknown_val == 0 && unknown_op == 1 && (known_val == 0 || known_val == 1) && known_op == 2)
4448 {
4449 sprintf (explanation, "%s", "All sequences of Ns will be converted to gaps of known length.");
4450 Enable (gcp->acceptBtn);
4451 }
4452 else if ((unknown_val == 0 || unknown_val == 1) && unknown_op == 2 && known_val == 0 && known_op == 1)
4453 {
4454 sprintf (explanation, "%s", "All sequences of Ns will be converted to gaps of unknown length (size 100).");
4455 Enable (gcp->acceptBtn);
4456 }
4457 else if (unknown_val == 0 && unknown_op == 1)
4458 {
4459 if (known_op == 1)
4460 {
4461 sprintf (explanation,
4462 "All sequences of exactly %d Ns will be converted to gaps of known length.\n"
4463 "All other sequences of Ns will remain as Ns.", known_val);
4464 Enable (gcp->acceptBtn);
4465 }
4466 else
4467 {
4468 sprintf (explanation,
4469 "All sequences of %d or more Ns will be converted to gaps of known length.\n"
4470 "All sequences of less than %d Ns will remain as Ns.", known_val, known_val);
4471 Enable (gcp->acceptBtn);
4472 }
4473 }
4474 else if (known_val == 0 && known_op == 1)
4475 {
4476 if (unknown_op == 1)
4477 {
4478 sprintf (explanation,
4479 "All sequences of exactly %d Ns will be converted to gaps of unknown length (size 100).\n"
4480 "All other sequences of Ns will remain as Ns.", unknown_val);
4481 Enable (gcp->acceptBtn);
4482 }
4483 else if (unknown_op == 2)
4484 {
4485 sprintf (explanation,
4486 "All sequences of %d or more Ns will be converted to gaps of unknown length.\n"
4487 "All sequences of less than %d Ns will remain as Ns.", unknown_val, unknown_val);
4488 Enable (gcp->acceptBtn);
4489 }
4490 }
4491 else if (known_op == 1 && unknown_op == 1)
4492 {
4493 sprintf (explanation,
4494 "All sequences of exactly %d Ns will be converted to gaps of known length.\n"
4495 "All sequences of exactly %d Ns will be converted to gaps of unknown length (size 100).\n"
4496 "All sequences of Ns with lengths other than %d or %d will remain as Ns.",
4497 known_val, unknown_val, known_val, unknown_val);
4498 Enable (gcp->acceptBtn);
4499 }
4500 else if (known_op == 2 && unknown_op == 2)
4501 {
4502 /* handle cases where both operators are greater than/equal to */
4503 if (known_val > unknown_val)
4504 {
4505 if (unknown_val == 0 || unknown_val == 1)
4506 {
4507 sprintf (explanation,
4508 "All sequences of Ns with lengths >= 1 and <= %d will be converted to gaps of unknown length (size 100).\n"
4509 "All sequences of Ns with lengths >= %d will be converted to gaps of known length.\n",
4510 known_val -1, known_val);
4511 }
4512 else
4513 {
4514 sprintf (explanation,
4515 "All sequences of Ns with lengths >= %d and <= %d will be converted to gaps of unknown length (size 100).\n"
4516 "All sequences of Ns with lengths >= %d will be converted to gaps of known length.\n"
4517 "All sequences of Ns with lengths <= %d will remain as Ns.",
4518 unknown_val, known_val -1, known_val, unknown_val - 1);
4519 }
4520 }
4521 else
4522 {
4523 if (known_val == 0 || known_val == 1)
4524 {
4525 sprintf (explanation,
4526 "All sequences of Ns with lengths >= 1 and <= %d will be converted to gaps of known length.\n"
4527 "All sequences of Ns with lengths >= %d will be converted to gaps of unknown length (size 100).\n",
4528 unknown_val -1, unknown_val);
4529 }
4530 else
4531 {
4532 sprintf (explanation,
4533 "All sequences of Ns with lengths >= %d and <= %d will be converted to gaps of known length.\n"
4534 "All sequences of Ns with lengths >= %d will be converted to gaps of unknown length (size 100).\n"
4535 "All sequences of Ns with lengths <= %d will remain as Ns.",
4536 known_val, unknown_val -1, unknown_val, known_val - 1);
4537 }
4538 }
4539 }
4540 else if (known_val > unknown_val)
4541 {
4542 if (known_op == 1)
4543 {
4544 /* we know that unknown_op is 2 */
4545 if (unknown_val == 0 || unknown_val == 1)
4546 {
4547 sprintf (explanation,
4548 "All sequences of exactly %d Ns will be converted to gaps of known length.\n"
4549 "All sequences of Ns with lengths >= 1 and <= %d or lengths >= %d will be converted to gaps of unknown length (size 100).\n",
4550 known_val, known_val - 1, known_val + 1);
4551 }
4552 else
4553 {
4554 sprintf (explanation,
4555 "All sequences of exactly %d Ns will be converted to gaps of known length.\n"
4556 "All sequences of Ns with lengths >= %d and <= %d or lengths >= %d will be converted to gaps of unknown length (size 100).\n"
4557 "All sequences of Ns with lengths <= %d will remain as Ns.",
4558 known_val, unknown_val, known_val - 1, known_val + 1, unknown_val - 1);
4559 }
4560 Enable (gcp->acceptBtn);
4561 }
4562 else if (known_op == 2)
4563 {
4564 /* we know that unknown_op is 1 */
4565 if (unknown_val == 1)
4566 {
4567 sprintf (explanation,
4568 "All sequences of exactly 1 Ns will be converted to gaps of unknown length (size 100).\n"
4569 "All sequences with lengths >= %d will be converted to gaps of known length.\n"
4570 "All sequences of Ns with lengths >= 2 and <= %d will remain as Ns",
4571 known_val, known_val - 1);
4572 }
4573 else
4574 {
4575 sprintf (explanation,
4576 "All sequences of exactly %d Ns will be converted to gaps of unknown length (size 100).\n"
4577 "All sequences of Ns with lengths >= %d will be converted to gaps of known length.\n"
4578 "All sequences of Ns with lengths >= %d or lengths >= %d and <= %d will remain as Ns. ",
4579 unknown_val, known_val, unknown_val - 1, unknown_val + 1, known_val - 1);
4580 }
4581 Enable (gcp->acceptBtn);
4582 }
4583 }
4584 else
4585 {
4586 /* unknown_val > known_val */
4587 if (known_op == 1)
4588 {
4589 /* we know that unknown_op is 2 */
4590 sprintf (explanation,
4591 "All sequences of exactly %d Ns will be converted to gaps of known length.\n"
4592 "All sequences of Ns with lengths >= %d will be converted to gaps of unknown length (size 100).\n"
4593 "All sequences of Ns with lengths <= %d or lengths >= %d and <= %d will remain as Ns.\n",
4594 known_val, unknown_val, known_val - 1, known_val + 1, unknown_val - 1);
4595 }
4596 else
4597 {
4598 /* we know that unknown_op is 1, known_op is 2 */
4599 if (known_val == 0 || known_val == 1)
4600 {
4601 sprintf (explanation,
4602 "All sequences of exactly %d Ns will be converted to gaps of unknown length (size 100).\n"
4603 "All sequences of Ns with lengths >= 1 and <= %d or lengths >= %d will be converted to gaps of known length.\n",
4604 unknown_val, unknown_val - 1, unknown_val + 1);
4605 }
4606 else
4607 {
4608 sprintf (explanation,
4609 "All sequences of exactly %d Ns will be converted to gaps of unknown length (size 100).\n"
4610 "All sequences of Ns with lengths >= %d and <= %d or lengths >= %d will be converted to gaps of known length.\n"
4611 "All sequences of Ns with lengths <= %d will remain as Ns.",
4612 unknown_val, known_val, unknown_val - 1, unknown_val + 1, known_val);
4613
4614 }
4615 }
4616 Enable (gcp->acceptBtn);
4617 }
4618 AppendText (gcp->explanation, explanation, &faParFmt, &faColFmt, programFont);
4619 UpdateDocument (gcp->explanation, 0, 0);
4620 Update ();
4621 }
4622
4623 static void SetGapsConvertAcceptButtonAndTextGroup (GrouP g)
4624 {
4625 GapConversionPtr gcp;
4626
4627 gcp = (GapConversionPtr) GetObjectExtra (g);
4628 SetConvertGapsAcceptAndText (gcp);
4629 }
4630
4631 static void SetGapsConvertAcceptButtonAndTextText (TexT nText)
4632 {
4633 GapConversionPtr gcp;
4634
4635 gcp = (GapConversionPtr) GetObjectExtra (nText);
4636 SetConvertGapsAcceptAndText (gcp);
4637 }
4638
4639 static void ConvertGaps (ButtoN b)
4640 {
4641 GapConversionPtr gcp;
4642 SeqEntryPtr sep;
4643 Int4 gap_sizes[2];
4644 Char str[15];
4645 Int4 unknown_val, known_val;
4646 Int4 unknown_op, known_op;
4647
4648 if (b == NULL) return;
4649 gcp = (GapConversionPtr) GetObjectExtra (b);
4650 if (gcp == NULL) return;
4651 sep = GetTopSeqEntryForEntityID (gcp->input_entityID);
4652 if (sep == NULL) return;
4653
4654 GetTitle (gcp->unknown_val_txt, str, sizeof (str));
4655 unknown_val = atoi (str);
4656 unknown_op = GetValue (gcp->unknown_op);
4657 if (unknown_op == 1)
4658 {
4659 gap_sizes [0] = unknown_val;
4660 }
4661 else
4662 {
4663 if (unknown_val == 0)
4664 unknown_val = 1;
4665 gap_sizes[0] = 0 - unknown_val;
4666 }
4667 GetTitle (gcp->known_val_txt, str, sizeof (str));
4668 known_val = atoi (str);
4669 known_op = GetValue (gcp->known_op);
4670 if (known_op == 1)
4671 {
4672 gap_sizes [1] = known_val;
4673 }
4674 else
4675 {
4676 if (known_val == 0)
4677 known_val = 1;
4678 gap_sizes[1] = 0 - known_val;
4679 }
4680
4681
4682 Hide (gcp->form);
4683 ConvertNsToGapsWithSizeList (gcp->input_entityID, gap_sizes, GetStatus (gcp->adjust_CDS_locations));
4684
4685 Remove (gcp->form);
4686 }
4687
4688 static void ListRawSequencesInAlignments (BioseqPtr bsp, Pointer userdata)
4689 {
4690 ValNodePtr PNTR raw_list;
4691 Char id_str [128];
4692
4693 if (bsp == NULL || bsp->repr != Seq_repr_raw || userdata == NULL)
4694 {
4695 return;
4696 }
4697
4698 if (!IsBioseqInAnyAlignment (bsp, bsp->idx.entityID))
4699 {
4700 return;
4701 }
4702
4703 raw_list = (ValNodePtr PNTR) userdata;
4704 SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_str, PRINTID_REPORT, sizeof (id_str) - 1);
4705 ValNodeAddPointer (raw_list, 0, StringSave (id_str));
4706 }
4707
4708 static Boolean ContinueWithSequencesInAlignments (SeqEntryPtr sep)
4709 {
4710 ValNodePtr raw_in_aln = NULL;
4711 CharPtr msg;
4712 MsgAnswer ans;
4713
4714 VisitBioseqsInSep (sep, &raw_in_aln, ListRawSequencesInAlignments);
4715 if (raw_in_aln != NULL)
4716 {
4717 msg = CreateListMessage ("Sequence",
4718 raw_in_aln->next == NULL
4719 ? " is in an alignment. The alignment will be automatically adjusted after conversion. Do you want to continue?"
4720 : " are in alignments. The alignment will be automatically adjusted after conversion. Do you want to continue?",
4721 raw_in_aln);
4722 raw_in_aln = ValNodeFreeData (raw_in_aln);
4723 ans = Message (MSG_YN, msg);
4724 msg = MemFree (msg);
4725 if (ans == ANS_NO)
4726 {
4727 return FALSE;
4728 }
4729 }
4730 return TRUE;
4731 }
4732
4733 static void ListDeltaSequences (BioseqPtr bsp, Pointer userdata)
4734 {
4735 ValNodePtr PNTR delta_list;
4736 Char id_str [128];
4737
4738 if (bsp == NULL || bsp->repr != Seq_repr_delta || userdata == NULL)
4739 {
4740 return;
4741 }
4742
4743 delta_list = (ValNodePtr PNTR) userdata;
4744 SeqIdWrite (SeqIdFindBest (bsp->id, SEQID_GENBANK), id_str, PRINTID_REPORT, sizeof (id_str) - 1);
4745 ValNodeAddPointer (delta_list, 0, StringSave (id_str));
4746 }
4747
4748 static Boolean ContinueWithDeltaSequences (SeqEntryPtr sep)
4749 {
4750 ValNodePtr delta_list = NULL;
4751 CharPtr msg;
4752 MsgAnswer ans;
4753
4754 VisitBioseqsInSep (sep, &delta_list, ListDeltaSequences);
4755 if (delta_list != NULL)
4756 {
4757 msg = CreateListMessage ("Sequence",
4758 delta_list->next == NULL
4759 ? " is already a delta sequence and gaps will not be added. Do you want to continue?"
4760 : " are already delta sequences and gaps will not be added. Do you want to continue?",
4761 delta_list);
4762 delta_list = ValNodeFreeData (delta_list);
4763 ans = Message (MSG_YN, msg);
4764 msg = MemFree (msg);
4765 if (ans == ANS_NO)
4766 {
4767 return FALSE;
4768 }
4769 }
4770 return TRUE;
4771 }
4772
4773
4774 static void RawSeqToDeltaSeqUnknownWithUnknownLengthGaps (IteM i)
4775 {
4776 BaseFormPtr bfp;
4777 GapConversionPtr gcp;
4778 WindoW w;
4779 GrouP h, l, g, c;
4780 RecT r;
4781 PrompT p1, p2;
4782 SeqEntryPtr sep;
4783
4784 #ifdef WIN_MAC
4785 bfp = currentFormDataPtr;
4786 #else
4787 bfp = GetObjectExtra (i);
4788 #endif
4789 if (bfp == NULL) return;
4790
4791 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
4792 if (!ContinueWithDeltaSequences (sep))
4793 {
4794 return;
4795 }
4796 if (!ContinueWithSequencesInAlignments (sep))
4797 {
4798 return;
4799 }
4800
4801 gcp = (GapConversionPtr) MemNew (sizeof (GapConversionData));
4802 if (gcp == NULL) return;
4803
4804 gcp->input_entityID = bfp->input_entityID;
4805 w = FixedWindow (-50, -33, -10, -10, "Convert Ns to Gaps of Unknown Length", StdCloseWindowProc);
4806 SetObjectExtra (w, gcp, StdCleanupFormProc);
4807 gcp->form = (ForM) w;
4808 h = HiddenGroup (w, -1, 0, NULL);
4809 SetGroupSpacing (h, 10, 10);
4810 p1 = StaticPrompt (h, "Choose size of length of Ns to convert to gaps of unknown length", 0, dialogTextHeight, programFont, 'c');
4811 g = HiddenGroup (h, 2, 0, NULL);
4812 gcp->unknown_op = HiddenGroup (g, 0, 2, SetGapsConvertAcceptButtonAndTextGroup);
4813 SetObjectExtra (gcp->unknown_op, gcp, NULL);
4814 RadioButton (gcp->unknown_op, "=");
4815 RadioButton (gcp->unknown_op, ">=");
4816 SetValue (gcp->unknown_op, 1);
4817 gcp->unknown_val_txt = DialogText (g, "100", 14, SetGapsConvertAcceptButtonAndTextText);
4818 SetObjectExtra (gcp->unknown_val_txt, gcp, NULL);
4819 p2 = StaticPrompt (h, "Choose size of length of Ns to convert to gaps of known length", 0, dialogTextHeight, programFont, 'c');
4820 l = HiddenGroup (h, 2, 0, NULL);
4821 gcp->known_op = HiddenGroup (l, 0, 2, SetGapsConvertAcceptButtonAndTextGroup);
4822 SetObjectExtra (gcp->known_op, gcp, NULL);
4823 RadioButton (gcp->known_op, "=");
4824 RadioButton (gcp->known_op, ">=");
4825 SetValue (gcp->known_op, 1);
4826 gcp->known_val_txt = DialogText (l, "0", 14, SetGapsConvertAcceptButtonAndTextText);
4827 SetObjectExtra (gcp->known_val_txt, gcp, NULL);
4828
4829 /* status text */
4830 gcp->explanation = DocumentPanel (h, stdCharWidth * 27, stdLineHeight * 8);
4831 ObjectRect (gcp->explanation, &r);
4832 InsetRect (&r, 4, 4);
4833 faColFmt.pixWidth = r.right - r.left;
4834
4835 gcp->adjust_CDS_locations = CheckBox (h, "Adjust CDS locations for gaps", NULL);
4836 SetStatus (gcp->adjust_CDS_locations, TRUE);
4837
4838 c = HiddenGroup (h, 4, 0, NULL);
4839 gcp->acceptBtn = PushButton (c, "Accept", ConvertGaps);
4840 SetObjectExtra (gcp->acceptBtn, gcp, NULL);
4841 PushButton (c, "Cancel", StdCancelButtonProc);
4842
4843 AlignObjects (ALIGN_CENTER, (HANDLE) p1,
4844 (HANDLE) g,
4845 (HANDLE) p2,
4846 (HANDLE) l,
4847 (HANDLE) gcp->explanation,
4848 (HANDLE) gcp->adjust_CDS_locations,
4849 (HANDLE) c,
4850 NULL);
4851
4852 SetConvertGapsAcceptAndText (gcp);
4853 RealizeWindow (w);
4854 Show (w);
4855 Update ();
4856 }
4857
4858 static Uint2 deltaconversionedittypes [] =
4859 {
4860 TAGLIST_TEXT, TAGLIST_POPUP, TAGLIST_TEXT, TAGLIST_POPUP
4861 };
4862
4863 ENUM_ALIST(deltaconversionedit_alist)
4864 {"Unknown length", 0},
4865 {"Known Length", 1},
4866 END_ENUM_ALIST
4867
4868 ENUM_ALIST(deltaconversionedit_type_alist)
4869 {"Insert", 0},
4870 {"Replace", 1},
4871 END_ENUM_ALIST
4872
4873 EnumFieldAssocPtr deltaconversionedit_alists [] = {
4874 NULL, deltaconversionedit_alist, NULL, deltaconversionedit_type_alist
4875 };
4876
4877 static Uint2 deltaconversionedit_widths [] = {
4878 5, 5, 5, 5
4879 };
4880
4881 typedef struct deltaconversion
4882 {
4883 FEATURE_FORM_BLOCK
4884
4885 DialoG gap_locations;
4886 GrouP coord_grp;
4887 ButtoN adjust_CDS_locations;
4888
4889 } DeltaConversionData, PNTR DeltaConversionPtr;
4890
4891
4892 static SeqAlignPtr
4893 AdjustOneAlignmentForOneBioseqBasedOnGapLocations
4894 (SeqAlignPtr salp_to_adjust,
4895 BioseqPtr bsp,
4896 ValNodePtr gaps,
4897 SeqAlignPtr gap_salp)
4898 {
4899 Int4 aln_index;
4900 SeqIdPtr sip;
4901 ValNodePtr gap_vnp;
4902 GapLocInfoPtr glip;
4903 SeqLocPtr slp;
4904 Int4 gap_start;
4905 Int4 cumulative_offset = 0;
4906 DenseSegPtr dsp;
4907
4908 if (salp_to_adjust == NULL || salp_to_adjust->segtype != SAS_DENSEG
4909 || bsp == NULL || gaps == NULL)
4910 {
4911 return salp_to_adjust;
4912 }
4913
4914 dsp = (DenseSegPtr) salp_to_adjust->segs;
4915 if (dsp == NULL) {
4916 return salp_to_adjust;
4917 }
4918 sip = bsp->id;
4919 aln_index = 0;
4920 while (sip != NULL && aln_index == 0)
4921 {
4922 aln_index = SeqIdOrderInBioseqIdList (sip, dsp->ids);
4923 if (aln_index == 0)
4924 {
4925 sip = sip->next;
4926 }
4927 }
4928 if (aln_index == 0) {
4929 /* bioseq not in alignment */
4930 return salp_to_adjust;
4931 }
4932
4933 for (gap_vnp = gaps; gap_vnp != NULL; gap_vnp = gap_vnp->next)
4934 {
4935 glip = (GapLocInfoPtr) gap_vnp->data.ptrvalue;
4936 if (glip == NULL || glip->replace)
4937 {
4938 continue;
4939 }
4940 gap_start = glip->start_pos;
4941 if (gap_salp != NULL)
4942 {
4943 gap_start = AlnMgr2MapSeqAlignToBioseq(gap_salp, gap_start, aln_index);
4944 }
4945 if (gap_start < 1)
4946 {
4947 continue;
4948 }
4949 gap_start += cumulative_offset;
4950 if (gap_start > bsp->length)
4951 {
4952 continue;
4953 }
4954 slp = SeqLocIntNew (gap_start, gap_start + glip->length - 1, Seq_strand_plus, sip);
4955 salp_to_adjust = SeqAlignInsertByLoc (slp, salp_to_adjust);
4956 cumulative_offset += glip->length;
4957 }
4958
4959 return salp_to_adjust;
4960 }
4961
4962
4963 static void ShiftAlignmentForGapLocations (SeqAnnotPtr sanp, ValNodePtr gaps)
4964 {
4965 SeqAlignPtr salp;
4966 DenseSegPtr dsp;
4967 Int4 alignment_position = 0, k;
4968 Int4 cumulative_offset = 0;
4969 BoolPtr shift_this_row;
4970 Int4 seg_num = 0, shift_seg;
4971 ValNodePtr gap_vnp;
4972 GapLocInfoPtr glip;
4973
4974 if (sanp == NULL || sanp->data == NULL || sanp->type != 2 || gaps == NULL)
4975 {
4976 return;
4977 }
4978
4979 salp = (SeqAlignPtr) sanp->data;
4980 if (salp->segtype != SAS_DENSEG || salp->segs == NULL)
4981 {
4982 return;
4983 }
4984
4985 dsp = (DenseSegPtr) salp->segs;
4986
4987 shift_this_row = (BoolPtr) MemNew (sizeof (Boolean) * dsp->dim);
4988
4989 for (gap_vnp = gaps; gap_vnp != NULL; gap_vnp = gap_vnp->next)
4990 {
4991 glip = (GapLocInfoPtr) gap_vnp->data.ptrvalue;
4992 if (glip == NULL || glip->replace)
4993 {
4994 continue;
4995 }
4996 while (seg_num < dsp->numseg
4997 && alignment_position + dsp->lens [seg_num] < glip->start_pos + cumulative_offset)
4998
4999 {
5000 alignment_position += dsp->lens [seg_num];
5001 seg_num++;
5002 }
5003
5004 if (seg_num < dsp->numseg)
5005 {
5006 dsp->lens [seg_num] += glip->length;
5007 for (k = 0; k < dsp->dim; k++)
5008 {
5009 if (dsp->starts [seg_num * dsp->dim + k] == -1)
5010 {
5011 shift_this_row[k] = FALSE;
5012 }
5013 else
5014 {
5015 shift_this_row[k] = TRUE;
5016 }
5017 }
5018
5019 /* shift the rows for which a gap was inserted */
5020 for (k = 0; k < dsp->dim; k++)
5021 {
5022 if (!shift_this_row[k])
5023 {
5024 continue;
5025 }
5026 /* shift start for minus strand rows for seg_num only */
5027 if (dsp->strands != NULL
5028 && dsp->strands [seg_num * dsp->dim + k] == Seq_strand_minus
5029 && dsp->starts [seg_num * dsp->dim + k] != -1)
5030 {
5031 dsp->starts [seg_num * dsp->dim + k] -= glip->length;
5032 }
5033 /* shift starts for rows after seg_num */
5034 for (shift_seg = seg_num + 1;
5035 shift_seg < dsp->numseg;
5036 shift_seg++)
5037 {
5038 if (dsp->starts [shift_seg * dsp->dim + k] != -1)
5039 {
5040 if (dsp->strands == NULL
5041 || dsp->strands [shift_seg * dsp->dim + k] != Seq_strand_minus)
5042 {
5043 dsp->starts [shift_seg * dsp->dim + k] += glip->length;
5044 }
5045 else
5046 {
5047 dsp->starts [shift_seg * dsp->dim + k] -= glip->length;
5048 }
5049 }
5050 }
5051 }
5052 }
5053 cumulative_offset += glip->length;
5054 }
5055 shift_this_row = MemFree (shift_this_row);
5056 }
5057
5058 static void
5059 AdjustAlignmentsBasedOnGapLocations
5060 (ValNodePtr adjusted_bsp_list,
5061 ValNodePtr gaps,
5062 SeqAlignPtr salp,
5063 Uint2 entityID)
5064 {
5065 ValNodePtr align_annot_list, annot_vnp, bsp_vnp;
5066 SeqAnnotPtr sanp, adjustment_sanp = NULL;
5067 BioseqPtr bsp;
5068
5069 for (bsp_vnp = adjusted_bsp_list; bsp_vnp != NULL; bsp_vnp = bsp_vnp->next)
5070 {
5071 bsp = (BioseqPtr)(bsp_vnp->data.ptrvalue);
5072 align_annot_list = FindAlignSeqAnnotsForBioseq (bsp);
5073 for (annot_vnp = align_annot_list;
5074 annot_vnp != NULL;
5075 annot_vnp = annot_vnp->next)
5076 {
5077 sanp = annot_vnp->data.ptrvalue;
5078 if (sanp != NULL && sanp->type == 2)
5079 {
5080 if (sanp->data == salp)
5081 {
5082 adjustment_sanp = sanp;
5083 }
5084 else
5085 {
5086 sanp->data = AdjustOneAlignmentForOneBioseqBasedOnGapLocations
5087 (sanp->data, bsp, gaps, salp);
5088 }
5089 }
5090 }
5091 align_annot_list = ValNodeFree (align_annot_list);
5092 }
5093
5094 if (adjustment_sanp != NULL)
5095 {
5096 ShiftAlignmentForGapLocations (adjustment_sanp, gaps);
5097 }
5098
5099 CleanupAlignmentsAfterConversion (adjusted_bsp_list, entityID);
5100 }
5101
5102
5103 static void
5104 ConvertRawBioseqToDelta
5105 (BioseqPtr bsp,
5106 ValNodePtr gaps,
5107 SeqAlignPtr salp,
5108 Int4 aln_row)
5109
5110 {
5111 CharPtr bases;
5112 Int4 len;
5113 ValNodePtr seq_ext;
5114 SeqLitPtr slp;
5115 IntFuzzPtr ifp;
5116 ValNodePtr gap_vnp;
5117 GapLocInfoPtr glip;
5118 Int4 orig_seq_offset;
5119 Char tmp_ch;
5120 Int4 gap_start;
5121 SeqEntryPtr sep;
5122
5123 if (bsp == NULL || bsp->repr != Seq_repr_raw || ISA_aa (bsp->mol)
5124 || gaps == NULL)
5125 {
5126 return;
5127 }
5128 if (salp != NULL && aln_row < 1)
5129 {
5130 return;
5131 }
5132
5133 bases = GetSequenceByBsp (bsp);
5134 if (bases == NULL) return;
5135
5136 seq_ext = NULL;
5137 len = 0;
5138 orig_seq_offset = 0;
5139
5140 for (gap_vnp = gaps; gap_vnp != NULL; gap_vnp = gap_vnp->next)
5141 {
5142 glip = (GapLocInfoPtr) gap_vnp->data.ptrvalue;
5143 if (glip == NULL)
5144 {
5145 continue;
5146 }
5147 gap_start = glip->start_pos;
5148 /* remap for alignment coordinates if desired */
5149 if (salp != NULL)
5150 {
5151 gap_start = AlnMgr2MapSeqAlignToBioseq(salp, gap_start, aln_row);
5152 }
5153 if (gap_start < 1 || gap_start > bsp->length)
5154 {
5155 continue;
5156 }
5157
5158 /* add data since last gap */
5159 if (gap_start - orig_seq_offset > 0) {
5160 slp = (SeqLitPtr) MemNew (sizeof (SeqLit));
5161 if (slp != NULL)
5162 {
5163 slp->length = gap_start - orig_seq_offset;
5164 ValNodeAddPointer (&(seq_ext), (Int2) 2, (Pointer) slp);
5165 slp->seq_data = (SeqDataPtr) BSNew (slp->length);
5166 slp->seq_data_type = Seq_code_iupacna;
5167 tmp_ch = bases [gap_start];
5168 bases [gap_start] = 0;
5169 AddBasesToByteStore ((ByteStorePtr) slp->seq_data, bases + orig_seq_offset);
5170 bases [gap_start] = tmp_ch;
5171 len += slp->length;
5172 orig_seq_offset += slp->length;
5173 }
5174 }
5175
5176 /* add gap */
5177 slp = (SeqLitPtr) MemNew (sizeof (SeqLit));
5178 if (slp != NULL)
5179 {
5180 ValNodeAddPointer ((ValNodePtr PNTR) &(seq_ext), (Int2) 2, (Pointer) slp);
5181 if (glip->is_known)
5182 {
5183 slp->length = glip->length;
5184 }
5185 else
5186 {
5187 ifp = IntFuzzNew ();
5188 ifp->choice = 4;
5189 slp->fuzz = ifp;
5190 slp->length = 100;
5191 }
5192 len += slp->length;
5193 }
5194 if (glip->replace)
5195 {
5196 orig_seq_offset += glip->length;
5197 }
5198 }
5199
5200 /* add remaining data after last gap to end */
5201 if (bsp->length - orig_seq_offset > 0) {
5202 slp = (SeqLitPtr) MemNew (sizeof (SeqLit));
5203 if (slp != NULL)
5204 {
5205 slp->length = bsp->length - orig_seq_offset;
5206 ValNodeAddPointer (&(seq_ext), (Int2) 2, (Pointer) slp);
5207 slp->seq_data = (SeqDataPtr) BSNew (slp->length);
5208 slp->seq_data_type = Seq_code_iupacna;
5209 AddBasesToByteStore ((ByteStorePtr) slp->seq_data, bases + orig_seq_offset);
5210 len += slp->length;
5211 }
5212 }
5213
5214 MemFree (bases);
5215
5216 bsp->seq_data = SeqDataFree (bsp->seq_data, bsp->seq_data_type);
5217 bsp->seq_data_type = 0;
5218 bsp->repr = Seq_repr_delta;
5219 bsp->seq_ext_type = 4;
5220 bsp->seq_ext = seq_ext;
5221 bsp->length = len;
5222
5223 BioseqPack (bsp);
5224
5225 /* now adjust features for insertion */
5226 orig_seq_offset = 0;
5227 for (gap_vnp = gaps; gap_vnp != NULL; gap_vnp = gap_vnp->next)
5228 {
5229 glip = (GapLocInfoPtr) gap_vnp->data.ptrvalue;
5230 if (glip == NULL)
5231 {
5232 continue;
5233 }
5234 gap_start = glip->start_pos;
5235 /* remap for alignment coordinates if desired */
5236 if (salp != NULL)
5237 {
5238 gap_start = AlnMgr2MapSeqAlignToBioseq(salp, gap_start, aln_row);
5239 }
5240 if (gap_start < 1 || gap_start > bsp->length)
5241 {
5242 continue;
5243 }
5244 if (!glip->replace) {
5245 AdjustFeaturesForInsertion (bsp, bsp->id,
5246 gap_start + orig_seq_offset,
5247 glip->length,
5248 FALSE);
5249 } else if (glip->length != 100 && !glip->is_known) {
5250 AdjustFeaturesForInsertion (bsp, bsp->id, gap_start + orig_seq_offset,
5251 100 - glip->length,
5252 FALSE);
5253 }
5254 orig_seq_offset += glip->length;
5255 }
5256
5257 sep = GetTopSeqEntryForEntityID (bsp->idx.entityID);
5258
5259 VisitFeaturesInSep (sep, (Pointer) Sequin_GlobalAlign2Seq, AdjustCDSLocationsForUnknownGapsCallback);
5260
5261 }
5262
5263 typedef struct converttodelta
5264 {
5265 ValNodePtr location_list;
5266 ValNodePtr affected_bioseq_list;
5267 SeqAlignPtr salp;
5268 } ConvertToDeltaData, PNTR ConvertToDeltaPtr;
5269
5270 static void ConvertBioseqToDeltaWithSequenceGapList (BioseqPtr bsp, Pointer userdata)
5271 {
5272 ConvertToDeltaPtr ctdp;
5273
5274 if (bsp == NULL || bsp->id == NULL
5275 || bsp->repr != Seq_repr_raw || ISA_aa (bsp->mol)
5276 || userdata == NULL)
5277 {
5278 return;
5279 }
5280 ctdp = (ConvertToDeltaPtr) userdata;
5281 if (ctdp->location_list == NULL)
5282 {
5283 return;
5284 }
5285 ValNodeAddPointer (&(ctdp->affected_bioseq_list), 0, bsp);
5286 ConvertRawBioseqToDelta (bsp, ctdp->location_list, NULL, -1);
5287 }
5288
5289 static void ConvertBioseqToDeltaWithAlignmentGapList (BioseqPtr bsp, Pointer userdata)
5290 {
5291 Int4 aln_row = -1;
5292 SeqIdPtr sip, sip_next;
5293 SeqAlignPtr salp;
5294 ConvertToDeltaPtr ctdp;
5295 ValNodePtr annot_list;
5296 SeqAnnotPtr sanp;
5297
5298 if (bsp == NULL || bsp->id == NULL
5299 || bsp->repr != Seq_repr_raw || ISA_aa (bsp->mol)
5300 || userdata == NULL)
5301 {
5302 return;
5303 }
5304 ctdp = (ConvertToDeltaPtr) userdata;
5305 if (ctdp->location_list == NULL)
5306 {
5307 return;
5308 }
5309
5310 annot_list = FindAlignSeqAnnotsForBioseq (bsp);
5311 if (annot_list == NULL || annot_list->data.ptrvalue == NULL)
5312 {
5313 return;
5314 }
5315 sanp = (SeqAnnotPtr) annot_list->data.ptrvalue;
5316 if (sanp->type != 2 || sanp->data == NULL)
5317 {
5318 return;
5319 }
5320
5321 salp = sanp->data;
5322 ctdp->salp = salp;
5323
5324 /* Make sure alignment is indexed.
5325 */
5326 AlnMgr2IndexSeqAlignEx(salp, FALSE);
5327
5328 sip = bsp->id;
5329
5330 while (sip != NULL && aln_row == -1)
5331 {
5332 sip_next = sip->next;
5333 sip->next = NULL;
5334 aln_row = AlnMgr2GetFirstNForSip (salp, sip);
5335 sip->next = sip_next;
5336 sip = sip_next;
5337 }
5338
5339 ValNodeAddPointer (&(ctdp->affected_bioseq_list), 0, bsp);
5340 ConvertRawBioseqToDelta (bsp, ctdp->location_list, salp, aln_row);
5341 }
5342
5343 static int LIBCALLBACK SortGapLocations (VoidPtr ptr1, VoidPtr ptr2)
5344
5345 {
5346 ValNodePtr vnp1, vnp2;
5347 GapLocInfoPtr glip1, glip2;
5348
5349 if (ptr1 != NULL && ptr2 != NULL) {
5350 vnp1 = *((ValNodePtr PNTR) ptr1);
5351 vnp2 = *((ValNodePtr PNTR) ptr2);
5352 if (vnp1 != NULL && vnp2 != NULL) {
5353 glip1 = (GapLocInfoPtr) vnp1->data.ptrvalue;
5354 glip2 = (GapLocInfoPtr) vnp2->data.ptrvalue;
5355 if (glip1 != NULL && glip2 != NULL) {
5356 if (glip1->start_pos < glip2->start_pos)
5357 {
5358 return -1;
5359 }
5360 else if (glip1->start_pos > glip2->start_pos)
5361 {
5362 return 1;
5363 }
5364 else if (glip1->length < glip2->length)
5365 {
5366 return -1;
5367 }
5368 else if (glip1->length > glip2->length)
5369 {
5370 return 1;
5371 }
5372 else
5373 {
5374 return 0;
5375 }
5376 }
5377 }
5378 }
5379 return 0;
5380 }
5381
5382 static Pointer DeltaLocToData (DialoG d)
5383 {
5384 TagListPtr tlp;
5385 ValNodePtr result_list = NULL, vnp;
5386 CharPtr str;
5387 Int4 start_pos, len;
5388 Boolean is_known, replace;
5389 GapLocInfoPtr glip;
5390
5391 tlp = (TagListPtr) GetObjectExtra (d);
5392
5393 if (tlp == NULL) return NULL;
5394
5395 for (vnp = tlp->vnp;
5396 vnp != NULL;
5397 vnp = vnp->next)
5398 {
5399 str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 0);
5400 if (StringHasNoText (str))
5401 {
5402 str = MemFree (str);
5403 }
5404 else
5405 {
5406 start_pos = atoi (str) - 1;
5407 str = MemFree (str);
5408 if (start_pos > 0)
5409 {
5410 str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 3);
5411 if (StringICmp (str, "1") == 0)
5412 {
5413 replace = TRUE;
5414 }
5415 else
5416 {
5417 replace = FALSE;
5418 }
5419 str = MemFree (str);
5420
5421 str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 1);
5422 if (StringICmp (str, "1") == 0)
5423 {
5424 str = MemFree (str);
5425 is_known = TRUE;
5426 len = -1;
5427 str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 2);
5428 if (!StringHasNoText (str))
5429 {
5430 len = atoi (str);
5431 }
5432 str = MemFree (str);
5433 if (len < 1)
5434 {
5435 Message (MSG_ERROR, "Must supply a length greater than zero for gaps of known length!");
5436 result_list = ValNodeFreeData (result_list);
5437 return NULL;
5438 }
5439 }
5440 else
5441 {
5442 str = MemFree (str);
5443 is_known = FALSE;
5444 if (replace)
5445 {
5446 str = ExtractTagListColumn ((CharPtr) vnp->data.ptrvalue, 2);
5447 if (StringHasNoText (str))
5448 {
5449 len = 100;
5450 }
5451 else
5452 {
5453 len = atoi (str);
5454 if (len < 1)
5455 {
5456 len = 100;
5457 }
5458 }
5459 str = MemFree (str);
5460 }
5461 else
5462 {
5463 len = 100;
5464 }
5465 }
5466
5467 glip = (GapLocInfoPtr) MemNew (sizeof (GapLocInfoData));
5468 if (glip != NULL)
5469 {
5470 glip->start_pos = start_pos;
5471 glip->is_known = is_known;
5472 glip->length = len;
5473 glip->replace = replace;
5474 ValNodeAddPointer (&result_list, 0, glip);
5475 }
5476 }
5477 }
5478 }
5479
5480 result_list = ValNodeSort (result_list, SortGapLocations);
5481 return result_list;
5482 }
5483
5484 static void DoConvertRawToDeltaWithGapLocations (ButtoN b)
5485 {
5486 DeltaConversionPtr dcp;
5487 SeqEntryPtr sep;
5488 ConvertToDeltaData ctdd;
5489
5490 dcp = (DeltaConversionPtr) GetObjectExtra (b);
5491 if (dcp == NULL)
5492 {
5493 return;
5494 }
5495
5496 sep = GetTopSeqEntryForEntityID (dcp->input_entityID);
5497 if (sep == NULL)
5498 {
5499 return;
5500 }
5501
5502 ctdd.location_list = DialogToPointer (dcp->gap_locations);
5503 if (ctdd.location_list == NULL)
5504 {
5505 Message (MSG_ERROR, "Must supply valid gap locations!");
5506 return;
5507 }
5508 ctdd.affected_bioseq_list = NULL;
5509 ctdd.salp = NULL;
5510
5511 Hide (dcp->form);
5512 WatchCursor ();
5513 Update ();
5514 if (dcp->coord_grp == NULL || GetValue (dcp->coord_grp) == 1)
5515 {
5516 VisitBioseqsInSep (sep, &ctdd, ConvertBioseqToDeltaWithSequenceGapList);
5517 }
5518 else
5519 {
5520 VisitBioseqsInSep (sep, &ctdd, ConvertBioseqToDeltaWithAlignmentGapList);
5521 }
5522
5523 AdjustAlignmentsBasedOnGapLocations (ctdd.affected_bioseq_list,
5524 ctdd.location_list, ctdd.salp,
5525 dcp->input_entityID);
5526
5527 ctdd.affected_bioseq_list = ValNodeFree (ctdd.affected_bioseq_list);
5528 ctdd.location_list = ValNodeFreeData (ctdd.location_list);
5529
5530 if (GetStatus (dcp->adjust_CDS_locations))
5531 {
5532 VisitFeaturesInSep (sep, (Pointer)Sequin_GlobalAlign2Seq, AdjustCDSLocationsForUnknownGapsCallback);
5533 DeleteMarkedObjects (dcp->input_entityID, 0, NULL);
5534 }
5535
5536 ObjMgrSetDirtyFlag (dcp->input_entityID, TRUE);
5537 ObjMgrSendMsg (OM_MSG_UPDATE, dcp->input_entityID, 0, 0);
5538 Remove (dcp->form);
5539 ArrowCursor ();
5540 Update ();
5541 }
5542
5543 extern DialoG CreateTagListDialogEx (GrouP h, Uint2 rows, Uint2 cols,
5544 Int2 spacing, Uint2Ptr types,
5545 Uint2Ptr textWidths, EnumFieldAssocPtr PNTR alists,
5546 Boolean useBar, Boolean noExtend,
5547 ToDialogFunc tofunc, FromDialogFunc fromfunc);
5548
5549 static void ConvertRawToDeltaWithGapLocations (IteM i)
5550 {
5551 BaseFormPtr bfp;
5552 DeltaConversionPtr dcp;
5553 WindoW w;
5554 GrouP h, p, c;
5555 ButtoN b;
5556 PrompT p1, p2, p3;
5557 SeqEntryPtr sep;
5558 RecT r1, r2;
5559 TagListPtr tlp;
5560
5561 #ifdef WIN_MAC
5562 bfp = currentFormDataPtr;
5563 #else
5564 bfp = GetObjectExtra (i);
5565 #endif
5566 if (bfp == NULL) return;
5567
5568 dcp = (DeltaConversionPtr) MemNew (sizeof (DeltaConversionData));
5569 if (dcp == NULL) return;
5570
5571 dcp->input_entityID = bfp->input_entityID;
5572 sep = GetTopSeqEntryForEntityID (dcp->input_entityID);
5573 if (sep == NULL)
5574 {
5575 return;
5576 }
5577
5578 if (!ContinueWithDeltaSequences (sep))
5579 {
5580 return;
5581 }
5582 if (!ContinueWithSequencesInAlignments (sep))
5583 {
5584 return;
5585 }
5586
5587 w = FixedWindow (-50, -33, -10, -10, "Convert Raw Sequence to Delta Sequence", StdCloseWindowProc);
5588 SetObjectExtra (w, dcp, StdCleanupFormProc);
5589 dcp->form = (ForM) w;
5590 h = HiddenGroup (w, -1, 0, NULL);
5591 SetGroupSpacing (h, 10, 10);
5592
5593 p = HiddenGroup (h, 3, 0, NULL);
5594 p1 = StaticPrompt (p, "Start", 0, dialogTextHeight, programFont, 'c');
5595 p2 = StaticPrompt (p, "Type", 0, dialogTextHeight, programFont, 'c');
5596 p3 = StaticPrompt (p, "Length", 0, dialogTextHeight, programFont, 'c');
5597 dcp->gap_locations = CreateTagListDialogEx (h, 4, 4, 2,
5598 deltaconversionedittypes,
5599 deltaconversionedit_widths,
5600 deltaconversionedit_alists,
5601 TRUE, FALSE, NULL, DeltaLocToData);
5602 dcp->coord_grp = NormalGroup (h, 2, 0, "Coordinates", programFont, NULL);
5603 RadioButton (dcp->coord_grp, "Sequence");
5604 RadioButton (dcp->coord_grp, "Alignment");
5605 SetValue (dcp->coord_grp, 1);
5606 if (!SeqEntryHasAligns (dcp->input_entityID, sep))
5607 {
5608 Disable (dcp->coord_grp);
5609 }
5610
5611 dcp->adjust_CDS_locations = CheckBox (h, "Adjust CDS locations for gaps", NULL);
5612 SetStatus (dcp->adjust_CDS_locations, TRUE);
5613
5614 c = HiddenGroup (h, 2, 0, NULL);
5615 b = PushButton (c, "Accept", DoConvertRawToDeltaWithGapLocations);
5616 SetObjectExtra (b, dcp, NULL);
5617 PushButton (c, "Cancel", StdCancelButtonProc);
5618
5619 AlignObjects (ALIGN_CENTER, (HANDLE) dcp->gap_locations,
5620 (HANDLE) dcp->coord_grp,
5621 (HANDLE) dcp->adjust_CDS_locations,
5622 (HANDLE) c,
5623 NULL);
5624
5625 tlp = GetObjectExtra (dcp->gap_locations);
5626 if (tlp != NULL)
5627 {
5628 ObjectRect (tlp->control [0], &r1);
5629 ObjectRect (p1, &r2);
5630 r2.left = r1.left;
5631 r2.right = r1.right;
5632 SetPosition (p1, &r2);
5633
5634 ObjectRect (tlp->control [1], &r1);
5635 ObjectRect (p2, &r2);
5636 r2.left = r1.left;
5637 r2.right = r1.right;
5638 SetPosition (p2, &r2);
5639
5640 ObjectRect (tlp->control [2], &r1);
5641 ObjectRect (p3, &r2);
5642 r2.left = r1.left;
5643 r2.right = r1.right;
5644 SetPosition (p3, &r2);
5645 }
5646 RealizeWindow (w);
5647
5648 Show (w);
5649 Update ();
5650 }
5651
5652 typedef struct xrefgenedata {
5653 GeneRefPtr grp;
5654 SeqLocPtr slp;
5655 Boolean pseudo;
5656 } XrefGeneData, PNTR XrefGenePtr;
5657
5658 static Boolean XrefToGeneCallback (GatherContextPtr gcp)
5659
5660 {
5661 GeneRefPtr grp;
5662 SeqFeatXrefPtr PNTR last;
5663 SeqFeatXrefPtr next;
5664 SeqFeatPtr sfp;
5665 ValNodePtr PNTR vnpp;
5666 XrefGenePtr xgp;
5667 SeqFeatXrefPtr xref;
5668
5669 if (gcp->thistype != OBJ_SEQFEAT) return TRUE;
5670 vnpp = (ValNodePtr PNTR) gcp->userdata;
5671 if (vnpp == NULL) return TRUE;
5672 sfp = (SeqFeatPtr) gcp->thisitem;
5673 if (sfp == NULL || sfp->location == NULL) return TRUE;
5674 if (sfp->xref == NULL) return TRUE;
5675 grp = NULL;
5676 last = (SeqFeatXrefPtr PNTR) &(sfp->xref);
5677 xref = sfp->xref;
5678 while (xref != NULL) {
5679 next = xref->next;
5680 if (xref->data.choice == SEQFEAT_GENE) {
5681 *last = next;
5682 xref->next = NULL;
5683 grp = (GeneRefPtr) xref->data.value.ptrvalue;
5684 xref->data.value.ptrvalue = NULL;
5685 SeqFeatXrefFree (xref);
5686 } else {
5687 last = &(xref->next);
5688 }
5689 xref = next;
5690 }
5691 if (grp == NULL) return TRUE;
5692 xgp = MemNew (sizeof (XrefGeneData));
5693 if (xgp == NULL) return TRUE;
5694 xgp->grp = grp;
5695 xgp->slp = AsnIoMemCopy (sfp->location, (AsnReadFunc) SeqLocAsnRead,
5696 (AsnWriteFunc) SeqLocAsnWrite);
5697 /* if feature is pseudo, gene created from xref on feature should also be pseudo */
5698 xgp->pseudo = sfp->pseudo;
5699
5700 ValNodeAddPointer (vnpp, 0, xgp);
5701 return TRUE;
5702 }
5703
5704 static void XrefToGene (IteM i)
5705
5706 {
5707 BaseFormPtr bfp;
5708 BioseqPtr bsp;
5709 Uint2 entityID = 0;
5710 GatherScope gs;
5711 ValNodePtr head;
5712 SeqEntryPtr nsep;
5713 SeqFeatPtr sfp;
5714 SelStructPtr ssp;
5715 ValNodePtr vnp;
5716 XrefGenePtr xgp;
5717
5718 head = NULL;
5719 ssp = ObjMgrGetSelected ();
5720 if (ssp == NULL) {
5721 #ifdef WIN_MAC
5722 bfp = currentFormDataPtr;
5723 #else
5724 bfp = GetObjectExtra (i);
5725 #endif
5726 if (bfp == NULL) {
5727 Message (MSG_ERROR, "XrefToGene error");
5728 return;
5729 }
5730 entityID = bfp->input_entityID;
5731 MemSet ((Pointer) (&gs), 0, sizeof (GatherScope));
5732 gs.seglevels = 1;
5733 MemSet((Pointer)(gs.ignore), (int)(TRUE), (size_t)(OBJ_MAX * sizeof(Boolean)));
5734 gs.ignore[OBJ_BIOSEQ] = FALSE;
5735 gs.ignore[OBJ_BIOSEQ_SEG] = FALSE;
5736 gs.ignore[OBJ_SEQANNOT] = FALSE;
5737 gs.ignore[OBJ_SEQFEAT] = FALSE;
5738 GatherEntity (bfp->input_entityID, (Pointer) &head, XrefToGeneCallback, &gs);
5739 } else {
5740 entityID = ssp->entityID;
5741 if (ssp->itemtype != OBJ_SEQFEAT) {
5742 Message (MSG_ERROR, "Feature must be selected");
5743 return;
5744 }
5745 GatherItem (ssp->entityID, ssp->itemID, ssp->itemtype, (Pointer) &head, XrefToGeneCallback);
5746 }
5747 if (head == NULL || entityID == 0) return;
5748 for (vnp = head; vnp != NULL; vnp = vnp->next) {
5749 xgp = (XrefGenePtr) vnp->data.ptrvalue;
5750 if (xgp != NULL) {
5751 bsp = GetBioseqGivenSeqLoc (xgp->slp, entityID);
5752 if (bsp != NULL) {
5753 nsep = SeqMgrGetSeqEntryForData (bsp);
5754 if (! ExtendGene (xgp->grp, nsep, xgp->slp)) {
5755 sfp = CreateNewFeature (nsep, NULL, SEQFEAT_GENE, NULL);
5756 if (sfp != NULL) {
5757 sfp->data.value.ptrvalue = (Pointer) xgp->grp;
5758 xgp->grp = NULL;
5759 sfp->location = SeqLocFree (sfp->location);
5760 sfp->location = xgp->slp;
5761 xgp->slp = NULL;
5762 sfp->pseudo = xgp->pseudo;
5763 }
5764 }
5765 }
5766 GeneRefFree (xgp->grp);
5767 SeqLocFree (xgp->slp);
5768 }
5769 }
5770 ValNodeFreeData (head);
5771 ObjMgrSetDirtyFlag (entityID, TRUE);
5772 ObjMgrSendMsg (OM_MSG_UPDATE, entityID, 0, 0);
5773 }
5774
5775 static void GeneToXrefCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
5776
5777 {
5778 BaseFormPtr bfp;
5779 BioseqPtr bsp;
5780 BioseqSetPtr bssp;
5781 SeqFeatPtr gene;
5782 GeneRefPtr grp;
5783 SeqFeatPtr sfp;
5784 SeqAnnotPtr sap;
5785 SeqFeatXrefPtr xref;
5786
5787 if (sep == NULL) return;
5788 bfp = (BaseFormPtr) mydata;
5789 if (bfp == NULL) return;
5790 if (IS_Bioseq (sep)) {
5791 bsp = (BioseqPtr) sep->data.ptrvalue;
5792 sap = bsp->annot;
5793 } else if (IS_Bioseq_set (sep)) {
5794 bssp = (BioseqSetPtr) sep->data.ptrvalue;
5795 sap = bssp->annot;
5796 } else return;
5797 while (sap != NULL) {
5798 if (sap->type == 1) {
5799 sfp = (SeqFeatPtr) sap->data;
5800 while (sfp != NULL) {
5801 if (sfp->data.choice != SEQFEAT_GENE) {
5802 FindGeneAndProtForCDS (bfp->input_entityID, sfp, &gene, NULL);
5803 if (gene != NULL) {
5804 grp = (GeneRefPtr) gene->data.value.ptrvalue;
5805 if (grp != NULL) {
5806 xref = SeqFeatXrefNew ();
5807 if (xref != NULL) {
5808 xref->data.choice = SEQFEAT_GENE;
5809 xref->data.value.ptrvalue = AsnIoMemCopy ((Pointer) grp,
5810 (AsnReadFunc) GeneRefAsnRead,
5811 (AsnWriteFunc) GeneRefAsnWrite);
5812 xref->next = sfp->xref;
5813 sfp->xref = xref;
5814 }
5815 }
5816 }
5817 }
5818 sfp = sfp->next;
5819 }
5820 }
5821 sap = sap->next;
5822 }
5823 }
5824
5825 static void GeneToXref (IteM i)
5826
5827 {
5828 BaseFormPtr bfp;
5829 SeqEntryPtr sep;
5830
5831 #ifdef WIN_MAC
5832 bfp = currentFormDataPtr;
5833 #else
5834 bfp = GetObjectExtra (i);
5835 #endif
5836 if (bfp == NULL) {
5837 Message (MSG_ERROR, "GeneToXref error");
5838 return;
5839 }
5840 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
5841 if (sep == NULL) return;
5842 SeqEntryExplore (sep, (Pointer) bfp, GeneToXrefCallback);
5843 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
5844 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
5845 }
5846
5847 typedef struct featurefieldforgenechoice
5848 {
5849 Int4 first_choice;
5850 Int4 second_choice;
5851 CharPtr field_txt;
5852 } FeatureFieldForGeneChoiceData, PNTR FeatureFieldForGeneChoicePtr;
5853
5854 static FeatureFieldForGeneChoicePtr FeatureFieldForGeneChoiceFree (FeatureFieldForGeneChoicePtr fcp)
5855 {
5856 if (fcp != NULL)
5857 {
5858 fcp->field_txt = MemFree (fcp->field_txt);
5859 fcp = MemFree (fcp);
5860 }
5861 return fcp;
5862 }
5863
5864 typedef struct featuretogene
5865 {
5866 FEATURE_FORM_BLOCK
5867
5868 DialoG *gene_src_dlg_list;
5869 Int4 num_choices;
5870 ValNodePtr feature_choices;
5871
5872 TexT label_txt;
5873 PopuP genechoice;
5874 GrouP qual_caps_grp;
5875 DialoG feature_dlg;
5876 DialoG filter_grp;
5877 DialoG accept_cancel;
5878
5879 ButtoN single_interval_btn;
5880 ButtoN selected_features_only_btn;
5881
5882 Boolean single_interval;
5883 FeatureFieldForGeneChoicePtr fcp;
5884
5885 } FeatureToGeneData, PNTR FeatureToGenePtr;
5886
5887 static Int4 GetGeneSrcDlgIndex (FeatureToGenePtr fgp)
5888 {
5889 ValNodePtr vnp, check_vnp;
5890 Int4 rval = -1, i;
5891
5892 if (fgp == NULL) return -1;
5893
5894 vnp = DialogToPointer (fgp->feature_dlg);
5895 if (vnp == NULL)
5896 {
5897 return -1;
5898 }
5899
5900 check_vnp = fgp->feature_choices;
5901 i = 0;
5902 while (check_vnp != NULL && check_vnp->choice != vnp->choice)
5903 {
5904 check_vnp = check_vnp->next;
5905 i++;
5906 }
5907 if (check_vnp != NULL)
5908 {
5909 rval = i;
5910 }
5911 ValNodeFreeData (vnp);
5912 return rval;
5913 }
5914
5915 static void EnableFeatureToGeneControls (Pointer userdata)
5916 {
5917 Int4 i;
5918 FeatureToGenePtr fgp;
5919 FeatureFieldForGeneChoicePtr fcp;
5920
5921 fgp = (FeatureToGenePtr) userdata;
5922 if (fgp == NULL) return;
5923 Disable (fgp->qual_caps_grp);
5924 Disable (fgp->genechoice);
5925
5926 i = GetGeneSrcDlgIndex (fgp);
5927 if (i >= 0)
5928 {
5929 fcp = (FeatureFieldForGeneChoicePtr) DialogToPointer (fgp->gene_src_dlg_list [i]);
5930 if (fcp != NULL)
5931 {
5932 if (fcp->first_choice > 1 || !StringHasNoText (fcp->field_txt))
5933 {
5934 Enable (fgp->qual_caps_grp);
5935 Enable (fgp->genechoice);
5936 }
5937 fcp = FeatureFieldForGeneChoiceFree (fcp);
5938 }
5939 }
5940 }
5941
5942 static void EnableFeatureToGeneControlsPopup (PopuP p)
5943 {
5944 FeatureToGenePtr fgp;
5945
5946 fgp = (FeatureToGenePtr) GetObjectExtra (p);
5947 EnableFeatureToGeneControls (fgp);
5948 }
5949
5950 static void EnableFeatureToGeneControlsText (TexT t)
5951 {
5952 FeatureToGenePtr fgp;
5953
5954 fgp = (FeatureToGenePtr) GetObjectExtra (t);
5955 EnableFeatureToGeneControls (fgp);
5956
5957 }
5958
5959 typedef struct featurefieldforgenedlg
5960 {
5961 DIALOG_MESSAGE_BLOCK
5962 PopuP first_choice_popup;
5963 PopuP second_choice_popup;
5964 TexT label_txt;
5965 Nlm_ChangeNotifyProc change_notify;
5966 Pointer change_userdata;
5967 } FeatureFieldForGeneDlgData, PNTR FeatureFieldForGeneDlgPtr;
5968
5969 static void ResetFeatureFieldForGeneDlg (FeatureFieldForGeneDlgPtr dlg)
5970 {
5971 if (dlg == NULL)
5972 {
5973 return;
5974 }
5975
5976 SetValue (dlg->first_choice_popup, 1);
5977 SafeSetValue (dlg->second_choice_popup, 1);
5978 SetTitle (dlg->label_txt, "");
5979 }
5980
5981 static void FeatureFieldForGeneToDialog (DialoG d, Pointer userdata)
5982 {
5983 FeatureFieldForGeneDlgPtr dlg;
5984 FeatureFieldForGeneChoicePtr data;
5985
5986 dlg = (FeatureFieldForGeneDlgPtr) GetObjectExtra (d);
5987 data = (FeatureFieldForGeneChoicePtr) userdata;
5988 if (dlg == NULL)
5989 {
5990 return;
5991 }
5992 ResetFeatureFieldForGeneDlg (dlg);
5993 if (data == NULL)
5994 {
5995 return;
5996 }
5997 if (data->first_choice > 0)
5998 {
5999 SetValue (dlg->first_choice_popup, data->first_choice);
6000 }
6001 if (data->second_choice > 0)
6002 {
6003 SafeSetValue (dlg->second_choice_popup, data->second_choice);
6004 }
6005 if (!StringHasNoText (data->field_txt))
6006 {
6007 SetTitle (dlg->label_txt, data->field_txt);
6008 }
6009 }
6010
6011 static Pointer FeatureFieldForGeneFromDialog (DialoG d)
6012 {
6013 FeatureFieldForGeneDlgPtr dlg;
6014 FeatureFieldForGeneChoicePtr data;
6015
6016 dlg = (FeatureFieldForGeneDlgPtr) GetObjectExtra (d);
6017 if (dlg == NULL)
6018 {
6019 return NULL;
6020 }
6021 data = (FeatureFieldForGeneChoicePtr) MemNew (sizeof (FeatureFieldForGeneChoiceData));
6022 if (data != NULL)
6023 {
6024 data->first_choice = GetValue (dlg->first_choice_popup);
6025 if (dlg->second_choice_popup != NULL)
6026 {
6027 data->second_choice = GetValue (dlg->second_choice_popup);
6028 }
6029 else
6030 {
6031 data->second_choice = 0;
6032 }
6033 if (TextHasNoText (dlg->label_txt))
6034 {
6035 data->field_txt = NULL;
6036 }
6037 else
6038 {
6039 data->field_txt = SaveStringFromText (dlg->label_txt);
6040 }
6041 }
6042 return data;
6043 }
6044
6045 static void FeatureFieldForGeneChange (FeatureFieldForGeneDlgPtr dlg)
6046 {
6047 if (dlg == NULL)
6048 {
6049 return;
6050 }
6051 if (GetValue (dlg->first_choice_popup) > 1)
6052 {
6053 SafeEnable (dlg->second_choice_popup);
6054 }
6055 else
6056 {
6057 SafeDisable (dlg->second_choice_popup);
6058 }
6059 if (dlg->change_notify != NULL)
6060 {
6061 (dlg->change_notify) (dlg->change_userdata);
6062 }
6063 }
6064
6065 static void FeatureFieldForGeneChangePopup (PopuP p)
6066 {
6067 FeatureFieldForGeneDlgPtr dlg;
6068
6069 dlg = (FeatureFieldForGeneDlgPtr) GetObjectExtra (p);
6070 FeatureFieldForGeneChange (dlg);
6071 }
6072
6073 static void FeatureFieldForGeneChangeText (TexT t)
6074 {
6075 FeatureFieldForGeneDlgPtr dlg;
6076
6077 dlg = (FeatureFieldForGeneDlgPtr) GetObjectExtra (t);
6078 FeatureFieldForGeneChange (dlg);
6079 }
6080
6081 static PopuP MakeFieldChoicePopup (GrouP g, Int4 featdef_choice, Pointer extradata)
6082 {
6083 PopuP p;
6084
6085 p = PopupList (g, TRUE, FeatureFieldForGeneChangePopup);
6086 SetObjectExtra (p, extradata, NULL);
6087
6088 if (featdef_choice == FEATDEF_CDS
6089 || featdef_choice == FEATDEF_tRNA
6090 || featdef_choice == FEATDEF_rRNA
6091 || featdef_choice == FEATDEF_misc_RNA
6092 || featdef_choice == FEATDEF_mRNA)
6093 {
6094 PopupItem (p, "None");
6095 PopupItem (p, "Comment");
6096 PopupItem (p, "Product");
6097 }
6098 else
6099 {
6100 PopupItem (p, "None");
6101 PopupItem (p, "Comment");
6102 }
6103 SetValue (p, 1);
6104 return p;
6105 }
6106
6107 static DialoG
6108 FeatureFieldForGeneDialog
6109 (GrouP parent,
6110 Int4 featdef_choice,
6111 Nlm_ChangeNotifyProc change_notify,
6112 Pointer change_userdata)
6113 {
6114 FeatureFieldForGeneDlgPtr dlg;
6115 GrouP p;
6116
6117 dlg = (FeatureFieldForGeneDlgPtr) MemNew (sizeof (FeatureFieldForGeneDlgData));
6118 if (dlg == NULL)
6119 {
6120 return NULL;
6121 }
6122
6123 p = NormalGroup (parent, 2, 0, "Select qualifier to use in gene", NULL, NULL);
6124 SetObjectExtra (p, dlg, StdCleanupExtraProc);
6125
6126 dlg->dialog = (DialoG) p;
6127 dlg->todialog = FeatureFieldForGeneToDialog;
6128 dlg->fromdialog = FeatureFieldForGeneFromDialog;
6129 dlg->dialogmessage = NULL;
6130 dlg->testdialog = NULL;
6131 dlg->change_notify = change_notify;
6132 dlg->change_userdata = change_userdata;
6133
6134 StaticPrompt (p, "1st Choice", 0, 0, programFont, 'c');
6135 dlg->first_choice_popup = MakeFieldChoicePopup (p, featdef_choice, dlg);
6136
6137 if (featdef_choice == FEATDEF_CDS
6138 || featdef_choice == FEATDEF_tRNA
6139 || featdef_choice == FEATDEF_rRNA
6140 || featdef_choice == FEATDEF_misc_RNA
6141 || featdef_choice == FEATDEF_mRNA)
6142 {
6143 StaticPrompt (p, "2nd Choice", 0, 0, programFont, 'c');
6144 dlg->second_choice_popup = MakeFieldChoicePopup (p, featdef_choice, dlg);
6145 Disable (dlg->second_choice_popup);
6146 }
6147 else
6148 {
6149 dlg->second_choice_popup = NULL;
6150 }
6151
6152 StaticPrompt (p, "Use this string:", 0, 0, programFont, 'c');
6153 dlg->label_txt = DialogText (p, "", 10, FeatureFieldForGeneChangeText);
6154 SetObjectExtra (dlg->label_txt, dlg, NULL);
6155
6156 return (DialoG) p;
6157 }
6158
6159 static CharPtr GetGeneSrcChoice (SeqFeatPtr sfp, Int4 choice)
6160 {
6161 CharPtr src_txt = NULL;
6162 RnaRefPtr rrp;
6163 SeqMgrFeatContext fcontext;
6164
6165 if (sfp == NULL || choice < 2)
6166 {
6167 return NULL;
6168 }
6169
6170 if (choice == 2 && !StringHasNoText (sfp->comment))
6171 {
6172 src_txt = StringSave (sfp->comment);
6173 }
6174 else if (choice == 3)
6175 {
6176 if (sfp->idx.subtype == FEATDEF_tRNA)
6177 {
6178 sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL,
6179 0, 0, sfp, &fcontext);
6180 if (!StringHasNoText (fcontext.label))
6181 {
6182 src_txt = (CharPtr) MemNew (StringLen (fcontext.label) + 6);
6183 if (src_txt != NULL)
6184 {
6185 sprintf (src_txt, "tRNA-%s", fcontext.label);
6186 }
6187 }
6188 }
6189 else if (sfp->idx.subtype == FEATDEF_CDS
6190 || sfp->idx.subtype == FEATDEF_mRNA)
6191 {
6192 sfp = SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL,
6193 0, 0, sfp, &fcontext);
6194 if (!StringHasNoText (fcontext.label))
6195 {
6196 src_txt = StringSave (fcontext.label);
6197 }
6198 }
6199 else if (sfp->data.choice == SEQFEAT_RNA)
6200 {
6201 rrp = (RnaRefPtr) (sfp->data.value.ptrvalue);
6202 if (rrp != NULL && rrp->ext.choice == 1
6203 && !StringHasNoText (rrp->ext.value.ptrvalue))
6204 {
6205 src_txt = StringSave (rrp->ext.value.ptrvalue);
6206 }
6207 }
6208 }
6209 return src_txt;
6210 }
6211
6212 static CharPtr GetGeneSrc (SeqFeatPtr sfp, FeatureFieldForGeneChoicePtr fcp)
6213 {
6214 CharPtr src_txt = NULL;
6215
6216 if (sfp == NULL || fcp == NULL)
6217 {
6218 return NULL;
6219 }
6220
6221 src_txt = GetGeneSrcChoice (sfp, fcp->first_choice);
6222 if (src_txt == NULL)
6223 {
6224 src_txt = GetGeneSrcChoice (sfp, fcp->second_choice);
6225 }
6226 if (src_txt == NULL && !StringHasNoText (fcp->field_txt))
6227 {
6228 src_txt = StringSave (fcp->field_txt);
6229 }
6230 return src_txt;
6231 }
6232
6233 static Boolean IsBioseqmRNA (BioseqPtr bsp)
6234 {
6235 SeqDescrPtr sdp;
6236 SeqMgrDescContext context;
6237 MolInfoPtr mip;
6238
6239 sdp = SeqMgrGetNextDescriptor (bsp, NULL, Seq_descr_molinfo, &context);
6240 if (sdp == NULL || sdp->data.ptrvalue == NULL)
6241 {
6242 return FALSE;
6243 }
6244
6245 mip = (MolInfoPtr) sdp->data.ptrvalue;
6246 if (mip->biomol == 3)
6247 {
6248 return TRUE;
6249 }
6250 return FALSE;
6251 }
6252
6253 static void FeatureToGeneCallback (SeqFeatPtr sfp, Pointer userdata, FilterSetPtr fsp)
6254 {
6255 SeqFeatPtr gene, overlap_gene;
6256 GeneRefPtr grp;
6257 Boolean partial5, partial3;
6258 FeatureToGenePtr fgp;
6259 CharPtr gene_val = NULL;
6260 Int4 i;
6261 BioseqPtr bsp;
6262 CharPtr cp;
6263 SeqLocPtr gene_location;
6264
6265 if (sfp == NULL || userdata == NULL) return;
6266 fgp = (FeatureToGenePtr) userdata;
6267
6268 if (SeqMgrGetGeneXref (sfp) != NULL) return;
6269
6270 bsp = BioseqFindFromSeqLoc (sfp->location);
6271 if (bsp == NULL) return;
6272
6273 gene_location = SeqLocMerge (bsp, sfp->location, NULL, fgp->single_interval, FALSE, FALSE);
6274 if (gene_location == NULL) return;
6275
6276 overlap_gene = SeqMgrGetOverlappingGene (sfp->location, NULL);
6277 if (overlap_gene != NULL && SeqLocCompare (gene_location, overlap_gene->location) == SLC_A_EQ_B)
6278 {
6279 gene_location = SeqLocFree (gene_location);
6280 return;
6281 }
6282
6283 if (IsBioseqmRNA (bsp))
6284 {
6285 gene_location = SeqLocFree (gene_location);
6286 gene_location = SeqLocIntNew (0, bsp->length - 1,
6287 SeqLocStrand (sfp->location),
6288 SeqIdFindBest (bsp->id, 0));
6289 }
6290
6291 gene_val = GetGeneSrc (sfp, fgp->fcp);
6292
6293 if (gene_val != NULL)
6294 {
6295 /* apply capitalization */
6296 switch (GetValue (fgp->qual_caps_grp))
6297 {
6298 case 1:
6299 /* do nothing, leave capitalization as is */
6300 break;
6301 case 2:
6302 /* capitalize first letter */
6303 gene_val [0] = toupper (gene_val[0]);
6304 break;
6305 case 3:
6306 /* capitalize all letters */
6307 for (cp = gene_val; *cp != 0; cp++)
6308 {
6309 *cp = toupper (*cp);
6310 }
6311 break;
6312 }
6313 }
6314
6315 gene = SeqFeatNew ();
6316 if (gene == NULL) return;
6317
6318 grp = GeneRefNew ();
6319 if (grp == NULL) return;
6320 i = GetValue (fgp->genechoice);
6321 switch (i)
6322 {
6323 case 1:
6324 grp->locus = gene_val;
6325 break;
6326 case 2:
6327 grp->locus_tag = gene_val;
6328 break;
6329 case 3:
6330 grp->desc = gene_val;
6331 break;
6332 case 4:
6333 grp->allele = gene_val;
6334 break;
6335 default:
6336 gene->comment = gene_val;
6337 break;
6338 }
6339
6340 gene->data.choice = SEQFEAT_GENE;
6341 gene->data.value.ptrvalue = (Pointer) grp;
6342 gene->location = gene_location;
6343 CheckSeqLocForPartial (sfp->location, &partial5, &partial3);
6344 SetSeqLocPartial (gene->location, partial5, partial3);
6345 gene->partial = sfp->partial;
6346 gene->next = sfp->next;
6347 sfp->next = gene;
6348 }
6349
6350 static Boolean FeatureToGeneAccept (Pointer userdata)
6351 {
6352 FeatureToGenePtr fgp;
6353 SeqEntryPtr sep;
6354 SelStructPtr sel;
6355 SeqFeatPtr sfp;
6356 SeqMgrFeatContext fcontext;
6357 FilterSetPtr fsp;
6358 Int4 i, featdef_choice;
6359 ValNodePtr vnp;
6360
6361 fgp = (FeatureToGenePtr) userdata;
6362 if (fgp == NULL) return FALSE;
6363
6364 vnp = DialogToPointer (fgp->feature_dlg);
6365 if (vnp == NULL)
6366 {
6367 return FALSE;
6368 }
6369 featdef_choice = vnp->choice;
6370 vnp = ValNodeFreeData (vnp);
6371
6372 i = GetGeneSrcDlgIndex (fgp);
6373 if (i < 0)
6374 {
6375 return FALSE;
6376 }
6377
6378 fgp->fcp = DialogToPointer (fgp->gene_src_dlg_list [i]);
6379
6380 fsp = DialogToPointer (fgp->filter_grp);
6381
6382 sep = GetTopSeqEntryForEntityID (fgp->input_entityID);
6383 if (sep == NULL) return FALSE;
6384 fgp->single_interval = GetStatus (fgp->single_interval_btn);
6385 if (GetStatus (fgp->selected_features_only_btn))
6386 {
6387 sel = ObjMgrGetSelected ();
6388 while (sel != NULL)
6389 {
6390 if (sel->itemtype == OBJ_SEQFEAT)
6391 {
6392 sfp = SeqMgrGetDesiredFeature (sel->entityID, NULL, sel->itemID, 0, NULL, &fcontext);
6393 if (sfp != NULL)
6394 {
6395 FeatureToGeneCallback (sfp, fgp, NULL);
6396 }
6397 }
6398 sel = sel->next;
6399 }
6400 }
6401 else
6402 {
6403 OperateOnSeqEntryConstrainedObjects (sep, fsp, FeatureToGeneCallback,
6404 NULL, 0, featdef_choice, 0, fgp);
6405 }
6406
6407 FilterSetFree (fsp);
6408 fgp->fcp = FeatureFieldForGeneChoiceFree (fgp->fcp);
6409
6410 ObjMgrSetDirtyFlag (fgp->input_entityID, TRUE);
6411 ObjMgrSendMsg (OM_MSG_UPDATE, fgp->input_entityID, 0, 0);
6412 return TRUE;
6413 }
6414
6415 static void ChangeGeneFeatureSelection (Pointer userdata)
6416 {
6417 FeatureToGenePtr fgp;
6418 Int4 i;
6419
6420 fgp = (FeatureToGenePtr) userdata;
6421 if (fgp == NULL)
6422 {
6423 return;
6424 }
6425
6426 for (i = 0; i < fgp->num_choices; i++)
6427 {
6428 Hide (fgp->gene_src_dlg_list [i]);
6429 }
6430
6431 i = GetGeneSrcDlgIndex (fgp);
6432
6433 if (i < 0)
6434 {
6435 DisableAcceptCancelDialogAccept (fgp->accept_cancel);
6436 }
6437 else
6438 {
6439 EnableAcceptCancelDialogAccept (fgp->accept_cancel);
6440 Show (fgp->gene_src_dlg_list [i]);
6441 }
6442 EnableFeatureToGeneControls (fgp);
6443 }
6444
6445 static void CleanupFeatureToGeneForm (GraphiC g, VoidPtr data)
6446 {
6447 FeatureToGenePtr fgp;
6448
6449 fgp = (FeatureToGenePtr) data;
6450 if (fgp != NULL)
6451 {
6452 fgp->feature_choices = ValNodeFreeData (fgp->feature_choices);
6453 MemFree (fgp);
6454 }
6455 }
6456
6457 static void FeatureToGeneClearText (Pointer userdata)
6458 {
6459 FeatureToGenePtr fgp;
6460 Int4 j;
6461 FilterSetPtr fsp;
6462 FeatureFieldForGeneChoicePtr fcp;
6463
6464 fgp = (FeatureToGenePtr) userdata;
6465 if (fgp == NULL)
6466 {
6467 return;
6468 }
6469
6470 for (j = 0; j < fgp->num_choices; j++)
6471 {
6472 fcp = (FeatureFieldForGeneChoicePtr) DialogToPointer (fgp->gene_src_dlg_list [j]);
6473 if (fcp != NULL)
6474 {
6475 fcp->field_txt = MemFree (fcp->field_txt);
6476 }
6477 PointerToDialog (fgp->gene_src_dlg_list [j], fcp);
6478 FeatureFieldForGeneChoiceFree (fcp);
6479 }
6480
6481 fsp = (FilterSetPtr) DialogToPointer (fgp->filter_grp);
6482 FilterSetClearText (fsp);
6483 PointerToDialog (fgp->filter_grp, fsp);
6484 FilterSetFree (fsp);
6485 EnableFeatureToGeneControls (fgp);
6486 }
6487
6488 static void FeatureToGeneClear (Pointer userdata)
6489 {
6490 FeatureToGenePtr fgp;
6491 Int4 j;
6492
6493 fgp = (FeatureToGenePtr) userdata;
6494 if (fgp == NULL)
6495 {
6496 return;
6497 }
6498
6499 PointerToDialog (fgp->feature_dlg, NULL);
6500 for (j = 0; j < fgp->num_choices; j++)
6501 {
6502 PointerToDialog (fgp->gene_src_dlg_list [j], NULL);
6503 }
6504 PointerToDialog (fgp->filter_grp, NULL);
6505
6506 SetValue (fgp->qual_caps_grp, 1);
6507 SetValue (fgp->genechoice, 1);
6508 SetStatus (fgp->single_interval_btn, TRUE);
6509 SetStatus (fgp->selected_features_only_btn, FALSE);
6510
6511 ChangeGeneFeatureSelection (fgp);
6512 EnableFeatureToGeneControls (fgp);
6513 }
6514
6515 static void FeatureToGene (IteM i)
6516 {
6517 BaseFormPtr bfp;
6518 FeatureToGenePtr fgp;
6519 WindoW w;
6520 Int4 j;
6521 GrouP h, k, m, n;
6522 ValNodePtr vnp;
6523 SeqEntryPtr sep;
6524
6525 #ifdef WIN_MAC
6526 bfp = currentFormDataPtr;
6527 #else
6528 bfp = GetObjectExtra (i);
6529 #endif
6530 if (bfp == NULL) {
6531 Message (MSG_ERROR, "Feature to Gene error");
6532 return;
6533 }
6534
6535 fgp = (FeatureToGenePtr) MemNew (sizeof (FeatureToGeneData));
6536 if (fgp == NULL) return;
6537 fgp->input_entityID = bfp->input_entityID;
6538 w = FixedWindow (-50, -33, -10, -10, "Feature to Gene", StdCloseWindowProc);
6539 SetObjectExtra (w, fgp, CleanupFeatureToGeneForm);
6540 fgp->form = (ForM) w;
6541
6542 h = HiddenGroup (w, -1, 0, NULL);
6543 SetGroupSpacing (h, 10, 10);
6544
6545 sep = GetTopSeqEntryForEntityID(bfp->input_entityID);
6546 fgp->feature_dlg = FeatureSelectionDialogEx (h, FALSE, sep, ChangeGeneFeatureSelection, fgp);
6547 k = HiddenGroup (h, 0, 0, NULL);
6548
6549 fgp->feature_choices = BuildFeatureDialogList (TRUE, sep);
6550 fgp->num_choices = ValNodeLen (fgp->feature_choices);
6551 fgp->gene_src_dlg_list = (DialoG *) MemNew (fgp->num_choices * sizeof (DialoG));
6552
6553 for (j = 0, vnp = fgp->feature_choices;
6554 j < fgp->num_choices && vnp != NULL;
6555 j++, vnp = vnp->next)
6556 {
6557 fgp->gene_src_dlg_list [j] = FeatureFieldForGeneDialog (k, vnp->choice,
6558 EnableFeatureToGeneControls,
6559 fgp);
6560 }
6561
6562 fgp->qual_caps_grp = NormalGroup (h, 3, 0,
6563 "Capitalization for gene", NULL, NULL);
6564 RadioButton (fgp->qual_caps_grp, "As is");
6565 RadioButton (fgp->qual_caps_grp, "Capitalize first initial");
6566 RadioButton (fgp->qual_caps_grp, "Capitalize all");
6567 SetValue (fgp->qual_caps_grp, 1);
6568 Disable (fgp->qual_caps_grp);
6569 m = HiddenGroup (h, 2, 0, NULL);
6570 StaticPrompt (m, "Select gene qualifier to populate", 0,0, programFont, 'c');
6571 fgp->genechoice = PopupList (m, TRUE, NULL);
6572 PopupItem (fgp->genechoice, "locus");
6573 PopupItem (fgp->genechoice, "locus_tag");
6574 PopupItem (fgp->genechoice, "gene description");
6575 PopupItem (fgp->genechoice, "allele");
6576 PopupItem (fgp->genechoice, "gene comment");
6577 SetValue (fgp->genechoice, 1);
6578 Disable (fgp->genechoice);
6579
6580 n = HiddenGroup (h, 2, 0, NULL);
6581 fgp->single_interval_btn = CheckBox (n, "Create gene with single interval location", NULL);
6582 SetStatus (fgp->single_interval_btn, TRUE);
6583 fgp->selected_features_only_btn = CheckBox (n, "Only create genes for selected features", NULL);
6584 SetStatus (fgp->selected_features_only_btn, FALSE);
6585
6586 fgp->filter_grp = FilterGroup (h, TRUE, FALSE, FALSE, FALSE, FALSE, "Where feature field contains");
6587
6588 fgp->accept_cancel = AcceptCancelDialog (h, FeatureToGeneAccept, NULL, FeatureToGeneClear, FeatureToGeneClearText, (Pointer)fgp, w);
6589
6590 AlignObjects (ALIGN_CENTER, (HANDLE) fgp->feature_dlg,
6591 (HANDLE) k,
6592 (HANDLE) fgp->qual_caps_grp,
6593 (HANDLE) m,
6594 (HANDLE) n,
6595 (HANDLE) fgp->filter_grp,
6596 (HANDLE) fgp->accept_cancel,
6597 NULL);
6598
6599 RealizeWindow (w);
6600 Show (w);
6601 Update ();
6602 ChangeGeneFeatureSelection (fgp);
6603 }
6604
6605
6606 typedef struct featuretocdsform
6607 {
6608 FEATURE_FORM_BLOCK
6609 PopuP feature_choice;
6610
6611 DialoG gene_field;
6612 DialoG exon_field;
6613 DialoG mrna_field;
6614 GrouP qual_caps_grp;
6615 TexT append_text;
6616 ButtoN accept_btn;
6617 ButtoN fuse_multiple_btn;
6618 ButtoN include_utr_btn;
6619
6620 Int4 featdef_choice;
6621 ValNodePtr gene_field_list;
6622 ValNodePtr mrna_field_list;
6623 ValNodePtr exon_field_list;
6624 CharPtr append_string;
6625 Int4 caps_choice;
6626 Boolean fuse_multiple;
6627 Boolean makemRNA;
6628 Boolean include_utr;
6629 SeqEntryPtr sep;
6630 LogInfoData lid;
6631
6632 } FeatureToCDSFormData, PNTR FeatureToCDSFormPtr;
6633
6634 #define FEATURE_TO_CDS_GENE 1
6635 #define FEATURE_TO_CDS_MRNA 2
6636 #define FEATURE_TO_CDS_EXON 3
6637
6638 static void EnableFeatureToCDSControls (Pointer data)
6639 {
6640 FeatureToCDSFormPtr fp;
6641 Int4 feature_choice;
6642 Boolean need_name_string = FALSE;
6643 ValNodePtr missing = NULL;
6644 CharPtr cp;
6645
6646 fp = (FeatureToCDSFormPtr) data;
6647 if (fp == NULL)
6648 {
6649 return;
6650 }
6651 Enable (fp->accept_btn);
6652 feature_choice = GetValue (fp->feature_choice);
6653 if (feature_choice == FEATURE_TO_CDS_GENE)
6654 {
6655 missing = TestDialog (fp->gene_field);
6656 if (missing != NULL)
6657 {
6658 need_name_string = TRUE;
6659 ValNodeFree (missing);
6660 }
6661 }
6662 else if (feature_choice == FEATURE_TO_CDS_EXON)
6663 {
6664 missing = DialogToPointer (fp->exon_field);
6665 if (missing == NULL)
6666 {
6667 need_name_string = TRUE;
6668 }
6669 ValNodeFree (missing);
6670 }
6671 else if (feature_choice == FEATURE_TO_CDS_MRNA)
6672 {
6673 missing = DialogToPointer (fp->mrna_field);
6674 if (missing == NULL)
6675 {
6676 need_name_string = TRUE;
6677 }
6678 ValNodeFree (missing);
6679 }
6680
6681 if (need_name_string)
6682 {
6683 Disable (fp->qual_caps_grp);
6684 cp = SaveStringFromText (fp->append_text);
6685 if (StringHasNoText (cp))
6686 {
6687 Disable (fp->accept_btn);
6688 }
6689 MemFree (cp);
6690 }
6691 else
6692 {
6693 Enable (fp->qual_caps_grp);
6694 }
6695 }
6696
6697 static void EnableFeatureToCDSControlsText (TexT t)
6698 {
6699 FeatureToCDSFormPtr fp;
6700
6701 fp = (FeatureToCDSFormPtr) GetObjectExtra (t);
6702 EnableFeatureToCDSControls (fp);
6703 }
6704
6705 static void ChangeFeatureToCDS (PopuP p)
6706 {
6707 FeatureToCDSFormPtr fp;
6708 Int4 feature_choice;
6709
6710 fp = (FeatureToCDSFormPtr) GetObjectExtra (p);
6711 if (fp != NULL)
6712 {
6713 feature_choice = GetValue (fp->feature_choice);
6714 if (feature_choice == FEATURE_TO_CDS_GENE)
6715 {
6716 Show (fp->gene_field);
6717 Hide (fp->mrna_field);
6718 Hide (fp->exon_field);
6719 }
6720 else if (feature_choice == FEATURE_TO_CDS_MRNA)
6721 {
6722 Show (fp->mrna_field);
6723 Hide (fp->gene_field);
6724 Hide (fp->exon_field);
6725 }
6726 else
6727 {
6728 Show (fp->exon_field);
6729 Hide (fp->mrna_field);
6730 Hide (fp->gene_field);
6731 }
6732 }
6733 EnableFeatureToCDSControls (fp);
6734 }
6735
6736 static void CleanupFeatureToCDSPage (GraphiC g, VoidPtr data)
6737 {
6738 FeatureToCDSFormPtr fp;
6739
6740 fp = (FeatureToCDSFormPtr) data;
6741 if (fp != NULL)
6742 {
6743 fp->append_string = MemFree (fp->append_string);
6744 fp->gene_field_list = ValNodeFree (fp->gene_field_list);
6745 fp->mrna_field_list = ValNodeFree (fp->mrna_field_list);
6746 fp->exon_field_list = ValNodeFree (fp->exon_field_list);
6747 MemFree (fp);
6748 }
6749 }
6750
6751 static void LogFeatureToCDSNoProtein (FeatureToCDSFormPtr fp, CharPtr feature_label, SeqIdPtr sip)
6752 {
6753 Char id [41];
6754
6755 if (fp == NULL || fp->lid.fp == NULL || sip == NULL) return;
6756
6757 id [0] = '\0';
6758 SeqIdWrite (SeqIdFindBest (sip, 0), id, PRINTID_FASTA_LONG, sizeof (id) - 1);
6759
6760 if (StringHasNoText (feature_label))
6761 {
6762 fprintf (fp->lid.fp, "No protein added for unlabeled feature on sequence %s\n", id);
6763 }
6764 else
6765 {
6766 fprintf (fp->lid.fp, "No protein added for %s on sequence %s\n", feature_label, id);
6767 }
6768 fp->lid.data_in_log = TRUE;
6769 }
6770
6771 static CharPtr GetNewProteinName (SeqFeatPtr sfp, FeatureToCDSFormPtr fp)
6772 {
6773 SeqMgrFeatContext context;
6774 CharPtr prot_name_src = NULL;
6775 CharPtr protName = NULL;
6776 Int4 prot_len;
6777 CharPtr cp;
6778
6779 if (sfp == NULL || fp == NULL || sfp->idx.subtype != fp->featdef_choice)
6780 {
6781 return NULL;
6782 }
6783
6784 if (SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL,
6785 0, 0, sfp, &context) == NULL) return NULL;
6786
6787 /* determine the new protein name */
6788 if (fp->featdef_choice == FEATDEF_GENE)
6789 {
6790 prot_name_src = GetGeneFieldString (sfp, fp->gene_field_list, NULL);
6791 }
6792 else if (fp->featdef_choice == FEATDEF_mRNA)
6793 {
6794 prot_name_src = GetmRNAFieldString (sfp, fp->mrna_field_list, NULL);
6795 }
6796 else if (fp->featdef_choice == FEATDEF_exon)
6797 {
6798 prot_name_src = GetExonFieldString (sfp, fp->exon_field_list);
6799 }
6800 else if (fp->featdef_choice == FEATDEF_CDS)
6801 {
6802 prot_name_src = GetCDSFieldString(sfp, fp->mrna_field_list, NULL);
6803 }
6804
6805 if (StringHasNoText (prot_name_src) && StringHasNoText (fp->append_string))
6806 {
6807 return NULL;
6808 }
6809
6810 prot_len = StringLen (prot_name_src) + StringLen (fp->append_string) + 2;
6811
6812 /* add one to length for terminating null */
6813 protName = (CharPtr) MemNew (prot_len * sizeof (Char));
6814 if (protName == NULL) return NULL;
6815
6816 if (!StringHasNoText (prot_name_src))
6817 {
6818 StringCpy (protName, prot_name_src);
6819 /* apply capitalization */
6820 switch (fp->caps_choice)
6821 {
6822 case 1:
6823 /* do nothing, leave capitalization as is */
6824 break;
6825 case 2:
6826 /* capitalize first letter */
6827 protName [0] = toupper (protName[0]);
6828 break;
6829 case 3:
6830 /* capitalize all letters */
6831 for (cp = protName; *cp != 0; cp++)
6832 {
6833 *cp = toupper (*cp);
6834 }
6835 break;
6836 }
6837 if (!StringHasNoText (fp->append_string))
6838 {
6839 StringCat (protName, " ");
6840 }
6841 }
6842 prot_name_src = MemFree (prot_name_src);
6843 if (!StringHasNoText (fp->append_string))
6844 {
6845 StringCat (protName, fp->append_string);
6846 }
6847 return protName;
6848 }
6849
6850 static SeqFeatPtr MakeCDS(SeqLocPtr location, CharPtr name_str, Uint2 entityID, SeqEntryPtr sep, LogInfoPtr lip)
6851 {
6852 SeqFeatPtr cds, sfp;
6853 Int2 genCode;
6854 CdRegionPtr crp;
6855 ByteStorePtr bs;
6856 BioseqPtr bsp;
6857 SeqEntryPtr psep, nsep, old, topsep;
6858 MolInfoPtr mip;
6859 ProtRefPtr prp;
6860 Char ch;
6861 ValNodePtr descr;
6862 Int2 i;
6863 Boolean partial5, partial3;
6864 CharPtr prot;
6865 CharPtr ptr;
6866 ValNodePtr vnp;
6867
6868 cds = SeqFeatNew ();
6869
6870 CheckSeqLocForPartial (location, &partial5, &partial3);
6871
6872 if (cds == NULL) return NULL;
6873 cds->data.choice = SEQFEAT_CDREGION;
6874
6875 genCode = SeqEntryToGeneticCode (sep, NULL, NULL, 0);
6876 crp = CreateNewCdRgn (1, FALSE, genCode);
6877 if (crp == NULL) {
6878 return NULL;
6879 }
6880
6881 cds->data.value.ptrvalue = (Pointer) crp;
6882 cds->location = SeqLocFree (cds->location);
6883 cds->location = AsnIoMemCopy ((Pointer) location,
6884 (AsnReadFunc) SeqLocAsnRead,
6885 (AsnWriteFunc) SeqLocAsnWrite);
6886 cds->partial = partial5 | partial3;
6887
6888 if (!SetBestFrameByLocation (cds)) {
6889 LogCDSAmbiguousFrame (lip, cds);
6890 }
6891
6892 bs = ProteinFromCdRegionEx (cds, TRUE, FALSE);
6893 if (bs != NULL) {
6894 prot = BSMerge (bs, NULL);
6895 bs = BSFree (bs);
6896 if (prot != NULL) {
6897 ptr = prot;
6898 ch = *ptr;
6899 while (ch != '\0') {
6900 *ptr = TO_UPPER (ch);
6901 ptr++;
6902 ch = *ptr;
6903 }
6904 i = (Int2) StringLen (prot);
6905 if (i > 0 && prot [i - 1] == '*') {
6906 prot [i - 1] = '\0';
6907 }
6908 bs = BSNew (1000);
6909 if (bs != NULL) {
6910 ptr = prot;
6911 BSWrite (bs, (VoidPtr) ptr, (Int4) StringLen (ptr));
6912 }
6913 }
6914 }
6915 bsp = BioseqNew ();
6916 if (bsp == NULL) return NULL;
6917 bsp->repr = Seq_repr_raw;
6918 bsp->mol = Seq_mol_aa;
6919 bsp->seq_data_type = Seq_code_ncbieaa;
6920 bsp->seq_data = (SeqDataPtr) bs;
6921 bsp->length = BSLen (bs);
6922 bs = NULL;
6923 old = SeqEntrySetScope (NULL);
6924 bsp->id = MakeNewProteinSeqId (cds->location, NULL);
6925 SeqMgrAddToBioseqIndex (bsp);
6926 SeqEntrySetScope (old);
6927 psep = SeqEntryNew ();
6928 if (psep != NULL) {
6929 psep->choice = 1;
6930 psep->data.ptrvalue = (Pointer) bsp;
6931 SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) bsp, psep);
6932 mip = MolInfoNew ();
6933 if (mip != NULL) {
6934 mip->biomol = 8;
6935 mip->tech = 8;
6936 if (partial5 && partial3) {
6937 mip->completeness = 5;
6938 } else if (partial5) {
6939 mip->completeness = 3;
6940 } else if (partial3) {
6941 mip->completeness = 4;
6942 }
6943 vnp = CreateNewDescriptor (psep, Seq_descr_molinfo);
6944 if (vnp != NULL) {
6945 vnp->data.ptrvalue = (Pointer) mip;
6946 }
6947 }
6948 descr = ExtractBioSourceAndPubs (sep);
6949 if (IS_Bioseq_set (sep))
6950 {
6951 topsep = sep;
6952 }
6953 else
6954 {
6955 topsep = GetBestTopParentForData (entityID, sep->data.ptrvalue);
6956 }
6957 AddSeqEntryToSeqEntry (topsep, psep, TRUE);
6958 nsep = FindNucSeqEntry (sep);
6959 ReplaceBioSourceAndPubs (sep, descr);
6960 SetSeqFeatProduct (cds, bsp);
6961 prp = CreateNewProtRef (name_str, NULL, NULL, NULL);
6962 sfp = CreateNewFeature (psep, NULL, SEQFEAT_PROT, NULL);
6963 if (sfp != NULL) {
6964 sfp->data.value.ptrvalue = (Pointer) prp;
6965 }
6966 }
6967 return cds;
6968
6969 }
6970
6971
6972 static SeqFeatPtr MakemRNA (SeqLocPtr location, CharPtr protName, SeqEntryPtr sep, Boolean include_utr)
6973 {
6974 SeqFeatPtr sfp;
6975 RnaRefPtr rrp;
6976 Boolean partial5, partial3;
6977
6978 sfp = SeqFeatNew();
6979 rrp = RnaRefNew();
6980 rrp->type = RNA_TYPE_mRNA;
6981 rrp->ext.choice = 1;
6982 rrp->ext.value.ptrvalue = protName;
6983 sfp->data.value.ptrvalue = rrp;
6984 sfp->data.choice = SEQFEAT_RNA;
6985
6986 CheckSeqLocForPartial (location, &partial5, &partial3);
6987 sfp->location = SeqLocFree (sfp->location);
6988 if (include_utr) {
6989 sfp->location = GetmRNALocationFromCDSLocation (location, sfp->idx.entityID);
6990 } else {
6991 sfp->location = AsnIoMemCopy ((Pointer) location,
6992 (AsnReadFunc) SeqLocAsnRead,
6993 (AsnWriteFunc) SeqLocAsnWrite);
6994 }
6995 sfp->partial = partial5 | partial3;
6996
6997 return sfp;
6998 }
6999
7000
7001 static SeqFeatPtr FeatureToCDS (SeqFeatPtr sfp, FeatureToCDSFormPtr fp)
7002
7003 {
7004 SeqFeatPtr cds;
7005 SeqMgrFeatContext context;
7006 CharPtr protName = NULL;
7007 RnaRefPtr rrp;
7008
7009
7010 if (sfp == NULL || fp == NULL || sfp->idx.subtype != fp->featdef_choice)
7011 {
7012 return NULL;
7013 }
7014
7015 if (fp->makemRNA) {
7016 cds = SeqMgrGetOverlappingmRNA (sfp->location, &context);
7017 } else {
7018 cds = SeqMgrGetOverlappingCDS (sfp->location, &context);
7019 }
7020 if (cds != NULL)
7021 {
7022 return NULL;
7023 }
7024
7025 if (SeqMgrGetDesiredFeature (sfp->idx.entityID, NULL,
7026 0, 0, sfp, &context) == NULL)
7027 {
7028 return NULL;
7029 }
7030
7031 protName = GetNewProteinName (sfp, fp);
7032 if (protName == NULL)
7033 {
7034 LogFeatureToCDSNoProtein (fp, context.label, SeqLocId (sfp->location));
7035 return NULL;
7036 }
7037
7038 /* make sure mRNA product name matches CDS protein name */
7039 if (fp->featdef_choice == FEATDEF_mRNA && !fp->makemRNA)
7040 {
7041 rrp = (RnaRefPtr) sfp->data.value.ptrvalue;
7042 if (rrp != NULL)
7043 {
7044 rrp->ext.value.ptrvalue = MemFree (rrp->ext.value.ptrvalue);
7045 rrp->ext.value.ptrvalue = StringSave (protName);
7046 }
7047 }
7048
7049 /* need to remove string */
7050 if (fp->featdef_choice == FEATDEF_GENE)
7051 {
7052 RemoveGeneFieldString (sfp, fp->gene_field_list);
7053 }
7054 else if (fp->featdef_choice == FEATDEF_mRNA)
7055 {
7056 RemovemRNAFieldString (sfp, fp->mrna_field_list);
7057 }
7058 else if (fp->featdef_choice == FEATDEF_exon)
7059 {
7060 RemoveExonFieldString (sfp, fp->exon_field_list);
7061 }
7062 else if (fp->featdef_choice == FEATDEF_CDS)
7063 {
7064 RemoveCDSFieldString (sfp, fp->mrna_field_list);
7065 }
7066
7067 if (fp->makemRNA) {
7068 cds = MakemRNA (sfp->location, protName, fp->sep, fp->include_utr);
7069 } else {
7070 cds = MakeCDS(sfp->location, protName, fp->input_entityID, fp->sep, &(fp->lid));
7071 }
7072
7073 cds->partial = sfp->partial;
7074 cds->next = sfp->next;
7075 sfp->next = cds;
7076
7077 return cds;
7078 }
7079
7080 static void
7081 LogFeatureToCDSMismatchProtein
7082 (FeatureToCDSFormPtr fp,
7083 SeqIdPtr sip)
7084 {
7085 Char id [41];
7086
7087 if (fp == NULL || fp->lid.fp == NULL || sip == NULL) return;
7088
7089 id [0] = '\0';
7090 SeqIdWrite (SeqIdFindBest (sip, 0), id, PRINTID_FASTA_LONG, sizeof (id) - 1);
7091
7092 fprintf (fp->lid.fp, "The protein names generated from features on %s do not match\n", id);
7093
7094 fp->lid.data_in_log = TRUE;
7095 }
7096
7097 extern void LogCDSAmbiguousFrame (LogInfoPtr lip, SeqFeatPtr sfp)
7098 {
7099 CharPtr loc_str;
7100
7101 if (lip == NULL || lip->fp == NULL || sfp == NULL) {
7102 return;
7103 }
7104
7105 loc_str = SeqLocPrintUseBestID (sfp->location);
7106 fprintf (lip->fp, "Ambiguous frames detected for coding region at %s\n", loc_str);
7107 loc_str = MemFree (loc_str);
7108 lip->data_in_log = TRUE;
7109 }
7110
7111 static void FeatureToCDSBioseqCheckCallback (BioseqPtr bsp, Pointer userdata)
7112
7113 {
7114 FeatureToCDSFormPtr fp;
7115 CharPtr last_prot_name = NULL, new_prot_name;
7116 SeqMgrFeatContext feature_context, cds_context;
7117 SeqFeatPtr sfp, cds;
7118
7119 if (bsp == NULL || userdata == NULL) return;
7120 fp = (FeatureToCDSFormPtr) userdata;
7121 fp->sep = SeqMgrGetSeqEntryForData (bsp);
7122
7123 /* if we are fusing features, find all the features on this Bioseq for
7124 * our type.
7125 */
7126 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &feature_context);
7127 while (sfp != NULL)
7128 {
7129 if (sfp->idx.subtype == fp->featdef_choice)
7130 {
7131 if (fp->makemRNA) {
7132 cds = SeqMgrGetOverlappingmRNA (sfp->location, &cds_context);
7133 } else {
7134 cds = SeqMgrGetOverlappingCDS (sfp->location, &cds_context);
7135 }
7136 if (cds == NULL)
7137 {
7138 new_prot_name = GetNewProteinName (sfp, fp);
7139 if (!fp->fuse_multiple)
7140 {
7141 if (new_prot_name == NULL)
7142 {
7143 LogFeatureToCDSNoProtein (fp, feature_context.label, SeqLocId (sfp->location));
7144 }
7145 }
7146 else if (last_prot_name == NULL && new_prot_name != NULL)
7147 {
7148 if (new_prot_name == NULL)
7149 {
7150 LogFeatureToCDSNoProtein (fp, feature_context.label, SeqLocId (sfp->location));
7151 }
7152 else
7153 {
7154 last_prot_name = new_prot_name;
7155 }
7156 }
7157 else if (new_prot_name == NULL)
7158 {
7159 /* do nothing - will use protein name from prior CDS */
7160 }
7161 else if (StringCmp (last_prot_name, new_prot_name) == 0)
7162 {
7163 /* no conflict */
7164 MemFree (new_prot_name);
7165 }
7166 else
7167 {
7168 LogFeatureToCDSMismatchProtein (fp, SeqLocId (sfp->location));
7169 MemFree (last_prot_name);
7170 last_prot_name = new_prot_name;
7171 }
7172 }
7173 }
7174 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, fp->featdef_choice, &feature_context);
7175 }
7176 }
7177
7178 static void FeatureToCDSBioseqActCallback (BioseqPtr bsp, Pointer userdata)
7179
7180 {
7181 FeatureToCDSFormPtr fp;
7182 SeqFeatPtr first = NULL;
7183 CharPtr new_prot_name;
7184 SeqMgrFeatContext feature_context, cds_context;
7185 SeqFeatPtr sfp, cds;
7186 SeqLocPtr new_cds_location = NULL, slp, tmp_loc;
7187 Boolean first_partial5, first_partial3;
7188 Int4 first_start_pos, first_stop_pos;
7189 Boolean sfp_partial5, sfp_partial3;
7190 Int4 sfp_start_pos, sfp_stop_pos;
7191
7192 if (bsp == NULL || userdata == NULL) return;
7193 fp = (FeatureToCDSFormPtr) userdata;
7194 fp->sep = SeqMgrGetSeqEntryForData (bsp);
7195
7196 /* if we are fusing features, find all the features on this Bioseq for
7197 * our type.
7198 */
7199 sfp = SeqMgrGetNextFeature (bsp, NULL, 0, 0, &feature_context);
7200 while (sfp != NULL)
7201 {
7202 if (sfp->idx.subtype == fp->featdef_choice)
7203 {
7204 if (fp->makemRNA) {
7205 cds = SeqMgrGetOverlappingmRNA (sfp->location, &cds_context);
7206 } else {
7207 cds = SeqMgrGetOverlappingCDS (sfp->location, &cds_context);
7208 }
7209 if (cds == NULL)
7210 {
7211 if (fp->fuse_multiple)
7212 {
7213 if (first == NULL)
7214 {
7215 new_prot_name = GetNewProteinName (sfp, fp);
7216 if (new_prot_name != NULL)
7217 {
7218 first = sfp;
7219 new_cds_location = (SeqLocPtr) AsnIoMemCopy ((Pointer) sfp->location,
7220 (AsnReadFunc) SeqLocAsnRead,
7221 (AsnWriteFunc) SeqLocAsnWrite);
7222 MemFree (new_prot_name);
7223 }
7224 }
7225 else
7226 {
7227 /* preserve partialness of ends */
7228 CheckSeqLocForPartial (new_cds_location, &first_partial5, &first_partial3);
7229 first_start_pos = SeqLocStart (new_cds_location);
7230 first_stop_pos = SeqLocStop (new_cds_location);
7231 CheckSeqLocForPartial (sfp->location, &sfp_partial5, &sfp_partial3);
7232 sfp_start_pos = SeqLocStart (sfp->location);
7233 sfp_stop_pos = SeqLocStop (sfp->location);
7234 if (first_start_pos > sfp_start_pos)
7235 {
7236 first_partial5 = sfp_partial5;
7237 }
7238 if (first_stop_pos < sfp_stop_pos)
7239 {
7240 first_partial3 = sfp_partial3;
7241 }
7242
7243 slp = SeqLocMerge (bsp, sfp->location, new_cds_location, FALSE, TRUE, FALSE);
7244 new_cds_location = SeqLocFree (new_cds_location);
7245 new_cds_location = slp;
7246 SetSeqLocPartial (new_cds_location, first_partial5, first_partial3);
7247 first_start_pos = SeqLocStart (new_cds_location);
7248 first_stop_pos = SeqLocStop (new_cds_location);
7249 }
7250 }
7251 else
7252 {
7253 FeatureToCDS (sfp, fp);
7254 }
7255 }
7256 }
7257 sfp = SeqMgrGetNextFeature (bsp, sfp, 0, fp->featdef_choice, &feature_context);
7258 }
7259 if (fp->fuse_multiple && first != NULL)
7260 {
7261 tmp_loc = first->location;
7262 first->location = new_cds_location;
7263 cds = FeatureToCDS (first, fp);
7264 if (cds != NULL)
7265 {
7266 cds->partial = CheckSeqLocForPartial (cds->location, &first_partial5, &first_partial3);
7267 }
7268 first->location = tmp_loc;
7269 new_cds_location = SeqLocFree (new_cds_location);
7270 }
7271 }
7272
7273 static void FeatureToCDSAccept (ButtoN b)
7274 {
7275 FeatureToCDSFormPtr fp;
7276 Int4 feature_choice;
7277 MsgAnswer ans = ANS_YES;
7278
7279 fp = (FeatureToCDSFormPtr) GetObjectExtra (b);
7280 if (fp == NULL)
7281 {
7282 return;
7283 }
7284
7285 feature_choice = GetValue (fp->feature_choice);
7286 if (feature_choice == FEATURE_TO_CDS_GENE)
7287 {
7288 fp->featdef_choice = FEATDEF_GENE;
7289 fp->gene_field_list = DialogToPointer (fp->gene_field);
7290 }
7291 else if (feature_choice == FEATURE_TO_CDS_MRNA)
7292 {
7293 if (fp->makemRNA) {
7294 fp->featdef_choice = FEATDEF_CDS;
7295 } else {
7296 fp->featdef_choice = FEATDEF_mRNA;
7297 }
7298 fp->mrna_field_list = DialogToPointer (fp->mrna_field);
7299 }
7300 else if (feature_choice == FEATURE_TO_CDS_EXON)
7301 {
7302 fp->featdef_choice = FEATDEF_exon;
7303 fp->exon_field_list = DialogToPointer (fp->exon_field);
7304 }
7305 else
7306 {
7307 return;
7308 }
7309
7310 TmpNam (fp->lid.path);
7311 fp->lid.fp = FileOpen (fp->lid.path, "wb");
7312 if (fp->lid.fp == NULL) return;
7313 fp->lid.display_title = "Name Problems";
7314
7315 Hide (fp->form);
7316 WatchCursor ();
7317 Update ();
7318
7319 fp->sep = GetTopSeqEntryForEntityID (fp->input_entityID);
7320 if (fp->sep == NULL) return;
7321
7322 fp->caps_choice = GetValue (fp->qual_caps_grp);
7323
7324 fp->append_string = JustSaveStringFromText (fp->append_text);
7325
7326 fp->fuse_multiple = GetStatus (fp->fuse_multiple_btn);
7327 if (fp->makemRNA) {
7328 fp->include_utr = GetStatus (fp->include_utr_btn);
7329 }
7330
7331 VisitBioseqsInSep (fp->sep, (Pointer) fp, FeatureToCDSBioseqCheckCallback);
7332
7333 if (ans == ANS_YES)
7334 {
7335 fp->sep = GetTopSeqEntryForEntityID (fp->input_entityID);
7336 VisitBioseqsInSep (fp->sep, (Pointer) fp, FeatureToCDSBioseqActCallback);
7337 }
7338
7339 CloseLog (&(fp->lid));
7340
7341 ArrowCursor ();
7342 Update ();
7343
7344 ObjMgrSetDirtyFlag (fp->input_entityID, TRUE);
7345 ObjMgrSendMsg (OM_MSG_UPDATE, fp->input_entityID, 0, 0);
7346 if (GetStatus (fp->leave_dlg_up)) {
7347 Show (fp->form);
7348 } else {
7349 Remove (fp->form);
7350 }
7351 }
7352
7353 static void FeatureToCDSormRNA (IteM i, Boolean makemRNA)
7354
7355 {
7356 BaseFormPtr bfp;
7357 FeatureToCDSFormPtr fp;
7358 WindoW w;
7359 GrouP h, g, m, c;
7360 CharPtr title, grp_title;
7361
7362 #ifdef WIN_MAC
7363 bfp = currentFormDataPtr;
7364 #else
7365 bfp = GetObjectExtra (i);
7366 #endif
7367 if (bfp == NULL) {
7368 Message (MSG_ERROR, "FeatureToCDS error");
7369 return;
7370 }
7371
7372 fp = (FeatureToCDSFormPtr) MemNew (sizeof (FeatureToCDSFormData));
7373 if (fp == NULL) return;
7374 fp->input_entityID = bfp->input_entityID;
7375 fp->input_itemID = bfp->input_itemID;
7376 fp->input_itemtype = bfp->input_itemtype;
7377
7378 fp->makemRNA = makemRNA;
7379
7380 if (makemRNA) {
7381 title = "Feature to mRNA";
7382 } else {
7383 title = "Feature to CDS";
7384 }
7385 w = FixedWindow (-50, -33, -10, -10, title, StdCloseWindowProc);
7386 SetObjectExtra (w, fp, CleanupFeatureToCDSPage);
7387 fp->form = (ForM) w;
7388
7389 h = HiddenGroup (w, -1, 0, NULL);
7390 SetGroupSpacing (h, 10, 10);
7391
7392 fp->feature_choice = PopupList (h, TRUE, ChangeFeatureToCDS);
7393 PopupItem (fp->feature_choice, "Gene");
7394 if (makemRNA) {
7395 PopupItem (fp->feature_choice, "CDS");
7396 } else {
7397 PopupItem (fp->feature_choice, "mRNA");
7398 }
7399 PopupItem (fp->feature_choice, "exon");
7400 SetValue (fp->feature_choice, FEATURE_TO_CDS_GENE);
7401 SetObjectExtra (fp->feature_choice, fp, NULL);
7402
7403 if (makemRNA) {
7404 grp_title = "Source for new mRNA name";
7405 } else {
7406 grp_title = "Source for new CDS protein name";
7407 }
7408 g = NormalGroup (h, 0, 0, grp_title, NULL, NULL);
7409 fp->gene_field = FeatureFieldChoiceDialog (g, GeneFieldSelectionDialog, TRUE, EnableFeatureToCDSControls, fp);
7410 fp->mrna_field = FeatureFieldChoiceDialog (g, MRNAFieldSelectionDialog, TRUE, EnableFeatureToCDSControls, fp);
7411 fp->exon_field = FeatureFieldChoiceDialog (g, ExonFieldSelectionDialog, TRUE, EnableFeatureToCDSControls, fp);
7412 Hide (fp->mrna_field);
7413 Hide (fp->exon_field);
7414 AlignObjects (ALIGN_CENTER, (HANDLE) fp->gene_field,
7415 (HANDLE) fp->mrna_field,
7416 (HANDLE) fp->exon_field,
7417 NULL);
7418
7419 fp->qual_caps_grp = NormalGroup (h, 3, 0,
7420 "Capitalization for field in name", NULL, NULL);
7421 RadioButton (fp->qual_caps_grp, "As is");
7422 RadioButton (fp->qual_caps_grp, "Capitalize first initial");
7423 RadioButton (fp->qual_caps_grp, "Capitalize all");
7424 SetValue (fp->qual_caps_grp, 1);
7425
7426 m = HiddenGroup (h, 0, 2, NULL);
7427 StaticPrompt (m, "Append text to name", 0, 0, programFont, 'c');
7428 fp->append_text = DialogText (m, "", 14, EnableFeatureToCDSControlsText);
7429 SetObjectExtra (fp->append_text, fp, NULL);
7430
7431 if(makemRNA) {
7432 fp->fuse_multiple_btn = CheckBox (h, "Fuse multiple intervals for new mRNA", NULL);
7433 fp->include_utr_btn = CheckBox (h, "Include UTR regions in mRNA location", NULL);
7434 } else {
7435 fp->fuse_multiple_btn = CheckBox (h, "Fuse multiple intervals for new CDS", NULL);
7436 fp->include_utr_btn = NULL;
7437 }
7438
7439 c = HiddenGroup (h, 4, 0, NULL);
7440 fp->accept_btn = PushButton (c, "Accept", FeatureToCDSAccept);
7441 SetObjectExtra (fp->accept_btn, fp, NULL);
7442 EnableFeatureToCDSControls (fp);
7443
7444 PushButton (c, "Cancel", StdCancelButtonProc);
7445 fp->leave_dlg_up = CheckBox (c, "Leave Dialog Up", NULL);
7446
7447 AlignObjects (ALIGN_CENTER, (HANDLE) fp->feature_choice,
7448 (HANDLE) g,
7449 (HANDLE) fp->qual_caps_grp,
7450 (HANDLE) m,
7451 (HANDLE) fp->fuse_multiple_btn,
7452 (HANDLE) c,
7453 (HANDLE) fp->include_utr_btn,
7454 NULL);
7455
7456 RealizeWindow (w);
7457 Show (w);
7458 Update ();
7459
7460 }
7461
7462 static void FeatureToCds (IteM i)
7463 {
7464 FeatureToCDSormRNA (i, FALSE);
7465 }
7466
7467
7468 static void FeatureTomRNA (IteM i)
7469 {
7470 FeatureToCDSormRNA (i, TRUE);
7471 }
7472
7473
7474 static void AddFeatureToBioseq (SeqFeatPtr sfp, BioseqPtr bsp)
7475
7476 {
7477 SeqFeatPtr prev;
7478 SeqAnnotPtr sap;
7479
7480 if (sfp == NULL || bsp == NULL) return;
7481 sap = bsp->annot;
7482 while (sap != NULL && (sap->name != NULL || sap->desc != NULL || sap->type != 1)) {
7483 sap = sap->next;
7484 }
7485 if (sap == NULL) {
7486 sap = SeqAnnotNew ();
7487 if (sap != NULL) {
7488 sap->type = 1;
7489 sap->next = bsp->annot;
7490 bsp->annot = sap;
7491 }
7492 }
7493 sap = bsp->annot;
7494 if (sap != NULL) {
7495 if (sap->data != NULL) {
7496 prev = sap->data;
7497 while (prev->next != NULL) {
7498 prev = prev->next;
7499 }
7500 prev->next = sfp;
7501 } else {
7502 sap->data = (Pointer) sfp;
7503 }
7504 }
7505 }
7506
7507 static void PackageFeatureCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
7508
7509 {
7510 BaseFormPtr bfp;
7511 BioseqPtr bsp = NULL;
7512 BioseqSetPtr bssp = NULL;
7513 SeqAnnotPtr nextsap;
7514 SeqFeatPtr nextsfp;
7515 Pointer PNTR prevsap;
7516 Pointer PNTR prevsfp;
7517 SeqAnnotPtr sap;
7518 SeqFeatPtr sfp;
7519 BioseqPtr target;
7520
7521 if (sep == NULL || sep->data.ptrvalue == NULL) return;
7522 bfp = (BaseFormPtr) mydata;
7523 if (bfp == NULL) return;
7524 if (IS_Bioseq (sep)) {
7525 bsp = (BioseqPtr) sep->data.ptrvalue;
7526 sap = bsp->annot;
7527 prevsap = (Pointer PNTR) &(bsp->annot);
7528 } else if (IS_Bioseq_set (sep)) {
7529 bssp = (BioseqSetPtr) sep->data.ptrvalue;
7530 sap = bssp->annot;
7531 prevsap = (Pointer PNTR) &(bssp->annot);
7532 } else return;
7533 while (sap != NULL) {
7534 nextsap = sap->next;
7535 if (sap->type == 1) {
7536 sfp = (SeqFeatPtr) sap->data;
7537 prevsfp = (Pointer PNTR) &(sap->data);
7538 while (sfp != NULL) {
7539 nextsfp = sfp->next;
7540 target = GetBioseqGivenSeqLoc (sfp->location, bfp->input_entityID);
7541 if (target != bsp) {
7542 *(prevsfp) = sfp->next;
7543 sfp->next = NULL;
7544 AddFeatureToBioseq (sfp, target);
7545 } else {
7546 prevsfp = (Pointer PNTR) &(sfp->next);
7547 }
7548 sfp = nextsfp;
7549 }
7550 }
7551 if (sap->data == NULL) {
7552 *(prevsap) = sap->next;
7553 sap->next = NULL;
7554 SeqAnnotFree (sap);
7555 } else {
7556 prevsap = (Pointer PNTR) &(sap->next);
7557 }
7558 sap = nextsap;
7559 }
7560 }
7561
7562 static void PackageOnParts (IteM i)
7563
7564 {
7565 BaseFormPtr bfp;
7566 SeqEntryPtr sep;
7567
7568 #ifdef WIN_MAC
7569 bfp = currentFormDataPtr;
7570 #else
7571 bfp = GetObjectExtra (i);
7572 #endif
7573 if (bfp == NULL) return;
7574 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
7575 if (sep == NULL) return;
7576 WatchCursor ();
7577 Update ();
7578 SeqEntryExplore (sep, bfp, PackageFeatureCallback);
7579 ArrowCursor ();
7580 Update ();
7581 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
7582 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
7583 }
7584
7585 static void ForcePackageFeatureCallback (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
7586
7587 {
7588 BaseFormPtr bfp;
7589 BioseqPtr bsp = NULL;
7590 BioseqSetPtr bssp = NULL;
7591 SeqAnnotPtr firstsap;
7592 SeqAnnotPtr nextsap;
7593 SeqFeatPtr nextsfp;
7594 Pointer PNTR prevsap;
7595 Pointer PNTR prevsfp;
7596 SeqAnnotPtr sap;
7597 SeqFeatPtr sfp;
7598 BioseqPtr target;
7599
7600 if (sep == NULL || sep->data.ptrvalue == NULL) return;
7601 bfp = (BaseFormPtr) mydata;
7602 if (bfp == NULL) return;
7603 if (IS_Bioseq (sep)) {
7604 bsp = (BioseqPtr) sep->data.ptrvalue;
7605 sap = bsp->annot;
7606 prevsap = (Pointer PNTR) &(bsp->annot);
7607 } else if (IS_Bioseq_set (sep)) {
7608 bssp = (BioseqSetPtr) sep->data.ptrvalue;
7609 sap = bssp->annot;
7610 prevsap = (Pointer PNTR) &(bssp->annot);
7611 } else return;
7612 firstsap = sap;
7613 while (sap != NULL) {
7614 nextsap = sap->next;
7615 if (sap->type == 1) {
7616 sfp = (SeqFeatPtr) sap->data;
7617 prevsfp = (Pointer PNTR) &(sap->data);
7618 while (sfp != NULL) {
7619 nextsfp = sfp->next;
7620 target = GetBioseqGivenSeqLoc (sfp->location, bfp->input_entityID);
7621 if (target != bsp || sap != firstsap) {
7622 *(prevsfp) = sfp->next;
7623 sfp->next = NULL;
7624 AddFeatureToBioseq (sfp, target);
7625 } else {
7626 prevsfp = (Pointer PNTR) &(sfp->next);
7627 }
7628 sfp = nextsfp;
7629 }
7630 }
7631 if (sap->data == NULL) {
7632 *(prevsap) = sap->next;
7633 sap->next = NULL;
7634 SeqAnnotFree (sap);
7635 } else {
7636 prevsap = (Pointer PNTR) &(sap->next);
7637 }
7638 sap = nextsap;
7639 }
7640 }
7641
7642 static void ForceRepackage (IteM i)
7643
7644 {
7645 BaseFormPtr bfp;
7646 SeqEntryPtr sep;
7647
7648 #ifdef WIN_MAC
7649 bfp = currentFormDataPtr;
7650 #else
7651 bfp = GetObjectExtra (i);
7652 #endif
7653 if (bfp == NULL) return;
7654 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
7655 if (sep == NULL) return;
7656 WatchCursor ();
7657 Update ();
7658 SeqEntryExplore (sep, bfp, ForcePackageFeatureCallback);
7659 ArrowCursor ();
7660 Update ();
7661 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
7662 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
7663 }
7664
7665 static BioseqSetPtr GetParentNPS (BioseqPtr bsp)
7666 {
7667 BioseqSetPtr bssp;
7668
7669 if (bsp == NULL) return NULL;
7670 if (bsp->idx.parenttype != OBJ_BIOSEQSET) return NULL;
7671 bssp = (BioseqSetPtr) bsp->idx.parentptr;
7672 while (bssp != NULL && bssp->_class != BioseqseqSet_class_nuc_prot && bssp->idx.parenttype == OBJ_BIOSEQSET) {
7673 bssp = (BioseqSetPtr) bssp->idx.parentptr;
7674 }
7675 if (bssp->_class == BioseqseqSet_class_nuc_prot) return bssp;
7676 return NULL;
7677 }
7678
7679 static Boolean NucAndProtNotInSameNPS (BioseqPtr nuc, BioseqPtr prt)
7680 {
7681 BioseqSetPtr bssp;
7682
7683 if (nuc == NULL || prt == NULL) return FALSE;
7684 bssp = GetParentNPS (nuc);
7685 if (bssp == NULL) return TRUE;
7686 if (GetParentNPS (prt) != bssp) return TRUE;
7687 return FALSE;
7688 }
7689
7690 typedef struct nppack {
7691 BioseqPtr nuc;
7692 BioseqPtr prt;
7693 } NpPack, PNTR NpPackPtr;
7694
7695 static void PackageProteinsCallback (SeqFeatPtr sfp, Pointer userdata)
7696
7697 {
7698 BioseqSetPtr bssp;
7699 SeqMgrDescContext context;
7700 ValNodePtr PNTR headp;
7701 MolInfoPtr mip;
7702 NpPackPtr npp;
7703 BioseqPtr nuc, prt;
7704 SeqDescrPtr sdp;
7705
7706 if (sfp == NULL || sfp->data.choice != SEQFEAT_CDREGION || sfp->product == NULL) return;
7707 nuc = BioseqFindFromSeqLoc (sfp->location);
7708 prt = BioseqFindFromSeqLoc (sfp->product);
7709 if (nuc == NULL || prt == NULL) return;
7710
7711 headp = (ValNodePtr PNTR) userdata;
7712
7713 /* if CDS location is on genomic nucleotide in genomic product set, bail */
7714
7715 if (nuc->idx.parenttype == OBJ_BIOSEQSET) {
7716 bssp = (BioseqSetPtr) nuc->idx.parentptr;
7717 if (bssp != NULL && bssp->_class == BioseqseqSet_class_gen_prod_set) {
7718 sdp = SeqMgrGetNextDescriptor (nuc, NULL, Seq_descr_molinfo, &context);
7719 if (sdp != NULL) {
7720 mip = (MolInfoPtr) sdp->data.ptrvalue;
7721 if (mip != NULL) {
7722 if (mip->biomol != MOLECULE_TYPE_MRNA) return;
7723 }
7724 }
7725 }
7726 }
7727
7728 if (NucAndProtNotInSameNPS (nuc, prt)) {
7729 npp = (NpPackPtr) MemNew (sizeof (NpPack));
7730 if (npp == NULL) return;
7731 npp->nuc = nuc;
7732 npp->prt = (BioseqPtr) AsnIoMemCopy ((Pointer) prt,
7733 (AsnReadFunc) BioseqAsnRead,
7734 (AsnWriteFunc) BioseqAsnWrite);
7735 ValNodeAddPointer (headp, 0, (Pointer) npp);
7736 prt->idx.deleteme = TRUE;
7737 }
7738 }
7739
7740 static void PackageOnNucs (IteM i)
7741
7742 {
7743 BaseFormPtr bfp;
7744 ValNodePtr descr;
7745 ValNodePtr head = NULL, vnp;
7746 NpPackPtr npp;
7747 BioseqSetPtr nps;
7748 SeqEntryPtr nsep, psep;
7749 BioseqPtr nuc, prt;
7750 SeqEntryPtr sep;
7751
7752 #ifdef WIN_MAC
7753 bfp = currentFormDataPtr;
7754 #else
7755 bfp = GetObjectExtra (i);
7756 #endif
7757 if (bfp == NULL) return;
7758 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
7759 if (sep == NULL) return;
7760 WatchCursor ();
7761 Update ();
7762
7763 VisitFeaturesInSep (sep, &head, PackageProteinsCallback);
7764
7765 DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
7766 SeqMgrClearFeatureIndexes (bfp->input_entityID, NULL);
7767
7768 for (vnp = head; vnp != NULL; vnp = vnp->next) {
7769 npp = (NpPackPtr) vnp->data.ptrvalue;
7770 if (npp == NULL) continue;
7771 nuc = npp->nuc;
7772 prt = npp->prt;
7773 if (nuc == NULL || prt == NULL) continue;
7774 nsep = nuc->seqentry;
7775 nps = GetParentNPS (nuc);
7776 if (nps != NULL) {
7777 nsep = nps->seqentry;
7778 }
7779 psep = SeqEntryNew ();
7780 if (nsep == NULL || psep == NULL) continue;
7781 psep->choice = 1;
7782 psep->data.ptrvalue = (Pointer) prt;
7783 SeqMgrSeqEntry (SM_BIOSEQ, (Pointer) prt, psep);
7784 descr = ExtractBioSourceAndPubs (nsep);
7785 AddSeqEntryToSeqEntry (nsep, psep, TRUE);
7786 ReplaceBioSourceAndPubs (nsep, descr);
7787 AssignIDsInEntity (bfp->input_entityID, 0, NULL);
7788 }
7789 ValNodeFreeData (head);
7790
7791 ArrowCursor ();
7792 Update ();
7793 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
7794 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
7795 }
7796
7797 extern EnumFieldAssoc enum_bond_alist [];
7798 extern EnumFieldAssoc enum_site_alist [];
7799
7800 static Boolean alistBoxUp;
7801 static Boolean alistBoxAccept;
7802 static PopuP alistBoxPopup;
7803
7804 static void AcceptAlistMessage (ButtoN b)
7805
7806 {
7807 alistBoxAccept = TRUE;
7808 alistBoxUp = FALSE;
7809 }
7810
7811 static void CancelAlistMessage (ButtoN b)
7812
7813 {
7814 alistBoxAccept = FALSE;
7815 alistBoxUp = FALSE;
7816 }
7817
7818 extern Boolean AlistMessage (EnumFieldAssocPtr al, UIEnumPtr val, UIEnum dflt, CharPtr mssg)
7819
7820 {
7821 GrouP c;
7822 GrouP g;
7823 PrompT ppt;
7824 WindoW w;
7825
7826 if (al == NULL || val == NULL) return FALSE;
7827 alistBoxUp = TRUE;
7828 alistBoxAccept = FALSE;
7829 w = ModalWindow (-50, -20, -20, -20, NULL);
7830 if (w != NULL) {
7831 g = HiddenGroup (w, -1, 0, NULL);
7832 SetGroupSpacing (g, 10, 10);
7833 ppt = StaticPrompt (g, mssg, 0, 0, programFont, 'c');
7834 alistBoxPopup = PopupList (g, TRUE, NULL);
7835 InitEnumPopup (alistBoxPopup, al, NULL);
7836 SetEnumPopup (alistBoxPopup, al, dflt);
7837 c = HiddenGroup (g, 2, 0, NULL);
7838 DefaultButton (c, "Accept", AcceptAlistMessage);
7839 PushButton (c, "Cancel", CancelAlistMessage);
7840 AlignObjects (ALIGN_CENTER, (HANDLE) ppt, (HANDLE) alistBoxPopup, (HANDLE) c, NULL);
7841 RealizeWindow (w);
7842 Show (w);
7843 Select (w);
7844 while (alistBoxUp) {
7845 ProcessExternalEvent ();
7846 Update ();
7847 }
7848 ProcessAnEvent ();
7849 if (! GetEnumPopup (alistBoxPopup, al, val)) {
7850 alistBoxAccept = FALSE;
7851 }
7852 Remove (w);
7853 }
7854 return alistBoxAccept;
7855 }
7856
7857 static void DefaultMessageProc (ForM f, Int2 mssg)
7858
7859 {
7860 StdEditorProcsPtr sepp;
7861
7862 sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
7863 if (sepp != NULL) {
7864 if (sepp->handleMessages != NULL) {
7865 sepp->handleMessages (f, mssg);
7866 }
7867 }
7868 }
7869
7870 typedef struct multtransformdata {
7871 FEATURE_FORM_BLOCK
7872
7873 Uint1 type;
7874 LisT fromfeatlist;
7875 PopuP siteorbondlist;
7876 Uint1 feattype;
7877 Int4 siteorbondtype;
7878 } MultTransFormData, PNTR MultTransFormPtr;
7879
7880 static void ProcessMultiTrans (SeqEntryPtr sep, Pointer mydata, Int4 index, Int2 indent)
7881
7882 {
7883 BioseqPtr bsp;
7884 BioseqSetPtr bssp;
7885 SeqFeatPtr cds;
7886 MultTransFormPtr mfp;
7887 SeqFeatPtr newsfp;
7888 BioseqPtr pbsp;
7889 SeqEntryPtr psep;
7890 SeqAnnotPtr sap;
7891 SeqBondPtr sbp;
7892 SeqFeatPtr sfp;
7893 SeqIdPtr sip;
7894 SeqLocPtr slp;
7895 SeqPntPtr spp;
7896 Uint1 subtype;
7897
7898 mfp = (MultTransFormPtr) mydata;
7899 if (sep == NULL || mfp == NULL) return;
7900 if (IS_Bioseq (sep)) {
7901 bsp = (BioseqPtr) sep->data.ptrvalue;
7902 sap = bsp->annot;
7903 } else if (IS_Bioseq_set (sep)) {
7904 bssp = (BioseqSetPtr) sep->data.ptrvalue;
7905 sap = bssp->annot;
7906 } else return;
7907 while (sap != NULL) {
7908 if (sap->type == 1) {
7909 sfp = (SeqFeatPtr) sap->data;
7910 while (sfp != NULL) {
7911 subtype = FindFeatDefType (sfp);
7912 if (subtype == mfp->feattype) {
7913 cds = SeqMgrGetOverlappingCDS (sfp->location, NULL);
7914 if (cds != NULL) {
7915 slp = dnaLoc_to_aaLoc (cds, sfp->location, TRUE, NULL, FALSE);
7916 if (slp != NULL) {
7917 pbsp = BioseqFindFromSeqLoc (slp);
7918 if (pbsp != NULL) {
7919 psep = SeqMgrGetSeqEntryForData (pbsp);
7920 if (psep != NULL) {
7921 newsfp = SeqFeatNew ();
7922 if (newsfp != NULL) {
7923 newsfp->data.choice = mfp->type;
7924 if (mfp->type == SEQFEAT_BOND || mfp->type == SEQFEAT_SITE) {
7925 newsfp->data.value.intvalue = (Int4) mfp->siteorbondtype;
7926 } else if (mfp->type == SEQFEAT_REGION) {
7927 newsfp->data.value.ptrvalue = sfp->comment;
7928 sfp->comment = NULL;
7929 }
7930 CreateNewFeature (psep, NULL, mfp->type, newsfp);
7931 newsfp->location = slp;
7932 newsfp->comment = sfp->comment;
7933 sfp->comment = NULL;
7934 SeqFeatDataFree (&sfp->data); /* free duplicate feature data */
7935 sfp->data.choice = SEQFEAT_GENE; /* fake as empty gene, to be removed */
7936 sfp->data.value.ptrvalue = GeneRefNew ();
7937 if (mfp->type == SEQFEAT_BOND) {
7938 if (slp->choice != SEQLOC_BOND) {
7939 sip = SeqLocId (slp);
7940 if (sip != NULL) {
7941 sbp = SeqBondNew ();
7942 if (sbp != NULL) {
7943 slp = ValNodeNew (NULL);
7944 if (slp != NULL) {
7945 slp->choice = SEQLOC_BOND;
7946 slp->data.ptrvalue = (Pointer) sbp;
7947 spp = SeqPntNew ();
7948 if (spp != NULL) {
7949 spp->strand = SeqLocStrand (newsfp->location);
7950 spp->id = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (sip, 0)));
7951 spp->point = SeqLocStart (newsfp->location);
7952 sbp->a = spp;
7953 }
7954 spp = SeqPntNew ();
7955 if (spp != NULL) {
7956 spp->strand = SeqLocStrand (newsfp->location);
7957 spp->id = SeqIdStripLocus (SeqIdDup (SeqIdFindBest (sip, 0)));
7958 spp->point = SeqLocStop (newsfp->location);
7959 sbp->b = spp;
7960 }
7961 newsfp->location = SeqLocFree (newsfp->location);
7962 newsfp->location = slp;
7963 }
7964 }
7965 }
7966 }
7967 }
7968 }
7969 }
7970 }
7971 }
7972 }
7973 }
7974 sfp = sfp->next;
7975 }
7976 }
7977 sap = sap->next;
7978 }
7979 }
7980
7981 static void DoMultiTransform (ButtoN b)
7982
7983 {
7984 UIEnum enumval;
7985 Int2 feattype;
7986 MultTransFormPtr mfp;
7987 SeqEntryPtr sep;
7988 Int2 siteorbondtype = 0;
7989 UIEnumPtr uptr;
7990
7991 mfp = (MultTransFormPtr) GetObjectExtra (b);
7992 if (mfp == NULL) return;
7993 sep = GetTopSeqEntryForEntityID (mfp->input_entityID);
7994 if (sep == NULL) return;
7995 Hide (mfp->form);
7996 WatchCursor ();
7997 Update ();
7998 uptr = (UIEnumPtr) DialogToPointer ((DialoG) mfp->fromfeatlist);
7999 if (uptr != NULL) {
8000 enumval = *uptr;
8001 feattype = (Int2) enumval;
8002 uptr = (UIEnumPtr) DialogToPointer ((DialoG) mfp->siteorbondlist);
8003 if (uptr != NULL) {
8004 enumval = *uptr;
8005 siteorbondtype = (Int2) enumval;
8006 }
8007 if (feattype > 0) {
8008 mfp->feattype = (Uint1) feattype;
8009 mfp->siteorbondtype = (Int4) siteorbondtype;
8010 if (siteorbondtype > 0 || mfp->type == SEQFEAT_REGION) {
8011 SeqEntryExplore (sep, (Pointer) mfp, ProcessMultiTrans);
8012 }
8013 }
8014 }
8015 ArrowCursor ();
8016 Update ();
8017 SeqEntryExplore (sep, NULL, CleanupEmptyFeatCallback);
8018 SeqEntryExplore (sep, NULL, MergeAdjacentAnnotsCallback);
8019 ObjMgrSetDirtyFlag (mfp->input_entityID, TRUE);
8020 ObjMgrSendMsg (OM_MSG_UPDATE, mfp->input_entityID, 0, 0);
8021 Remove (mfp->form);
8022 }
8023
8024 static void MultiTransformProc (IteM i, Uint1 targettype)
8025
8026 {
8027 EnumFieldAssocPtr ap;
8028 ButtoN b;
8029 BaseFormPtr bfp;
8030 GrouP c;
8031 GrouP g;
8032 GrouP h;
8033 GrouP k;
8034 Int2 listHeight;
8035 MultTransFormPtr mfp;
8036 EnumFieldAssocPtr realalist;
8037 SeqEntryPtr sep;
8038 StdEditorProcsPtr sepp;
8039 CharPtr title = "?";
8040 WindoW w;
8041
8042 #ifdef WIN_MAC
8043 bfp = currentFormDataPtr;
8044 #else
8045 bfp = GetObjectExtra (i);
8046 #endif
8047 if (bfp == NULL) return;
8048 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8049 if (sep == NULL) return;
8050 mfp = (MultTransFormPtr) MemNew (sizeof (MultTransFormData));
8051 if (mfp == NULL) return;
8052
8053 if (targettype == SEQFEAT_BOND) {
8054 title = "Transform to Bond";
8055 } else if (targettype == SEQFEAT_SITE) {
8056 title = "Transform to Site";
8057 } else if (targettype == SEQFEAT_REGION) {
8058 title = "Transform to Region";
8059 }
8060
8061 w = FixedWindow (-50, -33, -10, -10, title, StdCloseWindowProc);
8062 SetObjectExtra (w, mfp, StdCleanupFormProc);
8063 mfp->form = (ForM) w;
8064 mfp->formmessage = DefaultMessageProc;
8065
8066 sepp = (StdEditorProcsPtr) GetAppProperty ("StdEditorForm");
8067 if (sepp != NULL) {
8068 SetActivate (w, sepp->activateForm);
8069 mfp->appmessage = sepp->handleMessages;
8070 }
8071
8072 mfp->type = targettype;
8073
8074 mfp->input_entityID = bfp->input_entityID;
8075 mfp->input_itemID = bfp->input_itemID;
8076 mfp->input_itemtype = bfp->input_itemtype;
8077
8078 h = HiddenGroup (w, -1, 0, NULL);
8079 SetGroupSpacing (h, 10, 10);
8080
8081 g = HiddenGroup (h, 0, 2, NULL);
8082
8083 ap = import_featdef_alist (TRUE, FALSE, TRUE);
8084 realalist = ap;
8085 ap++;
8086 StaticPrompt (g, "From Feature", 0, 0, programFont, 'c');
8087 if (indexerVersion) {
8088 listHeight = 16;
8089 } else {
8090 listHeight = 8;
8091 }
8092 mfp->fromfeatlist = CreateEnumListDialog (g, 10, listHeight, NULL, ap, 0, NULL);
8093 FreeEnumFieldAlist (realalist);
8094
8095 k = NULL;
8096 if (targettype != SEQFEAT_REGION) {
8097 k = HiddenGroup (h, 0, 2, NULL);
8098
8099 if (targettype == SEQFEAT_BOND) {
8100 StaticPrompt (k, "Select type of bond", 0, 0, programFont, 'c');
8101 mfp->siteorbondlist = CreateEnumPopupDialog (k, TRUE, NULL, enum_bond_alist, 0, NULL);
8102 } else if (targettype == SEQFEAT_SITE) {
8103 StaticPrompt (k, "Select type of site", 0, 0, programFont, 'c');
8104 mfp->siteorbondlist = CreateEnumPopupDialog (k, TRUE, NULL, enum_site_alist, 0, NULL);
8105 }
8106 }
8107
8108 c = HiddenGroup (h, 4, 0, NULL);
8109 b = DefaultButton (c, "Accept", DoMultiTransform);
8110 SetObjectExtra (b, mfp, NULL);
8111 PushButton (c, "Cancel", StdCancelButtonProc);
8112
8113 AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, (HANDLE) k, NULL);
8114 RealizeWindow (w);
8115 Show (w);
8116 Update ();
8117 }
8118
8119 static Boolean UnlinkPubDesc (GatherContextPtr gcp)
8120
8121 {
8122 ValNodePtr sdp;
8123 ValNodePtr PNTR vnpp;
8124
8125 if (gcp->thistype != OBJ_SEQDESC) return TRUE;
8126 sdp = (ValNodePtr) gcp->thisitem;
8127 if (sdp == NULL || sdp->choice != Seq_descr_pub) return TRUE;
8128 vnpp = (ValNodePtr PNTR) gcp->userdata;
8129 if (vnpp == NULL) return TRUE;
8130 *(gcp->prevlink) = sdp->next;
8131 sdp->next = NULL;
8132 *vnpp = sdp;
8133 return TRUE;
8134 }
8135
8136 static void AddConvertedDescFeat (SeqEntryPtr sep, ValNodePtr vnp)
8137 {
8138 BioseqSetPtr bssp;
8139 BioseqPtr bsp;
8140 SeqFeatPtr sfp;
8141
8142 if (sep == NULL || vnp == NULL) return;
8143 if (IS_Bioseq_set (sep)) {
8144 bssp = (BioseqSetPtr) sep->data.ptrvalue;
8145 for (sep = bssp->seq_set; sep != NULL; sep = sep->next) {
8146 AddConvertedDescFeat (sep, vnp);
8147 }
8148 } else {
8149 bsp = (BioseqPtr) sep->data.ptrvalue;
8150 if (ISA_aa (bsp->mol)) return;
8151 sfp = CreateNewFeature (sep, NULL, SEQFEAT_PUB, NULL);
8152 if (sfp != NULL) {
8153 sfp->data.value.ptrvalue = AsnIoMemCopy ((Pointer) vnp->data.ptrvalue,
8154 (AsnReadFunc) PubdescAsnRead,
8155 (AsnWriteFunc) PubdescAsnWrite);
8156 }
8157 }
8158 }
8159
8160 static void CommonConvertDescToFeat (BaseFormPtr bfp, Boolean pub, Boolean src, Boolean com, CharPtr findstring)
8161
8162 {
8163 SeqEntryPtr sep;
8164 SelStructPtr sel;
8165 ValNodePtr vnp;
8166 Boolean asked_about_prop = FALSE;
8167 Boolean propagate_descriptors = FALSE;
8168
8169 if (bfp == NULL) return;
8170 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8171 if (sep == NULL) return;
8172 sel = ObjMgrGetSelected ();
8173 if (pub && sel != NULL) {
8174 if (sel->entityID == bfp->input_entityID &&
8175 sel->next == NULL && sel->itemtype == OBJ_SEQDESC) {
8176 vnp = NULL;
8177 sep = GetBestTopParentForItemID (sel->entityID, sel->itemID, sel->itemtype);
8178 if (sep != NULL) {
8179 /* unlink changes itemID, so sep must be determined first */
8180 GatherItem (sel->entityID, sel->itemID, sel->itemtype, (Pointer) &vnp, UnlinkPubDesc);
8181 if (vnp != NULL) {
8182 AddConvertedDescFeat (sep, vnp);
8183 ValNodeFree (vnp);
8184 }
8185 }
8186 }
8187 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8188 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8189 return;
8190 }
8191 if (ConvertPubSrcComDescsToFeats (sep, pub, src, com, FALSE, &asked_about_prop, &propagate_descriptors, findstring)) {
8192 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8193 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8194 }
8195 }
8196
8197
8198 static void CommonConvertDescToFeatMenuItem (IteM i, Boolean pub, Boolean src, Boolean com)
8199 {
8200 BaseFormPtr bfp;
8201
8202 #ifdef WIN_MAC
8203 bfp = currentFormDataPtr;
8204 #else
8205 bfp = GetObjectExtra (i);
8206 #endif
8207 if (bfp == NULL) return;
8208 CommonConvertDescToFeat (bfp, pub, src, com, NULL);
8209 }
8210
8211 static void ConvertPubDescToFeat (IteM i)
8212
8213 {
8214 CommonConvertDescToFeatMenuItem (i, TRUE, FALSE, FALSE);
8215 }
8216
8217 static void ConvertSrcDescToFeat (IteM i)
8218
8219 {
8220 CommonConvertDescToFeatMenuItem (i, FALSE, TRUE, FALSE);
8221 }
8222
8223 static void ConvertComDescToFeat (IteM i)
8224
8225 {
8226 CommonConvertDescToFeatMenuItem (i, FALSE, FALSE, TRUE);
8227 }
8228
8229 typedef struct convertpubdescdata {
8230 DESCRIPTOR_FORM_BLOCK
8231 BaseFormPtr bfp;
8232 TexT findthis;
8233 Char findString [255];
8234 } ConvertPubDescData, PNTR ConvertPubDescPtr;
8235
8236
8237 static void DoConvertPubDescStringConstraint (ButtoN b)
8238 {
8239 ConvertPubDescPtr cpdp;
8240
8241 cpdp = (ConvertPubDescPtr) GetObjectExtra (b);
8242 if (cpdp == NULL) return;
8243 Hide (cpdp->form);
8244
8245 GetTitle (cpdp->findthis, cpdp->findString, sizeof (cpdp->findString) - 1);
8246 if (StringHasNoText (cpdp->findString)) {
8247 CommonConvertDescToFeat (cpdp->bfp, TRUE, FALSE, FALSE, NULL);
8248 } else {
8249 CommonConvertDescToFeat (cpdp->bfp, TRUE, FALSE, FALSE, cpdp->findString);
8250 }
8251
8252 ObjMgrSetDirtyFlag (cpdp->input_entityID, TRUE);
8253 ObjMgrSendMsg (OM_MSG_UPDATE, cpdp->input_entityID, 0, 0);
8254 Remove (cpdp->form);
8255 }
8256
8257 static void CreateConvertPubDescStringConstraintDialogX (IteM i)
8258 {
8259 BaseFormPtr bfp;
8260 ConvertPubDescPtr cpdp;
8261 WindoW w;
8262 GrouP h, g, c;
8263 ButtoN b;
8264
8265 #ifdef WIN_MAC
8266 bfp = currentFormDataPtr;
8267 #else
8268 bfp = GetObjectExtra (i);
8269 #endif
8270 if (bfp == NULL) return;
8271
8272 cpdp = (ConvertPubDescPtr) MemNew (sizeof (ConvertPubDescData));
8273 if (cpdp == NULL) return;
8274 cpdp->bfp = bfp;
8275
8276 w = FixedWindow (-50, -33, -10, -10, "Convert Pub Descriptors", StdCloseWindowProc);
8277 SetObjectExtra (w, cpdp, StdCleanupFormProc);
8278 cpdp->form = (ForM) w;
8279 cpdp->formmessage = NULL;
8280
8281 cpdp->input_entityID = bfp->input_entityID;
8282
8283 h = HiddenGroup (w, 0, 2, NULL);
8284 g = HiddenGroup (h, 2, 0, NULL);
8285 StaticPrompt (g, "Optional string constraint", 0, dialogTextHeight, programFont, 'c');
8286 cpdp->findthis = DialogText (g, "", 14, NULL);
8287
8288 c = HiddenGroup (h, 2, 0, NULL);
8289 b = DefaultButton (c, "Accept", DoConvertPubDescStringConstraint);
8290 SetObjectExtra (b, cpdp, NULL);
8291 PushButton (c, "Cancel", StdCancelButtonProc);
8292
8293 AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) c, NULL);
8294 RealizeWindow (w);
8295 Show (w);
8296 Update ();
8297 }
8298
8299
8300 typedef struct feattodesc {
8301 Boolean pub;
8302 Boolean src;
8303 Boolean com;
8304 } FeatToDescData, PNTR FeatToDescPtr;
8305
8306 static void ConvertOneFeatToDesc (SeqFeatPtr sfp, Pointer userdata)
8307 {
8308 SeqDescPtr sdp;
8309 SeqEntryPtr sep;
8310 SeqIdPtr sip;
8311 BioseqPtr bsp;
8312 ValNode vn;
8313 FeatToDescPtr fdp;
8314 BioSourcePtr biop;
8315 SubSourcePtr ssp, last_ssp = NULL;
8316 CharPtr new_note;
8317
8318 if (sfp == NULL || (fdp = (FeatToDescPtr) userdata) == NULL
8319 || (sfp->data.choice == SEQFEAT_PUB && !fdp->pub)
8320 || (sfp->data.choice == SEQFEAT_BIOSRC && !fdp->src)
8321 || (sfp->data.choice == SEQFEAT_COMMENT && !fdp->com)
8322 || (sfp->data.choice != SEQFEAT_PUB
8323 && sfp->data.choice != SEQFEAT_BIOSRC
8324 && sfp->data.choice != SEQFEAT_COMMENT)) {
8325 return;
8326 }
8327
8328 /* perform only if feature is full-length */
8329 sip = SeqLocId (sfp->location);
8330 bsp = BioseqFind (sip);
8331 if (bsp == NULL) return;
8332 sip = SeqIdFindBest(bsp->id, 0);
8333 if (sip == NULL) return;
8334 vn.choice = SEQLOC_WHOLE;
8335 vn.extended = 0;
8336 vn.data.ptrvalue = (Pointer) sip;
8337 vn.next = NULL;
8338 /* is feature full length? */
8339 if (SeqLocCompare (sfp->location, &vn) != SLC_A_EQ_B) return;
8340
8341 sep = GetBestTopParentForItemID (sfp->idx.entityID, sfp->idx.itemID, OBJ_SEQFEAT);
8342 if (sep == NULL) return;
8343
8344 if (sfp->data.choice == SEQFEAT_PUB) {
8345 sdp = CreateNewDescriptor (sep, Seq_descr_pub);
8346 sdp->data.ptrvalue = AsnIoMemCopy ((Pointer) sfp->data.value.ptrvalue,
8347 (AsnReadFunc) PubdescAsnRead,
8348 (AsnWriteFunc) PubdescAsnWrite);
8349 } else if (sfp->data.choice == SEQFEAT_BIOSRC) {
8350 sdp = CreateNewDescriptor (sep, Seq_descr_source);
8351 sdp->data.ptrvalue = AsnIoMemCopy ((Pointer) sfp->data.value.ptrvalue,
8352 (AsnReadFunc) BioSourceAsnRead,
8353 (AsnWriteFunc) BioSourceAsnWrite);
8354 if (!StringHasNoText (sfp->comment)) {
8355 biop = (BioSourcePtr) sdp->data.ptrvalue;
8356 ssp = biop->subtype;
8357 while (ssp != NULL && ssp->subtype != 255) {
8358 last_ssp = ssp;
8359 ssp = ssp->next;
8360 }
8361 if (ssp == NULL) {
8362 ssp = SubSourceNew ();
8363 ssp->subtype = 255;
8364 ssp->name = StringSave (sfp->comment);
8365 if (last_ssp == NULL) {
8366 biop->subtype = ssp;
8367 } else {
8368 last_ssp->next = ssp;
8369 }
8370 } else if (StringHasNoText (ssp->name)) {
8371 ssp->name = MemFree (ssp->name);
8372 ssp->name = StringSave (sfp->comment);
8373 } else {
8374 new_note = (CharPtr) MemNew (sizeof(Char) * (StringLen (ssp->name) + StringLen (sfp->comment) + 2));
8375 sprintf (new_note, "%s;%s", ssp->name, sfp->comment);
8376 ssp->name = MemFree (ssp->name);
8377 ssp->name = new_note;
8378 }
8379 }
8380 } else if (sfp->data.choice == SEQFEAT_COMMENT) {
8381 sdp = CreateNewDescriptor (sep, Seq_descr_comment);
8382 sdp->data.ptrvalue = StringSave (sfp->comment);
8383 }
8384
8385 sfp->idx.deleteme = TRUE;
8386 }
8387
8388
8389 static void CommonConvertFeatToDesc (IteM i, Boolean pub, Boolean src, Boolean com)
8390
8391 {
8392 SeqEntryPtr sep;
8393 SelStructPtr sel;
8394 SeqFeatPtr sfp;
8395 FeatToDescData fdd;
8396 BaseFormPtr bfp;
8397 SeqMgrFeatContext fcontext;
8398
8399 #ifdef WIN_MAC
8400 bfp = currentFormDataPtr;
8401 #else
8402 bfp = GetObjectExtra (i);
8403 #endif
8404 if (bfp == NULL) return;
8405 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8406 if (sep == NULL) return;
8407
8408 fdd.pub = pub;
8409 fdd.src = src;
8410 fdd.com = com;
8411
8412 sel = ObjMgrGetSelected ();
8413 if (sel != NULL) {
8414 while (sel != NULL) {
8415 if (sel->entityID == bfp->input_entityID && sel->itemtype == OBJ_SEQFEAT) {
8416 sfp = SeqMgrGetDesiredFeature (bfp->input_entityID, NULL, sel->itemID, 0, NULL, &fcontext);
8417 ConvertOneFeatToDesc (sfp, &fdd);
8418 }
8419 sel = sel->next;
8420 }
8421 } else {
8422 VisitFeaturesInSep (sep, &fdd, ConvertOneFeatToDesc);
8423 }
8424 DeleteMarkedObjects (bfp->input_entityID, 0, NULL);
8425 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8426 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8427 }
8428
8429
8430 static void ConvertPubFeatToDesc (IteM i)
8431 {
8432 CommonConvertFeatToDesc (i, TRUE, FALSE, FALSE);
8433 }
8434
8435
8436 static void ConvertSrcFeatToDesc (IteM i)
8437 {
8438 CommonConvertFeatToDesc (i, FALSE, TRUE, FALSE);
8439 }
8440
8441
8442 static void ConvertCommentFeatToDesc (IteM i)
8443 {
8444 CommonConvertFeatToDesc (i, FALSE, FALSE, TRUE);
8445 }
8446
8447
8448
8449 static void MoveSecondProtName (SeqFeatPtr sfp, Pointer userdata)
8450
8451 {
8452 ValNodePtr nxt;
8453 ProtRefPtr prp;
8454 ValNodePtr vnp;
8455
8456 if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT) return;
8457 prp = (ProtRefPtr) sfp->data.value.ptrvalue;
8458 if (prp == NULL || prp->desc != NULL) return;
8459 vnp = prp->name;
8460 if (vnp == NULL) return;
8461 nxt = vnp->next;
8462 if (nxt == NULL || nxt->next != NULL) return;
8463 vnp->next = NULL;
8464 prp->desc = nxt->data.ptrvalue;
8465 nxt->data.ptrvalue = NULL;
8466 ValNodeFree (nxt);
8467 }
8468
8469 static void SecondProtNameToDesc (IteM i)
8470
8471 {
8472 BaseFormPtr bfp;
8473 SeqEntryPtr sep;
8474
8475 #ifdef WIN_MAC
8476 bfp = currentFormDataPtr;
8477 #else
8478 bfp = GetObjectExtra (i);
8479 #endif
8480 if (bfp == NULL) return;
8481 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8482 if (sep == NULL) return;
8483 VisitFeaturesInSep (sep, NULL, MoveSecondProtName);
8484 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8485 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8486 }
8487
8488 static void MoveProtDesc (SeqFeatPtr sfp, Pointer userdata)
8489
8490 {
8491 ProtRefPtr prp;
8492 CharPtr str;
8493 ValNodePtr vnp;
8494
8495 if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT) return;
8496 prp = (ProtRefPtr) sfp->data.value.ptrvalue;
8497 if (prp == NULL || prp->desc == NULL) return;
8498 vnp = prp->name;
8499 if (vnp == NULL) return;
8500 str = prp->desc;
8501 prp->desc = NULL;
8502 ValNodeAddStr (&(prp->name), 0, str);
8503 }
8504
8505 static void ProtDescToSecondName (IteM i)
8506
8507 {
8508 BaseFormPtr bfp;
8509 SeqEntryPtr sep;
8510
8511 #ifdef WIN_MAC
8512 bfp = currentFormDataPtr;
8513 #else
8514 bfp = GetObjectExtra (i);
8515 #endif
8516 if (bfp == NULL) return;
8517 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8518 if (sep == NULL) return;
8519 VisitFeaturesInSep (sep, NULL, MoveProtDesc);
8520 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8521 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8522 }
8523
8524 typedef struct ecrepdata {
8525 CharPtr before;
8526 CharPtr after;
8527 } EcRepData, PNTR EcRepPtr;
8528
8529 static ValNodePtr ec_rep_list = NULL;
8530 static EcRepPtr PNTR ec_rep_data = NULL;
8531 static Int4 ec_rep_len = 0;
8532
8533 static int LIBCALLBACK SortVnpByEcBefore (VoidPtr ptr1, VoidPtr ptr2)
8534
8535 {
8536 EcRepPtr erp1, erp2;
8537 CharPtr str1, str2;
8538 ValNodePtr vnp1, vnp2;
8539
8540 if (ptr1 == NULL || ptr2 == NULL) return 0;
8541 vnp1 = *((ValNodePtr PNTR) ptr1);
8542 vnp2 = *((ValNodePtr PNTR) ptr2);
8543 if (vnp1 == NULL || vnp2 == NULL) return 0;
8544 erp1 = (EcRepPtr) vnp1->data.ptrvalue;
8545 erp2 = (EcRepPtr) vnp2->data.ptrvalue;
8546 if (erp1 == NULL || erp2 == NULL) return 0;
8547 str1 = erp1->before;
8548 str2 = erp2->before;
8549 if (str1 == NULL || str2 == NULL) return 0;
8550 return StringCmp (str1, str2);
8551 }
8552
8553 static void SetupECReplacementTable (CharPtr file)
8554
8555 {
8556 EcRepPtr erp;
8557 FileCache fc;
8558 FILE *fp = NULL;
8559 Int4 i;
8560 ValNodePtr last = NULL;
8561 Char line [512];
8562 Char path [PATH_MAX];
8563 CharPtr ptr;
8564 ErrSev sev;
8565 CharPtr str;
8566 ValNodePtr vnp;
8567
8568 if (ec_rep_data != NULL) return;
8569
8570 if (FindPath ("ncbi", "ncbi", "data", path, sizeof (path))) {
8571 FileBuildPath (path, NULL, file);
8572 sev = ErrSetMessageLevel (SEV_ERROR);
8573 fp = FileOpen (path, "r");
8574 ErrSetMessageLevel (sev);
8575 if (fp != NULL) {
8576 FileCacheSetup (&fc, fp);
8577
8578 str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
8579 while (str != NULL) {
8580 if (StringDoesHaveText (str)) {
8581 ptr = StringChr (str, '\t');
8582 if (ptr != NULL) {
8583 *ptr = '\0';
8584 ptr++;
8585 erp = (EcRepPtr) MemNew (sizeof (EcRepData));
8586 if (erp != NULL) {
8587 erp->before = StringSave (str);
8588 erp->after = StringSave (ptr);
8589 vnp = ValNodeAddPointer (&last, 0, (Pointer) erp);
8590 if (ec_rep_list == NULL) {
8591 ec_rep_list = vnp;
8592 }
8593 last = vnp;
8594 }
8595 }
8596 }
8597 str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
8598 }
8599
8600 FileClose (fp);
8601 ec_rep_len = ValNodeLen (ec_rep_list);
8602 if (ec_rep_len > 0) {
8603 ec_rep_list = ValNodeSort (ec_rep_list, SortVnpByEcBefore);
8604 ec_rep_data = (EcRepPtr PNTR) MemNew (sizeof (EcRepPtr) * (ec_rep_len + 1));
8605 if (ec_rep_data != NULL) {
8606 for (vnp = ec_rep_list, i = 0; vnp != NULL; vnp = vnp->next, i++) {
8607 erp = (EcRepPtr) vnp->data.ptrvalue;
8608 ec_rep_data [i] = erp;
8609 }
8610 }
8611 }
8612 }
8613 }
8614 }
8615
8616 static void UpdateProtEC (SeqFeatPtr sfp, Pointer userdata)
8617
8618 {
8619 EcRepPtr erp;
8620 Int4 L, R, mid;
8621 ProtRefPtr prp;
8622 CharPtr str;
8623 ValNodePtr vnp;
8624
8625 if (sfp == NULL || sfp->data.choice != SEQFEAT_PROT) return;
8626 prp = (ProtRefPtr) sfp->data.value.ptrvalue;
8627 if (prp == NULL || prp->ec == NULL) return;
8628 for (vnp = prp->ec; vnp != NULL; vnp = vnp->next) {
8629 str = (CharPtr) vnp->data.ptrvalue;
8630 if (StringHasNoText (str)) continue;
8631 L = 0;
8632 R = ec_rep_len - 1;
8633 while (L < R) {
8634 mid = (L + R) / 2;
8635 erp = ec_rep_data [(int) mid];
8636 if (erp != NULL && StringCmp (erp->before, str) < 0) {
8637 L = mid + 1;
8638 } else {
8639 R = mid;
8640 }
8641 }
8642 erp = ec_rep_data [(int) R];
8643 if (erp != NULL && StringCmp (erp->before, str) == 0) {
8644 vnp->data.ptrvalue = MemFree (vnp->data.ptrvalue);
8645 vnp->data.ptrvalue = StringSave (erp->after);
8646 }
8647 }
8648 }
8649
8650 static void UpdateECNumbersBaseForm (BaseFormPtr bfp)
8651 {
8652 SeqEntryPtr sep;
8653
8654 if (bfp == NULL) return;
8655 sep = GetTopSeqEntryForEntityID (bfp->input_entityID);
8656 if (sep == NULL) return;
8657 SetupECReplacementTable ("ecnum_replaced.txt");
8658 if (ec_rep_data != NULL && ec_rep_len > 0) {
8659 VisitFeaturesInSep (sep, NULL, UpdateProtEC);
8660 }
8661 ObjMgrSetDirtyFlag (bfp->input_entityID, TRUE);
8662 ObjMgrSendMsg (OM_MSG_UPDATE, bfp->input_entityID, 0, 0);
8663 }
8664
8665 static void UpdateECnumbers (IteM i)
8666
8667 {
8668 BaseFormPtr bfp;
8669
8670 #ifdef WIN_MAC
8671 bfp = currentFormDataPtr;
8672 #else
8673 bfp = GetObjectExtra (i);
8674 #endif
8675
8676 UpdateECNumbersBaseForm (bfp);
8677 }
8678
8679
8680 typedef struct icrepdata {
8681 CharPtr code;
8682 CharPtr name;
8683 } IcRepData, PNTR IcRepPtr;
8684
8685 static ValNodePtr ic_rep_list = NULL;
8686 static IcRepPtr PNTR ic_rep_data = NULL;
8687 static Int4 ic_rep_len = 0;
8688
8689 static int LIBCALLBACK SortVnpByInstituteName (VoidPtr ptr1, VoidPtr ptr2)
8690
8691 {
8692 int compare;
8693 IcRepPtr irp1, irp2;
8694 CharPtr str1, str2;
8695 ValNodePtr vnp1, vnp2;
8696
8697 if (ptr1 == NULL || ptr2 == NULL) return 0;
8698 vnp1 = *((ValNodePtr PNTR) ptr1);
8699 vnp2 = *((ValNodePtr PNTR) ptr2);
8700 if (vnp1 == NULL || vnp2 == NULL) return 0;
8701 irp1 = (IcRepPtr) vnp1->data.ptrvalue;
8702 irp2 = (IcRepPtr) vnp2->data.ptrvalue;
8703 if (irp1 == NULL || irp2 == NULL) return 0;
8704 str1 = irp1->name;
8705 str2 = irp2->name;
8706 if (str1 == NULL || str2 == NULL) return 0;
8707 compare = StringCmp (str1, str2);
8708 if (compare > 0) {
8709 return 1;
8710 } else if (compare < 0) {
8711 return -1;
8712 }
8713 str1 = irp1->code;
8714 str2 = irp2->code;
8715 if (str1 == NULL || str2 == NULL) return 0;
8716 compare = StringCmp (str1, str2);
8717 if (compare > 0) {
8718 return 1;
8719 } else if (compare < 0) {
8720 return -1;
8721 }
8722 return 0;
8723 }
8724
8725 static void SetupInstituteCodeNameTable (void)
8726
8727 {
8728 FileCache fc;
8729 CharPtr file = "institution_codes.txt";
8730 FILE *fp = NULL;
8731 Int4 i;
8732 IcRepPtr irp;
8733 ValNodePtr last = NULL;
8734 Char line [512];
8735 Char path [PATH_MAX];
8736 CharPtr ptr;
8737 ErrSev sev;
8738 CharPtr str;
8739 ValNodePtr vnp;
8740
8741 if (ic_rep_data != NULL) return;
8742
8743 if (FindPath ("ncbi", "ncbi", "data", path, sizeof (path))) {
8744 FileBuildPath (path, NULL, file);
8745 sev = ErrSetMessageLevel (SEV_ERROR);
8746 fp = FileOpen (path, "r");
8747 ErrSetMessageLevel (sev);
8748 if (fp != NULL) {
8749 FileCacheSetup (&fc, fp);
8750
8751 str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
8752 while (str != NULL) {
8753 if (StringDoesHaveText (str)) {
8754 ptr = StringChr (str, '\t');
8755 if (ptr != NULL) {
8756 *ptr = '\0';
8757 ptr++;
8758 ptr = StringChr (ptr, '\t');
8759 if (ptr != NULL) {
8760 *ptr = '\0';
8761 ptr++;
8762 irp = (IcRepPtr) MemNew (sizeof (IcRepData));
8763 if (irp != NULL) {
8764 TrimSpacesAroundString (str);
8765 TrimSpacesAroundString (ptr);
8766 irp->code = StringSave (str);
8767 irp->name = StringSave (ptr);
8768 vnp = ValNodeAddPointer (&last, 0, (Pointer) irp);
8769 if (ic_rep_list == NULL) {
8770 ic_rep_list = vnp;
8771 }
8772 last = vnp;
8773 }
8774 }
8775 }
8776 }
8777 str = FileCacheReadLine (&fc, line, sizeof (line), NULL);
8778 }
8779
8780 FileClose (fp);
8781 ic_rep_len = ValNodeLen (ic_rep_list);
8782 if (ic_rep_len > 0) {
8783 ic_rep_list = ValNodeSort (ic_rep_list, SortVnpByInstituteName);
8784 ic_rep_data = (IcRepPtr PNTR) MemNew (sizeof (IcRepPtr) * (ic_rep_len + 1));
8785 if (ic_rep_data != NULL) {
8786 for (vnp = ic_rep_list, i = 0; vnp != NULL; vnp = vnp->next, i++) {
8787 irp = (IcRepPtr) vnp->data.ptrvalue;
8788 ic_rep_data [i] = irp;
8789 }
8790 }
8791 }
8792 }
8793 }
8794 }
8795
8796 static CharPtr CheckForInstitutionFullName (CharPtr name, BoolPtr ambigP)
8797
8798 {
8799 CharPtr code = NULL;
8800 IcRepPtr irp;
8801 Int4 L, R, mid;
8802
8803 if (ambigP != NULL) {
8804 *ambigP = FALSE;
8805 }
8806 if (StringHasNoText (name)) return NULL;
8807 L = 0;
8808 R = ic_rep_len - 1;
8809 while (L < R) {
8810 mid = (L + R) / 2;
8811 irp = ic_rep_data [(int) mid];
8812 if (irp != NULL && StringCmp (irp->name, name) < 0) {
8813 L = mid + 1;
8814 } else {
8815 R = mid;
8816 }
8817 }
8818 irp = ic_rep_data [(int) R];
8819 if (irp != NULL && StringCmp (irp->name, name) == 0) {
8820 code = irp->code;
8821 /* need to check for uniqueness */
8822 if (R < ic_rep_len - 1) {
8823 irp = ic_rep_data [(int) R + 1];
8824 if (irp != NULL && StringCmp (irp->name, name) == 0) {
8825 if (ambigP != NULL) {
8826 *ambigP = TRUE;
8827 }
8828 return NULL;
8829 }
8830 }
8831 }
8832 return code;
8833 }
8834
8835 static void ConvertInstitutionName (OrgModPtr mod)
8836
8837 {
8838