77022fe69d73bf7488dedd6a7a0c5a9dea3e854a
hiram
  Tue Oct 27 14:16:26 2020 -0700
appears to be working OK even in dynamic update move refs #21980

diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c
index b78a3e0..5240177 100644
--- src/hg/hgTracks/wigTrack.c
+++ src/hg/hgTracks/wigTrack.c
@@ -840,124 +840,124 @@
 wgo->image = image;
 wgo->vLine = vLineViaHvg;
 wgo->xOff = xOff;
 wgo->yOff = yOff;
 return wgo;
 }
 
 /* prototype version of mouseOverData using this static array,
  *   will alter this to be a private linked list
  */
 static struct wigMouseOver *mouseOverData = NULL;
 static int mouseOverIdx = -1;
 
 struct wigMouseOver
     {
-    int x;	/* x,y coordinates bottom left corner of box */
-    int y;
-    int width;	/* width,height of this box */
-    int height;
+    int x1;	/* beginning of a rectangle for this value */
+    int x2;	/* end of the rectangle */
     double value;	/* data value for this region */
     };
 
 void graphPreDraw(struct preDrawElement *preDraw, int preDrawZero, int width,
     struct track *tg, void *image, WigVerticalLineVirtual vLine, int xOff, int yOff, double *yOffsets, int numTrack,
     double graphUpperLimit, double graphLowerLimit, double graphRange,
     double epsilon, Color *colorArray, enum trackVisibility vis,
     struct wigCartOptions *wigCart, struct pixelCountBin *pixelBins)
 /*	graph the preDraw array */
 {
 int x1;
 int h = tg->lineHeight;	/*	the height of our drawing window */
 double scaleFactor = h/graphRange;
 Color oldDrawColor = colorArray[0] + 1;	/* Just to be different from 1st drawColor. */
 Color mediumColor = MG_BLACK;	// Will be overriden
 Color lightColor = MG_BLACK;	// Will be overriden
 Color clipColor = MG_MAGENTA;
 enum wiggleTransformFuncEnum transformFunc = wigCart->transformFunc;
 enum wiggleGraphOptEnum lineBar = wigCart->lineBar;
 boolean whiskers = (wigCart->windowingFunction == wiggleWindowingWhiskers
 			&& width < winEnd-winStart);
 
+/* start new data for a new track, freez old data if exists */
+if (mouseOverData)
+    {
+    mouseOverIdx = -1;
+    freez(&mouseOverData);
+    }
 AllocArray(mouseOverData, width);
 
 int mouseOverX2 = -1;
 double previousValue = 0;
 boolean skipMouseOvers = FALSE;
 #define epsilonLimit 1.0e-6
 // if (psOutput)
 //    skipMouseOvers = TRUE;
 
 /*	right now this is a simple pixel by pixel loop.  Future
  *	enhancements could draw boxes where pixels
  *	are all the same height in a run.
  */
 for (x1 = 0; x1 < width; ++x1)
     {
     int x = x1 + xOff;
     int preDrawIndex = x1 + preDrawZero;
     struct preDrawElement *p = &preDraw[preDrawIndex];
     /* ===== mouseOver calculations===== */
     if (!skipMouseOvers && (p->count > 0)) /* checking mouseOver construction */
 	{
 	if (p->count < 3)	/* allow 1 or 2 values to display */
 	    {
 	    double thisValue = p->sumData/p->count;	/* average if 2 */
 	    if (mouseOverX2 < 0)    /* first valid data found */
 		{
 		++mouseOverIdx;
 		mouseOverX2 = x1+1;
-		mouseOverData[mouseOverIdx].x = xOff+x1;
-		mouseOverData[mouseOverIdx].width = mouseOverX2 - x1;
-		mouseOverData[mouseOverIdx].y = yOff;
-		mouseOverData[mouseOverIdx].height = h;
+		mouseOverData[mouseOverIdx].x1 = x1;
+		mouseOverData[mouseOverIdx].x2 = mouseOverX2;
 		mouseOverData[mouseOverIdx].value = thisValue;
 		previousValue = thisValue;
 		}
 	    else	/* see if we need a new item */
 		{
 		if (fabs(thisValue - previousValue) > epsilonLimit)
 		    {
 		    /* finish off the existing run of data */
-		    mouseOverData[mouseOverIdx].width = mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff);
+		    mouseOverData[mouseOverIdx].x2 = mouseOverX2;
 		    mouseOverX2 = x1+1;
 		    ++mouseOverIdx;
-		    mouseOverData[mouseOverIdx].x = xOff+x1;
-		    mouseOverData[mouseOverIdx].width = mouseOverX2 - x1;
-		    mouseOverData[mouseOverIdx].y = yOff;
-		    mouseOverData[mouseOverIdx].height = h;
+		    mouseOverData[mouseOverIdx].x1 = x1;
+		    mouseOverData[mouseOverIdx].x2 = mouseOverX2;
 		    mouseOverData[mouseOverIdx].value = thisValue;
 		    previousValue = thisValue;
 		    }
 		else	/* continue run of same data value */
 		    mouseOverX2 = x1+1;
 		}
 	    }
 	else
 	    skipMouseOvers = TRUE;	/* has become too dense to make sense */
 	}
     else  /* perhaps entered region without values after some data already */
 	{
 	if (mouseOverX2 > 0)	/* yes, been in data, end it here */
 	    {
-	    mouseOverData[mouseOverIdx].width = mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff);
+	    mouseOverData[mouseOverIdx].x2 = mouseOverX2;
 	    mouseOverX2 = -1;	/* start over with new data when found */
 	    }
 	}
     /* potentially end the last mouseOver box */
-    if (mouseOverX2 > 0 && (mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff)) > mouseOverData[mouseOverIdx].width)
-	    mouseOverData[mouseOverIdx].width = mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff);
+    if (mouseOverX2 > 0 && mouseOverX2 > mouseOverData[mouseOverIdx].x2)
+	    mouseOverData[mouseOverIdx].x2 = mouseOverX2;
 
     /* ===== done with mouseOver calculations===== */
 
     assert(x1/pixelBins->binSize < pixelBins->binCount);
     unsigned long *bitCount = &pixelBins->bins[x1/pixelBins->binSize];
 
     Color drawColor = colorArray[x1];
     if (drawColor != oldDrawColor)
         {
 	mediumColor = somewhatLighterColor32(drawColor);
 	lightColor = somewhatLighterColor32(mediumColor);
 	oldDrawColor = drawColor;
         }
 
     /*	count is non-zero meaning valid data exists here	*/
@@ -1149,31 +1149,34 @@
 	    double grayValue;
 	    int grayIndex;
 	    /* honor the viewLimits, data below is white, data above is black */
 	    grayValue = max(dataValue,graphLowerLimit);
 	    grayValue = min(grayValue,graphUpperLimit);
 	    grayIndex = ((grayValue-graphLowerLimit)/graphRange)*MAX_WIG_VALUE;
 
 	    drawColor =
 		tg->colorShades[grayInRange(grayIndex, 0, MAX_WIG_VALUE)];
 	    doLine(image, x, yOff, tg->lineHeight, drawColor);
             }   /*	vis == tvDense || vis == tvSquish	*/
 	}	/*	if (preDraw[].count)	*/
     }	/*	for (x1 = 0; x1 < width; ++x1)	*/
 
     if (skipMouseOvers || mouseOverIdx < 0)
+	{
+        mouseOverIdx = -1;
 	freez(&mouseOverData);
+	}
 
 }	/*	graphPreDraw()	*/
 
 static void graphPreDrawContainer(struct preDrawContainer *preDrawContainer, 
     int preDrawZero, int width, struct track *tg, struct hvGfx *hvg, 
     int xOff, int yOff, double graphUpperLimit, double graphLowerLimit, 
     double graphRange, enum trackVisibility vis, struct wigCartOptions *wigCart)
 /* Draw the graphs for all tracks in container. */
 {
 double epsilon = graphRange / tg->lineHeight;
 struct preDrawElement *preDraw = preDrawContainer->preDraw;
 Color *colorArray = makeColorArray(preDraw, width, preDrawZero, wigCart, tg, hvg);
 struct wigGraphOutput *wgo = tg->wigGraphOutput;
 graphPreDraw(preDraw, preDrawZero, width,
 	tg, wgo->image, wgo->vLine, wgo->xOff, wgo->yOff, wgo->yOffsets, wgo->numTrack,
@@ -1433,72 +1436,76 @@
 wigTrackSetGraphOutputDefault(tg, xOff, yOff, width, hvg); 
 
 graphPreDrawContainer(preContainer, preDrawZero, width, tg, hvg, xOff, yOff, 
     graphUpperLimit, graphLowerLimit, graphRange, vis, wigCart);
 
 drawZeroLine(vis, wigCart->horizontalGrid,
     graphUpperLimit, graphLowerLimit,
     hvg, xOff, yOff, width, tg->lineHeight);
 
 drawArbitraryYLine(vis, (enum wiggleGridOptEnum)wigCart->yLineOnOff,
     graphUpperLimit, graphLowerLimit,
     hvg, xOff, yOff, width, tg->lineHeight, wigCart->yLineMark, graphRange,
     wigCart->yLineOnOff);
 
 #ifdef NOT_READY_TO_GO
-if (mouseOverData)
+if (NULL != mouseOverData)
     {
     static boolean beenHereDoneThat = FALSE;
     struct tempName jsonData;
     trashDirFile(&jsonData, "hgt", tg->track, ".json");
     FILE *trashJson = mustOpen(jsonData.forCgi, "w");
     struct jsonWrite *jw = jsonWriteNew();
     jsonWriteObjectStart(jw, NULL);
     jsonWriteListStart(jw, tg->track);
     int i;
     /* could put up a 'no data' box when these items are not contiguous
      *    e.g. when gaps interrupt the track data
      */
     for (i = 0; i <= mouseOverIdx; ++i)
 	{
         jsonWriteObjectStart(jw, NULL);
-        jsonWriteNumber(jw, "x1", (long long)mouseOverData[i].x);
-        jsonWriteNumber(jw, "y1", (long long)mouseOverData[i].y);
-        jsonWriteNumber(jw, "x2", (long long)(mouseOverData[i].x + mouseOverData[i].width));
-        jsonWriteNumber(jw, "y2", (long long)(mouseOverData[i].y + mouseOverData[i].height));
+        jsonWriteNumber(jw, "x1", (long long)mouseOverData[i].x1);
+        jsonWriteNumber(jw, "x2", (long long)mouseOverData[i].x2);
         jsonWriteDouble(jw, "v", mouseOverData[i].value);
         jsonWriteObjectEnd(jw);
         }
     jsonWriteListEnd(jw);
     jsonWriteObjectEnd(jw);
     fputs(jw->dy->string,trashJson);
+    mouseOverIdx = -1;
+    freez(&mouseOverData);
     // This is the hidden signal to the javaScript of where to pick up
     //  the json file
     hPrintf("<MAP Name=%s class=mouseOver trashFile='%s'>\n", tg->track, jsonData.forHtml);
     hPrintf("</MAP>\n");
     carefulClose(&trashJson);
     if (! beenHereDoneThat )
 	{
 	hPrintf("<div id='mouseOverContainer' class='wigMouseOver'>\n");
 	hPrintf("  <span id='mouseOverText' class=wigMouseOverValue'>\n");
 	hPrintf("  </span>\n");
 	hPrintf("</div>\n");
         beenHereDoneThat = TRUE;
+// hPrintf("<div id='mouseDbg'><span id='debugMsg'><p>. . . mouseDbg</p></span></div>\n");
+// hPrintf("<div id='mouseXY'><span id='xyMouse'><p>. . . mouse X,Y</p></span></div>\n");
+// hPrintf("<div id='rectEvent'><span id='eventRects'><p>. . . eventRects</p></span></div>\n");
+// hPrintf("<div id='dbgMsg'><span id='msgDebug'><p>. . . debug message</p></span></div>\n");
 	}
     }
 else
-#endif
+#endif  /*       NOT_READY_TO_GO        */
     wigMapSelf(tg, hvg, seqStart, seqEnd, xOff, yOff, width);
 }
 
 struct preDrawContainer *wigLoadPreDraw(struct track *tg, int seqStart, int seqEnd, int width)
 /* Do bits that load the predraw buffer tg->preDrawContainer. */
 {
 /* Just need to do this once... */
 if (tg->preDrawContainer)
     return tg->preDrawContainer;
 
 struct wigItem *wi;
 double pixelsPerBase = scaleForPixels(width);
 double basesPerPixel = 1.0;
 int itemCount = 0;
 char *currentFile = NULL;