home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 428_02 / ed / navigate.c < prev   
Encoding:
C/C++ Source or Header  |  1994-03-13  |  7.7 KB  |  404 lines

  1. /*
  2. ** navigate.c
  3. **
  4. ** Ed, Version 1.51, Copyright (c) 1992-94 SoftCircuits
  5. ** Redistributed by permission.
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <pictor.h>
  10. #include "ed.h"
  11.  
  12. /*
  13. ** shows the current row/column on the status bar
  14. */
  15. void show_status()
  16. {
  17.     xprintf(statusbar,"%-24.24s\xB3 <F1>=Help  <F10>=Exit  [%c]  "
  18.         "%s  Row %-6dCol %-5d",filename,(modified) ? '*' : ' ',
  19.         (insert_mode) ? "INS" : "OVR",file_row + 1,file_col + 1);
  20.  
  21. } /* show_status */
  22.  
  23. /*
  24. ** displays one line of text at the specified row
  25. */
  26. void show_line(LINE *line,int row)
  27. {
  28.     int i,col,tab_cols;
  29.  
  30.     vcolor(edit_color);
  31.     setvpos(row,edit_left);
  32.  
  33.     /* scan line up to point visible on screen */
  34.     col = 0;
  35.     for(i = 0;col < left_col && i < line->len;i++) {
  36.         if(line->text[i] == '\t')
  37.             col = NEXT_TAB(col);
  38.         else col++;
  39.     }
  40.  
  41.     /* write out any unfinished tab */
  42.     if(col > left_col)
  43.         vrepc(' ',col - left_col);
  44.  
  45.     /* write visible portion of line */
  46.     for( ;col < (left_col + EDIT_COLS)
  47.         && i < line->len;i++) {
  48.  
  49.         if(line->text[i] == '\t') {
  50.             tab_cols = (tab_size - (col % tab_size));
  51.             if((col + tab_cols) > (left_col + EDIT_COLS))
  52.                 tab_cols = ((left_col + EDIT_COLS) - col);
  53.             vrepc(' ',tab_cols);
  54.             col += tab_cols;
  55.         }
  56.         else {
  57.             vputc(line->text[i]);
  58.             col++;
  59.         }
  60.     }
  61.  
  62.     /* fill remaining columns with spaces */
  63.     if(col < (left_col + EDIT_COLS))
  64.         vrepc(' ',(left_col + EDIT_COLS) - ((col > left_col) ? col : left_col));
  65.  
  66. } /* show_line */
  67.  
  68. /*
  69. ** repaints the edit window
  70. */
  71. void show_text()
  72. {
  73.     int i;
  74.     LINE *line = top_line;
  75.  
  76.     /* write line buffers */
  77.     for(i = edit_top;i <= edit_bottom && line;i++) {
  78.         show_line(line,i);
  79.         line = line->next;
  80.     }
  81.  
  82.     /* clear remaining lines (if any) */
  83.     for( ;i <= edit_bottom;i++) {
  84.         setvpos(i,edit_left);
  85.         vrepc(' ',EDIT_COLS);
  86.     }
  87.  
  88. } /* show_text */
  89.  
  90. /*
  91. ** sets file_col to represent line_ndx
  92. */
  93. void set_file_col()
  94. {
  95.     int i;
  96.  
  97.     /* count columns up to line_ndx */
  98.     for(file_col = 0,i = 0;i < line_ndx;i++) {
  99.         if(curr_line->text[i] == '\t')
  100.             file_col = NEXT_TAB(file_col);
  101.         else
  102.             file_col++;
  103.     }
  104.  
  105. } /* set_file_col */
  106.  
  107. /*
  108. ** sets line_ndx to represent pref_col
  109. ** if pref_col exceeds the number of line columns,
  110. ** line_ndx is set to the end of the line
  111. */
  112. void set_line_ndx()
  113. {
  114.     int col = 0;
  115.  
  116.     /* count line index up to pref_col */
  117.     for(line_ndx = 0;line_ndx < curr_line->len;line_ndx++) {
  118.         if(curr_line->text[line_ndx] == '\t')
  119.             col = NEXT_TAB(col);
  120.         else
  121.             col++;
  122.         if(col > pref_col)
  123.             break;
  124.     }
  125.  
  126. } /* set_line_ndx */
  127.  
  128. /*
  129. ** updates the edit cursor
  130. ** screen is updated if indicated by update_state
  131. ** horizontal scrolling is performed if required
  132. **
  133. ** if set_pref_col is non-zero, the preferred
  134. ** column (pref_col) is set to match file_col
  135. */
  136. void update_cursor(int set_pref_col)
  137. {
  138.     /* determine actual column */
  139.     set_file_col();
  140.  
  141.     /* make current column the preferred column */
  142.     if(set_pref_col)
  143.         pref_col = file_col;
  144.  
  145.     /* check for horizontal scroll */
  146.     if(file_col < left_col) {
  147.         left_col = file_col;
  148.         update_state = UPDATE_REPAINT;
  149.     }
  150.     else if((file_col - EDIT_COLS) >= left_col) {
  151.         left_col = ((file_col - EDIT_COLS) + 1);
  152.         update_state = UPDATE_REPAINT;
  153.     }
  154.  
  155.     /* update screen */
  156.     switch(update_state) {
  157.         case UPDATE_REPAINT:
  158.             show_text();
  159.             break;
  160.         case UPDATE_SCROLLUP:
  161.             vcolor(edit_color);
  162.             scroll(1,edit_top,edit_left,EDIT_ROWS,EDIT_COLS);
  163.             show_line(curr_line,edit_bottom);
  164.             break;
  165.         case UPDATE_SCROLLDN:
  166.             vcolor(edit_color);
  167.             scroll(-1,edit_top,edit_left,EDIT_ROWS,EDIT_COLS);
  168.             show_line(curr_line,edit_top);
  169.             break;
  170.     }
  171.  
  172.     /* set cursor position */
  173.     setcurs((file_row - top_row) + edit_top,
  174.         (file_col - left_col) + edit_left);
  175.  
  176.     /* update status bar */
  177.     show_status();
  178.  
  179.     update_state = UPDATE_NOUPDATE;
  180.  
  181. } /* update_cursor */
  182.  
  183. /*
  184. ** moves left one character -- screen is not updated
  185. */
  186. void _left()
  187. {
  188.     if(line_ndx > 0) {
  189.         /* move left */
  190.         line_ndx--;
  191.     }
  192.     else if(curr_line->prev != NULL) {
  193.         /* wrap to previous line */
  194.         _up();
  195.         line_ndx = curr_line->len;
  196.     }
  197.  
  198. } /* _left */
  199.  
  200. /*
  201. ** moves right one character -- screen is not updated
  202. */
  203. void _right()
  204. {
  205.     if(line_ndx < curr_line->len) {
  206.         /* move right */
  207.         line_ndx++;
  208.     }
  209.     else if(curr_line->next != NULL) {
  210.         /* wrap to next line */
  211.         _down();
  212.         line_ndx = 0;
  213.     }
  214.  
  215. } /* _right */
  216.  
  217. /*
  218. ** moves up one line -- screen is not updated
  219. */
  220. void _up()
  221. {
  222.     curr_line = curr_line->prev;
  223.     file_row--;
  224.  
  225.     /* scroll if required */
  226.     if(file_row < top_row) {
  227.         top_line = top_line->prev;
  228.         top_row--;
  229.         update_state = UPDATE_SCROLLDN;
  230.     }
  231.  
  232.     /* set line_ndx to match column in previous line */
  233.     set_line_ndx();
  234.  
  235. } /* _up */
  236.  
  237. /*
  238. ** moves down one line -- screen is not updated
  239. */
  240. void _down()
  241. {
  242.     curr_line = curr_line->next;
  243.     file_row++;
  244.  
  245.     /* scroll if required */
  246.     if((file_row - top_row) >= EDIT_ROWS) {
  247.         top_line = top_line->next;
  248.         top_row++;
  249.         update_state = UPDATE_SCROLLUP;
  250.     }
  251.  
  252.     /* set line_ndx to match column in previous line */
  253.     set_line_ndx();
  254.  
  255. } /* _down */
  256.  
  257. /*
  258. ** moves one character left
  259. */
  260. void cursor_left()
  261. {
  262.     if(line_ndx > 0 || curr_line->prev != NULL) {
  263.         _left();
  264.         update_cursor(TRUE);
  265.     }
  266. } /* cursor_left */
  267.  
  268. /*
  269. ** moves one character right
  270. */
  271. void cursor_right()
  272. {
  273.     if(line_ndx < curr_line->len || curr_line->next != NULL) {
  274.         _right();
  275.         update_cursor(TRUE);
  276.     }
  277. } /* cursor_left */
  278.  
  279. /*
  280. ** moves one line up
  281. */
  282. void cursor_up()
  283. {
  284.     if(curr_line->prev != NULL) {
  285.         _up();
  286.         update_cursor(FALSE);
  287.     }
  288. } /* cursor_up */
  289.  
  290. /*
  291. ** moves one line down
  292. */
  293. void cursor_down()
  294. {
  295.     if(curr_line->next != NULL) {
  296.         _down();
  297.         update_cursor(FALSE);
  298.     }
  299. } /* cursor_down */
  300.  
  301. /*
  302. ** moves up one screen
  303. */
  304. void page_up()
  305. {
  306.     int i;
  307.  
  308.     if(curr_line->prev != NULL) {
  309.         /* change cursor position */
  310.         for(i = 0;curr_line->prev != NULL && i < EDIT_ROWS;i++) {
  311.             curr_line = curr_line->prev;
  312.             file_row--;
  313.         }
  314.         /* change scroll position */
  315.         if(top_line->prev != NULL) {
  316.             for(i = 0;top_line->prev != NULL && i < EDIT_ROWS;i++) {
  317.                 top_line = top_line->prev;
  318.                 top_row--;
  319.             }
  320.             update_state = UPDATE_REPAINT;
  321.         }
  322.  
  323.         /* set line_ndx to match column in prev line */
  324.         set_line_ndx();
  325.         update_cursor(FALSE);
  326.     }
  327.  
  328. } /* page_up */
  329.  
  330. /*
  331. ** moves down one screen
  332. */
  333. void page_down()
  334. {
  335.     int i;
  336.  
  337.     if(curr_line->next != NULL) {
  338.         /* change cursor position */
  339.         for(i = 0;curr_line->next != NULL && i < EDIT_ROWS;i++) {
  340.             curr_line = curr_line->next;
  341.             file_row++;
  342.         }
  343.         /* change scroll position */
  344.         if(top_line->next != NULL) {
  345.             for(i = 0;top_line->next != NULL && i < EDIT_ROWS;i++) {
  346.                 top_line = top_line->next;
  347.                 top_row++;
  348.             }
  349.             update_state = UPDATE_REPAINT;
  350.         }
  351.  
  352.         /* set line_ndx to match column in prev line */
  353.         set_line_ndx();
  354.         update_cursor(FALSE);
  355.     }
  356.  
  357. } /* page_down */
  358.  
  359. /*
  360. ** moves to the start of the first line
  361. */
  362. void file_home()
  363. {
  364.     /* if not already at file home */
  365.     if(curr_line->prev != NULL || file_col > 0) {
  366.         /* set displayed lines */
  367.         if(top_line->prev != NULL) {
  368.             top_line = head;
  369.             top_row = 0;
  370.             update_state = UPDATE_REPAINT;
  371.         }
  372.  
  373.         /* set current line */
  374.         curr_line = head;
  375.         file_row = 0;
  376.         line_ndx = 0;
  377.         update_cursor(TRUE);
  378.     }
  379.  
  380. } /* file_home */
  381.  
  382. /*
  383. ** moves to the end of the last line
  384. */
  385. void file_end()
  386. {
  387.     /* if not already at file end */
  388.     if(curr_line->next != NULL || file_col < curr_line->len) {
  389.         /* set displayed lines */
  390.         if(top_line->next != NULL) {
  391.             top_line = tail;
  392.             top_row = (num_lines - 1);
  393.             update_state = UPDATE_REPAINT;
  394.         }
  395.  
  396.         /* set current line */
  397.         curr_line = tail;
  398.         file_row = (num_lines - 1);
  399.         line_ndx = curr_line->len;
  400.         update_cursor(TRUE);
  401.     }
  402.  
  403. } /* file_end */
  404.