/* Skivregister-browser                            */
/* l�nka i LARGE MODEL med BULLET_L.LIB            */

#include <dos.h>
#include <bios.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <bullet.h>


struct memorypack MP;
struct initpack IP;
struct exitpack EP;
struct createdatapack CDP;
struct createkeypack CKP;
struct dosfilepack DFP;
struct openpack OP;
struct accesspack AP[5];
struct statdatapack SDP;
struct exitpack EP;


struct skivrectype {
       char tag[1];
       char artist[35];
       char titel[35];
       char utg_ar[4];
       char musiktyp[20];
       char format[2];
       char utlanad[1];
       char kommentar[50];
};
struct skivrectype skivrec;

struct latrectype {
       char tag[1];
       char artist[35];
       char titel[35];
       char latnr[2];
       char lat[50];
};
struct latrectype latrec;

struct fielddesctype fieldlist1[7],fieldlist2[4];

int     rez, level;
div_t   div_rez;
int no_songs = 0;

char    tmpstr[129];

char skivDATname[80];
char latDATname[80];

char *skivIDXname[3] = {
       "ARTIST.IDX\0",
       "TITEL.IDX\0",
       "ARTTIT.IDX\0"
};

char *latIDXname[2] = {
       "LAT.IDX\0",
       "LATART.IDX\0"
};


char *skivIDXkey[3] = {
       "SUBSTR(ARTIST,1,15)+UTG_AR+SUBSTR(TITEL,1,15)\0",
       "SUBSTR(TITEL,1,15)\0",
       "SUBSTR(ARTIST,1,15)+SUBSTR(TITEL,1,15)\0"
};

char *latIDXkey[2] = {
       "SUBSTR(LAT,1,15)\0",
       "SUBSTR(ARTIST,1,15)+SUBSTR(TITEL,1,15)+LATNR\0"
};

unsigned int skivDAThandle, skivIDXhandle[3];
unsigned int latDAThandle, latIDXhandle[2];


char skivkeybuf[64];
char latkeybuf[64],latkeybuf2[64];

char fkeybuf[10][80];
FILE* fkeyf;

char *exceed_msg[2] = {
       "Du �r redan vid slutet av registret!                                           ",
       "Du �r redan vid b�rjan av registret!                                           "
};


int key,scan;

#define S_ARTIST 0
#define S_TITLE  1
#define S_SONG   2

char *smodestr[3] = {"Artist","Titel","L�t"};

#define YES 0x24
#define NO 49
#define QUIT 16

#define ADDMODE 0
#define EDITMODE 1

char gettmp[80];
char temp_artist[35];
char temp_titel[35];


int main(int argc, char **argv)
{

       if(argc == 3){
               strcpy(skivDATname,argv[1]);
               strcpy(latDATname,argv[2]);
       }
       else{
               printf("SKIVLOOK Skivregister-browser\n");
               printf("usage: skivlook <skivdbfname> <l�tdbfname>\n");
               exit(1);
       }

       init();

       while(1)
       {
               clrscr();
               HideCur();
               printf("\n");
               printf("*------------------------*                                 %d skivor totalt\n",getrecordno());
               printf("|  SKIVREGISTER-BROWSER  |\n");
               printf("*------------------------*\n\n");
               printf("(1) S�k Artist\n");
               printf("(2) S�k Titel\n");
               printf("(3) S�k L�t\n");
               printf("(4) Re-indexera databas\n");
               printf("\n<ESC> Avsluta program\n");

               scan = (bioskey(0) >> 8) & 0xff;
               switch(scan){
                       case 1: quit();break;
                       case 2: search(S_ARTIST);break;
                       case 3: search(S_TITLE);break;
                       case 4: search(S_SONG);break;
                       case 5: reindex();break;
               }
       }
}


search(int mode)
{
       clrscr();
       ShowCur();

       printf("S�k vilken %s? ",smodestr[mode]);

       if(mode != S_SONG) {
               gets(skivkeybuf);
               HideCur();
               if(strlen(skivkeybuf) == 0) return;

               if(getequal(&AP[0],skivIDXhandle[mode],&skivrec,skivkeybuf) != 0)
                       getnext(&AP[0],skivIDXhandle[mode],&skivrec,skivkeybuf);
       }
       else {
               gets(latkeybuf);
               HideCur();
               if(strlen(latkeybuf) == 0) return;

               if(getequal(&AP[2],latIDXhandle[0],&latrec,latkeybuf) != 0)
                       getnext(&AP[2],latIDXhandle[0],&latrec,latkeybuf);
               link_to_skivor();
       }

       clrscr();
       while(1)
       {
               if((AP[0].stat != 202) && (AP[0].stat != 203))
                       draw_info_scr();
               else {
                       gotoxy(1,25);
                       printf(exceed_msg[AP[0].stat-202]);
               }

               scan = (bioskey(0) >> 8) & 0xff;

               switch(scan){
                       case 81: if(mode != S_SONG)
                                                       getnext(&AP[0],skivIDXhandle[mode],&skivrec,skivkeybuf);
                                               else {
                                                       getnext(&AP[2],latIDXhandle[0],&latrec,latkeybuf);
                                                       link_to_skivor();
                                               }
                                               break;
                       case 73: if(mode != S_SONG)
                                                       getprev(&AP[0],skivIDXhandle[mode],&skivrec,skivkeybuf);
                                               else {
                                                       getprev(&AP[2],latIDXhandle[0],&latrec,latkeybuf);
                                                       link_to_skivor();
                                               }
                                               break;
                       case 1: return;
               }
       }
}

link_to_skivor()
{
int i;
       memset(skivkeybuf,0,64);
       comb_latart_tit(skivkeybuf);

       if(getequal(&AP[0],skivIDXhandle[2],&skivrec,skivkeybuf) != 0)
               getnext(&AP[0],skivIDXhandle[2],&skivrec,skivkeybuf);
}

draw_info_scr()
{
       draw_record_info();
       draw_song_info();

       gotoxy(1,25);
       printf("(PgUp) F�reg�ende  (PgDn) N�sta  (ESC) Avbryt");
}

draw_record_info()
{
       clrscr();
       printf("   ARTIST  %.35s",skivrec.artist);
       if(skivrec.tag[0] == '*')
               printf("        *** RADERAD ***");
       printf("\n");
       printf("    TITEL  %.35s\n",skivrec.titel);
       printf("   UTG-�R  %.4s\n",skivrec.utg_ar);
       printf(" MUSIKTYP  %.20s\n",skivrec.musiktyp);
       printf(" CD/LP/SI  %.2s\n",skivrec.format);
       printf("  UTL�NAD  %.1s\n",skivrec.utlanad);
       printf("KOMMENTAR  %.50s\n",skivrec.kommentar);
}

draw_song_info()
{
char titelcmpstr[35];

       find_first_song();
       strncpy(titelcmpstr,latrec.titel,35);

       printf("\n-- L�TAR --------------------------------------------------------------------\n\n");

       if(rez != 200)
       {
               while(1) {
                       if(strnicmp(titelcmpstr,latrec.titel,15)) break;
                       printf("%.2s  %.50s\n",latrec.latnr, latrec.lat);

                       if(getnext(&AP[2],latIDXhandle[1],&latrec,latkeybuf) != 0) break;

                       if( (wherey() == 24) && (! strnicmp(titelcmpstr,latrec.titel,15)) )
                       {
                               printf("\n<Return> f�r fler l�tar...");
                               while((bioskey(0) & 0xff) != 13);
                               draw_record_info();
                               printf("\n-- L�TAR --------------------------------------------------------------------\n\n");
                       }
               }
       }
}

find_first_song()
{
       comb_art_tit(latkeybuf);
       if(getequal(&AP[2],latIDXhandle[1],&latrec,latkeybuf) != 0)
               getnext(&AP[2],latIDXhandle[1],&latrec,latkeybuf);
}

reindex()
{
int i;

       level = 1210;
       printf("\nRe-indexerar databas... ");

       for(i=0;i<3;i++)
       {
               AP[i].func = REINDEXXB;
               AP[i].handle = skivIDXhandle[i];
               AP[i].nextptr = &AP[i+1];
       }
       AP[2].nextptr = NULL;

       if((rez = BULLET(&AP)) != 0){
         rez = AP[rez-1].stat;
         error();
       }

       level = 1211;

       for(i=0;i<2;i++)
       {
               AP[i].func = REINDEXXB;
               AP[i].handle = latIDXhandle[i];
               AP[i].nextptr = &AP[i+1];
       }
       AP[1].nextptr = NULL;

       if((rez = BULLET(&AP)) != 0){
         rez = AP[rez-1].stat;
         error();
       }
}

init()
{
int i;
int  handle;

       level = 100;
       MP.func = MEMORYXB;
       rez = BULLET(&MP);
       if (MP.memory < 40000l) {
               rez = 8;
               error();
       }

       level = 110;
       IP.func = INITXB;
       IP.jftmode = 0;
       if((rez = BULLET(&IP)) != 0) error();

       opendbf(skivDATname,&skivDAThandle);
       opendbf(latDATname,&latDAThandle);

       for(i=0;i<3;i++)
       {
               if ((handle = open(skivIDXname[i], O_RDONLY)) == -1)
                       createidx(skivIDXname[i],skivIDXkey[i],skivDAThandle,cCHAR);
               else close(handle);
       }

       for(i=0;i<2;i++)
       {
               if ((handle = open(latIDXname[i], O_RDONLY)) == -1)
                       createidx(latIDXname[i],latIDXkey[i],latDAThandle,cCHAR);
               else close(handle);
       }

       for(i=0;i<3;i++)
               openidx(skivIDXname[i],skivDAThandle,&skivIDXhandle[i]);

       for(i=0;i<2;i++)
               openidx(latIDXname[i],latDAThandle,&latIDXhandle[i]);

}

quit()
{
       printf("\nVill du verkligen sluta (j/n)?");

       while(1) {
               scan = (bioskey(0) >> 8) & 0xff;
               if((scan == 0x24) || (scan == 0x31)) break;
       }

       if(scan == 0x24)
       {
               EP.func = EXITXB;
               rez = BULLET(&EP);
               clrscr();
               ShowCur();
               exit(0);
       }
}

error()
{
       printf("Error: %u at level %u while performing ",rez,level);
       switch (level) {
       case 100:
         printf("a memory request of 140K.\n");
         break;
       default:
         printf("(See source)\n");    /* just check the source */
       }
       ShowCur();
       exit(1);
}

newgets(char *s,int len)
{
       ShowCur();

       memset(gettmp,32,80);

       while(! bioskey(1));
       scan = (bioskey(1) >> 8) & 0xff;
       if((scan >= 0x3b) && (scan <= 0x44)) {
               bioskey(0);
               strcpy(gettmp,fkeybuf[scan-0x3b]);
       }
       else
               gets(gettmp);
       gettmp[strlen(gettmp)] = 32;
       strncpy(s,gettmp,len);
       HideCur();
}


clear_fields()
{
       memset(skivrec.tag,32,1);
       memset(skivrec.artist,32,35);
       memset(skivrec.titel,32,35);
       memset(skivrec.utg_ar,32,4);
       memset(skivrec.musiktyp,32,20);
       memset(skivrec.format,32,2);
       memset(skivrec.utlanad,'F',1);
       memset(skivrec.kommentar,32,50);
}


createdbf(char far *fname,unsigned nofields,char far *fieldlist)
{
       CDP.func = CREATEDXB;
       CDP.filenameptr = fname;
       CDP.nofields = nofields;
       CDP.fieldlistptr = fieldlist;
       CDP.fileid = 3;

       if((rez = BULLET(&CDP)) != 0) error();
}
createidx(char far *idxname,char far *idxkey, unsigned dathandle,unsigned keyflags)
{
       level = 1100;
       CKP.func = CREATEKXB;
       CKP.filenameptr = idxname;
       CKP.keyexpptr = idxkey;
       CKP.xblink = dathandle;
       CKP.keyflags = keyflags;
       CKP.codepageid = -1;
       CKP.countrycode = -1;
       CKP.collateptr = NULL;
       rez = BULLET(&CKP);
       if (rez !=0) error();
}

opendbf(char far *fname,unsigned *handle)
{
       level = 1010;
       OP.func = OPENDXB;
       OP.filenameptr = fname;
       OP.asmode = READWRITE | DENYNONE;
       if((rez = BULLET(&OP)) != 0) error();
       *handle = OP.handle;
}
openidx(char far *fname, unsigned dathandle, unsigned *idxhandle)
{
       OP.func = OPENKXB;
       OP.filenameptr = fname;
       OP.asmode = READWRITE | DENYNONE;
       OP.xblink = dathandle;
       if( (rez = BULLET(&OP)) != 0) error();
       *idxhandle = OP.handle;
}


getequal(struct accesspack *accpptr, unsigned idxhandle,char far *recbuf, char far *keybuf)
{
       accpptr->func = GETEQUALXB;
       accpptr->handle = idxhandle;
       accpptr->recptr = recbuf;
       accpptr->keyptr = keybuf;
       if((rez = BULLET(accpptr)) != 0) {
               if(rez == 200)
                       return(200);
               else
                       error();
       }
       else
               return(0);
}
getnext(struct accesspack *accpptr, unsigned idxhandle,char far *recbuf, char far *keybuf)
{
       accpptr->func = GETNEXTXB;
       accpptr->handle = idxhandle;
       accpptr->recptr = recbuf;
       accpptr->keyptr = keybuf;
       if((rez = BULLET(accpptr)) != 0) {
               if(rez != 202) error();
       }
       else
               return(0);
}
getprev(struct accesspack *accpptr, unsigned idxhandle,char far *recbuf, char far *keybuf)
{
       accpptr->func = GETPREVXB;
       accpptr->handle = idxhandle;
       accpptr->recptr = recbuf;
       accpptr->keyptr = keybuf;
       if((rez = BULLET(accpptr)) != 0) {
               if(rez != 203) error();
       }
       else
               return(0);
}

deleterecord(struct accesspack *accpptr,unsigned dathandle,long recno)
{
       accpptr->func = DELETERECORDXB;
       accpptr->handle = dathandle;
       accpptr->recno = recno;
       if((rez = BULLET(accpptr)) != 0) error();
}
undeleterecord(struct accesspack *accpptr,unsigned dathandle,long recno)
{
       accpptr->func = UNDELETERECORDXB;
       accpptr->handle = dathandle;
       accpptr->recno = recno;
       if((rez = BULLET(accpptr)) != 0) error();
}


packrecords(unsigned dathandle)
{
       AP[0].func = PACKRECORDSXB;
       AP[0].handle = dathandle;
       if((rez = BULLET(&AP)) != 0) error();
}

getrecordno()
{
       SDP.func = STATDXB;
       SDP.handle = skivDAThandle;
       rez = BULLET(&SDP);
       return(SDP.recs);
}

HideCur()
{
         asm{
                 push ax
                 push cx

                 mov ah,01h
                 mov ch,00100110b
                 mov cl,00000111b
                 int 10H

                 pop cx
                 pop ax
         }
}

ShowCur()
{
         asm{
                 push ax
                 push cx

                 mov ah,01H
                 mov ch,00000110b
                 mov cl,00000111b
                 int 10H

                 pop cx
                 pop ax
         }
}

comb_art_tit(char *deststr)
{
       strncpy(deststr,skivrec.artist,15);
       deststr[15] = 0;
       strncat(deststr,skivrec.titel,15);
       deststr[30] = 0;
}
comb_latart_tit(char *deststr)
{
       strncpy(deststr,latrec.artist,15);
       deststr[15] = 0;
       strncat(deststr,latrec.titel,15);
       deststr[30] = 0;
}