home *** CD-ROM | disk | FTP | other *** search
/ ftp.uv.es / 2014.11.ftp.uv.es.tar / ftp.uv.es / pub / unix / pine4.10.tar.gz / pine4.10.tar / pine4.10 / pico / basic.c < prev    next >
C/C++ Source or Header  |  1998-04-02  |  21KB  |  869 lines

  1. #if    !defined(lint) && !defined(DOS)
  2. static char rcsid[] = "$Id: basic.c,v 4.29 1998/04/02 05:58:20 mikes Exp $";
  3. #endif
  4. /*
  5.  * Program:    Cursor manipulation functions
  6.  *
  7.  *
  8.  * Michael Seibel
  9.  * Networks and Distributed Computing
  10.  * Computing and Communications
  11.  * University of Washington
  12.  * Administration Builiding, AG-44
  13.  * Seattle, Washington, 98195, USA
  14.  * Internet: mikes@cac.washington.edu
  15.  *
  16.  * Please address all bugs and comments to "pine-bugs@cac.washington.edu"
  17.  *
  18.  *
  19.  * Pine and Pico are registered trademarks of the University of Washington.
  20.  * No commercial use of these trademarks may be made without prior written
  21.  * permission of the University of Washington.
  22.  * 
  23.  * Pine, Pico, and Pilot software and its included text are Copyright
  24.  * 1989-1998 by the University of Washington.
  25.  * 
  26.  * The full text of our legal notices is contained in the file called
  27.  * CPYRIGHT, included with this distribution.
  28.  *
  29.  */
  30. /*
  31.  * The routines in this file move the cursor around on the screen. They
  32.  * compute a new value for the cursor, then adjust ".". The display code
  33.  * always updates the cursor location, so only moves between lines, or
  34.  * functions that adjust the top line in the window and invalidate the
  35.  * framing, are hard.
  36.  */
  37. #include        "headers.h"
  38.  
  39. #ifdef    ANSI
  40.     int getgoal(struct LINE *);
  41. #else
  42.     int getgoal();
  43. #endif
  44.  
  45.  
  46. /*
  47.  * Move the cursor to the
  48.  * beginning of the current line.
  49.  * Trivial.
  50.  */
  51. gotobol(f, n)
  52. int f, n;
  53. {
  54.     curwp->w_doto  = 0;
  55.     return (TRUE);
  56. }
  57.  
  58. /*
  59.  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  60.  * "forwchar" to actually do the move. Otherwise compute the new cursor
  61.  * location. Error if you try and move out of the buffer. Set the flag if the
  62.  * line pointer for dot changes.
  63.  */
  64. backchar(f, n)
  65. int             f;
  66. register int    n;
  67. {
  68.     register LINE   *lp;
  69.  
  70.     if (n < 0)
  71.       return (forwchar(f, -n));
  72.  
  73.     while (n--) {
  74.     if (curwp->w_doto == 0) {
  75.         if ((lp=lback(curwp->w_dotp)) == curbp->b_linep){
  76.         if(Pmaster && Pmaster->headents)
  77.             /*
  78.              * go up into editing the mail header if on 
  79.              * the top line and the user hits the left arrow!!!
  80.              *
  81.              * if the editor returns anything except -1, the 
  82.              * user requested something special, so let 
  83.              * pico know...
  84.              */
  85.           return(HeaderEditor(2, 1));
  86.         else
  87.           return (FALSE);
  88.         }
  89.  
  90.         curwp->w_dotp  = lp;
  91.         curwp->w_doto  = llength(lp);
  92.         curwp->w_flag |= WFMOVE;
  93.     } else
  94.       curwp->w_doto--;
  95.     }
  96.  
  97.     return (TRUE);
  98. }
  99.  
  100.  
  101. /*
  102.  * Move the cursor to the end of the current line. Trivial. No errors.
  103.  */
  104. gotoeol(f, n)
  105. int f, n;
  106. {
  107.     curwp->w_doto  = llength(curwp->w_dotp);
  108.     return (TRUE);
  109. }
  110.  
  111.  
  112. /*
  113.  * Move the cursor forwwards by "n" characters. If "n" is less than zero call
  114.  * "backchar" to actually do the move. Otherwise compute the new cursor
  115.  * location, and move ".". Error if you try and move off the end of the
  116.  * buffer. Set the flag if the line pointer for dot changes.
  117.  */
  118. forwchar(f, n)
  119. int             f;
  120. register int    n;
  121. {
  122.     if (n < 0)
  123.       return (backchar(f, -n));
  124.  
  125.     while (n--) {
  126.     if (curwp->w_doto == llength(curwp->w_dotp)) {
  127.         if (curwp->w_dotp == curbp->b_linep)
  128.           return (FALSE);
  129.  
  130.         curwp->w_dotp  = lforw(curwp->w_dotp);
  131.         curwp->w_doto  = 0;
  132.         curwp->w_flag |= WFMOVE;
  133.     }
  134.     else
  135.       curwp->w_doto++;
  136.     }
  137.     
  138.     return (TRUE);
  139. }
  140.  
  141.  
  142. /*
  143.  * move to a particular line.
  144.  * argument (n) must be a positive integer for
  145.  * this to actually do anything
  146.  */
  147. gotoline(f, n)
  148. int f, n;
  149. {
  150.     if (n < 1)        /* if a bogus argument...then leave */
  151.       return(FALSE);
  152.  
  153.     /* first, we go to the start of the buffer */
  154.     curwp->w_dotp  = lforw(curbp->b_linep);
  155.     curwp->w_doto  = 0;
  156.     return(forwline(f, n-1));
  157. }
  158.  
  159.  
  160. /*
  161.  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  162.  * considered to be hard motion; it really isn't if the original value of dot
  163.  * is the same as the new value of dot. Normally bound to "M-<".
  164.  */
  165. gotobob(f, n)
  166. int f, n;
  167. {
  168.     curwp->w_dotp  = lforw(curbp->b_linep);
  169.     curwp->w_doto  = 0;
  170.     curwp->w_flag |= WFHARD;
  171.     return (TRUE);
  172. }
  173.  
  174.  
  175. /*
  176.  * Move to the end of the buffer. Dot is always put at the end of the file
  177.  * (ZJ). The standard screen code does most of the hard parts of update.
  178.  * Bound to "M->".
  179.  */
  180. gotoeob(f, n)
  181. int f, n;
  182. {
  183.     curwp->w_dotp  = curbp->b_linep;
  184.     curwp->w_doto  = 0;
  185.     curwp->w_flag |= WFHARD;
  186.     return (TRUE);
  187. }
  188.  
  189.  
  190. /*
  191.  * Move forward by full lines. If the number of lines to move is less than
  192.  * zero, call the backward line function to actually do it. The last command
  193.  * controls how the goal column is set. Bound to "C-N". No errors are
  194.  * possible.
  195.  */
  196. forwline(f, n)
  197. int f, n;
  198. {
  199.     register LINE   *dlp;
  200.  
  201.     if (n < 0)
  202.       return (backline(f, -n));
  203.  
  204.     if ((lastflag&CFCPCN) == 0)             /* Reset goal if last   */
  205.       curgoal = getccol(FALSE);       /* not C-P or C-N       */
  206.  
  207.     thisflag |= CFCPCN;
  208.     dlp = curwp->w_dotp;
  209.     while (n-- && dlp!=curbp->b_linep)
  210.       dlp = lforw(dlp);
  211.  
  212.     curwp->w_dotp  = dlp;
  213.     curwp->w_doto  = getgoal(dlp);
  214.     curwp->w_flag |= WFMOVE;
  215.     return (TRUE);
  216. }
  217.  
  218.  
  219. /*
  220.  * This function is like "forwline", but goes backwards. The scheme is exactly
  221.  * the same. Check for arguments that are less than zero and call your
  222.  * alternate. Figure out the new line and call "movedot" to perform the
  223.  * motion. No errors are possible. Bound to "C-P".
  224.  */
  225. backline(f, n)
  226. int f, n;
  227. {
  228.     register LINE   *dlp;
  229.     register int    status = 0;
  230.  
  231.     if (n < 0)
  232.       return (forwline(f, -n));
  233.  
  234.     if(Pmaster && Pmaster->headents){
  235.     /*
  236.      * go up into editing the mail header if on the top line
  237.      * and the user hits the up arrow!!!
  238.      */
  239.     if (lback(curwp->w_dotp) == curbp->b_linep)
  240.       /*
  241.        * if the editor returns anything except -1 then the user
  242.        * has requested something special, so let pico know...
  243.        */
  244.       return(HeaderEditor(1, 1));
  245.     }
  246.  
  247.     if ((lastflag&CFCPCN) == 0)             /* Reset goal if the    */
  248.       curgoal = getccol(FALSE);       /* last isn't C-P, C-N  */
  249.  
  250.     thisflag |= CFCPCN;
  251.     dlp = curwp->w_dotp;
  252.     while (n-- && lback(dlp)!=curbp->b_linep)
  253.       dlp = lback(dlp);
  254.  
  255.     curwp->w_dotp  = dlp;
  256.     curwp->w_doto  = getgoal(dlp);
  257.     curwp->w_flag |= WFMOVE;
  258.     return (TRUE);
  259. }
  260.  
  261.  
  262. /*
  263.  * go back to the begining of the current paragraph
  264.  * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  265.  * combination to delimit the begining of a paragraph    
  266.  */
  267. gotobop(f, n)
  268. int f, n;    /* default Flag & Numeric argument */
  269. {
  270.     int quoted, qlen;
  271.  
  272.     if (n < 0)    /* the other way...*/
  273.       return(gotoeop(f, -n));
  274.  
  275.     while (n-- > 0) {    /* for each one asked for */
  276.  
  277.     while(lisblank(curwp->w_dotp)
  278.           && lback(curwp->w_dotp) != curbp->b_linep){
  279.         curwp->w_dotp = lback(curwp->w_dotp);
  280.         curwp->w_doto = 0;
  281.     }
  282.     
  283.     /* scan line by line until we come to a line ending with
  284.      * a <NL><NL> or <NL><TAB> or <NL><SPACE>
  285.      *
  286.      * PLUS: if there's a quote string, a quoted-to-non-quoted
  287.      *     line transition.
  288.      */
  289.     quoted = (Pmaster && Pmaster->quote_str
  290.           && quote_match(Pmaster->quote_str, curwp->w_dotp));
  291.     qlen   = quoted ? strlen(Pmaster->quote_str) : 0;
  292.     while(lback(curwp->w_dotp) != curbp->b_linep
  293.           && llength(lback(curwp->w_dotp)) > qlen
  294.           && ((Pmaster && Pmaster->quote_str)
  295.             ? quoted == quote_match(Pmaster->quote_str,
  296.                         lback(curwp->w_dotp))
  297.             : 1)
  298.           && lgetc(curwp->w_dotp, qlen).c != TAB
  299.           && lgetc(curwp->w_dotp, qlen).c != ' ')
  300.       curwp->w_dotp = lback(curwp->w_dotp);
  301.  
  302.     if(n){
  303.         /* keep looking */
  304.         if(lback(curwp->w_dotp) == curbp->b_linep)
  305.           break;
  306.         else
  307.           curwp->w_dotp = lback(curwp->w_dotp);
  308.  
  309.         curwp->w_doto = 0;
  310.     }
  311.     else{
  312.       /* leave cursor on first word in para */
  313.         curwp->w_doto = 0;
  314.         while(isspace((unsigned char)lgetc(curwp->w_dotp, curwp->w_doto).c))
  315.           if(++curwp->w_doto >= llength(curwp->w_dotp)){
  316.           curwp->w_doto = 0;
  317.           curwp->w_dotp = lforw(curwp->w_dotp);
  318.           if(curwp->w_dotp == curbp->b_linep)
  319.             break;
  320.           }
  321.     }
  322.     }
  323.  
  324.     curwp->w_flag |= WFMOVE;    /* force screen update */
  325.     return(TRUE);
  326. }
  327.  
  328.  
  329. /* 
  330.  * go forword to the end of the current paragraph
  331.  * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  332.  * combination to delimit the begining of a paragraph
  333.  */
  334. gotoeop(f, n)
  335. int f, n;    /* default Flag & Numeric argument */
  336.  
  337. {
  338.     int quoted, qlen;
  339.  
  340.     if (n < 0)    /* the other way...*/
  341.       return(gotobop(f, -n));
  342.  
  343.     while (n-- > 0) {    /* for each one asked for */
  344.  
  345.     while(lisblank(curwp->w_dotp)){
  346.         curwp->w_doto = 0;
  347.         if((curwp->w_dotp = lforw(curwp->w_dotp)) == curbp->b_linep)
  348.           break;
  349.     }
  350.  
  351.     /* scan line by line until we come to a line ending with
  352.      * a <NL><NL> or <NL><TAB> or <NL><SPACE>
  353.      *
  354.      * PLUS: if there's a quote string, a quoted-to-non-quoted
  355.      *     line transition.
  356.      */
  357.     quoted = (Pmaster && Pmaster->quote_str
  358.           && quote_match(Pmaster->quote_str, curwp->w_dotp));
  359.     qlen   = quoted ? strlen(Pmaster->quote_str) : 0;
  360.     
  361.     while(curwp->w_dotp != curbp->b_linep
  362.           && llength(lforw(curwp->w_dotp)) > qlen
  363.           && ((Pmaster && Pmaster->quote_str)
  364.            ? quoted == quote_match(Pmaster->quote_str,
  365.                        lforw(curwp->w_dotp))
  366.            : 1)
  367.           && lgetc(lforw(curwp->w_dotp), qlen).c != TAB
  368.           && lgetc(lforw(curwp->w_dotp), qlen).c != ' ')
  369.       curwp->w_dotp = lforw(curwp->w_dotp);
  370.  
  371.     curwp->w_doto = llength(curwp->w_dotp);
  372.  
  373.     /* still looking? */
  374.     if(n){
  375.         if(curwp->w_dotp == curbp->b_linep)
  376.           break;
  377.         else
  378.           curwp->w_dotp = lforw(curwp->w_dotp);
  379.  
  380.         curwp->w_doto = 0;
  381.     }
  382.     }
  383.  
  384.     curwp->w_flag |= WFMOVE;    /* force screen update */
  385.     return(curwp->w_dotp != curbp->b_linep);
  386. }
  387.  
  388. /*
  389.  * This routine, given a pointer to a LINE, and the current cursor goal
  390.  * column, return the best choice for the offset. The offset is returned.
  391.  * Used by "C-N" and "C-P".
  392.  */
  393. getgoal(dlp)
  394. register LINE   *dlp;
  395. {
  396.     register int    c;
  397.     register int    col;
  398.     register int    newcol;
  399.     register int    dbo;
  400.  
  401.     col = 0;
  402.     dbo = 0;
  403.     while (dbo != llength(dlp)) {
  404.     c = lgetc(dlp, dbo).c;
  405.     newcol = col;
  406.     if (c == '\t')
  407.       newcol |= 0x07;
  408.     else if (c<0x20 || c==0x7F)
  409.       ++newcol;
  410.  
  411.     ++newcol;
  412.     if (newcol > curgoal)
  413.       break;
  414.  
  415.     col = newcol;
  416.     ++dbo;
  417.     }
  418.  
  419.     return (dbo);
  420. }
  421.  
  422.  
  423.  
  424. /*
  425.  * Scroll the display forward (up) n lines.
  426.  */
  427. scrollforw (n, movedot)
  428. register int    n;
  429. int        movedot;
  430. {
  431.     register LINE   *lp;
  432.     LINE        *lp2;
  433.     register int    nl;
  434.     int            i;
  435.  
  436.     nl = n;
  437.     lp = curwp->w_linep;
  438.     while (n-- && lp!=curbp->b_linep)
  439.       lp = lforw(lp);
  440.  
  441.     if (movedot) {            /* Move dot to top of page. */
  442.     curwp->w_dotp  = lp;
  443.     curwp->w_doto  = 0;
  444.     }
  445.  
  446.     curwp->w_flag |= WFHARD;
  447.     if(lp == curbp->b_linep)
  448.       return(TRUE);
  449.     else
  450.       curwp->w_linep = lp;
  451.  
  452.     /*
  453.      * if the header is open, close it ...
  454.      */
  455.     if(Pmaster && Pmaster->headents && ComposerTopLine != COMPOSER_TOP_LINE){
  456.     n -= ComposerTopLine - COMPOSER_TOP_LINE;
  457.     ToggleHeader(0);
  458.     }
  459.  
  460.     /*
  461.      * scroll down from the top the same number of lines we've moved 
  462.      * forward
  463.      */
  464.     if(optimize)
  465.       scrollup(curwp, -1, nl-n-1);
  466.  
  467.     if(!movedot){
  468.     /* Requested to not move the dot.  Look for the dot in the current
  469.      * window.  loop through all lines, stop when at end of window
  470.      * or endof buffer.  If the dot is found, it can stay where it
  471.      * is, otherwise we do need to move it.
  472.      */
  473.     movedot = TRUE;
  474.     for (    lp2 = lp, i = 0; 
  475.         lp2 != curbp->b_linep && i < curwp->w_ntrows;  
  476.         lp2 = lforw(lp2), ++i) {
  477.         if (curwp->w_dotp == lp2) {
  478.          movedot = FALSE;
  479.          break;
  480.         }
  481.         }
  482.     if (movedot) {
  483.         /* Dot not found in window.  Move to first line of window. */
  484.         curwp->w_dotp  = lp;
  485.         curwp->w_doto  = 0;
  486.         }
  487.     }
  488.  
  489.     return (TRUE);
  490. }
  491.  
  492.  
  493. /*
  494.  * Scroll forward by a specified number of lines, or by a full page if no
  495.  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  496.  * the overlap; this value is the default overlap value in ITS EMACS. Because
  497.  * this zaps the top line in the display window, we have to do a hard update.
  498.  */
  499. forwpage(f, n)
  500. int             f;
  501. register int    n;
  502. {
  503.  
  504.     if (f == FALSE) {
  505.     n = curwp->w_ntrows - 2;        /* Default scroll.      */
  506.     if (n <= 0)                     /* Forget the overlap   */
  507.       n = 1;                  /* if tiny window.      */
  508.     } else if (n < 0)
  509.       return (backpage(f, -n));
  510. #if     CVMVAS
  511.     else                                    /* Convert from pages   */
  512.       n *= curwp->w_ntrows;           /* to lines.            */
  513. #endif
  514.     return (scrollforw (n, TRUE));
  515. }
  516.  
  517.  
  518. /*
  519.  * Scroll back (down) number of lines.  
  520.  */
  521. scrollback (n, movedot)
  522. register int    n;
  523. int        movedot;
  524. {
  525.     register LINE   *lp, *tp;
  526.     register int    nl;
  527.     int             status = 0;
  528.     int            i;
  529.  
  530.     if(Pmaster && Pmaster->headents){
  531.     /*
  532.      * go up into editing the mail header if on the top line
  533.      * and the user hits the up arrow!!!
  534.      */
  535.     if (lback(curwp->w_dotp) == curbp->b_linep){
  536.         /*
  537.          * if the editor returns anything except -1 then the user
  538.          * has requested something special, so let pico know...
  539.          */
  540.         return(HeaderEditor(1, 1));
  541.     }
  542.     }
  543.  
  544.     /*
  545.      * Count back the number of lines requested.
  546.      */
  547.     nl = n;
  548.     lp = curwp->w_linep;
  549.     while (n-- && lback(lp)!=curbp->b_linep)
  550.       lp = lback(lp);
  551.  
  552.     curwp->w_linep = lp;
  553.     curwp->w_flag |= WFHARD;
  554.  
  555.     /*
  556.      * scroll down from the top the same number of lines we've moved 
  557.      * forward
  558.      *
  559.      * This isn't too cool, but it has to be this way so we can 
  560.      * gracefully scroll in the message header
  561.      */
  562.     if(Pmaster && Pmaster->headents){
  563.     if((lback(lp)==curbp->b_linep) && (ComposerTopLine==COMPOSER_TOP_LINE))
  564.       n -= entry_line(1000, TRUE); /* never more than 1000 headers */
  565.     if(nl-n-1 < curwp->w_ntrows)
  566.       if(optimize)
  567.         scrolldown(curwp, -1, nl-n-1);
  568.     }
  569.     else
  570.       if(optimize)
  571.     scrolldown(curwp, -1, nl-n-1);
  572.  
  573.     if(Pmaster && Pmaster->headents){
  574.     /*
  575.      * if we're at the top of the page, and the header is closed, 
  576.      * open it ...
  577.      */
  578.     if((lback(lp) == curbp->b_linep) 
  579.        && (ComposerTopLine == COMPOSER_TOP_LINE)){
  580.         ToggleHeader(1);
  581.         movecursor(ComposerTopLine, 0);
  582.     }
  583.     }
  584.     
  585.     /*
  586.      * Decide if we move the dot or not.  Calculation done AFTER deciding
  587.      * if we display the header because that will change the number of
  588.      * lines on the screen.
  589.      */
  590.     if (movedot) {
  591.     /* Dot gets put at top of window. */
  592.     curwp->w_dotp  = curwp->w_linep;
  593.     curwp->w_doto  = 0;
  594.     }
  595.     else {
  596.     /* Requested not to move dot, but we do need to keep in on
  597.      * the screen.  Verify that it is still in the range of lines
  598.      * visable in the window.  Loop from the first line to the
  599.      * last line, until we reach the end of the buffer or the end
  600.      * of the window.  If we find the dot, then we don't need
  601.      * to move it. */
  602.     movedot = TRUE;
  603.     for (    tp = curwp->w_linep, i = 0; 
  604.         tp != curbp->b_linep && i < curwp->w_ntrows;  
  605.         tp = lforw(tp), ++i) {
  606.         if (curwp->w_dotp == tp) {
  607.          movedot = FALSE;
  608.          break;
  609.         }
  610.         }
  611.     if (movedot) {
  612.         /* Dot not found in window.  Move to last line of window. */
  613.         curwp->w_dotp  = lback (tp);
  614.         curwp->w_doto  = 0;
  615.         }
  616.     }
  617.  
  618.     return (TRUE);
  619. }
  620.  
  621.  
  622.  
  623.  
  624. /*
  625.  * This command is like "forwpage", but it goes backwards. The "2", like
  626.  * above, is the overlap between the two windows. The value is from the ITS
  627.  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  628.  * reason.
  629.  */
  630. backpage(f, n)
  631. int             f;
  632. register int    n;
  633. {
  634.  
  635.     if (f == FALSE) {
  636.     n = curwp->w_ntrows - 2;        /* Default scroll.      */
  637.     if (n <= 0)                     /* Don't blow up if the */
  638.       n = 1;                  /* window is tiny.      */
  639.     } else if (n < 0)
  640.       return (forwpage(f, -n));
  641. #if     CVMVAS
  642.     else                                    /* Convert from pages   */
  643.       n *= curwp->w_ntrows;           /* to lines.            */
  644. #endif
  645.     return (scrollback (n, TRUE));
  646. }
  647.  
  648.  
  649.  
  650. scrollupline (f, n)
  651. int f, n;
  652. {
  653.     return (scrollback (1, FALSE));
  654. }
  655.  
  656.  
  657. scrolldownline (f, n)
  658. int f, n;
  659. {
  660.     return (scrollforw (1, FALSE));
  661. }
  662.  
  663.  
  664.  
  665. /*
  666.  * Scroll to a position.
  667.  */
  668. scrollto (f, n)
  669. int f, n;
  670. {
  671. #ifdef _WINDOWS
  672.     long    scrollLine;
  673.     LINE    *lp;
  674.     int        i;
  675.     
  676.     scrollLine = mswin_getscrollto ();
  677.     
  678.     /*
  679.      * Starting at the first data line in the buffer, step forward
  680.      * 'scrollLine' lines to find the new top line.  It is a circular
  681.      * list of buffers, so watch for the first line to reappear.  if
  682.      * it does, we have some sort of internal error, abort scroll
  683.      * operation.  Also watch for NULL, just in case.
  684.      */
  685.     lp = lforw (curbp->b_linep);
  686.     for (i = 0; i < scrollLine && lp != curbp->b_linep && lp != NULL; ++i)
  687.     lp = lforw(lp);
  688.  
  689.     if (lp == curbp->b_linep || lp == NULL)
  690.     return (FALSE);                    /* Whoops! */
  691.     
  692.  
  693.     /* Set the new top line for the window and flag a redraw. */
  694.     curwp->w_linep = lp;
  695.     curwp->w_dotp  = lp;
  696.     curwp->w_doto  = 0;
  697.     curwp->w_flag |= WFHARD;
  698.     
  699.     if(Pmaster && Pmaster->headents){
  700.     /*
  701.      * If we are at the top of the page and header not open, open it.
  702.      * If we are not at the top of the page and the header is open,
  703.      * close it.
  704.      */
  705.     if((lback(lp) == curbp->b_linep) 
  706.        && (ComposerTopLine == COMPOSER_TOP_LINE)){
  707.         ToggleHeader(1);
  708.         movecursor(ComposerTopLine, 0);
  709.     }
  710.     else if((lback(lp) != curbp->b_linep) 
  711.        && (ComposerTopLine != COMPOSER_TOP_LINE)){
  712.        ToggleHeader (0);
  713.         }
  714.     }
  715.  
  716.     return (TRUE);
  717. #endif
  718. }
  719.  
  720.  
  721.  
  722. /*
  723.  * Set the mark in the current window to the value of "." in the window. No
  724.  * errors are possible. Bound to "M-.".  If told to set an already set mark
  725.  * unset it.
  726.  */
  727. setmark(f, n)
  728. int f, n;
  729. {
  730.     if(!curwp->w_markp){
  731.         curwp->w_markp = curwp->w_dotp;
  732.         curwp->w_marko = curwp->w_doto;
  733.     emlwrite("Mark Set", NULL);
  734.     }
  735.     else{
  736.     /* clear inverse chars between here and dot */
  737.     markregion(0);
  738.     curwp->w_markp = NULL;
  739.     emlwrite("Mark UNset", NULL);
  740.     }
  741.  
  742. #ifdef    _WINDOWS
  743.     mswin_allowcopycut(curwp->w_markp ? kremove : NULL);
  744. #endif
  745.     return (TRUE);
  746. }
  747.  
  748.  
  749. /*
  750.  * Swap the values of "." and "mark" in the current window. This is pretty
  751.  * easy, bacause all of the hard work gets done by the standard routine
  752.  * that moves the mark about. The only possible error is "no mark". Bound to
  753.  * "C-X C-X".
  754.  */
  755. swapmark(f, n)
  756. int f, n;
  757. {
  758.     register LINE   *odotp;
  759.     register int    odoto;
  760.  
  761.     if (curwp->w_markp == NULL) {
  762.     if(Pmaster == NULL)
  763.       emlwrite("No mark in this window", NULL);
  764.     return (FALSE);
  765.     }
  766.  
  767.     odotp = curwp->w_dotp;
  768.     odoto = curwp->w_doto;
  769.     curwp->w_dotp  = curwp->w_markp;
  770.     curwp->w_doto  = curwp->w_marko;
  771.     curwp->w_markp = odotp;
  772.     curwp->w_marko = odoto;
  773.     curwp->w_flag |= WFMOVE;
  774.     return (TRUE);
  775. }
  776.  
  777.  
  778. /*
  779.  * Set the mark in the current window to the value of "." in the window. No
  780.  * errors are possible. Bound to "M-.".  If told to set an already set mark
  781.  * unset it.
  782.  */
  783. setimark(f, n)
  784. int f, n;
  785. {
  786.     curwp->w_imarkp = curwp->w_dotp;
  787.     curwp->w_imarko = curwp->w_doto;
  788.     return(TRUE);
  789. }
  790.  
  791.  
  792. /*
  793.  * Swap the values of "." and "mark" in the current window. This is pretty
  794.  * easy, bacause all of the hard work gets done by the standard routine
  795.  * that moves the mark about. The only possible error is "no mark". Bound to
  796.  * "C-X C-X".
  797.  */
  798. swapimark(f, n)
  799. int f, n;
  800. {
  801.     register LINE   *odotp;
  802.     register int    odoto;
  803.  
  804.     if (curwp->w_imarkp == NULL) {
  805.     if(Pmaster == NULL)
  806.       emlwrite("Programmer botch! No mark in this window", NULL);
  807.     return (FALSE);
  808.     }
  809.  
  810.     odotp = curwp->w_dotp;
  811.     odoto = curwp->w_doto;
  812.     curwp->w_dotp  = curwp->w_imarkp;
  813.     curwp->w_doto  = curwp->w_imarko;
  814.     curwp->w_imarkp = odotp;
  815.     curwp->w_imarko = odoto;
  816.     curwp->w_flag |= WFMOVE;
  817.     return (TRUE);
  818. }
  819.  
  820.  
  821.  
  822. #ifdef MOUSE
  823.  
  824. /*
  825.  * Handle a mouse down.
  826.  */
  827. mousepress (f, n)
  828. int f, n;
  829. {
  830.     MOUSEPRESS    mp;
  831.     LINE    *lp;
  832.     int    i;
  833.  
  834.  
  835.     mouse_get_last (NULL, &mp);
  836.  
  837.  
  838.     lp = curwp->w_linep;
  839.     i = mp.row - ((Pmaster && Pmaster->headents) ? ComposerTopLine : 2);
  840.     if (i < 0) {
  841.     if (Pmaster) {
  842.         /* Clear existing region. */
  843.         if (curwp->w_markp)
  844.         setmark(0,1);    
  845.  
  846.         /* Move to top of document before editing header. */
  847.         curwp->w_dotp = curwp->w_linep;
  848.         curwp->w_doto = 0;
  849.         curwp->w_flag |= WFMOVE;
  850.         update ();                /* And update. */
  851.  
  852.         return (HeaderEditor (1, 1));
  853.         }
  854.     }
  855.     else {
  856.     while(i-- && lp != curbp->b_linep)
  857.       lp = lforw(lp);
  858.  
  859.     curgoal = mp.col;
  860.     curwp->w_dotp = lp;
  861.     curwp->w_doto = getgoal(lp);
  862.     curwp->w_flag |= WFMOVE;
  863.  
  864.     if(mp.doubleclick)
  865.         setmark(0, 1);
  866.     }
  867. }
  868. #endif
  869.