/* * Concordance Programming Language Selective Overlay Program * * Copyright (c) 1995 Dataflight Software, Inc. * ALL RIGHTS RESERVED. * 2337 Roscomare Road, Suite 11 * Los Angeles, CA 90077 * * Author: Bill Caefer * * 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) 1995 YOUR NAME. ALL RIGHTS RESERVED. * Portions copyright (c) 1995 Dataflight Software, Inc. */ /* Key field -- search/select for match * Open database -- receive data * Go -- Prompt for delimited ASCII file name to load * struct(db,"TEMP.DCB"); * tempDB = opendb("TEMP.DCB"); * load(tempDB,delimited ASCII file's name); * Then copy from temporary database to opened database, * based on key field match. * Then zap and delete temporary database. */ /************************************************** ********** Global Variable Declarations *********** **************************************************/ char ESC = 27, EOF = -1, FALSE = 0, TRUE = 1, CR = 13, LF = 10, APPEND = 0; text Copyright = "Copyright (c) 1991 Dataflight Software, Inc. ALL RIGHTS RESERVED."; main() { int db, /* Handle to database for overlaying. */ tempdb, /* Handle to temporary database */ i, /* Miscellaneous loop variable. */ key, /* Used to store keyboard key input. */ field, /* Field number selected for matching. */ blocks, /* Number of "status blocks" displayed. */ queryZero, /* Documents in query zero. */ oldQueryNumber; char string[80]; /* Miscellaneous usage, stores words. */ text FieldNameArray[255]; /* Array of fields available in database. */ float percent; /* Used to calculate and display % completed. */ char testorder[102]; char loadorder[102]; text TopPrompt; text tempDatabaseName; int COMMA, QUOTE, NEWLINE; text NULLDATABASE = "|<>|"; /* Display this program's title screen, and its reason for being. */ TopPrompt = "This program allows you to overlay selected "+ "fields in a database with new information unloaded from "+ "another database with the same structure. It will match "+ "records based on a key field."+chr(CR)+chr(LF)+ " Press any key to continue..."; /* Initialize the screen and display the title screen message. */ Pcls(rep("+=",40)); cursoroff(); status(db); puts(0,0,program(),MenuColor_); scroll(07,15,15,62,0,0,MenuColor_); box(07,14,15,65,"3D",MenuColor_); edit(TopPrompt,08,16,13,61,-1,1,1,MenuColor_); if (getkey() == ESC) return; if (ver() < 5.10) return(Message("Concordance version 5.10 or greater required.")); /* Clear the title information from the screen, get a database to use. */ Pcls(rep("ΔΕ",40)); if( db.documents > 0 ) if( Message("Use the "+FileName(db.database)+" database?") <> 'Y') closedb( db ); if( db.documents < 0 ) { while( (key <> CR) and (key <> ESC) ) key = getfile("Database","*.DCB",string); db = opendb( string ); } /* If a database wasn't opened, quit. There is nothing to do. */ if( db.documents < 0 ) return; /* Display the database's name on the screen, create a menu with */ /* all of the field names and types in it. */ status( db ); InitMenu( db, FieldNameArray ); if( Message( "Overlay from ASCII file or Database? [A or D]" ) == 'A' ) { /* Ask user for the ASCII file to load */ key = 0; string[0] = 0; while((key <> CR) and (key <> ESC)) key = getfile("Overlay file","*.DAT",string); if ((key == ESC) or (string == "")) return; /* Try to create a temporary database, but don't try forever. */ while(struc(db,tempDatabaseName = "TEMP"+str(i,4,0,'z')) < 0) if ((i = i + 1) > 250) break; if ((tempdb = opendb(tempDatabaseName)) < 0) return(Message("Couldn't create a temporary database.")); zap(tempdb); for(i = 1; i <= tempdb.fields; i = i + 1) tempdb.order[i] = i; TopPrompt = "Select field order to load"; i = CallMarkFields(tempdb, /* Handle to data base. */ loadorder, /* Array with order of selected fields. */ TopPrompt, /* Prompt displayed on top of screen. */ 10, /* Used with Display mode, shows fields.*/ 'E'); /* Edits if 'E', displays if not 'E'. */ if( i <> 0 ) { Message("Exiting because no fields were marked for load."); return; } /* Load the database */ puts(0,0,rep('_',80),MenuColor_); puts(0,0,"Loading Temporary Database",MenuColor_); if (ver() >= 5.2) load(tempdb,string,COMMA = 44,QUOTE = 34,NEWLINE = 174,0,71,MenuColor_); else load(tempdb,string); } else { /* use an existing database */ tempDatabaseName = NULLDATABASE; key = not(CR); while( (key <> CR) and (key <> ESC) ) key = getfile("Database","*.DCB",string); if( (tempdb = opendb( string )) < 0 ) return( Message("Couldn't open the overlay database.") ); } status(db); /* Display the list of field names, asking */ /* the user to select one for use as a key. */ field = db.fields + 2; while(field > db.fields) field = menu(2,25,MaxRow_-2,54,FieldNameArray,i); if (field <= 0) return; TopPrompt = "Select fields to overlay"; i = CallMarkFields(db, /* Handle to data base. */ testorder, /* Array with order of selected fields. */ TopPrompt, /* Prompt displayed on top of screen. */ 10, /* Used with Display mode, shows fields.*/ 'E'); /* Edits if 'E', displays if not 'E'. */ if( i <> 0 ) { Message("Exiting because no fields were marked for overlay."); return; } if (Message("[O]verlay or [A]ppend information to fields? [O or A](default = O)") == 'A') APPEND = 1; /* Initialize the screen for status display */ /* while we are processing the data base. */ blocks = 59-19-3; Pcls(rep("__",40)); scroll(09,19,15,59,0,0,MenuColor_); box(09,19,17,61,"3D",MenuColor_); puts(10,21,"Processing document",MenuColor_); puts(11,21,"Overlay document",MenuColor_); puts(12,21,"Database processed",MenuColor_); puts(14,21,rep('°',blocks),MenuColor_); puts(12,58,"%",MenuColor_); cursoroff(); /* Cycle through the database. Process each loaded document, ** looking for its match in the database. If there is no match, ** just append the data. */ query(db,-1); queryZero = count(db); cycle( tempdb ) { puts(11,48,str(i = docno(tempdb),10,0,','),MenuColor_); percent = (i*1.0)/count(tempdb); puts(12,48,str(percent*100.0,10),MenuColor_); puts(14,21,rep('²',blocks*percent),MenuColor_); /* Search for the field value. Enclose it in quotes in */ /* case it has some weird characters embedded in it. */ oldQueryNumber = db.query; switch( db.type[ field ] ) { case 'P' : search(db, ' "' + trim(str(tempdb->field)) + '".' + db.name[field] + '. '); break; case 'N' : case 'T' : search(db, db.name[field]+' EQ "'+trim(str(tempdb->field))+'" '); break; case 'D' : search(db, db.name[field]+' EQ "'+trim(dtoc(tempdb->field))+'" '); break; } if( count( db ) <= 0 ) { /* If there is no match for this document, just append it. */ puts(10,48,str(db.documents+1,10,0,','),MenuColor_); blank(db); for(i = 1; i <= db.fields; i = i + 1) if (db.type[i] == 'D') memcpy(db->i, tempdb->i, 8); else db->i = tempdb->i; append(db); } else { /* Cancel the routine if the user cancelled the search(). */ if (oldQueryNumber == db.query) break; /* Matched a record, copy the selected fields. */ cycle(db) { puts(10,48,str(recno(db),10,0,','),MenuColor_); for(i = 1; i <= db.fields; i = i + 1) if(db.order[i] <> 0) if( APPEND ) { switch(db.type[i]) { case 'D': case 'N': db->i = tempdb->i; case 'T': db->i = trim(db->i) + " " + trim(tempdb->i); case 'P': db->i = db->i+chr(13)+chr(10)+tempdb->i; break; } } else { switch(db.type[i]) { case 'D': if (dtoc(tempdb->i) <> "00/00/0000") memcpy(db->i,tempdb->i,8); break; case 'N': db->i = tempdb->i; break; case 'P': case 'T': if (len(tempdb->i) <> 0) db->i = tempdb->i; break; } } } } if((db.query mod 20) == 0) query( db, -1 ); /* Terminate the loop if the user presses the [Esc] key. */ /* Don't exit the program here though, we need to erase */ /* the temporary database we created even if canceled. */ if (keypress()) { if (getkey() == ESC) if (Message("Cancel processing? Y/N?") == 'Y') break; cursoroff(); } } /* We are finished, close the temporary file and erase it. */ query( db, -1 ); if( tempDatabaseName <> NULLDATABASE ) { zap( tempdb ); closedb( tempdb ); erase( tempDatabaseName+".DCB" ); erase( tempDatabaseName+".KEY" ); } else closedb( tempdb ); } /* main() */ /**************************************************************** * Name: status * * Synopsis: Display status information. * ****************************************************************/ status(int db) { puts(0,0,rep('_',80),MenuColor_); puts(MaxRow_,0,rep(' ',80),MenuColor_); puts(MaxRow_,0,"Concordance Selective Overlay Program",MenuColor_); if (db.documents >= 0) puts(0,0,db.database,MenuColor_); } /* status() */ /**************************************************************** * Name: InitMenu * * Synopsis: Initialize the field selection menu. * ****************************************************************/ InitMenu(int db; text namearray[]) { int i; namearray[0] = "Key Field"; for(i = 1; i <= db.fields; i = i +1) switch(db.type[i]) { case 'P' : namearray[i] = pad(db.name[i],'L',17)+ "Paragraph"; case 'T' : namearray[i] = pad(db.name[i],'L',17)+ "Text "; case 'N' : namearray[i] = pad(db.name[i],'L',17)+ "Numeric "; case 'D' : namearray[i] = pad(db.name[i],'L',17)+ "Date "; } } /* InitMenu() */ /**************************************************************** * Name: FileName * * Synopsis: Trims the path from the file name. * ****************************************************************/ FileName(text name) { int i; 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,8,69); box(5,13,8,69,"3D", MenuColor_); puts(6,14,pad(message,'C',53),MenuColor_); key = getkey(); restore(5,13,screen); return(asc(upper(chr(key)))); } /* Message() */ /**************************************************************** * Name: Pcls * * Synopsis: Clears the screen to the pattern parameter. * ****************************************************************/ Pcls(text pattern) { int i; for(i = 1; i < MaxRow_; i = i + 1) puts(i,0,pattern); } /* Pcls() */ /**************************************************************** * Name: Path * * Synopsis: Returns the path up to the last \ and without * * the file's name. * ****************************************************************/ Path(text dosPath) { int i, j; if ((i = match(dosPath,":",1)) == 0) i = match(dosPath,"\",1); while(j = match(dosPath,"\",i+1)) i = j; return(substr(dosPath,1,i)); } /* Path() */ /************************************************************************ * name CallMarkFields() * * synopsis Mark or unmark fields as selected. * * description Fields are displayed and marked as selected or not * * selected. Display begins on row parameter, mode is * * display only if editmode parameter is not 'E'. * * results returns a nonzero value if a error was encountered. * ************************************************************************/ CallMarkFields(int db; /* Handle to data base. */ char fs[]; /* Array with order of selected fields. */ text prompt; /* Prompt displayed on top of screen. */ int minrow, /* Used with Display mode, shows fields.*/ editmode) /* Edits if 'E', displays if not 'E'. */ { text string; int i, j, error; string = "markfields(db,fs,prompt,0,'E')"; eval('run("mark",string)',error); if (error) { if (error == 138) Message("Can't find the MARK program to run"); else Message("Error "+str(error)+" while running MARK"); } else { /* Count the field numbers while we copy them over. */ /* If it totals zero, no fields were selected. */ for(i = 1; i <= db.fields; i = i + 1) j = j + (db.order[i] = fs[i]); if (j == 0) Message("You should select at least one field to overlay"); } /* A nonzero return value indicates an error. */ return( (error <> 0) or (j == 0) ); } /* CallMarkFields() */