3f93bb2b97119baf71d90dad97a8be00a4372382
braney
  Wed Oct 8 16:07:53 2014 -0700
fix bug in mapBox placement when passing in negative numbers
diff --git src/hg/hgTracks/snakeTrack.c src/hg/hgTracks/snakeTrack.c
index 98abfec..110d2d1 100644
--- src/hg/hgTracks/snakeTrack.c
+++ src/hg/hgTracks/snakeTrack.c
@@ -730,30 +730,55 @@
 };
 
 static int snakePalette[] =
 {
 0x1f77b4, 0xff7f0e, 0x2ca02c, 0xd62728, 0x9467bd, 0x8c564b, 0xe377c2, 0x7f7f7f, 0xbcbd22, 0x17becf
 };
 
 static Color hashColor(char *name)
 {
 bits32 hashVal = hashString(name);
 unsigned int colorInt = snakePalette2[hashVal % (sizeof(snakePalette2)/sizeof(Color))];
 
 return MAKECOLOR_32(((colorInt >> 16) & 0xff),((colorInt >> 8) & 0xff),((colorInt >> 0) & 0xff));
 }
 
+static void boundMapBox(struct hvGfx *hvg, int start, int end, int x, int y, int width, int height,
+                       char *track, char *item, char *statusLine, char *directUrl, boolean withHgsid,
+                       char *extra)
+// make sure start x and end x position are on the screen
+// otherwise the tracking box code gets confused
+{
+if (x > insideWidth)
+    return;
+
+if (x < 0)
+    {
+    width -= -x;
+    x = 0;
+    }
+
+if (x + width > insideWidth)
+    {
+    width -= x + width - insideWidth;
+    }
+
+mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height,
+                       track, item, statusLine, directUrl, withHgsid,
+                       extra);
+}
+
 static void snakeDrawAt(struct track *tg, void *item,
 	struct hvGfx *hvg, int xOff, int y, double scale, 
 	MgFont *font, Color color, enum trackVisibility vis)
 /* Draw a single simple bed item at position. */
 {
 unsigned showSnpWidth = cartOrTdbInt(cart, tg->tdb, 
     SNAKE_SHOW_SNP_WIDTH, SNAKE_DEFAULT_SHOW_SNP_WIDTH);
 struct linkedFeatures  *lf = (struct linkedFeatures *)item;
 
 
 if (tg->visibility == tvFull) 
     calcFullSnake(tg, item);
 else if (tg->visibility == tvPack)
     calcPackSnake(tg, item);
 
@@ -911,31 +936,31 @@
 	
     if (vis == tvFull)
 	safef(buffer, sizeof buffer, "%d-%d",sf->qStart,sf->qEnd);
     else
 	safef(buffer, sizeof buffer, "%s:%d-%d",sf->qName,sf->qStart,sf->qEnd);
     if (sx < insideX)
 	{
 	int olap = insideX - sx;
 	sx = insideX;
 	w -= olap;
 	}
     char qAddress[4096];
     if ((vis == tvFull) || (vis == tvPack) )
 	{
 	safef(qAddress, sizeof qAddress, "qName=%s&qs=%d&qe=%d&qWidth=%d",sf->qName,  qs, qe,  winEnd - winStart);
-	mapBoxHgcOrHgGene(hvg, s, e, sx+1, y, w-2, heightPer, tg->track,
+	boundMapBox(hvg, s, e, sx+1, y, w-2, heightPer, tg->track,
 		    buffer, buffer, NULL, TRUE, qAddress);
 	}
     hvGfxBox(hvg, sx, y, w, heightPer, color);
 
     // now draw the mismatches if we're at high enough resolution 
     if ((isHalSnake && sf->qSequence != NULL) && (winBaseCount < showSnpWidth) && ((vis == tvFull) || (vis == tvPack)))
 	{
 	char *twoBitString = trackDbSetting(tg->tdb, "twoBit");
 	static struct twoBitFile *tbf = NULL;
 	static char *lastTwoBitString = NULL;
 	static struct dnaSeq *seq = NULL;
 	static char *lastQName = NULL;
 
 	// sequence for chain snakes is in 2bit files which we cache
 	if (!isHalSnake)
@@ -1065,96 +1090,96 @@
 	{
 	char buffer[1024];
 #define MG_ORANGE  0xff0082E6
 	int color = MG_GRAY;
 
 	if (lastQEnd != qs)
 	    color = MG_ORANGE;
 
 	// draw the vertical orange bars if there is an insert in the other sequence
 	if ((winBaseCount < showSnpWidth) )
 	    {
 	    if ((sf->orientation == 1) && (qs != lastQEnd) && (lastE == s))
 		{
 		hvGfxLine(hvg, sx, y2 - lineHeight/2 , sx, y2 + lineHeight/2, MG_ORANGE);
 		safef(buffer, sizeof buffer, "%dbp", qs - lastQEnd);
-		mapBoxHgcOrHgGene(hvg, s, e, sx, y2 - lineHeight/2, 1, lineHeight, tg->track,
+		boundMapBox(hvg, s, e, sx, y2 - lineHeight/2, 1, lineHeight, tg->track,
 				    "foo", buffer, NULL, TRUE, NULL);
 		}
 	    else if ((sf->orientation == -1) && (qs != lastQEnd) && (lastS == e))
 		{
 		hvGfxLine(hvg, ex, y2 - lineHeight/2 , ex, y2 + lineHeight/2, MG_ORANGE);
 		safef(buffer, sizeof buffer, "%dbp", qs - lastQEnd);
-		mapBoxHgcOrHgGene(hvg, s, e, ex, y2 - lineHeight/2, 1, lineHeight, tg->track,
+		boundMapBox(hvg, s, e, ex, y2 - lineHeight/2, 1, lineHeight, tg->track,
 				    "foo", buffer, NULL, TRUE, NULL);
 		}
 	    }
 
 	// now draw the lines between blocks
 	if ((!((lastX == sx) && (y1 == y2))) &&
 	    (sf->drawn  || ((prevSf != NULL) && (prevSf->drawn))) &&
 	    (((lastE >= winStart) && (lastE <= winEnd)) || 
 	    ((s > winStart) && (s < winEnd))))
 	    {
 	    if (lastLevel == sf->level)
 		{
 		safef(buffer, sizeof buffer, "%dbp", qs - lastQEnd);
 		if (sf->orientation == -1)
 		    {
 		    if (lastX != ex)
 			{
 			hvGfxLine(hvg, ex, y1, lastX, y2, color);
-			mapBoxHgcOrHgGene(hvg, s, e, ex, y1, lastX-ex, 1, tg->track,
+			boundMapBox(hvg, s, e, ex, y1, lastX-ex, 1, tg->track,
 				"", buffer, NULL, TRUE, NULL);
 			}
 		    }
 		else
 		    {
 		    if (lastX != sx)
 			{
 			hvGfxLine(hvg, lastX, y1, sx, y2, color);
-			mapBoxHgcOrHgGene(hvg, s, e, lastX, y1, sx-lastX, 1, tg->track,
+			boundMapBox(hvg, s, e, lastX, y1, sx-lastX, 1, tg->track,
 				"", buffer, NULL, TRUE, NULL);
 			}
 		    }
 		}
 	    else if (lastLevel > sf->level)
 		{
 		hvGfxLine(hvg, lastX, y1, sx, y2, color);
 		hvGfxLine(hvg, sx, y2, sx, y2 - lineHeight - lineHeight/3, color);
 		char buffer[1024];
 		safef(buffer, sizeof buffer, "%d-%d %dbp gap",prevSf->qStart,prevSf->qEnd, qs - lastQEnd);
-		mapBoxHgcOrHgGene(hvg, s, e, sx, y2 - lineHeight - lineHeight/3, 2, lineHeight + lineHeight/3, tg->track,
+		boundMapBox(hvg, s, e, sx, y2 - lineHeight - lineHeight/3, 2, lineHeight + lineHeight/3, tg->track,
 	                    "", buffer, NULL, TRUE, NULL);
 
 		}
 	    else
 		{
 		char buffer[1024];
 		safef(buffer, sizeof buffer, "%d-%d %dbp gap",prevSf->qStart,prevSf->qEnd, qs - lastQEnd);
 		if (sf->orientation == -1)
 		    {
 		    hvGfxLine(hvg, lastX-1, y1, ex, y2, color);
 		    hvGfxLine(hvg, ex, y2, ex, y2 + lineHeight , color);
-		    mapBoxHgcOrHgGene(hvg, s, e, ex-1, y2, 2, lineHeight , tg->track,
+		    boundMapBox(hvg, s, e, ex-1, y2, 2, lineHeight , tg->track,
 				"", buffer, NULL, TRUE, NULL);
 		    }
 		else
 		    {
 		    hvGfxLine(hvg, lastX-1, y1, sx, y2, color);
 		    hvGfxLine(hvg, sx, y2, sx, y2 + lineHeight , color);
-		    mapBoxHgcOrHgGene(hvg, s, e, sx-1, y2, 2, lineHeight , tg->track,
+		    boundMapBox(hvg, s, e, sx-1, y2, 2, lineHeight , tg->track,
 				"", buffer, NULL, TRUE, NULL);
 
 		    }
 		}
 	    }
 	}
     tEnd = e;
     tStart = s;
     qStart = sf->qStart;
     if (sf->orientation == -1)
 	lastX = sx;
     else
 	lastX = ex;
     lastS = s;
     lastE = e;