d3752edc12da1bf08427946150f564dbdd5d2254
angie
  Thu Oct 24 13:55:51 2019 -0700
bigDbSnp track handler code - initial commit.  refs #23283
* dnautil: Added trimRefAltLeft to get left-justified trimming (a la VCF not HGVS).
* bigBedClick: do hReplaceGbdb up front in parseDetailsTablUrls instead of waiting until endpoint.
* trackDbCustom.c: consolidating type-handling for wig/bigWig vs. bigBed-based big*.

diff --git src/lib/dnautil.c src/lib/dnautil.c
index 9ee6d78..cf82e9e 100644
--- src/lib/dnautil.c
+++ src/lib/dnautil.c
@@ -1200,49 +1200,81 @@
 char aaUC = toupper(aa);
 int ix;
 for (ix = 0;  ix < ArraySize(aminoAcidTable);  ix++)
     {
     if (aaUC == aminoAcidTable[ix].letter)
         {
         // safencpy(...3) is required here because aminoAcidTable.abbreviation is char[3] not [4]
         safencpy(abbrBuf, abbrBufSize, aminoAcidTable[ix].abbreviation, 3);
         abbrBuf[0] = toupper(abbrBuf[0]);
         return;
         }
     }
 safef(abbrBuf, abbrBufSize, "?%c?", aa);
 }
 
-void trimRefAlt(char *ref, char *alt, uint *pStart, uint *pEnd, int *pRefLen, int *pAltLen)
+void trimRefAltDir(char *ref, char *alt, uint *pStart, uint *pEnd, int *pRefLen, int *pAltLen,
+                   boolean leftJustify)
 /* If ref and alt have identical bases at beginning and/or end, trim those & update all params. */
 {
-int trimStart = 0;
-while (ref[trimStart] != '\0' && alt[trimStart] != '\0' && ref[trimStart] == alt[trimStart])
-    trimStart++;
+int trimStart = 0, trimEnd = 0;
 int refLen = strlen(ref);
 int altLen = strlen(alt);
-int iR = refLen - 1, iA = altLen - 1, trimEnd = 0;
+if (leftJustify)
+    {
+    // first trim end, then start
+    while (refLen > 0 && altLen > 0 && ref[refLen-1] == alt[altLen-1])
+        {
+        (*pEnd)--;
+        refLen--;
+        altLen--;
+        ref[refLen] = 0;
+        alt[altLen] = 0;
+        }
+    while (ref[trimStart] != '\0' && alt[trimStart] != '\0' && ref[trimStart] == alt[trimStart])
+        trimStart++;
+    }
+else
+    {
+    // first trim start, then end
+    while (ref[trimStart] != '\0' && alt[trimStart] != '\0' && ref[trimStart] == alt[trimStart])
+        trimStart++;
+    int iR = refLen - 1, iA = altLen - 1;
     while (iR >= trimStart && iA >= trimStart && ref[iR] == alt[iA])
         {
         iR--;
         iA--;
         trimEnd++;
         }
+    }
 if (trimEnd)
     {
     *pEnd -= trimEnd;
     refLen -= trimEnd;
     altLen -= trimEnd;
     ref[refLen] = '\0';
     alt[altLen] = '\0';
     }
 if (trimStart)
     {
     *pStart += trimStart;
     refLen -= trimStart;
     altLen -= trimStart;
     memmove(ref, ref+trimStart, refLen+1);
     memmove(alt, alt+trimStart, altLen+1);
     }
 *pRefLen = refLen;
 *pAltLen = altLen;
 }
+
+void trimRefAlt(char *ref, char *alt, uint *pStart, uint *pEnd, int *pRefLen, int *pAltLen)
+/* If ref and alt have identical bases at beginning and/or end, trim those & update all params. */
+{
+trimRefAltDir(ref, alt, pStart, pEnd, pRefLen, pAltLen, FALSE);
+}
+
+void trimRefAltLeft(char *ref, char *alt, uint *pStart, uint *pEnd, int *pRefLen, int *pAltLen)
+/* If ref and alt have identical bases at beginning and/or end, trim those starting on the right
+ * so we get the leftmost representation & update all params. */
+{
+trimRefAltDir(ref, alt, pStart, pEnd, pRefLen, pAltLen, TRUE);
+}