home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / jade-3.0.lha / Jade / src / housekeeping.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-19  |  11.4 KB  |  425 lines

  1. /* housekeeping.c -- Generally editor fiddly stuff
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4. This file is part of Jade.
  5.  
  6. Jade is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. Jade is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with Jade; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. _PR void keepposaddx(TX *, long, long, long);
  24. _PR void keeppossubx(TX *, long, long, long);
  25. _PR void keepposaddy(TX *, long, long);
  26. _PR void keeppossuby(TX *, long, long);
  27. _PR void keeppossplity(TX *, long, long);
  28. _PR void keepposjoiny(TX *, long, long);
  29. _PR void resyncx(VW *);
  30. _PR void resyncy(VW *);
  31. _PR void resyncxy(VW *);
  32. _PR void setstartcol(VW *, long);
  33. _PR void setstartline(VW *, long);
  34. _PR void resetallviews(TX *);
  35.  
  36. /*
  37.  * The next few routines deal with updating the various references to
  38.  * coordinates throughout the views after chunks have been deleted and
  39.  * inserted.
  40.  */
  41. void
  42. keepposaddx(TX *tx, long addx, long xpos, long ypos)
  43. {
  44.     VW *thisvw;
  45.     Mark *thismark;
  46.  
  47. #define UPD(x,y) if((y == ypos) && (x >= xpos)) x += addx
  48.  
  49.     for(thisvw = ViewChain; thisvw; thisvw = thisvw->vw_Next)
  50.     {
  51.     if(thisvw->vw_Tx == tx)
  52.     {
  53.         UPD(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  54.         UPD(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  55.         UPD(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  56.     }
  57.     }
  58.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  59.     {
  60.     UPD(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  61.     }
  62.     UPD(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  63.     UPD(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  64.     UPD(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  65.     UPD(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  66. #if 1
  67.     if((tx->tx_ModStart.pos_Line == ypos) && (tx->tx_ModStart.pos_Col > xpos))
  68.     tx->tx_ModStart.pos_Col += addx;
  69. #else
  70.     UPD(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  71. #endif
  72.     UPD(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  73.  
  74. #undef UPD(x,y)
  75. }
  76.  
  77. void
  78. keeppossubx(TX *tx, long subx, long xpos, long ypos)
  79. {
  80.     VW *thisvw;
  81.     Mark *thismark;
  82.  
  83. #define UPD(x,y) if((y == ypos) && (x >= xpos)) { if((x -= subx) < xpos) x = xpos; }
  84.  
  85.     for(thisvw = ViewChain; thisvw; thisvw = thisvw->vw_Next)
  86.     {
  87.     if(thisvw->vw_Tx == tx)
  88.     {
  89.         UPD(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  90.         UPD(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  91.         UPD(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  92.     }
  93.     }
  94.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  95.     {
  96.     UPD(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  97.     }
  98.     UPD(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  99.     UPD(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  100.     UPD(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  101.     UPD(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  102.  
  103.     UPD(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  104. #if 1
  105.     if((tx->tx_ModEnd.pos_Line == ypos) && (tx->tx_ModEnd.pos_Col > xpos))
  106.     {
  107.     if((tx->tx_ModEnd.pos_Col -= subx) < xpos)
  108.         tx->tx_ModEnd.pos_Col = xpos;
  109.     }
  110. #else
  111.     UPD(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  112. #endif
  113.  
  114. #undef UPD(x,y)
  115. }
  116.  
  117. /*
  118.  * Whole lines only please
  119.  */
  120. void
  121. keepposaddy(TX *tx, long addy, long ypos)
  122. {
  123.     VW *thisvw;
  124.     Mark *thismark;
  125.  
  126. #define UPD(y) if(y >= ypos) y += addy
  127.  
  128.     for(thisvw = ViewChain; thisvw; thisvw = thisvw->vw_Next)
  129.     {
  130.     if(thisvw->vw_Tx == tx)
  131.     {
  132.         UPD(thisvw->vw_CursorPos.pos_Line);
  133.         UPD(thisvw->vw_BlockS.pos_Line);
  134.         UPD(thisvw->vw_BlockE.pos_Line);
  135.         if(thisvw != CurrVW)
  136.         UPD(thisvw->vw_StartLine);
  137.     }
  138.     }
  139.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  140.     {
  141.     UPD(VPOS(thismark->mk_Pos).pos_Line);
  142.     }
  143.     UPD(tx->tx_SavedCPos.pos_Line);
  144.     UPD(tx->tx_SavedWPos.pos_Line);
  145.     UPD(tx->tx_SavedBlockPos[0].pos_Line);
  146.     UPD(tx->tx_SavedBlockPos[1].pos_Line);
  147.  
  148. #if 1
  149.     if(tx->tx_ModStart.pos_Line > ypos)
  150.     tx->tx_ModStart.pos_Line += addy;
  151. #else
  152.     UPD(tx->tx_ModStart.pos_Line);
  153. #endif
  154.     UPD(tx->tx_ModEnd.pos_Line);
  155.  
  156. #undef UPD(y)
  157. }
  158.  
  159. /*
  160.  * Whole lines only please
  161.  */
  162. void
  163. keeppossuby(TX *tx, long suby, long ypos)
  164. {
  165.     VW *thisvw;
  166.     Mark *thismark;
  167.  
  168. #define UPD(y) if(y > ypos) { if((y -= suby) < ypos) y = ypos; }
  169. #define UPD2(x,y) if(y >= ypos) { if((y -= suby) < ypos) {y = ypos; x = 0; }}
  170.  
  171.     for(thisvw = ViewChain; thisvw; thisvw = thisvw->vw_Next)
  172.     {
  173.     if(thisvw->vw_Tx == tx)
  174.     {
  175.         UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  176.         UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  177.         UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  178.         if(thisvw != CurrVW)
  179.         UPD(thisvw->vw_StartLine);
  180.     }
  181.     }
  182.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  183.     {
  184.     UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  185.     }
  186.     UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  187.     UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  188.     UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  189.     UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  190.  
  191.     UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  192. #if 1
  193.     if(tx->tx_ModEnd.pos_Line > ypos)
  194.     {
  195.     if((tx->tx_ModEnd.pos_Line -= suby) < ypos)
  196.     {
  197.         tx->tx_ModEnd.pos_Line = ypos;
  198.         tx->tx_ModEnd.pos_Col = 0;
  199.     }
  200.     }
  201. #else
  202.     UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  203. #endif
  204.  
  205. #undef UPD(y)
  206. #undef UPD2(x,y)
  207. }
  208.  
  209. /*
  210.  * Use when splitting a line into 2, cursor should be at position of split
  211.  */
  212. void
  213. keeppossplity(TX *tx, long xpos, long ypos)
  214. {
  215.     VW *thisvw;
  216.     Mark *thismark;
  217.  
  218. #define UPD(y) if(y > ypos) y++
  219. #define UPD2(x,y) if((y == ypos) && (x >= xpos)) { x -= xpos; y++; } else if(y > ypos) y++
  220.  
  221.     for(thisvw = ViewChain; thisvw; thisvw = thisvw->vw_Next)
  222.     {
  223.     if(thisvw->vw_Tx == tx)
  224.     {
  225.         UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  226.         UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  227.         UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  228.         if(thisvw != CurrVW)
  229.         UPD(thisvw->vw_StartLine);
  230.     }
  231.     }
  232.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  233.     {
  234.     UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  235.     }
  236.     UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  237.     UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  238.     UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  239.     UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  240.  
  241. #if 1
  242.     if((tx->tx_ModStart.pos_Line == ypos) && (tx->tx_ModStart.pos_Col > xpos))
  243.     {
  244.     tx->tx_ModStart.pos_Col -= xpos;
  245.     tx->tx_ModStart.pos_Line++;
  246.     }
  247.     else if(tx->tx_ModStart.pos_Line > ypos)
  248.     tx->tx_ModStart.pos_Line++;
  249. #else
  250.     UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  251. #endif
  252.     UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  253.  
  254. #undef UPD(y)
  255. #undef UPD2(x,y)
  256. }
  257.  
  258. /*
  259.  * Use when compacting 2 adjacent lines into one
  260.  */
  261. void
  262. keepposjoiny(TX *tx, long xpos, long ypos)
  263. {
  264.     VW *thisvw;
  265.     Mark *thismark;
  266.  
  267. #define UPD(y) if(y > ypos) y--
  268. #define UPD2(x,y) if(y > ypos) { if(y == ypos + 1) x += xpos; y--; }
  269.  
  270.     for(thisvw = ViewChain; thisvw; thisvw = thisvw->vw_Next)
  271.     {
  272.     if(thisvw->vw_Tx == tx)
  273.     {
  274.         UPD2(thisvw->vw_CursorPos.pos_Col, thisvw->vw_CursorPos.pos_Line);
  275.         UPD2(thisvw->vw_BlockS.pos_Col, thisvw->vw_BlockS.pos_Line);
  276.         UPD2(thisvw->vw_BlockE.pos_Col, thisvw->vw_BlockE.pos_Line);
  277.         if(thisvw != CurrVW)
  278.         UPD(thisvw->vw_StartLine);
  279.     }
  280.     }
  281.     for(thismark = tx->tx_MarkChain; thismark; thismark = thismark->mk_Next)
  282.     {
  283.     UPD2(VPOS(thismark->mk_Pos).pos_Col, VPOS(thismark->mk_Pos).pos_Line);
  284.     }
  285.     UPD2(tx->tx_SavedCPos.pos_Col, tx->tx_SavedCPos.pos_Line);
  286.     UPD2(tx->tx_SavedWPos.pos_Col, tx->tx_SavedWPos.pos_Line);
  287.     UPD2(tx->tx_SavedBlockPos[0].pos_Col, tx->tx_SavedBlockPos[0].pos_Line);
  288.     UPD2(tx->tx_SavedBlockPos[1].pos_Col, tx->tx_SavedBlockPos[1].pos_Line);
  289.     UPD2(tx->tx_ModStart.pos_Col, tx->tx_ModStart.pos_Line);
  290.     UPD2(tx->tx_ModEnd.pos_Col, tx->tx_ModEnd.pos_Line);
  291.  
  292. #undef UPD(y)
  293. #undef UPD2(x,y)
  294. }
  295.  
  296. /*
  297.  * These routines are called to recalculate the cursor's position on the
  298.  * screen,
  299.  */
  300. void
  301. resyncx(VW *vw)
  302. {
  303.     while((vw->vw_CursorPos.pos_Col - vw->vw_StartCol) >= vw->vw_MaxX)
  304.     {
  305.     vw->vw_StartCol += vw->vw_XStep;
  306.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  307.     }
  308.     while(vw->vw_CursorPos.pos_Col < vw->vw_StartCol)
  309.     {
  310.     vw->vw_StartCol -= vw->vw_XStep;
  311.     if(vw->vw_StartCol < 0)
  312.         vw->vw_StartCol = 0;
  313.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  314.     }
  315. }
  316.  
  317. void
  318. resyncy(VW *vw)
  319. {
  320.     TX *tx = vw->vw_Tx;
  321.     long y = vw->vw_CursorPos.pos_Line - vw->vw_LastDisplayOrigin.pos_Line;
  322.     if(y < 0)
  323.     {
  324.     if(-y > vw->vw_YStep)
  325.         vw->vw_StartLine = vw->vw_CursorPos.pos_Line;
  326.     else
  327.     {
  328.         vw->vw_StartLine -= vw->vw_YStep;
  329.         if(vw->vw_StartLine < 0)
  330.         vw->vw_StartLine = 0;
  331.     }
  332.     }
  333.     else if(y >= vw->vw_MaxY)
  334.     {
  335.     if((vw->vw_MaxY + vw->vw_YStep) <= y)
  336.         vw->vw_StartLine = vw->vw_CursorPos.pos_Line - vw->vw_MaxY + 1;
  337.     else
  338.     {
  339.         vw->vw_StartLine += vw->vw_YStep;
  340.         if(vw->vw_StartLine >= tx->tx_NumLines)
  341.         vw->vw_StartLine = tx->tx_NumLines - 1;
  342.     }
  343.     }
  344. }
  345.  
  346. void
  347. resyncxy(VW *vw)
  348. {
  349.     vw->vw_LastDisplayOrigin = vw->vw_DisplayOrigin;
  350.     resyncx(vw);
  351.     resyncy(vw);
  352. }
  353.  
  354. void
  355. setstartcol(VW *vw, long col)
  356. {
  357.     if(vw->vw_StartCol != col)
  358.     {
  359.     vw->vw_Flags |= VWFF_FORCE_REFRESH;
  360.     vw->vw_StartCol = col;
  361.     }
  362. }
  363.  
  364. void
  365. setstartline(VW *vw, long line)
  366. {
  367.     long cline = vw->vw_StartLine;
  368.     if(line != cline)
  369.     {
  370.     long yord = vw->vw_CursorPos.pos_Line - cline;
  371.     vw->vw_StartLine = line;
  372.     if(!(vw->vw_Flags & VWFF_FORCE_REFRESH))
  373.     {
  374.         long diff = line - cline;
  375.         if((diff > 0) && (diff <= vw->vw_MaxScroll))
  376.         {
  377.         long ypos = vw->vw_MaxY - 1;
  378.         scrollvw(vw, diff);
  379.         redrawlines(vw, cline + ypos, line + ypos + 1);
  380.         }
  381.         else if((diff < 0) && (diff >= -vw->vw_MaxScroll))
  382.         {
  383.         scrollvw(vw, diff);
  384.         redrawlines(vw, line, cline);
  385.         }
  386.         else
  387.         vw->vw_Flags |= VWFF_FORCE_REFRESH;
  388.     }
  389.     else
  390.         vw->vw_Flags |= VWFF_FORCE_REFRESH;
  391.     vw->vw_CursorPos.pos_Line = line + yord;
  392.     if(vw->vw_CursorPos.pos_Line >= vw->vw_Tx->tx_NumLines)
  393.         vw->vw_CursorPos.pos_Line = vw->vw_Tx->tx_NumLines - 1;
  394.     }
  395. }
  396.  
  397. /*
  398.  * This makes all views of this file have their cursor at the top of the
  399.  * file, it also refreshes each view.
  400.  */
  401. void
  402. resetallviews(TX *tx)
  403. {
  404.     VW *thisvw;
  405.     for(thisvw = ViewChain; thisvw; thisvw = thisvw->vw_Next)
  406.     {
  407.     if(thisvw->vw_Tx == tx)
  408.     {
  409.         thisvw->vw_CursorPos.pos_Col = 0;
  410.         thisvw->vw_CursorPos.pos_Line = 0;
  411.         thisvw->vw_StartCol = 0;
  412.         thisvw->vw_StartLine = 0;
  413.         thisvw->vw_BlockStatus = -1;
  414.         thisvw->vw_Flags |= VWFF_FORCE_REFRESH;
  415.         thisvw->vw_NonStdTitle = FALSE;
  416.         stdtitle(thisvw);
  417.     }
  418.     tx->tx_SavedCPos.pos_Col = 0;
  419.     tx->tx_SavedCPos.pos_Line = 0;
  420.     tx->tx_SavedWPos.pos_Col = 0;
  421.     tx->tx_SavedWPos.pos_Line = 0;
  422.     tx->tx_SavedBlockStatus = -1;
  423.     }
  424. }
  425.