home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DClap / DTableView.cpp < prev    next >
Encoding:
Text File  |  1996-07-05  |  28.2 KB  |  1,178 lines  |  [TEXT/R*ch]

  1. // DTableView.cp
  2. // d.g.gilbert
  3.  
  4. // this class is used a lot for various display/user interaction arrays of items
  5. // still needs work for multiple selections, run arrays for height/width?
  6. // 
  7.  
  8. #include "DTableView.h"
  9. #include "DTabSelect.h"
  10. #include <DPanel.h>
  11. #include <DUtil.h>
  12. #include <DApplication.h>
  13. #include <Dvibrant.h>
  14. #include <DTracker.h>
  15. #include <ncbi.h>
  16. #include <dgg.h>
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23. //class DTableView : public DPanel
  24.  
  25.  
  26. DTableView::DTableView(long id, DView* itsSuperior, short pixwidth, short pixheight, 
  27.                                                 long nrows, long ncols, short itemwidth, short itemheight,
  28.                                                 Boolean hasVscroll, Boolean hasHscroll):
  29.         DAutoPanel( id, itsSuperior, pixwidth, pixheight, hasVscroll, hasHscroll),
  30.         fItemWidth(itemwidth), fItemHeight(itemheight),
  31.         fSelection(NULL), fHScrollScale(1), fVScrollScale(1),
  32.         fTop(0), fLeft(0), fColsDrawn(0), fMaxRows(nrows), fMaxCols(ncols), 
  33.         fIsPrinting(false), fWidths(NULL), fHeights(NULL),
  34.         fFont(Nlm_programFont)
  35. {
  36.     Nlm_BaR sb;
  37.     sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  38.   fHasVbar= (sb != NULL);
  39.   sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  40.   fHasHbar= (sb != NULL);
  41.     fSelection= new DTabSelection( this, fMaxRows, fMaxCols);
  42.     
  43.   FindLocation();
  44.   SetTableSize( fMaxRows, fMaxCols);
  45.     fTabSelector= new DTabSelector( this);
  46.     //fTabSelector->ITabSelector( this);
  47.     fCurrentTracker= fTabSelector;
  48. }
  49.         
  50. DTableView::~DTableView()
  51. {
  52.     MemFree(fWidths);
  53.     MemFree(fHeights);
  54.     //if (fTabSelector) delete fTabSelector; //<< causing Motif crashes !?
  55. }
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62. Nlm_Boolean DTableView::ScrollIntoView(Nlm_RecT itemr)
  63. {
  64.     enum { horizontal= false, vertical= true };
  65.     short    lastitem;
  66.     long    atpix;
  67.     Nlm_BaR sb;
  68.     Boolean didscroll= false;
  69.     
  70.      // fItemWidth << this isn't accurate for variable width/height.
  71.     if (fWidths) {
  72.         for (lastitem= fLeft, atpix= 0; lastitem< fMaxCols; lastitem++) { 
  73.             atpix += fWidths[lastitem]; 
  74.             if (atpix > fRect.right) break;
  75.             }
  76.         }
  77.     else
  78.         lastitem= fLeft + (fRect.right - fRect.left)/fItemWidth;
  79.      
  80.     if (itemr.left > lastitem || itemr.left < fLeft) {
  81.          didscroll= true;
  82.         sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  83.         if (sb) { 
  84.             //Nlm_ResetClip(); // ! TEST: are we losing scrollbar update due to cliprect?
  85.             long barval= itemr.left;
  86. #if 1
  87.             if (fHScrollScale > 1)  barval /= fHScrollScale;
  88. #endif
  89.             Nlm_SetValue(sb, Max(0, barval - 1));  // calls our scroll funct
  90.             }
  91.         }
  92.     
  93.     if (fHeights) {
  94.         for (lastitem= fTop, atpix= 0; lastitem< fMaxRows; lastitem++) { 
  95.             atpix += fHeights[lastitem]; 
  96.             if (atpix > fRect.bottom) break;
  97.             }
  98.         }
  99.     else
  100.         lastitem= fTop + (fRect.bottom - fRect.top)/fItemHeight;
  101.         
  102.     if (itemr.top > lastitem || itemr.top < fTop) {
  103.          didscroll= true;
  104.         sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  105.         if (sb) {
  106.             long barval= itemr.top;
  107. #if 1
  108.             if (fVScrollScale > 1)  barval /= fVScrollScale;
  109. #endif
  110.             Nlm_SetValue(sb,  Max(0, barval - 1));  
  111.             }
  112.         }
  113.         
  114.     return didscroll;
  115. }
  116.  
  117.  
  118.  
  119.  
  120. void DTableView::SetTableFont( Nlm_FonT itsFont)
  121. {
  122.     fFont= itsFont;
  123. }
  124.  
  125. void DTableView::SetTableSize( long rows, long cols)
  126. {
  127.     long i;
  128.     
  129.     if (fWidths && cols!=fMaxCols) {
  130.         fWidths= (short*)MemMore( fWidths, (cols+1) * sizeof(short));
  131.         for (i= fMaxCols; i<=cols; i++) fWidths[i]= fItemWidth;
  132.         }
  133.         
  134.     if (fHeights && rows!=fMaxRows) {
  135.         fHeights= (short*)MemMore( fHeights, (rows+1) * sizeof(short));
  136.         for (i= fMaxRows; i<=rows; i++) fHeights[i]= fItemHeight;
  137.         }
  138.     
  139.     fMaxRows= rows; 
  140.     fMaxCols= cols;
  141.     fSelection->SetTableSize( rows, cols);
  142.  
  143.     SetScrollPage();
  144. }
  145.  
  146. void DTableView::ChangeRowSize( long atrow, long deltarows)
  147. {
  148.     Boolean needupdate;
  149.     long newrows= Max(0, fMaxRows + deltarows);
  150.     Nlm_RecT  r;
  151.     ViewRect(fRect); 
  152.     Nlm_InsetRect( &fRect, 1, 1);
  153.     GetRowRect( atrow, r, (fMaxRows - atrow));
  154.     needupdate= Nlm_SectRect( &r, &fRect, &r);
  155.     //fSelection->ChangeRowSize( atrow, deltarows); // done thru SetTableSize
  156.     SetTableSize( newrows, fMaxCols);
  157.     if (needupdate) this->InvalRect( r);
  158. }
  159.  
  160. void DTableView::ChangeColSize( long atcol, long deltacols)
  161. {
  162.     long newcols= Max(0, fMaxCols + deltacols);
  163.     Boolean needupdate= (atcol >= fLeft && atcol <= (fRect.right - fRect.left) / fItemWidth);
  164.         // ^^ needs work
  165.     //fSelection->ChangeColSize( atcol, deltacols);// done thru SetTableSize
  166.     SetTableSize( fMaxRows, newcols);
  167.     if (needupdate) {
  168.         //this->Invalidate(); // locate just update rect??    
  169.         Nlm_RecT r;
  170.         long ncols= ((fRect.right - fRect.left) / fItemWidth) - atcol;
  171.         GetColRect( atcol, r, ncols);
  172.         this->InvalRect( r);
  173.         }
  174. }
  175.  
  176.         
  177. void DTableView::SetItemWidth(long atcol, long ncols, short itemwidth)
  178. {
  179.     long i;
  180.     if (ncols >= fMaxCols && !fWidths) {
  181.         fItemWidth= itemwidth;
  182.         }
  183.     else {
  184.         if (!fWidths) {
  185.             // make fWidths
  186.             fWidths= (short*)MemNew( (fMaxCols+1)*sizeof(short));
  187.             for (i= 0; i<=fMaxCols; i++) fWidths[i]= fItemWidth;
  188.             }
  189.         long ncol= Min(fMaxCols, atcol+ncols);
  190.         for (i= atcol; i<ncol; i++) fWidths[i]= itemwidth;
  191.     fItemWidth= Max( fItemWidth, itemwidth);
  192.         }
  193.   SetScrollPage();
  194. }
  195.  
  196. void DTableView::SetItemHeight(long atrow, long nrows, short itemheight)
  197. {
  198.     long i;
  199.     if (nrows >= fMaxRows && !fHeights) {
  200.         fItemHeight= itemheight;
  201.         }
  202.     else {
  203.         if (!fHeights) {
  204.             fHeights= (short*)MemNew( (fMaxRows+1)*sizeof(short));
  205.             for (i= 0; i<=fMaxRows; i++) fHeights[i]= fItemHeight;
  206.             }
  207.         long nrow= Min(fMaxRows, atrow+nrows);
  208.         for (i= atrow; i<nrow; i++) fHeights[i]= itemheight;
  209. #if 0
  210.     if (itemheight) fItemHeight= MIN( fItemHeight, itemheight);
  211. #else
  212.     fItemHeight= MAX( fItemHeight, itemheight);
  213. #endif
  214.         }
  215.   SetScrollPage();
  216. }
  217.         
  218.  
  219. long DTableView::GetItemWidth(long atcol)
  220. {
  221.     if (fWidths && atcol >= 0 && atcol < fMaxCols) 
  222.         return fWidths[atcol];
  223.     else 
  224.         return fItemWidth;
  225. }
  226.  
  227. long DTableView::GetItemHeight(long atrow)
  228. {
  229.     if (fHeights && atrow >= 0 && atrow < fMaxRows) 
  230.         return fHeights[atrow];
  231.     else 
  232.         return fItemHeight;
  233. }
  234.  
  235.         
  236. void DTableView::SetScrollPage()
  237. {
  238.     // set paging size of hor/vert sbars.. need to do on open & on resize
  239.     Nlm_BaR sb;
  240.     long pgDn, pg, maxn;
  241.     if (fHasHbar) {
  242.         sb = Nlm_GetSlateHScrollBar((Nlm_SlatE) GetNlmObject());
  243.         if (sb) {
  244.             pg= (fRect.right - fRect.left) / fItemWidth;
  245.             pgDn= Max(1, pg - 1);
  246.             maxn= Max( fMaxCols - pgDn, 1);
  247.  
  248. #if 1
  249.         // test fix for long int range !            
  250.             if (fMaxCols > SHRT_MAX) {
  251.                 fHScrollScale= (fMaxCols + SHRT_MAX-1) / SHRT_MAX;
  252.                 pg /= fHScrollScale;
  253.                 pgDn /= fHScrollScale;
  254.                 maxn /= fHScrollScale;
  255.                 }
  256.             else fHScrollScale= 1;
  257. #endif
  258.             Nlm_SetRange(sb, pgDn, pgDn, maxn);
  259.             }
  260.         }
  261.         
  262.     if (fHasVbar) {
  263.         sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) GetNlmObject());
  264.         if (sb) {
  265.             pg= (fRect.bottom - fRect.top) / fItemHeight;
  266.             pgDn= Max(1, pg - 1);
  267.             maxn= Max( fMaxRows - pgDn, 1);
  268. #if 1
  269.         // test fix for long int range !            
  270.             if (fMaxRows > SHRT_MAX) {
  271.                 fVScrollScale= (fMaxRows + SHRT_MAX-1) / SHRT_MAX;
  272.                 pg /= fVScrollScale;
  273.                 pgDn /= fVScrollScale;
  274.                 maxn /= fVScrollScale;
  275.                 }
  276.             else fVScrollScale= 1;
  277. #endif
  278.             Nlm_SetRange(sb, pgDn, pgDn, maxn);
  279.             }
  280.         }
  281. }
  282.  
  283. void DTableView::FindLocation()
  284. {
  285.     ViewRect(fRect); //this->GetPosition(fRect); // ?? this isn't changing except w/ resize ??
  286.     Nlm_InsetRect( &fRect, 1, 1);
  287.     SetScrollPage();
  288. }
  289.         
  290. void DTableView::SizeToSuperview( DView* super, Boolean horiz, Boolean vert)
  291. {
  292. #ifndef WIN_MSWIN
  293.     DView::SizeToSuperview(super, horiz, vert);
  294. #else
  295.     Nlm_RecT r, myr;
  296.     super->ViewRect(r);
  297.     ViewRect(myr);
  298.             // these sizes draw off by -1... thus the +1
  299.     if (horiz) {
  300.         myr.left = 0;
  301.         myr.right= myr.left + (r.right - r.left) +1;
  302. #ifdef WIN_MSWIN
  303.         if (fHasVbar) myr.right -= (Nlm_vScrollBarWidth - 8);
  304. #endif
  305.         }
  306.     if (vert) {
  307.         myr.top = 0;
  308.         myr.bottom = myr.top + (r.bottom - r.top) +1;
  309. #ifdef WIN_MSWIN
  310.         if (fHasHbar) myr.bottom -= (Nlm_hScrollBarHeight + 10);
  311. #endif
  312.         }
  313.     SetPosition( myr);
  314. #endif
  315.     this->FindLocation(); //?? added 14Mar94, gopher tables were doing this
  316. }
  317.  
  318.  
  319. void DTableView::Resize(DView* superview, Nlm_PoinT sizechange)
  320. {
  321.         // !! need this fRect change to deal w/ Resize() update event, 
  322.         // which isn't put in a nice event queue, but is done immediately !!
  323.     fRect.right  += sizechange.x;
  324.     fRect.bottom += sizechange.y;
  325.     DPanel::Resize(superview, sizechange);
  326.     FindLocation();
  327. }
  328.  
  329. void DTableView::Scroll(Boolean vertical, DView* scrollee, long newval, long oldval)
  330. {
  331.     Nlm_RecT    r = fRect;
  332.     long delta, i, diff;
  333.     this->Select(); // need for motif !
  334.     if (vertical) {
  335.         if (fVScrollScale>1) { newval *= fVScrollScale; oldval *= fVScrollScale; }
  336.         diff= newval-oldval;
  337.  
  338.       if (fHeights) {
  339.         delta= 0;
  340.             if (oldval>newval) {
  341.                 for (i=oldval-1; i>=newval; i--) delta -= fHeights[i];
  342.                 }
  343.         else {
  344.                 for (i=oldval; i<newval; i++) delta += fHeights[i];
  345.                 }
  346.             }
  347.         else
  348.             delta= diff * fItemHeight;
  349.  
  350.         fTop += diff;
  351.         Nlm_ScrollRect (&r, 0, -delta);
  352.         if (diff<0) r.bottom= r.top - delta; // + Min(10,-delta/2);
  353.         else r.top= r.bottom - delta; // - Min(10,delta/2);
  354.         }
  355.         
  356.     else {
  357.         if (fHScrollScale>1) { newval *= fHScrollScale; oldval *= fHScrollScale; }
  358.         diff= newval-oldval;
  359.  
  360. #if 1
  361.       if (fWidths) {
  362.         delta= 0;
  363.             if (oldval>newval) {
  364.                 for (i=oldval-1; i>=newval; i--) delta -= fWidths[i];
  365.                 }
  366.         else {
  367.                 for (i=oldval; i<newval; i++) delta += fWidths[i];
  368.                 }
  369.             }
  370.         else
  371.             delta= diff * fItemWidth;
  372.             
  373.         fLeft += diff;
  374.         Nlm_ScrollRect (&r, -delta, 0);
  375.         if (diff<0) r.right= Min(r.right, r.left - delta); // + Min(fItemWidth,-delta/2));
  376.         else r.left= Max(r.left, r.right - delta); // - Min(fItemWidth,delta/2));
  377. #else
  378.         if (fWidths) {
  379.             // fix later, for now redraw all w/o bitscroll
  380.             fLeft += diff;
  381.             }
  382.         else {
  383.             fLeft += diff;
  384.             delta= diff * fItemWidth;
  385.             Nlm_ScrollRect (&r, -delta, 0);
  386.             if (diff<0) r.right= r.left - delta + Min(10,-delta/2);
  387.             else r.left= r.right - delta - Min(10,delta/2);
  388.             }
  389. #endif
  390.         }
  391.     this->InvalRect( r);
  392.   Nlm_Update(); //!? need since took out vibwnds autoupdate for RestorePort
  393. }
  394.             
  395.  
  396. void DTableView::GetRowRect( long row, Nlm_RecT& r, long nrows)
  397. {
  398.     long i;
  399.     r= fRect;
  400.     if (fHeights) {
  401.         for (i= fTop; i<row; i++) r.top += fHeights[i];
  402.         r.bottom= r.top;
  403.         for (i= 0; i<nrows; i++) r.bottom += fHeights[row+i];
  404.         }
  405.     else {
  406.         r.top += (row-fTop) * fItemHeight;
  407.         r.bottom = r.top + nrows*fItemHeight;
  408.         }
  409. }
  410.  
  411. void DTableView::GetColRect( long col, Nlm_RecT& r, long ncols)
  412. {
  413.     long i;
  414.     r= fRect;
  415.     if (fWidths) {
  416.         for (i= fLeft; i<col; i++) r.left += fWidths[i];
  417.         r.right= r.left;
  418.         for (i= 0; i<ncols; i++) r.right += fWidths[col+i];
  419.         }
  420.     else {
  421.         r.left += (col-fLeft) * fItemWidth;
  422.         r.right = r.left + ncols*fItemWidth;
  423.         }
  424. }
  425.  
  426. void DTableView::GetCellRect( long row, long col, Nlm_RecT& r)
  427. {
  428.     long i;
  429.     r= fRect;
  430.     if (fWidths) {
  431.         for (i= fLeft; i<col; i++) r.left += fWidths[i];
  432.         r.right= r.left + fWidths[col];
  433.         }
  434.     else {
  435.         r.left += (col-fLeft) * fItemWidth;
  436.         r.right = r.left + fItemWidth;
  437.         }
  438.     if (fHeights) {
  439.         for (i= fTop; i<row; i++) r.top += fHeights[i];
  440.         r.bottom= r.top + fHeights[row];
  441.         }
  442.     else {
  443.         r.top += (row-fTop) * fItemHeight;
  444.         r.bottom = r.top + fItemHeight;
  445.         }
  446. }
  447.  
  448. void DTableView::GetCellRect(Nlm_RecT cellr, Nlm_RecT& r)
  449. {
  450.     long i;
  451.     r= fRect;
  452.     if (fWidths) {
  453.         for (i= fLeft; i<cellr.left; i++) r.left += fWidths[i];
  454.         r.right= r.left;
  455.         for (i=cellr.left; i<cellr.right; i++) r.right += fWidths[i];
  456.         }
  457.     else {
  458.         r.left += (cellr.left-fLeft) * fItemWidth;
  459.         r.right = r.left + (cellr.right - cellr.left) * fItemWidth;
  460.         }
  461.         
  462.     if (fHeights) {
  463.         for (i= fTop; i<cellr.top; i++) r.top += fHeights[i];
  464.         r.bottom= r.top;
  465.         for (i=cellr.top; i<cellr.bottom; i++) r.bottom += fHeights[i];
  466.         }
  467.     else {
  468.         r.top += (cellr.top-fTop) * fItemHeight;
  469.         r.bottom = r.top + (cellr.bottom - cellr.top) * fItemHeight;
  470.         }
  471. }
  472.  
  473.     
  474.  
  475.  
  476.  
  477. #ifdef WIN_MOTIF
  478.  
  479. #include <ncbi.h>
  480. #include <ncbidraw.h>
  481. //typedef unsigned long XID; // this is failing in X.h !?
  482. //#define XID  unsigned long
  483. #include <ncbiwin.h>
  484. #include <ncbiport.h>
  485.  
  486. extern Display      *Nlm_currentXDisplay;
  487. extern int          Nlm_currentXScreen;
  488. extern Window       Nlm_currentXWindow;
  489. extern GC           Nlm_currentXGC;
  490. extern Nlm_Uint4    Nlm_XbackColor;
  491. extern Nlm_Uint4    Nlm_XforeColor;
  492. extern Nlm_IntD     Nlm_XOffset;
  493. extern Nlm_IntD     Nlm_YOffset;
  494. extern Nlm_RegioN   Nlm_clpRgn;
  495.  
  496. #endif
  497.  
  498.  
  499. inline void DTableInvertRect( Nlm_RecT& r)
  500. {    
  501. #ifdef notWIN_MOTIF
  502. // vals: GXcopy  GXand  GXor GXequiv GXinvert GXorInverted
  503. // !! GXor looks GOOD for colored x -- makes gray rect
  504. // but isn't reverting to regular on deselect, unless click is in selrect !?? 
  505. // GXxor looks okay at start, but repeated calls mess it up (conflict??)
  506. // fill vals: FillStippled  FillOpaqueStippled  FillSolid  FillTiled
  507.  
  508. #define newfunc  GXxor
  509. #define currentFunction  GXcopy
  510. #define newfill  FillStippled
  511. #define currentFillStyle   FillStippled
  512.   Nlm_RectTool  rtool;
  513.  
  514. #if 1
  515.   if (Nlm_currentXDisplay && Nlm_currentXWindow && Nlm_currentXGC) {
  516.     rtool.x = MIN (r.left, r.right);
  517.     rtool.y = MIN (r.top, r.bottom);
  518.     rtool.width = ABS (r.right - r.left);
  519.     rtool.height = ABS (r.bottom - r.top);
  520.  
  521.         // ! recommended by Xlib vol 1, sect. 7.4.3: foreground( forecol ^ backcol)
  522.         // ! and it works !
  523.         ulong xorcolor= Nlm_XforeColor ^ Nlm_XbackColor;
  524.         XSetForeground( Nlm_currentXDisplay,Nlm_currentXGC, xorcolor);
  525.     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, newfunc);
  526.     //XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, newfill);
  527.     XFillRectangle (Nlm_currentXDisplay, Nlm_currentXWindow, Nlm_currentXGC,
  528.                     rtool.x - Nlm_XOffset, rtool.y - Nlm_YOffset,
  529.                     rtool.width, rtool.height);
  530.     XSetFunction (Nlm_currentXDisplay, Nlm_currentXGC, currentFunction);
  531.     //XSetFillStyle (Nlm_currentXDisplay, Nlm_currentXGC, currentFillStyle);
  532.         XSetForeground( Nlm_currentXDisplay,Nlm_currentXGC, Nlm_XforeColor);
  533.    }
  534.  
  535. #else
  536.     Nlm_InvertMode();
  537.     Nlm_PaintRect( &r);
  538.     Nlm_CopyMode();
  539. #endif
  540.  
  541. #else
  542.     // patched both Nlm_InvertMode & Nlm_InvertRect for Motif
  543.   Nlm_InvertRect( &r);
  544. #endif 
  545. }
  546.  
  547. void DTableView::InvertRect( Nlm_RecT& r)
  548. {    
  549.     Nlm_WindoW w= Nlm_SavePort( fNlmObject);
  550. #ifdef WIN_MOTIF
  551.     this->Select();
  552. #endif
  553.     ::DTableInvertRect( r);
  554.     if (w) Nlm_UseWindow (w); 
  555. }
  556.  
  557.  
  558.  
  559. void DTableView::GetPixRgn(Nlm_RecT cellrect, Nlm_RegioN cellrgn, Nlm_RegioN pixrgn)
  560. {
  561.     long i;
  562.     Nlm_PoinT pt;
  563.     Nlm_RecT  r;
  564.     
  565.     r= fRect;
  566.     Nlm_RegioN ptrgn= Nlm_CreateRgn();
  567.     if (fHeights) for (i= fTop; i<cellrect.top; i++) r.top += fHeights[i];
  568.     else r.top += (cellrect.top-fTop) * fItemHeight;
  569.     
  570.     for (long irow= cellrect.top; irow<=cellrect.bottom; irow++) {
  571.         r.left= fRect.left;
  572.         if (fWidths) for (i= fLeft; i<cellrect.left; i++) r.left += fWidths[i];
  573.         else r.left += (cellrect.left-fLeft) * fItemWidth;
  574.         if (fHeights) r.bottom= r.top + fHeights[irow];
  575.         else r.bottom = r.top + fItemHeight;
  576.         
  577.         for (long jcol= cellrect.left; jcol<=cellrect.right; jcol++) {
  578.             pt.y= irow; pt.x= jcol;
  579.             if (fWidths) r.right= r.left + fWidths[jcol];
  580.             else r.right= r.left + fItemWidth;
  581.             if (Nlm_PtInRgn( pt, cellrgn)) {
  582.                 Nlm_LoadRectRgn( ptrgn, r.left, r.top, r.right, r.bottom);
  583.                 Nlm_UnionRgn( pixrgn, ptrgn, pixrgn);
  584.                 }
  585.             r.left= r.right;
  586.             }
  587.         r.top= r.bottom;
  588.         }
  589.     ptrgn= Nlm_DestroyRgn(ptrgn);
  590. }
  591.  
  592.  
  593. void DTableView::InvertRgn( Nlm_RegioN pixrgn)
  594. {    
  595.     Nlm_WindoW w= Nlm_SavePort( fNlmObject);
  596. #ifdef WIN_MOTIF
  597.     this->Select();
  598. #endif
  599.   Nlm_InvertRgn(pixrgn);
  600.     if (w) Nlm_UseWindow (w); 
  601. }
  602.  
  603.  
  604.  
  605.  
  606.  
  607. void DTableView::DoubleClickAt(long row, long col)
  608. {
  609. }
  610.  
  611.  
  612. void DTableView::SingleClickAt(long row, long col)
  613. {
  614.     if ( fSelection->IsSelected(row, col) && !gKeys->shift()) 
  615.         fSelection->SetEmptySelection( true);
  616.     else {
  617.         long ext;
  618.         if (gKeys->shift()) ext= DTabSelection::kExtendSingle;
  619.         else if (gKeys->command()) ext= DTabSelection::kExtendMulti;
  620.         else ext= DTabSelection::kDontExtend;
  621.         fSelection->SelectCells(  row, col, ext, 
  622.                     DTabSelection::kHighlight, DTabSelection::kSelect);
  623.         }
  624. }
  625.             
  626.  
  627. void DTableView::PointToCell(Nlm_PoinT mouse, long& row, long& col)
  628. {
  629.     if (fHeights) {
  630.         row= fTop - 1;
  631.         long yrow= fRect.top;
  632.         do {
  633.             row++;
  634.             if (row<=fMaxRows) yrow += fHeights[row];
  635.             else yrow= mouse.y;
  636.             } while (yrow < mouse.y);
  637.         }
  638.     else
  639.         row= fTop  + (mouse.y - fRect.top)  / fItemHeight;
  640.  
  641.     if (fWidths) {
  642.         col= fLeft - 1;
  643.         long xcol= fRect.left;
  644.         do {
  645.             col++;
  646.             if (col<=fMaxCols) xcol += fWidths[col];
  647.             else xcol= mouse.x;
  648.             } while (xcol < mouse.x);
  649.         }
  650.     else
  651.         col= fLeft + (mouse.x - fRect.left) / fItemWidth;
  652. }
  653.  
  654.  
  655.  
  656. void DTableView::Click(Nlm_PoinT mouse)
  657. {
  658.     long row, col;
  659.     
  660.     //if (gLastCommand) gLastCommand->Commit();    //?? prevent bombs from prev. cmds ?
  661.     //if (fCurrentTracker) fCurrentTracker->Reset();
  662.     SetTracker( fCurrentTracker); // ??  make new one each click?
  663.     DAutoPanel::Click(mouse);         // sets fMouseStillDown= false
  664.  
  665.     if (!fCurrentTracker) {
  666.         // TrackMouse::trackEnd does this now, if click is tracked...
  667.         PointToCell( mouse, row, col);
  668.         if (row >=0 && row < fMaxRows && col >= 0 && col < fMaxCols) {
  669.             if (Nlm_dblClick) DoubleClickAt( row, col);
  670.             else SingleClickAt( row, col);
  671.             }
  672.         }
  673. }
  674.  
  675. void DTableView::Drag(Nlm_PoinT mouse)
  676. {
  677.     DAutoPanel::Drag(mouse); // sets fMouseStillDown= true,... 
  678. }
  679.  
  680. void DTableView::Release(Nlm_PoinT mouse)
  681. {
  682.     DAutoPanel::Release(mouse); // sets fMouseStillDown= false,... 
  683. }
  684.  
  685.  
  686. void DTableView::TrackMouse( short aTrackPhase,
  687.                     Nlm_PoinT& anchorPoint, Nlm_PoinT& previousPoint,
  688.                     Nlm_PoinT& nextPoint,    Nlm_Boolean mouseDidMove)
  689. {
  690.  
  691.     switch (aTrackPhase) {
  692.     
  693.         case DTracker::trackBegin:
  694.             if (gKeys->shift()) {  
  695.                 Nlm_PoinT pt;
  696.                 Nlm_RecT  pixr;
  697.                 long    diff1, diff2;
  698.                 
  699.                 GetCellRect( fSelection->GetSelRect(), pixr);
  700.                 diff1= anchorPoint.x - pixr.left;
  701.                 diff2= anchorPoint.x - pixr.right;
  702.                 if (abs(diff1) > abs(diff2)) pt.x= pixr.left; 
  703.                 else pt.x= pixr.right;
  704.                 diff1= anchorPoint.y - pixr.top;
  705.                 diff2= anchorPoint.y - pixr.bottom;
  706.                 if (abs(diff1) > abs(diff2)) pt.y= pixr.top; 
  707.                 else pt.y= pixr.bottom;
  708.                 
  709.                 // tracker::Start makes 3 pts all same
  710.                 anchorPoint = pt;
  711.                 previousPoint = pt;
  712.                 nextPoint = pt;
  713.                 //fTracker->fMovedOnce= true; // force it for single-click extend?
  714.                 }
  715.              break;
  716.     
  717.         case DTracker::trackContinue:
  718.             break;
  719.             
  720.         case DTracker::trackEnd:
  721.             {
  722.             long row, col;
  723.             Boolean moved= gKeys->shift() // extend
  724.                     || abs(anchorPoint.x - nextPoint.x) > 2
  725.                     || abs(anchorPoint.y - nextPoint.y) > 2;
  726.             if (!moved) {
  727.                 PointToCell( nextPoint, row, col);
  728.                 if (row >=0 && row < fMaxRows && col >= 0 && col < fMaxCols) {
  729.                     if (Nlm_dblClick) DoubleClickAt( row, col);
  730.                     else SingleClickAt( row, col);
  731.                     }
  732.                 }
  733.             }
  734.             break;
  735.             
  736.         }
  737. }
  738.  
  739. void DTableView::TrackFeedback( short aTrackPhase,
  740.                     const Nlm_PoinT& anchorPoint, const Nlm_PoinT& previousPoint,
  741.                     const Nlm_PoinT& nextPoint, Nlm_Boolean mouseDidMove, Nlm_Boolean turnItOn)
  742. {
  743.     if (mouseDidMove) {
  744.         Nlm_RecT    pixr;
  745.  
  746.         pixr.left= MIN( anchorPoint.x, nextPoint.x);
  747.         pixr.right= MAX( anchorPoint.x, nextPoint.x);
  748.         pixr.top= MIN( anchorPoint.y, nextPoint.y);
  749.         pixr.bottom= MAX( anchorPoint.y, nextPoint.y);
  750.         
  751.         Nlm_InsetRect( &pixr, 1,1); //??
  752.         Nlm_InvertMode();
  753.         Nlm_FrameRect( &pixr);
  754.         Nlm_CopyMode();
  755.         }
  756. }
  757.  
  758.  
  759.  
  760.  
  761. void DTableView::DrawCell(Nlm_RecT r, long row, long col)
  762. {
  763.     char    snum[80];
  764.     sprintf(snum,"r%d,c%d", row, col);
  765.     Nlm_DrawString( &r, snum, 'c', false);
  766. }
  767.     
  768. Boolean gHasSel = false;
  769.  
  770. void DTableView::DrawRow(Nlm_RecT r, long row)
  771. {
  772.     long col = fLeft; 
  773.     if (fWidths && col <= fMaxCols) r.right= r.left + fWidths[col];
  774.     else r.right= r.left + fItemWidth;
  775.     while (r.left < fRect.right && col < fMaxCols) {
  776.         if (Nlm_RectInRgn (&r, Nlm_updateRgn))  {
  777.             DrawCell( r, row, col);
  778. #if 1
  779.              if (gHasSel && fSelection->IsSelected(row, col) ) 
  780.                  InvertRect( r);
  781. #endif
  782.             }
  783.         if (fWidths) {
  784.             Nlm_OffsetRect( &r, fWidths[col], 0);
  785.             r.right= r.left + fWidths[col+1];
  786.             }
  787.         else
  788.             Nlm_OffsetRect( &r, fItemWidth, 0);
  789.         col++;
  790.         }
  791.     fColsDrawn= col - fLeft;
  792. }
  793.  
  794.  
  795. void DTableView::GetPageCount(Nlm_RecT pagerect, long& rowpages, long& colpages)
  796. {
  797.     long left, top, row, col;     
  798.     rowpages= colpages= 1;
  799.     
  800.     for (col=0, left=0; col < fMaxCols; col++) {
  801.         if (fWidths) left += fWidths[col];  
  802.         else left += fItemWidth;
  803.         if (left >= pagerect.right) { 
  804.             colpages++; 
  805.             left= 0; 
  806.             }
  807.         }
  808.     for (row=0, top=0; row < fMaxRows; row++) {
  809.         if (fHeights) top += fHeights[row];  
  810.         else top += fItemHeight;
  811.         if (top >= pagerect.bottom) { 
  812.             rowpages++; 
  813.             top= 0; 
  814.             }
  815.         }
  816. }
  817.  
  818.  
  819. void DTableView::Draw()
  820. {
  821.     Nlm_RecT         r2, r = fRect;
  822.     Nlm_PoinT      pt;
  823.     long             row = fTop; 
  824.     Boolean            hasSel;
  825.     Nlm_RegioN saveUpdrgn = NULL;
  826.     
  827.     if (fHeights) r.bottom= r.top + fHeights[row];
  828.     else r.bottom= r.top + fItemHeight;
  829.     Nlm_SelectFont(fFont); //?? here
  830.     hasSel= fSelection->IsSelected();
  831.     gHasSel= hasSel;
  832.     if (hasSel) {
  833. #if 0
  834.         saveUpdrgn= Nlm_CreateRgn();
  835.         Nlm_UnionRgn(saveUpdrgn,Nlm_updateRgn, saveUpdrgn);
  836. #endif
  837. #if 0
  838.         pt.x= fSelection->GetSelectedCol();
  839.         r2= fSelection->GetSelRect();
  840.         GetCellRect( r2, r2);
  841. #endif        
  842.         }
  843.     while (r.top < fRect.bottom && row < fMaxRows) {
  844.         if (Nlm_RectInRgn (&r, Nlm_updateRgn)) { 
  845.             DrawRow( r, row);
  846.              pt.y= row;
  847. #if 0
  848.              if (hasSel && fSelection->IsSelected(pt.y, pt.x) ) {
  849.                  Nlm_RecT ir= r;
  850.                  ir.left= r2.left;
  851.                  ir.right= r2.right;
  852.                 InvertRect( ir);
  853.                  }
  854. #endif
  855.           }
  856.         if (fHeights) {
  857.             Nlm_OffsetRect( &r, 0, fHeights[row]);
  858.             r.bottom= r.top + fHeights[row+1];
  859.             }
  860.         else
  861.             Nlm_OffsetRect( &r, 0, fItemHeight);
  862.         row++;
  863.         }
  864. #if 0
  865.     if (hasSel) {
  866.         fSelection->InvertSelection(saveUpdrgn); // ! only do redrawn section !!
  867.         saveUpdrgn= Nlm_DestroyRgn(saveUpdrgn);
  868.         }
  869. #endif
  870. }
  871.         
  872.  
  873. enum { kWritingAsPICT = 9 };
  874.  
  875. void DTableView::ViewRect(Nlm_RecT& r) 
  876.     if (fIsPrinting == kWritingAsPICT) {
  877.         r= fRect; // fRect is set at start of AsPICT
  878.         }
  879.     else if (fIsPrinting) {
  880.         r= fRect; //fRect is set at start of Print 
  881.         // Nlm_PrintingRect(&r);
  882.         }
  883.     else
  884.         DView::ViewRect(r);  
  885. }
  886.         
  887. void DTableView::Print()  
  888. {
  889. #if (defined(WIN_MAC) || defined (WIN_MSWIN))
  890.   Nlm_WindoW    w;
  891.   Boolean           goOn, newPage, widerThanPage;
  892.   Nlm_RecT        pager, r, saverect;
  893.     long                  row = 0, rowpages, colpages; 
  894.     long                    saveleft;
  895.     
  896.     // problems: assumes each row < page height
  897.     
  898.   w = Nlm_StartPrinting();
  899.   if (w) {
  900.       fIsPrinting= true;
  901.         gCursor->watch();    
  902.         saverect= fRect;
  903.         Nlm_PrintingRect(&pager);
  904.         fRect= pager;
  905.         Nlm_SelectFont(fFont); 
  906.         saveleft= fLeft; fLeft= 0; 
  907.         //savetop= fTop; fTop= 0; 
  908.         GetPageCount( pager, rowpages, colpages);
  909.         
  910.     newPage = true;
  911.     goOn = row < fMaxRows;
  912.     widerThanPage= colpages > 1; 
  913.     
  914.     // make update region large...
  915.     if (Nlm_updateRgn != NULL)  
  916.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  917.     
  918.     while (goOn) {
  919.     
  920.       if (newPage) {
  921.         goOn = Nlm_StartPage();
  922.         newPage = false;
  923.           r= pager;
  924.           
  925.                 if (fHeights) r.bottom= r.top + fHeights[row];
  926.                 else r.bottom= r.top + fItemHeight;
  927.            }
  928.       
  929.       if (goOn) {
  930.                 fColsDrawn= fMaxCols; // in case DrawRow forgets to set this
  931.                 DrawRow( r, row);
  932.                 
  933.                 if (widerThanPage) {
  934.                   fLeft +=     fColsDrawn;
  935.                     newPage = (fLeft < fMaxCols);
  936.                     if (newPage) goOn = Nlm_EndPage();    
  937.                     else fLeft= 0;
  938.                     }
  939.                 
  940.                 if (!newPage) {    
  941.                     if (fHeights) {
  942.                         Nlm_OffsetRect( &r, 0, fHeights[row]);
  943.                         r.bottom= r.top + fHeights[row+1];
  944.                         }
  945.                     else
  946.                         Nlm_OffsetRect( &r, 0, fItemHeight);
  947.                     newPage = (r.bottom > pager.bottom);
  948.                     if (newPage) goOn = Nlm_EndPage();    
  949.                     row++;
  950.                     if (goOn) goOn= (row < fMaxRows);
  951.                     }
  952.                     
  953.                 }
  954.             }
  955.             
  956.           if (!newPage) (void) Nlm_EndPage();
  957.       Nlm_EndPrinting(w);
  958.         fIsPrinting= false;
  959.         fRect= saverect;
  960.         fLeft= saveleft;
  961.         gCursor->arrow();
  962.         }       
  963. #else
  964.     Nlm_Message(MSG_OK,"Printing is not yet defined for this window system");
  965. #endif
  966. }
  967.  
  968.  
  969. #ifdef WIN_MAC
  970. #undef Handle
  971. #undef Rect
  972. #include <QuickDraw.h>
  973. #include <Memory.h>
  974. #endif
  975.  
  976. #ifdef WIN_MSWIN
  977. #undef FAR 
  978. #undef NEAR 
  979. #include <windows.h>
  980. extern "C" HWND         Nlm_currentHWnd;
  981. extern "C" HDC          Nlm_currentHDC;
  982.  
  983. struct METAFILEHEADER { // must be 22 bytes !
  984.     DWORD    key;
  985.     WORD    hmf; // HANDLE hmf; for Win16 !
  986.     //RECT    bbox; for Win16 !
  987.     WORD  boxleft;
  988.     WORD  boxtop;
  989.     WORD  boxright;
  990.     WORD  boxbottom;
  991.     WORD    inch;
  992.     DWORD    reserved;
  993.     WORD    checksum;
  994. };
  995.  
  996.       
  997. void CalcMFChecksum(METAFILEHEADER* pMFHead)
  998. {
  999.   WORD *p;
  1000.  
  1001.   for (p =(WORD *)pMFHead, pMFHead->checksum = 0;
  1002.          p < (WORD *)&pMFHead->checksum; ++p)
  1003.          pMFHead->checksum ^= *p;
  1004. }
  1005.  
  1006. #endif
  1007.  
  1008. void DTableView::WriteToPICT(DFile* afile)  
  1009. {
  1010.     if (!afile) return;
  1011.     
  1012. #ifdef WIN_MAC
  1013.   Nlm_RecT        pager, saverect, cellr;
  1014.     
  1015.     gCursor->watch();    
  1016.     saverect= fRect;
  1017.      fIsPrinting= kWritingAsPICT;
  1018.      Nlm_LoadRect( &cellr, 0, 0, fMaxCols, fMaxRows);
  1019.     this->GetCellRect( cellr, pager);
  1020.     fRect= pager;
  1021.     
  1022.   Rect  picrect;
  1023.   picrect.left= pager.left;
  1024.   picrect.right= pager.right;
  1025.   picrect.top = pager.top;
  1026.   picrect.bottom= pager.bottom;
  1027.     Handle pic= (Handle) OpenPicture( &picrect); 
  1028.     
  1029.   if (pic) { 
  1030.       enum { kPicHeadsize = 512 };
  1031.       ulong count;
  1032.         // make update region large...
  1033.     if (Nlm_updateRgn != NULL)  
  1034.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1035.     Draw();                
  1036.       ClosePicture();
  1037.       
  1038.           // now write pic to file
  1039.       afile->Delete();
  1040.       afile->Create("PICT","ttxt"); 
  1041.         afile->Open("wb"); // Damn "wb" -- must by BINARY 
  1042.       count= kPicHeadsize;
  1043.       char * header = (char *) Nlm_MemGet(kPicHeadsize,MGET_CLEAR);
  1044.       afile->WriteData( header, count);
  1045.       Nlm_MemFree( header);
  1046.         HLock(pic);
  1047.       count= GetHandleSize(pic);
  1048.       afile->WriteData( *pic, count);
  1049.       afile->Close();
  1050.       HUnlock(pic);
  1051.       KillPicture ( (PicHandle)pic);
  1052.         } 
  1053.     fIsPrinting= false;        
  1054.     fRect= saverect;
  1055.     gCursor->arrow();
  1056.     return;
  1057. #endif
  1058.  
  1059. #ifdef WIN_MSWIN
  1060.   Nlm_RecT        pager, saverect, cellr;
  1061.   RECT  picrect;
  1062.     
  1063.     gCursor->watch();    
  1064.     saverect= fRect;
  1065.      fIsPrinting= kWritingAsPICT;
  1066.      Nlm_LoadRect( &cellr, 0, 0, fMaxCols, fMaxRows);
  1067.     this->GetCellRect( cellr, pager);
  1068.     fRect= pager;
  1069.   picrect.left= pager.left;
  1070.   picrect.top = pager.top;
  1071.   picrect.right = pager.right;
  1072.   picrect.bottom= pager.bottom;
  1073.     
  1074.     char* fname= (char*) afile->GetName();
  1075.     fname= (char*)DFileManager::FilenameFromPath(fname); // CreateMF fails for full path !?
  1076.     //fname= "test.wmf";
  1077.     
  1078. #if 1
  1079. //#ifdef WIN16
  1080.     HDC hdcMeta= CreateMetaFile(fname); // (fname)
  1081.     
  1082. #define MetaHandle HMETAFILE
  1083. #define MetaClose(x)  CloseMetaFile(x)
  1084. #define MetaDelete(x) DeleteMetaFile(x)
  1085. #define MetaGetData(a,b,c)  GetMetaFileBitsEx(a,b,c)
  1086.  
  1087. #else
  1088.   char  describes[120];
  1089.   char  titlebuf[80];
  1090.   char  *dp, *np, *ep;
  1091.   
  1092.   np= (char*)gApplication->Shortname();
  1093.   dp= describes;
  1094.   ep= dp + sizeof(describes) - 2;
  1095.   if (np) while (*np && dp < ep) { *dp++ = *np++; }
  1096.   *dp++ = 0;
  1097.   np= this->GetTitle(titlebuf, sizeof(titlebuf));
  1098.   if (np) while (*np && dp < ep) { *dp++ = *np++; }
  1099.   *dp++ = 0;
  1100.  
  1101.   // need pixel to .01 mm conversion for picrect !
  1102.   // need some needlessly complex SetMapMode, MapPoint, ResetMapMode...
  1103.   
  1104.     HDC hdcMeta= CreateEnhMetaFile( Nlm_currentHDC, NULL, &picrect, describes);
  1105. #define MetaHandle HENHMETAFILE
  1106. #define MetaClose(x)  CloseEnhMetaFile(x)
  1107. #define MetaDelete(x) DeleteEnhMetaFile(x)
  1108. #define MetaGetData(a,b,c)  GetEnhMetaFileBits(a,b,c)
  1109. #endif
  1110.  
  1111.   if (hdcMeta) { 
  1112.       POINT point;
  1113.       SIZE  size;
  1114.  
  1115.        HDC savehdc= Nlm_currentHDC;
  1116.       Nlm_currentHDC= hdcMeta;  
  1117.       SetMapMode( hdcMeta, MM_ANISOTROPIC);
  1118.         SetWindowOrgEx(hdcMeta, 0,0, &point);
  1119.         SetWindowExtEx(hdcMeta, picrect.right-picrect.left, 
  1120.                         picrect.bottom-picrect.top, &size);
  1121.  
  1122.       Nlm_ResetDrawingTools();
  1123.       
  1124.         // make update region large...
  1125.     if (Nlm_updateRgn != NULL)  
  1126.             Nlm_LoadRectRgn(Nlm_updateRgn, -32767, -32767, 32767, 32767);
  1127.     Draw();  
  1128.       
  1129.       MetaHandle hmf = MetaClose( hdcMeta);
  1130.  
  1131. #ifdef WIN16
  1132.       // win16 code
  1133.       //HGLOBAL hgmf = GetMetaFileBits( hmf);
  1134. #else
  1135.       // win32 code
  1136.       ulong count, bufsize;
  1137.       METAFILEHEADER placeheader;
  1138.       bufsize= GetEnhMetaFileBits( hmf, 0, NULL);
  1139.       char* buf= (char*) MemNew( bufsize + 1);
  1140.       if ( GetEnhMetaFileBits( hmf, bufsize, (unsigned char*)buf) ) { 
  1141.         placeheader.key= 0x9AC6CDD7L;
  1142.         placeheader.hmf= 0;
  1143.         //c0 f4 90 f7 36 0b 66 08 is bbox rect that powerpnt made
  1144.         placeheader.boxtop = 0xf4c0; //picrect.top; //?? some neg.num?
  1145.         placeheader.boxleft= 0xf790; //picrect.left;  //?? some neg.num?
  1146.         placeheader.boxbottom= 0x0b36; //picrect.bottom;
  1147.         placeheader.boxright = 0x0866; //picrect.right;
  1148.         placeheader.inch= 576;
  1149.         placeheader.reserved= 0;
  1150.         placeheader.checksum= 0x5551;  
  1151.         CalcMFChecksum( &placeheader); // == 0x5551 ?
  1152.     
  1153.         afile->Delete();
  1154.         afile->Create("WMF","DCLAP"); 
  1155.           afile->Open("wb"); 
  1156.         count= 22; //!! not -> sizeof(placeheader);
  1157.         afile->WriteData( &placeheader, count);
  1158.         count= bufsize;
  1159.         afile->WriteData( buf, count);  
  1160.         afile->Close();
  1161.         }
  1162.       MemFree( buf);
  1163. #endif
  1164.  
  1165.       MetaDelete( hmf); // just deletes handle, not disk file !
  1166.       Nlm_currentHDC= savehdc;  
  1167.         }       
  1168.     fIsPrinting= false;        
  1169.     fRect= saverect;
  1170.     gCursor->arrow();
  1171.     return;
  1172. #endif
  1173.       
  1174.     Nlm_Message(MSG_OK,"DrawToPicture is not yet defined for this window system");
  1175. }
  1176.  
  1177.