home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / less2912.zip / jump.c < prev    next >
C/C++ Source or Header  |  1995-03-03  |  7KB  |  296 lines

  1. /*
  2.  * Copyright (c) 1984,1985,1989,1994,1995  Mark Nudelman
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice in the documentation and/or other materials provided with 
  12.  *    the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
  15.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
  17.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
  18.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
  20.  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
  21.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
  22.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
  23.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 
  24.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * Routines which jump to a new location in the file.
  30.  */
  31.  
  32. #include "less.h"
  33. #include "position.h"
  34.  
  35. extern int hit_eof;
  36. extern int jump_sline;
  37. extern int squished;
  38. extern int screen_trashed;
  39. extern int sc_width, sc_height;
  40.  
  41. /*
  42.  * Jump to the end of the file.
  43.  */
  44.     public void
  45. jump_forw()
  46. {
  47.     POSITION pos;
  48.  
  49.     if (ch_end_seek())
  50.     {
  51.         error("Cannot seek to end of file", NULL_PARG);
  52.         return;
  53.     }
  54.     /*
  55.      * Position the last line in the file at the last screen line.
  56.      * Go back one line from the end of the file
  57.      * to get to the beginning of the last line.
  58.      */
  59.     pos = back_line(ch_tell());
  60.     if (pos == NULL_POSITION)
  61.         jump_loc((POSITION)0, sc_height-1);
  62.     else
  63.         jump_loc(pos, sc_height-1);
  64. }
  65.  
  66. /*
  67.  * Jump to line n in the file.
  68.  */
  69.     public void
  70. jump_back(n)
  71.     int n;
  72. {
  73.     POSITION pos;
  74.     PARG parg;
  75.  
  76.     /*
  77.      * Find the position of the specified line.
  78.      * If we can seek there, just jump to it.
  79.      * If we can't seek, but we're trying to go to line number 1,
  80.      * use ch_beg_seek() to get as close as we can.
  81.      */
  82.     pos = find_pos(n);
  83.     if (pos != NULL_POSITION && ch_seek(pos) == 0)
  84.     {
  85.         jump_loc(pos, jump_sline);
  86.     } else if (n <= 1 && ch_beg_seek() == 0)
  87.     {
  88.         jump_loc(ch_tell(), jump_sline);
  89.         error("Cannot seek to beginning of file", NULL_PARG);
  90.     } else
  91.     {
  92.         parg.p_int = n;
  93.         error("Cannot seek to line number %d", &parg);
  94.     }
  95. }
  96.  
  97. /*
  98.  * Repaint the screen.
  99.  */
  100.     public void
  101. repaint()
  102. {
  103.     struct scrpos scrpos;
  104.     /*
  105.      * Start at the line currently at the top of the screen
  106.      * and redisplay the screen.
  107.      */
  108.     get_scrpos(&scrpos);
  109.     pos_clear();
  110.     jump_loc(scrpos.pos, scrpos.ln);
  111. }
  112.  
  113. /*
  114.  * Jump to a specified percentage into the file.
  115.  */
  116.     public void
  117. jump_percent(percent)
  118.     int percent;
  119. {
  120.     POSITION pos, len;
  121.  
  122.     /*
  123.      * Determine the position in the file
  124.      * (the specified percentage of the file's length).
  125.      */
  126.     if ((len = ch_length()) == NULL_POSITION)
  127.     {
  128.         ierror("Determining length of file", NULL_PARG);
  129.         ch_end_seek();
  130.     }
  131.     if ((len = ch_length()) == NULL_POSITION)
  132.     {
  133.         error("Don't know length of file", NULL_PARG);
  134.         return;
  135.     }
  136.     /*
  137.      * {{ This calculation may overflow! }}
  138.      */
  139.     pos = (percent * len) / 100;
  140.     if (pos >= len)
  141.         pos = len-1;
  142.  
  143.     jump_line_loc(pos, jump_sline);
  144. }
  145.  
  146. /*
  147.  * Jump to a specified position in the file.
  148.  * Like jump_loc, but the position need not be 
  149.  * the first character in a line.
  150.  */
  151.     public void
  152. jump_line_loc(pos, sline)
  153.     POSITION pos;
  154.     int sline;
  155. {
  156.     int c;
  157.  
  158.     if (ch_seek(pos) == 0)
  159.     {
  160.         /*
  161.          * Back up to the beginning of the line.
  162.          */
  163.         while ((c = ch_back_get()) != '\n' && c != EOI)
  164.             ;
  165.         if (c == '\n')
  166.             (void) ch_forw_get();
  167.         pos = ch_tell();
  168.     }
  169.     jump_loc(pos, sline);
  170. }
  171.  
  172. /*
  173.  * Jump to a specified position in the file.
  174.  * The position must be the first character in a line.
  175.  * Place the target line on a specified line on the screen.
  176.  */
  177.     public void
  178. jump_loc(pos, sline)
  179.     POSITION pos;
  180.     int sline;
  181. {
  182.     register int nline;
  183.     POSITION tpos;
  184.     POSITION bpos;
  185.  
  186.     /*
  187.      * Normalize sline.
  188.      */
  189.     sline = adjsline(sline);
  190.  
  191.     if ((nline = onscreen(pos)) >= 0)
  192.     {
  193.         /*
  194.          * The line is currently displayed.  
  195.          * Just scroll there.
  196.          */
  197.         nline -= sline;
  198.         if (nline > 0)
  199.             forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0);
  200.         else
  201.             back(-nline, position(TOP), 1, 0);
  202.         return;
  203.     }
  204.  
  205.     /*
  206.      * Line is not on screen.
  207.      * Seek to the desired location.
  208.      */
  209.     if (ch_seek(pos))
  210.     {
  211.         error("Cannot seek to that file position", NULL_PARG);
  212.         return;
  213.     }
  214.  
  215.     /*
  216.      * See if the desired line is before or after 
  217.      * the currently displayed screen.
  218.      */
  219.     tpos = position(TOP);
  220.     bpos = position(BOTTOM_PLUS_ONE);
  221.     if (tpos == NULL_POSITION || pos >= tpos)
  222.     {
  223.         /*
  224.          * The desired line is after the current screen.
  225.          * Move back in the file far enough so that we can
  226.          * call forw() and put the desired line at the 
  227.          * sline-th line on the screen.
  228.          */
  229.         for (nline = 0;  nline < sline;  nline++)
  230.         {
  231.             if (bpos != NULL_POSITION && pos <= bpos)
  232.             {
  233.                 /*
  234.                  * Surprise!  The desired line is
  235.                  * close enough to the current screen
  236.                  * that we can just scroll there after all.
  237.                  */
  238.                 forw(sc_height-sline+nline-1, bpos, 1, 0, 0);
  239.                 return;
  240.             }
  241.             pos = back_line(pos);
  242.             if (pos == NULL_POSITION)
  243.             {
  244.                 /*
  245.                  * Oops.  Ran into the beginning of the file.
  246.                  * Exit the loop here and rely on forw()
  247.                  * below to draw the required number of
  248.                  * blank lines at the top of the screen.
  249.                  */
  250.                 break;
  251.             }
  252.         }
  253.         lastmark();
  254.         hit_eof = 0;
  255.         squished = 0;
  256.         screen_trashed = 0;
  257.         forw(sc_height-1, pos, 1, 0, sline-nline);
  258.     } else
  259.     {
  260.         /*
  261.          * The desired line is before the current screen.
  262.          * Move forward in the file far enough so that we
  263.          * can call back() and put the desired line at the 
  264.          * sline-th line on the screen.
  265.          */
  266.         for (nline = sline;  nline < sc_height - 1;  nline++)
  267.         {
  268.             pos = forw_line(pos);
  269.             if (pos == NULL_POSITION)
  270.             {
  271.                 /*
  272.                  * Ran into end of file.
  273.                  * This shouldn't normally happen, 
  274.                  * but may if there is some kind of read error.
  275.                  */
  276.                 break;
  277.             }
  278.             if (pos >= tpos)
  279.             {
  280.                 /* 
  281.                  * Surprise!  The desired line is
  282.                  * close enough to the current screen
  283.                  * that we can just scroll there after all.
  284.                  */
  285.                 back(nline+1, tpos, 1, 0);
  286.                 return;
  287.             }
  288.         }
  289.         lastmark();
  290.         clear();
  291.         screen_trashed = 0;
  292.         add_back_pos(pos);
  293.         back(sc_height-1, pos, 1, 0);
  294.     }
  295. }
  296.