
/* Generated by Interface Builder */

#import "PfindApp.h"
#import <streams/streams.h>
#import <appkit/ScrollView.h>
#import <appkit/Text.h>
#import <appkit/Cursor.h>
#import <stdio.h>
#import <stdlib.h>
#import  <appkit/Matrix.h>
#import <appkit/Form.h>
#import <appkit/OpenPanel.h>
#import <sys/param.h>
#import <string.h>
#import <appkit/defaults.h>
#import <sys/fcntl.h>
#import <text/text.h>
#import <libc.h>

#define MAXFILES 10
#define MAXCOMMANDSIZE 1000
#define Notify(title, msg) NXRunAlertPanel(title, msg, "OK", NULL, NULL)

const char *pfinddir = "/.pfind";
const char *inpfind = "/inpfind";
const char *outpfind = "/outpfind";
const char *temppfind = "/temppfind";
const char *databasesdir = "/databases";

char *homepath;
char command[MAXCOMMANDSIZE];
char currentdbpath[MAXPATHLEN+1];
char includedfilespath[MAXPATHLEN+1];
char pfindpath[MAXPATHLEN+1];
char inpfindpath[MAXPATHLEN+1];
char outpfindpath[MAXPATHLEN+1];
char temppfindpath[MAXPATHLEN+1];
char  databasespath[MAXPATHLEN+1];
char currentdbnamepath[MAXPATHLEN+1];
id openpanel;

@implementation PfindApp

 char fullpaths[MAXFILES][MAXPATHLEN+1];  /* Full pathnames of included files */
 int numfiles;
 long dbmodtime;

+ initialize
{
    static NXDefaultsVector pfindDefaults = {
        {"CurrentDb", NULL},
        { NULL}
    };
    NXRegisterDefaults("Pfind", pfindDefaults);
    return self;
}
    	
+ new
{
    self = [super new];
    currentdb = NULL;
    searchdb = currentdb;
    homepath = getenv("HOME");
    strcpy(pfindpath, homepath);
    strcat(pfindpath,pfinddir);
    strcpy(inpfindpath,pfindpath);
    strcat(inpfindpath, inpfind);
    strcpy(outpfindpath,pfindpath);
    strcat(outpfindpath,outpfind);
    strcpy(temppfindpath, pfindpath);
    strcat(temppfindpath, temppfind);
    strcpy(databasespath,pfindpath);
    strcat(databasespath, databasesdir);
    sprintf(command, "mkdirs %s %s", pfindpath, databasespath);
    system(command);
    currentdb = NXGetDefaultValue("Pfind", "CurrentDb");
    freopen("/dev/null", "w", stderr);
    return self;
}

- run
{
   [self setcurrentdb:self];
   [[includedfilesview docView] setEditable:NO];
   [super run];
   return self;
}    

- terminate:sender
{
  sprintf(command, "rm -f -r %s %s %s %s", inpfindpath,outpfindpath,temppfindpath, temppfindpath);
  strcat(command, ".ig");
  system(command);
  NXWriteDefault("Pfind", "CurrentDb", currentdb);
  [super terminate:sender];
  return self;
}  

    
- setResultsview:anObject
{
    resultsview = anObject;
    return self;
}

- setIncludedfilesview:anObject
{
    includedfilesview = anObject;
    return self;
}

- setCurrentdbfield:anObject
{
   currentdbfield = anObject;
    return self;
}

- setOpenPanelAccessory:anObject
{
    openPanelAccessory = anObject;
    return self;
}   

-setSearchdbmatrix:anObject
{
    searchdbmatrix = anObject;
    return self;
}     

- setcurrentdb:sender
{
    FILE *fd;
    NXStream *s;
    int i, fl;
    char *p;
    /* Get db name if not already given */
    if ((sender != self) || !currentdb) {
        openpanel = [OpenPanel new];
        [openpanel allowMultipleFiles:NO];
        [openpanel setAccessoryView:NULL];
        if ([openpanel runModalForDirectory:databasespath  file:NULL]) {
	      if (strcmp([openpanel directory],databasespath)) {
	           NXRunAlertPanel("Set Db", "Database must be chosen from directory %s",NULL,NULL,\
		      NULL, databasespath);
                    return self;
		  }		      
	    currentdb = [openpanel filenames][0];
	    }
  	}
    [[includedfilesview docView] setText:NULL];
    [[resultsview docView] setText:NULL];
    [currentdbfield setStringValue:NULL];
    sprintf(command,"rm -f -r  %s",temppfindpath);
    system(command);
    [searchdbmatrix selectCellAt:0:0];
    if (!currentdb) return self;
    strcpy(currentdbpath,pfindpath);
    strcat(currentdbpath, "/");
    strcat(currentdbpath,currentdb);
    if (!(fd =fopen(currentdbpath, "r"))) {
        currentdb = NULL;
        searchdb = NULL;
        return self;
        }
    fclose(fd);		
    [currentdbfield setStringValue:currentdb];
    searchdb = currentdbpath;
    strcpy(includedfilespath,currentdbpath);
    strcat(includedfilespath,".files"); 
    if (!(s = NXMapFile(includedfilespath, NX_READONLY))) return self;
    [[includedfilesview docView] readText:s];
    NXClose(s);
    /* Fill up fullpaths with contents of includedfiles */
    fd = fopen(includedfilespath, "r");
    i = 0;
    while (fgets(fullpaths[i], MAXPATHLEN, fd)){
      p = strchr(fullpaths[i], ' ');  /* Strip space and lf */
      *p = '\0';
      i++;
    }
    numfiles = i;
    fclose(fd);
    /* Get last modification date of currentdb name */
    strcpy(currentdbnamepath, databasespath);
    strcat(currentdbnamepath, "/");
    strcat(currentdbnamepath, currentdb);
    fl = open(currentdbnamepath, O_RDONLY);
    dbmodtime = fdWriteDate(fl);
    close(fl);
    return self;
}

- createdb:sender
{
    const char * const *filenames;
    const char *directory;
    FILE *fd;
    int i, nfiles;
    openpanel = [OpenPanel new];
    [openpanel allowMultipleFiles:YES];
    [openpanel setAccessoryView:openPanelAccessory];
    if (![openpanel runModal]) return self;
    currentdb = [openPanelAccessory stringValueAt:0];
    if (!currentdb || !(*currentdb)) {
         if (NX_ALERTALTERNATE == NXRunAlertPanel("Createdb", \
	   "Database name field must be filled in", "OK", "Cancel", NULL))
	   return self;
	 else
	   return [self createdb:self];
	 }
    [NXWait push];	 
    directory = [openpanel directory];
    filenames = [openpanel filenames];  
    /* Make  full path names */
    i = 0;    
    while  (filenames && *filenames) {
        strcpy(fullpaths[i], directory);
        strcat (fullpaths[i],"/");
        strcat (fullpaths[i],*filenames);
        filenames++;
	i++;
        }
    nfiles= i;
    strcpy(currentdbpath,pfindpath);
    strcat(currentdbpath, "/");
    strcat(currentdbpath,currentdb);
    /* Make currentdb be a link to first file */
    sprintf(command, "ln -s  %s %s", fullpaths[0],currentdbpath);
    system(command);
    /*  Create index */
    sprintf(command, "cd %s; indxbib %s",pfindpath, currentdb);
    if (nfiles > 1)
        for (i = 1; i <nfiles; i++) {
           strcat(command, " ");
	  strcat(command, fullpaths[i]);
  	  }
    if( system(command)) {
        Notify("Create", "Can't execute indxbib, check protection");
	}
    /* Store included files */
    strcpy(includedfilespath,currentdbpath);
    strcat(includedfilespath,".files");
    fd = fopen(includedfilespath, "w");
    for (i = 0; i<nfiles; i++) {
         fprintf(fd, "%s \n", fullpaths[i]);
	}
    fclose(fd);
    /* Place currentdb name in databases subdirectory  */
    sprintf(command, "cd %s; touch %s", databasespath, currentdb);
    system(command);
    /* Make new db be current one */
    [self  setcurrentdb:self];
    [NXWait pop];	
    return self;
}

- deletedb:sender
{   
    if (!currentdb) return self;
    if (NX_ALERTALTERNATE == NXRunAlertPanel("Delete", "Do you really want to delete %s?",\
          "Yes", "No", NULL, currentdb)) return self;
    sprintf(command, "rm -f -r %s %s", currentdbpath, currentdbpath);
    strcat(command,".ia ");
    strcat(command,currentdbpath);
    strcat(command,".ib ");
    strcat(command, currentdbpath);
    strcat(command,".ic ");
    strcat(command,currentdbpath);
    strcat(command,".files ");
    strcat(command,databasespath);
    strcat(command,"/");
    strcat(command,currentdb);
    system(command);	  
    currentdb = NULL;
    searchdb=NULL;
    [currentdbfield setStringValue:NULL];
    [[includedfilesview docView] setText:NULL];
    [[resultsview docView] setText:NULL];
    return self;
}
               
- savelastsearch:sender
{
    NXStream *s;
    FILE *fd;
    id savepanel;
    const char *filename;
     if (!searchdb) return self;
    savepanel = [SavePanel new];
    if (![savepanel runModal]) return self;
    filename = [savepanel filename];
    if (!(fd = fopen(filename, "w"))) return self;
    fclose(fd);
    sprintf(command, "touch %s", filename);
    system(command);
    if (!(s = NXMapFile(filename, NX_WRITEONLY))) return self;
    [[resultsview docView] writeText:s];
    NXSaveToFile(s, filename);
    NXCloseMemory(s,NX_FREEBUFFER);
    return self;
 }

- setsearchdb:sender
{
	FILE *fd;
        if (!currentdb) return self;
        switch ([sender selectedRow])  {
        case 0:
	      searchdb = currentdbpath;
	      break;
        case 1:
	      if(!(fd = fopen(temppfindpath, "r"))) 
	          [sender  selectCellAt:0:0];
	      else {
	          fclose(fd);   		  
	          searchdb = temppfindpath;
	      } 
	      break;
        default:
	      break;
        }	      	      	      
    return self;
}

- findparagraphs:sender
{
    NXStream  *s;
    FILE *fd;
    const char *str;
    char filename[MAXPATHLEN+1];
    int i, fl;
    BOOL updated;
    long mod;
    if (!searchdb) return self;
    /*  Save results view to results file in case it has been edited */
    if (!(fd = fopen(temppfindpath, "w"))) return self;
    fclose(fd);
    sprintf(command, "touch %s", temppfindpath);
    system(command);
    if (!(s = NXMapFile(temppfindpath, NX_WRITEONLY))) return self;
    [[resultsview docView] writeText:s];
    NXSaveToFile(s, temppfindpath);
    NXCloseMemory(s,NX_FREEBUFFER);
    /*  Make sure included files have not been updated. If so, re-index */
    updated = NO;
    for (i = 0; i <numfiles; i++) {
        strcpy(filename, fullpaths[i]);
        fl = open(filename, O_RDONLY);
	if (fl == -1) {
	    NXRunAlertPanel("Pfind", "%s cannot be opened", NULL, NULL, \
			    NULL, filename);
            return self;
	  }
    	mod = fdWriteDate(fl);
	if  (mod > dbmodtime) updated = YES;
	close(fl);
	}
    if (updated) {
        [NXWait push];
        sprintf(command, "cd %s; indxbib %s", pfindpath, currentdb);
	if (numfiles > 1)
	    for (i=1; i < numfiles; i++) {
	        strcat(command, " ");
		strcat(command, fullpaths[i]);
		}
        system(command);
        sprintf(command, "touch %s", currentdbnamepath);
        system(command);
        [NXWait pop];	
	}		
      /* Setup input file  */
    str= [sender stringValueAt:0];
    if(!(fd = fopen(searchdb, "r"))) return self;
    fclose(fd);
    if(!(fd = fopen(inpfindpath, "w"))) return self;
    fprintf(fd, "%s  \n",str);
    fclose(fd);
    /* Search using lookbib */
    sprintf(command,"lookbib -n %s  <%s >%s \n", searchdb, inpfindpath, outpfindpath);
    if (system(command)) Notify("Find", "Can't access lookbib, check protection");
    sprintf(command,"mv %s %s \n", outpfindpath, temppfindpath);
    system(command);
    /* Read results into results view */
    if (!(s = NXMapFile(temppfindpath, NX_READONLY))) return self;
    [[resultsview docView] readText:s];
    NXClose(s);
    return self;
}


@end
