// bbs216_20110124.cms    by あすかぜ
// 1 列目、2列目、3 列目をキーとし、クイックソートでテーブルをソートします。
// 編集・再配布は自由です。
// 
// 使い方:
// このファイルは「Sort.cms」という名前で Macro フォルダに置いてください。
// 任意のマクロファイル内で、
//   Sort.qsort(l,t,r,b,x,d);
// とすると実行できます。
// ただし、l,t,r,b はそれぞれソート範囲の左端、上端、右端、下端
// x は無視されます
// d は昇順ならば False, 降順ならば True
//
// ソート対象は数値のみです。文字列はソートできません。
// ソート対象列が同じ値のデータに関しては順番が保存されません。

function compare(y1, y2, x) {
  // 最初に 1 列目を比較する
  r = [1,y1] - [1,y2];
  if(r != 0){ return r;}

  // 1 列目が等しい場合、2 列目を比較する
  r = [2,y1] - [2,y2];
  if(r != 0){ return r;}

  // 2 列目も等しい場合、3 列目を比較する
  r = [3,y1] - [3,y2];
  if(r != 0){ return r;}

  // 1, 2, 3 列目すべてが等しければ 0 を返す
  return 0;
}

function swaprow(y1, y2, l, r){
  for(x=l; x<=r; x++){ swap([x,y1],[x,y2]); }
}

function qsort(l, t, r, b, x, d){
  y = (t-0)+1;
  while(y <= b && compare(y,t,x) == 0){ y++; }
  if(y > b){ return; }
  if(compare(y,t,x) > 0){ p = y; }else{ p = t; }

  y1 = t;
  y2 = b;
  while(y1 <= y2){
    while(!d && compare(y1,p,x) <  0 && y1 <= y2){ y1++; }
    while(!d && compare(y2,p,x) >= 0 && y1 <= y2){ y2--; }
    while( d && compare(y1,p,x) >= 0 && y1 <= y2){ y1++; }
    while( d && compare(y2,p,x) <  0 && y1 <= y2){ y2--; }
    if(y1 < y2){
      if(p == y1){
        p = y2;
      }else if(p == y2){
        p = y1;
      }
      swaprow(y1,y2,l,r);
    }
  }
  if(t < y2){ qsort(l,t,r,y2,x,d); }
  if(y1 < b){ qsort(l,y1,r,b,x,d); }
}

// 引数を省略可能に
function qsort(l, t, r, b, x){
  qsort(l,t,r,b,x,False);
}

// 引数を省略可能に
function qsort(l, t, r, b){
  qsort(l,t,r,b,l,False);
}

// 普通のマクロとして実行すると現在の選択範囲をソートする
// キー列が選択範囲に含まれていないとソートが終わらず異常終了する
if(SelLeft > 1 || SelRight < 3){
  MessageBox("1 列目から 3 列目までを選択範囲に含めてください");
  return;
}
qsort(SelLeft, SelTop, SelRight, SelBottom, 0, False);