home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 287.lha / TY_v1.3 / src / prim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-07  |  8.7 KB  |  293 lines

  1. /*************************************************************************
  2.  ***                        prim.c                       (JJB TEMPLAR) ***
  3.  *** Date modifications begun: 7/8/89.                                 ***
  4.  *** Last modified: 27/8/89.                                           ***
  5.  *************************************************************************/
  6. /*** Primitives for displaying the file on the screen.                 ***
  7.  *************************************************************************/
  8.  
  9. #include "less.h"
  10. #include "position.h"
  11. #include "screen.h"
  12.  
  13. int     hit_eof;    /* Keeps track of how many times we hit end of file */
  14.  
  15. extern int  quiet;
  16. extern int  top_scroll;
  17. extern int  back_scroll;
  18. extern int  sc_height;
  19. extern char *line;
  20. extern int  page_break;
  21.  
  22. #define eof_bell()  bell()
  23.  
  24. void    prepaint(LONG);
  25.  
  26. static void eof_check() /*===============================================*/
  27. {                       /* Check if EOF displayed.                       */
  28. LONG    pos;
  29.  
  30.   /* If the bottom line is empty, we are at EOF.
  31.      If the bottom line ends at the file length, we must be just at EOF. */
  32.     pos = position(BOTTOM_PLUS_ONE);
  33.     if (((pos == NULL_POSITION) && !page_break) || (pos == ch_length()))
  34.         hit_eof++;
  35. }
  36.  
  37. static void forw(n, pos, force, only_last) /*============================*/
  38. register int n;     /* Display n lines, scrolling forward.    */
  39. LONG    pos;        /* Starting from position pos in the file. */
  40. int     force;      /* Display lines even if hit eof. */
  41. int     only_last;  /* Display only last screenful if n > screen size. */
  42. {
  43. int     eof = 0;
  44. int     nlines = 0;
  45. int     repaint_flag,top_flag = 0;
  46.  
  47.     repaint_flag = (only_last && (n > sc_height-1));
  48.  
  49.     if (!repaint_flag) {
  50.         if (top_scroll && (n >= sc_height - 1)) {
  51.             clear();        /* From top of screen */
  52.             home();
  53.             force = 1;
  54.             top_flag = 1;   /* Don't precede top line with '\n' */
  55.         }
  56.         else {              /* Or from bottom left */
  57.             lower_left();
  58.         }
  59.  
  60.         if (pos != position(BOTTOM_PLUS_ONE)) {
  61.           /* This is not contiguous with what is currently displayed.
  62.              Clear the screen image (position table) and start a new screen. */
  63.             pos_clear();
  64.             add_forw_pos(pos);
  65.             force = 1;
  66.             if (top_scroll) {
  67.                 clear();
  68.                 home();
  69.                 top_flag = 1;
  70.             }
  71.             else puts("...skipping...\n");
  72.     }
  73.     }
  74.  
  75.     while (--n >= 0) {
  76.       /* Read the next line of input. */
  77.         pos = forw_line(pos);
  78.         if (pos == NULL_POSITION) {
  79.           /* End of file: stop here unless the top line
  80.              is still empty, or "force" is true. */
  81.             if (!page_break) eof = 1;
  82.             if (!force && (position(TOP) != NULL_POSITION)) break;
  83.             line = NULL;
  84.         }
  85.       /* Add the position of the next line to the position table.
  86.          Display the current line on the screen. */
  87.         add_forw_pos(pos);
  88.         nlines++;
  89.         if (!repaint_flag) {
  90.             if (top_flag) top_flag = 0;
  91.             else putc('\n');
  92.             put_line();
  93.         }
  94.     }
  95.  
  96.     if (eof) hit_eof++;
  97.     else eof_check();
  98.     if (!nlines) eof_bell();
  99.     else if (repaint_flag) repaint();
  100.     page_break = 0;
  101. }
  102.  
  103. static void back(n, pos, force, only_last) /*============================*/
  104. register int n;                            /* As above, but backward     */
  105. LONG    pos;
  106. int     force;
  107. int     only_last;
  108. {
  109. int nlines = 0;
  110. int repaint_flag;
  111. int tempn = n;
  112.  
  113.     repaint_flag = ((n > back_scroll) || (only_last && (n > sc_height-1)));
  114.     hit_eof = 0;
  115.     while (--n >= 0) {
  116.       /* Get the previous line of input. */
  117.         pos = back_line(pos);
  118.         if (pos == NULL_POSITION) {
  119.           /* Beginning of file: stop here unless "force" is true. */
  120.             if (!force) break;
  121.             line = NULL;
  122.         }
  123.         if (page_break && (n == tempn - 1)) page_break = 0;
  124.       /* Add the position of the previous line to the position table.
  125.          Display the line on the screen. */
  126.         add_back_pos(pos);
  127.         nlines++;
  128.         if (!repaint_flag && !page_break) {
  129.             home();
  130.             add_line();
  131.             put_line();     putc('\n');
  132.         }
  133.     }
  134.  
  135.     if (page_break) {
  136.         page_break = 0;
  137.         pos = forw_line(pos);
  138.         page_break = 0;
  139.         set_top_pos(pos);       /* Patched together with a nappy pin and */
  140.         repaint(pos);           /* chewing gum... Very wierd this. */
  141.     }
  142.     else {
  143.         eof_check();
  144.         if (!nlines) eof_bell();
  145.         else if (repaint_flag) repaint();
  146.     }
  147. }
  148.  
  149. void    forward(n, only_last) /*=========================================*/
  150. int     n;                    /* Display n more lines, forward.          */
  151. int     only_last;
  152. {
  153. LONG    pos;
  154.  
  155.     pos = position(BOTTOM_PLUS_ONE);
  156.     if (pos == NULL_POSITION) {
  157.         eof_bell();
  158.         hit_eof++;
  159.         return;
  160.     }
  161.     forw(n, pos, 0, only_last);
  162. }
  163.  
  164. void    backward(n, only_last) /*========================================*/
  165. int     n;                     /* Display n more lines, backward.        */
  166. int     only_last;
  167. {
  168. LONG    pos;
  169.  
  170.     pos = position(TOP);
  171.     if (pos == NULL_POSITION) {
  172.       /* This will almost never happen,
  173.          because the top line is almost never empty. */
  174.         eof_bell();
  175.         return;
  176.     }
  177.     back(n, pos, 0, only_last);
  178. }
  179.  
  180. static void prepaint(pos) /*=============================================*/
  181. LONG    pos;              /* Repaint, starting from a specified pos.     */
  182. {
  183.     hit_eof = 0;
  184.     forw(sc_height-1, pos, 0, 0);
  185. }
  186.  
  187. void    repaint() /*=====================================================*/
  188. {  /* Start at line currently at the top of screen and redisplay screen. */
  189. register int    temp;
  190.     temp = top_scroll;
  191.     top_scroll = 1;
  192.     prepaint(position(TOP));
  193.     top_scroll = temp;
  194. }
  195.  
  196. void    jump_forw() /*===================================================*/
  197. {
  198. LONG    pos;
  199.  
  200. /* Jump to the end of the file. It is more convenient to paint the screen
  201.  * backward, from the end of the file toward the beginning. */
  202.     end_seek();
  203.     pos = ch_tell();
  204.     clear();
  205.     pos_clear();
  206.     add_back_pos(pos);
  207.     back(sc_height - 1, pos, 0, 0);
  208. }
  209.  
  210. void    jump_back(n) /*==================================================*/
  211. register int n;      /* Jump to line n in file.                          */
  212. {
  213. register int c;
  214.  
  215.   /* This is done the slow way, by starting at the beginning
  216.      of the file and counting newlines. */
  217.     if (ch_seek(0)) {
  218.         /* Probably a pipe with beginning of file no longer buffered. */
  219.         error("Cannot get to beginning of file",0);
  220.         return;
  221.     }
  222.  
  223.   /* Start counting lines. */
  224.     while (--n > 0) {
  225.         while ((c = ch_forw_get()) != '\n')
  226.             if (c == EOF) {
  227.                 error("File is not that long",0);
  228.                     /* {{ Maybe tell him how long it is? }} */
  229.                 return;
  230.             }
  231.     }
  232.  
  233.   /* Finally found the place to start.
  234.      Clear and redisplay the screen from there.
  235.      {{ We *could* figure out if the new position is close enough to just
  236.         scroll there without clearing the screen, but it's not worth it. }} */
  237.     prepaint(ch_tell());
  238. }
  239.  
  240. void    jump_percent() /*================================================*/
  241. {                      /* Jump a %age into the file.                     */
  242. static int  percent;
  243. LONG    pos,len;
  244.  
  245.     if (!(r_int("Percentage",&percent,3))) return;      /* 2 digits max */
  246.     if (percent < 0) percent = 0;
  247.  
  248.     if ((len = ch_length()) == NULL_POSITION) {
  249.         error("Don't know length of file",0);
  250.         return;
  251.     }
  252.     pos = (percent * len) / 100;
  253.     jump_loc(pos);
  254.     setbar(0);
  255. }
  256.  
  257. void    jump_loc(pos) /*=================================================*/
  258. LONG    pos;
  259. {
  260. register int c;
  261. register int nline;
  262. LONG    tpos;
  263.  
  264.   /* See if the desired line is BEFORE the currently displayed screen.
  265.      If so, see if it is close enough to scroll backwards to it. */
  266.     tpos = position(TOP);
  267.     if (pos < tpos) {
  268.         for (nline = 1;  nline <= back_scroll;  nline++) {
  269.             tpos = back_line(tpos);
  270.             if (tpos == NULL_POSITION || tpos <= pos) {
  271.                 back(nline, position(TOP), 1, 0);
  272.                 return;
  273.             }
  274.         }
  275.     }
  276.     else if ((nline = onscreen(pos)) >= 0) {
  277.       /* The line is currently displayed. Just scroll there. */
  278.         forw(nline, position(BOTTOM_PLUS_ONE), 1, 0);
  279.         return;
  280.     }
  281.  
  282.   /* Line is not on screen. Back up to the beginning of the current line. */
  283.     if (ch_seek(pos)) {
  284.         error("Cannot seek to that position",0);
  285.         return;
  286.     }
  287.     while ((c = ch_back_get()) != '\n' && c != EOF);
  288.     if (c == '\n') ch_forw_get();
  289.  
  290.   /* Clear and paint the screen. */
  291.     prepaint(ch_tell());
  292. }
  293.