Category : C Source Code
Archive   : TCXLV103.ZIP
Filename : V.C

 
Output of file : V.C contained in archive : TCXLV103.ZIP
/*
** v.c -- a simple file browser using TCXL 5.5
** version 1.03
** copyright (c) 1990 David A. Seidel [71511,2217]
** for Turbo C/C++, compact model
** compile with: tcc -k- -mc -G -O -Z v.c tcxltcc.lib
*/

#include
#include
#include
#include
#include
#include
#include

#include
#include
#include
#include
#include
#include
#include
#include


/* manifest constants */
#define FBUF 8191
#define BUF 512
#define SRCH_LEN 32
#define DEFTAB 8

/* help categories */
#define H_NONE 0
#define H_FNAME 1
#define H_FLIST 2
#define H_VIEW 3
#define H_TAB 4
#define H_SRCHCASE 5
#define H_SRCHNOCASE 6
#define H_GOTO 7


/* user types */
TYP struct _LnLnk /* linked list element */
{
ChrP txt; /* ptr to a line of text */
WrdT lnum; /* line number of record */
struct _LnLnk *prev, *next; /* previous/next line */
} LnItmT;

TYP LnItmT *LnItmP;


/* globals */
VcelP saveScrn = NULL; /* ptr to saved DOS screen */
VposT saveCurs; /* starting cursor position */
LnItmT lnBuf = { NULL, 0, NULL, NULL }; /* root of line list */
LnItmP lnTop, lnBot, /* top and bottom lines */
lnSrch = NULL; /* line of last search */
FILE *fp; /* file pointer */
WrdT lnCnt, lnCur; /* total, current lines */
ChrT fName[80], buf[BUF]; /* filename, scratch buffer */
IntT pgDep, pgWid, pgCtr, /* window depth, height, ctr*/
lftCol, /* current left column */
tabWid = DEFTAB; /* tab width for display */
FlgT hexDsp; /* flag hex display */


/* constants */
ChrP errorText[] = /* global error message table */
{
NULL, /* errnum = 0, no error */
NULL, /* errnum = 1, windowing error */
"\nOut of memory!",
"\nError opening file!",
"\nUnknown command-line option!",
"\nUsage:\tv [-tn] [filename]"
"\nWhere is the tab width for the display"
};


/* local prototypes */
ChrP CTYP ParseCmdLine(IntT, ChrI);
VOID CTYP SetUp(NOARG);
VOID CTYP GetFileName(NOARG);
VOID CTYP ValidFName (VOID);
VOID CTYP ReadFile(ChrP);
VOID CTYP ShowFile(NOARG);
VOID CTYP GetTabWid(NOARG);
VOID CTYP GotoLine (NOARG);
VOID CTYP Search (FlgT);
WrdT CTYP DoSearch(ChrP, FlgT);
VOID CTYP ShowFound (WrdT);
VOID CTYP ShowNotFound (NOARG);
VOID CTYP Refresh(WrdT);
VOID CTYP ResetTabs(NOARG);
VOID CTYP StatusLine(NOARG);
FlgT CTYP AddLine(ChrP);
LnItmP GetLine (WrdT);
ChrP CTYP BuildLine (ChrP);
VOID CTYP AddShadow(NOARG);
VOID CTYP CleanUp(NOARG);
VOID CTYP NormalExit(NOARG);
VOID CTYP ErrorExit(IntT);


/* program entry point */
IntT CDC main(IntT argC, ChrP argV[])
{
SetUp();
ReadFile(ParseCmdLine(argC, argV));
ShowFile();
NormalExit();
return 0;
}


/* initialize video system, set up screen, etc. */
VOID CTYP SetUp(NOARG)
{
TcxlInit();
KextOff();
VcurGet(saveCurs);
if ((saveScrn = Vsave()) == NULL)
ErrorExit(2);
Vclear(WHITE|_BLUE);
VcurHid(0);
if (!Wopen(1, 0, VidDep - 2, VidWid - 1, BOX_HOR,
WHITE|_BLUE, WHITE|_BLUE))
ErrorExit(1);
KbndSet(Key_A_X, NormalExit, 0);
pgDep = VidDep - 4;
pgWid = VidWid - 2;
pgCtr = pgDep / 2;
HlpDef(searchpath("V.HLP"), Key_F1, YELLOW|_RED, LGREEN|_RED,
WHITE|_RED, RED|_LGREY, AddShadow);
}


/* process cmdline options, return filename to view */
ChrP CTYP ParseCmdLine(IntT ac, ChrP av[])
{
REG IntT i;
REG ChrP p;

for (i = 1; i < ac; i++)
{
p = av[i];
if (*p == '-' || *p == '/')
{
switch (tolower(*++p))
{
case 't':
if (*++p)
tabWid = cvtci(p);
break;
case '?':
ErrorExit(5);
default:
ErrorExit(4);
}
}
else if (*p == '?')
ErrorExit(5);
else
break;
}
return av[i];
}


/* get a filename from user */
VOID CTYP GetFileName(NOARG)
{
if (!WpopUp(CNT_CNT, 0, 0, 2, 44, BOX_SNG, LCYAN|_RED, LCYAN|_RED))
ErrorExit(1);
HlpSet(H_FNAME);
Wshadow(DGREY|_BLACK);
VcurHid(1);
KwGetFmt(fName, "' Filename: 'WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
VcurHid(0);
Wclose();
ValidFName();
}


VOID CTYP ValidFName (VOID)
{
ChrP fn;

if (*fName == EOS || strpbrk(fName, "?*") != NULL)
{
HlpSet(H_FLIST);
fn = SelFile(VidDep/4 - 1, VidWid/4 - 1,
VidDep - VidDep/4 - 1, VidWid - VidWid/4 - 1,
BOX_SNG, LCYAN|_RED, LGREY|_RED, RED|_LGREY, 1,
*fName ? fName : "*.*", AddShadow);
if (fn == NULL)
GetFileName();
strcpy(fName, fn);
}
}


/* read file into memory, display file statistics */
VOID CTYP ReadFile(ChrP fn)
{
REG IntT len;
LCL ChrT fBuf[FBUF];
IntT sz;
LngT chCnt = 0;
struct ftime ft;

/* see if we have a filename */
if (fn == NULL)
GetFileName();
else
strcpy(fName, fn);

/* try to open the file */
if ((fp = fopen(fName, "rb")) == NULL)
ErrorExit(3);
setvbuf(fp, fBuf, _IOFBF, FBUF);

/* get file statistics */
getftime(fileno(fp), &ft);
sprintf(buf, " <%s> %ld bytes %02u-%02u-%02u %02u:%02u ",
fName, filelength(fileno(fp)),
ft.ft_month, ft.ft_day, ft.ft_year + 80,
ft.ft_hour, ft.ft_min);
Vprints(0, 0, YELLOW|_BLUE, buf);
sz = strlen(buf);
Vprints(VidDep - 1, 0, YELLOW|_BLUE|_BLINK, " Reading...");
WsetTab(tabWid);

/* read in the file */
while (!feof(fp))
{
if (fgets(buf, BUF, fp) != NULL)
{
len = strlen(buf);
if (buf[len - 1] == LF) /* eliminate CRs or CR/LFs */
{
if (buf[len - 2] == CR)
buf[len - 2] = EOS;
else
buf[len - 1] = EOS;
}
if (!AddLine(buf))
break;
if (lnCnt == pgDep) /* show first screen */
Refresh(1);
chCnt += len;
}
}
fclose(fp);

/* report amount actually read */
sprintf(buf, "(%ld bytes read)", chCnt);
Vprints(0, sz, YELLOW|_BLUE, buf);
Vprints(VidDep - 1, pgWid - 6, YELLOW|_BLUE, "F1=Help");
}


/* display the file, allow user to move around */
VOID CTYP ShowFile(NOARG)
{
REG KeyT k;

HlpSet(H_VIEW);
lftCol = 0;
if (lnCnt < pgDep)
Refresh(1);

/* respond to user */
while (1)
{
lnCur = lnTop->lnum;
StatusLine();
k = KeyGetc();
switch (k)
{
case Key_Esc: /* [Esc] -> quit */
return;
case Key_Home: /* [Home] -> go to top */
if (lnTop->lnum > 1)
Refresh(1);
break;
case Key_End: /* [End] -> go to last page */
if (lnBot->lnum < lnCnt)
Refresh(lnCnt - pgDep + 1);
break;
case Key_Dwn: /* [Dwn] -> down one line */
if (lnBot->next != NULL)
{
WlinIns(VidDep - 5, DIR_UP);
lnTop = lnTop->next;
lnBot = lnBot->next;
if (*lnBot->txt)
Wprts(VidDep - 5, 0, WHITE|_BLUE,
BuildLine(lnBot->txt));
}
break;
case Key_Up: /* [Up] -> up one line */
if (lnTop->prev != NULL)
{
WlinIns(0, DIR_DWN);
lnTop = lnTop->prev;
lnBot = lnBot->prev;
if (*lnTop->txt)
Wprts(0, 0, WHITE|_BLUE, BuildLine(lnTop->txt));
}
break;
case Key_PgDn: /* [PgDn] -> down a screen */
if (lnBot->next != NULL)
{
IntT delta = lnCnt - lnBot->lnum;
if (delta >= pgDep)
Refresh(lnBot->lnum + 1);
else
Refresh(lnTop->lnum + delta);
}
break;
case Key_PgUp: /* [PgUp] -> up a screen */
if (lnTop->prev != NULL)
{
if (lnTop->lnum >= pgDep)
Refresh(lnTop->lnum - pgDep);
else
Refresh(1);
}
break;
case Key_Rgt: /* [Rgt] -> scroll right */
lftCol++;
Refresh(lnCur);
break;
case Key_Lft: /* [Lft] -> scroll left */
if (lftCol)
{
lftCol--;
Refresh(lnCur);
}
break;
case Key_S_Lft:
if (lftCol)
{
lftCol = 0;
Refresh(lnCur);
}
break;
case Key_Tab: /* [Tab] -> get new tabs */
GetTabWid();
break;
case Key_F3:
Search(YES);
break;
case Key_F4:
Search(NO);
break;
case Key_F2:
if (lnSrch != NULL)
{
WrdT n;
n = DoSearch(NULL, 0);
if (n)
ShowFound(n);
else
ShowNotFound();
}
break;
case Key_F5:
GotoLine();
break;
/*
case Key_A_H:
hexDsp = hexDsp ? OFF : ON;
Refresh(lnCur);
break;
*/
default:
break;
}
}
}


/* fill the display window, starting at the given line */
VOID CTYP Refresh(WrdT start)
{
REG IntT i;
REG LnItmP lp;
LnItmP top;

/* seek to record for starting line */
lp = GetLine(start);

/* fill the window */
top = lp;
Wclear();
for (i = 0; i < pgDep && lp != NULL; i++, lp = lp->next)
{
if (*lp->txt)
Wprts(i, 0, WHITE|_BLUE, BuildLine(lp->txt));
lnBot = lp;
}
lnTop = top;
}


/* display the current line and top line number */
VOID CTYP StatusLine(NOARG)
{
sprintf(buf, " Line: %u/%u Col: %d", lnCur, lnCnt, lftCol + 1);
Vgotoxy(VidDep - 1, 0);
VputSpa(VidWid - 8);
Vprints(VidDep - 1, 0, YELLOW|_BLUE, buf);
}


/* redisplay with requested line on top */
VOID CTYP GotoLine (NOARG)
{
WrdT n;

if (!WpopUp(CNT_CNT, 0, 0, 2, 19, BOX_SNG,
LCYAN|_RED, LCYAN|_RED))
ErrorExit(1);
HlpSet(H_GOTO);
AddShadow();
VcurHid(1);
KwGetFmt(buf, "' Go to line: '######");
VcurHid(0);
Wclose();
n = cvtci(buf);
if (n && n <= lnCnt)
Refresh(n);
}


/* get new tab width from user and implement */
VOID CTYP GetTabWid(NOARG)
{
ChrT tmp[3];

if (!WpopUp(CNT_CNT, 0, 0, 2, 16, BOX_SNG, LCYAN|_RED, LCYAN|_RED))
ErrorExit(1);
HlpSet(H_TAB);
AddShadow();
VcurHid(1);
KwGetFmt(tmp, "' Tab width: '##");
if (TcxlErr != W_ESCPRESS && *tmp)
tabWid = cvtci(tmp);
VcurHid(0);
Wclose();
ResetTabs();
}


/* set new tab width and redisplay */
VOID CTYP ResetTabs(NOARG)
{
WsetTab(tabWid);
Refresh(lnTop->lnum);
}


/* get search request */
VOID CTYP Search (FlgT mode)
{
ChrT srch[SRCH_LEN];
WrdT n;

if (!WpopUp(CNT_CNT, 0, 0, 2, SRCH_LEN + 9, BOX_SNG,
LCYAN|_RED, LCYAN|_RED))
ErrorExit(1);
HlpSet(mode ? H_SRCHCASE : H_SRCHNOCASE);
AddShadow();
VcurHid(1);
srch[0] = EOS;
KwGetFmt(srch, "' Search: '********************************");
VcurHid(0);
Wclose();
if (srch[0])
{
n = DoSearch(srch, mode);
if (n)
ShowFound(n);
else
ShowNotFound();
}
}


/* perform search */
WrdT CTYP DoSearch(ChrP s, FlgT mode)
{
LCL ChrT srch[80];
LCL FlgT csens = YES;
REG LnItmP lp;
REG ChrP sp;

if (s != NULL)
{
strcpy(srch, s);
csens = mode;
}
if (!csens)
strupr(srch);
lp = lnSrch != NULL ? lnSrch->next : lnTop->next;
for ( ; lp != NULL; lp = lp->next)
{
if (*lp->txt)
{
if (!csens)
{
strcpy(buf, lp->txt);
strupr(buf);
sp = buf;
}
else
sp = lp->txt;
if (strstr(sp, srch) != NULL)
break;
}
}
if (lp != NULL)
return lp->lnum;
return 0;
}


/* display the result of a succesful search */
VOID CTYP ShowFound (WrdT n)
{
LnItmP lp;
IntT top;
ChrP sp;

top = (n >= pgCtr) ? n - pgCtr : n;
Refresh(top);
lnSrch = lp = GetLine(n);
Wgotoxy((top == n) ? 0 : pgCtr, 0);
for (sp = BuildLine(lp->txt); isspace(*sp); sp++)
Wputc(*sp);
Wputf("\033A%c%s\033A%c",
BLACK|_LGREY, sp, WHITE|_BLUE);
}


/* notify user of an unsuccesful search */
VOID CTYP ShowNotFound (NOARG)
{
lnSrch = NULL;
Refresh(lnCur);
if (!WpopUp(CNT_CNT, 0, 0, 2, 13, BOX_SNG,
LCYAN|_RED, YELLOW|_RED|_BLINK))
ErrorExit(1);
Wputs(" Not found!");
_Delay(20);
Wclose();
}


/* add a line of text to the linked list */
FlgT CTYP AddLine(ChrP s)
{
REG LnItmP lp = &lnBuf,
prev = NULL;

if (lnCnt) /* if not the first line, go to next available item */
{
while (lp->next != NULL)
{
prev = lp;
lp = lp->next;
}
}

if (lp->txt != NULL) /* if second item, force next item */
{
prev = lp;
lp = lp->next;
}

if (prev != NULL) /* if not root, allocate new item and link it */
{
if ((lp = (LnItmP) calloc(1, SIZ(LnItmT))) == NULL)
return NO;
prev->next = lp;
}

if ((lp->txt = strdup(s)) == NULL) /* allocate and store text */
return NO;
lp->lnum = ++lnCnt; /* store line number */
lp->next = NULL;
if (prev != NULL)
lp->prev = prev;
return YES;
}


/* given a line number, return a pointer to the line's record */
LnItmP GetLine (WrdT n)
{
REG LnItmP lp;

for (lp = &lnBuf; lp != NULL; lp = lp->next)
if (lp->lnum == n)
return lp;
return NULL;
}


/* copy a string into the scratch buffer with tab expansion,
return pointer to display column */
ChrP CTYP BuildLine (ChrP s)
{
REG IntT n;
REG ChrP sp;
IntT pad;

buf[lftCol] = EOS;
for (sp = s, n = 0; *sp; sp++)
{
if (*sp == HT)
{
pad = TabNxt(n, tabWid) - n;
memset(&buf[n], ' ', pad);
n += pad;
}
else
buf[n++] = *sp;
}
buf[n] = EOS;
sp = &buf[lftCol];
*(sp + pgWid) = EOS;
return sp;
}


/* draw a shadow for current window */
VOID CTYP AddShadow(NOARG)
{
Wshadow(LGREY|_BLACK);
}


/* restore the original screen */
VOID CTYP CleanUp(NOARG)
{
if (saveScrn != NULL)
{
Vrestore(saveScrn);
VcurPut(saveCurs);
VcurHid(1);
}
}


/* exit with no errors */
VOID CTYP NormalExit(NOARG)
{
CleanUp();
exit(0);
}


/* exit with error message */
VOID CTYP ErrorExit(IntT e)
{
if (e)
{
CleanUp();
if (e == 1)
Werror();
else
puts(errorText[e]);
exit(e);
}
}


/* end of v.c */


  3 Responses to “Category : C Source Code
Archive   : TCXLV103.ZIP
Filename : V.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/