#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <bios.h>
#include <time.h>
#include "panel.h"

void move();
void get_dir();
void put_dir();
void add_entry();
void sort();
void search();
void trim(char []);
void setup();
void init_port();
void out_port(unsigned);
void upclock();

struct entry {
    int empty;
    char name[32];
    char number[25];
    } entries[100];

union REGS regs;
int aid, top_of_page=1, last_entry, mdt;
unsigned port;
time_t ltime;
char *stime;

main()
{
    char buf[25], cursor[10], num[25], dial[85];
    int i, k, sub, j;

    panel_activate("ptd");
    get_dir();

    strcpy(cursor, "sel");
    sub = 1;

    set_idle_func(upclock);

    while (1) {

        move();

        upclock();

        if ((aid = panel_execute(cursor, sub, 0)) == ESC) break;

        strcpy(cursor, "sel");
        sub = 1;
        put_field("message",1,"");
        mdt = 0;

        /* Process selection codes C)hange and E)rase */
        for (i=1;i<=14;i++) {
            get_field("sel",i,buf);
            switch (toupper(buf[0])) {
                case 'C':
                    k = top_of_page + i - 1;
                    modify_field_attr("name",i,"ur");
                    modify_field_attr("number",i,"ur");
                    if (panel_execute("name",i,0) != ESC) {
                        get_field("name",i,entries[k].name);
                        get_field("number",i,entries[k].number);
                        mdt = 1;
                        }
                    modify_field_attr("name",i,"ph");
                    modify_field_attr("number",i,"ph");
                    put_field("sel",i,"");
                    break;
                case 'E':
                    k = top_of_page + i - 1;
                    entries[k].empty = 1;
                    mdt = 1;
                    put_field("sel",i,"");
                    break;
                }
            }


        /* Process a dial or invalid selection code */
        for (i=1;i<=14;i++) {
            get_field("sel",i,buf);
            switch (toupper(buf[0])) {
                case 'D':
                    get_field("number",i,num);
                    trim(num);
                    strcpy(dial, entries[0].name+4);
                    strcat(dial, num);
                    strcat(dial, entries[0].number);
                    k = strlen(dial);
                    for (j=0;j<k;j++)
                        out_port(dial[j]);
                    out_port(0x0d);
                    break;
                case ' ':
                    break;
                default:
                    put_field("message",1,"Invalid selection code");
                    if (cursor[0] == 0) {
                        strcpy(cursor, "sel");
                        sub = i;
                        }
                    break;
                }
            }

        if (mdt) sort();

        /* Process function key */
        switch (aid) {
            case F1:     /* help */
                panel_activate("ptdh");
                panel_execute("",1,0);
                destroy_panel();
                break;
            case F2:     /* add */
                add_entry();
                break;
            case F4:     /* search */
                search();
                break;
            case PGUP:
                if (top_of_page > 14)
                    top_of_page -= 14;
                else
                    if (top_of_page > 1)
                        top_of_page = 1;
                    else
                        put_field("message",1,"First page is displayed");
                break;
            case PGDN:
                if (top_of_page+14 <= last_entry)
                    top_of_page += 14;
                else
                    put_field("message",1,"Last page is displayed");
                break;
            case F10:    /* setup */
                setup();
                break;
            }


        }

    destroy_panel();
    put_dir();

}


void upclock()
    {
    time(&ltime);

    stime = ctime(&ltime);
    stime[24] = 0;

    put_field("time", 1, stime);

    }


void move()
    {
    int j, k;

    for (j=1; j<=14; j++)
        {
        k = top_of_page + j - 1;
        if (k > last_entry)
            {
            put_field("name", j, "");
            put_field("number", j, "");
            put_field("sel", j, "");
            modify_field_attr("sel", j, "ph4");
            }
        else
            {
            put_field("name", j, entries[k].name);
            put_field("number", j, entries[k].number);
            put_field("sel", j, "");
            modify_field_attr("sel", j, "uh4");
            }
        }

    }

void put_dir()
{
    FILE *h_dir;
    h_dir = fopen("ptd.dat","wb");
    fwrite((char *)entries, sizeof(struct entry), 100, h_dir);
    fclose(h_dir);
}


void get_dir()
{
    FILE *h_dir;
    int i;
    if ((h_dir = fopen("ptd.dat","rb")) == NULL) {
        entries[0].empty = 300;
        strcpy(entries[0].name, "1N18ATDT");
        strcpy(entries[0].number, ";H0");
        for (i=1;i<100;i++) {
            entries[i].empty = 1;
            entries[i].name[0] = 0;
            entries[i].number[0] = 0;
            }
        put_field("message",1,"Creating new directory file!");
        }
    else {
        fread((char *)entries, sizeof(struct entry), 100, h_dir);
        fclose(h_dir);
        }

    init_port();

    /* determine subscript of last entry */
    for (i=1;i<100;i++)
        if (entries[i].empty) {
            last_entry = i - 1;
            return;
            }
    last_entry = 99;

}


void add_entry()
{

    if (last_entry >= 99) {
        put_field("message",1,"Directory is full!");
        return;
        }

    panel_activate("ptda");

    if (panel_execute("",1,0) != ESC) {
        last_entry++;
        entries[last_entry].empty = 0;
        get_field("name",1,entries[last_entry].name);
        get_field("number",1,entries[last_entry].number);
        sort();
        }

    destroy_panel();

}

void sort()
{
    int i, done=0;
    struct entry temp;

    while (!done) {
        done = 1;
        for (i=1;i<99;i++) {
            if ((entries[i].empty > entries[i+1].empty) ||
               (entries[i].empty == entries[i+1].empty &&
                strcmpi(entries[i].name, entries[i+1].name) > 0)) {
                memcpy(&temp, &entries[i], sizeof(struct entry));
                memcpy(&entries[i], &entries[i+1], sizeof(struct entry));
                memcpy(&entries[i+1], &temp, sizeof(struct entry));
                done = 0;
                }
            }
        }

    /* determine subscript of last entry */
    for (i=1;i<100;i++)
        if (entries[i].empty) {
            last_entry = i - 1;
            return;
            }
    last_entry = 99;


}

void search()
{
    int i, l;
    char find[25];

    get_field("search",1,find);
    trim(find);
    l = strlen(find);
    for (i=1;i<=last_entry;i++)
        if (strnicmp(find, entries[i].name, l) == 0) {
            top_of_page = i;
            put_field("search",1,"");
            return;
            }

    put_field("message",1,"String not found");

}

void trim(char strg[])
{
    int i;

    for (i=strlen(strg)-1;i>=0;i--)
        if (strg[i] != ' ') {
            strg[i+1] = 0;
            return;
            }

    strg[0] = 0;

}

void init_port()
{
    unsigned parm, status;

    parm = 0x00;
    switch (entries[0].empty) {
        case 110:
            break;
        case 150:
            parm |= 0x20;
            break;
        case 600:
            parm |= 0x60;
            break;
        case 1200:
            parm |= 0x80;
            break;
        case 2400:
            parm |= 0xa0;
            break;
        case 4800:
            parm |= 0xc0;
            break;
        case 9600:
            parm |= 0xe0;
            break;
        default:
            parm |= 0x40;
        }

    switch (entries[0].name[1]) {
        case 'O':
            parm |= 0x08;
            break;
        case 'E':
            parm |= 0x18;
        }

    switch (entries[0].name[2]) {
        case '2':
            parm |= 0x04;
        }

    switch (entries[0].name[3]) {
        case '7':
            parm |= 0x02;
            break;
        default:
            parm |= 0x03;
        }

    switch (entries[0].name[0]) {
        case '1':
            port = 0;
            break;
        default:
            port = 1;
        }

    status = _bios_serialcom(_COM_INIT, port, parm);

}

void out_port(unsigned byte)
{
    unsigned status;

    status = _bios_serialcom(_COM_STATUS,0,0);
    status = _bios_serialcom(_COM_SEND, port, byte);
    status = _bios_serialcom(_COM_STATUS,0,0);

}

void setup()
{
    int error=1;
    char resp[20], parity[2], stop[2], word[2], port[2], baud[17];
    char cursor[8];

    panel_activate("ptds");
    parity[0] = entries[0].name[1];
    parity[1] = 0;
    stop[0] = entries[0].name[2];
    stop[1] = 0;
    word[0] = entries[0].name[3];
    word[1] = 0;
    port[0] = entries[0].name[0];
    port[1] = 0;
    itoa(entries[0].empty, baud, 10);
    put_field("port",1,port);
    put_field("baud",1,baud);
    put_field("parity",1,parity);
    put_field("stop",1,stop);
    put_field("word",1,word);
    put_field("prefix",1,entries[0].name+4);
    put_field("suffix",1,entries[0].number);

    cursor[0] = 0;

    while (error) {

        if (panel_execute(cursor,1,(cursor[0] != 0)) == ESC) {
            destroy_panel();
            return;
            }
        error = 0;
        strcpy(cursor, "");

        get_field("port",1,port);
        switch (port[0]) {
            case '1': case '2':
                break;
            default:
                if (!error) {
                    put_field("mess",1,"Invalid port!");
                    error = 1;
                    strcpy(cursor, "port");
                    }
                }
        get_field("baud",1,baud);
        switch (atoi(baud)) {
            case 110: case 150: case 300: case 600: case 1200: case 2400:
            case 4800: case 9600:
                break;
            default:
                if (!error) {
                    put_field("mess",1,"Invalid baud rate!");
                    error = 1;
                    strcpy(cursor, "baud");
                    }
                }

        get_field("parity",1,parity);
        switch (toupper(parity[0])) {
            case 'N': case 'O': case 'E':
                 break;
            default:
                if (!error) {
                    put_field("mess",1,"Invalid parity!");
                    error = 1;
                    strcpy(cursor, "parity");
                    }
                }

        get_field("stop",1,stop);
        switch (stop[0]) {
            case '1': case '2':
                break;
            default:
                if (!error) {
                    put_field("mess",1,"Invalid number of stop bits!");
                    error = 1;
                    strcpy(cursor, "stop");
                    }
                }

        get_field("word",1,word);
        switch (word[0]) {
            case '7': case '8':
                break;
            default:
                if (!error) {
                    put_field("mess",1,"Invalid word size!");
                    error = 1;
                    strcpy(cursor, "word");
                    }
                }




        }

    entries[0].name[0] = port[0];
    entries[0].name[1] = toupper(parity[0]);
    entries[0].name[2] = stop[0];
    entries[0].name[3] = word[0];
    entries[0].empty = atoi(baud);

    get_field("prefix",1,resp);
    trim(resp);
    strcpy(entries[0].name+4, resp);
    get_field("suffix",1,resp);
    trim(resp);
    strcpy(entries[0].number, resp);

    destroy_panel();

}
