/*                                TaskList.c                             */
/* This module takes care of Reading and Disposing of our list of tasks  */
/*                                  2/7/91                               */

#include <exec/types.h>
#include <proto/exec.h>
#include <exec/execbase.h>
#include <exec/exec.h>
#include <libraries/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "TaskTool.h"


extern struct ExecBase *SysBase;
extern TaskNode TaskList[];



/*------------------------------------------------------------------------*/
int DisposeTaskList(TaskNode TaskArray[], int ArrayCount)
/* Pre: Task Array is a valid Array of TaskNodes, and ArrayCount is a
 *      count of how many are valid nodes.
 * Post:All memory allocations in the TaskArray disposed of, returns 0
 *      Frees in reverse order of allocation
 */
{
    LONG count=ArrayCount-1;

    for (;count+1;count--) {
        if(TaskArray[count].Name)
            (VOID) FreeMem(TaskArray[count].Name,strlen(TaskArray[count].Name)+1);
    }

    return(0);
}


/*------------------------------------------------------------------------*/
int ReadTaskList(TaskNode TaskArray[])

/* Action: Reads in task details into TaskNode structures in array
 * TaskArray. Returns number of tasks read. 4/9/91: Now reads name of
 * this (TaskTool) task!
 */

{
    struct Task *task;
    LONG count=0;


    /* Get This Task (TaskTool!) */

    TaskArray[count].Pri = SysBase->ThisTask->tc_Node.ln_Pri;
    TaskArray[count].TaskID = (struct Task *)SysBase->ThisTask;

    if (!(TaskArray[count].Name =
        (STRPTR) AllocMem(strlen(SysBase->ThisTask->tc_Node.ln_Name)+1,MEMF_PUBLIC)))
        return(0); /* Out of Memory */

    strcpy(TaskArray[count++].Name,SysBase->ThisTask->tc_Node.ln_Name);



    Disable();

    /* Get Waiting Tasks */

    for ( task= (struct Task *)SysBase->TaskWait.lh_Head;
            (NULL != task->tc_Node.ln_Succ) && (count<TASKARRAYSIZE);
            task= (struct Task *)task->tc_Node.ln_Succ,count++)
    {
        TaskArray[count].Pri  = task->tc_Node.ln_Pri;
        TaskArray[count].TaskID = (struct Task *)task;

        if (!(TaskArray[count].Name =
            (STRPTR) AllocMem(strlen(task->tc_Node.ln_Name)+1,MEMF_PUBLIC)))
        {
            Enable();
            return(count-1); /* Out of Memory- just return those we got */
        }
        strcpy(TaskArray[count].Name,task->tc_Node.ln_Name);
    }

    /* Get Ready Tasks */

    for ( task= (struct Task*)SysBase->TaskReady.lh_Head;
            (NULL != task->tc_Node.ln_Succ) && (count<TASKARRAYSIZE);
            task= (struct Task*)task->tc_Node.ln_Succ,count++) {
        TaskArray[count].Pri  = task->tc_Node.ln_Pri;
        TaskArray[count].TaskID = (struct Task *)task;

        if (!(TaskArray[count].Name =
            (STRPTR)AllocMem(strlen(task->tc_Node.ln_Name)+1,MEMF_PUBLIC))) {
            Enable();
            return(count-1); /* Out of Memory- just return those we got */
        }

        strcpy(TaskArray[count].Name,task->tc_Node.ln_Name);
    }

    Enable();

    return(count);
}

/*------------------------------------------------------------------------*/
ULONG FindInList(STRPTR Name, struct Task *TaskID, ULONG numentries)
/*  Checks TaskList for Task matching Name and TaskID.
 *  Returns index in TaskList where occurs, or 0 if fails.
 *  Note: 0 is also a valid TaskList index.
 */

{
    ULONG i;
    extern TaskNode TaskList[];

    for(i=numentries-1;i>0;i--) {
        if (!strcmp(Name,TaskList[i].Name) && TaskList[i].TaskID==TaskID)
            break;
    }

    return(i);
}

/*------------------------------------------------------------------------*/
struct Task *
FindTaskAll(STRPTR Name, struct Task *TaskID)
/*  Checks ThisTask, ReadyTask and WaitTask List for Task matching the
 *  Given name and TaskID. Returns a valid Task * if task exists.
 *  4/9/91: Now finds this (TaskTool) Task!
 */

{
    struct Task *Task;

    Disable();  /* So things don't change while we are looking */


    /* First check if it is the TaskTool task we are changing */
    if (!strcmp(Name,SysBase->ThisTask->tc_Node.ln_Name)
        && TaskID==SysBase->ThisTask) {
        Enable();
        return(SysBase->ThisTask);
    }

    /*- Search Ready Task List for name -*/

    if ( Task = FindName( (struct List *)&(SysBase->TaskReady), Name) )
        while (Task && Task!=TaskID)
            Task = FindName((struct List *)Task, Name);

    if (Task && Task==TaskID) {     /* Name found and ID Matches */
        Enable();
        return(Task);
    }


    /*- Search Waiting Task List for name -*/

    if (Task = FindName( (struct List *)&(SysBase->TaskWait), Name))
        while (Task && Task!=TaskID)
            Task = FindName((struct List *)Task, Name);

    if (Task && Task==TaskID) {     /* Name found and ID matches */
        Enable();
        return(Task);
    }


    Enable();
    return((struct Task *)NULL); /* Search for name failed */
}

/*------------------------------------------------------------------------*/
BOOL SetTaskPriSafely( TaskListInfo *TTInfo )
/*  Change Task Priority to match data held in TaskListInfo structure
 *  checking first to make sure task exists. Returns FALSE if Task
 *  not there.
 */

{
    extern TaskNode TaskList[];
    struct Task *Task;
    STRPTR Name   = TaskList[TTInfo->Task].Name;
    struct Task *TaskID = TaskList[TTInfo->Task].TaskID;

    struct Task *FindTaskAll();

    Disable(); /* So nothing changes when we are looking... */

    if (Task = FindTaskAll(Name, TaskID))
        (VOID)SetTaskPri(Task,TaskList[TTInfo->Task].Pri);

    Enable();  /* Resume multitasking */

    return((BOOL)(Task != (struct Task *)NULL));
}

/*------------------------------------------------------------------------*/

