/***********************************************************************
    WiseCrack -    A fortune cookie program using Nico Françios
                   ReqTools library for simplicity.
                    
                   Version 1.0 by Lars Magnus Nordeide.
                   
                   This program is written using SAS/C V5.10a.
                   (See SASCOPTS for the compiler options.)
 ***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <math.h>
#include <libraries/dos.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <libraries/reqtools.h>
#include <proto/reqtools.h>
#include <proto/icon.h>

/* 
 * Global variables.
 */
struct ReqToolsBase *ReqToolsBase = NULL;
struct Library *IconBase = NULL;
BOOL window = FALSE, fromwb;
char *filepath, *wisetext;

/* 
 * Prototypes.
 */
void PrintHelp(char *), CleanExit(char *, int), ReadText(char *, char *);

void main(int argc, char **argv)
{
    int next = 1;
    char option, *odata, *tooltype, **toolarray;
    char *opts = "f";
    FILE *fpout;
    struct TagItem reqtags[] = { RTEZ_ReqTitle, (ULONG)"WiseCrack V1.0",
                                 TAG_END };
    struct WBStartup *wbenchmsg;
    struct WBArg *wbarg;
    struct DiskObject *dobj;
    
    /*
     * Allocate space for filepath and assign default datafile name.
     */
    filepath = (char *)malloc(FMSIZE);
    if (!filepath)
        CleanExit("Cannot allocate space.", RETURN_FAIL);
    strcpy(filepath, "S:WiseCrack.dat");

    /* 
     * Allocate space for the text. 2400 bytes should be more than
     * enough. This corresponds to a window with size 80x30 characters, 
     * full of text.
     */
    wisetext = (char *)malloc(2400);
    if (!wisetext)
        CleanExit("Cannot allocate space.", RETURN_FAIL);
    
    /* 
     * Are we started from the workbench?
     */
    fromwb = window = (argc == 0);
    
    if (!fromwb) {     /* Program was started from CLI, parse arguments */
        while ((odata = argopt(argc, argv, opts, &next, &option)) 
                != NULL) {
            switch(option) {
                case 'h':
                case '?':
                    PrintHelp(argv[0]);
                    break;
                case 'w':
                    window = TRUE;
                    break;
                default:
                    CleanExit("Illegal option!", RETURN_ERROR);
                    break;
            }
        }
        
        if (next < argc) {
            if (argv[next][0] == '?')
                PrintHelp(argv[0]);
            else
                strcpy(filepath, argv[next]);
        }
    }
    else {  /* Started from the workbench */
        wbenchmsg = (struct WBStartup *)argv;
        
        /*
         * Get the arguments for this tool.
         */
        wbarg = wbenchmsg->sm_ArgList;
        
        /* 
         * Open icon.library.
         */
        IconBase =(struct Library *) OpenLibrary("icon.library", 33);
        if (!IconBase)
            CleanExit("Cannot open icon.library.", RETURN_FAIL);
        
        /*
         * Read the iconfile.
         */
        dobj = GetDiskObject(wbarg->wa_Name);
        if (!dobj)
            CleanExit("Cannot open icon.", RETURN_FAIL);
        
        /*
         * Get the filename if given.
         */
        toolarray = (char **)dobj->do_ToolTypes;
        tooltype = FindToolType(toolarray, "DATAFILE");
        if(tooltype && tooltype[0] != '\0')
            strcpy(filepath, tooltype);
        
        /*
         * Free the DiskObject.
         */
        FreeDiskObject(dobj);
        
        /* 
         * Close The icon library.
         */
        if (IconBase)
        CloseLibrary((struct Library *)IconBase);
    }
    
    /*
     * Read text to print.
     */
    ReadText(filepath, wisetext);
    
    /*
     * Print out text, either to the console or in a separate window.
     */
    if (window) {
        /*
         * Open ReqTool library.
         */
        ReqToolsBase = (struct ReqToolsBase *)
                    OpenLibrary(REQTOOLSNAME, REQTOOLSVERSION);
        if (!ReqToolsBase)
            CleanExit("Cannot open reqtools.library", RETURN_FAIL);
        
        rtEZRequestA(wisetext, "OK", NULL, NULL, reqtags);
    }
    else {
        /*
         * Open stdout.
         */
        fpout = fopen("*", "w");
        fprintf(fpout, "%s\n", wisetext);
        close(fpout);
    }
        
    /* 
     * Ok, we are finished.
     */
    CleanExit(NULL, RETURN_OK);
}

/***********************************************************************/

void ReadText(char *filepath, char *text)
{
    struct FILEINFO *info;
    int cnt = 0;
    char ch;
    long size, pos;
    unsigned int clock[2];
    unsigned short seed[3];
    FILE *infile;
        
    /*
     * Initialize stuff.
     */
    info = (struct FILEINFO *)malloc(sizeof(struct FILEINFO));
    if (!info)
        CleanExit("Cannot allocate space.", RETURN_FAIL);
    
    /*
     * Check if datafile exist in specified filepath.
     */
    if (dfind(info, filepath, 0)) {
        sprintf(text, "Cannot find file %s", filepath);
        return;
    }
    
    /*
     * Find the size of the file in bytes.
     */
    size = info->fib_Size;
    
    /*
     * Have no more use for info. Free it.
     */
    free(info);
    
    /*
     * Compute a random position in the file.
     */
    timer(clock);
	seed[0] = clock[0];
	seed[1] = clock[1];
	seed[2] = clock[0];
	pos = nrand48(seed) % size;
    
    /*
     * Open file.
     */
    infile = fopen(filepath, "r");
    if (infile == NULL) {
        sprintf(text, "Cannot open %s.", filepath);
        return;
    }
    
    /*
     * Fast forward to computed position.
     */
    fseek(infile, pos, 0);
    
    /*
     * Find next start of text to print out.
     */
    while(((ch = fgetc(infile)) != '\\') && (ch != EOF));

    /*
     * Sometimes we are unlucky and will read past the end of the file. 
     * Instead of trying again, it's easier just to use a standard text. 
     * It's okay as it won't happen to often. 
     */
    if (ch == EOF) {
        strcpy(text,"How many IBM PC's does it take to execute a job?\n");
        strcat(text,"Four. Three to hold it down, and one to rip it's");
        strcat(text," head of.\n");
    }
    else {
        /*
         * Read text until the next '\' or EOF.
         */
        while(((ch = fgetc(infile)) != '\\') && (ch != EOF)) {
            text[cnt] = ch;
            cnt++;
        }
        text[cnt-1] = '\0';
    }
    
    /*
     * Close the file because we are done.
     */
    fclose(infile);
}    

/***********************************************************************/

void PrintHelp(char *name)
{
    FILE *fpout;
    
    fpout = fopen("*", "w");
    fprintf(fpout, "WiseCrack V1.0 by Lars Magnus Nordeide\n");
    fprintf(fpout, "Usage: %s [-w] [filename]\n", name);
    fclose(fpout);
    
    CleanExit(NULL, RETURN_OK);
}

/***********************************************************************/

void CleanExit(char *message, int ret_val)
{
    FILE *fpout;

    /*
     * Close the opened libraries.
     */
    if (ReqToolsBase)
        CloseLibrary((struct Library *)ReqToolsBase);

    /*
     * Free the space allocated for the filename.
     */
    if (wisetext)
        free(wisetext);
    if (filepath)
        free(filepath);
        
    /*
     * If there is an error then print the error message.
     */
    if (message && !fromwb) {
        fpout = fopen("*", "w");
        fprintf(fpout, "WiseCrack: %s\n", message);
        fclose(fpout);
    }
        
    exit(ret_val);
}
