home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
375.lha
/
ARPTools_v1.0
/
src
/
Mr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-02
|
6KB
|
327 lines
/*
Mr - Pager for piped files.
Original effort by Fabio Rossetti.
(c) 1989 by Fabio Rossetti
To compile under Lattice C v5.0x use:
lc -O -v s
blink lib:cres.o s.o to s lib lib:a.lib lib:lc.lib sd nd
*/
#include <exec/types.h>
#include <exec/ports.h>
#include <exec/io.h>
#include <exec/memory.h>
#include <exec/libraries.h>
#include <devices/console.h>
#include <devices/conunit.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/arpbase.h>
#include <arpfunctions.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include <intuition/intuitionbase.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#define BFSIZE 1024
#define LINSIZE 512
#define ENDFILE 0
#define FORMFEED -1
#define LINEOK 1
/* command line arguments */
/* */
/* global */
/* */
struct ArpBase *ArpBase;
struct IntuitionBase *IntuitionBase;
struct Window *CliWin; /* poUSHORTer to console window */
struct Process *Pr;
USHORT dsplin,x,y,xf,yf,count,bp=0;
BPTR stdi;
TEXT *Buf,*Lin;
TEXT *Morpos="\033[0;0H\033[000;2H\033[7m\033[3m ";
#define CYPOS 8
#define CYOFF 48
struct Window *w;
/* this is exec stuff for GetWin, to be kept global for Cleanup() */
struct MsgPort iorp = {
{0, 0, NT_MSGPORT, 0, 0}, 0,
-1, /* initialize signal to -1 */
0,
/* start with empty list */
{&iorp.mp_MsgList.lh_Tail, 0, &iorp.mp_MsgList.lh_Head, 0, 0}
};
struct IOStdReq ior = {
{{0, 0, 0, 0, 0}, &iorp, 0},
0 /* device is zero */
};
VOID MemCleanup()
{
}
/* general shutdown routine*/
VOID Cleanup(code,retcode,msg)
LONG code;
LONG retcode;
STRPTR msg;
{
if (ior.io_Device != 0) {
if (iorp.mp_SigBit != -1) {
FreeSignal(iorp.mp_SigBit);
}
CloseDevice(&ior);
}
CloseLibrary((struct Library*)ArpBase);
if (msg) Puts(msg);
Pr->pr_Result2=retcode;
exit(code);
}
/* bulletproofly obtain a pointer to the CLI window sending a ACTION_DISK_INFO
packet to the console process and looking into InfoData */
struct Window *GetWin(mode)
USHORT mode;
#define RAW -1
#define CON 0
#define POINTER 1
{
struct MsgPort *con;
struct StandardPacket *packet=NULL;
struct InfoData *id=NULL;
/* open the console device */
if ((OpenDevice("console.device", -1, &ior, 0)) != 0) {
Cleanup(RETURN_FAIL,ERROR_DEVICE_NOT_MOUNTED,NULL);
}
/* set up the message port in the I/O request */
if ((iorp.mp_SigBit = AllocSignal(-1)) < 0) {
Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,"No mem");
}
iorp.mp_SigTask = (struct Task*)Pr;
/* try to find console associated with calling process */
/* if started from CLI, than is */
if ((iorp.mp_SigTask->tc_Node.ln_Type == NT_PROCESS)) {
con = (struct MsgPort *)
((struct Process *) iorp.mp_SigTask) -> pr_ConsoleTask;
if (con != 0) {
if ((packet = (struct StandardPacket *)
ArpAlloc(sizeof(*packet)))) {
/* this is the console handlers packet port */
packet->sp_Msg.mn_Node.ln_Name = &(packet->sp_Pkt);
packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
packet->sp_Pkt.dp_Port = &iorp;
if (mode == POINTER) {
if (!(id = (struct id *) ArpAlloc(sizeof(*id))))
return((struct Window *)-1);
packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
packet->sp_Pkt.dp_Arg1 = ((ULONG) id) >> 2;
}
else {
packet->sp_Pkt.dp_Type = ACTION_SCREEN_MODE;
packet->sp_Pkt.dp_Arg1 = mode;
}
PutMsg(con, packet);
WaitPort(&iorp);
/* Pointer to console window, all we need..*/
if (mode == POINTER)
return( (struct Window*)(id->id_VolumeNode));
else return(0);
}
}
/* error */
return((struct Window *)-1);
}
}
VOID Clear(fl)
BPTR fl;
{
(VOID)Write(fl,"\033[0;0H\033[J",9);
dsplin = 0;
x = (w->Width-24) / xf;
y = (w->Height-16) / yf;
}
TEXT Banner(fl,ban)
BPTR fl;
STRPTR ban;
{
TEXT ch;
USHORT j = y+1;
Morpos[CYPOS] = (TEXT)((j / 100) + CYOFF);
Morpos[CYPOS+1] = (TEXT)(((j - ((j / 100)*100)) / 10) + CYOFF);
Morpos[CYPOS+2] =
(TEXT)((j - ((j / 100)*100) - ((j - ((j / 100)*100)) / 10)*10) + CYOFF);
(VOID)Write(fl,Morpos,strlen(Morpos));
(VOID)Write(fl,ban,strlen(ban));
/* hide crsr */
(VOID)Write(fl," \033[0m\033[K\033[43m \010",16);
(VOID)Read(fl,&ch,1);
(VOID)Write(fl,"\033[0m",4);
return(ch);
}
Displine(fl)
BPTR fl;
{
REGISTER TEXT chr;
REGISTER ULONG ln = 0,actlin=0;
for (;;) {
if(!bp) if (!(count = Read(stdi,Buf,BFSIZE))) {
return(ENDFILE);
}
chr = *(Buf + bp++);
*(Lin + ln++) = chr;
actlin++;
switch (chr) {
case '\n':
Write(fl,Lin,ln);
dsplin++;
if (bp >= count) bp = 0;
return(LINEOK);
break;
case '\t':
actlin+=8;
break;
case '\010': /* backspace */
actlin--;
break;
case '\014':
Write(fl,Lin,ln-1);
Write(fl,"\n^L",3);
if (bp >= count) bp = 0;
return(FORMFEED);
break;
}
if (actlin >= x) {
Write(fl,Lin,ln);
dsplin++;
if (bp >= count) bp = 0;
return (LINEOK);
}
if (bp >= count) bp = 0;
}
}
VOID Bye(fl)
BPTR fl;
{
Write(fl,"\015\033[K",4);
(VOID)GetWin(CON);
Cleanup(RETURN_OK,NULL,NULL);
}
/* _main used instead of main to slim code */
VOID _main(Line)
STRPTR Line;
{
BPTR fil;
ULONG st;
TEXT c;
Pr = (struct Process *) FindTask(NULL);
if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion)))
Cleanup(RETURN_FAIL,ERROR_INVALID_RESIDENT_LIBRARY,NULL);
if (!(Buf = ArpAllocMem(BFSIZE,MEMF_CLEAR)) ||
!(Lin = ArpAllocMem(LINSIZE,MEMF_CLEAR)))
Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,"No mem");
stdi = Input();
if (IsInteractive(stdi)) Cleanup(RETURN_ERROR,NULL,"Use a pipe");
w = GetWin(POINTER);
xf = w->RPort->Font->tf_XSize;
yf = w->RPort->Font->tf_YSize;
(VOID)GetWin(RAW);
fil = Open("*",MODE_OLDFILE);
for (;;) {
Clear(fil);
while (dsplin <= (y-1)) {
if ((st = Displine(fil)) != LINEOK) break;
}
if (st == ENDFILE) {
Banner(fil,"--End of file--");
break;
}
else {
/* Goodbye Mr Wirth :-) */
more:
switch(c = Banner(fil,"--More--")) {
case ' ':
break;
case 'q':
Bye(fil);
break;
case '\003':
Bye(fil);
break;
case '\015':
Write(fil,"\015\033[K",4);
Displine(fil);
goto more;
break;
default:
Banner(fil,"--???--");
}
}
}
Bye(fil);
}