/* * Concordance Programming Language List File Management Program * * Copyright (c) 1991 Dataflight Software, Inc. * ALL RIGHTS RESERVED. * 2337 Roscomare Road, Suite 11 * Los Angeles, CA 90077 * * Unauthorized distribution, adaptation or use may be * subject to civil and criminal penalties. * * You may incorporate this program into your own programs * ONLY if you incorporate the following copyright notice: * * Copyright (c) 1991 YOUR NAME. ALL RIGHTS RESERVED. * Portions copyright (c) 1991 Dataflight Software, Inc. * * NOTE: List.CPL DOES NOT unload data values to text * List2.CPL DOES unload data values to text */ /************************************************** ********** Global Variable Declarations *********** **************************************************/ char EOF = -1, ESC = 27, CR = 13, LF = 10, TAB = 9; short F1 = 15104, F2 = 15360, F3 = 15616, F4 = 15872, F5 = 16128, F6 = 16384, F7 = 16640, F8 = 16896, F9 = 17152, F10 = 17408, LEFT = 19200, RIGHT = 19712, PGUP = 18688, PGDN = 20736, HOME = 18176, END = 20224; int isWindows; x(text p) { return(Message(p)); } /*************************************************************** * Name: List File Management * * Synopsis: Loads and manages list files (b+trees). * ***************************************************************/ main() { text dictmenu[9]; int finished, next, i, key, tree; char string[80]; cls(); cursor(0,0); ver(string); isWindows = match(upper(string),"WINDOWS",1); dictmenu[0] = "List File Management"; dictmenu[1] = "Edit list file"; dictmenu[2] = "Unload list file to text"; dictmenu[3] = "Load list file from text"; dictmenu[4] = "Merge two list files"; dictmenu[5] = "Status of list file"; dictmenu[6] = "Open or create list file"; dictmenu[7] = "Create an authority list"; dictmenu[8] = "Quit"; next = 1; tree = EOF; while(finished == 0) { Status(string); switch(next = menu(5, 21, 16, 52, dictmenu, next, "EULMSOCQ")) { case 0: finished = (func(-1) <> ""); break; case 1: if( tree == EOF ) { Message("Open a list file first."); next = 6; } else editList(tree); break; case 2: unloadList(tree); break; case 3: loadList(tree); break; case 4: mergeLists(tree); break; case 5: btstat(tree); break; case 6: /* Open or create a list file. */ btclose(tree); tree = EOF; if (getfile("List File","*.LST",string) == CR) if (exist(string)) { tree = btopen(string); next = 1; } else if (Message("Not found, create as new? Y/N") == 'Y') tree = btcreate(string,0); break; case 7: /* Create an authority list. */ if (btcount(tree) < 0) Message("Open or create a list file first."); else btExplode(tree,0,string); break; case 8: finished = 1; } } } /* main() */ /**************************************************************** * Name: Status * * Synopsis: Displays data base and program status. * ****************************************************************/ Status(char string[]) { text line; cursoroff(); cursor(0,0); puts(MaxRow_,0,pad("Concordance Information Retrieval System",'L',80),MenuColor_); puts(MaxRow_,61,"Dataflight Software",MenuColor_); puts(0,0,pad(string,'L',80),MenuColor_); } /* Status() */ /********************************************************************** * Name: btReplace * Synopsis: Replaces existing entry with new, preserving data value ***********************************************************************/ btReplace( int tree; char key[]; int data ) { int i; char new[151]; text line; line = save(0,0,0,79); new = key; while((i <> ESC) and (i <> CR)) i = edit( "Entry: ", 0, 0, 0, 7, '@', new, 0, 7, 0, 69, 'SET', data, 0, 70, 0, 79, 'SEN:9.0', 2, "", 1, 1, TextColor_); if( i == CR ) { btdelete(tree, key); btinsert(tree, new, data); } restore(0,0,line); } /** btReplace **/ /**************************************************************** * Name: editList * * Synopsis: Displays and updates a list file. * ****************************************************************/ editList( int tree ) { char key[225]; int data, i, finished; text options[5], screen; options[1] = "Add to List File"; options[2] = "Delete Entry"; options[3] = "Edit Entry"; options[4] = "Quit"; finished = 0; puts(22,30,"[CtrlEnter] New Words"); while(finished == 0) switch(i = btmenu( tree, 7, 0, 22, 79, "List File Editor", key, data, "E")) { case 0: finished = 1; case 1: case 2: if (key == "") finished = 1; else { options[0] = trim( pad( key,'L', 25 )); screen = save(11,50,17,78); switch( menu( 11, 50, 18, 78, options, 1,"ADEQ")) { case 1: btinsert( tree, key, 0 ); break; case 2: btdelete( tree, key ); break; case 3: btReplace( tree, key, data ); break; case 4: finished = 1; break; } restore( 11, 50, screen ); } case -1: Message("btmenu() processing error."); finished = 1; } cursor(0,0); cls(); return(0); } /** editList() **/ /**************************************************************** * Name: btstat * * Synopsis: Show status of btree. * ****************************************************************/ btstat(int tree) { char string[80]; int data; text screen; if (tree == EOF) Message("Open or create a file first."); else { cursoroff(); screen = save(8,10,13,70); scroll(8,10,12,68,0,0,MenuColor_); box(8,10,13,70,'3D',MenuColor_); puts(09,11,"Total entries "+trim(str(btcount(tree),10,0,',')),MenuColor_); if (btfirst(tree,string,data)) string[0] = 0; puts(10,11,"First entry "+pad(string,'L',43),MenuColor_); if (btlast(tree,string,data)) string[0] = 0; puts(11,11,"Last entry "+pad(string,'L',43),MenuColor_); getkey(); restore(8,10,screen); } } /* btstat() */ /**************************************************************** * Name: mergeLists * * Synopsis: Merge two list files. * ****************************************************************/ mergeLists(int tree) { int key, i, j, file, data; char buffer[512]; if (tree == EOF) return(Message("Open a list file first.")); if (getfile("Input List File","*.LST",buffer) <> CR) return(0); else if ((file = btopen(buffer)) == EOF) return(Message("Couldn't open the input list file.")); /* Enter the processing loop, read through the data base */ /* until the end of the file, or user hits the ESC key. */ key = 0; cursor(0,0); cursoroff(); scroll(9,39,11,60,0,1,MenuColor_); box(9,39,11,60,'3D', MenuColor_, MenuBackground_); puts(10,41,"Merging",MenuColor_, MenuBackground_); i = 1; for(j = btfirst(file,buffer,data); (j >= 0) and (key <> ESC); j = btnext(file,buffer,data)) { if (((i = i + 1) mod 10) == 0) puts(10,50,str(i,9,0,','),MenuColor_, MenuBackground_); if (len(buffer = trim(buffer))) btinserta(tree,buffer,data); if (keypress()) key = getkey(); } btclose(file); scroll(9,39,11,60,0,1); } /* mergeLists() */ /**************************************************************** * Name: loadList * * Synopsis: Loads a list file from an ASCII file. * ****************************************************************/ loadList(int tree) { int key, i, j, k, m, file, data; char buffer[512], szTab[5]; if (tree == EOF) return(Message("Open a list file first.")); if (getfile("Input File","*.TXT",buffer) <> CR) return(0); else if ((file = open(buffer,"r")) == EOF) return(Message("Couldn't open the input text file.")); /* Enter the processing loop, read through the database */ /* until the end of the file, or user hits the ESC key. */ i = 1; key = 0; cursor(0,0); cursoroff(); scroll(9,39,11,60,0,1,MenuColor_); box(9,39,11,60,'3D',MenuColor_,MenuBackground_); puts(10,41,"Loading",MenuColor_,MenuBackground_); szTab = chr(TAB); while((readln(file,buffer) <> EOF) and (key <> ESC)) { puts(10,50,str(i = i + 1,9,0,','),MenuColor_,MenuBackground_); k = 0; m = 0; while (j = match(buffer, szTab, m + 1)) { m = j; } if (m > 0) { k = num(addr(buffer,m + 1)); buffer[m-1] = 0; } if (btexact(tree,buffer,k)) btinserta(tree,buffer,k); if (keypress()) key = getkey(); } close(file); scroll(9,39,12,62,0,1); } /* loadList() */ /**************************************************************** * Name: unloadList * * Synopsis: Unloads a list file to an ASCII file. * ****************************************************************/ unloadList(int tree) { int key, file, error, i, j; char buffer[512], szTab[5]; if (tree == EOF) return(Message("Open a list file first.")); if (getfile("Output File","*.TXT",buffer) <> CR) return(0); else if ((file = open(buffer,"w+")) == EOF) return(Message("Couldn't open the output file.")); /* Enter the processing loop, read through the data base */ /* until the end of the file, or user hits the ESC key. */ i = 0; key = 0; cursor(0,0); cursoroff(); scroll(8,39,10,60,0,1,MenuColor_); box(8, 39, 10, 61,'3D',MenuColor_,MenuBackground_); puts(9,41,"Unloading",MenuColor_,MenuBackground_); szTab = chr(TAB); for(error = btfirst(tree,buffer,j); error <> EOF; error = btnext(tree,buffer,j)) { wrap(buffer,6000); if (j) buffer = buffer + szTab + str(j); writeln(file,buffer,len(buffer)); puts(9,50,str(i=i+1,9,0,','),MenuColor_,MenuBackground_); if (keypress()) { if (getkey() == ESC) break; } } close(file); scroll(8,39,11,63,0,1); } /* unloadList() */ /**************************************************************** * Name: btExplode * * Synopsis: Creates a b+tree with the exploded sort field. * ****************************************************************/ btExplode(int tree, db; char treeName[]) { int field, delimiter; int i; float total; char string[80]; text fields[101]; text screen; /* Make sure this database is the one the user wants. */ if (db.documents >= 0) if (Message("Use "+FileName(db.database)+" as the database? Y/N") <> 'Y') closedb(db); /* Make sure a database is open and ready for use. */ if (db.documents < 0) if (getfile("Database","*.DCB",string) == CR) db = opendb(string); /* Return if no database has been opened for use. */ if (db.documents < 0) return; /* Copy all the field names to a list for display. */ for(i = 1; i <= db.fields; i = i + 1) { fields[i] = pad(db.name[i],'L',18); switch(db.type[i]) { case 'D': fields[i] = fields[i]+"Date"; case 'P': fields[i] = fields[i]+"Paragraph"; case 'N': fields[i] = fields[i]+"Numeric"; case 'T': fields[i] = fields[i]+"Text"; } } /* Now get the field number to explode. */ /* Display them in a menu() and ask the user. */ fields[0] = "Select Authority Field"; field = db.fields + 1; screen = save(7,24,18,55); /* Prompt in a loop to value check. Ignore LEFT, ** RIGHT, and function keys that the user may type. */ while(field > db.fields) { if ((field = menu(7, 24, 18, 55, fields, 1)) <= db.fields) { /* if statement added in the concordw version */ if ((field <> 0) and (db.type[field] <> 'P') and (db.type[field] <> 'T') and (field <= db.fields)) { Message("Please select a paragraph or text field."); field = db.fields + 1; } } } restore(7,24,screen); /* Quit if the user pressed the [Esc] key. */ if (field == 0) return; /* Now get the delimiter to use. Show the first record ** in the data base and allow the user to move between ** records with the cursor control keys. */ screen = save(18,0,MaxRow_,79); scroll(18,0,MaxRow_-3,77,0,'U',MenuColor_); box(18,0,MaxRow_-1,79,'3D',MenuColor_); puts(18,1,db.name[field],MenuColor_); puts(MaxRow_,0,pad("[PgDn]Next [PgUp]Previous [Home]First [End]Last",'L',80),MenuHighlight_ | 128); sleep(1000); puts(MaxRow_,0,pad("[PgDn]Next [PgUp]Previous [Home]First [End]Last",'L',80),MenuColor_); puts(0,0,pad("Delimiter:",'L',80),MenuColor_); while(delimiter == 0) { i = TextColor_; TextColor_ = MenuColor_; show(db->field,19,1,MaxRow_-3,76,1); TextColor_ = i; cursor(0,11); cursoron(); switch(i = getkey()) { case HOME:first(db); break; case END: last(db); break; case PGUP:prev(db); break; case PGDN:next(db); break; case ESC: delimiter = i; break; default: /* Here's where we check for a valid delimiter character. */ /* Extended ASCII and alphanumeric values are illegal, beep. */ if (((delimiter = i & 255) == 0) or isalnum(delimiter)) { beep(0,0); delimiter = 0; } else { /* Valid delimiter was typed, display it and confirm with user. */ puts(0,11,chr(delimiter),MenuColor_); if (Message("Use "+chr(delimiter)+" in field "+db.name[field]+"? Y/N") <> 'Y') delimiter = 0; } break; } } restore(18,0,screen); Status(treeName); if (delimiter == ESC) return; /* We have all of the information, create the list. */ cursoroff(); total = count(db); screen = save(14,43,17,63); box(14,43,17,63,"3D", MenuColor_); puts(15,44," Processing % ",MenuColor_); cycle(db) { puts(15,56,str(docno(db)/total*100.0,3),MenuColor_); if ((i = insert(db,field,delimiter,tree)) == ESC) break; } restore(14,43,screen); return(i); } /* btExplode() */ /**************************************************************** * Name: insert * * Synopsis: Parses the field, inserting each entry into the * * b+tree file. Stores the document number as the * * key's data element. * * Returns: Watches for the user pressing the Escape key. * * Returns value of key pressed. Returns ESC to * * signal a disk full condition. * ****************************************************************/ insert(int db,field,delimiter,tree) { int i, j, k; char string[200]; text ch; ch = chr(delimiter); if (len(trim(db->field))) { /* Loop through the field storing the substrings. */ wrap(db->field,31000); i = 1; while(j = match(db->field,ch,i)) { btinsert(tree,trim(substr(db->field,i,j-i)),docno(db)); i = j + 1; while(isspace(addr(db->field,i))) i = i + 1; } /* The parsing loop ended, store the field's last entry. */ string = trim(substr(db->field,i)); if (len(string)) btinsert(tree,string,docno(db)); } /* Check for a user cancellation with the ESCape key. */ i = 0; while(keypress()) if (getkey() == ESC) if (Message("Cancel processing? Y/N") == 'Y') i = ESC; return(i); } /* insert() */ /**************************************************************** * Name: FileName * * Synopsis: Trims the path from the file name. * ****************************************************************/ FileName(text name) { int i; if (i = match(name,":",1)) name = substr(name,i+1); while(i = match(name,"\",1)) name = substr(name,i+1); return(name); } /**************************************************************** * Name: Message * * Synopsis: Displays error message and waits for key. * ****************************************************************/ Message(text message) { text screen; int key; cursoroff(); screen = save(5,13,10,69); box(7,13,10,69,"3D", MenuColor_); puts(8,14,pad(message,'C',53),MenuColor_); key = getkey(); restore(5,13,screen); if (islower(key)) key = key - ('a' - 'A'); /* asc(upper(chr(key))); */ return(key); } /* Message() */