
/* This Object is the application's delegate. It is responsible for setting 
 * itself up as the Delegate for Services requests specific to this 
 * application. It interfaces with another object which handles services 
 * preferences
 */
#import <appkit/appkit.h>
#import <defaults/defaults.h>
#import <strings.h>
#import <mach/mach.h>

#import "DefaultHandler.h"
#import "MyDelegate.h"


@implementation MyDelegate

/* Setup Services Delegate and Initialize defaults */

- appDidInit:sender
{
    [[NXApp appListener] setServicesDelegate:self];  
    [defaultHandler readDefaults:self];
    return self;
}

/* Brings up the Info panel.   Not done on startup because it's in a separate
 * interface file. Saves startup time for the user if we do this when they ask
 * for it, and not before.
 */
- infoPanel:sender
{
    if( ! infoPanel ){
        [NXApp loadNibSection:"Information.nib" owner:self];
    }
    [infoPanel makeKeyAndOrderFront:sender];
    return self;    
}

/*
 * Brings up the Help panel (as above)
 */
- helpPanel:sender
{
    if( ! helpPanel ){
        [NXApp loadNibSection:"Information.nib" owner:self];
    }
    [helpPanel makeKeyAndOrderFront:sender];
    return self;    

}

/*  This method sends the data from the sender's "preferred" pasteboard
 *  (the first on the "types" list) through the Unix sort utility and 
 *  back to both the Ascii and TabText pasteboards.
 */
 
- sort:(id)pasteboard
    userData:(const char *)sortArgs
    error:(char **)errorMessage
{
    int length, lengths[2], storedOutput[2], thisPboard, currentType;
    const char *data;
    const char *const *ptypes;
    char *myTypes[2];
    char *outputPboards[2];
    
    myTypes[0] = (char *) NXAsciiPboardType;             storedOutput[0] = 0;
    myTypes[1] = (char *) NXTabularTextPboardType;       storedOutput[1] = 0;
    
    ptypes=[pasteboard types];
    
   /* calculate over all pasteboardtypes passed in */
    for (currentType=0; ptypes[currentType] ; currentType++ )
        if (    ( !strcmp(ptypes[currentType],NXTabularTextPboardType) ) ||
                ( !strcmp(ptypes[currentType],NXAsciiPboardType) )) {
        FILE *temp, *process;
        int i;
        char filename[25], command[256];
        char *outbuffer;
        
        [pasteboard readType:ptypes[currentType] data:&data length:&length];
        thisPboard= ( strcmp(ptypes[currentType],myTypes[0]) );
        
        outputPboards[thisPboard]=malloc(length+2);
        outbuffer=outputPboards[thisPboard];
        
        strncpy(outbuffer, data, length);
        if ( outbuffer[length-1] != '\n' ) {
        
          /* Sort data needs a newline at the end,  add one */
            outbuffer[length] = '\n';
            outbuffer[length+1] = '\0';
        }
        else outbuffer[length]='\0';

      /* Make a temporary file to give to Sort */
        
        strcpy(filename,"/tmp/file000000Selection" );
        NXGetTempFilename(filename,9);
        temp=fopen(filename,"w");
        fprintf(temp,outbuffer);
        fclose(temp);
        
      /* Call Sort using popen(),  The userData supplied has the
       * arguments for Sort (see "services" file).
       */
        sprintf(command,"sort %s %s %s\n",
                [defaultHandler sortFields],sortArgs,filename);
        process=popen(command,"r");
        
        for (i=0; ((outbuffer[i]=getc(process)) != EOF); i++)
            outbuffer[i+1] = '\0';
            
        lengths[thisPboard] = i;
        storedOutput[thisPboard] = 1;   
        
        unlink(filename);
        pclose(process);
    }
    
    if (!storedOutput[0] && !storedOutput[1]) 
        *errorMessage = "No ASCII text found in your selection.";
    else  {
        [pasteboard declareTypes:&myTypes[0] num:2 owner:self];
        
      /* Place the results on the corresponding pasteboards. The two pboards
       * are somewhat interchangeable,  if one result doesn't exist,  send the
       * other result in its place.  A service must provide all pboard types 
       * mentioned as "Return Types" in the services section. 
       */
        
        [pasteboard writeType:myTypes[0] 
            data: storedOutput[0] ? outputPboards[0] : outputPboards[1]
            length:storedOutput[0] ? lengths[0] : lengths[1]];
        [pasteboard writeType:myTypes[1] 
            data: storedOutput[1] ? outputPboards[1] : outputPboards[0]
            length:storedOutput[1] ? lengths[1] : lengths[0]];
        if (storedOutput[0]) free(outputPboards[0]);
        if (storedOutput[1]) free(outputPboards[1]);
        }

    return self;
}
 
/* Another simple service that capitalizes words */

- capitalize:pb userData:(const char *)userData error:(char **)errorMessage
{
    char *data;
    int length;
    const char *const *types;
    int hasAscii, i;

    types = [pb types];
    hasAscii=0;
    for (i=0; !hasAscii && types[i] ; i++) 
        if (!strcmp(types[i], NXAsciiPboardType)) hasAscii=1;
    if (hasAscii) {
        [pb readType:NXAsciiPboardType data:&data length:&length];
        if (data && length) {
            int First, i;
            char *returnData;
            
            returnData=malloc(length+1);
            First=TRUE;
            data = strncpy(returnData, data, length);
            returnData[length] = '\0';
            for (i=1;i<=length;i++) {
                if ( NXIsLower(*data) && First ) {
                        *data = NXToUpper(*data);
                        First=FALSE;
                }
                else if (! NXIsAlpha(*data)) First=TRUE;
                    else First=FALSE;
                data++;
            }
            [pb declareTypes:&NXAsciiPboardType num:1 owner:self];
            [pb writeType:NXAsciiPboardType data:returnData length:length];
            free(returnData);
        } 
        else *errorMessage = "No data in your selection.";
    } 
    else *errorMessage = "No ASCII text found in your selection.";

    return self;
}

/*  This is an example of a Service that take no input.  It simply returns
 *  the current date and time.
 */
 
- timestamp:(id)pasteboard
    userData:(const char *)sortArgs
    error:(char **)msg
{
    long timenum;
    char *data;

    timenum=time(NULL);
    data=asctime(localtime(&timenum));
    [pasteboard declareTypes:&NXAsciiPboardType num:1 owner:self];
    [pasteboard writeType:NXAsciiPboardType data:data length:25];
    return self;
}

@end
