home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
telecom
/
uucp_442
/
src
/
dnews
/
display.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-08
|
13KB
|
620 lines
/*
* DISPLAY.C
*
* This module handles all display windows.
*
*/
#include <exec/types.h>
#include "defs.h"
#include <intuition/intuition.h>
Prototype int getyn(char *);
Prototype void *OpenBrowseDisplay(char *, char *, short);
Prototype void SetBrowseTitle(void *, char *);
Prototype void CloseBrowseDisplay(void *);
Prototype void ChangeBrowseDisplay(void *, char *, char *);
Prototype int WaitBrowseEvent(void **, int *, int *);
Prototype void LoadDisplayConfig(void);
Prototype void SaveDisplayConfig(void);
Local void TabExpand(char *, short);
#define MAXCONF 3
typedef struct Window Window;
typedef struct NewWindow NewWindow;
typedef struct IntuiMessage IMsg;
typedef struct Display {
struct Display *Next;
Window *Win; /* associated window */
char *Name; /* name of file */
char *Title; /* window title */
FILE *Fi; /* file pointer */
long WMask; /* wait mask for window */
short Id; /* config id */
short FlagRefresh;
short ColStart;
long FirstNonHdrLine;/* first non-header line */
long TLineNo; /* line # for top line */
long TPos; /* position (top line) */
long BPos; /* position (bottom line) */
long XPos; /* end of file (or scan) */
long WLines; /* lines displayed in win */
long FLines; /* lines in file if known */
} Display;
typedef struct Config {
short TopEdge;
short LeftEdge;
short Width;
short Height;
} Config;
static long WMask; /* Window mask */
static Display *CachDisp; /* last display that had an event */
static Display *DispBase; /* list of displays */
static short FlagRefresh;
static Config ConfAry[MAXCONF];
Local int HandleEvent(Display *, int *, int *);
Local void RefreshBrowseDisplay(Display *);
Local void SaveWindowConfig(Display *);
Local long BackupFile(Display *, long, long);
Local void SetRefresh(Display *, int);
#ifndef LATTICE
extern void *OpenWindow();
extern void *GetMsg();
#endif
void *
OpenBrowseDisplay(fileName, title, id)
char *fileName;
char *title;
short id;
{
static NewWindow Nw = {
0, 0, 320, 200, -1, -1,
CLOSEWINDOW|NEWSIZE|MOUSEBUTTONS|VANILLAKEY|REFRESHWINDOW,
WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|
SIMPLE_REFRESH|ACTIVATE,
NULL, NULL, NULL, NULL, NULL,
32, 16, -1, -1, WBENCHSCREEN
};
Display *disp = malloc(sizeof(Display));
if (title == NULL)
title = fileName;
setmem(disp, sizeof(Display), 0);
if (id < 0 || id >= MAXCONF)
id = MAXCONF - 1;
{
Config *conf = ConfAry + id;
Nw.LeftEdge = conf->LeftEdge;
Nw.TopEdge = conf->TopEdge;
Nw.Width = conf->Width;
Nw.Height = conf->Height;
if (Nw.Width < 32) {
Nw.LeftEdge = 40;
Nw.Width = 600;
}
if (Nw.Height < 16)
Nw.Height = 150;
}
disp->Win = OpenWindow(&Nw);
if (disp->Win == NULL) {
Nw.LeftEdge = 0;
Nw.TopEdge = 0;
Nw.Width = 320;
Nw.Height = 100;
disp->Win = OpenWindow(&Nw);
}
if (disp->Win) {
disp->Name = strdup(fileName);
disp->Title= strdup(title);
disp->WMask = 1 << disp->Win->UserPort->mp_SigBit;
disp->Id = id;
SetAPen(disp->Win->RPort, 1);
SetWindowTitles(disp->Win, disp->Title, (char *)-1L);
disp->Next = DispBase;
DispBase = disp;
WMask |= disp->WMask;
SetRefresh(disp, 0);
if (disp->Fi = fopen(disp->Name, "r")) {
disp->FirstNonHdrLine = 0;
while (fgets(TmpBuf, sizeof(TmpBuf), disp->Fi) && TmpBuf[0] != '\n')
++disp->FirstNonHdrLine;
}
} else {
free(disp);
disp = NULL;
}
return((void *)disp);
}
void
SetBrowseTitle(_disp, title)
void *_disp;
char *title;
{
Display *disp = _disp;
char *old = disp->Title;
disp->Title = strdup(title);
SetWindowTitles(disp->Win, disp->Title, (char *)-1L);
free(old);
}
void
CloseBrowseDisplay(_disp)
void *_disp;
{
Display *disp = _disp;
Display *d;
if (disp == CachDisp)
CachDisp = NULL;
if (DispBase == disp) { /* unlink display */
DispBase = disp->Next;
} else {
for (d = DispBase; d; d = d->Next) {
if (d->Next == disp) {
d->Next = disp->Next;
break;
}
}
}
SetWindowTitles(disp->Win, NULL, NULL);
if (disp->Win) {
SaveWindowConfig(disp);
CloseWindow(disp->Win);
}
WMask &= ~disp->WMask;
free(disp->Title);
free(disp->Name);
if (disp->Fi)
fclose(disp->Fi);
free(disp);
}
/*
* Change file being displayed
*/
void
ChangeBrowseDisplay(_disp, fileName, title)
void *_disp;
char *fileName;
char *title;
{
Display *disp = _disp;
Window *win = disp->Win;
if (title == NULL)
title = fileName;
{
char *old = disp->Title;
disp->Title = strdup(title);
SetWindowTitles(disp->Win, disp->Title, (char *)-1L);
free(old);
}
free(disp->Name);
disp->Name = strdup(fileName);
if (disp->Fi) {
fclose(disp->Fi);
disp->Fi = NULL;
}
disp->TLineNo = 0;
disp->TPos = 0;
disp->XPos = 0;
disp->WLines = 0;
disp->FLines = 0;
SetRefresh(disp, 0);
}
/*
* Wait for an event. While waiting finish up scanning files for which we
* do not know the line number extent. Returns 0 if there are no windows
* left.
*/
int
WaitBrowseEvent(_pdisp, prow, pcol)
void **_pdisp;
int *prow;
int *pcol;
{
long mask;
Display **pdisp = _pdisp;
if (WMask == 0)
return(0);
for (;;) {
Display *disp;
if (FlagRefresh && (SetSignal(0,0) & WMask) == 0) {
for (disp = DispBase; disp; disp = disp->Next) {
if (disp->FlagRefresh)
RefreshBrowseDisplay(disp);
}
FlagRefresh = 0;
}
mask = Wait(WMask);
if ((disp = CachDisp) && (disp->WMask & mask)) {
mask &= ~disp->WMask;
if (HandleEvent(disp, prow, pcol))
goto event_handled;
}
if (mask) {
for (disp = DispBase; disp; disp = disp->Next) {
if (mask & disp->WMask) {
mask &= ~disp->WMask;
if (HandleEvent(disp, prow, pcol)) {
event_handled:
*pdisp = disp;
if (GetHead(&disp->Win->UserPort->mp_MsgList))
mask |= disp->WMask;
if (mask)
SetSignal(mask, mask);
return(1);
}
}
}
}
}
}
static int
HandleEvent(disp, prow, pcol)
Display *disp;
int *prow;
int *pcol;
{
int ret = 0;
IMsg *im;
Window *win = disp->Win;
while ((ret == 0) && (im = GetMsg(win->UserPort))) {
switch(im->Class) {
case CLOSEWINDOW:
*prow = -1;
*pcol = -1;
ret = 1;
break;
case VANILLAKEY:
switch(im->Code) {
case '2': /* page down */
case ' ':
if (disp->BPos != disp->XPos) {
disp->TPos = disp->BPos;
disp->TLineNo += disp->WLines;
SetRefresh(disp, 0);
}
break;
case '8': /* page up this article */
if (disp->TPos != 0) {
disp->TPos = BackupFile(disp, disp->TPos, disp->WLines);
disp->TLineNo -= disp->WLines;
SetRefresh(disp, 0);
}
break;
case '3':
if (disp->BPos != disp->XPos) {
disp->TPos = BackupFile(disp, disp->XPos, disp->WLines);
disp->TLineNo = disp->FLines - disp->WLines; /* XXX */
if (disp->TLineNo < 0)
disp->TLineNo = 0;
SetRefresh(disp, 0);
}
break;
case '9':
if (disp->TPos != 0) {
disp->TPos = 0;
disp->TLineNo = 0;
SetRefresh(disp, 0);
}
break;
case '6':
SetRefresh(disp, disp->ColStart + 40);
break;
case '4':
SetRefresh(disp, disp->ColStart - 40);
break;
default:
*prow = -1;
*pcol = im->Code;
ret = 1;
}
break;
case MOUSEBUTTONS:
if (im->Code == SELECTDOWN) {
*pcol = (im->MouseX - win->BorderLeft) >> 3;
*prow = ((im->MouseY - win->BorderTop) >> 3) + disp->TLineNo;
if (*prow >= 0)
ret = 1;
}
break;
case NEWSIZE:
SetRefresh(disp, 0);
break;
case REFRESHWINDOW:
BeginRefresh(win);
RefreshBrowseDisplay(disp);
EndRefresh(win, 1);
break;
default:
break;
}
ReplyMsg(im);
}
return(ret);
}
static void
RefreshBrowseDisplay(disp)
Display *disp;
{
long x, y;
int maxx;
int dispLines = 0;
int lineNo;
Window *win = disp->Win;
short b;
short isHdr;
short rvsMode;
disp->FlagRefresh = 0;
SetAPen(win->RPort, 0);
RectFill(win->RPort, win->BorderLeft, win->BorderTop, win->Width - win->BorderRight, win->Height - win->BorderBottom);
SetAPen(win->RPort, 1);
if (disp->Fi == NULL) {
disp->Fi = fopen(disp->Name, "r");
if (disp->Fi == NULL) /* can't refresh if can't open file */
return;
fseek(disp->Fi, 0L, 2);
disp->XPos = ftell(disp->Fi);
}
if (ftell(disp->Fi) != disp->TPos)
fseek(disp->Fi, disp->TPos, 0);
lineNo = disp->TLineNo - 1;
x = win->BorderLeft;
y = win->BorderTop + win->RPort->TxBaseline;
maxx = (win->Width - win->BorderLeft - win->BorderRight) / win->RPort->TxWidth;
b = 0;
TmpBuf[0] = 0;
while (y < win->Height - win->BorderBottom - 2) {
int len;
if (TmpBuf[b] == 0) {
if (fgets(TmpBuf, sizeof(TmpBuf), disp->Fi) == NULL)
break;
rvsMode = 0;
if (++lineNo < disp->FirstNonHdrLine) {
isHdr = 1;
if (strncmp(TmpBuf, "Subject:", 8) == 0)
rvsMode = 1;
} else {
isHdr = 0;
}
TabExpand(TmpBuf, sizeof(TmpBuf));
b = 0;
}
len = strlen(TmpBuf + b) - disp->ColStart;
if (len > maxx)
len = maxx;
if (len > 0) {
if (rvsMode) {
SetAPen(win->RPort, 0);
SetBPen(win->RPort, 1);
}
Move(win->RPort, x, y);
Text(win->RPort, TmpBuf + b + disp->ColStart, len);
if (rvsMode) {
SetAPen(win->RPort, 1);
SetBPen(win->RPort, 0);
}
}
++dispLines;
y += win->RPort->TxHeight;
if (isHdr || disp->ColStart || len <= 0)
b = strlen(TmpBuf);
else
b += len;
}
disp->BPos = ftell(disp->Fi);
disp->WLines = dispLines;
}
void
LoadDisplayConfig()
{
FILE *fi;
if (fi = fopen("s:dnews.config", "r")) {
fread(ConfAry, 1, sizeof(ConfAry), fi);
fclose(fi);
}
}
void
SaveDisplayConfig()
{
FILE *fi;
if (fi = fopen("s:dnews.config", "w")) {
fwrite(ConfAry, 1, sizeof(ConfAry), fi);
fclose(fi);
}
}
static void
SaveWindowConfig(disp)
Display *disp;
{
Config *conf = ConfAry + disp->Id;
Window *win = disp->Win;
conf->TopEdge = win->TopEdge;
conf->LeftEdge = win->LeftEdge;
conf->Width = win->Width;
conf->Height = win->Height;
}
/*
* Count lines backwards
*/
static long
BackupFile(disp, pos, rlines)
Display *disp;
long pos;
long rlines;
{
long n;
long i;
if (disp->Fi == NULL) {
disp->Fi = fopen(disp->Name, "r");
if (disp->Fi == NULL)
return(0);
}
++rlines; /* think of the case where rlines is 1 in the below code */
while (rlines && pos) {
n = sizeof(TmpBuf);
if (pos < n)
n = pos;
fseek(disp->Fi, pos - n, 0);
fread(TmpBuf, 1, n, disp->Fi);
for (i = n - 1; i >= 0; --i) {
if (TmpBuf[i] == '\n') {
if (--rlines == 0)
break;
}
}
++i;
pos = pos - n + i;
}
return(pos);
}
/*
* Flag that the display should be refreshed without doing so immediately.
* This allows the user to skip around articles without having to wait
* for the display to catch up.
*/
static void
SetRefresh(disp, lrc)
Display *disp;
int lrc;
{
FlagRefresh = 1;
if (lrc < 0)
lrc = 0;
if (lrc > TMPBSIZE - 1)
lrc = TMPBSIZE - 1;
disp->FlagRefresh = 1;
disp->ColStart = lrc;
}
/*
* YES OR NO
*/
typedef struct IntuiText ITEXT;
typedef unsigned char ubyte;
int
getyn(text)
char *text;
{
int result;
ITEXT *body, *pos, *neg;
if (DispBase == NULL)
return(0);
body = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
pos = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
neg = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
setmem(body, sizeof(ITEXT), 0);
setmem(pos , sizeof(ITEXT), 0);
setmem(neg , sizeof(ITEXT), 0);
body->BackPen = pos->BackPen = neg->BackPen = 1;
body->DrawMode= pos->DrawMode= neg->DrawMode= AUTODRAWMODE;
body->LeftEdge = 10;
body->TopEdge = 12;
body->IText = (ubyte *)text;
pos->LeftEdge = AUTOLEFTEDGE;
pos->TopEdge = AUTOTOPEDGE;
pos->IText = (ubyte *)"OK";
neg->LeftEdge = AUTOLEFTEDGE;
neg->TopEdge = AUTOTOPEDGE;
neg->IText = (ubyte *)"CANCEL";
result = AutoRequest(DispBase->Win, body, pos, neg, 0, 0, 320, 58);
FreeMem(body, sizeof(ITEXT));
FreeMem(pos , sizeof(ITEXT));
FreeMem(neg , sizeof(ITEXT));
return(result);
}
void
TabExpand(buf, max)
char *buf;
short max;
{
short i;
short len = strlen(buf);
char *ptr;
max -= 9;
for (i = 0, ptr = buf; *ptr; ++ptr, ++i) {
if (*ptr == '\n') {
*ptr = 0;
break;
}
if (*ptr == 9 && len < max) {
int n = ~i & 7;
movmem(ptr, ptr + n, len - i + 1);
setmem(ptr, n + 1, ' ');
len += n;
}
}
}