diff --git a/aspi/ASPI.C b/aspi/ASPI.C new file mode 100644 index 0000000..c6ed586 --- /dev/null +++ b/aspi/ASPI.C @@ -0,0 +1,25 @@ +#include +#include + +extern WORD GetASPISupportInfo(VOID); + + +int main() + +{ + + WORD ASPIStatus; + BYTE NumAdapters; + HWND hwnd; + + ASPIStatus = GetASPISupportInfo(); + + switch (HIBYTE(ASPIStatus)) + { + case SS_COMP: + break; + + default: + break; + } +} diff --git a/aspi/ASPI.EXE b/aspi/ASPI.EXE new file mode 100644 index 0000000..5bb8d96 --- /dev/null +++ b/aspi/ASPI.EXE Binary files differ diff --git a/aspi/ASPI.MAK b/aspi/ASPI.MAK new file mode 100644 index 0000000..fdea5ee --- /dev/null +++ b/aspi/ASPI.MAK @@ -0,0 +1,145 @@ +# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +!IF "$(CFG)" == "" +CFG=Win32 Debug +!MESSAGE No configuration specified. Defaulting to Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "aspi.mak" CFG="Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +################################################################################ +# Begin Project +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +OUTDIR=. +INTDIR=. + +ALL : $(OUTDIR)/aspi.exe $(OUTDIR)/aspi.bsc + +# ADD BASE CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c +# ADD CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c +CPP_PROJ=/nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\ + /FR$(INTDIR)/ /Fp$(OUTDIR)/"aspi.pch" /Fo$(INTDIR)/ /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +BSC32_SBRS= \ + $(INTDIR)/aspi.sbr +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"aspi.bsc" + +$(OUTDIR)/aspi.bsc : $(OUTDIR) $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/aspi.obj +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\ + /PDB:$(OUTDIR)/"aspi.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"aspi.exe" + +$(OUTDIR)/aspi.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +OUTDIR=. +INTDIR=. + +ALL : $(OUTDIR)/aspi.exe $(OUTDIR)/aspi.bsc + +# ADD BASE CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c +# ADD CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c +CPP_PROJ=/nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\ + /FR$(INTDIR)/ /Fp$(OUTDIR)/"aspi.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"aspi.pdb" /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +BSC32_SBRS= \ + $(INTDIR)/aspi.sbr +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o$(OUTDIR)/"aspi.bsc" + +$(OUTDIR)/aspi.bsc : $(OUTDIR) $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LINK32=link.exe +DEF_FILE= +LINK32_OBJS= \ + $(INTDIR)/aspi.obj +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\ + /PDB:$(OUTDIR)/"aspi.pdb" /DEBUG /MACHINE:I386 /OUT:$(OUTDIR)/"aspi.exe" + +$(OUTDIR)/aspi.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx.obj: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Group "Source Files" + +################################################################################ +# Begin Source File + +SOURCE=.\aspi.c + +$(INTDIR)/aspi.obj : $(SOURCE) $(INTDIR) + +# End Source File +# End Group +# End Project +################################################################################ diff --git a/aspi/ASPI.OBJ b/aspi/ASPI.OBJ new file mode 100644 index 0000000..56fe22a --- /dev/null +++ b/aspi/ASPI.OBJ Binary files differ diff --git a/aspi/ASPI.PDB b/aspi/ASPI.PDB new file mode 100644 index 0000000..81b8d52 --- /dev/null +++ b/aspi/ASPI.PDB Binary files differ diff --git a/aspi/ASPI.VCP b/aspi/ASPI.VCP new file mode 100644 index 0000000..f50f985 --- /dev/null +++ b/aspi/ASPI.VCP Binary files differ diff --git a/border/BORDER.C b/border/BORDER.C new file mode 100644 index 0000000..ef69106 --- /dev/null +++ b/border/BORDER.C @@ -0,0 +1,33 @@ +/* BORDER.C - Draws user selected border + Last Modified: 06/19/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + +#include + + +void border(startv,starth,width,height,vattrib) + +char vattrib; +int startv,starth,width,height; +{ +int x; + + v_rowcol(startv,starth); + scr_aputs(mkstr(BORDERNW,1),vattrib); + scr_aputs(mkstr(BORDERH,width-2),vattrib); + scr_aputs(mkstr(BORDERNE,1),vattrib); + v_rowcol(startv+height-1,starth); + scr_aputs(mkstr(BORDERSW,1),vattrib); + scr_aputs(mkstr(BORDERH,width-2),vattrib); + scr_aputs(mkstr(BORDERSE,1),vattrib); + + for (x=startv+1;x<=(startv+height-2);x++) + { + v_rowcol(x,starth); + scr_aputs(mkstr(BORDERV,1),vattrib); + v_rowcol(x,starth+width-1); + scr_aputs(mkstr(BORDERV,1),vattrib); + } + +} diff --git a/bplus/BPLUS.C b/bplus/BPLUS.C new file mode 100644 index 0000000..5f29858 --- /dev/null +++ b/bplus/BPLUS.C @@ -0,0 +1,948 @@ +/********************************************************************/ +/* */ +/* BPLUS file indexing program - Version 1.1A */ +/* */ +/* A "shareware program" */ +/* */ +/* */ +/* Copyright (C) 1987 by */ +/* */ +/* Hunter and Associates */ +/* 7050 NW Zinfandel Lane */ +/* Corvallis, Oregon 97330 */ +/* (503) 745 - 7186 */ +/* */ +/********************************************************************/ + + +#include +#include +#include +#include /* delete this line for Turbo C */ +#include +#include +#include "bplus.h" + + +/* macros, constants, data types */ + +#define NULLREC (-1L) +#define FREE_BLOCK (-2) + +#define ENT_ADR(pb,off) ((ENTRY*)((char*)((pb)->entries) + off)) +#define ENT_SIZE(pe) strlen((pe)->key) + 1 + 2 * sizeof(RECPOS) +#define BUFDIRTY(j) (mci->cache[j].dirty) +#define BUFHANDLE(j) (mci->cache[j].handle) +#define BUFBLOCK(j) (mci->cache[j].mb) +#define BUFCOUNT(j) (mci->cache[j].count) +#define CB(j) (pci->pos[j].cblock) +#define CO(j) (pci->pos[j].coffset) + + /* BPLUS uses the library routine */ + /* memmove which must be used with */ + /* Turboc 1.5, Quick C and MS C 5.0 */ +/* #define memmove memcpy */ /* Use this macro for Microsoft C4.0 */ + +/* declare some global variables */ + +IX_DESC *pci; +IX_BUFFER bt_buffer; +IX_BUFFER *mci = &bt_buffer; +BLOCK *block_ptr; +BLOCK *spare_block; +int cache_ptr = 0; +int cache_init = 0; +int split_size = IXB_SPACE; +int comb_size = (IXB_SPACE/2); + +void pascal error(int, long); +void pascal read_if(long, char *, int); +void pascal write_if(int, long, char *, int); +int pascal creat_if(char *); +int pascal open_if(char *); +void pascal close_if(int); +void pascal update_block(void); +void pascal init_cache(void); +int pascal find_cache(RECPOS); +int pascal new_cache(void); +void pascal load_cache(RECPOS); +void pascal get_cache(RECPOS); +void pascal retrieve_block(int, RECPOS); +int pascal prev_entry(int); +int pascal next_entry(int); +void pascal copy_entry(ENTRY *, ENTRY *); +int pascal scan_blk(int); +int pascal last_entry(void); +void pascal write_free( RECPOS, BLOCK *); +RECPOS pascal get_free(void); +int pascal find_block(ENTRY *, int *); +void pascal movedown(BLOCK *, int, int); +void pascal moveup(BLOCK *, int, int); +void pascal ins_block(BLOCK *, ENTRY *, int); +void pascal del_block(BLOCK *, int); +void pascal split(int, ENTRY *, ENTRY *); +void pascal ins_level(int, ENTRY *); +int pascal insert_ix(ENTRY *, IX_DESC *); +int pascal find_ix(ENTRY *, IX_DESC *, int); +int pascal combineblk(RECPOS, int); +void pascal replace_entry(ENTRY *); +void print_blk(BLOCK *); + + +/* file I/O for B-PLUS module */ + +void pascal error(j, l) + int j; + long l; + { + static char *msg[3] = {"ERROR - CANNOT OPEN/CLOSE FILE", + "ERROR WHILE READING FILE", + "ERROR WHILE WRITING FILE"}; + printf("\n %s - Record Number %ld\n", msg[j], l); + exit(1); + } /* error */ + + +void pascal read_if(start, buf, nwrt) + long start; + char *buf; + int nwrt; + { + long err; + err = start - lseek(pci->ixfile, start, SEEK_SET); + if (err == 0) err = nwrt - read(pci->ixfile, buf, nwrt); + if (err != 0) error(1, start); + } /* read_if */ + + +void pascal write_if(handle, start, buf, nwrt) + int handle; + long start; + char *buf; + int nwrt; + { + long err; + err = start - lseek(handle, start, SEEK_SET); + if (err == 0) err = nwrt - write(handle, buf, nwrt); + if (err != 0) error(2, start); + } /* write_if */ + + +int pascal creat_if(fn) + char *fn; + { + int ret; + ret = open(fn,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE); + if (ret < 0) error(0,0L); + return (ret); + } /* creat_if */ + + +int pascal open_if(fn) + char *fn; + { + int ret; + ret = open(fn,O_RDWR|O_BINARY); + if (ret < 1) error(0,0L); + return (ret); + } /* open_if */ + + +void pascal close_if(handle) + int handle; + { + if(close(handle) < 0) error(2,0L); + } /* close_if */ + + +int cdecl open_index(name, pix, dup) + char *name; + IX_DESC *pix; + int dup; + { + pci = pix; + pci->ixfile = open_if(name); + pci->duplicate = dup; + read_if(0L,(char *)&(pix->root), (sizeof(BLOCK) + sizeof(IX_DISK))); + if (!cache_init) + { + init_cache(); + cache_init = 1; + } + first_key(pix); + return ( IX_OK ); + } /* open_index */ + + +int cdecl close_index(pix) + IX_DESC *pix; + { + int i; + write_if(pix->ixfile, 0L,(char *)&(pix->root), + (sizeof(BLOCK) + sizeof(IX_DISK))); + for (i = 0; i < NUM_BUFS; i++) + if (BUFHANDLE(i) == pix->ixfile) + { + if (BUFDIRTY(i)) + { + write_if(BUFHANDLE(i), + BUFBLOCK(i).brec, + (char *) &BUFBLOCK(i), + sizeof(BLOCK)); + BUFDIRTY(i) = 0; + } + BUFBLOCK(i).brec = NULLREC; + } + close_if(pix->ixfile); + return( IX_OK ); + } /* close_index */ + + +int cdecl make_index(name, pix, dup) + char *name; + IX_DESC *pix; + int dup; + { + pci = pix; + pci->ixfile = creat_if(name); + pci->duplicate = dup; + pci->dx.nl = 1; + pci->dx.ff = NULLREC; + pci->level = 0; + CO(0) = -1; + CB(0) = 0L; + pci->root.brec = 0L; + pci->root.bend = 0; + pci->root.p0 = NULLREC; + write_if(pci->ixfile, 0L,(char *)&(pix->root), + (sizeof(BLOCK) + sizeof(IX_DISK))); + if (!cache_init) + { + init_cache(); + cache_init = 1; + } + first_key(pix); + return ( IX_OK ); + } /* make_index */ + + +/* cache I/O for BPLUS */ + +void pascal update_block() + { + if (block_ptr != &(pci->root)) + BUFDIRTY(cache_ptr) = 1; + } /* update_block */ + + +void pascal init_cache() + { + register int j; + for (j = 0; j < NUM_BUFS; j++) + { BUFDIRTY(j) = 0; + BUFCOUNT(j) = 0; + BUFBLOCK(j).brec = NULLREC; + } + } /* init_cache */ + + +int pascal find_cache(r) + RECPOS r; + { + register int j; + for (j = 0; j < NUM_BUFS; j++) + { + if((BUFBLOCK(j).brec == r) && (BUFHANDLE(j) == pci->ixfile)) + { cache_ptr = j; + return (1); + } } + return (-1); + } /* find_cache */ + + +int pascal new_cache() + { + register int i; + i = (cache_ptr + 1) % NUM_BUFS; + if (BUFDIRTY(i)) write_if(BUFHANDLE(i), + BUFBLOCK(i).brec, + (char *) &BUFBLOCK(i), + sizeof(BLOCK)); + BUFHANDLE(i) = pci->ixfile; + BUFDIRTY(i) = 0; + return (i); + } /* new_cache */ + + +void pascal load_cache(r) + RECPOS r; + { + cache_ptr = new_cache(); + read_if(r, (char *)&BUFBLOCK(cache_ptr), sizeof(BLOCK)); + } /* load_cache */ + + +void pascal get_cache(r) + RECPOS r; + { + if (find_cache(r) < 0) + load_cache(r); + block_ptr = &BUFBLOCK(cache_ptr); + } /* get_cache */ + + +void pascal retrieve_block(j, r) + int j; + RECPOS r; + { + if (j == 0) + block_ptr = &(pci->root); + else get_cache(r); + CB(j) = block_ptr->brec; + } /* retrieve_block */ + + +/* low level functions of BPLUS */ + +int pascal prev_entry(off) + int off; + { + if (off <= 0) + { + off = -1; + CO(pci->level) = off; + } + else + off = scan_blk(off); + return(off); + } /* prev_entry */ + + +int pascal next_entry(off) + int off; + { + if (off == -1) + off = 0; + else + { + if (off < block_ptr->bend) + off += ENT_SIZE(ENT_ADR(block_ptr,off)); + } + CO(pci->level) = off; + return (off); + } /* next_entry */ + + +void pascal copy_entry(to, from) + ENTRY *to; + ENTRY *from; + { + int me; + me = ENT_SIZE(from); + memmove(to, from, me); + } /* copy_entry */ + + +int pascal scan_blk(n) + int n; + { + register int off, last; + off = 0; + last = -1; + while (off < n ) + { last = off; + off += ENT_SIZE(ENT_ADR(block_ptr,off)); + } + CO(pci->level) = last; + return (last); + } /* scan_blk */ + + +int pascal last_entry() + { + return( scan_blk(block_ptr->bend) ); + } /* last_entry */ + + +/* maintain list of free index blocks */ + +void pascal write_free(r, pb) + RECPOS r; + BLOCK *pb; + { + pb->p0 = FREE_BLOCK; + pb->brec = pci->dx.ff; + write_if(pci->ixfile, r, (char *) pb, sizeof(BLOCK)); + pci->dx.ff = r; + } /* write_free */ + + +RECPOS pascal get_free() + { + RECPOS r, rt; + + r = pci->dx.ff; + if ( r != NULLREC ) + { read_if(r, (char *)&rt, sizeof( RECPOS )); + pci->dx.ff = rt; + } + else + r = filelength (pci->ixfile); + return (r); + } /* get_free */ + + +/* general BPLUS block level functions */ + +int pascal find_block(pe, poff) + ENTRY *pe; + int *poff; + { + register int pos, nextpos, ret; + pos = -1; + nextpos = 0; + ret = 1; + while ( nextpos < block_ptr->bend) + { + ret = strcmp((char *)(pe->key), + (char *)(ENT_ADR(block_ptr, nextpos)->key)); + if (ret <= 0) + { + if (ret == 0) pos = nextpos; + break; + } + pos = nextpos; + nextpos = next_entry(pos); + } + CO(pci->level) = pos; + *poff = pos; + return (ret); + } /* find_block */ + + +void pascal movedown(pb, off, n) + BLOCK *pb; + int off; + int n; + { + memmove(ENT_ADR(pb, off), + ENT_ADR(pb, off + n), + pb -> bend - (off + n)); + } /* movedown */ + + +void pascal moveup(pb, off, n) + BLOCK *pb; + int off; + int n; + { + memmove(ENT_ADR(pb, off + n), + ENT_ADR(pb, off), + pb->bend - off); + } /* moveup */ + + +void pascal ins_block(pb, pe, off) + BLOCK *pb; + ENTRY *pe; + int off; + { + int size; + size = ENT_SIZE(pe); + moveup(pb,off,size); + copy_entry(ENT_ADR(pb,off),pe); + pb->bend += size; + } /* ins_block */ + + +void pascal del_block(pb, off) + BLOCK *pb; + int off; + { + int ne; + ne = ENT_SIZE(ENT_ADR(pb, off)); + movedown(pb, off, ne); + pb->bend -= ne; + } /* del_block */ + + +/* position at start/end of index */ + +int cdecl first_key(pix) + IX_DESC *pix; + { + pci = pix; + block_ptr = &(pci->root); + CB(0) = 0L; + CO(0) = -1; + pci->level = 0; + while(block_ptr->p0 != NULLREC) + { + retrieve_block(++(pci->level), block_ptr->p0); + CO(pci->level) = -1; + } + return ( IX_OK ); + } /* first_key */ + + +int cdecl last_key(pix) + IX_DESC *pix; + { + long ads; + pci = pix; + block_ptr = &(pci->root); + CB(0) = 0L; + pci->level = 0; + if(last_entry() >= 0) + { + while ((ads = ENT_ADR(block_ptr,last_entry())->idxptr) != NULLREC) + retrieve_block(++(pci->level), ads); + } + CO(pci->level) = block_ptr->bend; + return ( IX_OK ); + } /* last_key */ + + +/* get next, previous entries */ + +int cdecl next_key(pe, pix) + ENTRY *pe; + IX_DESC *pix; + { + RECPOS address; + pci = pix; + retrieve_block(pci->level, CB(pci->level)); + if(CO(pci->level) == -1) address = block_ptr->p0; + else + { + if (CO(pci->level) == block_ptr->bend) address = NULLREC; + else address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + } + while (address != NULLREC) + { + retrieve_block(++(pci->level), address); + CO(pci->level) = -1; + address = block_ptr->p0; + } + next_entry(CO(pci->level)); + if (CO(pci->level) == block_ptr->bend) + { + do + { if(pci->level == 0) + { + last_key(pci); + return (EOIX); + } + --(pci->level); + retrieve_block(pci->level, CB(pci->level)); + next_entry(CO(pci->level)); + } while (CO(pci->level) == block_ptr->bend); + } + copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + return ( IX_OK ); + } /* next_key */ + + +int cdecl prev_key(pe, pix) + ENTRY *pe; + IX_DESC *pix; + { + RECPOS address; + pci = pix; + retrieve_block(pci->level, CB(pci->level)); + prev_entry(CO(pci->level)); + if (CO(pci->level) == -1) + address = block_ptr->p0; + else + address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + if (address != NULLREC) + { do + { + retrieve_block(++(pci->level), address); + address = ENT_ADR(block_ptr, last_entry())->idxptr; + } while (address != NULLREC); + } + if (CO(pci->level) == -1) + { do + { + if(pci->level == 0) + { + first_key(pci); + return (EOIX); + } + --(pci->level); + } while (CO(pci->level) == -1); + retrieve_block(pci->level, CB(pci->level)); + } + copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + return ( IX_OK ); + } /* prev_key */ + + +/* insert new entries into tree */ + +void pascal split(l, pe, e) + int l; + ENTRY *pe; + ENTRY *e; + { + int half, ins_pos, size; + ins_pos = CO(pci->level); + half = scan_blk(block_ptr->bend / 2 + sizeof(RECPOS)); + if (half == ins_pos) + *e = *pe; + else + { + copy_entry(e, ENT_ADR(block_ptr, half)); + size = ENT_SIZE(e); + movedown(block_ptr, half, size); + block_ptr->bend -= size; + } + spare_block = &BUFBLOCK(new_cache()); + memmove(spare_block->entries, + ENT_ADR(block_ptr,half), + block_ptr->bend - half); + spare_block->brec = get_free(); + spare_block->bend = block_ptr->bend - half; + spare_block->p0 = e->idxptr; + block_ptr->bend = half; + e->idxptr = spare_block->brec; + if (ins_pos < half) + ins_block(block_ptr,pe,ins_pos); + else if (ins_pos > half) + { + ins_pos -= ENT_SIZE(e); + ins_block(spare_block,pe,ins_pos - half); + CB(l) = e->idxptr; + CO(l) = CO(l) - half; + } + write_if(pci->ixfile, spare_block->brec, + (char *) spare_block, sizeof(BLOCK)); + } /* split */ + + +void pascal ins_level(l, e) + int l; + ENTRY *e; + { + int i; + if ( l < 0) + { for (i = 1; i < MAX_LEVELS; i++) + { CO(MAX_LEVELS - i) = CO(MAX_LEVELS - i - 1); + CB(MAX_LEVELS - i) = CB(MAX_LEVELS - i - 1); + } + memmove(spare_block, &(pci->root), sizeof(BLOCK)); + spare_block->brec = get_free(); + write_if(pci->ixfile, spare_block->brec, + (char *) spare_block, sizeof(BLOCK)); + pci->root.p0 = spare_block->brec; + copy_entry((ENTRY *) (pci->root.entries), e); + pci->root.bend = ENT_SIZE(e); + CO(0) = 0; + pci->level = 0; + (pci->dx.nl)++; + } + else ins_block(block_ptr,e,CO(l)); + } /* ins_level */ + + +int pascal insert_ix(pe, pix) + ENTRY *pe; + IX_DESC *pix; + { + ENTRY e, ee; + int h; + h = 0; + pci = pix; + ee = *pe; + do + { + if(CO(pci->level) >= 0) + CO(pci->level) += + ENT_SIZE(ENT_ADR(block_ptr, CO(pci->level))); + else + CO(pci->level) = 0; + update_block(); + if( (block_ptr->bend + ENT_SIZE(&ee)) <= split_size) + { + ins_level(pci->level, &ee); + break; + } + else + { + h = 1; + split(pci->level,&ee, &e); + ee = e; + pci->level--; + if (pci->level < 0) + { + ins_level(pci->level, &e); + break; + } + retrieve_block(pci->level, CB(pci->level)); + } + } + while (1); + if (h) find_ix(pe, pix, 0); + return ( IX_OK ); + } /* insert_ix */ + + +/* BPLUS find and add key functions */ + +int pascal find_ix(pe, pix, find) + ENTRY *pe; + IX_DESC *pix; + int find; + { + int level, off, ret; + RECPOS ads; + pci = pix; + ads = 0L; + level = ret = 0; + while (ads != NULLREC) + { pci->level = level; + retrieve_block(level, ads); + if (find_block(pe, &off) == 0) ret = 1; + if (ret && find) break; + if (off == -1) + ads = block_ptr->p0; + else + ads = ENT_ADR(block_ptr, off)->idxptr; + CO(level++) = off; + } + return ( ret ); + } /* find_ix */ + + +int cdecl find_key(pe, pix) + ENTRY *pe; + IX_DESC *pix; + { + int ret; + ret = find_ix(pe, pix, 1); + if ( ret ) copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + return ( ret ); + } /* find_key */ + + +int cdecl add_key(pe, pix) + ENTRY *pe; + IX_DESC *pix; + { + int ret; + ret = find_ix(pe, pix, 0); + if ( ret && (pci->duplicate == 0)) return ( IX_FAIL ); + pe->idxptr = NULLREC; + return (insert_ix(pe, pix)); + } /* add_key */ + + +int cdecl locate_key(pe, pix) + ENTRY *pe; + IX_DESC *pix; + { + int ret; + ret = find_ix(pe, pix, 1); + if (ret) copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + else if (next_key(pe,pix) == EOIX) ret = EOIX; + return ( ret ); + } /* locate_key */ + + +int cdecl find_exact(pe, pix) + ENTRY *pe; + IX_DESC * pix; + { + int ret; + ENTRY e; + copy_entry(&e, pe); + ret = find_key(&e, pix); + if ( ret && pci->duplicate) + { + do + { + ret = (e.recptr == pe->recptr); + if( !ret ) ret = next_key(&e, pci); + if (ret) ret = (strcmp(e.key, pe->key) == 0); + if ( !ret ) return ( 0 ); + } while ( !ret ); + } + copy_entry(pe, &e); + return ( ret ); + } /* find_exact */ + + +/* BPLUS delete key functions */ + +int cdecl delete_key(pe, pix) + ENTRY *pe; + IX_DESC *pix; + { + ENTRY e; + RECPOS ads; + int h, leveli, levelf; + if (!find_exact(pe, pix)) return( IX_FAIL ); + h = 1; + if ((ads = pe->idxptr) != NULLREC) + { + leveli = pci->level; + do + { + retrieve_block(++(pci->level), ads); + CO(pci->level) = -1; + } + while ((ads = block_ptr->p0) != NULLREC); + CO(pci->level) = 0; + copy_entry(&e, ENT_ADR(block_ptr, CO(pci->level))); + levelf = pci->level; + pci->level = leveli; + replace_entry(&e); + pci->level = levelf; + } + while ( h ) + { + retrieve_block(pci->level, CB(pci->level)); + del_block(block_ptr, CO(pci->level)); + update_block(); + if ( (pci->level == 0) && (block_ptr->bend == 0)) + /* tree was reduced in height */ + { + if (pci->root.p0 != NULLREC) + { + retrieve_block(++pci->level, pci->root.p0); + memmove(&(pci->root), block_ptr, sizeof(BLOCK)); + (pci->dx.nl)--; + write_free(block_ptr->brec, block_ptr); + BUFDIRTY(cache_ptr) = 0; + BUFHANDLE(cache_ptr) = 0; + } + break; + } + h = (block_ptr->bend < comb_size) && (pci->level > 0); + if ( h ) + h = combineblk(CB(pci->level), block_ptr->bend); + } + find_ix(pe,pix,0); + return( IX_OK ); + } /* delete_key */ + + +int pascal combineblk(ads, size) + RECPOS ads; + int size; + { + ENTRY e; + RECPOS address; + int esize, off, ret, saveoff, ibuff; + ret = 0; + saveoff = CO(--(pci->level)); + retrieve_block(pci->level, CB(pci->level)); + if ((off = next_entry( saveoff )) < block_ptr->bend) + /* combine with page on right */ + { + if ( (ENT_SIZE(ENT_ADR(block_ptr, off)) + size) < split_size) + { + copy_entry(&e, ENT_ADR(block_ptr, off)); + address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + retrieve_block(++pci->level, address); + ibuff = cache_ptr; + spare_block = block_ptr; + retrieve_block(pci->level, ads); + esize = ENT_SIZE(&e); + if(((block_ptr->bend + spare_block->bend + esize) >= split_size) + && (spare_block->bend <= block_ptr->bend + esize)) + return( ret ); + e.idxptr = spare_block->p0; + ins_block(block_ptr, &e, block_ptr->bend); + update_block(); + if ((block_ptr->bend + spare_block->bend) < split_size) + /* combine the blocks */ + { + memmove(ENT_ADR(block_ptr, block_ptr->bend), + ENT_ADR(spare_block, 0), + spare_block->bend); + block_ptr->bend += spare_block->bend; + write_free(spare_block->brec, spare_block); + BUFDIRTY(ibuff) = 0; + BUFHANDLE(ibuff) = 0; + --pci->level; + ret = 1; + } + else + /* move an entry up to replace the one moved */ + { + copy_entry(&e, ENT_ADR(spare_block, 0)); + esize = ENT_SIZE(&e); + movedown(spare_block, 0, esize); + spare_block->bend -= esize; + spare_block->p0 = e.idxptr; + BUFDIRTY(ibuff) = 1; + --(pci->level); + replace_entry(&e); + } + } + } + else + /* move from page on left */ + { + if ( (ENT_SIZE(ENT_ADR(block_ptr, CO(pci->level))) + size) + < split_size) + { + copy_entry(&e, ENT_ADR(block_ptr, saveoff)); + off = prev_entry(saveoff); + if (CO(pci->level) == -1) address = block_ptr->p0; + else address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + retrieve_block(++pci->level, address); + off = last_entry(); + ibuff = cache_ptr; + spare_block = block_ptr; + retrieve_block(pci->level, ads); + esize = ENT_SIZE(&e); + if(((block_ptr->bend + spare_block->bend + esize) >= split_size) + && (spare_block->bend <= block_ptr->bend + esize)) + return( ret ); + BUFDIRTY(ibuff) = 1; + CO(pci->level) = 0; + e.idxptr = block_ptr->p0; + ins_block(block_ptr, &e, 0); + if ((block_ptr->bend + spare_block->bend) < split_size) + /* combine the blocks */ + { + memmove(ENT_ADR(spare_block, spare_block->bend), + ENT_ADR(block_ptr, 0), + block_ptr->bend); + spare_block->bend += block_ptr->bend; + write_free(block_ptr->brec, block_ptr); + BUFDIRTY(cache_ptr) = 0; + BUFHANDLE(cache_ptr) = 0; + CO(--(pci->level)) = saveoff; + ret = 1; + } + else + /* move an entry up to replace the one moved */ + { + block_ptr->p0 = ENT_ADR(spare_block,off)->idxptr; + copy_entry(&e, ENT_ADR(spare_block, off)); + spare_block->bend = off; + update_block(); + CO(--(pci->level)) = saveoff; + replace_entry(&e); + } + } + } + return ( ret ); + } /* combineblk */ + + +void pascal replace_entry(pe) + ENTRY *pe; + { + retrieve_block(pci->level, CB(pci->level)); + pe->idxptr = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + del_block(block_ptr, CO(pci->level)); + prev_entry(CO(pci->level)); + insert_ix(pe, pci); + } /* replace_entry */ + + \ No newline at end of file diff --git a/bplus/BPLUS.DOC b/bplus/BPLUS.DOC new file mode 100644 index 0000000..687dc05 --- /dev/null +++ b/bplus/BPLUS.DOC @@ -0,0 +1,582 @@ + + + + + + + THE B-PLUS PROGRAM + A B-TREE INDEXING FILE MODULE + FOR C PROGRAMMERS + by + Hunter and Associates + + + + B-PLUS is a versatile, carefully designed module for C + programmers who need a fast, efficient program for indexing + data files. B-PLUS allows data records to be retrieved based + on a key value without regard to their position in the data + file. The data records can also be accessed in sequential + order in either a forward and reverse direction. + + The B-PLUS Program Module is based on the famous and + widely used b-tree algorithm and has a number of useful + extensions which are not found in many programs of this type. + Some of its features are the following: + + - Variable length keys are allowed + + - File size limited only by DOS or by disk space + + - All functions are non-recursive so very little stack + space is required + + - The most recently used key values are stored in a + cache buffer in main memory for fast access + + - Duplicate keys are allowed + + Version 1.1A of the B-PLUS program has been tested + for Microsoft C Compilers, Versions 4.0, 5.0, 5.1 and the + Borland Turbo C Compiler Version 1.5. The compiled object + file is less than 10K bytes in length for these compilers. + See the instructions at the end of this user's guide for a + special note regarding Microsoft's older C Version 4.0. + + Version 1.1A has several new features that were not in + Version 1.0. The next_key and prev_key routines can now be + called immediately after adding or deleting an index key. It + is no longer necessary to "reset" the index file with a + find_key or locate_key function call after adding or deleting + keys. All known bugs have been corrected in Version 1.1A. + + + + LICENSE AND REGISTRATION + + B-PLUS is distributed as a "share ware" program. Please + help us get it known by giving unmodified copies of the + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + program and documentation to other programmers who may find + B-PLUS useful. + + B-PLUS is copyright (C) 1987 by Hunter and Associates. + It is not public domain or free software. Non-registered + users are granted a limited license to use B-PLUS on a trial + basis for determining whether or not it is suitable for their + needs. Registration permits the use of B-PLUS on one CPU and + allows the use of the compiled B-PLUS modules in programs for + general sale and/or distribution. + + The registration fee is $25 or $35. Users who pay the + $35 fee will be sent a disk containing a fully commented + listing of the latest source code, the user documentation, + and a number of useful sample programs. Users who pay the + $25 fee are not sent a new disk but are included in the + mailing list for announcements about both current and future + products. Your prompt registration of your copy of the B- + PLUS program is appreciated. + + A trial disk with supporting documentation is available + directly from Hunter and Associates for $10. + + Register your usage of B-PLUS by sending the registra- + tion fee to: + + Hunter and Associates + 7900 Edgewater Drive + Wilsonville, OR 97070 + Telephone: (503) 694-1449 + + Your comments regarding the B-PLUS program or any suggestions + you have for extensions or for other programs that would be + useful to you are welcomed. + + Hunter and Associates makes no warranties whatsoever + regarding the B-PLUS computer programs or the supporting + documentation. + + + USING B-PLUS IN YOUR PROGRAMS + + The B-PLUS File Indexing Module contains twelve + functions that handle the retrieval of data records by key + value. The keys that are used to locate records are null + terminated strings. The data structures and constants that + are used are defined in the header file bplus.h. + + If the data record field that you want to use as a key + contains numeric data, you can use one of the library + + Page 2 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + conversion routines (fcvt, evct, sprintf) to convert the data + to string format. + + The connection between a key and its reference is + formalized as a structure of type ENTRY. This structure + contains three elements: + + typedef struct + { + RECPOS idxptr; /* long pointer to next index + level */ + RECPOS recptr; /* long pointer to the file + position of data record */ + char key[MAXKEY]; /* with this key value */ + } ENTRY; + + The application program uses only the recptr and key[] + fields. The idxptr is used and maintained by the B-PLUS + modules. + + A variable of type IX_DESC is declared for each open + index file. See the header file bplus.h if you are + interested in the elements of this structure. ENTRY and + IX_DESC are the only two data types that are normally used by + application programs. + + Here is a sample program stub which calls the open_index + and find_index subroutines. + + + Example: + + #include "bplus.h" + main() + { + ENTRY e; + IX_DESC names; + + /* open index file called NAMES.IDX */ + + open_index("NAMES.IDX", &names, 0); + + /* find an index record for John Smith */ + + strcpy(e.key, "SMITH JOHN"); + if(find_key(&e, &names)) + printf("Data record address is %ld", e.recptr); + else + printf("Cannot find record for that key"); + } + + Page 3 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + Each of the twelve subroutines is now described. + + int cdecl open_index(name, pix, dup); + + char *name; File path name + IX_DESC *pix; Pointer to index file variable + int dup; 0 - no duplicate keys allowed + 1 - allow duplicate keys + + Description: The open_index function is used to open + and initialize an existing index file specified by name + and prepares the file for subsequent reading or writing. + The file structure variable pix is defined in the + application program. Duplicate keys are allowed or not + allowed depending on whether dup has the value of 0 or + 1. The open_index function returns the value IX_OK (1) + if the file is opened successfully. If the file cannot + be opened, an error message is displayed and the program + is aborted. + + + + int cdecl make_index(name, pix, dup); + + char *name; File path name + IX_DESC *pix; Pointer to index file variable + int dup; 0 - no duplicate keys allowed + 1 - allow duplicate keys + + Description: The make_index function is used to create + and initialize a new index file specified by name and to + prepare the file for subsequent reading or writing. If + a file of this name already exists, its contents are + destroyed when the new file is created. The file + structure variable pix is defined in the application + program. Duplicate keys are allowed or not allowed + depending on whether dup has the value of 0 or 1. The + make_index function returns the value IX_OK (1) if the + file is created successfully. If the file cannot be + created, an error message is displayed and the program + is aborted. + + + + int cdecl close_index(pix); + + IX_DESC *pix; Pointer to index file variable + + Description: The close_index file function clears the + internal cache buffer and closes the specified index + + Page 4 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + file. It is very important that each index file be + closed. Otherwise data that is stored in the internal + + cache buffer may be lost and the index file may not be + properly updated. The close_index function returns the + value IX_OK (1) if the file is successfully closed. + + + + int cdecl find_key(pe, pix); + + ENTRY *pe; Pointer to variable of type ENTRY + IX_DESC *pix; Pointer to index file variable + + Description: The find_key function searches the index + file for the key value contained in pe.key. If an exact + match is found, the value IX_OK (1) is returned and the + location of the data record with this key value is + stored in pe.recptr. If an exact match is not found, + the value IX_FAIL (0) is returned and pe.recptr is + undefined. If the index file contains duplicate keys, + the first key is always found. + + + + int cdecl locate_key(pe, pix); + + ENTRY *pe; Pointer to variable of type ENTRY + IX_DESC *pix; Pointer to index file variable + + Description: The locate key function searches the index + file for the first key value which is equal to or + greater than that stored in pe.key. The location of the + data record which is equal to or greater than pe.key is + stored in pe.recptr. This function can be used to + locate an entry in the index file when only part of the + key value is known. If the index file contains + duplicate keys, locate_key will locate the first key. + The following values are returned by locate_key: + + IX_OK - the value (1) is returned if an exact + match is found + + IX_FAIL - the value (0) is returned if an exact + match is not found + + EOIX - the value (-2) is returned for end of + index if the search key is greater than + all keys in the index file and pe.recptr + is undefined. + + Page 5 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + + + int cdecl add_key(pe, pix); + + ENTRY *pe; Pointer to variable of type ENTRY + IX_DESC *pix; Pointer to index file variable + + Description: The add_key function adds new entries to + the index file. The calling program stores the key + value in pe.key and the data record address in + pe.recptr. Add_key first looks to see if an entry with + this key already exists in the index file. If no entry + with this key exists, the new entry is added. If an + entry with this key already exists, the new entry is + added only if duplicate keys are allowed (as defined by + the open_index function). If the entry is successfully + added, IX_OK (1) is returned; otherwise IX_FAIL (0) is + returned. + + + + int cdecl delete_key(pe, pix); + + ENTRY *pe; Pointer to variable of type ENTRY + IX_DESC *pix; Pointer to index file variable + + Description: The delete_key function deletes entries + in the index file. The key to be deleted is stored in + pe.key. If duplicate records are allowed, the + corresponding data record address must also be stored in + pe.recptr. In this case, delete key needs the record + number to distinguish entries. If there are not + duplicate entries, this field is ignored. If the entry + is successfully deleted, IX_OK (1) is returned; + otherwise IX_FAIL (0) is returned. The space that was + occupied by the entry is marked as free for reused by + B_PLUS. + + + + int cdecl first_key(pix); + + IX_DESC *pix; Pointer to index file variable + + Description: The first_key function positions the index + file pointer to the beginning of the index file. The + function next_key can then be used to list the file in + key order. The first_key function returns the value + IX_OK (1). + + + Page 6 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + int cdecl last_key(pix); + + IX_DESC *pix; Pointer to index file variable + + Description: The last_key function positions the index + file pointer at the end of the index file. The function + previous_key can then be used to list the file in + reverse key order. The last_key function returns the + value IX_OK (1). + + + + int cdecl next_key(pe, pix); + + ENTRY *pe; Pointer to variable of type ENTRY + IX_DESC *pix; Pointer to index file variable + + Description: The next_key function returns the next + entry in the index file. After deleting or adding keys, + next_key returns the key immediately following the + addition or deletion. Next_key can be used to locate + the desired data record when duplicate keys are allowed. + Next_key is used to process files sequential. Next_key + returns the value IX_OK (1) if the next key is present + and the value EOIX (-2) when the file pointer is at the + end of the index file. The following program processes + an indexed file sequentially: + + #include "bplus.h" + main() + { + ENTRY e; + IX_DESC names; + + /* open the index file */ + open_index("names.idx", &names); + + /* now process the file sequentially */ + first_key(&names); + ret = next_key(&e, &names); + while (ret == IX_OK) + { + /* the data record location is e.recptr */ + /* the program would retrieve and process it */ + ret = next_key(&e, &names); + } + + /* remember to always close open files */ + close_index(&names); + } + + Page 7 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + int cdecl prev_key(pe, pix); + + ENTRY *pe; Pointer to variable of type ENTRY + IX_DESC *pix; Pointer to index file variable + + Description: The prev_key function returns the previous + entry in the index file. After deleting or adding keys, + prev_key returns the key immediately preceeding the + addition or deletion. Prev_key can be used to process + files sequentially in reverse order. Prev_key returns + the value IX_OK (1) if there is a previous key and the + value EOIX (-2) when the file pointer is at the + beginning of the index file. + + + + int cdecl find_exact(pe, pix); + + ENTRY *pe; Pointer to variable of type ENTRY + IX_DESC *pix; Pointer to index file variable + + Description: The find_exact function searches the index + file for the key value contained in pe.key and the data + record position stored in pe.recptr. If an exact match + is found for both of these values, the value IX_OK (1) + is returned, and the internal index file pointer is set + to that position in the index file. If an exact match + is not found, the value IX_FAIL (0) is returned. + + + + TAILORING OR CHANGING B-PLUS + + Most applications can use the B-PLUS program as it is + distributed by Hunter and Associates without any changes. It + allows multiple, large data files to be indexed in a fast, + efficient manner. However, a description of the values that + can be changed to tailor B-PLUS are given in this section. + + An index tree becomes full when no more entries can be + added to the tree. This is the case when adding another + entry to the tree would cause the tree to grow larger than + its maximum allowed height. This height depends on the size + of the index blocks and the average size of the keys used by + the data files. The minimum capacity of a b-tree index is + given by the following formula: + + C = (B / E + 1) * (B / (2 * E) + 1) ** (H - 1) + + where C is the number of entries in the index file, B is the + + Page 8 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + block size in bytes, E is the average size of an ENTRY in + bytes, and H is the maximum tree height. + + The maximum key size is defined by MAXKEY and is set at + 100. The block size is 1024 bytes as defined by IXB_SIZE. + Ten bytes are used by pointers so 1014 bytes are used by + entries. The size of an ENTRY is 9 + the key length. + + Thus, if the average key length is 11, an average ENTRY + is 20 bytes long and the minimum number of entries that can + be contained in a tree of height 4 is: + + C = (1014 / 20 + 1) * (1014 / 40 + 1) ** 3 + = 945,072 + + If the average ENTRY is 40 bytes long, the minimum number of + entries that can be contained in a tree of height 4 is + 67,384. The corresponding values for a tree of height 3 are + 35,896 and 4927, respectively. + + The maximum tree height is determined by MAX_LEVELS and + is set to eight. Very little memory space is used by + allowing the maximum tree height to be this large. B-PLUS + increases the height of the tree dynamically as required by + the number of records in the data file. + + If your application does not use long keys and your + files are not huge, IXB_SIZE can be changed to 512 bytes with + only a slight degradation in performance. + + The root of an open index file is always memory resident + as defined by the variable of type IX_DESC. A dynamic pool + of cache buffers is used for other index blocks of the tree. + The number of blocks in the pool is defined by NUM_BUFS with + a default value of 8. Each memory block is sizeof(IXB_SIZE) + + 8 bytes in length so approximately 8K of memory is used for + cache storage of index blocks. If the number of index files + that are open simultaneously is larger than 4, you may want + to increase NUM_BUFS. If the usage of memory is critical, + the number of buffers can be decreased. However, NUM_BUFS + must be at least 2. In general, the speed of file access can + be expected to improve if the number of buffers is increased + since more of the index file is memory resident. + + Because some indices are always memory resident, and + because the DOS Operating System requires it, it is very + important that all open index files be closed before an + application program terminates. + + As stated earlier, the B-PLUS program has been tested + + Page 9 + + + HUNTER AND ASSOCIATES B-PLUS FILE INDEXING PROGRAM + ------------------------------------------------------------- + + + using Microsoft's Optimizing C Compilers, Versions 4, 4.5 and + 5.0, and Borland's Turbo C, Version 1.0. However, standard K + & R programming guidelines are followed so B-PLUS should be + able to be used with other C Compilers with little + modification. Since B-PLUS is non-recursive, the usage of + stack space does not change dynamically. It is recommend + that the B-PLUS program be complied without stack checking. + For Microsoft C, the /Ox option can be used to maximize speed + and minimize code size. For Turbo C, B-PLUS can be complied + with maximum optimization to minimize the object size and + improve performance. + + + ACKNOWLEDGMENTS AND REFERENCES + + The following reference materials were used and helpful + in writing the B-PLUS program: + + Wirth, Niklaus: + Algorithms + Data Structures = Programs + Prentice Hall (1976) + + Hunt, William James: + The C Toolbox + (Serious C Programming for the IBM PC) + Addison-Wesley (1985) + + + Wirth's book is a standard reference source for binary + trees and data structures. Hunt's C Toolbox contains useful + C programming concepts with carefully constructed programming + examples. + + + USING THE BPLUS ROUTINES + + The BPLUS.C routines must be compiled and the object + file (BPLUS.OBJ) loaded with programs that use the B_PLUS + toolkit. Several sample C programs have been included which + illustrate how to use the BPLUS Toolkit. These programs + should be compiled and run to make sure your copy of the + program is correct. + + + A SPECIAL NOTE REGARDING MICROSOFT C 4.0 COMPILER + + The Microsoft C library routines are different for + Version 4.0 and for Version 5.0 and Quick C. In particular, + the memmove routine must be changed to the memcpy routine in + Version 4.0. A macro is included in BPLUS.C which makes this + substitution. Remove the comments delimiters for this version. + + Page 10 +  \ No newline at end of file diff --git a/bplus/BPLUS.H b/bplus/BPLUS.H new file mode 100644 index 0000000..20a86f7 --- /dev/null +++ b/bplus/BPLUS.H @@ -0,0 +1,71 @@ + +/* bplus.h - data structures and constants */ + + +#define IX_OK 1 +#define IX_FAIL 0 +#define EOIX (-2) +#define MAXKEY 100 +#define NUM_BUFS 8 +#define MAX_LEVELS 8 +#define IXB_SIZE 1024 +#define IXB_SPACE (IXB_SIZE - sizeof(int) - sizeof(long) * 2) + +typedef long RECPOS; + +typedef struct /* entry structure in index */ + { RECPOS idxptr; /* points to lower index level */ + RECPOS recptr; /* points to data record */ + char key[MAXKEY]; /* start of record key */ + } ENTRY; + +typedef struct /* index record format */ + { RECPOS brec; /* position in index file */ + /* or location of next free block */ + int bend; /* first unused block location */ + RECPOS p0; /* points to next level */ + char entries[IXB_SPACE]; /* here are the key entries */ + } BLOCK; + +typedef struct /* disk file info */ + { RECPOS ff; /* location of first free block */ + int nl; /* number of index levels */ + } IX_DISK; + +typedef struct /* memory buffer pool of indx blks */ + { int dirty; /* true if changed */ + int handle; /* index file handle */ + int count; /* number of times referenced */ + BLOCK mb; + } MEMBLOCK; + +typedef struct + { MEMBLOCK cache [ NUM_BUFS ]; + } IX_BUFFER; + +typedef struct /* in-memory index descriptor */ + { int ixfile; + int level; /* level in btree */ + int duplicate; /* no duplicate keys if 0 */ + struct + { RECPOS cblock; /* position in index file */ + int coffset; /* current offset within block */ + } pos [ MAX_LEVELS ]; + BLOCK root; /* root index record */ + IX_DISK dx; + } IX_DESC; + +int cdecl open_index(char *,IX_DESC *, int); +int cdecl close_index(IX_DESC *); +int cdecl make_index(char *,IX_DESC *, int); +int cdecl first_key(IX_DESC *); +int cdecl last_key(IX_DESC *); +int cdecl next_key(ENTRY *, IX_DESC *); +int cdecl prev_key(ENTRY *, IX_DESC *); +int cdecl find_key(ENTRY *, IX_DESC *); +int cdecl add_key(ENTRY *, IX_DESC *); +int cdecl locate_key(ENTRY *, IX_DESC *); +int cdecl delete_key(ENTRY *, IX_DESC *); +int cdecl find_exact(ENTRY *, IX_DESC *); + + \ No newline at end of file diff --git a/bplus/CPLUS.C b/bplus/CPLUS.C new file mode 100644 index 0000000..50d349e --- /dev/null +++ b/bplus/CPLUS.C @@ -0,0 +1,1001 @@ +/********************************************************************/ +/* */ +/* BPLUS file indexing program - Version 1.1 */ +/* */ +/* A "shareware program" */ +/* */ +/* */ +/* Copyright (C) 1987 by */ +/* */ +/* Hunter and Associates */ +/* 7050 NW Zinfandel Lane */ +/* Corvallis, Oregon 97330 */ +/* (503) 745 - 7186 */ +/* */ +/********************************************************************/ + + +#include +#include +#include +#include /* delete this line for Turbo C */ +#include +#include +#include "bplus.h" + + +/* macros, constants, data types */ + +#define NULLREC (-1L) /* special value for RECPOS variable */ +#define FREE_BLOCK (-2) /* designates a free block in index file */ + /* the address of an entry in a block */ +#define ENT_ADR(pb,off) ((ENTRY*)((char*)((pb)->entries) + off)) + /* the size of an entry */ +#define ENT_SIZE(pe) strlen((pe)->key) + 1 + 2 * sizeof(RECPOS) + /* the cache changed indicator */ +#define BUFDIRTY(j) (mci->cache[j].dirty) + /* the index file handle for memblock j */ +#define BUFHANDLE(j) (mci->cache[j].handle) + /* memory cache block j */ +#define BUFBLOCK(j) (mci->cache[j].mb) + /* number of times cache blk j is referenced */ +#define BUFCOUNT(j) (mci->cache[j].count) + /* address of current block for level j */ +#define CB(j) (pci->pos[j].cblock) + /* offset of current block for level j */ +#define CO(j) (pci->pos[j].coffset) + + +/* declare some global variables */ + +IX_DESC *pci; /* pointer to index descriptor */ +IX_BUFFER bt_buffer; /* memory cache for index blocks */ +IX_BUFFER *mci = &bt_buffer; /* pointer to cache index blocks */ +BLOCK *block_ptr; /* pointer to index record block */ +BLOCK *spare_block; /* pointer to spare index block */ +int cache_ptr = 0; /* index to cache memory pool */ +int cache_init = 0; /* 1 when cache is initilized */ +int split_size = IXB_SPACE; /* split block when greater than */ +int comb_size = (IXB_SPACE/2); /* combine blocks when less than */ + +/* #define memmove memcpy */ /* Use this macro for MicroSoft C 4.0 */ + +/* list all function prototypes */ +void pascal error(int, long); +void pascal read_if(long, char *, int); +void pascal write_if(int, long, char *, int); +int pascal creat_if(char *); +int pascal open_if(char *); +void pascal close_if(int); +void pascal update_block(void); +void pascal init_cache(void); +int pascal find_cache(RECPOS); +int pascal new_cache(void); +void pascal load_cache(RECPOS); +void pascal get_cache(RECPOS); +void pascal retrieve_block(int, RECPOS); +int pascal prev_entry(int); +int pascal next_entry(int); +void pascal copy_entry(ENTRY *, ENTRY *); +int pascal scan_blk(int); +int pascal last_entry(void); +void pascal write_free( RECPOS, BLOCK *); +RECPOS pascal get_free(void); +int pascal find_block(ENTRY *, int *); +void pascal movedown(BLOCK *, int, int); +void pascal moveup(BLOCK *, int, int); +void pascal ins_block(BLOCK *, ENTRY *, int); +void pascal del_block(BLOCK *, int); +void pascal split(int, ENTRY *, ENTRY *); +void pascal ins_level(int, ENTRY *); +int pascal insert_ix(ENTRY *, IX_DESC *); +int pascal find_ix(ENTRY *, IX_DESC *, int); +int pascal combineblk(RECPOS, int); +void pascal replace_entry(ENTRY *); +void print_blk(BLOCK *); + + +/* file I/O for B-PLUS module */ + +void pascal error(j, l) /* print file error messages */ + int j; /* error number */ + long l; /* current file position */ + { + static char *msg[3] = {"ERROR - CANNOT OPEN/CLOSE FILE", + "ERROR WHILE READING FILE", + "ERROR WHILE WRITING FILE"}; + printf("\n %s - Record Number %ld\n", msg[j], l); + exit(1); /* delete this line to not halt program */ + /* and call your error handlng routine */ + } /* error */ + + +void pascal read_if(start, buf, nwrt) /* read pci index file */ + long start; /* file read position */ + char *buf; /* data holding buffer */ + int nwrt; /* number bytes to read */ + { + long err; + /* seek to read position in current index file */ + err = start - lseek(pci->ixfile, start, SEEK_SET); + /* if no error read an index file block */ + if (err == 0) err = nwrt - read(pci->ixfile, buf, nwrt); + /* call error routine if number bytes read != nwrt */ + if (err != 0) error(1, start); + } /* read_if */ + + +void pascal write_if(handle, start, buf, nwrt) /* write index record */ + int handle; /* write to this file handle */ + long start; /* write to this position in file */ + char *buf; /* write data from this buffer */ + int nwrt; /* write this many bytes of data */ + { + long err; + /* seek to file write position */ + err = start - lseek(handle, start, SEEK_SET); + /* if no error write index block block */ + if (err == 0) err = nwrt - write(handle, buf, nwrt); + /* call error routine if number bytes written != nwrt */ + if (err != 0) error(2, start); + } /* write_if */ + + +int pascal creat_if(fn) /* make a new index file */ + char *fn; /* name and path of file */ + { + int ret; + ret = open(fn,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE); + if (ret < 0) error(0,0L); /* there was an error if ret < 0 */ + return (ret); + } /* creat_if */ + + +int pascal open_if(fn) /* open an existing index file */ + char *fn; /* path and name of index file */ + { + int ret; + ret = open(fn,O_RDWR|O_BINARY); + if (ret < 1) error(0,0L); /* there was an error is ret < 1 */ + return (ret); + } /* open_if */ + + +void pascal close_if(handle) /* close an open index file */ + int handle; /* with this file handle */ + { + if(close(handle) < 0) error(2,0L); + } /* close_if */ + + +int cdecl open_index(name, pix, dup) /* open and initilize index file */ + char *name; /* path and name of index file */ + IX_DESC *pix; /* pointer to index descriptor */ + int dup; /* allow duplicate keys if != 0 */ + { + pci = pix; /* pci is global index descriptor */ + pci->ixfile = open_if(name); /* file handle */ + pci->duplicate = dup; /* set duplicate keys flag */ + /* read root descriptor for index */ + read_if(0L,(char *)&(pix->root), (sizeof(BLOCK) + sizeof(IX_DISK))); + if (!cache_init) /* if cache not initilized */ + { + init_cache(); /* initilize cache memory */ + cache_init = 1; /* but only once */ + } + first_key(pix); /* position to first index key */ + return ( IX_OK ); + } /* open_index */ + + +int cdecl close_index(pix) /* close an open index file */ + IX_DESC *pix; + { + int i; + /* write out the root block for the index descriptor */ + write_if(pix->ixfile, 0L,(char *)&(pix->root), + (sizeof(BLOCK) + sizeof(IX_DISK))); + /* save all memory blocks for index that have been changed */ + for (i = 0; i < NUM_BUFS; i++) /* check all of cache */ + if (BUFHANDLE(i) == pix->ixfile) + { + if (BUFDIRTY(i)) + { + write_if(BUFHANDLE(i), /* if changed, write to disk */ + BUFBLOCK(i).brec, + (char *) &BUFBLOCK(i), + sizeof(BLOCK)); + BUFDIRTY(i) = 0; + } + BUFBLOCK(i).brec = NULLREC; /* same handle can be used again */ + } + close_if(pix->ixfile); /* close the index file */ + return( IX_OK ); + } /* close_index */ + + +int cdecl make_index(name, pix, dup) /* create a new index file */ + char *name; /* pointer to path and file name */ + IX_DESC *pix; /* pointer to index descriptor */ + int dup; /* duplicate keys allow is != 0 */ + { + pci = pix; /* set global pci to this index descriptor */ + pci->ixfile = creat_if(name); + pci->duplicate = dup; + pci->dx.nl = 1; /* the only block is the root */ + pci->dx.ff = NULLREC; /* there are no free index blocks */ + pci->level = 0; /* the root is level 0 */ + CO(0) = -1; /* the current block offset is -1 */ + CB(0) = 0L; /* the current block address 0L */ + pci->root.brec = 0L; /* root block address is 0L */ + pci->root.bend = 0; /* no entries yet so block end is 0 */ + pci->root.p0 = NULLREC; /* p0 points to next index level */ + + /* write the root block of the index descriptor */ + write_if(pci->ixfile, 0L,(char *)&(pix->root), + (sizeof(BLOCK) + sizeof(IX_DISK))); + if (!cache_init) + { /* initiate memory cache but only once */ + init_cache(); + cache_init = 1; + } + first_key(pix); /* initialize to first key in index */ + return ( IX_OK ); + } /* make_index */ + + +/* cache I/O for BPLUS */ + +void pascal update_block() + /* set flag that a memory block has changed */ + /* no action necessary if current block is root */ + { + if (block_ptr != &(pci->root)) + BUFDIRTY(cache_ptr) = 1; + } /* update_block */ + + +void pascal init_cache() /* initialize the cache memory buffers */ + { + register int j; + for (j = 0; j < NUM_BUFS; j++) + { BUFDIRTY(j) = 0; /* the buffer has not been changed */ + BUFCOUNT(j) = 0; /* number of references is 0 */ + BUFBLOCK(j).brec = NULLREC; /* each memory block is empty */ + } + } /* init_cache */ + + +int pascal find_cache(r) /* find a block in the cache memory */ + RECPOS r; + { + register int j; + for (j = 0; j < NUM_BUFS; j++) /* repeat for each index buffer */ + { + /* check handle and index address for a match */ + if((BUFBLOCK(j).brec == r) && (BUFHANDLE(j) == pci->ixfile)) + { cache_ptr = j; /* if match, set cache_ptr */ + return (1); /* and return true */ + } } + return (-1); /* return false if not in cache memory */ + } /* find_cache */ + + +int pascal new_cache() /* assign a block in cache memory */ + { + register int i; + i = (cache_ptr + 1) % NUM_BUFS; /* assign memory buffer */ + /* if it has been changed, save it to disk */ + if (BUFDIRTY(i)) write_if(BUFHANDLE(i), + BUFBLOCK(i).brec, + (char *) &BUFBLOCK(i), + sizeof(BLOCK)); + BUFHANDLE(i) = pci->ixfile; /* save index file handle */ + BUFDIRTY(i) = 0; /* buffer change flag is false */ + return (i); /* return memory buffer pointer */ + } /* new_cache */ + + +void pascal load_cache(r) /* load index block in cache memory */ + RECPOS r; + { + cache_ptr = new_cache(); /* get a block in cache memory */ + /* and then load the index block */ + read_if(r, (char *)&BUFBLOCK(cache_ptr), sizeof(BLOCK)); + } /* load_cache */ + + +void pascal get_cache(r) /* load an index block into cache */ + RECPOS r; + { + if (find_cache(r) < 0) /* if block is not in cache memory */ + load_cache(r); /* load the block in memory */ + /* and set block point to this block */ + block_ptr = &BUFBLOCK(cache_ptr); + } /* get_cache */ + + +void pascal retrieve_block(j, r) /* load an index block */ + int j; + RECPOS r; + { + if (j == 0) /* if the block wanted is the root */ + block_ptr = &(pci->root); /* then point to the root */ + else get_cache(r); /* else get from cache memory */ + CB(j) = block_ptr->brec; /* store index block address */ + } /* retrieve_block */ + + +/* low level functions of BPLUS */ + +int pascal prev_entry(off) /* back up one entry in current block */ + int off; + { + if (off <= 0) /* if off <= can not back up */ + { + off = -1; /* set to beginning of block */ + CO(pci->level) = off; + } + else + off = scan_blk(off); /* find previous entry */ + return(off); + } /* prev_entry */ + + +int pascal next_entry(off) /* find next entry in current block */ + int off; + { + if (off == -1) /* at beginning of the block */ + off = 0; + else /* move to next entry if not at end */ + { + if (off < block_ptr->bend) + off += ENT_SIZE(ENT_ADR(block_ptr,off)); + } + CO(pci->level) = off; /* save the offset position in block */ + return (off); + } /* next_entry */ + + +void pascal copy_entry(to, from) /* copy an entry */ + ENTRY *to; /* to here */ + ENTRY *from; /* from here */ + { + int me; + me = ENT_SIZE(from); /* get the entry's size */ + memmove(to, from, me); /* and copy */ + } /* copy_entry */ + + +int pascal scan_blk(n) /* find the offset of last entry in */ +int n; /* current block before postion n */ + { + register int off, last; + off = 0; + last = -1; + while (off < n ) /* repeat until position >= n */ + { last = off; + off += ENT_SIZE(ENT_ADR(block_ptr,off)); + } + CO(pci->level) = last; /* save new block offset positioon */ + return (last); + } /* scan_blk */ + + +int pascal last_entry() /* find offset of last entry in block */ + { + return( scan_blk(block_ptr->bend) ); + } /* last_entry */ + + +/* maintain list of free index blocks */ + +void pascal write_free(r, pb) /* update list of free index blocks */ + RECPOS r; /* free index position */ + BLOCK *pb; /* free block */ + { + pb->p0 = FREE_BLOCK; /* mark as free */ + pb->brec = pci->dx.ff; /* keep old first free address */ + write_if(pci->ixfile, r, (char *) pb, sizeof(BLOCK)); + pci->dx.ff = r; /* set first free address to r */ + } /* write_free */ + + +RECPOS pascal get_free() /* get address of free index block */ + { + RECPOS r, rt; + + r = pci->dx.ff; /* use block address ff if free */ + if ( r != NULLREC ) + { read_if(r, (char *)&rt, sizeof( RECPOS )); + pci->dx.ff = rt; /* save next free index block */ + } + else /* else add to end of index file */ + r = filelength (pci->ixfile); + return (r); /* return index block address */ + } /* get_free */ + + +/* general BPLUS block level functions */ + +int pascal find_block(pe, poff) /* find a key with current block */ + ENTRY *pe; /* use this entry */ + int *poff; /* return offset within block */ + { + register int pos, nextpos, ret; + pos = -1; + nextpos = 0; + ret = 1; + while ( nextpos < block_ptr->bend) /* repeat until end of block */ + { + ret = strcmp((char *)(pe->key), + (char *)(ENT_ADR(block_ptr, nextpos)->key)); + if (ret <= 0) /* if the entry key >= search key */ + { + if (ret == 0) pos = nextpos; /* move to matching key */ + break; /* and break loop */ + } + pos = nextpos; /* save current offset */ + nextpos = next_entry(pos); /* get next entry position */ + } + CO(pci->level) = pos; /* save offset within current block */ + *poff = pos; /* store offset position */ + return (ret); + } /* find_block */ + + +void pascal movedown(pb, off, n) /* move part of block downward */ + BLOCK *pb; /* block to move down */ + int off; /* start move here */ + int n; /* move this far */ + { + memmove(ENT_ADR(pb, off), + ENT_ADR(pb, off + n), + pb -> bend - (off + n)); + } /* movedown */ + + +void pascal moveup(pb, off, n) /* move part of a block upward */ + BLOCK *pb; /* the block */ + int off; /* start move here */ + int n; /* move up n bytes */ + { + memmove(ENT_ADR(pb, off + n), + ENT_ADR(pb, off), + pb->bend - off); + } /* moveup */ + + +void pascal ins_block(pb, pe, off) /* insert entry into a block */ + BLOCK *pb; /* add to this block */ + ENTRY *pe; /* add this entry */ + int off; /* at this position */ + { + int size; + size = ENT_SIZE(pe); /* size of new entry */ + moveup(pb,off,size); /* move entries to make room */ + copy_entry(ENT_ADR(pb,off),pe); /* copy new entry */ + pb->bend += size; /* adjust block size */ + } /* ins_block */ + + +void pascal del_block(pb, off) /* delete entry in a block */ + BLOCK *pb; /* this block */ + int off; /* delete entry at this position */ + { + int ne; + ne = ENT_SIZE(ENT_ADR(pb, off)); /* size of deleted entry */ + movedown(pb, off, ne); /* move entries down */ + pb->bend -= ne; /* adjust block size */ + } /* del_block */ + + +/* position at start/end of index */ + +int cdecl first_key(pix) /* position to first key */ + IX_DESC *pix; /* in this index file */ + { + pci = pix; /* set global index descriptor */ + block_ptr = &(pci->root); /* start with the root */ + CB(0) = 0L; /* root address is 0L */ + CO(0) = -1; /* offset is -1 */ + pci->level = 0; /* 0 level in index file */ + while(block_ptr->p0 != NULLREC) /* repeat for all levels */ + { /* get index block for next level */ + retrieve_block(++(pci->level), block_ptr->p0); + CO(pci->level) = -1; /* position to start of block */ + } + return ( IX_OK ); + } /* first_key */ + + +int cdecl last_key(pix) /* position at last key */ + IX_DESC *pix; /* in this index file */ + { + long ads; + pci = pix; + block_ptr = &(pci->root); /* start with the root */ + CB(0) = 0L; + pci->level = 0; + if(last_entry() >= 0) /* repeat for all levels */ + { /* get block for next level */ + while ((ads = ENT_ADR(block_ptr,last_entry())->idxptr) != NULLREC) + retrieve_block(++(pci->level), ads); + } + CO(pci->level) = block_ptr->bend; /* set offset position to the end */ + return ( IX_OK ); + } /* last_key */ + + +/* get next, previous entries */ + +int cdecl next_key(pe, pix) /* get next key */ + ENTRY *pe; /* and put it here */ + IX_DESC *pix; /* for this index */ + { + RECPOS address; + pci = pix; + /* get block for current level */ + retrieve_block(pci->level, CB(pci->level)); + /* set address for next level */ + if(CO(pci->level) == -1) address = block_ptr->p0; + else + { + if (CO(pci->level) == block_ptr->bend) address = NULLREC; + else address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + } + while (address != NULLREC) /* repeat until at leaf level */ + { + retrieve_block(++(pci->level), address); + CO(pci->level) = -1; + address = block_ptr->p0; + } + next_entry(CO(pci->level)); /* get next entry for leaf block */ + if (CO(pci->level) == block_ptr->bend) /* check for end of block */ + { + do + { if(pci->level == 0) /* if this is the root block */ + { + last_key(pci); /* go to end of root block */ + return (EOIX); /* return end of index file */ + } + --(pci->level); /* level of ancestor block */ + retrieve_block(pci->level, CB(pci->level)); + next_entry(CO(pci->level)); /* next entry for ancestor */ + } while (CO(pci->level) == block_ptr->bend); + } + /* copy the next entry and return */ + copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + return ( IX_OK ); + } /* next_key */ + + +int cdecl prev_key(pe, pix) /* get the previous key */ + ENTRY *pe; /* put it here */ + IX_DESC *pix; /* for this index */ + { + RECPOS address; + pci = pix; + /* get block for current level */ + retrieve_block(pci->level, CB(pci->level)); + prev_entry(CO(pci->level)); /* previous entry in this block */ + if (CO(pci->level) == -1) + address = block_ptr->p0; + else + address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + if (address != NULLREC) /* go to the leaf level of index */ + { do + { + retrieve_block(++(pci->level), address); + address = ENT_ADR(block_ptr, last_entry())->idxptr; + } while (address != NULLREC); + } + if (CO(pci->level) == -1) /* check if at beginning of block */ + { do + { + if(pci->level == 0) /* if this is the root block */ + { + first_key(pci); /* get first key */ + return (EOIX); /* and return end of index */ + } + --(pci->level); /* level for ancestor block */ + } while (CO(pci->level) == -1); /* repeat if beginning */ + retrieve_block(pci->level, CB(pci->level)); /* get block */ + } + /* copy entry and return */ + copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + return ( IX_OK ); + } /* prev_key */ + + +/* insert new entries into tree */ + +void pascal split(l, pe, e) /* split an index block */ + int l; /* level in tree */ + ENTRY *pe; /* entry to insert */ + ENTRY *e; /* entry to pass up to next level */ + { + int half, ins_pos, size; + ins_pos = CO(pci->level); /* save current offset */ + /* and divide block in half */ + half = scan_blk(block_ptr->bend / 2 + sizeof(RECPOS)); + if (half == ins_pos) /* if inserting at half */ + *e = *pe; /* pass up entry pe */ + else /* else copy entry at half */ + { + copy_entry(e, ENT_ADR(block_ptr, half)); + size = ENT_SIZE(e); + movedown(block_ptr, half, size); /* move block entries down */ + block_ptr->bend -= size; /* and adjust the size */ + } + spare_block = &BUFBLOCK(new_cache()); /* allocate a spare block */ + memmove(spare_block->entries, /* and copy half the entries */ + ENT_ADR(block_ptr,half), + block_ptr->bend - half); + spare_block->brec = get_free(); /* index address of new block */ + spare_block->bend = block_ptr->bend - half; /* set size of block */ + spare_block->p0 = e->idxptr; /* set all the pointers */ + block_ptr->bend = half; + e->idxptr = spare_block->brec; + if (ins_pos < half) /* insert the new entry */ + ins_block(block_ptr,pe,ins_pos); /* in current block */ + else if (ins_pos > half) /* else insert the entry */ + { /* in the spare block */ + ins_pos -= ENT_SIZE(e); + ins_block(spare_block,pe,ins_pos - half); + CB(l) = e->idxptr; /* set block address */ + CO(l) = CO(l) - half; /* and offset */ + } + write_if(pci->ixfile, spare_block->brec, /* write to disk */ + (char *) spare_block, sizeof(BLOCK)); + } /* split */ + + +void pascal ins_level(l, e) /* insert an entry e */ + int l; /* into block level l */ + ENTRY *e; + { + int i; + if ( l < 0) /* tree height has increased */ + { for (i = 1; i < MAX_LEVELS; i++) /* save offset and addresses */ + { CO(MAX_LEVELS - i) = CO(MAX_LEVELS - i - 1); + CB(MAX_LEVELS - i) = CB(MAX_LEVELS - i - 1); + } + /* copy old root to spare block */ + memmove(spare_block, &(pci->root), sizeof(BLOCK)); + /* get index address and write to disk */ + spare_block->brec = get_free(); + write_if(pci->ixfile, spare_block->brec, + (char *) spare_block, sizeof(BLOCK)); + pci->root.p0 = spare_block->brec; /* set p0 pointer */ + copy_entry((ENTRY *) (pci->root.entries), e); /* copy insert e */ + pci->root.bend = ENT_SIZE(e); /* root contains only e */ + CO(0) = 0; /* root offset is 0 */ + pci->level = 0; /* set current level */ + (pci->dx.nl)++; /* increment no. of levels */ + } + else ins_block(block_ptr,e,CO(l)); /* insert in current block */ + } /* ins_level */ + + +int pascal insert_ix(pe, pix) /* insert at current level */ + ENTRY *pe; /* insert entry pe */ + IX_DESC *pix; /* into this index */ + { + ENTRY e, ee; + int h; + h = 0; + pci = pix; + ee = *pe; + do + { + if(CO(pci->level) >= 0) /* set new offset */ + CO(pci->level) += + ENT_SIZE(ENT_ADR(block_ptr, CO(pci->level))); + else + CO(pci->level) = 0; + update_block(); /* we are going to change this block */ + /* if new block size < split size */ + if( (block_ptr->bend + ENT_SIZE(&ee)) <= split_size) + { + ins_level(pci->level, &ee); /* insert into current block */ + break; /* and break */ + } + else + { + h = 1; /* must reset index pointers */ + split(pci->level,&ee, &e); /* split the current block */ + ee = e; /* this entry is passed up */ + pci->level--; /* to insert at this level */ + if (pci->level < 0) /* increase tree height */ + { + ins_level(pci->level, &e); + break; + } + /* get block for next level */ + retrieve_block(pci->level, CB(pci->level)); + } + } + while (1); + if (h) find_ix(pe, pix, 0); /* reset pointers if necessary */ + return ( IX_OK ); + } /* insert_ix */ + + +/* BPLUS find and add key functions */ + +int pascal find_ix(pe, pix, find) /* search an index file */ + ENTRY *pe; /* for this entry */ + IX_DESC *pix; /* in this index */ + int find; /* 1 to find_key, 0 to locate_key */ + { + int level, off, ret; + RECPOS ads; + pci = pix; + ads = 0L; /* start at the root */ + level = ret = 0; + while (ads != NULLREC) /* repeat until done */ + { pci->level = level; /* set level */ + retrieve_block(level, ads); /* get index block */ + /* and search for entry */ + if (find_block(pe, &off) == 0) ret = 1; /* found? */ + if (ret && find) break; /* done? */ + if (off == -1) /* get next block address */ + ads = block_ptr->p0; + else + ads = ENT_ADR(block_ptr, off)->idxptr; + CO(level++) = off; /* increment level */ + } + return ( ret ); + } /* find_ix */ + + +int cdecl find_key(pe, pix) /* find a key */ + ENTRY *pe; /* this entry */ + IX_DESC *pix; /* in this index */ + { + int ret; + ret = find_ix(pe, pix, 1); /* find_ix does all the work */ + /* if found, copy the entry */ + if ( ret ) copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + return ( ret ); + } /* find_key */ + + +int cdecl add_key(pe, pix) /* add a new key */ + ENTRY *pe; /* this entry */ + IX_DESC *pix; /* this index file */ + { + int ret; + ret = find_ix(pe, pix, 0); /* see if key is already in index */ + /* if found, are dupicates are OK? */ + if ( ret && (pci->duplicate == 0)) return ( IX_FAIL ); + pe->idxptr = NULLREC; /* add new key on leaf level */ + return (insert_ix(pe, pix)); /* insert_ix does the work */ + } /* add_key */ + + +int cdecl locate_key(pe, pix) /* locate first key */ + ENTRY *pe; /* <= this entry */ + IX_DESC *pix; /* in this index */ + { + int ret; + ret = find_ix(pe, pix, 1); /* search index for entry */ + /* if found, copy it to pe */ + if (ret) copy_entry(pe, ENT_ADR(block_ptr, CO(pci->level))); + /* else get the next key */ + else if (next_key(pe,pix) == EOIX) ret = EOIX; + return ( ret ); + } /* locate_key */ + + +int cdecl find_exact(pe, pix) /* find an exact match */ + ENTRY *pe; /* for this entry */ + IX_DESC * pix; /* in this index */ + { + int ret; + ENTRY e; + copy_entry(&e, pe); /* make a copy of the entry */ + ret = find_key(&e, pix); /* is it in the index? */ + if ( ret && pci->duplicate) /* if duplicate key are allowed */ + { /* then search for recptr match */ + do + { + ret = (e.recptr == pe->recptr); + if( !ret ) ret = next_key(&e, pci); + if (ret) ret = (strcmp(e.key, pe->key) == 0); + if ( !ret ) return ( 0 ); /* no match was found */ + } while ( !ret ); + } + copy_entry(pe, &e); /* if found, data is contained in e */ + return ( ret ); + } /* find_exact */ + + +/* BPLUS delete key functions */ + +int cdecl delete_key(pe, pix) /* delete a key */ + ENTRY *pe; /* this entry */ + IX_DESC *pix; /* in this index */ + { + ENTRY e; + RECPOS ads; + int h, leveli, levelf; + /* search index for exact match */ + if (!find_exact(pe, pix)) return( IX_FAIL ); + h = 1; + if ((ads = pe->idxptr) != NULLREC) /* if not the leaf level */ + { + leveli = pci->level; /* save current level */ + do /* go to leaf level of index */ + { + retrieve_block(++(pci->level), ads); + CO(pci->level) = -1; + } + while ((ads = block_ptr->p0) != NULLREC); + CO(pci->level) = 0; + copy_entry(&e, ENT_ADR(block_ptr, CO(pci->level))); + levelf = pci->level; /* save leaf level */ + pci->level = leveli; /* reset starting level */ + replace_entry(&e); /* replace with entry from leaf */ + pci->level = levelf; /* leaf level */ + } + while ( h ) + { + /* get block and delete current entry */ + retrieve_block(pci->level, CB(pci->level)); + del_block(block_ptr, CO(pci->level)); + update_block(); /* block has been changed */ + if ( (pci->level == 0) && (block_ptr->bend == 0)) + /* tree was reduced in height */ + { + if (pci->root.p0 != NULLREC) /* replace root block */ + { + retrieve_block(++pci->level, pci->root.p0); + memmove(&(pci->root), block_ptr, sizeof(BLOCK)); + (pci->dx.nl)--; /* decrement number of levels */ + write_free(block_ptr->brec, block_ptr); /* reuse space */ + BUFDIRTY(cache_ptr) = 0; /* block saved on disk */ + BUFHANDLE(cache_ptr) = 0; + } + break; + } + /* see if we can combine index blocks */ + h = (block_ptr->bend < comb_size) && (pci->level > 0); + if ( h ) + h = combineblk(CB(pci->level), block_ptr->bend); + } + find_ix(pe, pix, 0); /* restore CO and CB for each level */ + return( IX_OK ); + } /* delete_key */ + + +int pascal combineblk(ads, size) /* combine index blocks */ + RECPOS ads; /* block at this address */ + int size; /* and is this size */ + { + ENTRY e; + RECPOS address; + int esize, off, ret, saveoff, ibuff; + ret = 0; + /* ancestor level and save offset */ + saveoff = CO(--(pci->level)); + /* retrieve ancestor index block */ + retrieve_block(pci->level, CB(pci->level)); + if ((off = next_entry( saveoff )) < block_ptr->bend) + /* combine with page on right */ + { + if ( (ENT_SIZE(ENT_ADR(block_ptr, off)) + size) < split_size) + /* okay to combine */ + { + copy_entry(&e, ENT_ADR(block_ptr, off)); /* save entry */ + address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + retrieve_block(++pci->level, address); + ibuff = cache_ptr; /* save cache pointer */ + spare_block = block_ptr; /* use as spare block */ + retrieve_block(pci->level, ads); + esize = ENT_SIZE(&e); + if(((block_ptr->bend + spare_block->bend + esize) >= split_size) + && (spare_block->bend <= block_ptr->bend + esize)) + return( ret ); + e.idxptr = spare_block->p0; + ins_block(block_ptr, &e, block_ptr->bend); + update_block(); + if ((block_ptr->bend + spare_block->bend) < split_size) + /* combine the blocks */ + { + memmove(ENT_ADR(block_ptr, block_ptr->bend), + ENT_ADR(spare_block, 0), + spare_block->bend); + /* set block length and free spare block space */ + block_ptr->bend += spare_block->bend; + write_free(spare_block->brec, spare_block); + BUFDIRTY(ibuff) = 0; + BUFHANDLE(ibuff) = 0; + --pci->level; + ret = 1; + } + else + /* move an entry up to replace the one moved */ + { + copy_entry(&e, ENT_ADR(spare_block, 0)); + esize = ENT_SIZE(&e); + /* fixup spare block and pointers */ + movedown(spare_block, 0, esize); + spare_block->bend -= esize; + spare_block->p0 = e.idxptr; + BUFDIRTY(ibuff) = 1; + --(pci->level); + replace_entry(&e); + } + } + } + else + /* move from page on left */ + { + if ( (ENT_SIZE(ENT_ADR(block_ptr, CO(pci->level))) + size) + < split_size) + /* okay to proceed */ + { + copy_entry(&e, ENT_ADR(block_ptr, saveoff)); /* save entry */ + /* get page which is on the left */ + off = prev_entry(saveoff); + if (CO(pci->level) == -1) address = block_ptr->p0; + else address = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + retrieve_block(++pci->level, address); + off = last_entry(); + ibuff = cache_ptr; + /* set spare block to left page */ + spare_block = block_ptr; + /* get current block */ + retrieve_block(pci->level, ads); + esize = ENT_SIZE(&e); + if(((block_ptr->bend + spare_block->bend + esize) >= split_size) + && (spare_block->bend <= block_ptr->bend + esize)) + return( ret ); + BUFDIRTY(ibuff) = 1; /* we have changed things */ + CO(pci->level) = 0; + e.idxptr = block_ptr->p0; + ins_block(block_ptr, &e, 0); + if ((block_ptr->bend + spare_block->bend) < split_size) + /* combine the blocks */ + { + memmove(ENT_ADR(spare_block, spare_block->bend), + ENT_ADR(block_ptr, 0), + block_ptr->bend); + /* set block length and freeup block */ + spare_block->bend += block_ptr->bend; + write_free(block_ptr->brec, block_ptr); + BUFDIRTY(cache_ptr) = 0; + BUFHANDLE(cache_ptr) = 0; + CO(--(pci->level)) = saveoff; + ret = 1; + } + else + /* move an entry up to replace the one moved */ + { + block_ptr->p0 = ENT_ADR(spare_block,off)->idxptr; + copy_entry(&e, ENT_ADR(spare_block, off)); + spare_block->bend = off; + update_block(); + CO(--(pci->level)) = saveoff; + replace_entry(&e); + } + } + } + return ( ret ); + } /* combineblk */ + + +void pascal replace_entry(pe) /* replace entry at current position */ + ENTRY *pe; /* with this entry */ + { + retrieve_block(pci->level, CB(pci->level)); /* get current block */ + /* set address for the replacement entry */ + pe->idxptr = ENT_ADR(block_ptr, CO(pci->level))->idxptr; + del_block(block_ptr, CO(pci->level)); /* now delete the entry */ + prev_entry(CO(pci->level)); /* backup one entry */ + insert_ix(pe, pci); /* and insert new entry */ + } /* replace_entry */ + + \ No newline at end of file diff --git a/bplus/LISTTREE.C b/bplus/LISTTREE.C new file mode 100644 index 0000000..557fe06 --- /dev/null +++ b/bplus/LISTTREE.C @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* */ +/* LISTTREE.C */ +/* */ +/* This program displays each block in an index file. The root node */ +/* of the index tree is displayed first. Then the left most descendant */ +/* block is displayed for each level in the tree. After the leaf block */ +/* is displayed, the right most descendant from the ancestor block is */ +/* displayed. That is, a preordering method of transversing the tree */ +/* is used. The complete block is displayed including the data file */ +/* address, the index file address, and the index key. The printtree */ +/* routine is recursive. */ +/* */ +/*************************************************************************/ + +#include +#include "bplus.h" + +/* constant and macros */ +#define NULLREC (-1L) +#define ENT_ADR(pb,off) ((ENTRY*)((char*)((pb)->entries) + off)) +#define ENT_SIZE(pe) strlen((pe)->key) + 1 + 2 * sizeof(RECPOS) + +/* global variables defined in BPLUS.C */ +extern IX_DESC *pci; +extern BLOCK *block_ptr; + +IX_DESC ixfile; + +void pascal retrieve_block(int, RECPOS); +int pascal copy_entry(ENTRY *, ENTRY *); + +void print_blk(pb) /* list each entry in block pb */ + BLOCK *pb; + { + int i; + i = 0; + printf("%ld ",pb->brec); + printf("%d %ld ",pb->bend,pb->p0); + while (i < pb->bend) + { + printf(" %ld ",ENT_ADR(pb,i) -> idxptr); + printf(" %ld ",ENT_ADR(pb,i) -> recptr); + printf("%s ",ENT_ADR(pb,i) -> key); + i = i + ENT_SIZE(ENT_ADR(pb,i)); + } + printf("\n"); + } + +void printtree(num, l, level) /* print the index tree */ + RECPOS num; /* index block address */ + int l; /* indent each level l */ + int level; /* level in index file */ + { + long address; + int end, i, j; + if (num != NULLREC) + { + for (i=1; i<=l; i++) + printf(" "); + retrieve_block(level, num); + print_blk(block_ptr); + address = block_ptr -> p0; + printtree(address, l + 1,level + 1); + retrieve_block(level, num); + j = 0; + end = block_ptr -> bend; + while (j < end) + { + address = ENT_ADR(block_ptr,j) -> idxptr; + printtree(address, l + 1, level + 1); + retrieve_block(level, num); + j = j + ENT_SIZE(ENT_ADR(block_ptr,j)); + } + } + } + +main() + { + char name[80]; + + printf("\n\n Display An Index Tree\n\n"); + printf(" Name of index file: "); + gets(name); + open_index(name,&ixfile, 1); + printtree(0L,1,0); + close_index(&ixfile); + } + \ No newline at end of file diff --git a/bplus/NAMES.C b/bplus/NAMES.C new file mode 100644 index 0000000..70c1564 --- /dev/null +++ b/bplus/NAMES.C @@ -0,0 +1,227 @@ +/*******************************************************************/ +/* NAMES.C */ +/* */ +/* This example shows how easy it is to write a program for an */ +/* online address book using the B-PLUS file indexing toolkit. */ +/* The program creates a file of names, addresses, and telephone */ +/* numbers. A record is displayed on the screen by entering part */ +/* or all of the name. Although the program is usefully as written */ +/* it has purposely been kept simple. You may want to add new */ +/* features to the progran. */ +/* */ +/********************************************************************/ + + +#include +#include +#include "bplus.h" + + +typedef struct /* Here is the address record definition */ + { + char lastname[16]; /* last name */ + char firstname[16]; /* first name */ + char address1[31]; /* first address line */ + char address2[31]; /* second address line */ + char city[21]; /* the city */ + char state[3]; /* the state */ + char zipcode[6]; /* postal zip code */ + char telephone[14]; /* telephone number */ + } ADDRESS; + + +IX_DESC nameindex; /* index file variable */ +FILE *namefile; /* data file pointer */ +ADDRESS person; /* data record variable */ + + +void openfiles(void); +void closefiles(void); +int addrecord(void); +void getstring(char*, int); +void newaddress(void); +void printname(ENTRY*); +void getname(void); +void nextname(void); +void listnames(void); + + +void openfiles() + /* If the file NAMES.DAT already exist, open the index and data */ + /* file. Otherwise, these files are created. */ + { + if ((namefile = fopen("names.dat","r+")) != NULL) + open_index("names.idx", &nameindex, 1); /* open index file */ + else + { + namefile = fopen("names.dat","w+"); /* create data file */ + if (namefile == NULL) + { + printf("Unable to open namefile\n"); + exit(1); + } + make_index("names.idx", &nameindex, 1); /* creat index file */ + } /* allow duplicate keys */ + } /* openfiles */ + + +void closefiles() + /* close all files and exit */ + { + fclose(namefile); + close_index(&nameindex); + exit(0); + } /* closefiles */ + + +int addrecord() + /* add a new address to the data file - add index to index file */ + { + ENTRY ee; + char name[32]; + int ret; + ret = fseek(namefile, 0L, SEEK_END); /* seek to end of datafile */ + if (ret == 0) + { + strcpy(ee.key, person.lastname); /* key is last name followed */ + strcat(ee.key, person.firstname); /* first name. Capitalize */ + strupr(ee.key); /* and copy to ee.key. */ + ee.recptr = ftell(namefile); /* get position in datafile */ + if (ee.recptr != -1L) + { + if (add_key(&ee, &nameindex) == IX_OK) /* add key to index */ + { + fwrite(&person,sizeof(person),1,namefile); /* add address */ + return (IX_OK); + } + } + } + else printf("Seek error - data file"); + return (IX_FAIL); + } /* addrecord */ + + +void getstring(mes, length) + char *mes; + int length; + /* input a string and check that it is not too long */ + { + char message[80]; + gets(message); + if (strlen(message) > length) message[length] = '\0'; + strcpy(mes,message); + } /* getstring */ + + +void newaddress() + /* add new address records */ + { + while (1) + { + printf("\n\nLast Name : "); + getstring(person.lastname,15); + if ( strlen(person.lastname) > 0) /* quit if no last name */ + { + printf("First Name : "); + getstring(person.firstname,15); + printf("Address Line 1 : "); + getstring(person.address1,30); + printf("Address Line 2 : "); + getstring(person.address2,30); + printf("City : "); + getstring(person.city,20); + printf("State : "); + getstring(person.state,2); + printf("Zip Code : "); + getstring(person.zipcode,5); + printf("Telephone : "); + getstring(person.telephone,13); + addrecord(); /* update data and index files */ + printf("\n"); + } + else return ; + } + } /* newaddress */ + + +void printname(e) + ENTRY *e; + /* retrieve a data record and print it on the screen */ + { + int ret; + + /* seek to the record address stored in ENTRY e->recptr */ + ret = fseek(namefile, e->recptr, SEEK_SET); + + if (ret == 0) /* if OK read the record and display */ + { + fread(&person,sizeof(person),1,namefile); + printf("\n\n %s %s" , person.firstname,person.lastname); + printf("\n %s", person.address1); + if (strlen(person.address2) > 0) + printf("\n %s", person.address2); + printf("\n %s, %s %s", person.city,person.state,person.zipcode); + printf("\n %s\n", person.telephone); + } + else printf("Seek error - data file"); + } /* printname */ + + +void getname() + /* Get an address record by entering part or all of name */ + /* Enter last name first then first name with no spaces */ + { + ENTRY ee; + printf("\n\nEnter name: "); + gets(ee.key); + + /* make all upper case letters and copy to ee.key */ + strupr(ee.key); + + /* use locate_key instead of find_key so an exact match not required */ + if (locate_key(&ee, &nameindex) != EOIX) printname(&ee); + else printf("No key this large in index file\n"); + } /* getname */ + + +void nextname() + /* display the next address in the address file */ + { + ENTRY ee; + if (next_key(&ee, &nameindex) == IX_OK) printname(&ee); + else printf("\nEnd of index file\n"); + } /* nextname */ + + +void listnames() + /* list all the names in the address file */ + { + ENTRY ee; + first_key(&nameindex); + while (next_key(&ee, &nameindex) == IX_OK) printname(&ee); + } /* listnames */ + +main() + /* Here is the main program loop */ + { + char cmd; + int done; + done = 0; + openfiles(); + do + { + printf("\nCommand: A (Add Name), F (Find), N (Next), L (List), Q (Quit): "); + cmd = toupper(getche()); + switch (cmd) + { + case 'A': newaddress(); break; /* add a name to address file */ + case 'F': getname(); break; /* find an address */ + case 'N': nextname(); break; /* display next address in file */ + case 'L': listnames(); break; /* display all addresses */ + case 'Q': closefiles(); /* quit and close files */ + } + } + while (!done); + } /* main */ + + \ No newline at end of file diff --git a/bplus/READ.ME b/bplus/READ.ME new file mode 100644 index 0000000..b5fb306 --- /dev/null +++ b/bplus/READ.ME @@ -0,0 +1,57 @@ + + + + + + + + + + BPLUS.C - Version 1.1A + + + Thank you for registering your copy of the BPLUS "toolkit" + with Hunter and Associates. Your support is appreciated. + Customers like you help reinforce the principal that quality + "shareware" software is indeed a viable one. + + This version of BPLUS has been thoroughly tested and is + properly configured for Turboc C Versions 1.0 and 1.5, and + Microsoft's Quick C, C 5.0, and C 5.1 (OS/2). If you are using + Microsoft's C 4.0 compiler, you must use the memcpy rather than + the memmove routine. See the comments in BPLUS.C. + + Your registration disk contains nine files. These files are + the following: + + BPLUS.H - the header file to include in your "C" programs + which use the BPLUS Toolkit + + BPLUS.C - the source code for Version 1.1 of BPLUS + + CPLUS.C - the source code for Version 1.1 of BPLUS with + extensive comments added + + BPLUS.DOC - the user's manual for BPLUS + + VTEST.C - a test program which creates two index files + + NAMES.C - a program for creating and using an on-line + name and address book + + REINDEX.C - a program to re-index the data file used in + NAMES.C + + LISTTREE.C - a program which lists the index tree + + READ.ME - this message file + + + ADDRESS CHANGE + + We have moved and our new address is: + + 7900 Edgewater Drive + Wilsonville, OR 97070 + Tel: (503) 694-1449 +  \ No newline at end of file diff --git a/bplus/REINDEX.C b/bplus/REINDEX.C new file mode 100644 index 0000000..01ad8aa --- /dev/null +++ b/bplus/REINDEX.C @@ -0,0 +1,100 @@ +/********************************************************************/ +/* REINDEX.C */ +/* */ +/* This is a sample program which demonstrates how to reindex a */ +/* data file. The data file which is used is the one created by */ +/* NAMES.C which creates an online address book using the B-PLUS */ +/* file indexing toolkit. */ +/* */ +/********************************************************************/ + + +#include +#include +#include "bplus.h" + + +typedef struct /* Here is the address record definition */ + { + char lastname[16]; /* last name */ + char firstname[16]; /* first name */ + char address1[31]; /* first address line */ + char address2[31]; /* second address line */ + char city[21]; /* the city */ + char state[3]; /* the state */ + char zipcode[6]; /* postal zip code */ + char telephone[14]; /* telephone number */ + } ADDRESS; + + +IX_DESC nameindex; /* index file variable */ +FILE *namefile; /* data file pointer */ +ADDRESS person; /* data record variable */ + + +void openfiles(void); +void closefiles(void); +long makeindex(void); + + +void openfiles() + /* The file NAMES.DAT already exists. It is opened and a new */ + /* index file is created. */ + { + if ((namefile = fopen("names.dat","r")) != NULL) + make_index("names.idx", &nameindex, 1); /* create index file */ + else + { + printf("\nUnable to open NAMES.DAT\n"); + exit(1); + } + } /* openfiles */ + + +void closefiles() + /* close all files and exit */ + { + fclose(namefile); + close_index(&nameindex); + } /* closefiles */ + + +long makeindex() + /* read address records and add key to index file */ + { + ENTRY ee; + long num, position, size; + int ret; + size = sizeof(person); /* data record size */ + ret = fread(&person,size,1,namefile); /* ret is number of data */ + /* records that were read */ + num = 0L; /* num = data items read */ + position = 0L; /* position in datafile */ + while (ret == 1) + { + strcpy(ee.key, person.lastname); /* key is last name followed */ + strcat(ee.key, person.firstname); /* first name. Capitalize */ + strupr(ee.key); /* and copy to ee.key. */ + ee.recptr = position; /* position in datafile */ + if (add_key(&ee, &nameindex) != IX_OK) /* add key to index */ + printf("Error while adding key to index file"); + position += size; /* new position in datafile */ + num++; /* increment data items read */ + ret = fread(&person,sizeof(person),1,namefile); + } + return ( num ); + } /* makeindex */ + + +main() + /* Here is the main program */ + { + long num; + openfiles(); + printf("\n\n MAKING THE NEW INDEX FILE\n\n"); + num = makeindex(); + closefiles(); + printf(" REINDEXING IS COMPLETE - %ld ITEMS WERE INDEXED\n", num); + } /* main */ + + \ No newline at end of file diff --git a/bplus/VTEST.C b/bplus/VTEST.C new file mode 100644 index 0000000..9f2dc05 --- /dev/null +++ b/bplus/VTEST.C @@ -0,0 +1,103 @@ +/* VTEST.C test program. */ +/* This is a simple test program which creates two index files. */ +/* 100 keys are added to each file, some keys are deleted and */ +/* then the keys are added back to the file. The keys are listed */ +/* in ascending and decending order. */ + +#include "bplus.h" +#include +#include +#include + +IX_DESC name1, name2; /* index file variables */ + +void uplist(name) /* list keys in ascending order */ + IX_DESC *name; + { + ENTRY ee; + first_key(name); + while (next_key(&ee, name) == IX_OK) printf("%s ",ee.key); + printf("\nPress any key to continue \n"); + getch(); + } + +void downlist(name) /* list keys in decending order */ + IX_DESC *name; + { + ENTRY ee; + last_key(name); + while (prev_key(&ee, name) == IX_OK) printf("%s ",ee.key); + printf("\nPress any key to continue \n"); + getch(); + } + +main() + { + long i; + long ltime; + ENTRY e; + printf("Make two index files\n"); + make_index("test1.idx",&name1, 0); + make_index("test2.idx",&name2, 1); + printf("Indexing 100 items in two index files:\n"); + + /* note the time to index */ + time(<ime); + printf("%s",ctime(<ime)); + + /* add 100 keys to each index file */ + for (i = 0L; i < 100L; i++) + { + e.recptr = i; + sprintf(e.key, "VALUE1-%2d",i); + add_key(&e, &name1); + sprintf(e.key, "VALUE2-%2d",i); + add_key(&e, &name2); + } + + /* print the time required for indexing the two files */ + time(<ime); + printf("%s",ctime(<ime)); + printf("Indexing is complete\n\n"); + printf("List the keys in each index file in ascending order:\n\n"); + uplist(&name1); + uplist(&name2); + + /* delete some keys and list again */ + printf("\nNow delete all keys from 20 to 90 in each file\n\n"); + for (i = 20L; i < 90L; i++) + { + e.recptr = i; + sprintf(e.key, "VALUE1-%2d",i); + delete_key(&e, &name1); + sprintf(e.key, "VALUE2-%2d",i); + delete_key(&e, &name2); + } + printf("List the keys now for each index file in ascending order:\n\n"); + uplist(&name1); + uplist(&name2); + + /* add the keys back and list again */ + printf("Now add back all items from 20 to 90 to each index\n\n"); + for (i = 20L; i < 90L; i++) + { + e.recptr = i; + sprintf(e.key, "VALUE1-%d",i); + add_key(&e, &name1); + sprintf(e.key, "VALUE2-%d",i); + add_key(&e, &name2); + } + printf("List the keys for each index file again in ascending order:\n\n"); + uplist(&name1); + uplist(&name2); + + /* list both files in decending order */ + printf("List the keys for each index file in decending order\n\n"); + downlist(&name1); + downlist(&name2); + + /* always close all files */ + close_index(&name1); + close_index(&name2); + } + \ No newline at end of file diff --git a/fastfngr/FASTFNGR.BAS b/fastfngr/FASTFNGR.BAS new file mode 100644 index 0000000..33a6f16 --- /dev/null +++ b/fastfngr/FASTFNGR.BAS @@ -0,0 +1,6 @@ +'HOTKEY.DLL functions +DefInt A-Z + +Declare Function CreateHK& Lib "HOTKEY.DLL" (ByVal KeyCode, ByVal Shift, ByVal hWnd, ByVal UserVK) +Declare Sub KillHK Lib "HOTKEY.DLL" (ByVal hHotKey&) + diff --git a/fastfngr/FASTFNGR.EXE b/fastfngr/FASTFNGR.EXE new file mode 100644 index 0000000..d61b308 --- /dev/null +++ b/fastfngr/FASTFNGR.EXE Binary files differ diff --git a/fastfngr/FASTFNGR.FRM b/fastfngr/FASTFNGR.FRM new file mode 100644 index 0000000..7f8eed1 --- /dev/null +++ b/fastfngr/FASTFNGR.FRM Binary files differ diff --git a/fastfngr/FASTFNGR.INI b/fastfngr/FASTFNGR.INI new file mode 100644 index 0000000..71f12bd --- /dev/null +++ b/fastfngr/FASTFNGR.INI @@ -0,0 +1,42 @@ +[Aliases] +3=prthplj +3l=prthplj /tr1 +4=4print -q -s -oprn +4t=c:\4tex\texfiles\4tex +bin=cdd c:\bin +c=cls +cd=cdd +ck=chkdsk +cp=copy +d=dir /o/l +dw=cdd c:\dwnl +e=exit +em=d:\emacs\emacs @d:\emacs\emacs.rc +gm=c:\bin\demacs +h=cd\ +lo=exit +ll=c:\ll\llremote +ls=ls -al +lt=latex +nu=net use /yes +p=pcopy +pk=pkarc +pl=pdel /nw +pm=pmap +pp=pp -w80 -l60 -h -n +px=pkxarc +s=ds ne /s +t=xpand type +tm=cdd c:\tmp +tn=telnet +tx=c:\telix\telix +v=list +wi=whereis +win=runwin +wp=cdd c:\docs +x= tdir +zc=pkzip -z +zk=pkzip +zl=pkunzip -v +zx=pkunzip + diff --git a/fastfngr/FASTFNGR.MAK b/fastfngr/FASTFNGR.MAK new file mode 100644 index 0000000..9f17e79 --- /dev/null +++ b/fastfngr/FASTFNGR.MAK @@ -0,0 +1,10 @@ +FASTFNGR.FRM +C:\WINDOWS\SYSTEM\CMDIALOG.VBX +C:\WINDOWS\SYSTEM\GRID.VBX +C:\WINDOWS\SYSTEM\MSOLE2.VBX +FASTFNGR.BAS +ProjWinSize=76,573,225,148 +ProjWinShow=2 +IconForm="FastFinger" +Title="FASTFNGR" +ExeName="FASTFNGR.EXE" diff --git a/fastfngr/FASTFNGR.TXT b/fastfngr/FASTFNGR.TXT new file mode 100644 index 0000000..a249ae2 --- /dev/null +++ b/fastfngr/FASTFNGR.TXT @@ -0,0 +1,429 @@ +Dim Paths(50) As String +Dim Extensions(5) As String +Dim Pindex As Integer + +Const MaxAlias = 100 +Dim Aliases(MaxAlias, 2) As String +Dim aindex As Integer + +Const MaxHist = 20 +Dim HistIndex +Dim HistBuff(MaxHist) As String +Dim HistRoll +Dim PBIndex +Dim MaxHistUsed + +Const HOTKEY = 32 ' Space Bar +Const ToggleKey = 200 ' Value to send here + +Const SHIFT_MASK = 1 +Const CTRL_MASK = 2 +Const ALT_MASK = 4 +Const KEY_MASK = CTRL_MASK + ALT_MASK + +Const KEY_ESC = 27 + + +Sub AliasSubst () + + ' Do relevant alias substitutions on buffer text + x = Len(buffer.Text) + y$ = Left$(buffer.Text, 1) + If ((y$ = "!") Or (y$ = "@")) Then + z = 2 + Else + y$ = "" + z = 1 + End If + + While ((z <= x) And (Mid$(buffer.Text, z, 1) <> " ")) + z = z + 1 + Wend + + If (y$ = "") Then + q$ = Left$(buffer.Text, z - 1) + Else + q$ = Mid$(buffer.Text, 2, z - 2) + End If + + m$ = Mid$(buffer.Text, z) + r = 0 + x = 1 + While ((x <= aindex) And (r = 0)) + If (q$ = Aliases(x, 1)) Then + q$ = Aliases(x, 2) + r = 1 + End If + x = x + 1 + Wend + buffer.Text = y$ + q$ + m$ + +End Sub + +Sub Buffer_DblClick () + If ((HistRoll <> 0) Or (HistIndex <> 1)) Then + CmdHist.Clear + index = HistIndex - 1 'Start with last cmd + While (index <> 0) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + If (HistRoll = 1) Then + index = MaxHist + While (index > HistIndex) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + End If + CmdHist.Visible = 1 + End If +End Sub + +Sub Buffer_KeyPress (Key As Integer) + + Select Case Key + Case 1 ' Ctrl-A + SendKeys "{Home}" + Key = 0 ' Stop the beep madness + + Case 2 ' Ctrl-B + SendKeys "{Left}" + Key = 0 + + Case 4 ' Ctrl-D + SendKeys "{Del}" + Key = 0 + + Case 5 ' Ctrl-E + SendKeys "{End}" + Key = 0 + + Case 6 ' Ctrl-F + SendKeys "{Right}" + Key = 0 + + Case 11 ' Ctrl-K + buffer.Text = Left$(buffer.Text, buffer.SelStart) + SendKeys "{End}" + Key = 0 + + Case 13 ' Ctrl-M + If (buffer.Text <> "") Then + RunCommand + End If + Key = 0 + + Case 14 ' Ctrl-N + If PBIndex < MaxHistUsed Then + PBIndex = PBIndex + 1 + Else + PBIndex = 1 + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case 16 ' Ctrl-P + If PBIndex > 1 Then + PBIndex = PBIndex - 1 + Else + PBIndex = MaxHistUsed + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case KEY_ESC ' Abort On Escape + buffer.Text = "" + Key = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Sub CmdHist_DblClick () + + ' Only get the command - allow normal editing + buffer.Text = CmdHist.Text + CmdHist.Visible = 0 + SendKeys "{END}" ' Position cursor at the end + +End Sub + +Sub CmdHist_KeyPress (Key As Integer) + + Select Case Key + + Case KEY_ESC ' Abort On Escape + Key = 0 + CmdHist.Visible = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Function FindFile (Pgm As String) As String + Retval$ = "" + index = 1 + + On Error GoTo error_handler + While ((Retval$ = "") And (x <= Pindex)) + trial$ = Paths$(x) + Pgm + Open trial$ For Input As 1 + Close 1 + Retval$ = trial$ +try_next: + x = x + 1 + Wend + + FindFile = Retval$ + Exit Function + +error_handler: + Close 1 + Resume try_next +End Function + +Function FindPgm (Pgm As String) As String + + ' First split into program name and arguments + index = 1 + split = 0 + Prog$ = Pgm + While ((split = 0) And (index <= Len(Pgm))) + If (Mid$(Pgm, index, 1) = " ") Then + split = index + Prog$ = Mid$(Pgm$, 1, split - 1) + Args$ = Mid$(Pgm$, split) + End If + index = index + 1 + Wend + + index = 1 + Retval$ = "" + While ((Retval$ = "") And (index <= 5)) + Retval$ = FindFile(Prog$ + Extensions(index)) + index = index + 1 + Wend + + If (Retval$ = "") Then + FindPgm = Pgm$ + Else + FindPgm = Retval$ + Args$ + End If + +End Function + +Sub Form_KeyDown (Key As Integer, Shift As Integer) + Select Case Key + Case ToggleKey + If FastFinger.Visible = 0 Then + FastFinger.Visible = 1 + Else + FastFinger.Visible = 0 + End If + End Select +End Sub + +Sub Form_Load () + InitExt + InitBuf + InitPaths + InitAliases + HistIndex = 1 + HistRoll = 0 + MaxHistUsed = 0 + hHotKey = CreateHK&(HOTKEY, KEY_MASK, HWnd, ToggleKey) + FastFinger.Visible = 0 + CmdHist.Visible = 0 +End Sub + +Sub Form_Unload (Cancel As Integer) + KillHK hHotKey +End Sub + +Sub InitAliases () + + aindex = 0 ' Means no aliases have been found + IniFile$ = App.Path + "\" + App.EXEName + ".INI" + + On Error GoTo INI_file_done + Open IniFile$ For Input As 1 + Input #1, x$ + While (Not EOF(1)) + If (InStr(1, x$, "[aliases]", 1)) Then + Input #1, x$ + While (Not EOF(1) And (Not InStr(x$, "[")) And (aindex < MaxAlias)) + aindex = aindex + 1 + Aliases(aindex, 1) = x$ + Input #1, x$ + Wend + GoTo INI_file_done + End If + Input #1, x$ + Wend + +INI_file_done: + Close 1 + + If (aindex > 0) Then + y = 1 + While (y <= aindex) + eindex = InStr(Aliases(y, 1), "=") + If (eindex > 0) Then + Aliases(y, 2) = Scrub(Mid$(Aliases(y, 1), eindex + 1)) + Aliases(y, 1) = Scrub(Left$(Aliases(y, 1), eindex - 1)) + End If + y = y + 1 + Wend + End If +End Sub + +Sub InitBuf () + buffer.Text = "" ' Clear out text +End Sub + +Sub InitExt () + + Extensions(1) = "" + Extensions(2) = ".COM" + Extensions(3) = ".EXE" + Extensions(4) = ".BAT" + Extensions(5) = ".PIF" + +End Sub + +Sub InitPaths () + + Path$ = Environ("PATH") + + ' First, get each path component into separate array location + Pindex = 0 + start = 1 + + While (start <= Len(Path$)) + Pindex = Pindex + 1 + last = start + char$ = Mid$(Path$, last, 1) + While ((char$ <> ";") And (last <= Len(Path$))) + last = last + 1 + char$ = Mid$(Path$, last, 1) + Wend + Paths(Pindex) = Mid$(Path$, start, last - start) + start = last + 1 + Wend + + ' Now, make sure each ends with directory separator + For x = 1 To Pindex Step 1 + If (Mid$(Paths$(x), Len(Paths$(x)), 1) <> "\") Then + Paths$(x) = Paths$(x) + "\" + End If + Next +End Sub + +Sub RunCommand () + + ' Store command in (circular) history buffer + HistBuff(HistIndex) = buffer.Text + HistIndex = HistIndex + 1 + If (HistIndex > MaxHist) Then + HistRoll = 1 + HistIndex = 1 + End If + MaxHistUsed = MaxHistUsed + 1 + If (MaxHistUsed > MaxHist) Then + MaxHistUsed = MaxHist + End If + PBIndex = HistIndex + + AliasSubst + + ' If we see <, >, or |, force command interpreter use + index = 1 + bang = 0 + While (index <= Len(buffer.Text) And (bang = 0)) + Select Case Mid$(buffer.Text, index, 1) + Case "<" + bang = 1 + Case ">" + bang = 1 + Case "|" + bang = 1 + End Select + index = index + 1 + Wend + If ((bang = 1) And (Left$(buffer.Text, 1) <> "!")) Then + buffer.Text = "!" + buffer.Text + End If + + ' Should we do post-processing? + dopost = 0 + If (Left$(buffer.Text, 1) = "@") Then + buffer.Text = "!" + Mid$(buffer.Text, 2) + dopost = 1 + End If + + ' Are we pre-processing? + If (Left$(buffer.Text, 1) = "!") Then + Prefix$ = Environ$("FF_SHPRE") + If (Prefix$ = "") Then + Prefix$ = "command.com /c" + End If + Pgm$ = Mid$(buffer.Text, 2) + Else + Prefix$ = "" + Pgm$ = buffer.Text + Pgm$ = FindPgm(Pgm$) + End If + + ' Setup any relevant pre- and post-processing + If (Prefix$ <> "") Then + Pgm$ = Prefix$ + " " + Pgm$ + End If + + Postfix$ = Environ$("FF_SHPOST") + If ((Postfix$ <> "") And (dopost = 1)) Then + Pgm$ = Pgm$ + " | " + Postfix$ + End If + + ' Execute the command + On Error Resume Next + If (Pgm$ <> "") Then + TaskID = Shell(Pgm$, 1) + End If + InitBuf + +End Sub + +Function Scrub (xxx As String) As String + + ' Scrub leading and trailing spaces from the string + + z = Len(xxx) + j = 0 + k = 0 + l = 0 + + While ((j < z) And (k = 0)) ' Find start of string + j = j + 1 + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then k = j + Wend + + j = z + While ((j > 0) And (l = 0)) ' Find end of string + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then l = j + j = j - 1 + Wend + + Scrub = Mid$(xxx, k, l - k + 1) + +End Function + diff --git a/fastfngr/FASTFNGR.WRI b/fastfngr/FASTFNGR.WRI new file mode 100644 index 0000000..2c3dc53 --- /dev/null +++ b/fastfngr/FASTFNGR.WRI Binary files differ diff --git a/fastfngr/FF10D/FASTFNGR.BAS b/fastfngr/FF10D/FASTFNGR.BAS new file mode 100644 index 0000000..33a6f16 --- /dev/null +++ b/fastfngr/FF10D/FASTFNGR.BAS @@ -0,0 +1,6 @@ +'HOTKEY.DLL functions +DefInt A-Z + +Declare Function CreateHK& Lib "HOTKEY.DLL" (ByVal KeyCode, ByVal Shift, ByVal hWnd, ByVal UserVK) +Declare Sub KillHK Lib "HOTKEY.DLL" (ByVal hHotKey&) + diff --git a/fastfngr/FF10D/FASTFNGR.EXE b/fastfngr/FF10D/FASTFNGR.EXE new file mode 100644 index 0000000..089c81c --- /dev/null +++ b/fastfngr/FF10D/FASTFNGR.EXE Binary files differ diff --git a/fastfngr/FF10D/FASTFNGR.FRM b/fastfngr/FF10D/FASTFNGR.FRM new file mode 100644 index 0000000..141a21f --- /dev/null +++ b/fastfngr/FF10D/FASTFNGR.FRM Binary files differ diff --git a/fastfngr/FF10D/FASTFNGR.MAK b/fastfngr/FF10D/FASTFNGR.MAK new file mode 100644 index 0000000..d373264 --- /dev/null +++ b/fastfngr/FF10D/FASTFNGR.MAK @@ -0,0 +1,10 @@ +FASTFNGR.FRM +C:\WINDOWS\SYSTEM\CMDIALOG.VBX +C:\WINDOWS\SYSTEM\GRID.VBX +C:\WINDOWS\SYSTEM\MSOLE2.VBX +FASTFNGR.BAS +ProjWinSize=68,405,225,148 +ProjWinShow=2 +IconForm="FastFinger" +Title="FASTFNGR" +ExeName="FASTFNGR.EXE" diff --git a/fastfngr/FF10D/FASTFNGR.TXT b/fastfngr/FF10D/FASTFNGR.TXT new file mode 100644 index 0000000..1b3edd8 --- /dev/null +++ b/fastfngr/FF10D/FASTFNGR.TXT @@ -0,0 +1,262 @@ +Dim Paths(50) As String +Dim Extensions(5) As String +Dim Pindex As Integer + +Dim HistIndex +Dim HistBuff(20) As String +Dim HistRoll + +Const HOTKEY = 32 ' Space Bar +Const ToggleKey = 200 ' Value to send here + +Const SHIFT_MASK = 1 +Const CTRL_MASK = 2 +Const ALT_MASK = 4 +Const KEY_MASK = CTRL_MASK + ALT_MASK + +Const KEY_ESC = 27 + +Sub Buffer_DblClick () + If ((HistRoll <> 0) Or (HistIndex <> 1)) Then + CmdHist.Clear + index = HistIndex - 1 'Start with last cmd + While (index <> 0) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + If (HistRoll = 1) Then + index = 20 + While (index > HistIndex) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + End If + CmdHist.Visible = 1 + End If +End Sub + +Sub Buffer_KeyPress (Key As Integer) + + Select Case Key + Case 13 ' Handle Carriage Returns + If (Buffer.Text <> "") Then + RunCommand + End If + Key = 0 ' Stop the beep madness + + Case KEY_ESC ' Abort On Escape + Buffer.Text = "" + Key = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Sub CmdHist_DblClick () + + ' Only get the command - allow normal editing + Buffer.Text = CmdHist.Text + CmdHist.Visible = 0 + SendKeys "{END}" ' Position cursor at the end + +End Sub + +Sub CmdHist_KeyPress (Key As Integer) + + Select Case Key + + Case KEY_ESC ' Abort On Escape + Key = 0 + CmdHist.Visible = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Function FindFile (Pgm As String) As String + Retval$ = "" + index = 1 + + On Error GoTo error_handler + While ((Retval$ = "") And (x <= Pindex)) + trial$ = Paths$(x) + Pgm + Open trial$ For Input As 1 + Close 1 + Retval$ = trial$ +try_next: + x = x + 1 + Wend + + FindFile = Retval$ + Exit Function + +error_handler: + Close 1 + Resume try_next +End Function + +Function FindPgm (Pgm As String) As String + + ' First split into program name and arguments + index = 1 + split = 0 + Prog$ = Pgm + While ((split = 0) And (index <= Len(Pgm))) + If (Mid$(Pgm, index, 1) = " ") Then + split = index + Prog$ = Mid$(Pgm$, 1, split - 1) + Args$ = Mid$(Pgm$, split) + End If + index = index + 1 + Wend + + index = 1 + Retval$ = "" + While ((Retval$ = "") And (index <= 5)) + Retval$ = FindFile(Prog$ + Extensions(index)) + index = index + 1 + Wend + + If (Retval$ = "") Then + FindPgm = Pgm$ + Else + FindPgm = Retval$ + Args$ + End If + +End Function + +Sub Form_KeyDown (Key As Integer, Shift As Integer) + Select Case Key + Case ToggleKey + If FastFinger.Visible = 0 Then + FastFinger.Visible = 1 + Else + FastFinger.Visible = 0 + End If + End Select +End Sub + +Sub Form_Load () + Extensions(1) = "" + Extensions(2) = ".COM" + Extensions(3) = ".EXE" + Extensions(4) = ".BAT" + Extensions(5) = ".PIF" + InitBuf + InitPaths + HistIndex = 1 + HistRoll = 0 + hHotKey = CreateHK&(HOTKEY, KEY_MASK, HWnd, ToggleKey) + FastFinger.Visible = 0 + CmdHist.Visible = 0 +End Sub + +Sub Form_Unload (Cancel As Integer) + KillHK hHotKey +End Sub + +Sub InitBuf () + Buffer.Text = "" ' Clear out text +End Sub + +Sub InitPaths () + + Path$ = Environ("PATH") + + ' First, get each path component into separate array location + Pindex = 0 + start = 1 + + While (start <= Len(Path$)) + Pindex = Pindex + 1 + last = start + char$ = Mid$(Path$, last, 1) + While ((char$ <> ";") And (last <= Len(Path$))) + last = last + 1 + char$ = Mid$(Path$, last, 1) + Wend + Paths(Pindex) = Mid$(Path$, start, last - start) + start = last + 1 + Wend + + ' Now, make sure each ends with directory separator + For x = 1 To Pindex Step 1 + If (Mid$(Paths$(x), Len(Paths$(x)), 1) <> "\") Then + Paths$(x) = Paths$(x) + "\" + End If + Next +End Sub + +Sub RunCommand () + + ' Store command in (circular) history buffer + HistBuff(HistIndex) = Buffer.Text + HistIndex = HistIndex + 1 + If (HistIndex > 20) Then + HistRoll = 1 + HistIndex = 1 + End If + + ' If we see <, >, or |, force command interpreter use + index = 1 + bang = 0 + While (index <= Len(Buffer.Text) And (bang = 0)) + Select Case Mid$(Buffer.Text, index, 1) + Case "<" + bang = 1 + Case ">" + bang = 1 + Case "|" + bang = 1 + End Select + index = index + 1 + Wend + If ((bang = 1) And (Left$(Buffer.Text, 1) <> "!")) Then + Buffer.Text = "!" + Buffer.Text + End If + + ' Should we do post-processing? + dopost = 0 + If (Left$(Buffer.Text, 1) = "@") Then + Buffer.Text = "!" + Mid$(Buffer.Text, 2) + dopost = 1 + End If + + ' Are we pre-processing? + If (Left$(Buffer.Text, 1) = "!") Then + Prefix$ = Environ$("FF_SHPRE") + If (Prefix$ = "") Then + Prefix$ = "command.com /c" + End If + Pgm$ = Mid$(Buffer.Text, 2) + Else + Prefix$ = "" + Pgm$ = Buffer.Text + Pgm$ = FindPgm(Pgm$) + End If + + ' Setup any relevant pre- and post-processing + If (Prefix$ <> "") Then + Pgm$ = Prefix$ + " " + Pgm$ + End If + + Postfix$ = Environ$("FF_SHPOST") + If ((Postfix$ <> "") And (dopost = 1)) Then + Pgm$ = Pgm$ + " | " + Postfix$ + End If + + ' Execute the command + On Error Resume Next + If (Pgm$ <> "") Then + TaskID = Shell(Pgm$, 3) + End If + InitBuf + +End Sub + diff --git a/fastfngr/FF10E/FASTFNGR.BAS b/fastfngr/FF10E/FASTFNGR.BAS new file mode 100644 index 0000000..33a6f16 --- /dev/null +++ b/fastfngr/FF10E/FASTFNGR.BAS @@ -0,0 +1,6 @@ +'HOTKEY.DLL functions +DefInt A-Z + +Declare Function CreateHK& Lib "HOTKEY.DLL" (ByVal KeyCode, ByVal Shift, ByVal hWnd, ByVal UserVK) +Declare Sub KillHK Lib "HOTKEY.DLL" (ByVal hHotKey&) + diff --git a/fastfngr/FF10E/FASTFNGR.EXE b/fastfngr/FF10E/FASTFNGR.EXE new file mode 100644 index 0000000..089c81c --- /dev/null +++ b/fastfngr/FF10E/FASTFNGR.EXE Binary files differ diff --git a/fastfngr/FF10E/FASTFNGR.FRM b/fastfngr/FF10E/FASTFNGR.FRM new file mode 100644 index 0000000..fab91e2 --- /dev/null +++ b/fastfngr/FF10E/FASTFNGR.FRM Binary files differ diff --git a/fastfngr/FF10E/FASTFNGR.INI b/fastfngr/FF10E/FASTFNGR.INI new file mode 100644 index 0000000..7e68a6f --- /dev/null +++ b/fastfngr/FF10E/FASTFNGR.INI @@ -0,0 +1,3 @@ +[Aliases] +clown=bozo + diff --git a/fastfngr/FF10E/FASTFNGR.MAK b/fastfngr/FF10E/FASTFNGR.MAK new file mode 100644 index 0000000..d373264 --- /dev/null +++ b/fastfngr/FF10E/FASTFNGR.MAK @@ -0,0 +1,10 @@ +FASTFNGR.FRM +C:\WINDOWS\SYSTEM\CMDIALOG.VBX +C:\WINDOWS\SYSTEM\GRID.VBX +C:\WINDOWS\SYSTEM\MSOLE2.VBX +FASTFNGR.BAS +ProjWinSize=68,405,225,148 +ProjWinShow=2 +IconForm="FastFinger" +Title="FASTFNGR" +ExeName="FASTFNGR.EXE" diff --git a/fastfngr/FF10E/FASTFNGR.TXT b/fastfngr/FF10E/FASTFNGR.TXT new file mode 100644 index 0000000..fb8776a --- /dev/null +++ b/fastfngr/FF10E/FASTFNGR.TXT @@ -0,0 +1,274 @@ +Dim Paths(50) As String +Dim Extensions(5) As String +Dim Pindex As Integer + +Const MaxAlias = 100 +Dim Aliases(MaxAlias, 2) As String +Dim Aindex As Integer + +Const MaxHist = 20 +Dim HistIndex +Dim HistBuff(MaxHist) As String +Dim HistRoll + +Const HOTKEY = 32 ' Space Bar +Const ToggleKey = 200 ' Value to send here + +Const SHIFT_MASK = 1 +Const CTRL_MASK = 2 +Const ALT_MASK = 4 +Const KEY_MASK = CTRL_MASK + ALT_MASK + +Const KEY_ESC = 27 + +Sub Buffer_DblClick () + If ((HistRoll <> 0) Or (HistIndex <> 1)) Then + CmdHist.Clear + index = HistIndex - 1 'Start with last cmd + While (index <> 0) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + If (HistRoll = 1) Then + index = 20 + While (index > HistIndex) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + End If + CmdHist.Visible = 1 + End If +End Sub + +Sub Buffer_KeyPress (Key As Integer) + + Select Case Key + Case 13 ' Handle Carriage Returns + If (Buffer.Text <> "") Then + RunCommand + End If + Key = 0 ' Stop the beep madness + + Case KEY_ESC ' Abort On Escape + Buffer.Text = "" + Key = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Sub CmdHist_DblClick () + + ' Only get the command - allow normal editing + Buffer.Text = CmdHist.Text + CmdHist.Visible = 0 + SendKeys "{END}" ' Position cursor at the end + +End Sub + +Sub CmdHist_KeyPress (Key As Integer) + + Select Case Key + + Case KEY_ESC ' Abort On Escape + Key = 0 + CmdHist.Visible = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Function FindFile (Pgm As String) As String + Retval$ = "" + index = 1 + + On Error GoTo error_handler + While ((Retval$ = "") And (x <= Pindex)) + trial$ = Paths$(x) + Pgm + Open trial$ For Input As 1 + Close 1 + Retval$ = trial$ +try_next: + x = x + 1 + Wend + + FindFile = Retval$ + Exit Function + +error_handler: + Close 1 + Resume try_next +End Function + +Function FindPgm (Pgm As String) As String + + ' First split into program name and arguments + index = 1 + split = 0 + Prog$ = Pgm + While ((split = 0) And (index <= Len(Pgm))) + If (Mid$(Pgm, index, 1) = " ") Then + split = index + Prog$ = Mid$(Pgm$, 1, split - 1) + Args$ = Mid$(Pgm$, split) + End If + index = index + 1 + Wend + + index = 1 + Retval$ = "" + While ((Retval$ = "") And (index <= 5)) + Retval$ = FindFile(Prog$ + Extensions(index)) + index = index + 1 + Wend + + If (Retval$ = "") Then + FindPgm = Pgm$ + Else + FindPgm = Retval$ + Args$ + End If + +End Function + +Sub Form_KeyDown (Key As Integer, Shift As Integer) + Select Case Key + Case ToggleKey + If FastFinger.Visible = 0 Then + FastFinger.Visible = 1 + Else + FastFinger.Visible = 0 + End If + End Select +End Sub + +Sub Form_Load () + Extensions(1) = "" + Extensions(2) = ".COM" + Extensions(3) = ".EXE" + Extensions(4) = ".BAT" + Extensions(5) = ".PIF" + InitBuf + InitPaths + InitAliases + HistIndex = 1 + HistRoll = 0 + hHotKey = CreateHK&(HOTKEY, KEY_MASK, HWnd, ToggleKey) + FastFinger.Visible = 0 + CmdHist.Visible = 0 +End Sub + +Sub Form_Unload (Cancel As Integer) + KillHK hHotKey +End Sub + +Sub InitAliases () + + Aindex = 0 ' Means no aliases have been found + +End Sub + +Sub InitBuf () + Buffer.Text = "" ' Clear out text +End Sub + +Sub InitPaths () + + Path$ = Environ("PATH") + + ' First, get each path component into separate array location + Pindex = 0 + start = 1 + + While (start <= Len(Path$)) + Pindex = Pindex + 1 + last = start + char$ = Mid$(Path$, last, 1) + While ((char$ <> ";") And (last <= Len(Path$))) + last = last + 1 + char$ = Mid$(Path$, last, 1) + Wend + Paths(Pindex) = Mid$(Path$, start, last - start) + start = last + 1 + Wend + + ' Now, make sure each ends with directory separator + For x = 1 To Pindex Step 1 + If (Mid$(Paths$(x), Len(Paths$(x)), 1) <> "\") Then + Paths$(x) = Paths$(x) + "\" + End If + Next +End Sub + +Sub RunCommand () + + ' Store command in (circular) history buffer + HistBuff(HistIndex) = Buffer.Text + HistIndex = HistIndex + 1 + If (HistIndex > MaxHist) Then + HistRoll = 1 + HistIndex = 1 + End If + + ' If we see <, >, or |, force command interpreter use + index = 1 + bang = 0 + While (index <= Len(Buffer.Text) And (bang = 0)) + Select Case Mid$(Buffer.Text, index, 1) + Case "<" + bang = 1 + Case ">" + bang = 1 + Case "|" + bang = 1 + End Select + index = index + 1 + Wend + If ((bang = 1) And (Left$(Buffer.Text, 1) <> "!")) Then + Buffer.Text = "!" + Buffer.Text + End If + + ' Should we do post-processing? + dopost = 0 + If (Left$(Buffer.Text, 1) = "@") Then + Buffer.Text = "!" + Mid$(Buffer.Text, 2) + dopost = 1 + End If + + ' Are we pre-processing? + If (Left$(Buffer.Text, 1) = "!") Then + Prefix$ = Environ$("FF_SHPRE") + If (Prefix$ = "") Then + Prefix$ = "command.com /c" + End If + Pgm$ = Mid$(Buffer.Text, 2) + Else + Prefix$ = "" + Pgm$ = Buffer.Text + Pgm$ = FindPgm(Pgm$) + End If + + ' Setup any relevant pre- and post-processing + If (Prefix$ <> "") Then + Pgm$ = Prefix$ + " " + Pgm$ + End If + + Postfix$ = Environ$("FF_SHPOST") + If ((Postfix$ <> "") And (dopost = 1)) Then + Pgm$ = Pgm$ + " | " + Postfix$ + End If + + ' Execute the command + On Error Resume Next + If (Pgm$ <> "") Then + TaskID = Shell(Pgm$, 1) + End If + InitBuf + +End Sub + diff --git a/fastfngr/FF10F/FASTFNGR.BAS b/fastfngr/FF10F/FASTFNGR.BAS new file mode 100644 index 0000000..33a6f16 --- /dev/null +++ b/fastfngr/FF10F/FASTFNGR.BAS @@ -0,0 +1,6 @@ +'HOTKEY.DLL functions +DefInt A-Z + +Declare Function CreateHK& Lib "HOTKEY.DLL" (ByVal KeyCode, ByVal Shift, ByVal hWnd, ByVal UserVK) +Declare Sub KillHK Lib "HOTKEY.DLL" (ByVal hHotKey&) + diff --git a/fastfngr/FF10F/FASTFNGR.EXE b/fastfngr/FF10F/FASTFNGR.EXE new file mode 100644 index 0000000..089c81c --- /dev/null +++ b/fastfngr/FF10F/FASTFNGR.EXE Binary files differ diff --git a/fastfngr/FF10F/FASTFNGR.FRM b/fastfngr/FF10F/FASTFNGR.FRM new file mode 100644 index 0000000..1383c08 --- /dev/null +++ b/fastfngr/FF10F/FASTFNGR.FRM Binary files differ diff --git a/fastfngr/FF10F/FASTFNGR.INI b/fastfngr/FF10F/FASTFNGR.INI new file mode 100644 index 0000000..7e68a6f --- /dev/null +++ b/fastfngr/FF10F/FASTFNGR.INI @@ -0,0 +1,3 @@ +[Aliases] +clown=bozo + diff --git a/fastfngr/FF10F/FASTFNGR.MAK b/fastfngr/FF10F/FASTFNGR.MAK new file mode 100644 index 0000000..d373264 --- /dev/null +++ b/fastfngr/FF10F/FASTFNGR.MAK @@ -0,0 +1,10 @@ +FASTFNGR.FRM +C:\WINDOWS\SYSTEM\CMDIALOG.VBX +C:\WINDOWS\SYSTEM\GRID.VBX +C:\WINDOWS\SYSTEM\MSOLE2.VBX +FASTFNGR.BAS +ProjWinSize=68,405,225,148 +ProjWinShow=2 +IconForm="FastFinger" +Title="FASTFNGR" +ExeName="FASTFNGR.EXE" diff --git a/fastfngr/FF10F/FASTFNGR.TXT b/fastfngr/FF10F/FASTFNGR.TXT new file mode 100644 index 0000000..fb8776a --- /dev/null +++ b/fastfngr/FF10F/FASTFNGR.TXT @@ -0,0 +1,274 @@ +Dim Paths(50) As String +Dim Extensions(5) As String +Dim Pindex As Integer + +Const MaxAlias = 100 +Dim Aliases(MaxAlias, 2) As String +Dim Aindex As Integer + +Const MaxHist = 20 +Dim HistIndex +Dim HistBuff(MaxHist) As String +Dim HistRoll + +Const HOTKEY = 32 ' Space Bar +Const ToggleKey = 200 ' Value to send here + +Const SHIFT_MASK = 1 +Const CTRL_MASK = 2 +Const ALT_MASK = 4 +Const KEY_MASK = CTRL_MASK + ALT_MASK + +Const KEY_ESC = 27 + +Sub Buffer_DblClick () + If ((HistRoll <> 0) Or (HistIndex <> 1)) Then + CmdHist.Clear + index = HistIndex - 1 'Start with last cmd + While (index <> 0) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + If (HistRoll = 1) Then + index = 20 + While (index > HistIndex) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + End If + CmdHist.Visible = 1 + End If +End Sub + +Sub Buffer_KeyPress (Key As Integer) + + Select Case Key + Case 13 ' Handle Carriage Returns + If (Buffer.Text <> "") Then + RunCommand + End If + Key = 0 ' Stop the beep madness + + Case KEY_ESC ' Abort On Escape + Buffer.Text = "" + Key = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Sub CmdHist_DblClick () + + ' Only get the command - allow normal editing + Buffer.Text = CmdHist.Text + CmdHist.Visible = 0 + SendKeys "{END}" ' Position cursor at the end + +End Sub + +Sub CmdHist_KeyPress (Key As Integer) + + Select Case Key + + Case KEY_ESC ' Abort On Escape + Key = 0 + CmdHist.Visible = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Function FindFile (Pgm As String) As String + Retval$ = "" + index = 1 + + On Error GoTo error_handler + While ((Retval$ = "") And (x <= Pindex)) + trial$ = Paths$(x) + Pgm + Open trial$ For Input As 1 + Close 1 + Retval$ = trial$ +try_next: + x = x + 1 + Wend + + FindFile = Retval$ + Exit Function + +error_handler: + Close 1 + Resume try_next +End Function + +Function FindPgm (Pgm As String) As String + + ' First split into program name and arguments + index = 1 + split = 0 + Prog$ = Pgm + While ((split = 0) And (index <= Len(Pgm))) + If (Mid$(Pgm, index, 1) = " ") Then + split = index + Prog$ = Mid$(Pgm$, 1, split - 1) + Args$ = Mid$(Pgm$, split) + End If + index = index + 1 + Wend + + index = 1 + Retval$ = "" + While ((Retval$ = "") And (index <= 5)) + Retval$ = FindFile(Prog$ + Extensions(index)) + index = index + 1 + Wend + + If (Retval$ = "") Then + FindPgm = Pgm$ + Else + FindPgm = Retval$ + Args$ + End If + +End Function + +Sub Form_KeyDown (Key As Integer, Shift As Integer) + Select Case Key + Case ToggleKey + If FastFinger.Visible = 0 Then + FastFinger.Visible = 1 + Else + FastFinger.Visible = 0 + End If + End Select +End Sub + +Sub Form_Load () + Extensions(1) = "" + Extensions(2) = ".COM" + Extensions(3) = ".EXE" + Extensions(4) = ".BAT" + Extensions(5) = ".PIF" + InitBuf + InitPaths + InitAliases + HistIndex = 1 + HistRoll = 0 + hHotKey = CreateHK&(HOTKEY, KEY_MASK, HWnd, ToggleKey) + FastFinger.Visible = 0 + CmdHist.Visible = 0 +End Sub + +Sub Form_Unload (Cancel As Integer) + KillHK hHotKey +End Sub + +Sub InitAliases () + + Aindex = 0 ' Means no aliases have been found + +End Sub + +Sub InitBuf () + Buffer.Text = "" ' Clear out text +End Sub + +Sub InitPaths () + + Path$ = Environ("PATH") + + ' First, get each path component into separate array location + Pindex = 0 + start = 1 + + While (start <= Len(Path$)) + Pindex = Pindex + 1 + last = start + char$ = Mid$(Path$, last, 1) + While ((char$ <> ";") And (last <= Len(Path$))) + last = last + 1 + char$ = Mid$(Path$, last, 1) + Wend + Paths(Pindex) = Mid$(Path$, start, last - start) + start = last + 1 + Wend + + ' Now, make sure each ends with directory separator + For x = 1 To Pindex Step 1 + If (Mid$(Paths$(x), Len(Paths$(x)), 1) <> "\") Then + Paths$(x) = Paths$(x) + "\" + End If + Next +End Sub + +Sub RunCommand () + + ' Store command in (circular) history buffer + HistBuff(HistIndex) = Buffer.Text + HistIndex = HistIndex + 1 + If (HistIndex > MaxHist) Then + HistRoll = 1 + HistIndex = 1 + End If + + ' If we see <, >, or |, force command interpreter use + index = 1 + bang = 0 + While (index <= Len(Buffer.Text) And (bang = 0)) + Select Case Mid$(Buffer.Text, index, 1) + Case "<" + bang = 1 + Case ">" + bang = 1 + Case "|" + bang = 1 + End Select + index = index + 1 + Wend + If ((bang = 1) And (Left$(Buffer.Text, 1) <> "!")) Then + Buffer.Text = "!" + Buffer.Text + End If + + ' Should we do post-processing? + dopost = 0 + If (Left$(Buffer.Text, 1) = "@") Then + Buffer.Text = "!" + Mid$(Buffer.Text, 2) + dopost = 1 + End If + + ' Are we pre-processing? + If (Left$(Buffer.Text, 1) = "!") Then + Prefix$ = Environ$("FF_SHPRE") + If (Prefix$ = "") Then + Prefix$ = "command.com /c" + End If + Pgm$ = Mid$(Buffer.Text, 2) + Else + Prefix$ = "" + Pgm$ = Buffer.Text + Pgm$ = FindPgm(Pgm$) + End If + + ' Setup any relevant pre- and post-processing + If (Prefix$ <> "") Then + Pgm$ = Prefix$ + " " + Pgm$ + End If + + Postfix$ = Environ$("FF_SHPOST") + If ((Postfix$ <> "") And (dopost = 1)) Then + Pgm$ = Pgm$ + " | " + Postfix$ + End If + + ' Execute the command + On Error Resume Next + If (Pgm$ <> "") Then + TaskID = Shell(Pgm$, 1) + End If + InitBuf + +End Sub + diff --git a/fastfngr/FF20/FASTFNGR.BAS b/fastfngr/FF20/FASTFNGR.BAS new file mode 100644 index 0000000..33a6f16 --- /dev/null +++ b/fastfngr/FF20/FASTFNGR.BAS @@ -0,0 +1,6 @@ +'HOTKEY.DLL functions +DefInt A-Z + +Declare Function CreateHK& Lib "HOTKEY.DLL" (ByVal KeyCode, ByVal Shift, ByVal hWnd, ByVal UserVK) +Declare Sub KillHK Lib "HOTKEY.DLL" (ByVal hHotKey&) + diff --git a/fastfngr/FF20/FASTFNGR.EXE b/fastfngr/FF20/FASTFNGR.EXE new file mode 100644 index 0000000..b1231f8 --- /dev/null +++ b/fastfngr/FF20/FASTFNGR.EXE Binary files differ diff --git a/fastfngr/FF20/FASTFNGR.FRM b/fastfngr/FF20/FASTFNGR.FRM new file mode 100644 index 0000000..835a29b --- /dev/null +++ b/fastfngr/FF20/FASTFNGR.FRM Binary files differ diff --git a/fastfngr/FF20/FASTFNGR.INI b/fastfngr/FF20/FASTFNGR.INI new file mode 100644 index 0000000..72d7330 --- /dev/null +++ b/fastfngr/FF20/FASTFNGR.INI @@ -0,0 +1,6 @@ +[Aliases] +d = dir + +l = ls -alR +v = list + diff --git a/fastfngr/FF20/FASTFNGR.MAK b/fastfngr/FF20/FASTFNGR.MAK new file mode 100644 index 0000000..d6e81d2 --- /dev/null +++ b/fastfngr/FF20/FASTFNGR.MAK @@ -0,0 +1,10 @@ +FASTFNGR.FRM +C:\WINDOWS\SYSTEM\CMDIALOG.VBX +C:\WINDOWS\SYSTEM\GRID.VBX +C:\WINDOWS\SYSTEM\MSOLE2.VBX +FASTFNGR.BAS +ProjWinSize=68,404,225,148 +ProjWinShow=2 +IconForm="FastFinger" +Title="FASTFNGR" +ExeName="FASTFNGR.EXE" diff --git a/fastfngr/FF20/FASTFNGR.TXT b/fastfngr/FF20/FASTFNGR.TXT new file mode 100644 index 0000000..a249ae2 --- /dev/null +++ b/fastfngr/FF20/FASTFNGR.TXT @@ -0,0 +1,429 @@ +Dim Paths(50) As String +Dim Extensions(5) As String +Dim Pindex As Integer + +Const MaxAlias = 100 +Dim Aliases(MaxAlias, 2) As String +Dim aindex As Integer + +Const MaxHist = 20 +Dim HistIndex +Dim HistBuff(MaxHist) As String +Dim HistRoll +Dim PBIndex +Dim MaxHistUsed + +Const HOTKEY = 32 ' Space Bar +Const ToggleKey = 200 ' Value to send here + +Const SHIFT_MASK = 1 +Const CTRL_MASK = 2 +Const ALT_MASK = 4 +Const KEY_MASK = CTRL_MASK + ALT_MASK + +Const KEY_ESC = 27 + + +Sub AliasSubst () + + ' Do relevant alias substitutions on buffer text + x = Len(buffer.Text) + y$ = Left$(buffer.Text, 1) + If ((y$ = "!") Or (y$ = "@")) Then + z = 2 + Else + y$ = "" + z = 1 + End If + + While ((z <= x) And (Mid$(buffer.Text, z, 1) <> " ")) + z = z + 1 + Wend + + If (y$ = "") Then + q$ = Left$(buffer.Text, z - 1) + Else + q$ = Mid$(buffer.Text, 2, z - 2) + End If + + m$ = Mid$(buffer.Text, z) + r = 0 + x = 1 + While ((x <= aindex) And (r = 0)) + If (q$ = Aliases(x, 1)) Then + q$ = Aliases(x, 2) + r = 1 + End If + x = x + 1 + Wend + buffer.Text = y$ + q$ + m$ + +End Sub + +Sub Buffer_DblClick () + If ((HistRoll <> 0) Or (HistIndex <> 1)) Then + CmdHist.Clear + index = HistIndex - 1 'Start with last cmd + While (index <> 0) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + If (HistRoll = 1) Then + index = MaxHist + While (index > HistIndex) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + End If + CmdHist.Visible = 1 + End If +End Sub + +Sub Buffer_KeyPress (Key As Integer) + + Select Case Key + Case 1 ' Ctrl-A + SendKeys "{Home}" + Key = 0 ' Stop the beep madness + + Case 2 ' Ctrl-B + SendKeys "{Left}" + Key = 0 + + Case 4 ' Ctrl-D + SendKeys "{Del}" + Key = 0 + + Case 5 ' Ctrl-E + SendKeys "{End}" + Key = 0 + + Case 6 ' Ctrl-F + SendKeys "{Right}" + Key = 0 + + Case 11 ' Ctrl-K + buffer.Text = Left$(buffer.Text, buffer.SelStart) + SendKeys "{End}" + Key = 0 + + Case 13 ' Ctrl-M + If (buffer.Text <> "") Then + RunCommand + End If + Key = 0 + + Case 14 ' Ctrl-N + If PBIndex < MaxHistUsed Then + PBIndex = PBIndex + 1 + Else + PBIndex = 1 + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case 16 ' Ctrl-P + If PBIndex > 1 Then + PBIndex = PBIndex - 1 + Else + PBIndex = MaxHistUsed + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case KEY_ESC ' Abort On Escape + buffer.Text = "" + Key = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Sub CmdHist_DblClick () + + ' Only get the command - allow normal editing + buffer.Text = CmdHist.Text + CmdHist.Visible = 0 + SendKeys "{END}" ' Position cursor at the end + +End Sub + +Sub CmdHist_KeyPress (Key As Integer) + + Select Case Key + + Case KEY_ESC ' Abort On Escape + Key = 0 + CmdHist.Visible = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Function FindFile (Pgm As String) As String + Retval$ = "" + index = 1 + + On Error GoTo error_handler + While ((Retval$ = "") And (x <= Pindex)) + trial$ = Paths$(x) + Pgm + Open trial$ For Input As 1 + Close 1 + Retval$ = trial$ +try_next: + x = x + 1 + Wend + + FindFile = Retval$ + Exit Function + +error_handler: + Close 1 + Resume try_next +End Function + +Function FindPgm (Pgm As String) As String + + ' First split into program name and arguments + index = 1 + split = 0 + Prog$ = Pgm + While ((split = 0) And (index <= Len(Pgm))) + If (Mid$(Pgm, index, 1) = " ") Then + split = index + Prog$ = Mid$(Pgm$, 1, split - 1) + Args$ = Mid$(Pgm$, split) + End If + index = index + 1 + Wend + + index = 1 + Retval$ = "" + While ((Retval$ = "") And (index <= 5)) + Retval$ = FindFile(Prog$ + Extensions(index)) + index = index + 1 + Wend + + If (Retval$ = "") Then + FindPgm = Pgm$ + Else + FindPgm = Retval$ + Args$ + End If + +End Function + +Sub Form_KeyDown (Key As Integer, Shift As Integer) + Select Case Key + Case ToggleKey + If FastFinger.Visible = 0 Then + FastFinger.Visible = 1 + Else + FastFinger.Visible = 0 + End If + End Select +End Sub + +Sub Form_Load () + InitExt + InitBuf + InitPaths + InitAliases + HistIndex = 1 + HistRoll = 0 + MaxHistUsed = 0 + hHotKey = CreateHK&(HOTKEY, KEY_MASK, HWnd, ToggleKey) + FastFinger.Visible = 0 + CmdHist.Visible = 0 +End Sub + +Sub Form_Unload (Cancel As Integer) + KillHK hHotKey +End Sub + +Sub InitAliases () + + aindex = 0 ' Means no aliases have been found + IniFile$ = App.Path + "\" + App.EXEName + ".INI" + + On Error GoTo INI_file_done + Open IniFile$ For Input As 1 + Input #1, x$ + While (Not EOF(1)) + If (InStr(1, x$, "[aliases]", 1)) Then + Input #1, x$ + While (Not EOF(1) And (Not InStr(x$, "[")) And (aindex < MaxAlias)) + aindex = aindex + 1 + Aliases(aindex, 1) = x$ + Input #1, x$ + Wend + GoTo INI_file_done + End If + Input #1, x$ + Wend + +INI_file_done: + Close 1 + + If (aindex > 0) Then + y = 1 + While (y <= aindex) + eindex = InStr(Aliases(y, 1), "=") + If (eindex > 0) Then + Aliases(y, 2) = Scrub(Mid$(Aliases(y, 1), eindex + 1)) + Aliases(y, 1) = Scrub(Left$(Aliases(y, 1), eindex - 1)) + End If + y = y + 1 + Wend + End If +End Sub + +Sub InitBuf () + buffer.Text = "" ' Clear out text +End Sub + +Sub InitExt () + + Extensions(1) = "" + Extensions(2) = ".COM" + Extensions(3) = ".EXE" + Extensions(4) = ".BAT" + Extensions(5) = ".PIF" + +End Sub + +Sub InitPaths () + + Path$ = Environ("PATH") + + ' First, get each path component into separate array location + Pindex = 0 + start = 1 + + While (start <= Len(Path$)) + Pindex = Pindex + 1 + last = start + char$ = Mid$(Path$, last, 1) + While ((char$ <> ";") And (last <= Len(Path$))) + last = last + 1 + char$ = Mid$(Path$, last, 1) + Wend + Paths(Pindex) = Mid$(Path$, start, last - start) + start = last + 1 + Wend + + ' Now, make sure each ends with directory separator + For x = 1 To Pindex Step 1 + If (Mid$(Paths$(x), Len(Paths$(x)), 1) <> "\") Then + Paths$(x) = Paths$(x) + "\" + End If + Next +End Sub + +Sub RunCommand () + + ' Store command in (circular) history buffer + HistBuff(HistIndex) = buffer.Text + HistIndex = HistIndex + 1 + If (HistIndex > MaxHist) Then + HistRoll = 1 + HistIndex = 1 + End If + MaxHistUsed = MaxHistUsed + 1 + If (MaxHistUsed > MaxHist) Then + MaxHistUsed = MaxHist + End If + PBIndex = HistIndex + + AliasSubst + + ' If we see <, >, or |, force command interpreter use + index = 1 + bang = 0 + While (index <= Len(buffer.Text) And (bang = 0)) + Select Case Mid$(buffer.Text, index, 1) + Case "<" + bang = 1 + Case ">" + bang = 1 + Case "|" + bang = 1 + End Select + index = index + 1 + Wend + If ((bang = 1) And (Left$(buffer.Text, 1) <> "!")) Then + buffer.Text = "!" + buffer.Text + End If + + ' Should we do post-processing? + dopost = 0 + If (Left$(buffer.Text, 1) = "@") Then + buffer.Text = "!" + Mid$(buffer.Text, 2) + dopost = 1 + End If + + ' Are we pre-processing? + If (Left$(buffer.Text, 1) = "!") Then + Prefix$ = Environ$("FF_SHPRE") + If (Prefix$ = "") Then + Prefix$ = "command.com /c" + End If + Pgm$ = Mid$(buffer.Text, 2) + Else + Prefix$ = "" + Pgm$ = buffer.Text + Pgm$ = FindPgm(Pgm$) + End If + + ' Setup any relevant pre- and post-processing + If (Prefix$ <> "") Then + Pgm$ = Prefix$ + " " + Pgm$ + End If + + Postfix$ = Environ$("FF_SHPOST") + If ((Postfix$ <> "") And (dopost = 1)) Then + Pgm$ = Pgm$ + " | " + Postfix$ + End If + + ' Execute the command + On Error Resume Next + If (Pgm$ <> "") Then + TaskID = Shell(Pgm$, 1) + End If + InitBuf + +End Sub + +Function Scrub (xxx As String) As String + + ' Scrub leading and trailing spaces from the string + + z = Len(xxx) + j = 0 + k = 0 + l = 0 + + While ((j < z) And (k = 0)) ' Find start of string + j = j + 1 + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then k = j + Wend + + j = z + While ((j > 0) And (l = 0)) ' Find end of string + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then l = j + j = j - 1 + Wend + + Scrub = Mid$(xxx, k, l - k + 1) + +End Function + diff --git a/fastfngr/FF20C/FASTFNGR.BAS b/fastfngr/FF20C/FASTFNGR.BAS new file mode 100644 index 0000000..33a6f16 --- /dev/null +++ b/fastfngr/FF20C/FASTFNGR.BAS @@ -0,0 +1,6 @@ +'HOTKEY.DLL functions +DefInt A-Z + +Declare Function CreateHK& Lib "HOTKEY.DLL" (ByVal KeyCode, ByVal Shift, ByVal hWnd, ByVal UserVK) +Declare Sub KillHK Lib "HOTKEY.DLL" (ByVal hHotKey&) + diff --git a/fastfngr/FF20C/FASTFNGR.EXE b/fastfngr/FF20C/FASTFNGR.EXE new file mode 100644 index 0000000..d61b308 --- /dev/null +++ b/fastfngr/FF20C/FASTFNGR.EXE Binary files differ diff --git a/fastfngr/FF20C/FASTFNGR.FRM b/fastfngr/FF20C/FASTFNGR.FRM new file mode 100644 index 0000000..7f8eed1 --- /dev/null +++ b/fastfngr/FF20C/FASTFNGR.FRM Binary files differ diff --git a/fastfngr/FF20C/FASTFNGR.INI b/fastfngr/FF20C/FASTFNGR.INI new file mode 100644 index 0000000..71f12bd --- /dev/null +++ b/fastfngr/FF20C/FASTFNGR.INI @@ -0,0 +1,42 @@ +[Aliases] +3=prthplj +3l=prthplj /tr1 +4=4print -q -s -oprn +4t=c:\4tex\texfiles\4tex +bin=cdd c:\bin +c=cls +cd=cdd +ck=chkdsk +cp=copy +d=dir /o/l +dw=cdd c:\dwnl +e=exit +em=d:\emacs\emacs @d:\emacs\emacs.rc +gm=c:\bin\demacs +h=cd\ +lo=exit +ll=c:\ll\llremote +ls=ls -al +lt=latex +nu=net use /yes +p=pcopy +pk=pkarc +pl=pdel /nw +pm=pmap +pp=pp -w80 -l60 -h -n +px=pkxarc +s=ds ne /s +t=xpand type +tm=cdd c:\tmp +tn=telnet +tx=c:\telix\telix +v=list +wi=whereis +win=runwin +wp=cdd c:\docs +x= tdir +zc=pkzip -z +zk=pkzip +zl=pkunzip -v +zx=pkunzip + diff --git a/fastfngr/FF20C/FASTFNGR.MAK b/fastfngr/FF20C/FASTFNGR.MAK new file mode 100644 index 0000000..9f17e79 --- /dev/null +++ b/fastfngr/FF20C/FASTFNGR.MAK @@ -0,0 +1,10 @@ +FASTFNGR.FRM +C:\WINDOWS\SYSTEM\CMDIALOG.VBX +C:\WINDOWS\SYSTEM\GRID.VBX +C:\WINDOWS\SYSTEM\MSOLE2.VBX +FASTFNGR.BAS +ProjWinSize=76,573,225,148 +ProjWinShow=2 +IconForm="FastFinger" +Title="FASTFNGR" +ExeName="FASTFNGR.EXE" diff --git a/fastfngr/FF20C/FASTFNGR.TXT b/fastfngr/FF20C/FASTFNGR.TXT new file mode 100644 index 0000000..a249ae2 --- /dev/null +++ b/fastfngr/FF20C/FASTFNGR.TXT @@ -0,0 +1,429 @@ +Dim Paths(50) As String +Dim Extensions(5) As String +Dim Pindex As Integer + +Const MaxAlias = 100 +Dim Aliases(MaxAlias, 2) As String +Dim aindex As Integer + +Const MaxHist = 20 +Dim HistIndex +Dim HistBuff(MaxHist) As String +Dim HistRoll +Dim PBIndex +Dim MaxHistUsed + +Const HOTKEY = 32 ' Space Bar +Const ToggleKey = 200 ' Value to send here + +Const SHIFT_MASK = 1 +Const CTRL_MASK = 2 +Const ALT_MASK = 4 +Const KEY_MASK = CTRL_MASK + ALT_MASK + +Const KEY_ESC = 27 + + +Sub AliasSubst () + + ' Do relevant alias substitutions on buffer text + x = Len(buffer.Text) + y$ = Left$(buffer.Text, 1) + If ((y$ = "!") Or (y$ = "@")) Then + z = 2 + Else + y$ = "" + z = 1 + End If + + While ((z <= x) And (Mid$(buffer.Text, z, 1) <> " ")) + z = z + 1 + Wend + + If (y$ = "") Then + q$ = Left$(buffer.Text, z - 1) + Else + q$ = Mid$(buffer.Text, 2, z - 2) + End If + + m$ = Mid$(buffer.Text, z) + r = 0 + x = 1 + While ((x <= aindex) And (r = 0)) + If (q$ = Aliases(x, 1)) Then + q$ = Aliases(x, 2) + r = 1 + End If + x = x + 1 + Wend + buffer.Text = y$ + q$ + m$ + +End Sub + +Sub Buffer_DblClick () + If ((HistRoll <> 0) Or (HistIndex <> 1)) Then + CmdHist.Clear + index = HistIndex - 1 'Start with last cmd + While (index <> 0) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + If (HistRoll = 1) Then + index = MaxHist + While (index > HistIndex) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + End If + CmdHist.Visible = 1 + End If +End Sub + +Sub Buffer_KeyPress (Key As Integer) + + Select Case Key + Case 1 ' Ctrl-A + SendKeys "{Home}" + Key = 0 ' Stop the beep madness + + Case 2 ' Ctrl-B + SendKeys "{Left}" + Key = 0 + + Case 4 ' Ctrl-D + SendKeys "{Del}" + Key = 0 + + Case 5 ' Ctrl-E + SendKeys "{End}" + Key = 0 + + Case 6 ' Ctrl-F + SendKeys "{Right}" + Key = 0 + + Case 11 ' Ctrl-K + buffer.Text = Left$(buffer.Text, buffer.SelStart) + SendKeys "{End}" + Key = 0 + + Case 13 ' Ctrl-M + If (buffer.Text <> "") Then + RunCommand + End If + Key = 0 + + Case 14 ' Ctrl-N + If PBIndex < MaxHistUsed Then + PBIndex = PBIndex + 1 + Else + PBIndex = 1 + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case 16 ' Ctrl-P + If PBIndex > 1 Then + PBIndex = PBIndex - 1 + Else + PBIndex = MaxHistUsed + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case KEY_ESC ' Abort On Escape + buffer.Text = "" + Key = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Sub CmdHist_DblClick () + + ' Only get the command - allow normal editing + buffer.Text = CmdHist.Text + CmdHist.Visible = 0 + SendKeys "{END}" ' Position cursor at the end + +End Sub + +Sub CmdHist_KeyPress (Key As Integer) + + Select Case Key + + Case KEY_ESC ' Abort On Escape + Key = 0 + CmdHist.Visible = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Function FindFile (Pgm As String) As String + Retval$ = "" + index = 1 + + On Error GoTo error_handler + While ((Retval$ = "") And (x <= Pindex)) + trial$ = Paths$(x) + Pgm + Open trial$ For Input As 1 + Close 1 + Retval$ = trial$ +try_next: + x = x + 1 + Wend + + FindFile = Retval$ + Exit Function + +error_handler: + Close 1 + Resume try_next +End Function + +Function FindPgm (Pgm As String) As String + + ' First split into program name and arguments + index = 1 + split = 0 + Prog$ = Pgm + While ((split = 0) And (index <= Len(Pgm))) + If (Mid$(Pgm, index, 1) = " ") Then + split = index + Prog$ = Mid$(Pgm$, 1, split - 1) + Args$ = Mid$(Pgm$, split) + End If + index = index + 1 + Wend + + index = 1 + Retval$ = "" + While ((Retval$ = "") And (index <= 5)) + Retval$ = FindFile(Prog$ + Extensions(index)) + index = index + 1 + Wend + + If (Retval$ = "") Then + FindPgm = Pgm$ + Else + FindPgm = Retval$ + Args$ + End If + +End Function + +Sub Form_KeyDown (Key As Integer, Shift As Integer) + Select Case Key + Case ToggleKey + If FastFinger.Visible = 0 Then + FastFinger.Visible = 1 + Else + FastFinger.Visible = 0 + End If + End Select +End Sub + +Sub Form_Load () + InitExt + InitBuf + InitPaths + InitAliases + HistIndex = 1 + HistRoll = 0 + MaxHistUsed = 0 + hHotKey = CreateHK&(HOTKEY, KEY_MASK, HWnd, ToggleKey) + FastFinger.Visible = 0 + CmdHist.Visible = 0 +End Sub + +Sub Form_Unload (Cancel As Integer) + KillHK hHotKey +End Sub + +Sub InitAliases () + + aindex = 0 ' Means no aliases have been found + IniFile$ = App.Path + "\" + App.EXEName + ".INI" + + On Error GoTo INI_file_done + Open IniFile$ For Input As 1 + Input #1, x$ + While (Not EOF(1)) + If (InStr(1, x$, "[aliases]", 1)) Then + Input #1, x$ + While (Not EOF(1) And (Not InStr(x$, "[")) And (aindex < MaxAlias)) + aindex = aindex + 1 + Aliases(aindex, 1) = x$ + Input #1, x$ + Wend + GoTo INI_file_done + End If + Input #1, x$ + Wend + +INI_file_done: + Close 1 + + If (aindex > 0) Then + y = 1 + While (y <= aindex) + eindex = InStr(Aliases(y, 1), "=") + If (eindex > 0) Then + Aliases(y, 2) = Scrub(Mid$(Aliases(y, 1), eindex + 1)) + Aliases(y, 1) = Scrub(Left$(Aliases(y, 1), eindex - 1)) + End If + y = y + 1 + Wend + End If +End Sub + +Sub InitBuf () + buffer.Text = "" ' Clear out text +End Sub + +Sub InitExt () + + Extensions(1) = "" + Extensions(2) = ".COM" + Extensions(3) = ".EXE" + Extensions(4) = ".BAT" + Extensions(5) = ".PIF" + +End Sub + +Sub InitPaths () + + Path$ = Environ("PATH") + + ' First, get each path component into separate array location + Pindex = 0 + start = 1 + + While (start <= Len(Path$)) + Pindex = Pindex + 1 + last = start + char$ = Mid$(Path$, last, 1) + While ((char$ <> ";") And (last <= Len(Path$))) + last = last + 1 + char$ = Mid$(Path$, last, 1) + Wend + Paths(Pindex) = Mid$(Path$, start, last - start) + start = last + 1 + Wend + + ' Now, make sure each ends with directory separator + For x = 1 To Pindex Step 1 + If (Mid$(Paths$(x), Len(Paths$(x)), 1) <> "\") Then + Paths$(x) = Paths$(x) + "\" + End If + Next +End Sub + +Sub RunCommand () + + ' Store command in (circular) history buffer + HistBuff(HistIndex) = buffer.Text + HistIndex = HistIndex + 1 + If (HistIndex > MaxHist) Then + HistRoll = 1 + HistIndex = 1 + End If + MaxHistUsed = MaxHistUsed + 1 + If (MaxHistUsed > MaxHist) Then + MaxHistUsed = MaxHist + End If + PBIndex = HistIndex + + AliasSubst + + ' If we see <, >, or |, force command interpreter use + index = 1 + bang = 0 + While (index <= Len(buffer.Text) And (bang = 0)) + Select Case Mid$(buffer.Text, index, 1) + Case "<" + bang = 1 + Case ">" + bang = 1 + Case "|" + bang = 1 + End Select + index = index + 1 + Wend + If ((bang = 1) And (Left$(buffer.Text, 1) <> "!")) Then + buffer.Text = "!" + buffer.Text + End If + + ' Should we do post-processing? + dopost = 0 + If (Left$(buffer.Text, 1) = "@") Then + buffer.Text = "!" + Mid$(buffer.Text, 2) + dopost = 1 + End If + + ' Are we pre-processing? + If (Left$(buffer.Text, 1) = "!") Then + Prefix$ = Environ$("FF_SHPRE") + If (Prefix$ = "") Then + Prefix$ = "command.com /c" + End If + Pgm$ = Mid$(buffer.Text, 2) + Else + Prefix$ = "" + Pgm$ = buffer.Text + Pgm$ = FindPgm(Pgm$) + End If + + ' Setup any relevant pre- and post-processing + If (Prefix$ <> "") Then + Pgm$ = Prefix$ + " " + Pgm$ + End If + + Postfix$ = Environ$("FF_SHPOST") + If ((Postfix$ <> "") And (dopost = 1)) Then + Pgm$ = Pgm$ + " | " + Postfix$ + End If + + ' Execute the command + On Error Resume Next + If (Pgm$ <> "") Then + TaskID = Shell(Pgm$, 1) + End If + InitBuf + +End Sub + +Function Scrub (xxx As String) As String + + ' Scrub leading and trailing spaces from the string + + z = Len(xxx) + j = 0 + k = 0 + l = 0 + + While ((j < z) And (k = 0)) ' Find start of string + j = j + 1 + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then k = j + Wend + + j = z + While ((j > 0) And (l = 0)) ' Find end of string + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then l = j + j = j - 1 + Wend + + Scrub = Mid$(xxx, k, l - k + 1) + +End Function + diff --git a/fastfngr/FF20C/FASTFNGR.WRI b/fastfngr/FF20C/FASTFNGR.WRI new file mode 100644 index 0000000..2c3dc53 --- /dev/null +++ b/fastfngr/FF20C/FASTFNGR.WRI Binary files differ diff --git a/fastfngr/FF21/FASTFNGR.BAS b/fastfngr/FF21/FASTFNGR.BAS new file mode 100644 index 0000000..33a6f16 --- /dev/null +++ b/fastfngr/FF21/FASTFNGR.BAS @@ -0,0 +1,6 @@ +'HOTKEY.DLL functions +DefInt A-Z + +Declare Function CreateHK& Lib "HOTKEY.DLL" (ByVal KeyCode, ByVal Shift, ByVal hWnd, ByVal UserVK) +Declare Sub KillHK Lib "HOTKEY.DLL" (ByVal hHotKey&) + diff --git a/fastfngr/FF21/FASTFNGR.EXE b/fastfngr/FF21/FASTFNGR.EXE new file mode 100644 index 0000000..426c9bf --- /dev/null +++ b/fastfngr/FF21/FASTFNGR.EXE Binary files differ diff --git a/fastfngr/FF21/FASTFNGR.FRM b/fastfngr/FF21/FASTFNGR.FRM new file mode 100644 index 0000000..c186ce2 --- /dev/null +++ b/fastfngr/FF21/FASTFNGR.FRM Binary files differ diff --git a/fastfngr/FF21/FASTFNGR.MAK b/fastfngr/FF21/FASTFNGR.MAK new file mode 100644 index 0000000..9f17e79 --- /dev/null +++ b/fastfngr/FF21/FASTFNGR.MAK @@ -0,0 +1,10 @@ +FASTFNGR.FRM +C:\WINDOWS\SYSTEM\CMDIALOG.VBX +C:\WINDOWS\SYSTEM\GRID.VBX +C:\WINDOWS\SYSTEM\MSOLE2.VBX +FASTFNGR.BAS +ProjWinSize=76,573,225,148 +ProjWinShow=2 +IconForm="FastFinger" +Title="FASTFNGR" +ExeName="FASTFNGR.EXE" diff --git a/fastfngr/FF21/FASTFNGR.TXT b/fastfngr/FF21/FASTFNGR.TXT new file mode 100644 index 0000000..a249ae2 --- /dev/null +++ b/fastfngr/FF21/FASTFNGR.TXT @@ -0,0 +1,429 @@ +Dim Paths(50) As String +Dim Extensions(5) As String +Dim Pindex As Integer + +Const MaxAlias = 100 +Dim Aliases(MaxAlias, 2) As String +Dim aindex As Integer + +Const MaxHist = 20 +Dim HistIndex +Dim HistBuff(MaxHist) As String +Dim HistRoll +Dim PBIndex +Dim MaxHistUsed + +Const HOTKEY = 32 ' Space Bar +Const ToggleKey = 200 ' Value to send here + +Const SHIFT_MASK = 1 +Const CTRL_MASK = 2 +Const ALT_MASK = 4 +Const KEY_MASK = CTRL_MASK + ALT_MASK + +Const KEY_ESC = 27 + + +Sub AliasSubst () + + ' Do relevant alias substitutions on buffer text + x = Len(buffer.Text) + y$ = Left$(buffer.Text, 1) + If ((y$ = "!") Or (y$ = "@")) Then + z = 2 + Else + y$ = "" + z = 1 + End If + + While ((z <= x) And (Mid$(buffer.Text, z, 1) <> " ")) + z = z + 1 + Wend + + If (y$ = "") Then + q$ = Left$(buffer.Text, z - 1) + Else + q$ = Mid$(buffer.Text, 2, z - 2) + End If + + m$ = Mid$(buffer.Text, z) + r = 0 + x = 1 + While ((x <= aindex) And (r = 0)) + If (q$ = Aliases(x, 1)) Then + q$ = Aliases(x, 2) + r = 1 + End If + x = x + 1 + Wend + buffer.Text = y$ + q$ + m$ + +End Sub + +Sub Buffer_DblClick () + If ((HistRoll <> 0) Or (HistIndex <> 1)) Then + CmdHist.Clear + index = HistIndex - 1 'Start with last cmd + While (index <> 0) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + If (HistRoll = 1) Then + index = MaxHist + While (index > HistIndex) + CmdHist.AddItem HistBuff(index) + index = index - 1 + Wend + End If + CmdHist.Visible = 1 + End If +End Sub + +Sub Buffer_KeyPress (Key As Integer) + + Select Case Key + Case 1 ' Ctrl-A + SendKeys "{Home}" + Key = 0 ' Stop the beep madness + + Case 2 ' Ctrl-B + SendKeys "{Left}" + Key = 0 + + Case 4 ' Ctrl-D + SendKeys "{Del}" + Key = 0 + + Case 5 ' Ctrl-E + SendKeys "{End}" + Key = 0 + + Case 6 ' Ctrl-F + SendKeys "{Right}" + Key = 0 + + Case 11 ' Ctrl-K + buffer.Text = Left$(buffer.Text, buffer.SelStart) + SendKeys "{End}" + Key = 0 + + Case 13 ' Ctrl-M + If (buffer.Text <> "") Then + RunCommand + End If + Key = 0 + + Case 14 ' Ctrl-N + If PBIndex < MaxHistUsed Then + PBIndex = PBIndex + 1 + Else + PBIndex = 1 + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case 16 ' Ctrl-P + If PBIndex > 1 Then + PBIndex = PBIndex - 1 + Else + PBIndex = MaxHistUsed + End If + buffer.Text = HistBuff(PBIndex) + SendKeys "{End}" + Key = 0 + + Case KEY_ESC ' Abort On Escape + buffer.Text = "" + Key = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Sub CmdHist_DblClick () + + ' Only get the command - allow normal editing + buffer.Text = CmdHist.Text + CmdHist.Visible = 0 + SendKeys "{END}" ' Position cursor at the end + +End Sub + +Sub CmdHist_KeyPress (Key As Integer) + + Select Case Key + + Case KEY_ESC ' Abort On Escape + Key = 0 + CmdHist.Visible = 0 + + Case Else + ' Ignore All Else + + End Select + +End Sub + +Function FindFile (Pgm As String) As String + Retval$ = "" + index = 1 + + On Error GoTo error_handler + While ((Retval$ = "") And (x <= Pindex)) + trial$ = Paths$(x) + Pgm + Open trial$ For Input As 1 + Close 1 + Retval$ = trial$ +try_next: + x = x + 1 + Wend + + FindFile = Retval$ + Exit Function + +error_handler: + Close 1 + Resume try_next +End Function + +Function FindPgm (Pgm As String) As String + + ' First split into program name and arguments + index = 1 + split = 0 + Prog$ = Pgm + While ((split = 0) And (index <= Len(Pgm))) + If (Mid$(Pgm, index, 1) = " ") Then + split = index + Prog$ = Mid$(Pgm$, 1, split - 1) + Args$ = Mid$(Pgm$, split) + End If + index = index + 1 + Wend + + index = 1 + Retval$ = "" + While ((Retval$ = "") And (index <= 5)) + Retval$ = FindFile(Prog$ + Extensions(index)) + index = index + 1 + Wend + + If (Retval$ = "") Then + FindPgm = Pgm$ + Else + FindPgm = Retval$ + Args$ + End If + +End Function + +Sub Form_KeyDown (Key As Integer, Shift As Integer) + Select Case Key + Case ToggleKey + If FastFinger.Visible = 0 Then + FastFinger.Visible = 1 + Else + FastFinger.Visible = 0 + End If + End Select +End Sub + +Sub Form_Load () + InitExt + InitBuf + InitPaths + InitAliases + HistIndex = 1 + HistRoll = 0 + MaxHistUsed = 0 + hHotKey = CreateHK&(HOTKEY, KEY_MASK, HWnd, ToggleKey) + FastFinger.Visible = 0 + CmdHist.Visible = 0 +End Sub + +Sub Form_Unload (Cancel As Integer) + KillHK hHotKey +End Sub + +Sub InitAliases () + + aindex = 0 ' Means no aliases have been found + IniFile$ = App.Path + "\" + App.EXEName + ".INI" + + On Error GoTo INI_file_done + Open IniFile$ For Input As 1 + Input #1, x$ + While (Not EOF(1)) + If (InStr(1, x$, "[aliases]", 1)) Then + Input #1, x$ + While (Not EOF(1) And (Not InStr(x$, "[")) And (aindex < MaxAlias)) + aindex = aindex + 1 + Aliases(aindex, 1) = x$ + Input #1, x$ + Wend + GoTo INI_file_done + End If + Input #1, x$ + Wend + +INI_file_done: + Close 1 + + If (aindex > 0) Then + y = 1 + While (y <= aindex) + eindex = InStr(Aliases(y, 1), "=") + If (eindex > 0) Then + Aliases(y, 2) = Scrub(Mid$(Aliases(y, 1), eindex + 1)) + Aliases(y, 1) = Scrub(Left$(Aliases(y, 1), eindex - 1)) + End If + y = y + 1 + Wend + End If +End Sub + +Sub InitBuf () + buffer.Text = "" ' Clear out text +End Sub + +Sub InitExt () + + Extensions(1) = "" + Extensions(2) = ".COM" + Extensions(3) = ".EXE" + Extensions(4) = ".BAT" + Extensions(5) = ".PIF" + +End Sub + +Sub InitPaths () + + Path$ = Environ("PATH") + + ' First, get each path component into separate array location + Pindex = 0 + start = 1 + + While (start <= Len(Path$)) + Pindex = Pindex + 1 + last = start + char$ = Mid$(Path$, last, 1) + While ((char$ <> ";") And (last <= Len(Path$))) + last = last + 1 + char$ = Mid$(Path$, last, 1) + Wend + Paths(Pindex) = Mid$(Path$, start, last - start) + start = last + 1 + Wend + + ' Now, make sure each ends with directory separator + For x = 1 To Pindex Step 1 + If (Mid$(Paths$(x), Len(Paths$(x)), 1) <> "\") Then + Paths$(x) = Paths$(x) + "\" + End If + Next +End Sub + +Sub RunCommand () + + ' Store command in (circular) history buffer + HistBuff(HistIndex) = buffer.Text + HistIndex = HistIndex + 1 + If (HistIndex > MaxHist) Then + HistRoll = 1 + HistIndex = 1 + End If + MaxHistUsed = MaxHistUsed + 1 + If (MaxHistUsed > MaxHist) Then + MaxHistUsed = MaxHist + End If + PBIndex = HistIndex + + AliasSubst + + ' If we see <, >, or |, force command interpreter use + index = 1 + bang = 0 + While (index <= Len(buffer.Text) And (bang = 0)) + Select Case Mid$(buffer.Text, index, 1) + Case "<" + bang = 1 + Case ">" + bang = 1 + Case "|" + bang = 1 + End Select + index = index + 1 + Wend + If ((bang = 1) And (Left$(buffer.Text, 1) <> "!")) Then + buffer.Text = "!" + buffer.Text + End If + + ' Should we do post-processing? + dopost = 0 + If (Left$(buffer.Text, 1) = "@") Then + buffer.Text = "!" + Mid$(buffer.Text, 2) + dopost = 1 + End If + + ' Are we pre-processing? + If (Left$(buffer.Text, 1) = "!") Then + Prefix$ = Environ$("FF_SHPRE") + If (Prefix$ = "") Then + Prefix$ = "command.com /c" + End If + Pgm$ = Mid$(buffer.Text, 2) + Else + Prefix$ = "" + Pgm$ = buffer.Text + Pgm$ = FindPgm(Pgm$) + End If + + ' Setup any relevant pre- and post-processing + If (Prefix$ <> "") Then + Pgm$ = Prefix$ + " " + Pgm$ + End If + + Postfix$ = Environ$("FF_SHPOST") + If ((Postfix$ <> "") And (dopost = 1)) Then + Pgm$ = Pgm$ + " | " + Postfix$ + End If + + ' Execute the command + On Error Resume Next + If (Pgm$ <> "") Then + TaskID = Shell(Pgm$, 1) + End If + InitBuf + +End Sub + +Function Scrub (xxx As String) As String + + ' Scrub leading and trailing spaces from the string + + z = Len(xxx) + j = 0 + k = 0 + l = 0 + + While ((j < z) And (k = 0)) ' Find start of string + j = j + 1 + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then k = j + Wend + + j = z + While ((j > 0) And (l = 0)) ' Find end of string + tmp$ = Mid$(xxx, j, 1) + If (tmp$ <> " ") Then l = j + j = j - 1 + Wend + + Scrub = Mid$(xxx, k, l - k + 1) + +End Function + diff --git a/fastfngr/FF21/FASTFNGR.WRI b/fastfngr/FF21/FASTFNGR.WRI new file mode 100644 index 0000000..2c3dc53 --- /dev/null +++ b/fastfngr/FF21/FASTFNGR.WRI Binary files differ diff --git a/fastfngr/HOTKEY.DLL b/fastfngr/HOTKEY.DLL new file mode 100644 index 0000000..43465b2 --- /dev/null +++ b/fastfngr/HOTKEY.DLL Binary files differ diff --git a/fastfngr/README.1ST b/fastfngr/README.1ST new file mode 100644 index 0000000..d60c20a --- /dev/null +++ b/fastfngr/README.1ST @@ -0,0 +1,97 @@ +05-09-95 + +Thanks for taking the time to try FastFinger. Please read the installation and +user documentation below. After you've used this tool for a few days, please +fill out the questionnaire at the end of this file and return it to me (email +is fine: tundra@ct.covia.com). PLEASE: Do not redistribute these files to +other people or onto BBS systems. + + +WHAT FASTFINGER DOES +==================== + +FastFinger is a Windows utility which provides a "pop up" command line +interface from which you may launch either Windows or MS-DOS programs. By +using FastFinger you avoid having to navigate back to the Program Manager +or File Manager windows to launch other programs. + + +INSTALLATION +============ + +There are three files in the FastFinger distribution: FASTFNGR.EXE, HOTKEY.DLL, +and VBRUN300.DLL. Copy all three of these into your WINDOWS directory. + +Launch FASTFNGR.EXE as you would any other Windows program. You may find it +convenient to add it to the RUN= line of the WIN.INI file so that FastFinger is +available each time you start Windows. + + +USING FASTFINGER +================ + +When you first start FastFinger, it is running, but invisible. To make +FastFinger visible, press the Alt, Ctrl, and spacebar keys simultaneously. +Pressing this key combination again will toggle FastFinger back to its +invisible state. + +To start a program, type the program name in the FastFinger command line window +and press the Enter key. If you want to re-execute a command, use the mouse to +double-click in the command window. A scrollable list of up to the last 20 +commands will be displayed. Simply double-click on the command you wish to +re-execute. + +By default, FastFinger assumes that you entered a program name without an +extension. It searches the directories specified by the PATH environment +variable to see if it can find your program with the .COM, .EXE, .BAT, or .PIF +extensions respectively. + +FastFinger automatically launches either Windows or MS-DOS programs. If you +know your program is an MS-DOS program and want to skip the searching described +above, you can tell FastFinger to just pass the command line as you typed it to +the DOS command interpreter. This is done by beginning the command line with +an exclamation mark (!). Even if you do not use this escape mechanism, +FastFinger will automatically insert it if your command contains redirection or +piping characters (<, >, or |). + + +NOW ITS YOUR TURN ... +===================== + +Please take the time to email back the following questionnaire. Answer each +question with a number from 1 to 5 keyed as follows: + + 1) I Disagree Strongly + 2) I Tend To Disagree + 3) I Have No Opinion + 4) I Tend To Agree + 5) I Agree Strongly + + +___________________________________________________________________________________ + + QUESTIONNAIRE + ============= + +I am an experienced MS-Windows User _____ + +I am unfamiliar with MS-DOS command lines. _____ + +FastFinger made Windows use simpler. _____ + +Using FastFinger slowed me down. _____ + +FastFinger is something I now use regularly. _____ + +FastFinger does nothing I need. _____ + +FastFinger is now part of my default environment. _____ + + +OTHER COMMENTS: + + + + +___________________________________________________________________________________ + diff --git a/fastfngr/VBRUN300.DLL b/fastfngr/VBRUN300.DLL new file mode 100644 index 0000000..7966645 --- /dev/null +++ b/fastfngr/VBRUN300.DLL Binary files differ diff --git a/ff/FF.ASM b/ff/FF.ASM new file mode 100644 index 0000000..901d42a --- /dev/null +++ b/ff/FF.ASM @@ -0,0 +1,113 @@ + + PAGE 66,132 + TITLE FF.ASM +; +; +; ********** +; * FF - Automatic Printer FormFeed - Version 1.0.0 +; * Copyright (c) 1984 by T.A. Daneliuk +; * Last Modified: 07/06/84 +; ********** +; +; +; ********** +; * SYSTEM EQUATES +; ********** +; +; +FORMFEED EQU 0CH ; Formfeed character +SVC EQU 21H ; DOS System Entry +PRINT_STRING EQU 09H ; Print string call +PRINTER EQU 05H ; Print character on printer +EXIT EQU 00H ; DOS Exit Vector +EOL EQU 0A0DH ; End of Line +; +; +; ********** +; * STACK SEGMENT +; ********** +; +; +STACK SEGMENT PARA STACK 'STACK' +; +; + DB 10 DUP('STACK ') +; +; +STACK ENDS +; +; +; ********** +; * SEGMENT CONTAINING SIGNON MESSAGE +; ********** +; +; +LOGON_MSG SEGMENT WORD 'DATA' +; +; +MSG1 DB 'Printer FormFeed - Version 1.0.0' + DW EOL + DB 'Copyright (c) 1984, T.A. Daneliuk' + DW EOL + DB '$' +; +; +LOGON_MSG ENDS +; +; +; ********** +; * SEGMENT CONTAINING ACTUAL RUNTIME CODE +; ********** +; +; +RUNTIME SEGMENT WORD 'CODE' +; +; + ASSUME CS:RUNTIME,DS:LOGON_MSG,SS:STACK +; +; +START PROC FAR +; +; +; First setup the return on the stack +; +; + PUSH DS ; Save for return + XOR AX,AX + PUSH AX +; +; +; Now point DS to the message field +; +; + MOV AX,LOGON_MSG + MOV DS,AX +; +; +; Now display the message +; +; + MOV DX,OFFSET MSG1 + MOV AH,PRINT_STRING + INT SVC +; +; +; Now send the FormFeed to the printer +; +; + MOV DL,FORMFEED ; Character to send printer + MOV AH,PRINTER + INT SVC +; +; +; Time to go back to the DOS +; +; + RET +; +; +START ENDP +; +; +RUNTIME ENDS + END START diff --git a/filefind/FILEFIND.A b/filefind/FILEFIND.A new file mode 100644 index 0000000..e1ec837 --- /dev/null +++ b/filefind/FILEFIND.A @@ -0,0 +1,152 @@ +; Fixed bugs in error return handling in FindFirst and FindNext +; 02-17-87 T.A. Daneliuk +; +; +; Copyright (c) 1985 Martin Nohr and Tom Serface +; All Rights Reserved +; +;Revision Date Description +;-------- --------- -------------------------------------------- + +; Interrupt and codes for the keyboard interface. +DOSINT equ 21h ;call to ibm dos function + + cseg + +; DOS 2.0 functions to find files given filespec the argument to +; FindFirst() is a pointer to a filespec containing d:\path\filespec +; and an integer permission attribute for the files to find. +; FindNext() simply continues and fills in the DTA area with the file +; matching the next pattern. FileFind.h must be included in any subroutines +; using these routines. +; In the calling program you would first call SetDta(&dataArea); +; and then call FindFirst(filespec,attr) finally subsequent calls to +; FindNext(attr) can be made. +; The filename and attributes can be read from dataArea. + +;SetDta Set up DTA for Wild Card Conversions or whatever +; This version assumes that the Struct is in the +; programs DS. +; +; Call as SetDta(&dataArea) +; Where dataArea is struct *DTA dataArea +;void SetDta(); +;struct DTA dataArea; + + public SetDta_ +SetDta_: + push bp + mov bp,sp + mov dx,[bp+4] + mov ah,1Ah ; set disk transfer address + int DOSINT + pop bp + ret + +;GetDta Get the current DTA segment and offset +; +; Call as GetDta(&segment,&offset) +; Where segment and offset are unsigned +; +;void GetDta(); +;unsigned segment, offset; + + public GetDta_ +GetDta_: + push bp + mov bp,sp + mov ah,2fh ; get disk transfer address + int DOSINT + mov ax,es + mov si,[bp+4] + mov word [si],ax + mov si,[bp+6] + mov word [si],bx + pop bp + ret + +;RestDta Restore DTA Saved with GetDta +; +; Call as RestDta(segment,offset) +; Where segment and offset are unsigned +;void RestDta(); +;unsigned segment, offset; + + public RestDta_ +RestDta_: + push bp + mov bp,sp + push ds + mov ds,[bp+4] + mov dx,[bp+6] + mov ah,1Ah ; set disk transfer address + int DOSINT + pop ds + pop bp + ret + +;FindFirst Find the First File From a Wild Card Pattern +; +; Call as: FindFirst(filespec,attr) +; Where filespec is a char * +; and attr is an int attribute for the file +; 76543210 Bits +; 00000000 - Regular file +; 1 - Read Only +; 1 - Hidden +; 1 - System +; 1 - Volume Label +; 1 - Subdirectory +; 1 - Archive +; 1 - Unused +; 1 - Unused +; Returns 0 if no file found 1 if file is found +; +;int FindFirst(); +;char *filespec; +;int attr; + + public FindFirst_ +FindFirst_: + push bp + mov bp,sp + mov dx,[bp+4] ;pointer to filespec + mov cx,[bp+6] ;attribute to search + mov ah, 04eh + int DOSINT + and ax,ax ; 0 from DOS means file found - tad + jnz no_mor + inc ax ; found file so return 1 - tad + jmp don +no_mor: + xor ax,ax ; no file found, return 0 - tad +don: + pop bp + ret + + +;FindNext Find the Next File From a Wild Card Pattern +; +; Call as: FindNext(attr) +; Where: attr is an int attribute for the files +; to find. +; Returns 0 if no file found 1 if file is found +;int FindNext(); +;int attr; + + public FindNext_ +FindNext_: + push bp + mov bp,sp + mov cx,[bp+4] ;attribute + mov ah, 04fH ;find next file in filespec + int DOSINT + and ax,ax ; 0 from DOS means file found - tad + jnz no_more + inc ax ; found file so return 1 - tad + jmp done +no_more: + xor ax,ax ; no file found, return 0 - tad +done: + pop bp + ret diff --git a/fldedi/FLD_EDI.C b/fldedi/FLD_EDI.C new file mode 100644 index 0000000..75000f7 --- /dev/null +++ b/fldedi/FLD_EDI.C @@ -0,0 +1,34 @@ +/* fld_edi.c - Set Of Routines For Simple Field Editing + + Last Modified: 05-23-90 + Copyright (C) 1990, T.A. Daneliuk + +*/ + +#include + + + +/*============ Global Control And Keystroke Translation Tables ===============*/ + + +struct CXLATE ctrl_xlate[CTRL_ENTRY] = {2, 0, 80, NXT_FLD, /* Dn. Arrow */ + 1, 9, 0, NXT_FLD, /* Tab */ + 2, 0, 15, PRV_FLD, /* Back Tab */ + 2, 0, 72, PRV_FLD, /* Up Arrow */ + 2, 0, 73, FST_FLD, /* PgUp */ + 2, 0, 81, LST_FLD, /* PgDn */ + 2, 0, 75, CUR_LFT, /* Lft. Arrow */ + 2, 0, 77, CUR_RGT, /* Rt. Arrow */ + 2, 0, 71, BEG_FLD, /* Home */ + 2, 0, 79, END_FLD, /* End */ + 1, 10, 0, CLR_FLD, /* Ctrl-Enter */ + 2, 0, 117, CLR_END, /* Ctrl-End */ + 1, 13, 0, EXT_FLD, /* Enter */ + 2, 0, 82, INS, /* Ins */ + 2, 0, 83, DEL, /* Del */ + 1, 8, 00, BS, /* Backspace */ + 2, 0, 59, HELP, /* Fn. 1 */ + 1, 27, 0, EXT_SCR /* Esc */ + }; + diff --git a/fstam/FSTAMP.A b/fstam/FSTAMP.A new file mode 100644 index 0000000..51840da --- /dev/null +++ b/fstam/FSTAMP.A @@ -0,0 +1,123 @@ +; FSTAMP.A - Routine callable by DeSmet C returning file time/date stamp +; Copyright (c) 1986, T.A. Daneliuk +; Last Modified: 09/20/86 +; +; +; usage: fstamp(fp,date,time); +; where, fp is pointer to an open file +; date is a pointer to a character array to hold date (mm-dd-yy) +; time is a pointer to a character array to hold time (hh:mm:ss) +; +; If system call fails, the arrays are returned with zeros +; +; +; Passed Parameters +; +fp equ [bp+4] +date equ [bp+6] +time equ [bp+8] +; +; + dseg +; +; +idat db '00-00-8000:00:00' +fdate dw 0 +ftime dw 0 +; +; + cseg + public fstamp_ +; +; +fstamp_: + push bp ; Procedure prologue + mov bp,sp + push si ; Need a couple pointers + push di + mov si,time + mov di,date + mov bx,offset idat + mov cx,8 +init: mov al,[bx] + mov ds:[di],al + mov al,[bx+8] + mov ds:[si],al + inc si + inc di + inc bx + loop init + mov byte ds:[di],0 ; Put Null terminators in + mov byte ds:[si],0 + pop di + pop si + mov ax,5700h + mov bx,fp + int 21h + jc alldone ; Had and error, so quit now + mov fdate,dx ; Save binary images + mov ftime,cx + mov bx,date ; Do date digits first + inc bx ; Month field first + mov ax,dx + mov cl,5 + shr ax,cl + and ax,000fh + call addasc + add bx,3 ; Day field next + mov ax,fdate + and ax,001fh + call addasc + add bx,3 ; Year field last + mov ax,fdate + mov cl,9 + shr ax,cl + and ax,007fh + call addasc + mov bx,time ; Now do time digits + inc bx ; Hours field first + mov ax,cx + mov cl,11 + shr ax,cl + and ax,001fh + call addasc + add bx,3 ; Minutes field next + mov ax,ftime + mov cl,5 + shr ax,cl + and ax,003fh + call addasc + add bx,3 ; Seconds field last + mov ax,ftime + and ax,001fh + shl ax,1 ; Multiply by 2 + call addasc +alldone: pop bp + ret +; +; +; Do An ASCII Addition: Add Binary Contents In AL To ASCII String At BX +; +; +addasc: +top: dec al + cmp al,-1 + jz done + mov ah,[bx] + cmp ah,'9' + jz digit2 + inc byte [bx] + jmp top +digit2: mov ah,'0' + mov [bx],ah + mov ah,[bx-1] + cmp ah,'9' + jz digit3 + inc byte [bx-1] + jmp top +digit3: mov ah,'0' + mov [bx-1],ah + jmp top +done: ret + end + diff --git a/getopt/GETOPT.C b/getopt/GETOPT.C new file mode 100644 index 0000000..d8ed332 --- /dev/null +++ b/getopt/GETOPT.C @@ -0,0 +1,194 @@ +#define MODNAME "getopt" + +/***************************************************************************** +** +** GETOPT -- Function to provide look-alike functionality to the +** Unix System V getopt(3) function. +** +** See the Unix System V User's Manual getopt(3) for complete usage +** details. +** +*****************************************************************************/ +#include +/* #include */ + +typedef int BOOL; + +#define MINUS '-' +#define COLON ':' +#define QUESTION '?' +#define CNULL '\0' + + +char *optarg = NULL; +int optind = 0; + +getopt(argc,argv,optstring) +int argc; +char **argv; +char *optstring; +{ + static int curarg = 0; + static int curopt = 0; + static BOOL done = FALSE; + static char progname[13]; + char *tptr; + + if ((curarg == 0) && (curopt == 0)) + { + tptr = strrchr(*argv,'\\'); + tptr++; + tptr = strncpy(progname,tptr,12); + if ((tptr = strrchr(progname,'.')) != NULL) + *tptr = CNULL; + curarg = curopt = 1; + } + if (!done && (argv[curarg] != NULL) && (*argv[curarg] == MINUS)) + { + if ((curopt == 1) && (argv[curarg][curopt] == MINUS)) + { + curarg++; + curopt = 1; + done = TRUE; + } + else if ((tptr = strchr(optstring,argv[curarg][curopt])) != NULL) + { + curopt++; + if (*(tptr+1) == COLON) + { + if (argv[curarg][curopt] == CNULL) + { + curarg++; + optarg = argv[curarg]; + curarg++; + curopt = 1; + } + else + { + optarg = &argv[curarg][curopt]; + curarg++; + curopt = 1; + } + } + else + { + if (argv[curarg][curopt] == CNULL) + { + curarg++; + curopt = 1; + } + optarg = NULL; + } + return((int)*tptr); + } + else + { + fprintf(stderr,"%s: illegal option -- %c\n",progname,argv[curarg][curopt]); + curopt++; + if (argv[curarg][curopt] == CNULL) + { + curarg++; + curopt = 1; + } + optarg = NULL; + return((int)QUESTION); + } + } + else + done = TRUE; + + optind = curarg; + optarg = NULL; + return(EOF); +} + +/***************************************************************************** +** +** Programming Example: (taken from AT&T's Internal UNIX System Calls +** class manual, pages 2.1.4 through 2.1.12) +** +*********** +** +** #define MODNAME "test" +** +** #include +** +** extern char *optarg; +** extern int optind; +** +** main(argc,argv) +** int argc; +** char **argv; +** { +** int getopt(),c; +** static char options[] = "adf:g:"; +** int n, invalid = 0, a_ind = 0, d_ind = 0; +** char *f_ptr = NULL, *g_ptr = NULL; +** +** printf("argc contains %d\n",argc); +** printf("argv contains %0X\n\n",argv); +** +** while ((c = getopt(argc,argv,options)) != EOF) +** switch(c) +** { +** case 'a': +** { +** a_ind++; +** break; +** } +** case 'd': +** { +** d_ind++; +** break; +** } +** case 'f': +** { +** f_ptr = optarg; +** break; +** } +** case 'g': +** { +** g_ptr = optarg; +** break; +** } +** case '?': +** invalid++; +** } +** printf("argc contains %d\n",argc); +** printf("argv contains %0X\n",argv); +** printf("a_ind contains %d\n",a_ind); +** printf("d_ind contains %d\n",d_ind); +** printf("f_ptr points to %s\n",f_ptr); +** printf("g_ptr points to %s\n",g_ptr); +** printf("invalid contains %d\n",invalid); +** printf("optind contains %d\n",optind); +** for (;optind < argc;optind++) +** printf("next parameter[%d] = %s\n",optind,argv[optind]); +** return; +** } +** +*********** +** +** Invoke this example with: +** +** C>test -abcfabc -g hij -a file1 file2 +** +** Output: +** +** argc contains 7 +** argv contains FD0 +** +** TEST: illegal option -- b +** TEST: illegal option -- c +** argc contains 7 +** argv contains FD0 +** a_ind contains 2 +** d_ind contains 0 +** f_ptr points to abc +** g_ptr points to hij +** invalid contains 2 +** optind contains 5 +** next parameter[5] = file1 +** next parameter[6] = file2 +** +*****************************************************************************/ diff --git a/hsefi/HSEFI.BAS b/hsefi/HSEFI.BAS new file mode 100644 index 0000000..4c43c2c --- /dev/null +++ b/hsefi/HSEFI.BAS @@ -0,0 +1,120 @@ +10 REM Last Modified 8/4/2000 +40 OPEN "I",1,"C:\ETC\HSEDATA.DAT" +50 INPUT#1,R,U,C,I,F,G,P,A,D,H,Z,S,M1,M2,A1,D1,W,S1,M3,Y +60 CLOSE 1 +70 PRINT "INITIALIZE VALUES FOR BEGINING OF NEW MONTH Y/N";:INPUT A$ +80 IF A$="Y" GOTO 570 +90 IF A$="N" GOTO 110 +100 GOTO 70 +110 GOSUB 3000 +220 GOSUB 1090 +230 PRINT USING "REMAINING INCOME: ######.##";Y;:PRINT USING" REMAINING FREE FUNDS:######.##";B +240 PRINT +250 PRINT"ANY BILLS PAID OR EXTRA INCOME TO ENTER Y/N";:INPUT B$ +260 IF B$="Y" GOTO 600 +270 IF B$="N" GOTO 300 +280 GOTO 250 +290 PRINT +300 GOSUB 3000 +420 GOSUB 1090 +430 PRINT USING "REMAINING INCOME: ######.##";Y;:PRINT USING" REMAINING FREE FUNDS: ######.##";B +440 PRINT +450 PRINT"DO WISH TO CHANGE VALUES ANY FURTHER? Y/N";:INPUT Z$ +460 IF Z$="Y" GOTO 600 +470 IF Z$="N" GOTO 490 +480 GOTO 880 +490 PRINT"TYPE P FOR HARD-COPY OR C TO CONTINUE" +500 IF INKEY$="P" GOTO 530 +510 IF INKEY$="C" GOTO 540 +520 GOTO 500 +530 GOSUB 1110 +540 OPEN "O",1,"C:\ETC\HSEDATA.DAT":PRINT#1,R,U,C,I,F,G,P,A,D,H,Z,S,M1,M2,A1,D1,W,S1,M3,Y:CLOSE 1 +550 END +560 END +570 R=R+2225.00:Y=Y+2000.00 +580 GOTO 110 +590 END +600 PRINT"ENTER CATEGORY AND AMOUNT": :PRINT:PRINT"NOTE:VALUE IS ADDED TO INCOME, BUT SUBTRACTED FROM BILL.":PRINT +610 INPUT C$ +620 INPUT A5 +630 IF C$="Rent" GOTO 840 +640 IF C$="Utilities" GOTO 850 +650 IF C$="Car" GOTO 860 +660 IF C$="Extra1" GOTO 870 +670 IF C$="Food" GOTO 880 +680 IF C$="Gas" GOTO 890 +690 IF C$="Phone" GOTO 900 +700 IF C$="Extra2"GOTO 910 +710 IF C$="Savings" GOTO 920 +720 IF C$="Extra4" GOTO 930 +730 IF C$="Chris" GOTO 940 +740 IF C$="Extra9" GOTO 950 +750 IF C$="Extra6" GOTO 960 +760 IF C$="Extra8" GOTO 970 +770 IF C$="Extra3" GOTO 980 +780 IF C$="Meadows" GOTO 990 +790 IF C$="Extra5" GOTO 1000 +800 IF C$ ="Extra7" GOTO 1010 +810 IF C$="Credit Cards" GOTO 1020 +820 IF C$="Income" GOTO 1030 +830 PRINT "ILLEGAL CATEGORY---REDO":PRINT:GOTO 250 +840 R=R-A5:GOSUB 1050:PRINT"REMAINING Rent:"R:GOTO 250 +850 U=U-A5:GOSUB 1050:PRINT "REMAINING Utilities:"U: GOTO 250 +860 C=C-A5:GOSUB 1050:PRINT "REMAINING Car Payment"C: GOTO 250 +870 I=I-A5:GOSUB 1050:PRINT "REMAINING Extra1:"I: GOTO 250 +880 F=F-A5:GOSUB 1050:PRINT"REMAINING Food:"F:GOTO 250 +890 G=G-A5:GOSUB 1050:PRINT"REMAINING Gas:"G:GOTO 250 +900 P=P-A5:GOSUB 1050:PRINT"REMAINING Phone:"P:GOTO 250 +910 A=A-A5:GOSUB 1050:PRINT"REMAINING Extra2:"A:GOTO 250 +920 D=D-A5:GOSUB 1050:PRINT"REMAINING Savings:"D:GOTO 250 +930 H=H-A5:GOSUB 1050:PRINT"REMAINING Extra4:"H:GOTO 250 +940 Z=Z-A5:GOSUB 1050:PRINT"REMAINING DUE Chris:"Z:GOTO 250 +950 S=S-A5:GOSUB 1050:PRINT"REMAINING Savings:"S:GOTO 250 +960 M1=M1-A5:GOSUB 1050:PRINT"REMAINING Extra6:"M1:GOTO 250 +970 M2=M2-A5:GOSUB 1050:PRINT"REMAINING Extra8:"M2:GOTO 250 +980 A1=A1-A5:GOSUB 1050:PRINT"REMAINING Extra3:"A1:GOTO 250 +990 D1=D1-A5:GOSUB 1050:PRINT"REMAINING Meadows:"D1:GOTO 250 +1000 W=W-A5:GOSUB 1050:PRINT"REMAINING Extra5:"W:GOTO 250 +1010 S1=S1-A5:GOSUB 1050:PRINT"REMAINING Extra7:"S1:GOTO 250 +1020 M3=M3-A5:GOSUB 1050:PRINT"REMAINING Credit Cards:"M3:GOTO 250 +1030 Y=Y+A5:PRINT"REMAINING INCOME:"Y:GOTO 250 +1040 END +1050 Q=SGN(A5) +1060 IF Q=-1 THEN RETURN +1070 Y=Y-A5 +1080 RETURN +1090 T=R+U+C+I+F+G+P+A+D+H +1091 T=T+Z+S+M1+M2+A1+D1+W+S1+M3:B=Y-T:RETURN +1100 END +1110 LPRINT:LPRINT"PRESENT VALUES ARE:" +1120 LPRINT ,"Rent",R,"Chris",Z +1130 LPRINT ,"Credit Cards",M3,"Savings",D +1140 LPRINT ,"Meadows",D1,"Car",C +1150 LPRINT ,"Utilities",U,"Food",F +1160 LPRINT ,"Gas",G,"Phone",P +1170 LPRINT ,"Extra1",I,"Extra2",A +1180 LPRINT ,"Extra3",A1,"Extra4",H +1190 LPRINT ,"Extra5",W,"Extra6",M1 +1200 LPRINT ,"Extra7",S1,"Extra8",M2 +1210 LPRINT ,"Extra9",S +1220 LPRINT +1230 GOSUB 1090 +1240 LPRINT USING "REMAINING INCOME: ######.##";Y;:LPRINT USING" REMAINING FREE FUNDS: ######.##";B +1250 LPRINT +1260 LPRINT DATE$:LPRINT TIME$ +1270 LPRINT CHR$(12); +1280 RETURN +3000 CLS:PRINT ,"HOME FINANCE"," DISK VERSION 1.6", "August 4, 2000":PRINT ,"****************************************************************":PRINT +3010 PRINT ,"Rent",R,"Chris",Z +3020 PRINT ,"Credit Cards",M3,"Savings",D +3030 PRINT ,"Meadows",D1,"Car",C +3040 PRINT ,"Utilities",U,"Food",F +3045 PRINT ,"Gas",G,"Phone",P +3050 PRINT ,"Extra1",I,"Extra2",A +3055 PRINT ,"Extra3",A1,"Extra4",H +3060 PRINT ,"Extra5",W,"Extra6",M1 +3065 PRINT ,"Extra7",S1,"Extra8",M2 +3070 PRINT ,"Extra9",S +3080 PRINT +3090 RETURN +4000 END diff --git a/hsefi/HSEFI.EXE b/hsefi/HSEFI.EXE new file mode 100644 index 0000000..e440217 --- /dev/null +++ b/hsefi/HSEFI.EXE Binary files differ diff --git a/hsefi/HSEFI.LST b/hsefi/HSEFI.LST new file mode 100644 index 0000000..6ed7812 --- /dev/null +++ b/hsefi/HSEFI.LST @@ -0,0 +1,153 @@ + PAGE 1 + 04 Aug 00 + 18:14:18 +Offset Data Source Line Microsoft (R) QuickBASIC Compiler Version 4.00 + + 0030 0006 10 REM Last Modified 8/4/2000 + 0030 0006 40 OPEN "I",1,"C:\ETC\HSEDATA.DAT" + 0045 0006 50 INPUT#1,R,U,C,I,F,G,P,A,D,H,Z,S,M1,M2,A1,D1,W,S1,M3,Y + 0143 0056 60 CLOSE 1 + 014D 0056 70 PRINT "INITIALIZE VALUES FOR BEGINING OF NEW MONTH Y/N";:INP + UT A$ + 0180 005A 80 IF A$="Y" GOTO 570 + 0195 005A 90 IF A$="N" GOTO 110 + 01AA 005A 100 GOTO 70 + 01AC 005A 110 GOSUB 3000 + 01B4 005A 220 GOSUB 1090 + 01BC 005A 230 PRINT USING "REMAINING INCOME: ######.##";Y;:PRINT USING" + REMAINING FREE FUNDS:######.##";B + 01ED 005E 240 PRINT + 01F6 005E 250 PRINT"ANY BILLS PAID OR EXTRA INCOME TO ENTER Y/N";:INPUT B + $ + 0229 0062 260 IF B$="Y" GOTO 600 + 023E 0062 270 IF B$="N" GOTO 300 + 0253 0062 280 GOTO 250 + 0255 0062 290 PRINT + 025E 0062 300 GOSUB 3000 + 0266 0062 420 GOSUB 1090 + 026E 0062 430 PRINT USING "REMAINING INCOME: ######.##";Y;:PRINT USING" + REMAINING FREE FUNDS: ######.##";B + 029F 0062 440 PRINT + 02A8 0062 450 PRINT"DO WISH TO CHANGE VALUES ANY FURTHER? Y/N";:INPUT Z$ + 02DB 0066 460 IF Z$="Y" GOTO 600 + 02F0 0066 470 IF Z$="N" GOTO 490 + 0305 0066 480 GOTO 880 + 0308 0066 490 PRINT"TYPE P FOR HARD-COPY OR C TO CONTINUE" + 0311 0066 500 IF INKEY$="P" GOTO 530 + 0328 0066 510 IF INKEY$="C" GOTO 540 + 033F 0066 520 GOTO 500 + 0341 0066 530 GOSUB 1110 + 0349 0066 540 OPEN "O",1,"C:\ETC\HSEDATA.DAT":PRINT#1,R,U,C,I,F,G,P,A,D,H + ,Z,S,M1,M2,A1,D1,W,S1,M3,Y:CLOSE 1 + 0475 0066 550 END + 047A 0066 560 END + 047F 0066 570 R=R+2225.00:Y=Y+2000.00 + 04A1 0066 580 GOTO 110 + 04A4 0066 590 END + 04A9 0066 600 PRINT"ENTER CATEGORY AND AMOUNT": :PRINT:PRINT"NOTE:VALUE I + S ADDED TO INCOME, BUT SUBTRACTED FROM BILL.":PRINT + 04CD 0066 610 INPUT C$ + 04F7 006A 620 INPUT A5 + 0520 006E 630 IF C$="Rent" GOTO 840 + 0535 006E 640 IF C$="Utilities" GOTO 850 + 054A 006E 650 IF C$="Car" GOTO 860 + 055F 006E 660 IF C$="Extra1" GOTO 870 + 0574 006E 670 IF C$="Food" GOTO 880 + 0589 006E 680 IF C$="Gas" GOTO 890 + 059E 006E 690 IF C$="Phone" GOTO 900 + 05B3 006E 700 IF C$="Extra2"GOTO 910 + 05C8 006E 710 IF C$="Savings" GOTO 920 + PAGE 2 + 04 Aug 00 + 18:14:18 +Offset Data Source Line Microsoft (R) QuickBASIC Compiler Version 4.00 + + 05DD 006E 720 IF C$="Extra4" GOTO 930 + 05F2 006E 730 IF C$="Chris" GOTO 940 + 0607 006E 740 IF C$="Extra9" GOTO 950 + 061C 006E 750 IF C$="Extra6" GOTO 960 + 0631 006E 760 IF C$="Extra8" GOTO 970 + 0646 006E 770 IF C$="Extra3" GOTO 980 + 065B 006E 780 IF C$="Meadows" GOTO 990 + 0670 006E 790 IF C$="Extra5" GOTO 1000 + 0685 006E 800 IF C$ ="Extra7" GOTO 1010 + 069A 006E 810 IF C$="Credit Cards" GOTO 1020 + 06AF 006E 820 IF C$="Income" GOTO 1030 + 06C4 006E 830 PRINT "ILLEGAL CATEGORY---REDO":PRINT:GOTO 250 + 06D9 006E 840 R=R-A5:GOSUB 1050:PRINT"REMAINING Rent:"R:GOTO 250 + 070B 006E 850 U=U-A5:GOSUB 1050:PRINT "REMAINING Utilities:"U: GOTO 250 + 073D 006E 860 C=C-A5:GOSUB 1050:PRINT "REMAINING Car Payment"C: GOTO 250 + 076F 006E 870 I=I-A5:GOSUB 1050:PRINT "REMAINING Extra1:"I: GOTO 250 + 07A1 006E 880 F=F-A5:GOSUB 1050:PRINT"REMAINING Food:"F:GOTO 250 + 07D3 006E 890 G=G-A5:GOSUB 1050:PRINT"REMAINING Gas:"G:GOTO 250 + 0805 006E 900 P=P-A5:GOSUB 1050:PRINT"REMAINING Phone:"P:GOTO 250 + 0837 006E 910 A=A-A5:GOSUB 1050:PRINT"REMAINING Extra2:"A:GOTO 250 + 0869 006E 920 D=D-A5:GOSUB 1050:PRINT"REMAINING Savings:"D:GOTO 250 + 089B 006E 930 H=H-A5:GOSUB 1050:PRINT"REMAINING Extra4:"H:GOTO 250 + 08CD 006E 940 Z=Z-A5:GOSUB 1050:PRINT"REMAINING DUE Chris:"Z:GOTO 250 + 08FF 006E 950 S=S-A5:GOSUB 1050:PRINT"REMAINING Savings:"S:GOTO 250 + 0931 006E 960 M1=M1-A5:GOSUB 1050:PRINT"REMAINING Extra6:"M1:GOTO 250 + 0963 006E 970 M2=M2-A5:GOSUB 1050:PRINT"REMAINING Extra8:"M2:GOTO 250 + 0995 006E 980 A1=A1-A5:GOSUB 1050:PRINT"REMAINING Extra3:"A1:GOTO 250 + 09C7 006E 990 D1=D1-A5:GOSUB 1050:PRINT"REMAINING Meadows:"D1:GOTO 250 + 09F9 006E 1000 W=W-A5:GOSUB 1050:PRINT"REMAINING Extra5:"W:GOTO 250 + 0A2B 006E 1010 S1=S1-A5:GOSUB 1050:PRINT"REMAINING Extra7:"S1:GOTO 250 + 0A5D 006E 1020 M3=M3-A5:GOSUB 1050:PRINT"REMAINING Credit Cards:"M3:GOTO + 250 + 0A8F 006E 1030 Y=Y+A5:PRINT"REMAINING INCOME:"Y:GOTO 250 + 0AB9 006E 1040 END + 0ABE 006E 1050 Q=SGN(A5) + 0AD1 0072 1060 IF Q=-1 THEN RETURN + 0AEC 0072 1070 Y=Y-A5 + 0AFD 0072 1080 RETURN + 0B02 0072 1090 T=R+U+C+I+F+G+P+A+D+H + 0B3B 0076 1091 T=T+Z+S+M1+M2+A1+D1+W+S1+M3:B=Y-T:RETURN + 0B8A 0076 1100 END + 0B8F 0076 1110 LPRINT:LPRINT"PRESENT VALUES ARE:" + 0BAB 0076 1120 LPRINT ,"Rent",R,"Chris",Z + 0BE5 0076 1130 LPRINT ,"Credit Cards",M3,"Savings",D + 0C1F 0076 1140 LPRINT ,"Meadows",D1,"Car",C + 0C59 0076 1150 LPRINT ,"Utilities",U,"Food",F + 0C93 0076 1160 LPRINT ,"Gas",G,"Phone",P + 0CCD 0076 1170 LPRINT ,"Extra1",I,"Extra2",A + 0D07 0076 1180 LPRINT ,"Extra3",A1,"Extra4",H + 0D41 0076 1190 LPRINT ,"Extra5",W,"Extra6",M1 + 0D7B 0076 1200 LPRINT ,"Extra7",S1,"Extra8",M2 + 0DB5 0076 1210 LPRINT ,"Extra9",S + 0DD9 0076 1220 LPRINT + 0DE7 0076 1230 GOSUB 1090 + PAGE 3 + 04 Aug 00 + 18:14:18 +Offset Data Source Line Microsoft (R) QuickBASIC Compiler Version 4.00 + + 0DEF 0076 1240 LPRINT USING "REMAINING INCOME: ######.##";Y;:LPRINT USING + " REMAINING FREE FUNDS: ######.##";B + 0E2A 0076 1250 LPRINT + 0E38 0076 1260 LPRINT DATE$:LPRINT TIME$ + 0E58 0076 1270 LPRINT CHR$(12); + 0E71 0076 1280 RETURN + 0E76 0076 3000 CLS:PRINT ,"HOME FINANCE"," DISK VERSION 1.6", "August + 4, 2000":PRINT ,"********************************************* + *******************":PRINT + 0EBE 0076 3010 PRINT ,"Rent",R,"Chris",Z + 0EF3 0076 3020 PRINT ,"Credit Cards",M3,"Savings",D + 0F28 0076 3030 PRINT ,"Meadows",D1,"Car",C + 0F5D 0076 3040 PRINT ,"Utilities",U,"Food",F + 0F92 0076 3045 PRINT ,"Gas",G,"Phone",P + 0FC7 0076 3050 PRINT ,"Extra1",I,"Extra2",A + 0FFC 0076 3055 PRINT ,"Extra3",A1,"Extra4",H + 1031 0076 3060 PRINT ,"Extra5",W,"Extra6",M1 + 1066 0076 3065 PRINT ,"Extra7",S1,"Extra8",M2 + 109B 0076 3070 PRINT ,"Extra9",S + 10BA 0076 3080 PRINT + 10C3 0076 3090 RETURN + 10C8 0076 4000 END + 10CD 0076 + 1468 0076 + +43052 Bytes Available +38532 Bytes Free + + 0 Warning Error(s) + 0 Severe Error(s) diff --git a/hsefi/HSEFI.MAP b/hsefi/HSEFI.MAP new file mode 100644 index 0000000..d744144 --- /dev/null +++ b/hsefi/HSEFI.MAP @@ -0,0 +1,55 @@ + + Start Stop Length Name Class + 00000H 01467H 01468H HSEFI_CODE BC_CODE + 01470H 02071H 00C02H _TEXT CODE + 02072H 07BA0H 05B2FH CODE CODE + 07BA2H 07BF7H 00056H TERM_CODE CODE + 07BF8H 07E73H 0027CH INIT_CODE CODE + 07E80H 0A194H 02315H EMULATOR_TEXT CODE + 0A196H 0A196H 00000H C_ETEXT ENDCODE + 0A196H 0A19DH 00008H FAR_HDR FAR_MSG + 0A19EH 0A88BH 006EEH FAR_MSG FAR_MSG + 0A88CH 0A88DH 00002H FAR_PAD FAR_MSG + 0A88EH 0A88EH 00001H FAR_EPAD FAR_MSG + 0A890H 0A9AFH 00120H EMULATOR_DATA FAR_DATA + 0A9B0H 0A9B0H 00000H BR_DATA BLANK + 0A9B0H 0A9DFH 00030H BR_SKYS BLANK + 0A9E0H 0A9E0H 00000H COMMON BLANK + 0A9E0H 0AA55H 00076H BC_DATA BC_VARS + 0AA56H 0AA5BH 00006H NMALLOC BC_VARS + 0AA5CH 0AA5CH 00000H ENMALLOC BC_VARS + 0AA5CH 0AA5CH 00000H BC_FT BC_SEGS + 0AA60H 0AF57H 004F8H BC_CN BC_SEGS + 0AF60H 0AF62H 00003H BC_DS BC_SEGS + 0AF64H 0AF64H 00000H BC_SAB BC_SEGS + 0AF64H 0AF6BH 00008H BC_SA BC_SEGS + 0AF6CH 0B287H 0031CH _DATA DATA + 0B288H 0B295H 0000EH CDATA DATA + 0B296H 0B296H 00000H XIFB DATA + 0B296H 0B296H 00000H XIF DATA + 0B296H 0B296H 00000H XIFE DATA + 0B296H 0B296H 00000H XIB DATA + 0B296H 0B2B5H 00020H XI DATA + 0B2B6H 0B2B6H 00000H XIE DATA + 0B2B6H 0B2B6H 00000H XPB DATA + 0B2B6H 0B2B6H 00000H XP DATA + 0B2B6H 0B2B6H 00000H XPE DATA + 0B2B6H 0B2B6H 00000H XCB DATA + 0B2B6H 0B2B9H 00004H XC DATA + 0B2BAH 0B2BAH 00000H XCE DATA + 0B2BAH 0B2BAH 00000H XCFB DATA + 0B2BAH 0B2BAH 00000H XCF DATA + 0B2BAH 0B2BAH 00000H XCFE DATA + 0B2BAH 0B667H 003AEH _BSS DATA + 0B668H 0B762H 000FBH BR_DATA DATA + 0B764H 0B811H 000AEH CONST DATA + 0B812H 0B812H 00000H XOB BSS + 0B812H 0B812H 00000H XO BSS + 0B812H 0B812H 00000H XOE BSS + 0B820H 0C01FH 00800H STACK STACK + + Origin Group + 0A9B:0 DGROUP + 0A19:0 FMGROUP + +Program entry point at 0147:0010 diff --git a/hsefi/HSEFI.OBJ b/hsefi/HSEFI.OBJ new file mode 100644 index 0000000..03b8dce --- /dev/null +++ b/hsefi/HSEFI.OBJ Binary files differ diff --git a/ice/BKU b/ice/BKU new file mode 100644 index 0000000..2b90861 --- /dev/null +++ b/ice/BKU @@ -0,0 +1 @@ +c:\msc\ice\*.*/S/V diff --git a/ice/BKU.BAT b/ice/BKU.BAT new file mode 100644 index 0000000..e17ef43 --- /dev/null +++ b/ice/BKU.BAT @@ -0,0 +1,4 @@ +del c:\fastback\fastback.cat +c:\fastback\fastback @bku +c:\fastback\fastback @bku + diff --git a/ice/CVALID.DOC b/ice/CVALID.DOC new file mode 100644 index 0000000..ef1378b --- /dev/null +++ b/ice/CVALID.DOC @@ -0,0 +1,25 @@ + + + + + IceScreen Character Validation Codes + ==================================== + + Character Meaning Accepted Characters + ========= ======= =================== + + + x Any entry valid All + a Alphabetic Only (A-Z, a-z) + n Alphanumeric Only (A-Z, a-z, 0-9) + b Binary Digits (0, 1) + o Octal Digits (0-7) + d Decimal Digits (0-9) + h Hexadecimal Digits (0-9, A-F, a-f) + f Floating Point Digits (0-9, +, -, .) + s Scientific Digits (0-9, +, -, ., E, e) + $ Financial Digits (0-9, +, -, ., $) + + 0-9 Pointer To Literal Character Lists + + p Protected Literal Character diff --git a/ice/DICE b/ice/DICE new file mode 100644 index 0000000..5c534d6 --- /dev/null +++ b/ice/DICE @@ -0,0 +1,27 @@ +# ICE - Make File For IceScreen V1.D, PCDOS, BIOS Version +# Copyright (c) 1988, 1989, 1990 by T.A. Daneliuk +# Last Modified: 06-13-90 + +# ****************************** +# ****** DEBUGGING VERSION ***** +# ****************************** + + +# ----------------------------------------------------------------------------- +# Dependency Lists +# ----------------------------------------------------------------------------- + +$(model)\dicelogd.obj: ice_logd.c ice_defs.h + cl /A$(cmodel) /Od /Zi /c /V"IceScreen V1.D Copyright (c) 1988, 1989, 1990 TundraWare" /Fo$(model)\dicelogd.OBJ ice_logd.C + lib ice_libs\d_$(cmodel)_ice.LIB -+$(model)\$*.OBJ; + +$(model)\dicekeyi.obj: ice_keyi.c ice_defs.h + cl /A$(cmodel) /Od /Zi /c /V"IceScreen V1.D Copyright (c) 1988, 1989, 1990 TundraWare" /Fo$(model)\dicekeyi.OBJ ice_keyi.C + lib ice_libs\d_$(cmodel)_ice.LIB -+$(model)\$*.OBJ; + +$(model)\dicefedi.obj: ice_fedi.c ice_defs.h + cl /A$(cmodel) /Od /Zi /c /V"IceScreen V1.D Copyright (c) 1988, 1989, 1990 TundraWare" /Fo$(model)\dicefedi.OBJ ice_fedi.c + lib ice_libs\d_$(cmodel)_ice.LIB -+$(model)\$*.OBJ; + + + diff --git a/ice/DICE.BAT b/ice/DICE.BAT new file mode 100644 index 0000000..1168632 --- /dev/null +++ b/ice/DICE.BAT @@ -0,0 +1,7 @@ +echo off +make model=SMALL cmodel=S dice +make model=MEDIUM cmodel=M dice +make model=COMPACT cmodel=C dice +make model=LARGE cmodel=L dice +make model=HUGE cmodel=H dice + diff --git a/ice/HUGE/DICEFEDI.OBJ b/ice/HUGE/DICEFEDI.OBJ new file mode 100644 index 0000000..e46ba89 --- /dev/null +++ b/ice/HUGE/DICEFEDI.OBJ Binary files differ diff --git a/ice/HUGE/DICEKEYI.OBJ b/ice/HUGE/DICEKEYI.OBJ new file mode 100644 index 0000000..8f1f2eb --- /dev/null +++ b/ice/HUGE/DICEKEYI.OBJ Binary files differ diff --git a/ice/HUGE/DICELOGD.OBJ b/ice/HUGE/DICELOGD.OBJ new file mode 100644 index 0000000..94c03f7 --- /dev/null +++ b/ice/HUGE/DICELOGD.OBJ Binary files differ diff --git a/ice/HUGE/ICE_KEYI.OBJ b/ice/HUGE/ICE_KEYI.OBJ new file mode 100644 index 0000000..03e8b58 --- /dev/null +++ b/ice/HUGE/ICE_KEYI.OBJ Binary files differ diff --git a/ice/HUGE/ICE_LOGD.OBJ b/ice/HUGE/ICE_LOGD.OBJ new file mode 100644 index 0000000..7ca5722 --- /dev/null +++ b/ice/HUGE/ICE_LOGD.OBJ Binary files differ diff --git a/ice/ICE b/ice/ICE new file mode 100644 index 0000000..a1e11cf --- /dev/null +++ b/ice/ICE @@ -0,0 +1,20 @@ +# ICE - Make File For IceScreen V1.0, PCDOS, BIOS Version +# Copyright (c) 1988, 1989, 1990, By T.A. Daneliuk +# Last Modified: 06-13-90 + + + + + +# ----------------------------------------------------------------------------- +# Dependency Lists +# ----------------------------------------------------------------------------- + +$(model)\ice_logd.obj: ice_logd.c ice_defs.h + cl /A$(cmodel) /Ot /c /V"IceScreen V1.1 Copyright (c) 1988, 1989, 1990 TundraWare" /Fo$(model)\$*.OBJ $*.C + lib ice_libs\$(cmodel)_ice.LIB -+$(model)\$*.OBJ; + +$(model)\ice_keyi.obj: ice_keyi.c ice_defs.h + cl /A$(cmodel) /Ot /c /V"IceScreen V1.1 Copyright (c) 1988, 1989, 1990 TundraWare" /Fo$(model)\$*.OBJ $*.C + lib ice_libs\$(cmodel)_ice.LIB -+$(model)\$*.OBJ; + diff --git a/ice/ICE.BAT b/ice/ICE.BAT new file mode 100644 index 0000000..61b6a95 --- /dev/null +++ b/ice/ICE.BAT @@ -0,0 +1,7 @@ +echo off +make model=SMALL cmodel=S ice +make model=MEDIUM cmodel=M ice +make model=COMPACT cmodel=C ice +make model=LARGE cmodel=L ice +make model=HUGE cmodel=H ice + diff --git a/ice/ICE_DEFS.H b/ice/ICE_DEFS.H new file mode 100644 index 0000000..7cb5a92 --- /dev/null +++ b/ice/ICE_DEFS.H @@ -0,0 +1,254 @@ +/* ICE_DEFS.H - IceScreen Definitions, Global Variables, Etc. + + Last Modified: 06-06-90 + Copyright (C) 1988, 1989, 1990 by T.A. Daneliuk +*/ + + +/*========================== DEBUGGING OPTIONS ===============================*/ + +#define DEBUG 0 /* Set To 1 To Enable Debugging */ + + +/*=========================== PROGRAM DEFINITIONS ============================*/ + +#define PROGNAME "IceScreen" +#define VERSION "1.1" + +/*============================= COMPILER =====================================*/ + +#define MSC 1 /* Microsoft C */ +#define TURBO 0 /* Borland TurboC */ +#define PCCV 0 /* UNIX System V Compiler */ +#define PCCB 0 /* UNIX BSD 4.x Compiler */ +#define ANSI 1 /* Compiler is ANSI Compliant */ + + +/*========================= PRESENTATION SERVICE =============================*/ + +#define PC_BIOS 1 /* IBM-PC Via Standard Bios */ +#define PC_WIND 0 /* IBM-PC Via MS-Windows */ +#define PC_OSPM 0 /* OS/2 Presentation Manager */ +#define CURSES 0 /* UNIX Curses */ +#define XWINDOWS 0 /* Generic X-Windows */ + +/*========================== OPERATING SYSTEM ================================*/ + +#define PCDOS 1 /* Standard PC-DOS */ +#define OS_2 0 /* OS/2 */ +#define UNIXV 0 /* UNIX System V.x */ +#define UNIXB 0 /* UNIX BSD 4.x */ + + +/*=============== MISC. CONSTANTS DEFINITIONS & TYPEDEFS =====================*/ + +#define FALSE 0 +#define TRUE !FALSE + +#ifndef BOOL +typedef int BOOL; /* Boolean Datatype */ +#endif + +#if PCDOS & PC_BIOS + +#define CUROFF 32,7 /* Cursor Settings */ +#define CURSML 6,7 +#define CURBLK 0,7 + +typedef short VCOORD; /* Screen Coordinates */ +typedef short VATRB; /* Video Attribute */ +typedef short VMODE; /* Video Mode */ +typedef short VPAGE; /* Video Page */ +typedef unsigned char KEYSTR; /* Keystroke */ +typedef unsigned int VALCODE; /* Character Validation Code */ +typedef unsigned char ICE_ERROR; /* Internal Error Code */ +typedef unsigned char F_TYPE; /* Field Type Codes */ +typedef int FLEN; /* Field Length */ + +#endif + + +/*=================== SCREEN AND FIELD CONTROL STRUCTURES ====================*/ + + +struct ICE_FIELD /* FIELD Control Structure */ +{ + /* Members Common Top Both Prompt And Response Field Types */ + + F_TYPE ftype; /* Field Type */ + VCOORD frow; /* Field Vertical Position */ + VCOORD fcol; /* Field Horizontal Position */ + VATRB fattrib; /* Field Display Colors/Attributes */ + KEYSTR * field; /* Array Containing Field Contents */ + + + + /* Members Response Field Screen Control */ + + FLEN rlen; /* Maximum Allowed User Response Len. */ + VATRB rattrib; /* Input Colors/Attributes */ + VATRB cattrib; /* Attribute To Use When Clearing */ + KEYSTR rfill; /* Keyin Time Fill Character */ + KEYSTR rclear; /* Character To Use When Clearing */ + + /* Members For Single Character Validation */ + + BOOL rspace; /* TRUE Allows Blanks In Response */ + KEYSTR * mask; /* Character Validation Mask */ + KEYSTR ** v_lists; /* Array Of Char. Val. Strings */ + + + /* Members For Full Field Validation, Error Handling, Help, And Autoskip */ + + BOOL rmustfill; /* TRUE Means Field Must Be Filled */ + BOOL rreqd; /* TRUE Means A Response Is Required */ +#if ANSI + char *(*rvalid) (struct ICE_FIELD *x); /* See Below */ + void (*flderr) (struct ICE_FIELD *x, ICE_ERROR y, char *z); +#else + char *(*rvalid) (); /* Whole Field Validation Function */ + void (*flderr) (); /* Pointer To Error Handler */ +#endif + + struct ICE_SCRN *rhelp; /* Pointer To Help Screen Structure */ + BOOL rskp; /* TRUE Means Autoskip On */ +}; + + +struct ICE_SCRN /* SCREEN Control Structure */ +{ + void (* before) (); /* Do This Before Using Screen */ + void (* after) (); /* Do This Before Exiting Screen */ + struct ICE_FIELD *fields; /* Fields Present On This Screen */ + VATRB clr; /* Attribute To Use During Screen Clr.*/ + char autoborder; /* Automatically Border The Screen? */ +}; + + +/*============================= FIELD TYPES ==================================*/ + +#define FLD_PROMPT 0 +#define FLD_RESP 1 + + +/*======================= CHARACTER VALIDATION CODES =========================*/ + +#define ICE_LITERAL_L 'x' /* No Character Validation */ +#define ICE_LITERAL_U 'X' +#define ICE_LITERAL_N 'j' + +#define ICE_ALPHA_L 'a' /* Alphabetic Only */ +#define ICE_ALPHA_U 'A' +#define ICE_ALPHA_N 'k' + +#define ICE_ALPHANUM_L 'n' /* Alphanumeric Only */ +#define ICE_ALPHANUM_U 'N' +#define ICE_ALPHANUM_N 'l' + +#define ICE_BINARY 'b' /* Binary Digits Only */ +#define ICE_OCTAL 'o' /* Octal Digits Only */ +#define ICE_DECIMAL 'd' /* Decimal Digits Only */ +#define ICE_HEX_L 'h' /* Hex Digits Only */ +#define ICE_HEX_U 'H' +#define ICE_HEX_N 'u' +#define ICE_FLOATING 'f' /* Floating Point Digits Only */ +#define ICE_SCIENT_L 's' /* Scientific Digits Only */ +#define ICE_SCIENT_U 'S' +#define ICE_SCIENT_N 'v' +#define ICE_FINANCIAL '$' /* Financial Digits Only */ +#define ICE_YN_L 'y' /* Yes/No */ +#define ICE_YN_U 'Y' +#define ICE_YN_N 'w' + +#define ICE_LIST0 '0' /* Literal Lists */ +#define ICE_LIST1 '1' +#define ICE_LIST2 '2' +#define ICE_LIST3 '3' +#define ICE_LIST4 '4' +#define ICE_LIST5 '5' +#define ICE_LIST6 '6' +#define ICE_LIST7 '7' +#define ICE_LIST8 '8' +#define ICE_LIST9 '9' + + +/*=================== INTERNAL CONTROL CODE MAPPINGS ========================*/ + +/* Screen Control Codes */ + +#define HELP 0 +#define NXT_FLD 1 +#define PRV_FLD 2 +#define FST_FLD 3 +#define LST_FLD 4 +#define SCR_DONE 5 + +/* Field Control Codes */ + +#define CUR_LEFT 6 +#define CUR_RIGHT 7 +#define CUR_UP 8 +#define CUR_DOWN 9 +#define CUR_PG_UP 10 +#define CUR_PG_DOWN 11 +#define CUR_BGN_LIN 12 +#define CUR_END_LIN 13 +#define CUR_BGN_FLD 14 +#define CUR_END_FLD 15 +#define CLR_FLD 16 +#define CLR_TO_END 17 +#define CANCEL_EDIT 18 +#define INSERT 19 +#define DELETE 20 +#define BS 21 +#define FLD_DONE 22 + +/*=================== INTERNAL ERROR AND STATUS CODES =======================*/ + + +#define ICE_NOERR (ICE_ERROR) 0 /* No Error */ +#define ICE_ENOTRES (ICE_ERROR) 1 /* No Response Allow */ +#define ICE_EFNULL (ICE_ERROR) 3 /* Null Array In Fld.*/ +#define ICE_EBAD_CTRL (ICE_ERROR) 4 /* Bad Keybd. Ctrl. */ +#define ICE_NULFPTR (ICE_ERROR) 5 /* Null Fld. Ptr. */ +#define ICE_MUSTFIL (ICE_ERROR) 6 /* Must Fill Error */ +#define ICE_RESREQD (ICE_ERROR) 7 /* RReqd. Error */ +#define ICE_IEUVALID (ICE_ERROR) 8 /* User Valid. Error */ +#define ICE_NOMEM (ICE_ERROR) 9 /* Out Of Memory */ + +/*======================== FUNCTION DECLARATIONS =============================*/ + + +#if ANSI + + /*** GENERIC IceScreen FUNCTIONS ***/ + +void ice_sound(int x, int y); +void ice_cursor(unsigned char x, unsigned char y); +unsigned long ice_rdcursor(void); +void ice_rowcol(VCOORD y, VCOORD x); +void ice_cls(VATRB x); +KEYSTR ice_getc(void); +void ice_aputs(char *x, VATRB y); +KEYSTR ice_keyin(void); +ICE_ERROR ice_fedit(struct ICE_FIELD *x, KEYSTR *y); +void ice_fdsply(struct ICE_FIELD *x, BOOL y, FLEN z); + +#else + /*** GENERIC IceScreen FUNCTIONS ***/ + +void ice_sound(); +void ice_cursor(); +unsigned long ice_rdcursor(); +void ice_rowcol(); +void ice_cls(); +KEYSTR ice_getc(); +void ice_aputs(); +KEYSTR ice_keyin(); +ICE_ERROR ice_fedit(); +void ice_fdsply(); + +#endif + +/*=====================END OF INSERT DECK =======================*/ + diff --git a/ice/ICE_FEDI.C b/ice/ICE_FEDI.C new file mode 100644 index 0000000..969d5f2 --- /dev/null +++ b/ice/ICE_FEDI.C @@ -0,0 +1,160 @@ +/* ICE_FEDI.C - IceScreen Field Edit Routines + + Copyright (c) 1988, 1989, 1990 By T.A. Daneliuk + Last Modified: 06-06-90 + + These routines edit a specific field in accordance with the + definitions in a structure type called ICE_FIELD. On entry, + the calling routine passes a pointer to such a field. On + return, ICE_NOERR is returned if the edit was successful. + An error code is returned if the edit failed for some reason. + This will occur under the following conditions: + + The pointer passed to ice_fedit() is NULL (ICE_NULFPTR) + The passed structure points to a Prompt field (ICE_ENOTRES) + The the "field" structure member is NULL (ICE_EFNULL) + + The function will not accept any characters which do not meet + the character validation conditions, and will not return until + the whole field validation function passes successfully. +*/ + +#include +#include +#include +#include +#include +#include + +#if ANSI +static void dsply_fld(struct ICE_FIELD *x, FLEN y); +#else +static void dsply_fld(); +#endif + + +/*====================== MAIN FIELD EDITING FUNCTION =========================*/ + +ICE_ERROR ice_fedit(fldptr, retnkey) + +struct ICE_FIELD *fldptr; +KEYSTR *retnkey; + +{ + BOOL done, getkey, insert; + FLEN posn; + ICE_ERROR fedit_status; + KEYSTR *buffer, key; + + fedit_status = ICE_NOERR; + + if (fldptr == NULL) /* See If Bad Pointer Passed */ + fedit_status = ICE_NULFPTR; + + if (fldptr->ftype != FLD_RESP) /* See If Response Allowed */ + fedit_status = ICE_ENOTRES; + else + if (fldptr->field == NULL) /* Is Response Fld. Ptr. OK? */ + fedit_status = ICE_EFNULL; + + if ((buffer = (KEYSTR *) malloc((size_t) ((fldptr->rlen) + 1))) == NULL) + fedit_status = ICE_NOMEM; /* No Mem. For Wking. Buffer */ + + if (fedit_status != ICE_NOERR) /* Error Detected, Get Out */ + return(fedit_status); + + + insert = done = FALSE; /* Prepare To Edit Field */ + getkey = TRUE; + posn = 0; + ice_rowcol(fldptr->frow, fldptr->fcol); + (void) strcpy((char *) buffer, (char *) fldptr->field); /* Bld Wrk Buffer */ + ice_cursor(CURSML); + + while (!done) + { + if (getkey) + key = ice_keyin(); + + switch(key) + { + case NXT_FLD: /* All These Initiate Close & Exit Processing */ + case PRV_FLD: + case FST_FLD: + case LST_FLD: + case SCR_DONE: + case FLD_DONE: + *retnkey = key; + done = TRUE; + break; + + case HELP: + break; + + case CUR_LEFT: + break; + + case CUR_RIGHT: + break; + + case CUR_UP: + break; + + case CUR_DOWN: + break; + + case CUR_PG_UP: + break; + + case CUR_PG_DOWN: + break; + + case CUR_BGN_LIN: + break; + + case CUR_END_LIN: + break; + + case CUR_BGN_FLD: + break; + + case CUR_END_FLD: + break; + + case CLR_FLD: + break; + + case CLR_TO_END: + break; + + case CANCEL_EDIT: + break; + + case INSERT: + break; + + case DELETE: + break; + + case BS: + break; + + default: + break; + } + + } + + free(buffer); + return(fedit_status); +} + +/*************** Paint All Or Part Of A Field With Trailing Fill **************/ + +static void dsply_fld(buffer, offset) +struct ICE_FIELD *buffer; +FLEN offset; + +{ + +} diff --git a/ice/ICE_KEYI.C b/ice/ICE_KEYI.C new file mode 100644 index 0000000..236e0ac --- /dev/null +++ b/ice/ICE_KEYI.C @@ -0,0 +1,198 @@ +/* ICE_KEYIN.C - IceScreen Keystroke Capture & Mapping Routines + This Code Captures A Keystroke And Maps It According + To The Global Key Value Maps. + + Last Modified: 06-05-90 + Copyright (C) 1988, 1989, 1990 by T.A. Daneliuk + + +*/ + + +#include +#include + +#define K_XLATE ((unsigned) ((KEYSTR) -1))+1 /* # of unique keyvals */ + +KEYSTR key_xlate[K_XLATE] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, 197, + 198, 199, 200, 201, 202, 203, 204, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255 + }; + +/*====================== Get And Map Keyboard Input ==========================*/ + +KEYSTR ice_keyin() + +{ + + static char progname[] = PROGNAME; + static char version[] = VERSION; + static char module[] = "ice_keyin()"; + + KEYSTR key, retval; + BOOL validkey; + + validkey = FALSE; + while(!validkey) + { + key = ice_getc(); + switch (key) + { + case 0: /* Control Sequence Introducer */ + key = ice_getc(); + switch (key) + { + case 15: /* BACKTAB */ + retval = (KEYSTR) PRV_FLD; + validkey = TRUE; + break; + + case 117: /* Ctrl-END */ + retval = (KEYSTR) CUR_END_FLD; + validkey = TRUE; + break; + + case 119: /* Ctrl-HOME */ + retval = (KEYSTR) CUR_BGN_FLD; + validkey = TRUE; + break; + + case 83: /* DEL */ + retval = (KEYSTR) DELETE; + validkey = TRUE; + break; + + case 80: /* DOWN ARROW */ + retval = (KEYSTR) CUR_DOWN; + validkey = TRUE; + break; + + case 79: /* END */ + retval = (KEYSTR) CUR_END_LIN; + validkey = TRUE; + break; + + case 71: /* HOME */ + retval = (KEYSTR) CUR_BGN_LIN; + validkey = TRUE; + break; + + case 82: /* INS */ + retval = (KEYSTR) INSERT; + validkey = TRUE; + break; + + case 75: /* LEFT ARROW */ + retval = (KEYSTR) CUR_LEFT; + validkey = TRUE; + break; + + case 59: /* PF 1 */ + retval = (KEYSTR) HELP; + validkey = TRUE; + break; + + case 81: /* PgDn */ + retval = (KEYSTR) CUR_PG_DOWN; + validkey = TRUE; + break; + + case 73: /* PgUp */ + retval = (KEYSTR) CUR_PG_UP; + validkey = TRUE; + break; + + case 77: /* RIGHT ARROW */ + retval = (KEYSTR) CUR_RIGHT; + validkey = TRUE; + break; + + case 72: /* UP ARROW */ + retval = (KEYSTR) CUR_UP; + validkey = TRUE; + break; + + case 132: /* Ctrl-PgUp */ + retval = (KEYSTR) FST_FLD; + validkey = TRUE; + break; + + case 118: /* Ctrl-PgDn */ + retval = (KEYSTR) LST_FLD; + validkey = TRUE; + break; + } + break; + + case 9: /* TAB */ + retval = (KEYSTR) NXT_FLD; + validkey = TRUE; + break; + + case 8: /* BACKSPACE */ + retval = (KEYSTR) BS; + validkey = TRUE; + break; + + case 10: /* Ctrl-ENTER */ + retval = (KEYSTR) CLR_FLD; + validkey = TRUE; + break; + + case 13: /* ENTER */ + retval = (KEYSTR) FLD_DONE; + validkey = TRUE; + break; + + case 27: /* ESCAPE */ + retval = (KEYSTR) SCR_DONE; + validkey = TRUE; + break; + + case 03: /* Ctrl-C */ + retval = (KEYSTR) CANCEL_EDIT; + validkey = TRUE; + break; + + case 11: /* Ctrl-K */ + retval = (KEYSTR) CLR_TO_END; + validkey = TRUE; + break; + + default: + retval = (KEYSTR) key_xlate[key]; + validkey = TRUE; + break; + } + } + + return(retval); + +} diff --git a/ice/ICE_LIBS/D_H_ICE.LIB b/ice/ICE_LIBS/D_H_ICE.LIB new file mode 100644 index 0000000..367cabc --- /dev/null +++ b/ice/ICE_LIBS/D_H_ICE.LIB Binary files differ diff --git a/ice/ICE_LIBS/D_L_ICE.LIB b/ice/ICE_LIBS/D_L_ICE.LIB new file mode 100644 index 0000000..5bacba9 --- /dev/null +++ b/ice/ICE_LIBS/D_L_ICE.LIB Binary files differ diff --git a/ice/ICE_LIBS/D__ICE.LIB b/ice/ICE_LIBS/D__ICE.LIB new file mode 100644 index 0000000..1a25ffd --- /dev/null +++ b/ice/ICE_LIBS/D__ICE.LIB Binary files differ diff --git a/ice/ICE_LIBS/H_ICE.LIB b/ice/ICE_LIBS/H_ICE.LIB new file mode 100644 index 0000000..e886a60 --- /dev/null +++ b/ice/ICE_LIBS/H_ICE.LIB Binary files differ diff --git a/ice/ICE_LIBS/L_ICE.LIB b/ice/ICE_LIBS/L_ICE.LIB new file mode 100644 index 0000000..5514bbb --- /dev/null +++ b/ice/ICE_LIBS/L_ICE.LIB Binary files differ diff --git a/ice/ICE_LOGD.C b/ice/ICE_LOGD.C new file mode 100644 index 0000000..2e6ecd4 --- /dev/null +++ b/ice/ICE_LOGD.C @@ -0,0 +1,49 @@ +/* ICE_LOGDVR.C - IceScreen Logical Device Driver Interfaces + + Last Modified: 06-13-90 + Copyright (C) 1988, 1989, 1990 by T.A. Daneliuk +*/ + +#include +#include +#include +#include + +/*============================ Low-Level Keyboard Read =======================*/ + +KEYSTR ice_getc() + +{ + union REGS inregs, outregs; + + inregs.h.ah = 7; + intdos(&inregs, &outregs); + return((KEYSTR) outregs.h.al); +} + +/*============================ Position Cursor ===============================*/ + +void ice_rowcol(row, col) +VCOORD row, col; + +{ + + + row += (col/80); /* Normalize Coordinates For 80 x 25 Screen */ + col %= 80; + row %= 25; + col++; /* MSC Routines Are 1,1 Relative */ + row++; + _settextposition(row, col); +} + +/*======================= Write String With Attribute ========================*/ + +void ice_aputs(str, attr) +char *str; +VATRB attr; + +{ + _settextcolor(attr); + _outtext(str); +} diff --git a/ice/LARGE/DICEFEDI.OBJ b/ice/LARGE/DICEFEDI.OBJ new file mode 100644 index 0000000..83c1d76 --- /dev/null +++ b/ice/LARGE/DICEFEDI.OBJ Binary files differ diff --git a/ice/LARGE/DICEKEYI.OBJ b/ice/LARGE/DICEKEYI.OBJ new file mode 100644 index 0000000..f4af8f8 --- /dev/null +++ b/ice/LARGE/DICEKEYI.OBJ Binary files differ diff --git a/ice/LARGE/DICELOGD.OBJ b/ice/LARGE/DICELOGD.OBJ new file mode 100644 index 0000000..5fa6a4c --- /dev/null +++ b/ice/LARGE/DICELOGD.OBJ Binary files differ diff --git a/ice/LARGE/ICE_KEYI.OBJ b/ice/LARGE/ICE_KEYI.OBJ new file mode 100644 index 0000000..3e1d0ea --- /dev/null +++ b/ice/LARGE/ICE_KEYI.OBJ Binary files differ diff --git a/ice/LARGE/ICE_LOGD.OBJ b/ice/LARGE/ICE_LOGD.OBJ new file mode 100644 index 0000000..7ca5722 --- /dev/null +++ b/ice/LARGE/ICE_LOGD.OBJ Binary files differ diff --git a/ice/PCBIOS.ASM b/ice/PCBIOS.ASM new file mode 100644 index 0000000..b8d519e --- /dev/null +++ b/ice/PCBIOS.ASM @@ -0,0 +1,285 @@ + PAGE 88,132 + TITLE System Specific Routines For IBM-PC Using BIOS + SUBTTL Copyright (c) 1986, 1987, 1988 T.A. Daneliuk +; +; Last Modified: 07-26-88 +; + + +; ======================= Setup, Notes, And Facts ============================= + +; Must Use /Dmemmodel=model size on MASM command line !!!!! +% .model memmodel,c + +.LALL ; Want To See All MASM Generated Expansions + + +; =========================== Data Section ==================================== + .data + +; =========================== Actual Data ===================================== + +VIDEO_MODE db 3 ; Current Video Mode +VIDEO_PAGE db 0 ; Current Video Page +VIDEO_WIDTH dw 80 ; Current Screen Width +VIDEO_HEIGHT dw 25 ; Current Screen Height + +; =========================== Code Section ==================================== + + .code + + +; ========================= Sound Generation ================================== +; +; USAGE: pcbios_sound(FREQ,DURATION) +; WHERE, FREQ is unsigned int in Hertz +; DURATION is unsigned int (18 per second) +; +; +portb_8255 equ 61h ; 8255 port b +freq_8253 equ 42h ; 8253 timer latch +command_8253 equ 43h ; 8253 time command register +clockh equ 0012h ; clock rate high byte - 1193180 hz +clockl equ 34dch ; clock rate low byte + +; +; +pcbios_sound proc freq:word, duration:word +; +local elapsed:word ; elapsed time ticks stored here +local startl:word ; stores initial timer count +local starth:word +; +; + xor ax,ax ; zero register + mov elapsed,ax ; init. elapsed time + mov startl, ax ; init. startl + mov starth,ax ; init. starth + mov ax,freq ; make sure freq. <> 0! + and ax,ax + jz sound_done ; if so, skip the whole thing + in al,portb_8255 ; get current 8255 value + or al,3 ; turn on speaker/gate signal + out portb_8255,al ; write back to 8255 + mov al,0b6h ; tell timer, frequency is sent next + out command_8253,al + mov dx,clockh ; divide clock rate by passed + mov ax,clockl ; frequency to get total + mov cx,freq ; number of ticks to wait + div cx + out freq_8253,al ; low byte to timer + xchg al,ah ; intel's neat instruction set! + out freq_8253,al ; high byte to timer + xor ax,ax ; get current timer count in cx:dx + int 1ah + mov starth,cx ; save for future reference + mov startl,dx +delay: mov ax,duration ; wait till elapsed time is + cmp ax,elapsed ; >= duration passed on stack + jbe sound_off + xor ax,ax ; get current timer count + int 1ah + mov ax,starth ; get starting time + mov bx,startl + sub dx,bx ; low word first + sbb cx,ax ; high word with carry + jnz sound_off ; only can deal with 16 bit intervals + mov elapsed,dx ; save time elapsed + jmp delay +sound_off: in al,portb_8255 ; turn off speaker/gate signal + and al,11111100b + out portb_8255,al +sound_done: ret ; there's no place like home! +; +pcbios_sound endp + + +; ========================== Set Cursor Size ================================== +; +; usage: pcbios_cursor(startline, endline) +; +; startline & endline define starting and ending +; scanlines respectively +; +; +pcbios_cursor proc sline:byte, eline:byte +; + mov ah,1 + mov ch,sline + mov cl,eline + int 10h + ret +; +pcbios_cursor endp + + +; ======================== Read Current Cursor Position ======================= + +pcbios_rdcursor proc uses ds +; + mov ax,DGROUP + mov ds, ax + mov ah,3 + mov bh,VIDEO_PAGE + int 10h + mov ax,dx ; ah=row, al=column + mov dx,cx ; dh=1st scan line, dl=last + ret +; +pcbios_rdcursor endp + +; ======================== Absolute Cursor Positioning ======================== +; +; usage: pcbios_rowcol(x-coordinate, y-coordinate) +; +; if coordinates > than physical screen: +; +; x position overflows from right end of screen to next line +; y position wraps to top of screen +; +pcbios_rowcol proc uses ds, ypos:word, xpos:word +; + mov ax,DGROUP + mov ds, ax + mov ax,VIDEO_WIDTH + mov bx,VIDEO_HEIGHT + mov dx,xpos + mov cx,ypos +check_xposn: cmp ax,dx ; Bounds Check On X-coord + jg check_yposn + sub dx,ax ; Do modulo ax arithmetic + inc cx ; And Move Down A Line + jmp check_xposn +check_yposn: cmp cx,bx ; Bounds Check On Y-coord + jl set_row_col + sub cx,bx + jmp check_yposn +set_row_col: mov ypos,cx ; Save The Normalized Values + mov xpos,dx + mov ah,2 + mov bh,VIDEO_PAGE + mov dh,cl + int 10h + mov ax,xpos ; Return Normalized Coordinates + mov dx,ypos + ret +; +pcbios_rowcol endp + + +; ====================Clear Screen With Video Attribute ======================= + +pcbios_cls proc cls_attrib:byte +; + mov ax,0600H ; Scroll Up Whole Screen + mov bh,cls_attrib + xor cx,cx ; Start At 0,0 + mov dx,184FH + int 10H + ret +; +pcbios_cls endp + + +; =========================== Get A Keystroke ================================= + +pcbios_getc proc +; + mov ah,7 + int 21h + ret +; +pcbios_getc endp + + +; ===================== Write String With Video Attribute ===================== + +pcbios_aputs proc uses ds es, string:ptr, attr:byte +; +local row:word ; Current Row +local col:word ; Current Column +local lcount:word ; Length Count +; + mov ax,DGROUP + mov ds, ax + mov lcount,0 ; Initialize Length Count + call pcbios_rdcursor ; Get Current Position + mov dl,ah + xor ah,ah + mov col,ax + xor dh,dh + mov row,dx + IF @DataSize ; Use Pointer Based On Model + les si,string + ELSE + mov si,string + ENDIF +get_a_char: mov al,es:[si] ; Get A Character + and al,al ; If 0, We're Done! + jz aputs_done + mov ah,9 + mov bh,VIDEO_PAGE + mov bl,attr + xor cx,cx ; Repeat 1 Time + inc cx + int 10h + inc col + push col ; Adjust Cursor Position + push row + call pcbios_rowcol + pop row ; Get Normalized Coordinates + pop col + inc lcount ; Update Counter + inc si ; And String Pointer + jmp get_a_char ; Keep Looping For Whole String +aputs_done: mov ax,lcount ; Return String Length + ret +; +pcbios_aputs endp + + +; ======================== Get Current Video Mode ============================= + +pcbios_getvmode proc uses DS +; + mov ax,DGROUP + mov ds,ax + mov ah,0fh + int 10h + mov VIDEO_MODE,al + mov VIDEO_PAGE,bh + mov al,ah ; Make a word out of the width + xor ah,ah + mov VIDEO_WIDTH,ax + ret +; +pcbios_getvmode endp + + +; ============================= Set Video Mode ================================ + +pcbios_setvmode proc vmode:byte +; + xor ah,ah + mov al,vmode + int 10h + call pcbios_getvmode + ret +; +pcbios_setvmode endp + + +; ============================= Set Video Page ================================ + +pcbios_setvpage proc vpage:byte +; + mov ah,5 + mov al,vpage + int 10h + call pcbios_getvmode + ret +pcbios_setvpage endp + + +; ============================ END OF ROUTINES ================================ + end diff --git a/ice/SD2_FEDI.C b/ice/SD2_FEDI.C new file mode 100644 index 0000000..d0eafa7 --- /dev/null +++ b/ice/SD2_FEDI.C @@ -0,0 +1,599 @@ +/* SD2_FEDI.C - Screen Door II Field Edit Routines + + Copyright (c), 1988 By T.A. Daneliuk + Last Modified: 08-11-88 + + These routines edit a specific field in accordance with the + definitions in a structure type called SD2_FIELD. On entry, + the calling routine passes a pointer to such a field. On + return, SD2_NOERR is returned if the edit was successful. + An error code is returned if the edit failed for some reason. + This will occur under the following conditions: + + The pointer passed to sd2_fedit() is NULL (SD2_NULFPTR) + The passed structure points to a Prompt field (SD2_ENOTRES) + The the "field" structure member is NULL (SD2_EFNULL) + + The function will not accept any characters which do not meet + the character validation conditions, and will not return until + the whole field validation function passes successfully. +*/ + +#include +#include +#include +#include + +#if ANSI +static BOOL end_fld(struct SD2_FIELD *x); +static BOOL mask_val(struct SD2_FIELD *x, KEYSTR *y, FLEN z); +#else +static BOOL end_fld(); +static BOOL mask_val(); +#endif + +static BOOL firsttime; + + +/*====================== MAIN FIELD EDITING FUNCTION =========================*/ + +ERRCODE sd2_fedit(fldptr, retnkey) + +struct SD2_FIELD *fldptr; +KEYSTR *retnkey; + +{ + ERRCODE fedit_status; + BOOL fediting; + KEYSTR key, ktemp; + BOOL fmodified; + FLEN fposn, flen, rlen, temp; + BOOL ins_mode; + BOOL paint; + BOOL get_next_key; + BOOL store_key; + + + fedit_status = SD2_NOERR; + + if (fldptr == NULL) /* See If Bad Pointer Passed */ + fedit_status = SD2_NULFPTR; + + if (fldptr->ftype != FLD_RESP) /* See If Response Allowed */ + fedit_status = SD2_ENOTRES; + else + if (fldptr->field == NULL) /* Is Response Fld. Ptr. OK? */ + fedit_status = SD2_EFNULL; + + + firsttime = TRUE; /* Setup The State Machine */ + fediting = TRUE; + fmodified = FALSE; + fposn = 0; + ins_mode = FALSE; + paint = TRUE; + get_next_key = TRUE; + + while ((fediting == TRUE) && (fedit_status == SD2_NOERR)) + { + if (paint == TRUE) + { + if ((fldptr->mask != NULL) && (fldptr->field[fposn] != '\0')) + { + temp = fposn; /* Make Any Case Corrections For Char. Val. */ + while (fldptr->field[temp] != '\0') + { + mask_val(fldptr, &(fldptr->field[temp]), temp); + temp++; + } + } + sd2_fdsply(fldptr, fmodified, fposn); /* Display Updates */ + } + sd2_rowcol(fldptr->frow, (fldptr->fcol)+fposn); /* Position Cursor */ + (ins_mode==TRUE ? sd2_cursor(CURBLK) : sd2_cursor(CURSML)); + if (get_next_key == TRUE) + { + key = sd2_keyin(); /* Get Next Keystroke */ + *retnkey = key; /* Save For Return */ + } + flen = strlen(fldptr->field); /* Current Field Length */ + rlen = fldptr->rlen; /* Maximum Field Length */ + + + /* Inter-Field, Exit-Field, & Exit-Screen All Force End Of Field Editing */ + + if ((key == NXTFLD) || (key == PRVFLD) || (key == FSTFLD) || + (key == LSTFLD) || (key == EXTFLD) || (key == EXTSCR)) + { + if (end_fld(fldptr) == TRUE) /* All Field Validations OK */ + { + fediting = FALSE; /* Done With Field Editing */ + fposn = 0; /* For Cosmetic Consistency */ + } + } + + else + if (key == SD2_EBAD_CTRL); /* Ignore Bad Control Sequences */ + + else + if (key == CURLFT) + + { + if (flen > 0) /* If Nothing In Field, Can't Move*/ + fposn = (fposn == 0 ? flen : --fposn); /* Wrap If Neces.*/ + fposn = (fposn == rlen ? --fposn : fposn); + paint = FALSE; + } + else + if (key == CURRGT) + { + if (flen > 0) + fposn = (fposn == flen ? 0: ++fposn); + fposn = (fposn == rlen ? 0 : fposn); + paint = FALSE; + get_next_key = TRUE; /* We Might Just Have Put A New Char */ + } + + else + if (key == BEGFLD) + { + fposn = 0; + paint = FALSE; + } + + else + if (key == ENDFLD) + { + fposn = flen; + fposn = (fposn == rlen ? --fposn : fposn); + paint = FALSE; + } + + else + if (key == CLRFLD) + { + fposn = 0; + fldptr->field[0] = '\0'; + paint = TRUE; + fmodified = TRUE; + firsttime = TRUE; /* Force Whole Field Repaint */ + } + + else + if (key == CLREND) + { + fldptr->field[fposn] = '\0'; + paint = TRUE; + fmodified = TRUE; + firsttime = TRUE; + } + + else + if (key == INSERT) + { + if (flen < rlen) /* No Insert On Full Field */ + { + ins_mode = (ins_mode == TRUE ? FALSE : TRUE); + paint = FALSE; + } + } + + else + if (key == DELETE) + { + store_key = TRUE; + if (fldptr->field[fposn] != '\0') + { + if (fldptr->mask != NULL) /* Make Sure Moving Left Is OK*/ + { + temp = fposn; /* Can Current Character */ + ktemp = fldptr->field[temp+1];/* Legally Move Over? */ + + while(ktemp != '\0') /* Check All Remaining */ + { + store_key = store_key && + mask_val(fldptr, &ktemp, temp); + temp++; + ktemp = fldptr->field[temp+1]; + } + } + } + if (store_key == TRUE) /* Character Validations OK */ + { + strcpy(&(fldptr->field[fposn]), &(fldptr->field[fposn+1])); + fldptr->field[flen-1] = '\0'; + fmodified = TRUE; + paint = TRUE; + } + else + if (get_next_key == FALSE) /* Were Trying To Bkspc */ + fposn++; + + get_next_key = TRUE; /* In Case We Just Backspaced */ + } + + else + if (key == BKSPC) + { + if (fposn > 0) /* No Bksp. @ Fld. Beginning */ + { + --fposn; /* Just Backup One Position And Delete */ + key = DELETE; + get_next_key = FALSE; /* Inhibit Keyboard Read */ + } + } + + else + if (key == HELPKEY) + { + if (fldptr->rhelp != NULL) /* Help Is Avail.*/ + sd2_help(fldptr->rhelp); + } + else /* We Have A Data Keystroke */ + { + store_key = TRUE; /* Do Character Validations */ + + + if ((key == ' ') && (fldptr->rspace == FALSE)) /* Spaces Allowed? */ + store_key = FALSE; + + if (fldptr->mask != NULL) /* Do Only If Char Validations Enabled */ + { + store_key = store_key && mask_val(fldptr, &key, fposn); + + if (ins_mode == TRUE) /* Check All Subsequent If Inserting */ + { + if (fldptr->field[fposn] != '\0') /* Only If Not At End */ + { + temp = fposn; /* Can Current Character */ + ktemp = fldptr->field[temp]; /* Legally Move Over? */ + + while(ktemp != '\0') /* Check All Remaining */ + { + store_key = store_key && + mask_val(fldptr, &ktemp, temp+1); + temp++; + ktemp = fldptr->field[temp]; + } + } + } + } + + if (store_key == TRUE) /* Character Passed Validation */ + { + if (ins_mode == TRUE) + { + temp = flen; + while(temp >= fposn) + { + fldptr->field[temp+1] = fldptr->field[temp]; + --temp; + } + + fldptr->field[fposn] = key; + if ((flen+1) == rlen) /* Field Now Is Filled */ + { + ins_mode = FALSE; + sd2_cursor(CURSML); + } + } + else + { + if (fldptr->field[fposn] == '\0') + fldptr->field[fposn+1] = '\0'; + fldptr->field[fposn] = key; + } + key = CURRGT; /* Move Cursor Over One */ + get_next_key = FALSE; /* Before Getting Next */ + fmodified = TRUE; /* Keystroke */ + paint = TRUE; + } + } + + } + + + sd2_fdsply(fldptr, FALSE, fposn); + return(fedit_status); + +} + + +/*========================== DISPLAY A FIELD =================================*/ + +void sd2_fdsply(fld, modified, cposn) +struct SD2_FIELD *fld; +BOOL modified; +FLEN cposn; + +{ + + FLEN x, y; + char fill[2]; + + sd2_cursor(CUROFF); /* Turn Off Cursor */ + + if (modified == FALSE) /* Use Default Colors, No Fill */ + { /* Use Input Color And Fill */ + x = strlen(fld->field); + fill[0] = fld->rclear; + fill[1] = '\0'; + + sd2_rowcol(fld->frow, (fld->fcol)+cposn); /* Position Cursor */ + sd2_aputs(&(fld->field[cposn]), fld->fattrib); /* Display String */ + while (x < fld->rlen) + { + sd2_rowcol(fld->frow, (fld->fcol)+x); /* Clear Any Fill Chars. */ + sd2_aputs(fill, fld->cattrib); + x++; + } + } + else + { /* Use Input Color And Fill */ + y = x = strlen(fld->field); + fill[0] = fld->rfill; + fill[1] = '\0'; + + if (firsttime == TRUE) /* First Time Display Whole Field */ + { + firsttime = FALSE; + cposn = 0; + } + else /* At Most, Only Need 1 Fill Char */ + y = (y == fld->rlen ? y : (fld->rlen) - 1); + + + sd2_rowcol(fld->frow, (fld->fcol)+cposn); /* Position Cursor */ + sd2_aputs(&(fld->field[cposn]), fld->rattrib); /* Display String */ + + while (y < fld->rlen) /* Have To Add A Fill Char */ + { + sd2_rowcol(fld->frow, (fld->fcol)+x); /* Then Fill Chars. */ + sd2_aputs(fill, fld->rattrib); + ++y; + ++x; + } + } +} + + +/*======================= END FIELD PROCESSING ===============================*/ + +static BOOL end_fld(fld) /* Does Whole Fld, RReq, User Validation, etc. */ +struct SD2_FIELD *fld; /* Returns True If All OK, False If Not */ + +{ + ERRCODE status; + char *errmsg; + static char mfill[] = "This Field Must Be Filled!"; + static char rreqd[] = "This Field Requires A Response!"; + + status = SD2_NOERR; + + if ((fld->rmustfill == TRUE) && (strlen(fld->field) != fld->rlen)) + { + status = SD2_MUSTFIL; + errmsg = mfill; + } + + else + if ((fld->rreqd == TRUE) && (fld->field[0] == '\0')) + { + status = SD2_RESREQD; + errmsg = rreqd; + } + + else if (fld->rvalid != NULL) + { + errmsg = (*(fld->rvalid)) (fld); + if (errmsg != NULL) + status = SD2_IEUVALID; + } + + if ((status != SD2_NOERR) && (fld->flderr != NULL)) + (*(fld->flderr)) (fld, status, errmsg); + + if (status != SD2_NOERR) + return(FALSE); + else + return(TRUE); + +} + +/*============== CHECK A CHARACTER AGAINST THE MASK CONDITION ================*/ + +static BOOL mask_val(fldptr, key, fposn) /* Returns TRUE If All OK */ +struct SD2_FIELD *fldptr; +KEYSTR *key; +FLEN fposn; + +{ + BOOL store_key, btemp; + FLEN temp, temp1; + KEYSTR ktemp; + + store_key = TRUE; + + + switch(fldptr->mask[fposn]) /* Check For Relevant Validation */ + { + case SD2_LITERAL_N: + case SD2_LITERAL_L: + case SD2_LITERAL_U: + switch (fldptr->mask[fposn]) + { + case SD2_LITERAL_N: /* No Case Conversion */ + break; /* Do Nothing */ + case SD2_LITERAL_L: + *key = tolower(*key); + break; + case SD2_LITERAL_U: + *key = toupper(*key); + break; + } + break; + + case SD2_ALPHA_N: + case SD2_ALPHA_L: + case SD2_ALPHA_U: + if (isalpha(*key)) + { + switch (fldptr->mask[fposn]) + { + case SD2_ALPHA_N: + break; + case SD2_ALPHA_L: + *key = tolower(*key); + break; + case SD2_ALPHA_U: + *key = toupper(*key); + break; + } + } + else + store_key = FALSE; + break; + + case SD2_ALPHANUM_N: + case SD2_ALPHANUM_L: + case SD2_ALPHANUM_U: + if (isalnum(*key)) + { + switch (fldptr->mask[fposn]) + { + case SD2_ALPHANUM_N: + break; + case SD2_ALPHANUM_L: + *key = tolower(*key); + break; + case SD2_ALPHANUM_U: + *key = toupper(*key); + break; + } + } + else + store_key = FALSE; + break; + + case SD2_BINARY: + if (*key != '0' && *key != '1') + store_key = FALSE; + break; + + case SD2_OCTAL: + if (!isdigit(*key) || (*key > '7')) + store_key = FALSE; + break; + + case SD2_DECIMAL: + if (!isdigit(*key)) + store_key = FALSE; + break; + + case SD2_HEX_N: + case SD2_HEX_L: + case SD2_HEX_U: + if (!isxdigit(*key)) + store_key = FALSE; + else + switch (fldptr->mask[fposn]) + { + case SD2_HEX_N: + break; + case SD2_HEX_L: + *key = tolower(*key); + break; + case SD2_HEX_U: + *key = toupper(*key); + break; + } + break; + + case SD2_FLOATING: + if (!isdigit(*key) && (*key != '+') && (*key != '-') + && (*key != '.')) + store_key = FALSE; + break; + + case SD2_SCIENT_N: + case SD2_SCIENT_L: + case SD2_SCIENT_U: + if (!isdigit(*key) && (*key != '+') && (*key != '-') + && (*key != '.') && (*key != 'e') && (*key != 'E')) + store_key = FALSE; + else + switch (fldptr->mask[fposn]) + { + case SD2_SCIENT_N: + break; + case SD2_SCIENT_L: + *key = tolower(*key); + break; + case SD2_SCIENT_U: + *key = toupper(*key); + break; + } + break; + + case SD2_FINANCIAL: + if (!isdigit(*key) && (*key != '+') && (*key != '-') + && (*key != '.') && (*key != '$')) + store_key = FALSE; + break; + + case SD2_YN_N: + case SD2_YN_L: + case SD2_YN_U: + if ((toupper(*key) != 'Y') && (toupper(*key) != 'N')) + store_key = FALSE; + else + switch (fldptr->mask[fposn]) + { + case SD2_YN_N: + break; + case SD2_YN_L: + *key = tolower(*key); + break; + case SD2_YN_U: + *key = toupper(*key); + break; + } + break; + + case SD2_LIST0: + case SD2_LIST1: + case SD2_LIST2: + case SD2_LIST3: + case SD2_LIST4: + case SD2_LIST5: + case SD2_LIST6: + case SD2_LIST7: + case SD2_LIST8: + case SD2_LIST9: + if (fldptr->v_lists != NULL) /* Only If Enabled */ + { + temp = (fldptr->mask[fposn]) - '0'; /* Only Works In ASCII*/ + if (fldptr->v_lists[temp] != NULL) + { + btemp = FALSE; /* Scan Literal List And Look */ + temp1 = 0; /* For Matching Character */ + ktemp = 'x'; /* Dummy So While Below Works */ + while ((btemp == FALSE) && (ktemp != '\0')) + { + ktemp = fldptr->v_lists[temp][temp1]; + if (*key == ktemp) + btemp = TRUE; + ++temp1; + } + store_key = store_key && btemp; + } + } + break; + + default: /* Invalid Validation Code, Ignore *key */ + store_key = FALSE; + break; + } + + return(store_key); +} diff --git a/ice/SD2_HELP.C b/ice/SD2_HELP.C new file mode 100644 index 0000000..3222425 --- /dev/null +++ b/ice/SD2_HELP.C @@ -0,0 +1,16 @@ +/* SD2_HELP.C - ScreenDoor II Field Help Function + + Copyright (c) 1988, By T.A. Daneliuk + Last Modified: 07-30-88 +*/ + +#include +#include + + +void sd2_help(hscrn) +struct SD2_SCRN *hscrn; + +{ + +} diff --git a/ice/TEST.C b/ice/TEST.C new file mode 100644 index 0000000..ab51235 --- /dev/null +++ b/ice/TEST.C @@ -0,0 +1,30 @@ +#include +#include + + +extern ice_getvmode(); +extern ice_aputs(char *x, unsigned int y); +extern ice_rowcol(); +extern ice_cls(); + +void main() + +{ + static char x1[]="This is 0,0"; + static char x2[]="This is 3,4"; + static char x3[]="This is 10,75"; + static char x4[]="This is 24,0"; + static char x5[]="This is 24,77"; + + ice_rowcol(0,0); + printf("%s", x1); + ice_rowcol(3,4); + ice_aputs(x2, 7); + ice_rowcol(10,75); + ice_aputs(x3, 7); + ice_rowcol(24,0); + ice_aputs(x4, 7); + ice_rowcol(24,77); + ice_aputs(x5, 7); + +} diff --git a/ice/TEST.EXE b/ice/TEST.EXE new file mode 100644 index 0000000..9353c85 --- /dev/null +++ b/ice/TEST.EXE Binary files differ diff --git a/ice/TEST.MAP b/ice/TEST.MAP new file mode 100644 index 0000000..91ce669 --- /dev/null +++ b/ice/TEST.MAP @@ -0,0 +1,49 @@ + + Start Stop Length Name Class + 00000H 000B9H 000BAH TEST_TEXT CODE + 000BAH 00161H 000A8H ICE_LOGD_TEXT CODE + 00162H 01CBCH 01B5BH _TEXT CODE + 01CBEH 01CBEH 00000H C_ETEXT ENDCODE + 01CC0H 01D01H 00042H NULL BEGDATA + 01D02H 02601H 00900H _DATA DATA + 02602H 0260FH 0000EH CDATA DATA + 02610H 02610H 00000H XIFB DATA + 02610H 02610H 00000H XIF DATA + 02610H 02610H 00000H XIFE DATA + 02610H 02610H 00000H XIB DATA + 02610H 02610H 00000H XI DATA + 02610H 02610H 00000H XIE DATA + 02610H 02610H 00000H XPB DATA + 02610H 02613H 00004H XP DATA + 02614H 02614H 00000H XPE DATA + 02614H 02614H 00000H XCB DATA + 02614H 02614H 00000H XC DATA + 02614H 02614H 00000H XCE DATA + 02614H 02614H 00000H XCFB DATA + 02614H 02614H 00000H XCF DATA + 02614H 02614H 00000H XCFE DATA + 02614H 02615H 00002H CONST CONST + 02616H 0261DH 00008H HDR MSG + 0261EH 026EBH 000CEH MSG MSG + 026ECH 026EDH 00002H PAD MSG + 026EEH 026EEH 00001H EPAD MSG + 026F0H 02885H 00196H _BSS BSS + 02886H 02886H 00000H XOB BSS + 02886H 02886H 00000H XO BSS + 02886H 02886H 00000H XOE BSS + 02890H 0308FH 00800H STACK STACK + + Origin Group + 01CC:0 DGROUP + +Program entry point at 0016:0012 + +Unresolved externals: + + +__settextposition in file(s): + ICE_LIBS\D_L_ICE.LIB(ice_logd.C) +__outtext in file(s): + ICE_LIBS\D_L_ICE.LIB(ice_logd.C) +__settextcolor in file(s): + ICE_LIBS\D_L_ICE.LIB(ice_logd.C) diff --git a/ice/TEST.OBJ b/ice/TEST.OBJ new file mode 100644 index 0000000..7a9a5b2 --- /dev/null +++ b/ice/TEST.OBJ Binary files differ diff --git a/ice/TST b/ice/TST new file mode 100644 index 0000000..f22e728 --- /dev/null +++ b/ice/TST @@ -0,0 +1,5 @@ +test.obj: test.c ice_defs.h + cl /Zi /Od /AL /c test.c + +test.exe: test.obj large\dicelogd.obj large\dicefedi.obj large\dicekeyi.obj + link test,,,ice_libs\d_l_ice.lib/CO; diff --git a/ice/TST.BAT b/ice/TST.BAT new file mode 100644 index 0000000..1ac85f6 --- /dev/null +++ b/ice/TST.BAT @@ -0,0 +1,2 @@ +make model=LARGE cmodel=L dice +make tst diff --git a/ice/X1.C b/ice/X1.C new file mode 100644 index 0000000..f32f8d7 --- /dev/null +++ b/ice/X1.C @@ -0,0 +1,25 @@ +#include +#include +#include +#include +void handler(void); + +void main () + +{ + int x; + if (signal(SIGINT,SIG_IGN) == SIG_ERR) + printf("Couldn't set signal()\n\n\n"); + while ((x=_bios_keybrd(_KEYBRD_READ)) != 255) + { + putchar(x); + printf(" %d\n", (char) x); + } +} + +void handler() + +{ +printf("Ctrl-C Pressed!\n\n\n"); +signal(SIGINT,handler); +} diff --git a/ice/X1.EXE b/ice/X1.EXE new file mode 100644 index 0000000..ee802c9 --- /dev/null +++ b/ice/X1.EXE Binary files differ diff --git a/ice/X2.C b/ice/X2.C new file mode 100644 index 0000000..247a0a7 --- /dev/null +++ b/ice/X2.C @@ -0,0 +1,29 @@ +#include + + +extern pcbios_getvmode(); +extern pcbios_aputs(char *x, unsigned int y); +extern pcbios_rowcol(); +extern pcbios_cls(); + +void main() + +{ + static char x1[]="This is 0,0"; + static char x2[]="This is 3,4"; + static char x3[]="This is 10,75"; + static char x4[]="This is 24,0"; + static char x5[]="This is 24,77"; + + pcbios_rowcol(0,0); + printf("%s", x1); + pcbios_rowcol(3,4); + pcbios_aputs(x2, 7); + pcbios_rowcol(10,75); + pcbios_aputs(x3, 7); + pcbios_rowcol(24,0); + pcbios_aputs(x4, 7); + pcbios_rowcol(24,77); + pcbios_aputs(x5, 7); + +} diff --git a/lj-env/LJ-ENV.BAS b/lj-env/LJ-ENV.BAS new file mode 100644 index 0000000..7f3f3cc --- /dev/null +++ b/lj-env/LJ-ENV.BAS @@ -0,0 +1,39 @@ +10 ' HP Laser Jet Envelope Printing Utility Version 1.0 +20 ' Copyright (C), 1985 by T.A. Daneliuk Chicago, IL +30 ' Last Modified 11/21/85 +40 ' +50 ' +60 ' +70 CLEAR 1500:LM=55:TM=22:LINES=5 +80 CLS:WIDTH "lpt1:",132 +90 PRINT "HP Laser Jet Envelope Printing Utility Version 1.0" +100 PRINT "Copyright (C), 1985 by T.A. Daneliuk Chicago, IL" +110 PRINT:PRINT:PRINT +120 ESC$=CHR$(27) +130 INIT$=ESC$+"&l1O"+ESC$+"&l3H"+ESC$+"(s3B" +140 RES$=ESC$+"E" +150 FOR Y=1 TO LINES +160 PRINT "Input Line ";Y;": "; +170 LINE INPUT A$(Y-1) +180 NEXT Y +190 PRINT:PRINT +200 FOR Y=1 TO LINES +210 PRINT A$(Y-1) +220 NEXT Y +230 PRINT:PRINT:PRINT "Is this correct (Y/N)? "; +240 A$=INKEY$:IF A$="N" OR A$="n" THEN GOTO 70 +250 IF A$<>"Y" AND A$<>"y" THEN GOTO 240 +260 PRINT:LPRINT INIT$; +270 FOR X=1 TO TM +280 LPRINT TAB(LM)" " +290 NEXT X +300 FOR Y=1 TO LINES +310 LPRINT STRING$(LM," ");A$(Y-1) +320 NEXT Y +330 LPRINT ESC$+"&l1H"+RES$; +340 PRINT:PRINT:PRINT "Print Again (Y/N)? "; +350 B$=INKEY$:IF B$="Y" OR B$="y" THEN GOTO 190 +360 IF B$="N" OR B$="n" THEN GOTO 70 +370 GOTO 350 +380 END + \ No newline at end of file diff --git a/ljtoibm/LJTOIBM.ASM b/ljtoibm/LJTOIBM.ASM new file mode 100644 index 0000000..4b98173 --- /dev/null +++ b/ljtoibm/LJTOIBM.ASM @@ -0,0 +1,206 @@ + + PAGE 40,132 + TITLE LJTOIBM.ASM +; +; +; ********** +; * LJTOIBM.ASM - Laser Jet -> IBM Graphics XLATE - VERSION 1.2.3 +; * LAST MODIFIED: 11/24/85 +; * COPYRIGHT (C) 1985 BY T.A. DANELIUK +; ********** +; +; +; ********** +; * SYSTEM EQUATES +; ********** +; +; +SPACE EQU 20H ; ASCII SPACE +DOS EQU 21H ; DOS INTERRUPT +EOL EQU 0A0DH ; END-OF-LINE STRING +EXIT EQU 4CH ; NORMAL EXIT TO DOS +GET_IR_VECT EQU 35H ; GET VECTOR FROM IR TABLE +PRINTER_IR EQU 17H ; PRINTER IR VECTOR +PRINT_STRING EQU 09H ; IR TO PRINT STRING ON DISPLAY +SET_IR_VECT EQU 25H ; SET AN IR VECTOR IN TABLE +TAB EQU 09H ; ASCII TAB +TAIL_BEGIN EQU 81H ; OFFSET OF COMMAND TAIL IN PSP +TAIL_LENGTH EQU 80H ; LOC OF LENGTH BYTE IN CMD TAIL +TERMINATE EQU 31H ; TERMINATE/STAY RESIDENT +; +; +; +; ********** +; * CODE SEGMENT +; ********** +; +; +LJ_XL SEGMENT WORD 'CODE' + ASSUME CS:LJ_XL,DS:LJ_XL,ES:LJ_XL +; +; + + ORG 100H +; +START_RUN EQU THIS BYTE +; +; +START: JMP INIT ; GO TO INITIALIZATION CODE +; +; +; TRANSLATION TABLE FROM IBM TO LASER JET CHARACTER SET +; +; +; +TABLE DB 000H,001H,002H,003H,004H,005H,006H,007H + DB 008H,009H,00AH,00BH,00CH,00DH,00EH,00FH + DB 0FDH,0FBH,012H,013H,014H,015H,016H,017H + DB 018H,019H,01AH,01BH,01CH,01DH,01EH,01FH + DB 020H,021H,022H,023H,024H,025H,026H,027H + DB 028H,029H,02AH,02BH,02CH,02DH,02EH,02FH + DB 030H,031H,032H,033H,034H,035H,036H,037H + DB 038H,039H,03AH,03BH,03CH,03DH,03EH,03FH + DB 040H,041H,042H,043H,044H,045H,046H,047H + DB 048H,049H,04AH,04BH,04CH,04DH,04EH,04FH + DB 050H,051H,052H,053H,054H,055H,056H,057H + DB 058H,059H,05AH,05BH,05CH,05DH,05EH,05FH + DB 060H,061H,062H,063H,064H,065H,066H,067H + DB 068H,069H,06AH,06BH,06CH,06DH,06EH,06FH + DB 070H,071H,072H,073H,074H,075H,076H,077H + DB 078H,079H,07AH,07BH,07CH,07DH,07EH,07FH + DB 0B4H,0CFH,0C5H,0C0H,0CCH,0C8H,0D4H,0B5H + DB 0C1H,0CDH,0C9H,0DDH,0D1H,0D9H,0D8H,0D0H + DB 0DCH,0D7H,0D3H,0C2H,0CEH,0CAH,0C3H,0CBH + DB 0EEH,0DAH,0DBH,0BFH,0BBH,0BCH,020H,0BEH + DB 0C4H,0D5H,0C6H,0C7H,0B7H,0B6H,0F9H,0FAH + DB 0B9H,02DH,02DH,0F8H,0F7H,0B8H,0FBH,0FDH + DB 07FH,07FH,07FH,07CH,07CH,07CH,02DH,02DH + DB 02DH,07CH,07CH,02DH,02DH,02DH,02DH,02DH + DB 02DH,02DH,02DH,07CH,02DH,02BH,07CH,07CH + DB 02DH,02DH,02DH,02DH,07CH,02DH,02BH,02DH + DB 02DH,02DH,02DH,02DH,02DH,02DH,02DH,02BH + DB 02BH,02DH,02DH,0FCH,0FCH,0FCH,0FCH,0FCH + DB 020H,0DEH,020H,020H,020H,020H,020H,020H + DB 020H,020H,020H,020H,020H,0D2H,020H,020H + DB 020H,0FEH,020H,020H,020H,020H,020H,020H + DB 0B3H,020H,020H,020H,020H,020H,020H,020H +; +; +LJ_IBM EQU THIS BYTE +; +; FIRST COMES THE HEADER +; + JMP SHORT ENTRY + DW OFFSET END_RUN-1 ; LAST ADDR. OF RESIDENT CODE +MOD_NAME DB 'LJTOIBM ' ; NAME OF MODULE IN ASCII +; +; THE FOLLOWING 4 HEADER BYTES ARE APPLICATION DEFINED. +; + DB 0 + DB 0 + DB 0 + DB 0 +; +; NOW THE ACTUAL RESIDENT INTERRUPT CODE +; +ENTRY: PUSH AX ; SAVE CHARACTER + OR AH,AH ; WE ONLY DEAL WITH 0 + JNZ RUN_DONE + PUSH BX + MOV BX, OFFSET TABLE ; GET TABLE LOCATION + PUSH DS + PUSH CS + POP DS + XLAT ; GET SUBSTITUTE CHARACTER + POP DS + POP BX +RUN_DONE: PUSHF ; FAKE AN INTERRUPT + CALL DWORD PTR CS:OLD_VECTOR ; CALL ORIGINAL ROUTINE +; +GO_BACK EQU THIS BYTE +; + CLI ; INTERRUPTS OFF FOR NOW + MOV CS:TEMP,AH ; SAVE RETURN STATUS + POP AX ; GET ORIGINAL CHARACTER BACK + MOV AH,CS:TEMP + IRET ; BACK TO THE OUTSIDE WORLD +; +OLD_VECTOR DD ? +TEMP DB ? +; +END_RUN EQU THIS BYTE +; +; + PAGE +; ********** +; * LOADER/INSTALL CODE +; ********** +; +; +INIT: PUSHF ; SAVE IR STATUS + CLI ; TURN 'EM OFF FOR NOW +; +; +; DISPLAY BANNER +; +; + MOV DX,OFFSET MSG1 + MOV AH,PRINT_STRING + INT DOS +; +; +; GET EXISTING PRINTER VECTOR AND SAVE FOR CHAINING +; +; +CHAIN_IR: MOV AH,GET_IR_VECT ; FUNCTION NUMBER + MOV AL,PRINTER_IR ; INTERRUPT NUMBER + INT DOS + MOV BP,OFFSET OLD_VECTOR + MOV CS:[BP],BX ; WE GOT THE OLD VECTOR IN ES:BX + MOV BX,ES ; GET SEGMENT + MOV CS:[BP+2],BX +; +; +; STUFF NEW VECTOR INTO TABLE SO WE GET CONTROL FIRST +; +; + MOV DX,OFFSET LJ_IBM ; VECTOR IN DS:DX - DS ALREADY OK + MOV AH,SET_IR_VECT + MOV AL,PRINTER_IR + INT DOS +; +; +; TERMINATE, BUT STAY RESIDENT EXIT CODE +; +; +RESIDE_EXIT: MOV AX,OFFSET END_RUN ; CALCULATE MODULE LENGTH IN PARAS + MOV CL,10H ; DIVISOR + DIV CL + AND AH,AH ; ANY REMAINDER? + JZ NO_REMAINDER ; NO + INC AL ; YES, BUMP A FULL PARAGRAPH +NO_REMAINDER: XOR DX,DX ; CLEAR DX + MOV DL,AL ; TERMINATE FN. NEEDS LENGTH IN DX + XOR AL,AL ; SET RETURN ERROR CODE TO 0 + MOV AH,TERMINATE ; TERMINATE & STAY RESIDENT FN + POPF ; RESET ORIGINAL IR STATUS + INT DOS ; DO THE DOS CALL + PAGE +; BANNER MESSAGE STRINGS +; +; +MSG1 DW EOL + DB 'LJTOIBM - LASER JET TO IBM CHARACTER XLATE - Version 1.2.3' + DW EOL + DB 'Copyright (c) 1985, T.A. Daneliuk, Chicago, IL 60625' + DW EOL + DB 'Permission Granted To Reproduce This Program' + DW EOL + DB 'For PERSONAL, *** NON-COMMERCIAL *** Use Only!' + DW EOL,EOL + DB '$' +; +; +; +LJ_XL ENDS + END START diff --git a/loan/loan.c b/loan/loan.c new file mode 100644 index 0000000..b4f031b --- /dev/null +++ b/loan/loan.c @@ -0,0 +1,175 @@ +From UICVM.UIC.EDU!INDYCMS.BITNET!COHERENT Sat Jan 18 12:08:38 1992 remote from clout +Received: by eskimo.chi.il.us (smail2.5-coherent) id AA00378; 18 Jan 92 12:08:38 +Received: by clout.chi.il.us (/\==/\ Smail3.1.25.1 #25.2) + id ; Sat, 18 Jan 92 05:36 CST +Message-Id: +Received: from UICVM by UICVM.UIC.EDU (IBM VM SMTP V2R1) with BSMTP id 8127; + Sat, 18 Jan 92 05:35:53 CST +Received: from UICVM.BITNET by UICVM (Mailer R2.07) with BSMTP id 1875; Sat, 18 + Jan 92 05:35:48 CST +Date: Fri, 17 Jan 1992 20:00:53 GMT +Reply-To: "Coherent operating system" +Sender: "Coherent operating system" +From: Mike Willett +Subject: Source file "loan.c" +Comments: To: coherent@indycms.iupui.edu +To: Multiple recipients of list COHERENT + +Since the interest rates have been falling here in the States, and many +people (such as myself) want to take advantage of this money saver, I +made some minor changes to this program I have had around forever so +that it would run on Coherent. Don't hold me to the accuracy of the +output, it could be improved by a super C hack, but, it is good enough +for most of us to get an excellent idea what the loan payments would be... + +Enjoy and best regards! Kom-sa-hom-ni-da! + +--Mike + + +/* + * Note to Coherent Users: compile with: + * cc -o loan loan.c -f -lm + * --Mike + * + * loan.c + * @(#) loan.c amoritization program + * + * acronym: loan amortization program + * ---- + * + * purpose: calculates monthly payment, future value + * and creates an amortization schedule + * + * 06/27/84 Bill Gregg, Informatics General Corp. + * 07/12/84 Revision 1 + * 07/12/84 Revision 2 + * 11/05/85 Jane Medefesser, Implementation NPSN Unix (wilbur) + * compile as follows: 'cc -o loan.c -lm' + * 12/05/85 Changes to direct output to a file. + * 03/02/88 Implemented on Eternity 5.3.1 + * 01/15/92 Mike Willett, added P&I field and pause function + * and minor library changes to port to Coherent + * (compile with cc -o loan loan.c -f -lm) + */ + +#include +#include + +/* + * + */ + +main() /* loan program */ +{ + float amt, term, rate, ic, total; + float r, temp, pmt, fv; + float exp, prin, x, y, mbeg, mnbr, yrint = 0; + int month, i, k, a = 0, yr=1; + char d, filename[9], c; + FILE *fp; + + + + + /* prompt for input from terminal */ + + printf("Enter principal amount: "); + scanf("%f", &amt); + + printf("Enter term in years: "); + scanf("%f", &term); + + printf("Enter interest rate in percent: "); + scanf("%f", &rate); + + printf("Enter month payments begin (ex: 8 = August): "); + scanf("%f", &mbeg); + + /* compute payment and future value */ + + r = rate/100.0; + x = 1.0 + r/12.0; + y = term*12.0; + temp = (1.0 / pow(x,y)); + pmt = (amt*r/12.0) / (1-temp); + k = term*12; + fv = pmt*k; + ic = fv - amt; + + printf("Do you want the report directed to a file or to the screen?"); + printf("\n[f = file / s = screen] : "); + d = getchar(); /* This is only here to eat up the '\n' left over + from the last scanf. */ + d = getchar(); + switch(d) { + case 'f': + d = getchar(); + printf("\nEnter a filename: "); + scanf("%s", filename); + while((c = getchar()) != '\n') { + filename[a] = c; a++; } + fp = fopen(filename, "w"); + break; + default: + fp = stdout; + break; + } + + /* print header */ + + fprintf(fp,"\n\t *** Amortization Schedule ***\n\n"); + fprintf(fp,"Principal: %.2f\n", amt); + fprintf(fp,"Future value: %.2f\n", fv); + fprintf(fp,"Term of loan in years: %.1f\n", term); + fprintf(fp,"Interest Rate: %3.3f\n", rate); + fprintf(fp,"Total Interest Charge: %.2f\n", ic); + fprintf(fp,"Payment: %.2f\n", pmt); + fprintf(fp,"\nMONTH PRINCIPAL INTEREST TOTAL PMT + BALANCE\n"); + + /* start of loop to print amortization schedule */ + + mnbr=mbeg; + for (i=1; i<=k; i++) { + month = i; + exp = amt*(r/12.0); + yrint=yrint+exp; + prin = pmt-exp; + amt = amt-prin; + total = prin + exp; + mnbr++; + fprintf(fp,"%d\t %.2f\t\t %.2f\t\t %.2f\t\t + %.2f\n",month,prin,exp,total,amt); + if (mnbr > 12 ) { + fprintf(fp,"\t\tInterest paid for year %d is %.2f\n\n",yr,yrint); + yr++; + pause(); + yrint=0; + mnbr=1; + } +} + fprintf(fp,"\t\tInterest paid for year %d is %.2f\n\n",yr,yrint); + fclose(fp); +} + +pause() +{ + +static int flag; + + if(flag!=1) + { + getchar(); /* Flush buffer since we are not in raw mode */ + flag=1; + } + + printf("Press return to continue:"); + while(getchar() !='\012'); +} + +-- +Michael Willett, mike@array.com uupsi!monarch!mike uunet!csn!monarch!mike + So much fun, so little time to enjoy it... + + diff --git a/lookey/LOOKEY.C b/lookey/LOOKEY.C new file mode 100644 index 0000000..cf3d787 --- /dev/null +++ b/lookey/LOOKEY.C @@ -0,0 +1,27 @@ +/* LOOKEY.C - This utility gets a keystroke from STDIN and displays both + the decimal and hexadecimal equivalent values on STDOUT. + + Last Modified: 01/01/85 - Copyright (c) 1985 By T.A. Daneliuk */ + + +#include + +main() + +{ + +char c; +int i; +static char array[3]={"\0\0\0"}; + +while ((c=bdos(7,0,0)) != 0x1A) /* Cntrl-Z Terminates */ + + { + + i = (int) c; /* Cast to integer value */ + tohex2(i,array); /* Get 2 digit hex equivalent */ + printf("%c Key Value Is: %d Decimal %s Hexadecimal\n",c,i,array); + + } + +} \ No newline at end of file diff --git a/macro/MACRO.TXT b/macro/MACRO.TXT new file mode 100644 index 0000000..706d970 --- /dev/null +++ b/macro/MACRO.TXT @@ -0,0 +1,660 @@ + Calling Macros in DOS.INC and BIOS.INC + +You are responsible for saving and restoring registers used in +macros. The "Registers used" field identifies registers to save. + +Macros that accept address parameters use internal macros that +allow you to specify addresses in several ways. The macro +automatically identifies the type of the argument and handles it +appropriately. For example, assume the following declarations: + + String DB "test$" + pString DW Str + fpString DD Str + +Given these values, the macro @DispStr (which displays the string +at DS:DX) has the following effects: + + Kind of argument Example Value loaded + + Label of byte variable @DispStr String DS:OFFSET String + Near pointer variable @DispStr pString DS:pString + Far pointer variable @DispStr fpString fpString[2]:fpString[0] + Constant @DispStr 0 DS:0 + Pointer in register @DispStr si DS:SI + Near Pointer with segment @DispStr pString,es ES:pString + Constant with segment @DispStr 0,es ES:0 + Register with segment @DispStr di,es ES:DI + +Note that if a far pointer or a segment is given, DS must be +saved before the macro call and restored afterward. Segments may +be given as registers, constants, or word variables. + +In syntax, parameters enclosed in brackets are optional. +Paramaters sometimes have a leading symbol to indicate that the +argument must have a certain type, as shown below: + + Leading Symbol Example Limitation + + # #return Must be constant + & &vector Must be offset address as described above + $ $terminator May be constant or register, but not memory + +Parameters with no leading symbol may be constants, registers, or +variables. Parameters are 16-bit except where noted in the description. + +Symbols must be previously defined before they can be passed as +arguments to most of the DOS macros. Generally this means that +data must be declared before code in the source file. + + DOS Macro Syntax and Description + +KEYBOARD INPUT + +@GetKey (01h, 07h, 08h, 0Ch) + +Gets a keystroke from the keyboard + +Syntax: @GetKey [#echo] [,[#break] [,#clearbuf]] + +Arguments: echo = nonzero to echo keystroke - default yes + break = nonzero to accept Control-C - default yes + clearbuf = nonzero to clear keyboard buffer - default no + (Arguments may be omitted to get defaults) +Return: ASCII code of key in AL +Registers used: AX used for all, DL used if echo on and ctrl-c off + + +@GetStr (0Ah) + +Gets a string from the keyboard + +Syntax: @GetStr &buffer [,[$terminator] [,[#limit] [,segment]]] + +Arguments: buffer = Offset of buffer where string will be stored + Byte 1 = Maximum length of string (before call) + Byte 2 = Actual length of string (after call) + Byte 3+ = Bytes of string + terminator = Terminating byte - usually null (0) or $ (24h) + limit = Maximum length of string (if not given as + argument, must be in buffer before macro call) + segment = Segment of buffer (DS if not given) +Return: Pointer to string in SI, length of string in BX +Registers used: AX, DX, BX, SI + +OUTPUT + +@DispCh (02h) + +Displays one or more characters to screen + +Syntax: @DispCh char [,char]... + +Arguments: char = 8-bit ASCII code +Return: Code in AL +Registers used: AX and DL + + +@PrtCh (05h) + +Prints one or more characters to LPT1 + +Syntax: @PrtCh char [,char]... + +Arguments: char = 8-bit ASCII code +Return: Code in AL +Registers used: AX and DL + + +@DispStr (09h) + +Displays a $-terminated string + +Syntax: @DispStr &address [,segment] + +Arguments: address = Address of string terminated by "$" (24h) + segment = Segment of address string (DS if not given) +Return: None +Registers used: AX and DS + +DEVICE I/O + +@Read (3Fh) + +Reads data from a file or device + +Syntax: @Read &buffer, length [,[handle] [,segment]] + +Arguments: buffer = Offset of buffer where data will be stored + length = Length of data in bytes + handle = File or device handle; if none given, + keyboard (handle 0) is assumed + segment = Segment of address string (DS if not given) +Return: If carry clear, bytes read in AX +Registers used: Always AX, DX, BX, and CX; DS if segment changed + + +@Write (40h) + +Writes data to a file or device + +Syntax: @Write &buffer, length, [,[handle] [,segment]] + +Arguments: buffer = Offset of buffer where data is stored + length = Length of data in bytes + handle = File or device handle; if none given, screen + (handle 1) is assumed + segment = Segment of address string (DS if not given) +Return: If carry clear, bytes written in AX +Registers used: Always AX, DX, BX, and CX; DS if segment changed + +FILE CONTROL + +@MakeFil (3Ch, 5Ah, 5Bh) + +Creates a file + +Syntax: @MakeFil &path [,[attrib] [,[segment] [,#kind]]] + +Arguments: path = ASCIIZ string of file + attrib = File atrribute (0 is default if none given) + segment = Segment of address string (DS if not given) + kind = If none given, a file is always created even if + one already exists. Under DOS 3+ "tmp" can be + given to create a unique file or "new" to create + file only if one doesn't already exist. +Return: If carrry clear, file handle in AX +Registers used: Always AX, DX, and CX; DS if segment changed + + +@OpenFil (3Dh) + +Opens a file for input or output + +Syntax: @OpenFil &path, #access [,segment] + +Arguments: path = ASCIIZ string of file + access = File access code + segment = Segment of address string (DS if not given) +Return: If carrry set, error code in AX +Registers used: Always AX and DX; DS if segment changed + + +@ClosFil (3Eh) + +Closes an open file handle + +Syntax: @ClosFil handle + +Arguments: handle = Previously opened file handle +Return: If carrry set, error code in AX +Registers used: AX and BX + + +@DelFil (41h) + +Deletes a specified file + +Syntax: @DelFil &path [,segment] + +Arguments: path = Offset of ASCIIZ filespec + segment = Segment of path (DS if none given) +Return: If carrry set, error code in AX +Registers used: AX and DX; DS if segment changed + +@MoveFil (56h) + +Moves or renames a file by changing its path specification. + +Syntax: @MoveFil &old, &new [,[segold] [,segnew]] + +Arguments: old = Offset of file spec to be renamed + new = Offset of new file spec + segold = Segment of old name (DS if none given) + segnew = Segment of new name (ES if none given) +Return: If carry set, error code in AX +Registers used: AX, DX, and DI; DS and ES if corresponding segments changed + + +@GetFirst (4Eh) and @GetNext (4Fh) + +Parses file specifications (optionally including wild cards) into +file names + +Syntax: @GetFirst &path [,[attribute] [,segment]] + @GetNext + +Arguments: path = Offset of ASCIIZ filespec (can have wild cards) + attribute = File attribute to search for (0 for normal if + none given) + segment = Segment of path (DS if none given) +Return: If carrry set, error code in AX +Registers used: @GetFirst = AX, CX, and DX; DS if segment changed + @GetNext = AX only + + +@GetDTA (1Ah) and @SetDTA (2Fh) + +Gets or sets the Disk Transfer Address (DTA) + +Syntax: @GetDTA + @SetDTA &buffer [,segment] + +Arguments: buffer = Offset of new DTA buffer + segment = Segment of new DTA buffer (DS if none given) +Return: @GetDTA = ES:BX points to DTA + @SetDTA = None +Registers used: AX for both; DS and DX for @SetDTA; ES and BX for @GetDTA + +@GetFilSz (42h) + +Gets the file size by moving the file pointer to end of the file. +Note that the file pointer is reset to zero. Thus this macro should +not be called during operations that move the pointer. + +Syntax: @GetFilSz handle + +Arguments: handle = Previously opened file handle +Return: If carrry clear, file length in DX:AX +Registers used: AX, BX, CX, and DX + + +@MovePrtAbs and @MovePtrRel (42h) + +Moves the file pointer in an open file. The pointer can be moved to +an absolute position, or relative to its current position. + +Syntax: @MovePrtAbs handle [,distance] + @MovePrtRel handle [,distance] + +Arguments: handle = Previously opened file handle + distance = Distance to move pointer - must be a 16-bit + constant or a 16- or 32-bit variable; or + leave blank and set distance in CX:DX before + macro call +Return: If carrry clear, file pointer position in DX:AX +Registers used: AX, BX, CX, and DX + +DIRECTORY CONTROL + +@MkDir, (39h), @RmDir (3Ah), and @ChDir (3Bh) + +Creates, deletes, or changes to the specified directory + +Syntax: @MkDir &path [,segment] + @RmDir &path [,segment] + @ChDir &path [,segment] + +Arguments: path = Offset of ASCIIZ string to + segment = Segment of path (DS if none given) +Return: If carrry set, error code in AX +Registers used: AX and DX; DS if segment changed + + +@GetDir (47h) + +Returns the current directory of the specified drive + +Syntax: @GetDir &path [,[drive] [,segment]] + +Arguments: buffer = Offset of buffer to receive ASCIIZ directory + drive = 8-bit drive number - 0=current, 1=A, 2=B, etc. + (0 if none given) + segment = Segment of path (DS if none given) +Return: If carrry set, error code in AX +Registers used: AX, SI, and DL; DS if segment changes + + +DRIVE CONTROL + +@GetDrv (0Eh) and @SetDrv (19h) + +Gets or sets the current drive + +Syntax: @GetDrv + @SetDrv drive + +Argument: drive = 8-bit drive number (0=A, 1=B, etc.) +Return: @GetDrv = Drive number in AL (0=A, 1=B, etc.) + @SetDrv = Number of drives in AL +Registers used: AX for both; DL for @SetDrv + + +@ChkDrv (36h) + +Gets various data about a disk + +Syntax: @ChkDrv [drive] + +Argument: drive = 8-bit drive number (0=current,A=1, B=2, etc.); + if none given, current assumed +Return: AX = Sectors per cluster (-1 if drive invalid) + BX = Available clusters + CX = Bytes per sector + DX = Clusters per drive +Registers used: AX, BX, CX, and DX + +PROCESS CONTROL + +@Exit (4Ch) + +Exits to DOS with return code + +Syntax: @Exit [#return] + +Argument: return = 8-bit code to return to DOS; if none given, + AL is used +Return: None +Registers used: AX + + +@Exec (4Bh) + +Executes a child process or an overlay + +Syntax: @Exec path, params [,[segpath] [,[segparams] [,overlay]]] + +Arguments: path = Offset of ASCIIZ filespec to be executed + params = Offset of process parameter block + segpath = Segment of filespec (DS if none given) + segparams = Segment of parameter block (ES if none given) + overlay = If not defined, normal process executed; + if defined, overlay executed +Return: If carry set, error code +Registers used: AX, SI, and DI; DS and ES if corresponding segments given + + +@GetRet (4Dh) + +Gets the return code of a child process + +Syntax: @GetRet + +Argument: None +Return: Return code in AX +Register used: AX + + +@TSR (31h) + +Terminates a program, but leaves it resident in memory + +Syntax: @TSR paragraphs [,#return] + +Arguments: return = Code to return to DOS; if none, AL used + paragraphs = Memory in paragraphs (16 bytes) to + allocate for resident program +Return: None +Registers used: AX and DX + +MEMORY CONTROL + +@FreeBlok (49h) + +Frees a block of memory + +Syntax: @FreeBlok [segment] + +Argument: segment = Starting address of memory to be freed; + if none, ES address assumed +Return: If carry set, error code in AX +Register used: AX; ES if segment given + + +@GetBlok (48h) + +Allocates a block of memory + +Syntax: @GetBlok paragraphs + +Argument: paragraphs = Paragraphs (16 bytes) of memory wanted +Return: AX and ES = Segment address of allocated memory + BX = Paragraphs actually allocated (may be + less than requested if memory is short) +Register used: AX and BX + + +@ModBlok (48h) + +Modifies an allocated block of memory + +Syntax: @ModBlok paragraphs [,segment] + +Argument: paragraphs = Paragraphs (16 bytes) of memory wanted + segment = Starting address of memory to be freed; + if none, ES address assumed +Return: If carry set, error code in AX, else: + ES = Segment address of allocated memory + BX = If carry is clear, paragraphs allocated +Register used: AX and BX; ES if segment given + +MISCELLANEOUS + +@GetDate (2Ah) and @SetDate (2Bh) + +Gets or sets the system date + +Syntax: @GetDate + @SetDate month, day, year + +Arguments: year = 16-bit year (1980-2099) + month = 8-bit month (1-12) + day = 8-bit day (1-31) +Return: For @GetDate: + AL = Day of week (0 = Sunday, 1 = Monday, etc.) + CX = Year (1980-2099) + DL = Month (1-12) + DH = Day (1-31) + For @SetDate: + AL = If date was valid 0, else -1 +Registers used: AX, CX, and DX + + +@GetTime (2Ch) and @SetTime (2Dh) + +Gets or sets the system time + +Syntax: @GetTime + @SetTime hour,minute,second,hundredth + +Arguments: hour = 8-bit hour (0-23) + minute = 8-bit hour (0-59) + second = 8-bit hour (0-59) + hundredth = 8-bit hour (0-99) +Return: For @GetTime: + CL = Hour (0-23) + CH = Minute (0-59) + DL = Second (0-59) + DH = Hundredth (0-99) + For @SetTime: + AL = If time was valid 0, else -1 +Registers used: AX, CX, and DX + + +@GetVer (30h) + +Gets the DOS version + +Syntax: @GetVer + +Argument: None +Return: AL = Major version (0 for versions prior to 2.0) + AH = Minor version + BH = OEM serial number + BL:CX = 24-bit user number +Register used: AX, BX, and CX + +@GetInt (35h) and @SetInt (25h) + +Gets or sets the vector for a specified interrupt routine + +Syntax: @GetInt #interrupt + @SetInt #interrupt, &vector [,segment] + +Arguments: interrupt = 8-bit interrupt number + vector = Offset of interrupt routine + segment = Segment of routine - if none given, DS assumed + for data; segment ignored for code labels +Return: @GetInt = None + @SetInt = ES:BX points to interrupt routine +Registers used: AX for both; ES and BX for @GetInt; DS and DS for @SetInt + + BIOS Macro Syntax and Description + + +MODE, PAGE, AND COLOR CONTROL + +@GetMode (I 10h F 0Fh) + +Gets the current video mode and page + +Syntax: @GetMode + +Arguments: None +Return: AL = Mode + AH = Width in characters + BH = Page +Registers used: AX and BH + + +@SetMode (I 10h F 00h) + +Gets the current video mode and page + +Syntax: @SetMode mode + +Arguments: mode = 8-bit video mode +Return: none +Registers used: AX + + +@SetColor (I 10h F 0Bh) + +Sets the background color + +Syntax: @SetColor color + +Arguments: color = 8-bit background color (0-15); + border color in text modes +Return: none +Registers used: AX and BX + + +@SetPalet (I 10h F 0Bh) + +Sets the color palette + +Syntax: @SetPalet color + +Arguments: color = 8-bit color palette (0-1 for modes 5 and 6) +Return: none +Registers used: AX and BX + +@SetPage (I 10h F 05h) + +Sets the video page + +Syntax: @SetPage page + +Arguments: page = 8-bit page number; 0-3 for modes 2 and 3 +Return: none +Registers used: AX + + +CHARACTER AND CURSOR CONTROL + +@GetCur (I 10h F 04h) + +Gets the cursor position and size + +Syntax: @GetCur [page] + +Arguments: page = 8-bit page with cursor (if none, 0 assumed) +Return: DL = Column + DH = Row + CL = Starting scan line + CH = Ending scan line +Registers used: AX, DX, CX, and BH + + +@SetCurPos (I 10h F 02h) + +Sets the cursor position + +Syntax: @SetCurSz [column] [,[row] [,page]] + +Arguments: column = 8-bit column; if none, DL used + row = 8-bit row; if none, DH used + page = 8-bit page with cursor (if none, 0 assumed) +Return: none +Registers used: AX, DX, and BH + + +@SetCurSz (I 10h F 01h) + +Sets the cursor size and shape by specifying active scan lines. The +CGA adapter the lines are 0-7. The monochrome adapter has lines 0-13. + +Syntax: @SetCurSz startline, endline + +Arguments: startline = 8-bit starting scan line (default CGA=6; MA=12) + endline = 8-bit ending scan line (default CGA=7; MA=13) +Return: none +Registers used: AX and CX + +@GetChAtr (I 10h F 08h) + +Gets the character and attribute at the cursor location + +Syntax: @GetChAtr [page] + +Arguments: page = 8-bit page to check (if none, 0 assumed) +Return: AH = Attribute + AL = ASCII character +Registers used: AX and BH + + +@PutChAtr (I 10h F 09h) and @PutCh (I 10h F 0Ah) + +Puts one or more characters and attributes at the current cursor +position. For @PutCh, the current attribute is used in text modes +and any specified attribute is ignored. + +Syntax: @PutChAtr [character] [,[attrib] [,[page] [,count]]] + +Arguments: character = 8-bit ASCII character to put; if none, AL used + attrib = 8-bit attribute to put; if none, BL used + page = 8-bit page to put on (if none, 0 assumed) + count = Number to put (if none, 1 assumed) +Return: AH = Attribute + AL = ASCII character +Registers used: AX, BX, CX + + +@Scroll (I 10h F 06h and 07h) + +Scrolls a specified window up or down + +Syntax: @Scroll dist [,[attr] [,[uprow [,[upcol [,[dnrow] [,dncol]]]]] + +Arguments: dist = 8-bit number of lines to scroll; positive + scrolls down; negative scrolls up; 0 clears + attr = 8-bit attribute for blank lines (if none, 07h) + uprow = Upper left row (if none, CH used) + upcol = Upper left column (if none, CL used) + dnrow = Lower right row (if none, DH used) + dncol = Lower right column (if none, DL used) +Return: none +Registers used: AX, CX, DX, and BH + + +@Cls (I 10h F 06, 08h, and 02h) + +Clears the screen of the current page + +Syntax: @Cls + +Arguments: None +Return: None +Registers used: AX, BX, CX, and DX + diff --git a/masm/MASM.TXT b/masm/MASM.TXT new file mode 100644 index 0000000..8a4b504 --- /dev/null +++ b/masm/MASM.TXT @@ -0,0 +1,1184 @@ + Microsoft(R) Macro Assembler Package + Version 5.10 + Copyright 1988, Microsoft Corporation + +Text files on the Macro Assembler disks are tabbed to save +disk space. If your printer does not automatically handle +tabs during printing, you must use a print program that +expands tabs. For example, use the DOS PRINT program to print +this and other document or source files on the disk. + + + The Microsoft Macro Assembler (MASM) + +Mixed-Language Support for Variables and Procedures +--------------------------------------------------- +All EXTRN, PUBLIC, and PROC items, as well as uses of the .MODEL +directive, support a language type. The language type of EXTRN +and PUBLIC variables determine whether or not an underscore is +prefixed to the name (an underscore is prefixed only for variables +with a C language type), and the language type of a procedure determines +its calling and naming conventions. For an explanation of calling +and naming conventions, see the Microsoft Mixed-Language Programming +Guide. + +The language type consists of the word "C" or "Pascal" and uses the +following syntax (lowercase items are placeholders, and bracketed items +are optional): + +EXTRN [] : +PUBLIC [] +procName PROC [NEAR|FAR] [] [USES ,] + +For example, the C and Pascal keywords are used correctly in the +following example: + + .MODEL SMALL,C + EXTRN Pascal DosOpen:FAR + PUBLIC C myVar +myOpen PROC Pascal fName:PTR, mode:WORD +. +. +. +myOpen ENDP + + +EVEN and ALIGN Directives +------------------------- +Padding for EVEN and ALIGN is now optimized. Data segments +are padded with zeros. Code segments are padded with special +two-byte NOP instructions where possible. The two-byte NOP +consists of the instruction XCHG BX,BX (87 DB hexadecimal) +which is executed faster than two one-byte NOP instructions. + +/B Option Ignored +----------------- +The /B option is now ignored, because its effect is irrelevant, +given the new file buffering mechanism. However, the option is +still accepted for the purposes of compatibility. + +The PTR Operator +---------------- +The PTR operator can be used to specify the size of a +register indirect operand for a CALL or JMP instruction. +However, the size cannot be specified with NEAR or FAR. Use +WORD or DWORD instead. (In 80386 32-bit segments, use DWORD +or FWORD.) Examples are shown below: + + ; 8086, 80826, or 80386 16-bit mode + + jmp WORD PTR [bx] ; Legal near jump + call NEAR PTR [bx] ; Illegal near call + call DWORD PTR [bx] ; Legal far call + jmp FAR PTR [bx] ; Illegal far jump + + ; 80386 32-bit mode only + + jmp DWORD PTR [bx] ; Legal near jump + call NEAR PTR [bx] ; Illegal near call + call FWORD PTR [bx] ; Legal far call + jmp FAR PTR [bx] ; Illegal far jump + +This limitation only applies to register indirect operands. +NEAR or FAR can be applied to operands associated with +labels. Examples are shown below: + + jmp NEAR PTR pointer[bx] ; Legal + call FAR PTR location ; Legal + +Assembler Behavior Change +------------------------- +Some errors and questionable practices that were ignored by +earlier versions are now flagged as errors. As a result, +existing source code may produce errors or warnings. +The following are examples: + + - Labels defined only during pass 1 cause errors if + used in expressions. + - A CS ASSUME that changes from pass 1 to pass 2 causes + an error. + - Constants are now checked for type overflow. + - Reserved words used as labels produce warnings. + - The OFFSET operator used with a constant causes an error. + +The STACK Combine Type +---------------------- +The description of the STACK combine type in Section 5.2.2.3 +does not explain how multiple initialized stack segments are +combined. The total size of the stack is the total size of +all stack definitions. LINK puts initialized data for each +defined stack segment at the end of the stack. Data initialized +in the last segment linked override data initialized in +previous segments. This behavior is usually not relevant, since +most programs only define one stack of uninitialized data. +Stack data cannot be initialized with simplified segment +directives. + +Clarification of Parsing Error +------------------------------ +The following error can be difficult to interpret because of the +way the assembler parses (analyzes) source code: + +A2015: Symbol already different kind: + +Typically, the assembler generates this error message when a +symbol is used in a way inconsistent with how it was declared: for +example, a symbol is declared as an external absolute but then used +as a local code label. However, the assembler also generates this +error when a symbol in the second source-code field can be interpreted +as either an operation or an operand. The following example illustrates +this problem: + +SYM1 MACRO structName, varName +varName structName <> + ENDM + +SYM2 STRUCT +field1 DB +field2 DW +SYM2 ENDS + + +SYM1 SYM2, + +The last line of code causes error A2015 to be generated. The +assembler first looks at the second field of the line, which +contains the symbol SYM2. Since SYM2 is a structure, the assembler +considers SYM2 to be an operation rather than an operand, and therefore +it considers SYM1 to be a label (rather than an operation). The way +to avoid this error is simply code the instruction as: + +SYM1 , + + +HIGH and LOW Operators +---------------------- +The HIGH and LOW operators work reliably only with constants +and with offsets to external symbols. HIGH and LOW operations are +not supported for offsets to local symbols. + +Mixed-Mode Programming (386 Only) +--------------------------------- +When assembling code for .386 mode, the assembler now supports direct- +addressing modes between segments with different USE sizes. (Segments can +have the USE16 or USE32 attribute; these attributes refer to the default +size of offsets.) Direct-addressing references to labels in other segments +are correctly resolved. In the following example, the assembler correctly +uses a 32-bit offset to access the data at label a32: + +.386 +SEG32 SEGMENT USE32 +a32 DD ? +SEG32 ENDS + +SEG16 SEGMENT USE16 + assume ds:seg32 + mov eax,a32 +SEG16 ENDS + +You can also execute a CALL or a JMP to a label in a segment with a +different USE size. However, the label must be declared FAR, and the +CALL or JMP must not be a forward reference. The following example +shows the correct method for executing such a CALL or JMP: + +.386 +COD16 SEGMENT USE16 'CODE' +proc16 PROC FAR + ret +proc16 ENDP + +lab16 LABEL FAR +COD16 ENDS + +COD32 SEGMENT USE32 'CODE' + call proc16 + jmp lab16 +COD32 ENDS + +Additional Error Messages +------------------------- + +19 Wrong type of register + +The register specified in the operand field was incompatible with the +directive or instruction in the operation field. For example, the following +instruction causes this error because you cannot increment the +code segment: + + inc cs + + +36 Extra NOP inserted + +During pass 1 the assembler did not have enough information to +correctly infer the length of the encoding for the instruction. +During pass 2 the encoding was found to be shorter than the space +allocated from pass 1, so one or more NOP instructions were inserted +as padding. It may be possible to generate a smaller amount of code +by eliminating a forward reference to a symbol. + + + The Microsoft Cross-Reference Utility (CREF) + +New Feature +----------- +Cross-reference listing files created with CREF now have an +additional symbol. A line number followed by + indicates +that a symbol is modified at the given line. For example: + + TST . . . . . . . . . . . . . . 134# 237 544+ + +The symbol TST is defined at line 134, used at line 237, and +modified at line 544. + + + The Mouse Driver + +If you use the Microsoft Mouse with the Microsoft CodeView(R) debugger +you must have Version 6.0 or later of the Microsoft Mouse. If you do not, use +the version of the MOUSE.COM driver provided in this package. Copy MOUSE.COM +to the appropriate mouse directory. When you are ready to use the mouse, type + + mouse + +at the DOS command level. If you want to install the mouse driver automatically +every time you reboot, insert the "mouse" command in your AUTOEXEC.BAT file. + +Note that in earlier releases of Microsoft C, both the MOUSE.SYS and the +MOUSE.COM driver were provided. If you have been using an earlier version +of the MOUSE.SYS driver, delete the following line from your CONFIG.SYS file: + + device=\\mouse.sys + +where is the directory where the earlier mouse driver resides. + + + Microsoft CodeView Debugger + +New Command-Line Option +----------------------- +If you have an IBM Personal System/2, then you can use the /50 +command-line option to start the CodeView debugger in 50-line mode. +Note that you must be in 25-line mode to effectively use either the +/43 or /50 command-line option. + +CONFIG.SYS Setting for CVP +-------------------------- +To run the protected-mode CodeView debugger (CVP.EXE), you must have +the following line in your CONFIG.SYS file: + + IOPL=YES + + +Using the 7 Command in Protected Mode +------------------------------------- +If you are using OS/2 protected mode and have a math coprocessor, then +you need to use a patch before you can use the CVP 7 command. To apply +the patch, use the OS2PATCH.EXE and PTRACE87.PAT files that come on the +same disk that CVP.EXE comes on. You also need to locate the PATCH.EXE file +that comes with OS/2 and make sure that this file is in a directory listed +in your PATH environment variable. Then follow these steps: + +1) Change the current drive and directory to the root directory of the + boot disk. (If the boot disk is a floppy, make sure it is inserted + in the drive you used to boot from.) + +2) Give the following command line at the DOS prompt: + + OS2PATCH /A PTRACE87.PAT + +Note that you may need to give the complete path names for the +OS2PATCH.EXE and for the PTRACE87.PAT file. You do not need to give +a path name for the OS2PATCH.EXE file if you have placed this file +in a directory listed in your PATH environment variable. + +Using the Real-Mode Debugger in the Compatibility Box +----------------------------------------------------- +When running the real-mode CodeView debugger in the DOS 3.x +compatibility box, start the debugger with the /S command-line +option. Otherwise, the mouse pointer will not appear. + +Using the CodeView Debugger with BIND +------------------------------------- +The real-mode CodeView debugger cannot debug bound (dual-mode) +applications. However, the protected-mode CodeView debugger, +CVP, can debug bound applications. + +Expression Evaluator for BASIC Programs +--------------------------------------- +In the BASIC expression evaluator, "+" is not supported for string +concatenation. + +Stack Trace Command +------------------- +In order for the Stack Trace command (or the Calls menu) to work +reliably, you need to execute to at least the beginning of the main +function or procedure, and the current module should have full CodeView +information (a module has full CodeView information if compiled or +assembled with /Zi). + +Error Messages +-------------- +The error message "? cannot display" indicates that the Display +Expression command (?) has been passed a valid symbol that it +cannot display. In previous versions of the debugger, structures +could not be displayed. With current version of the debugger, only +the enums type cannot be displayed. + +The error message "Expression not a memory address" occurs when +the Tracepoint command is given without a symbol that evaluates to +a single memory address. For example, the commands "TP?1" and +"TP?a+b" each produce this error message. The proper way to put a +tracepoint on the word at address 1 is with the command "TPW 1". + +The error message "Function call before 'main'" occurs when you +attempt to evaluate a program-defined function before you have entered +the main function. Execute to at least to the beginning of the main +function before attempting to evaluate program-defined functions. + +The error message "Bad emulator info" occurs when CodeView cannot +read data from the floating-point emulator. + +The error message "Floating point not loaded" has a special meaning +for CVP (in addition to the explanation given in the CodeView and +Utilities manual). Each thread has its own floating-point emulator. +This message is issued when the current thread has not initialized +its own emulator. + +Microsoft Pascal Programs +------------------------- +In this release, Microsoft Pascal programs cannot be debugged with +the CodeView debugger. + + + Exit Codes for Utilities + +The exit codes for LINK and the utilities in the Microsoft CodeView +and Utilities manual should appear as follows: + +LINK +---- + Code Meaning + + 0 No error. + + 2 Program error--something was wrong with the commands + or files input to the linker. + + 4 System error. The linker + + - ran out of space on output files + - was unable to reopen the temporary file + - experienced an internal error + - was interrupted by the user + +LIB, EXEPACK, EXEMOD, MAKE, and SETENV +--------------------------------------- + Code Meaning + + 0 No error. + + 2 Program error--something was wrong with the commands + or files input to the utility. + + 4 System error. The utility ran out of memory, was + interrupted by the user, or experienced an internal + error. + + Microsoft Overlay Linker (LINK) + +Overlay Restrictions +-------------------- +You cannot use long jumps (using the longjmp library function) or indirect +calls (through a function pointer) to pass control to an overlay. When a +function is called through a pointer, the called function must be in the same +overlay or in the root. + +Changed LINK Error Messages +--------------------------- +The explanation for fatal-error message L1008 is changed as follows: + + The /SEGMENTS option specified a limit greater than 3072 on the + number of segments allowed. + +Error message L1009 has been changed to read as follows: + + L1009 : CPARMAXALLOC : illegal value + +Error message L1053 has been changed to read as follows: + + L1053 out of memory for symbol table + + The program had more symbolic information (such as public, external, + segment, group, class, and file names) than the amount that could fit + in available real memory. + + Try freeing memory by linking from the DOS command level instead of + from a MAKE file or from an editor. Otherwise, combine modules or + segments and try to eliminate as many public symbols as possible. + +Warning message L4050 has been changed as follows: + + L4050 too many public symbols for sorting + + The linker uses the stack and all available memory in the + near heap to sort public symbols for the /MAP option. If + the number of public symbols exceeds the space available + for them, this warning is issued, and the symbols are not + sorted in the map file but are listed in arbitrary order. + +New LINK Error Messages +----------------------- +L1003 /QUICKLIB, /EXEPACK incompatible + +You cannot link with both the /QU option and the /E option. + +L1006 : stack size exceeds 65535 bytes + +The value given as a parameter to the /STACKSIZE option exceeds the +maximum allowed. + +L1063 out of memory for CodeView information + +The linker was given too many object files with debug information, +and the linker ran out of space to store it. Reduce the number +of object files that have debug information. + +L1115 /QUICKLIB, overlays incompatible + +You specified overlays and used the /QUICKLIB option. +These cannot be used together. + +L2013 LIDATA record too large + +An LIDATA record contained more than 512 bytes. This is +probably a compiler error. + +L2024 : special symbol already defined + +Your program defined a symbol name that is already used by the linker +for one of its own low-level symbols. (For example, the linker +generates special symbols used in overlay support and other operations.) +Choose another name for the symbol in order to avoid conflict. + +L2025 : segment with > 1 class name not allowed with /INC + +Your program defined a segment more than once, giving the segment +different class names. Different class names for the same segment +are not allowed when you link with the /INCREMENTAL option. Normally, +this error should never appear unless you are programming with MASM. +For example, if you give the two MASM statements + +_BSS segment 'BSS' + +and + +_BSS segment 'DATA' + +then the statements have the effect of declaring two distinct segments. +ILINK does not support this situation, so it is disallowed when the +/INCREMENTAL option is used. + + +L2041 stack plus data exceed 64K + +The total of near data and requested stack size exceeds 64K, +and the program will not run correctly. Reduce the stack size. +The linker only checks for this condition if /DOSSEG +is enabled, which is done automatically in the library +startup module. + +L2043 Quick Library support module missing + +When creating a Quick library, you did not link with the required +QUICKLIB.OBJ module. + +L2044 : symbol multiply defined, use /NOE + +The linker found what it interprets as a public-symbol +redefinition, probably because you have redefined a symbol that +is defined in a library. Relink with the /NOEXTDICTIONARY +(/NOE) option. If error L2025 results for the same symbol, then you +have a genuine symbol-redefinition error. + +L4003 intersegment self-relative fixup at in segment + pos: Record type: 9C target external '' + +The linker found an intersegment self-relative fixup. This error +may be caused by compiling a small-model program with the /NT +option. + +L4034 more than 239 overlay segments; extra put in root + +Your program designated more than the limit of 239 segments to +go in overlays. Starting with the 234th segment, they are assigned to +the root (that is, the permanently resident portion of the program). + + + Microsoft Library Manager (LIB) + +New Option +---------- +There is a new option for LIB: /NOIGNORECASE (abbreviated as /N). +This option tells LIB to not ignore case when comparing symbols. +names. By default, LIB ignores case. Multiple symbols that are +the same except for case can be put in the same library. An +example of this is: "_Open" and "_open". Normally you could not +add both these symbols to the same library. + +Note that if a library is built with /NOI, the library is +internally "marked" to indicate /NOI. All libraries built +with earlier versions of LIB are not marked. + +If you combine multiple libraries, and any one of them is +marked /NOI, then /NOI is assumed for the output library. + +In addition, LIB also supports the option /IGNORECASE (/I), which +is completely analogous to /NOIGNORECASE. /I is the default. The only +reason to use it would be if you have an existing library marked /NOI +that you wanted to combine with other libraries which were not marked, +and have the output library be not marked. If you don't use +/IGNORECASE, the output is marked /NOI (see above). + +Changed LIB Error Messages +-------------------------- +Warning messages U4152, U4155, and U4157-U4159 for LIB are now +nonfatal error messages U2152, U2155, and U2157-U2159, respectively. + +Warning message U4151 has been changed to read as follows: + + U4151 '' : symbol defined in module , redefinition ignored + +New LIB Error Messages +---------------------- +The following new warning messages have been added for LIB: + +U4155 : module not in library + +A module specified to be replaced does not already exist in the +library. LIB adds the module anyway. + +U4157 insufficient memory, extended dictionary not created +U4158 internal error, extended dictionary not created + +For the reason indicated, LIB could not create an extended +dictionary. The library is still valid, but the linker +is not able to take advantage of the extended dictionary +to speed linking. + + + Microsoft Program Maintenance Utility (MAKE) + +New Error Message +----------------- +U1015: : error redirection failed + +This error occurs if the /X option is given and error output cannot +be redirected to the given file (for example, because the file +is read-only). + +Inference Rules +--------------- +You cannot have inference rules in both the TOOLS.INI and the description +file that use both the same inextension and outextension. For example, you +cannot place the following inference rule in the TOOLS.INI file: + + .c.obj: + cl /c /Zi /Od $*.c + +while also placing the following line in the description file: + + .c.obj: + cl /Ot $*.c + +However, you can define the same macro in both the TOOLS.INI and the +description file. In such cases, the definition in the description file +takes precedence. + +Backslash (\) as Continuation Character +--------------------------------------- +Note that MAKE considers a backslash immediately followed by a new-line +character to be a continuation character. When it finds this combination +in a description file, MAKE concatenates the line immediately following +the combination with the line where the combination appears. + +If you define a macro that ends in a backslash, make sure that you put a +space after the terminating backslash. For example, if you want to define +macros for the path C:\SRC\BIN and C:\SRC\LIB, you must use the format +illustrated below: + + BINPATH=C:\SRC\BIN\ + LIBPATH=C:\SRC\LIB\ + +To illustrate the problems that can result if you do not put a space before the +new-line character, assume that the macros above appear as shown below +instead: + + BINPATH=C:\SRC\BIN\ + LIBPATH=C:\SRC\LIB\ + +Because a new-line character appears immediately after the backslash at the end +of the first macro, MAKE assumes that you are defining the single macro shown +below: + + BINPATH=C:\SRC\BIN\LIBPATH=C:\SRC\LIB\ + + + + Microsoft STDERR Redirection Utility (ERROUT) + +The ERROUT utility does not accept batch files. To redirect standard-error +output from a batch file, you must enter a command of the following form: + + ERROUT COMMAND /c + +If no /f option is given, then ERROUT redirects standard-error output to +the standard-output device. + + + Mixed-Language Programming + +Setting Up Calls to High-Level Languages +---------------------------------------- +Section 6.6 of the Microsoft Mixed-Language Programming Guide gives in- +structions for setting up a call to a high-level language from assembly +language. Before you execute a call to a BASIC, Pascal, or FORTRAN routine, +remember to declare an additional parameter if the return value is noninteger. +This additional parameter must contain the offset address of the return value, +for which you must allocate room within the stack segment (normally DGROUP, +the same as the default data segment). + + + The BIND Utility + +Specifying Libraries +-------------------- +You need to include DOSCALLS.LIB on the BIND command line. If +DOSCALLS.LIB is not in the current directory, you must give the +complete path name to DOSCALLS.LIB. + +BIND automatically searches for API.LIB by looking in directories +listed in the LIB environment variable. However, if API.LIB is +specified on the command line, then BIND will not check the LIB +environment variable; instead, you will need to give the complete +path name. + +For example, the following command line successfully uses BIND, if +API.LIB is located in a directory listed in the LIB environment +variable: + +BIND FOO.EXE \LIB\DOSCALLS.LIB + +Using BIND with Packed Files +---------------------------- +The version of BIND released with this package does not work with +files that have been linked with the /EXEPACK linker option. + +Running Bound Files with DOS 2.1 +-------------------------------- +A dual-mode executable file produced with BIND can be run in both +DOS 3.x and DOS 2.x environments. However, if you change the name +of an executable file produced by BIND, then it will not run under +DOS 2.1. + + + The Microsoft Incremental Linker (ILINK) + +ILINK Fatal Error Messages +-------------------------- + +.sym seek error +.sym read error + + The .SYM file is corrupted. Do a full link. If the error + persists, contact Microsoft. + +.sym write error + + The disk is full or the .SYM file already exists with the + READONLY attribute. + +map for segment exceeds 64K + + The symbolic information associated with the given segment + exceeds 64K bytes, which is more than ILINK can handle. + +can't ilink library + + You tried to incrementally link an altered library. + ILINK does not link .LIB files but only .OBJ files. + Use a full link instead. + +.obj close error + + The operating system returned an error when ILINK attempted + to close one of the .OBJ files. Do a full link. If the error + persists, contact Microsoft. + +too many LNAMES in + + An object module has more than 255 LNAME records. + +too many SEGDEFs in + + The given object module has more than 100 SEGDEF records. + +too many GRPDEFs in + + The given object module has more than 10 GRPDEF records. + +symbol multiply defined + + The given symbol is defined more than once. + +#3 + + Please report this error to Microsoft. + +Out of Memory + + ILINK ran out of memory for processing the input. If you + are running ILINK under MAKE, try running it from the shell. + Otherwise, do a full link. + +could not run exec + + ILINK was unable to find the file EXEC.EXE, which should be + placed somewhere in the search path or in the current + directory. + +.exe file too big, change alignment + + The segment sector alignment value in the .EXE file is too + small to express the size of one of the segments. Do a full + link and increase the alignment value with the /ALIGNMENT + option to LINK. + +.ilk seek error + + The .ILK file is corrupted. Do a full link. If the error + persists, contact Microsoft. + +Too many defined segments + + ILINK has a limit of 255 defined segments, which are segments + defined in an object module as opposed to an executable segment. + Reduce the number of segments if you want to use ILINK. + +too many library files + + ILINK has a limit of 32 runtime libraries (.LIB files). Reduce + the number of libraries. + +too many modules + + ILINK has a limit of 1204 modules in a program. Reduce the + number of modules. + +.ilk write error + + The disk is full, or else ILINK cannot write to the .SYM file + because a .SYM file currently exists and has the READONLY attribute. + +file does not exist + + ILINK was unable to open the given file. The file named was + in the file list in the .ILK file. + +seek error on library + + A .LIB file was corrupted. Do a full link and check your .LIB + files. + +library close error + + The operating system returned an error when ILINK attempted + to close one of the .LIB files. Do a full link. If the error + persists, contact Microsoft. + +error closing EXE file + + The operating system returned an error when ILINK attempted + to close the .EXE file. Do a full link. If the error + persists, contact Microsoft. + +Invalid module reference + + The program makes a dynamic link reference to a dynamic link + module which is not represented in the .EXE file. + +could not update time on + + The operating system returned an error when ILINK attempted + to update the time on the given file. Possibly the file had + the READONLY attribute set. + +invalid flag +only one -e command allowed + + The ILINK command syntax is incorrect. + +User Abort + + The user issued CTRL+C or CTRL+BREAK. + +file write protected + + The .EXE, .ILK, or .SYM file needed to be updated and has the + READONLY attribute. Change attribute to READWRITE. + +file missing + + One of the .OBJ files specified on the command line is missing. + +file invalid .OBJ format +file has invalid record + + The given .OBJ file has an invalid format or one that is not + recognized by ILINK. This may have been caused by a compiler + or assembler. + +file was not full linked + + An .OBJ file was specified as input to ILINK, which was not in + the list of files in the original full link. + +LOBYTE seg-relative fixups not supported + + This error message should occur only with MASM files. See the + Microsoft Macro Assembler 5.0 Programmer's Guide. This type of + object module is not supported by ILINK. + + undefined symbols + + The given number of symbols were referred to in fixups but + never publicly defined in the program. + +Incremental Violations +---------------------- +These errors cause a full link to occur if the -e option is used and -i +is not used, else they are fatal errors: + +symbol deleted + + A symbol was deleted from an incrementally-linked module. + + contains new SEGMENT + + A segment was added to the program. + + contains changed segment + + The segment contribution (code or data which the module + contributes to a segment) changed for the given module: it + contributed to a segment it didn't previously contribute to, + or a contribution was removed. + +'s segment grew too big + + The given segment grew beyond the padding for the given module. + + contains new GROUP + + A new group was defined, via the GROUP directive in assembly + language or via the /ND C compiler option. + + redefines group to include + + The members of the given group changed. + +symbol changed + + The given data symbol was moved. + +can't add new communal data symbol + + A new communal data symbol was added as an uninitialized variable + in C or with the COMM feature in MASM. + +communal variable grew too big + + The given communal variable changed size too much. + +invalid symbol type for + + A symbol which was previously code became data, or vice versa. + +too many COMDEFS +too many EXTDEFS + + The limit on the total of COMDEF records (communal data variables) + and EXTDEF records (external references) is 2000. + +invalid CodeView information in .EXE file + + The CodeView information found is invalid. + + contains new Codeview symbolic info + + A module previously compiled without -Zi was compiled with -Zi. + + contains new linnum info + + A module previously compiled without -Zi or -Zd was compiled + with -Zi or -Zd. + + contains new public CV info + + New information on public-symbol addresses was added. + +invalid .exe file + + The .EXE file is invalid. Make sure you are using an up-to-date + linker. If the error persists, contact Microsoft. + +invalid .ilk file +.ilk read error +.ilk seek error + + The .ILK file is invalid. Make sure you are using an up-to-date + linker. If the error persists, contact Microsoft. + +.SYM/.ILK mismatch + + The .SYM and .ILK files are out of sync. Make sure you are using + an up-to-date linker. If the error persists, contact Microsoft. + + has changed + + The given library has changed. + +can't link 64K-length segments + + ILINK cannot handle segments greater than 65,535 bytes long. + +can't link iterated segments + + ILINK cannot handle programs linked with /EXEPACK. + +Entry table expansion not implemented + + The program call tree changed in such a way that ILINK could + not handle it. + +file does not exist + + The .EXE, .SYM, or .ILK files are missing. + + has changed + + The given library module name has changed. + +ILINK Warning messages +---------------------- + +Fixup frame relative to an (as yet) undefined symbol - assuming ok + + See documentation for LINK error messages L4001 and L4002, + in the Microsoft CodeView and Utilities manual. + + contains TYPEDEFs - ignored + contains BLKDEFs - ignored + + The .OBJ file contains records no longer supported by Microsoft + language compilers. + +old .EXE free information lost + + The free list in the .EXE file has been corrupted. The free + list keeps track of "holes" of free space in the EXE file. These + holes are made available when segments are moved to new locations. + +file has no useful contribution + + The given module makes no contribution to any segment. + +Main entry point moved + + The program starting address changed. You may want to consider + doing a full link. + + + Microsoft Editor + +Installing the Editor +--------------------- +The Microsoft Editor does not come with an MESETUP program. Instead, +run the setup program for the assembler. This program offers you choices +about how to set up the editor. + +Keystroke Configurations +------------------------ +Some of the keystroke configurations listed in Table A.2 of the +Microsoft Editor User's Guide may need to be changed. + +In the Quick/WordStar configuration, the Sinsert function is assigned +to ALT+INS, not CTRL+INS. + +In the BRIEF configuration, the Plines function is assigned to CTRL+Z, +and the Refresh function is assigned to CTRL+]. + +In the EPSILON configuration, the Ppage function is assigned to PGDN, +and the Sdelete function is assigned to DEL and CTRL+D. + +The Compile Function +-------------------- +The commands + + Arg streamarg Compile + Arg textarg Compile + +each use the command specified by the extmake:text switch. The +editor does not check the extension of the file name given as an +argument, but instead uses the "text" extension. The streamarg +or textarg replaces a %s in the command. These commands are typically +used to invoke MAKE. + +The Setfile Function +-------------------- +The commands that use Setfile, along with a streamarg or textarg, +accept a variety of input: either the name of a file, a file name +with a wild-card character (* or ?), the name of a directory, or the +name of a disk drive. File names can also include environment variables, +such as $INIT. If the streamarg or textarg is a directory name, then +the editor changes the current directory. If the argument is a drive +name, then the editor changes the current drive. Environment variables +are translated into directories to be searched for a file. For example, +the following macro directs the editor to search the $INIT environment +variable in order to find the tools.ini file: + + tools.ini := Arg "$INIT:tools.ini" Setfile + tools.ini :ctrl+j + +Entering Strings in Macros +-------------------------- +When you enter a text argument directly, no characters have special +meaning (except when the argument is interpreted as a regular +expression). However, when you enter text as part of a macro, then +strings inside of quotes are interpreted according to the C string +format. This format uses a backslash followed by double quotes (\") +to represent double quotes and it uses two backslashes (\\) to represent +a single backslash. Therefore, to find the next occurrence of the string + + She wrote, "Here is a backslash: \ " + +you could use the following macro definition: + + findit := Arg "She wrote, \"Here is a backslash: \\ \"" Psearch + +Note that to indicate a backslash for a regular expression that is +also part of a macro definition, you must use four consecutive +backslashes. + + +Using Text Switches +------------------- +The text switches extmake and readonly each take a special +kind of syntax that allows you to specify drive, file name, +base name, or file extension. The syntax consists of the +characters: + +%|F + +where consists of any of the following: "p" for path, +"d" for drive, "f" for file base name, or "e" for file extension. +For example, if you are editing the file c:\dir1\sample.c, and you +make the following switch assignment: + +extmake:c cl /Fod:%|pfF %|dfeF + +then each time you give the command , the editor +performs the following system-level command: + +cl /Fod:\dir1\sample c:sample.c + +The expression "%s" is equivalent to "%|feF" except that the former +only works once, whereas the latter can appear any number of times +in the extmake switch assignment. The expression "%|F" is equivalent +to "%|dpfeF". + +The Filetab Switch +------------------ +The filetab switch is a numeric switch that determines how the +editor translates tabs when loading a file into memory. The value +of the switch gives the number of spaces associated with each tab +column. For example, the setting "filetab:4" assumes a tab column +every 4 positions on each line. Every time the editor finds a tab +character in a file, it loads the buffer with the number of spaces +necessary to get to the next tab column. Depending on the value of +the entab switch, the editor also uses the filetab switch to determine +how to convert spaces into tabs when writing to a file. The default +value of filetab is 8. + + +Functions Callable by C Extensions +---------------------------------- +The following list summarizes functions from the standard compact- +memory-model library, which should work when called by a C-extension +module. (The technique of programming C extensions is presented in +Chapter 8 of the Microsoft Editor User's Guide.) The memory model +of the extension is assumed to be /Asfu (small code pointers, far +data pointers, and stack segment unequal to data segment). This list +uses the function categories from Chapter 4 of the Microsoft C +Optimizing Compiler Run-Time Library Reference (Version 4.0 +or later.) + +Buffer Manipulation: All functions can be called. + +Character Classification and Conversion: All functions can be called. + +Data Conversion: All functions can be called except for + + strtod() + +Directory Control: All functions can be called except for + + getcwd() + +File Handling: All functions can be called. + +Low-Level I/O Routines: All functions can be called, but write() +will not work in binary mode. + +Console and Port I/O: All functions can be called except for + + cgets() + cprintf() + cscanf() + +Searching and Sorting: All functions can be called except for + + qsort() + +String Manipulation: All functions can be called except for + + strdup() + +BIOS Interface: All functions can be called. + +MS-DOS Interface: All functions can be called except for + + int86() + int86x() + +Time: All functions can be called except for + + ctime() + gmtime() + localtime() + utime() + +Miscellaneous: All functions can be called except for + + assert() + getenv() + perror() + putenv() + _searchenv() + + +Linking Extensions in Protected Mode +-------------------------------------- +To link C extension modules in protected mode, link with the +object file EXTHDRP.OBJ, instead of the real-mode header +EXTHDR.OBJ. diff --git a/masm5/masm5.txt b/masm5/masm5.txt new file mode 100644 index 0000000..8a4b504 --- /dev/null +++ b/masm5/masm5.txt @@ -0,0 +1,1184 @@ + Microsoft(R) Macro Assembler Package + Version 5.10 + Copyright 1988, Microsoft Corporation + +Text files on the Macro Assembler disks are tabbed to save +disk space. If your printer does not automatically handle +tabs during printing, you must use a print program that +expands tabs. For example, use the DOS PRINT program to print +this and other document or source files on the disk. + + + The Microsoft Macro Assembler (MASM) + +Mixed-Language Support for Variables and Procedures +--------------------------------------------------- +All EXTRN, PUBLIC, and PROC items, as well as uses of the .MODEL +directive, support a language type. The language type of EXTRN +and PUBLIC variables determine whether or not an underscore is +prefixed to the name (an underscore is prefixed only for variables +with a C language type), and the language type of a procedure determines +its calling and naming conventions. For an explanation of calling +and naming conventions, see the Microsoft Mixed-Language Programming +Guide. + +The language type consists of the word "C" or "Pascal" and uses the +following syntax (lowercase items are placeholders, and bracketed items +are optional): + +EXTRN [] : +PUBLIC [] +procName PROC [NEAR|FAR] [] [USES ,] + +For example, the C and Pascal keywords are used correctly in the +following example: + + .MODEL SMALL,C + EXTRN Pascal DosOpen:FAR + PUBLIC C myVar +myOpen PROC Pascal fName:PTR, mode:WORD +. +. +. +myOpen ENDP + + +EVEN and ALIGN Directives +------------------------- +Padding for EVEN and ALIGN is now optimized. Data segments +are padded with zeros. Code segments are padded with special +two-byte NOP instructions where possible. The two-byte NOP +consists of the instruction XCHG BX,BX (87 DB hexadecimal) +which is executed faster than two one-byte NOP instructions. + +/B Option Ignored +----------------- +The /B option is now ignored, because its effect is irrelevant, +given the new file buffering mechanism. However, the option is +still accepted for the purposes of compatibility. + +The PTR Operator +---------------- +The PTR operator can be used to specify the size of a +register indirect operand for a CALL or JMP instruction. +However, the size cannot be specified with NEAR or FAR. Use +WORD or DWORD instead. (In 80386 32-bit segments, use DWORD +or FWORD.) Examples are shown below: + + ; 8086, 80826, or 80386 16-bit mode + + jmp WORD PTR [bx] ; Legal near jump + call NEAR PTR [bx] ; Illegal near call + call DWORD PTR [bx] ; Legal far call + jmp FAR PTR [bx] ; Illegal far jump + + ; 80386 32-bit mode only + + jmp DWORD PTR [bx] ; Legal near jump + call NEAR PTR [bx] ; Illegal near call + call FWORD PTR [bx] ; Legal far call + jmp FAR PTR [bx] ; Illegal far jump + +This limitation only applies to register indirect operands. +NEAR or FAR can be applied to operands associated with +labels. Examples are shown below: + + jmp NEAR PTR pointer[bx] ; Legal + call FAR PTR location ; Legal + +Assembler Behavior Change +------------------------- +Some errors and questionable practices that were ignored by +earlier versions are now flagged as errors. As a result, +existing source code may produce errors or warnings. +The following are examples: + + - Labels defined only during pass 1 cause errors if + used in expressions. + - A CS ASSUME that changes from pass 1 to pass 2 causes + an error. + - Constants are now checked for type overflow. + - Reserved words used as labels produce warnings. + - The OFFSET operator used with a constant causes an error. + +The STACK Combine Type +---------------------- +The description of the STACK combine type in Section 5.2.2.3 +does not explain how multiple initialized stack segments are +combined. The total size of the stack is the total size of +all stack definitions. LINK puts initialized data for each +defined stack segment at the end of the stack. Data initialized +in the last segment linked override data initialized in +previous segments. This behavior is usually not relevant, since +most programs only define one stack of uninitialized data. +Stack data cannot be initialized with simplified segment +directives. + +Clarification of Parsing Error +------------------------------ +The following error can be difficult to interpret because of the +way the assembler parses (analyzes) source code: + +A2015: Symbol already different kind: + +Typically, the assembler generates this error message when a +symbol is used in a way inconsistent with how it was declared: for +example, a symbol is declared as an external absolute but then used +as a local code label. However, the assembler also generates this +error when a symbol in the second source-code field can be interpreted +as either an operation or an operand. The following example illustrates +this problem: + +SYM1 MACRO structName, varName +varName structName <> + ENDM + +SYM2 STRUCT +field1 DB +field2 DW +SYM2 ENDS + + +SYM1 SYM2, + +The last line of code causes error A2015 to be generated. The +assembler first looks at the second field of the line, which +contains the symbol SYM2. Since SYM2 is a structure, the assembler +considers SYM2 to be an operation rather than an operand, and therefore +it considers SYM1 to be a label (rather than an operation). The way +to avoid this error is simply code the instruction as: + +SYM1 , + + +HIGH and LOW Operators +---------------------- +The HIGH and LOW operators work reliably only with constants +and with offsets to external symbols. HIGH and LOW operations are +not supported for offsets to local symbols. + +Mixed-Mode Programming (386 Only) +--------------------------------- +When assembling code for .386 mode, the assembler now supports direct- +addressing modes between segments with different USE sizes. (Segments can +have the USE16 or USE32 attribute; these attributes refer to the default +size of offsets.) Direct-addressing references to labels in other segments +are correctly resolved. In the following example, the assembler correctly +uses a 32-bit offset to access the data at label a32: + +.386 +SEG32 SEGMENT USE32 +a32 DD ? +SEG32 ENDS + +SEG16 SEGMENT USE16 + assume ds:seg32 + mov eax,a32 +SEG16 ENDS + +You can also execute a CALL or a JMP to a label in a segment with a +different USE size. However, the label must be declared FAR, and the +CALL or JMP must not be a forward reference. The following example +shows the correct method for executing such a CALL or JMP: + +.386 +COD16 SEGMENT USE16 'CODE' +proc16 PROC FAR + ret +proc16 ENDP + +lab16 LABEL FAR +COD16 ENDS + +COD32 SEGMENT USE32 'CODE' + call proc16 + jmp lab16 +COD32 ENDS + +Additional Error Messages +------------------------- + +19 Wrong type of register + +The register specified in the operand field was incompatible with the +directive or instruction in the operation field. For example, the following +instruction causes this error because you cannot increment the +code segment: + + inc cs + + +36 Extra NOP inserted + +During pass 1 the assembler did not have enough information to +correctly infer the length of the encoding for the instruction. +During pass 2 the encoding was found to be shorter than the space +allocated from pass 1, so one or more NOP instructions were inserted +as padding. It may be possible to generate a smaller amount of code +by eliminating a forward reference to a symbol. + + + The Microsoft Cross-Reference Utility (CREF) + +New Feature +----------- +Cross-reference listing files created with CREF now have an +additional symbol. A line number followed by + indicates +that a symbol is modified at the given line. For example: + + TST . . . . . . . . . . . . . . 134# 237 544+ + +The symbol TST is defined at line 134, used at line 237, and +modified at line 544. + + + The Mouse Driver + +If you use the Microsoft Mouse with the Microsoft CodeView(R) debugger +you must have Version 6.0 or later of the Microsoft Mouse. If you do not, use +the version of the MOUSE.COM driver provided in this package. Copy MOUSE.COM +to the appropriate mouse directory. When you are ready to use the mouse, type + + mouse + +at the DOS command level. If you want to install the mouse driver automatically +every time you reboot, insert the "mouse" command in your AUTOEXEC.BAT file. + +Note that in earlier releases of Microsoft C, both the MOUSE.SYS and the +MOUSE.COM driver were provided. If you have been using an earlier version +of the MOUSE.SYS driver, delete the following line from your CONFIG.SYS file: + + device=\\mouse.sys + +where is the directory where the earlier mouse driver resides. + + + Microsoft CodeView Debugger + +New Command-Line Option +----------------------- +If you have an IBM Personal System/2, then you can use the /50 +command-line option to start the CodeView debugger in 50-line mode. +Note that you must be in 25-line mode to effectively use either the +/43 or /50 command-line option. + +CONFIG.SYS Setting for CVP +-------------------------- +To run the protected-mode CodeView debugger (CVP.EXE), you must have +the following line in your CONFIG.SYS file: + + IOPL=YES + + +Using the 7 Command in Protected Mode +------------------------------------- +If you are using OS/2 protected mode and have a math coprocessor, then +you need to use a patch before you can use the CVP 7 command. To apply +the patch, use the OS2PATCH.EXE and PTRACE87.PAT files that come on the +same disk that CVP.EXE comes on. You also need to locate the PATCH.EXE file +that comes with OS/2 and make sure that this file is in a directory listed +in your PATH environment variable. Then follow these steps: + +1) Change the current drive and directory to the root directory of the + boot disk. (If the boot disk is a floppy, make sure it is inserted + in the drive you used to boot from.) + +2) Give the following command line at the DOS prompt: + + OS2PATCH /A PTRACE87.PAT + +Note that you may need to give the complete path names for the +OS2PATCH.EXE and for the PTRACE87.PAT file. You do not need to give +a path name for the OS2PATCH.EXE file if you have placed this file +in a directory listed in your PATH environment variable. + +Using the Real-Mode Debugger in the Compatibility Box +----------------------------------------------------- +When running the real-mode CodeView debugger in the DOS 3.x +compatibility box, start the debugger with the /S command-line +option. Otherwise, the mouse pointer will not appear. + +Using the CodeView Debugger with BIND +------------------------------------- +The real-mode CodeView debugger cannot debug bound (dual-mode) +applications. However, the protected-mode CodeView debugger, +CVP, can debug bound applications. + +Expression Evaluator for BASIC Programs +--------------------------------------- +In the BASIC expression evaluator, "+" is not supported for string +concatenation. + +Stack Trace Command +------------------- +In order for the Stack Trace command (or the Calls menu) to work +reliably, you need to execute to at least the beginning of the main +function or procedure, and the current module should have full CodeView +information (a module has full CodeView information if compiled or +assembled with /Zi). + +Error Messages +-------------- +The error message "? cannot display" indicates that the Display +Expression command (?) has been passed a valid symbol that it +cannot display. In previous versions of the debugger, structures +could not be displayed. With current version of the debugger, only +the enums type cannot be displayed. + +The error message "Expression not a memory address" occurs when +the Tracepoint command is given without a symbol that evaluates to +a single memory address. For example, the commands "TP?1" and +"TP?a+b" each produce this error message. The proper way to put a +tracepoint on the word at address 1 is with the command "TPW 1". + +The error message "Function call before 'main'" occurs when you +attempt to evaluate a program-defined function before you have entered +the main function. Execute to at least to the beginning of the main +function before attempting to evaluate program-defined functions. + +The error message "Bad emulator info" occurs when CodeView cannot +read data from the floating-point emulator. + +The error message "Floating point not loaded" has a special meaning +for CVP (in addition to the explanation given in the CodeView and +Utilities manual). Each thread has its own floating-point emulator. +This message is issued when the current thread has not initialized +its own emulator. + +Microsoft Pascal Programs +------------------------- +In this release, Microsoft Pascal programs cannot be debugged with +the CodeView debugger. + + + Exit Codes for Utilities + +The exit codes for LINK and the utilities in the Microsoft CodeView +and Utilities manual should appear as follows: + +LINK +---- + Code Meaning + + 0 No error. + + 2 Program error--something was wrong with the commands + or files input to the linker. + + 4 System error. The linker + + - ran out of space on output files + - was unable to reopen the temporary file + - experienced an internal error + - was interrupted by the user + +LIB, EXEPACK, EXEMOD, MAKE, and SETENV +--------------------------------------- + Code Meaning + + 0 No error. + + 2 Program error--something was wrong with the commands + or files input to the utility. + + 4 System error. The utility ran out of memory, was + interrupted by the user, or experienced an internal + error. + + Microsoft Overlay Linker (LINK) + +Overlay Restrictions +-------------------- +You cannot use long jumps (using the longjmp library function) or indirect +calls (through a function pointer) to pass control to an overlay. When a +function is called through a pointer, the called function must be in the same +overlay or in the root. + +Changed LINK Error Messages +--------------------------- +The explanation for fatal-error message L1008 is changed as follows: + + The /SEGMENTS option specified a limit greater than 3072 on the + number of segments allowed. + +Error message L1009 has been changed to read as follows: + + L1009 : CPARMAXALLOC : illegal value + +Error message L1053 has been changed to read as follows: + + L1053 out of memory for symbol table + + The program had more symbolic information (such as public, external, + segment, group, class, and file names) than the amount that could fit + in available real memory. + + Try freeing memory by linking from the DOS command level instead of + from a MAKE file or from an editor. Otherwise, combine modules or + segments and try to eliminate as many public symbols as possible. + +Warning message L4050 has been changed as follows: + + L4050 too many public symbols for sorting + + The linker uses the stack and all available memory in the + near heap to sort public symbols for the /MAP option. If + the number of public symbols exceeds the space available + for them, this warning is issued, and the symbols are not + sorted in the map file but are listed in arbitrary order. + +New LINK Error Messages +----------------------- +L1003 /QUICKLIB, /EXEPACK incompatible + +You cannot link with both the /QU option and the /E option. + +L1006 : stack size exceeds 65535 bytes + +The value given as a parameter to the /STACKSIZE option exceeds the +maximum allowed. + +L1063 out of memory for CodeView information + +The linker was given too many object files with debug information, +and the linker ran out of space to store it. Reduce the number +of object files that have debug information. + +L1115 /QUICKLIB, overlays incompatible + +You specified overlays and used the /QUICKLIB option. +These cannot be used together. + +L2013 LIDATA record too large + +An LIDATA record contained more than 512 bytes. This is +probably a compiler error. + +L2024 : special symbol already defined + +Your program defined a symbol name that is already used by the linker +for one of its own low-level symbols. (For example, the linker +generates special symbols used in overlay support and other operations.) +Choose another name for the symbol in order to avoid conflict. + +L2025 : segment with > 1 class name not allowed with /INC + +Your program defined a segment more than once, giving the segment +different class names. Different class names for the same segment +are not allowed when you link with the /INCREMENTAL option. Normally, +this error should never appear unless you are programming with MASM. +For example, if you give the two MASM statements + +_BSS segment 'BSS' + +and + +_BSS segment 'DATA' + +then the statements have the effect of declaring two distinct segments. +ILINK does not support this situation, so it is disallowed when the +/INCREMENTAL option is used. + + +L2041 stack plus data exceed 64K + +The total of near data and requested stack size exceeds 64K, +and the program will not run correctly. Reduce the stack size. +The linker only checks for this condition if /DOSSEG +is enabled, which is done automatically in the library +startup module. + +L2043 Quick Library support module missing + +When creating a Quick library, you did not link with the required +QUICKLIB.OBJ module. + +L2044 : symbol multiply defined, use /NOE + +The linker found what it interprets as a public-symbol +redefinition, probably because you have redefined a symbol that +is defined in a library. Relink with the /NOEXTDICTIONARY +(/NOE) option. If error L2025 results for the same symbol, then you +have a genuine symbol-redefinition error. + +L4003 intersegment self-relative fixup at in segment + pos: Record type: 9C target external '' + +The linker found an intersegment self-relative fixup. This error +may be caused by compiling a small-model program with the /NT +option. + +L4034 more than 239 overlay segments; extra put in root + +Your program designated more than the limit of 239 segments to +go in overlays. Starting with the 234th segment, they are assigned to +the root (that is, the permanently resident portion of the program). + + + Microsoft Library Manager (LIB) + +New Option +---------- +There is a new option for LIB: /NOIGNORECASE (abbreviated as /N). +This option tells LIB to not ignore case when comparing symbols. +names. By default, LIB ignores case. Multiple symbols that are +the same except for case can be put in the same library. An +example of this is: "_Open" and "_open". Normally you could not +add both these symbols to the same library. + +Note that if a library is built with /NOI, the library is +internally "marked" to indicate /NOI. All libraries built +with earlier versions of LIB are not marked. + +If you combine multiple libraries, and any one of them is +marked /NOI, then /NOI is assumed for the output library. + +In addition, LIB also supports the option /IGNORECASE (/I), which +is completely analogous to /NOIGNORECASE. /I is the default. The only +reason to use it would be if you have an existing library marked /NOI +that you wanted to combine with other libraries which were not marked, +and have the output library be not marked. If you don't use +/IGNORECASE, the output is marked /NOI (see above). + +Changed LIB Error Messages +-------------------------- +Warning messages U4152, U4155, and U4157-U4159 for LIB are now +nonfatal error messages U2152, U2155, and U2157-U2159, respectively. + +Warning message U4151 has been changed to read as follows: + + U4151 '' : symbol defined in module , redefinition ignored + +New LIB Error Messages +---------------------- +The following new warning messages have been added for LIB: + +U4155 : module not in library + +A module specified to be replaced does not already exist in the +library. LIB adds the module anyway. + +U4157 insufficient memory, extended dictionary not created +U4158 internal error, extended dictionary not created + +For the reason indicated, LIB could not create an extended +dictionary. The library is still valid, but the linker +is not able to take advantage of the extended dictionary +to speed linking. + + + Microsoft Program Maintenance Utility (MAKE) + +New Error Message +----------------- +U1015: : error redirection failed + +This error occurs if the /X option is given and error output cannot +be redirected to the given file (for example, because the file +is read-only). + +Inference Rules +--------------- +You cannot have inference rules in both the TOOLS.INI and the description +file that use both the same inextension and outextension. For example, you +cannot place the following inference rule in the TOOLS.INI file: + + .c.obj: + cl /c /Zi /Od $*.c + +while also placing the following line in the description file: + + .c.obj: + cl /Ot $*.c + +However, you can define the same macro in both the TOOLS.INI and the +description file. In such cases, the definition in the description file +takes precedence. + +Backslash (\) as Continuation Character +--------------------------------------- +Note that MAKE considers a backslash immediately followed by a new-line +character to be a continuation character. When it finds this combination +in a description file, MAKE concatenates the line immediately following +the combination with the line where the combination appears. + +If you define a macro that ends in a backslash, make sure that you put a +space after the terminating backslash. For example, if you want to define +macros for the path C:\SRC\BIN and C:\SRC\LIB, you must use the format +illustrated below: + + BINPATH=C:\SRC\BIN\ + LIBPATH=C:\SRC\LIB\ + +To illustrate the problems that can result if you do not put a space before the +new-line character, assume that the macros above appear as shown below +instead: + + BINPATH=C:\SRC\BIN\ + LIBPATH=C:\SRC\LIB\ + +Because a new-line character appears immediately after the backslash at the end +of the first macro, MAKE assumes that you are defining the single macro shown +below: + + BINPATH=C:\SRC\BIN\LIBPATH=C:\SRC\LIB\ + + + + Microsoft STDERR Redirection Utility (ERROUT) + +The ERROUT utility does not accept batch files. To redirect standard-error +output from a batch file, you must enter a command of the following form: + + ERROUT COMMAND /c + +If no /f option is given, then ERROUT redirects standard-error output to +the standard-output device. + + + Mixed-Language Programming + +Setting Up Calls to High-Level Languages +---------------------------------------- +Section 6.6 of the Microsoft Mixed-Language Programming Guide gives in- +structions for setting up a call to a high-level language from assembly +language. Before you execute a call to a BASIC, Pascal, or FORTRAN routine, +remember to declare an additional parameter if the return value is noninteger. +This additional parameter must contain the offset address of the return value, +for which you must allocate room within the stack segment (normally DGROUP, +the same as the default data segment). + + + The BIND Utility + +Specifying Libraries +-------------------- +You need to include DOSCALLS.LIB on the BIND command line. If +DOSCALLS.LIB is not in the current directory, you must give the +complete path name to DOSCALLS.LIB. + +BIND automatically searches for API.LIB by looking in directories +listed in the LIB environment variable. However, if API.LIB is +specified on the command line, then BIND will not check the LIB +environment variable; instead, you will need to give the complete +path name. + +For example, the following command line successfully uses BIND, if +API.LIB is located in a directory listed in the LIB environment +variable: + +BIND FOO.EXE \LIB\DOSCALLS.LIB + +Using BIND with Packed Files +---------------------------- +The version of BIND released with this package does not work with +files that have been linked with the /EXEPACK linker option. + +Running Bound Files with DOS 2.1 +-------------------------------- +A dual-mode executable file produced with BIND can be run in both +DOS 3.x and DOS 2.x environments. However, if you change the name +of an executable file produced by BIND, then it will not run under +DOS 2.1. + + + The Microsoft Incremental Linker (ILINK) + +ILINK Fatal Error Messages +-------------------------- + +.sym seek error +.sym read error + + The .SYM file is corrupted. Do a full link. If the error + persists, contact Microsoft. + +.sym write error + + The disk is full or the .SYM file already exists with the + READONLY attribute. + +map for segment exceeds 64K + + The symbolic information associated with the given segment + exceeds 64K bytes, which is more than ILINK can handle. + +can't ilink library + + You tried to incrementally link an altered library. + ILINK does not link .LIB files but only .OBJ files. + Use a full link instead. + +.obj close error + + The operating system returned an error when ILINK attempted + to close one of the .OBJ files. Do a full link. If the error + persists, contact Microsoft. + +too many LNAMES in + + An object module has more than 255 LNAME records. + +too many SEGDEFs in + + The given object module has more than 100 SEGDEF records. + +too many GRPDEFs in + + The given object module has more than 10 GRPDEF records. + +symbol multiply defined + + The given symbol is defined more than once. + +#3 + + Please report this error to Microsoft. + +Out of Memory + + ILINK ran out of memory for processing the input. If you + are running ILINK under MAKE, try running it from the shell. + Otherwise, do a full link. + +could not run exec + + ILINK was unable to find the file EXEC.EXE, which should be + placed somewhere in the search path or in the current + directory. + +.exe file too big, change alignment + + The segment sector alignment value in the .EXE file is too + small to express the size of one of the segments. Do a full + link and increase the alignment value with the /ALIGNMENT + option to LINK. + +.ilk seek error + + The .ILK file is corrupted. Do a full link. If the error + persists, contact Microsoft. + +Too many defined segments + + ILINK has a limit of 255 defined segments, which are segments + defined in an object module as opposed to an executable segment. + Reduce the number of segments if you want to use ILINK. + +too many library files + + ILINK has a limit of 32 runtime libraries (.LIB files). Reduce + the number of libraries. + +too many modules + + ILINK has a limit of 1204 modules in a program. Reduce the + number of modules. + +.ilk write error + + The disk is full, or else ILINK cannot write to the .SYM file + because a .SYM file currently exists and has the READONLY attribute. + +file does not exist + + ILINK was unable to open the given file. The file named was + in the file list in the .ILK file. + +seek error on library + + A .LIB file was corrupted. Do a full link and check your .LIB + files. + +library close error + + The operating system returned an error when ILINK attempted + to close one of the .LIB files. Do a full link. If the error + persists, contact Microsoft. + +error closing EXE file + + The operating system returned an error when ILINK attempted + to close the .EXE file. Do a full link. If the error + persists, contact Microsoft. + +Invalid module reference + + The program makes a dynamic link reference to a dynamic link + module which is not represented in the .EXE file. + +could not update time on + + The operating system returned an error when ILINK attempted + to update the time on the given file. Possibly the file had + the READONLY attribute set. + +invalid flag +only one -e command allowed + + The ILINK command syntax is incorrect. + +User Abort + + The user issued CTRL+C or CTRL+BREAK. + +file write protected + + The .EXE, .ILK, or .SYM file needed to be updated and has the + READONLY attribute. Change attribute to READWRITE. + +file missing + + One of the .OBJ files specified on the command line is missing. + +file invalid .OBJ format +file has invalid record + + The given .OBJ file has an invalid format or one that is not + recognized by ILINK. This may have been caused by a compiler + or assembler. + +file was not full linked + + An .OBJ file was specified as input to ILINK, which was not in + the list of files in the original full link. + +LOBYTE seg-relative fixups not supported + + This error message should occur only with MASM files. See the + Microsoft Macro Assembler 5.0 Programmer's Guide. This type of + object module is not supported by ILINK. + + undefined symbols + + The given number of symbols were referred to in fixups but + never publicly defined in the program. + +Incremental Violations +---------------------- +These errors cause a full link to occur if the -e option is used and -i +is not used, else they are fatal errors: + +symbol deleted + + A symbol was deleted from an incrementally-linked module. + + contains new SEGMENT + + A segment was added to the program. + + contains changed segment + + The segment contribution (code or data which the module + contributes to a segment) changed for the given module: it + contributed to a segment it didn't previously contribute to, + or a contribution was removed. + +'s segment grew too big + + The given segment grew beyond the padding for the given module. + + contains new GROUP + + A new group was defined, via the GROUP directive in assembly + language or via the /ND C compiler option. + + redefines group to include + + The members of the given group changed. + +symbol changed + + The given data symbol was moved. + +can't add new communal data symbol + + A new communal data symbol was added as an uninitialized variable + in C or with the COMM feature in MASM. + +communal variable grew too big + + The given communal variable changed size too much. + +invalid symbol type for + + A symbol which was previously code became data, or vice versa. + +too many COMDEFS +too many EXTDEFS + + The limit on the total of COMDEF records (communal data variables) + and EXTDEF records (external references) is 2000. + +invalid CodeView information in .EXE file + + The CodeView information found is invalid. + + contains new Codeview symbolic info + + A module previously compiled without -Zi was compiled with -Zi. + + contains new linnum info + + A module previously compiled without -Zi or -Zd was compiled + with -Zi or -Zd. + + contains new public CV info + + New information on public-symbol addresses was added. + +invalid .exe file + + The .EXE file is invalid. Make sure you are using an up-to-date + linker. If the error persists, contact Microsoft. + +invalid .ilk file +.ilk read error +.ilk seek error + + The .ILK file is invalid. Make sure you are using an up-to-date + linker. If the error persists, contact Microsoft. + +.SYM/.ILK mismatch + + The .SYM and .ILK files are out of sync. Make sure you are using + an up-to-date linker. If the error persists, contact Microsoft. + + has changed + + The given library has changed. + +can't link 64K-length segments + + ILINK cannot handle segments greater than 65,535 bytes long. + +can't link iterated segments + + ILINK cannot handle programs linked with /EXEPACK. + +Entry table expansion not implemented + + The program call tree changed in such a way that ILINK could + not handle it. + +file does not exist + + The .EXE, .SYM, or .ILK files are missing. + + has changed + + The given library module name has changed. + +ILINK Warning messages +---------------------- + +Fixup frame relative to an (as yet) undefined symbol - assuming ok + + See documentation for LINK error messages L4001 and L4002, + in the Microsoft CodeView and Utilities manual. + + contains TYPEDEFs - ignored + contains BLKDEFs - ignored + + The .OBJ file contains records no longer supported by Microsoft + language compilers. + +old .EXE free information lost + + The free list in the .EXE file has been corrupted. The free + list keeps track of "holes" of free space in the EXE file. These + holes are made available when segments are moved to new locations. + +file has no useful contribution + + The given module makes no contribution to any segment. + +Main entry point moved + + The program starting address changed. You may want to consider + doing a full link. + + + Microsoft Editor + +Installing the Editor +--------------------- +The Microsoft Editor does not come with an MESETUP program. Instead, +run the setup program for the assembler. This program offers you choices +about how to set up the editor. + +Keystroke Configurations +------------------------ +Some of the keystroke configurations listed in Table A.2 of the +Microsoft Editor User's Guide may need to be changed. + +In the Quick/WordStar configuration, the Sinsert function is assigned +to ALT+INS, not CTRL+INS. + +In the BRIEF configuration, the Plines function is assigned to CTRL+Z, +and the Refresh function is assigned to CTRL+]. + +In the EPSILON configuration, the Ppage function is assigned to PGDN, +and the Sdelete function is assigned to DEL and CTRL+D. + +The Compile Function +-------------------- +The commands + + Arg streamarg Compile + Arg textarg Compile + +each use the command specified by the extmake:text switch. The +editor does not check the extension of the file name given as an +argument, but instead uses the "text" extension. The streamarg +or textarg replaces a %s in the command. These commands are typically +used to invoke MAKE. + +The Setfile Function +-------------------- +The commands that use Setfile, along with a streamarg or textarg, +accept a variety of input: either the name of a file, a file name +with a wild-card character (* or ?), the name of a directory, or the +name of a disk drive. File names can also include environment variables, +such as $INIT. If the streamarg or textarg is a directory name, then +the editor changes the current directory. If the argument is a drive +name, then the editor changes the current drive. Environment variables +are translated into directories to be searched for a file. For example, +the following macro directs the editor to search the $INIT environment +variable in order to find the tools.ini file: + + tools.ini := Arg "$INIT:tools.ini" Setfile + tools.ini :ctrl+j + +Entering Strings in Macros +-------------------------- +When you enter a text argument directly, no characters have special +meaning (except when the argument is interpreted as a regular +expression). However, when you enter text as part of a macro, then +strings inside of quotes are interpreted according to the C string +format. This format uses a backslash followed by double quotes (\") +to represent double quotes and it uses two backslashes (\\) to represent +a single backslash. Therefore, to find the next occurrence of the string + + She wrote, "Here is a backslash: \ " + +you could use the following macro definition: + + findit := Arg "She wrote, \"Here is a backslash: \\ \"" Psearch + +Note that to indicate a backslash for a regular expression that is +also part of a macro definition, you must use four consecutive +backslashes. + + +Using Text Switches +------------------- +The text switches extmake and readonly each take a special +kind of syntax that allows you to specify drive, file name, +base name, or file extension. The syntax consists of the +characters: + +%|F + +where consists of any of the following: "p" for path, +"d" for drive, "f" for file base name, or "e" for file extension. +For example, if you are editing the file c:\dir1\sample.c, and you +make the following switch assignment: + +extmake:c cl /Fod:%|pfF %|dfeF + +then each time you give the command , the editor +performs the following system-level command: + +cl /Fod:\dir1\sample c:sample.c + +The expression "%s" is equivalent to "%|feF" except that the former +only works once, whereas the latter can appear any number of times +in the extmake switch assignment. The expression "%|F" is equivalent +to "%|dpfeF". + +The Filetab Switch +------------------ +The filetab switch is a numeric switch that determines how the +editor translates tabs when loading a file into memory. The value +of the switch gives the number of spaces associated with each tab +column. For example, the setting "filetab:4" assumes a tab column +every 4 positions on each line. Every time the editor finds a tab +character in a file, it loads the buffer with the number of spaces +necessary to get to the next tab column. Depending on the value of +the entab switch, the editor also uses the filetab switch to determine +how to convert spaces into tabs when writing to a file. The default +value of filetab is 8. + + +Functions Callable by C Extensions +---------------------------------- +The following list summarizes functions from the standard compact- +memory-model library, which should work when called by a C-extension +module. (The technique of programming C extensions is presented in +Chapter 8 of the Microsoft Editor User's Guide.) The memory model +of the extension is assumed to be /Asfu (small code pointers, far +data pointers, and stack segment unequal to data segment). This list +uses the function categories from Chapter 4 of the Microsoft C +Optimizing Compiler Run-Time Library Reference (Version 4.0 +or later.) + +Buffer Manipulation: All functions can be called. + +Character Classification and Conversion: All functions can be called. + +Data Conversion: All functions can be called except for + + strtod() + +Directory Control: All functions can be called except for + + getcwd() + +File Handling: All functions can be called. + +Low-Level I/O Routines: All functions can be called, but write() +will not work in binary mode. + +Console and Port I/O: All functions can be called except for + + cgets() + cprintf() + cscanf() + +Searching and Sorting: All functions can be called except for + + qsort() + +String Manipulation: All functions can be called except for + + strdup() + +BIOS Interface: All functions can be called. + +MS-DOS Interface: All functions can be called except for + + int86() + int86x() + +Time: All functions can be called except for + + ctime() + gmtime() + localtime() + utime() + +Miscellaneous: All functions can be called except for + + assert() + getenv() + perror() + putenv() + _searchenv() + + +Linking Extensions in Protected Mode +-------------------------------------- +To link C extension modules in protected mode, link with the +object file EXTHDRP.OBJ, instead of the real-mode header +EXTHDR.OBJ. diff --git a/nuts/Debug/nuts.pdb b/nuts/Debug/nuts.pdb new file mode 100644 index 0000000..18c93b2 --- /dev/null +++ b/nuts/Debug/nuts.pdb Binary files differ diff --git a/nuts/Debug/vc40.idb b/nuts/Debug/vc40.idb new file mode 100644 index 0000000..7a4faa2 --- /dev/null +++ b/nuts/Debug/vc40.idb Binary files differ diff --git a/nuts/Debug/vc40.pdb b/nuts/Debug/vc40.pdb new file mode 100644 index 0000000..a3d19eb --- /dev/null +++ b/nuts/Debug/vc40.pdb Binary files differ diff --git a/nuts/nuts.c b/nuts/nuts.c new file mode 100644 index 0000000..21c9bce --- /dev/null +++ b/nuts/nuts.c @@ -0,0 +1,76 @@ +#include + +LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); + +char szWinName[] = "MyWin"; + +int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, + LPSTR lpszArgs, int nWinMode) + +{ + HWND hwnd; + MSG msg; + WNDCLASSEX wcl; + + wcl.hInstance = hThisInst; + wcl.lpszClassName = szWinName; + wcl.lpfnWndProc = WindowFunc; + wcl.style = 0; + + wcl.cbSize = sizeof(WNDCLASSEX); + + wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO); + + wcl.hCursor = LoadCursor(NULL, IDC_ARROW); + wcl.lpszMenuName = NULL; + + wcl.cbClsExtra = 0; + wcl.cbWndExtra = 0; + + wcl.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); + + if(!RegisterClassEx(&wcl)) return 0; + + hwnd = CreateWindow( + szWinName, + "Tundra's Windows 95 Skeleton", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + HWND_DESKTOP, + NULL, + hThisInst, + NULL + ); + + ShowWindow(hwnd, nWinMode); + UpdateWindow(hwnd); + + while(GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return msg.wParam; + +} + +LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, + LPARAM lParam) + +{ + switch (message) + { + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hwnd, message, wParam, lParam); + } + return 0; +} + diff --git a/nuts/nuts.mak b/nuts/nuts.mak new file mode 100644 index 0000000..25d88a3 --- /dev/null +++ b/nuts/nuts.mak @@ -0,0 +1,195 @@ +# Microsoft Developer Studio Generated NMAKE File, Format Version 4.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +!IF "$(CFG)" == "" +CFG=nuts - Win32 Debug +!MESSAGE No configuration specified. Defaulting to nuts - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "nuts - Win32 Release" && "$(CFG)" != "nuts - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE on this makefile +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "nuts.mak" CFG="nuts - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "nuts - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "nuts - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF +################################################################################ +# Begin Project +# PROP Target_Last_Scanned "nuts - Win32 Debug" +CPP=cl.exe +MTL=mktyplib.exe +RSC=rc.exe + +!IF "$(CFG)" == "nuts - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +OUTDIR=.\Release +INTDIR=.\Release + +ALL : "$(OUTDIR)\nuts.exe" + +CLEAN : + -@erase ".\Release\nuts.exe" + -@erase ".\Release\nuts.obj" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/nuts.pch" /YX /Fo"$(INTDIR)/" /c +CPP_OBJS=.\Release/ +CPP_SBRS= +# ADD BASE MTL /nologo /D "NDEBUG" /win32 +# ADD MTL /nologo /D "NDEBUG" /win32 +MTL_PROJ=/nologo /D "NDEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/nuts.bsc" +BSC32_SBRS= +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /subsystem:windows /incremental:no\ + /pdb:"$(OUTDIR)/nuts.pdb" /machine:I386 /out:"$(OUTDIR)/nuts.exe" +LINK32_OBJS= \ + "$(INTDIR)/nuts.obj" + +"$(OUTDIR)\nuts.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ELSEIF "$(CFG)" == "nuts - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +OUTDIR=.\Debug +INTDIR=.\Debug + +ALL : "$(OUTDIR)\nuts.exe" + +CLEAN : + -@erase ".\Debug\nuts.exe" + -@erase ".\Debug\nuts.obj" + -@erase ".\Debug\nuts.ilk" + -@erase ".\Debug\nuts.pdb" + -@erase ".\Debug\vc40.pdb" + -@erase ".\Debug\vc40.idb" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS"\ + /Fp"$(INTDIR)/nuts.pch" /YX /Fo"$(INTDIR)/" /Fd"$(INTDIR)/" /c +CPP_OBJS=.\Debug/ +CPP_SBRS= +# ADD BASE MTL /nologo /D "_DEBUG" /win32 +# ADD MTL /nologo /D "_DEBUG" /win32 +MTL_PROJ=/nologo /D "_DEBUG" /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +BSC32_FLAGS=/nologo /o"$(OUTDIR)/nuts.bsc" +BSC32_SBRS= +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 +LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\ + advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib\ + odbccp32.lib /nologo /subsystem:windows /incremental:yes\ + /pdb:"$(OUTDIR)/nuts.pdb" /debug /machine:I386 /out:"$(OUTDIR)/nuts.exe" +LINK32_OBJS= \ + "$(INTDIR)/nuts.obj" + +"$(OUTDIR)\nuts.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS) + $(LINK32) @<< + $(LINK32_FLAGS) $(LINK32_OBJS) +<< + +!ENDIF + +.c{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_OBJS)}.obj: + $(CPP) $(CPP_PROJ) $< + +.c{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cpp{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +.cxx{$(CPP_SBRS)}.sbr: + $(CPP) $(CPP_PROJ) $< + +################################################################################ +# Begin Target + +# Name "nuts - Win32 Release" +# Name "nuts - Win32 Debug" + +!IF "$(CFG)" == "nuts - Win32 Release" + +!ELSEIF "$(CFG)" == "nuts - Win32 Debug" + +!ENDIF + +################################################################################ +# Begin Source File + +SOURCE=.\nuts.c + +"$(INTDIR)\nuts.obj" : $(SOURCE) "$(INTDIR)" + + +# End Source File +# End Target +# End Project +################################################################################ diff --git a/nuts/nuts.mdp b/nuts/nuts.mdp new file mode 100644 index 0000000..9a5f35c --- /dev/null +++ b/nuts/nuts.mdp Binary files differ diff --git a/pay/PAY.C b/pay/PAY.C new file mode 100644 index 0000000..bbecd9e --- /dev/null +++ b/pay/PAY.C @@ -0,0 +1,316 @@ +/* PAY.C - This program demonstrates some of the capabilities of the + SCREEN DOOR Screen Management System. + Copyright (c) 1986, By T.A. Daneliuk + Last Modified: 06/30/86 +*/ + +#include +#include +#include +#include + +/* Macro Color Definitions */ + +#define ICOLOR color(BLACK,WHITE) /* Input Color */ +#define PCOLOR color(YELLOW,BLUE) /* Prompt Color */ +#define RCOLOR color(GREEN,BLACK) /* Response Color */ +#define BCOLOR color(LCYAN,BLACK) /* Border Color */ +#define RBCOLOR color(BLACK,CYAN) /* Reverse Border Color */ +#define HCOLOR color(YELLOW,BLUE) /* Help Colors */ +#define HCOLOR2 color(YELLOW,BLACK) +#define HCOLOR3 color(LGREEN,BLACK) +#define HCOLOR4 color(HWHITE,BLACK) +#define HCOLOR5 color(LMAGENTA,BLACK) +#define HCOLOR6 color(LCYAN,BLACK) + +#define SAMEPG FALSE /* If TRUE, Both Help And Input On Same Video Page */ + +#if !SAMEPG +#define HELPLOC 11 +#define HELP1 help_screen1 +#define VPAGE 3 +#define HCLEAR TRUE +#define HMCLEAR FALSE +#endif + +#if SAMEPG +#define HELPLOC 20 +#define HELP1 NULL +#define VPAGE 0 +#define HCLEAR FALSE +#define HMCLEAR TRUE +#endif + +extern char *errmsg_rval,vpg_help; +extern int help_cls,help_msg_cls; +extern int recalc(); /* These Functions Will Show Up Later In The File */ +extern void hbord1(),hbord2(); + + +main() + +{ +vpg_help=VPAGE; +help_cls=HCLEAR; +help_msg_cls=HMCLEAR; + +/* Prompt, Response, And Help Strings + + These Must Precede The Control Tables Below Which Reference The + Arrays Because Some One-Pass Compilers (Such As DeSmet) Cannot + Resolve A Reference To A Variable Which Is Declared Later In The + File. + + Note That The Response Fields Are Dimensioned To A Size Equal To + rlen+1 To Make Room For The '\0' String Terminator Byte. Notice + Also That The Response Strings Are Initialized To Provide + Default Responses For The Response Fields On Screen. +*/ + +static char prompt1[]={"Principal Amount:"}; +static char prompt2[]={"Annual Interest Rate (%):"}; +static char prompt3[]={"Number Of Months To Payoff:"}; +static char prompt4[]={"Monthly Payment:"}; +static char prompt5[]={"[ SCREEN DOOR Demonstration ]"}; +static char prompt6[]={"[ Copyright (c) 1986, T&R Communications Associates ]"}; +static char prompt7[]={"[ F3 To QUIT, F1 For HELP ]"}; + + +static char resp1[11]={"10000"}; +static char resp2[6]={"10"}; +static char resp3[5]={"24"}; +static char resp4[14]={""}; + +static char h1[]={"This is a demonstration of the SCREEN DOOR Screen Management System."}; +static char h2[]={"SCREEN DOOR is a 'C' Language programming tool designed to speedup"}; +static char h3[]={"the creation and maintenance of data entry screens via simple tables."}; +static char h4[]={"SCREEN DOOR supports unlimited keyin-time full field data validations"}; +static char h5[]={"as well as a host of built in character-by-character validations."}; +static char h6[]={"The latter include Alpha-Only, Numeric-Only, Alphanumeric, Forced Case,"}; +static char h7[]={"Floating Point Format, Hexadecimal Format, Binary Format, and many others."}; +static char h8[]={"The programmer can manage any number of Prompt and Response fields."}; +static char h9[]={"Any Prompt field may be displayed or not, and any Response field may"}; +static char h10[]={"be protected from User modification. The programmer can also define"}; +static char h11[]={"fields which require User input at runtime (i.e., Disallow empty fields)."}; +static char h12[]={"Of course, context sensitive Help is available for any Response field"}; +static char h13[]={"the User is editing. In this example, a different Help screen is"}; +static char h14[]={"displayed for each Response field. SCREEN DOOR is also capable of"}; +static char h15[]={"displaying the same Help screen for each Response field being edited."}; +static char h16[]={"All of SCREEN DOOR's parameters can be dynamically varied, allowing"}; +static char h17[]={"the programmer to control screen and input behavior as the program runs."}; +static char h18[]={""}; +static char h19[]={"For more information on SCREEN DOOR contact:"}; +static char h21[]={"T&R Communications Associates"}; +static char h22[]={"4927 North Rockwell Street"}; +static char h23[]={"Chicago, IL 60625"}; +static char h24[]={"Enter Yearly Interest Rate In This Field."}; +static char h25[]={"Enter The Length Of The Loan (In Months) In This Field."}; + + + + +/* Screen Control Tables - One For Help Screen, One For Input Screen + As Before, The Help Table Must Precede Its Reference In The Actual + Screen Table To Accommodate One-Pass Compilers. +*/ + +static struct VSTRUCT help_screen1[]={ + + 0,HCOLOR2,1,5,TRUE,h1,HCOLOR2,2,5,FALSE,h2,0,0,0,0,hbord1,0,0,0,NULL,FALSE, + 0,HCOLOR2,3,5,TRUE,h3,HCOLOR3,4,5,FALSE,h4,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR3,5,5,TRUE,h5,HCOLOR3,6,5,FALSE,h6,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR3,7,5,TRUE,h7,HCOLOR4,8,5,FALSE,h8,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR4,9,5,TRUE,h9,HCOLOR4,10,5,FALSE,h10,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR4,11,5,TRUE,h11,HCOLOR5,12,5,FALSE,h12,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR5,13,5,TRUE,h13,HCOLOR5,14,5,FALSE,h14,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR5,15,5,TRUE,h15,HCOLOR6,16,5,FALSE,h16,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR6,17,5,TRUE,h17,HCOLOR,18,5,FALSE,h18,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR|BLINK,19,5,TRUE,h19,HCOLOR,21,23,FALSE,h21,0,0,0,0,NULL,0,0,0,NULL,FALSE, + 0,HCOLOR,22,26,TRUE,h22,HCOLOR,23,30,FALSE,h23,0,0,0,0,NULL,0,0,0,NULL,TRUE + + }; + +static struct VSTRUCT help_screen2[]={ + + 0,HCOLOR6,HELPLOC+1,10,TRUE,h24,0,0,0,FALSE,NULL,0,0,FALSE,0,hbord2,FALSE,TRUE,TRUE,NULL,TRUE + + }; + +static struct VSTRUCT help_screen3[]={ + + 0,HCOLOR5,HELPLOC+1,10,TRUE,h25,0,0,0,FALSE,NULL,0,0,FALSE,0,hbord2,FALSE,TRUE,TRUE,NULL,TRUE + + }; + + +static struct VSTRUCT input_screen[]={ + + ICOLOR,PCOLOR,10,25,TRUE,prompt1,RCOLOR,10,53,TRUE,resp1,10,'.',FALSE,15,recalc,FALSE,TRUE,FALSE,HELP1,FALSE, + ICOLOR,PCOLOR,11,25,TRUE,prompt2,RCOLOR,11,53,TRUE,resp2,5,'.',FALSE,15,recalc,FALSE,TRUE,FALSE,help_screen2,FALSE, + ICOLOR,PCOLOR,12,25,TRUE,prompt3,RCOLOR,12,53,TRUE,resp3,4,'.',FALSE,15,recalc,FALSE,TRUE,FALSE,help_screen3,FALSE, + ICOLOR,RBCOLOR,6,12,TRUE,prompt5,RCOLOR,15,55,FALSE,NULL,7,'.',FALSE,11,NULL,FALSE,TRUE,TRUE,NULL,FALSE, + ICOLOR,RBCOLOR,19,16,TRUE,prompt6,RCOLOR,15,55,FALSE,NULL,7,'.',FALSE,11,NULL,FALSE,TRUE,TRUE,NULL,FALSE, + ICOLOR,RBCOLOR,8,29,TRUE,prompt7,RCOLOR,15,55,FALSE,NULL,7,'.',FALSE,11,NULL,FALSE,TRUE,TRUE,NULL,FALSE, + ICOLOR,PCOLOR,15,25,TRUE,prompt4,RCOLOR,15,49,FALSE,resp4,13,'.',FALSE,11,NULL,FALSE,TRUE,TRUE,NULL,TRUE + + }; + +/****************************** END-OF-DATA-TABLES **************************/ + + +/* Actual Control Code Which Invokes Screen */ + +int ctr=0; +struct VSTRUCT *vptr; /* Declare A Pointer To A Screen Control Table */ + +vptr=help_screen1; /* Center All Lines On Help Screen For Grins */ + +while (ctr<11) /* This Also Demonstrates Runtime Table Modification */ + { + ((vptr+ctr)->phoriz)=center((vptr+ctr)->parray); + ((vptr+ctr)->rhoriz)=center((vptr+ctr)->rarray); + ctr++; + } + +vptr=help_screen2; +(vptr->phoriz)=center(vptr->parray); +vptr=help_screen3; +(vptr->phoriz)=center(vptr->parray); + + +scr_setup(); /* Initialize PCIO Screen Constants */ +scr_clr(); /* Clear Screen */ +border(8,20,45,10,BCOLOR); /* Draw Borders */ +border(6,10,65,14,BCOLOR); +vptr=input_screen; /* Point To The Input Screen */ +vdsply(vptr); /* Display It */ +recalc(vptr,0); /* So We Have An Answer 1st Time Through */ +vkeyin(vptr,0,FALSE); /* Accept User Input */ +scr_clr(); /* Clear Screen And Back To Dos */ + +} + +/****************************************************************************/ + +static void hbord1(vptr,fld) /* Draw A Border For The Help Screen */ + +struct VSTRUCT *vptr; /* These Are Always Passed By The Help Feature */ +int fld; /* But We Don't Use Them In This Case */ + +{ +border(0,0,79,25,HCOLOR); +} + + +/****************************************************************************/ + +static void hbord2(vptr,fld) /* Draw A Border For The Help Screen */ + +struct VSTRUCT *vptr; /* These Are Always Passed By The Help Feature */ +int fld; /* But We Don't Use Them In This Case */ + +{ +border(HELPLOC,0,79,3,HCOLOR3); +} + + +/****************************************************************************/ + +static void border(startv,starth,width,height,vattrib) + +char vattrib; +int startv,starth,width,height; +{ +int x; + + v_rowcol(startv,starth); + scr_aputs(mkstr(BORDERNW,1),vattrib); + scr_aputs(mkstr(BORDERH,width-2),vattrib); + scr_aputs(mkstr(BORDERNE,1),vattrib); + v_rowcol(startv+height-1,starth); + scr_aputs(mkstr(BORDERSW,1),vattrib); + scr_aputs(mkstr(BORDERH,width-2),vattrib); + scr_aputs(mkstr(BORDERSE,1),vattrib); + + for (x=startv+1;x<=(startv+height-2);x++) + { + v_rowcol(x,starth); + scr_aputs(mkstr(BORDERV,1),vattrib); + v_rowcol(x,starth+width-1); + scr_aputs(mkstr(BORDERV,1),vattrib); + } + +} + +/****************************************************************************/ + +/* This Is Our "Validation" Routine That's Really Being Used To + Recalculate The Monthly Payment */ + +static int recalc(vptr,fld) + +struct VSTRUCT *vptr; +int fld; + +{ + +int x,z,answlen,error,inrange; +inrange=error=FALSE; +answlen=((vptr+6)->rlen); + +double pay,princ,interest,period,y; +char *answer; + +static char msg[]={"Calculation Cannot Be Done Because Of Invalid Input Data!"}; +errmsg_rval=msg; /* This points SCREEN DOOR's global to our own error message */ + +answer=(vptr+6)->rarray; /* This is where we'll put our answer */ + +princ=atof(vptr->rarray); /* Convert input strings to floating point */ +interest=(atof((vptr+1)->rarray))/1200.0; +period=atof((vptr+2)->rarray); + +for(x=0;x < answlen;x++) /* Initialize answer display to zeros */ + *(answer+x)='0'; +*(answer+(answlen-3))='.'; /* Stick In The Decimal Point */ + +if (princ==0 || interest==0 || period==0) /* Make sure we have valid input */ + error=TRUE; + +if (!error) + pay=princ*(interest/(1.0-(pow((1.0/(1.0+interest)),period)))); /* Do the calculation */ + +if (pay >= exp10((double)(answlen-4))) /* Make sure answer can fit in the room alloted to it */ + error=TRUE; + +if (errno==EDOM || errno==ERANGE) /* Make sure the math routines didn't choke */ + error=TRUE; + +if (!error) /* Convert answer back to a string */ + { + for (x=answlen-4;x>-3;x--) /* Do it by powers of 10 */ + { + y=exp10((double)x); + z=(x<0 ? (answlen-x-3) : (answlen-x-4)); /* Remember the decimal pt.! */ + if ((pay < y) && !inrange) + *(((vptr+6)->rarray)+z)=' '; /* Don't want leading zeros */ + else + { + inrange=TRUE; + while (pay >= y) + { + pay=pay-y; + (*(((vptr+6)->rarray)+z))++; + } + } + } + } + + +vdsply(vptr); /* Make sure answer gets displayed */ +return(error); + +} + +/****************************************************************************/ + diff --git a/pdb/BLDPDBIX.C b/pdb/BLDPDBIX.C new file mode 100644 index 0000000..adcdd39 --- /dev/null +++ b/pdb/BLDPDBIX.C @@ -0,0 +1,201 @@ +/* BLDPDBIX.C - Build PDB Index File From Raw Data File + Last Modified: 07-25-90 + By T.A. Daneliuk +*/ + +#include +#include +#include + +#define DEBUG 0 /* 0= No Debug */ + +#define DUP 1 /* Allow Duplicate Keys */ +#define CR 0x0d /* Carriage Return */ +#define LF 0x0a /* LineFeed */ +#define EOR LF /* End-Of-Record */ + +int KEY1 = 0; /* Offset Of First Key In Record */ +int KEY2 = 46; /* Offset Of 2nd Key In Record */ +char data_file[255] = "P:\\PDBASE"; +char idx_file[255] = "P:\\PDBASE.IDX"; +char work[100]; /* Working Buffer */ +unsigned long offset; /* Record Position In File */ + +static void mk_idx(), bld_idx(), add_keys(); +static int get_rec(); + +/*============================================================================*/ + +main(argc,argv) +int argc; +char **argv; + +{ + int z; + + printf("PDB - Version 1.2, Copyright (c) 1988, 1990 T.A. Daneliuk - TundraWare!\n"); + printf("Released To The Public Domain - No Warranties Expressed Or Implied!\n\n"); + + z = 0; + while ((z++ < argc) && (argv[z][0] == '-')) + { + switch (argv[z][1]) + { + case 'i': + strcpy(idx_file, argv[z]+2); + break; + case 'd': + strcpy(data_file, argv[z]+2); + break; + default: + printf("Invalid Command Line Switch, Ignored!\n"); + } + } + + mk_idx(); + bld_idx(); +} + +/*============================================================================*/ + +static void mk_idx() /* Create The Index File */ +{ + IX_DESC node; + + printf("\nCreating Index File %s For Data File %s ...",idx_file, data_file); + make_index(idx_file, &node, DUP); + printf("\nIndex File %s Created.\n",idx_file); + close_index(&node); + } + +/*============================================================================*/ + +static void bld_idx() /* Build Index File */ + +{ + FILE *fp; + IX_DESC node; + ENTRY entry; + + fp = fopen(data_file, "rb"); /* Open Data File */ + if (fp == NULL) + { + printf("\n Cannot Open %s, Aborting ...\n", data_file); + return; + } + offset = 0; + + open_index(idx_file, &node, DUP); + + printf("\nBuilding Index Records ...\n"); + while (get_rec(fp) == 0) /* Get Record 'Till None Left */ + { +#if DEBUG + printf("%s\n", work); +#endif + if (strlen(work) <= KEY2) /* Improper Record Length */ + { + printf("Bad Record At Position %u:\n", offset); + printf("%s\n", work); + printf("Record NOT Added To Index List!\n"); + } + else + { + add_keys(&entry, &node); /* Add Keys */ + offset += strlen(work); /* Update Record Pointer */ + } + } + if (strlen(work) <= KEY2) /* Improper Record Length */ + { + printf("Bad Record At Position %lu:\n", offset); + printf("%s\n", work); + printf("Record NOT Added To Index List!\n"); + } + else + { + add_keys(&entry, &node); /* Add Keys */ + offset += strlen(work); /* Update Record Pointer */ + } + + printf("\nIndex Build Complete.\n"); + + close_index(&node); + fclose(fp); +} + +/*============================================================================*/ + +static int get_rec(fp) /* Read A Record */ +FILE *fp; + +{ + int c, x; + x=0; /* Index Into Work Buffer */ + + c = fgetc(fp); + while ((c != EOF) && (c != EOR)) /* Get A Record */ + { + work[x++] = c; + c = fgetc(fp); + } + if (c == EOR) + { + work[x++] = c; + work[x] = '\0'; /* Terminate Record String */ + return (0); /* Return With Good Status */ + } + else /* At End-Of-File */ + { + work[x] = '\0'; + return (1); + } +} + +/*============================================================================*/ + +static void add_keys(entry, node) /* Add Keys */ +ENTRY *entry; +IX_DESC *node; + +{ + int x, y, z, flag; + + x = KEY1; + y = 0; + entry->recptr = offset; + while ((z = work[x++]) != ' ') + entry->key[y++] = toupper(z); + entry->key[y] = '\0'; +#if DEBUG + printf("%s\n", entry->key); +#endif + add_key(entry, node); + + if (strcmp(work+strlen(work)-6, ".zip\r\n") != 0) + flag = 0; + else + { + flag = 1; + x = strlen(work)-3; + while ((work[x] != '/') && (x > KEY2)) + x--; + } + if (work[x] == '/') + x++; + + y = 0; + if (flag) /* A .ZIP File Member */ + { + entry->recptr = offset; + while ((z = work[x++]) != CR) + entry->key[y++] = toupper(z); + entry->key[y] = '\0'; +#if DEBUG + printf("%s\n", entry->key); +#endif + add_key(entry, node); + } + +} + +/*============================================================================*/ diff --git a/pdb/DPDB b/pdb/DPDB new file mode 100644 index 0000000..f715956 --- /dev/null +++ b/pdb/DPDB @@ -0,0 +1,12 @@ +bldpdbix.obj: bldpdbix.c + cl /c /Od /Zi bldpdbix.c + +bldpdbix.exe: bldpdbix.obj + link bldpdbix,,,sbplus /CO; + +pdb.obj: pdb.c + cl /c /Od /Zi pdb.c + +pdb.exe: pdb.obj + link pdb,,,sbplus /CO; + diff --git a/pdb/PDB b/pdb/PDB new file mode 100644 index 0000000..90c8efe --- /dev/null +++ b/pdb/PDB @@ -0,0 +1,12 @@ +bldpdbix.obj: bldpdbix.c + cl /c /Gs /Ox bldpdbix.c + +bldpdbix.exe: bldpdbix.obj + link bldpdbix,,,sbplus; + +pdb.obj: pdb.c + cl /c /Gs /Ox pdb.c + +pdb.exe: pdb.obj + link pdb,,,sbplus; + diff --git a/pdb/PDB.C b/pdb/PDB.C new file mode 100644 index 0000000..ef5997b --- /dev/null +++ b/pdb/PDB.C @@ -0,0 +1,113 @@ +/* PDB.C - Search PBASE Using Index + Last Modified: 07-25-90 + By T.A. Daneliuk +*/ + +#include +#include +#include +#include + +#define DEBUG 0 /* 0= No Debug */ + +#define DUP 1 /* Allow Duplicate Keys */ +#define LF 0x0a /* LineFeed */ +#define EOR LF /* End-Of-Record */ + +char data_file[255] = "P:\\PDBASE"; +char idx_file[255] = "P:\\PDBASE.IDX"; +char work[100]; /* Working Buffers */ +char scratch[100]; +long offset; /* Record Position In File */ + +static void display(); + +ENTRY entry; +IX_DESC node; +FILE *fp; + +/*============================================================================*/ + + +main(argc,argv) +int argc; +char **argv; + +{ + + int x, y, z; + + printf("PDB - Version 1.3, Copyright (c) 1988, 1990 T.A. Daneliuk - TundraWare!\n"); + printf("Released To The Public Domain - No Warranties Expressed Or Implied!\n\n"); + if (argc < 2) + printf("Bad Command Line!, Aborting ...\n"); + else + { + z = 0; + while ((z++ < argc) && (argv[z][0] == '-')) + { + switch (argv[z][1]) + { + case 'i': + strcpy(idx_file, argv[z]+2); + break; + case 'd': + strcpy(data_file, argv[z]+2); + break; + default: + printf("Invalid Command Line Switch, Ignored!\n"); + } + } + + fp=fopen(data_file, "rb"); + if (fp == NULL) + { + printf("Can't Open %s, Aborting ... \n", data_file); + exit(); + } + open_index(idx_file, &node, DUP); + + for (x=z; x +#include +#include + + +/* Global Defaults, Counters, Buffers, And State Flags */ + +#define HDRDEFALT 3 /* Default Header Length */ +static struct DataArea mydta; /* Working DTA For Wildcards */ +static int pwidth=132; /* Page Width */ +static int plen=56; /* Page Length */ +static int tabsz=4; /* Tab Expansion Size */ +static char line[6]; /* Current Source Line Number */ +static row=1; /* Current Physical Line Number */ +static int col=1; /* Horizontal Position Being Printed */ +static char page[4]; /* Page Counter */ +static char nest[3]; /* Curly Brace Nesting Level */ +static int linenums=TRUE; /* If TRUE, prints line numbers */ +static int header=TRUE; /* If TRUE, prints header */ +static int hdrlen=HDRDEFALT+1; /* Number Of Lines In Header */ +static int squote; /* Single Quote Flag */ +static int dquote; /* Double Quote Flag */ +static int comment; /* Comment Flag */ +static int prtstdin=FALSE; /* Means stdin In Input File List */ +static int messages=TRUE; /* Means Display Error Messages */ +static int start=1; /* Beginning Position Of Text */ + +/* Global Constants And Print Formatting Offsets */ + +#define CR 0x0d /* Carriage Return */ +#define LF 0x0a /* Line Feed */ +#define EOL 0x0d0a /* End-Of-Line */ +#define TOF 0x0c /* Top-Of-Form Character */ +#define OUTSZ (pwidth+3) /* Size Of Output Buffer */ +#define HDRSZ ((pwidth+2)*HDRDEFALT)+1 /* Size Of Header Buffer */ +#define PAGEPOS 8 /* Page Number Posn From Rt. Margin */ +#define DATEPOS 21 /* Date Position From Rt. Margin */ +#define TIMEPOS 8 /* Time Position From Rt. Margin */ +#define NESTPOS 0 /* Offset Of Nesting String */ +#define LINOPOS 3 /* Offset Of Line Number String */ +#define TEXTPOS 10 /* Offset Of Beginning Of Text */ + +/*********************** Main Body Of PP.C Logic *****************************/ + + +main(argc,argv) + +int argc; +char *argv[]; + +{ + +int c; /* Read Character */ +int f; /* argv Offset For Filenames */ +int g,h; /* Temporary */ +int fp; /* Working File Pointer */ +int first; /* Working Flag */ +char *fn; /* Filename Pointer */ +char name[129]; /* Name w/ Path For fopen() */ + +banner(); /* Display Logon Banner */ +f=parse_args(argc,argv); /* Parse Command Line Args. */ + +if ((f == argc) || (prtstdin)) /* No Filename Passed */ + { + if (messages) + fputs("Now Printing: ",stderr); /* So Use stdin Data */ + pp(stdin,""); + if (messages) + { + fputs(line,stderr); + fputs(" Line(s) Printed !\n",stderr); + } + } + +if (f != argc) + while(f < argc) /* Process Passed Filenames */ + { + for (h=0;*(argv[f]+h) != '\0';h++) + *(argv[f]+h)=toupper(*(argv[f]+h)); /* Make all UC */ + strcpy(name,argv[f]); /* Copy Full Name For The fopen() */ + h=strlen(name)-1; /* Strip Off Everything But Path */ + while((name[h]) != ':' && (name[h] != '\\') && (h > -1)) + h--; + first=TRUE; + while (wildcard(argv[f],&mydta,first) != 0) + { + first=FALSE; /* Made it thru 1st time */ + fn=mydta.dta_name; + name[h+1]='\0'; /* Append Filename To Path */ + strcat(name,fn); + fp=fopen(name,"r"); + if (fp != NULL) /* Successful Open */ + { + if (messages) + { + fputs("Now Printing: ",stderr); + fputs(name,stderr); + g=43-strlen(name); /* Pad So Line Display Aligns */ + while (--g) + fputc(' ',stderr); + } + pp(fp,fn); + fclose(fp); + if (messages) + { + fputs(line,stderr); + fputs(" Line(s) Printed !\n",stderr); + } + } + else if (messages) /* Open Failed */ + { + fputs("Cannot Open: ",stderr); + fputs(argv[f],stderr); + fputs("\n",stderr); + } + } + if (first && messages) /* Failed on 1st try, bad wc spec */ + { + fputs("Cannot Open: ",stderr); + fputs(argv[f],stderr); + fputs("\n",stderr); + } + f++; + } + +} + +/*************************** Display Logon Banner ****************************/ + +void banner() + +{ +scr_setup(); +scr_clr(); +scr_rowcol(0,0); +fputs("PP - Pretty Printer Version 1.2.1\n",stderr); +fputs("Copyright (C) 1986, 1987 By T&R Communications Associates, Chicago, IL, 60625\n",stderr); +fputs("Permission Granted For Unlimited * NON-COMMERCIAL * Distribution !!!\n\n",stderr); +} + +/*********************** Parse Command Line Arguments ************************/ + +parse_args(argc,argv) + +int argc; +char *argv[]; + +{ +int x,c,tmp; +FILE *fp; + +x = 1; +fp = NULL; + +while ( ((*argv[x]) == '-') && (x < argc) ) + { + switch(*(argv[x]+1)) + { + case 0: /* Just passed a - */ + prtstdin=TRUE; /* Treat stdin as a passed filename */ + break; + + case 'h': + if (*(argv[x]+2)) /* Should be NULL */ + error(NULL); + else + { + header=FALSE; + hdrlen=0; + } + break; + + case 'i': + if (*(argv[x]+2)) /* Is an init file named? */ + { + fp=fopen(argv[x]+2,"r"); + if (fp == NULL) /* Couldn't open init file */ + error(NULL); + while ((c=fgetc(fp)) != EOF) + fputc(c,stdout); + fclose(fp); + } + else + error(NULL); + break; + + case 'l': + tmp=atoi((argv[x]+2)); + if ((tmp < 10) || (tmp > 128)) + error(NULL); + else + plen=tmp; + break; + + case 'm': + if (*(argv[x]+2)) /* Should be NULL */ + error(NULL); + else + messages=FALSE; + break; + + case 'n': + if (*(argv[x]+2)) /* Should be NULL */ + error(NULL); + else + linenums=FALSE; + break; + + case 't': + tmp=atoi((argv[x]+2)); + if ((tmp < 2) || (tmp > 32)) + error(NULL); + else + tabsz=tmp; + break; + + case 'w': + tmp=atoi((argv[x]+2)); + if ((tmp < 50) || (tmp > 512)) + error(NULL); + else + pwidth=tmp; + break; + + default: + error(NULL); + } + x++; + } +return(x); +} + + +/*********************** Error Abort Handling Routine ************************/ + +void error(msg) +char *msg; + +{ +if (messages) + { + if (msg) + { + fputs("PP Error: ",stderr); + fputs(msg,stderr); + fputs(" !!!\n\n",stderr); + } + else + fputs("Usage: pp [-h -i -l -m -n -t -w -] filename(s) [>output device]\n\n",stderr); + } + +exit(1); +} + +/***************** Initialize Header Buffer And Globals **********************/ + +void init(hdrptr,filnam,fp) + +char *hdrptr,*filnam; +int fp; + +{ +int tmp; +char t[9],d[9],ft[9],fd[9],*offset; +times(t); +dates(d); +for (tmp=0;tmp < 8;tmp++) /* Stuff DeSmet's spaces */ + { + if (t[tmp] == ' ') + t[tmp] = '0'; + if (d[tmp] == ' ') + d[tmp] = '0'; + } + +if (fp != stdin) + fstamp(fp,fd,ft); /* Get File Date/Time Stamp */ +else + { + strcpy(fd,d); /* Use today for stdin stamp */ + strcpy(ft,t); + } + +tmp=0; /* First Do The Header */ +while (tmp < HDRSZ) + { + *(hdrptr+tmp)=' '; /* Initialize With Blanks */ + tmp++; + } + +tmp=1; +while (tmp <= HDRDEFALT) /* Stuff CR/LF Characters */ + { + offset=(hdrptr+(pwidth*tmp)+(2*(tmp-1))); + *offset=CR; + *(offset+1)=LF; + tmp++; + } + +*(hdrptr+HDRSZ-1)='\0'; /* Stuff Strings */ +strdup(hdrptr,filnam); +strdup((hdrptr+pwidth-PAGEPOS-8)," Page:"); +strdup((hdrptr+(pwidth*2)+2-DATEPOS-9),"Printed: At:"); +strdup((hdrptr+(pwidth*2)+2-DATEPOS),d); +strdup((hdrptr+(pwidth*2)+2-TIMEPOS),t); +strdup((hdrptr+(pwidth*3)+4-DATEPOS-15),"Last Modified: At:"); +strdup((hdrptr+(pwidth*3)+4-DATEPOS),fd); +strdup((hdrptr+(pwidth*3)+4-TIMEPOS),ft); + +strcpy(line,"00001"); /* Now Do All The Globals */ +col=1; +strcpy(page,"001"); +strcpy(nest,"01"); +squote=FALSE; +dquote=FALSE; +comment=FALSE; +if (linenums) + start=(sizeof(line)+2); /* Default is 1 - No line nums */ + +} + +/***************************** Force New Page ********************************/ + +void newpage(hdrptr) + +char *hdrptr; + +{ + +fputc(TOF,stdout); +if (header) + { + strdup(hdrptr+pwidth-PAGEPOS,page); + fputs(hdrptr,stdout); + fputc('\n',stdout); + bump(page,sizeof(page)); + } +newline(); +row=hdrlen+1; + +} + +/***************************** Begin New Line ********************************/ + +void newline() + +{ + +if (linenums) + { + fputs(line,stdout); + fputs(" ",stdout); + } +col=start; + +} + +/******************************* Wrap A Line *********************************/ + +void wrap(hdrptr,fp) + +char *hdrptr; +int fp; + +{ + +int x; + +x=fgetc(fp); /* Throw away whitespace */ +while ((x == ' ') || (x == TAB) || (x == '\r')) + x=fgetc(fp); +ungetc(x,fp); + +fputc('\n',stdout); +row++; +if (row > plen) + newpage(hdrptr); +else + { + x=start; + while (x) + { + fputc(' ',stdout); + x--; + } + col=start+1; + + } + +} + +/**************************** Bump ASCII Count *******************************/ + +void bump(ptr,sz) + +char *ptr; +int sz; + +{ +int carry,tmp; +carry=1; +sz=sz-2; + +while (sz >= 0) + { + tmp=(*(ptr+sz))-'0'; + tmp=tmp+carry; + if (tmp < 10) + carry=0; + else + { + tmp=tmp-10; + carry=1; + } + *(ptr+sz)=('0'+tmp); + sz--; + } + +} + +/***************************** Print Routine *********************************/ + +void pp(fp,filnam) + +int fp; +char *filnam; + +{ +int c,e,x; /* Working Character */ +char *hdrptr; /* Buffer Pointers */ +c = e = x = 0; + +/* Get Buffer Space And Initialize Buffer Pointers */ + +hdrptr = calloc(HDRSZ,sizeof(char)); +if (hdrptr == NULL) + error("Couldn't Allocate Header Buffer - Insufficient Memory"); + +init(hdrptr,filnam,fp); /* Initialize Header/Globals */ + +/* Actual Print Logic */ + +c=fgetc(fp); +if (c != EOF) + newpage(hdrptr); +ungetc(c,fp); + +while ((c=fgetc(fp)) != EOF) + { + if (col > pwidth) /* Start next line */ + { + ungetc(c,fp); /* Save for next time around */ + c=-1; + } + + switch(c) + { + + case -1: /* Gotta start a new line */ + wrap(hdrptr,fp); + e=' '; /* Last char really printed */ + break; + + case TOF: /* Allow embedded formfeeds */ + if (e != '\n') /* Terminate partial line */ + fputc('\n',stdout); + newpage(hdrptr); + if (linenums) /* Save last char printed */ + e=' '; + else + e='\n'; + break; + + case '\r': /* Ignore CR because of fputc() */ + break; /* Translates LF to CR-LF ! */ + + case '\n': /* Process end of line */ + fputc(c,stdout); + if ((c=fgetc(fp)) != EOF) /* Count up if not a file end */ + { + bump(line,sizeof(line)); /* Bump source line number */ + row++; /* Bump physical line number */ + if (row > plen) + newpage(hdrptr); + else + newline(); + } + ungetc(c,fp); + c='\n'; + break; + + case TAB: /* Expand TABs to spaces */ + x = ((col-start+1) % tabsz); + x = (x == 0 ? tabsz : x); + x = (tabsz+1) - x; + while (x) + { + if (col > pwidth) + { + c=wrap(hdrptr,fp); + x=0; + } + else + { + fputc(' ',stdout); + x--; + col++; + } + } + e=' '; /* Last char really printed */ + break; + + default: + fputc(c,stdout); + col++; + e=c; + break; + } + } + + if (e != '\n') /* For printers like laser */ + fputs("\n",stdout); /* That maintain column after FF */ + +/* Release Buffer Space */ + +free(hdrptr); + +} diff --git a/prfile/PR_FILE.ASM b/prfile/PR_FILE.ASM new file mode 100644 index 0000000..ed0341e --- /dev/null +++ b/prfile/PR_FILE.ASM @@ -0,0 +1,90 @@ + + PAGE 66,132 + TITLE PR_FILE.ASM +; +; +; ********** +; * PR_FILE.ASM - PRINTER-TO-FILE REDIRECTION UTILITY - VERSION 1.0 +; * LAST MODIFIED: 05/09/85 +; * COPYRIGHT (C) BY T.A. DANELIUK +; ********** +; +; +; ********** +; * SYSTEM EQUATES +; ********** +; +; +DOS EQU 21H ; DOS INTERRUPT +TERMINATE EQU 31H ; TERMINATE/STAY RESIDENT +PRINTER_IR EQU 5CH ; PRINTER IR VECTOR +ALLOC_MEM EQU 48H ; ALLOCATE MEMORY DOS FN +SET_BLOCK EQU 4AH ; GROW OR SHRINK ALLOC. BLOCK +EXIT EQU 4CH ; NORMAL EXIT TO DOS +EOL EQU 0A0DH ; END-OF-LINE STRING +STD_CON_OUT EQU 02H ; OUTPUT BYTE TO STDOUT +; +; +; ********** +; * CODE SEGMENT +; ********** +; +; +PR_FILE SEGMENT WORD 'CODE' + ASSUME CS:PR_FILE,DS:PR_FILE,ES:PR_FILE +; +; + ORG 100H ; THIS WILL BE A .COM FILE +; +; +START_RUN EQU THIS BYTE +; +; +START: JMP INIT ; GO TO INITIALIZATION CODE +RUNTIME: AND AL,AL ; CHECK IF 0 - PRINT REQ. + JZ RUN_RET ; NO, JUST RETURN GOOD STATUS + MOV DL,AL ; PRINT CHAR ON STDOUT + MOV AH,STD_CON_OUT + INT DOS +RUN_RET: MOV AH,90H ; SET PRINTER STATUS, OK + IRET ; AND RETURN +; +; +END_RUN EQU THIS BYTE +; +; + PAGE +; ********** +; * LOADER/INSTALL CODE +; ********** +; +; +INIT: PUSHF ; SAVE IR STATUS + CLI ; TURN 'EM OFF FOR NOW +; +; +; NOW POINT PRINTER VECTOR TO RUNTIME CODE +; +; + XOR DX,DX ; POINT DS TO VECTOR TBL. + MOV DS,DX + MOV BP,PRINTER_IR ; LOCATION OF IR VECTOR + MOV DS:[BP+2],CS ; SEGMENT OF CODE + MOV WORD PTR DS:[BP],OFFSET RUNTIME ; OFFSET OF CODE +; +; +; NOW TERMINATE, BUT STAY RESIDENT +; +; + XOR AL,AL ; SET RETURN ERROR CODE TO 0 + MOV AH,TERMINATE ; TERMINATE & STAY RESIDENT FN + MOV DX,END_RUN-START_RUN+100H ; SIZE OF RUN CODE IN BYTES + MOV CL,4 ; CONVERT TO PARAGRAPHS + SHR DX,CL ; BY DIVIDING BY 16 + INC DX ; ADD 1 FOR NOT BEING ON BOUNDRY + POPF ; RESET ORIGINAL IR STATUS + INT DOS ; DO THE DOS CALL +; +; +PR_FILE ENDS + END START diff --git a/prvid/PR_VID.ASM b/prvid/PR_VID.ASM new file mode 100644 index 0000000..ed0341e --- /dev/null +++ b/prvid/PR_VID.ASM @@ -0,0 +1,90 @@ + + PAGE 66,132 + TITLE PR_FILE.ASM +; +; +; ********** +; * PR_FILE.ASM - PRINTER-TO-FILE REDIRECTION UTILITY - VERSION 1.0 +; * LAST MODIFIED: 05/09/85 +; * COPYRIGHT (C) BY T.A. DANELIUK +; ********** +; +; +; ********** +; * SYSTEM EQUATES +; ********** +; +; +DOS EQU 21H ; DOS INTERRUPT +TERMINATE EQU 31H ; TERMINATE/STAY RESIDENT +PRINTER_IR EQU 5CH ; PRINTER IR VECTOR +ALLOC_MEM EQU 48H ; ALLOCATE MEMORY DOS FN +SET_BLOCK EQU 4AH ; GROW OR SHRINK ALLOC. BLOCK +EXIT EQU 4CH ; NORMAL EXIT TO DOS +EOL EQU 0A0DH ; END-OF-LINE STRING +STD_CON_OUT EQU 02H ; OUTPUT BYTE TO STDOUT +; +; +; ********** +; * CODE SEGMENT +; ********** +; +; +PR_FILE SEGMENT WORD 'CODE' + ASSUME CS:PR_FILE,DS:PR_FILE,ES:PR_FILE +; +; + ORG 100H ; THIS WILL BE A .COM FILE +; +; +START_RUN EQU THIS BYTE +; +; +START: JMP INIT ; GO TO INITIALIZATION CODE +RUNTIME: AND AL,AL ; CHECK IF 0 - PRINT REQ. + JZ RUN_RET ; NO, JUST RETURN GOOD STATUS + MOV DL,AL ; PRINT CHAR ON STDOUT + MOV AH,STD_CON_OUT + INT DOS +RUN_RET: MOV AH,90H ; SET PRINTER STATUS, OK + IRET ; AND RETURN +; +; +END_RUN EQU THIS BYTE +; +; + PAGE +; ********** +; * LOADER/INSTALL CODE +; ********** +; +; +INIT: PUSHF ; SAVE IR STATUS + CLI ; TURN 'EM OFF FOR NOW +; +; +; NOW POINT PRINTER VECTOR TO RUNTIME CODE +; +; + XOR DX,DX ; POINT DS TO VECTOR TBL. + MOV DS,DX + MOV BP,PRINTER_IR ; LOCATION OF IR VECTOR + MOV DS:[BP+2],CS ; SEGMENT OF CODE + MOV WORD PTR DS:[BP],OFFSET RUNTIME ; OFFSET OF CODE +; +; +; NOW TERMINATE, BUT STAY RESIDENT +; +; + XOR AL,AL ; SET RETURN ERROR CODE TO 0 + MOV AH,TERMINATE ; TERMINATE & STAY RESIDENT FN + MOV DX,END_RUN-START_RUN+100H ; SIZE OF RUN CODE IN BYTES + MOV CL,4 ; CONVERT TO PARAGRAPHS + SHR DX,CL ; BY DIVIDING BY 16 + INC DX ; ADD 1 FOR NOT BEING ON BOUNDRY + POPF ; RESET ORIGINAL IR STATUS + INT DOS ; DO THE DOS CALL +; +; +PR_FILE ENDS + END START diff --git a/screendoor/BDEMO2.C b/screendoor/BDEMO2.C new file mode 100644 index 0000000..e779d01 --- /dev/null +++ b/screendoor/BDEMO2.C @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include + + +uvalid(vptr,fld) + +struct VSTRUCT *vptr; +int fld; + +{ + +if ((*((vptr+fld)->rarray)) != '1') + return(TRUE); +else + return(FALSE); + +} + + + +main() + +{ + +/* +extern int errmsg_attr,errmsg_row,errmsg_col,errmsg_on,errmsg_cattr,errmsg_len; +extern char *errmsg_rreqd,*errmsg_mfill,errmsg_fill; +static char m1[]={"This is the new RREQD!"}; +static char m2[]={"MFILL Isn't Being Satisfied!"}; + +errmsg_attr=clrinp; +errmsg_row=0; +errmsg_col=3; +errmsg_rreqd=m1; +errmsg_mfill=m2; +errmsg_len=40; +errmsg_cattr=clrresp; +errmsg_fill='='; +errmsg_on=FALSE; +*/ + +static char prompt0[]={"This Is A Demonstration\n"}; +static char prompt1[]={"Of The VKEYIN Screen Management System\n"}; +static char prompt2[]={"Developed By:\n"}; +static char prompt3[]={"T&R Communications Associates\n"}; +static char prompt4[]={"Chicago, IL 60625\n"}; +static char vp1[]={"Alpha Only"}; +static char vp2[]={"Alpha Only - UC"}; +static char vp3[]={"Alpha Only - LC"}; +static char vp4[]={"AlphaNumeric Only"}; +static char vp5[]={"AlphaNumeric Only - UC"}; +static char vp6[]={"AlphaNumeric Only - LC"}; +static char vp7[]={"Binary Digits"}; +static char vp8[]={"Octal Digits"}; +static char vp9[]={"Decimal Digits"}; +static char vp10[]={"Hexadecimal Digits"}; + +static char resp0[16]={"Response #0"}; +static char resp1[16]={""}; +static char resp2[16]={"Response #2"}; +static char resp3[16]={"Response #3"}; +static char resp4[16]={"Response #4"}; +static char vr1[16]={""}; +static char vr2[16]={""}; +static char vr3[16]={""}; +static char vr4[16]={""}; +static char vr5[16]={""}; +static char vr6[16]={""}; +static char vr7[16]={""}; +static char vr8[16]={""}; +static char vr9[16]={""}; +static char vr10[16]={""}; + +static char h0[16]={"This Is Help #0"}; +static char h1[16]={"This Is Help #1"}; +static char h2[16]={"This Is Help #2"}; +static char h3[16]={"This Is Help #3"}; +static char h4[16]={"This Is Help #4"}; + + + +static struct VSTRUCT help[]={ + + clrinp,clrprmt,0,0,TRUE,h0,clrresp,7,60,FALSE,NULL,15,'.',TRUE,0,NULL,FALSE,FALSE,TRUE,NULL,TRUE, + clrinp,clrinp,7,15,TRUE,h1,clrresp,7,60,FALSE,NULL,15,'.',TRUE,0,NULL,FALSE,FALSE,TRUE,NULL,TRUE, + clrinp,clrbord,8,60,TRUE,h2,clrresp,7,60,FALSE,NULL,15,'.',TRUE,0,NULL,FALSE,FALSE,TRUE,NULL,TRUE, + clrinp,clrbmsg,11,35,TRUE,h3,clrresp,7,60,TRUE,NULL,15,'.',TRUE,0,NULL,FALSE,FALSE,TRUE,NULL,TRUE, + clrinp,clrerr,24,15,TRUE,h4,clrresp,7,60,FALSE,NULL,15,'.',TRUE,0,NULL,FALSE,FALSE,TRUE,NULL,TRUE + + }; + + +static struct VSTRUCT screen0[]={ + + clrinp,clrprmt,5,15,TRUE,prompt0,clrresp,5,60,TRUE,resp0,15,'.',TRUE,0,NULL,FALSE,FALSE,TRUE,&help[0],FALSE, + clrinp,clrprmt,6,15,TRUE,prompt1,clrresp,6,60,TRUE,resp1,15,'.',TRUE,1,NULL,FALSE,FALSE,TRUE,&help[1],FALSE, + clrinp,clrprmt,7,15,TRUE,prompt2,clrresp,7,60,FALSE,resp2,15,'.',TRUE,2,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,8,15,TRUE,prompt3,clrresp,8,60,TRUE,resp3,15,'.',TRUE,0,uvalid,TRUE,FALSE,TRUE,&help[3],FALSE, + clrinp,clrprmt,9,15,TRUE,prompt4,clrresp,9,60,TRUE,resp4,15,'.',FALSE,0,NULL,FALSE,TRUE,TRUE,&help[4],FALSE, + clrinp,clrprmt,11,15,TRUE,vp1,clrresp,11,60,TRUE,vr1,15,'.',TRUE,3,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,12,15,TRUE,vp2,clrresp,12,60,TRUE,vr2,15,'.',TRUE,4,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,13,15,TRUE,vp3,clrresp,13,60,TRUE,vr3,15,'.',TRUE,5,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,14,15,TRUE,vp4,clrresp,14,60,TRUE,vr4,15,'.',TRUE,6,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,15,15,TRUE,vp5,clrresp,15,60,TRUE,vr5,15,'.',TRUE,7,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,16,15,TRUE,vp6,clrresp,16,60,TRUE,vr6,15,'.',TRUE,8,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,17,15,TRUE,vp7,clrresp,17,60,TRUE,vr7,15,'.',TRUE,9,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,18,15,TRUE,vp8,clrresp,18,60,TRUE,vr8,15,'.',TRUE,10,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,19,15,TRUE,vp9,clrresp,19,60,TRUE,vr9,15,'.',TRUE,11,NULL,FALSE,FALSE,TRUE,NULL,FALSE, + clrinp,clrprmt,20,15,TRUE,vp10,clrresp,20,60,FALSE,vr10,15,'.',TRUE,12,NULL,FALSE,FALSE,TRUE,NULL,TRUE + + }; + + +struct VSTRUCT *vptr; +static char time[9],date[9]; + +scr_setup(); +scr_clr(); +verset('X','Y','Z'); +trbord(); +times(time); +dates(date); +dsplylin(2,5,date,clrbmsg); +dsplylin(2,66,time,clrbmsg); +cursorblk(TRUE); +vptr=screen0; +vdsply(vptr); +cursorblk(FALSE); +vkeyin(vptr,0,FALSE); +fill_lin(statlin,0,' ',statlen,clrclr); +fill_lin(23,center(mkstr('.',46)),'.',46,clrerr); + +} diff --git a/screendoor/BDEMO3.C b/screendoor/BDEMO3.C new file mode 100644 index 0000000..77a9537 --- /dev/null +++ b/screendoor/BDEMO3.C @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include + + +main() + +{ +static char resp0[200]={"x"}; + +static struct VSTRUCT screen0[]={ + clrinp,clrprmt,7,15,FALSE,NULL,clrresp,15,0,TRUE,resp0,199,'*',TRUE,0,NULL,FALSE,FALSE,TRUE,NULL,TRUE + }; + +struct VSTRUCT *vptr; +static char time[9],date[9]; + +scr_setup(); +scr_clr(); +vptr=screen0; +vdsply(vptr); +cursorblk(FALSE); +vkeyin(vptr,0,FALSE); + +} + diff --git a/screendoor/CURSORSZ.C b/screendoor/CURSORSZ.C new file mode 100644 index 0000000..b43a90e --- /dev/null +++ b/screendoor/CURSORSZ.C @@ -0,0 +1,22 @@ +/* CURSORSZ.C - Set Cursor Size + Last Modified: 06/11/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + +#include +#include + + +void cursorsz(top,bottom) + +int top,bottom; + +{ + +extern unsigned _rcx,_rax; + + _rcx=(top<<8)|(bottom); + _rax=0x0100; + _doint(16); /* Call BIOS and set cursor size */ + +} diff --git a/screendoor/MKSTR.C b/screendoor/MKSTR.C new file mode 100644 index 0000000..472e512 --- /dev/null +++ b/screendoor/MKSTR.C @@ -0,0 +1,29 @@ +/* MKSTR.C - Makes A String Of Character 'c' Having Length 'n' + Up To Maximum Length String Allowed In System + + Last Modified: 06/11/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + + +#include +#include + + +char *mkstr(c,n) + +char c; +int n; + +{ +static char string[MAXSTRING+1]; +int count; + + for (count=0;count<=((n<=MAXSTRING) ? (n-1):(MAXSTRING-1));count++) + string[count]=c; + + string[count]='\0'; + + return(string); + +} diff --git a/screendoor/S/CURSORSZ.OBJ b/screendoor/S/CURSORSZ.OBJ new file mode 100644 index 0000000..4b5527c --- /dev/null +++ b/screendoor/S/CURSORSZ.OBJ Binary files differ diff --git a/screendoor/S/MKSTR.OBJ b/screendoor/S/MKSTR.OBJ new file mode 100644 index 0000000..d807ca0 --- /dev/null +++ b/screendoor/S/MKSTR.OBJ Binary files differ diff --git a/screendoor/S/SET_VPAG.OBJ b/screendoor/S/SET_VPAG.OBJ new file mode 100644 index 0000000..8d404b3 --- /dev/null +++ b/screendoor/S/SET_VPAG.OBJ Binary files differ diff --git a/screendoor/S/VDSPLY.OBJ b/screendoor/S/VDSPLY.OBJ new file mode 100644 index 0000000..6dfcf4b --- /dev/null +++ b/screendoor/S/VDSPLY.OBJ Binary files differ diff --git a/screendoor/S/V_ROWCOL.OBJ b/screendoor/S/V_ROWCOL.OBJ new file mode 100644 index 0000000..5898b28 --- /dev/null +++ b/screendoor/S/V_ROWCOL.OBJ Binary files differ diff --git a/screendoor/SCRNDOOR b/screendoor/SCRNDOOR new file mode 100644 index 0000000..854f2df --- /dev/null +++ b/screendoor/SCRNDOOR @@ -0,0 +1,46 @@ +# MAKE File To Create A Working SCREENDOOR Library Under Microsoft C +# Last Modified: 06-13-87 +# Copyright (c) 1987, By T.A. Daneliuk + + +$(MODEL)\v_rowcol.obj: v_rowcol.c $(INCLUDE)\dos.h $(INCLUDE)\t&r.h + MSC v_rowcol,$(MODEL)\v_rowcol.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\v_rowcol.obj; + +$(MODEL)\vdsply.obj: vdsply.c $(INCLUDE)\stdio.h $(INCLUDE)\system.h \ + $(INCLUDE)\vstruct.h $(INCLUDE)\t&r.h + MSC vdsply,$(MODEL)\vdsply.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\vdsply.obj; + +$(MODEL)\mkstr.obj: mkstr.c $(INCLUDE)\system.h $(INCLUDE)\t&r.h + MSC mkstr,$(MODEL)\mkstr.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\mkstr.obj; + +$(MODEL)\cursorsz.obj: cursorsz.c $(INCLUDE)\dos.h $(INCLUDE)\t&r.h + MSC cursorsz,$(MODEL)\cursorsz.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\cursorsz.obj; + +$(MODEL)\set_vpag.obj: set_vpag.c $(INCLUDE)\dos.h $(INCLUDE)\t&r.h + MSC set_vpag,$(MODEL)\set_vpag.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\set_vpag.obj; + +$(MODEL)\sound.obj: sound.asm + MASM sound,$(MODEL)\sound.obj,NUL,NUL /D$(MODEL)MODEL /MX; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\sound.obj; + +$(MODEL)\vundsply.obj: vundsply.c $(INCLUDE)\stdio.h $(INCLUDE)\system.h \ + $(INCLUDE)\vstruct.h $(INCLUDE)\t&r.h + MSC vundsply,$(MODEL)\vundsply.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\vundsply.obj; + +$(MODEL)\show_hlp.obj: show_hlp.c $(INCLUDE)\stdio.h $(INCLUDE)\system.h \ + $(INCLUDE)\vstruct.h $(INCLUDE)\t&r.h + MSC show_hlp,$(MODEL)\show_hlp.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\show_hlp.obj; + +$(MODEL)\vkeyin.obj: vkeyin.c $(INCLUDE)\stdio.h $(INCLUDE)\system.h \ + $(INCLUDE)\vstruct.h $(INCLUDE)\t&r.h + MSC vkeyin,$(MODEL)\vkeyin.obj,NUL,NUL /A$(MODEL) $(DEBUG) /DLINT_ARGS; + LIB $(LIB)\$(MODEL)_sdoor.lib -+$(MODEL)\vkeyin.obj; + + diff --git a/screendoor/SD2/SD2_DEFS.H b/screendoor/SD2/SD2_DEFS.H new file mode 100644 index 0000000..0594b17 --- /dev/null +++ b/screendoor/SD2/SD2_DEFS.H @@ -0,0 +1,329 @@ +/* SD2_DEFS.H - ScreenDoor II Definitions, Global Variables, Etc. + + Last Modified: 08-11-88 + Copyright (C) 1988, T.A. Daneliuk +*/ + + +/*========================== DEBUGGING OPTIONS ===============================*/ + +#define DEBUG 0 /* Set To 1 To Enable Debugging */ + + +/*=========================== PROGRAM DEFINITIONS ============================*/ + +#define PROGNAME "ScreenDoor II" +#define VERSION "1.1" + +/*============================= COMPILER =====================================*/ + +#define MSC 1 /* Microsoft C */ +#define TURBO 0 /* Borland TurboC */ +#define PCCV 0 /* UNIX System V Compiler */ +#define PCCB 0 /* UNIX BSD 4.x Compiler */ +#define ANSI 1 /* Compiler is ANSI Compliant */ + + +/*========================= PRESENTATION SERVICE =============================*/ + +#define PC_BIOS 1 /* IBM-PC Via Standard Bios */ +#define PC_WIND 0 /* IBM-PC Via MS-Windows */ +#define PC_OSPM 0 /* OS/2 Presentation Manager */ +#define CURSES 0 /* UNIX Curses */ +#define XWINDOWS 0 /* Generic X-Windows */ + +/*========================== OPERATING SYSTEM ================================*/ + +#define PCDOS 1 /* Standard PC-DOS */ +#define OS_2 0 /* OS/2 */ +#define UNIXV 0 /* UNIX System V.x */ +#define UNIXB 0 /* UNIX BSD 4.x */ + + +/*============== DIRECTLY MANAGE PHYSICAL SCREEN FOR NOW =====================*/ + +#if PC_BIOS & PCDOS + +#define sd2_sound pcbios_sound +#define sd2_cursor pcbios_cursor +#define sd2_rdcursor pcbios_rdcursor +#define sd2_rowcol pcbios_rowcol +#define sd2_cls pcbios_cls +#define sd2_getc pcbios_getc +#define sd2_aputs pcbios_aputs + +#define CUROFF 32,7 /* Cursor Settings */ +#define CURSML 6,7 +#define CURBLK 0,7 + +#endif + + +/*===================== MISC. DEFINITIONS & TYPEDEFS =========================*/ + +#define FALSE 0 +#define TRUE !FALSE + +#ifndef BOOL +typedef int BOOL; /* Boolean Datatype */ +#endif + +#if PCDOS & PC_BIOS + +typedef unsigned int VCOORD; /* Screen Coordinates */ +typedef unsigned char VATRB; /* Video Attribute */ +typedef unsigned char VMODE; /* Video Mode */ +typedef unsigned char VPAGE; /* Video Page */ +typedef unsigned char KEYSTR; /* Keystroke */ +typedef unsigned int VALCODE; /* Character Validation Code */ +typedef unsigned char ERRCODE; /* Internal Error Code */ +typedef unsigned char F_TYPE; /* Field Type Codes */ +typedef int FLEN; /* Field Length */ + + +#endif + + +/*=================== SCREEN AND FIELD CONTROL STRUCTURES ====================*/ + + +struct SD2_FIELD /* FIELD Control Structure */ +{ + /* Members Common Top Both Prompt And Response Field Types */ + + F_TYPE ftype; /* Field Type */ + VCOORD frow; /* Field Vertical Position */ + VCOORD fcol; /* Field Horizontal Position */ + VATRB fattrib; /* Field Display Colors/Attributes */ + KEYSTR * field; /* Array Containing Field Contents */ + + + + /* Members Response Field Screen Control */ + + FLEN rlen; /* Maximum Allowed User Response Len. */ + VATRB rattrib; /* Input Colors/Attributes */ + VATRB cattrib; /* Attribute To Use When Clearing */ + KEYSTR rfill; /* Keyin Time Fill Character */ + KEYSTR rclear; /* Character To Use When Clearing */ + + /* Members For Single Character Validation */ + + BOOL rspace; /* TRUE Allows Blanks In Response */ + KEYSTR * mask; /* Character Validation Mask */ + KEYSTR ** v_lists; /* Array Of Char. Val. Strings */ + + + /* Members For Full Field Validation, Error Handling, Help, And Autoskip */ + + BOOL rmustfill; /* TRUE Means Field Must Be Filled */ + BOOL rreqd; /* TRUE Means A Response Is Required */ +#if ANSI + char *(*rvalid) (struct SD2_FIELD *x); /* See Below */ + void (*flderr) (struct SD2_FIELD *x, ERRCODE y, char *z); +#else + char *(*rvalid) (); /* Whole Field Validation Function */ + void (*flderr) (); /* Pointer To Error Handler */ +#endif + + struct SD2_SCRN *rhelp; /* Pointer To Help Screen Structure */ + BOOL rskp; /* TRUE Means Autoskip On */ +}; + + +struct SD2_SCRN /* SCREEN Control Structure */ +{ + void (* before) (); /* Do This Before Using Screen */ + void (* after) (); /* Do This Before Exiting Screen */ + struct SD2_FIELD *fields; /* Fields Present On This Screen */ + VATRB clr; /* Attribute To Use During Screen Clr.*/ + char autoborder; /* Automatically Border The Screen? */ +}; + + +/*============================= FIELD TYPES ==================================*/ + +#define FLD_PROMPT 0 +#define FLD_RESP 1 + + +/*======================= CHARACTER VALIDATION CODES =========================*/ + +#define SD2_LITERAL_L 'x' /* No Character Validation */ +#define SD2_LITERAL_U 'X' +#define SD2_LITERAL_N 'j' + +#define SD2_ALPHA_L 'a' /* Alphabetic Only */ +#define SD2_ALPHA_U 'A' +#define SD2_ALPHA_N 'k' + +#define SD2_ALPHANUM_L 'n' /* Alphanumeric Only */ +#define SD2_ALPHANUM_U 'N' +#define SD2_ALPHANUM_N 'l' + +#define SD2_BINARY 'b' /* Binary Digits Only */ +#define SD2_OCTAL 'o' /* Octal Digits Only */ +#define SD2_DECIMAL 'd' /* Decimal Digits Only */ +#define SD2_HEX_L 'h' /* Hex Digits Only */ +#define SD2_HEX_U 'H' +#define SD2_HEX_N 'u' +#define SD2_FLOATING 'f' /* Floating Point Digits Only */ +#define SD2_SCIENT_L 's' /* Scientific Digits Only */ +#define SD2_SCIENT_U 'S' +#define SD2_SCIENT_N 'v' +#define SD2_FINANCIAL '$' /* Financial Digits Only */ +#define SD2_YN_L 'y' /* Yes/No */ +#define SD2_YN_U 'Y' +#define SD2_YN_N 'w' + +#define SD2_LIST0 '0' /* Literal Lists */ +#define SD2_LIST1 '1' +#define SD2_LIST2 '2' +#define SD2_LIST3 '3' +#define SD2_LIST4 '4' +#define SD2_LIST5 '5' +#define SD2_LIST6 '6' +#define SD2_LIST7 '7' +#define SD2_LIST8 '8' +#define SD2_LIST9 '9' + + + +/*============ KEY MAP, CONTROL KEY, AND INTERNAL ERROR DEFINITIONS ==========*/ + +/* Offsets Into sd2_ctrl_codes Array Where These Internal Codes Can Be Found */ + + +#define IENO_ERR 0 /* No Error Status Return Code */ +#define NXT_FLD 1 /* Inter-Field Control */ +#define PRV_FLD 2 +#define FST_FLD 3 +#define LST_FLD 4 + +#define CUR_LFT 5 /* Intra-Field Control */ +#define CUR_RGT 6 +#define BEG_FLD 7 +#define END_FLD 8 +#define CLR_FLD 9 +#define CLR_END 10 +#define EXT_FLD 11 +#define INS 12 +#define DEL 13 +#define BS 14 +#define HELP 15 + +#define EXT_SCR 16 /* Window/Screen Control */ + +#define IEBAD_CTRL 17 /* Internal Error Code Positions */ +#define IENOTRES 18 +#define IEFNULL 19 +#define IENUL_FPTR 20 +#define IEMUST_FIL 21 +#define IERES_REQD 22 +#define IE_UVALID 23 + +#define C_XLATE 24 /* # Of Internal Control Codes */ +#define CTRL_SIZE 2 /* Max Length Of Control String */ +#define CTRL_ENTRY C_XLATE*3 /* # Of Control Key Translations */ +#define K_XLATE ((unsigned) ((KEYSTR) -1))+1 /* # Of Unique Key Vals. */ + + +struct CXLATE { /* Control Key Translation Entry */ + + unsigned int length; /* Length Of Input String */ + KEYSTR ctrlin[CTRL_SIZE]; /* Input String */ + unsigned int sd_ctrl; /* Index To sd2_ctrl_codes*/ + }; + +extern KEYSTR sd2_ctrl_codes[]; /* Declare Global Tables */ +extern struct CXLATE ctrl_xlate[]; +extern KEYSTR key_xlate[]; + + +/*==================== INTERNAL KEY & ERROR CONTROL CODES ====================*/ + +#define NXTFLD sd2_ctrl_codes[NXT_FLD] /* Control Codes */ +#define PRVFLD sd2_ctrl_codes[PRV_FLD] +#define FSTFLD sd2_ctrl_codes[FST_FLD] +#define LSTFLD sd2_ctrl_codes[LST_FLD] +#define CURLFT sd2_ctrl_codes[CUR_LFT] +#define CURRGT sd2_ctrl_codes[CUR_RGT] +#define BEGFLD sd2_ctrl_codes[BEG_FLD] +#define ENDFLD sd2_ctrl_codes[END_FLD] +#define CLRFLD sd2_ctrl_codes[CLR_FLD] +#define CLREND sd2_ctrl_codes[CLR_END] +#define EXTFLD sd2_ctrl_codes[EXT_FLD] +#define INSERT sd2_ctrl_codes[INS] +#define DELETE sd2_ctrl_codes[DEL] +#define BKSPC sd2_ctrl_codes[BS] +#define HELPKEY sd2_ctrl_codes[HELP] +#define EXTSCR sd2_ctrl_codes[EXT_SCR] + + + /* INTERNAL ERROR AND STATUS CODES */ + +#define SD2_NOERR (ERRCODE) sd2_ctrl_codes[IENO_ERR] /* No Error */ +#define SD2_ENOTRES (ERRCODE) sd2_ctrl_codes[IENOTRES] /* No Response Allow */ +#define SD2_EFNULL (ERRCODE) sd2_ctrl_codes[IEFNULL] /* Null Array In Fld.*/ +#define SD2_EBAD_CTRL (ERRCODE) sd2_ctrl_codes[IEBAD_CTRL] /* Bad Keybd. Ctrl.*/ +#define SD2_NULFPTR (ERRCODE) sd2_ctrl_codes[IENUL_FPTR] /* Null Fld. Ptr. */ +#define SD2_MUSTFIL (ERRCODE) sd2_ctrl_codes[IEMUST_FIL] /* Must Fill Error */ +#define SD2_RESREQD (ERRCODE) sd2_ctrl_codes[IERES_REQD] /* RReqd. Error */ +#define SD2_IEUVALID (ERRCODE) sd2_ctrl_codes[IE_UVALID] /* User Valid. Error*/ + + +/*======================== FUNCTION DECLARATIONS =============================*/ + + +#if ANSI + + /*** GENERIC ScreenDoor FUNCTIONS ***/ + +void sd2_sound(int x, int y); +void sd2_cursor(unsigned char x, unsigned char y); +unsigned long sd2_rdcursor(void); +unsigned long sd2_rowcol(VCOORD y, VCOORD x); +void sd2_cls(VATRB x); +KEYSTR sd2_getc(void); +unsigned int sd2_aputs(char *x, VATRB y); + +#if PC_BIOS & PCDOS +void pcbios_getvmode(void); +void pcbios_setvmode(VMODE x); +void pcbios_setvpage(VPAGE x); +#endif + +KEYSTR sd2_keyin(void); +ERRCODE sd2_init(char *x); +ERRCODE sd2_fedit(struct SD2_FIELD *x, KEYSTR *y); +void sd2_fdsply(struct SD2_FIELD *x, BOOL y, FLEN z); +void sd2_help(struct SD2_SCRN *x); + +#else + /*** GENERIC ScreenDoor FUNCTIONS ***/ + +void sd2_sound(); +void sd2_cursor(); +unsigned long sd2_rdcursor(); +unsigned long sd2_rowcol(); +void sd2_cls(); +KEYSTR sd2_getc(); +unsigned int sd2_aputs(); + +#if PCDOS & PC_BIOS +void pcbios_getvmode(); +void pcbios_setvmode(); +void pcbios_setvpage(); +#endif + +KEYSTR sd2_keyin(); +ERRCODE sd2_init(); +ERRCODE sd2_fedit(); +void sd2_fdsply(); +void sd2_help(); + +#endif + + +/*=====================END OF INSERT DECK =======================*/ + diff --git a/screendoor/SD2/SD2_KEYI.C b/screendoor/SD2/SD2_KEYI.C new file mode 100644 index 0000000..c02d7bf --- /dev/null +++ b/screendoor/SD2/SD2_KEYI.C @@ -0,0 +1,169 @@ +/* SD2_KEYIN.C - ScreenDoor II Keystroke Capture & Mapping Routines + This Code Captures A Keystroke And Maps It According + To The Global Key Value Maps. + + Last Modified: 08-02-88 + Copyright (C) 1988, T.A. Daneliuk + + + Input keystrokes are translated two ways. First, a keystroke is + checked to see if it might be the beginning of a system specific + control key sequence. If so, additional keystrokes are read and + if a sequence of keystrokes matches one of the entries in + the control key mapping table (ctrl_xlate), an internal ScreenDoor + control code is returned. (This value is found in sd2_ctrl_codes.) + If after examining CTRL_SIZE number of keystrokes no entry has + been found in ctrl_xlate, those keystrokes are thrown away. + + If an input is seen as data, it is translated via the key_xlate array. + This allows one-for-one character mapping. + + The idea behind this is that all of the internal code representations + and key bindings can be modified at init time via sd2_init(). + +*/ + +#include +#include + +#if ANSI +static BOOL match(unsigned x, unsigned y); +#else +static BOOL match(); +#endif + + +/*============ Global Control And Keystroke Translation Tables ===============*/ + +KEYSTR sd2_ctrl_codes[C_XLATE]; /* Intialized By sd2_init() !!! */ + + +#if PCDOS & PC_BIOS /* Ctrl. Table Must Be Redefined For Each Environment */ + +struct CXLATE ctrl_xlate[CTRL_ENTRY] = {2, 0, 80, NXT_FLD, /* Dn. Arrow */ + 1, 9, 0, NXT_FLD, /* Tab */ + 2, 0, 15, PRV_FLD, /* Back Tab */ + 2, 0, 72, PRV_FLD, /* Up Arrow */ + 2, 0, 73, FST_FLD, /* PgUp */ + 2, 0, 81, LST_FLD, /* PgDn */ + 2, 0, 75, CUR_LFT, /* Lft. Arrow */ + 2, 0, 77, CUR_RGT, /* Rt. Arrow */ + 2, 0, 71, BEG_FLD, /* Home */ + 2, 0, 79, END_FLD, /* End */ + 1, 10, 0, CLR_FLD, /* Ctrl-Enter */ + 2, 0, 117, CLR_END, /* Ctrl-End */ + 1, 13, 0, EXT_FLD, /* Enter */ + 2, 0, 82, INS, /* Ins */ + 2, 0, 83, DEL, /* Del */ + 1, 8, 00, BS, /* Backspace */ + 2, 0, 59, HELP, /* Fn. 1 */ + 1, 27, 0, EXT_SCR /* Esc */ + }; +#endif + +KEYSTR key_xlate[K_XLATE]; /* Initialized By sd2_init() !!! */ + + +/*====================== Get And Map Keyboard Input ==========================*/ + + +static KEYSTR work[CTRL_SIZE]; /* Working Buffer For Ctrl. Sequences */ + +static BOOL match(); + + + +KEYSTR sd2_keyin() + +{ + BOOL in_ctrl; /* TRUE = Now Parsing Ctrl. String */ + unsigned first_ctrl; /* Index Of 1st Possible Ctrl. Match */ + unsigned index; /* Index Into Control String Itself */ + KEYSTR key; + unsigned x; /* Working Variable */ + + in_ctrl = FALSE; + first_ctrl = 0; + index = 1; + + key = sd2_getc(); /* Get A Character */ + + first_ctrl = 0; /* See If It Might Be A Ctrl. String */ + + while ((first_ctrl < CTRL_ENTRY) && (in_ctrl == FALSE)) + { + if ((ctrl_xlate[first_ctrl].length > 0) && + (ctrl_xlate[first_ctrl].ctrlin[0] == key)) + { + in_ctrl = TRUE; /* 1st Char Matches */ + work[0] = key; /* So Save It */ + } + first_ctrl++; + } + + if (in_ctrl == FALSE) /* Not A Control String */ + key = key_xlate[(unsigned) key]; /* So Translate The Character */ + + else /* Match/Xlate Control String */ + { + first_ctrl--; /* Adjust To Point To Real Field */ + while (in_ctrl == TRUE) /* Go 'Till Match Or Miss */ + { + x = first_ctrl; + while ((x < CTRL_ENTRY) && (in_ctrl == TRUE)) + { + if (match(x, index) == TRUE) + { + in_ctrl = FALSE; + key = sd2_ctrl_codes[ctrl_xlate[x].sd_ctrl]; + } + x++; /* Check From first_ctrl On For Match */ + } + if (in_ctrl == TRUE) /* Still No Match */ + { + if (index == CTRL_SIZE) /* Max. Length Input String */ + { + key = sd2_ctrl_codes[IEBAD_CTRL]; /* Bad Control String */ + in_ctrl = FALSE; /* We're Done */ + } + else + { + key = sd2_getc(); /* Get Another Keystroke */ + work[index] = key; + index++; + } + } + } + } + + return(key); +} + + +/*=========See If Control String So Far Matches A Translation Entry ==========*/ + +static BOOL match(x, y) +unsigned x, y; + +{ + + BOOL flag; + unsigned z, len; + z = 0; + len = ctrl_xlate[x].length; + + if (y != len) /* String Lengths Don't Match */ + flag = FALSE; + else /* Lengths The Same */ + { + while ((work[z] == ctrl_xlate[x].ctrlin[z]) && (z < len)) + z++; + if (z == len) /* All Chars Matched */ + flag = TRUE; + else + flag = FALSE; + } + + return (flag); + +} diff --git a/screendoor/SDOOR.BAT b/screendoor/SDOOR.BAT new file mode 100644 index 0000000..56755a7 --- /dev/null +++ b/screendoor/SDOOR.BAT @@ -0,0 +1,23 @@ +ECHO OFF +IF _%1 == _ GOTO error +IF %1 == S GOTO doit +IF %1 == M GOTO doit +IF %1 == C GOTO doit +IF %1 == L GOTO doit +IF %1 == H GOTO doit + +:error +ECHO Bad Command Line, Need Model: (S, M, C, L, H) & Debug Flag (D) +GOTO done + +:doit +IF _%2 == _D GOTO debug +IF _%2 == _d GOTO debug +MAKE model=%1 debug= SCRNDOOR +GOTO done + +:debug +MAKE model=%1 debug=/Zi SCRNDOOR + +:done + diff --git a/screendoor/SET_VPAG.C b/screendoor/SET_VPAG.C new file mode 100644 index 0000000..de332e6 --- /dev/null +++ b/screendoor/SET_VPAG.C @@ -0,0 +1,23 @@ +/* SET_VPAG.C - Select A Video Memory Page + Last Modified: 06/11/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + +#include +#include + +void set_vpage(page) /* Select a particular video memory page */ + +char page; + +{ +extern unsigned _rax; +extern char scr_page; + + scr_page=page; /* Inform PCIO where we're going */ + _rax=0x0500; /* Select video page by ORing into AL */ + page=page & 0x03; /* Mask out all but the significant bits */ + _rax=_rax | page; + _doint(0x10); + +} diff --git a/screendoor/SHOW_HLP.C b/screendoor/SHOW_HLP.C new file mode 100644 index 0000000..84286a4 --- /dev/null +++ b/screendoor/SHOW_HLP.C @@ -0,0 +1,65 @@ +/* SHOW_HLP.C - Help Screen Support For The vkeyin() Routine + Last Modified: 06/13/87 + Copyright (C) 1986, 1987 T.A. Daneliuk +*/ + + +#include +#include +#include +#include + +char vpg_help=3; /* Video Page Used For Help Screens */ +int help_cls=TRUE; /* TRUE Means Clear Screen Before Doing Help Screen */ +int help_msg_cls=FALSE; /* TRUE Means Clear Help Strings */ +int help_cattr=clrnorm; /* Color To Use When Clearing Help Strings */ +char help_fill=' '; /* Char. To Use When Clearing Help Strings */ + +int show_help(vptr,fld,lasthelp) + +struct VSTRUCT *vptr; +int fld,lasthelp; + +{ +extern char scr_page; /* Global Defining Video Page Used For Input Screen */ +struct VSTRUCT *hptr; /* Used As Temporary Pointer */ +int c; /* Used To Get KBD Input */ +char vpg_temp; /* Used To Save Video Page On Entry */ +hptr=((vptr+fld)->hlp); /* Pointer to Help structure */ +vpg_temp=scr_page; /* Save Current Video Page */ + +scr_cursoff(); /* Cursor Off During Help */ +set_vpage(vpg_help); /* Select Help video page */ +if ((lasthelp == 0xffff) || (lasthelp != fld)) /* Build Screen If Needed */ + { + if (help_cls) /* Clear screen if desired */ + scr_clr(); + if ((hptr->rvalid) != NULL) + (*(hptr->rvalid)) (vptr,fld); /* Help Setup Call */ + vdsply((vptr+fld)->hlp); + } +HELP_WAIT: +while ((c=ci()) != 0) /* Wait For User */ + ; +if ((c=ci()) != FN3) + goto HELP_WAIT; + +if ((lasthelp == 0xffff) || (lasthelp != fld)) /* If we built a screen */ + { + if ((hptr->rvalid) != NULL) + (*(hptr->rvalid)) (vptr,fld); /* Help Setup Call */ + } + +if (help_msg_cls) /* Clear out help strings */ + { + vundsply(((vptr+fld)->hlp),help_cattr,help_fill); /* Un-Display The Help Messages */ + lasthelp=0xffff; /* We'll Need To Redisplay Next Time Around */ + } +else + lasthelp=fld; + +set_vpage(vpg_temp); /* Return to original Input video page */ +scr_curson(); /* Cursor Back On */ +return(lasthelp); +} + diff --git a/screendoor/SOUND.ASM b/screendoor/SOUND.ASM new file mode 100644 index 0000000..bc6b955 --- /dev/null +++ b/screendoor/SOUND.ASM @@ -0,0 +1,99 @@ + PAGE 40,132 + TITLE IBM-PC Sound Generator + SUBTTL Copyright (c) 1986, 1987 T.A. Daneliuk + NAME SOUND +; +; +; SOUND.A - ROUTINE CALLABLE BY MICROSOFT C TO PRODUCE SOUND ON IBM-PC +; LAST MODIFIED: 07/08 /87 +; COPYRIGHT (C) 1986, 1987 T.A. DANELIUK +; +; +; USAGE: sound(FREQ,DURATION) +; WHERE, FREQ IS UNSIGNED IN HERTZ +; DURATION IS UNSIGNED (18/SECOND) +; + +INCLUDE MSCMODEL.INC ; Model Equates + +PORTB_8255 EQU 61H ; 8255 PORT B +FREQ_8253 EQU 42H ; 8253 TIMER LATCH +COMMAND_8253 EQU 43H ; 8253 TIME COMMAND REGISTER +CLOCKH EQU 0012H ; CLOCK RATE HIGH BYTE - 1193180 HZ +CLOCKL EQU 34DCH ; CLOCK RATE LOW BYTE + + IF FARCODE + X EQU 6 ;OFFSET OF ARGUMENTS + ELSE + X EQU 4 ;OFFSET OF ARGUMENTS + ENDIF +; +; +DURATION EQU [BP+X+8] ; PARAMETER OFFSETS +FREQ EQU [BP+X+6] +ELAPSED EQU [BP+6] ; ELAPSED TIME TICKS STORED HERE +STARTL EQU [BP+4] ; STORES INITIAL TIMER COUNT +STARTH EQU [BP+2] +; +; +_TEXT SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:_TEXT + + PUBLIC _sound + IF FARCODE +_sound PROC FAR + ELSE +_sound PROC NEAR + ENDIF +; +; + XOR AX,AX ; ZERO REGISTER + PUSH AX ; INIT. ELAPSED TIME + PUSH AX ; INIT. STARTL + PUSH AX ; INIT. STARTH + PUSH BP ; PRESERVE REGISTER + MOV BP,SP ; LOCAL STACK FRAME + MOV AX,FREQ ; MAKE SURE FREQ. <> 0! + AND AX,AX + JZ SOUND_DONE ; IF SO, SKIP THE WHOLE THING + IN AL,PORTB_8255 ; GET CURRENT 8255 VALUE + OR AL,3 ; TURN ON SPEAKER/GATE SIGNAL + OUT PORTB_8255,AL ; WRITE BACK TO 8255 + MOV AL,0B6H ; TELL TIMER, FREQUENCY IS SENT NEXT + OUT COMMAND_8253,AL + MOV DX,CLOCKH ; DIVIDE CLOCK RATE BY PASSED + MOV AX,CLOCKL ; FREQUENCY TO GET TOTAL + MOV CX,FREQ ; NUMBER OF TICKS TO WAIT + DIV CX + OUT FREQ_8253,AL ; LOW BYTE TO TIMER + XCHG AL,AH ; INTEL'S NEAT INSTRUCTION SET! + OUT FREQ_8253,AL ; HIGH BYTE TO TIMER + XOR AX,AX ; GET CURRENT TIMER COUNT IN CX:DX + INT 1AH + MOV STARTH,CX ; SAVE FOR FUTURE REFERENCE + MOV STARTL,DX +DELAY: MOV AX,DURATION ; WAIT TILL ELAPSED TIME IS + CMP AX,ELAPSED ; >= DURATION PASSED ON STACK + JBE SOUND_OFF + XOR AX,AX ; GET CURRENT TIMER COUNT + INT 1AH + MOV AX,STARTH ; GET STARTING TIME + MOV BX,STARTL + SUB DX,BX ; LOW WORD FIRST + SBB CX,AX ; HIGH WORD WITH CARRY + JNZ SOUND_OFF ; ONLY CAN DEAL WITH 16 BIT INTERVALS + MOV ELAPSED,DX ; SAVE TIME ELAPSED + JMP DELAY +SOUND_OFF: IN AL,PORTB_8255 ; TURN OFF SPEAKER/GATE SIGNAL + AND AL,11111100B + OUT PORTB_8255,AL +SOUND_DONE: POP BP ; RESTORE ENVIRONMENT + POP AX ; BALANCE THE STACK + POP AX + POP AX + RET ; THERE'S NO PLACE LIKE HOME! +; +; +_sound ENDP +_TEXT ENDS + END diff --git a/screendoor/STDMSGS.H b/screendoor/STDMSGS.H new file mode 100644 index 0000000..151defd --- /dev/null +++ b/screendoor/STDMSGS.H @@ -0,0 +1,12 @@ +/* STDMSGS.H - Standard Messages Used In T&R Communications Software Products + Last Modified: 03/13/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + +/* Standard Messages */ + +char copyright[]={"[ Copyright (C) 1986, T&R Communications Associates, Chicago, IL 60625 ]"}; +char version[]={"[ Version: 0.0.0 ]"}; + + +/* END OF INSERT DECK */ diff --git a/screendoor/SYSTEM.H b/screendoor/SYSTEM.H new file mode 100644 index 0000000..b267232 --- /dev/null +++ b/screendoor/SYSTEM.H @@ -0,0 +1,111 @@ +/* SYSTEM.H - Color, Video, And System Definitions For IBM-PC + Last Modified: 06/19/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + + +/* Color Attribute Definitions + + + General format for attribute byte is: + + + b0-b2 Foreground Color + b3 Low Intensity Bit + b4-b6 Background Color + b7 Blinking Bit + + Foreground and border can be any color. + Background must be 0 to 7. + +*/ + +#define BLACK 0 +#define BLUE 1 +#define GREEN 2 +#define CYAN 3 +#define RED 4 +#define MAGENTA 5 +#define BROWN 6 +#define WHITE 7 +#define GRAY 8 +#define LBLUE 9 +#define LGREEN 10 +#define LCYAN 11 +#define LRED 12 +#define LMAGENTA 13 +#define YELLOW 14 +#define HWHITE 15 +#define NORMAL 7 /* White On Black Video */ +#define REVERSE 0x70 /* Reverse Video */ +#define BLINK 0x80 /* Blink attribute bit */ +#define INTENSE HWHITE /* Emphasized White On Black */ + + +/* Terminal Definitions */ + + +#define VWIDTH 80 /* Display width */ +#define VHEIGHT 25 /* Display height */ + + +/* Cursor And Attribute Macros */ + + +#define color(fore,back) ((back<<4)|fore) /* Make valid PC color attribute from colors */ +#define center(string) (strlen(string)>=VWIDTH ? 0:(VWIDTH-strlen(string))/2) +#define dsplylin(v,h,s,a) {v_rowcol(v,h);scr_aputs(s,a);} +#define fill_lin(v,h,c,l,a) dsplylin(v,h,mkstr(c,l),a) +#define cursorblk(x) (x==TRUE ? cursorsz(0,7):cursorsz(6,7)) + + +/* Border Character Definitions */ + + +#define BORDERV 0xBA +#define BORDERH 0xCD +#define BORDERNE 0xBB +#define BORDERSE 0xBC +#define BORDERNW 0xC9 +#define BORDERSW 0xC8 + + +/* Key Definitions */ + + +#define TAB 0x09 +#define TABBK 0x0F /* Preceeded by 00 */ +#define INS 0x52 /* Preceeded by 00 */ +#define DEL 0x53 /* Preceeded by 00 */ +#define SPACE 0x20 +#define BKSPC 0x08 +#define ENTER 0x0D +#define CLR_FLD 0x0A +#define ESC 0x1B /* Preceeded by 00 */ +#define UARROW 0x48 /* Preceeded by 00 */ +#define DARROW 0x50 /* Preceeded by 00 */ +#define RARROW 0x4D /* Preceeded by 00 */ +#define LARROW 0x4B /* Preceeded by 00 */ +#define HOME 0x47 /* Preceeded by 00 */ +#define END 0x4F /* Preceeded by 00 */ +#define PGUP 0x49 /* Preceeded by 00 */ +#define PGDN 0x51 /* Preceeded by 00 */ +#define FN1 0x3B /* Preceeded by 00 */ +#define FN2 0x3C /* Preceeded by 00 */ +#define FN3 0x3D /* Preceeded by 00 */ +#define FN4 0x3E /* Preceeded by 00 */ +#define FN5 0x3F /* Preceeded by 00 */ +#define FN6 0x40 /* Preceeded by 00 */ +#define FN7 0x41 /* Preceeded by 00 */ +#define FN8 0x42 /* Preceeded by 00 */ +#define FN9 0x43 /* Preceeded by 00 */ +#define FN10 0x44 /* Preceeded by 00 */ +#define HELP FN1 /* Use function key 1 as Help */ + + +/* Misc. System Dependent Parameters */ + +#define MAXSTRING 199 /* Maximum string length (DeSmet) */ + + +/* END OF INSERT DECK */ diff --git a/screendoor/T&R.H b/screendoor/T&R.H new file mode 100644 index 0000000..95c77a4 --- /dev/null +++ b/screendoor/T&R.H @@ -0,0 +1,34 @@ +/* T&R.H - System Definitions For T&R Communications Software Products + Last Modified: 06/16/87 + Copyright (C) 1986, 1987 By T.A. Daneliuk +*/ + +/* Boolean Values And Data Types */ + +#define FALSE 0 +#define TRUE !FALSE + +typedef int BOOL; /* Boolean Variable Type */ + + +/* Color Definitions */ + +#define clrnorm color(WHITE,BLACK) /* Normal Color */ +#define clrbord color(LBLUE,BLACK) /* Borders */ +#define clrbmsg color(YELLOW,BLUE) /* Border Messages */ +#define clrprmt color(YELLOW,BLACK) /* Prompts */ +#define clrresp color(LGREEN,BLACK) /* Responses After Editing*/ +#define clrerr color(BLACK,RED) /* Errors */ +#define clrstat color(BLACK,GREEN) /* Status */ +#define clrclr color(BLACK,BLACK) /* Clear Line */ +#define clrinp REVERSE /* Input Color */ + + +/* Error And Status Line Parameters */ + +#define errlin 24 /* 25th Line For Errors */ +#define errlen 79 /* Length Of Error Line */ +#define statlin 23 /* 24th Line For Status */ +#define statlen 79 /* Length Of Status Line */ + +/* END OF INSERT DECK */ diff --git a/screendoor/VDSPLY.C b/screendoor/VDSPLY.C new file mode 100644 index 0000000..1cde2e5 --- /dev/null +++ b/screendoor/VDSPLY.C @@ -0,0 +1,27 @@ +/* VDSPLY.C - Display Prompts And Responses Per A VSTRUCT Structure + Last Modified: 06/12/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + +#include +#include +#include +#include + +void vdsply(vptr) + +struct VSTRUCT *vptr; + +{ + +int x; + + for (x=0;(x==0 ? TRUE : ((vptr+x-1)->lastfld)!=TRUE);x++) + { + if (((vptr+x)->pdsply)==TRUE && ((vptr+x)->parray)!=NULL) + dsplylin((vptr+x)->pvert,(vptr+x)->phoriz,(vptr+x)->parray,(vptr+x)->pattrib); + if (((vptr+x)->rarray)!=NULL) + dsplylin((vptr+x)->rvert,(vptr+x)->rhoriz,(vptr+x)->rarray,(vptr+x)->rattrib); + } + +} diff --git a/screendoor/VKEYIN.C b/screendoor/VKEYIN.C new file mode 100644 index 0000000..ae0710a --- /dev/null +++ b/screendoor/VKEYIN.C @@ -0,0 +1,511 @@ +/* VKEYIN.C - Main Keyboard And Video Handler For Programs Using + The VSTRUCT Video Control Structure + Last Modified: 06/13/87 + Copyright (C) 1986, 1986 T.A. Daneliuk +*/ + + +#include +#include +#include +#include + + +/* Error Messages */ + +static char msg_rreqd[]={"Entry Required In This Field!"}; +static char msg_mfill[]={"This Field Must Be Filled!"}; +static char msg_rval[]={"User Validation Error Occurred!"}; + + +/* Global Variables Needed By VKEYIN */ + +int errbeep_on=TRUE; /* If TRUE, Will Beep On Error */ +unsigned errfreq=600; /* Frequency In Hz Of Error Beep */ +unsigned errtime=7; /* Beep Duration - 18/second */ +int clear_attr=clrnorm; /* Color To Use For Clearing Edit Fill Characters */ +int errmsg_attr=clrerr; /* Color To Use For Displaying Error Messages */ +int errmsg_row=24; /* Beginning Row For Error Messages */ +int errmsg_col=0; /* Beginning Column For Error Messages */ +int errmsg_on=TRUE; /* If TRUE Error Messages Will Be Displayed */ +int errmsg_len=79; /* Maximum Error Message Length */ +int errmsg_cattr=clrnorm; /* Attribute To Use When Clearing Error Message */ +char clear_fill=' '; /* Character To Use When Clearing Edit Fill Characters */ +char errmsg_fill=' '; /* Character To Use When Clearing Error Message */ +char *errmsg_rreqd=msg_rreqd; /* Pointer To rreqd Validation Error Message */ +char *errmsg_mfill=msg_mfill; /* Pointer To mustfill Validation Error Message */ +char *errmsg_rval=msg_rval; /* Pointer To rvalid Validation Error Message */ +char vkeyin_version[]={"2.1.1.pcMsoft "}; + +/*****************************************************************************/ + +/* This Function Determines Whether The Current Field Can Receive A User Response. + User Response Is Allowed If: + 1) rallow is TRUE in the structure for the field, and + 2) rarray is not NULL for the field, and + 3) rlen is > 0 for the field + + If Any Of These Conditions Is Not Met, The Field Is Assumed Not To Receive + User Response. + + If The Field Can Receive A Response, TRUE Is Returned, Else FALSE Is Returned. +*/ + +static int res_allowed(fldptr) + +struct VSTRUCT *fldptr; + +{ +if (!(fldptr->rallow) || ((fldptr->rarray)==NULL) || ((fldptr->rlen)<=0)) + return(FALSE); +else + return(TRUE); +} + +/*****************************************************************************/ + +/* This Function Displays The Current Field With Editing Fill Chars */ + +static void showfld(vptr,offset) + +struct VSTRUCT *vptr; +int offset; + +{ + scr_cursoff(); + fill_lin(vptr->rvert,vptr->rhoriz,vptr->rfill,vptr->rlen,vptr->iattrib); /* Do a line of fill chars */ + dsplylin(vptr->rvert,vptr->rhoriz,vptr->rarray,vptr->iattrib); /* Overlay with existing data */ + v_rowcol(vptr->rvert,(vptr->rhoriz)+offset); /* Put cursor where it was */ + scr_curson(); +} + +/*****************************************************************************/ + +/* This Function Cleans Editing Garbage Currently On Screen And + Redisplays The Current Contents Of The Response Array + + This Function Also Performs Whole Field, Required Entry, And + Must Fill Validations. FALSE Is Returned If No Error Is + Detected. If Error Is Detected, TRUE Is Returned, And Error + Message Is Displayed Per The Global Error Variables. +*/ + + +static int endfld(xptr,fld) + +struct VSTRUCT *xptr; +int fld; + +{ + +struct VSTRUCT *vptr; +static int error=FALSE; /* Error Flag */ + +vptr=xptr+fld; + + fill_lin(vptr->rvert,vptr->rhoriz,clear_fill,vptr->rlen,clear_attr); /* This clears the fld we just ended */ + dsplylin(vptr->rvert,vptr->rhoriz,vptr->rarray,vptr->rattrib); /* This (re-)displays the contents of the current field */ + + if (error && errmsg_on) /* Currently processing and displaying errors */ + dsplylin(errmsg_row,errmsg_col,mkstr(errmsg_fill,errmsg_len),errmsg_cattr); /* Clear last error message */ + + error=FALSE; /* Assume the error has been corrected */ + + if ((vptr->rreqd) && (strlen(vptr->rarray)==0)) /* No entry found in a rreqd field */ + { + error=TRUE; + if (errmsg_on) + dsplylin(errmsg_row,errmsg_col,*errmsg_rreqd,errmsg_attr); + } + + else if ((vptr->mustfill) && (strlen(vptr->rarray)!=(vptr->rlen))) /* Field not full in mustfill field */ + { + error=TRUE; + if (errmsg_on) + dsplylin(errmsg_row,errmsg_col,*errmsg_mfill,errmsg_attr); + } + + else if ((vptr->rvalid) != NULL) /* See if user validation routine enabled */ + { + if ((*(vptr->rvalid)) (xptr,fld)) /* Call it - Validation error if TRUE returned */ + { + error=TRUE; + if (errmsg_on) + dsplylin(errmsg_row,errmsg_col,*errmsg_rval,errmsg_attr); + } + } + + if (error && errbeep_on) + sound(errfreq,errtime); + + return(error); /* Return error condition */ + +} + +/*****************************************************************************/ + +/* This Function Deletes The Character At Current Offset Within RARRAY, + Moves Characters To The Right Of This Location Over, And Appends A + \0 To The End Of The Array +*/ + +static void delchar(vptr,offset) + +struct VSTRUCT *vptr; +int offset; + +{ + scr_cursoff(); + strcpy((vptr->rarray)+offset,(vptr->rarray)+offset+1); + v_rowcol(vptr->rvert,vptr->rhoriz); + scr_aputs(vptr->rarray,vptr->iattrib); + scr_aputs(mkstr(vptr->rfill,1),vptr->iattrib); + scr_curson(); +} + + +/*****************************************************************************/ + +/* This Function Makes Room For A Character To Be Inserted At Current + Offset Position. +*/ + +static void inschar(vptr,offset) + +struct VSTRUCT *vptr; +int offset; + +{ + int length=strlen(vptr->rarray); + + scr_cursoff(); + + *((vptr->rarray)+length+1)='\0'; + + while(length > offset) + { + *((vptr->rarray)+length)=*((vptr->rarray)+length-1); + length--; + } + v_rowcol(vptr->rvert,(vptr->rhoriz)+offset+1); + scr_aputs(((vptr->rarray)+offset+1),vptr->iattrib); + + scr_curson(); +} + +/*****************************************************************************/ +/*****************************************************************************/ +/*****************************************************************************/ + +/* vkeyin() Function Entry: + + vptr - Pointer To An Array Of Structures Per VSTRUCT.H + fld - Field Number At Which Processing Is To Begin + singlefld - If TRUE, Forces vkeyin To Process Only One Field And Then Return + +*/ + + +void vkeyin(vptr,fld,singlefld) + +struct VSTRUCT *vptr; /* Pointer To Control Structure */ +unsigned int fld; /* Starting Field Number */ +int singlefld; /* If TRUE, Process Only One Field, Then Return */ + +{ + +int c,cntrl,insert,offset,flderror,last,modified,resallowed,dummy,firstfld; +int lasthelp; + +modified=insert=FALSE; +resallowed=FALSE; /* Will be set to TRUE if any field allows a response */ +last=offset=0; +lasthelp=0xffff; /* 0xffff Flags The Fact That This Is 1st Time Through */ + + firstfld=fld; /* Save in case we're only processing one field */ + + while (((vptr+last)->lastfld) != TRUE) /* Calculate last field number */ + last++; + + fld=(fld>last ? 0:fld); /* Force 1st field into range */ + + for (dummy=0;dummy<=last;++dummy) /* See if response allowed in any field */ + { + if (res_allowed(vptr+dummy)) + resallowed=TRUE; + } + + if (resallowed) /* Point to 1st field >= entry field which allows entry */ + { + while (!res_allowed(vptr+fld)) + fld=(fldrvert,(vptr+fld)->rhoriz); /* Position cursor */ + + if (singlefld && (firstfld != fld)) /* Make sure we're in field we started in */ + resallowed=FALSE; + +/* + Main loop executes only if: + 1) The user doen't terminate with an FN3 key. + 2) A response is allowed somewhere on the current screen. + 3) In the case of single field processing, loop executes until current field is terminated. +*/ + + while (resallowed) + + { + flderror=FALSE; /* TRUE means we got a fld validation error */ + + c=ci(); /* Get a character */ + cntrl=FALSE; + + if (c==0) /* Prefix To Extended ASCII */ + { + cntrl=TRUE; + c=ci(); /* Get next character */ + } + + if (c==ENTER || c==CLR_FLD || c==TAB || c==BKSPC) /* Cursor control key */ + cntrl=TRUE; + + + if (cntrl==TRUE) /* Must be cursor control */ + + { + + if (c==DARROW) + c=TAB; /* TAB and Dn-Arrow Same Thing */ + if (c==UARROW) + c=TABBK; /* BackTAB and Up-Arrow Same Thing */ + + switch(c) /* Cursor control handling */ + + { + + case FN3: /* User wants to quit */ + if (flderror=endfld(vptr,fld)) /* Got an Error! Can't quit. */ + ; /* So do nothing and keep looping */ + else /* No error, we're done */ + resallowed=FALSE; /* Turn main loop off */ + break; + + case HELP: + if ((vptr+fld)->hlp) /* FALSE==NULL means no help screen */ + lasthelp=show_help(vptr,fld,lasthelp); /* Display The Help Screen */ + break; + + case TAB: /* Tab */ + if (!(flderror=endfld(vptr,fld))) /* No Error Occured */ + fld=((fldautoskp) ? ++fld:fld); /* Increment if autoskip set */ + fld=(fld>last ? 0:fld); /* Make sure fld in range */ + } + offset=0; /* Beginning of fld */ + modified=insert=FALSE; + break; + + case PGUP: /* Pg Up */ + if (!(flderror=endfld(vptr,fld))) /* No error occured */ + fld=0; /* Pt to first fld */ + offset=0; /* Beginning of fld */ + modified=insert=FALSE; + break; + + case PGDN: /* Pg Dn */ + if (!(flderror=endfld(vptr,fld))) /* No error occured */ + { + fld=last; /* Pt to last fld */ + while (!res_allowed(vptr+fld)) + fld=(fld==0 ? last:--fld); /* No entry allowed, get next fld */ + } + offset=0; /* Beginning of fld */ + modified=insert=FALSE; + break; + + case INS: /* INSert mode toggle */ + insert=((insert==FALSE) ? TRUE:FALSE); + break; + + case DEL: /* DELete character */ + if (!modified) /* 1st time through */ + { + showfld(vptr+fld,offset); + modified=TRUE; /* Indicate that field was modified */ + } + delchar(vptr+fld,offset); + break; + + case CLR_FLD: + for (offset=0;offset <= ((vptr+fld)->rlen);offset++) + *(((vptr+fld)->rarray)+offset)='\0'; + offset=0; + showfld(vptr+fld,offset); + modified=TRUE; + break; + + case BKSPC: /* Backspace */ + if (!modified) /* 1st time through */ + { + showfld(vptr+fld,offset); + modified=TRUE; /* Indicate that field was modified */ + } + offset=(offset==0 ? ((vptr+fld)->rlen)-1:--offset); + offset=(offset>strlen((vptr+fld)->rarray) ? strlen((vptr+fld)->rarray):offset); /* Cursor past end of valid data */ + delchar(vptr+fld,offset); + break; + + case RARROW: /* Right Arrow */ + offset=(offset>=(((vptr+fld)->rlen)-1) ? 0:++offset); /* Position no greater than field length */ + offset=(offset>strlen((vptr+fld)->rarray) ? 0:offset); /* Position only 1 past end of existing data */ + break; + + case LARROW: /* Left Arrow */ + offset=(offset==0 ? ((vptr+fld)->rlen)-1:--offset); + offset=(offset>strlen((vptr+fld)->rarray) ? strlen((vptr+fld)->rarray):offset); /* Cursor past end of valid data */ + break; + + case HOME: /* Home Key */ + offset=0; /* Go to start of fld */ + break; + + case END: /* End Key */ + offset=strlen((vptr+fld)->rarray); /* Go to end of fld */ + if (offset==((vptr+fld)->rlen)) /* Never wrap back to beginning */ + --offset; + break; + + } + if ((!flderror) && singlefld && (c==TAB || c==TABBK || c==ENTER || c==PGUP || c==PGDN)) + resallowed=FALSE; /* Single Field Processing */ + } + + /* Not A Cursor Motion Control Character - Must Be Printable Or Out-Of-Range */ + + else if ((offset < ((vptr+fld)->rlen)) && isprint(c) && ((c!=SPACE) || (c==SPACE && ((vptr+fld)->rspace)))) /* Legitimate characters from 0x20 to 0x7E */ + { + + /* Individual Character Validations - If Validation Fails, c Is Set To 0 */ + + switch((vptr+fld)->rcval) + { + case 0: /* No Validation */ + break; + case 1: /* Force Upper Case */ + c=toupper(c); + break; + case 2: /* Force Lower Case */ + c=tolower(c); + break; + case 3: /* Alpha Only */ + if (!isalpha(c)) + c=0; + break; + case 4: /* Alpha Only - UC */ + c=toupper(c); + if (!isalpha(c)) + c=0; + break; + case 5: /* Alpha Only - LC */ + c=tolower(c); + if (!isalpha(c)) + c=0; + break; + case 6: /* AlphaNumeric Only */ + if (!isalnum(c)) + c=0; + break; + case 7: /* AlphaNumeric Only - UC */ + c=toupper(c); + if (!isalnum(c)) + c=0; + break; + case 8: /* AlphaNumeric Only - LC */ + c=tolower(c); + if (!isalnum(c)) + c=0; + break; + case 9: /* Binary Digits Only */ + if (c<'0' || c>'1') + c=0; + break; + case 10: /* Octal Digits Only */ + if (c<'0' || c>'7') + c=0; + break; + case 11: /* Decimal Digits Only */ + if (!isdigit(c)) + c=0; + break; + case 12: /* Hexadecimal Digits Only - UC */ + c=toupper(c); + if (!isdigit(c) && (c<'A' || c>'F')) + c=0; + break; + case 13: /* 'Y' or 'N' Only - UC */ + c=toupper(c); + if ((c!='Y') && (c!='N')) + c=0; + break; + case 14: /* Floating Point Format */ + if (!isdigit(c) && c!='.' && c!='+' && c!='-') + c=0; + break; + case 15: /* Unsigned Floating Point Format */ + if (!isdigit(c) && c!='.') + c=0; + break; + case 16: /* Exponential Floating Point Format */ + c=toupper(c); + if (!isdigit(c) && c!='E' && c!='.' && c!='+' && c!='-') + c=0; + break; + } + + if (c != 0) /* Process Character Only If Validation Was OK */ + { + + if (!modified) /* 1st time through */ + { + showfld(vptr+fld,offset); + modified=TRUE; /* Indicate that field was modified */ + } + scr_aputs(mkstr(c,1),(vptr+fld)->iattrib); /* Display the character */ + if (insert) /* Insert mode set */ + inschar((vptr+fld),offset); + *(((vptr+fld)->rarray)+offset)=c; /* And stuff into proper array location */ + ++offset; /* Increment position and don't wrap */ + } + } +/* + Housekeeping done each time we go through the main while loop +*/ + + while (!res_allowed(vptr+fld)) + fld=(fldrvert,((vptr+fld)->rhoriz)+offset); /* Position cursor */ + if (strlen((vptr+fld)->rarray)>=(vptr+fld)->rlen) + insert=FALSE; /* Field Full - Can't Insert */ + cursorblk(insert); /* Show current insert status */ + + } +} diff --git a/screendoor/VSTRUCT.H b/screendoor/VSTRUCT.H new file mode 100644 index 0000000..f889d07 --- /dev/null +++ b/screendoor/VSTRUCT.H @@ -0,0 +1,33 @@ +/* VSTRUCT.H - Video Data Control Structure Template + Last Modified: 06/11/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + + +struct VSTRUCT +{ + int iattrib; /* Input Color Attributes */ + int pattrib; /* Prompt Color Attributes */ + int pvert; /* Prompt Vertical Position */ + int phoriz; /* Prompt Horizontal Position */ + int pdsply; /* TRUE Means Display Prompt */ + char *parray; /* Pointer To Array Containing Prompt */ + int rattrib; /* Response Color Attributes */ + int rvert; /* Response Vertical Position */ + int rhoriz; /* Response Horizontal Position */ + int rallow; /* TRUE Means Allow User Response */ + char *rarray; /* Pointer To Array Receiving Response */ + int rlen; /* Maximum Allowed User Response Length */ + char rfill; /* Keyin Time Fill Character */ + int rspace; /* TRUE Allows Blanks In Response */ + int rcval; /* Single Char. Validation Code 0=None */ + int (*rvalid) (); /* Pointer To Validation Routine */ + int mustfill; /* TRUE Means Field Must Be Filled */ + int rreqd; /* TRUE Means A Response Is Required */ + int autoskp; /* TRUE Means Autoskip On */ + struct VSTRUCT *hlp; /* Pointer To Help Screen Structure */ + int lastfld; /* TRUE Indicates No More Field Defs. */ +}; + + +/* END OF INSERT DECK */ diff --git a/screendoor/VUNDSPLY.C b/screendoor/VUNDSPLY.C new file mode 100644 index 0000000..7540ea5 --- /dev/null +++ b/screendoor/VUNDSPLY.C @@ -0,0 +1,28 @@ +/* VUNDSPLY.C - Un-Displays Prompts And Responses Per A VSTRUCT Structure + Last Modified: 06/30/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + +#include +#include +#include +#include + +void vundsply(vptr,attr,fill) + +struct VSTRUCT *vptr; +int attr; +char fill; +{ + +int x; + + for (x=0;(x==0 ? TRUE : ((vptr+x-1)->lastfld)!=TRUE);x++) + { + if (((vptr+x)->pdsply)==TRUE && ((vptr+x)->parray)!=NULL) + dsplylin((vptr+x)->pvert,(vptr+x)->phoriz,mkstr(fill,strlen((vptr+x)->parray)),attr); + if (((vptr+x)->rarray)!=NULL) + dsplylin((vptr+x)->rvert,(vptr+x)->rhoriz,mkstr(fill,strlen((vptr+x)->rarray)),attr); + } + +} diff --git a/screendoor/V_ROWCOL.C b/screendoor/V_ROWCOL.C new file mode 100644 index 0000000..612a339 --- /dev/null +++ b/screendoor/V_ROWCOL.C @@ -0,0 +1,16 @@ +/* V_ROWCOL - This Is A Front End Processor To scr_rowcol(). + Does Bounds Checking Based On The Current Values Of scr_rows + And scr_cols And Adjusts The Row And Column Values Passed By + The Calling Routine Before Calling scr_rowcol(). + This Is Done To Prevent IBM BIOS Video Routines From Ever Being + Passed Invalid Row, Column Coordinates. In Effect, Column Values + Are Wrapped To The Next Video Line, And Row Values Are Wrapped + Vertically. + + Calling Sequence Is: v_rowcol(row,column); + + Last Modified: 06/13/87 + Copyright (c), 1986, 1987 By T.A. Daneliuk +*/ + +#include diff --git a/setcolor/FORM1.FRM b/setcolor/FORM1.FRM new file mode 100644 index 0000000..0f49a8d --- /dev/null +++ b/setcolor/FORM1.FRM @@ -0,0 +1,154 @@ +VERSION 4.00 +Begin VB.Form Setcolor + Appearance = 0 'Flat + BackColor = &H80000005& + BorderStyle = 3 'Fixed Dialog + Caption = "Tundra's Setcolor Demo (Because Amir Is Feeble)" + ClientHeight = 4248 + ClientLeft = 1968 + ClientTop = 2340 + ClientWidth = 6444 + BeginProperty Font + name = "MS Sans Serif" + charset = 0 + weight = 700 + size = 24 + underline = 0 'False + italic = 0 'False + strikethrough = 0 'False + EndProperty + ForeColor = &H80000008& + Height = 4632 + Left = 1920 + LinkTopic = "Form1" + ScaleHeight = 4248 + ScaleWidth = 6444 + Top = 2004 + Width = 6540 + Begin VB.HScrollBar BScroll + Height = 612 + Left = 3480 + Max = 15 + TabIndex = 4 + Top = 2880 + Width = 492 + End + Begin VB.HScrollBar FScroll + Height = 612 + Left = 2280 + Max = 15 + TabIndex = 3 + Top = 2880 + Width = 492 + End + Begin VB.CommandButton Background + Appearance = 0 'Flat + BackColor = &H80000005& + Caption = "Back" + BeginProperty Font + name = "MS Sans Serif" + charset = 0 + weight = 700 + size = 7.8 + underline = 0 'False + italic = 0 'False + strikethrough = 0 'False + EndProperty + Height = 852 + Left = 3360 + TabIndex = 1 + Top = 1800 + Width = 732 + End + Begin VB.CommandButton Foreground + Appearance = 0 'Flat + BackColor = &H80000005& + Caption = "Fore" + BeginProperty Font + name = "MS Sans Serif" + charset = 0 + weight = 700 + size = 7.8 + underline = 0 'False + italic = 0 'False + strikethrough = 0 'False + EndProperty + Height = 852 + Left = 2160 + TabIndex = 0 + Top = 1800 + Width = 732 + End + Begin VB.Label SampleText + Alignment = 2 'Center + Appearance = 0 'Flat + BackColor = &H80000005& + BorderStyle = 1 'Fixed Single + Caption = "Sample Text" + BeginProperty Font + name = "Courier New" + charset = 0 + weight = 700 + size = 18 + underline = 0 'False + italic = 0 'False + strikethrough = 0 'False + EndProperty + ForeColor = &H80000008& + Height = 852 + Left = 2040 + TabIndex = 2 + Top = 720 + Width = 2196 + End +End +Attribute VB_Name = "Setcolor" +Attribute VB_Creatable = False +Attribute VB_Exposed = False +Dim FColor As Integer +Dim BColor As Integer + +Private Sub Background_Click() + If (BColor = 15) Then + BColor = 0 + Else + BColor = BColor + 1 + End If + BScroll.Value = BColor + Call setem +End Sub + +Private Sub BScroll_Change() + BColor = BScroll.Value + Call setem +End Sub + +Private Sub Foreground_Click() + If (FColor = 15) Then + FColor = 0 + Else + FColor = FColor + 1 + End If + FScroll.Value = FColor + Call setem +End Sub + +Private Sub Form_Load() + FColor = 0 + BColor = 15 + FScroll.Value = FColor + BScroll.Value = BColor + SampleText.ForeColor = QBColor(FColor) + SampleText.BackColor = QBColor(BColor) +End Sub + +Private Sub FScroll_Change() + FColor = FScroll.Value + Call setem +End Sub + +Private Sub setem() + SampleText.BackColor = QBColor(BColor) + SampleText.ForeColor = QBColor(FColor) +End Sub + diff --git a/setcolor/Project1.mak b/setcolor/Project1.mak new file mode 100644 index 0000000..41687f4 --- /dev/null +++ b/setcolor/Project1.mak @@ -0,0 +1,18 @@ +Form=FORM1.FRM +Object={F9043C88-F6F2-101A-A3C9-08002B2F49FB}#1.0#0; COMDLG32.OCX +Reference=*\G{00025E04-0000-0000-C000-000000000046}#2.5#0#C:\PROGRAM FILES\COMMON FILES\MICROSOFT SHARED\DAO\dao2532.tlb#Microsoft DAO 2.5/3.0 Compatibility Library +ProjWinSize=74,385,252,122 +ProjWinShow=2 +IconForm="Setcolor" +Title="PROJECT1" +ExeName="SETCOLOR.EXE" +Name="Project1" +HelpContextID="0" +StartMode=0 +VersionCompatible32="0" +MajorVer=1 +MinorVer=0 +RevisionVer=0 +AutoIncrementVer=0 +ServerSupportFiles=0 +VersionCompanyName="TundraWare" diff --git a/setcolor/SETCOLOR.EXE b/setcolor/SETCOLOR.EXE new file mode 100644 index 0000000..d4de742 --- /dev/null +++ b/setcolor/SETCOLOR.EXE Binary files differ diff --git a/strdup/STRDUP.C b/strdup/STRDUP.C new file mode 100644 index 0000000..942210a --- /dev/null +++ b/strdup/STRDUP.C @@ -0,0 +1,19 @@ +/* STRDUP.C - String Copy Function Which Does Not Copy The Null Terminator + Copyright (C) 1986 T.A. Daneliuk + Last Modified: 09/15/86 +*/ + +void strdup(dst,src) + +char *dst,*src; + +{ + +while (*src != '\0') + { + *dst=*src; + src++; + dst++; + } + +} diff --git a/swpr/SW_PR.ASM b/swpr/SW_PR.ASM new file mode 100644 index 0000000..2ff0f3d --- /dev/null +++ b/swpr/SW_PR.ASM @@ -0,0 +1,294 @@ + + PAGE 40,132 + TITLE SW_PR.ASM +; +; +; ********** +; * SW_PR.ASM - PRINTER REASSIGNMENT FILTER - VERSION 1.5 +; * LAST MODIFIED: 12/11/85 +; * COPYRIGHT (C) BY T.A. DANELIUK +; ********** +; +; +; ********** +; * SYSTEM EQUATES +; ********** +; +; +SPACE EQU 20H ; ASCII SPACE +DOS EQU 21H ; DOS INTERRUPT +EOL EQU 0A0DH ; END-OF-LINE STRING +EXIT EQU 4CH ; NORMAL EXIT TO DOS +GET_IR_VECT EQU 35H ; GET VECTOR FROM IR TABLE +PRINTER_IR EQU 17H ; PRINTER IR VECTOR +PRINT_STRING EQU 09H ; IR TO PRINT STRING ON DISPLAY +SET_IR_VECT EQU 25H ; SET AN IR VECTOR IN TABLE +TAB EQU 09H ; ASCII TAB +TAIL_BEGIN EQU 81H ; OFFSET OF COMMAND TAIL IN PSP +TAIL_LENGTH EQU 80H ; LOC OF LENGTH BYTE IN CMD TAIL +TERMINATE EQU 31H ; TERMINATE/STAY RESIDENT +; +; +; +; ********** +; * CODE SEGMENT +; ********** +; +; +SW_PR SEGMENT WORD 'CODE' + ASSUME CS:SW_PR,DS:SW_PR,ES:SW_PR +; +; + + ORG 100H +; +START_RUN EQU THIS BYTE +; +; +START: JMP INIT ; GO TO INITIALIZATION CODE +; +SWITCH_PR EQU THIS BYTE +; +; FIRST COMES THE HEADER +; + JMP SHORT ENTRY + DW OFFSET END_RUN-1 ; LAST ADDR. OF RESIDENT CODE +MOD_NAME DB 'SW_PR ' ; NAME OF MODULE IN ASCII +; +; THE FOLLOWING 4 HEADER BYTES ARE APPLICATION DEFINED. IN THIS CASE THEY ARE USED +; AS A PRINTER LOOKUP AND TRANSLATION TABLE FOR THE 3 POSSIBLE PRINTER IDS. +; +LPT_TBL DB 0 ; DEFAULT FOR LPT1: + DB 1 ; DEFAULT FOR LPT2: + DB 2 ; DEFAULT FOR LPT3: + DB 0 ; UNUSED IN THIS CASE +; +; NOW THE ACTUAL RESIDENT INTERRUPT CODE +; +ENTRY: PUSH DX ; SAVE SCRATCH REGISTER + PUSH BX + MOV BX,OFFSET LPT_TBL ; POINT TO TABLE + ADD BX,DX ; POINT TO PROPER ENTRY + MOV DL,CS:[BX] ; GET THE VALUE THERE + POP BX ; RESTORE BX +RUN_DONE: PUSHF ; FAKE AN INTERRUPT + CALL DWORD PTR CS:OLD_VECTOR ; GO TO ORIGINAL IR HANDLER +; +GO_BACK EQU THIS BYTE +; + POP DX + IRET ; BACK TO THE OUTSIDE WORLD +; +OLD_VECTOR DD ? +; +END_RUN EQU THIS BYTE +; +; + PAGE +; ********** +; * LOADER/INSTALL CODE +; ********** +; +; +INIT: PUSHF ; SAVE IR STATUS + CLI ; TURN 'EM OFF FOR NOW +; +; +; DISPLAY BANNER +; +; + MOV DX,OFFSET MSG1 + MOV AH,PRINT_STRING + INT DOS +; +; +; FIRST, FIND OUT IF THE RESIDENT CODE IS ALREADY IN PLACE, AND SET THE +; FLAG CALLED MODULE_RESIDENT APPROPRIATELY. +; +; + MOV AH,GET_IR_VECT ; GET EXISTING PRINTER IR VECTOR + MOV AL,PRINTER_IR + INT DOS ; IT COMES BACK IN ES:BX + MOV DI,BX ; BUT CMPS WANTS IT IN ES:DI + ADD DI,4 ; POINT TO ASCII NAME IN HEADER + MOV SI,OFFSET MOD_NAME ; OTHER STRING FOR CMPS IN DS:SI + MOV CX,8 ; STRING LENGTH IN BYTES + REPZ CMPSB ; SEE IF STRINGS ARE EQUAL + JNZ MOD_NOT_IN ; RESIDENT CODE IS *NOT* IN + NOT MODULE_RESIDENT ; RESIDENT CODE *IS* IN + JMP SHORT BUILD_POINTERS +MOD_NOT_IN: MOV AX,CS ; SAVE SEGMENT OF IR CODE + MOV ES,AX +; +; +; NOW BUILD POINTERS TO THE EXCHANGE TABLE AND COMMAND TAIL STRING. +; +; +BUILD_POINTERS: MOV BP,TAIL_LENGTH ; GET TAIL'S LENGTH + MOV CL,CS:[BP] ; INTO CL + INC BP ; POINT TO BEGINNING OF TAIL + MOV BX,OFFSET LPT_TBL ; SETUP PTR TO XLATE TABLE +; +; +; NOW PARSE COMMAND TAIL AND BUILD THE PRINTER TRANSLATION TABLE. +; +; +PARSE: AND CL,CL ; ARE THERE 0 CHARACTERS LEFT? + JZ DSPL_STATUS ; YES, GO ON + MOV AL,CS:[BP] ; GET A CHARACTER + CMP AL,SPACE ; IS IT A BLANK? + JZ WHITE_SPACE ; YES, SKIP IT + CMP AL,TAB ; IS IT A TAB? + JZ WHITE_SPACE ; YES, SKIP IT + CALL VALIDATE_CHAR ; SEE IF ITS A LEGAL CHAR + JNC PARM_ERR ; IF VALID, CARRY IS SET + CMP CL,3 ; WE MUST HAVE AT LEAST 3 + JL PARM_ERR ; CHARACTERS LEFT IN TAIL + MOV AH,AL ; SAVE FOR FUTURE USE + MOV AL,CS:[BP+1] ; CHECK FOR VALID ASSIGNMENT + CMP AL,'=' ; CHARACTER + JNZ PARM_ERR + MOV AL,CS:[BP+2] ; GET RVALUE FOR TRANSLATION + CALL VALIDATE_CHAR + JNC PARM_ERR + CALL INSTALL_ENTRY ; SETUP TABLE ENTRY + ADD BP,3 ; POINT TO NEXT PART OF TAIL + SUB CX,3 ; DECREMENT CHARACTER COUNT + JMP PARSE ; DO 'TILL TAIL IS ALL PARSED +; +WHITE_SPACE: INC BP ; POINT TO NEXT TAIL LOCATION + DEC CL ; ADJUST CHARACTER COUNT + JMP PARSE ; GO TRY AGAIN +; +VALIDATE_CHAR: CMP AL,'1' ; CHARACTER MUST BE 1,2, OR 3 + JL BAD_CHAR + CMP AL,'3' + JG BAD_CHAR + SUB AL,'1' ; MAKE 0 RELATIVE BINARY + STC ; SET CARRY TO INDICATE GOOD CHAR + RET +BAD_CHAR: CLC ; NO CARRY FOR ERROR + RET +; +INSTALL_ENTRY: PUSH BX ; SAVE TABLE POINTER + PUSH AX + MOV AL,AH ; BUILD WORD OFFSET INTO TABLE + AND AH,00H + ADD BX,AX + POP AX ; RESTORE INSTALL DATA + MOV ES:[BX],AL ; INSTALL VALUE + POP BX ; RESTORE TABLE POINTER + RET +; +PARM_ERR: MOV AH,PRINT_STRING ; DISPLAY MESSAGE + MOV DX,OFFSET MSG3 + INT DOS + JMP DSPL_STATUS + PAGE +; DISPLAY CURRENT TRANSLATION VALUES ON SCREEN +; +; +DSPL_STATUS: MOV BP,OFFSET L1 ; ENTRY IN MESSAGE + CALL SET_PR_VALUE + MOV BP,OFFSET L2 + CALL SET_PR_VALUE + MOV BP,OFFSET L3 + CALL SET_PR_VALUE + MOV DX,OFFSET MSG2 ; DISPLAY THE MESSAGE + MOV AH,PRINT_STRING + INT DOS + MOV AL,MODULE_RESIDENT ; DEPENDING ON WHETHER MODULE + AND AL,AL ; IS RESIDENT, TERMINATE AND + JZ CHAIN_IR ; STAY RESIDENT + JMP NORM_EXIT ; OR JUST EXIT NORMALLY +; +SET_PR_VALUE: MOV AL,ES:[BX] ; GET TABLE ENTRY + INC AL ; MAKE "1 RELATIVE" + ADD AL,'0' ; CONVERT TO ASCII + MOV CS:[BP],AL ; SAVE IN MESSAGE + INC BX ; POINT TO NXT TBL ENTRY + RET ; BACK TO THE RANCH + PAGE +; GET EXISTING PRINTER VECTOR AND SAVE FOR CHAINING +; +; +CHAIN_IR: MOV AH,GET_IR_VECT ; FUNCTION NUMBER + MOV AL,PRINTER_IR ; INTERRUPT NUMBER + INT DOS + MOV BP,OFFSET OLD_VECTOR + MOV CS:[BP],BX ; WE GOT THE OLD VECTOR IN ES:BX + MOV BX,ES ; GET SEGMENT + MOV CS:[BP+2],BX +; +; +; STUFF NEW VECTOR INTO TABLE SO WE GET CONTROL FIRST +; +; + MOV DX,OFFSET SWITCH_PR ; VECTOR IN DS:DX - DS ALREADY OK + MOV AH,SET_IR_VECT + MOV AL,PRINTER_IR + INT DOS +; +; +; TERMINATE, BUT STAY RESIDENT EXIT CODE +; +; +RESIDE_EXIT: MOV AX,OFFSET END_RUN ; CALCULATE MODULE LENGTH IN PARAS + MOV CL,10H ; DIVISOR + DIV CL + AND AH,AH ; ANY REMAINDER? + JZ NO_REMAINDER ; NO + INC AL ; YES, BUMP A FULL PARAGRAPH +NO_REMAINDER: XOR DX,DX ; CLEAR DX + MOV DL,AL ; TERMINATE FN. NEEDS LENGTH IN DX + XOR AL,AL ; SET RETURN ERROR CODE TO 0 + MOV AH,TERMINATE ; TERMINATE & STAY RESIDENT FN + POPF ; RESET ORIGINAL IR STATUS + INT DOS ; DO THE DOS CALL + PAGE +; NORMAL EXIT CODE +; +; +NORM_EXIT: XOR AL,AL ; RETURN WITHOUT ERROR + MOV AH,EXIT + POPF + INT DOS + PAGE +; BANNER MESSAGE STRINGS +; +; +MSG1 DW EOL + DB 'SW_PR - PRINTER REASSIGNMENT FILTER - Version 1.5' + DW EOL + DB 'Copyright (c) 1985, T.A. Daneliuk, Chicago, IL 60625' + DW EOL + DB 'Permission Granted To Reproduce This Program' + DW EOL + DB 'For PERSONAL, *** NON-COMMERCIAL *** Use Only!' + DW EOL,EOL + DB '$' +; +MSG2 DB 'LPT1: Is Assigned To Physical Printer #' +L1 DB ? + DW EOL + DB 'LPT2: Is Assigned To Physical Printer #' +L2 DB ? + DW EOL + DB 'LPT3: Is Assigned To Physical Printer #' +L3 DB ? + DW EOL,EOL + DB '$' +; +MSG3 DB 'INVALID PARAMETER ON COMMAND LINE !!! ' + DW EOL,EOL + DB '$' +; +; +; STATIC STORAGE LOCATIONS +; +; +MODULE_RESIDENT DB 00H ; NON-ZERO MEANS MODULE ALREADY IN +; +; +SW_PR ENDS + END START diff --git a/sysenv/SYS_ENV.H b/sysenv/SYS_ENV.H new file mode 100644 index 0000000..914c67f --- /dev/null +++ b/sysenv/SYS_ENV.H @@ -0,0 +1,45 @@ +/* SYS_ENV.H - Environment Specific Definitions + (Accounts For Operating System, Hardware, Etc.) + + Last Modified: 07/12/88 + Copyright (C) 1988, T.A. Daneliuk +*/ + + + +/*========================== DEBUGGING OPTIONS ===============================*/ + +#define DEBUG 0 /* Set To 1 To Enable Debugging */ + + +/*=========================== PROGRAM DEFINITIONS ============================*/ + +#define PROGNAME "SYS_ENV" +#define VERSION "1.0" + +/*============================= COMPILER =====================================*/ + +#define MSC 1 /* Microsoft C */ +#define TURBO 0 /* Borland TurboC */ +#define PCCV 0 /* UNIX System V Compiler */ +#define PCCB 0 /* UNIX BSD 4.x Compiler */ + + +/*========================= PRESENTATION SERVICE =============================*/ + +#define PC_BIOS 1 /* IBM-PC Via Standard Bios */ +#define PC_WIND 0 /* IBM-PC Via MS-Windows */ +#define PC_OSPM 0 /* OS/2 Presentation Manager */ +#define CURSES 0 /* UNIX Curses */ + + +/*========================== OPERATING SYSTEM ================================*/ + +#define PCDOS 1 /* Standard PC-DOS */ +#define OS_2 0 /* OS/2 */ +#define UNIXV 0 /* UNIX System V.x */ +#define UNIXB 0 /* UNIX BSD 4.x */ + + +/*=====================END OF INSERT DECK ========================*/ + diff --git a/tee/TEE.ASM b/tee/TEE.ASM new file mode 100644 index 0000000..633f1fb --- /dev/null +++ b/tee/TEE.ASM @@ -0,0 +1,138 @@ + name tee + page 55,132 + title 'TEE - tee junction for DOS pipes' +; +; TEE --- A "tee" junction for DOS 2.x pipes +; after the fashion of the Unix function TEE +; +; Copyright (C) 1984 A. K. Head +; +; TEE reads from the standard input (redirectable) and +; outputs to both the standard output (redirectable) +; and a file, e.g.: DIR | TEE C:\MYDIR\FILE.EXT | SORT +; +; The file can be CON, LPT1, etc. If it is CON, then +; keyboard Control-S pauses the display as usual. + +command equ 80h ; buffer for command tail +buflen equ 16384 ; buffer length, alter to taste + +cr equ 0dh ; ASCII carriage return +lf equ 0ah ; ASCII line feed +ff equ 0ch ; ASCII form feed +eof equ 01ah ; End-of-file marker +tab equ 09h ; ASCII tab code +blank equ 20h ; ASCII blank + + ; DOS 2.x pre-defined handles +stdin equ 0000 ; standard input file +stdout equ 0001 ; standard output file +stderr equ 0002 ; standard error file +stdaux equ 0003 ; standard auxilliary file +stdprn equ 0004 ; standard printer file + + +cseg segment para public 'CODE' + + assume cs:cseg,ds:cseg + + org 100H ; start .COM at 100H + +tee proc far + + mov cl,ds:command ; get length of command tail. + xor ch,ch + ; address of command string. + mov si,offset command+1 + mov di,offset command+1 + +tee1: ; squeeze out leading spaces. + mov al,byte ptr [si] + cmp al,blank + jbe tee2 + mov byte ptr [di],al + inc di + +tee2: inc si ; look through command tail + loop tee1 ; until it's exhausted. + mov byte ptr [di],0 ; make ASCIIZ string. + mov ah,3ch ; create output file. + mov cx,0 ; attribute=0. + mov dx,offset command+1 + int 21h + jc tee6 ; can't create file + mov handle,ax ; save token for file. + +tee3: mov ah,3fh ; read standard input. + mov bx,stdin + mov cx,buflen + lea dx,buffer + int 21h + jc tee4 ; jump, error. + mov nchar,ax ; save length of read. + cmp ax,0 ; nothing read in? + je tee4 ; end of file, exit. + mov ah,40h ; write to file... + mov bx,handle + mov cx,nchar + int 21h + jc tee7 ; jump, write failed. + cmp ax,nchar + jne tee7 ; jump, write failed. + mov ah,40h ; now write to standard output... + mov bx,stdout + int 21h + jc tee7 ; jump, write failed. + cmp ax,nchar + jne tee7 ; jump, write failed. + jmp tee3 ; read again until end of file. + +tee4: mov ah,3eh ; close output file. + mov bx,handle + int 21h + +tee5: mov ax,4c00h ; exit with return code=0. + int 21h + +tee6: mov dx,offset err1 ; print "Can't create file". + mov cx,err1len + mov ah,40h ; display error message and exit. + mov bx,stderr + int 21h + mov ax,4c01h ; exit with return code=1. + int 21h + +tee7: mov dx,offset err2 ; print "Disk is full". + mov cx,err2len + mov ah,40h ; display error message and exit. + mov bx,stderr + int 21h + mov ah,3eh ; close output file. + mov bx,handle + int 21h + mov ax,4c02h ; exit with return code=2. + int 21h + +tee endp + + +nchar dw 0 ; number of chars actually input. +handle dw 0 ; token for output file. + +err1 db cr,lf + db 'tee: Cannot create file' + db cr,lf +err1len equ (this byte)-(offset err1) + +err2 db cr,lf + db 'tee: Disk is full.' + db cr,lf +err2len equ (this byte)-(offset err2) + +buffer equ this byte ; data is read here from + ; standard input + +cseg ends + + end tee + \ No newline at end of file diff --git a/timlbl/TIMLBL.BAS b/timlbl/TIMLBL.BAS new file mode 100644 index 0000000..6c20a18 --- /dev/null +++ b/timlbl/TIMLBL.BAS @@ -0,0 +1,16 @@ +10 CLEAR 1000:CLS:WIDTH "lpt1:",132 +20 I1=3:I2=30:I3=60:B=4:XYZ=B-2 +30 A$="T.A. Daneliuk" +40 B$="4927 N. Rockwell" +50 C$="Chicago, IL 60625" +60 FOR X=1 TO 12 +70 LPRINT TAB(I1)A$TAB(I2)A$TAB(I3)A$ +80 LPRINT TAB(I1)B$TAB(I2)B$TAB(I3)B$ +90 LPRINT TAB(I1)C$TAB(I2)C$TAB(I3)C$ +100 WHILE ((XYZ > 0) AND (X <> 12)) +110 LPRINT:XYZ = XYZ-1 +120 WEND +130 XYZ=B +140 NEXT X +150 LPRINT CHR$(12); + \ No newline at end of file diff --git a/tod/TOD.C b/tod/TOD.C new file mode 100644 index 0000000..87df080 --- /dev/null +++ b/tod/TOD.C @@ -0,0 +1,15 @@ +#include +#include +#include +#include + + +main() +{ +struct timeb timebuffer; +char *timeline; + +ftime(&timebuffer); +timeline = ctime(&(timebuffer.time)); +printf("%.19s.%hu %s",timeline, timebuffer.millitm, &timeline[20]); +} diff --git a/tohex2/TOHEX2.C b/tohex2/TOHEX2.C new file mode 100644 index 0000000..d867e21 --- /dev/null +++ b/tohex2/TOHEX2.C @@ -0,0 +1,29 @@ +/* TOHEX2.C - This function is passed an integer value and an array + location which can hold at least a 2 element string. + The low 8 bits of the integer are converted to an + equivalent hexadecimal string which is stored in the + array at subscripts 0 and 1. + + Last modified: 08/31/86 - Copyright (c) 1985, 1986 By T.A. Daneliuk */ + + +tohex2(i,array) + +int i; +char array[]; + +{ + +int temp; +static char conv[]={"0123456789ABCDEF"}; + +temp=i; +temp=temp & 0x000f; /* Mask all but low nybble */ +array[1]=conv[temp]; /* Use to index into conversion table */ +temp=i; /* Now do high nybble */ +temp=temp >> 4; +temp=temp & 0x000f; +array[0]=conv[temp]; + +} + diff --git a/trbord/TRBORD.C b/trbord/TRBORD.C new file mode 100644 index 0000000..42ba371 --- /dev/null +++ b/trbord/TRBORD.C @@ -0,0 +1,22 @@ +/* TRBORD.C - Draw Standard Border With Prompts For T&R Communications Software Products + Last Modified: 06/11/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + + +#include +#include +#include +extern char copyright[]; +extern char version[]; + + +void trbord() + +{ + + border(0,0,VWIDTH,VHEIGHT-2,clrbord); + dsplylin(VHEIGHT-3,center(copyright),copyright,clrbmsg); + dsplylin(0,VWIDTH-22,version,clrbmsg); + +} diff --git a/verset/VERSET.C b/verset/VERSET.C new file mode 100644 index 0000000..157fddd --- /dev/null +++ b/verset/VERSET.C @@ -0,0 +1,19 @@ +/* VERSET.C - Set Version Number In Standard Message String + Last Modified: 06/11/86 + Copyright (C) 1986, T.A. Daneliuk +*/ + +void verset(x,y,z) + +char x,y,z; + +{ + +extern char version[]; +char *ptr=&version[11]; + +*ptr=x; +*(ptr+2)=y; +*(ptr+4)=z; + +} \ No newline at end of file diff --git a/wildcard/WILDCARD.C b/wildcard/WILDCARD.C new file mode 100644 index 0000000..3ff2f53 --- /dev/null +++ b/wildcard/WILDCARD.C @@ -0,0 +1,23 @@ +/* WILDCARD.C - Uses the filefind routines to return wildcard matches. + Last Modified: 02/19/87 + Copyright (C) 1987, By T.A. Daneliuk +*/ + +#include + + +int wildcard(fn,dta,first) +char *fn; +struct DataArea *dta; +int first; + +{ + +if (first) /* New wildcard spec */ + { + SetDta(dta); + return(FindFirst(fn,F_NORMAL)); + } +else + return(FindNext(F_NORMAL)); +}