/* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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); }