text: /* chainToAxt - convert from chain to axt format. */
  
  #include "common.h"
  #include "chain.h"
  #include "dnautil.h"
  #include "dnaseq.h"
  #include "axt.h"
  #include "chainToAxt.h"
  
  
  static struct axt *axtFromBlocks(
  	struct chain *chain,
  	struct cBlock *startB, struct cBlock *endB,
  	struct dnaSeq *qSeq, int qOffset,
  	struct dnaSeq *tSeq, int tOffset)
  /* Convert a list of blocks (guaranteed not to have inserts in both
   * strands between them) to an axt. */
  {
  int symCount = 0;
  int dq, dt, blockSize = 0, symIx = 0;
  struct cBlock *b, *a = NULL;
  struct axt *axt;
  char *qSym, *tSym;
  
  /* Make a pass through figuring out how big output will be. */
  for (b = startB; b != endB; b = b->next)
      {
      if (a != NULL)
          {
  	dq = b->qStart - a->qEnd;
  	dt = b->tStart - a->tEnd;
  	symCount += dq + dt;
  	}
      blockSize = b->qEnd - b->qStart;
      symCount += blockSize;
      a = b;
      }
  
  /* Allocate axt and fill in most fields. */
  AllocVar(axt);
  axt->qName = cloneString(chain->qName);
  axt->qStart = startB->qStart;
  axt->qEnd = a->qEnd;
  axt->qStrand = chain->qStrand;
  axt->tName = cloneString(chain->tName);
  axt->tStart = startB->tStart;
  axt->tEnd = a->tEnd;
  axt->tStrand = '+';
  axt->symCount = symCount;
  axt->qSym = qSym = needLargeMem(symCount+1);
  qSym[symCount] = 0;
  axt->tSym = tSym = needLargeMem(symCount+1);
  tSym[symCount] = 0;
  
  /* Fill in symbols. */
  a = NULL;
  for (b = startB; b != endB; b = b->next)
      {
      if (a != NULL)
          {
  	dq = b->qStart - a->qEnd;
  	dt = b->tStart - a->tEnd;
  	if (dq == 0)
  	    {
  	    memset(qSym+symIx, '-', dt);
  	    memcpy(tSym+symIx, tSeq->dna + a->tEnd - tOffset, dt);
  	    symIx += dt;
  	    }
  	else
  	    {
  	    assert(dt == 0);
  	    memset(tSym+symIx, '-', dq);
  	    memcpy(qSym+symIx, qSeq->dna + a->qEnd - qOffset, dq);
  	    symIx += dq;
  	    }
  	}
      blockSize = b->qEnd - b->qStart;
      memcpy(qSym+symIx, qSeq->dna + b->qStart - qOffset, blockSize);
      memcpy(tSym+symIx, tSeq->dna + b->tStart - tOffset, blockSize);
      symIx += blockSize;
      a = b;
      }
  assert(symIx == symCount);
  
  /* Fill in score and return. */
  axt->score = axtScoreDnaDefault(axt);
  return axt;
  }
  
  struct axt *chainToAxt(struct chain *chain, 
  	struct dnaSeq *qSeq, int qOffset,
  	struct dnaSeq *tSeq, int tOffset, int maxGap, int maxChain)
  /* Convert a chain to a list of axt's.  This will break
   * where there is a double-sided gap in chain, or 
   * where there is a single-sided gap greater than maxGap, or 
   * where there is a chain longer than maxChain.
   */
  {
  struct cBlock *startB = chain->blockList, *a = NULL, *b;
  struct axt *axtList = NULL, *axt;
  
  for (b = chain->blockList; b != NULL; b = b->next)
      {
      if (a != NULL)
          {
  	int dq = b->qStart - a->qEnd;
  	int dt = b->tStart - a->tEnd;
  	if ((dq > 0 && dt > 0) || dt > maxGap || dq > maxGap || (b->tEnd - startB->tStart) > maxChain)
  	    {
  	    axt = axtFromBlocks(chain, startB, b, qSeq, qOffset, tSeq, tOffset);
  	    slAddHead(&axtList, axt);
  	    startB = b;
  	    }
  	}
      a = b;
      }
  axt = axtFromBlocks(chain, startB, NULL, qSeq, qOffset, tSeq, tOffset);
  slAddHead(&axtList, axt);
  slReverse(&axtList);
  return axtList;
  }
  