1 /*   saled.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *            National Center for Biotechnology Information (NCBI)
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government do not place any restriction on its use or reproduction.
13 *  We would, however, appreciate having the NCBI and the author cited in
14 *  any work or product based on this material
15 *
16 *  Although all reasonable efforts have been taken to ensure the accuracy
17 *  and reliability of the software and data, the NLM and the U.S.
18 *  Government do not and cannot warrant the performance or results that
19 *  may be obtained by using this software or data. The NLM and the U.S.
20 *  Government disclaim all warranties, express or implied, including
21 *  warranties of performance, merchantability or fitness for any particular
22 *  purpose.
23 *
24 * ===========================================================================
25 *
26 * File Name:  saled.c
27 *
28 * Author:  Colombe Chappey
29 *
30 * Version Creation Date:   1/27/96
31 *
32 * $Revision: 6.60 $
33 *
34 * File Description:
35 *
36 * Modifications:
37 * --------------------------------------------------------------------------
38 * Date     Name        Description of modification
39 * -------  ----------  -----------------------------------------------------
40 *
41 *
42 * ==========================================================================
43 */
44 #include <saledit.h>
45 #include <saled.h>
46 #include <salutil.h>
47 #include <salsap.h>
48 #include <salfiles.h>
49 #include <salpanel.h>
50 #include <salstruc.h>
51 #include <salparam.h>
52 #include <edutil.h>
53 #include <dlogutil.h>
54 #include <aliread.h>
55 #include <alignmgr2.h>
56 
57 #define SIDLAND          1
58 #define SEQLAND          2
59 #define BADLAND          3
60 #define HOLDDNLAND       4
61 #define HOLDUPLAND       5
62 
63 #define NOCLICK          0
64 #define CLICKID_BIOSEQ   1
65 #define CLICKID_SEQFEAT  2
66 #define CLICKID_FEAT     3
67 #define CLICKSEQ_BIOSEQ  4
68 #define CLICKSEQ_SEQFEAT 5
69 #define CLICKSEQ_FEAT    6
70 
71 #define MOUSE_NOACTION   0
72 #define MOUSE_CLICK      1
73 #define MOUSE_DRAG       2
74 #define MOUSE_RELEASE    3
75 
76 /**********************************************************/
77 
78 static Int4    timerCount = 0;
79 static Boolean typing_timerInUse   = FALSE;
80 static Boolean deleting_timerInUse = FALSE;
81 static Boolean selecting_timerInUse= FALSE;
82 
83 static void click_caret (RecT *rp, Int4 position, SelStructPtr csp, SelStructPtr caret, EditAlignDataPtr adp, Int2 line);
84 
BioseqLength(SeqIdPtr sip)85 static Int4 BioseqLength (SeqIdPtr sip)
86 {
87   BioseqPtr bsp;
88   Int4      position = APPEND_RESIDUE;
89 
90   bsp=BioseqLockById(sip);
91   if (bsp) {
92      position=bsp->length-1;
93      BioseqUnlock(bsp);
94   }
95   return position;
96 }
97 /*********************************************************
98 ***
99 ***  ??????
100 ***
101 **********************************************************/
OBJ_(Uint2 feattype)102 extern Uint2 OBJ_ (Uint2 feattype)
103 {
104   if ( feattype == FEATDEF_BAD ) return OBJ_BIOSEQ;
105   return OBJ_SEQFEAT;
106 }
107 
108 /******************************************************************/
get_client_rect(PaneL p,RectPtr prc)109 static void get_client_rect (PaneL p, RectPtr prc)
110 {
111   ObjectRect (p, prc);
112   InsetRect (prc, HRZ_BORDER_WIDTH, VER_BORDER_WIDTH);
113 }
114 
115 /******************************************************************/
locate_region(SelStructPtr ssp,Int4 from,Int4 to,SeqIdPtr sip,Uint1 strand,Boolean is_fuzz)116 extern SelStructPtr locate_region (SelStructPtr ssp, Int4 from, Int4 to, SeqIdPtr sip, Uint1 strand, Boolean is_fuzz)
117 {
118   SeqLocPtr slp=NULL;
119   SeqIdPtr  siptmp=NULL;
120 
121   if (sip)
122      siptmp = SeqIdDup(sip);
123   if (ssp->region != NULL)
124          ssp->region = SeqLocFree ((SeqLocPtr) ssp->region);
125   if (is_fuzz)
126          slp = fuzz_loc (from, to, strand, siptmp, TRUE, TRUE);
127   else {
128          slp = SeqLocIntNew (from, to, strand, siptmp);
129   }
130   if ( slp != NULL ) {
131          ssp->regiontype = OM_REGION_SEQLOC;
132          ssp->region = (Pointer) slp;
133   }
134   else
135          ssp->regiontype = 0;
136   if (siptmp)
137      SeqIdFree (siptmp);
138   return ssp;
139 }
140 
141 /******************************************************************/
change_to_seqpos(SelStructPtr ssp,SeqAlignPtr salp,ValNodePtr sqloc_list)142 static SelStructPtr change_to_seqpos (SelStructPtr ssp, SeqAlignPtr salp, ValNodePtr sqloc_list)
143 {
144   SelStructPtr tmp = ssp;
145   SeqLocPtr slp;
146   SeqIntPtr sit;
147   SeqIdPtr  sip;
148 
149   slp = (SeqLocPtr) tmp->region;
150   if (slp) {
151      sit = (SeqIntPtr) slp->data.ptrvalue;
152      sip = SeqLocId (slp);
153      sit->from = AlignCoordToSeqCoord (SeqLocStart(slp), sip, salp, sqloc_list, 0);
154      if (sit->from < 0)
155         sit->from = 0;
156      sit->to = AlignCoordToSeqCoord (SeqLocStop(slp), sip, salp, sqloc_list, 0);
157      if (sit->to < 0)
158         sit->to = BioseqLength (sip);
159   }
160   return tmp;
161 }
162 
163 /******************************************************************/
replace_region(SelStructPtr ssp,Uint2 ssp_ed,Uint2 ssp_id,Uint2 ssp_it,Int4 from,Int4 to,SeqIdPtr sip,Uint1 strand,Boolean is_fuzz)164 extern SelStructPtr replace_region (SelStructPtr ssp, Uint2 ssp_ed, Uint2 ssp_id, Uint2 ssp_it, Int4 from, Int4 to, SeqIdPtr sip, Uint1 strand, Boolean is_fuzz)
165 {
166   if (from < 0 || sip == NULL)
167          return NULL;
168   ssp->entityID = ssp_ed;
169   ssp->itemID = ssp_id;
170   ssp->itemtype = ssp_it;
171   if (ssp->regiontype == OM_REGION_SEQLOC)
172          ssp->regiontype = 0;
173   if (ssp->region != NULL)
174          ssp->region = SeqLocFree ((SeqLocPtr) ssp->region);
175   ssp = locate_region (ssp, from, to, sip, strand, is_fuzz);
176   ssp->next = NULL;
177   ssp->prev = NULL;
178   return ssp;
179 }
180 
181 /******************************************************************/
nextlineup(Int2 line,Uint2Ptr itemtype,Uint2Ptr itemsubtype)182 static Int2 nextlineup (Int2 line, Uint2Ptr itemtype, Uint2Ptr itemsubtype)
183 {
184   Int2 j;
185   for (j = line-1; j >= 0; j--)
186   {
187          if (itemtype[j] == itemtype[line]
188          && itemsubtype[j] == itemsubtype[line]) break;
189   }
190   return j;
191 }
nextlinedown(Int2 line,Int2 to,Uint2Ptr itemtype,Uint2Ptr itemsubtype)192 static Int2 nextlinedown (Int2 line, Int2 to, Uint2Ptr itemtype, Uint2Ptr itemsubtype)
193 {
194   Int2 j;
195   for (j = line+1; j <= to; j++) {
196          if (itemtype[j] == itemtype[line]
197          && itemsubtype[j] == itemsubtype[line]) break;
198   }
199   if (j > to) return -1;
200   return j;
201 }
202 
moveup_scrollbar(PaneL pnl,Int2 adpvoffset,Int2 offset)203 static Int2 moveup_scrollbar (PaneL pnl, Int2 adpvoffset, Int2 offset)
204 {
205   if (adpvoffset > offset)
206   {
207      adpvoffset -= offset;
208      SeqEdSetValueScrollBar (pnl, (Int2)adpvoffset);
209   }
210   return adpvoffset;
211 }
212 
movedown_scrollbar(PaneL pnl,Int2 adpvoffset,Int2 offset)213 static Int2 movedown_scrollbar (PaneL pnl, Int2 adpvoffset, Int2 offset)
214 {
215   adpvoffset += offset;
216   SeqEdSetValueScrollBar (pnl, (Int2)(adpvoffset));
217   return adpvoffset;
218 }
219 
220 /******************************************************************
221 ***
222 ***  GoToButton
223 ***  LookAtButton
224 ***
225 *******************************************************************/
GoToFunc(SeqEditViewFormPtr wdp)226 static void GoToFunc (SeqEditViewFormPtr wdp)
227 {
228   WindoW             temport;
229   PaneL              pnl;
230   EditAlignDataPtr   adp;
231   RecT               rp;
232   Char               str [16];
233   Int4               line, column;
234   Int4               val;
235   Boolean            goOn;
236 
237   if (wdp==NULL)
238      return;
239   pnl = wdp->pnl;
240   if ( ( adp = GetAlignDataPanel (pnl) ) == NULL ) return;
241   temport = SavePort (pnl);
242   Select (pnl);
243 
244   GetTitle (wdp->gototxt, str, 15);
245   goOn = CCStrToLong (str, &val);
246   if (!goOn) {
247      RestorePort (temport);
248      CaptureSlateFocus ((SlatE) pnl);
249      return;
250   }
251   ResetClip ();
252   if (val < 0) {
253      val = 0;
254      sprintf (str, "%ld", (long) val);
255      SetTitle (wdp->gototxt, str);
256   }
257   else if (val > adp->length) {
258      val = adp->length;
259      sprintf (str, "%ld", (long) val);
260      SetTitle (wdp->gototxt, str);
261   }
262   if (val < adp->hoffset || val >=  adp->hoffset + adp->visibleLength)
263   {
264      adp->voffset = hoffset2voffset(adp, adp->anp_list, adp->visibleWidth, 0, adp->length-1, val);
265      data_collect_arrange (adp, TRUE);
266      SeqEdSetValueScrollBar (pnl, (Int2) adp->voffset);
267   }
268   get_client_rect (pnl, &rp);
269   SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID, adp->caret.itemtype, val, &line, &column, adp->hoffset, adp);
270   click_caret (&rp, val, &(adp->caret), &(adp->caret), adp, line);
271   if (!adp->display_panel)
272      to_update_prompt (pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
273   RestorePort (temport);
274   CaptureSlateFocus ((SlatE) pnl);
275 }
276 
GoToButton(ButtoN b)277 extern void GoToButton (ButtoN b)
278 {
279   SeqEditViewFormPtr wdp;
280 
281   wdp = (SeqEditViewFormPtr) GetObjectExtra ((WindoW)ParentWindow (b));
282   GoToFunc (wdp);
283 }
284 
LookAtButton(ButtoN b)285 extern void LookAtButton (ButtoN b)
286 {
287   WindoW             temport;
288   PaneL              pnl;
289   SeqEditViewFormPtr wdp;
290   EditAlignDataPtr   adp;
291   Char               str [16];
292   Int4               val;
293   Boolean            goOn;
294 
295   wdp = (SeqEditViewFormPtr) GetObjectExtra ((WindoW)ParentWindow (b));
296   pnl = wdp->pnl;
297   if ( ( adp = GetAlignDataPanel (pnl) ) == NULL ) return;
298   temport = SavePort (pnl);
299   Select (pnl);
300 
301   GetTitle (wdp->lookattxt, str, 15);
302   goOn = CCStrToLong (str, &val);
303   if (!goOn) return;
304 
305   ResetClip ();
306   if (val < 0) {
307      val = 0;
308      sprintf (str, "%ld", (long) val);
309      SetTitle (wdp->lookattxt, str);
310   }
311   else if (val > adp->length) {
312      val = adp->length;
313      sprintf (str, "%ld", (long) val);
314      SetTitle (wdp->lookattxt, str);
315   }
316   if (val < adp->hoffset || val >=  adp->hoffset + adp->visibleLength)
317   {
318      adp->voffset = hoffset2voffset(adp, adp->anp_list, adp->visibleWidth, 0, adp->length-1, val);
319      data_collect_arrange (adp, TRUE);
320      SeqEdSetValueScrollBar (pnl, (Int2) adp->voffset);
321   }
322   inval_panel (pnl, -1, -1);
323   RestorePort (temport);
324   CaptureSlateFocus ((SlatE) pnl);
325 }
326 
checkfeatdel(SeqLocPtr slp,ValNodePtr feathead)327 static Boolean checkfeatdel (SeqLocPtr slp, ValNodePtr feathead)
328 {
329   ValNodePtr     vnpfeat;
330   SelEdStructPtr feat;
331   SeqLocPtr      slpfeat;
332   Int4           lg;
333   Boolean        include;
334   Boolean        overlap;
335 
336   for  (vnpfeat = feathead; vnpfeat != NULL; vnpfeat = vnpfeat->next)
337   {
338      feat = (SelEdStructPtr) vnpfeat->data.ptrvalue;
339      while ( feat != NULL )
340      {
341         slpfeat = (SeqLocPtr) feat->region;
342         include = include_ssp (slp, slpfeat);
343         if (include)
344            return FALSE;
345         overlap = overlapp_ssp (slp, slpfeat);
346         if (overlap) {
347            lg = 0;
348            if (SeqLocStart(slp) > SeqLocStart(slpfeat))
349               lg += SeqLocStart(slp) - SeqLocStart(slpfeat);
350            if (SeqLocStop(slpfeat) > SeqLocStop(slp))
351               lg += SeqLocStop(slpfeat) - SeqLocStop(slp);
352            if (lg < 2) {
353               return FALSE;
354            }
355         }
356         feat = feat->next;
357      }
358   }
359   return TRUE;
360 }
361 
CutBtn(ButtoN b)362 static void CutBtn (ButtoN b)
363 {
364   WindoW             wdialog;
365   DialogBoxDataPtr   dbdp;
366   EditAlignDataPtr   adp;
367   SelStructPtr       ssp;
368   SeqLocPtr          slp;
369   BioseqPtr          bsp;
370 
371   wdialog = ParentWindow (b);
372   Hide (wdialog);
373   Update();
374   dbdp = (DialogBoxDataPtr) GetObjectExtra (wdialog);
375   if ( ( adp = GetAlignEditData (dbdp->w) ) == NULL ) return;
376   WatchCursor ();
377   ssp = (SelStructPtr) adp->extra_data;
378   slp = (SeqLocPtr) ssp->region;
379   if (slp!=NULL) {
380      bsp = BioseqCopy (NULL, SeqLocId(slp), SeqLocStart(slp), SeqLocStop(slp), Seq_strand_plus, TRUE);
381      if (bsp == NULL) {
382          ErrPostEx (SEV_ERROR, 0, 0, "fail at BioseqCopy [9]");
383      }
384      else {
385         ObjMgrAddToClipBoard (0, (Pointer) bsp);
386         SeqDeleteByLoc (slp, TRUE, adp->spliteditmode);
387         adp->dirty = TRUE;
388         ObjMgrSetDirtyFlag (ssp->entityID, TRUE);
389         ObjMgrSendMsg(OM_MSG_UPDATE, ssp->entityID, ssp->itemID, ssp->itemtype);
390         ObjMgrDeSelect(ssp->entityID, ssp->itemID, ssp->itemtype, ssp->regiontype, ssp->region);
391      }
392      adp->extra_data = NULL;
393   }
394   ArrowCursor ();
395   Remove (wdialog);
396   Update ();
397 }
398 
do_cut_dialog(WindoW w)399 static void do_cut_dialog (WindoW w)
400 {
401   WindoW           wdialog;
402   DialogBoxDataPtr dbdp;
403   GrouP            g1;
404 
405   wdialog = FixedWindow (-50, -33, -10, -10, "Cut", StdCloseWindowProc);
406   dbdp = (DialogBoxDataPtr) MemNew (sizeof (DialogBoxData));
407   SetObjectExtra (wdialog, (Pointer) dbdp, StdCleanupExtraProc);
408   dbdp->w = w;
409   g1 = HiddenGroup (wdialog, 2, 0, NULL);
410   StaticPrompt (g1, "Cut is going to delete a feature",0,popupMenuHeight,systemFont, 'l');
411   g1 = HiddenGroup (wdialog, 2, 0, NULL);
412   PushButton (g1, "Process", CutBtn);
413   PushButton (g1, "Dismiss", StdCancelButtonProc);
414   RealizeWindow (wdialog);
415   Show (wdialog);
416   return;
417 }
418 
do_cut(PaneL pnl,EditAlignDataPtr adp,SelStructPtr ssp,Boolean cut)419 extern Boolean do_cut (PaneL pnl, EditAlignDataPtr adp, SelStructPtr ssp, Boolean cut)
420 {
421   BioseqPtr        bsp;
422   SeqLocPtr        slp;
423   SeqIntPtr        sit;
424   Int4             to;
425 
426   StringToClipboard (NULL);
427   if (ssp == NULL) {
428          ErrPostEx (SEV_ERROR, 0, 0, "Can not cut [1]");
429          return FALSE;
430   }
431   if (ssp->itemtype != OBJ_BIOSEQ) {
432          ErrPostEx (SEV_ERROR, 0, 0, "Can not cut [2]");
433          return FALSE;
434   }
435   slp = (SeqLocPtr) ssp->region;
436   if (slp == NULL) {
437          ErrPostEx (SEV_ERROR, 0, 0, "Can not cut [3]");
438          return FALSE;
439   }
440   if (SeqLocStop(slp) == APPEND_RESIDUE) {
441      to = BioseqLength (SeqLocId(slp));
442      if (to > 0) {
443         sit = (SeqIntPtr) slp->data.ptrvalue;
444         sit->to = to;
445      }
446      else {
447         ErrPostEx (SEV_ERROR, 0, 0, "Can not cut [6]");
448         return FALSE;
449      }
450   }
451   if (SeqLocLen(slp) <= 0 || SeqLocLen(slp) >= adp->length) {
452          ErrPostEx (SEV_ERROR, 0, 0, "Can not cut [5]");
453          return FALSE;
454   }
455 
456   if ( !checkfeatdel (slp, adp->seqfeat) ) {
457          adp->extra_data = (Pointer) ssp;
458          do_cut_dialog ((WindoW)ParentWindow(pnl));
459          return TRUE;
460   }
461   if (cut) {
462      WatchCursor ();
463      bsp = BioseqCopy (NULL, SeqLocId(slp), SeqLocStart(slp), SeqLocStop(slp), Seq_strand_plus, TRUE);
464      ArrowCursor ();
465      if (bsp == NULL) {
466          ErrPostEx (SEV_ERROR, 0, 0, "Can not cut [4]");
467          return FALSE;
468      }
469   }
470   WatchCursor ();
471   if (cut)
472      ObjMgrAddToClipBoard (0, (Pointer) bsp);
473   SeqDeleteByLoc (slp, TRUE, adp->spliteditmode);
474   adp->dirty = TRUE;
475   ObjMgrSetDirtyFlag (ssp->entityID, TRUE);
476   ObjMgrSendMsg (OM_MSG_UPDATE, ssp->entityID, ssp->itemID, ssp->itemtype);
477   ObjMgrDeSelect (ssp->entityID, ssp->itemID, ssp->itemtype, ssp->regiontype, ssp->region);
478   ArrowCursor ();
479   Update ();
480   return TRUE;
481 }
482 
483 /******************************************************************/
do_paste(PaneL pnl,EditAlignDataPtr adp,SeqIdPtr sourceid)484 extern Boolean do_paste (PaneL pnl, EditAlignDataPtr adp, SeqIdPtr sourceid)
485 {
486   SelStructPtr     caret;
487   SeqLocPtr        slpcaret;
488   Int4             caretpos;
489   Boolean          ok;
490 
491   caret = &(adp->caret);
492   slpcaret = (SeqLocPtr) caret->region;
493   if ( slpcaret == NULL ) {
494          ErrPostEx (SEV_ERROR, 0, 0, "Fail in do_paste [1]");
495          return FALSE;
496   }
497   caretpos = SeqLocStart (slpcaret);
498   if ( caretpos < 0 ) {
499          ErrPostEx (SEV_ERROR, 0, 0, "Fail in do_paste [2]");
500          return FALSE;
501   }
502   if ( caretpos == adp->length ) caretpos = -2;
503 
504   WatchCursor ();
505   ok = BioseqInsert (sourceid, FIRST_RESIDUE, LAST_RESIDUE, Seq_strand_plus, SeqLocId (slpcaret), caretpos, TRUE, TRUE, adp->spliteditmode);
506   ArrowCursor ();
507   if (!ok) {
508          ErrPostEx (SEV_ERROR, 0, 0, "Fail in do_paste [3]");
509          return FALSE;
510   }
511   Update ();
512   return TRUE;
513 }
514 
515 /******************************************************************/
do_copy(IteM i)516 extern void do_copy (IteM i)
517 {
518   SelStructPtr     ssp = NULL;
519   SeqLocPtr        slp;
520   BioseqPtr        bsp;
521   Int4             from, to;
522 
523   WatchCursor ();
524   StringToClipboard (NULL);
525   if ( checkOMss_for_itemtype (OBJ_BIOSEQ) ) {
526      ssp = ObjMgrGetSelected ();
527      for (; ssp != NULL; ssp = ssp->next)
528         if ( ssp->itemtype == OBJ_BIOSEQ && checkssp_for_editor (ssp) )
529            break;
530      if ( ssp != NULL ) {
531         slp = (SeqLocPtr) ssp->region;
532         from = SeqLocStart(slp);
533         to = SeqLocStop(slp);
534         if (to < 0)
535            to = BioseqLength (SeqLocId(slp));
536         if (to > 0) {
537            bsp=BioseqCopy(NULL, SeqLocId(slp), from, to, Seq_strand_plus, TRUE);
538            if (bsp != NULL)
539               ObjMgrAddToClipBoard (0, (Pointer) bsp);
540         }
541      }
542   }
543   ArrowCursor ();
544   return;
545 }
546 
CleanBufferProc(ValNodePtr bufvnp,Int2 nbseq,Int4 buflength)547 static Int4 CleanBufferProc (ValNodePtr bufvnp, Int2 nbseq, Int4 buflength)
548 {
549   TextAlignBufPtr tdp;
550   CharPtr PNTR    str;
551   ValNodePtr      vnp;
552   Boolean         goOn = TRUE;
553   Int2            j;
554 
555   str = (CharPtr PNTR) MemNew ((size_t) ((nbseq +1) * sizeof(CharPtr)));
556   for (vnp =bufvnp, j =0; vnp !=NULL && j <nbseq; vnp =vnp->next, j++) {
557          tdp = (TextAlignBufPtr) vnp->data.ptrvalue;
558          str[j] = tdp->buf;
559   }
560   while (goOn) {
561          for (j = 0; j < nbseq; j++) {
562                 if ( *(str[j] +buflength -1) != '-') break;
563          }
564          goOn = (Boolean) (j == nbseq);
565          if (goOn) {
566                 for (j=0; j<nbseq; j++)
567                 {
568                        *(str[j] +buflength -1) = '\0';
569                 }
570                 buflength--;
571          }
572   }
573   MemFree (str);
574   return buflength;
575 }
576 
AlignDataGapAddProc(Char ch,Int4 cursorx,ValNodePtr linebuff,Int4 bufferlength,Uint2 entityID,Uint2 itemID)577 static Boolean AlignDataGapAddProc (Char ch, Int4 cursorx, ValNodePtr linebuff, Int4 bufferlength, Uint2 entityID, Uint2 itemID)
578 {
579   TextAlignBufPtr  tap;
580   ValNodePtr       vnp;
581   CharPtr          buf;
582   Boolean          insert = FALSE;
583   Int4             k;
584 
585   for (vnp = linebuff; vnp != NULL; vnp = vnp->next)
586   {
587          tap = (TextAlignBufPtr) vnp->data.ptrvalue;
588          if (tap != NULL) {
589             if (OBJ_(tap->feattype) == OBJ_BIOSEQ) {
590                 buf = (CharPtr) tap->buf;
591                 if((tap->seqEntityID == entityID && tap->bsp_itemID == itemID)
592                 || is_selectedbyID(tap->seqEntityID,tap->bsp_itemID,OBJ_BIOSEQ))
593                 {
594                       for (k = bufferlength; k > cursorx; k--)
595                          buf [k] = buf [k-1];
596                       buf [cursorx] = ch;
597                       buf [bufferlength +1] = '\0';
598                       insert = TRUE;
599                 }
600                 else {
601                       buf [bufferlength] = '-';
602                       buf [bufferlength +1] = '\0';
603                 }
604             }
605          }
606   }
607   return insert;
608 }
609 
610 /******************************************************************
611 ***
612 ***   CLICK - DRAG - RELEASE procedure
613 ***
614 ******************************************************************/
update_prompt(PaneL pnl,CharPtr label,Int4 position)615 static void update_prompt (PaneL pnl, CharPtr label, Int4 position)
616 {
617   WindoW             w;
618   SeqEditViewFormPtr wdp;
619   SelStructPtr       ssp;
620   Char               str[128];
621   Int4               from, to;
622   Int2               k;
623 
624   w = getwindow_frompanel (pnl);
625   wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
626   ResetClip ();
627   if (position >= 0) {
628      sprintf (str, "%s Position %ld", label, (long)position);
629      SetTitle (wdp->pos, str);
630   }
631   else if (position == LAST_RESIDUE) {
632      sprintf (str, "%s", label);
633      SetTitle (wdp->pos, str);
634   }
635   else {
636      k = checkOMss_for_itemtype (OBJ_BIOSEQ);
637      if (k == 1) {
638         ssp = getOMselect_for_itemtype (OBJ_BIOSEQ);
639         from = SeqLocStart ((SeqLocPtr) ssp->region);
640         to = SeqLocStop ((SeqLocPtr) ssp->region);
641         sprintf (str, "%s Selection %ld - %ld", label, (long)(from+1), (long)(to+1));
642         SetTitle (wdp->pos, str);
643      }
644      else {
645         sprintf (str, " ");
646         SetTitle (wdp->pos, str);
647      }
648   }
649 }
650 
update_promptsel(PaneL pnl,CharPtr label)651 static void update_promptsel (PaneL pnl, CharPtr label)
652 {
653   WindoW             w;
654   SeqEditViewFormPtr wdp;
655 
656   w = getwindow_frompanel (pnl);
657   wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
658   ResetClip ();
659   SetTitle (wdp->pos, label);
660 }
661 
seqid_tolabel(SeqIdPtr sip,Uint1 choice)662 static CharPtr seqid_tolabel (SeqIdPtr sip, Uint1 choice)
663 {
664   BioseqPtr bsp;
665   SeqIdPtr  tmp = NULL;
666   Char      str[120];
667   CharPtr   strp;
668 
669   str[0] = '\0';
670   if (choice && choice <= PRINTID_GIcc && sip)
671   {
672      bsp = BioseqLockById(sip);
673      if (bsp!=NULL)
674      {
675         if (choice==PRINTID_GIcc)
676            tmp = SeqIdFindBest (bsp->id, 0);
677         else
678            tmp = SeqIdFindWorst (bsp->id);
679         if (tmp)
680         {
681            SeqIdWrite (tmp, str, choice, 120);
682            BioseqUnlock(bsp);
683            strp = StringSave (str);
684            return strp;
685         }
686         BioseqUnlock(bsp);
687      }
688   }
689   if (choice!=0 && sip) {
690      SeqIdWrite (sip, str, choice, 120);
691      strp = StringSave (str);
692      return strp;
693   }
694   strp = StringSave (str);
695   return strp;
696 }
697 
to_update_prompt(PaneL pnl,SelStructPtr ssp,SeqAlignPtr salp,ValNodePtr sqloc_list,Boolean sel,Uint1 choice)698 extern void to_update_prompt (PaneL pnl, SelStructPtr ssp, SeqAlignPtr salp, ValNodePtr sqloc_list, Boolean sel, Uint1 choice)
699 {
700   SeqIdPtr  sip;
701   Int4      pos, posto;
702   CharPtr   seqid=NULL;
703   Char      str[255];
704   Char      tmp[252];
705   CharPtr   strp;
706   SeqLocPtr slp;
707   SelStructPtr selp;
708 
709   if (ssp==NULL)
710      return;
711   if (ssp->region == NULL)
712      return;
713 
714   str[0] = '0';
715   slp = (SeqLocPtr) ssp->region;
716   sip = SeqLocId(slp);
717   if (choice == 0)
718      choice = PRINTID_FASTA_LONG;  /*PRINTID_TEXTID_ACCESSION;*/
719   seqid = seqid_tolabel (sip, choice);
720   selp = is_selectedbyID (ssp->entityID, ssp->itemID, ssp->itemtype);
721   if (selp != NULL)
722   {
723      strp = str;
724      pos = SeqLocStart((SeqLocPtr)selp->region);
725      posto = SeqLocStop((SeqLocPtr)selp->region);
726      if (posto == APPEND_RESIDUE)
727         posto = BioseqLength (sip);
728      if (selp->next == NULL)
729         sprintf (tmp, "%s Selection %ld - %ld", seqid, (long)(pos+1), (long)(posto+1));
730      else
731         sprintf (tmp, "%s Selections %ld - %ld", seqid, (long)(pos+1), (long)(posto+1));
732      strp = StringMove (strp, tmp);
733      selp = selp->next;
734      while (selp != NULL && (StringLen(str) < 200)) {
735         if (checkssp_for_editor (selp) && is_sameId (selp->entityID, selp->itemID, selp->itemtype, 255, ssp->entityID, ssp->itemID, ssp->itemtype, 255))
736         {
737            pos = SeqLocStart((SeqLocPtr)selp->region);
738            posto = SeqLocStop((SeqLocPtr)selp->region);
739            sprintf (tmp, ", %ld - %ld", (long)(pos+1), (long)(posto+1));
740            strp = StringMove (strp, tmp);
741         }
742         selp = selp->next;
743      }
744      update_promptsel (pnl, str);
745   }
746   else {
747      if (salp != NULL) {
748         pos = AlignCoordToSeqCoord (SeqLocStart(slp), sip, salp, sqloc_list, 1);
749         if (pos == APPEND_RESIDUE)
750            pos = BioseqLength (sip);
751      }
752      else pos = SeqLocStart(slp);
753      if (sel) {
754         if (salp != NULL) {
755            posto = AlignCoordToSeqCoord (SeqLocStop(slp), sip, salp, sqloc_list, 0);
756         }
757         else posto = SeqLocStop(slp);
758         if (posto == APPEND_RESIDUE)
759            posto = BioseqLength (sip);
760         sprintf (str, "%s Selection %ld - %ld", seqid, (long)(pos+1), (long)(posto+1));
761         update_promptsel (pnl, str);
762      }
763      else {
764         update_prompt (pnl, seqid, pos);
765      }
766   }
767   if (seqid)
768      MemFree (seqid);
769   return;
770 }
771 
update_edititem(PaneL pnl)772 extern void update_edititem (PaneL pnl)
773 {
774   WindoW             w;
775   EditAlignDataPtr   adp;
776   SeqEditViewFormPtr wdp;
777   Int2               k;
778 
779   w = getwindow_frompanel (pnl);
780   if ((adp = GetAlignEditData (w)) == NULL)
781      return;
782   if (adp->edit_mode == SEQ_EDIT || adp->edit_mode == ALIGN_EDIT)
783   {
784      wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
785      ResetClip ();
786      k = checkOMss_for_itemtype (OBJ_BIOSEQ);
787      if (k > 0) {
788         Enable (wdp->cutitem);
789         Enable (wdp->copyitem);
790      }
791      else {
792         Disable (wdp->cutitem);
793         Disable (wdp->copyitem);
794      }
795   }
796 }
797 
update_savefeatitem(PaneL pnl)798 static void update_savefeatitem (PaneL pnl)
799 {
800   WindoW             w;
801   EditAlignDataPtr   adp;
802   SeqEditViewFormPtr wdp;
803   Int2               k;
804 
805   w = getwindow_frompanel (pnl);
806   if ((adp = GetAlignEditData (w)) == NULL)
807      return;
808   if (adp->edit_mode == SEQ_EDIT || adp->edit_mode == ALIGN_EDIT) {
809      wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
810      ResetClip ();
811      k = checkOMss_for_itemtype(OBJ_SEQFEAT);
812      if (k > 0) {
813         Enable (wdp->savefeatitem);
814         Enable (wdp->savefeatbt);
815      }
816      else {
817         Disable (wdp->savefeatitem);
818         Disable (wdp->savefeatbt);
819      }
820   }
821 }
822 
update_translateitem(PaneL pnl,ValNodePtr seqfeathead,ValNodePtr feathead)823 extern void update_translateitem (PaneL pnl, ValNodePtr seqfeathead, ValNodePtr feathead)
824 {
825   WindoW             w;
826   SeqEditViewFormPtr wdp;
827   Int2               k;
828 
829   w = getwindow_frompanel (pnl);
830   wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
831   ResetClip ();
832   k = checkCDSselect_forprotein (seqfeathead, feathead, FALSE);
833   if (k == 0) {
834      Disable (wdp->translateitem);
835      Disable (wdp->translatebt);
836   }
837   else {
838      Enable  (wdp->translateitem);
839      Enable  (wdp->translatebt);
840   }
841 }
842 
update_codonstartbt(PaneL pnl,ValNodePtr seqfeathead,ValNodePtr feathead)843 extern void update_codonstartbt (PaneL pnl, ValNodePtr seqfeathead, ValNodePtr feathead)
844 {
845   WindoW             w;
846   SeqEditViewFormPtr wdp;
847   SelEdStructPtr     feat;
848   Char               str[128];
849   Int2               k;
850 
851   w = getwindow_frompanel (pnl);
852   wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
853   ResetClip ();
854   k = checkCDSselect_forprotein (seqfeathead, feathead, TRUE);
855   if (k == 1) {
856      feat = getCDSselect (seqfeathead, feathead);
857      sprintf (str, "Codon start %d", (int)(feat->codonstart));
858      SetTitle (wdp->codonstitem, str);
859      Enable  (wdp->codonstitem);
860   }
861   else {
862      sprintf (str, "Codon start");
863      SetTitle (wdp->codonstitem, str);
864      Disable (wdp->codonstitem);
865   }
866 }
867 
on_time(WindoW w)868 extern void on_time (WindoW w)
869 {
870   EditAlignDataPtr adp;
871 
872   if ((adp = GetAlignEditData (w)) == NULL) return;
873   timerCount++;
874   if (typing_timerInUse || deleting_timerInUse) {
875      if (adp->edit_item.entityID != 0 && timerCount > 40) {
876         typing_timerInUse = FALSE;
877         deleting_timerInUse = FALSE;
878         timerCount = 0;
879         ObjMgrSendMsg (OM_MSG_UPDATE, adp->caret.entityID, adp->caret.itemID, adp->caret.itemtype);
880      }
881   }
882   else if (selecting_timerInUse) {
883      if (timerCount > 80) {
884         selecting_timerInUse = FALSE;
885         timerCount = 0;
886         ObjMgrSendMsg (OM_MSG_SELECT, adp->caret.entityID, adp->caret.itemID, adp->caret.itemtype);
887      }
888   }
889   return;
890 }
891 
update_select_when_release(EditAlignDataPtr adp)892 static void update_select_when_release (EditAlignDataPtr adp)
893 {
894    if (selecting_timerInUse) {
895      selecting_timerInUse = FALSE;
896      timerCount = 0;
897      ObjMgrSendMsg (OM_MSG_SELECT, adp->caret.entityID, adp->caret.itemID, adp->caret.itemtype);
898   }
899   return;
900 }
901 
click_id(PaneL pnl,SelStructPtr csp,EditAlignDataPtr adp)902 static void click_id (PaneL pnl, SelStructPtr csp, EditAlignDataPtr adp)
903 {
904   SelStructPtr     spp;
905   SeqIdPtr         sip;
906   Int4             from, to;
907   Int4             start, stop;
908   ValNodePtr       vnp;
909   AlignNodePtr     anp;
910   SeqLocPtr        slp;
911   SeqAlignPtr      salp = (SeqAlignPtr) adp->sap_align->data;
912 
913   if ( csp == NULL ) {
914      ErrPostEx (SEV_ERROR, 0, 0, "fail in click_id [1]");
915      return;
916   }
917   Select (pnl);
918   spp = is_selectedbyID (csp->entityID, csp->itemID, csp->itemtype);
919   if (spp != NULL) {
920      ObjMgrDeSelectAll ();
921      if (! adp->display_panel)
922         to_update_prompt (pnl, &(adp->caret), salp, adp->sqloc_list, FALSE, adp->printid);
923   }
924   else if (shftKey && ctrlKey)
925   {
926      spp=ObjMgrGetSelected();
927      if(spp!=NULL) {
928           for(; spp!=NULL; spp=spp->next){
929              if(spp->entityID==csp->entityID && spp->itemID==csp->itemID)
930                 break;
931           }
932           if (spp == NULL) {
933              spp=ObjMgrGetSelected();
934              slp=(SeqLocPtr)spp->region;
935              start=SeqCoordToAlignCoord(SeqLocStart(slp), SeqLocId(slp), salp, 0, 0);
936              stop=SeqCoordToAlignCoord(SeqLocStop(slp), SeqLocId(slp), salp, 0, 0);
937              sip = SeqLocId ((SeqLocPtr)csp->region);
938              from=AlignCoordToSeqCoord (start, sip, salp, adp->sqloc_list, 0);
939              to=AlignCoordToSeqCoord (stop, sip, salp, adp->sqloc_list, 0);
940              slp = SeqLocIntNew(from, to, SeqLocStrand((SeqLocPtr)csp->region), sip);
941              ObjMgrAlsoSelect (csp->entityID, csp->itemID, csp->itemtype, OM_REGION_SEQLOC, (Pointer)slp);
942           }
943      }
944   }
945   else if (shftKey)
946   {
947      csp = change_to_seqpos (csp, salp, adp->sqloc_list);
948      for(spp=ObjMgrGetSelected(); spp!=NULL; spp=spp->next)
949            if (spp->entityID!=csp->entityID || spp->itemID!=csp->itemID)
950               break;
951      if (spp == NULL)
952      {
953            ObjMgrAlsoSelect (csp->entityID, csp->itemID, csp->itemtype, csp->regiontype, csp->region);
954      }
955      else {
956            for (vnp=adp->anp_list; vnp != NULL; vnp = vnp->next) {
957               anp = (AlignNodePtr) vnp->data.ptrvalue;
958               if (anp != NULL)
959                  if (anp->seq_entityID==spp->entityID && anp->bsp_itemID == spp->itemID )
960                    break;
961            }
962            if (vnp!=NULL) {
963               vnp = vnp->next;
964               for (; vnp!=NULL; vnp = vnp->next) {
965                  anp = (AlignNodePtr) vnp->data.ptrvalue;
966                  if (anp!=NULL) {
967                     spp = is_selectedbyID (anp->seq_entityID, anp->bsp_itemID, OBJ_BIOSEQ);
968                     if (spp==NULL) {
969                        slp = CollectSeqLocFromAlignNode(anp);
970                        if (slp!=NULL)
971                        {
972                           ObjMgrAlsoSelect (anp->seq_entityID, anp->bsp_itemID, OBJ_BIOSEQ, OM_REGION_SEQLOC, (Pointer)slp);
973                        }
974                        if (anp->seq_entityID==csp->entityID && anp->bsp_itemID == csp->itemID )
975                           break;
976                     }
977                  }
978               }
979            }
980      }
981   }
982   else if (ctrlKey)
983   {
984      csp = change_to_seqpos (csp, salp, adp->sqloc_list);
985      ObjMgrAlsoSelect (csp->entityID, csp->itemID, csp->itemtype, csp->regiontype, csp->region);
986   }
987   else {
988      csp = change_to_seqpos (csp, salp, adp->sqloc_list);
989      ObjMgrSelect (csp->entityID, csp->itemID, csp->itemtype, csp->regiontype, csp->region);
990   }
991   Update ();
992   return;
993 }
994 
995 /******************************************************************/
click_caret(RecT * rp,Int4 position,SelStructPtr csp,SelStructPtr caret,EditAlignDataPtr adp,Int2 line)996 static void click_caret (RecT *rp, Int4 position, SelStructPtr csp, SelStructPtr caret, EditAlignDataPtr adp, Int2 line)
997 {
998   SeqIdPtr sip;
999 
1000   if (csp != NULL) {
1001      if ( caret->regiontype != 0 )
1002         inval_selstructpos(adp,caret->entityID, caret->itemID, caret->itemtype, rp, SeqLocStart ((SeqLocPtr)caret->region));
1003      sip = SeqIdDup (SeqLocId((SeqLocPtr)csp->region));
1004      replace_region (caret, csp->entityID, csp->itemID, csp->itemtype, position, position, sip, SeqLocStrand((SeqLocPtr)csp->region), FALSE);
1005      SeqIdFree (sip);
1006      adp->caret_orig = position;
1007      adp->cur_pat = NULL;
1008      inval_selstructpos (adp, caret->entityID, caret->itemID, caret->itemtype, rp, position);
1009   }
1010 }
1011 
1012 /******************************************************************/
click_feat(PaneL pnl,Int4 position,SelStructPtr csp,EditAlignDataPtr adp,Int2 line)1013 static void click_feat (PaneL pnl, Int4 position, SelStructPtr csp, EditAlignDataPtr adp, Int2 line)
1014 {
1015   RecT             rp;
1016   SeqLocPtr        slp;
1017   SeqAlignPtr      salp;
1018   Int4             start, stop;
1019   Int2             width;
1020 
1021   if ( csp == NULL ) {
1022      ErrPostEx (SEV_ERROR, 0, 0, "fail in click_feat [1]");
1023      return;
1024   }
1025   get_client_rect (pnl, &rp);
1026   if ( ! shftKey ) {
1027      width = adp->visibleWidth;
1028      if (adp->columnpcell > 0)
1029         width += (Int2) adp->visibleWidth / (Int2) adp->columnpcell;
1030   }
1031   salp = (SeqAlignPtr) adp->sap_align->data;
1032   slp = (SeqLocPtr) csp->region;
1033   start = SeqLocStart(slp);
1034   stop = SeqLocStop(slp);
1035   start = SeqCoordToAlignCoord (start, SeqLocId(slp), salp, 0, 0);
1036   stop = SeqCoordToAlignCoord (stop, SeqLocId(slp), salp, 0, 0);
1037   if (position > start && position < stop)
1038      adp->click_feat = 3;
1039   else if (position <= start && position > start- 2)
1040      adp->click_feat = 1;
1041   else if (position >= stop  && position < stop + 2)
1042      adp->click_feat = 2;
1043   else adp->click_feat = 0;
1044   adp->feat_line = line;
1045   inval_selstructloc_forfeat (adp, csp->entityID, csp->itemID, csp->itemtype, 255, &rp, start, stop);
1046   csp = change_to_seqpos (csp, salp, adp->sqloc_list);
1047   if ( ! shftKey )
1048   {
1049      ObjMgrSelect (csp->entityID,csp->itemID, csp->itemtype, csp->regiontype, csp->region);
1050   }
1051   else
1052   {
1053      ObjMgrAlsoSelect (csp->entityID, csp->itemID, csp->itemtype, csp->regiontype, csp->region);
1054   }
1055 }
1056 
1057 /******************************************************************/
invalminmax(RecT * rp,SelStructPtr spp,Int4 position,EditAlignDataPtr adp)1058 static void invalminmax (RecT *rp, SelStructPtr spp, Int4 position, EditAlignDataPtr adp)
1059 {
1060   SeqLocPtr  slp;
1061   Int4       pos,
1062              posmin, posmax;
1063 
1064   slp = (SeqLocPtr) spp->region;
1065   if ( position > adp->caret_orig )
1066   {
1067      pos = MIN((Int4)SeqLocStart(slp),(Int4)SeqLocStop(slp));
1068      posmin = MIN(pos,(Int4) adp->edit_pos);
1069      posmax = MAX(pos,(Int4) adp->edit_pos);
1070      inval_selstructloc (adp, spp->entityID, spp->itemID, spp->itemtype, 255, rp, posmin, posmax);
1071   }
1072   else if ( position < adp->caret_orig )
1073   {
1074      pos = MAX((Int4)SeqLocStart(slp),(Int4)SeqLocStop(slp));
1075      posmin = MIN(pos,(Int4) adp->edit_pos);
1076      posmax = MAX(pos,(Int4) adp->edit_pos);
1077      inval_selstructloc (adp, spp->entityID, spp->itemID, spp->itemtype, 255, rp, posmin, posmax);
1078   }
1079 }
1080 
1081 
1082 /******************************************************************/
get_closest_selection(SelStructPtr caret,SeqAlignPtr salp,SelStructPtr current_point,ValNodePtr sqloc_list)1083 static SelStructPtr get_closest_selection (SelStructPtr caret, SeqAlignPtr salp, SelStructPtr current_point, ValNodePtr sqloc_list)
1084 {
1085   SelStructPtr ssp,
1086                car,
1087                this_selection=NULL;
1088   Int4         position;
1089   Int4         val , valmin = INT4_MAX;
1090 
1091   car = SelStructDup (caret);
1092   car = change_to_seqpos (car, salp, sqloc_list);
1093   if (car)
1094   {
1095      ssp = ObjMgrGetSelected();
1096      if (ssp==NULL)
1097         this_selection = current_point;
1098      else
1099      {
1100         position = SeqLocStart((SeqLocPtr)car->region);
1101         for (; ssp != NULL; ssp = ssp->next)
1102         {
1103            if ( checkssp_for_editor (ssp) && is_sameId (ssp->entityID, ssp->itemID, ssp->itemtype, 255, car->entityID, car->itemID, car->itemtype, 255) )
1104            {
1105               val = (Int4)(ABS(SeqLocStart((SeqLocPtr)ssp->region)-position)+ABS(SeqLocStop((SeqLocPtr)ssp->region)-position));
1106 
1107               if ( val < valmin )
1108               {
1109                  this_selection = ssp;
1110                  valmin = val;
1111               }
1112            }
1113         }
1114      }
1115      SelStructDel (car);
1116   }
1117   return this_selection;
1118 }
1119 
1120 
1121 /******************************************************************
1122 ***
1123 *** Open and Extend this_selection by AlsoSeqlect
1124 ***
1125 **************** *******************************************/
extend_selectregion(EditAlignDataPtr adp,SelStructPtr this_selection,Int4 position,Int4 old_caret_pos,Boolean IsOtherSel,PaneL pnl)1126 static Boolean extend_selectregion (EditAlignDataPtr adp, SelStructPtr this_selection, Int4 position,Int4 old_caret_pos, Boolean IsOtherSel, PaneL pnl)
1127 {
1128   SeqIdPtr         sip;
1129   SeqLocPtr        slp;
1130   SeqAlignPtr      salp;
1131   Int4             from, to, itmp;
1132   Uint2            sspei, sspii, sspit;
1133   Boolean          retval=FALSE;
1134 
1135   sspei = (Uint2) adp->caret.entityID;
1136   sspii = (Uint2) adp->caret.itemID;
1137   sspit = (Uint2) adp->caret.itemtype;
1138   if (is_sameId (this_selection->entityID, this_selection->itemID, this_selection->itemtype, 255, sspei, sspii, sspit, 255))
1139   {
1140      salp = (SeqAlignPtr) adp->sap_align->data;
1141 	 sip = SeqLocId((SeqLocPtr)adp->caret.region);
1142 	 if (!IsOtherSel){/*no previous close selection*/
1143 	    		   /*Create a SelStruct between old_caret_pos and position*/
1144 		from = AlignCoordToSeqCoord (old_caret_pos, sip, salp, adp->sqloc_list, 0);
1145 		to = AlignCoordToSeqCoord (position, sip, salp, adp->sqloc_list, 0);
1146 		if (from > to){
1147 			itmp=to; to=from; from=itmp;
1148 		}
1149 		slp = SeqLocIntNew (from, to, Seq_strand_plus, sip);
1150 		retval=ObjMgrAlsoSelect (this_selection->entityID, this_selection->itemID,
1151                    this_selection->itemtype, OM_REGION_SEQLOC, slp);
1152 	 }
1153  }
1154   return retval;
1155 }
1156 
1157 /******************************************************************/
dragcaret_selectrgn(PaneL pnl,Int4 position,SelStructPtr spp,SelStructPtr caret,EditAlignDataPtr adp,Int2 line)1158 static void dragcaret_selectrgn (PaneL pnl, Int4 position, SelStructPtr spp, SelStructPtr caret, EditAlignDataPtr adp, Int2 line)
1159 {
1160   SeqLocPtr        slp;
1161   SeqAlignPtr      salp;
1162   SeqIdPtr         sip;
1163   RecT             rp;
1164   float hratio;
1165 
1166   if ( spp == NULL)  {
1167 /*********
1168          ErrPostEx (SEV_ERROR, 0, 0, "fail in dragcaret_selectrgn [2]");
1169 *********/
1170          return;
1171   }
1172   get_client_rect (pnl, &rp);
1173   hratio = (float)adp->hoffset / (float)adp->length;
1174   salp = (SeqAlignPtr) adp->sap_align->data;
1175   selecting_timerInUse = TRUE;
1176   if ( position == adp->caret_orig )
1177   {
1178      invalminmax (&rp, spp, position, adp);
1179      inval_selstructloc (adp, spp->entityID, spp->itemID, spp->itemtype, 255, &rp, SeqLocStart((SeqLocPtr) spp->region), SeqLocStop((SeqLocPtr) spp->region));
1180      adp->caret_line = line;
1181      data_collect_arrange (adp, TRUE);
1182      SeqEdSetCorrectBarMax (pnl, adp, hratio);
1183      if (!adp->display_panel)
1184          to_update_prompt (pnl, spp, NULL, adp->sqloc_list, FALSE, adp->printid);
1185      ObjMgrDeSelect (spp->entityID, spp->itemID, spp->itemtype, spp->regiontype, spp->region);
1186   }
1187   else {
1188      slp = (SeqLocPtr) spp->region;
1189      sip = SeqLocId (slp);
1190      invalminmax (&rp, spp, position, adp);
1191      position = AlignCoordToSeqCoord (position, sip, salp, adp->sqloc_list, 0);
1192      if ( position > adp->caret_orig )
1193      {
1194         if (position < 0) position =BioseqLength (sip);
1195         slp = SeqLocIntNew (SeqLocStart(slp), position, Seq_strand_plus, sip);
1196      }
1197      else
1198      {
1199         if (position < 0) position = 0;
1200         slp = SeqLocIntNew (position, SeqLocStop(slp), Seq_strand_plus, sip);
1201      }
1202      ObjMgrAlsoSelect (spp->entityID, spp->itemID, spp->itemtype, OM_REGION_SEQLOC, slp);
1203      adp->caret_line = line;
1204      if (!adp->display_panel)
1205          to_update_prompt (pnl, spp, salp, adp->sqloc_list, TRUE, adp->printid);
1206   }
1207   return;
1208 }
1209 
1210 
1211 
1212 /******************************************************************/
drag_feat(PaneL pnl,Int4 position,SelEdStructPtr feat,EditAlignDataPtr adp,Int2 line,Int2 feattype,SelEdStructPtr prec,SelEdStructPtr next,SelStructPtr selssp)1213 static void drag_feat (PaneL pnl, Int4 position, SelEdStructPtr feat, EditAlignDataPtr adp, Int2 line, Int2 feattype, SelEdStructPtr prec, SelEdStructPtr next, SelStructPtr selssp)
1214 {
1215   SeqLocPtr        slp;
1216   SeqLocPtr        slpprec = NULL, slpnext = NULL;
1217   SeqIntPtr        sitfeat;
1218   SeqAlignPtr      salp;
1219   RecT             rp;
1220   Int4             linebefmv, lineaftmv, line2befmv, line2aftmv;
1221   Int4             column;
1222   Int2             width;
1223   Int4             oldposfrom, oldposto;
1224   Int4             oldseqfrom, oldseqto;
1225   Int4             minpos, maxpos;
1226   Boolean          updateline = FALSE;
1227   SeqLocPtr selslp;
1228   SeqIntPtr selsit;
1229   float hratio;
1230 
1231   if ( adp->click_feat == 0 ) return;
1232   if ( feat == NULL)  {
1233          ErrPostEx (SEV_ERROR, 0, 0, "fail in drag_feat [0]");
1234          return;
1235   }
1236   get_client_rect (pnl, &rp);
1237   width = adp->visibleWidth;
1238   if (adp->columnpcell > 0)
1239          width += (Int2) adp->visibleWidth / (Int2) adp->columnpcell;
1240   slp = (SeqLocPtr) feat->region;
1241   if (slp == NULL) {
1242          ErrPostEx (SEV_ERROR, 0, 0, "fail in drag_feat [2.1]");
1243          return;
1244   }
1245   sitfeat = (SeqIntPtr) slp->data.ptrvalue;
1246   if (sitfeat == NULL) {
1247          ErrPostEx (SEV_ERROR, 0, 0, "fail in drag_feat [2.2]");
1248          return;
1249   }
1250   hratio = (float)adp->hoffset / (float)adp->length;
1251   salp = (SeqAlignPtr) adp->sap_align->data;
1252   oldseqfrom = SeqLocStart (slp);
1253   oldseqto = SeqLocStop (slp);
1254   oldposfrom = SeqCoordToAlignCoord(oldseqfrom, SeqLocId(slp), salp, 0, 0);
1255   oldposto = SeqCoordToAlignCoord(oldseqto, SeqLocId(slp), salp, 0, 0);
1256   if (prec != NULL)
1257      slpprec = (SeqLocPtr) prec->region;
1258   if (next != NULL)
1259      slpnext = (SeqLocPtr) next->region;
1260   if ( adp->click_feat == 1 )
1261   {
1262       if ( position >= 0 && position <= oldposto)
1263       {
1264          sitfeat->from=AlignCoordToSeqCoord(position,SeqLocId(slp), salp, adp->sqloc_list, 0);
1265          if (!overlapp_ssp (slp, slpprec) && !overlapp_ssp (slp, slpnext))
1266          {
1267             if ((feattype == SEQFEAT_CDREGION || feattype == FEATDEF_CDS)
1268             && feat->data != NULL ) {
1269                sesp_to_pept (feat, salp, adp->sqloc_list, FALSE);
1270                inval_selstruct (adp, feat->entityID, feat->itemID, feat->itemtype, FEATDEF_TRSL, &rp, adp->margin.left, (Int2) (width *adp->charw));
1271             }
1272             minpos = MIN (oldposfrom, position);
1273             maxpos = MAX (oldposfrom, position) + 1;
1274             inval_selstructloc_forfeat (adp, feat->entityID, feat->itemID, feat->itemtype, feattype, &rp,  minpos, maxpos);
1275             updateline = TRUE;
1276          }
1277          else sitfeat->from = oldseqfrom;
1278       }
1279   }
1280   else if ( adp->click_feat == 2 )
1281   {
1282       if ( position < adp->length && position >= oldposfrom)
1283       {
1284          sitfeat->to =AlignCoordToSeqCoord(position,SeqLocId(slp), salp, adp->sqloc_list, 0);
1285          if (!overlapp_ssp (slp, slpprec) && !overlapp_ssp (slp, slpnext))
1286          {
1287             if ((feattype == SEQFEAT_CDREGION || feattype == FEATDEF_CDS)
1288             && feat->data != NULL ) {
1289                sesp_to_pept (feat, salp, adp->sqloc_list, FALSE);
1290                inval_selstruct (adp, feat->entityID, feat->itemID, feat->itemtype, FEATDEF_TRSL, &rp, adp->margin.left, (Int2) (width *adp->charw));
1291             }
1292             minpos = MIN (oldposto, position) - 1;
1293             maxpos = MAX (oldposto, position);
1294             inval_selstructloc_forfeat (adp, feat->entityID, feat->itemID, feat->itemtype, feattype, &rp, minpos, maxpos);
1295             updateline = TRUE;
1296          }
1297          else sitfeat->to = oldseqto;
1298       }
1299   }
1300   else if ( adp->click_feat == 3 )
1301   {
1302       if (oldposfrom >= adp->feat_pos - position
1303       && oldposto + position - adp->feat_pos < adp->length)
1304       {
1305          if(position < adp->feat_pos && oldposfrom > adp->feat_pos -position)
1306          {
1307                 sitfeat->from -= (adp->feat_pos - position);
1308                 sitfeat->to -= (adp->feat_pos - position);
1309          }
1310          else if (oldposto + adp->feat_pos - position < adp->length)
1311          {
1312                 sitfeat->from += (position - adp->feat_pos);
1313                 sitfeat->to += (position - adp->feat_pos);
1314          }
1315          if (!overlapp_ssp (slp, slpprec) && !overlapp_ssp (slp, slpnext))
1316          {
1317             if ((feattype == SEQFEAT_CDREGION || feattype == FEATDEF_CDS)
1318             && feat->data != NULL ) {
1319                sesp_to_pept (feat, salp, adp->sqloc_list, FALSE);
1320                inval_selstruct (adp, feat->entityID, feat->itemID, feat->itemtype, FEATDEF_TRSL, &rp, adp->margin.left, (Int2) (width *adp->charw));
1321             }
1322             maxpos = SeqCoordToAlignCoord(sitfeat->from, SeqLocId(slp), salp, 0, 0);
1323             minpos = MIN (oldposfrom, maxpos);
1324             maxpos = MAX (oldposfrom, sitfeat->from) + 1;
1325             inval_selstructloc_forfeat (adp, feat->entityID, feat->itemID, feat->itemtype, feattype, &rp, minpos, maxpos);
1326             maxpos = SeqCoordToAlignCoord(sitfeat->to, SeqLocId(slp), salp, 0, 0);
1327             minpos = MIN (oldposto, maxpos) - 1;
1328             maxpos = MAX (oldposto, maxpos);
1329             inval_selstructloc_forfeat (adp, feat->entityID, feat->itemID, feat->itemtype, feattype, &rp, minpos, maxpos);
1330             updateline = TRUE;
1331          }
1332          else {
1333             sitfeat->from = oldseqfrom;
1334             sitfeat->to = oldseqto;
1335          }
1336       }
1337   }
1338   selslp = (SeqLocPtr) selssp->region;
1339   selsit = (SeqIntPtr) selslp->data.ptrvalue;
1340   selsit->from = sitfeat->from;
1341   selsit->to = sitfeat->to;
1342 
1343   if (updateline)
1344   {
1345      SeqPosToLineColumn (feat->itemID, feat->entityID, feat->itemtype,
1346          oldposfrom, &linebefmv, &column, adp->hoffset, adp);
1347      SeqPosToLineColumn (feat->itemID, feat->entityID, feat->itemtype,
1348          oldposto, &line2befmv, &column, adp->hoffset, adp);
1349      SeqPosToLineColumn (feat->itemID, feat->entityID, feat->itemtype,
1350          SeqLocStart(slp), &lineaftmv, &column, adp->hoffset, adp);
1351      SeqPosToLineColumn (feat->itemID, feat->entityID, feat->itemtype,
1352          SeqLocStop(slp), &line2aftmv,&column, adp->hoffset, adp);
1353      if ( lineaftmv > linebefmv )
1354      {
1355          ResetClip ();
1356          inval_rect (rp.left, (Int2)(rp.top+ linebefmv *adp->lineheight),
1357                      rp.right, rp.bottom);
1358          data_collect_arrange (adp, TRUE);
1359          SeqEdSetCorrectBarMax (pnl, adp, hratio);
1360          adp->voffset = moveup_scrollbar (pnl, adp->voffset, 1);
1361          Update ();
1362 
1363      }
1364      else if ( lineaftmv < linebefmv )
1365      {
1366          ResetClip ();
1367          inval_rect (rp.left, (Int2)(rp.top+ lineaftmv *adp->lineheight),
1368                           rp.right, rp.bottom);
1369          data_collect_arrange (adp, TRUE);
1370          SeqEdSetCorrectBarMax (pnl, adp, hratio);
1371          adp->voffset = movedown_scrollbar (pnl, adp->voffset, (Int2)(1));
1372          Update ();
1373      }
1374      if ( line2aftmv < line2befmv ) {
1375          inval_rect (rp.left, (Int2)(rp.top+ line2befmv *adp->lineheight),
1376                           rp.right, rp.bottom);
1377          data_collect_arrange (adp, TRUE);
1378          SeqEdSetCorrectBarMax (pnl, adp, hratio);
1379      }
1380      else if ( line2aftmv > line2befmv ) {
1381          inval_rect (rp.left, (Int2)(rp.top+ line2aftmv *adp->lineheight),
1382                           rp.right, rp.bottom);
1383          data_collect_arrange (adp, TRUE);
1384          SeqEdSetCorrectBarMax (pnl, adp, hratio);
1385      }
1386      adp->feat_line = line;
1387   }
1388   adp->dirty = TRUE;
1389   return;
1390 }
1391 
1392 /******************************************************************/
release_caret(PaneL pnl,Int4 position,SelStructPtr csp,SelStructPtr caret,EditAlignDataPtr adp,Int2 line)1393 static void release_caret (PaneL pnl, Int4 position, SelStructPtr csp, SelStructPtr caret, EditAlignDataPtr adp, Int2 line)
1394 {
1395   RecT             rp;
1396 
1397   if ( csp == NULL ) {
1398          return;
1399   }
1400   if  ( adp->caret.regiontype == 0 || adp->caret.region == NULL)  {
1401 /*****
1402          ErrPostEx (SEV_ERROR, 0, 0, "fail in release_caret [2]");
1403 *****/
1404          return;
1405   }
1406   if ( !is_samessp (caret, csp) ) {
1407          get_client_rect (pnl, &rp);
1408          click_caret (&rp, position, csp, caret, adp, line);
1409          if (!adp->display_panel)
1410             to_update_prompt (pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
1411          ObjMgrDeSelectAll ();
1412   }
1413   update_select_when_release (adp);
1414 }
1415 
1416 /******************************************************************/
make_bspssp(SelStructPtr csp,ValNodePtr anp_list,Int4 from,Int4 to)1417 static SelStructPtr make_bspssp (SelStructPtr csp, ValNodePtr anp_list, Int4 from, Int4 to)
1418 {
1419   SeqIdPtr         sip;
1420   Uint1            strand;
1421 
1422   sip = (SeqIdPtr) SeqIdFromAlignNode (anp_list, csp->entityID, csp->itemID,
1423          csp->itemtype);
1424   if (sip == NULL) return NULL;
1425   strand = StrandFromAlignNode (anp_list, csp->entityID, csp->itemID,
1426          csp->itemtype);
1427   locate_region (csp, from, to, sip, strand, FALSE);
1428 
1429   return csp;
1430 }
1431 
1432 /******************************************************************/
get_featId_fromid(SelStructPtr csp,ValNodePtr feathead,Int2 itemsubtype)1433 static SeqIdPtr get_featId_fromid (SelStructPtr csp, ValNodePtr feathead, Int2 itemsubtype)
1434 {
1435   SelEdStructPtr   feat;
1436   SeqLocPtr        slp;
1437 
1438   feat = get_feat_fromid (feathead, itemsubtype, csp->entityID, csp->itemID, -1, NULL);
1439   if (feat == NULL)
1440      return NULL;
1441   slp = (SeqLocPtr) feat->region;
1442   if (slp == NULL)
1443      return NULL;
1444   return SeqLocId(slp);
1445 }
1446 /******************************************************************/
make_featssp(SelStructPtr csp,ValNodePtr feathead,Int2 itemsubtype,Int4 position,Int4 from,Int4 to)1447 static SelStructPtr make_featssp (SelStructPtr csp, ValNodePtr feathead, Int2 itemsubtype, Int4 position, Int4 from, Int4 to)
1448 {
1449   SelEdStructPtr   feat;
1450   SeqLocPtr        slp;
1451 
1452   feat = get_feat_fromid (feathead, itemsubtype, csp->entityID, csp->itemID, position, NULL);
1453   if (feat == NULL ) return NULL;
1454   slp = (SeqLocPtr) feat->region;
1455   if (slp == NULL) return NULL;
1456   if (from < 0) {
1457       locate_region (csp, SeqLocStart(slp), SeqLocStop(slp), SeqLocId (slp),
1458                     SeqLocStrand(slp), FALSE);
1459   }
1460   else
1461       locate_region (csp, from, to, SeqLocId(slp), SeqLocStrand(slp), FALSE);
1462   return csp;
1463 }
1464 
1465 /******************************************************************/
make_bufssp(SelStructPtr csp,SelStructPtr bufhead,Int2 itemsubtype)1466 static SelStructPtr make_bufssp (SelStructPtr csp, SelStructPtr bufhead, Int2 itemsubtype)
1467 {
1468   SelStructPtr     buf;
1469   SelStructPtr     ssp;
1470   SeqLocPtr        slp = NULL;
1471   Uint2            subtype, type;
1472   Boolean          locate = FALSE;
1473 
1474   if (itemsubtype==SEQFEAT_CDREGION) {
1475          subtype = SEQFEAT_CDREGION; type = OBJ_SEQFEAT;
1476   }
1477   else if (itemsubtype==FEATDEF_CDS) {
1478          subtype = FEATDEF_CDS; type = OBJ_SEQFEAT;
1479   }
1480   else {
1481          subtype = FEATDEF_BAD; type = OBJ_BIOSEQ;
1482   }
1483   for (buf = bufhead; buf != NULL; buf = buf->next) {
1484          ssp = (SelStructPtr) buf->region;
1485          if ( buf->itemtype == subtype && ssp->itemtype == type) {
1486                 slp = (SeqLocPtr) ssp->region;
1487          }
1488          else slp = NULL;
1489          if ( buf->itemtype == itemsubtype && slp != NULL ) {
1490                 ssp = (SelStructPtr) buf->region;
1491                 if ( is_samessp(ssp, csp) ) {
1492                    locate_region(csp, SeqLocStart(slp), SeqLocStop(slp),
1493                        SeqLocId(slp), SeqLocStrand(slp), FALSE);
1494                    locate = TRUE;
1495                    break;
1496                 }
1497          }
1498   }
1499   if (!locate) return NULL;
1500   return csp;
1501 }
1502 
1503 /*********************************************************
1504 ***
1505 ***  locate_point
1506 ***
1507 **********************************************************/
locate_point(PoinT pt,RecT rp,Uint4 * item_id,Uint2 * the_entity_id,Uint2 * item_type,Uint2 * item_subtype,Int4 * position,Int2 * line,EditAlignDataPtr adp)1508 extern Uint1 locate_point (PoinT pt, RecT rp, Uint4 *item_id, Uint2 *the_entity_id, Uint2 *item_type, Uint2 *item_subtype, Int4 *position, Int2 *line, EditAlignDataPtr adp)
1509 {
1510   Uint4 itemid = 0;
1511   Uint2 seqEntityid = 0;
1512   Uint2 itemtype = 0;
1513   Uint2 itemsubtype = 0;
1514   Int4  pos = -1;
1515   Int4  x = -1;
1516   Int4  dx;
1517   Int2  ligne = -1;
1518   Uint1 what = BADLAND;
1519 
1520   *item_id = *the_entity_id = (Uint4) 0;
1521   *item_type= *item_subtype = (Uint2) 0;
1522   *position = (Int4) -1;
1523   *line = (Int2) -1;
1524   if ( pt.x < rp.left || pt.x > rp.right ) return 0;
1525   ligne = (pt.y - rp.top) / adp->lineheight;
1526   if ( ligne >= 0 && ligne < adp->pnlLine ) {
1527 	 itemid = adp->item_id [ligne];
1528 	 seqEntityid = adp->seqEntity_id [ligne];
1529 	 itemtype = adp->itemtype [ligne];
1530 	 itemsubtype = adp->itemsubtype [ligne];
1531   }
1532   if (ligne > adp->pnlLine) {
1533          return HOLDDNLAND;
1534   }
1535   if (ligne < 0) {
1536          return HOLDUPLAND;
1537   }
1538   pos = (pt.x - rp.left - adp->margin.left);
1539 /**
1540   WriteLog ("locate ii %d ei %d it %d  ist %d\n", adp->item_id [ligne], adp->seqEntity_id [ligne], adp->itemtype [ligne], adp->itemsubtype [ligne]);
1541 **/
1542   if ( adp->seqEntity_id [ligne] > 0 && adp->item_id [ligne] > 0 )
1543   {
1544          if ( pos >= 0 )
1545          {
1546                 x = (Int4) (pos + (adp->charw/6)) / adp->charw;
1547                 if (adp->columnpcell > 0)
1548                 {
1549                         dx = (Int4) x / (Int4) adp->columnpcell;
1550                         dx = (Int4) (x -dx) / (Int4) adp->columnpcell;
1551                         x -= dx;
1552                 }
1553                 x += adp->hoffset - adp->bufferstart
1554                         + adp->alignline[ligne] * adp->visibleWidth;
1555                 if (adp->colonne[x]==-1 && adp->seqnumber==1 && x>adp->length) {
1556                    x = adp->length;
1557                 } else {
1558                    x = adp->colonne[x];
1559                 }
1560          }
1561          else if ( pos <  0 && pos > -adp->charw )
1562          {
1563                 x = adp->hoffset - adp->bufferstart
1564                         + adp->alignline[ligne] * adp->visibleWidth;
1565                 x = adp->colonne[x];
1566          }
1567          /* else WriteLog ("locate_point in margin\n"); */
1568          if ( x >= 0 && x <= adp->length )
1569                what = SEQLAND;
1570          else if ( x < 0 )
1571                what = SIDLAND;
1572   }
1573   if ( what == SIDLAND )
1574   {
1575          *item_id   = itemid;
1576          *the_entity_id = (Uint2) seqEntityid;
1577          *item_type = (Uint2) itemtype;
1578          *item_subtype = (Uint2) itemsubtype;
1579          *position = (Int4) -1;
1580          *line = (Int2) ligne;
1581   }
1582   else if ( what == SEQLAND )
1583   {
1584          *item_id   = itemid;
1585          *the_entity_id = (Uint2) seqEntityid;
1586          *item_type = (Uint2) itemtype;
1587          *item_subtype = (Uint2) itemsubtype;
1588          *position = (Int4) x;
1589          *line = (Int2) ligne;
1590   }
1591   return what;
1592 }
1593 
on_click(PaneL pnl,PoinT pt)1594 extern void on_click (PaneL pnl, PoinT pt)
1595 {
1596   EditAlignDataPtr adp;
1597   SeqAlignPtr      salp;
1598   SeqIdPtr         the_sip;
1599   SelStruct        sp;
1600   SelStructPtr     ssp = NULL;
1601   SelStructPtr     this_selection = NULL;
1602   RecT             rp;
1603   Int4             position;
1604   Int4             pos_inseq;
1605   Int2             line;
1606   Uint2            itemsubtype;
1607   Uint1            what;
1608 
1609   if ( ( adp = GetAlignDataPanel (pnl)) == NULL ) return;
1610   if ( adp->seqnumber == 0 ) return;
1611   get_client_rect (pnl, &rp);
1612   sp.regiontype = 0;
1613   sp.region = NULL;
1614   what = locate_point (pt, rp, &sp.itemID, &sp.entityID, &sp.itemtype,
1615           &itemsubtype, &position, &line, adp);
1616   if ( what >= BADLAND )
1617           return;
1618   if ( position > adp->length +1) {
1619           ErrPostEx (SEV_ERROR, 0, 0, "position> length");
1620           return;
1621   }
1622   adp->select_block = NULL;
1623   adp->mouse_mode = MOUSE_CLICK;
1624 /***
1625   WriteLog("click what %d  %d %d %d %d pos %d lin %d  \n", (int) what,
1626     (int) sp.itemID, (int) sp.entityID, (int)sp.itemtype, (int)itemsubtype,
1627     (int) position, (int)line);
1628 ****/
1629   salp = (SeqAlignPtr) adp->sap_align->data;
1630   switch (what)
1631   {
1632     case SIDLAND:
1633           if ( itemsubtype == FEATDEF_BAD )
1634           {
1635              ssp = make_bspssp (&sp, adp->anp_list, 0, -2);
1636              adp->clickwhat = CLICKID_BIOSEQ;
1637              if (dblClick) {
1638                 if (adp->edit_mode==SEQ_VIEW || adp->edit_mode==SEQ_EDIT || adp->edit_mode==ALIGN_EDIT) {
1639                    WatchCursor ();
1640                    Update ();
1641                    GatherProcLaunch (OMPROC_EDIT, FALSE, sp.entityID, sp.itemID, OBJ_BIOSEQ, 0, 0, OBJ_BIOSEQ, 0);
1642                    ArrowCursor ();
1643                    Update ();
1644                    ssp= NULL;
1645                 }
1646              }
1647           }
1648           else if (sp.itemtype == OBJ_SEQFEAT)
1649           {
1650              if (dblClick)
1651              {
1652                 WatchCursor ();
1653                 Update ();
1654                 GatherProcLaunch (OMPROC_EDIT, FALSE, sp.entityID, sp.itemID, sp.itemtype, 0, 0, sp.itemtype, 0);
1655                 ArrowCursor ();
1656                 Update ();
1657                 ssp = NULL;
1658              }
1659              else {
1660                 the_sip = get_featId_fromid(&sp, adp->seqfeat, itemsubtype);
1661                 pos_inseq = AlignCoordToSeqCoord (position, the_sip, salp, adp->sqloc_list, 0);
1662                 ssp = make_featssp (&sp, adp->seqfeat, itemsubtype, pos_inseq, -1, -1);
1663                 adp->clickwhat = CLICKID_SEQFEAT;
1664              }
1665           }
1666           else if( itemsubtype >=EDITDEF_RF1 && itemsubtype<=EDITDEF_RF6 )
1667           {
1668              ssp = make_bufssp (&sp, adp->buffer, itemsubtype);
1669              adp->clickwhat = CLICKID_FEAT;
1670           }
1671           if (ssp != NULL) {
1672              click_id (pnl, ssp, adp);
1673           }
1674           break;
1675     case SEQLAND:
1676           if ( position >=0 ) {
1677              adp->clickwhat = CLICKSEQ_BIOSEQ;
1678              if(adp->edit_mode==SEQ_VIEW || adp->edit_mode==SEQ_EDIT || adp->edit_mode == ALIGN_EDIT)
1679              {
1680                 if ( itemsubtype == FEATDEF_BAD )
1681                 {
1682                    if (!shftKey) {
1683 		      ssp=make_bspssp (&sp, adp->anp_list, position, position);
1684                       click_caret (&rp, position, ssp, &(adp->caret), adp, line);
1685                       if (!ctrlKey)
1686                          ObjMgrDeSelectAll ();
1687                    }
1688 		   else
1689                    {
1690                       this_selection = get_closest_selection(&(adp->caret),salp, &sp, adp->sqloc_list);
1691                       if (this_selection!=NULL) {
1692 			 extend_selectregion (adp, this_selection, position, adp->caret_orig, FALSE, pnl);
1693                       }
1694                    }
1695                    if (!adp->display_panel)
1696                       to_update_prompt(pnl,&(adp->caret), salp, adp->sqloc_list, FALSE, adp->printid);
1697                    adp->edit_pos = position;
1698                    adp->caret_line = line;
1699                 }
1700                 else if (sp.itemtype == OBJ_SEQFEAT)
1701                 {
1702                    if (dblClick)
1703                    {
1704                       WatchCursor ();
1705                       Update ();
1706                       GatherProcLaunch (OMPROC_EDIT, FALSE, sp.entityID, sp.itemID, sp.itemtype, 0, 0, sp.itemtype, 0);
1707                       ArrowCursor ();
1708                       Update ();
1709                    }
1710                    else {
1711                       the_sip = get_featId_fromid(&sp, adp->seqfeat, itemsubtype);
1712                       pos_inseq = AlignCoordToSeqCoord (position, the_sip, salp, adp->sqloc_list, 0);
1713                       ssp = make_featssp (&sp, adp->seqfeat, itemsubtype, pos_inseq, -1, -1);
1714                       if (ssp != NULL)
1715                       {
1716                          click_feat (pnl, position, ssp, adp, line);
1717                          adp->feat_pos = position;
1718                          adp->clickwhat = CLICKSEQ_SEQFEAT;
1719                       }
1720                    }
1721                 }
1722              }
1723           }
1724           break;
1725     default:
1726           adp->clickwhat = NOCLICK;
1727           break;
1728   }
1729   Update ();
1730 }
1731 
1732 /**************************************
1733 ***
1734 ***  Drag Procedure
1735 ***        2: drag on sequence
1736 ***
1737 ***************************************/
1738 /*if CtrlKey is pushed and the user clicks within a selected region,
1739 don't move the caret*/
getcurrentcaretpos(Int4 position,Uint2 eID,Uint2 iID,Uint2 itype,Boolean direction)1740 static Int4 getcurrentcaretpos (Int4 position, Uint2 eID, Uint2 iID, Uint2 itype, Boolean direction)
1741 {
1742    SelStructPtr sspsel=NULL;
1743 
1744  if (ctrlKey){
1745 	sspsel=ObjMgrGetSelected();
1746     	if (sspsel != NULL)
1747     	{
1748        		for (; sspsel != NULL; sspsel = sspsel->next)
1749        		{
1750        		   if ( checkssp_for_editor (sspsel) && is_sameId (sspsel->entityID, sspsel->itemID, sspsel->itemtype, 255, eID, iID, itype, 255) )
1751 		 {
1752             		  if ( (position>= SeqLocStart((SeqLocPtr)sspsel->region)) &&
1753 				(position<= SeqLocStop((SeqLocPtr)sspsel->region))){
1754 				if (direction)
1755 					return SeqLocStart((SeqLocPtr)sspsel->region);
1756 				else
1757 					return SeqLocStop((SeqLocPtr)sspsel->region);
1758 			   }
1759         	   }
1760        		}
1761     	}
1762   }
1763   return -1;
1764 }
1765 
on_drag(PaneL pnl,PoinT pt)1766 extern void on_drag (PaneL pnl, PoinT pt)
1767 {
1768   EditAlignDataPtr adp;
1769   SeqAlignPtr      salp;
1770   SeqIdPtr         the_sip;
1771   SelStruct        sp;
1772   SelStructPtr     this_selection = NULL;
1773   RecT             rp;
1774   Int4             position;
1775   Int2             line;
1776   Uint2            itemsubtype;
1777   Int4             from, to,
1778                    caret_origseq, new_caret_orig;
1779   SeqLocPtr        slp;
1780   Uint1            direction = Seq_strand_plus;
1781 
1782 
1783   if ( ( adp = GetAlignDataPanel (pnl)) == NULL ) return;
1784   if ( adp->seqnumber == 0 ) return;
1785   get_client_rect (pnl, &rp);
1786   sp.regiontype = 0;
1787   sp.region = NULL;
1788   locate_point (pt, rp, &sp.itemID, &sp.entityID, &sp.itemtype, &itemsubtype, &position, &line, adp);
1789   if ( position > adp->length) {
1790           ErrPostEx (SEV_ERROR, 0, 0, "position> length");
1791           return;
1792   }
1793   salp = (SeqAlignPtr) adp->sap_align->data;
1794   switch ( adp->clickwhat )
1795   {
1796     case CLICKID_BIOSEQ:
1797           break;
1798     case CLICKID_SEQFEAT:
1799           break;
1800     case CLICKID_FEAT:
1801           break;
1802     case CLICKSEQ_BIOSEQ:
1803           if (position>=0) {
1804            if (position != adp->edit_pos || adp->mouse_mode == MOUSE_DRAG)
1805            {
1806             this_selection = &sp;
1807             if (is_sameId (this_selection->entityID, this_selection->itemID,
1808                this_selection->itemtype, 255, adp->caret.entityID, adp->caret.itemID,
1809                adp->caret.itemtype, 255))
1810             {
1811                 if (position < adp->edit_pos) {
1812                    direction = Seq_strand_minus;
1813                 }
1814                 the_sip = SeqLocId((SeqLocPtr)adp->caret.region);
1815                 if (the_sip) {
1816                  caret_origseq = AlignCoordToSeqCoord (adp->caret_orig, the_sip, salp, adp->sqloc_list, 0);
1817                  if (adp->mouse_mode == MOUSE_CLICK)
1818                  {
1819                    new_caret_orig = getcurrentcaretpos (caret_origseq, adp->caret.entityID, adp->caret.itemID, adp->caret.itemtype, (Boolean)(direction==Seq_strand_plus));
1820                    if (new_caret_orig<0)
1821                      new_caret_orig=caret_origseq;
1822                    else if (caret_origseq != new_caret_orig) {
1823                       adp->caret_orig = SeqCoordToAlignCoord (new_caret_orig, the_sip, salp, 0, 0);
1824                    }
1825                  }
1826                  else {
1827                    new_caret_orig=caret_origseq;
1828                  }
1829                  from = new_caret_orig;
1830                  to = AlignCoordToSeqCoord (position, the_sip, salp, adp->sqloc_list, 0);
1831                  if (from > to) {
1832                    from = to;
1833                    to = new_caret_orig;
1834                  }
1835                  slp = SeqLocIntNew (from, to, direction, the_sip);
1836                  ObjMgrAlsoSelect (this_selection->entityID, this_selection->itemID,
1837                    this_selection->itemtype, OM_REGION_SEQLOC, slp);
1838                  adp->edit_pos = position;
1839                  adp->mouse_mode = MOUSE_DRAG;
1840                 }
1841              }
1842            }
1843            else if (adp->mouse_mode == MOUSE_CLICK)
1844               adp->mouse_mode = MOUSE_DRAG;
1845           }
1846           break;
1847 
1848     case CLICKSEQ_SEQFEAT:
1849 /********************
1850           if ( select != NULL )
1851           {
1852              sspei = (Uint2) select->entityID;
1853              sspii = (Uint2) select->itemID;
1854              sspit = (Uint2) select->itemtype;
1855              sspist= (Uint2) select->regiontype;
1856              if (position >= 0 && position < adp->length && sspit == OBJ_SEQFEAT)
1857              {
1858                 ssp = is_selectedbyID (sspei, sspii, sspit);
1859                 if ( ssp == NULL )
1860                 {
1861                    click_feat (pnl, position, adp->select, adp, line);
1862                    ssp = is_selectedbyID (sspei, sspii, sspit);
1863                 }
1864                 if ( ssp != NULL && position != adp->feat_pos )
1865                 {
1866                    prec = NULL;
1867                    pos_inseq = AlignCoordToSeqCoord (adp->feat_pos, SeqLocId((SeqLocPtr)ssp->region), salp, adp->sqloc_list, 0);
1868                    feat = get_feat_fromid (adp->seqfeat, sspist, sspei, sspii, pos_inseq, &prec);
1869                    if ( feat != NULL )
1870                    {
1871                        drag_feat (pnl, position, feat, adp, line, sspist, prec, feat->next, ssp);
1872                    }
1873                    adp->feat_pos = position;
1874                 }
1875              }
1876           }
1877 **********************/
1878           break;
1879 
1880     case NOCLICK:
1881           break;
1882     default:
1883           break;
1884   }
1885   Update ();
1886 }
1887 
1888 /**************************************
1889 ***
1890 ***  Hold Procedure
1891 ***        4: hold on sequence
1892 ***        5: hold on sequence
1893 ***
1894 ***************************************/
on_hold(PaneL pnl,PoinT pt)1895 extern void on_hold (PaneL pnl, PoinT pt)
1896 {
1897   EditAlignDataPtr adp;
1898   SeqAlignPtr      salp;
1899   RecT             rp;
1900   SelStruct        sp;
1901   SelStructPtr     this_selection = NULL;
1902   Int4             position;
1903   Int2             line;
1904   Uint2            itemsubtype;
1905   Uint1            what;
1906 
1907   SelEdStructPtr   feat, prec;
1908 
1909   if ( ( adp = GetAlignDataPanel (pnl)) == NULL ) return;
1910   if ( adp->seqnumber == 0 ) return;
1911   get_client_rect (pnl, &rp);
1912   sp.regiontype = 0;
1913   sp.region = NULL;
1914   what = locate_point (pt, rp, &sp.itemID, &sp.entityID, &sp.itemtype, &itemsubtype, &position, &line, adp);
1915   ResetClip ();
1916   salp = (SeqAlignPtr) adp->sap_align->data;
1917   if ( what == HOLDDNLAND ) {
1918           if (adp->voffset >= adp->nlines-1) return;
1919           adp->voffset = movedown_scrollbar (pnl, adp->voffset, (Int2)1);
1920           Update ();
1921           if ( adp->clickwhat == CLICKSEQ_BIOSEQ)
1922           {
1923              position = adp->edit_pos + adp->visibleWidth;
1924              if (position > adp->length) position = adp->length;
1925              adp->caret_line++;
1926              dragcaret_selectrgn (pnl, position, get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list), &(adp->caret), adp, adp->caret_line);
1927              setposition_tossp (&(adp->caret), position, position);
1928              adp->edit_pos = position;
1929           }
1930           else if (adp->clickwhat== CLICKSEQ_SEQFEAT || adp->clickwhat == CLICKSEQ_FEAT)
1931           {
1932              prec = NULL;
1933              this_selection = get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list);
1934              feat = get_feat_fromid (adp->feat, this_selection->regiontype, this_selection->entityID, this_selection->itemID, adp->feat_pos, &prec);
1935              if ( feat != NULL )
1936              {
1937                    adp->feat_line++;
1938                    position = adp->feat_pos + adp->visibleWidth;
1939                    drag_feat (pnl, position, feat, adp, adp->feat_line, this_selection->regiontype, prec, feat->next, NULL);
1940              }
1941              adp->feat_pos = position;
1942           }
1943   }
1944   else if ( what == HOLDUPLAND )
1945   {
1946           if (adp->voffset == 0 || adp->hoffset == 0) return;
1947           adp->voffset = moveup_scrollbar (pnl, adp->voffset, (Int2)1);
1948           Update ();
1949           if ( adp->clickwhat == CLICKSEQ_BIOSEQ)
1950           {
1951              position = adp->edit_pos - adp->visibleWidth;
1952              if (position < 0) position = 0;
1953              adp->caret_line--;
1954              dragcaret_selectrgn (pnl,position,get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list),&(adp->caret), adp, adp->caret_line);
1955              setposition_tossp (&(adp->caret), position, position);
1956              adp->edit_pos = position;
1957           }
1958           else if (adp->clickwhat == CLICKSEQ_SEQFEAT || adp->clickwhat == CLICKSEQ_FEAT)
1959           {
1960              this_selection = get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list);
1961              feat = get_feat_fromid (adp->feat, this_selection->regiontype, this_selection->entityID, this_selection->itemID, adp->feat_pos, &prec);
1962              if ( feat != NULL )
1963              {
1964                    adp->feat_line--;
1965                    position = adp->feat_pos - adp->visibleWidth;
1966                    drag_feat (pnl, position, feat, adp, adp->feat_line, this_selection->regiontype, prec, feat->next, NULL);
1967              }
1968              adp->feat_pos = position;
1969           }
1970   }
1971   Update ();
1972 }
1973 
1974 /**************************************
1975 ***
1976 ***  Release Procedure
1977 ***
1978 ***************************************/
on_release(PaneL pnl,PoinT pt)1979 extern void on_release (PaneL pnl, PoinT pt)
1980 {
1981   EditAlignDataPtr adp;
1982   SelStruct        sp;
1983   SelStructPtr     ssp = NULL;
1984   RecT             rp;
1985   Int2             line;
1986   Int4             position;
1987   Uint2            itemsubtype;
1988 
1989   if ( ( adp = GetAlignDataPanel (pnl)) == NULL ) return;
1990   if ( adp->seqnumber == 0 ) return;
1991   get_client_rect (pnl, &rp);
1992   sp.regiontype = 0;
1993   sp.region = NULL;
1994   locate_point (pt, rp, &sp.itemID, &sp.entityID, &sp.itemtype, &itemsubtype, &position, &line, adp);
1995   if ( position > adp->length +1) {
1996           ErrPostEx (SEV_ERROR, 0, 0, "position> length");
1997           return;
1998   }
1999   switch ( adp->clickwhat )
2000   {
2001     case CLICKID_BIOSEQ:
2002           break;
2003     case CLICKSEQ_BIOSEQ:
2004           if ( position >= 0 && adp->mouse_mode == MOUSE_DRAG) {
2005                 ssp = make_bspssp (&sp, adp->anp_list, position, position);
2006                 if (ssp != NULL) {
2007                    release_caret (pnl, position, ssp, &adp->caret, adp, line);
2008                    adp->edit_pos = position;
2009                 }
2010           }
2011           break;
2012     case NOCLICK:
2013           ObjMgrDeSelectAll ();
2014           break;
2015     default:
2016           break;
2017   }
2018   adp->clickwhat = NOCLICK;
2019   adp->mouse_mode = MOUSE_RELEASE;
2020   if (!adp->display_panel) {
2021      update_edititem (pnl);
2022      update_savefeatitem (pnl);
2023      update_translateitem (pnl, adp->seqfeat, adp->feat);
2024      update_codonstartbt (pnl, adp->seqfeat, adp->feat);
2025   }
2026   Update ();
2027 }
2028 
2029 #define FINDNEXT 14
2030 #define FINDPREV 16
2031 #define SNLM_DEL   8
2032 #define NLM_RETURN 13
2033 
2034 /*-----------------------*/
gap_insert(EditAlignDataPtr adp)2035 static Boolean gap_insert (EditAlignDataPtr adp)
2036 {
2037   Int4    position;
2038   Int4    oldbufferlength;
2039   Int2    newvisibleLine,
2040           oldvisibleLine;
2041   Boolean insert = FALSE;
2042 
2043   if ( (adp->bufferlength+1) >= adp->minbufferlength + adp->editbuffer) {
2044      ErrPostEx (SEV_ERROR, 0, 0, "Save alignment before");
2045      return FALSE;
2046   }
2047   position = SeqLocStart((SeqLocPtr)adp->caret.region);
2048   insert = AlignDataGapAddProc ('-', position, adp->linebuff, adp->bufferlength, adp->caret.entityID, adp->caret.itemID);
2049   if (insert)
2050   {
2051      oldbufferlength = adp->bufferlength;
2052      adp->bufferlength = CleanBufferProc(adp->linebuff, adp->seqnumber, adp->bufferlength +1);
2053      adp->edit_pos++;
2054      adp->colonne [adp->bufferlength] =adp->colonne [adp->bufferlength -1] +1;
2055      oldvisibleLine =1 +MIN ((Int2) ((oldbufferlength-1) / adp->visibleWidth), (Int2) ((adp->pnlLine -3)/ (adp->seqnumber +1 +2)));
2056      newvisibleLine =1 +MIN ((Int2) ((adp->bufferlength-1) / adp->visibleWidth), (Int2) ((adp->pnlLine -3)/ (adp->seqnumber +1 +2)));
2057      if ( newvisibleLine < 1)
2058      newvisibleLine = 1;
2059      if (newvisibleLine != oldvisibleLine)
2060      {
2061         adp->visibleLength =adp->visibleWidth * newvisibleLine;
2062      }
2063      if(oldbufferlength<adp->bufferlength && adp->length<adp->minbufferlength)
2064      {
2065         adp->length++;
2066      }
2067      return TRUE;
2068   }
2069   return FALSE;
2070 }
2071 
on_key(SlatE s,Char ch)2072 extern void on_key (SlatE s, Char ch)
2073 {
2074   PaneL            pnl;
2075   EditAlignDataPtr adp;
2076   SeqAlignPtr      salp;
2077   RecT             rp;
2078   SeqLocPtr        slp;
2079   SelStructPtr     ssp;
2080   Int4             caretstart;
2081   Int4             new_caretstart;
2082   Int4             k;
2083   Int4             line, oldline,
2084                    column, oldcolumn;
2085   Int4             j;
2086   Boolean          is_caretvisible;
2087   Boolean          minusstrand;
2088   CharPtr          str;
2089   Int4             width;
2090 
2091   if ( (int) ch == 0 ) return;
2092 
2093   pnl = (PaneL) s;
2094   Select (pnl);
2095   if ( (adp = GetAlignDataPanel (pnl)) == NULL ) return;
2096   if ( adp->seqnumber == 0 ) return;
2097   get_client_rect (pnl, &rp);
2098   if ( adp->caret.regiontype == 0 || adp->caret.region == NULL ) {
2099            return;
2100   }
2101   slp = (SeqLocPtr) adp->caret.region;
2102   caretstart = SeqLocStart(slp);
2103   if (caretstart < 0) {
2104            ErrPostEx (SEV_ERROR, 0, 0, "CARET position negative");
2105            return;
2106   }
2107   is_caretvisible = (Boolean)(caretstart >= adp->hoffset
2108                     && caretstart <= adp->hoffset + adp->visibleLength);
2109   if (!is_caretvisible)
2110   {
2111      adp->voffset=(Int2)(caretstart /(adp->visibleWidth));
2112      ResetClip ();
2113      SeqEdSetValueScrollBar (pnl, (Int2) adp->voffset);
2114      data_collect_arrange (adp, TRUE);
2115      Select (pnl);
2116      inval_panel (pnl, -1, -1);
2117      Update ();
2118   }
2119   width = adp->visibleWidth;
2120   if (adp->columnpcell > 0)
2121      width += (Int2) adp->visibleWidth / (Int2) adp->columnpcell;
2122   salp = (SeqAlignPtr) adp->sap_align->data;
2123   if (!ctrlKey && adp->edit_mode == SEQ_EDIT )
2124   {
2125      if ( (str = char_to_insert (&ch, 1, adp->mol_type)) != NULL)
2126      {
2127         if (adp->input_format == OBJ_BIOSEQ)
2128         {
2129            ssp = ObjMgrGetSelected ();
2130            if ( checkssp_for_editor(ssp) && ssp->itemtype == OBJ_BIOSEQ)
2131            {
2132               do_cut (pnl, adp, ssp, FALSE);
2133            }
2134            else ssp = NULL;
2135            if (insertchar_atcaret (str, adp))
2136            {
2137               adp->dirty = TRUE;
2138               ObjMgrSetDirtyFlag (adp->caret.entityID, TRUE);
2139 
2140               ObjMgrSendMsg (OM_MSG_UPDATE, adp->caret.entityID, adp->caret.itemID, adp->caret.itemtype);
2141 
2142               if (adp->edit_item.entityID == 0)
2143               {
2144                  adp->edit_item.entityID = adp->caret.entityID;
2145                  adp->edit_item.itemID = adp->caret.itemID;
2146                  adp->edit_item.itemtype = adp->caret.itemtype;
2147               }
2148               else if (adp->edit_item.entityID != adp->caret.entityID && adp->edit_item.itemID != adp->caret.itemID) {
2149                  ErrPostEx (SEV_ERROR, 0, 0, "Warning in SetWindowTimer");
2150                  adp->edit_item.entityID = 0;
2151                  adp->edit_item.itemID = 0;
2152                  adp->edit_item.itemtype = 0;
2153               }
2154               if (! typing_timerInUse)
2155               {
2156                  typing_timerInUse = TRUE;
2157                  timerCount = 0;
2158               }
2159            }
2160            MemFree (str);
2161         }
2162         else if (adp->input_format == OBJ_SEQALIGN)
2163         {
2164            Beep ();
2165         }
2166         return;
2167      }
2168   }
2169   if (!ctrlKey &&  adp->edit_mode == ALIGN_EDIT )
2170   {
2171      if (ch=='-') {
2172         if (adp->length < adp->minbufferlength) {
2173            if (gap_insert (adp)) {
2174               setposition_tossp (&adp->caret, caretstart+1, caretstart+1);
2175               adp->dirty = TRUE;
2176               inval_panel (pnl, -1, -1);
2177            }
2178         }
2179         return;
2180      }
2181   }
2182 
2183   switch ((int) TO_UPPER(ch))
2184   {
2185      case SNLM_DEL:
2186      case NLM_DEL:
2187           if ( adp->edit_mode == SEQ_EDIT )
2188           {
2189                k = checkOMss_for_itemtype (OBJ_BIOSEQ);
2190                if ( k > 0 ) {
2191                   ssp = getOMselect_for_itemtype (OBJ_BIOSEQ);
2192                }
2193                else {
2194                   ssp = (SelStructPtr) MemNew (sizeof (SelStruct));
2195                   ssp->entityID = adp->caret.entityID;
2196                   ssp->itemID = adp->caret.itemID;
2197                   ssp->itemtype = adp->caret.itemtype;
2198                   locate_region (ssp, caretstart - 1, caretstart - 1, SeqLocId(slp), Seq_strand_plus, FALSE);
2199                   ObjMgrSelect (ssp->entityID, ssp->itemID, ssp->itemtype,
2200 ssp->regiontype, ssp->region);
2201                }
2202                if ( ssp != NULL ) {
2203                   if (adp->input_format == OBJ_BIOSEQ)
2204                   {
2205                      if (do_cut (pnl, adp, ssp, FALSE))
2206                      {
2207                         if (adp->edit_item.entityID == 0)
2208                         {
2209                            adp->edit_item.entityID = adp->caret.entityID;
2210                            adp->edit_item.itemID = adp->caret.itemID;
2211                            adp->edit_item.itemtype = adp->caret.itemtype;
2212                         }
2213                         else if (adp->edit_item.entityID != adp->caret.entityID && adp->edit_item.itemID != adp->caret.itemID) {
2214                            ErrPostEx (SEV_ERROR, 0, 0, "Warning in SetWindowTimer");
2215                            adp->edit_item.entityID = 0;
2216                            adp->edit_item.itemID = 0;
2217                            adp->edit_item.itemtype = 0;
2218                         }
2219                         if (! deleting_timerInUse) {
2220                            deleting_timerInUse = TRUE;
2221                            timerCount = 0;
2222                         }
2223                      }
2224                   }
2225                   else if (adp->input_format == OBJ_SEQALIGN)
2226                   {
2227                      Beep ();
2228                   }
2229                }
2230           }
2231           break;
2232 
2233      case NLM_LEFT:
2234           if (ctrlKey) {
2235              adp->cur_pat = ShowPrecPattern(adp->match_pat, adp->cur_pat, adp->edit_pos);
2236           }
2237           else if ( SeqLocStart(slp) > 0 )
2238           {
2239                minusstrand=(Boolean)(SeqLocStrand((SeqLocPtr)adp->caret.region) == Seq_strand_minus);
2240                if (minusstrand)
2241                   new_caretstart = caretstart+1;
2242                else
2243                   new_caretstart = caretstart-1;
2244                SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID,  adp->caret.itemtype, caretstart, &oldline, &oldcolumn, adp->hoffset, adp);
2245                SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID, adp->caret.itemtype, new_caretstart, &line, &column, adp->hoffset, adp);
2246                setposition_tossp (&adp->caret, new_caretstart, new_caretstart);
2247                if ( oldline>=0 && ( abs(oldcolumn - column) >2 || column <0))
2248                    inval_rect((Int2)(rp.left+adp->margin.left+(oldcolumn-2)*adp->charw),
2249                        (Int2)(rp.top + adp->lineheight * oldline),
2250                        (Int2)(rp.left+ adp->margin.left + (oldcolumn+2)*adp->charw),
2251                        (Int2)(rp.top + adp->lineheight * (oldline+1)));
2252                if ( line>=0 && column>=0 ) {
2253                    inval_rect((Int2)(rp.left +adp->margin.left +(column-2)*adp->charw),
2254                        (Int2)(rp.top + adp->lineheight * line),
2255                        (Int2)(rp.left + adp->margin.left + (column+2)*adp->charw),
2256                        (Int2)(rp.top + adp->lineheight * (line+1)));
2257                }
2258                caretstart = SeqLocStart(slp);
2259                if ( ! shftKey ) {
2260                    slp = (SeqLocPtr) adp->caret.region;
2261                    if (!adp->display_panel) {
2262                       to_update_prompt (pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
2263                    }
2264                    adp->caret_orig = caretstart;
2265                    if (minusstrand)
2266                       adp->edit_pos--;
2267                    else
2268                       adp->edit_pos++;
2269                    ObjMgrDeSelectAll ();
2270                }
2271                else {
2272                    dragcaret_selectrgn (pnl, caretstart, get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list), &(adp->caret), adp, line);
2273                    adp->edit_pos --;
2274                }
2275           }
2276           break;
2277 
2278      case NLM_RIGHT:
2279           if (ctrlKey) {
2280              adp->cur_pat = ShowNextPattern(adp->match_pat, adp->cur_pat, adp->edit_pos);
2281           }
2282           else if ( SeqLocStart(slp) < adp->length )
2283           {
2284                minusstrand=(Boolean)(SeqLocStrand((SeqLocPtr)adp->caret.region) == Seq_strand_minus);
2285                if (minusstrand)
2286                   new_caretstart = caretstart-1;
2287                else
2288                   new_caretstart = caretstart+1;
2289                SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID,  adp->caret.itemtype, caretstart, &oldline, &oldcolumn, adp->hoffset, adp);
2290                SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID, adp->caret.itemtype, new_caretstart, &line, &column, adp->hoffset, adp);
2291                setposition_tossp (&adp->caret, new_caretstart, new_caretstart);
2292                if ( oldline>=0 && ( abs(oldcolumn - column) >2 || column <0))
2293                {
2294                   inval_rect ((Int2) (rp.left +adp->margin.left +(oldcolumn-2) *adp->charw), (Int2)(rp.top + adp->lineheight * oldline), (Int2)(rp.left+ adp->margin.left + (oldcolumn+2)*adp->charw), (Int2)(rp.top + adp->lineheight * (oldline+1)));
2295                }
2296                if ( line>=0 && column>=0 ) {
2297                   inval_rect ((Int2) (rp.left +adp->margin.left +(column-3) *adp->charw),  (Int2)(rp.top + adp->lineheight * line), (Int2)(rp.left + adp->margin.left + (column+2)*adp->charw), (Int2)(rp.top + adp->lineheight * (line+1)));
2298                }
2299                caretstart = SeqLocStart(slp);
2300                if ( ! shftKey ) {
2301                    slp = (SeqLocPtr) adp->caret.region;
2302                    if (!adp->display_panel)
2303                       to_update_prompt(pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
2304                    adp->caret_orig = caretstart;
2305                    if (minusstrand)
2306                       adp->edit_pos += 1;
2307                    else
2308                       adp->edit_pos -= 1;
2309                    ObjMgrDeSelectAll ();
2310                }
2311                else {
2312                    dragcaret_selectrgn (pnl, caretstart, get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list), &(adp->caret), adp, line);
2313                    adp->edit_pos ++;
2314                }
2315           }
2316           break;
2317 
2318      case NLM_UP:
2319           SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID,
2320                        adp->caret.itemtype, caretstart, &line, &column,
2321                        adp->hoffset, adp);
2322           adp->caret_line  = line;
2323           j = nextlineup (adp->caret_line, adp->itemtype, adp->itemsubtype);
2324           if ( j < 0 )
2325           {
2326              Int4      pos;
2327              if (adp->voffset != 0 && adp->hoffset != 0)
2328              {
2329                 ResetClip ();
2330                 adp->voffset = moveup_scrollbar (pnl, adp->voffset, 1);
2331                 Update ();
2332                 if (is_samess_ses (&(adp->caret), (SelEdStructPtr) adp->firstssp->region) )
2333                 {
2334                    pos = SeqLocStart(slp) - adp->visibleWidth;
2335                    if (pos < 0) pos = 0;
2336                    adp->caret_line = 0;
2337                    if ( ! shftKey ) {
2338                       click_caret (&rp, pos, &(adp->caret), &(adp->caret), adp, adp->caret_line);
2339                       if (!adp->display_panel)
2340                          to_update_prompt (pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
2341                       ObjMgrDeSelectAll ();
2342                    }
2343                    else {
2344                       dragcaret_selectrgn (pnl, pos, get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list), &(adp->caret), adp, adp->caret_line);
2345                       setposition_tossp (&(adp->caret), pos, pos);
2346                       adp->edit_pos = pos;
2347                    }
2348                 }
2349              }
2350           }
2351           else if ( j != adp->caret_line )
2352           {
2353                SeqIdPtr sip;
2354                Uint2 eid, it;
2355                Uint4 iid;
2356                eid = adp->caret.entityID;
2357                iid = adp->caret.itemID;
2358                it = adp->caret.itemtype;
2359                SeqPosToLineColumn (iid, eid, it, caretstart, &oldline,
2360                                    &oldcolumn, adp->hoffset, adp);
2361                if (adp->alignline[adp->caret_line] != adp->alignline[j])
2362                {
2363                    line=abs(adp->alignline[adp->caret_line] -adp->alignline[j]);
2364                    caretstart = caretstart -(line *adp->visibleWidth);
2365                    if (caretstart < 0) caretstart = 0;
2366                    setposition_tossp (&(adp->caret), caretstart, caretstart);
2367                }
2368                else
2369                    caretstart = SeqLocStart(slp);
2370                if (adp->seqEntity_id[adp->caret_line] != adp->seqEntity_id[j]
2371                 || adp->item_id[adp->caret_line] != adp->item_id[j])
2372                {
2373                    eid = adp->seqEntity_id[j];
2374                    iid = adp->item_id[j];
2375                    it = adp->itemtype[j];
2376                    adp->caret.entityID = eid;
2377                    adp->caret.itemID = iid;
2378                    adp->caret.itemtype = it;
2379                    sip=(SeqIdPtr)SeqIdFromAlignNode(adp->anp_list,eid, iid, it);
2380                    replace_region (&(adp->caret), eid, iid, it, caretstart, caretstart, sip, Seq_strand_plus, FALSE);
2381                }
2382                adp->caret_line = j;
2383                SeqPosToLineColumn (iid, eid, it, caretstart, &line, &column,
2384                        adp->hoffset, adp);
2385                inval_rect((Int2)(rp.left+adp->margin.left+(column-2)* adp->charw), (Int2)(rp.top + adp->lineheight * oldline), (Int2)(rp.left+ adp->margin.left + (column+2)*adp->charw), (Int2)(rp.top + adp->lineheight * (oldline+1)));
2386                inval_rect((Int2)(rp.left+adp->margin.left+(column-2)* adp->charw), (Int2)(rp.top + adp->lineheight * line), (Int2)(rp.left + adp->margin.left + (column+2)*adp->charw), (Int2)(rp.top + adp->lineheight * (line+1)));
2387                if ( ! shftKey )
2388                {
2389                    slp = (SeqLocPtr) adp->caret.region;
2390                    if (!adp->display_panel)
2391                       to_update_prompt (pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
2392                    adp->caret_orig = caretstart;
2393                    adp->edit_pos = caretstart;
2394                    ObjMgrDeSelectAll ();
2395                }
2396                else {
2397                    dragcaret_selectrgn (pnl, caretstart, get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list), &(adp->caret), adp, line);
2398                    adp->edit_pos -= adp->visibleWidth;
2399                }
2400           }
2401           break;
2402 
2403      case NLM_DOWN:
2404           SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID,
2405                        adp->caret.itemtype, caretstart, &line, &column,
2406                        adp->hoffset, adp);
2407           adp->caret_line  = line;
2408           j = nextlinedown (adp->caret_line, adp->pnlLine, adp->itemtype, adp->itemsubtype);
2409           if ( j < 0 )
2410           {
2411              Int4      pos;
2412              if (adp->voffset < adp->nlines-1)
2413              {
2414                 ResetClip ();
2415                 adp->voffset = movedown_scrollbar (pnl, adp->voffset, (Int2)1);
2416                 Update ();
2417                 if (is_samess_ses (&(adp->caret), adp->lastses) )
2418                 {
2419                    pos = SeqLocStart(slp) + adp->visibleWidth;
2420                    if (pos > adp->length) pos = adp->length;
2421                    adp->caret_line = adp->pnlLine -1;
2422                    if ( ! shftKey ) {
2423                       click_caret (&rp, pos, &(adp->caret), &(adp->caret), adp, adp->caret_line);
2424                       if (!adp->display_panel)
2425                          to_update_prompt (pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
2426                       ObjMgrDeSelectAll ();
2427                    }
2428                    else {
2429                       dragcaret_selectrgn (pnl, pos, get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list), &(adp->caret), adp, adp->caret_line);
2430                       setposition_tossp (&(adp->caret), pos, pos);
2431                       adp->edit_pos = pos;
2432                    }
2433                 }
2434              }
2435           }
2436           else if (j != adp->caret_line )
2437           {
2438                SeqIdPtr sip;
2439                Uint2 eid, it;
2440                Uint4 iid;
2441                eid = adp->caret.entityID;
2442                iid = adp->caret.itemID;
2443                it = adp->caret.itemtype;
2444                SeqPosToLineColumn (adp->caret.itemID, adp->caret.entityID,
2445                        adp->caret.itemtype, caretstart, &oldline,
2446                        &oldcolumn, adp->hoffset, adp);
2447                if (adp->alignline[adp->caret_line] != adp->alignline[j])
2448                {
2449                    line=abs(adp->alignline[adp->caret_line] -adp->alignline[j]);
2450                    caretstart = caretstart + (line * adp->visibleWidth);
2451                    if (caretstart > adp->length)
2452                       caretstart = adp->length;
2453                    setposition_tossp (&(adp->caret), caretstart, caretstart);
2454                }
2455                else
2456                    caretstart = SeqLocStart(slp);
2457                if (adp->seqEntity_id[adp->caret_line] != adp->seqEntity_id[j]
2458                 || adp->item_id[adp->caret_line] != adp->item_id[j])
2459                {
2460                    eid = adp->seqEntity_id[j];
2461                    iid = adp->item_id[j];
2462                    it = adp->itemtype[j];
2463                    adp->caret.entityID = eid;
2464                    adp->caret.itemID = iid;
2465                    adp->caret.itemtype = it;
2466                    sip=(SeqIdPtr)SeqIdFromAlignNode(adp->anp_list,eid, iid, it);
2467                    replace_region (&(adp->caret), eid, iid, it, caretstart, caretstart, sip, Seq_strand_plus, FALSE);
2468                }
2469                adp->caret_line = j;
2470 
2471                SeqPosToLineColumn (iid, eid, it, caretstart, &line, &column,
2472                        adp->hoffset, adp);
2473                inval_rect ((Int2) (rp.left+adp->margin.left +(column-2) * adp->charw), (Int2)(rp.top + adp->lineheight * oldline), (Int2)(rp.left+ adp->margin.left + (column+2)*adp->charw), (Int2)(rp.top + adp->lineheight * (oldline+1)));
2474                inval_rect((Int2)(rp.left+adp->margin.left+(column-2) * adp->charw), (Int2)(rp.top + adp->lineheight * line), (Int2)(rp.left + adp->margin.left + (column+2)*adp->charw), (Int2)(rp.top + adp->lineheight * (line+1)));
2475                if ( ! shftKey ) {
2476                    slp = (SeqLocPtr) adp->caret.region;
2477                    if (!adp->display_panel)
2478                       to_update_prompt (pnl, &(adp->caret), (SeqAlignPtr) adp->sap_align->data, adp->sqloc_list, FALSE, adp->printid);
2479                    adp->caret_orig = caretstart;
2480                    adp->edit_pos = caretstart;
2481                    ObjMgrDeSelectAll ();
2482                }
2483                else {
2484                    dragcaret_selectrgn(pnl, caretstart, get_closest_selection(&(adp->caret), salp, NULL, adp->sqloc_list), &(adp->caret),  adp, line);
2485                    adp->edit_pos += adp->visibleWidth;
2486                }
2487           }
2488           break;
2489 
2490      case FINDNEXT:
2491           adp->cur_pat = ShowNextPattern(adp->match_pat, adp->cur_pat, adp->edit_pos);
2492           break;
2493 
2494      case FINDPREV:
2495           adp->cur_pat = ShowPrecPattern(adp->match_pat, adp->cur_pat, adp->edit_pos);
2496           break;
2497 
2498      case NLM_RETURN:
2499 {
2500   WindoW w;
2501   SeqEditViewFormPtr wdp;
2502 
2503           w = getwindow_frompanel (pnl);
2504           wdp = (SeqEditViewFormPtr) GetObjectExtra (w);
2505           GoToFunc (wdp);
2506 }
2507           break;
2508 
2509      case NLM_ESC:
2510           break;
2511 
2512      default:
2513           Beep ();
2514           break;
2515   }
2516   if (!adp->display_panel)
2517      update_edititem (pnl);
2518   Update ();
2519 }
2520 
2521 
2522 const char *nucleotide_alphabet = "ABCDGHKMRSTUVWYabcdghkmrstuvwy";
2523 const char *protein_alphabet = "ABCDEFGHIKLMPQRSTUVWXYZabcdefghiklmpqrstuvwxyz";
2524 
2525 typedef struct alnsettingsdlg {
2526   DIALOG_MESSAGE_BLOCK
2527   TexT missing;
2528   TexT match;
2529   TexT beginning_gap;
2530   TexT middle_gap;
2531   TexT end_gap;
2532 
2533   PopuP sequence_type;
2534 } AlnSettingsDlgData, PNTR AlnSettingsDlgPtr;
2535 
AlnSettingsDlgToData(DialoG d)2536 static Pointer AlnSettingsDlgToData (DialoG d)
2537 {
2538   AlnSettingsDlgPtr dlg;
2539   TSequenceInfoPtr  sequence_info;
2540 
2541   dlg = (AlnSettingsDlgPtr) GetObjectExtra (d);
2542   if (dlg == NULL) return NULL;
2543 
2544   sequence_info = SequenceInfoNew ();
2545   if (sequence_info == NULL) return NULL;
2546 
2547   sequence_info->missing = MemFree (sequence_info->missing);
2548   sequence_info->missing = SaveStringFromText (dlg->missing);
2549 
2550   sequence_info->beginning_gap = MemFree (sequence_info->beginning_gap);
2551   sequence_info->beginning_gap = SaveStringFromText (dlg->beginning_gap);
2552 
2553   sequence_info->middle_gap = MemFree (sequence_info->middle_gap);
2554   sequence_info->middle_gap = SaveStringFromText (dlg->middle_gap);
2555 
2556   sequence_info->end_gap = MemFree (sequence_info->end_gap);
2557   sequence_info->end_gap = SaveStringFromText (dlg->end_gap);
2558 
2559   sequence_info->match = MemFree (sequence_info->match);
2560   sequence_info->match = SaveStringFromText (dlg->match);
2561 
2562   if (dlg->sequence_type != NULL)
2563   {
2564     if (GetValue (dlg->sequence_type) == 1) {
2565       sequence_info->alphabet = nucleotide_alphabet;
2566     } else {
2567       sequence_info->alphabet = protein_alphabet;
2568     }
2569   }
2570   else
2571   {
2572     sequence_info->alphabet = nucleotide_alphabet;
2573   }
2574 
2575   return sequence_info;
2576 }
2577 
2578 
DataToAlnSettingsDlg(DialoG d,Pointer data)2579 static void DataToAlnSettingsDlg (DialoG d, Pointer data)
2580 {
2581   AlnSettingsDlgPtr dlg;
2582   TSequenceInfoPtr  sequence_info;
2583 
2584   dlg = (AlnSettingsDlgPtr) GetObjectExtra (d);
2585   if (dlg == NULL) return;
2586 
2587   sequence_info = (TSequenceInfoPtr) data;
2588 
2589   if (sequence_info == NULL)
2590   {
2591     SetTitle (dlg->missing, "?Nn");
2592     SetTitle (dlg->beginning_gap, "-.Nn?");
2593     SetTitle (dlg->middle_gap, "-.");
2594     SetTitle (dlg->end_gap, "-.Nn?");
2595     SetTitle (dlg->match, ":");
2596     if (dlg->sequence_type != NULL)
2597     {
2598       SetValue (dlg->sequence_type, 1);
2599     }
2600   }
2601   else
2602   {
2603     SetTitle (dlg->missing, sequence_info->missing);
2604     SetTitle (dlg->beginning_gap, sequence_info->beginning_gap);
2605     SetTitle (dlg->middle_gap, sequence_info->middle_gap);
2606     SetTitle (dlg->end_gap, sequence_info->end_gap);
2607     SetTitle (dlg->match, sequence_info->match);
2608 
2609     if (dlg->sequence_type != NULL)
2610     {
2611       if (StringCmp (sequence_info->alphabet, protein_alphabet) == 0)
2612       {
2613         SetValue (dlg->sequence_type, 2);
2614       }
2615       else
2616       {
2617         SetValue (dlg->sequence_type, 1);
2618       }
2619     }
2620   }
2621 }
2622 
2623 
TestAlnSettingsDlg(DialoG d)2624 static ValNodePtr TestAlnSettingsDlg (DialoG d)
2625 {
2626   ValNodePtr        err_list = NULL;
2627   TSequenceInfoPtr  sequence_info;
2628   CharPtr           cp;
2629   CharPtr           fmt = "Character %c cannot appear in both %s and %s.";
2630   CharPtr           err_str;
2631   CharPtr           missing_name = "Ambiguous/Unknown";
2632   CharPtr           middle_gap_name = "Middle Gap";
2633   CharPtr           match_name = "Match";
2634 
2635   sequence_info = DialogToPointer (d);
2636   if (sequence_info == NULL) return NULL;
2637 
2638   /* missing and match cannot appear in middle gap list */
2639   cp = sequence_info->missing;
2640   while (cp != NULL && *cp != 0)
2641   {
2642     if (StringChr (sequence_info->middle_gap, *cp))
2643     {
2644       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt)
2645                                                    + StringLen (missing_name)
2646                                                    + StringLen (middle_gap_name)));
2647       sprintf (err_str, fmt, *cp, missing_name, middle_gap_name);
2648       ValNodeAddPointer (&err_list, 0, err_str);
2649     }
2650     cp++;
2651   }
2652 
2653   cp = sequence_info->match;
2654   while (cp != NULL && *cp != 0)
2655   {
2656     if (StringChr (sequence_info->middle_gap, *cp))
2657     {
2658       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt)
2659                                                    + StringLen (match_name)
2660                                                    + StringLen (middle_gap_name)));
2661       sprintf (err_str, fmt, *cp, match_name, middle_gap_name);
2662       ValNodeAddPointer (&err_list, 0, err_str);
2663     }
2664     cp++;
2665   }
2666 
2667   /* missing and match cannot share characters */
2668   cp = sequence_info->missing;
2669   while (cp != NULL && *cp != 0)
2670   {
2671     if (StringChr (sequence_info->match, *cp))
2672     {
2673       err_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (fmt)
2674                                                    + StringLen (missing_name)
2675                                                    + StringLen (match_name)));
2676       sprintf (err_str, fmt, *cp, missing_name, match_name);
2677       ValNodeAddPointer (&err_list, 0, err_str);
2678     }
2679     cp++;
2680   }
2681 
2682   return err_list;
2683 }
2684 
2685 
2686 static CharPtr aln_settings_help = "\
2687 Beginning Gap: When some of the sequences in an \
2688 alignment are shorter or longer than others, beginning \
2689 gap characters are added to the beginning of the sequence \
2690 to maintain the correct spacing.  These will not appear \
2691 in your sequence file.\n\
2692 Middle Gap: These characters are used to maintain the spacing \
2693 inside an alignment.  These are not nucleotides and will \
2694 not appear as part of your sequence file.\n\
2695 End Gap: When some of the sequences in an alignment are shorter \
2696 or longer than others, end gap characters are added to the end \
2697 of the sequence to maintain the correct spacing.  These will \
2698 not appear in your sequence file.\n\
2699 Ambiguous/Unknown: These characters are used to represent \
2700 indeterminate/ambiguous nucleotides.  These will appear in your \
2701 sequence file as 'n'.\n\
2702 Match: These characters are used to indicate positions where \
2703 sequences are identical to the first sequence.  These will be \
2704 replaced by the actual characters from the first sequence.";
2705 
2706 
AlnSettingsDlg(GrouP h,Boolean allow_sequence_type)2707 NLM_EXTERN DialoG AlnSettingsDlg (GrouP h, Boolean allow_sequence_type)
2708 {
2709   AlnSettingsDlgPtr dlg;
2710   GrouP             p, g, p_msg;
2711 
2712   dlg = (AlnSettingsDlgPtr) MemNew (sizeof (AlnSettingsDlgData));
2713   p = HiddenGroup (h, -1, 0, NULL);
2714   SetObjectExtra (p, dlg, StdCleanupExtraProc);
2715   SetGroupSpacing (p, 10, 10);
2716 
2717   dlg->dialog = (DialoG) p;
2718   dlg->todialog = DataToAlnSettingsDlg;
2719   dlg->fromdialog = AlnSettingsDlgToData;
2720   dlg->testdialog = TestAlnSettingsDlg;
2721 
2722   g = HiddenGroup (p, 2, 0, NULL);
2723   StaticPrompt (g, "Ambiguous/Unknown", 0, dialogTextHeight, programFont, 'c');
2724   dlg->missing = DialogText (g, "?Nn", 5, NULL);
2725   StaticPrompt (g, "Match", 0, dialogTextHeight, programFont, 'c');
2726   dlg->match = DialogText (g, ".", 5, NULL);
2727   StaticPrompt (g, "Beginning Gap", 0, dialogTextHeight, programFont, 'c');
2728   dlg->beginning_gap = DialogText (g, "-.?nN", 5, NULL);
2729   StaticPrompt (g, "Middle Gap", 0, dialogTextHeight, programFont, 'c');
2730   dlg->middle_gap = DialogText (g, "-", 5, NULL);
2731   StaticPrompt (g, "End Gap", 0, dialogTextHeight, programFont, 'c');
2732   dlg->end_gap = DialogText (g, "-.?nN", 5, NULL);
2733   if (allow_sequence_type) {
2734     StaticPrompt (g, "Sequence Type", 0, dialogTextHeight, programFont, 'c');
2735     dlg->sequence_type = PopupList (g, TRUE, NULL);
2736     PopupItem (dlg->sequence_type, "Nucleotide");
2737     PopupItem (dlg->sequence_type, "Protein");
2738     SetValue (dlg->sequence_type, 1);
2739   }
2740 
2741   p_msg = MultiLinePrompt (p, aln_settings_help, 750, systemFont);
2742 
2743   AlignObjects (ALIGN_CENTER, (HANDLE) g, (HANDLE) p_msg, NULL);
2744 
2745   return (DialoG) p;
2746 }
2747 
2748 
2749 typedef struct alignmentoptionsform
2750 {
2751   Boolean accepted;
2752   Boolean done;
2753 } AlignmentOptionsFormData, PNTR AlignmentOptionsFormPtr;
2754 
AcceptAlignmentOptions(ButtoN b)2755 static void AcceptAlignmentOptions (ButtoN b)
2756 {
2757   AlignmentOptionsFormPtr aofp;
2758 
2759   aofp = (AlignmentOptionsFormPtr) GetObjectExtra (b);
2760   if (aofp == NULL) return;
2761   aofp->accepted = TRUE;
2762   aofp->done = TRUE;
2763 }
2764 
CancelAlignmentOptions(ButtoN b)2765 static void CancelAlignmentOptions (ButtoN b)
2766 {
2767   AlignmentOptionsFormPtr aofp;
2768 
2769   aofp = (AlignmentOptionsFormPtr) GetObjectExtra (b);
2770   if (aofp == NULL) return;
2771   aofp->accepted = FALSE;
2772   aofp->done = TRUE;
2773 }
2774 
2775 
GetAlignmentOptions(Uint1Ptr moltype,TSequenceInfoPtr sequence_info)2776 NLM_EXTERN TSequenceInfoPtr GetAlignmentOptions (Uint1Ptr moltype, TSequenceInfoPtr sequence_info)
2777 {
2778   ButtoN                   b;
2779   GrouP                    c, h;
2780   WindoW                   w;
2781   AlignmentOptionsFormData aofd;
2782   DialoG                   d;
2783   ValNodePtr               err_list;
2784 
2785   aofd.accepted = FALSE;
2786   aofd.done = FALSE;
2787   w = ModalWindow (-50, -33, -10, -10, NULL);
2788 
2789   h = HiddenGroup (w, -1, 0, NULL);
2790   SetGroupSpacing (h, 10, 10);
2791 
2792   d = AlnSettingsDlg (h, moltype == NULL ? FALSE : TRUE);
2793   PointerToDialog (d, sequence_info);
2794 
2795   c = HiddenGroup (h, 4, 0, NULL);
2796   b = DefaultButton (c, "Accept", AcceptAlignmentOptions);
2797   SetObjectExtra (b, &aofd, NULL);
2798   b = PushButton (c, "Cancel", CancelAlignmentOptions);
2799   SetObjectExtra (b, &aofd, NULL);
2800 
2801   AlignObjects (ALIGN_CENTER, (HANDLE) d, (HANDLE) c, NULL);
2802   RealizeWindow (w);
2803   Show (w);
2804   Update ();
2805 
2806   while (!aofd.done) {
2807     while (!aofd.done)
2808     {
2809       ProcessExternalEvent ();
2810       Update ();
2811     }
2812     ProcessAnEvent ();
2813     if (!aofd.accepted)
2814     {
2815       Remove (w);
2816   	  return NULL;
2817     }
2818 
2819     err_list = TestDialog (d);
2820     if (err_list != NULL) {
2821       Message (MSG_ERROR, err_list->data.ptrvalue);
2822       err_list = ValNodeFreeData (err_list);
2823       aofd.done = FALSE;
2824       aofd.accepted = FALSE;
2825     }
2826   }
2827   sequence_info = DialogToPointer (d);
2828   if (sequence_info == NULL) return NULL;
2829   if (StringCmp (sequence_info->alphabet, protein_alphabet) == 0) {
2830     if (moltype != NULL) {
2831       *moltype = Seq_mol_aa;
2832     }
2833   } else {
2834     if (moltype != NULL) {
2835       *moltype = Seq_mol_na;
2836     }
2837   }
2838 
2839   Remove (w);
2840   return sequence_info;
2841 }
2842 
2843 
RemoveSequenceFromAlignmentFile(TAlignmentFilePtr afp,CharPtr str)2844 static void RemoveSequenceFromAlignmentFile (TAlignmentFilePtr afp, CharPtr str)
2845 {
2846   int pos, k;
2847 
2848   if (afp == NULL) {
2849     return;
2850   }
2851   for (pos = 0; pos < afp->num_sequences; pos++) {
2852     if (StringCmp (str, afp->ids[pos]) == 0) {
2853       free (afp->ids[pos]);
2854       for (k = pos + 1; k < afp->num_sequences; k++) {
2855         afp->ids[k - 1] = afp->ids[k];
2856       }
2857       free (afp->sequences[pos]);
2858       for (k = pos + 1; k < afp->num_sequences; k++) {
2859         afp->sequences[k - 1] = afp->sequences[k];
2860       }
2861       afp->num_sequences--;
2862       if (pos < afp->num_organisms) {
2863         free (afp->organisms[pos]);
2864         for (k = pos + 1; k < afp->num_organisms; k++) {
2865           afp->organisms[k - 1] = afp->organisms[k];
2866         }
2867         afp->num_organisms--;
2868       }
2869       if (pos < afp->num_deflines) {
2870         free (afp->deflines[pos]);
2871         for (k = pos + 1; k < afp->num_deflines; k++) {
2872           afp->deflines[k - 1] = afp->deflines[k];
2873         }
2874         afp->num_deflines--;
2875       }
2876     }
2877   }
2878 }
2879 
2880 
FixToFarPointer(TAlignmentFilePtr afp,Int4 index)2881 static void FixToFarPointer (TAlignmentFilePtr afp, Int4 index)
2882 {
2883   CharPtr tmp_id_str;
2884 
2885   if (afp == NULL || index < -1 || index >= afp->num_sequences)
2886   {
2887     return;
2888   }
2889   tmp_id_str = (CharPtr) MemNew (sizeof (Char) * (StringLen (afp->ids [index]) + 4));
2890   if (tmp_id_str == NULL)
2891   {
2892     return;
2893   }
2894   sprintf (tmp_id_str, "acc%s", afp->ids [index]);
2895   MemFree (afp->ids [index]);
2896   afp->ids[index] = tmp_id_str;
2897 }
2898 
2899 
RemoveNthSequenceFromAlignment(TAlignmentFilePtr afp,Int4 n)2900 static void RemoveNthSequenceFromAlignment (TAlignmentFilePtr afp, Int4 n)
2901 {
2902   Int4 i;
2903 
2904   if (afp == NULL || n < 0) {
2905     return;
2906   }
2907 
2908   if (afp->deflines != NULL && n < afp->num_deflines) {
2909     afp->deflines[n] = MemFree (afp->deflines[n]);
2910     for (i = n + 1; i < afp->num_deflines; i++) {
2911       afp->deflines[i - 1] = afp->deflines[i];
2912     }
2913     afp->deflines[afp->num_deflines - 1] = NULL;
2914     afp->num_deflines--;
2915   }
2916 
2917   if (afp->organisms != NULL && n < afp->num_organisms) {
2918     afp->organisms[n] = MemFree (afp->organisms[n]);
2919     for (i = n + 1; i < afp->num_organisms; i++) {
2920       afp->organisms[i - 1] = afp->organisms[i];
2921     }
2922     afp->organisms[afp->num_organisms - 1] = NULL;
2923     afp->num_organisms--;
2924   }
2925 
2926   if (afp->sequences != NULL && n < afp->num_sequences) {
2927     afp->sequences[n] = MemFree (afp->sequences[n]);
2928     afp->ids[n] = MemFree (afp->ids[n]);
2929     for (i = n + 1; i < afp->num_sequences; i++) {
2930       afp->sequences[i - 1] = afp->sequences[i];
2931       afp->ids[i - 1] = afp->ids[i];
2932     }
2933     afp->sequences[afp->num_sequences - 1] = NULL;
2934     afp->ids[afp->num_sequences - 1] = NULL;
2935     afp->num_sequences--;
2936   }
2937 }
2938 
2939 
FixAlignmentIdsOkCancel(ButtoN b)2940 static void FixAlignmentIdsOkCancel (ButtoN b)
2941 {
2942   BoolPtr bp;
2943 
2944   bp = (BoolPtr) GetObjectExtra (b);
2945   if (bp != NULL)
2946   {
2947     *bp = TRUE;
2948   }
2949 }
2950 
EnableTextID(GrouP g)2951 static void EnableTextID (GrouP g)
2952 {
2953   TexT id_text;
2954 
2955   id_text = (TexT) GetObjectExtra (g);
2956   if (id_text != NULL)
2957   {
2958     if (GetValue (g) > 5)
2959     {
2960       Enable (id_text);
2961     }
2962     else
2963     {
2964       Disable (id_text);
2965     }
2966   }
2967 }
2968 
2969 
ReplaceAlignmentIDsFromFile(TAlignmentFilePtr afp,Int4 index)2970 static Boolean ReplaceAlignmentIDsFromFile (TAlignmentFilePtr afp, Int4 index)
2971 {
2972   ReadBufferData    rbd;
2973   Char              path [PATH_MAX];
2974   CharPtr           line, cp, first_id, second_id;
2975   Int4              k;
2976   Boolean           found_id;
2977   ValNodePtr        err_list = NULL;
2978   CharPtr           err_msg = NULL;
2979   CharPtr           err_msg_prefix = "Unable to find ";
2980   CharPtr           err_msg_suffix = " from file in alignment";
2981   Int4              err_msg_len = 0;
2982   ValNodePtr        vnp;
2983 
2984   if (afp == NULL || index < -1 || index >= afp->num_sequences)
2985   {
2986     return FALSE;
2987   }
2988 
2989   rbd.fp = NULL;
2990   while (rbd.fp == NULL)
2991   {
2992     if (!GetInputFileName (path, sizeof (path), NULL, NULL))
2993     {
2994       return FALSE;
2995     }
2996     rbd.fp = FileOpen (path, "r");
2997     if (rbd.fp == NULL)
2998     {
2999       Message (MSG_ERROR, "Unable to open %s", path);
3000     }
3001   }
3002 
3003   rbd.current_data = NULL;
3004 
3005   line = AbstractReadFunction (&rbd);
3006   while (line != NULL)
3007   {
3008     cp = line;
3009     while (isspace ((Int4)(*cp)))
3010     {
3011       cp++;
3012     }
3013     if (*cp != 0)
3014     {
3015       first_id = cp;
3016       while (!isspace ((Int4)(*cp)) && *cp != 0)
3017       {
3018         cp++;
3019       }
3020       while (isspace ((Int4)(*cp)))
3021       {
3022         *cp = 0;
3023         cp++;
3024       }
3025       second_id = cp;
3026       TrimSpacesAroundString (second_id);
3027       if (*second_id != 0)
3028       {
3029         found_id = FALSE;
3030         for (k = index; k < afp->num_sequences && ! found_id; k++)
3031         {
3032           if (StringCmp (afp->ids[k], first_id) == 0)
3033           {
3034             found_id = TRUE;
3035             MemFree (afp->ids[k]);
3036             afp->ids[k] = StringSave (second_id);
3037           }
3038           else if (StringCmp (afp->ids[k], second_id) == 0)
3039           {
3040             found_id = TRUE;
3041             MemFree (afp->ids[k]);
3042             afp->ids[k] = StringSave (first_id);
3043           }
3044         }
3045         if (!found_id)
3046         {
3047           ValNodeAddPointer (&err_list, 0, StringSave (first_id));
3048           ValNodeAddPointer (&err_list, 0, StringSave (second_id));
3049           err_msg_len += StringLen (first_id) + StringLen (second_id) + 8;
3050         }
3051       }
3052     }
3053 
3054     line = AbstractReadFunction (&rbd);
3055   }
3056   FileClose (rbd.fp);
3057   if (err_list != NULL)
3058   {
3059     err_msg_len += StringLen (err_msg_prefix) + StringLen (err_msg_suffix) + 6;
3060     err_msg = (CharPtr) MemNew (err_msg_len * sizeof (Char));
3061     if (err_msg != NULL)
3062     {
3063       sprintf (err_msg, "%s", err_msg_prefix);
3064       vnp = err_list;
3065       while (vnp != NULL && vnp->next != NULL)
3066       {
3067         StringCat (err_msg, (CharPtr) vnp->data.ptrvalue);
3068         StringCat (err_msg, " or ");
3069         StringCat (err_msg, (CharPtr) vnp->next->data.ptrvalue);
3070 
3071         if (vnp->next->next != NULL)
3072         {
3073           StringCat (err_msg, ", ");
3074         }
3075         if (vnp->next->next != NULL && vnp->next->next->next != NULL && vnp->next->next->next->next == NULL)
3076         {
3077           StringCat (err_msg, " and ");
3078         }
3079         vnp = vnp->next->next;
3080       }
3081       StringCat (err_msg, err_msg_suffix);
3082       Message (MSG_ERROR, err_msg);
3083       MemFree (err_msg);
3084     }
3085   }
3086   return TRUE;
3087 }
3088 
3089 
FixAlignmentIDs(TAlignmentFilePtr afp,Int4 index,BoolPtr all_far,BoolPtr all_skip,BoolPtr removed)3090 static Boolean FixAlignmentIDs (TAlignmentFilePtr afp, Int4 index, BoolPtr all_far, BoolPtr all_skip, BoolPtr removed)
3091 {
3092   WindoW  w;
3093   GrouP   h, choice_grp, c;
3094   ButtoN  b;
3095   Boolean done = FALSE;
3096   Boolean cancelled = FALSE;
3097   PrompT  p;
3098   CharPtr prompt_str;
3099   CharPtr prompt_str_fmt = "Unable to find sequence %s from alignment in set.";
3100   TexT    id_text;
3101   CharPtr id_str;
3102   Int2    fix_choice;
3103 
3104   if (afp == NULL || index < -1 || index >= afp->num_sequences)
3105   {
3106     return FALSE;
3107   }
3108 
3109   id_str = afp->ids[index];
3110   if (StringHasNoText (id_str))
3111   {
3112     return FALSE;
3113   }
3114 
3115   w = MovableModalWindow (-20, -13, -10, -10, "Source Assistant", NULL);
3116   h = HiddenGroup(w, -1, 0, NULL);
3117   SetGroupSpacing (h, 10, 10);
3118 
3119   prompt_str = (CharPtr) MemNew ((StringLen (prompt_str_fmt) + StringLen (id_str)) * sizeof (Char));
3120   if (prompt_str != NULL)
3121   {
3122     sprintf (prompt_str, prompt_str_fmt, id_str);
3123   }
3124   p = StaticPrompt (h, prompt_str, 0, dialogTextHeight, systemFont, 'c');
3125   choice_grp = HiddenGroup (h, 0, 7, EnableTextID);
3126   RadioButton (choice_grp, "This is a far pointer");
3127   RadioButton (choice_grp, "All unmatched sequences are far pointers");
3128   RadioButton (choice_grp, "Read in a file that maps alignment IDs to sequence IDs");
3129   RadioButton (choice_grp, "Remove this sequence from the alignment");
3130   RadioButton (choice_grp, "Remove all unmatched sequences from the alignment");
3131   RadioButton (choice_grp, "Use this ID for this sequence");
3132   id_text = DialogText (choice_grp, "", 20, NULL);
3133   Disable (id_text);
3134   SetValue (choice_grp, 1);
3135   SetObjectExtra (choice_grp, id_text, NULL);
3136   c = HiddenGroup (h, 2, 0, NULL);
3137   b = PushButton(c, "OK", FixAlignmentIdsOkCancel);
3138   SetObjectExtra (b, &done, NULL);
3139   b = PushButton(c, "Cancel", FixAlignmentIdsOkCancel);
3140   SetObjectExtra (b, &cancelled, NULL);
3141   AlignObjects (ALIGN_CENTER, (HANDLE) p,  (HANDLE) choice_grp, (HANDLE) c, NULL);
3142 
3143   Show(w);
3144   Select (w);
3145   while (!done && !cancelled)
3146   {
3147     while (!done && !cancelled)
3148     {
3149       ProcessExternalEvent ();
3150       Update ();
3151     }
3152     ProcessAnEvent ();
3153     if (!cancelled)
3154     {
3155       fix_choice = GetValue (choice_grp);
3156       switch (fix_choice)
3157       {
3158         case 1:
3159           /* far pointer */
3160           FixToFarPointer (afp, index);
3161           break;
3162         case 2:
3163           /* all far pointers */
3164           if (all_far != NULL)
3165           {
3166             *all_far = TRUE;
3167           }
3168           FixToFarPointer (afp, index);
3169           break;
3170         case 3:
3171           /* read in file with replacements */
3172           if (!ReplaceAlignmentIDsFromFile (afp, index))
3173           {
3174             done = FALSE;
3175           }
3176           break;
3177         case 4:
3178           /* skip */
3179           RemoveNthSequenceFromAlignment (afp, index);
3180           if (removed != NULL) {
3181             *removed = TRUE;
3182           }
3183           break;
3184         case 5:
3185           /* skip all */
3186           RemoveNthSequenceFromAlignment (afp, index);
3187           if (all_skip != NULL)
3188           {
3189             *all_skip = TRUE;
3190           }
3191           if (removed != NULL) {
3192             *removed = TRUE;
3193           }
3194           break;
3195         case 6:
3196           /* use single replacement */
3197           id_str = SaveStringFromText (id_text);
3198           if (StringHasNoText (id_str))
3199           {
3200             MemFree (id_str);
3201             Message (MSG_ERROR, "You did not specify text for the ID!");
3202             done = FALSE;
3203           }
3204           else
3205           {
3206             MemFree (afp->ids [index]);
3207             afp->ids [index] = id_str;
3208           }
3209           break;
3210       }
3211     }
3212   }
3213   Remove (w);
3214   if (cancelled)
3215   {
3216     return FALSE;
3217   }
3218   else
3219   {
3220     return TRUE;
3221   }
3222 }
3223 
3224 
CorrectAlignmentIDs(TAlignmentFilePtr afp,Uint1 moltype)3225 NLM_EXTERN Boolean CorrectAlignmentIDs (TAlignmentFilePtr afp, Uint1 moltype)
3226 {
3227   Int4      index;
3228   CharPtr   seq_data;
3229   BioseqPtr bsp;
3230   Char      prot_str[200];
3231   Boolean   all_far = FALSE;
3232   Boolean   all_skip = FALSE;
3233   Boolean   removed;
3234   SeqEntryPtr nucprot_sep;
3235   BioseqSetPtr nucprot_bssp;
3236 
3237   for (index = 0; index < afp->num_sequences; index++) {
3238     seq_data = AlignmentStringToSequenceString (afp->sequences [index], moltype);
3239     if (! StringHasNoText (seq_data))
3240     {
3241       if (StringNCmp (afp->ids[index], "acc", 3) != 0)
3242       {
3243         bsp = BioseqFromAlignmentID (&(afp->ids[index]));
3244 
3245         if (bsp != NULL && moltype == Seq_mol_aa && !ISA_aa (bsp->mol))
3246         {
3247           /* IDs in alignment are for nucleotide sequences but this is
3248            * protein sequence - if single prot in nuc-prot set, replace
3249            * with protein sequence ID.  Otherwise set to NULL - don't
3250            * want this ID in our alignment */
3251           nucprot_sep = GetBestTopParentForData (bsp->idx.entityID, bsp);
3252           bsp = NULL;
3253           if (nucprot_sep != NULL && IS_Bioseq_set (nucprot_sep) && nucprot_sep->data.ptrvalue != NULL)
3254           {
3255             nucprot_bssp = nucprot_sep->data.ptrvalue;
3256             if (nucprot_bssp->seq_set != NULL
3257                 && nucprot_bssp->seq_set->next != NULL
3258                 && nucprot_bssp->seq_set->next->next == NULL
3259                 && IS_Bioseq (nucprot_bssp->seq_set->next))
3260             {
3261               bsp = (BioseqPtr) nucprot_bssp->seq_set->next->data.ptrvalue;
3262               SeqIdWrite (SeqIdFindBest (bsp->id, 0), prot_str, PRINTID_FASTA_LONG, sizeof (prot_str) - 1);
3263               afp->ids[index] = MemFree (afp->ids[index]);
3264               afp->ids[index] = StringSave (prot_str);
3265             }
3266           }
3267         }
3268 
3269         if (bsp == NULL)
3270         {
3271           if (all_far)
3272           {
3273             FixToFarPointer (afp, index);
3274           }
3275           else if (all_skip)
3276           {
3277             RemoveNthSequenceFromAlignment(afp, index);
3278             index--;
3279           }
3280           else
3281           {
3282             removed = FALSE;
3283             if (!FixAlignmentIDs (afp, index, &all_far, &all_skip, &removed))
3284             {
3285               /* bail - user does not want to fix IDs */
3286               return FALSE;
3287             }
3288             if (removed) {
3289               index--;
3290             }
3291           }
3292         }
3293 
3294       }
3295     }
3296     MemFree (seq_data);
3297   }
3298   return TRUE;
3299 }
3300 
3301 
ReadAlignmentForSeqEntry(SeqEntryPtr sep,Boolean is_nuc,Boolean allow_options,Boolean from_clipboard)3302 NLM_EXTERN SeqAlignPtr ReadAlignmentForSeqEntry (SeqEntryPtr sep, Boolean is_nuc, Boolean allow_options, Boolean from_clipboard)
3303 {
3304   Char              path [PATH_MAX];
3305   FILE              *fp;
3306   SeqAlignPtr       salp=NULL,
3307                     salpnew, salp_return = NULL;
3308   SeqEntryPtr       sepnew=NULL;
3309   Boolean           ok = TRUE,
3310                     dirty = FALSE;
3311   TSequenceInfoPtr  default_info, sequence_info;
3312   ReadBufferData    rbd;
3313   TErrorInfoPtr     error_list;
3314   TAlignmentFilePtr afp;
3315   Uint1             moltype;
3316   ErrSev            sev;
3317   SeqEntryPtr       scope;
3318   CharPtr           str;
3319 
3320   if (sep == NULL) return NULL;
3321 
3322   if (from_clipboard) {
3323     if (!Nlm_ClipboardHasString()) {
3324       Message (MSG_ERROR, "Clipboard is empty!");
3325       return NULL;
3326     }
3327     TmpNam (path);
3328     fp = FileOpen (path, "w");
3329     str = ClipboardToString();
3330     fprintf (fp, "%s", str);
3331     FileClose (fp);
3332     str = MemFree (str);
3333   } else if (! GetInputFileName (path, sizeof (path),"","TEXT")) {
3334     return NULL;
3335   }
3336   fp = FileOpen (path, "r");
3337   if (fp == NULL)
3338   {
3339     Message (MSG_ERROR, "Unable to open %s", path);
3340     if (from_clipboard) {
3341       FileRemove (path);
3342     }
3343     return NULL;
3344   }
3345 
3346   default_info = SequenceInfoNew ();
3347   if (is_nuc) {
3348     default_info->alphabet = nucleotide_alphabet;
3349   } else {
3350     default_info->alphabet = protein_alphabet;
3351   }
3352   default_info->beginning_gap = MemFree (default_info->beginning_gap);
3353   default_info->beginning_gap = StringSave ("-.Nn?");
3354   default_info->middle_gap = MemFree (default_info->middle_gap);
3355   default_info->middle_gap = StringSave ("-.#");
3356   default_info->end_gap = MemFree (default_info->end_gap);
3357   default_info->end_gap = StringSave ("-.Nn?");
3358   default_info->match = MemFree (default_info->match);
3359   default_info->match = StringSave (":");
3360   default_info->missing = MemFree (default_info->missing);
3361   default_info->missing = StringSave ("?Nn");
3362 
3363   if (allow_options) {
3364     sequence_info = GetAlignmentOptions (&moltype, default_info);
3365     SequenceInfoFree (default_info);
3366     if (sequence_info == NULL) return NULL;
3367     default_info = sequence_info;
3368   }
3369 
3370   WatchCursor();
3371   error_list = NULL;
3372 
3373   rbd.fp = fp;
3374   rbd.current_data = NULL;
3375   afp = ReadAlignmentFile ( AbstractReadFunction,
3376                             (Pointer) &rbd,
3377                             AbstractReportError,
3378                             (Pointer) &error_list,
3379                             default_info);
3380   FileClose (fp);
3381   if (from_clipboard) {
3382     FileRemove (path);
3383   }
3384   SequenceInfoFree (default_info);
3385   default_info = NULL;
3386   if (afp != NULL)
3387   {
3388     RemoveSequenceFromAlignmentFile (afp, "Consensus");
3389     SeqEntrySetScope (sep);
3390     if (CorrectAlignmentIDs (afp, moltype))
3391     {
3392       sepnew = MakeSequinDataFromAlignmentEx (afp, moltype, TRUE);
3393     }
3394   }
3395   if (sepnew == NULL) {
3396     ProduceAlignmentNotes (afp, error_list);
3397   }
3398   ErrorInfoFree (error_list);
3399   AlignmentFileFree (afp);
3400   if (sepnew)
3401   {
3402     salpnew = (SeqAlignPtr) FindSeqAlignInSeqEntry (sepnew, OBJ_SEQALIGN);
3403     if (salpnew) {
3404       sev = ErrSetMessageLevel (SEV_FATAL);
3405 
3406       scope = SeqEntrySetScope (NULL);
3407       /* adjust the start positions for the sequences read in from the alignments. */
3408       CalculateAlignmentOffsets (sepnew, sep);
3409       /* ValidateSeqAlignandACCInSeqEntry will readjust the start positions for
3410        * the alignments for far pointer sequences.
3411        */
3412       SeqEntrySetScope (scope);
3413       ok = ValidateSeqAlignandACCInSeqEntry (sepnew, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE);
3414 
3415       ErrSetMessageLevel (sev);
3416 
3417       if (ok) {
3418         AlnMgr2IndexSeqAlignEx(salpnew, FALSE);
3419         ok = CheckAlignmentSequenceLengths (salpnew);
3420       }
3421 
3422       if (ok) {
3423         /* make copy, otherwise it will be removed when we delete sep_new */
3424         salp_return = (SeqAlignPtr) AsnIoMemCopy (salpnew, (AsnReadFunc) SeqAlignAsnRead,
3425                                                    (AsnWriteFunc) SeqAlignAsnWrite);
3426       }
3427     }
3428     /* this statement will free salpnew as part of sepnew */
3429     ObjMgrFree (OBJ_SEQENTRY, (Pointer)sepnew);
3430     sepnew=NULL;
3431   }
3432   ArrowCursor();
3433   Update ();
3434   return salp_return;
3435 }
3436 
3437 
ReportPotentialDupIDs(TAlignmentFilePtr afp,FILE * fp)3438 static void ReportPotentialDupIDs (TAlignmentFilePtr afp, FILE *fp)
3439 {
3440   int     seq_index, k;
3441   int     curr_seg;
3442   int     num_sequences;
3443   Int4Ptr seq_len;
3444   BoolPtr may_be_dup;
3445   Int4    a, b;
3446 
3447   if (afp == NULL || afp->sequences == NULL || afp->num_sequences == 0) {
3448     return;
3449   }
3450 
3451   num_sequences = afp->num_sequences / afp->num_segments;
3452 
3453   may_be_dup = (BoolPtr) MemNew (sizeof (Boolean) * num_sequences);
3454   for (seq_index = 0; seq_index < num_sequences; seq_index++) {
3455     may_be_dup[seq_index] = FALSE;
3456   }
3457 
3458   seq_len = (Int4Ptr) MemNew (sizeof (Int4) * afp->num_sequences);
3459   for (seq_index = 0; seq_index < afp->num_sequences; seq_index++) {
3460     seq_len[seq_index] = StringLen (afp->sequences[seq_index]);
3461   }
3462 
3463   for (curr_seg = 0; curr_seg < afp->num_segments; curr_seg++) {
3464     for (seq_index = 0; seq_index < num_sequences - 1; seq_index++) {
3465       for (k = seq_index + 1; k < num_sequences; k++) {
3466         a = curr_seg * num_sequences + seq_index;
3467         b = curr_seg * num_sequences + k;
3468         if (seq_len[a] != seq_len[b]) {
3469           if (seq_len[a] % seq_len [b] == 0) {
3470             may_be_dup[seq_index] = TRUE;
3471           } else if (seq_len[b] % seq_len[a] == 0) {
3472             may_be_dup[k] = TRUE;
3473           }
3474         }
3475       }
3476     }
3477   }
3478   seq_len = MemFree (seq_len);
3479 
3480   for (seq_index = 0; seq_index < num_sequences; seq_index ++)
3481   {
3482     if (may_be_dup[seq_index]) {
3483       fprintf (fp, "Please check your file - %s may have been used as an ID for multiple sequences.\n", afp->ids[seq_index]);
3484     }
3485   }
3486 
3487   may_be_dup = MemFree (may_be_dup);
3488 }
3489 
3490 
PrintExtraErrorInstructions(FILE * fp,CharPtr message)3491 static void PrintExtraErrorInstructions (FILE *fp, CharPtr message)
3492 {
3493   CharPtr explanation, end;
3494   Char    tmp = '\0';
3495   if (fp == NULL || message == NULL) return;
3496 
3497   if (StringStr (message, "bad characters") == NULL
3498       && StringStr (message, " found at position ") == NULL) {
3499     return;
3500   }
3501 
3502   explanation = StringRChr (message, '(');
3503   if (explanation == NULL) return;
3504   if (StringNCmp (explanation, "(expect only ", 13) == 0) {
3505     end = StringStr (explanation + 13, " here)");
3506     if (end != NULL) {
3507       tmp = *end;
3508       *end = 0;
3509     }
3510     fprintf (fp,
3511              "Try changing the sequence character specifications for %s.\n",
3512              explanation + 13);
3513     if (StringNCmp (explanation + 13, "beginning", 9) == 0) {
3514       fprintf (fp,
3515 "\nWhen some of the sequences in an alignment are shorter or "
3516 "longer than others, beginning gap characters are added to "
3517 "the beginning of the sequence to maintain the correct spacing."
3518 "  These will not appear in your sequence file.\n");
3519     } else if (StringNCmp (explanation + 13, "end", 3) == 0) {
3520       fprintf (fp,
3521 "\nWhen some of the sequences in an alignment are shorter or "
3522 "longer than others, end gap characters are added to "
3523 "the end of the sequence to maintain the correct spacing."
3524 "  These will not appear in your sequence file.\n");
3525     } else {
3526       fprintf (fp,
3527 "\nMiddle gap characters are used to maintain the spacing "
3528 "inside an alignment.  These are not nucleotides and will "
3529 "not appear as part of your sequence file.\n"
3530 "Ambiguous/unknown characters are used to represent indeterminate/ambiguous "
3531 "nucleotides.  These will appear in your sequence file as 'n'.\n"
3532 "Match characters are used to indicate positions where "
3533 "sequences are identical to the first sequence.  These will be "
3534 "replaced by the actual characters from the first sequence.\n");
3535     }
3536     if (end != NULL) {
3537       *end = tmp;
3538     }
3539   } else if (StringCmp (explanation,
3540                         "(can't specify match chars in first sequence).") == 0) {
3541     fprintf (fp, "Try changing the match character specification.\n");
3542     fprintf (fp,
3543 "\nMatch characters are used to indicate positions where "
3544 "sequences are identical to the first sequence.  These will be "
3545 "replaced by the actual characters from the first sequence.\n");
3546   }
3547 }
3548 
3549 
PrintError(FILE * fp,TErrorInfoPtr eip)3550 static void PrintError (FILE *fp, TErrorInfoPtr eip)
3551 {
3552   if (eip == NULL || fp == NULL) return;
3553 
3554   fprintf (fp, "*****\nError category %d\n", eip->category);
3555   if (eip->line_num > -1) {
3556     fprintf (fp, "Line number %d\n", eip->line_num);
3557   }
3558   if (eip->id != NULL) {
3559     fprintf (fp, "Sequence ID %s\n", eip->id);
3560   }
3561   if (eip->message != NULL) {
3562     fprintf (fp, "%s\n", eip->message);
3563     PrintExtraErrorInstructions (fp, eip->message);
3564   }
3565 }
3566 
CountNucleotides(CharPtr sequence)3567 static Int4 CountNucleotides (CharPtr sequence)
3568 {
3569   Int4    num = 0;
3570   CharPtr cp;
3571 
3572   if (sequence == NULL) return 0;
3573   for (cp = sequence; *cp != 0; cp++)
3574   {
3575   	if (*cp != '-')
3576   	{
3577   	  num++;
3578   	}
3579   }
3580   return num;
3581 }
3582 
WalkErrorList(TErrorInfoPtr list,FILE * fp)3583 static void WalkErrorList (TErrorInfoPtr list, FILE *fp)
3584 {
3585   TErrorInfoPtr eip;
3586 
3587   if (list == NULL || fp == NULL) return;
3588 
3589   for (eip = list; eip != NULL; eip = eip->next) {
3590     PrintError (fp, eip);
3591   }
3592 
3593 }
3594 
3595 
PrintAlignmentSummary(TAlignmentFilePtr afp,FILE * fp)3596 static void PrintAlignmentSummary (TAlignmentFilePtr afp, FILE *fp)
3597 {
3598   Int4 index;
3599 
3600   if (fp == NULL) return;
3601 
3602   if (afp == NULL) {
3603     fprintf (fp, "Catastrophic failure during reading\n");
3604   } else {
3605     fprintf (fp, "Found %d sequences\n", afp->num_sequences);
3606     fprintf (fp, "Found %d organisms\n", afp->num_organisms);
3607     if (afp->num_sequences == afp->num_segments * afp->num_organisms)
3608     {
3609       for (index = 0; index < afp->num_sequences; index++)
3610       {
3611         fprintf (fp, "\t%s\t%d nucleotides\t", afp->ids [index],
3612                  CountNucleotides (afp->sequences[index]));
3613         if (index / afp->num_segments < afp->num_organisms) {
3614           fprintf (fp, "%s\n", afp->organisms [index / afp->num_segments]);
3615         } else {
3616           fprintf (fp, "No organism information\n");
3617         }
3618       }
3619     }
3620     else
3621     {
3622       for (index = 0; index < afp->num_sequences; index++)
3623       {
3624         fprintf (fp, "\t%s\t%d nucleotides\t", afp->ids [index],
3625                  CountNucleotides (afp->sequences[index]));
3626         if (index < afp->num_organisms) {
3627           fprintf (fp, "%s\n", afp->organisms [index]);
3628         } else {
3629           fprintf (fp, "No organism information\n");
3630         }
3631       }
3632       while (index < afp->num_organisms) {
3633         fprintf (fp, "Unclaimed organism: %s\n", afp->organisms [index]);
3634         index++;
3635       }
3636     }
3637   }
3638 }
3639 
3640 
3641 NLM_EXTERN void
ProduceAlignmentNotes(TAlignmentFilePtr afp,TErrorInfoPtr error_list)3642 ProduceAlignmentNotes
3643 (TAlignmentFilePtr afp,
3644  TErrorInfoPtr error_list)
3645 {
3646   Char         path [PATH_MAX];
3647   FILE         *fp;
3648   Boolean      ok_to_import = FALSE;
3649 
3650   TmpNam (path);
3651   fp = FileOpen (path, "wb");
3652   if (fp == NULL) return;
3653 
3654 
3655   if (afp != NULL && DoSequenceLengthsMatch (afp)) {
3656     ok_to_import = TRUE;
3657   }
3658 
3659 
3660   if (ok_to_import && error_list != NULL) {
3661     fprintf (fp, "Congratulations, you have successfully created a sequin file;\nhowever, I had trouble reading part of your file.\nPlease check your data carefully before submitting to be sure that all of your sequences\nwere included correctly.\nIf your file is incomplete, or contains incorrect sequences, please use the error report below\nto find the problem.\n");
3662   }
3663   ReportPotentialDupIDs (afp, fp);
3664 
3665   WalkErrorList (error_list, fp);
3666   PrintAlignmentSummary (afp, fp);
3667 
3668   FileClose (fp);
3669   LaunchGeneralTextViewer (path, "Alignment reading summary");
3670   FileRemove (path);
3671 }
3672 
3673