#include "shared.h"

static inline void MyDrawBitmap(short row, short x, short y) {
  DWord *src, *dst;
  src = (DWord *) BITP(row);
  dst = (DWord *) &g.bmdata;
  *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++;
  *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++;
  WinDrawBitmap(&g.bmheader, x, y);
}

static void newSort(GlobalData_t *gp, Word sortType) {
  Word* sort;
  KanjiData_t * kp = gp->kandp;
  Word *sortp = gp->sortp;

  //making this inline saves .05 seconds.  Woohh... 
  static inline Word 
  sortVal(Word index) {
    switch(sortType) {
      case SORT_BUSHU: return SORTVAL_BUSHU(index) *256 + SORTVAL_COUNT(index);
      case SORT_SKIP : return SORTVAL_SKIP(index) ;
      case SORT_SPAHN: return SORTVAL_SPAHN(index);
      case SORT_GRADE: return SORTVAL_GRADE(index) *256 + SORTVAL_COUNT(index);
      case SORT_FREQ : return SORTVAL_FREQ(index) ;
      case SORT_COUNT: return SORTVAL_COUNT(index) *256 + SORTVAL_BUSHU(index); 
      default:
      case SORT_NONE : return index;
    }
  } //sortVal is a local procedure !!!
  
  //requires that "sortp" be filled with keys for each index
  static void asm_adjust(Word start, Word max) {
      register Word *sortstart asm("a1");
      register Word *sortmax;
      register Word *sort0p asm("a2");
      Word tmp; 
      register Word tmpVal asm("d4");
      sortstart = &sort[start];
      sortmax = &sort[max];
      tmp = *sortstart;
      tmpVal = sortp[tmp];
      for(;;) { 
        register Word sort0 asm("d0");
 	register Word sort1 asm("d1");	
 	register Word val0  asm("d2");
        register Word val1  asm("d3");
        sort0p = &sort[((long)sortstart-(long)sort) ];
        if (sort0p >= sortmax) break;
        sort0 =*sort0p; 
	sort1 = sort0p[1];
        val0 = sortp[sort0]; val1 = sortp[sort1];
        if (val0 < val1) { 
          if (tmpVal >= val1) break;
          *sortstart = sort1;
          sortstart = sort0p+1;
        } else {
          if (tmpVal >= val0) break; 
          *sortstart = sort0;
          sortstart = sort0p;
        }
      }
      if (sort0p == sortmax && tmpVal < sortp[*sortmax]) {
	*sortstart = *sortmax;
        *sortmax = tmp;	
      } else
      *sortstart = tmp; 
  } //end of asm_adjust
  Word i;
  Long ticks=0;
  sort = MemPtrNew((gp->numBitmaps+1)*sizeof(Word) );
  ErrFatalDisplayIf(!sort,"sortp");

  //create a list of keys and save them temporarily (0..numBitmaps-1)
  for (i=0; i< gp->numBitmaps; i++) sort[i] = sortVal(i);
  DmWrite(gp->sortp, 0, sort, sizeof(Word)*(gp->numBitmaps) );               

  //create an ascending list of indices starting at 1
  for (i=0; i< gp->numBitmaps; i++) sort[i+1] = i;

  ticks = TimGetTicks();;
  if (sortType != SORT_NONE) {
    //sort them using heap sort (system routines too unstable) 
    //first, heapify
    for (i= gp->numBitmaps>>1; i ; --i) 
	asm_adjust(i, gp->numBitmaps);
  
    //now, adjust
    for(i=gp->numBitmaps; i>1; ) {
      {register Word tmp = sort[1]; sort[1]= sort[i]; sort[i] = tmp;}
      asm_adjust(1, --i);
    }
  }
//  { char buff[10];
//    ticks = TimGetTicks() - ticks;
//    StrIToA(buff, ticks);
//    WinDrawChars(buff, StrLen(buff), 60,0); 
//  }
  //write them into memory
  DmWrite(gp->sortp, 0, &sort[1], sizeof(Word)*gp->numBitmaps );               

  gp->numIndices = gp->numBitmaps;
  MemPtrFree(sort);
}
