/*

dmsort.c --- ソート処理ルーチン

Copyright (c) 1993 Delmonta

*/

#include<stdio.h>
#include<stdlib.h>
#include<farstr.h>
#include<dos.h>
#include<assert.h>
#include"dmove86.h"

static	int	cmpfname(p,q)
struct DIRENTRY	far **p,far **q;
{
	return	far_strncmp((*p)->filename,(*q)->filename,11);
}

static	int	cmpftime(p,q)
struct DIRENTRY	far **p,far **q;
{
	register unsigned short	a,b;

	a = 
	a = (*p)->date;
	b = (*q)->date;

	if	(a!=b)
		return a-b;

	a = (*p)->time;
	b = (*q)->time;

	return a-b;
}

static	int	cmpextname(p,q)
struct DIRENTRY	far **p,far **q;
{
	register int	a;

	a = far_strncmp((*p)->extname,(*q)->extname,3);
	if	(a)
		return a;
	else
		return	far_strncmp((*p)->filename,(*q)->filename,8);
}

static	int	cmpattr(p,q)
struct DIRENTRY	far **p,far **q;
{
	register unsigned char	a,b,x,y;

	a = (*p)->attr;
	b = (*q)->attr;
	x = y = 0;
					/* (1)ボリュームID	*/
	if	(a & _A_VOLID)		x += 0x40;
	if	(b & _A_VOLID)		y += 0x40;
					/* (2)システムファイル	*/
	if	(a & _A_SYSTEM)		x += 0x20;
	if	(b & _A_SYSTEM)		y += 0x20;
					/* (3)サブディレクトリ	*/
	if	(a & _A_SUBDIR)		x += 0x10;
	if	(b & _A_SUBDIR)		y += 0x10;

	return y-x;
}

static	int	Sortmode;	/* ソート基準(ﾌｧｲﾙ名/拡張子/日時/属性)	*/
static	int	Sorttype;	/* 昇順か降順か				*/

#define	SORT_FILENAME	0
#define	SORT_EXTNAME	1
#define	SORT_TIMESTAMP	2
#define	SORT_ATTR	3

#define	SORT_UP		0
#define	SORT_DOWN	1

static	int	cmpdirentry(p,q)
struct DIRENTRY	far **p,far **q;
{
	register int	a,b;

	a = (*p)->filename[0] - 0xe5;	/* 例外処理:未使用エントリーは	*/
	b = (*q)->filename[0] - 0xe5;	/* 無条件で後ろに回す		*/

	if	(a==0 && b==0)	return 0;
	else if	(a!=0 && b==0)	return -1;
	else if	(a==0 && b!=0)	return 1;

	a = (*p)->filename[0] - '.';	/* 例外処理:"."、".."は		*/
	b = (*q)->filename[0] - '.';	/* 無条件で先頭へ		*/

	if	(a==0 && b==0)	return 0;
	else if	(a!=0 && b==0)	return 1;
	else if	(a==0 && b!=0)	return -1;


	switch(Sortmode)
	{
	case SORT_FILENAME:
		a = cmpfname(p,q);
		break;
	case SORT_EXTNAME:
		a = cmpextname(p,q);
		break;
	case SORT_TIMESTAMP:
		a = cmpftime(p,q);
		break;
	case SORT_ATTR:
		a = cmpattr(p,q);
		break;
	}

	if	(Sorttype == SORT_UP)
		return a;
	else
		return -a;
}

void	dmsort(dirtbl,s,e)
struct	DIRENTRY far **dirtbl;
unsigned int	s,e;
{
mode:;
	switch(dm_errmes("ソート基準 F:ファイル名 E:拡張子 T:最終変更日時 A:属性"))
	{
	case 'F':
	case 'f':
		Sortmode = SORT_FILENAME;
		break;
	case 'E':
	case 'e':
		Sortmode = SORT_EXTNAME;
		break;
	case 'T':
	case 't':
		Sortmode = SORT_TIMESTAMP;
		break;
	case 'A':
	case 'a':
		Sortmode = SORT_ATTR;
		break;
	case '\033':
		return;
	default:
		putchar('\7');
		goto	mode;
	}

type:
	switch(dm_errmes("ソート順 U:昇順 D:降順"))
	{
	case 'u':
	case 'U':
		Sorttype = SORT_UP;
		break;
	case 'd':
	case 'D':
		Sorttype = SORT_DOWN;
		break;
	case '\033':
		return;
	default:
		goto type;
	}

	qsort(dirtbl+s, e-s+1, sizeof(struct DIRENTRY far *), cmpdirentry);
}
