/*
 *	Filename: VisualFontPanel.m
 *	Created : Tue May  2 08:01:01 1995
 *	Author  : Vince DeMarco <vdemarco@bou.shl.com>
 *	LastEditDate Was "Tue Jan 23 08:35:34 1996"
 */


#import "VisualFontPanel.h"
#import <objc/NXBundle.h>
#import <appkit/Application.h>
#import <appkit/FontManager.h>
#import <appkit/Font.h>
#import <appkit/Text.h>
#import <appkit/Matrix.h>
#import <appkit/NXCType.h>
#import <appkit/ButtonCell.h>

#import <stdlib.h>
#import <sys/param.h>
#import <string.h>

static id __shared = nil;

    /* Returns YES if str1 contains str2 */
static BOOL contains(const char *str1, const char *str2)
{
    int   len1;
    int   len2;
    char *s1;
    char *s2;
    int   i;


    if (str1 && str2){
	len1 = strlen(str1);
	len2 = strlen(str2);

	s1 = alloca(len1+1);
	s2 = alloca(len2+1);

	for(i=0;i<len1;i++){
	    s1[i] = NXToLower(str1[i]);
	}
	s1[len1] = '\000';

	for(i=0;i<len2;i++){
	    s2[i] = NXToLower(str2[i]);
	}
	s2[len2] = '\000';

	if (strstr(s1,s2)){
	    return YES;
	}else{
	    if (strcmp(s2,"medium") == 0){

		if (rindex(s1,'-')){  /* if the name doesn't have a '-' then it must
				       * be a Medium font (This isn't great but hey)
				       */
		    return NO;
		}else{
		    return YES;
		}
	    }else{
		return NO;
	    }
	}
    }
    return YES;
}

static BOOL isItalic(const char *str1)
{
    return contains(str1,"italic") || contains(str1,"oblique") || contains(str1,"obl");
}

static BOOL isRoman(const char *str1)
{
    return !isItalic(str1);
}

/* Quick Sort stuff */
extern int gnu_qsort (char *base_ptr, int total_elems, int size, int (*cmp)());

int cmp(const char **p1, const char **p2)
{
    return NXOrderStrings(*p1,*p2,YES,-1,NULL);
}

@implementation VisualFontPanel

+ new
{
    if (!__shared){
	char buf[MAXPATHLEN+1];
	[[NXBundle bundleForClass:[self class]] getPath:buf forResource:"VisualFontPanel" ofType:"nib"];
        __shared = self = [NXApp loadNibFile:buf owner:NXApp withNames:NO fromZone:[self zone]];
	[self setFrameAutosaveName:"VisualFontSelection"];
	[displayMatrix setAutoscroll:YES];
	[displayMatrix setTarget:self];
	[displayMatrix setDoubleAction:@selector(_setCellFont:)];
	[displayMatrix setAction:@selector(_setSelected:)];
	[self display:self];
	[setButton setEnabled:NO];
	[self setBecomeKeyOnlyIfNeeded:YES];
	[weightMatrix setTarget:self];
	[weightMatrix setAction:@selector(_setWeight:)];
    }
    return __shared;
}

- free
{
    return self;
}

- display:sender
{
    char         **availableFonts;
    unsigned int   numFonts;
    unsigned int   i,j;
    char         **filteredFonts;
    unsigned int   numFiltered;
    List          *selectedWeights;
    BOOL           selectRoman;
    BOOL           selectItalic;
    char           buf[512];

    [self disableDisplay];

    availableFonts = [[FontManager new] availableFonts];

    numFonts=0;
    while(availableFonts[numFonts]){
	numFonts++;
    }
    filteredFonts = NXZoneCalloc([self zone],numFonts,sizeof(char *));

    selectedWeights = [weightMatrix cellList];
    selectRoman  = [[[styleMatrix cellList] objectAt:0] state];
    selectItalic = [[[styleMatrix cellList] objectAt:1] state];

    numFiltered=0;
    for(i=0;i<numFonts;i++){
	if ([[selectedWeights objectAt:0] state]){
	    if ((selectRoman && isRoman(availableFonts[i])) ||
		(selectItalic && isItalic(availableFonts[i]))){
		filteredFonts[numFiltered++] = availableFonts[i];
		    /* No break here, or you will end up jump out of outer for loop */
	    }
	}else{
		/* Notice this starts at 1 not 0, first radio button is the all */
	    for(j=1;j<[selectedWeights count];j++){
		if ([[selectedWeights objectAt:j] state] &&
		    contains(availableFonts[i],[[selectedWeights objectAt:j] title])){
		    if ((selectRoman && isRoman(availableFonts[i])) ||
			(selectItalic && isItalic(availableFonts[i]))){
			filteredFonts[numFiltered++] = availableFonts[i];
			break;
		    }
		}
	    }
	}
    }
    filteredFonts[numFiltered] = NULL;

    gnu_qsort((char *)filteredFonts,numFiltered,sizeof(char *),cmp);

    [displayMatrix renewRows:numFiltered cols:1];
    [displayMatrix sizeToCells];
    for(i=0;i<numFiltered;i++){
	if (filteredFonts[i]){
	    [[displayMatrix cellAt:i :0] setTitle:filteredFonts[i]];
	}else{
	    [[displayMatrix cellAt:i :0] setTitle:"<<unusable font>>"];
	}
	[[displayMatrix cellAt:i :0]
	    setFont:[Font systemFontOfSize:12.0 matrix:NX_FLIPPEDMATRIX]];
    }

    [displayMatrix scrollCellToVisible:0 :0];
    [displayMatrix selectCellAt:0 :0];
    [[[displayMatrix superview] superview] update];

    [self perform:@selector(_setSelected:) with:self];

    free(availableFonts);
    free(filteredFonts);
    sprintf(buf,"%d/%d",numFiltered,numFonts);
    [selectedField setStringValue:buf];
    [self reenableDisplay];
    [self displayIfNeeded];
    return self;
}

- _setWeight:sender
{
    List *selectedWeights;
    int   i;

    selectedWeights = [weightMatrix cellList];

    if ([[sender selectedCell] tag] == -1){
	for(i=1;i<[selectedWeights count];i++){
	    if ([[selectedWeights objectAt:0] state] == 1){
		[[selectedWeights objectAt:i] setState:0];
	    }
	}
    }else{
	for(i=1;i<[selectedWeights count];i++){
	    if ([[selectedWeights objectAt:i] state] == 1){
		[[selectedWeights objectAt:0] setState:0];
	    }
	}
    }
    [weightMatrix display];
    return self;
}

- _setSelected:sender
{
    Font *fnt;

    if ([displayMatrix selectedCell]){
	fnt = [Font newFont:[[displayMatrix selectedCell] title] size:12.0];
	if (fnt){
	    [setButton setEnabled:YES];
	    [[displayMatrix selectedCell] setFont:fnt];
	    [displayMatrix update];
	    [fontnameField setStringValue:[fnt displayName]];
	}else{
	    [setButton setEnabled:NO];
	    [[displayMatrix selectedCell]
		setFont:[Font systemFontOfSize:12.0 matrix:NX_FLIPPEDMATRIX]];
	    [displayMatrix update];
	    [fontnameField setStringValue:""];
	}
    }else{
	[fontnameField setStringValue:""];
    }
    return self;
}

- _setCellFont:sender
{
    [setButton performClick:self];
    return self;
}

- set:sender
{
    id    responder;
    Font *fnt;

    fnt = [Font newFont:[[displayMatrix selectedCell] title] size:12.0];
    [[FontManager new] setSelFont:fnt isMultiple:NO];
    responder = [NXApp calcTargetForAction:@selector(setFont:)];
    [responder setFont:fnt];
    return self;
}
@end
