~ubuntu-branches/ubuntu/warty/ncbi-tools6/warty

« back to all changes in this revision

Viewing changes to api/edutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2002-04-04 22:13:09 UTC
  • Revision ID: james.westby@ubuntu.com-20020404221309-vfze028rfnlrldct
Tags: upstream-6.1.20011220a
ImportĀ upstreamĀ versionĀ 6.1.20011220a

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  edutil.c
 
2
* ===========================================================================
 
3
 
4
*                            PUBLIC DOMAIN NOTICE                          
 
5
*               National Center for Biotechnology Information
 
6
*                                                                          
 
7
*  This software/database is a "United States Government Work" under the   
 
8
*  terms of the United States Copyright Act.  It was written as part of    
 
9
*  the author's official duties as a United States Government employee and 
 
10
*  thus cannot be copyrighted.  This software/database is freely available 
 
11
*  to the public for use. The National Library of Medicine and the U.S.    
 
12
*  Government have not placed any restriction on its use or reproduction.  
 
13
*  
 
14
*  Although all reasonable efforts have been taken to ensure the accuracy  
 
15
*  and reliability of the software and data, the NLM and the U.S.          
 
16
*  Government do not and cannot warrant the performance or results that    
 
17
*  may be obtained by using this software or data. The NLM and the U.S.    
 
18
*  Government disclaim all warranties, express or implied, including       
 
19
*  warranties of performance, merchantability or fitness for any particular
 
20
*  purpose.                                                                
 
21
*                                                                          
 
22
*  Please cite the author in any work or product based on this material.   
 
23
*
 
24
* ===========================================================================
 
25
*
 
26
* File Name:  edutil.c
 
27
*
 
28
* Author:  James Ostell
 
29
*   
 
30
* Version Creation Date: 2/4/94
 
31
*
 
32
* $Revision: 6.14 $
 
33
*
 
34
* File Description:  Sequence editing utilities
 
35
*
 
36
* Modifications:  
 
37
* --------------------------------------------------------------------------
 
38
* Date     Name        Description of modification
 
39
* -------  ----------  -----------------------------------------------------
 
40
*
 
41
* $Log: edutil.c,v $
 
42
* Revision 6.14  2001/06/01 18:07:20  kans
 
43
* changes to SeqLocAdd to allow one plus and one unknown strand to be accepted
 
44
*
 
45
* Revision 6.13  2001/02/23 21:30:09  shkeda
 
46
* Fixed SeqLocAdd: Int-fuzz pointers should be set to NULL after IntFuzzFree
 
47
*
 
48
* Revision 6.12  2001/02/23 01:26:07  ostell
 
49
* Added support to BioseqDelete() for delta seqs
 
50
*
 
51
* Revision 6.11  2000/10/31 17:11:06  kans
 
52
* SeqLocReplaceID was handling SEQLOC_PACKED_PNT incorrectly
 
53
*
 
54
* Revision 6.10  1999/12/20 20:47:12  kans
 
55
* oldscope test was wrong everywhere
 
56
*
 
57
* Revision 6.9  1999/12/15 20:52:16  kans
 
58
* added IndexedSeqFeatsCopy if SeqMgrFeaturesAreIndexed
 
59
*
 
60
* Revision 6.8  1999/12/07 20:32:13  kans
 
61
* for most editing functions, if BioseqFind failed, temporarily clear scope/try again/reset scope
 
62
*
 
63
* Revision 6.7  1999/11/19 19:54:19  kans
 
64
* SeqLocAdd checks for NULL slp before dereferencing
 
65
*
 
66
* Revision 6.6  1998/09/03 20:43:52  kans
 
67
* added delta bioseq support to BioseqCopy
 
68
*
 
69
* Revision 6.5  1998/06/22 20:00:46  kans
 
70
* DelFeat was a bit too agressive when there were multiple feature tables
 
71
*
 
72
* Revision 6.4  1998/06/17 21:50:11  kans
 
73
* fixed unix compiler warnings, including 64-bit SGI
 
74
*
 
75
* Revision 6.3  1997/11/10 19:40:48  bazhin
 
76
* Fixed incorrect comment for ISAGappedSeqLoc() function.
 
77
*
 
78
* Revision 6.2  1997/10/24 19:16:17  bazhin
 
79
* Added three easy functions GapToSeqLoc(...), ISAGappedSeqLoc(...)
 
80
* and GappedSeqLocsToDeltaSeqs(...) for processing "gap(...)" tokens
 
81
* in CONTIG line.
 
82
*
 
83
* Revision 6.1  1997/10/10 20:18:02  ostell
 
84
* removed tab character from SeqLitTag for DeltaSeqsToSeqLoc
 
85
*
 
86
* Revision 6.0  1997/08/25 18:05:24  madden
 
87
* Revision changed to 6.0
 
88
*
 
89
* Revision 5.10  1997/07/25 20:34:51  kans
 
90
* added SegLocToPartsEx
 
91
*
 
92
* Revision 5.9  1997/06/19 18:37:30  vakatov
 
93
* [WIN32,MSVC++]  Adopted for the "NCBIOBJ.LIB" DLL'ization
 
94
*
 
95
* Revision 5.8  1996/12/20 17:59:34  kans
 
96
* SeqLocCopyRegion already reversed order for Seq_strand_minus, so no need
 
97
* to reverse it again (JO + JK)
 
98
*
 
99
 * Revision 5.7  1996/10/21  18:56:19  ostell
 
100
 * made SegLocToParts accept a complicated Seq-loc argument
 
101
 *
 
102
 * Revision 5.6  1996/10/09  17:27:34  chappey
 
103
 * *** empty log message ***
 
104
 *
 
105
 * Revision 5.5  1996/10/09  16:34:59  chappey
 
106
 * added SeqLocReplaceID() that replaces the Seq-Id of a Seq-Loc
 
107
 *
 
108
 * Revision 5.4  1996/07/15  14:43:51  epstein
 
109
 * change SeqLocAdd() so that it merges identical SEQLOC_PNTs
 
110
 *
 
111
 * Revision 5.3  1996/06/12  18:29:41  epstein
 
112
 * move SeqLocIntNew() and SeqLocPntNew() from edutil to sequtil
 
113
 *
 
114
 * Revision 5.1  1996/06/10  15:07:17  epstein
 
115
 * replace make_seq_loc() with SeqLocIntNew() and make_pnt_loc with SeqLocPntNew()
 
116
 *
 
117
 * Revision 5.0  1996/05/28  13:23:23  ostell
 
118
 * Set to revision 5.0
 
119
 *
 
120
 * Revision 4.10  1996/03/19  19:45:24  kans
 
121
 * fix of SegLocToParts (JO)
 
122
 *
 
123
 * Revision 4.9  1996/03/12  22:14:22  ostell
 
124
 * added SeqLocToParts()
 
125
 *
 
126
 * Revision 4.7  1996/02/19  19:58:05  ostell
 
127
 * added support for Code-break and tRNA.anticodon
 
128
 *
 
129
 * Revision 4.6  1996/01/30  16:24:04  ostell
 
130
 * changed name of SeqLocPack() to SeqLocPackage()
 
131
 *
 
132
 * Revision 4.5  1996/01/29  22:03:52  ostell
 
133
 * revised SeqLocAdd
 
134
 * added SeqLocPack
 
135
 *
 
136
 * Revision 4.4  1996/01/10  22:25:25  ostell
 
137
 * added SeqLocIntNew()
 
138
 *
 
139
 * Revision 4.3  1995/12/29  21:31:44  ostell
 
140
 * added mapping functions between delta seq and seq loc, for editing utilities
 
141
 *
 
142
 * Revision 4.2  1995/12/21  02:35:50  ostell
 
143
 * changed call for BSAdd
 
144
 *
 
145
 * Revision 4.1  1995/11/15  20:40:20  ostell
 
146
 * fixed SeqLocCopyPart so it correctly handles SEQLOC_NULL in segmented
 
147
 * records
 
148
 *
 
149
 * Revision 4.0  1995/07/26  13:49:01  ostell
 
150
 * force revision to 4.0
 
151
 *
 
152
 * Revision 1.22  1995/05/15  21:46:05  ostell
 
153
 * added Log line
 
154
 *
 
155
*
 
156
*
 
157
* ==========================================================================
 
158
*/
 
159
 
 
160
#include <edutil.h>
 
161
#include <explore.h>
 
162
 
 
163
 
 
164
 
 
165
/*****************************************************************************
 
166
*
 
167
*   SeqLocPackage(head)
 
168
*     head is a chain of 1 or more SeqLocs connected by slp->next
 
169
*     Assumes was built by SeqLocAdd to remove redundancy
 
170
*     Frees the last element if it is a NULL.
 
171
*     If more than one element left, then packages the chain into a SEQLOC_MIX,
 
172
*       or SEQLOC_PACKED_INT as appropriate
 
173
*     returns pointer to the head of the resulting single SeqLoc
 
174
*
 
175
*****************************************************************************/
 
176
NLM_EXTERN SeqLocPtr LIBCALL SeqLocPackage (SeqLocPtr head)
 
177
{
 
178
        SeqLocPtr newhead = NULL, tmp, prev;
 
179
        Boolean packed_int = TRUE;
 
180
        Int4 ctr = 0;
 
181
 
 
182
        if (head == NULL) return head;
 
183
 
 
184
        prev = NULL;    /* remove trailing NULL */
 
185
        for (tmp = head; tmp->next != NULL; tmp = tmp->next)
 
186
                prev = tmp;
 
187
 
 
188
        if (tmp->choice == SEQLOC_NULL)
 
189
        {
 
190
                SeqLocFree(tmp);
 
191
                if (prev != NULL)
 
192
                        prev->next = NULL;
 
193
                else
 
194
                        return NULL;   /* nothing left */
 
195
        }
 
196
 
 
197
        for (tmp = head; tmp != NULL; tmp = tmp->next)
 
198
        {
 
199
                ctr++;
 
200
                if (tmp->choice != SEQLOC_INT)
 
201
                        packed_int = FALSE;
 
202
        }
 
203
 
 
204
        if (ctr == 1)
 
205
                return head;
 
206
 
 
207
        newhead = ValNodeNew(NULL);
 
208
        if (packed_int)
 
209
                newhead->choice = SEQLOC_PACKED_INT;
 
210
        else
 
211
                newhead->choice = SEQLOC_MIX;
 
212
        newhead->data.ptrvalue = head;
 
213
 
 
214
        return newhead;
 
215
}
 
216
 
 
217
/*****************************************************************************
 
218
*
 
219
*   SeqLocAdd(headptr, slp, merge, do_copy)
 
220
*       creates a linked list of SeqLocs.
 
221
*       returns a pointer to the last SeqLoc in the chain
 
222
*       if (merge)
 
223
*         deletes double NULLs or Nulls at start (application must delete at stop)
 
224
*         merges adjacent intervals on the same strand
 
225
*       if (do_copy)
 
226
*         Makes copies of incoming SeqLocs
 
227
*         if incoming is merged, deletes the incoming SeqLoc
 
228
*
 
229
*****************************************************************************/
 
230
NLM_EXTERN SeqLocPtr LIBCALL SeqLocAdd (SeqLocPtr PNTR head, SeqLocPtr slp, Boolean merge, Boolean do_copy)
 
231
{
 
232
        SeqLocPtr tmp, last, retval = NULL;
 
233
        Boolean merged = FALSE;   /* intervals were merged */
 
234
 
 
235
        if (slp == NULL) return NULL;
 
236
 
 
237
        last = NULL;
 
238
        if (* head != NULL)
 
239
        {
 
240
                for (tmp = *head; tmp != NULL; tmp = tmp->next)
 
241
                {
 
242
                        last = tmp;
 
243
                }
 
244
        }
 
245
 
 
246
        if ((slp->choice == SEQLOC_NULL) && (merge))  /* no null at start, or two in a row */
 
247
        {
 
248
                if (last == NULL)  /* first one */
 
249
                {
 
250
                        merged = TRUE;
 
251
                        goto ret;
 
252
                }
 
253
                if (last->choice == SEQLOC_NULL)  /* double NULL */
 
254
                {
 
255
                        merged = TRUE;
 
256
                        goto ret;
 
257
                }
 
258
        }
 
259
 
 
260
        if ((last != NULL) && (merge))     /* check for merging intervals */
 
261
        {
 
262
                if ((last->choice == SEQLOC_INT) && (slp->choice == SEQLOC_INT))
 
263
                {
 
264
                        SeqIntPtr sip1, sip2;
 
265
                        Boolean samestrand;
 
266
                        Uint1 strand = Seq_strand_unknown;
 
267
 
 
268
                        sip1 = (SeqIntPtr)(last->data.ptrvalue);
 
269
                        sip2 = (SeqIntPtr)(slp->data.ptrvalue);
 
270
                        samestrand = FALSE;
 
271
                        if ((sip1->strand == sip2->strand) ||
 
272
                                (sip1->strand == Seq_strand_unknown && sip2->strand != Seq_strand_minus) ||
 
273
                        (sip1->strand == Seq_strand_unknown && sip2->strand != Seq_strand_minus)) {
 
274
                                samestrand = TRUE;
 
275
                                if (sip1->strand == Seq_strand_minus || sip1->strand == Seq_strand_minus) {
 
276
                                        strand = Seq_strand_minus;
 
277
                                } else if (sip1->strand == Seq_strand_plus || sip1->strand == Seq_strand_plus) {
 
278
                                        strand = Seq_strand_plus;
 
279
                                } else {
 
280
                                        strand = Seq_strand_unknown;
 
281
                                }
 
282
                }
 
283
                        if (samestrand && (SeqIdForSameBioseq(sip1->id, sip2->id)))
 
284
                        {
 
285
                                if (strand == Seq_strand_minus)
 
286
                                {
 
287
                                        if (sip1->from == (sip2->to + 1))  /* they are adjacent */
 
288
                                        {
 
289
                                                sip1->from = sip2->from;
 
290
                                                sip1->if_from = IntFuzzFree(sip1->if_from);
 
291
                                                if (sip2->if_from != NULL)   /* copy the fuzz */
 
292
                                                {
 
293
                                                        if (do_copy)
 
294
                                                                sip1->if_from = (IntFuzzPtr)AsnIoMemCopy((Pointer)(sip2->if_from),
 
295
                                                                    (AsnReadFunc)IntFuzzAsnRead, (AsnWriteFunc)IntFuzzAsnWrite);
 
296
                                                        else
 
297
                                                        {
 
298
                                                                sip1->if_from = sip2->if_from;
 
299
                                                                sip2->if_from = NULL;
 
300
                                                        }
 
301
                                                        sip1->strand = strand;
 
302
                                                }
 
303
                                                merged = TRUE;
 
304
                                        }
 
305
                                }
 
306
                                else
 
307
                                {
 
308
                                        if (sip1->to == (sip2->from - 1))  /* they are adjacent */
 
309
                                        {
 
310
                                                sip1->to = sip2->to;
 
311
                                                sip1->if_to = IntFuzzFree(sip1->if_to);
 
312
                                                if (sip2->if_to != NULL)   /* copy the fuzz */
 
313
                                                {
 
314
                                                        if (do_copy)
 
315
                                                                sip1->if_to = (IntFuzzPtr)AsnIoMemCopy((Pointer)(sip2->if_to),
 
316
                                                                    (AsnReadFunc)IntFuzzAsnRead, (AsnWriteFunc)IntFuzzAsnWrite);
 
317
                                                        else
 
318
                                                        {
 
319
                                                                sip1->if_to = sip2->if_to;
 
320
                                                                sip2->if_to = NULL;
 
321
                                                        }
 
322
                                                        sip1->strand = strand;
 
323
                                                }
 
324
                                                merged = TRUE;
 
325
                                        }
 
326
                                }
 
327
                        }
 
328
                } else if ((last->choice == SEQLOC_PNT) && (slp->choice == SEQLOC_PNT))
 
329
                {
 
330
                        SeqPntPtr sip1, sip2;
 
331
 
 
332
                        sip1 = (SeqPntPtr)(last->data.ptrvalue);
 
333
                        sip2 = (SeqPntPtr)(slp->data.ptrvalue);
 
334
                        if ((sip1->strand == sip2->strand) && sip1->point == sip2->point && (SeqIdForSameBioseq(sip1->id, sip2->id)))
 
335
                        {
 
336
                                sip1->fuzz = IntFuzzFree(sip1->fuzz);
 
337
                                if (sip2->fuzz != NULL)   /* copy the fuzz */
 
338
                                {
 
339
                                        if (do_copy)
 
340
                                                sip1->fuzz = (IntFuzzPtr)AsnIoMemCopy((Pointer)(sip2->fuzz),
 
341
                                                    (AsnReadFunc)IntFuzzAsnRead, (AsnWriteFunc)IntFuzzAsnWrite);
 
342
                                        else
 
343
                                        {
 
344
                                                sip1->fuzz = sip2->fuzz;
 
345
                                                sip2->fuzz = NULL;
 
346
                                        }
 
347
                                }
 
348
                                merged = TRUE;
 
349
                        }
 
350
                }
 
351
        }
 
352
 
 
353
ret:
 
354
        if (! merged)  /* then have to add a new one */
 
355
        {
 
356
                if (do_copy)
 
357
                        tmp = (SeqLocPtr)AsnIoMemCopy((Pointer)slp, (AsnReadFunc)SeqLocAsnRead, (AsnWriteFunc)SeqLocAsnWrite);
 
358
                else
 
359
                        tmp = slp;
 
360
 
 
361
                tmp->next = NULL;
 
362
 
 
363
                if (last != NULL)
 
364
                        last->next = tmp;
 
365
                else
 
366
                        *head = tmp;
 
367
                retval = tmp;
 
368
        }
 
369
        else
 
370
        {
 
371
                retval = last;
 
372
                if (! do_copy)   /* got to free it here */
 
373
                        SeqLocFree(slp);
 
374
        }
 
375
                
 
376
        return retval;
 
377
}
 
378
 
 
379
/*****************************************************************************
 
380
*
 
381
*   SegLocToParts(BioseqPtr seg, SeqLocPtr slp)
 
382
*       seg must be a segmented Bioseq
 
383
*       slp must be a SeqLoc on it
 
384
*       function maps slp to the components of seg
 
385
*       returns a new SeqLocPtr
 
386
*       does not delete slp
 
387
*
 
388
*****************************************************************************/
 
389
NLM_EXTERN SeqLocPtr LIBCALL SegLocToPartsEx (BioseqPtr seg, SeqLocPtr slp, Boolean nullsBetween)
 
390
{
 
391
        SeqLocPtr newloc = NULL, tmp, tmp2, tmp3, next, curr;
 
392
        ValNode thead;
 
393
        SeqIdPtr sip, tsip;
 
394
        Int4 left_end, right_end, tlen, tstart;
 
395
        SeqIntPtr sintp;
 
396
        Boolean split, notFirst = FALSE;
 
397
 
 
398
        if ((seg == NULL) || (slp == NULL)) return newloc;
 
399
        if (seg->repr != Seq_repr_seg) return newloc;
 
400
 
 
401
        sip = SeqLocId(slp);
 
402
        if (sip == NULL) return newloc;
 
403
        if (! SeqIdIn(sip, seg->id)) return newloc;
 
404
 
 
405
        MemSet(&thead, 0, sizeof(ValNode));
 
406
        thead.choice = SEQLOC_MIX;
 
407
        thead.data.ptrvalue = seg->seq_ext;
 
408
 
 
409
        curr = NULL;
 
410
        while ((curr = SeqLocFindNext(slp, curr)) != NULL)
 
411
        {
 
412
                left_end = 0;
 
413
                tmp = NULL;
 
414
                while ((tmp = SeqLocFindNext(&thead, tmp)) != NULL)
 
415
                {
 
416
                        tlen = SeqLocLen(tmp);
 
417
                        if (tlen > 0)
 
418
                        {
 
419
                                right_end = left_end + tlen - 1;
 
420
                                tsip = SeqLocId(tmp);
 
421
                                tstart = SeqLocStart(tmp);
 
422
                                tmp2 = SeqLocCopyRegion(tsip, curr, seg, left_end, right_end, SeqLocStrand(tmp),
 
423
                                        &split);
 
424
                                while (tmp2 != NULL)
 
425
                                {
 
426
                                        next = tmp2->next;
 
427
                                        tmp2->next = NULL;
 
428
                                        if (tmp2->choice == SEQLOC_INT)
 
429
                                        {
 
430
                                                if (nullsBetween  && notFirst) {
 
431
                                                        tmp3 = ValNodeNew (NULL);
 
432
                                                        if (tmp3 != NULL) {
 
433
                                                                tmp3->choice = SEQLOC_NULL;
 
434
                                                                SeqLocAdd (&newloc, tmp3, TRUE, FALSE);
 
435
                                                        }
 
436
                                                }
 
437
                                                notFirst = TRUE;
 
438
                                                sintp = (SeqIntPtr)(tmp2->data.ptrvalue);
 
439
                                                sintp->from += tstart;
 
440
                                                sintp->to += tstart;
 
441
                                                SeqLocAdd(&newloc, tmp2, TRUE, FALSE);
 
442
                                        }
 
443
                                        tmp2 = next;
 
444
                                }
 
445
                                left_end = right_end + 1;
 
446
                        }
 
447
                }
 
448
        }
 
449
 
 
450
        if (newloc != NULL)
 
451
                newloc = SeqLocPackage(newloc);
 
452
        return newloc;
 
453
}
 
454
 
 
455
NLM_EXTERN SeqLocPtr LIBCALL SegLocToParts (BioseqPtr seg, SeqLocPtr slp)
 
456
 
 
457
{
 
458
        return SegLocToPartsEx (seg, slp, FALSE);
 
459
}
 
460
 
 
461
static CharPtr seqlitdbtag = "SeqLit";
 
462
/*****************************************************************************
 
463
*
 
464
*   ISADeltaSeqsToSeqLoc(slp)
 
465
*       returns Index (> 0) if this (one) SeqLoc was converted from a Delta Seq by
 
466
*         DeltaSeqsToSeqLocs() by looking for the special Dbtag name
 
467
*
 
468
*****************************************************************************/
 
469
NLM_EXTERN Int4 LIBCALL ISADeltaSeqsToSeqLoc (SeqLocPtr slp)
 
470
{
 
471
        SeqIdPtr sip;
 
472
        Int4 retval = 0;
 
473
 
 
474
        if (slp == NULL) return retval;
 
475
        sip = SeqLocId(slp);
 
476
        if (sip == NULL) return retval;
 
477
 
 
478
        if (sip->choice != SEQID_GENERAL) return retval;
 
479
 
 
480
        if (! StringCmp(seqlitdbtag, ((DbtagPtr)(sip->data.ptrvalue))->db))
 
481
                retval = (((DbtagPtr)(sip->data.ptrvalue))->tag->id);
 
482
 
 
483
        return retval;
 
484
}
 
485
 
 
486
/*****************************************************************************
 
487
*
 
488
*   DeltaSeqsToSeqLocs(dsp)
 
489
*       converts a chain of delta seqs to seqlocs
 
490
*       each SeqLit is converted to SeqLoc of type Int with a SeqId of type
 
491
*          Dbtag where db="Seq\tLit" and objectId.id which is the index of the
 
492
*          element in the delta seq chain where 1 is the first one.
 
493
*       Returned SeqLoc is of type "mix" and must be freed by caller.
 
494
*
 
495
*****************************************************************************/
 
496
NLM_EXTERN SeqLocPtr LIBCALL DeltaSeqsToSeqLocs (DeltaSeqPtr dsp)
 
497
{
 
498
        SeqLocPtr head = NULL, thead=NULL;
 
499
        DeltaSeqPtr curr;
 
500
        SeqInt si;
 
501
        Dbtag db;
 
502
        ObjectId oi;
 
503
        ValNode vn, vn2;
 
504
 
 
505
        MemSet(&vn, 0, sizeof(ValNode));
 
506
        MemSet(&vn2, 0, sizeof(ValNode));
 
507
        MemSet(&si, 0, sizeof(SeqInt));
 
508
        MemSet(&db, 0, sizeof(Dbtag));
 
509
        MemSet(&oi, 0, sizeof(ObjectId));
 
510
        vn.choice = SEQLOC_INT;
 
511
        vn.data.ptrvalue = &si;
 
512
        si.id = &vn2;
 
513
        vn2.choice = SEQID_GENERAL;
 
514
        vn2.data.ptrvalue = &db;
 
515
        db.db = seqlitdbtag;
 
516
        db.tag = &oi;
 
517
        oi.id = 1;
 
518
 
 
519
        
 
520
        for (curr = dsp; curr != NULL; curr = curr->next)
 
521
        {
 
522
                if (curr->choice == 1)   /* a SeqLoc */
 
523
                        SeqLocAdd(&thead, (SeqLocPtr)(curr->data.ptrvalue), TRUE, TRUE);
 
524
                else
 
525
                {
 
526
                        si.to = ((SeqLitPtr)(curr->data.ptrvalue))->length - 1;
 
527
                        SeqLocAdd(&thead, &vn, TRUE, TRUE); 
 
528
                }
 
529
                oi.id++;
 
530
        }
 
531
 
 
532
        head = SeqLocPackage(thead);
 
533
        return head;
 
534
}
 
535
 
 
536
/*****************************************************************************
 
537
* GOHERE
 
538
*   SeqLocsToDeltaSeqs(dsp, slp)
 
539
*       converts a chain of seqlocs     generated by DeltaSeqToSeqLocs() back into
 
540
*         delta seqs. dsp is the original chain of DeltaSeqs, which is required
 
541
*         to convert the delta seqs back.
 
542
*
 
543
*****************************************************************************/
 
544
NLM_EXTERN DeltaSeqPtr LIBCALL SeqLocsToDeltaSeqs (DeltaSeqPtr dsp, SeqLocPtr slp)
 
545
{
 
546
        DeltaSeqPtr dhead=NULL, dcurr=NULL, dtmp;
 
547
        SeqLocPtr scurr;
 
548
        Int4 ctr, index, strt, stp;
 
549
        SeqIdPtr sip;
 
550
        Uint1 strand, newcode;
 
551
        SeqLitPtr slitp, slitp_new;
 
552
        SeqPortPtr spps;
 
553
        ByteStorePtr bsp;
 
554
        Int2 residue;
 
555
        ValNode vn;
 
556
 
 
557
        if ((dsp == NULL) || (slp == NULL))
 
558
                return dhead;
 
559
 
 
560
        vn.choice = SEQLOC_MIX;
 
561
        vn.next = NULL;
 
562
        vn.data.ptrvalue = slp;
 
563
        scurr = NULL;
 
564
        while ((scurr = SeqLocFindNext(&vn, scurr)) != NULL)
 
565
        {
 
566
                dcurr = ValNodeNew(dhead);
 
567
                if (dhead == NULL)
 
568
                        dhead = dcurr;
 
569
 
 
570
                index = ISADeltaSeqsToSeqLoc(scurr);
 
571
 
 
572
                if (index == 0)   /* just a SeqLoc */
 
573
                {
 
574
                        dcurr->choice = 1;
 
575
                        dcurr->data.ptrvalue = NULL;
 
576
                        dcurr->data.ptrvalue = AsnIoMemCopy((Pointer)scurr, (AsnReadFunc)SeqLocAsnRead, (AsnWriteFunc)SeqLocAsnWrite);
 
577
 
 
578
                }
 
579
                else                                 /* convert to a delta seq */
 
580
                {
 
581
                        dcurr->choice = 2;
 
582
                        sip = SeqLocId(scurr);
 
583
                        dtmp = dsp;
 
584
                        for (ctr = 1; ctr < index; ctr++)
 
585
                                dtmp = dtmp->next;
 
586
 
 
587
                        if (dtmp->choice != 2)   /* wups */
 
588
                        {
 
589
                                ErrPostEx(SEV_ERROR,0,0,"Wrong type in SeqLocsToDeltaSeqs");
 
590
                                dhead = DeltaSeqFree(dhead);
 
591
                                return dhead;
 
592
                        }
 
593
                        slitp = (SeqLitPtr)(dtmp->data.ptrvalue);
 
594
 
 
595
                        strt = SeqLocStart(scurr);
 
596
                        stp = SeqLocStop(scurr);
 
597
                        strand = SeqLocStrand(scurr);
 
598
 
 
599
                        if ((strt == 0) && (stp == (slitp->length - 1)) && (strand != Seq_strand_minus))  /* no change */
 
600
                        {
 
601
                                dcurr->data.ptrvalue = AsnIoMemCopy((Pointer)slitp, (AsnReadFunc)SeqLitAsnRead, (AsnWriteFunc)SeqLitAsnWrite);
 
602
                        }
 
603
                        else   /* got to copy part of it */
 
604
                        {
 
605
                                switch (slitp->seq_data_type)
 
606
                                {
 
607
                                        case Seq_code_iupacna:
 
608
                                        case Seq_code_iupacaa:
 
609
                                        case Seq_code_ncbi8na:
 
610
                                        case Seq_code_ncbi8aa:
 
611
                                        case Seq_code_ncbieaa:
 
612
                                        case Seq_code_ncbistdaa:
 
613
                                        case Seq_code_iupacaa3:
 
614
                                                newcode = slitp->seq_data_type;     /* one byte codes.. fine */
 
615
                                                break;
 
616
                                        case Seq_code_ncbipna:
 
617
                                                ErrPostEx(SEV_ERROR,0,0,"Converting from P residue codes");
 
618
                                                newcode = Seq_code_ncbieaa;
 
619
                                                break;
 
620
                                        case Seq_code_ncbipaa:
 
621
                                                ErrPostEx(SEV_ERROR,0,0,"Converting from P residue codes");
 
622
                                        case Seq_code_ncbi2na:
 
623
                                        case Seq_code_ncbi4na:
 
624
                                                newcode = Seq_code_iupacna;
 
625
                                                break;
 
626
                                        default:
 
627
                                                ErrPostEx(SEV_FATAL,0,0,"Unrecognized residue code [%d] in SeqLocsToDeltaSeqs",
 
628
                                                        (int)(slitp->seq_data_type));
 
629
                                                return DeltaSeqFree(dhead);
 
630
                                }
 
631
                                spps = MemNew(sizeof(SeqPort));
 
632
                                SeqPortSetUpFields (spps, strt, stp, strand, newcode);
 
633
                                SeqPortSetUpAlphabet(spps, slitp->seq_data_type, newcode);
 
634
                                spps->bp = slitp->seq_data;
 
635
                                slitp_new = SeqLitNew();
 
636
                                dcurr->data.ptrvalue = slitp_new;
 
637
                                slitp_new->seq_data_type = newcode;
 
638
                                slitp_new->length = (stp - strt + 1);
 
639
                                bsp = BSNew(slitp_new->length);
 
640
                                slitp_new->seq_data = bsp;
 
641
                                SeqPortSeek(spps, 0, SEEK_SET);
 
642
                                BSSeek(bsp, 0, SEEK_SET);
 
643
                            while (stp >= strt)
 
644
                                {
 
645
                                        residue = SeqPortGetResidue(spps);
 
646
                                        BSPutByte(bsp, residue);
 
647
                                        strt++;
 
648
                                }
 
649
                                SeqPortFree(spps);
 
650
                        }
 
651
 
 
652
                }
 
653
 
 
654
        }
 
655
        return dhead;
 
656
}
 
657
/*****************************************************************************
 
658
*
 
659
*   BioseqDelete (target, from, to, do_feat, do_split)
 
660
*      Deletes the region of sequence between from-to, inclusive, on the
 
661
*        Bioseq whose SeqId is target.
 
662
*      If do_feat, the feature table is updated to reflect the deletion
 
663
*        using SeqEntryDelFeat()
 
664
*      If do_split, the features across the deleted region are split into
 
665
*        two intervals on either side. If not, the feature is just shortened.
 
666
*****************************************************************************/
 
667
NLM_EXTERN Boolean LIBCALL BioseqDelete (SeqIdPtr target, Int4 from, Int4 to, Boolean do_feat, Boolean do_split)
 
668
{
 
669
        Boolean retval = FALSE;
 
670
        BioseqPtr bsp;
 
671
        SeqLocPtr tmp, head;
 
672
        Int4 len, deleted;
 
673
        Int4 totlen, templen, tfrom, tto, diff1, diff2;
 
674
        SeqLocPtr slp, tloc, newhead, prev;
 
675
        ValNode vn;
 
676
        SeqInt si;
 
677
        SeqLocPtr PNTR newheadptr;
 
678
        SeqFeatPtr sfpcurr, sfpnext, sfpprev;
 
679
        Int2 dropped;
 
680
        SeqEntryPtr oldscope;
 
681
        DeltaSeqPtr tdsp;
 
682
 
 
683
        bsp = BioseqFind(target);
 
684
        if (bsp == NULL) {
 
685
                oldscope = SeqEntrySetScope (NULL);
 
686
                if (oldscope != NULL) {
 
687
                        bsp = BioseqFind(target);
 
688
                        SeqEntrySetScope (oldscope);
 
689
                }
 
690
        }
 
691
        if (bsp == NULL) return retval;
 
692
 
 
693
        if ((from < 0) || (from >= bsp->length) || (to < 0) ||
 
694
                (to >= bsp->length) || (from > to)) return retval;
 
695
 
 
696
        if (do_feat)
 
697
                SeqEntryDelFeat(NULL, target, from, to, do_split);
 
698
 
 
699
        len = to - from + 1;
 
700
                   /* if actual sequence present */
 
701
 
 
702
        if ((bsp->repr == Seq_repr_raw) || (bsp->repr == Seq_repr_const))
 
703
        {
 
704
                if (ISA_na(bsp->mol))
 
705
                {
 
706
                        if (bsp->seq_data_type != Seq_code_iupacna)  /* need 1 byte/base */
 
707
                                BioseqRawConvert(bsp, Seq_code_iupacna);
 
708
                }
 
709
                else
 
710
                {
 
711
                        if (bsp->seq_data_type != Seq_code_ncbieaa)
 
712
                                BioseqRawConvert(bsp, Seq_code_ncbieaa);
 
713
                }
 
714
 
 
715
                BSSeek(bsp->seq_data, from, SEEK_SET);
 
716
                deleted = BSDelete(bsp->seq_data, len);
 
717
                if (deleted != len)  /* error */
 
718
                        ErrPost(CTX_NCBIOBJ, 1, "Delete of %ld residues failed", len);
 
719
                else
 
720
                        retval = TRUE;
 
721
        }
 
722
 
 
723
                           /* update segmented sequence */
 
724
        if ((bsp->repr == Seq_repr_seg) || (bsp->repr == Seq_repr_delta))
 
725
        {
 
726
                head = ValNodeNew(NULL);  /* allocate to facilitate SeqLocFree */
 
727
                head->choice = SEQLOC_MIX;   /* make a SeqLoc out of the extension */
 
728
                if (bsp->repr == Seq_repr_seg)
 
729
                        head->data.ptrvalue = bsp->seq_ext;
 
730
                else
 
731
                {
 
732
                        tdsp = (DeltaSeqPtr)(bsp->seq_ext);
 
733
                        head->data.ptrvalue = DeltaSeqsToSeqLocs(tdsp);
 
734
                }
 
735
                
 
736
                newhead = NULL;
 
737
                newheadptr = &newhead;
 
738
 
 
739
                tloc = &vn;
 
740
                MemSet((Pointer)tloc, 0, sizeof(ValNode));
 
741
                MemSet((Pointer)&si, 0, sizeof(SeqInt));
 
742
                tloc->choice = SEQLOC_INT;
 
743
                tloc->data.ptrvalue = (Pointer)(&si);
 
744
                
 
745
                slp = NULL;
 
746
                totlen = 0;
 
747
                while ((slp = SeqLocFindNext(head, slp)) != NULL)
 
748
                {
 
749
                        templen = SeqLocLen(slp);
 
750
                    tfrom = SeqLocStart(slp);
 
751
                        tto = SeqLocStop(slp);
 
752
                        
 
753
                        if (((totlen + templen - 1) < from) ||   /* before cut */
 
754
                                (totlen > to))                                            /* after cut */
 
755
                                tmp = SeqLocAdd(newheadptr, slp, TRUE, TRUE); /* add whole SeqLoc */
 
756
                        else                            
 
757
                        {
 
758
                                retval = 1;    /* will modify or drop interval */
 
759
                                diff1 = from - totlen;        /* partial beginning? */
 
760
                                diff2 = (templen + totlen - 1) - to;  /* partial end? */
 
761
                                si.id = SeqLocId(slp);
 
762
                                si.strand = SeqLocStrand(slp);
 
763
                                
 
764
                                if (diff1 > 0)    /* partial start */
 
765
                                {
 
766
                                        if (si.strand != Seq_strand_minus)
 
767
                                        {
 
768
                                           si.from = tfrom;
 
769
                                           si.to = tfrom + diff1 - 1;
 
770
                                        }
 
771
                                        else
 
772
                                        {
 
773
                                                si.from = tto - diff1 + 1;
 
774
                                                si.to = tto;
 
775
                                        }
 
776
                                        tmp = SeqLocAdd(newheadptr, tloc, TRUE, TRUE);
 
777
                                }
 
778
 
 
779
                                if (diff2 > 0)    /* partial end */
 
780
                                {
 
781
                                        if (si.strand != Seq_strand_minus)
 
782
                                        {
 
783
                                           si.from = tto - diff2 + 1;
 
784
                                           si.to = tto;
 
785
                                        }
 
786
                                        else
 
787
                                        {
 
788
                                                si.from = tfrom;
 
789
                                                si.to = tfrom + diff2 - 1;
 
790
                                        }
 
791
                                        tmp = SeqLocAdd(newheadptr, tloc, TRUE, TRUE);
 
792
                                }
 
793
                                
 
794
                        }
 
795
                        totlen += templen;
 
796
                }
 
797
 
 
798
                prev = NULL;
 
799
                for (tmp = newhead; tmp != NULL; tmp = tmp->next)
 
800
                {
 
801
                        if (tmp->next == NULL)   /* last one */
 
802
                        {
 
803
                                if (tmp->choice == SEQLOC_NULL)
 
804
                                {
 
805
                                        if (prev != NULL)
 
806
                                                prev->next = NULL;
 
807
                                        else                              /* only a NULL left */
 
808
                                        {
 
809
                                                newhead = NULL;
 
810
                                        }
 
811
                                        MemFree(tmp);
 
812
                                        break;
 
813
                                }
 
814
                        }
 
815
                        prev = tmp;
 
816
                }
 
817
 
 
818
                if (bsp->repr == Seq_repr_seg)
 
819
                        bsp->seq_ext = newhead;
 
820
                else
 
821
                {
 
822
                        bsp->seq_ext = SeqLocsToDeltaSeqs(tdsp, newhead);
 
823
                        DeltaSeqSetFree(tdsp);
 
824
                        SeqLocSetFree(newhead);
 
825
                }
 
826
                SeqLocFree(head);
 
827
                retval = TRUE;
 
828
        }
 
829
 
 
830
        if (bsp->repr == Seq_repr_map)      /* map bioseq */
 
831
        {
 
832
                sfpprev = NULL;
 
833
                sfpnext = NULL;
 
834
                sfpcurr = (SeqFeatPtr)(bsp->seq_ext);
 
835
                bsp->seq_ext = NULL;
 
836
                for (; sfpcurr != NULL; sfpcurr = sfpnext)
 
837
                {
 
838
                        sfpnext = sfpcurr->next;
 
839
                        dropped = SeqFeatDelete(sfpcurr, target, from, to, TRUE);
 
840
                        if (dropped == 2)   /* completely gone */
 
841
                        {
 
842
                                SeqFeatFree(sfpcurr);
 
843
                        }
 
844
                        else
 
845
                        {
 
846
                                if (sfpprev == NULL)
 
847
                                        bsp->seq_ext = (Pointer)sfpcurr;
 
848
                                else
 
849
                                        sfpprev->next = sfpcurr;
 
850
                                sfpcurr->next = NULL;
 
851
                                sfpprev = sfpcurr;
 
852
                        }
 
853
                }
 
854
                retval = TRUE;
 
855
        }
 
856
 
 
857
        if (bsp->repr == Seq_repr_virtual)
 
858
                retval = TRUE;                 /* nothing to do */
 
859
 
 
860
        if (retval)
 
861
                bsp->length -= len;
 
862
        return retval;
 
863
}
 
864
 
 
865
 
 
866
/*****************************************************************************
 
867
*
 
868
*   BioseqOverwrite (target, pos, residue, seqcode)
 
869
*      Overwrites the residue at pos with residue in the
 
870
*        Bioseq whose SeqId is target.
 
871
*      residue is iupacna for DNA or ncbieaa for protein
 
872
*      target MUST be a raw Bioseq right now
 
873
*
 
874
*****************************************************************************/
 
875
NLM_EXTERN Boolean LIBCALL BioseqOverwrite (SeqIdPtr target, Int4 pos, Uint1 residue)
 
876
{
 
877
        BioseqPtr bsp;
 
878
        Boolean retval = FALSE;
 
879
        SeqEntryPtr oldscope;
 
880
 
 
881
 
 
882
        bsp = BioseqFind(target);
 
883
        if (bsp == NULL) {
 
884
                oldscope = SeqEntrySetScope (NULL);
 
885
                if (oldscope != NULL) {
 
886
                        bsp = BioseqFind(target);
 
887
                        SeqEntrySetScope (oldscope);
 
888
                }
 
889
        }
 
890
        if (bsp == NULL) return retval;
 
891
 
 
892
        if ((pos < 0) || (pos >= bsp->length)) return retval;
 
893
        if (bsp->repr != Seq_repr_raw) return retval;
 
894
 
 
895
        if (ISA_na(bsp->mol))
 
896
        {
 
897
                if (bsp->seq_data_type != Seq_code_iupacna)  /* need 1 byte/base */
 
898
                        BioseqRawConvert(bsp, Seq_code_iupacna);
 
899
        }
 
900
        else
 
901
        {
 
902
                if (bsp->seq_data_type != Seq_code_ncbieaa)
 
903
                        BioseqRawConvert(bsp, Seq_code_ncbieaa);
 
904
        }
 
905
 
 
906
        BSSeek(bsp->seq_data, pos, SEEK_SET);
 
907
        BSPutByte(bsp->seq_data, (Int2)(TO_UPPER(residue)));
 
908
        retval = TRUE;
 
909
 
 
910
        return retval;
 
911
}
 
912
 
 
913
 
 
914
/*****************************************************************************
 
915
*
 
916
*   SeqInsertByLoc (target, offset, fragment)
 
917
*
 
918
*****************************************************************************/
 
919
NLM_EXTERN Boolean LIBCALL SeqInsertByLoc (SeqIdPtr target, Int4 offset, SeqLocPtr fragment)
 
920
{
 
921
        return TRUE;
 
922
}
 
923
 
 
924
 
 
925
/*****************************************************************************
 
926
*
 
927
*   SeqDeleteByLoc (slp, do_feat, do_split)
 
928
*
 
929
*****************************************************************************/
 
930
NLM_EXTERN Boolean LIBCALL SeqDeleteByLoc (SeqLocPtr slp, Boolean do_feat, Boolean do_split)
 
931
{
 
932
        SeqLocPtr tmp;
 
933
        Boolean retval = FALSE;
 
934
        Int2 numloc, i = 0, ctr, pick, totloc;
 
935
        SeqLocPtr PNTR locs, PNTR tlocs, PNTR theorder;
 
936
        SeqIdPtr the_id = NULL;
 
937
        BioseqPtr bsp;
 
938
        Int4 tstart, tstop;
 
939
 
 
940
        if (slp == NULL) return retval;
 
941
 
 
942
        numloc = 0;
 
943
        totloc = 0;
 
944
        locs = NULL;
 
945
        tmp = NULL;
 
946
 
 
947
        while ((tmp = SeqLocFindNext(slp, tmp)) != NULL)
 
948
        {
 
949
                switch (tmp->choice)
 
950
                {
 
951
                        case SEQLOC_INT:
 
952
                        case SEQLOC_PNT:
 
953
                                if (BioseqFind(SeqLocId(tmp)) != NULL)
 
954
                                {
 
955
                                        if (numloc == totloc)
 
956
                                        {
 
957
                                                tlocs = locs;
 
958
                                                locs = (SeqLocPtr PNTR)(MemNew((totloc+20) * sizeof(SeqLocPtr)));
 
959
                                                MemCopy(locs, tlocs, (size_t)(totloc * sizeof(SeqLocPtr)));
 
960
                                                MemFree(tlocs);
 
961
                                                totloc += 20;
 
962
                                        }
 
963
                                        locs[numloc] = tmp;
 
964
                                        numloc++;
 
965
                                }
 
966
                                break;
 
967
                        default:
 
968
                                Message(MSG_ERROR, "Unsupported Seqloc [%d] in SeqDeleteByLoc",
 
969
                                        (int)(tmp->choice));
 
970
                                break;
 
971
 
 
972
                }
 
973
        }
 
974
 
 
975
        if (! numloc) return retval;
 
976
 
 
977
                      
 
978
                                /***********************************************************
 
979
                                *
 
980
                                *   first gather all the seqlocs, grouped by Bioseq, and
 
981
                                *   ordered from end to beginning. They must be ordered
 
982
                                *   before the underlying Bioseq is changed.
 
983
                                *
 
984
                                ***********************************************************/
 
985
 
 
986
        retval = TRUE;
 
987
 
 
988
        bsp = NULL;
 
989
        theorder = (SeqLocPtr PNTR)MemNew((sizeof(SeqLocPtr) * numloc));
 
990
        for (ctr = 0; ctr < numloc; ctr++)
 
991
        {
 
992
                pick = -1;   /* flag none found */
 
993
                if (bsp != NULL)
 
994
                {
 
995
                        for (i = 0; i < numloc; i++)
 
996
                        {
 
997
                                if (locs[i] != NULL)
 
998
                                {
 
999
                                        if (SeqIdIn(SeqLocId(locs[i]), bsp->id))
 
1000
                                        {
 
1001
                                                pick = i;
 
1002
                                                i++;
 
1003
                                                break;
 
1004
                                        }
 
1005
                                }
 
1006
                        }
 
1007
                        if (pick < 0)
 
1008
                                bsp = NULL;   /* no more locs on this bioseq */
 
1009
                }
 
1010
 
 
1011
                if (bsp == NULL)  /* have to find a new bioseq */
 
1012
                {
 
1013
                        for (i = 0; i < numloc; i++)
 
1014
                        {
 
1015
                                if (locs[i] != NULL)
 
1016
                                {
 
1017
                                        bsp = BioseqFind(SeqLocId(locs[i]));
 
1018
                                        pick = i;
 
1019
                                        i++;
 
1020
                                        break;
 
1021
                                }
 
1022
                        }
 
1023
                }
 
1024
 
 
1025
                while (i < numloc)
 
1026
                {
 
1027
                        if (SeqLocOrder(locs[pick], locs[i], bsp) == (-1)) /* it's after */
 
1028
                                pick = i;
 
1029
                        i++;
 
1030
                }
 
1031
 
 
1032
                theorder[ctr] = locs[pick];
 
1033
                locs[pick] = NULL;
 
1034
        }
 
1035
 
 
1036
        MemFree(locs);   /* finished with original list */
 
1037
 
 
1038
                                /*************************************************************
 
1039
                                *
 
1040
                                *   Now do the actual deletions
 
1041
                                *
 
1042
                                *************************************************************/
 
1043
 
 
1044
 
 
1045
        for (ctr = 0; ctr < numloc; ctr++)
 
1046
        {
 
1047
                tstart = SeqLocStart(theorder[ctr]);
 
1048
                tstop = SeqLocStop(theorder[ctr]);
 
1049
                BioseqDelete(SeqLocId(theorder[ctr]), tstart, tstop, do_feat, do_split);
 
1050
        }
 
1051
 
 
1052
        MemFree(theorder);
 
1053
 
 
1054
        return retval;
 
1055
}
 
1056
 
 
1057
 
 
1058
/*****************************************************************************
 
1059
*
 
1060
*   SeqFeatDelete()
 
1061
*     0 = no changes made to location or product
 
1062
*     1 = changes made but feature still has some location
 
1063
*     2 = all of sfp->location in deleted interval
 
1064
*
 
1065
*   if (merge)
 
1066
*      1) correct numbers > to by subtraction
 
1067
*      2) do not split intervals spanning the deletion
 
1068
*   else
 
1069
*      1) do not change numbers > to
 
1070
*      2) split intervals which span the deletions
 
1071
*
 
1072
*****************************************************************************/
 
1073
NLM_EXTERN Int2 LIBCALL SeqFeatDelete (SeqFeatPtr sfp, SeqIdPtr target, Int4 from, Int4 to, Boolean merge)
 
1074
{
 
1075
        ValNode vn;
 
1076
        SeqLocPtr tloc;
 
1077
        SeqInt si;
 
1078
        Boolean changed = FALSE, tmpbool = FALSE;
 
1079
        CdRegionPtr crp;
 
1080
        CodeBreakPtr cbp, prevcbp, nextcbp;
 
1081
        RnaRefPtr rrp;
 
1082
        tRNAPtr trp;
 
1083
 
 
1084
        tloc = &vn;
 
1085
        MemSet((Pointer)tloc, 0, sizeof(ValNode));
 
1086
        MemSet((Pointer)&si, 0, sizeof(SeqInt));
 
1087
        tloc->choice = SEQLOC_INT;
 
1088
        tloc->data.ptrvalue = (Pointer)(&si);
 
1089
        si.id = target;
 
1090
        si.from = from;
 
1091
        si.to = to;
 
1092
 
 
1093
        sfp->location = SeqLocDelete(sfp->location, target, from, to, merge, &changed);
 
1094
 
 
1095
        sfp->product = SeqLocDelete(sfp->product, target, from, to, merge, &changed);
 
1096
 
 
1097
        if (sfp->location == NULL)
 
1098
                return 2;
 
1099
 
 
1100
        switch (sfp->data.choice)
 
1101
        {
 
1102
                case SEQFEAT_CDREGION:   /* cdregion */
 
1103
                        crp = (CdRegionPtr)(sfp->data.value.ptrvalue);
 
1104
                        prevcbp = NULL;
 
1105
                        for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp)
 
1106
                        {
 
1107
                                nextcbp = cbp->next;
 
1108
                                cbp->loc = SeqLocDelete(cbp->loc, target, from, to, merge, &tmpbool);
 
1109
                                if (cbp->loc == NULL)
 
1110
                                {
 
1111
                                        if (prevcbp != NULL)
 
1112
                                                prevcbp->next = nextcbp;
 
1113
                                        else
 
1114
                                                crp->code_break = nextcbp;
 
1115
                                        cbp->next = NULL;
 
1116
                                        CodeBreakFree(cbp);
 
1117
                                }
 
1118
                                else
 
1119
                                        prevcbp = cbp;
 
1120
                        }
 
1121
                        break;
 
1122
                case SEQFEAT_RNA:
 
1123
                        rrp = (RnaRefPtr)(sfp->data.value.ptrvalue);
 
1124
                        if (rrp->ext.choice == 2)   /* tRNA */
 
1125
                        {
 
1126
                                trp = (tRNAPtr)(rrp->ext.value.ptrvalue);
 
1127
                                if (trp->anticodon != NULL)
 
1128
                                {
 
1129
                                        trp->anticodon = SeqLocDelete(trp->anticodon, target, from, to, merge, &tmpbool);
 
1130
                                }
 
1131
                        }
 
1132
                        break;
 
1133
                default:
 
1134
                        break;
 
1135
        }
 
1136
                        
 
1137
        if (changed)
 
1138
        {
 
1139
                sfp->partial = TRUE;
 
1140
                return 1;
 
1141
        }
 
1142
        else
 
1143
                return 0;
 
1144
}
 
1145
 
 
1146
/*****************************************************************************
 
1147
*
 
1148
*   SeqLocDelete()
 
1149
*       returns altered head or NULL if nothing left.
 
1150
*   sets changed=TRUE if all or part of loc is deleted
 
1151
*   does NOT set changed if location coordinates are only moved
 
1152
*   if (merge) then corrects coordinates upstream of to
 
1153
*   else
 
1154
*     splits intervals covering from-to, does not correct upstream of to
 
1155
*
 
1156
*****************************************************************************/
 
1157
NLM_EXTERN SeqLocPtr LIBCALL SeqLocDelete (SeqLocPtr head, SeqIdPtr target, Int4 from, Int4 to, Boolean merge, BoolPtr changed)
 
1158
{
 
1159
        SeqIntPtr sip, sip2;
 
1160
        SeqPntPtr spp;
 
1161
        PackSeqPntPtr pspp, pspp2;
 
1162
        SeqBondPtr sbp;
 
1163
        SeqIdPtr sidp;
 
1164
        SeqLocPtr slp, tmp, prev, next, thead;
 
1165
        Int4 diff, numpnt, i, tpos;
 
1166
        BioseqPtr bsp;
 
1167
 
 
1168
        if ((head == NULL) || (target == NULL))
 
1169
                return head;
 
1170
 
 
1171
        head->next = NULL;   /* caller maintains chains */
 
1172
        diff = to - from + 1;
 
1173
        
 
1174
    switch (head->choice)
 
1175
    {
 
1176
        case SEQLOC_BOND:   /* bond -- 2 seqs */
 
1177
                        sbp = (SeqBondPtr)(head->data.ptrvalue);
 
1178
                        spp = sbp->a;
 
1179
                        if (SeqIdForSameBioseq(spp->id, target))
 
1180
                        {
 
1181
                                if (spp->point >= from)
 
1182
                                {
 
1183
                                        if (spp->point <= to)   /* delete it */
 
1184
                                        {
 
1185
                                            *changed = TRUE;
 
1186
                                                sbp->a = SeqPntFree(spp);
 
1187
                                        }
 
1188
                                        else if (merge)
 
1189
                                                spp->point -= diff;
 
1190
                                }
 
1191
                        }
 
1192
                        spp = sbp->b;
 
1193
                        if (spp != NULL)
 
1194
                        {
 
1195
                                if (SeqIdForSameBioseq(spp->id, target))
 
1196
                                {
 
1197
                                        if (spp->point >= from)
 
1198
                                        {
 
1199
                                                if (spp->point <= to)   /* delete it */
 
1200
                                                {
 
1201
                                                    *changed = TRUE;
 
1202
                                                        sbp->b = SeqPntFree(spp);
 
1203
                                                }
 
1204
                                                else if (merge)
 
1205
                                                        spp->point -= diff;
 
1206
                                        }
 
1207
                                }
 
1208
                        }
 
1209
                        if (sbp->a == NULL)
 
1210
                        {
 
1211
                                if (sbp->b != NULL)   /* only a required */
 
1212
                                {
 
1213
                                        sbp->a = sbp->b;
 
1214
                                        sbp->b = NULL;
 
1215
                                }
 
1216
                                else
 
1217
                                {
 
1218
                                        head = SeqLocFree(head);
 
1219
                                }
 
1220
                        }
 
1221
                        break;
 
1222
        case SEQLOC_FEAT:   /* feat -- can't track yet */
 
1223
        case SEQLOC_NULL:    /* NULL */
 
1224
        case SEQLOC_EMPTY:    /* empty */
 
1225
                        break;
 
1226
        case SEQLOC_WHOLE:    /* whole */
 
1227
                        sidp = (SeqIdPtr)(head->data.ptrvalue);
 
1228
                        if (SeqIdForSameBioseq(sidp, target))
 
1229
                        {
 
1230
                                bsp = BioseqFind(target);
 
1231
                                if (bsp != NULL)           /* split it */
 
1232
                                {
 
1233
                                        if ((from == 0) && (to >= (bsp->length - 1)))
 
1234
                                        {                                          /* complete delete */
 
1235
                                                head = SeqLocFree(head);
 
1236
                                                *changed = TRUE;
 
1237
                                                break;
 
1238
                                        }
 
1239
 
 
1240
                                        if (! merge)   /* split it up */
 
1241
                                        {
 
1242
                                                SeqIdFree(sidp);
 
1243
                                                head->choice = SEQLOC_PACKED_INT;
 
1244
                                                head->data.ptrvalue = NULL;
 
1245
                                                slp = NULL;
 
1246
                                                if (from != 0)
 
1247
                                                {
 
1248
                                                        sip = SeqIntNew();
 
1249
                                                        sip->from = 0;
 
1250
                                                        sip->to = from - 1;
 
1251
                                                        sip->id = SeqIdDup(target);
 
1252
                                                        slp = ValNodeNew(NULL);
 
1253
                                                        slp->choice = SEQLOC_INT;
 
1254
                                                        slp->data.ptrvalue = sip;
 
1255
                                                        head->data.ptrvalue = slp;
 
1256
                                                        *changed = TRUE;
 
1257
                                                }
 
1258
                                                if (to < (bsp->length - 1))
 
1259
                                                {
 
1260
                                                        sip = SeqIntNew();
 
1261
                                                        sip->from = to + 1;
 
1262
                                                        sip->to = bsp->length - 1;
 
1263
                                                        sip->id = SeqIdDup(target);
 
1264
                                                        tmp = ValNodeNew(NULL);
 
1265
                                                        tmp->choice = SEQLOC_INT;
 
1266
                                                        tmp->data.ptrvalue = sip;
 
1267
                                                        if (slp != NULL)
 
1268
                                                                slp->next = tmp;
 
1269
                                                        else
 
1270
                                                                head->data.ptrvalue = tmp;
 
1271
                                                        *changed = TRUE;
 
1272
                                                }
 
1273
 
 
1274
                                        }
 
1275
                                }
 
1276
                        }
 
1277
                        break;
 
1278
        case SEQLOC_MIX:    /* mix -- more than one seq */
 
1279
        case SEQLOC_EQUIV:    /* equiv -- ditto */
 
1280
        case SEQLOC_PACKED_INT:    /* packed int */
 
1281
                        prev = NULL;
 
1282
                        thead = NULL;
 
1283
                        for (slp = (SeqLocPtr)(head->data.ptrvalue); slp != NULL; slp = next)
 
1284
                        {
 
1285
                                next = slp->next;
 
1286
                                tmp = SeqLocDelete(slp, target, from, to, merge, changed);
 
1287
                                if (tmp != NULL)
 
1288
                                {
 
1289
                                        if (prev != NULL)
 
1290
                                        {
 
1291
                                                if ((merge) && (prev->choice == SEQLOC_INT) && (tmp->choice == SEQLOC_INT))
 
1292
                                                {
 
1293
                                                        sip = (SeqIntPtr)(prev->data.ptrvalue);
 
1294
                                                        sip2 = (SeqIntPtr)(tmp->data.ptrvalue);
 
1295
 
 
1296
                                                        if (SeqIdForSameBioseq(sip->id, sip2->id))
 
1297
                                                        {
 
1298
                                                                 /* merge intervals? */
 
1299
                                                                if ((sip->strand == Seq_strand_minus) &&
 
1300
                                                                        (sip2->strand == Seq_strand_minus))
 
1301
                                                                {
 
1302
                                                                        if (sip->from == (sip2->to + 1))
 
1303
                                                                        {
 
1304
                                                                                sip->from = sip2->from;
 
1305
                                                                                sip->if_from = sip2->if_from;
 
1306
                                                                                sip2->if_from = NULL;
 
1307
                                                                                tmp = SeqLocFree(tmp);
 
1308
                                                                        }
 
1309
                                                                }
 
1310
                                                                else if((sip->strand != Seq_strand_minus) &&
 
1311
                                                                        (sip2->strand != Seq_strand_minus))
 
1312
                                                                {
 
1313
                                                                        if (sip->to == (sip2->from - 1))
 
1314
                                                                        {
 
1315
                                                                                sip->to = sip2->to;
 
1316
                                                                                sip->if_to = sip2->if_to;
 
1317
                                                                                sip2->if_to = NULL;
 
1318
                                                                                tmp = SeqLocFree(tmp);
 
1319
                                                                        }
 
1320
                                                                }
 
1321
                                                        }
 
1322
                                                }
 
1323
                                                else if ((prev->choice == SEQLOC_NULL) && (tmp->choice == SEQLOC_NULL))
 
1324
                                                {
 
1325
                                                        tmp = SeqLocFree(tmp);
 
1326
                                                        *changed = TRUE;
 
1327
                                                }
 
1328
                                        }
 
1329
                                        else if (tmp->choice == SEQLOC_NULL)
 
1330
                                        {
 
1331
                                                tmp = SeqLocFree(tmp);
 
1332
                                                *changed = TRUE;
 
1333
                                        }
 
1334
 
 
1335
                                        if (tmp != NULL)   /* still have one? */
 
1336
                                        {
 
1337
                                                if (prev != NULL)
 
1338
                                                        prev->next = tmp;
 
1339
                                                else
 
1340
                                                        thead = tmp;
 
1341
                                                prev = tmp;
 
1342
                                        }
 
1343
                                }
 
1344
                                else
 
1345
                                        *changed = TRUE;
 
1346
                        }
 
1347
                        if (prev != NULL)
 
1348
                        {
 
1349
                                if (prev->choice == SEQLOC_NULL)  /* ends with NULL */
 
1350
                                {
 
1351
                                        prev = NULL;
 
1352
                                        for (slp = thead; slp->next != NULL; slp = slp->next)
 
1353
                                                prev = slp;
 
1354
                                        if (prev != NULL)
 
1355
                                        {
 
1356
                                                prev->next = NULL;
 
1357
                                                SeqLocFree(slp);
 
1358
                                        }
 
1359
                                        else
 
1360
                                        {
 
1361
                                                thead = SeqLocFree(thead);
 
1362
                                        }
 
1363
                                        *changed = TRUE;
 
1364
                                }
 
1365
                        }
 
1366
                        head->data.ptrvalue = thead;
 
1367
                        if (thead == NULL)
 
1368
                                head = SeqLocFree(head);
 
1369
            break;
 
1370
        case SEQLOC_INT:    /* int */
 
1371
                        sip = (SeqIntPtr)(head->data.ptrvalue);
 
1372
                        if (SeqIdForSameBioseq(sip->id, target))
 
1373
                        {
 
1374
                                if (sip->to < from)  /* completely before cut */
 
1375
                                        break;
 
1376
 
 
1377
                                                                     /* completely contained in cut */
 
1378
                                if ((sip->from >= from) && (sip->to <= to))
 
1379
                                {
 
1380
                                        head = SeqLocFree(head);
 
1381
                                        *changed = TRUE;
 
1382
                                        break;
 
1383
                                }
 
1384
 
 
1385
                                if (sip->from > to)  /* completely past cut */
 
1386
                                {
 
1387
                                        if (merge)
 
1388
                                        {
 
1389
                                                sip->from -= diff;
 
1390
                                                sip->to -= diff;
 
1391
                                        }
 
1392
                                        break;
 
1393
                                }
 
1394
                                                                        /* overlap here */
 
1395
 
 
1396
                                if (sip->to > to)
 
1397
                                {
 
1398
                                        if (merge)
 
1399
                                                sip->to -= diff;
 
1400
                                }
 
1401
                                else                /* to inside cut, so partial delete */
 
1402
                                {
 
1403
                                        sip->to = from - 1;
 
1404
                                        *changed = TRUE;
 
1405
                                }
 
1406
                
 
1407
                                if (sip->from >= from)   /* from inside cut, partial del */
 
1408
                                {
 
1409
                                        *changed = TRUE;
 
1410
                                        sip->from = to + 1;
 
1411
                                        if (merge)
 
1412
                                                sip->from -= diff;
 
1413
                                }
 
1414
 
 
1415
                                if (merge)
 
1416
                                        break;
 
1417
 
 
1418
                                                   /* interval spans cut.. only in non-merge */
 
1419
                                           /* have to split */
 
1420
 
 
1421
                                if ((sip->from < from) && (sip->to > to))
 
1422
                                {
 
1423
                                        *changed = TRUE;
 
1424
                                        head->choice = SEQLOC_PACKED_INT;
 
1425
                                        head->data.ptrvalue = NULL;
 
1426
                                        tmp = ValNodeNew(NULL);
 
1427
                                        tmp->choice = SEQLOC_INT;
 
1428
                                        tmp->data.ptrvalue = sip;
 
1429
 
 
1430
                                        sip2 = SeqIntNew();
 
1431
                                        sip2->from = to + 1;
 
1432
                                        sip2->to = sip->to;
 
1433
                                        sip2->strand = sip->strand;
 
1434
                                        sip2->if_to = sip->if_to;
 
1435
                                        sip2->id = SeqIdDup(target);
 
1436
                                        slp = ValNodeNew(NULL);
 
1437
                                        slp->choice = SEQLOC_INT;
 
1438
                                        slp->data.ptrvalue = sip2;
 
1439
 
 
1440
                                        sip->if_to = NULL;
 
1441
                                        sip->to = from - 1;
 
1442
 
 
1443
                                        if (sip->strand == Seq_strand_minus)
 
1444
                                        {
 
1445
                                                head->data.ptrvalue = slp;
 
1446
                                                slp->next = tmp;
 
1447
                                        }
 
1448
                                        else
 
1449
                                        {
 
1450
                                                head->data.ptrvalue = tmp;
 
1451
                                                tmp->next = slp;
 
1452
                                        }
 
1453
 
 
1454
                                }
 
1455
 
 
1456
                        }
 
1457
            break;
 
1458
        case SEQLOC_PNT:    /* pnt */
 
1459
                        spp = (SeqPntPtr)(head->data.ptrvalue);
 
1460
                        if (SeqIdForSameBioseq(spp->id, target))
 
1461
                        {
 
1462
                                if ((spp->point >= from) && (spp->point <= to))
 
1463
                                {
 
1464
                                        head = SeqLocFree(head);
 
1465
                                        *changed = TRUE;
 
1466
                                }
 
1467
                                else if (spp->point > to)
 
1468
                                {
 
1469
                                        if (merge)
 
1470
                                                spp->point -= diff;
 
1471
                                }
 
1472
                        }
 
1473
            break;
 
1474
        case SEQLOC_PACKED_PNT:    /* packed pnt */
 
1475
                        pspp = (PackSeqPntPtr)(head->data.ptrvalue);
 
1476
                        if (SeqIdForSameBioseq(pspp->id, target))
 
1477
                        {
 
1478
                                numpnt = PackSeqPntNum(pspp);
 
1479
                                pspp2 = PackSeqPntNew();
 
1480
                                head->data.ptrvalue = pspp2;
 
1481
                                for (i = 0; i < numpnt; i++)
 
1482
                                {
 
1483
                                        tpos = PackSeqPntGet(pspp, i);
 
1484
                                        if (tpos < from)
 
1485
                                                PackSeqPntPut(pspp2, tpos);
 
1486
                                        else
 
1487
                                        {
 
1488
                                                if (tpos > to)
 
1489
                                                {
 
1490
                                                        if (merge)
 
1491
                                                                tpos -= diff;
 
1492
                                                        PackSeqPntPut(pspp2, tpos);
 
1493
                                                }
 
1494
                                                else
 
1495
                                                        *changed = TRUE;
 
1496
                                        }
 
1497
                                }
 
1498
                                pspp2->id = pspp->id;
 
1499
                                pspp->id = NULL;
 
1500
                                pspp2->fuzz = pspp->fuzz;
 
1501
                                pspp->fuzz = NULL;
 
1502
                                pspp2->strand = pspp->strand;
 
1503
                                PackSeqPntFree(pspp);
 
1504
                                numpnt = PackSeqPntNum(pspp2);
 
1505
                                if (! numpnt)
 
1506
                                        head = SeqLocFree(head);
 
1507
 
 
1508
                        }
 
1509
            break;
 
1510
        default:
 
1511
            break;
 
1512
    }
 
1513
 
 
1514
        return head;
 
1515
}
 
1516
 
 
1517
typedef struct delstruct {
 
1518
        SeqIdPtr sip;
 
1519
        Int4 from, to;
 
1520
        Boolean merge;
 
1521
} DelStruct, PNTR DelStructPtr;
 
1522
 
 
1523
NLM_EXTERN void DelFeat (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent);
 
1524
 
 
1525
NLM_EXTERN void DelFeat (SeqEntryPtr sep, Pointer data, Int4 index, Int2 indent)
 
1526
{
 
1527
        DelStructPtr dsp;
 
1528
        BioseqPtr bsp;
 
1529
        BioseqSetPtr bssp;
 
1530
        SeqAnnotPtr sap, nextsap;
 
1531
        SeqFeatPtr sfp, nextsfp;
 
1532
        Pointer PNTR prevsap, PNTR prevsfp;
 
1533
 
 
1534
        dsp = (DelStructPtr)data;
 
1535
        if (IS_Bioseq(sep))
 
1536
        {
 
1537
                bsp = (BioseqPtr)(sep->data.ptrvalue);
 
1538
                sap = bsp->annot;
 
1539
                prevsap = (Pointer PNTR) &(bsp->annot);
 
1540
        }
 
1541
        else
 
1542
        {
 
1543
                bssp = (BioseqSetPtr)(sep->data.ptrvalue);
 
1544
                sap = bssp->annot;
 
1545
                prevsap = (Pointer PNTR) &(bssp->annot);
 
1546
        }
 
1547
 
 
1548
        while (sap != NULL)
 
1549
        {
 
1550
                nextsap = sap->next;
 
1551
                if (sap->type == 1)   /* feature table */
 
1552
                {
 
1553
                        sfp = (SeqFeatPtr) sap->data;
 
1554
                        prevsfp = (Pointer PNTR) &(sap->data);
 
1555
                        while (sfp != NULL)
 
1556
                        {
 
1557
                                nextsfp = sfp->next;
 
1558
                                if (SeqFeatDelete(sfp, dsp->sip, dsp->from, dsp->to, dsp->merge) == 2)
 
1559
                                {
 
1560
                                        /* location completely gone */
 
1561
                                        *(prevsfp) = sfp->next;
 
1562
                                        sfp->next = NULL;
 
1563
                                        SeqFeatFree(sfp);
 
1564
                                } else {
 
1565
                                        prevsfp = (Pointer PNTR) &(sfp->next);
 
1566
                                }
 
1567
                                sfp = nextsfp;
 
1568
                        }
 
1569
                }
 
1570
 
 
1571
                if (sap->data == NULL)  /* all features deleted */
 
1572
                {
 
1573
                        *(prevsap) = sap->next;
 
1574
                        sap->next = NULL;
 
1575
                        SeqAnnotFree (sap);
 
1576
                } else {
 
1577
                        prevsap = (Pointer PNTR) &(sap->next);
 
1578
                }
 
1579
 
 
1580
                sap = nextsap;
 
1581
        }
 
1582
 
 
1583
        return;
 
1584
}
 
1585
 
 
1586
/*****************************************************************************
 
1587
*
 
1588
*   SeqEntryDelFeat(sep, id, from, to, do_split)
 
1589
*       Deletes or truncates features on Bioseq (id) in the range
 
1590
*       from-to, inclusive
 
1591
*       
 
1592
*               Moves features > to left to account for decrease in length
 
1593
*       if do_split, breaks intervals across the deletion
 
1594
*       else just reduces their size
 
1595
*
 
1596
*       If sep == NULL, then calls SeqEntryFind(id) to set scope to look
 
1597
*       for features.
 
1598
*   
 
1599
*****************************************************************************/
 
1600
NLM_EXTERN Boolean      LIBCALL SeqEntryDelFeat (SeqEntryPtr sep, SeqIdPtr sip, Int4 from, Int4 to, Boolean do_split)
 
1601
{
 
1602
 
 
1603
        DelStruct ds;
 
1604
 
 
1605
        if (sip == NULL)
 
1606
                return FALSE;
 
1607
 
 
1608
        if (sep == NULL)
 
1609
                sep     = SeqEntryFind(sip);
 
1610
 
 
1611
        if (sep == NULL) return FALSE;
 
1612
 
 
1613
        ds.sip = sip;
 
1614
        ds.from = from;
 
1615
        ds.to = to;
 
1616
        if (do_split)
 
1617
                ds.merge = FALSE;
 
1618
        else
 
1619
                ds.merge = TRUE;
 
1620
 
 
1621
        SeqEntryExplore(sep, (Pointer)(&ds), DelFeat);
 
1622
 
 
1623
        return TRUE;
 
1624
}
 
1625
 
 
1626
/*****************************************************************************
 
1627
*
 
1628
*   DescrToFeatures(sep)
 
1629
*       Moves all Seqdescr to features in sep where possible
 
1630
*
 
1631
*****************************************************************************/
 
1632
 
 
1633
 
 
1634
/*****************************************************************************
 
1635
*
 
1636
*   BioseqCopy(newid, sourceid, from, to, strand, do_feat)
 
1637
*      Creates a new Bioseq from sourceid in the range from-to inclusive.
 
1638
*      If strand==Seq_strand_minus, reverse complements the sequence in
 
1639
*        the copy and (if do_feat) corrects the feature table appropriately.
 
1640
*      Names new Bioseq as newid, if not NULL
 
1641
*        else Creates seqid.local = "Clipboard" if newid is NULL
 
1642
*      If do_feat == TRUE copies appropriate region of feature table from
 
1643
*        sourceid to new copy using SeqFeatsCopy().
 
1644
*
 
1645
*****************************************************************************/
 
1646
NLM_EXTERN BioseqPtr LIBCALL BioseqCopy (SeqIdPtr newid, SeqIdPtr sourceid, Int4 from, Int4 to,
 
1647
                               Uint1 strand, Boolean do_feat)
 
1648
{
 
1649
        BioseqPtr newbsp=NULL, oldbsp, tmpbsp;
 
1650
        SeqPortPtr spp=NULL;
 
1651
        ByteStorePtr bsp;
 
1652
        Uint1 seqtype;
 
1653
        ValNodePtr tmp;
 
1654
        ObjectIdPtr oid;
 
1655
        Int4 len, i;
 
1656
        Int2 residue;
 
1657
        ValNode fake;
 
1658
        SeqLocPtr the_segs, head, curr;
 
1659
        Boolean handled = FALSE, split;
 
1660
        SeqFeatPtr sfp, newsfp, lastsfp;
 
1661
        DeltaSeqPtr dsp;
 
1662
        SeqEntryPtr oldscope;
 
1663
 
 
1664
 
 
1665
        if ((sourceid == NULL) || (from < 0)) return FALSE;
 
1666
 
 
1667
        oldbsp = BioseqFind(sourceid);
 
1668
        if (oldbsp == NULL) {
 
1669
                oldscope = SeqEntrySetScope (NULL);
 
1670
                if (oldscope != NULL) {
 
1671
                        oldbsp = BioseqFind(sourceid);
 
1672
                        SeqEntrySetScope (oldscope);
 
1673
                }
 
1674
        }
 
1675
        if (oldbsp == NULL) return NULL;
 
1676
 
 
1677
        len = to - from + 1;
 
1678
        if (len <= 0) return NULL;
 
1679
 
 
1680
        newbsp = BioseqNew();
 
1681
        if (newid != NULL)
 
1682
                newbsp->id = SeqIdDup(newid);
 
1683
        else
 
1684
        {
 
1685
                tmp = ValNodeNew(NULL);
 
1686
                tmp->choice = SEQID_LOCAL;
 
1687
                oid = ObjectIdNew();
 
1688
                tmp->data.ptrvalue = (Pointer)oid;
 
1689
                oid->str = StringSave("Clipboard");
 
1690
                tmpbsp = BioseqFind(tmp);   /* old clipboard present? */
 
1691
                if (tmpbsp == NULL) {
 
1692
                        oldscope = SeqEntrySetScope (NULL);
 
1693
                        if (oldscope != NULL) {
 
1694
                                tmpbsp = BioseqFind(tmp);
 
1695
                                SeqEntrySetScope (oldscope);
 
1696
                        }
 
1697
                }
 
1698
                if (tmpbsp != NULL)
 
1699
                        BioseqFree(tmpbsp);
 
1700
                newbsp->id = tmp;
 
1701
        }
 
1702
 
 
1703
        newbsp->repr = oldbsp->repr;
 
1704
        newbsp->mol = oldbsp->mol;
 
1705
        newbsp->length = len;
 
1706
        newbsp->seq_ext_type = oldbsp->seq_ext_type;
 
1707
 
 
1708
        if (newbsp->repr == Seq_repr_virtual)
 
1709
                handled = TRUE;               /* no more to do */
 
1710
 
 
1711
        if ((newbsp->repr == Seq_repr_raw) ||
 
1712
                (newbsp->repr == Seq_repr_const))
 
1713
        {
 
1714
                if (ISA_aa(newbsp->mol))
 
1715
                {
 
1716
                        seqtype = Seq_code_ncbieaa;
 
1717
                }
 
1718
                else
 
1719
                {
 
1720
                        seqtype = Seq_code_iupacna;
 
1721
                }
 
1722
                newbsp->seq_data_type = seqtype;
 
1723
                bsp = BSNew(len);
 
1724
                if (bsp == NULL) goto erret;
 
1725
 
 
1726
                newbsp->seq_data = bsp;
 
1727
                spp = SeqPortNew(oldbsp, from, to, strand, seqtype);
 
1728
                if (spp == NULL) goto erret;
 
1729
 
 
1730
                for (i = 0; i < len; i++)
 
1731
                {
 
1732
                        residue = SeqPortGetResidue(spp);
 
1733
                        if (! IS_residue(residue)) goto erret;
 
1734
                        BSPutByte(bsp, residue);
 
1735
                }
 
1736
 
 
1737
                SeqPortFree(spp);
 
1738
                handled = TRUE;
 
1739
        }
 
1740
 
 
1741
        if ((newbsp->repr == Seq_repr_seg) ||
 
1742
                (newbsp->repr == Seq_repr_ref) ||
 
1743
                (newbsp->repr == Seq_repr_delta))
 
1744
        {
 
1745
        if (newbsp->repr == Seq_repr_seg)  /* segmented */
 
1746
                {
 
1747
                        fake.choice = SEQLOC_MIX;   /* make SEQUENCE OF Seq-loc, into one */
 
1748
                        fake.data.ptrvalue = oldbsp->seq_ext;
 
1749
                        fake.next = NULL;
 
1750
                        the_segs = (SeqLocPtr)&fake;
 
1751
                        head = SeqLocCopyPart (the_segs, from, to, strand, FALSE, NULL, NULL);
 
1752
                }
 
1753
                else if (newbsp->repr == Seq_repr_ref)  /* reference: is a Seq-loc */
 
1754
                {
 
1755
                        head = SeqLocCopyPart ((SeqLocPtr)(oldbsp->seq_ext), from, to,
 
1756
                                                 strand, TRUE, NULL, NULL);
 
1757
                }
 
1758
                else if (newbsp->repr == Seq_repr_delta)
 
1759
                {
 
1760
                        dsp = (DeltaSeqPtr)(oldbsp->seq_ext);  /* real data is here */
 
1761
                        the_segs = DeltaSeqsToSeqLocs(dsp);
 
1762
                        head = SeqLocCopyPart (the_segs, from, to, strand, FALSE, NULL, NULL);
 
1763
                        SeqLocFree (the_segs);
 
1764
                }
 
1765
 
 
1766
        newbsp->seq_ext = (Pointer)head;
 
1767
                handled = TRUE;
 
1768
        }
 
1769
 
 
1770
        if (newbsp->repr == Seq_repr_map)
 
1771
        {
 
1772
                lastsfp = NULL;
 
1773
                for (sfp = (SeqFeatPtr)(oldbsp->seq_ext); sfp != NULL; sfp = sfp->next)
 
1774
                {
 
1775
                        split = FALSE;
 
1776
                        curr = SeqLocCopyRegion(newbsp->id, sfp->location, oldbsp, from, to, strand, &split);
 
1777
                        if (curr != NULL)   /* got one */
 
1778
                        {
 
1779
                                newsfp = (SeqFeatPtr)AsnIoMemCopy((Pointer)sfp, (AsnReadFunc)SeqFeatAsnRead, (AsnWriteFunc)SeqFeatAsnWrite);
 
1780
                                SeqLocFree(newsfp->location);
 
1781
                                newsfp->location = curr;
 
1782
                                if (split)
 
1783
                                        newsfp->partial = TRUE;
 
1784
                                if (lastsfp == NULL)  /* first one */
 
1785
                                        newbsp->seq_ext = (Pointer)newsfp;
 
1786
                                else
 
1787
                                        lastsfp->next = newsfp;
 
1788
                                lastsfp = newsfp;
 
1789
                        }
 
1790
                }
 
1791
                handled = TRUE;
 
1792
        }
 
1793
        
 
1794
 
 
1795
        if (! handled) goto erret;
 
1796
 
 
1797
                       /* get descriptors */
 
1798
                       /* get features */
 
1799
 
 
1800
        if (do_feat)
 
1801
                SeqFeatsCopy (newbsp, oldbsp, from, to, strand);
 
1802
 
 
1803
        return newbsp;
 
1804
 
 
1805
erret:
 
1806
        BioseqFree(newbsp);
 
1807
        SeqPortFree(spp);
 
1808
        return NULL;
 
1809
}
 
1810
 
 
1811
/*****************************************************************************
 
1812
*
 
1813
*       SeqLocCopyPart (the_segs, from, to, strand, group, first_segp, last_segp)
 
1814
*      cuts out from the_segs the part from offset from to offset to
 
1815
*      reverse complements resulting seqloc if strand == Seq_strand_minus
 
1816
*      if (group) puts resulting intervals into a new Seq-loc (of type
 
1817
*        PACKED_INT if no SEQLOC_NULL, else SEQLOC_MIX).
 
1818
*      Currently this always makes intervals or nulls. Is really for segmented and
 
1819
*        reference sequence extensions
 
1820
*      If first_segp and last_segp are not NULL, then they are filled in with the
 
1821
*        ordinal number of the source segments that remain in the copy, based
 
1822
*        on SeqLocFindNext, where 1 is the first one. Thus if the third and
 
1823
*        fourth segments were copied, first is 3 and last is 4. If the
 
1824
*        location was reverse complemented, first is 4 and last is 3.
 
1825
*
 
1826
*****************************************************************************/
 
1827
NLM_EXTERN SeqLocPtr LIBCALL SeqLocCopyPart (SeqLocPtr the_segs, Int4 from, Int4 to, Uint1 strand,
 
1828
                                        Boolean group, Int2Ptr first_segp, Int2Ptr last_segp)
 
1829
{
 
1830
        SeqLocPtr currseg, newhead, head, prev, curr, last;
 
1831
        Int2 numloc, first_seg = 0, last_seg = 0, seg_ctr = 0;
 
1832
        Int4 oldpos, tlen, tfrom, tto, tstart, tstop, xfrom, xto;
 
1833
        Uint1 tstrand;
 
1834
        SeqIdPtr tid;
 
1835
        SeqIntPtr sip;
 
1836
        Boolean done, started, wasa_null, hada_null;
 
1837
        BioseqPtr bsp;
 
1838
 
 
1839
        if (the_segs == NULL) return NULL;
 
1840
        if ((from < 0) || (to < 0)) return NULL;
 
1841
 
 
1842
   currseg = NULL;
 
1843
   oldpos = 0;     /* position in old sequence */
 
1844
   done = FALSE;
 
1845
   started = FALSE;
 
1846
   head = NULL;
 
1847
   prev = NULL;
 
1848
   numloc = 0;
 
1849
   wasa_null = FALSE;
 
1850
   hada_null = FALSE;
 
1851
   while ((oldpos <= to) && ((currseg = SeqLocFindNext(the_segs, currseg)) != NULL))
 
1852
   {
 
1853
                seg_ctr++;
 
1854
                tlen = SeqLocLen(currseg);
 
1855
                tid = SeqLocId(currseg);
 
1856
                if (tlen < 0) {
 
1857
                        bsp = BioseqLockById (tid);  /* only necessary for locations of type WHOLE */
 
1858
                        tlen = SeqLocLen (currseg);
 
1859
                        BioseqUnlock (bsp);
 
1860
                }
 
1861
                tstrand = SeqLocStrand(currseg);
 
1862
                tfrom = SeqLocStart(currseg);
 
1863
                tto = SeqLocStop(currseg);
 
1864
 
 
1865
                if (! started)
 
1866
                {
 
1867
                        wasa_null = FALSE;
 
1868
                        if (((oldpos + tlen - 1) >= from) &&
 
1869
                                (currseg->choice != SEQLOC_NULL))
 
1870
                        {
 
1871
                                tstart = from - oldpos;
 
1872
                                started = TRUE;
 
1873
                                first_seg = seg_ctr;
 
1874
                        }
 
1875
                        else
 
1876
                                tstart = -1;
 
1877
                }
 
1878
                else
 
1879
                {
 
1880
                        if (currseg->choice == SEQLOC_NULL)
 
1881
                        {
 
1882
                                wasa_null = TRUE;
 
1883
                                tstart = -1;  /* skip it till later */
 
1884
                        }
 
1885
                        else
 
1886
                                tstart = 0;
 
1887
                }
 
1888
 
 
1889
                if (tstart >= 0)   /* have a start */
 
1890
                {
 
1891
                        if ((oldpos + tlen - 1) >= to)
 
1892
                        {
 
1893
                                done = TRUE;   /* hit the end */
 
1894
                                tstop = ((oldpos + tlen - 1) - to);
 
1895
                        }
 
1896
                        else
 
1897
                                tstop = 0;
 
1898
 
 
1899
                        if (tstrand == Seq_strand_minus)
 
1900
                        {
 
1901
                                xfrom = tfrom + tstop;
 
1902
                                xto = tto - tstart;
 
1903
                        }
 
1904
                        else
 
1905
                        {
 
1906
                                xfrom = tfrom + tstart;
 
1907
                                xto = tto - tstop;
 
1908
                        }
 
1909
 
 
1910
                        sip = SeqIntNew();
 
1911
                        sip->id = SeqIdDup(tid);
 
1912
                        sip->strand = tstrand;
 
1913
                        sip->from = xfrom;
 
1914
                        sip->to = xto;
 
1915
                        if (wasa_null)  /* previous SEQLOC_NULL */
 
1916
                        {
 
1917
                                curr = ValNodeAddInt(&head, SEQLOC_NULL, 0);
 
1918
                                numloc++;
 
1919
                                wasa_null = FALSE;
 
1920
                                hada_null = TRUE;
 
1921
                        }
 
1922
                        curr = ValNodeAddPointer(&head, SEQLOC_INT, (Pointer)sip);
 
1923
                        numloc++;
 
1924
                        last_seg = seg_ctr;
 
1925
                }
 
1926
 
 
1927
                oldpos += tlen;
 
1928
   }
 
1929
 
 
1930
   if (strand == Seq_strand_minus)  /* reverse order and complement */
 
1931
   {
 
1932
                newhead = NULL;
 
1933
                last = NULL;
 
1934
                while (head != NULL)
 
1935
                {
 
1936
                        prev = NULL;
 
1937
                        for (curr = head; curr->next != NULL; curr = curr->next)
 
1938
                                prev = curr;
 
1939
                        if (prev != NULL)
 
1940
                                prev->next = NULL;
 
1941
                        else
 
1942
                                head = NULL;
 
1943
 
 
1944
                        if (newhead == NULL)
 
1945
                                newhead = curr;
 
1946
                        else
 
1947
                                last->next = curr;
 
1948
                        last = curr;
 
1949
                        if (curr->choice == SEQLOC_INT)
 
1950
                        {
 
1951
                                sip = (SeqIntPtr)(curr->data.ptrvalue);
 
1952
                                sip->strand = StrandCmp(sip->strand);
 
1953
                        }
 
1954
                }
 
1955
 
 
1956
                head = newhead;
 
1957
                seg_ctr = last_seg;
 
1958
                last_seg = first_seg;
 
1959
                first_seg = seg_ctr;
 
1960
   }
 
1961
 
 
1962
   if ((numloc) && (group))
 
1963
   {
 
1964
                curr = ValNodeNew(NULL);
 
1965
                if (hada_null)
 
1966
                        curr->choice = SEQLOC_MIX;
 
1967
                else
 
1968
                        curr->choice = SEQLOC_PACKED_INT;
 
1969
                curr->data.ptrvalue = (Pointer)head;
 
1970
                head = curr;
 
1971
   }
 
1972
 
 
1973
   if (first_segp != NULL)
 
1974
         *first_segp = first_seg;
 
1975
   if (last_segp != NULL)
 
1976
         *last_segp = last_seg;
 
1977
 
 
1978
   return head;
 
1979
}
 
1980
 
 
1981
/*****************************************************************************
 
1982
*
 
1983
*   SeqFeatCopy(new, old, from, to, strand)
 
1984
*
 
1985
*****************************************************************************/
 
1986
static Int2 LIBCALL IndexedSeqFeatsCopy (BioseqPtr newbsp, BioseqPtr oldbsp, Int4 from, Int4 to, Uint1 strand)
 
1987
 
 
1988
{
 
1989
        Int2 ctr=0;
 
1990
        SeqFeatPtr head=NULL, sfp, last=NULL, newsfp;
 
1991
        SeqInt si;
 
1992
        ValNode vn;
 
1993
        ValNodePtr region;
 
1994
        SeqLocPtr newloc;
 
1995
        Boolean split = FALSE;
 
1996
        SeqAnnotPtr sap = NULL, saptmp;
 
1997
        CdRegionPtr crp;
 
1998
        CodeBreakPtr cbp, prevcbp, nextcbp;
 
1999
        RnaRefPtr rrp;
 
2000
        tRNAPtr trp;
 
2001
        SeqMgrFeatContext fcontext;
 
2002
 
 
2003
        region = &vn;
 
2004
        vn.choice = SEQLOC_INT;
 
2005
        vn.data.ptrvalue = (Pointer)(&si);
 
2006
        si.from = from;
 
2007
        si.to = to;
 
2008
        si.id = oldbsp->id;
 
2009
        si.if_from = NULL;
 
2010
        si.if_to = NULL;
 
2011
 
 
2012
        sfp = NULL;
 
2013
        while ((sfp = SeqMgrGetNextFeature (oldbsp, sfp, 0, 0, &fcontext)) != NULL)
 
2014
        {
 
2015
                /* can exit once past rightmost limit */
 
2016
                if (fcontext.left > to) return ctr;
 
2017
 
 
2018
                if (fcontext.right >= from && fcontext.left <= to) {
 
2019
 
 
2020
                        split = FALSE;
 
2021
                        newloc = SeqLocCopyRegion(newbsp->id, sfp->location, oldbsp, from, to, strand, &split);
 
2022
                        if (newloc != NULL)   /* got one */
 
2023
                        {
 
2024
                                newsfp = (SeqFeatPtr)AsnIoMemCopy((Pointer)sfp, (AsnReadFunc)SeqFeatAsnRead, (AsnWriteFunc)SeqFeatAsnWrite);
 
2025
                                SeqLocFree(newsfp->location);
 
2026
                                newsfp->location = newloc;
 
2027
                                if (split)
 
2028
                                        newsfp->partial = TRUE;
 
2029
                                if (last == NULL)  /* first one */
 
2030
                                {
 
2031
                                        sap = SeqAnnotNew();
 
2032
                                        if (newbsp->annot == NULL)
 
2033
                                                newbsp->annot = sap;
 
2034
                                        else
 
2035
                                        {
 
2036
                                                for (saptmp = newbsp->annot; saptmp->next != NULL; saptmp = saptmp->next)
 
2037
                                                        continue;
 
2038
                                                saptmp->next = sap;
 
2039
                                        }
 
2040
                                        sap->type = 1;   /* feature table */
 
2041
                                        sap->data = (Pointer)newsfp;
 
2042
                                }
 
2043
                                else
 
2044
                                        last->next = newsfp;
 
2045
                                last = newsfp;
 
2046
 
 
2047
                                switch (newsfp->data.choice)
 
2048
                                {
 
2049
                                        case SEQFEAT_CDREGION:   /* cdregion */
 
2050
                                                crp = (CdRegionPtr)(newsfp->data.value.ptrvalue);
 
2051
                                                prevcbp = NULL;
 
2052
                                                for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp)
 
2053
                                                {
 
2054
                                                        nextcbp = cbp->next;
 
2055
                                                        cbp->loc = SeqLocCopyRegion(newbsp->id, cbp->loc, oldbsp, from, to, strand, &split);
 
2056
                                                        if (cbp->loc == NULL)
 
2057
                                                        {
 
2058
                                                                if (prevcbp != NULL)
 
2059
                                                                        prevcbp->next = nextcbp;
 
2060
                                                                else
 
2061
                                                                        crp->code_break = nextcbp;
 
2062
                                                                cbp->next = NULL;
 
2063
                                                                CodeBreakFree(cbp);
 
2064
                                                        }
 
2065
                                                        else
 
2066
                                                                prevcbp = cbp;
 
2067
                                                }
 
2068
                                                break;
 
2069
                                        case SEQFEAT_RNA:
 
2070
                                                rrp = (RnaRefPtr)(newsfp->data.value.ptrvalue);
 
2071
                                                if (rrp->ext.choice == 2)   /* tRNA */
 
2072
                                                {
 
2073
                                                        trp = (tRNAPtr)(rrp->ext.value.ptrvalue);
 
2074
                                                        if (trp->anticodon != NULL)
 
2075
                                                        {
 
2076
                                                                trp->anticodon = SeqLocCopyRegion(newbsp->id, trp->anticodon, oldbsp, from, to, strand, &split);
 
2077
                                                        }
 
2078
                                                }
 
2079
                                                break;
 
2080
                                        default:
 
2081
                                                break;
 
2082
                                }
 
2083
                        }
 
2084
                }
 
2085
                
 
2086
        }
 
2087
        return ctr;
 
2088
}
 
2089
 
 
2090
NLM_EXTERN Int2 LIBCALL SeqFeatsCopy (BioseqPtr newbsp, BioseqPtr oldbsp, Int4 from, Int4 to, Uint1 strand)
 
2091
{
 
2092
        Int2 ctr=0;
 
2093
        BioseqContextPtr bcp = NULL;
 
2094
        SeqFeatPtr head=NULL, sfp, last=NULL, newsfp;
 
2095
        SeqInt si;
 
2096
        ValNode vn;
 
2097
        ValNodePtr region;
 
2098
        SeqLocPtr newloc;
 
2099
        Boolean split = FALSE;
 
2100
        SeqAnnotPtr sap = NULL, saptmp;
 
2101
        CdRegionPtr crp;
 
2102
        CodeBreakPtr cbp, prevcbp, nextcbp;
 
2103
        RnaRefPtr rrp;
 
2104
        tRNAPtr trp;
 
2105
        Uint2 entityID;
 
2106
 
 
2107
        if (oldbsp == NULL) return ctr;
 
2108
 
 
2109
        entityID = ObjMgrGetEntityIDForPointer (oldbsp);
 
2110
        if (entityID > 0 && SeqMgrFeaturesAreIndexed (entityID)) {
 
2111
                /* indexed version should be much faster */
 
2112
                return IndexedSeqFeatsCopy (newbsp, oldbsp, from, to, strand);
 
2113
        }
 
2114
 
 
2115
        bcp = BioseqContextNew(oldbsp);
 
2116
        if (bcp == NULL) return ctr;
 
2117
 
 
2118
        region = &vn;
 
2119
        vn.choice = SEQLOC_INT;
 
2120
        vn.data.ptrvalue = (Pointer)(&si);
 
2121
        si.from = from;
 
2122
        si.to = to;
 
2123
        si.id = oldbsp->id;
 
2124
        si.if_from = NULL;
 
2125
        si.if_to = NULL;
 
2126
 
 
2127
        sfp = NULL;
 
2128
        while ((sfp = BioseqContextGetSeqFeat(bcp, 0, sfp, NULL, 0)) != NULL)
 
2129
        {
 
2130
                split = FALSE;
 
2131
                newloc = SeqLocCopyRegion(newbsp->id, sfp->location, oldbsp, from, to, strand, &split);
 
2132
                if (newloc != NULL)   /* got one */
 
2133
                {
 
2134
                        newsfp = (SeqFeatPtr)AsnIoMemCopy((Pointer)sfp, (AsnReadFunc)SeqFeatAsnRead, (AsnWriteFunc)SeqFeatAsnWrite);
 
2135
                        SeqLocFree(newsfp->location);
 
2136
                        newsfp->location = newloc;
 
2137
                        if (split)
 
2138
                                newsfp->partial = TRUE;
 
2139
                        if (last == NULL)  /* first one */
 
2140
                        {
 
2141
                                sap = SeqAnnotNew();
 
2142
                                if (newbsp->annot == NULL)
 
2143
                                        newbsp->annot = sap;
 
2144
                                else
 
2145
                                {
 
2146
                                        for (saptmp = newbsp->annot; saptmp->next != NULL; saptmp = saptmp->next)
 
2147
                                                continue;
 
2148
                                        saptmp->next = sap;
 
2149
                                }
 
2150
                                sap->type = 1;   /* feature table */
 
2151
                                sap->data = (Pointer)newsfp;
 
2152
                        }
 
2153
                        else
 
2154
                                last->next = newsfp;
 
2155
                        last = newsfp;
 
2156
 
 
2157
                        switch (newsfp->data.choice)
 
2158
                        {
 
2159
                                case SEQFEAT_CDREGION:   /* cdregion */
 
2160
                                        crp = (CdRegionPtr)(newsfp->data.value.ptrvalue);
 
2161
                                        prevcbp = NULL;
 
2162
                                        for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp)
 
2163
                                        {
 
2164
                                                nextcbp = cbp->next;
 
2165
                                                cbp->loc = SeqLocCopyRegion(newbsp->id, cbp->loc, oldbsp, from, to, strand, &split);
 
2166
                                                if (cbp->loc == NULL)
 
2167
                                                {
 
2168
                                                        if (prevcbp != NULL)
 
2169
                                                                prevcbp->next = nextcbp;
 
2170
                                                        else
 
2171
                                                                crp->code_break = nextcbp;
 
2172
                                                        cbp->next = NULL;
 
2173
                                                        CodeBreakFree(cbp);
 
2174
                                                }
 
2175
                                                else
 
2176
                                                        prevcbp = cbp;
 
2177
                                        }
 
2178
                                        break;
 
2179
                                case SEQFEAT_RNA:
 
2180
                                        rrp = (RnaRefPtr)(newsfp->data.value.ptrvalue);
 
2181
                                        if (rrp->ext.choice == 2)   /* tRNA */
 
2182
                                        {
 
2183
                                                trp = (tRNAPtr)(rrp->ext.value.ptrvalue);
 
2184
                                                if (trp->anticodon != NULL)
 
2185
                                                {
 
2186
                                                        trp->anticodon = SeqLocCopyRegion(newbsp->id, trp->anticodon, oldbsp, from, to, strand, &split);
 
2187
                                                }
 
2188
                                        }
 
2189
                                        break;
 
2190
                                default:
 
2191
                                        break;
 
2192
                        }
 
2193
                }
 
2194
                
 
2195
        }
 
2196
        BioseqContextFree (bcp);
 
2197
        return ctr;
 
2198
}
 
2199
 
 
2200
 
 
2201
NLM_EXTERN SeqLocPtr LIBCALL SeqLocCopyRegion(SeqIdPtr newid, SeqLocPtr head, BioseqPtr oldbsp,
 
2202
        Int4 from, Int4 to, Uint1 strand, BoolPtr split)
 
2203
{
 
2204
        SeqLocPtr newhead = NULL, last=NULL, tmp, slp, prev, next, thead;
 
2205
        SeqIntPtr sip, sip2;
 
2206
        SeqPntPtr spp, spp2;
 
2207
        PackSeqPntPtr pspp, pspp2;
 
2208
        SeqBondPtr sbp, sbp2;
 
2209
        SeqIdPtr sidp, oldids;
 
2210
        Int4 numpnt, i, tpos, len, intcnt, othercnt;
 
2211
        Pointer ptr = NULL;
 
2212
        Boolean dropped_one;
 
2213
        IntFuzzPtr ifp;
 
2214
        ValNode vn;
 
2215
        
 
2216
        if ((head == NULL) || (oldbsp == NULL)) return NULL;
 
2217
 
 
2218
        oldids = oldbsp->id;
 
2219
        len = to - from + 1;
 
2220
        switch (head->choice)
 
2221
        {
 
2222
        case SEQLOC_BOND:   /* bond -- 2 seqs */
 
2223
                        sbp2 = NULL;
 
2224
                        sbp = (SeqBondPtr)(head->data.ptrvalue);
 
2225
                        vn.choice = SEQLOC_PNT;
 
2226
                        vn.data.ptrvalue = sbp->a;
 
2227
                        vn.next = NULL;
 
2228
                        tmp = SeqLocCopyRegion(newid, (SeqLocPtr)(&vn), oldbsp, from, to, strand, split);
 
2229
                        if (tmp != NULL)
 
2230
                        {
 
2231
                                sbp2 = SeqBondNew();
 
2232
                                sbp2->a = (SeqPntPtr)(tmp->data.ptrvalue);
 
2233
                                MemFree(tmp);
 
2234
                        }
 
2235
                        if (sbp->b != NULL)
 
2236
                        {
 
2237
                                vn.data.ptrvalue = sbp->b;
 
2238
                                tmp = SeqLocCopyRegion(newid, (SeqLocPtr)(&vn), oldbsp, from, to, strand, split);
 
2239
                                if (tmp != NULL)
 
2240
                                {
 
2241
                                        if (sbp2 == NULL)
 
2242
                                        {
 
2243
                                                sbp2 = SeqBondNew();
 
2244
                                                sbp2->a = (SeqPntPtr)(tmp->data.ptrvalue);
 
2245
                                        }
 
2246
                                        else
 
2247
                                                sbp2->b = (SeqPntPtr)(tmp->data.ptrvalue);
 
2248
                                        MemFree(tmp);
 
2249
                                }
 
2250
                        }
 
2251
                        if (sbp2 != NULL)
 
2252
                        {
 
2253
                                newhead = ValNodeNew(NULL);
 
2254
                                newhead->choice = SEQLOC_BOND;
 
2255
                                newhead->data.ptrvalue = sbp2;
 
2256
                                if ((sbp->b != NULL) && (sbp2->b == NULL))
 
2257
                                        *split = TRUE;
 
2258
                        }
 
2259
                        break;
 
2260
        case SEQLOC_FEAT:   /* feat -- can't track yet */
 
2261
        case SEQLOC_NULL:    /* NULL */
 
2262
        case SEQLOC_EMPTY:    /* empty */
 
2263
                        break;
 
2264
        case SEQLOC_WHOLE:    /* whole */
 
2265
                        sidp = (SeqIdPtr)(head->data.ptrvalue);
 
2266
                        if (SeqIdIn(sidp, oldids))
 
2267
                        {
 
2268
                                if ((from != 0) || (to != (oldbsp->length - 1)))
 
2269
                                {
 
2270
                                        *split = TRUE;
 
2271
                                }
 
2272
                                newhead = ValNodeNew(NULL);
 
2273
                                sip2 = SeqIntNew();
 
2274
                                sip2->id = SeqIdDup(newid);
 
2275
                                sip2->from = 0;
 
2276
                                sip2->to = to - from;
 
2277
                                newhead->choice = SEQLOC_INT;
 
2278
                                newhead->data.ptrvalue = (Pointer)sip2;
 
2279
                                if (strand == Seq_strand_minus)
 
2280
                                        sip2->strand = Seq_strand_minus;
 
2281
                        }
 
2282
                        break;
 
2283
        case SEQLOC_EQUIV:    /* does it stay equiv? */
 
2284
        case SEQLOC_MIX:    /* mix -- more than one seq */
 
2285
        case SEQLOC_PACKED_INT:    /* packed int */
 
2286
                        prev = NULL;
 
2287
                        thead = NULL;
 
2288
                        dropped_one = FALSE;
 
2289
                        for (slp = (SeqLocPtr)(head->data.ptrvalue); slp != NULL; slp = next)
 
2290
                        {
 
2291
                                next = slp->next;
 
2292
                                tmp = SeqLocCopyRegion(newid, slp, oldbsp, from, to, strand, split);
 
2293
                                if (tmp != NULL)
 
2294
                                {
 
2295
                                        if (prev != NULL)
 
2296
                                        {
 
2297
                                                if ((prev->choice == SEQLOC_INT) && (tmp->choice == SEQLOC_INT))
 
2298
                                                {
 
2299
                                                        sip = (SeqIntPtr)(prev->data.ptrvalue);
 
2300
                                                        sip2 = (SeqIntPtr)(tmp->data.ptrvalue);
 
2301
 
 
2302
                                                        if ((sip->strand == Seq_strand_minus) &&
 
2303
                                                                (sip2->strand == Seq_strand_minus))
 
2304
                                                        {
 
2305
                                                                if (sip->from == (sip2->to + 1))
 
2306
                                                                {
 
2307
                                                                        sip->from = sip2->from;
 
2308
                                                                        sip->if_from = sip2->if_from;
 
2309
                                                                        sip2->if_from = NULL;
 
2310
                                                                        tmp = SeqLocFree(tmp);
 
2311
                                                                }
 
2312
                                                        }
 
2313
                                                        else if((sip->strand != Seq_strand_minus) &&
 
2314
                                                                (sip2->strand != Seq_strand_minus))
 
2315
                                                        {
 
2316
                                                                if (sip->to == (sip2->from - 1))
 
2317
                                                                {
 
2318
                                                                        sip->to = sip2->to;
 
2319
                                                                        sip->if_to = sip2->if_to;
 
2320
                                                                        sip2->if_to = NULL;
 
2321
                                                                        tmp = SeqLocFree(tmp);
 
2322
                                                                }
 
2323
                                                        }
 
2324
                                                }
 
2325
                                                else if ((prev->choice == SEQLOC_NULL) && (tmp->choice == SEQLOC_NULL))
 
2326
                                                {
 
2327
                                                        tmp = SeqLocFree(tmp);
 
2328
                                                        dropped_one = TRUE;
 
2329
                                                }
 
2330
                                        }
 
2331
                                        else if (tmp->choice == SEQLOC_NULL)
 
2332
                                        {
 
2333
                                                tmp = SeqLocFree(tmp);
 
2334
                                                dropped_one = TRUE;
 
2335
                                        }
 
2336
 
 
2337
                                        if (tmp != NULL)   /* still have one? */
 
2338
                                        {
 
2339
                                                if (prev != NULL)
 
2340
                                                        prev->next = tmp;
 
2341
                                                else
 
2342
                                                        thead = tmp;
 
2343
                                                prev = tmp;
 
2344
                                        }
 
2345
                                        else
 
2346
                                                dropped_one = TRUE;
 
2347
                                }
 
2348
                                else
 
2349
                                        dropped_one = TRUE;
 
2350
                        }
 
2351
                        if (prev != NULL)
 
2352
                        {
 
2353
                                if (prev->choice == SEQLOC_NULL)  /* ends with NULL */
 
2354
                                {
 
2355
                                        prev = NULL;
 
2356
                                        for (slp = thead; slp->next != NULL; slp = slp->next)
 
2357
                                                prev = slp;
 
2358
                                        if (prev != NULL)
 
2359
                                        {
 
2360
                                                prev->next = NULL;
 
2361
                                                SeqLocFree(slp);
 
2362
                                        }
 
2363
                                        else
 
2364
                                        {
 
2365
                                                thead = SeqLocFree(thead);
 
2366
                                        }
 
2367
                                        dropped_one = TRUE;
 
2368
                                }
 
2369
                        }
 
2370
                        if (thead != NULL)
 
2371
                        {
 
2372
                                if (dropped_one)
 
2373
                                        *split = TRUE;
 
2374
                                intcnt = 0;
 
2375
                                othercnt = 0;
 
2376
                                for (slp = thead; slp != NULL; slp = slp->next)
 
2377
                                {
 
2378
                                        if (slp->choice == SEQLOC_INT)
 
2379
                                                intcnt++;
 
2380
                                        else
 
2381
                                                othercnt++;
 
2382
                                }
 
2383
                                if ((intcnt + othercnt) > 1)
 
2384
                                {
 
2385
                                        newhead = ValNodeNew(NULL);
 
2386
                                        if (head->choice == SEQLOC_EQUIV)
 
2387
                                                newhead->choice = SEQLOC_EQUIV;
 
2388
                                        else
 
2389
                                        {
 
2390
                                                if (othercnt == 0)
 
2391
                                                        newhead->choice = SEQLOC_PACKED_INT;
 
2392
                                                else
 
2393
                                                        newhead->choice = SEQLOC_MIX;
 
2394
                                        }
 
2395
 
 
2396
                                        newhead->data.ptrvalue = (Pointer)thead;
 
2397
                                }
 
2398
                                else                 /* only one SeqLoc left */
 
2399
                                        newhead = thead;
 
2400
 
 
2401
                        }
 
2402
            break;
 
2403
        case SEQLOC_INT:    /* int */
 
2404
                        sip = (SeqIntPtr)(head->data.ptrvalue);
 
2405
                        if (SeqIdIn(sip->id, oldids))
 
2406
                        {
 
2407
                                if (sip->to < from)  /* completely before cut */
 
2408
                                        break;
 
2409
                                if (sip->from > to)  /* completely after cut */
 
2410
                                        break;
 
2411
 
 
2412
                                sip2 = SeqIntNew();
 
2413
                                sip2->id = SeqIdDup(newid);
 
2414
                                sip2->strand = sip->strand;
 
2415
 
 
2416
                                if (sip->to > to)
 
2417
                                {
 
2418
                                        sip2->to = to;
 
2419
                                        *split = TRUE;
 
2420
                                        ifp = IntFuzzNew();
 
2421
                                        ifp->choice = 4;   /* lim */
 
2422
                                        ifp->a = 1;        /* greater than */
 
2423
                                        sip2->if_to = ifp;
 
2424
                                }
 
2425
                                else
 
2426
                                {
 
2427
                                        sip2->to = sip->to;
 
2428
                                        if (sip->if_to != NULL)
 
2429
                                        {
 
2430
                                                ifp = IntFuzzNew();
 
2431
                                                MemCopy((Pointer)ifp, (Pointer)(sip->if_to), sizeof(IntFuzz));
 
2432
                                                sip2->if_to = ifp;
 
2433
                                        }
 
2434
                                }
 
2435
 
 
2436
                                if (sip->from < from)
 
2437
                                {
 
2438
                                        sip2->from = from;
 
2439
                                        *split = TRUE;
 
2440
                                        ifp = IntFuzzNew();
 
2441
                                        ifp->choice = 4;   /* lim */
 
2442
                                        ifp->a = 2;        /* less than */
 
2443
                                        sip2->if_from = ifp;
 
2444
                                }
 
2445
                                else
 
2446
                                {
 
2447
                                        sip2->from = sip->from;
 
2448
                                        if (sip->if_from != NULL)
 
2449
                                        {
 
2450
                                                ifp = IntFuzzNew();
 
2451
                                                MemCopy((Pointer)ifp, (Pointer)(sip->if_from), sizeof(IntFuzz));
 
2452
                                                sip2->if_from = ifp;
 
2453
                                        }
 
2454
                                }
 
2455
                                                                          /* set to region coordinates */
 
2456
                                sip2->from -= from;
 
2457
                                sip2->to -= from;
 
2458
                                IntFuzzClip(sip2->if_from, from, to, strand, split);
 
2459
                                IntFuzzClip(sip2->if_to, from, to, strand, split);
 
2460
 
 
2461
                                if (strand == Seq_strand_minus)  /* rev comp */
 
2462
                                {
 
2463
                                        sip2->strand = StrandCmp(sip2->strand);
 
2464
                                        tpos = len - sip2->from - 1;
 
2465
                                        sip2->from = len - sip2->to - 1;
 
2466
                                        sip2->to = tpos;
 
2467
                                              /* IntFuzz already complemented by IntFuzzClip */
 
2468
                                              /* just switch order */
 
2469
                                        ifp = sip2->if_from;
 
2470
                                        sip2->if_from = sip2->if_to;
 
2471
                                        sip2->if_to = ifp;
 
2472
                                }
 
2473
 
 
2474
                                newhead = ValNodeNew(NULL);
 
2475
                                newhead->choice = SEQLOC_INT;
 
2476
                                newhead->data.ptrvalue = (Pointer)sip2;
 
2477
                        }
 
2478
            break;
 
2479
        case SEQLOC_PNT:    /* pnt */
 
2480
                        spp = (SeqPntPtr)(head->data.ptrvalue);
 
2481
                        if (SeqIdIn(spp->id, oldids))
 
2482
                        {
 
2483
                                if ((spp->point >= from) && (spp->point <= to))
 
2484
                                {
 
2485
                                        spp2 = SeqPntNew();
 
2486
                                        spp2->id = SeqIdDup(newid);
 
2487
                                        spp2->point = spp->point - from;
 
2488
                                        spp2->strand = spp->strand;
 
2489
                                        if (spp->fuzz != NULL)
 
2490
                                        {
 
2491
                                                ifp = IntFuzzNew();
 
2492
                                                spp2->fuzz = ifp;
 
2493
                                                MemCopy((Pointer)ifp, (Pointer)spp->fuzz, sizeof(IntFuzz));
 
2494
                                                IntFuzzClip(ifp, from, to, strand, split);
 
2495
                                        }
 
2496
                                        if (strand == Seq_strand_minus)
 
2497
                                        {
 
2498
                                                spp2->point = len - spp2->point - 1;
 
2499
                                                spp2->strand = StrandCmp(spp->strand);
 
2500
                                        }
 
2501
                                        newhead = ValNodeNew(NULL);
 
2502
                                        newhead->choice = SEQLOC_PNT;
 
2503
                                        newhead->data.ptrvalue = (Pointer)spp2;
 
2504
                                }
 
2505
                        }
 
2506
            break;
 
2507
        case SEQLOC_PACKED_PNT:    /* packed pnt */
 
2508
                        pspp = (PackSeqPntPtr)(head->data.ptrvalue);
 
2509
                        if (SeqIdIn(pspp->id, oldids))
 
2510
                        {
 
2511
                                numpnt = PackSeqPntNum(pspp);
 
2512
                                pspp2 = PackSeqPntNew();
 
2513
                                pspp2->strand = pspp->strand;
 
2514
                                intcnt = 0;          /* use for included points */
 
2515
                                othercnt = 0;    /* use for exclued points */
 
2516
                                for (i = 0; i < numpnt; i++)
 
2517
                                {
 
2518
                                        tpos = PackSeqPntGet(pspp, i);
 
2519
                                        if ((tpos < from) || (tpos > to))
 
2520
                                        {
 
2521
                                                othercnt++;
 
2522
                                        }
 
2523
                                        else
 
2524
                                        {
 
2525
                                                intcnt++;
 
2526
                                                PackSeqPntPut(pspp2, tpos - from);
 
2527
                                        }
 
2528
                                }
 
2529
                                if (! intcnt)  /* no points in region */
 
2530
                                {
 
2531
                                        PackSeqPntFree(pspp2);
 
2532
                                        break;
 
2533
                                }
 
2534
                                if (othercnt)
 
2535
                                        *split = TRUE;
 
2536
                                if (pspp->fuzz != NULL)
 
2537
                                {
 
2538
                                        ifp = IntFuzzNew();
 
2539
                                        MemCopy((Pointer)ifp, (Pointer)(pspp->fuzz), sizeof(IntFuzz));
 
2540
                                }
 
2541
                                else
 
2542
                                        ifp = NULL;
 
2543
 
 
2544
                                if (strand == Seq_strand_minus)  /* rev comp */
 
2545
                                {
 
2546
                                        IntFuzzClip(ifp, from, to, strand, split);
 
2547
                                        pspp = pspp2;
 
2548
                                        pspp2 = PackSeqPntNew();
 
2549
                                        pspp2->strand = StrandCmp(pspp->strand);
 
2550
                                        numpnt = PackSeqPntNum(pspp);
 
2551
                                        numpnt--;
 
2552
                                        for (i = numpnt; i >= 0; i--)    /* reverse order */
 
2553
                                        {
 
2554
                                                tpos = PackSeqPntGet(pspp, i);
 
2555
                                                PackSeqPntPut(pspp2, (len - tpos - 1));
 
2556
                                        }
 
2557
                                        PackSeqPntFree(pspp);
 
2558
                                }
 
2559
                                pspp2->id = SeqIdDup(newid);
 
2560
                                pspp2->fuzz = ifp;
 
2561
 
 
2562
                                newhead = ValNodeNew(NULL);
 
2563
                                newhead->choice = SEQLOC_PACKED_PNT;
 
2564
                                newhead->data.ptrvalue = (Pointer)pspp2;
 
2565
 
 
2566
                        }
 
2567
            break;
 
2568
        default:
 
2569
            break;
 
2570
 
 
2571
        }
 
2572
        return newhead;
 
2573
}
 
2574
 
 
2575
/*****************************************************************************
 
2576
*
 
2577
*   IntFuzzClip()
 
2578
*       returns TRUE if clipped range values
 
2579
*       in all cases, adjusts and/or complements IntFuzz
 
2580
*       Designed for IntFuzz on SeqLocs
 
2581
*
 
2582
*****************************************************************************/
 
2583
NLM_EXTERN void LIBCALL IntFuzzClip(IntFuzzPtr ifp, Int4 from, Int4 to, Uint1 strand, BoolPtr split)
 
2584
{
 
2585
        Int4 len, tmp;
 
2586
 
 
2587
        if (ifp == NULL) return;
 
2588
        len = to - from + 1;
 
2589
        switch (ifp->choice)
 
2590
        {
 
2591
                case 1:      /* plus/minus - no changes */
 
2592
                case 3:      /* percent - no changes */
 
2593
                        break;
 
2594
                case 2:      /* range */
 
2595
                        if (ifp->a > to)     /* max */
 
2596
                        {
 
2597
                                *split = TRUE;
 
2598
                                ifp->a = to;
 
2599
                        }
 
2600
                        if (ifp->a < from) 
 
2601
                        {
 
2602
                                *split = TRUE;
 
2603
                                ifp->a = from;
 
2604
                        }
 
2605
                        if (ifp->b > to)     /* min */
 
2606
                        {
 
2607
                                *split = TRUE;
 
2608
                                ifp->b = to;
 
2609
                        }
 
2610
                        if (ifp->b < from) 
 
2611
                        {
 
2612
                                *split = TRUE;
 
2613
                                ifp->b = from;
 
2614
                        }
 
2615
                        ifp->a -= from;     /* adjust to window */
 
2616
                        ifp->b -= to;
 
2617
                        if (strand == Seq_strand_minus)
 
2618
                        {
 
2619
                                tmp = len - ifp->a;   /* reverse/complement */
 
2620
                                ifp->a = len - ifp->b;
 
2621
                                ifp->b = tmp;
 
2622
                        }
 
2623
                        break;
 
2624
                case 4:     /* lim */
 
2625
                        if (strand == Seq_strand_minus)  /* reverse/complement */
 
2626
                        {
 
2627
                                switch (ifp->a)
 
2628
                                {
 
2629
                                        case 1:    /* greater than */
 
2630
                                                ifp->a = 2;
 
2631
                                                break;
 
2632
                                        case 2:    /* less than */
 
2633
                                                ifp->a = 1;
 
2634
                                                break;
 
2635
                                        case 3:    /* to right of residue */
 
2636
                                                ifp->a = 4;
 
2637
                                                break;
 
2638
                                        case 4:    /* to left of residue */
 
2639
                                                ifp->a = 3;
 
2640
                                                break;
 
2641
                                        default:
 
2642
                                                break;
 
2643
                                }
 
2644
                        }
 
2645
                        break;
 
2646
        }
 
2647
        return;
 
2648
}
 
2649
 
 
2650
/*****************************************************************************
 
2651
*
 
2652
* BioseqInsert (from_id, from, to, strand, to_id, pos, from_feat, to_feat,
 
2653
*                                                                  do_split)
 
2654
*       Inserts a copy the region "from"-"to" on "strand" of the Bioseq
 
2655
*          identified by "from_id" into the Bioseq identified by "to_id" 
 
2656
*          before "pos".
 
2657
*       if from_feat = TRUE, copies the feature table from "from" and updates
 
2658
*          to locations to point to the proper residues in "to_id"
 
2659
*       If to_feat = TRUE, updates feature table on "to_id" as well.
 
2660
*          if do_split == TRUE, then splits features in "to_id" (to_feat must
 
2661
*             be TRUE as well). Otherwise expands features at insertion.
 
2662
*
 
2663
*       All operations are copies. "frombsp" is unchanged.
 
2664
*       Insert will only occur between certain Bioseq.repr classes as below
 
2665
*
 
2666
*   From Bioseq.repr                      To Bioseq.repr
 
2667
*   
 
2668
*                                             virtual       raw      segmented        map
 
2669
*                                          +---------------------------------------------------
 
2670
*                virtual   |   length       inst          SeqLoc                 length
 
2671
*                                          +---------------------------------------------------
 
2672
*                                raw   |   error        copy      SeqLoc         error
 
2673
*                                          +---------------------------------------------------
 
2674
*                  segmented   |   error        inst      SeqLoc*        error
 
2675
*                                          +---------------------------------------------------
 
2676
*                                map   |   error        inst*     SeqLoc         copy
 
2677
*                                          +---------------------------------------------------
 
2678
*
 
2679
*   length = changes length of "to" by length of "from"
 
2680
*   error  = insertion not allowed
 
2681
*   inst   = "from" instantiated as residues ("N" or "X" for virtual "from")
 
2682
*   inst*  = as above, but a restriction map can instantiate other bases
 
2683
*            than "N" for known restriction recognition sites.
 
2684
*   copy   = copy of "from" inserted into "to"
 
2685
*   SeqLoc = a SeqLoc added to "to" which points to "from". No copy of residues.
 
2686
*   SeqLoc* = as above, but note that "to" points to "from" directly, not
 
2687
*             what "from" itself may point to.
 
2688
*   
 
2689
*****************************************************************************/
 
2690
NLM_EXTERN Boolean LIBCALL BioseqInsert (SeqIdPtr from_id, Int4 from, Int4 to, Uint1 strand, SeqIdPtr to_id, Int4 pos,
 
2691
                        Boolean from_feat, Boolean to_feat, Boolean do_split)
 
2692
{
 
2693
        BioseqPtr tobsp, frombsp;
 
2694
        Int4 len, i, ctr, tlen;
 
2695
        Boolean from_type, to_type;
 
2696
        Uint1 seqtype;
 
2697
        SeqAnnotPtr sap, newsap;
 
2698
        SeqFeatPtr sfp, newsfp, prevsfp, sfphead = NULL;
 
2699
        BioseqContextPtr bcp;
 
2700
        Boolean handled = FALSE;
 
2701
        SeqPortPtr spp;
 
2702
        Int2 residue;
 
2703
        Boolean split, added = FALSE;
 
2704
        SeqLocPtr newloc, curr, head, tloc, xloc, yloc, fake;
 
2705
        SeqIntPtr sip;
 
2706
        CdRegionPtr crp;
 
2707
        CodeBreakPtr cbp, prevcbp, nextcbp;
 
2708
        RnaRefPtr rrp;
 
2709
        tRNAPtr trp;
 
2710
        SeqEntryPtr oldscope;
 
2711
 
 
2712
 
 
2713
        if ((from_id == NULL) || (to_id == NULL)) return FALSE;
 
2714
 
 
2715
        tobsp = BioseqFind(to_id);
 
2716
        if (tobsp == NULL) {
 
2717
                oldscope = SeqEntrySetScope (NULL);
 
2718
                if (oldscope != NULL) {
 
2719
                        tobsp = BioseqFind(to_id);
 
2720
                        SeqEntrySetScope (oldscope);
 
2721
                }
 
2722
        }
 
2723
        if (tobsp == NULL) return FALSE;
 
2724
 
 
2725
        len = BioseqGetLen(tobsp);
 
2726
 
 
2727
        if (pos == LAST_RESIDUE)
 
2728
                pos = len - 1;
 
2729
        else if (pos == APPEND_RESIDUE)
 
2730
                pos = len;
 
2731
 
 
2732
        if ((pos < 0) || (pos > len)) return FALSE;
 
2733
 
 
2734
        frombsp = BioseqFind(from_id);
 
2735
        if (frombsp == NULL) {
 
2736
                oldscope = SeqEntrySetScope (NULL);
 
2737
                if (oldscope != NULL) {
 
2738
                        frombsp = BioseqFind(from_id);
 
2739
                        SeqEntrySetScope (oldscope);
 
2740
                }
 
2741
        }
 
2742
        if (frombsp == NULL) return FALSE;
 
2743
        
 
2744
        from_type = ISA_na(frombsp->mol);
 
2745
        to_type = ISA_na(tobsp->mol);
 
2746
 
 
2747
        if (from_type != to_type) return FALSE;
 
2748
 
 
2749
        len = BioseqGetLen(frombsp);
 
2750
        if (to == LAST_RESIDUE)
 
2751
                to = len - 1;
 
2752
        
 
2753
        if ((from < 0) || (to >= len)) return FALSE;
 
2754
 
 
2755
        len = to - from + 1;
 
2756
 
 
2757
        if (tobsp->repr == Seq_repr_virtual)
 
2758
        {
 
2759
                if (frombsp->repr != Seq_repr_virtual)
 
2760
                        return FALSE;
 
2761
 
 
2762
                handled = TRUE;                    /* just length and features */
 
2763
        }
 
2764
 
 
2765
        if ((tobsp->repr == Seq_repr_raw) || (tobsp->repr == Seq_repr_const))
 
2766
        {
 
2767
                if (ISA_na(tobsp->mol))
 
2768
                {
 
2769
                        seqtype = Seq_code_iupacna;
 
2770
                }
 
2771
                else
 
2772
                {
 
2773
                        seqtype = Seq_code_ncbieaa;
 
2774
                }
 
2775
 
 
2776
                if (tobsp->seq_data_type != seqtype)
 
2777
                        BioseqRawConvert(tobsp, seqtype);
 
2778
                BSSeek(tobsp->seq_data, pos, SEEK_SET);
 
2779
                Nlm_BSAdd(tobsp->seq_data, len, FALSE);
 
2780
 
 
2781
                i = 0;
 
2782
 
 
2783
                spp = SeqPortNew(frombsp, from, to, strand, seqtype);
 
2784
                while ((residue = SeqPortGetResidue(spp)) != SEQPORT_EOF)
 
2785
                {
 
2786
                        if (! IS_residue(residue))
 
2787
                        {
 
2788
                                ErrPost(CTX_NCBIOBJ, 1, "Non-residue in BioseqInsert [%d]",
 
2789
                                        (int)residue);
 
2790
                        }
 
2791
                        else
 
2792
                        {
 
2793
                                BSPutByte(tobsp->seq_data, residue);
 
2794
                                i++;
 
2795
                        }
 
2796
                }
 
2797
                SeqPortFree(spp);
 
2798
 
 
2799
                if (i != len)
 
2800
                {
 
2801
                        ErrPost(CTX_NCBIOBJ, 1, "Tried to insert %ld residues but %ld went in",
 
2802
                                len, i);
 
2803
                        return FALSE;
 
2804
                }
 
2805
 
 
2806
                handled = TRUE;
 
2807
        }
 
2808
 
 
2809
        if ((tobsp->repr == Seq_repr_seg) || (tobsp->repr == Seq_repr_ref))
 
2810
        {
 
2811
                sip = SeqIntNew();
 
2812
                sip->id = SeqIdDup(from_id);
 
2813
                sip->from = from;
 
2814
                sip->to = to;
 
2815
                sip->strand = strand;
 
2816
                tloc = ValNodeNew(NULL);
 
2817
                tloc->choice = SEQLOC_INT;
 
2818
                tloc->data.ptrvalue = (Pointer)sip;
 
2819
                head = NULL;
 
2820
                if (tobsp->repr == Seq_repr_seg)
 
2821
                {
 
2822
                        fake = ValNodeNew(NULL);
 
2823
                        fake->choice = SEQLOC_MIX;
 
2824
                        fake->data.ptrvalue = (Pointer)(tobsp->seq_ext);
 
2825
                }
 
2826
                else
 
2827
                        fake = (SeqLocPtr)(tobsp->seq_ext);
 
2828
                curr = NULL;
 
2829
                ctr = 0;
 
2830
                while ((curr = SeqLocFindNext(fake, curr)) != NULL)
 
2831
                {
 
2832
                        if ((! added) && (ctr == pos))
 
2833
                        {
 
2834
                                newloc = SeqLocAdd(&head, tloc, TRUE, TRUE);
 
2835
                                added = TRUE;
 
2836
                        }
 
2837
                        tlen = SeqLocLen(curr);
 
2838
                        if ((! added) && ((ctr + tlen) > pos))  /* split interval */
 
2839
                        {
 
2840
                                yloc = NULL;
 
2841
                                xloc = SeqLocAdd(&yloc, curr, TRUE, TRUE);
 
2842
                                i = (pos - ctr) + SeqLocStart(curr);
 
2843
                            newloc = SeqLocInsert(xloc, SeqLocId(xloc), i, 0, TRUE, NULL);
 
2844
                                xloc = newloc;
 
2845
                                yloc = newloc->next;
 
2846
                                SeqLocAdd(&head, xloc, TRUE, TRUE);
 
2847
                                SeqLocAdd(&head, tloc, TRUE, TRUE);
 
2848
                                SeqLocAdd(&head, yloc, TRUE, TRUE);
 
2849
                                SeqLocFree(xloc);
 
2850
                                SeqLocFree(yloc);
 
2851
                                added = TRUE;
 
2852
                        }
 
2853
                        else
 
2854
                                newloc = SeqLocAdd(&head, curr, TRUE, TRUE);
 
2855
                        ctr += tlen;
 
2856
                }
 
2857
                if ((! added) && (ctr == pos))
 
2858
                {
 
2859
                        newloc = SeqLocAdd(&head, tloc, TRUE, TRUE);
 
2860
                        added = TRUE;
 
2861
                }
 
2862
                SeqLocFree(tloc);
 
2863
                SeqLocFree(fake);
 
2864
                if (tobsp->repr == Seq_repr_seg)
 
2865
                {
 
2866
                        tobsp->seq_ext = (Pointer)head;
 
2867
                }
 
2868
                else
 
2869
                {
 
2870
                        tobsp->seq_ext = SeqLocPackage(head);
 
2871
                }
 
2872
                handled = TRUE;
 
2873
        }
 
2874
 
 
2875
        if (tobsp->repr == Seq_repr_map)
 
2876
        {
 
2877
                if (! ((frombsp->repr == Seq_repr_map) || (frombsp->repr == Seq_repr_virtual)))
 
2878
                        return FALSE;
 
2879
 
 
2880
                prevsfp = NULL;
 
2881
                for (sfp = (SeqFeatPtr)(tobsp->seq_ext); sfp != NULL; sfp = sfp->next)
 
2882
                {
 
2883
                        sfp->location = SeqLocInsert(sfp->location, to_id, pos, len, TRUE, NULL);
 
2884
                        prevsfp = sfp;
 
2885
                }
 
2886
 
 
2887
                if (frombsp->repr == Seq_repr_map)
 
2888
                {
 
2889
                        for (sfp = (SeqFeatPtr)(frombsp->seq_ext); sfp != NULL; sfp = sfp->next)
 
2890
                        {
 
2891
                                split = FALSE;
 
2892
                                newloc = SeqLocCopyRegion(to_id, sfp->location, frombsp, from, to, strand, &split);
 
2893
                                if (newloc != NULL)   /* got one */
 
2894
                                {
 
2895
                                        newsfp = (SeqFeatPtr)AsnIoMemCopy((Pointer)sfp, (AsnReadFunc)SeqFeatAsnRead, (AsnWriteFunc)SeqFeatAsnWrite);
 
2896
                                        SeqLocFree(newsfp->location);
 
2897
                                        newsfp->location = newloc;
 
2898
                                        if (split)
 
2899
                                                newsfp->partial = TRUE;
 
2900
                                        
 
2901
                                        if (prevsfp == NULL)
 
2902
                                                tobsp->seq_ext = (Pointer)newsfp;
 
2903
                                        else
 
2904
                                                prevsfp->next = newsfp;
 
2905
                                        prevsfp = newsfp;
 
2906
                
 
2907
                                        newsfp->location = SeqLocInsert(newsfp->location, to_id, 0,
 
2908
                                                                          pos, TRUE, to_id);
 
2909
                                }
 
2910
                        }
 
2911
                }
 
2912
                handled = TRUE;
 
2913
        }
 
2914
 
 
2915
        if (! handled) return FALSE;
 
2916
 
 
2917
        tobsp->length += len;
 
2918
 
 
2919
        if (to_feat)                 /* fix up sourceid Bioseq feature table(s) */
 
2920
        {
 
2921
                bcp = BioseqContextNew(tobsp);
 
2922
                sfp = NULL;
 
2923
                                     /* adjust features pointing by location */
 
2924
                while ((sfp = BioseqContextGetSeqFeat(bcp, 0, sfp, NULL, 0)) != NULL)
 
2925
                {
 
2926
                        sfp->location = SeqLocInsert(sfp->location, to_id,pos, len, do_split, NULL);
 
2927
                        switch (sfp->data.choice)
 
2928
                        {
 
2929
                                case SEQFEAT_CDREGION:   /* cdregion */
 
2930
                                        crp = (CdRegionPtr)(sfp->data.value.ptrvalue);
 
2931
                                        prevcbp = NULL;
 
2932
                                        for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp)
 
2933
                                        {
 
2934
                                                nextcbp = cbp->next;
 
2935
                                                cbp->loc = SeqLocInsert(cbp->loc, to_id,pos, len, do_split, NULL);
 
2936
                                                if (cbp->loc == NULL)
 
2937
                                                {
 
2938
                                                        if (prevcbp != NULL)
 
2939
                                                                prevcbp->next = nextcbp;
 
2940
                                                        else
 
2941
                                                                crp->code_break = nextcbp;
 
2942
                                                        cbp->next = NULL;
 
2943
                                                        CodeBreakFree(cbp);
 
2944
                                                }
 
2945
                                                else
 
2946
                                                        prevcbp = cbp;
 
2947
                                        }
 
2948
                                        break;
 
2949
                                case SEQFEAT_RNA:
 
2950
                                        rrp = (RnaRefPtr)(sfp->data.value.ptrvalue);
 
2951
                                        if (rrp->ext.choice == 2)   /* tRNA */
 
2952
                                        {
 
2953
                                                trp = (tRNAPtr)(rrp->ext.value.ptrvalue);
 
2954
                                                if (trp->anticodon != NULL)
 
2955
                                                {
 
2956
                                                        trp->anticodon = SeqLocInsert(trp->anticodon, to_id,pos, len, do_split, NULL);
 
2957
                                                }
 
2958
                                        }
 
2959
                                        break;
 
2960
                                default:
 
2961
                                        break;
 
2962
                        }
 
2963
                }
 
2964
        
 
2965
                sfp = NULL;
 
2966
                                     /* adjust features pointing by product */
 
2967
                while ((sfp = BioseqContextGetSeqFeat(bcp, 0, sfp, NULL, 1)) != NULL)
 
2968
                        sfp->product = SeqLocInsert(sfp->product, to_id,pos, len, do_split, NULL);
 
2969
 
 
2970
                BioseqContextFree(bcp);
 
2971
        }
 
2972
 
 
2973
        if (from_feat)                          /* add source Bioseq features to sourceid */
 
2974
        {
 
2975
                bcp = BioseqContextNew(frombsp);
 
2976
                sfp = NULL;                                     /* NOTE: should make NEW feature table */
 
2977
                prevsfp = NULL;
 
2978
                                    /* is there an old feature table to use? */
 
2979
                for (newsap = tobsp->annot; newsap != NULL; newsap = newsap->next)
 
2980
                {
 
2981
                        if (newsap->type == 1)  /* feature table */
 
2982
                                break;
 
2983
                }
 
2984
                if (newsap != NULL)
 
2985
                {                                                       /* create a new one if necessary */
 
2986
                        for (prevsfp = (SeqFeatPtr)(newsap->data); prevsfp != NULL;
 
2987
                                                                    prevsfp = prevsfp->next)
 
2988
                        {
 
2989
                                if (prevsfp->next == NULL)
 
2990
                                        break;
 
2991
                        }
 
2992
                }
 
2993
                                                     /* get features by location */
 
2994
                while ((sfp = BioseqContextGetSeqFeat(bcp, 0, sfp, NULL, 0)) != NULL)
 
2995
                {                                                                       /* copy all old features */
 
2996
                        split = FALSE;
 
2997
                        newloc = SeqLocCopyRegion(to_id, sfp->location, frombsp, from, to, strand, &split);
 
2998
                        if (newloc != NULL)   /* got one */
 
2999
                        {
 
3000
                                newsfp = (SeqFeatPtr)AsnIoMemCopy((Pointer)sfp, (AsnReadFunc)SeqFeatAsnRead, (AsnWriteFunc)SeqFeatAsnWrite);
 
3001
                                SeqLocFree(newsfp->location);
 
3002
                                newsfp->location = newloc;
 
3003
 
 
3004
                                if (split)
 
3005
                                        newsfp->partial = TRUE;
 
3006
 
 
3007
                                if (prevsfp == NULL)
 
3008
                                        sfphead = newsfp;
 
3009
                                else
 
3010
                                        prevsfp->next = newsfp;
 
3011
                                prevsfp = newsfp;
 
3012
 
 
3013
                                newsfp->location = SeqLocInsert(newsfp->location, to_id, 0,
 
3014
                                                                          pos, TRUE, to_id);
 
3015
                                switch (newsfp->data.choice)
 
3016
                                {
 
3017
                                        case SEQFEAT_CDREGION:   /* cdregion */
 
3018
                                                crp = (CdRegionPtr)(newsfp->data.value.ptrvalue);
 
3019
                                                prevcbp = NULL;
 
3020
                                                for (cbp = crp->code_break; cbp != NULL; cbp = nextcbp)
 
3021
                                                {
 
3022
                                                        nextcbp = cbp->next;
 
3023
                                                        cbp->loc = SeqLocCopyRegion(to_id, cbp->loc, frombsp, from, to, strand, &split);
 
3024
                                                        if (cbp->loc == NULL)
 
3025
                                                        {
 
3026
                                                                if (prevcbp != NULL)
 
3027
                                                                        prevcbp->next = nextcbp;
 
3028
                                                                else
 
3029
                                                                        crp->code_break = nextcbp;
 
3030
                                                                cbp->next = NULL;
 
3031
                                                                CodeBreakFree(cbp);
 
3032
                                                        }
 
3033
                                                        else
 
3034
                                                        {
 
3035
                                                                cbp->loc = SeqLocInsert(cbp->loc, to_id, 0,
 
3036
                                                                          pos, TRUE, to_id);
 
3037
                                                                prevcbp = cbp;
 
3038
                                                        }
 
3039
                                                }
 
3040
                                                break;
 
3041
                                        case SEQFEAT_RNA:
 
3042
                                                rrp = (RnaRefPtr)(newsfp->data.value.ptrvalue);
 
3043
                                                if (rrp->ext.choice == 2)   /* tRNA */
 
3044
                                                {
 
3045
                                                        trp = (tRNAPtr)(rrp->ext.value.ptrvalue);
 
3046
                                                        if (trp->anticodon != NULL)
 
3047
                                                        {
 
3048
                                                                trp->anticodon = SeqLocCopyRegion(to_id, trp->anticodon, frombsp, from, to, strand, &split);
 
3049
                                                                trp->anticodon = SeqLocInsert(trp->anticodon, to_id, 0,
 
3050
                                                                          pos, TRUE, to_id);
 
3051
                                                        }
 
3052
                                                }
 
3053
                                                break;
 
3054
                                        default:
 
3055
                                                break;
 
3056
                                }
 
3057
                        }
 
3058
                }
 
3059
 
 
3060
                sfp = NULL;
 
3061
                                                                /* get features by product */
 
3062
                while ((sfp = BioseqContextGetSeqFeat(bcp, 0, sfp, NULL, 1)) != NULL)
 
3063
                {                                                                       /* copy all old features */
 
3064
                        split = FALSE;
 
3065
                        newloc = SeqLocCopyRegion(to_id, sfp->product, frombsp, from, to, strand, &split);
 
3066
                        if (newloc != NULL)   /* got one */
 
3067
                        {
 
3068
                                newsfp = (SeqFeatPtr)AsnIoMemCopy((Pointer)sfp, (AsnReadFunc)SeqFeatAsnRead, (AsnWriteFunc)SeqFeatAsnWrite);
 
3069
                                SeqLocFree(newsfp->product);
 
3070
                                newsfp->product = newloc;
 
3071
                                if (split)
 
3072
                                        newsfp->partial = TRUE;
 
3073
 
 
3074
                                if (prevsfp == NULL)
 
3075
                                        sfphead = newsfp;
 
3076
                                else
 
3077
                                        prevsfp->next = newsfp;
 
3078
                                prevsfp = newsfp;
 
3079
 
 
3080
                                newsfp->product = SeqLocInsert(newsfp->product, to_id, 0, pos,
 
3081
                                                                                TRUE, to_id);
 
3082
                        }
 
3083
                }
 
3084
                BioseqContextFree(bcp);
 
3085
        
 
3086
 
 
3087
                if (sfphead != NULL)    /* orphan chain of seqfeats to attach */
 
3088
                {
 
3089
                        if (newsap == NULL)
 
3090
                        {
 
3091
                                for (sap = tobsp->annot; sap != NULL; sap = sap->next)
 
3092
                                {
 
3093
                                        if (sap->next == NULL)
 
3094
                                                break;
 
3095
                                }
 
3096
                                newsap = SeqAnnotNew();
 
3097
                                newsap->type = 1;
 
3098
                                if (sap == NULL)
 
3099
                                        tobsp->annot = newsap;
 
3100
                                else
 
3101
                                        sap->next = newsap;
 
3102
                        }
 
3103
 
 
3104
                        newsap->data = (Pointer)sfphead;
 
3105
                }
 
3106
        }
 
3107
 
 
3108
        return TRUE;
 
3109
}
 
3110
 
 
3111
/*****************************************************************************
 
3112
*
 
3113
*   SeqLocInsert()
 
3114
*       alters "head" by insert "len" residues before "pos" in any SeqLoc
 
3115
*         on the Bioseq "target"
 
3116
*       all SeqLocs not on "target" are unaltered
 
3117
*       for SeqLocs on "target"
 
3118
*          all SeqLocs before "pos" are unaltered
 
3119
*          all SeqLocs >= "pos" are incremented by "len"
 
3120
*          all SeqLocs spanning "pos"
 
3121
*             if "split" == TRUE, are split into two SeqLocs, one to the
 
3122
*               left of the insertion, the other to right
 
3123
*             if "split" != TRUE, the SeqLoc is increased in length to cover
 
3124
*               the insertion
 
3125
*       returns altered head or NULL if nothing left.
 
3126
*       if ("newid" != NULL) replaces "target" with "newid" whether the
 
3127
*          SeqLoc is altered on not.
 
3128
*
 
3129
*       Usage hints:
 
3130
*          1) To update a feature location on "target" when 10 residues of
 
3131
*               sequence have been inserted before position 5
 
3132
*          SeqFeatPtr->location = SeqLocInsert ( SeqFeatPtr->location ,
 
3133
*                "target", 5, 10, TRUE, NULL);  [for some feature types
 
3134
*                      you may want "split" equal FALSE]
 
3135
*          2) To insert the complete feature table from "source" into a
 
3136
*                different Bioseq "dest" before position 20 in "dest"
 
3137
*          SFP->location = SeqLocInsert(SFP->location, "source", 0, 20,
 
3138
*                FALSE, "dest");
 
3139
*   
 
3140
*
 
3141
*****************************************************************************/
 
3142
NLM_EXTERN SeqLocPtr LIBCALL SeqLocInsert (SeqLocPtr head, SeqIdPtr target, Int4 pos, Int4 len,
 
3143
                                               Boolean split, SeqIdPtr newid)
 
3144
{
 
3145
        SeqIntPtr sip, sip2;
 
3146
        SeqPntPtr spp;
 
3147
        PackSeqPntPtr pspp, pspp2;
 
3148
        SeqBondPtr sbp;
 
3149
        SeqLocPtr slp, tmp, prev, next, thead, tmp2;
 
3150
        Int4 diff, numpnt, i, tpos;
 
3151
        Uint1 oldchoice;
 
3152
        ValNode vn;
 
3153
        SeqIdPtr sidp;
 
3154
 
 
3155
        if ((head == NULL) || (target == NULL))
 
3156
                return head;
 
3157
 
 
3158
        head->next = NULL;   /* caller maintains chains */
 
3159
 
 
3160
        diff = len;
 
3161
 
 
3162
    switch (head->choice)
 
3163
    {
 
3164
        case SEQLOC_BOND:   /* bond -- 2 seqs */
 
3165
                        vn.next = NULL;
 
3166
                        vn.choice = SEQLOC_PNT;
 
3167
 
 
3168
                        sbp = (SeqBondPtr)(head->data.ptrvalue);
 
3169
                        vn.data.ptrvalue = (Pointer)(sbp->a);
 
3170
                        SeqLocInsert(&vn, target, pos, len, split, newid);
 
3171
                        sbp->a = (SeqPntPtr)(vn.data.ptrvalue);
 
3172
                        if (sbp->b != NULL)
 
3173
                        {
 
3174
                                vn.data.ptrvalue = (Pointer)(sbp->b);
 
3175
                                SeqLocInsert(&vn, target, pos, len, split, newid);
 
3176
                                sbp->b = (SeqPntPtr)(vn.data.ptrvalue);
 
3177
                        }
 
3178
                        break;
 
3179
        case SEQLOC_FEAT:   /* feat -- can't track yet */
 
3180
        case SEQLOC_NULL:    /* NULL */
 
3181
                        break;
 
3182
        case SEQLOC_EMPTY:    /* empty */
 
3183
        case SEQLOC_WHOLE:    /* whole */
 
3184
                        if (newid != NULL)
 
3185
                        {
 
3186
                                sidp = (SeqIdPtr)(head->data.ptrvalue);
 
3187
                                if (SeqIdForSameBioseq(sidp, target))
 
3188
                                {
 
3189
                                        SeqIdFree(sidp);
 
3190
                                        sidp = SeqIdDup(newid);
 
3191
                                        head->data.ptrvalue = (Pointer)sidp;
 
3192
                                }
 
3193
                        }
 
3194
                        break;
 
3195
        case SEQLOC_MIX:    /* mix -- more than one seq */
 
3196
        case SEQLOC_EQUIV:    /* equiv -- ditto */
 
3197
        case SEQLOC_PACKED_INT:    /* packed int */
 
3198
                        prev = NULL;
 
3199
                        thead = NULL;
 
3200
                        for (slp = (SeqLocPtr)(head->data.ptrvalue); slp != NULL; slp = next)
 
3201
                        {
 
3202
                                next = slp->next;
 
3203
                                oldchoice = slp->choice;
 
3204
                                tmp = SeqLocInsert(slp, target, pos, len, split, newid);
 
3205
                                if (tmp != NULL)
 
3206
                                {
 
3207
                                        if ((head->choice != SEQLOC_EQUIV) &&
 
3208
                                                (oldchoice != tmp->choice))  /* split interval? */
 
3209
                                        {
 
3210
                                                if ((oldchoice == SEQLOC_INT) &&
 
3211
                                                        (tmp->choice == SEQLOC_PACKED_INT))
 
3212
                                                {
 
3213
                                                        tmp2 = tmp;
 
3214
                                                        tmp = (SeqLocPtr)(tmp2->data.ptrvalue);
 
3215
                                                        MemFree(tmp2);
 
3216
                                                        while (tmp->next != NULL)
 
3217
                                                        {
 
3218
                                                                if (prev != NULL)
 
3219
                                                                        prev->next = tmp;
 
3220
                                                                else
 
3221
                                                                        thead = tmp;
 
3222
                                                                prev = tmp;
 
3223
                                                                tmp = tmp->next;
 
3224
                                                        }
 
3225
                                                }
 
3226
                                        }
 
3227
                                        if (prev != NULL)
 
3228
                                                prev->next = tmp;
 
3229
                                        else
 
3230
                                                thead = tmp;
 
3231
                                        prev = tmp;
 
3232
                                }
 
3233
                        }
 
3234
                        head->data.ptrvalue = thead;
 
3235
                        if (thead == NULL)
 
3236
                                head = SeqLocFree(head);
 
3237
            break;
 
3238
        case SEQLOC_INT:    /* int */
 
3239
                        sip = (SeqIntPtr)(head->data.ptrvalue);
 
3240
                        if (SeqIdForSameBioseq(sip->id, target))
 
3241
                        {
 
3242
                                if (newid != NULL)   /* change id? */
 
3243
                                {
 
3244
                                        SeqIdFree(sip->id);
 
3245
                                        sip->id = SeqIdDup(newid);
 
3246
                                }
 
3247
 
 
3248
                                if (sip->to < pos)  /* completely before insertion */
 
3249
                                {
 
3250
                                        break;
 
3251
                                }
 
3252
 
 
3253
                                if ((! split) || (sip->from >= pos))  /* interval unbroken */
 
3254
                                {
 
3255
                                        if (sip->from >= pos)
 
3256
                                                sip->from += len;
 
3257
                                        sip->to += len;
 
3258
                                        break;
 
3259
                                }
 
3260
 
 
3261
                                                                          /* split interval */
 
3262
                                sip2 = SeqIntNew();
 
3263
                                slp = ValNodeNew(NULL);
 
3264
                                slp->choice = SEQLOC_INT;
 
3265
                                slp->data.ptrvalue = (Pointer)sip2;
 
3266
                                sip2->strand = sip->strand;
 
3267
                                sip2->id = SeqIdDup(sip->id);
 
3268
 
 
3269
                                sip2->to = sip->to + len;
 
3270
                                sip2->from = pos + len;
 
3271
                                sip2->if_to = sip->if_to;
 
3272
                                sip->if_to = NULL;
 
3273
                                sip->to = pos - 1;
 
3274
                                head->next = slp;
 
3275
 
 
3276
                                if (sip->strand == Seq_strand_minus)  /* reverse order */
 
3277
                                {
 
3278
                                        head->data.ptrvalue = (Pointer)sip2;
 
3279
                                        slp->data.ptrvalue = (Pointer)sip;
 
3280
                                }
 
3281
 
 
3282
                                thead = head;   /* make split interval into PACKED_INT */
 
3283
                                head = ValNodeNew(NULL);
 
3284
                                head->choice = SEQLOC_PACKED_INT;
 
3285
                                head->data.ptrvalue = thead;
 
3286
 
 
3287
                        }
 
3288
            break;
 
3289
        case SEQLOC_PNT:    /* pnt */
 
3290
                        spp = (SeqPntPtr)(head->data.ptrvalue);
 
3291
                        if (SeqIdForSameBioseq(spp->id, target))
 
3292
                        {
 
3293
                                if (newid != NULL)   /* change id? */
 
3294
                                {
 
3295
                                        SeqIdFree(spp->id);
 
3296
                                        spp->id = SeqIdDup(newid);
 
3297
                                }
 
3298
 
 
3299
                                if (spp->point >= pos)
 
3300
                                        spp->point += len;
 
3301
                        }
 
3302
            break;
 
3303
        case SEQLOC_PACKED_PNT:    /* packed pnt */
 
3304
                        pspp = (PackSeqPntPtr)(head->data.ptrvalue);
 
3305
                        if (SeqIdForSameBioseq(pspp->id, target))
 
3306
                        {
 
3307
                                if (newid != NULL)   /* change id? */
 
3308
                                {
 
3309
                                        SeqIdFree(pspp->id);
 
3310
                                        pspp->id = SeqIdDup(newid);
 
3311
                                }
 
3312
 
 
3313
                                numpnt = PackSeqPntNum(pspp);
 
3314
                                pspp2 = PackSeqPntNew();
 
3315
                                head->data.ptrvalue = pspp2;
 
3316
                                for (i = 0; i < numpnt; i++)
 
3317
                                {
 
3318
                                        tpos = PackSeqPntGet(pspp, i);
 
3319
                                        if (tpos >= pos)
 
3320
                                                tpos += len;
 
3321
                                        PackSeqPntPut(pspp2, tpos);
 
3322
                                }
 
3323
                                pspp2->id = pspp->id;
 
3324
                                pspp->id = NULL;
 
3325
                                pspp2->fuzz = pspp->fuzz;
 
3326
                                pspp->fuzz = NULL;
 
3327
                                pspp2->strand = pspp->strand;
 
3328
                                PackSeqPntFree(pspp);
 
3329
                        }
 
3330
            break;
 
3331
        default:
 
3332
            break;
 
3333
    }
 
3334
 
 
3335
        if (head == NULL)
 
3336
                ErrPost(CTX_NCBIOBJ, 1, "SeqLocInsert: lost a SeqLoc");
 
3337
 
 
3338
        return head;
 
3339
}
 
3340
 
 
3341
/*****************************************************************************
 
3342
*
 
3343
*   SeqLocSubtract (SeqLocPtr head, SeqLocPtr piece)
 
3344
*       Deletes piece from head.
 
3345
*       head may be changed.
 
3346
*       returns the changed head.
 
3347
*
 
3348
*****************************************************************************/
 
3349
NLM_EXTERN SeqLocPtr LIBCALL SeqLocSubtract (SeqLocPtr head, SeqLocPtr piece)
 
3350
{
 
3351
        SeqLocPtr slp = NULL;
 
3352
        SeqIdPtr sip;
 
3353
        Int4 from, to;
 
3354
        Boolean changed = FALSE;
 
3355
 
 
3356
        if ((head == NULL) || (piece == NULL))
 
3357
                return NULL;
 
3358
 
 
3359
        while ((slp = SeqLocFindNext(piece, slp)) != NULL)
 
3360
        {
 
3361
                sip = SeqLocId(slp);
 
3362
                from = SeqLocStart(slp);
 
3363
                to = SeqLocStop(slp);
 
3364
                head = SeqLocDelete(head, sip, from, to, FALSE, &changed);
 
3365
        }
 
3366
 
 
3367
        return head;
 
3368
}
 
3369
 
 
3370
/********************************************************************
 
3371
*
 
3372
* SeqLocReplaceID
 
3373
*   replaces the Seq-Id in a Seq-Loc (slp) with a new Seq-Id (new_sip)
 
3374
*
 
3375
**********************************************************************/
 
3376
NLM_EXTERN SeqLocPtr SeqLocReplaceID (SeqLocPtr slp, SeqIdPtr new_sip)
 
3377
{
 
3378
  SeqLocPtr        curr;
 
3379
  PackSeqPntPtr    pspp;
 
3380
  SeqIntPtr        target_sit;
 
3381
  SeqPntPtr        spp;
 
3382
 
 
3383
  switch (slp->choice) {
 
3384
     case SEQLOC_PACKED_INT :
 
3385
     case SEQLOC_MIX :
 
3386
     case SEQLOC_EQUIV :
 
3387
        curr = NULL;
 
3388
        while ((curr = SeqLocFindNext (slp, curr)) != NULL) {
 
3389
           curr = SeqLocReplaceID (curr, new_sip);
 
3390
        }
 
3391
        break;
 
3392
     case SEQLOC_PACKED_PNT :
 
3393
        pspp = (PackSeqPntPtr) slp->data.ptrvalue;
 
3394
        if (pspp != NULL) {
 
3395
          SeqIdFree (pspp->id);
 
3396
          pspp->id = SeqIdDup (new_sip);
 
3397
        }
 
3398
        break;
 
3399
     case SEQLOC_EMPTY :
 
3400
     case SEQLOC_WHOLE :
 
3401
        SeqIdFree ((SeqIdPtr) slp->data.ptrvalue);
 
3402
        slp->data.ptrvalue = (Pointer) SeqIdDup (new_sip);
 
3403
        break;
 
3404
     case SEQLOC_INT :
 
3405
        target_sit = (SeqIntPtr) slp->data.ptrvalue;
 
3406
        SeqIdFree (target_sit->id);
 
3407
        target_sit->id = SeqIdDup (new_sip);
 
3408
        break;
 
3409
     case SEQLOC_PNT :
 
3410
        spp = (SeqPntPtr)slp->data.ptrvalue;
 
3411
        SeqIdFree(spp->id);
 
3412
        spp->id = SeqIdDup(new_sip);
 
3413
        break;
 
3414
     default :
 
3415
        break;
 
3416
  }
 
3417
  return slp;
 
3418
}
 
3419
 
 
3420
/**********************************************************
 
3421
 *
 
3422
 *   NLM_EXTERN SeqLocPtr LIBCALL GapToSeqLoc(range):
 
3423
 *
 
3424
 *      Gets the size of gap and constructs SeqLoc block with
 
3425
 *   $(seqlitdbtag) value as Dbtag.db and Dbtag.tag.id = 0.
 
3426
 *
 
3427
 **********************************************************/
 
3428
NLM_EXTERN SeqLocPtr LIBCALL GapToSeqLoc(Int4 range)
 
3429
{
 
3430
    SeqLocPtr slp;
 
3431
    SeqIntPtr sip;
 
3432
    SeqIdPtr  sidp;
 
3433
    DbtagPtr  dp;
 
3434
 
 
3435
    if(range < 0)
 
3436
        return(NULL);
 
3437
 
 
3438
    slp = ValNodeNew(NULL);
 
3439
    if(range == 0)
 
3440
    {
 
3441
        slp->choice = SEQLOC_NULL;
 
3442
        slp->data.ptrvalue = NULL;
 
3443
        slp->next = NULL;
 
3444
        return(slp);
 
3445
    }
 
3446
 
 
3447
    dp = DbtagNew();
 
3448
    dp->db = StringSave(seqlitdbtag);
 
3449
    dp->tag = ObjectIdNew();
 
3450
    dp->tag->id = 0;
 
3451
    dp->tag->str = NULL;
 
3452
 
 
3453
    sidp = ValNodeNew(NULL);
 
3454
    sidp->choice = SEQID_GENERAL;
 
3455
    sidp->data.ptrvalue = dp;
 
3456
 
 
3457
    sip = SeqIntNew();
 
3458
    sip->from = 0;
 
3459
    sip->to = range - 1;
 
3460
    sip->id = sidp;
 
3461
 
 
3462
    slp->choice = SEQLOC_INT;
 
3463
    slp->data.ptrvalue = sip;
 
3464
 
 
3465
    return(slp);
 
3466
}
 
3467
 
 
3468
/**********************************************************
 
3469
 *
 
3470
 *   NLM_EXTERN Boolean LIBCALL ISAGappedSeqLoc(slp):
 
3471
 *
 
3472
 *      Looks at a single SeqLoc item. If it has the SeqId
 
3473
 *   of type GENERAL with Dbtag.db == $(seqlitdbtag) and
 
3474
 *   Dbtag.tag.id == 0, then returns TRUE, otherwise
 
3475
 *   returns FALSE.
 
3476
 *
 
3477
 **********************************************************/
 
3478
NLM_EXTERN Boolean LIBCALL ISAGappedSeqLoc(SeqLocPtr slp)
 
3479
{
 
3480
    SeqIdPtr sip;
 
3481
    DbtagPtr dp;
 
3482
 
 
3483
    if(slp == NULL)
 
3484
        return(FALSE);
 
3485
 
 
3486
    sip = SeqLocId(slp);
 
3487
    if(sip == NULL || sip->choice != SEQID_GENERAL)
 
3488
        return(FALSE);
 
3489
 
 
3490
    dp = (DbtagPtr) sip->data.ptrvalue;
 
3491
    if(dp == NULL || dp->db == NULL || dp->tag == NULL)
 
3492
        return(FALSE);
 
3493
 
 
3494
    if(StringCmp(seqlitdbtag, dp->db) == 0 && dp->tag->id == 0)
 
3495
        return(TRUE);
 
3496
 
 
3497
    return(FALSE);
 
3498
}
 
3499
 
 
3500
/**********************************************************
 
3501
 *
 
3502
 *   NLM_EXTERN DeltaSeqPtr LIBCALL GappedSeqLocsToDeltaSeqs(slp):
 
3503
 *
 
3504
 *      This functions is used only in the case, if ISAGappedSeqLoc()
 
3505
 *   has returned TRUE.
 
3506
 *      Converts SeqLoc set to the sequence of DeltaSeqs.
 
3507
 *   Gbtag'ed SeqLocs it turns into SeqLits with the only "length"
 
3508
 *   element. The regular SeqLocs saves as they are. Returns
 
3509
 *   obtained DeltaSeq.
 
3510
 *
 
3511
 **********************************************************/
 
3512
NLM_EXTERN DeltaSeqPtr LIBCALL GappedSeqLocsToDeltaSeqs(SeqLocPtr slp)
 
3513
{
 
3514
    DeltaSeqPtr res;
 
3515
    DeltaSeqPtr dsp;
 
3516
    SeqIntPtr   sip;
 
3517
    SeqLitPtr   slip;
 
3518
 
 
3519
    dsp = ValNodeNew(NULL);
 
3520
    dsp->next = NULL;
 
3521
    dsp->choice = 0;
 
3522
    res = dsp;
 
3523
    for(; slp != NULL; slp = slp->next)
 
3524
    {
 
3525
        if(ISAGappedSeqLoc(slp) != FALSE)
 
3526
        {
 
3527
            dsp->next = ValNodeNew(NULL);
 
3528
            dsp = dsp->next;
 
3529
            sip = slp->data.ptrvalue;
 
3530
            slip = SeqLitNew();
 
3531
            slip->length = sip->to - sip->from + 1;
 
3532
            dsp->choice = 2;
 
3533
            dsp->data.ptrvalue = slip;
 
3534
        }
 
3535
        else
 
3536
        {
 
3537
            dsp->next = ValNodeNew(NULL);
 
3538
            dsp = dsp->next;
 
3539
            dsp->choice = 1;
 
3540
            dsp->data.ptrvalue = AsnIoMemCopy((Pointer) slp,
 
3541
                                              (AsnReadFunc) SeqLocAsnRead,
 
3542
                                              (AsnWriteFunc) SeqLocAsnWrite);
 
3543
        }
 
3544
    }
 
3545
    dsp = res->next;
 
3546
    MemFree(res);
 
3547
    return(dsp);
 
3548
}