home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / more_20b.zip / SOURCE.ZIP / MORE.C < prev    next >
C/C++ Source or Header  |  1993-08-12  |  10KB  |  441 lines

  1. /* "A better More" version 1.1
  2.    (C) 1993 Stephen M. Lacy
  3.  
  4.    This program still needs a bit of refinement and addition of options,
  5.    although its kind of nice for now.
  6.  
  7.    Revision history:
  8.  
  9.    Version 1.0: Well, sort of. This was used by only me for about two
  10.    days.  Bugs: Defaulted to 80x24, and printed the last line twice
  11.  
  12.    Version 1.1: First release version.  The 0-9 keys were added, along, 
  13.    with the 'q' key to quit.  The last line problem was fixed, and I added
  14.    some code to see how big the window was, it used to default to 80x24.
  15.  
  16.    Version 2.0: Completely ignores carriage return characters, but on a
  17.    line feed, does both line feed and carriage return.
  18.  
  19.    KNOWN BUGS:
  20.  
  21.    Version 1.1: The disappering cursor thingy.  Icky formatting issues.
  22.    
  23.  
  24.    */
  25.  
  26. /* #define INCL_DOS */
  27. #define INCL_VIO
  28. #define INCL_KBD
  29. #include <os2.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34. typedef struct _dllist {
  35.     char *string;
  36.     struct _dllist *next,*previous;
  37. } dllist, *pdllist, **ppdllist;
  38.  
  39.  
  40. #define CONTROL_S 19
  41. #define PROMPT "-- MORE v2.0ß (C)1993 --"
  42. #define EOF_STRING "-- EOF --"
  43. #define CELLSIZE 2
  44. #define DEFAULT_SCROLLUP 4
  45. #define DEFAULT_TABSIZE 4
  46. #define DEFAULT_ATTRIB 0x07
  47. #define DEFAULT_BOLD 0x0f
  48. #define DEFAULT_PROMPT 0x1e
  49. #define DEFAULT_UNDERSCORE 0x0e
  50.  
  51. #define MORE_EOF 1
  52.  
  53. int tabsize,options,scrollup;
  54. CHAR bright[2],attrib[2],blankcell[2],colorcell[2],underscore,bold;
  55.  
  56. void add_dllist(ppdllist first, ppdllist prev, ppdllist new) {
  57.     if (*prev) {
  58.         (*new)->next=(*prev)->next;
  59.         (*new)->previous=(*prev);
  60.         (*prev)->next=(*new);
  61.         (*prev)=(*new);
  62.     }
  63.     else {
  64.         (*new)->next=NULL;
  65.         (*new)->previous=NULL;
  66.         *prev=*new;
  67.         *first=*new;
  68.     }
  69. }
  70.  
  71. char *get_single_line(FILE *input,int width) {
  72.     char *result,readin;
  73.     int counter,j,end,reread;
  74.     
  75.     result=(char*)malloc((width+1)*2*sizeof(char));
  76.     for (counter=0;counter<width*2;counter++) {
  77.         result[counter++]=' ';
  78.         result[counter]=attrib[0];
  79.     }
  80.     counter=0;
  81.     end=FALSE;
  82.     reread=TRUE;
  83.     while(counter<width*2 && !end) {
  84.         if (reread) readin=fgetc(input);
  85.         switch (readin) {
  86.         case '\t':
  87.             for (j=0;j<tabsize;j++) {
  88.                 result[counter]=' ';
  89.                 counter+=CELLSIZE;
  90.             }
  91.             break;
  92.         case '\b':
  93.             readin=fgetc(input);
  94.             switch(result[counter-CELLSIZE]) {
  95.             case '_':
  96.                 result[counter-CELLSIZE+1]=underscore;
  97.                 break;
  98.             default:
  99.                 result[counter-CELLSIZE+1]=bold;
  100.                 break;
  101.             }
  102.             result[counter-CELLSIZE]=readin;
  103.             break;
  104.         case '\r':
  105.             break;
  106.         case '\n':
  107.             end=TRUE;
  108.             break;
  109.         default:
  110.             result[counter]=readin;
  111.             counter+=CELLSIZE;
  112.             break;
  113.         }
  114.     }
  115.     return(result);
  116. }
  117.  
  118. int get_screenful(FILE *input,
  119.                   ppdllist first,
  120.                   ppdllist after,
  121.                   int width,
  122.                   int height) {
  123.     int counter;
  124.     char *temp;
  125.     pdllist new_element;
  126.     
  127.     counter=0;
  128.     while (counter<height && !feof(input)) {
  129.         new_element=(pdllist)malloc(sizeof(dllist));
  130.         new_element->string=get_single_line(input,width);
  131.         add_dllist(first,after,&new_element);
  132.         counter++;
  133.     }
  134.     return(counter);
  135. }
  136.  
  137. void display_screenful(pdllist first,int height,int width, int read) {
  138.     int i;
  139.     char *display;
  140.     pdllist current;
  141.     int counter,j;
  142.     USHORT row,col;
  143.  
  144.     VioGetCurPos(&row,&col,0);
  145.     display=(char*)malloc(2*(height+1)*(width+1)*sizeof(char));
  146.     current=first;
  147.     counter=0;
  148.     j=0;
  149.     while (current && j<height ) {
  150.         memcpy((&display[counter]),current->string,width*2);
  151.         counter+=width*2;
  152.         current=current->next;
  153.         j++;
  154.     }
  155.  
  156.     if (-read==height) read=-read;
  157.     if (read<0) {
  158.         read=-read;
  159.         VioScrollDn(0,0,height-1,width,read,blankcell,0);
  160.         VioWrtCellStr(display,width*read*2,0,0,0);
  161.     } else  if (row+read<height) {
  162.         VioSetCurPos(row+read,0,0);
  163.         VioWrtCellStr(display,width*read*2,row,0,0);
  164.     } else if (row+read>height && read<height) {
  165.         if (first->previous!=NULL) display+=width*2*(height-read);
  166.         VioScrollUp(0,0,height,width,abs(read-(height-row)),blankcell,0);
  167.         VioWrtCellStr(display,width*read*2,height-read,0,0);
  168.         VioSetCurPos(height,0,0);
  169.     } else {
  170.         VioWrtCellStr(display,width*height*2,0,0,0);
  171.         VioSetCurPos(height,0,0);
  172.     }
  173.     free(display);
  174. }
  175.  
  176. int backup(ppdllist which, int n) {
  177.     int i=0;
  178.     while ((*which)->previous && n) {
  179.         (*which)=(*which)->previous;
  180.         n--;
  181.         i++;
  182.     }
  183.     return(i);
  184. }
  185.  
  186. void forward_search(ppdllist list,
  187.                     ppdllist end_of_list,
  188.                     FILE *input,
  189.                     char *string,
  190.                     int rows,
  191.                     int cols,
  192.                     int *offscreen) {
  193.     char expanded[600];
  194.     INT counter,i;
  195.     pdllist new_element;
  196.  
  197.     counter=0;
  198.     for (i=0;i<512;) {
  199.         expanded[i++]=string[counter++];
  200.         expanded[i++]=attrib[0];
  201.     }
  202.     while(1) {
  203.         if (strstr((*list)->string,expanded)) break;
  204.         if (feof(input) && (*end_of_list)->next==NULL) break;
  205.         if ((*list)->next) {
  206.             (*list)=(*list)->next;
  207.             (*offscreen)--;
  208.         } else {
  209.             new_element=(pdllist)malloc(sizeof(dllist));
  210.             new_element->string=get_single_line(input,cols);
  211.             add_dllist(list,end_of_list,&new_element);
  212.         }
  213.     }
  214.     backup(end_of_list,rows);
  215. }
  216.  
  217. void more_file(FILE *input) {
  218.     PVIOMODEINFO vmi;
  219.     KBDKEYINFO kbdi;
  220.     SHORT rows,cols;
  221.     CHAR string[255],searchbuffer[255],*tempstr;
  222.     CHAR *display;
  223. /*    CHAR searchstring[255],previous_search[255]; */
  224.     STRINGINBUF stringbuf;
  225.     pdllist whole_list,current,end_of_list;
  226.     int i,val,read,lines,offscreen;
  227.     USHORT rc,upval,r,c;
  228.     KBDINFO kbdinfo;
  229.  
  230.     KbdGetStatus(&kbdinfo,0);
  231.     vmi=(PVIOMODEINFO)malloc(sizeof(VIOMODEINFO));
  232.     vmi->cb=sizeof(VIOMODEINFO);
  233.     rc=VioGetMode(vmi,0);
  234.     if (rc!=0) {
  235.         printf("Error doing VioGetMode! %d\n",rc);
  236.         exit(0);
  237.     }
  238.     rows=vmi->row-1;
  239.     cols=vmi->col;
  240.     whole_list=NULL;
  241.     end_of_list=NULL;
  242.     lines=rows;
  243.     offscreen=0;
  244.     while (options&MORE_EOF?1:!feof(input)) {
  245.         if (lines-offscreen>0) {
  246.             read=get_screenful(input,
  247.                                &whole_list,
  248.                                &end_of_list,
  249.                                cols,
  250.                                lines-offscreen);
  251.             if (read!=lines-offscreen) 
  252.                 backup(&whole_list,lines-offscreen-read);
  253.             display_screenful(whole_list,rows,cols,read);
  254.         } else {
  255.             display_screenful(whole_list,rows,cols,lines);
  256.         }
  257.         if (lines>0) offscreen-=lines;
  258.         if (offscreen<0) offscreen=0; 
  259.         if (options&MORE_EOF?1:!feof(input))  {
  260.             if (feof(input)) 
  261.                 VioWrtCharStrAtt(EOF_STRING,strlen(EOF_STRING),
  262.                                  rows,0,bright,0);
  263.             else VioWrtCharStrAtt(PROMPT,strlen(PROMPT),rows,0,bright,0);
  264.             KbdCharIn(&kbdi,0,0);
  265.             if (kbdi.fbStatus & 0x0002) {
  266.                 switch (kbdi.chScan) {
  267.                 case 72:
  268.                     /* Up arrow */
  269.                     lines=scrollup;
  270.                     offscreen+=lines=backup(&whole_list,lines);
  271.                     lines=-lines;
  272.                     break;
  273.                 case 80:
  274.                     /* Down Arrow */
  275.                     lines=scrollup;
  276.                     break;
  277.                 case 73:
  278.                     /* Page up */
  279.                     lines=rows;
  280.                     offscreen+=lines=backup(&whole_list,lines);
  281.                     lines=-lines;
  282.                     break;
  283.                 case 81:
  284.                     /* Page Down */
  285.                     lines=rows;
  286.                     break;
  287.                 default:
  288.                     if (feof(input)) return;
  289.                     break;
  290.                 }
  291.             } else 
  292.                 switch(kbdi.chChar) {
  293. /*                case '/':
  294.                     lines=0;
  295.                     VioWrtNCell(colorcell,cols,rows,0,0);
  296.                     stringbuf.cb=255;
  297.                     kbdinfo.fsMask|=KEYBOARD_ASCII_MODE;
  298.                     kbdinfo.fsMask&=~KEYBOARD_BINARY_MODE;
  299.                     KbdSetStatus(&kbdinfo,0);
  300.                     KbdStringIn(searchstring,&stringbuf,0,0);
  301.                     searchstring[strlen(searchstring)-1]='\0';
  302.                     kbdinfo.fsMask&=~KEYBOARD_ASCII_MODE;
  303.                     kbdinfo.fsMask|=KEYBOARD_BINARY_MODE;
  304.                     KbdSetStatus(&kbdinfo,0);
  305.                     if (strcmp(searchstring,"\0D"))
  306.                         forward_search(&whole_list,
  307.                                        &end_of_list,
  308.                                        input,
  309.                                        searchstring,
  310.                                        rows,
  311.                                        cols,
  312.                                        &offscreen);
  313.                     else if (strcmp(previous_search,"\0D"))
  314.                         forward_search(&whole_list,
  315.                                        &end_of_list,
  316.                                        input,
  317.                                        previous_search,
  318.                                        rows,
  319.                                        cols,
  320.                                        &offscreen);
  321.                     strcpy(previous_search,searchstring);
  322.                     break;
  323. */                    
  324.                 case 'f':
  325.                 case 'F':
  326.                     lines=scrollup;
  327.                     break;
  328.                 case 'b':
  329.                 case 'B':
  330.                     lines=scrollup;
  331.                     offscreen+=lines=backup(&whole_list,lines);
  332.                     lines=-lines;
  333.                     break;
  334.                 case 13:
  335.                     lines=scrollup;
  336.                     break;
  337.                 case 'n':
  338.                 case 'N':
  339.                     while (input==stdin && !feof(input)) fgetc(input);
  340.                     fclose(input);
  341.                     VioWrtNCell(blankcell,cols,rows,0,0);
  342.                     KbdFlushBuffer(0);
  343.                     return;
  344.                     break;
  345.                 
  346.                 case 'q':
  347.                 case 'Q':
  348.                     while (input==stdin && !feof(input)) fgetc(input);
  349.                     fclose(input);
  350.                     VioWrtNCell(blankcell,cols,rows,0,0);
  351.                     KbdFlushBuffer(0);
  352.                     return;
  353.                 default:
  354.                     lines=rows;
  355.                     if (feof(input)) return;
  356.                     break;
  357.                 }
  358.             for (i=0;i<lines && whole_list->next;i++)
  359.                 whole_list=whole_list->next;
  360.         }
  361.     }
  362.     KbdFlushBuffer(0);
  363. }
  364.  
  365. char *strupper(char *string) {
  366.     int i;
  367.     char *original;
  368.     original=string;
  369.     while (*string) {
  370.         if (*string>='a' && *string<='z')
  371.             *string-='a'-'A';
  372.         string++;
  373.     }
  374.     return(original);
  375. }
  376.  
  377. void main (int argc, char *argv[]) {
  378.     FILE *input;
  379.     USHORT row, col;
  380.     pdllist file_list,current,new;
  381.     HDIR hdirDir;
  382.     ULONG file_attrib,searchCount,infoLevel;
  383.     USHORT rc;
  384.     FILEFINDBUF3 ffbData;
  385.     CHAR prompt[128];
  386.     CHAR result[255];
  387.     PSZ temp;
  388.     KBDKEYINFO kbdi;
  389.     KBDINFO kbdinfo;
  390.     INT i;
  391.  
  392.     tabsize=DEFAULT_TABSIZE;
  393.     scrollup=DEFAULT_SCROLLUP;
  394.     underscore=DEFAULT_UNDERSCORE;
  395.     bold=DEFAULT_BOLD;
  396.     attrib[0]=DEFAULT_ATTRIB;
  397.     bright[0]=DEFAULT_PROMPT;
  398.     blankcell[0]=' ';
  399.     blankcell[1]=DEFAULT_ATTRIB;
  400.     colorcell[0]=' ';
  401.     colorcell[1]=DEFAULT_ATTRIB;
  402.  
  403.     options=MORE_EOF;
  404.     file_list=current=NULL;
  405.     KbdGetStatus(&kbdinfo,0);
  406.     kbdinfo.fsMask&=~KEYBOARD_ASCII_MODE;
  407.     kbdinfo.fsMask|=KEYBOARD_BINARY_MODE;
  408.     KbdSetStatus(&kbdinfo,0);
  409.     if (argc==1) {
  410.         more_file(stdin);
  411.     }
  412.     else {
  413.         for (i=1;i<argc;i++) {
  414.             input=fopen(argv[i],"r");
  415.             if (input==NULL) {
  416.                 printf("Error opening file '%s'.\n",argv[i]);
  417.                 printf("Most likely, file non-existant.\n");
  418.                 exit(0);
  419.             }
  420.             more_file(input);
  421.             if (i<argc-1) {
  422.                 sprintf(prompt,"-- BEGIN FILE %s --",strupper(argv[i+1]));
  423.                 VioGetCurPos(&row,&col,0);
  424.                 VioWrtCharStrAtt(prompt,strlen(prompt),row,0,bright,0);
  425.                 VioWrtNCell(blankcell,col,row,0,0);
  426.                 KbdCharIn(&kbdi,0,0);
  427.                 switch(kbdi.chChar) {
  428.                 case 'q':
  429.                 case 'Q':
  430.                     VioGetCurPos(&row,&col,0);
  431.                     VioSetCurPos(row-1,0,0);
  432.                     exit(0);
  433.                 }
  434.             }
  435.         }
  436.     }
  437.  
  438.     VioGetCurPos(&row,&col,0);
  439.     VioSetCurPos(row-1,0,0);
  440. }
  441.