home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff284.lzh / ARPTools / src / Mr.c < prev    next >
C/C++ Source or Header  |  1989-11-27  |  6KB  |  327 lines

  1. /*
  2.           Mr - Pager for piped files.
  3.  
  4.           Original effort by Fabio Rossetti.
  5.  
  6.           (c) 1989 by Fabio Rossetti
  7.  
  8.           To compile under Lattice C v5.0x use:
  9.  
  10.         lc -O -v s
  11.         blink lib:cres.o s.o to s lib lib:a.lib lib:lc.lib sd nd
  12. */
  13.  
  14. #include <exec/types.h>
  15. #include <exec/ports.h>
  16. #include <exec/io.h>
  17. #include <exec/memory.h>
  18. #include <exec/libraries.h>
  19.  
  20. #include <devices/console.h>
  21. #include <devices/conunit.h>
  22.  
  23. #include <libraries/dos.h>
  24. #include <libraries/dosextens.h>
  25. #include <libraries/arpbase.h>
  26.  
  27.  
  28. #include <arpfunctions.h>
  29. #include <proto/exec.h>
  30. #include <proto/intuition.h>
  31. #include <proto/dos.h>
  32.  
  33. #include <intuition/intuitionbase.h>
  34. #include <intuition/intuition.h>
  35.  
  36. #include <graphics/text.h>
  37.  
  38. #define BFSIZE 1024
  39. #define LINSIZE 512
  40.  
  41. #define ENDFILE 0
  42. #define FORMFEED -1
  43. #define LINEOK 1
  44.  
  45. /* command line arguments */
  46.  
  47. /*        */
  48. /* global */
  49. /*        */
  50.  
  51. struct ArpBase *ArpBase;
  52. struct IntuitionBase *IntuitionBase;
  53. struct Window *CliWin;     /* poUSHORTer to console window */
  54. struct Process *Pr;
  55.  
  56.  
  57. USHORT dsplin,x,y,xf,yf,count,bp=0;
  58. BPTR stdi;
  59. TEXT *Buf,*Lin;
  60. TEXT *Morpos="\033[0;0H\033[000;2H\033[7m\033[3m  ";
  61. #define CYPOS 8
  62. #define CYOFF 48
  63. struct Window *w;
  64.  
  65. /* this is exec stuff for GetWin, to be kept global for Cleanup() */
  66. struct MsgPort iorp = {
  67.     {0, 0, NT_MSGPORT, 0, 0}, 0,
  68.     -1,                /* initialize signal to -1 */
  69.     0,
  70.                 /* start with empty list */
  71.     {&iorp.mp_MsgList.lh_Tail, 0, &iorp.mp_MsgList.lh_Head, 0, 0}
  72. };
  73. struct IOStdReq ior = {
  74.     {{0, 0, 0, 0, 0}, &iorp, 0},
  75.     0                /* device is zero */
  76. };
  77.  
  78. VOID MemCleanup()
  79. {
  80. }
  81.  
  82. /* general shutdown routine*/
  83. VOID Cleanup(code,retcode,msg)
  84. LONG code;
  85. LONG retcode;
  86. STRPTR msg;
  87. {
  88.     if (ior.io_Device != 0) {
  89.         if (iorp.mp_SigBit != -1) {
  90.         FreeSignal(iorp.mp_SigBit);
  91.         }
  92.         CloseDevice(&ior);
  93.     }
  94.  
  95.     CloseLibrary((struct Library*)ArpBase);
  96.  
  97.     if (msg) Puts(msg);
  98.  
  99.     Pr->pr_Result2=retcode;
  100.  
  101.     exit(code);
  102. }
  103. /* bulletproofly obtain a pointer to the CLI window sending a ACTION_DISK_INFO
  104.    packet to the console process and looking into InfoData */
  105. struct Window *GetWin(mode)
  106. USHORT mode;
  107. #define RAW -1
  108. #define CON 0
  109. #define POINTER 1
  110.  
  111. {
  112.     struct MsgPort *con;
  113.     struct StandardPacket *packet=NULL;
  114.     struct InfoData *id=NULL;
  115.  
  116.     /* open the console device */
  117.     if ((OpenDevice("console.device", -1, &ior, 0)) != 0) {
  118.     Cleanup(RETURN_FAIL,ERROR_DEVICE_NOT_MOUNTED,NULL);
  119.     }
  120.  
  121.     /* set up the message port in the I/O request */
  122.     if ((iorp.mp_SigBit = AllocSignal(-1)) < 0) {
  123.     Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,"No mem");
  124.     }
  125.     iorp.mp_SigTask = (struct Task*)Pr;
  126.  
  127.     /* try to find console associated with calling process */
  128.     /* if started from CLI, than is  */
  129.     if ((iorp.mp_SigTask->tc_Node.ln_Type == NT_PROCESS)) {
  130.     con = (struct MsgPort *)
  131.         ((struct Process *) iorp.mp_SigTask) -> pr_ConsoleTask;
  132.     if (con != 0) {
  133.         if ((packet = (struct StandardPacket *)
  134.             ArpAlloc(sizeof(*packet)))) {
  135.  
  136.             /* this is the console handlers packet port */
  137.             packet->sp_Msg.mn_Node.ln_Name = &(packet->sp_Pkt);
  138.             packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  139.             packet->sp_Pkt.dp_Port = &iorp;
  140.             if (mode == POINTER) {
  141.             if (!(id = (struct id *) ArpAlloc(sizeof(*id))))
  142.                                 return((struct Window *)-1);
  143.             packet->sp_Pkt.dp_Type = ACTION_DISK_INFO;
  144.             packet->sp_Pkt.dp_Arg1 = ((ULONG) id) >> 2;
  145.                     }
  146.             else {
  147.             packet->sp_Pkt.dp_Type = ACTION_SCREEN_MODE;
  148.             packet->sp_Pkt.dp_Arg1 = mode;
  149.             }
  150.             PutMsg(con, packet);
  151.              WaitPort(&iorp);
  152.             /* Pointer to console window, all we need..*/
  153.             if (mode == POINTER)
  154.                 return( (struct Window*)(id->id_VolumeNode));
  155.             else return(0);
  156.     }
  157.     }
  158.     /* error */
  159.     return((struct Window *)-1);
  160. }
  161. }
  162.  
  163. VOID Clear(fl)
  164. BPTR fl;
  165. {
  166.     (VOID)Write(fl,"\033[0;0H\033[J",9);
  167.         dsplin = 0;
  168.     x = (w->Width-24) / xf;
  169.     y = (w->Height-16) / yf;
  170. }
  171.  
  172. TEXT Banner(fl,ban)
  173. BPTR fl;
  174. STRPTR ban;
  175. {
  176.  
  177.     TEXT ch;
  178.     USHORT j = y+1;
  179.  
  180.     Morpos[CYPOS] = (TEXT)((j / 100) + CYOFF);
  181.     Morpos[CYPOS+1] = (TEXT)(((j - ((j / 100)*100)) / 10) + CYOFF);
  182.     Morpos[CYPOS+2] =
  183.     (TEXT)((j - ((j / 100)*100) - ((j - ((j / 100)*100)) / 10)*10) + CYOFF);
  184.  
  185.  
  186.     (VOID)Write(fl,Morpos,strlen(Morpos));
  187.     (VOID)Write(fl,ban,strlen(ban));
  188.     /* hide crsr */
  189.     (VOID)Write(fl,"  \033[0m\033[K\033[43m \010",16);
  190.  
  191.         (VOID)Read(fl,&ch,1);
  192.     (VOID)Write(fl,"\033[0m",4);
  193.  
  194.     return(ch);
  195. }
  196.  
  197. Displine(fl)
  198. BPTR fl;
  199. {
  200.  
  201.     REGISTER TEXT chr;
  202.     REGISTER ULONG ln = 0,actlin=0;
  203.  
  204.     for (;;) {
  205.  
  206.     if(!bp) if (!(count = Read(stdi,Buf,BFSIZE))) {
  207.             return(ENDFILE);
  208.             }
  209.  
  210.     chr = *(Buf + bp++);
  211.     
  212.     *(Lin + ln++) = chr;
  213.     actlin++;
  214.     switch (chr) {
  215.  
  216.         case '\n':
  217.         Write(fl,Lin,ln);
  218.         dsplin++;
  219.         if (bp >= count) bp = 0;
  220.         return(LINEOK);
  221.         break;
  222.         case '\t':
  223.         actlin+=8;
  224.         break;
  225.         case '\010': /* backspace */
  226.         actlin--;
  227.         break;
  228.         case '\014':
  229.         Write(fl,Lin,ln-1);
  230.         Write(fl,"\n^L",3);
  231.         if (bp >= count) bp = 0;
  232.         return(FORMFEED);
  233.         break;
  234.     }
  235.     if (actlin >= x) {
  236.         Write(fl,Lin,ln);
  237.         dsplin++;
  238.         if (bp >= count) bp = 0;
  239.         return (LINEOK);
  240.         }
  241.     if (bp >= count) bp = 0;
  242.     }
  243. }
  244.  
  245. VOID Bye(fl)
  246. BPTR fl;
  247. {
  248.      Write(fl,"\015\033[K",4);
  249.     (VOID)GetWin(CON);
  250.     Cleanup(RETURN_OK,NULL,NULL);
  251. }
  252.  
  253. /* _main used instead of main to slim code */
  254. VOID _main(Line)
  255. STRPTR Line;
  256.  
  257. {
  258.  
  259.     BPTR fil;
  260.     ULONG st;
  261.     TEXT c;
  262.  
  263.     Pr = (struct Process *) FindTask(NULL);
  264.     if(!(ArpBase = (struct ArpBase*)OpenLibrary(ArpName,ArpVersion)))
  265.          Cleanup(RETURN_FAIL,ERROR_INVALID_RESIDENT_LIBRARY,NULL);
  266.  
  267.  
  268.     if (!(Buf = ArpAllocMem(BFSIZE,MEMF_CLEAR)) ||
  269.  
  270.         !(Lin = ArpAllocMem(LINSIZE,MEMF_CLEAR)))
  271.             Cleanup(RETURN_FAIL,ERROR_NO_FREE_STORE,"No mem");
  272.  
  273.     stdi = Input();
  274.  
  275.     if (IsInteractive(stdi)) Cleanup(RETURN_ERROR,NULL,"Use a pipe");
  276.  
  277.     w = GetWin(POINTER);
  278.  
  279.     xf = w->RPort->Font->tf_XSize;
  280.     yf = w->RPort->Font->tf_YSize;
  281.  
  282.     (VOID)GetWin(RAW);
  283.  
  284.     fil = Open("*",MODE_OLDFILE);
  285.  
  286.  
  287.     for (;;) {
  288.  
  289.     Clear(fil);
  290.     while (dsplin <= (y-1)) {
  291.  
  292.         if ((st = Displine(fil)) != LINEOK) break;
  293.  
  294.             }
  295.  
  296.     if (st == ENDFILE) {
  297.             Banner(fil,"--End of file--");
  298.             break;
  299.             }
  300.     else {
  301.  
  302.     /* Goodbye Mr Wirth :-) */
  303.     more: 
  304.      switch(c = Banner(fil,"--More--")) {
  305.  
  306.         case ' ':
  307.         break;
  308.         case 'q':
  309.         Bye(fil);
  310.         break;
  311.         case '\003':
  312.         Bye(fil);
  313.         break;
  314.         case '\015':
  315.         Write(fil,"\015\033[K",4);
  316.         Displine(fil);
  317.         goto more;
  318.         break;
  319.         default:
  320.         Banner(fil,"--???--");
  321.     }
  322.     }
  323. }        
  324.     Bye(fil);
  325. }
  326.  
  327.