home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / Drtf / DRichViewNu.cpp < prev    next >
Encoding:
Text File  |  1995-12-17  |  102.2 KB  |  3,947 lines  |  [TEXT/R*ch]

  1. // DRichView.cpp
  2. // d.g.gilbert
  3.  
  4.  
  5. #include "Dvibrant.h"
  6. #include "DWindow.h"
  7. #include "DPanel.h"
  8. #include "DControl.h"
  9. #include "DFile.h"
  10. #include "DFindDlog.h"
  11. #include "DList.h"
  12. #include "DUtil.h"
  13. #include "DDialogText.h"
  14. #include "DViewCentral.h"
  15.  
  16. #include "DDrawPICT.h"
  17.  
  18. #include "DRichStyle.h"
  19. #include "DRichViewNu.h"
  20. #include "DRTFHandler.h"
  21. #include "DPICTHandler.h"
  22. #include "DHTMLHandler.h"
  23. #include "DGIFHandler.h"
  24.  
  25.  
  26. #include "DIconLib.h"
  27. #include "DIcons.h"
  28.  
  29.  
  30. static DDrawPict* gDrawPict = NULL; 
  31.  
  32. static Boolean gNotInitted = true;
  33.  
  34. #ifdef DBUG
  35. #define Debug(x)  fprintf(stderr,x)
  36. #define Debug1(x,y)  fprintf(stderr,x,y);
  37. #else
  38. #define Debug(x) 
  39. #define Debug1(x,y)
  40. #endif
  41.  
  42. enum {
  43.     chPictTag = 26,
  44.     MAXFONTS  = 32
  45.     };
  46.  
  47. static struct fontheights {
  48.   Nlm_FonT  font;
  49.   short          height;
  50.     } gFontHeights[MAXFONTS];
  51.  
  52.  
  53. //short DRichView::GetFontHeight(Nlm_FonT font)
  54. static short GetFontHeight(Nlm_FonT font)
  55. {
  56.             // Returns the pixel height of a font, caching for quicker access
  57.   short  height, i;
  58.   height = 0;
  59.   i = 0;
  60.   while (i < MAXFONTS && gFontHeights[i].font != font
  61.          && gFontHeights[i].font != NULL)
  62.             i++;
  63.   if (gFontHeights[i].font == font) 
  64.     return gFontHeights[i].height;
  65.     else {
  66.     Nlm_SelectFont(font);
  67.     height = Nlm_LineHeight();
  68.     if (i < MAXFONTS) {
  69.       gFontHeights[i].font = font;
  70.       gFontHeights[i].height = height;
  71.         }
  72.        return height;
  73.         }
  74. }
  75.  
  76.  
  77.  
  78. // struct DRichStyle
  79.  
  80. DRichStyle::DRichStyle()
  81. {
  82.   //SetClass("DRichStyle",sizeof(DRichStyle));
  83.     ispict= false;
  84.     ismap= false;
  85.     ownpict= false;
  86.     fPict= NULL; 
  87.  
  88.     boxed= false;
  89.     hidden= false;
  90.     last= false; //??
  91.     color= 0; // black ??
  92.     nextofs= 0;
  93.     pixheight= pixwidth= pixleft= 0;
  94.     linkid= 0;
  95.     font= NULL;
  96.     superSub= 0;
  97.     underline= kNoUnderline;
  98.     bold= false;
  99.     italic= false;
  100.     outline= false;
  101.     shadow= false;
  102.     strikeout= false;
  103.     smallcaps= false;
  104.     allcaps= false;
  105. }
  106.  
  107. DRichStyle::~DRichStyle()
  108. {
  109.     // this was killing things due to large # of static variables of this type
  110.     // commonly used as save temps -- was deleting same data more than once !!
  111. #if 1
  112.     if (ownpict && fPict) {
  113.         fPict->suicide(); 
  114.         // if (ownpict) ownpict= true; //  debug trap 
  115.         }
  116. #else
  117.     //if (ownpict) MemFree(picdata);  
  118. #endif
  119. }
  120.  
  121. Boolean DRichStyle::suicide(void) 
  122.     if (GetOwnerCount() <= 1) { 
  123.         delete this; 
  124.         return true; 
  125.         }
  126.     else 
  127.         return DObject::suicide();
  128. }
  129.  
  130. Boolean DRichStyle::suicide(short ownercount)
  131. {
  132.     if (ownercount < 1) {
  133.         delete this; 
  134.         return true; 
  135.         }
  136.     else 
  137.         return DObject::suicide(ownercount);
  138. }
  139.  
  140. #if 0
  141. // this bombs......
  142. DRichStyle& DRichStyle::operator=( DRichStyle& ast)
  143. {
  144.     if (this != &ast) {
  145.         //*this ::= ast; 
  146.         //this->DObject::operator=(ast);
  147.       MemCpy( this, &ast, sizeof(DRichStyle)); //<<! subclass bad !!
  148.         this->ownpict= false;
  149.         }
  150.     return *this;
  151. }
  152. #endif
  153.  
  154. #if 0
  155. DObject* DRichStyle::Clone()
  156. {
  157.     DRichStyle* result = (DRichStyle*) DObject::Clone();
  158.     if (picdata) {
  159.          result->picdata= (char*) MemDup( picdata,  picsize);
  160.          result->ownpict= true;
  161.          }
  162.     return result;
  163. }
  164. #endif
  165.  
  166. Boolean DRichStyle::IsNotEqual(DRichStyle* other)
  167. {
  168.     if ( 0 == MemCmp( this, other, sizeof(DRichStyle)) )
  169.         return false;
  170.     else if (ispict && other->ispict) {
  171.         // ?? need some better way to test if two picts are the same ??
  172.         return ( linkid != other->linkid
  173.                     || ismap != other->ismap
  174.                     || (fPict && fPict->IsNotEqual(other->fPict))
  175.                     );
  176.         }
  177.     else
  178.       return (  linkid != other->linkid 
  179.                     || ispict != other->ispict
  180.                     || ismap != other->ismap
  181.                     || color != other->color 
  182.                     || superSub != other->superSub 
  183.                     || underline != other->underline
  184.                     || bold != other->bold
  185.                     || italic != other->italic
  186.                     || hidden != other->hidden
  187.                     || outline != other->outline
  188.                     || shadow != other->shadow
  189.                     || strikeout != other->strikeout
  190.                     || smallcaps != other->smallcaps
  191.                     || allcaps != other->allcaps
  192.                     || boxed != other->boxed
  193.                     );
  194. }
  195.  
  196.  
  197.  
  198.  
  199.  
  200. // class DPictStyle
  201.  
  202. DPictStyle::DPictStyle()
  203. {
  204.     fKind= kPictOther;  // kPictMac
  205.     fSize= 0;
  206.     fData= NULL;
  207.     fLinks = NULL;
  208.     fNumLinks= 0;
  209. }
  210.  
  211. DPictStyle::DPictStyle( short kind, void* data, ulong dsize, Boolean owndata)
  212. {
  213.     fKind= kind;
  214.     fSize= 0;
  215.     fData= NULL;
  216.     fLinks = NULL;
  217.     fNumLinks= 0;
  218.     SetData( kind, data, dsize, owndata);
  219. }
  220.  
  221. DPictStyle::~DPictStyle()
  222. {
  223.     MemFree( fData);
  224.     MemFree( fLinks);
  225. }
  226.  
  227. Boolean DPictStyle::suicide(void) 
  228.     if (GetOwnerCount() <= 1) { 
  229.         delete this; 
  230.         return true; 
  231.         }
  232.     else 
  233.         return DObject::suicide();
  234. }
  235.  
  236. Boolean DPictStyle::suicide(short ownercount)
  237. {
  238.     if (ownercount < 1) {
  239.         delete this; 
  240.         return true; 
  241.         }
  242.     else 
  243.         return DObject::suicide(ownercount);
  244. }
  245.  
  246. Boolean DPictStyle::IsNotEqual(DPictStyle* other)
  247. {
  248.     if ( !other 
  249.         || fSize != other->fSize 
  250.         || fKind != other->fKind   
  251.         || (fData == NULL) != (other->fData == NULL)
  252.         )  return true;
  253.     if (fData && other->fData)  
  254.         return (0 != MemCmp( fData, other->fData, fSize));
  255.     else
  256.         return false; 
  257. }
  258.  
  259. void DPictStyle::SetData( short kind, void* data, ulong dsize, Boolean owndata)
  260. {
  261.     if (fData) MemFree( fData); 
  262.     fKind= kind;
  263.     if (owndata) fData= (char*) data;   // this was bad ?!?
  264.     else fData= (char*) MemDup(data, dsize); 
  265.     fSize= dsize;
  266. }
  267.  
  268.  
  269. short DPictStyle::GetLink( Nlm_PoinT atp, short& kind)
  270. {
  271.     for (short i= 0; i<fNumLinks; i++) {
  272.         if (Nlm_PtInRect( atp, &fLinks[i].fLoc)) {
  273.             kind= fLinks[i].fKind;
  274.             return fLinks[i].fLinkid;
  275.             }
  276.         }
  277.     kind= 0;
  278.     return 0;
  279. }
  280.  
  281. short DPictStyle::GetLink( short index, short& kind, Nlm_RecT& loc)
  282. {
  283.     if (index>=0 && index<fNumLinks) {
  284.         kind= fLinks[index].fKind;
  285.         loc= fLinks[index].fLoc;
  286.         return fLinks[index].fLinkid;
  287.         }
  288.     else {
  289.         kind= 0;
  290.         return 0;
  291.         }
  292. }
  293.  
  294. void DPictStyle::AddLink( short kind, short linkid, Nlm_RecT loc)
  295. {
  296.     PictLinkIndex lnk;
  297.     lnk.fLinkid= linkid;
  298.     lnk.fLoc= loc;
  299.     lnk.fKind= kind;
  300.     fNumLinks++;
  301.     if ( fLinks )
  302.         fLinks= (PictLinkIndex*) MemMore( fLinks, fNumLinks * sizeof(PictLinkIndex));
  303.     else
  304.         fLinks= (PictLinkIndex*) MemNew( fNumLinks * sizeof(PictLinkIndex));
  305.     fLinks[fNumLinks-1]= lnk;
  306. }
  307.  
  308. Boolean DPictStyle::HasNetPict()
  309. {    
  310.     return (fLinks && 
  311.         (fKind == DPictStyle::kPictNetLink 
  312.     || fKind == DPictStyle::kPictNetPic));
  313. }
  314.  
  315. Boolean DPictStyle::CanDraw()
  316. {    
  317.     return (fKind == kPictMac); // add more later...
  318. }
  319.  
  320. void DPictStyle::Draw( Nlm_RecT area)
  321. {
  322.     if (fKind == kPictMac) gDrawPict->Draw( &area, fData, fSize, fKind);
  323.     else if (fKind == kPictNetLink) gNetpicIcon.Draw( area); 
  324.     else gPictureIcon.Draw( area);
  325. }
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333. // struct DParagraph
  334.  
  335. void DParagraph::Initialize()
  336. {
  337.   //SetClass("DParagraph", sizeof(DParagraph));  
  338.     just = 'l';
  339.      tablead = ' ';                  
  340.     deftabstop = 36;
  341.   numstops = 0;
  342.     tabstops = NULL;
  343.     tabkinds = NULL;
  344.     firstInset= leftInset= rightInset= 0;
  345.     spaceBefore= spaceAfter= spaceBetween = 0;
  346.     minLines = minHeight = 0;
  347.     startsAt = numRows = 0;     
  348.     lineHeight = leadHeight = 0; 
  349.   
  350.   fDataPtr = NULL;     
  351.     fText = NULL;             
  352.     fStyleIndex = NULL;
  353.     fNumStyles = 0;
  354.  
  355.     borderstyle    = kNoBorder;
  356.     bordertop  = false;
  357.     borderbottom = false;
  358.     borderleft  = false;
  359.     borderright = false;
  360.     borderbetween = false;
  361.     borderbar = false;
  362.     borderbox = false;
  363.      
  364.     openSpace = FALSE; // was TRUE;
  365.     keepWithNext = FALSE;
  366.     keepTogether = FALSE;
  367.     newPage = FALSE;
  368.     minLines = 0;
  369.     minHeight = 0;
  370.     just = 'l';
  371.     leftInset = 0;
  372.     wrap =  TRUE;
  373.  
  374.     notCached = TRUE;
  375.     neverCached = TRUE;
  376.     fDocOwnsData= false;
  377.     fDocOwnsStyles= true;
  378. }
  379.  
  380.  
  381. DParagraph::~DParagraph()
  382. {
  383. #if 1
  384.     if (fDocOwnsData) MemFree( fDataPtr);
  385.     if (fDocOwnsStyles) MemFree( fStyleIndex);
  386.     MemFree( fText);
  387.     MemFree( tabkinds);
  388.     MemFree( tabstops);
  389. #endif
  390. }
  391.  
  392. Boolean DParagraph::suicide(void) 
  393.     if (GetOwnerCount() <= 1) { 
  394.         delete this; 
  395.         return true; 
  396.         }
  397.     else
  398.         return DObject::suicide();
  399. }
  400.  
  401. Boolean DParagraph::suicide(short ownercount)
  402. {
  403.     if (ownercount < 1) {
  404.         delete this; 
  405.         return true; 
  406.         }
  407.     else 
  408.         return DObject::suicide(ownercount);
  409. }
  410.  
  411. #if 0
  412. DObject* DParagraph::Clone()
  413. {
  414.     DParagraph* result = (DParagraph*) DObject::Clone();
  415.     
  416.     if (fDocOwnsStyles) {
  417.         result->fStyleIndex= (StyleIndex*) MemDup( fStyleIndex, fNumStyles*sizeof(StyleIndex));
  418.         }
  419.     result->fText= (char*) StrDup( fText);
  420.     if (fDocOwnsData) result->fDataPtr= (char*) StrDup( fDataPtr);
  421.     result->tabkinds=  (char*) MemDup( tabkinds, numstops*sizeof(char) );
  422.     result->tabstops=  (short*) MemDup( tabstops, numstops*sizeof(short) );
  423.     return result;
  424. }
  425. #endif
  426.  
  427.  
  428. #if 0
  429. DParagraph& DParagraph::operator=( const DParagraph &val)
  430. {
  431.     this = (DParagraph*) val.Clone();
  432.     return *this; // ??????????
  433. }
  434. #endif
  435.  
  436.  
  437. void DParagraph::Copy(DParagraph* it)
  438. {
  439.     just = it->just;
  440.      tablead = it->tablead;                  
  441.     deftabstop = it->deftabstop;
  442.   numstops = it->numstops;
  443.     tabstops = it->tabstops;
  444.     tabkinds = it->tabkinds;
  445.     firstInset= it->firstInset;
  446.     leftInset= it->leftInset;
  447.     rightInset= it->rightInset;
  448.     spaceBefore= it->spaceBefore;
  449.     spaceAfter= it->spaceAfter;
  450.     spaceBetween =spaceBetween;
  451.     minLines = it->minLines;
  452.     minHeight = it->minHeight;
  453.     startsAt = it->startsAt;
  454.     numRows = it->numRows;     
  455.     lineHeight = it->lineHeight;
  456.     leadHeight = it->leadHeight; 
  457.   
  458.   fDataPtr = it->fDataPtr;     
  459.     fText = it->fText;             
  460.     fStyleIndex = it->fStyleIndex;
  461.     fNumStyles = it->fNumStyles;
  462.  
  463.     borderstyle    = it->borderstyle;
  464.     bordertop  = it->bordertop;
  465.     borderbottom = it->borderbottom;
  466.     borderleft  = it->borderleft;
  467.     borderright = it->borderright;
  468.     borderbetween = it->borderbetween;
  469.     borderbar = it->borderbar;
  470.     borderbox = it->borderbox;
  471.      
  472.     openSpace = it->openSpace;
  473.     keepWithNext = it->keepWithNext;
  474.     keepTogether = it->keepTogether;
  475.     newPage = it->newPage;
  476.     minLines = it->minLines;
  477.     minHeight = it->minHeight;
  478.     wrap = it-> wrap;
  479.  
  480.     notCached = it->notCached;
  481.     neverCached = it->neverCached;
  482.     fDocOwnsData= it->fDocOwnsData;
  483.     fDocOwnsStyles= it->fDocOwnsStyles;
  484. }
  485.  
  486.  
  487.  
  488. DParagraph::DParagraph()
  489. {
  490.     Initialize();
  491. }
  492.  
  493. DParagraph::DParagraph( char* data, Boolean docOwnsData, short lines, DParagraph* parFmt, 
  494.                        StyleIndex* styles, short numstyle, Boolean docOwnsStyles) 
  495. {
  496.     Initialize();
  497.     if (parFmt) {
  498.         //*this= *parFmt;
  499.         this->Copy( parFmt);
  500.     minLines= MAX( parFmt->minLines, (short) 1);
  501.     fText= NULL;
  502.     tabkinds= (char*) MemDup( parFmt->tabkinds, numstops*sizeof(char) );
  503.     tabstops= (short*)MemDup( parFmt->tabstops, numstops*sizeof(short) );
  504.       } 
  505.      fDataPtr= data;
  506.     fDocOwnsData = docOwnsData;
  507.     fDocOwnsStyles = docOwnsStyles;
  508.      fStyleIndex= styles;
  509.      fNumStyles= numstyle;
  510.     numRows = MAX(lines, 1);
  511. }
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519. //class DRichView : public DPanel
  520.  
  521.  
  522. extern "C" void richPanelClickProc(Nlm_PaneL item, Nlm_PoinT mouse)
  523. {
  524.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  525.     if (obj) obj->Click(mouse);
  526. }
  527.  
  528. extern "C" void richPanelDragProc(Nlm_PaneL item, Nlm_PoinT mouse)
  529. {
  530.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  531.     if (obj) obj->Drag(mouse);
  532. }
  533.  
  534. extern "C" void richPanelHoldProc(Nlm_PaneL item, Nlm_PoinT mouse)
  535. {
  536.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  537.     if (obj) obj->Hold(mouse);
  538. }
  539.  
  540. extern "C" void richPanelReleaseProc(Nlm_PaneL item, Nlm_PoinT mouse)
  541. {
  542.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  543.     if (obj) obj->Release(mouse);
  544. }
  545.  
  546. extern "C" void richPanelDrawProc(Nlm_PaneL item)
  547. {
  548.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  549.     if (obj) obj->Draw();
  550. }
  551.  
  552. extern "C" void richPanelScrollProc(Nlm_BaR sb, Nlm_SlatE slate, short newval, short oldval)
  553. {
  554.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)slate);
  555.     if (obj) obj->ScrollDoc(sb, newval, oldval);
  556.     //if (obj) obj->Scroll(true, obj, newval, oldval);
  557. }
  558.  
  559. extern "C" void richPanelResetProc(Nlm_PaneL item)
  560. {
  561.     DRichView *obj= (DRichView*) Nlm_GetObject( (Nlm_GraphiC)item);
  562.         // damn, this is called by Vibrant cleaner-upper AFTER DRichView::~DRichView() !!
  563.     if (obj) obj->ResetDoc();
  564. }
  565.  
  566.  
  567. //typedef    short (*CompareFunc)( void*, void*);     // compare two list/array Items 
  568.  
  569. short richPanelCompareStyles( void* item1, void* item2)
  570. {
  571. #if 0
  572.     if ( ((DRichStyle*) item1)->IsNotEqual( (DRichStyle*) item2) ) { 
  573.         if (item1 > item2) return 1;
  574.         else return -1;
  575.         }
  576.     else 
  577.         return 0;
  578. #else
  579.     return MemCmp( item1, item2, sizeof(DRichStyle));
  580. #endif
  581.  
  582.  
  583.  
  584. DRichView::DRichView(long id, DView* itsSuperior, short pixwidth, short pixheight):
  585.     DPanel(id, itsSuperior, pixwidth, pixheight, DPanel::subclasscreates)
  586. {
  587.      fNumItems= 0;
  588.     fNumLines= 0;
  589.     fBarmax= 0;
  590.     fDocFormat= 0;
  591.     fTabCount= 1;
  592.   fAutoAdjust= true; 
  593.   fIsVirtual= false; 
  594.   fDodraw= true;
  595.     fStyles= NULL; 
  596.     fParags= NULL; 
  597.     fCurrentStyle= NULL;
  598.     fSelParag= fSelChar= fSelEndParag= fSelEndChar= 0;
  599.     fSelected= fSelInPict= false;
  600.     ZeroCharWidths();
  601.  
  602. #if 0    
  603.     if (!Nlm_EmptyRect( &DRichTextDoc::gRichDocRect)) {
  604.         pixwidth= DRichTextDoc::gRichDocRect.right - DRichTextDoc::gRichDocRect.left;
  605.         pixheight= DRichTextDoc::gRichDocRect.bottom - DRichTextDoc::gRichDocRect.top;
  606.         }
  607. #endif        
  608.     if (pixwidth ==0) pixwidth = Nlm_screenRect.right - Nlm_screenRect.left - 60;
  609.     if (pixheight==0) pixheight= Nlm_screenRect.bottom - Nlm_screenRect.top - 120;
  610.             // these -## adjustments are not very good -- need to know what other
  611.             // views are in the given window and adjust for their size !?
  612.  
  613.     if (!itsSuperior) return; // FAILNil(itsSuperior)
  614.     Nlm_GrouP prnt= (Nlm_GrouP)itsSuperior->GetNlmObject();
  615.     if (!prnt) return; // FAILNil(prnt)
  616.   Nlm_WindoW tempPort = Nlm_SavePort(prnt);
  617.   fPanel= Nlm_AutonomousPanel(prnt, pixwidth, pixheight, richPanelDrawProc,
  618.                                richPanelScrollProc, NULL, 0,
  619.                                NULL/*richPanelResetProc*/, NULL);
  620.   if (!fPanel) return;  //FailNIL(fPanel);
  621.   if (tempPort) Nlm_RestorePort(tempPort);
  622.   
  623.     Nlm_SetPanelClick(fPanel, richPanelClickProc, richPanelDragProc, richPanelHoldProc, 
  624.                                         richPanelReleaseProc);
  625.     this->SetNlmObject(fPanel);
  626.     this->SetAutoAdjust(true); // used after append/insert/replace/delete
  627.     this->SetSlateBorder(true);
  628.  
  629.     fStyles= new DList( ::richPanelCompareStyles ); //, DList::kDeleteObjects); // + DList::kOwnObjects 
  630.     fParags= new DList( ); // NULL, DList::kDeleteObjects);
  631.     //fStyles->fArrayIncrement= 30;
  632.     //fParags->fArrayIncrement= 30;
  633.     
  634.     if (gNotInitted) InitRichView();
  635.     fCurrentStyle= new DRichStyle();
  636.     ClearCurrentStyle();
  637.  
  638.     Nlm_LoadRect( &fDrawr, 0,0,0,0);
  639.     fAtpt.x= fAtpt.y= 0;
  640.             
  641.     DWindow* win= this->GetWindow();
  642.     if (win) {
  643.         win->fPrintHandler= this;
  644.         win->fSaveHandler= this;
  645.         }
  646. }
  647.     
  648. DRichView::~DRichView()
  649. {
  650.     //?? need for SetDocData's DocFreeProc call...
  651.     //if (fStyles) delete fStyles; fStyles= NULL;
  652.     //if (fParags) delete fParags; fParags= NULL;
  653.         // damn, delete fList isn't calling object destructors !!!!
  654.     long i, n;
  655.     if (fStyles) {
  656.         n= fStyles->GetSize();
  657.         for (i=0; i<n; i++) {
  658.             DRichStyle* st= (DRichStyle*) fStyles->At(i);
  659.             if (st) delete st;
  660.             }
  661.         delete fStyles;
  662.         }
  663.     if (fParags) {
  664.         n= fParags->GetSize();
  665.         for (i=0; i<n; i++) {
  666.             DParagraph* pa= (DParagraph*) fParags->At(i);
  667.             if (pa) delete pa;
  668.             }
  669.         delete fParags;
  670.         }
  671.     if (fCurrentStyle) {
  672.         fCurrentStyle->ownpict= false;
  673.         delete fCurrentStyle;
  674.         }
  675. }
  676.  
  677. void  DRichView::DeleteAll() 
  678. {
  679.     short i, n;
  680.     if (fStyles) {
  681.         n= fStyles->GetSize();
  682.         for (i=0; i<n; i++) {
  683.             DRichStyle* st= (DRichStyle*) fStyles->At(i);
  684.             delete st;
  685.             }
  686.         fStyles->DeleteAll();
  687.         //delete fStyles;
  688.         }
  689.     if (fParags) {
  690.         n= fParags->GetSize();
  691.         for (i=0; i<n; i++) {
  692.             DParagraph* pa= (DParagraph*) fParags->At(i);
  693.             delete pa;
  694.             }
  695.         fParags->DeleteAll();
  696.         //delete fParags;
  697.         }
  698.     fNumItems= fNumLines= 0;
  699. }
  700.  
  701.  
  702.  
  703. void DRichView::InitRichView()
  704. {
  705.     gNotInitted= true;
  706.   for (short i = 0; i < MAXFONTS; i++) {
  707.     gFontHeights[i].font = NULL;
  708.     gFontHeights[i].height = 0;
  709.       }
  710.     gDrawPict = new DDrawPict();
  711. }
  712.  
  713.  
  714.  
  715. void DRichView::ViewRect( Nlm_RecT& r)  
  716.     DPanel::ViewRect( r);
  717.     Nlm_InsetRect(&r, 10, 4); 
  718. }
  719.  
  720.  
  721.  
  722.     
  723. void DRichView::SetSlateBorder(Boolean turnon) 
  724. {
  725.      Nlm_SetSlateBorder((Nlm_SlatE)fPanel, turnon);  
  726. }
  727.  
  728. void DRichView::SizeToSuperview( DView* super, Boolean horiz, Boolean vert)
  729. {
  730. #if 0
  731. #ifdef WIN_MOTIF
  732.     DPanel::SizeToSuperview( super, horiz, vert);
  733. #else
  734.     // size only lower and right sides == leave top area...
  735.     Nlm_RecT r, myr;
  736.     super->ViewRect(r);
  737.     GetPosition( myr); // ViewRect(myr); <<!!NO, diff from Get/SetPos
  738.     if (horiz)     myr.right= (r.right - r.left) +1;
  739.     // myr.right -= (Nlm_vScrollBarWidth - 8); // mswin patch !?
  740.     if (vert) myr.bottom =  (r.bottom - r.top)  +1; 
  741.     SetPosition( myr);
  742. #endif
  743. #endif
  744. }
  745.   
  746.  
  747. void DRichView::Resize(DView* superview, Nlm_PoinT sizechange)
  748. {
  749.     DPanel::Resize( superview, sizechange);
  750. }
  751.  
  752.  
  753.  
  754.  
  755.  
  756. DRichStyle* DRichView::GetStyle( short styleid)
  757. {
  758.     return (DRichStyle*) fStyles->At(styleid);
  759. }
  760.  
  761. DRichStyle* DRichView::GetStyleAtIndex(DParagraph* aParag, short styleindex)
  762. {    
  763.     short id= -1;
  764.     if (aParag) {
  765.         id= aParag->fStyleIndex[styleindex].styleid;
  766.         return (DRichStyle*) fStyles->At(id);  // id-1?? NO
  767.         }
  768.   else return NULL;
  769. }
  770.  
  771. DRichStyle* DRichView::GetStyleAtChar( DParagraph* aParag, short atchar)
  772. {
  773.     short id= -1;
  774.     if (aParag) {
  775.         short i;
  776.         for (i= aParag->fNumStyles-1; i>0; i--) { 
  777.             if (atchar >= aParag->fStyleIndex[i].nextofs) 
  778.                 break;
  779.             }
  780.         id= aParag->fStyleIndex[i].styleid; 
  781.         }
  782.     return (DRichStyle*) fStyles->At(id);  // id-1?? NO
  783. }
  784.  
  785. DRichStyle* DRichView::GetStyleAtChar( short atparag, short atchar)
  786. {
  787.     return GetStyleAtChar( (DParagraph*)fParags->At(atparag), atchar);
  788. }
  789.  
  790. short DRichView::FindOrAddStyle( DRichStyle* theStyle)
  791.     short styleid= fStyles->GetEqualItemNo( theStyle);
  792.     if (styleid == kEmptyIndex) {
  793.         DRichStyle* bst= new DRichStyle();
  794.         *bst= *theStyle;   // need a smart assign/copy method !! ?? a FIXED clone() ??
  795.         bst->ownpict= true;
  796.         theStyle->fPict= NULL; //theStyle->picdata= NULL;
  797.         fStyles->InsertLast(bst);
  798.         styleid= fStyles->GetSize() - 1;
  799.         }
  800.     return styleid;
  801. }
  802.  
  803.  
  804.  
  805.  
  806. DParagraph* DRichView::GetParaPtr( short item)
  807.     return (DParagraph*) fParags->At(item); 
  808. }
  809.  
  810.  
  811.  
  812. DParagraph* DRichView::MakeNewParag( void* data, short lines, 
  813.                         DParagraph* parFormat, DRichStyle* styles, short nstyles, Boolean docOwnsData)
  814. {
  815.     short ist, nst=0;
  816.     //if (styles) do nst++; while (!styles[nst-1].last);
  817.     StyleIndex* styleindex= (StyleIndex*) MemNew( nstyles*sizeof(StyleIndex));
  818.     for (ist=0; ist<nstyles; ist++) {
  819.         short id= FindOrAddStyle( &styles[ist]);
  820.         styleindex[ist].styleid= id;
  821.         styleindex[ist].nextofs= styles[ist].nextofs;
  822.         }
  823.     
  824.     return  new DParagraph( (char*)data, docOwnsData, lines, parFormat, styleindex, nstyles);
  825. }
  826.  
  827.  
  828. void     DRichView::AppendParag( DParagraph* aParag)
  829. {    
  830.   if (aParag) {
  831.         aParag->startsAt= fNumLines;
  832.     fNumLines += aParag->numRows;
  833.         fParags->InsertLast(aParag);
  834.     fNumItems++; // == fParags->GetSize();
  835.       }
  836. }
  837.  
  838. void     DRichView::Append( void* data, short lines, DParagraph* parFormat,  
  839.                         DRichStyle* styles, short nstyles, Boolean docOwnsData)
  840. {    
  841.     DParagraph* aParag= MakeNewParag( data, lines, parFormat, styles, nstyles, docOwnsData);
  842.   if (aParag) {
  843.     UpdateItemHeights(aParag);
  844.     AppendParag( aParag);
  845.     if (fAutoAdjust) AdjustScroll();
  846.       }
  847. }
  848.  
  849. void     DRichView::Insert( short item, void* data, short lines, DParagraph* parFormat, 
  850.                         DRichStyle* styles, short nstyles, Boolean docOwnsData)
  851. {
  852.     DParagraph* aParag= MakeNewParag( data, lines, parFormat, styles, nstyles, docOwnsData);
  853.   if (aParag) {
  854.     UpdateItemHeights(aParag);
  855.         DParagraph* pat= (DParagraph*)fParags->At(item);
  856.         if (pat) {
  857.             aParag->startsAt= pat->startsAt;
  858.             fParags->InsertBefore(item, aParag);
  859.         fNumLines = UpdateLineStarts(item);
  860.             fNumItems++; // == fParags->GetSize();
  861.         }
  862.       else {
  863.             AppendParag( aParag);    
  864.           }
  865.     if (fAutoAdjust) AdjustScroll();
  866.       }
  867. }
  868.  
  869. void     DRichView::Replace( short item, void* data, short lines, DParagraph* parFormat,  
  870.                 DRichStyle* styles, short nstyles, Boolean docOwnsData)
  871. {
  872.     DParagraph* aParag= MakeNewParag( data, lines, parFormat, styles, nstyles, docOwnsData);
  873.   if (aParag) {
  874.     UpdateItemHeights(aParag);
  875.         DParagraph* pat= (DParagraph*) fParags->At(item);
  876.         if (pat) {
  877.             aParag->startsAt= pat->startsAt;
  878.             fParags->AtPut(item, aParag);
  879.         fNumLines = UpdateLineStarts(item);
  880.             delete pat; // !? should DList do this on AtPut ?? it doesn't
  881.         }
  882.       else {
  883.             AppendParag( aParag);
  884.           }
  885.     if (fAutoAdjust) AdjustScroll();
  886.       }
  887. }
  888.  
  889.  
  890. void     DRichView::UpdateStyleHeight( DRichStyle* theStyle)
  891. {
  892.   if (theStyle) {
  893.       short theid= fStyles->GetIdentityItemNo( theStyle);
  894.         if (theid == kEmptyIndex) return;
  895.         
  896.       short j, item, nitem= fParags->GetSize();
  897.       for (item= 0; item<nitem; item++) {
  898.             DParagraph* pat= (DParagraph*) fParags->At(item);
  899.             for (j= 0; j< pat->fNumStyles; j++) {
  900.                 if (pat->fStyleIndex[j].styleid == theid) {
  901.                 short rtop, rbottom, firstline;
  902.                 UpdateItemHeights(pat);
  903.                 if (IsVisible( item, rtop, rbottom, firstline )) {
  904.                     Nlm_RecT    rec;
  905.                     ViewRect( rec);
  906.                         rec.top= rtop;
  907.                         InvalRect( rec);
  908.                     }
  909.                 break;
  910.                 }
  911.             }
  912.         }
  913.     if (fAutoAdjust) AdjustScroll();
  914.       }
  915. }
  916.  
  917.  
  918.  
  919.  
  920.  
  921. short DRichView::GetItemNum(short desiredLine)
  922. {
  923.     // Returns the number of the paragraph containing the desired line
  924.  
  925.   short mid = 1;
  926.   short left = 1;
  927.   short right = fNumItems;
  928.   Boolean goOn = TRUE;
  929.   while (left <= right && goOn) {
  930.     mid = (left + right) / 2;
  931.     DParagraph* aParag = GetParaPtr(mid - 1);
  932.     if (aParag) {
  933.       if (desiredLine < aParag->startsAt + aParag->numRows)  
  934.         right = mid - 1;
  935.       if (desiredLine >= aParag->startsAt)  
  936.         left = mid + 1;
  937.         } 
  938.     else {
  939.       goOn = FALSE;
  940.       mid = 1;
  941.         }
  942.   }
  943.   return mid - 1;
  944. }
  945.  
  946.  
  947.  
  948. void DRichView::SetStyle(DRichStyle* theStyle)
  949. {
  950.     if (!theStyle || theStyle->linkid || theStyle->ispict) 
  951.         return; /* do these styles separately */
  952.     if (theStyle->font != fCurrentStyle->font) 
  953.         Nlm_SelectFont(theStyle->font);
  954.     if (theStyle->color != fCurrentStyle->color)
  955.         Nlm_SetColor(theStyle->color);
  956.  
  957.     ZeroCharWidths();
  958.     *fCurrentStyle = *theStyle;
  959. }
  960.  
  961.  
  962. void DRichView::ClearCurrentStyle()
  963. {
  964.     fCurrentStyle->ispict= false;
  965.     fCurrentStyle->ismap= false;
  966.     fCurrentStyle->ownpict= false;
  967.     fCurrentStyle->fPict= NULL; //fCurrentStyle->picdata= NULL;
  968.     fCurrentStyle->font= NULL;
  969.     fCurrentStyle->superSub= 0;
  970.     fCurrentStyle->color= 0;
  971. }
  972.  
  973.  
  974.  
  975. short DRichView::CharWidth(char ch)
  976. {
  977.     unsigned char cw= fCharWidths[ch];
  978.     if (cw == kNoCharWidth) {
  979.         cw= Nlm_CharWidth(ch);
  980.          fCharWidths[ch]= cw;
  981.          }
  982.     return cw;
  983. }
  984.  
  985. void DRichView::ZeroCharWidths()
  986. {
  987.     Nlm_MemFill( fCharWidths, kNoCharWidth, 256); // sizeof(fCharWidths)
  988. }
  989.  
  990. short DRichView::StyleLineWidth(char* texts, short maxwid, DParagraph* itemPtr, short& istyle)
  991. {
  992.   Char               ch;
  993.   short              i,swid,wid,nextofs,numStyles;
  994.     Boolean         styleset;
  995.     DRichStyle * atstyle, savestyle;
  996.     
  997.   styleset= FALSE;
  998.   i = wid = swid = 0;
  999.     nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  1000.     numStyles= itemPtr->fNumStyles;
  1001.     atstyle= GetStyleAtIndex(itemPtr, istyle);
  1002.     savestyle= *atstyle;
  1003.     
  1004.      if (atstyle->ispict) wid += atstyle->pixwidth; 
  1005.     if (texts && maxwid > 0) {
  1006.     ch = texts[i];
  1007.     while (ch != '\0' && ch != '\n' && ch != '\r' && wid <= maxwid) {
  1008.  
  1009.       if (i>=nextofs && istyle<numStyles-1) {  // && !atstyle->last    
  1010.                 ++istyle;
  1011.                 nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  1012.                 atstyle= GetStyleAtIndex(itemPtr, istyle);
  1013.              SetStyle(atstyle);
  1014.              styleset= TRUE;
  1015.               if (atstyle->ispict) wid += atstyle->pixwidth; 
  1016.         }
  1017.         
  1018.       else if (!atstyle->hidden) {
  1019.             if (ch == '\t') {
  1020.                         // fix this tab width !!!
  1021.                   }
  1022.             else wid += CharWidth(ch);
  1023.           }
  1024.       
  1025.       i++;
  1026.       ch = texts [i];
  1027.         }
  1028.       }
  1029.     if (styleset) SetStyle( &savestyle);
  1030.     savestyle.ownpict= false;
  1031.   return wid;
  1032. }
  1033.  
  1034.  
  1035.  
  1036. short DRichView::FitTextToWidth(char* texts, short maxwid, Boolean byPixels,
  1037.                           DParagraph* itemPtr, short& istyle)
  1038. {
  1039.             // Returns the number of characters in the next block, including 
  1040.             // trailing spaces (which are trimmed back later)
  1041.   Char  ch;
  1042.   short  i,j,wid, swid, nextofs, numStyles;
  1043.     Boolean wordWrap, styleset;
  1044.     DRichStyle *atstyle, savestyle;
  1045.     
  1046.     nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  1047.     numStyles= itemPtr->fNumStyles;
  1048.     atstyle= GetStyleAtIndex(itemPtr, istyle);
  1049.     SetStyle(atstyle); // be sure ??
  1050.     savestyle= *atstyle;
  1051.     wordWrap= itemPtr->wrap;
  1052.   i = j = 0;
  1053.   wid = swid = 0;
  1054.   if (texts && maxwid > 0) {
  1055.     ch = texts [i];
  1056.     while (ch != '\0' && ch != '\n' && ch != '\r' && wid <= maxwid) {
  1057.       if (wordWrap) {
  1058.           if (i>=nextofs && istyle<numStyles-1) {   //if (ch == chStyleTag) 
  1059.                     ++istyle;
  1060.                     nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  1061.                     atstyle= GetStyleAtIndex(itemPtr, istyle);
  1062.                SetStyle(atstyle);
  1063.                styleset= TRUE;
  1064.                 if (atstyle->ispict && byPixels) wid += atstyle->pixwidth; 
  1065.             }
  1066.             
  1067.         else if (!atstyle->hidden) {
  1068.               if (ch == '\t') {
  1069.                         /* !!! FIX THIS !?!?! */
  1070.                 }
  1071.           else if (byPixels) wid += CharWidth (ch);
  1072.           else wid++;
  1073.             }
  1074.           }
  1075.       i++;
  1076.       ch = texts [i];
  1077.         }
  1078.           
  1079.     j = i;
  1080.     if (wordWrap && wid > maxwid) {
  1081.         // don't break in a word, and leave trailing spaces at end of line 
  1082.       j--;
  1083.       if (byPixels)  
  1084.         while (Nlm_TextWidth(texts, i) >= maxwid)  i--;
  1085.       else 
  1086.         while (i >= maxwid) i--;
  1087.       while (i > 0 && texts[i - 1] != ' ' && texts[i - 1] != '-')  i--;
  1088.       while (texts [i] == ' ')  i++;
  1089.         }
  1090.         
  1091.       }
  1092.     if (styleset) SetStyle( &savestyle);
  1093.     savestyle.ownpict= false; //!!
  1094.   if (i > 0 && i < j) return i;
  1095.     else if (j > 0) return j;
  1096.     else  return 0;
  1097. }
  1098.  
  1099.  
  1100.  
  1101.  
  1102.  
  1103.  
  1104. void DRichView::ParseText(DParagraph* itemPtr, char* text, Boolean byPixels, Nlm_RecT r)
  1105. {
  1106.             //  Parses text that contains \t, \r and \n characters into a list of
  1107.             //  cells organized by row and column
  1108.  
  1109.   char        ch, just;
  1110.   short       inset,
  1111.             istyle, numStyles, col, blklen, len,width,maxwid,
  1112.                       numRows,tabRow,returnRow,row;
  1113.   Uint2        start;
  1114.   Boolean      wrap;
  1115.     char           * ptex, * newtex;
  1116.     ulong         maxsize, newsize;
  1117.     
  1118.   if (itemPtr && text && *text != '\0') {
  1119.       numStyles= itemPtr->fNumStyles;
  1120.        istyle= 0;
  1121.     if (numStyles) {
  1122.         DRichStyle savestyle;
  1123.         savestyle= *fCurrentStyle;
  1124.         ClearCurrentStyle();
  1125.         SetStyle(GetStyleAtIndex(itemPtr, istyle));
  1126.         
  1127.           maxsize= (ulong) (StrLen(text) + 50 + itemPtr->minLines);
  1128.           newsize= 0;
  1129.           newtex = (char*) MemNew (maxsize);
  1130.          ptex= newtex;
  1131.          
  1132.       width = 0;
  1133.       inset = itemPtr->leftInset; /* pixLeft, pixFirst ?? */
  1134.       just = itemPtr->just; /*'l';*/
  1135.       wrap = itemPtr->wrap; /* TRUE; /* fix this as choice ... */
  1136.       start = 0;
  1137.       row = 0;
  1138.       tabRow = 0;
  1139.       returnRow = 1;
  1140.       col = 0;
  1141.       numRows = 0;
  1142.       while (text[start] != '\0') {
  1143.         ch = text[start];
  1144.         if (ch != '\0' && ch != '\n' && ch != '\r'  ) {
  1145.           maxwid =  r.right - r.left - 15; // !!! Need PAGEWIDTH here !!
  1146.           short istyle0= istyle;                    
  1147.           blklen =  FitTextToWidth(text + start, maxwid, byPixels, 
  1148.                               itemPtr, istyle);
  1149.                 if (istyle!=istyle0) SetStyle(GetStyleAtIndex(itemPtr, istyle));
  1150.           len = blklen;
  1151.           
  1152.           if (len > 0) {
  1153.             if (text[start + len] != '\0') { // eat trailing spaces 
  1154.               while (len > 0 && text [start + len - 1] == ' ') len--;
  1155.               if (len == 0) len = blklen;
  1156.                 }
  1157.             if (newsize+len > maxsize) {
  1158.                 maxsize= newsize+len+100;
  1159.                 newtex= (char*) MemMore(newtex, maxsize);  
  1160.                 }
  1161.             MemCpy( newtex+newsize, text+start, len);
  1162.             newsize += len;
  1163.             start += blklen;
  1164.               } 
  1165.               
  1166.           else { // len==0, shouldn't be true ? 
  1167.  
  1168.               }
  1169.             }
  1170.             
  1171.         ch = text [start];
  1172.         if (ch == '\n') {
  1173.                  newtex[newsize++]= '\n';
  1174.               start++;
  1175.           row = returnRow;
  1176.           tabRow = row;
  1177.           returnRow++;
  1178.           col = 0;
  1179.             } 
  1180.         else if (ch == '\r') {
  1181.                  newtex[newsize++]= '\n';
  1182.           start++;
  1183.           row++;
  1184.           returnRow = MAX (returnRow, row + 1);
  1185.                } 
  1186. #if 0
  1187.         else if (ch == '\t') {
  1188.           start++;
  1189.           row = tabRow;
  1190.               newtex[newsize++]= '\t';
  1191.           if (text [start] == '\0') row = returnRow;
  1192.             } 
  1193. #endif
  1194.         else if (ch != '\0' && wrap) {
  1195.               newtex[newsize++]= '\n';
  1196.           if (len == 0) start++;
  1197.           row++;
  1198.           returnRow = MAX (returnRow, row + 1);
  1199.             } 
  1200.         else if (ch != '\0') 
  1201.             start++;
  1202.         else if (text [start - 1] != '\n' && text [start - 1] != '\r')  
  1203.           row = returnRow;
  1204.          
  1205.         numRows = MAX (numRows, row);
  1206.           }
  1207.       itemPtr->numRows = MAX (numRows, itemPtr->minLines);
  1208.             newtex[newsize++]= '\0';
  1209.             itemPtr->fText = newtex;
  1210.             SetStyle(&savestyle);
  1211.             savestyle.ownpict= false; // !!
  1212.         }
  1213.       } 
  1214.   else if (itemPtr != NULL)  
  1215.     itemPtr->numRows = 0;
  1216. }
  1217.  
  1218.  
  1219.  
  1220.  
  1221.  
  1222. // temp globals...
  1223.  
  1224. static short gMapOfs = 0;
  1225. //static DRichStyle* gMapStyle = NULL;
  1226.  
  1227. short DRichView::DrawStyledItem(DParagraph* itemPtr, Nlm_RectPtr rpara, short item,
  1228.                                       short frst, Boolean forPrinter, Nlm_PoinT* mapPoint)
  1229. {
  1230.                 // Draws a given paragraph(item) on the screen, using parag & char styles 
  1231.   char         ch, just, csave;
  1232.   Boolean      isnewline, bartab, dotab, mapPt, drawSelection,   
  1233.                           aBorderLast, aBorderNext, gray, doborder;
  1234.   char         * ptext, * text;
  1235.   unsigned long            nextofs;
  1236.   short     lineHeight, num, row, rsult, rleft, rright, rbottom, width, maxwid,
  1237.                          istyle,styleid, istyle2, numStyles, superSub, txtwidth, yfont; 
  1238.                       
  1239.   DRichStyle    * astyle;  
  1240.   Nlm_RecT         rct; // drw
  1241.     Nlm_PoinT            pt1, pt2; //, atpt;
  1242.     
  1243.     mapPt= (mapPoint != NULL);
  1244.     if (mapPt) fMapStyle= NULL;
  1245.     fDodraw= (mapPoint == NULL);
  1246.     drawSelection= (fSelected && fDodraw && !forPrinter 
  1247.                                     && item >= fSelParag && item <= fSelEndParag);
  1248.   rsult = 0;
  1249.   if (itemPtr && rpara) {
  1250.     text = itemPtr->fText;
  1251.     numStyles= itemPtr->fNumStyles;
  1252.     
  1253.     if (text && *text != '\0') {
  1254.         just= itemPtr->just;
  1255.       lineHeight = itemPtr->lineHeight;
  1256.       rct.top = rpara->top;
  1257.       rct.bottom = rct.top;
  1258.             rbottom = rct.top + lineHeight * (itemPtr->numRows - frst);
  1259.              rleft= fAtpt.x = rpara->left + itemPtr->leftInset + itemPtr->firstInset;
  1260.       fAtpt.y = rpara->top;
  1261.       row = 0;
  1262.       txtwidth= 0;
  1263.       ptext = text;
  1264.       ch = *ptext;
  1265.           gray = FALSE;
  1266.             isnewline= TRUE;
  1267.  
  1268. //Debug("1");
  1269.          istyle= 0;
  1270.          styleid= itemPtr->fStyleIndex[istyle].styleid;
  1271.          nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  1272.              astyle= GetStyle(styleid);
  1273.  
  1274.             Nlm_LoadRect(&fDrawr, rleft, rpara->top, rpara->right, rbottom);
  1275.             
  1276.       if (itemPtr->newPage) {
  1277.           /* probably on line by self... */
  1278.           /* record footnote text somewhere and dump out here before page break... */
  1279.           if (fDodraw && !forPrinter) {
  1280.                     Nlm_Dashed(); // Nlm_Dotted(); 
  1281.                 Nlm_FrameRect(&fDrawr);
  1282.                     Nlm_ResetDrawingTools();
  1283.                     }
  1284.           }
  1285.                        
  1286.          ClearCurrentStyle();
  1287.          SetStyle(astyle);
  1288.             superSub= astyle->superSub;
  1289.             
  1290.       while (ch != '\0') {
  1291.       
  1292.         if (ch == '\n') {
  1293.           rct.top = rpara->top + (row - frst) * lineHeight;
  1294.           rct.bottom = rct.top + lineHeight;
  1295.             rleft= fAtpt.x = rpara->left + itemPtr->leftInset;
  1296.           row++;
  1297.           ptext++; 
  1298.           isnewline= TRUE;
  1299. //Debug("/");
  1300.             } 
  1301.                     
  1302.         else if (ch == chPictTag) {
  1303.           ptext++;
  1304.             } 
  1305.            
  1306.         else  {
  1307.         
  1308.                     while ( (ptext - text >= nextofs) && (istyle < numStyles-1)) {
  1309. //Debug("s");
  1310.                      istyle++;
  1311.                      styleid= itemPtr->fStyleIndex[istyle].styleid;
  1312.                      nextofs= itemPtr->fStyleIndex[istyle].nextofs;
  1313.                      if (!((ptext - text >= nextofs) && (istyle < numStyles-1))) {
  1314.                              astyle= GetStyle(styleid);
  1315.                          SetStyle(astyle);
  1316.                             superSub= astyle->superSub;
  1317.                             }
  1318.                         }
  1319.  
  1320.                   if (isnewline) {
  1321.                          doborder= itemPtr->borderright || itemPtr->borderleft 
  1322.                                 || itemPtr->borderbottom || itemPtr->bordertop 
  1323.                                 || itemPtr->borderbox;
  1324.                         if (doborder) {        
  1325.                          DParagraph*  otherItem;
  1326.                            
  1327.                            aBorderLast= FALSE;
  1328.                            aBorderNext= FALSE;
  1329.                          if (item>1 && itemPtr->bordertop || itemPtr->borderbox) {
  1330.                              otherItem = GetParaPtr(item-2);  //! item# is +1 of parag# 
  1331.                              aBorderLast= (otherItem->bordertop || otherItem->borderbox);
  1332.                              }
  1333.                          if (itemPtr->borderbottom || itemPtr->borderbox) {
  1334.                              otherItem = GetParaPtr(item);    //! item# is +1 of parag# 
  1335.                                 if (otherItem) aBorderNext= (otherItem->borderbottom || otherItem->borderbox);
  1336.                              }
  1337.                          }
  1338.  
  1339.                 if (just != 'l') {
  1340.                     istyle2= istyle;
  1341.                   maxwid=  rpara->right - rpara->left; //!!! Need PAGEWIDTH here !!
  1342.                              width= StyleLineWidth( ptext, maxwid, itemPtr, istyle2);
  1343.                              if (width<maxwid) {
  1344.                                  switch (just) {
  1345.                                      case 'r': 
  1346.                                          fAtpt.x= /*rleft= */ MAX( rleft, rpara->right - itemPtr->rightInset - width); 
  1347.                                          break;
  1348.                                      case 'c': { 
  1349.                                          short rhalf= ((rpara->right - itemPtr->rightInset - rleft) - width) / 2; 
  1350.                                          if (rhalf>0) fAtpt.x= rleft += rhalf;
  1351.                                          }
  1352.                                          break;
  1353.                                      }
  1354.                                  }
  1355.                     }
  1356.                       isnewline= FALSE;
  1357.                       }
  1358.                       
  1359.                 num = 0;
  1360.                 while ( ch == '\t') ch= ptext[++num];
  1361.           while ( ch != '\0' && ch != '\n' && ch != '\t' 
  1362.               && ( (num + ptext - text) < nextofs))   
  1363.                 ch = ptext[++num];
  1364.  
  1365.           if (row >= frst) {
  1366.                     Boolean inrect;
  1367.  
  1368.  //Debug("r");
  1369.             rct.top = rpara->top + (row - frst) * lineHeight;
  1370.             rct.bottom = rct.top + lineHeight;
  1371.             rct.left = fAtpt.x;  
  1372.             rct.right = rpara->right - itemPtr->rightInset; 
  1373.                         if (doborder && row == itemPtr->numRows-1 
  1374.                             && (itemPtr->borderbottom || itemPtr->borderbox)) 
  1375.                                 rct.bottom--;
  1376.             Nlm_LoadRect (&fDrawr, MAX (rct.left, rpara->left), rct.top,
  1377.                       MIN (rct.right, rpara->right), rct.bottom);
  1378.  
  1379. #if 1
  1380.                         inrect= (rct.top <= rpara->bottom && rct.bottom > rpara->top);
  1381. #else
  1382.                          inrect= Nlm_SectRect( &fDrawr, rpara, &rsect);
  1383. #endif
  1384.             if ( inrect && (mapPt || forPrinter || Nlm_updateRgn == NULL ||
  1385.                      Nlm_RectInRgn (&rct, Nlm_updateRgn))) {
  1386.               fDrawr = rct;
  1387.                             fDrawr.top += superSub; 
  1388.                             fDrawr.bottom += superSub;  
  1389. // Debug1("%d",num);
  1390.               if (num > 0  && !(astyle->hidden)) {
  1391. // Debug("i");
  1392.                   just= 'l';
  1393.                        bartab= FALSE;
  1394.                      dotab= FALSE;
  1395.  
  1396.                         /* yfont= fDrawr.top + Nlm_Ascent();  /* a. large font mismatch */
  1397.                            /* yfont= fDrawr.bottom - Nlm_Descent() - Nlm_Leading(); /* b. better than a */
  1398.                            /* yfont= fDrawr.bottom - Nlm_Descent(); /* c. almost perfect, slight font mismatch */
  1399.                         /* yfont= fDrawr.top + Nlm_FontHeight(); /* d. bad, too low, font mismatch */
  1400.                            yfont= fDrawr.bottom - 4; /* Nlm_stdDescent; /* e. !! YES, but what is right ## ?? */
  1401.                            /* yfont= fDrawr.top + Nlm_FontHeight() - Nlm_Descent(); /* f. ?? */
  1402.  
  1403.                 while (num > 0 && *ptext == '\t') {
  1404.                   dotab= TRUE;
  1405.                   num--;
  1406.                   ptext++;
  1407.                   
  1408.                   if (fDrawr.left < rleft) /* rpara->left + itemPtr->leftInset + itemPtr->firstInset */
  1409.                       fDrawr.left= rleft;
  1410.                   else if (itemPtr->numstops) {
  1411.                        short istop, nextstop;
  1412.                        istop= 0;
  1413.                       do { 
  1414.                           /* nextstop = rpara->left + itemPtr->leftInset + itemPtr->tabstops[istop]; */
  1415.                           nextstop = rleft + itemPtr->tabstops[istop];
  1416.                           istop++; 
  1417.                           }
  1418.                       while (istop<itemPtr->numstops && nextstop>0 && nextstop<fDrawr.left);
  1419.                       
  1420.                       /* ?? 27may */
  1421.                       nextstop = MIN(nextstop, rpara->right - itemPtr->rightInset/* - width*/);
  1422.                       
  1423.                       if (*ptext == '\t')
  1424.                           fDrawr.left= nextstop;
  1425.                       else switch (itemPtr->tabkinds[istop-1]) {
  1426.                           case DParagraph::kTabBar:
  1427.                                   bartab= TRUE;
  1428.                           case DParagraph::kTabDecimal: 
  1429.                           case DParagraph::kTabLeft    : 
  1430.                                   just= 'l'; 
  1431.                                      fDrawr.left= nextstop;
  1432.                                   break;
  1433.                           case DParagraph::kTabRight: 
  1434.                                   just= 'r'; 
  1435.                                   fDrawr.right= nextstop;
  1436.                                   break;
  1437.                           case DParagraph::kTabCenter: 
  1438.                                   just= 'c'; 
  1439.                                   fDrawr.right= nextstop + (nextstop - fDrawr.left);
  1440.                                   break;
  1441.                           }
  1442.                          }
  1443.                   else { 
  1444.                       short nextstop= rleft; /* rpara->left + itemPtr->leftInset;*/
  1445.                       if (itemPtr->deftabstop>0)
  1446.                        do { nextstop += itemPtr->deftabstop; }
  1447.                        while (nextstop>0 && fDrawr.left > nextstop);
  1448.                       fDrawr.left= nextstop;
  1449.                       }
  1450.                         
  1451.                     fAtpt.x = fDrawr.left; /* ??? */
  1452.                     }
  1453.                     
  1454.                    if (dotab && itemPtr->tablead > ' ') {
  1455.                     char    tabbuf[256];
  1456.                     short    cwidth, tabcount= 0;
  1457.                     Nlm_RecT    tabr;
  1458.                     
  1459.                     cwidth= CharWidth(itemPtr->tablead);
  1460.                                 tabr= rct;
  1461.                                 tabr.right= fDrawr.left;
  1462.                                 tabcount= MIN(254, MAX(1, (tabr.right - tabr.left - 1) / cwidth + 1));
  1463.                                 Nlm_MemFill( tabbuf, itemPtr->tablead, tabcount);
  1464.                                 tabbuf[tabcount]= 0;
  1465.                        Nlm_MoveTo(tabr.left, yfont); /*! need to ajust for leading !*/
  1466.                        if (fDodraw) Nlm_PaintString(tabbuf);
  1467.                     }
  1468.                
  1469.                                 if (bartab) {
  1470.                                     pt1.x= pt2.x= fDrawr.left;
  1471.                                     pt1.y= rct.top;
  1472.                                     pt2.y= rct.bottom;
  1473.                                     if (fDodraw) Nlm_DrawLine(pt1,pt2);
  1474.                                     fAtpt.x= ++fDrawr.left;
  1475.                                     }
  1476.  
  1477.                     if (astyle->allcaps || astyle->smallcaps) { 
  1478.                         char* cp= ptext;
  1479.                         for (short i=0; i<num; i++) cp[i]= to_upper(cp[i]);
  1480.                             // need to shift fontsize down for lowercases 
  1481.                         }
  1482.  
  1483.                         txtwidth= Nlm_TextWidth(ptext, num); 
  1484.                          
  1485.                   switch (just) {
  1486.                          case 'c': 
  1487.                              rright= (fDrawr.left + txtwidth + fDrawr.right)/ 2; 
  1488.                                         fDrawr.left += (fDrawr.right - fDrawr.left - txtwidth) / 2; 
  1489.                              break;
  1490.                          case 'r':
  1491.                              rright = fDrawr.right; 
  1492.                              fDrawr.left = fDrawr.right - txtwidth; 
  1493.                              break;
  1494.                          default:
  1495.                          case 'l':
  1496.                                    /* rright= fDrawr.left + astyle->pixwidth; */
  1497.                                 rright= fDrawr.left + txtwidth + 1;
  1498.                              break;
  1499.                          }
  1500.                          
  1501.                      /* these are no good for multilines w/ same style, & resizing changes */
  1502.                                 if (astyle->pixwidth==0) astyle->pixwidth= rright - fAtpt.x;
  1503.                                 astyle->pixleft= fAtpt.x;
  1504.  
  1505. #if 0
  1506.     // this looks too messy !!
  1507.     // ?? quick fix for html text that is off screen to left or right ?
  1508.                                 if (rright > rpara->right) Nlm_OffsetRect( &fDrawr, rpara->right-rright, 0);
  1509.                                 if (fDrawr.left < rpara->left) fDrawr.left= rpara->left;
  1510. #endif
  1511.                                 
  1512.                      Nlm_MoveTo(fDrawr.left, yfont);  // yfont == adjust for leading
  1513.                      if (fDodraw) {
  1514.                          csave= ptext[num]; ptext[num]= 0;
  1515.                          Nlm_PaintString(ptext);
  1516.                      ptext[num]= csave;                                    
  1517.                               }
  1518.  
  1519.                      else if (mapPoint && Nlm_PtInRect( *mapPoint, &fDrawr)) {
  1520.                          if (astyle->ispict) {
  1521. #if 0
  1522.                                         astyle->fPict->FindPt( fDrawr, pt);
  1523.                                         // return isInPict && point-rel to pict && astyle or styleid !!
  1524. #endif
  1525.                                 fAtpt.x= rright;
  1526.                              fDrawr.left= fAtpt.x;  
  1527.                              gMapOfs= (short)(ptext - text); // pict point ??
  1528.                            fMapStyle= astyle;
  1529.                              return gMapOfs; // text point..
  1530.                              }
  1531.                          else {
  1532.                              // return also num chars !?
  1533.                              short atx= mapPoint->x - fDrawr.left;
  1534.                              short    i= num;
  1535.                              if (Nlm_TextWidth(ptext, i) >= atx) {
  1536.                                  while (i>0 && Nlm_TextWidth(ptext, i) > atx) i--;
  1537.                                  gMapOfs= (short)(ptext + i - text);
  1538.                                             fMapStyle= astyle;
  1539.     
  1540.                                      // !! not finding proper style (for links)
  1541.                                  short ist= istyle;
  1542.                                  short nof= nextofs;
  1543.                                  short sid= styleid;
  1544.                                  while ( gMapOfs >= nof && ist < numStyles-1 ) {
  1545.                                              ist++;
  1546.                                              sid= itemPtr->fStyleIndex[ist].styleid;
  1547.                                              nof= itemPtr->fStyleIndex[ist].nextofs;
  1548.                                                 fMapStyle= GetStyle(sid);
  1549.                                                 }
  1550.                                  return gMapOfs; // text point..
  1551.                                  }
  1552.                              else {
  1553.                                  // ??? continue on for more of ptext, if proper line ...
  1554.                                  // there must be some mistake in fDrawr if we get here??
  1555.                                  }
  1556.                              }
  1557.                          }
  1558.  
  1559.                                 if (astyle->linkid && fDodraw) {
  1560.                                   if (!forPrinter) {
  1561.                                          Nlm_SetColor(astyle->color);
  1562. #if 1
  1563.                                         Nlm_WidePen(2);
  1564.                                         /* Nlm_Dotted(); /* Nlm_Dashed(); */
  1565.                                         Nlm_MoveTo( fDrawr.left, fDrawr.bottom-2);
  1566.                                         Nlm_LineTo( rright-1, fDrawr.bottom-2);
  1567.                                         Nlm_WidePen(1);
  1568.                                         Nlm_Solid();
  1569. #else
  1570.                                         fDrawr.right= rright-1;
  1571.                                         Nlm_FrameRect( &fDrawr);
  1572. #endif
  1573.                                         Nlm_SetColor(fCurrentStyle->color);
  1574.                                         }
  1575.                                     }
  1576.                                 else if (astyle->boxed && fDodraw) {
  1577.                                     fDrawr.right= rright-1;
  1578.                                     Nlm_FrameRect( &fDrawr);
  1579.                                     }
  1580.  
  1581.                                 Nlm_Black(); /* need this or something like to fix color bug in XWin */
  1582.  
  1583.                                 if (drawSelection) {
  1584.                                     short textofs= ptext - text; 
  1585.                                     short textend= textofs + num; 
  1586.                                     Nlm_RecT selr= fDrawr;
  1587.                                     Boolean showsel= true;
  1588.                                     short  baseleft= selr.left;
  1589.                                     
  1590.                                     if (item == fSelParag) {
  1591.                                         if (textend < fSelChar) showsel= false;
  1592.                                         if (showsel && textofs < fSelChar) 
  1593.                                             selr.left = MIN( selr.right, 
  1594.                                                 baseleft + Nlm_TextWidth( ptext, fSelChar - textofs));
  1595.                                         }
  1596.                                         
  1597.                                     if (showsel && item == fSelEndParag) {
  1598.                                       if (textofs > fSelEndChar) showsel= false;
  1599.                                         if (showsel && textofs < fSelEndChar) //textend > fSelEndChar
  1600.                                             selr.right = MAX(selr.left, 
  1601.                                                 baseleft + Nlm_TextWidth( ptext, fSelEndChar - textofs));
  1602.                                         }
  1603.  
  1604.                                     if (showsel) Nlm_InvertRect( &selr);
  1605.                                     }
  1606.                                     
  1607.                                     
  1608.                         fAtpt.x= rright;
  1609.  
  1610.                    if (astyle->strikeout && fDodraw) {
  1611.                        short dmid= (fDrawr.top + fDrawr.bottom) / 2;
  1612.                        Nlm_MoveTo( fDrawr.left, dmid);
  1613.                        Nlm_LineTo( fAtpt.x, dmid);
  1614.                        }
  1615.                      fDrawr.left= fAtpt.x;  
  1616.  
  1617.                                 if (astyle->ispict) {
  1618.                                     fDrawr.right = fDrawr.left + astyle->pixwidth;
  1619.                                     fDrawr.bottom= fDrawr.top + astyle->pixheight;
  1620.                                   fAtpt.x= fDrawr.right+1;
  1621.                                     if (fDodraw) {
  1622.                                         if (astyle->fPict) astyle->fPict->Draw( fDrawr);
  1623.                                         Nlm_ResetDrawingTools();
  1624.                                         }
  1625.                                     fDrawr.left= fAtpt.x;
  1626.                                     }
  1627.                    }
  1628.                  fDrawr.right = rct.right;
  1629.               
  1630.                                 // !! top/bottom borders need to be turned off when adjacent parags also have them 
  1631.                             if (doborder && fDodraw) {
  1632.  
  1633.                                 switch (itemPtr->borderstyle) {
  1634.                                     case DParagraph::kBorderThick    : Nlm_WidePen(3); break;
  1635.                                     case DParagraph::kBorderDot        : Nlm_Dotted(); break;
  1636.                                     case DParagraph::kBorderDash    : Nlm_Dashed(); break;
  1637.                                     case DParagraph::kBorderDouble: break;
  1638.                                     case DParagraph::kBorderSingle: break;
  1639.                                     case DParagraph::kBorderShadow: break;
  1640.                                     case DParagraph::kBorderHair    : break;
  1641.                                     }
  1642.  
  1643.                                 if (!aBorderLast && (itemPtr->bordertop || itemPtr->borderbox) && row==0) {
  1644.                                     /* respect borderstyle...*/
  1645.                                     pt1.x= rpara->left;
  1646.                                     pt2.x= rpara->right-1;
  1647.                                     pt1.y= pt2.y= rct.top;
  1648.                                     Nlm_DrawLine(pt1,pt2);
  1649.                                     if (itemPtr->borderstyle == DParagraph::kBorderDouble) {
  1650.                                         pt1.y= pt2.y= rct.top-2;
  1651.                                         Nlm_DrawLine(pt1,pt2);
  1652.                                         }
  1653.                                     }
  1654.                                 if (!aBorderNext && row == itemPtr->numRows-1 && (itemPtr->borderbottom || itemPtr->borderbox)) {
  1655.                                     pt1.x= rpara->left;
  1656.                                     pt2.x= rpara->right-1;
  1657.                                     pt1.y= pt2.y= rct.bottom;
  1658.                                     Nlm_DrawLine(pt1,pt2);
  1659.                                     if (itemPtr->borderstyle == DParagraph::kBorderDouble) {
  1660.                                         pt1.y= pt2.y= rct.bottom+2;
  1661.                                         Nlm_DrawLine(pt1,pt2);
  1662.                                         }
  1663.                                     }
  1664.                                 if ((itemPtr->borderleft || itemPtr->borderbox)) {
  1665.                                     pt1.x= pt2.x= rpara->left;
  1666.                                     pt1.y= rct.top;
  1667.                                     pt2.y= rct.bottom;
  1668.                                     Nlm_DrawLine(pt1,pt2);
  1669.                                     if (itemPtr->borderstyle == DParagraph::kBorderDouble) {
  1670.                                         pt1.x= pt2.x= rpara->left-2;
  1671.                                         Nlm_DrawLine(pt1,pt2);
  1672.                                         }
  1673.                                     }
  1674.                                 if ((itemPtr->borderright || itemPtr->borderbox)) {
  1675.                                     pt1.x= pt2.x= rpara->right-1; /* past scrollbar...*/
  1676.                                     pt1.y= rct.top;
  1677.                                     pt2.y= rct.bottom;
  1678.                                     Nlm_DrawLine(pt1,pt2);
  1679.                                     if (itemPtr->borderstyle == DParagraph::kBorderDouble) {
  1680.                                         pt1.x= pt2.x= rpara->right+2;
  1681.                                         Nlm_DrawLine(pt1,pt2);
  1682.                                         }
  1683.                                     }
  1684.                                 Nlm_ResetDrawingTools();
  1685.                                  doborder= FALSE;
  1686.                                 }
  1687.               }
  1688.               }
  1689.                     if (!num) ptext++; else ptext += num;
  1690.             }
  1691.         ch = *ptext;
  1692.              }
  1693.       rct.top = rct.bottom;
  1694.       rsult = rct.top - rpara->top;
  1695.         }
  1696.     Nlm_SelectFont(Nlm_programFont);  //Nlm_systemFont
  1697.       }
  1698.   if (mapPt) return -1;   // couldn't find mapPoint if we got here
  1699.   else return rsult;
  1700. }
  1701.  
  1702.  
  1703.  
  1704.  
  1705.  
  1706. char* DRichView::DataToChar(char* ptr)  
  1707. {
  1708.   if (ptr) 
  1709.     return Nlm_StringSave((char*)ptr);
  1710.   else 
  1711.     return NULL;
  1712. }
  1713.  
  1714.  
  1715. void DRichView::FormatText( short item, DParagraph* itemPtr, Boolean byPixels)
  1716. {
  1717.         // parses and rearranges the text so that it can be displayed, saved, or printed
  1718.   char           ch;
  1719.   Boolean        needToParse;
  1720.   short       numRows;
  1721.   char*            text;
  1722.     Nlm_RecT        r;
  1723.     
  1724.     /* dgg &fix this */
  1725.  
  1726.   if (itemPtr && itemPtr->fText == NULL) {
  1727.         this->ViewRect( r);
  1728.     needToParse = TRUE;
  1729.         text = this->DataToChar(itemPtr->fDataPtr);
  1730.         
  1731.     if (needToParse && text && *text != '\0') {
  1732.       ParseText(itemPtr, text, byPixels, r);
  1733.       itemPtr->notCached = FALSE;
  1734.       itemPtr->neverCached = FALSE;
  1735.       MemFree(text);
  1736.         } 
  1737.     else  
  1738.       itemPtr->fText = text;
  1739.      
  1740.     text = itemPtr->fText;
  1741.     if (text == NULL || *text == '\0') {
  1742.       MemFree(itemPtr->fText);
  1743.       itemPtr->fText = StringSave(" \n");
  1744.       itemPtr->numRows = 1;
  1745.       itemPtr->notCached = FALSE;
  1746.       itemPtr->neverCached = FALSE;
  1747.       needToParse = TRUE;
  1748.         } 
  1749.     else if (fIsVirtual) {
  1750.       numRows = 0;
  1751.       ch = *text;
  1752.       while (ch != '\0') {
  1753.         if (ch == '\n') numRows++;
  1754.         text++;
  1755.         ch = *text;
  1756.           }
  1757.       numRows = MAX (1, numRows);
  1758.       itemPtr->numRows = MAX (numRows, itemPtr->minLines);
  1759.         }
  1760.   }
  1761. }
  1762.  
  1763.  
  1764. short DRichView::GetLineStart(short item)
  1765. {
  1766.             // Returns the first line of the item
  1767.   DParagraph*  itemPtr = GetParaPtr(item);  
  1768.   if (itemPtr) return itemPtr->startsAt;
  1769.   else return 0;
  1770. }
  1771.  
  1772. short DRichView::GetNumRows(short item)
  1773. {
  1774.                 //   Returns the number of rows in the item
  1775.   DParagraph*  itemPtr  = GetParaPtr( item);  
  1776.   if (itemPtr)  return itemPtr->numRows;
  1777.   else return 0;
  1778. }
  1779.  
  1780. short DRichView::GetLineHeight(short item)
  1781. {
  1782.         //     Returns the pixel height of the item
  1783.   DParagraph*  itemPtr  = GetParaPtr( item);  
  1784.   if (itemPtr)  return itemPtr->lineHeight;
  1785.   else return 0;
  1786. }
  1787.  
  1788.  
  1789.  
  1790.  
  1791.     
  1792. Boolean DRichView::Doc2ViewOffset(short& xoff, short& yoff)
  1793. {
  1794.   Nlm_RecT             viewr, rct;
  1795.   short             atline, itemNum, leadHeight, lineHeight, numRows, off;
  1796.   Nlm_BaR          sb;
  1797.   DParagraph*      itemPtr;
  1798.     
  1799.     ViewRect( viewr);
  1800.     Nlm_LoadRect( &rct, 0, 0, viewr.right - viewr.left, 0);
  1801.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  1802.     if (sb) off = Nlm_GetValue(sb); // line offset of view
  1803.     else off= 0;
  1804.     
  1805.     //for (atline=0; atline<= off; atline++)  
  1806.     atline = 0;
  1807.     leadHeight = 0;
  1808.     itemNum = 0; //= GetItemNum( atline);
  1809.     while (itemNum < fNumItems && atline < off) {
  1810.         itemPtr = GetParaPtr( itemNum);
  1811.       if (itemPtr) {
  1812.             rct.top = rct.bottom + leadHeight;
  1813.       CacheIfNever( itemNum + 1, itemPtr, &viewr);
  1814.           if (atline>0) rct.top += itemPtr->spaceBefore;
  1815.       lineHeight = itemPtr->lineHeight;
  1816.       rct.top += leadHeight;
  1817.       numRows = itemPtr->numRows;
  1818.       rct.bottom = rct.top + lineHeight * (numRows) + itemPtr->spaceAfter;
  1819.            leadHeight = itemPtr->leadHeight;
  1820.           atline += numRows;
  1821.             }
  1822.         itemNum++;
  1823.         }
  1824.  
  1825.     xoff = rct.left;
  1826.     yoff = rct.top; // - viewr.top; // ??? was +top
  1827.     return true;
  1828. }    
  1829.  
  1830.     
  1831. Boolean DRichView::MapDoc2View( Nlm_RecT& selr)
  1832. {
  1833.   Nlm_RecT     viewr, rct;
  1834.     short        xoff, yoff;
  1835.  
  1836.     Doc2ViewOffset(xoff, yoff);
  1837.     selr.left         -= xoff;
  1838.     selr.right     -= xoff;
  1839.     selr.top         -= yoff;
  1840.     selr.bottom -= yoff;
  1841.     
  1842.     ViewRect( viewr);
  1843. #ifdef DBUG
  1844.     return true;        // !! SectRect always false for WIN_MOTIF !!!!!        
  1845. #else
  1846.     Boolean visible= Nlm_SectRect( &selr, &viewr, &rct);
  1847.     return visible;
  1848. #endif
  1849. }
  1850.  
  1851. void DRichView::MapView2Doc( Nlm_RecT& selr)
  1852. {
  1853.     short        xoff, yoff;
  1854.     
  1855.     Doc2ViewOffset(xoff, yoff);
  1856.     selr.left         += xoff;
  1857.     selr.right     += xoff;
  1858.     selr.top         += yoff;
  1859.     selr.bottom += yoff;
  1860. }
  1861.     
  1862. void DRichView::MapView2Doc( Nlm_PoinT& mpt)
  1863. {
  1864.     short        xoff, yoff;
  1865.     
  1866.     Doc2ViewOffset(xoff, yoff);
  1867.     mpt.x         += xoff;
  1868.     mpt.y         += yoff;
  1869. }
  1870.  
  1871.  
  1872. Boolean    DRichView::HiliteText(short startparag, short startchar, 
  1873.                                                             short endparag, short endchar, Boolean turnon) 
  1874.             // Finds the visible region of an startparag in a document
  1875.   short             firstItem, fstLine, itemNum, leadHeight,lineHeight, numRows, off;
  1876.   Nlm_RecT         viewr, rct;
  1877.   Boolean              goOn, rsult;
  1878.   Nlm_BaR          sb;
  1879.   DParagraph*      itemPtr;
  1880.  
  1881.   rsult = FALSE;
  1882.      //top = 0;
  1883.      //bottom = 0;
  1884.   //firstline = 0;
  1885.  
  1886.     ViewRect( viewr);
  1887.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  1888.   if (sb) off = Nlm_GetValue(sb);
  1889.   else off= 0;
  1890.   if (startparag >= 0 && startparag < fNumItems) {
  1891.     goOn = TRUE;
  1892.     Nlm_LoadRect(&rct, viewr.left, viewr.top, viewr.right, viewr.top);
  1893.     itemNum = GetItemNum( off);
  1894.     itemPtr = GetParaPtr( itemNum);
  1895.     if (itemPtr) {
  1896.       fstLine = off - itemPtr->startsAt;
  1897.       firstItem = itemNum;
  1898.       lineHeight = 0;
  1899.       leadHeight = 0;
  1900.       numRows = 0;
  1901.       while (goOn && itemNum < fNumItems && itemNum <= startparag) {
  1902.         itemPtr = GetParaPtr( itemNum);
  1903.         if (itemPtr) {
  1904.           CacheIfNever( itemNum + 1, itemPtr, &viewr);
  1905.           if (itemNum > firstItem)  
  1906.             leadHeight = itemPtr->leadHeight;
  1907.             else  
  1908.             leadHeight = 0;
  1909.               if (fstLine==0) rct.top += itemPtr->spaceBefore;
  1910.           
  1911.           lineHeight = itemPtr->lineHeight;
  1912.           rct.top += leadHeight;
  1913.           numRows = MIN (itemPtr->numRows,
  1914.                          MAX ((viewr.bottom - rct.top) / lineHeight, 0));
  1915.           rct.bottom = rct.top + lineHeight * (numRows - fstLine);
  1916.               rct.bottom += itemPtr->spaceAfter;
  1917.           if (itemNum == startparag) {
  1918.             //goOn = FALSE;
  1919.             if (numRows > 0) {
  1920.                 //top = rct.top;
  1921.                 //bottom = rct.bottom;
  1922.                 //firstline = fstLine;
  1923.                 fSelRect.top= rct.top;
  1924.                 fSelRect.bottom= rct.bottom;
  1925.                 //gMapOfs
  1926.                 fSelRect.left= rct.left; // this is bogus, just is left edge...
  1927.                 fSelRect.right= rct.right; // this also is bogus
  1928.               rsult = TRUE;
  1929.                 }
  1930.               } 
  1931.           else  
  1932.             rct.top = rct.bottom;
  1933.           if (numRows < itemPtr->numRows)  
  1934.             goOn = FALSE;
  1935.             }
  1936.         itemNum++;
  1937.         fstLine = 0;
  1938.           }
  1939.         }
  1940.       }
  1941.     fSelRect.bottom= rct.bottom; //????
  1942.      MapView2Doc( fSelRect); //?? need to get it working ??
  1943.   return rsult;
  1944. }
  1945.  
  1946.  
  1947.  
  1948.  
  1949. void DRichView::HiliteSelection(Boolean turnon)
  1950. {
  1951.     if (fSelected) {
  1952.         Nlm_RecT viewr, selr;
  1953.         
  1954.         selr= fSelRect;
  1955.         Boolean visible= MapDoc2View( selr);
  1956.         // !! must map sel location to current view (w/ sb) and see if it
  1957.         // is in view window !!
  1958.         
  1959.         if (!visible) 
  1960.             return;
  1961.         else {
  1962.                 // getting cases where this is called when this view's window is NOT front
  1963.             //DWindow* savewin=  gWindowManager->SavePort(this);
  1964.             if (fSelInPict) {
  1965.                 //Nlm_InvertRect( &selr);
  1966.                 Nlm_InvertMode();
  1967.                 Nlm_FrameRect( &selr);
  1968.                 Nlm_CopyMode();
  1969.                 }
  1970.             else {
  1971.                 ViewRect( viewr);
  1972.                 selr.left= viewr.left;
  1973.                 selr.right= viewr.right;
  1974.                 selr.top= MAX( viewr.top, selr.top - 20);  // expand inval area for full line
  1975.                 selr.bottom = MIN( viewr.bottom, selr.bottom ); 
  1976.                 InvalRect( selr); // let DrawStyledItem do work ?
  1977.                 Boolean savesel= fSelected;
  1978.                 fSelected= turnon;
  1979.                 Nlm_Update();  // this->Draw();
  1980.                 fSelected= savesel;
  1981.                 }
  1982.             //if (savewin) gWindowManager->RestorePort(savewin);
  1983.             }
  1984.         }
  1985. }
  1986.  
  1987. void DRichView::ClearSelection()
  1988. {
  1989.         //?? before unHilite to cure draw bug ??
  1990.     fSelParag= fSelChar= fSelEndParag= fSelEndChar= 0;
  1991.     HiliteSelection(false);
  1992.     //fSelParag= fSelChar= fSelEndParag= fSelEndChar= 0;
  1993.     fSelInPict= false;
  1994.     fSelected= false;
  1995. }
  1996.  
  1997.  
  1998. void DRichView::SetSelectedText( short startparag, short startchar, 
  1999.                                                                     short endparag, short endchar)
  2000. {
  2001.     ClearSelection(); // clear any old sel -- i.e., wipe view markings
  2002.     fSelInPict= false; //!! check if selrect is in a picture !!
  2003.     fSelParag    = Max(0, Min(startparag, fNumItems));      
  2004.     fSelChar    = Max(0, startchar);          // check max !? 
  2005.     
  2006.     fSelEndParag    = Max(0, Min(endparag, fNumItems));      
  2007.     // if endchar==0 endchar== maxchar ??
  2008.     fSelEndChar      = Max(0, endchar);     // check max !? 
  2009.     fSelected= (fSelParag > 0 || fSelChar > 0 || fSelEndChar > 0);
  2010.  
  2011.             // !! NEED THIS parag/char -> fSelRect mapper !!
  2012.     if (HiliteText( fSelParag, fSelChar, fSelEndParag, fSelEndChar, false) ) ;
  2013.  
  2014.     HiliteSelection(fSelected);
  2015. }
  2016.  
  2017. void DRichView::SelectAll()
  2018. {
  2019.     short                    itemNum, leadHeight, atline;
  2020.   Nlm_RecT            viewr, rct;
  2021.   DParagraph*      itemPtr;
  2022.     
  2023.     ClearSelection(); // clear any old sel -- i.e., wipe view markings
  2024.     ViewRect( viewr);
  2025.     Nlm_LoadRect( &rct, 0, 0, viewr.right - viewr.left, 0);
  2026.     atline = 0;
  2027.     leadHeight = 0; 
  2028.     itemNum = 0; //= GetItemNum( atline);
  2029.     while (itemNum < fNumItems) {
  2030.         itemPtr = GetParaPtr( itemNum);
  2031.       if (itemPtr) {
  2032.       CacheIfNever( itemNum + 1, itemPtr, &viewr); // this counts item->numRows
  2033.       if (atline>0) rct.bottom += itemPtr->spaceBefore; 
  2034.       rct.bottom += leadHeight  
  2035.                               + itemPtr->lineHeight * (itemPtr->numRows) 
  2036.                               + itemPtr->spaceAfter;
  2037.            leadHeight = itemPtr->leadHeight;
  2038.           atline += itemPtr->numRows;
  2039.             }
  2040.         itemNum++;
  2041.         }
  2042.  
  2043.     fSelRect= rct;  
  2044.     //MapView2Doc( fSelRect);
  2045.     fSelInPict= false; //!! check if selrect is in a picture !!
  2046.     fSelParag= 1;     // parag # are +1 from MapPoint !!
  2047.     fSelChar= 0;      
  2048.     fSelEndParag= fNumItems;         // parag # are +1 of item# from MapPoint !!
  2049.     fSelEndChar= 0;       
  2050.     fSelected= (fSelParag > 0 && fSelEndParag > 0);
  2051.     HiliteSelection(fSelected);
  2052. }
  2053.  
  2054.  
  2055. void DRichView::MarkSelection( Nlm_RecT selrect)
  2056. {
  2057.     Nlm_PoinT pt;
  2058.     short            row, parag;
  2059.     Nlm_RecT    arect;
  2060.     char            word[50];
  2061.     
  2062.     ClearSelection(); // clear any old sel -- i.e., wipe view markings
  2063.     fSelRect= selrect; // ?? don't we need to map selrect in view coords to doc coords !?
  2064.     MapView2Doc( fSelRect);
  2065.     fSelInPict= false; //!! check if selrect is in a picture !!
  2066.  
  2067.     pt.x= selrect.left;
  2068.     pt.y= selrect.top;
  2069.     MapPoint( pt, parag, row, &arect, word, 40, &fSelStyle);
  2070.     fSelParag= parag;     // parag # are +1 from MapPoint !!
  2071.     fSelChar= gMapOfs;     // dang global... fix mappoint to return it!
  2072.                         // fSelChar was correct
  2073.     if (fSelStyle.ispict) {
  2074.         fSelInPict= true;
  2075.             // ??? must make fSelRect relative to pict frame
  2076.         //fSelRect.left -= fDrawr.left;
  2077.         //fSelRect.right -= fDrawr.left;
  2078.         //fSelRect.top -= fDrawr.top;
  2079.         //fSelRect.bottom -= fDrawr.top;
  2080.         fSelEndParag= 0;
  2081.         fSelEndChar= 0;
  2082.         fSelected= (fSelParag > 0);
  2083.         }
  2084.     else {    
  2085.         pt.x= selrect.right;
  2086.         pt.y= selrect.bottom;
  2087.         MapPoint( pt, parag, row, &arect, word, 40, NULL);
  2088.         fSelEndParag= parag;         // parag # are +1 of item# from MapPoint !!
  2089.         fSelEndChar= gMapOfs;      // fSelEndChar is too large ???
  2090.         fSelected= (fSelParag > 0 && fSelEndParag > 0);
  2091.         }
  2092.     HiliteSelection(fSelected);
  2093. }
  2094.  
  2095.  
  2096. Boolean DRichView::GetSelection( Boolean& inpict,
  2097.                     short& selparag, short& selchar, 
  2098.                     short& selendparag, short& selendchar,
  2099.                     Nlm_RecT& selrect, DRichStyle* selstyle)
  2100. {
  2101.     inpict= fSelInPict;
  2102.     selparag= fSelParag - 1; // !!!!!! FIX DAMN +1 used above !!!!!!
  2103.     selchar= fSelChar;
  2104.     selendparag= fSelEndParag - 1; // !!!!!! FIX DAMN +1 used above !!!!!!
  2105.     selendchar= fSelEndChar;
  2106.     selrect= fSelRect; // !? must we map from doc coords to view coords ??
  2107.     if (selstyle) { *selstyle = fSelStyle; } //style at start of selection (for pict !?)
  2108.     return fSelected;
  2109. }
  2110.  
  2111. char* DRichView::GetSelectedText()
  2112. {
  2113.     long startp, endp, startc, endc;
  2114.     char* theText= NULL;
  2115.  
  2116.     if (fSelInPict) {
  2117.         return NULL; // for now, fix to copy pict to system clipboard
  2118.         }
  2119.         
  2120.     if (fSelParag) {
  2121.         // if selection == NULL ?? return all of text ????
  2122.         startp= fSelParag - 1; 
  2123.         endp= fSelEndParag - 1;
  2124.         startc= fSelChar;
  2125.         endc= fSelEndChar;
  2126.         }
  2127.     else {
  2128.         startp= 0; 
  2129.         endp= fNumItems-1;
  2130.         startc= 0;
  2131.         endc= 0;
  2132.         }
  2133.     
  2134.     for (short par= startp; par<= endp; par++) {
  2135.             // need to handle start/end chars ...
  2136.         DParagraph* itemPtr = GetParaPtr( par);
  2137.         if (itemPtr) {
  2138.             Boolean first= (par == startp);
  2139.             Boolean last = (par == endp);
  2140.             char  savec = 0;
  2141.             char* partext= (char*) itemPtr->fDataPtr;
  2142. #if 1
  2143.             if (first) partext += startc;
  2144.             if (last && endc) {
  2145.                 savec= partext[endc+1];
  2146.                 partext[endc+1]= 0;
  2147.                 }
  2148. #endif
  2149.             if (theText) StrExtendCat( &theText, partext);
  2150.             else theText= StrDup( partext);
  2151.             StrExtendCat( &theText, LINEEND); // append newline for each parag ?
  2152.             if (savec) partext[endc+1]= savec;
  2153.             }
  2154.         }
  2155.          
  2156.     return theText;
  2157. }
  2158.  
  2159.  
  2160.  
  2161. short DRichView::UpdateLineStarts(short first)
  2162. {
  2163.             //  Recalculates the first lines as a running sum of the number of rows
  2164.   short     i;
  2165.   DParagraph*  itemPtr;
  2166.   short     totalNumLines;
  2167.  
  2168.   totalNumLines = 0;
  2169.     itemPtr  = GetParaPtr( first);
  2170.   if (itemPtr) totalNumLines = itemPtr->startsAt;
  2171.   for (i = first; i < fNumItems; i++) {
  2172.     itemPtr = GetParaPtr( i);
  2173.     if (itemPtr) {
  2174.       itemPtr->startsAt = totalNumLines;
  2175.       totalNumLines += itemPtr->numRows;
  2176.         }
  2177.       }
  2178.   return totalNumLines;
  2179. }
  2180.  
  2181.  
  2182. void DRichView::CollectRange(short item, short& lowest, short& highest)
  2183. {
  2184.   lowest  = MIN(lowest, item);
  2185.   highest = MAX(highest, item);
  2186. }
  2187.  
  2188.  
  2189.  
  2190. void DRichView::CacheAndFormat(short item, DParagraph* itemPtr, Nlm_RectPtr r)
  2191. {
  2192.                 //  Formats text (for drawing) if the item text is not currently cached
  2193.   if (itemPtr && r && itemPtr->notCached) FormatText(item, itemPtr, TRUE);
  2194. }
  2195.  
  2196. void DRichView::CacheIfNever( short item, DParagraph* itemPtr, Nlm_RectPtr r)
  2197. {
  2198.         //     Formats text (for obtaining the correct number of rows) if the item
  2199.         //     text has never been cached
  2200.   if (itemPtr && r && itemPtr->neverCached) FormatText(item, itemPtr, TRUE);
  2201. }
  2202.  
  2203.  
  2204. void DRichView::FreeCachedItem( short item, short& lowest, short& highest)
  2205. {
  2206.         // Frees the formatted text string for an item that is not currently visible
  2207.   DParagraph*  itemPtr = GetParaPtr( item);
  2208.   if (itemPtr) {
  2209.     itemPtr->fText = (char*) MemFree (itemPtr->fText);
  2210.     itemPtr->notCached = TRUE;
  2211.     if (fIsVirtual && fNumItems > 0) {
  2212.       itemPtr->numRows = 30000 / fNumItems;
  2213.       CollectRange(item, lowest, highest);
  2214.         }
  2215.       }
  2216. }
  2217.  
  2218.  
  2219. short DRichView::VisLinesAbove(Nlm_RectPtr r, short item,
  2220.                            short line, short& lowest, short& highest)
  2221. {
  2222.         //    Returns the number of lines visible on the screen if the given line
  2223.         //    in the given item is the last line visible
  2224.   DParagraph*  itemPtr;
  2225.   short     pixels, vis;
  2226.  
  2227.   vis = 0;
  2228.   if ( r && item < fNumItems) {
  2229.     pixels = r->bottom - r->top;
  2230.     while (pixels > 0 && item >= 0) {
  2231.       itemPtr = GetParaPtr( item);
  2232.       if (itemPtr) {
  2233.         CollectRange( item, lowest, highest);
  2234.         CacheIfNever( item + 1, itemPtr, r);
  2235.         if (line < 0)  line = itemPtr->numRows - 1;
  2236.         while (pixels > 0 && line >= 0 && line < itemPtr->numRows) {
  2237.           pixels -= itemPtr->lineHeight;
  2238.           if (pixels >= 0)  vis++;
  2239.           line--;
  2240.             }
  2241.         pixels -= itemPtr->leadHeight;
  2242.         pixels -= itemPtr->spaceBefore + itemPtr->spaceAfter;
  2243.           }
  2244.       item--;
  2245.         }
  2246.       }
  2247.   return vis;
  2248. }
  2249.  
  2250.  
  2251.  
  2252. short DRichView::VisLinesBelow( Nlm_RectPtr r, short item,
  2253.                                        short line, short& lowest, short& highest)
  2254. {
  2255.         //    Returns the number of lines visible on the screen if the given line
  2256.         //    in the given item is the first line visible
  2257.   DParagraph*  itemPtr;
  2258.   short     pixels, vis;
  2259.  
  2260.   vis = 0;
  2261.   if (r && item < fNumItems && item >= 0) {
  2262.     pixels = r->bottom - r->top;
  2263.     while (pixels > 0 && item < fNumItems) {
  2264.       itemPtr = GetParaPtr( item);
  2265.       if (itemPtr) {
  2266.         CollectRange(item, lowest, highest);
  2267.         CacheIfNever(item + 1, itemPtr, r);
  2268.         if (line  < 0) {
  2269.           line = 0;
  2270.           pixels -= itemPtr->leadHeight;
  2271.             pixels -= itemPtr->spaceBefore + itemPtr->spaceAfter;
  2272.             }
  2273.         while (pixels > 0 && line >= 0 && line < itemPtr->numRows) {
  2274.           pixels -= itemPtr->lineHeight;
  2275.           if (pixels >= 0) vis++;
  2276.           line++;
  2277.             }
  2278.         line = -1;
  2279.           }
  2280.       item++;
  2281.         }
  2282.       }
  2283.   return vis;
  2284. }
  2285.  
  2286.  
  2287.  
  2288. short DRichView::PixelsBetween( Nlm_RectPtr r, short firstLine,
  2289.                            short lastLine, short& lowest, short& highest)
  2290. {
  2291.              //   Returns the number of pixels between two lines
  2292.      short     count;
  2293.   short     item;
  2294.   DParagraph*  itemPtr;
  2295.   short     line;
  2296.   short     numLines;
  2297.   short     onItem;
  2298.   short     pixels;
  2299.  
  2300.   pixels = 0;
  2301.   if ( r ) {
  2302.       // dgg -- are these line no.s off by one??  came from Scroll()
  2303.       // firstLine--; lastLine--;
  2304.     count = ABS (lastLine - firstLine);
  2305.     item = GetItemNum( MIN (firstLine, lastLine));
  2306.     itemPtr = GetParaPtr( item);
  2307.     onItem = item;
  2308.     if (itemPtr != NULL && item >= 0) {
  2309.       CollectRange( item, lowest, highest);
  2310.       CacheIfNever( item + 1, itemPtr, r);
  2311.       line = MIN (firstLine, lastLine) - itemPtr->startsAt;
  2312.       while (count > 0 && item < fNumItems) {
  2313.         if (item != onItem) {
  2314.           itemPtr = GetParaPtr( item);
  2315.           onItem = item;
  2316.             }
  2317.         if ( itemPtr ) {
  2318.           CollectRange (item, lowest, highest);
  2319.           CacheIfNever ( item + 1, itemPtr, r);
  2320.           numLines = itemPtr->numRows;
  2321. #if 1
  2322.                     if (line == 0) pixels += itemPtr->spaceBefore;
  2323.                     if (MAX(firstLine,lastLine) >= numLines + itemPtr->startsAt)
  2324.                         pixels += itemPtr->spaceAfter;
  2325. #else
  2326.         // ?? old here is bad -- don't do spaceBefore unless this is 1st line in parag
  2327.         // likewise spaceafter if this is last
  2328.                 pixels += itemPtr->spaceBefore + itemPtr->spaceAfter;  
  2329. #endif
  2330.           while (count > 0 && line >= 0 && line < numLines) {
  2331.             pixels += itemPtr->lineHeight;
  2332.             line++;
  2333.             count--;
  2334.               }
  2335.             }
  2336.         item++;
  2337.         if (line >= numLines) {
  2338.           itemPtr = GetParaPtr( item);
  2339.           onItem = item;
  2340.           if (itemPtr != NULL) {
  2341.             CollectRange (item, lowest, highest);
  2342.             CacheIfNever ( item + 1, itemPtr, r);
  2343.             pixels += itemPtr->leadHeight;
  2344.               }
  2345.             }
  2346.         line = 0;
  2347.           }
  2348.       if (lastLine < firstLine)  pixels = -pixels;
  2349.         }
  2350.       }
  2351.   return pixels;
  2352. }
  2353.  
  2354.  
  2355.  
  2356. void DRichView::Draw()
  2357. {
  2358.             //    Panel callback that traverses the item list and draws visible items
  2359.             //    Clipping is to the intersection of the Nlm_updateRgn (the portion of the
  2360.             //    panel exposed) and the inset area of the document, leaving a four-
  2361.             //    pixel margin
  2362.  
  2363.   Nlm_RegioN   dst;
  2364.   DParagraph*  itemPtr;
  2365.   short          firstLine, highest, item, lowest, off, pixels;
  2366.   Nlm_RecT     r, rct;
  2367.   Nlm_BaR      sb;
  2368.   Nlm_RegioN   src;
  2369.  
  2370.   if (fNumItems > 0) {
  2371. //Debug("DRichView::Draw\n");
  2372.         ViewRect( r);
  2373.     sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  2374.         if (sb) off = Nlm_GetValue(sb);
  2375.         else off= 0;
  2376.     src = Nlm_CreateRgn ();
  2377.     dst = Nlm_CreateRgn ();
  2378.     Nlm_LoadRectRgn (src, r.left, r.top, r.right, r.bottom);
  2379.     Nlm_SectRgn (src, Nlm_updateRgn, dst);
  2380.     Nlm_ClipRgn (dst);
  2381.     Nlm_DestroyRgn (src);
  2382.     Nlm_DestroyRgn (dst);
  2383.     pixels = 0;
  2384.     lowest = INT2_MAX;
  2385.     highest = INT2_MIN;
  2386.     item = GetItemNum( off);
  2387.     itemPtr = GetParaPtr( item);
  2388.     if (itemPtr) {
  2389.       firstLine = off - itemPtr->startsAt;
  2390.       do {
  2391.         if (itemPtr) {
  2392.           if (itemPtr->neverCached)  CollectRange(item, lowest, highest);
  2393.           CacheAndFormat( item+1, itemPtr, &r);
  2394.           if (pixels != 0)  r.top += itemPtr->leadHeight;
  2395.                   if (firstLine == 0) r.top += itemPtr->spaceBefore;
  2396.           rct = r;
  2397.           rct.bottom = rct.top + itemPtr->lineHeight * (itemPtr->numRows - firstLine);
  2398.           Boolean inrgn= (Nlm_updateRgn == NULL || Nlm_RectInRgn (&rct, Nlm_updateRgn));
  2399.           if (inrgn) {
  2400. //Debug(".");
  2401.             pixels = DrawStyledItem( itemPtr, &r, item+1, firstLine, FALSE, NULL);
  2402.               } 
  2403.           else  
  2404.             pixels = rct.bottom - rct.top;
  2405.            
  2406.           r.top += pixels;
  2407.                   r.top += itemPtr->spaceAfter;
  2408.             }
  2409.         item++;
  2410.         firstLine = 0;
  2411.         itemPtr = GetParaPtr( item);
  2412.       } while (r.top < r.bottom && item < fNumItems);
  2413.       if (lowest < INT2_MAX) 
  2414.         fNumLines = UpdateLineStarts( lowest);
  2415.      
  2416.     }
  2417.     Nlm_ResetClip ();
  2418.      
  2419.   }
  2420.     Nlm_SelectFont(Nlm_programFont);  //Nlm_systemFont
  2421. //Debug("DRichView::Draw done\n");
  2422. }
  2423.  
  2424.  
  2425.  
  2426.  
  2427.  
  2428.  
  2429.  
  2430.  
  2431. void  DRichView::AdjustScroll() 
  2432. {
  2433.             // Calculates an estimate for the scroll bar maximum
  2434.   short     barmax,barval,firstShown,highest, item;
  2435.   short     line,lineInto,lowest;
  2436.   short     pgDn, pgUp, vis;
  2437.   DParagraph*  itemPtr;
  2438.   Nlm_RecT     r;
  2439.   Nlm_BaR      sb;
  2440.  
  2441.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE) fPanel);
  2442.   if (sb) {
  2443.     if (fNumLines > 0 && fNumItems > 0) {
  2444.           Nlm_SelectFont(Nlm_programFont);  //Nlm_systemFont
  2445.             ViewRect( r);
  2446.       barval = Nlm_GetValue (sb);
  2447.       item = GetItemNum ( barval);
  2448.       line = barval - GetLineStart( item);
  2449.       firstShown = item;
  2450.       lineInto = line;
  2451.       lowest = INT2_MAX;
  2452.       highest = INT2_MIN;
  2453.       itemPtr = GetParaPtr(fNumItems - 1);
  2454.       if (itemPtr) 
  2455.         vis = VisLinesAbove ( &r, fNumItems - 1,
  2456.                              itemPtr->numRows - 1, lowest, highest);
  2457.       pgUp = VisLinesAbove ( &r, item, line, lowest, highest) - 1;
  2458.       pgDn = VisLinesBelow ( &r, item, line, lowest, highest) - 1;
  2459.       if (pgDn < 1) pgDn = 1;
  2460.       if (pgUp < 1) pgUp = 1;
  2461.       if (lowest < INT2_MAX) 
  2462.         fNumLines = UpdateLineStarts( lowest);
  2463.       
  2464.       itemPtr = GetParaPtr(fNumItems - 1);
  2465.       if (itemPtr) {
  2466.         barmax = 0;
  2467.               ViewRect( r);
  2468.         lowest = INT2_MAX;
  2469.         highest = INT2_MIN;
  2470.         vis = VisLinesAbove ( &r, fNumItems - 1,
  2471.                              itemPtr->numRows - 1, lowest,  highest);
  2472.         if (lowest < INT2_MAX) 
  2473.           fNumLines = UpdateLineStarts ( lowest);
  2474.          
  2475.         barmax = fNumLines - vis;
  2476.         barval = GetLineStart(firstShown) + lineInto;
  2477.         Nlm_CorrectBarPage (sb, pgUp, pgDn);
  2478.         if (barval > fBarmax) {
  2479.           Nlm_CorrectBarMax (sb, barmax);
  2480.           Nlm_CorrectBarValue (sb, barval);
  2481.             } 
  2482.         else {
  2483.           Nlm_CorrectBarValue (sb, barval);
  2484.           Nlm_CorrectBarMax (sb, barmax);
  2485.             }
  2486.         fBarmax = barmax;
  2487.           }
  2488.         } 
  2489.     else  
  2490.       Nlm_Reset (sb);
  2491.       }
  2492. }
  2493.  
  2494.  
  2495.  
  2496.  
  2497.  
  2498.  
  2499. void  DRichView::UpdateItemHeights(DParagraph* aParag)
  2500. {
  2501.             // Returns the maximum height of all fonts used in an item
  2502.   short         i, linhgt,maxhgt;
  2503.  
  2504.   if (aParag) {
  2505.     maxhgt = 0;
  2506.     i = aParag->fNumStyles;
  2507.     while (i > 0) {
  2508.       i--;
  2509.       DRichStyle* st= GetStyleAtIndex(aParag, i);
  2510.       if (st->ispict) 
  2511.                  linhgt = st->pixheight + 4; // add a few pixels for leading !?
  2512.       else  
  2513.           linhgt = GetFontHeight(st->font) + abs(st->superSub); 
  2514.       if (linhgt > maxhgt) maxhgt = linhgt;
  2515.         }
  2516.     if (maxhgt == 0)  maxhgt = Nlm_stdLineHeight;
  2517.     aParag->lineHeight = MAX(maxhgt, aParag->minHeight);
  2518.     if ( aParag->openSpace)  
  2519.       aParag->leadHeight = maxhgt;
  2520.     else 
  2521.       aParag->leadHeight = 0;
  2522.       }
  2523. }
  2524.  
  2525.  
  2526. short DRichView::SkipPastNewLine(char* text, short cnt)
  2527. {
  2528.   char  ch;
  2529.   ch = *(text + cnt);
  2530.   while (ch != '\0' && ch != '\n' && cnt < 16380) {
  2531.     cnt++;
  2532.     ch = *(text + cnt);
  2533.       }
  2534.   while ((ch == '\n' || ch == '\r') && cnt < 16380) {
  2535.     cnt++;
  2536.     ch = *(text + cnt);
  2537.       }
  2538.   return cnt;
  2539. }
  2540.  
  2541. void     DRichView::HandleAddInsRep( handleMode mode, short item, char* text, 
  2542.                     DParagraph* parFormat, DRichStyle* styles, short nstyles, Nlm_FonT aFont) 
  2543. {
  2544.     DRichStyle    * aStyle = NULL;
  2545.   DParagraph     * para = NULL;
  2546.     
  2547.     if (!parFormat) {
  2548.         para= new DParagraph();
  2549.         parFormat= para;
  2550.         }
  2551.     
  2552.     if (!styles) {
  2553.         aStyle= new DRichStyle();
  2554.         if (aFont) aStyle->font= aFont;
  2555.         aStyle->last= true;
  2556.         styles= aStyle;
  2557.         nstyles= 1;
  2558.         }
  2559.         
  2560.     if (text && *text != '\0') {
  2561.       long start = 0;
  2562.       short atstyle= 0;
  2563.       long cntr = StringLen (text);
  2564.       long cnt = MIN (cntr, 16000);
  2565.       cnt = SkipPastNewLine (text + start, cnt);
  2566.       while (cnt > 0) {
  2567.         char* txt = (char*) MemNew(cnt + 1);
  2568.         MemCopy(txt, text + start, cnt);
  2569.         
  2570.         // damn !!! have to fiddle w/ styles[...].nextofs for this newline cutting stuff !!
  2571.         short ist= atstyle, nst= 0;
  2572.         if (nstyles) {
  2573.             do ist++; 
  2574.             while (ist<nstyles && styles[ist].nextofs <= start + cnt);
  2575.             nst= ist - atstyle;     
  2576.             }
  2577.             
  2578.         switch (mode) {
  2579.             case kAppend: 
  2580.                 Append( txt, (cnt / 50) + 1, parFormat, &styles[atstyle], nst, true);
  2581.                 break;
  2582.             case kReplace:
  2583.                     Replace( item, txt, (cnt / 50) + 1, parFormat, &styles[atstyle], nst, true);
  2584.                 break;
  2585.             case kInsert:
  2586.                     Insert( item, txt, (cnt / 50) + 1, parFormat, &styles[atstyle], nst, true);
  2587.                 break;
  2588.             }
  2589.             
  2590.         atstyle += nst - 1;
  2591.         start += cnt;
  2592.         cntr -= cnt;
  2593.         cnt = MIN (cntr, 16000);
  2594.         cnt = SkipPastNewLine (text + start, cnt);
  2595.           }
  2596.         } 
  2597.     else switch (mode) {
  2598.       case kAppend: 
  2599.             Append( "", 1, parFormat, styles, nstyles, false);
  2600.           break;
  2601.       case kReplace:
  2602.             Replace( item, "", 1, parFormat, styles, nstyles, false);
  2603.           break;
  2604.         case kInsert:
  2605.             Insert( item, "", 1, parFormat, styles, nstyles, false);
  2606.           break;
  2607.       }
  2608.       
  2609.   if (para) delete para;
  2610.   //if (aStyle) delete aStyle;
  2611. }
  2612.  
  2613.  
  2614. void     DRichView::Append( char* text, DParagraph* parFormat, DRichStyle* styles, 
  2615.                     short nstyles, Nlm_FonT aFont) 
  2616. {
  2617.     HandleAddInsRep( kAppend, 0,  text, parFormat, styles, nstyles, aFont);
  2618. }
  2619.  
  2620. void     DRichView::Replace( short item, char* text, DParagraph* parFormat, 
  2621.                                 DRichStyle* styles, short nstyles, Nlm_FonT aFont) 
  2622. {
  2623.     HandleAddInsRep( kReplace, item, text, parFormat, styles, nstyles, aFont);
  2624. }
  2625.  
  2626. void     DRichView::Insert( short item, char* text, DParagraph* parFormat,
  2627.              DRichStyle* styles, short nstyles, Nlm_FonT aFont) 
  2628. {
  2629.     HandleAddInsRep( kInsert, item, text, parFormat, styles, nstyles, aFont);
  2630. }
  2631.  
  2632.  
  2633.  
  2634. void  DRichView::Delete( short item) 
  2635. {
  2636.                 //  Deletes an item from a document
  2637.   if (item >= 0 && item < fNumItems) {
  2638.         fParags->AtDelete(item);
  2639.     fNumItems = fParags->GetSize(); 
  2640.     fNumLines = UpdateLineStarts( item);
  2641.     if (fAutoAdjust) AdjustScroll();
  2642.     }
  2643. }
  2644.  
  2645.  
  2646. void  DRichView::GetDocStats( short& numParags, short& numLines) 
  2647. {
  2648.   numParags = fNumItems;
  2649.   numLines = fNumLines;  
  2650. }
  2651.  
  2652.  
  2653.  
  2654. void  DRichView::GetItemStats( short item, short& startsAt, short& numRows, 
  2655.                                                              short& lineHeight) 
  2656. {
  2657.     DParagraph* itemPtr = GetParaPtr( item );  // item starts at 0
  2658.   if (itemPtr) {
  2659.     startsAt = itemPtr->startsAt;
  2660.     numRows = itemPtr->numRows;
  2661.     lineHeight = itemPtr->lineHeight;
  2662.       }
  2663.   else {
  2664.       startsAt = 0;
  2665.       numRows = 0;
  2666.       lineHeight = 0;  
  2667.       }
  2668. }
  2669.  
  2670.  
  2671.  
  2672.  
  2673.  
  2674. void     DRichView::MapPoint( Nlm_PoinT pt, short& item, short& row, Nlm_RectPtr rct,
  2675.                     char* wordAt, short maxword, DRichStyle* styleAt) 
  2676. {
  2677.                 // Converts a mouse point to a item, row positions  within a document
  2678.   short     cl,firstItem,firstLine;
  2679.   short     itemNum,rw,itm,leadHeight,lineHeight,numRows,off;
  2680.   Boolean      goOn;
  2681.   Nlm_RecT     viewr, paragr, rc;
  2682.   Nlm_BaR      sb;
  2683.   DParagraph*  itemPtr;
  2684.  
  2685.   itm = 0;
  2686.   rw = 0;
  2687.   cl = 0;
  2688.   Nlm_LoadRect (&rc, 0, 0, 0, 0);
  2689.  
  2690.     ViewRect( viewr);
  2691.   if (Nlm_PtInRect (pt, &viewr)) {
  2692.     sb = Nlm_GetSlateVScrollBar ((Nlm_SlatE) fPanel);
  2693.         if (sb) off = Nlm_GetValue(sb);
  2694.         else off= 0;
  2695.     goOn = TRUE;
  2696.     itemNum = GetItemNum( off);
  2697.     itemPtr = GetParaPtr( itemNum);
  2698.     if (itemPtr) {
  2699.             paragr= viewr;
  2700.       firstLine = off - itemPtr->startsAt;
  2701.       firstItem = itemNum;
  2702.       while (goOn && itemNum < fNumItems) {
  2703.         itemPtr = GetParaPtr( itemNum);
  2704.         if (itemPtr) {
  2705.           CacheIfNever( itemNum + 1, itemPtr, ¶gr);
  2706.           if (itemNum > firstItem)  
  2707.             leadHeight = itemPtr->leadHeight;
  2708.             else 
  2709.             leadHeight = 0;
  2710.           if (firstLine==0) paragr.top += itemPtr->spaceBefore;
  2711.        
  2712.           lineHeight = itemPtr->lineHeight;
  2713.           numRows = MIN (itemPtr->numRows - firstLine,
  2714.                          MAX ((viewr.bottom - paragr.top - leadHeight) / lineHeight, 1));
  2715.           paragr.bottom = paragr.top + leadHeight + lineHeight * numRows;
  2716.                paragr.bottom += itemPtr->spaceAfter;
  2717.                
  2718.              if (Nlm_PtInRect(pt, ¶gr) && numRows > 0) {
  2719.             goOn = FALSE;
  2720.             itm = itemNum + 1;
  2721.             if (pt.y <= paragr.top + leadHeight)  
  2722.               rw = 0;
  2723.             else  
  2724.               rw = firstLine + ((pt.y - paragr.top - leadHeight) / lineHeight) + 1;
  2725.  
  2726.               rc = paragr;
  2727.               if (rw) rc.top += (rw-1) * lineHeight;
  2728.               rc.bottom = rc.top + lineHeight;
  2729.               
  2730.             // dgg -- map to style section                 
  2731.             if (wordAt || styleAt) {
  2732.                       short textofs = DrawStyledItem( itemPtr, ¶gr, itm/*itemNum+1*/, 
  2733.                                                   firstLine/*rw*/, FALSE, &pt);
  2734.                             if (wordAt) {
  2735.                                 if (textofs<0) {
  2736.                                     StrNCpy(wordAt, "**not found", maxword);
  2737.                          wordAt[maxword-1]= 0;
  2738.                                     }
  2739.                                 else {
  2740.                                     char *cbase= itemPtr->fText;
  2741.                                     char *cstart= cbase + textofs;
  2742.                                     if (*cstart <= ' ') {
  2743.                                         if (cstart[1] > ' ') cstart++;
  2744.                                         else if (cstart[-1] > ' ') cstart--;
  2745.                                         }
  2746.                                     char *cend= cstart;
  2747.                        while (cstart > cbase && cstart[-1] > ' ') cstart--;
  2748.                           while (*cend > ' ') cend++;
  2749.                        short len= MAX(1, MIN( maxword-1, cend - cstart));
  2750.                          StrNCpy(wordAt, cstart, len);
  2751.                          wordAt[len]= 0;
  2752.                          }
  2753.                        }
  2754.               if (styleAt && fMapStyle) {
  2755.                   *styleAt= *fMapStyle; // GetStyleAtChar( itemPtr, textofs);
  2756.                   }
  2757.                    }
  2758.                    
  2759.               } 
  2760.           else  
  2761.             paragr.top = paragr.bottom;
  2762.            
  2763.           if (numRows < itemPtr->numRows - firstLine)  
  2764.             goOn = FALSE;
  2765.             }
  2766.         itemNum++;
  2767.         firstLine = 0;
  2768.         }
  2769.       }
  2770.     }
  2771.  
  2772.     item = itm;
  2773.     row = rw;
  2774.     if (rct) *rct = rc;
  2775. }
  2776.  
  2777.  
  2778.  
  2779.  
  2780. Boolean DRichView::Find( char* match, short& itemat, short& charat,
  2781.                             short startitem, short startchar, Boolean caseSensitive) 
  2782. {
  2783.   DParagraph*        itemPtr;
  2784.   short            i, stop;
  2785.     
  2786.   if (match) {
  2787.         char* tempmatch= StrDup( match);
  2788.     if (fNumItems > 0) {
  2789.           stop = fNumItems;
  2790.         if (startitem < 0) startitem = 0;
  2791.         for (i = startitem; i < stop; i++) {
  2792.           itemPtr = GetParaPtr( i);
  2793.           if (itemPtr) {
  2794.                          char* text;
  2795.                         text= (char*) itemPtr->fDataPtr;
  2796.             if (text) {
  2797.                             Nlm_Uint4        foundat;
  2798.                             Boolean         found 
  2799.                                     = Nlm_StrngPos(text, tempmatch, startchar, caseSensitive, &foundat);
  2800.               if (found) {
  2801.                   itemat= i;
  2802.                     charat= foundat;
  2803.                                 MemFree( tempmatch);
  2804.                   return TRUE;
  2805.                   }      
  2806.                   }
  2807.               }
  2808.           startchar= 0; // ! zero it !! or we miss others ! 
  2809.           }
  2810.                 }
  2811.         MemFree( tempmatch);
  2812.         }
  2813.     return FALSE;
  2814. }
  2815.  
  2816.  
  2817.  
  2818.  
  2819. Boolean     DRichView::FindURL(short& itemat, short& charat, short& charlen,
  2820.                                                         short startitem, short startchar) 
  2821. {
  2822.   DParagraph*     itemPtr;
  2823.   short            i, stop;
  2824.     
  2825.     if (fNumItems > 0) {
  2826.       stop = fNumItems;
  2827.     if (startitem < 0) startitem = 0;
  2828.     for (i = startitem; i < stop; i++) {
  2829.       itemPtr = GetParaPtr( i);
  2830.       if (itemPtr) {
  2831.                 char* text;
  2832.                 // text= (char*) itemPtr->fDataPtr; << this is bad, need fText !
  2833.                 FormatText( i, itemPtr, TRUE);
  2834.                 text = itemPtr->fText;
  2835.           if (text) {
  2836.                     char             *cp, *ep;
  2837.  
  2838.                     for (cp= text+startchar+3; *cp; cp++) { 
  2839.                         if (*cp == ':') {
  2840.                             if ( (cp[1] == '/' && cp[2] == '/') 
  2841.                                 || (0 == Nlm_StringNICmp( MAX(text, cp-6), "mailto", 6))
  2842.                                 || (0 == Nlm_StringNICmp( MAX(text, cp-4), "news", 4))
  2843.                                 /* ^^^^ Should use DURL::IsURL(cp) !! */
  2844.                                 ) {
  2845.                                   cp--;
  2846.                                     while (isalnum(*cp) && cp>text) cp--;
  2847.                                     if (*cp == '"') ep= strchr(cp+1,'"');
  2848.                                     else if (*cp == '\'') ep= strchr(cp+1,'\'');
  2849.                                     else if (*cp == '<') ep= strchr(cp+1,'>');
  2850.                                     else if (*cp == '=' 
  2851.                                         && 0 == Nlm_StringNICmp( MAX(text,cp-4), "href=", 4 )) 
  2852.                                             ep= strchr(cp+1,'>');
  2853.                                     else ep= NULL;
  2854.                                     if (!isalnum(*cp)) cp++;
  2855.                                   if (ep == NULL) for (ep=cp; isgraph(*ep); ep++) ;
  2856.                       itemat= i;
  2857.                       charat= cp - text;
  2858.                                     charlen= ep ? ep - cp : 0;
  2859.                       return TRUE;
  2860.                       }
  2861.                             } 
  2862.                         }     
  2863.               }
  2864.           }
  2865.       startchar= 0; // ! zero it !! or we miss others ! 
  2866.       }
  2867.         }
  2868.  
  2869.     return FALSE;
  2870. }
  2871.  
  2872.  
  2873.  
  2874.  
  2875.  
  2876. void     DRichView::InsertStyle( short atitem, short atchar, short atlength, 
  2877.                                                             DRichStyle* theStyle)
  2878. {
  2879.   DParagraph*     itemPtr;
  2880.     short                    numStyles;
  2881.     
  2882.     itemPtr = GetParaPtr( atitem);
  2883.   if (theStyle && itemPtr) {
  2884.         short ist, jst;
  2885.         numStyles= itemPtr->fNumStyles;
  2886.         StyleIndex* si = itemPtr->fStyleIndex;
  2887.         short newofs= atchar + atlength;
  2888.         short newnum= numStyles + 2;
  2889.         StyleIndex* sinew=    
  2890.             (StyleIndex*) MemNew( newnum*sizeof(StyleIndex)); 
  2891.  
  2892.         short styleid= FindOrAddStyle(theStyle);
  2893.         Boolean notat= true, notnew= true;
  2894.         for (ist=0, jst= 0; ist<numStyles && jst<newnum; ist++) {
  2895.             short ofs= si[ist].nextofs;
  2896.             
  2897.             if (atchar <= ofs && notat) {
  2898.                 if (atchar < ofs) {
  2899.                     sinew[jst]= si[ist];
  2900.                     sinew[jst].nextofs= atchar;
  2901.                     if (jst<newnum) jst++;
  2902.                     }
  2903.                 else {
  2904.                     sinew[jst]= si[ist];
  2905.                     if (jst<newnum) jst++;
  2906.                     }
  2907.                 sinew[jst].nextofs= newofs;
  2908.                 sinew[jst].styleid= styleid;
  2909.                 if (jst<newnum) jst++;
  2910.                 notat= false;
  2911.                 }
  2912.             else {  // atchar > ofs
  2913.                 sinew[jst]= si[ist];
  2914.                 if (jst<newnum) jst++;
  2915.                 }
  2916.             
  2917.             if (newofs <= ofs && notnew) {
  2918.                 sinew[jst]= si[ist];
  2919.                 if (jst<newnum) jst++;
  2920.                 notnew= false;
  2921.                 }
  2922.             }
  2923.             
  2924.         itemPtr->fStyleIndex= sinew;
  2925.         itemPtr->fNumStyles = jst; // newnum
  2926.         MemFree( si);
  2927.         
  2928.         
  2929.       }
  2930.      
  2931. }
  2932.  
  2933.  
  2934.  
  2935.  
  2936.  
  2937.  
  2938.  
  2939. char* DRichView::GetText(short item, short row) 
  2940. {
  2941.             //   Returns a string with text from a document.  If item, row
  2942.             //   parameters are 0, text is taken from any item, row,
  2943.             //   respectively.  The string must be freed by the application
  2944.   ByteStorePtr      bsp;
  2945.   char              ch;
  2946.   short              cl, i;
  2947.   short              k, num;
  2948.   short              rw, start, stop;
  2949.   char                    * text;
  2950.   char                    * ptr;
  2951.   Nlm_RecT            r;
  2952.   DParagraph*        itemPtr;
  2953.  
  2954.   text = NULL;
  2955.   if (item >= 0) {
  2956.         ViewRect( r);
  2957.     if (fNumItems > 0) {
  2958.       bsp = BSNew (0);
  2959.       if (bsp != NULL) {
  2960.         if (item == 0) {
  2961.           start = 0;
  2962.           stop = fNumItems;
  2963.             } 
  2964.         else if (item <= fNumItems) {
  2965.           start = item - 1;
  2966.           stop = item;
  2967.             } 
  2968.         else {
  2969.           start = 0;
  2970.           stop = 0;
  2971.             }
  2972.  
  2973. #if 1
  2974.             if (row < 0) {
  2975.         itemPtr = GetParaPtr( start);
  2976.         if (itemPtr) {
  2977.                     text= (char*) itemPtr->fDataPtr;
  2978.                       // if (text) text= MemDup(text);   //!? caller expects to own this data !? 
  2979.                     }
  2980.                 return text;
  2981.                 }
  2982. #else
  2983.             if (row < 0) {
  2984.         for (i = start; i < stop; i++) {
  2985.           itemPtr = GetParaPtr( i);
  2986.           if (itemPtr) {
  2987.                       if (!text) text = DataToChar(itemPtr->fDataPtr);
  2988.                         }
  2989.                     }
  2990.                   return text;
  2991.                 }
  2992. #endif
  2993.  
  2994.         for (i = start; i < stop; i++) {
  2995.           itemPtr = GetParaPtr( i);
  2996.           if (itemPtr) {
  2997.                         DParagraph itemData( itemPtr->fDataPtr, false, itemPtr->numRows, itemPtr, 
  2998.                                                 itemPtr->fStyleIndex, itemPtr->fNumStyles, false);
  2999.             FormatText(i, &itemData, TRUE);
  3000.             text = itemData.fText;
  3001.             if (text && *text != '\0') {
  3002.               if (i > start && itemPtr->openSpace > 0 && item == 0) 
  3003.                 BSPutByte (bsp, (short) '\n');
  3004.               rw = 0;
  3005.               cl = 0;
  3006.               ptr = text;
  3007.               ch = *ptr;
  3008.               while (ch != '\0') {
  3009.                 if (ch == '\n') {
  3010.                   if ((rw + 1 == row) || row == 0)  
  3011.                     BSPutByte (bsp, (short) '\n');
  3012.                   cl = 0;
  3013.                   rw++;
  3014.                   ptr++;
  3015.                     } 
  3016.                 else if (ch == '\t') {
  3017.                   if ((rw + 1 == row || row == 0)) 
  3018.                     BSPutByte (bsp, (short) '\t');
  3019.                    
  3020.                   cl++;
  3021.                   ptr++;
  3022.                     } 
  3023.                 else {
  3024.                   num = 0;
  3025.                   while (ch != '\0' && ch != '\t' && ch != '\n') {
  3026.                     num++;
  3027.                     ch = ptr [num];
  3028.                       }
  3029.                   if (num > 0  &&
  3030.                       (rw + 1 == row || row == 0)) {
  3031.                     for (k = 0; k < num; k++) 
  3032.                       BSPutByte (bsp, (short) ptr [k]);
  3033.                     }
  3034.                   ptr += num;
  3035.                     }
  3036.                 ch = *ptr;
  3037.                   }
  3038.                 }
  3039.               }
  3040.             }
  3041.         text = (char*) BSMerge (bsp, NULL);
  3042.         BSFree (bsp);
  3043.           }
  3044.         }
  3045.       }
  3046.   return text;
  3047. }
  3048.  
  3049.  
  3050.  
  3051.  
  3052.  
  3053. Boolean    DRichView::IsVisible( short item, short& top, short& bottom, short& firstline) 
  3054. {
  3055.             // Finds the visible region of an item in a document
  3056.   short             firstItem, fstLine, itemNum, leadHeight,lineHeight, numRows,off;
  3057.   Nlm_RecT         r, rct;
  3058.   Boolean              goOn, rsult;
  3059.   Nlm_BaR          sb;
  3060.   DParagraph*      itemPtr;
  3061.  
  3062.   rsult = FALSE;
  3063.      top = 0;
  3064.      bottom = 0;
  3065.   firstline = 0;
  3066.  
  3067.     ViewRect(  r);
  3068.   sb = Nlm_GetSlateVScrollBar ((Nlm_SlatE) fPanel);
  3069.   if (sb) off = Nlm_GetValue (sb);
  3070.   else off= 0;
  3071.   if (item > 0 && item <= fNumItems) {
  3072.     item--;
  3073.     goOn = TRUE;
  3074.     Nlm_LoadRect (&rct, r.left, r.top, r.right, r.top);
  3075.     itemNum = GetItemNum ( off);
  3076.     itemPtr = GetParaPtr( itemNum);
  3077.     if (itemPtr) {
  3078.       fstLine = off - itemPtr->startsAt;
  3079.       firstItem = itemNum;
  3080.       lineHeight = 0;
  3081.       leadHeight = 0;
  3082.       numRows = 0;
  3083.       while (goOn && itemNum < fNumItems && itemNum <= item) {
  3084.         itemPtr = GetParaPtr( itemNum);
  3085.         if (itemPtr ) {
  3086.           CacheIfNever ( itemNum + 1, itemPtr, &r);
  3087.           if (itemNum > firstItem)  
  3088.             leadHeight = itemPtr->leadHeight;
  3089.             else  
  3090.             leadHeight = 0;
  3091.               if (fstLine==0) rct.top += itemPtr->spaceBefore;
  3092.           
  3093.           lineHeight = itemPtr->lineHeight;
  3094.           rct.top += leadHeight;
  3095.           numRows = MIN (itemPtr->numRows,
  3096.                          MAX ((r.bottom - rct.top) / lineHeight, 0));
  3097.           rct.bottom = rct.top + lineHeight * (numRows - fstLine);
  3098.               rct.bottom += itemPtr->spaceAfter;
  3099.           if (itemNum == item) {
  3100.             goOn = FALSE;
  3101.             if (numRows > 0) {
  3102.                 top = rct.top;
  3103.                 bottom = rct.bottom;
  3104.                 firstline = fstLine;
  3105.               rsult = TRUE;
  3106.                 }
  3107.               } 
  3108.           else  
  3109.             rct.top = rct.bottom;
  3110.           if (numRows < itemPtr->numRows)  
  3111.             goOn = FALSE;
  3112.             }
  3113.         itemNum++;
  3114.         fstLine = 0;
  3115.           }
  3116.         }
  3117.       }
  3118.   
  3119.   return rsult;
  3120. }
  3121.  
  3122.  
  3123.  
  3124.  
  3125.  
  3126. Boolean DRichView::GetScrollStats( short& offset, short& firstShown, short& firstLine) 
  3127. {
  3128.   short     item, line,off;
  3129.   Boolean      rsult;
  3130.   Nlm_BaR        sb;
  3131.  
  3132.   sb = Nlm_GetSlateVScrollBar((Nlm_SlatE)fPanel);
  3133.   if (sb) {
  3134.     off = Nlm_GetValue (sb);
  3135.     item = GetItemNum ( off);
  3136.     line = off - GetLineStart(item);
  3137.     rsult = TRUE;
  3138.       }
  3139.   else {
  3140.       off = 0;
  3141.       item = 0;
  3142.       line = 0;  
  3143.       rsult = FALSE;
  3144.       }
  3145.   offset = off;
  3146.   firstShown = item + 1;
  3147.   firstLine = line;
  3148.   return rsult;
  3149. }
  3150.  
  3151.  
  3152.  
  3153.  
  3154.  
  3155.  
  3156. void  DRichView::Update( short from, short to) 
  3157. {
  3158.             // Invalidates and updates items in a document
  3159.   short         bottom,item,start,stop,swap,top, f1;
  3160.   DParagraph*  itemPtr;
  3161.   Nlm_RecT     r;
  3162.   Nlm_WindoW   tempPort;
  3163.  
  3164.   if (from >= 0 && to >= 0) {
  3165.     if (from == 0 || from > fNumItems) {
  3166.       start = 0;
  3167.       from = 0;
  3168.         } 
  3169.     else  
  3170.       start = from - 1;
  3171.      
  3172.     if (to == 0 || to > fNumItems) 
  3173.       stop = to = fNumItems;
  3174.     else  
  3175.       stop = to;
  3176.     
  3177.     for (item = start; item < stop; item++) {
  3178.       itemPtr = GetParaPtr(item);
  3179.       if (itemPtr) {
  3180.         itemPtr->fText = (char*) MemFree (itemPtr->fText);
  3181.         itemPtr->notCached = TRUE;
  3182.         itemPtr->neverCached = TRUE;
  3183.           }
  3184.         }
  3185.     if (Nlm_Enabled(fPanel) && Nlm_AllParentsEnabled(fPanel) &&
  3186.         Nlm_Visible(fPanel) && Nlm_AllParentsVisible(fPanel)) {
  3187.       tempPort = Nlm_SavePort(fPanel);
  3188.             ViewRect( r);
  3189.       Nlm_Select(fPanel);
  3190.       if (from > to && from != 0 && to != fNumItems) {
  3191.         swap = from;
  3192.         from = to;
  3193.         to = swap;
  3194.           }
  3195.       if (from > 0 && from <= fNumItems && IsVisible( from, top, bottom, f1))  
  3196.         r.top = top;
  3197.       if (to > 0 && to < fNumItems && IsVisible( to, top, bottom, f1))  
  3198.         r.bottom = bottom;
  3199.       Nlm_InsetRect(&r, -1, -1);
  3200.       Nlm_InvalRect(&r);
  3201.       if (tempPort) Nlm_RestorePort(tempPort);
  3202.         }
  3203.     AdjustScroll();
  3204.       }
  3205. }
  3206.  
  3207.  
  3208.  
  3209. void DRichView::SaveTableItem(DParagraph* itemPtr, FILE *f, Boolean tabStops)
  3210. {
  3211.                 //    Reformats and saves an item to a file
  3212.   char         ch;
  3213.   short     i;
  3214.   short     next,num,pos,row;
  3215.   char    *     ptr;
  3216.   char    *        text;
  3217.  
  3218.   next= 0;
  3219.   if (itemPtr && f) {
  3220.     text = itemPtr->fText;
  3221.     if (text && *text != '\0') {
  3222.       pos = 0;
  3223.       row = 0;
  3224.       ptr = text;
  3225.       ch = *ptr;
  3226.       while (ch != '\0') {
  3227.         if (ch == '\n') {
  3228.           row++;
  3229.           ptr++;
  3230.           pos = 0;
  3231.           fputc ('\n', f);
  3232.             } 
  3233.         else  {
  3234.           num = 0;
  3235.           while (ch != '\0' && ch != '\n') {
  3236.             num++;
  3237.             ch = ptr [num];
  3238.               }
  3239.           if (num > 0) {
  3240.             while (num > 0 && *ptr == '\t') {
  3241.               num--;
  3242.               ptr++;
  3243.               next += fTabCount;
  3244.                 }
  3245.             while (pos < next) {
  3246.               fputc (' ', f);
  3247.               pos++;
  3248.                 }
  3249.             for (i = 0; i < num; i++) {
  3250.               fputc (ptr [i], f);
  3251.               pos++;
  3252.                 }
  3253.               }
  3254.           ptr += num;
  3255.             }
  3256.         ch = *ptr;
  3257.       }
  3258.     }
  3259.   }
  3260. }
  3261.  
  3262.  
  3263.  
  3264.  
  3265. void DRichView::Save(DFile* f) 
  3266.   if ( f ) {
  3267.     Boolean savevirt= fIsVirtual;
  3268.     fIsVirtual = FALSE;
  3269.     for (short i = 0; i < fNumItems; i++) {
  3270.       DParagraph* itemPtr = GetParaPtr( i);
  3271.       if (itemPtr) {
  3272.                 DParagraph itemData( itemPtr->fDataPtr, false, itemPtr->numRows, itemPtr, 
  3273.                                         itemPtr->fStyleIndex, itemPtr->fNumStyles, false);
  3274.            FormatText(0, &itemData, FALSE);
  3275.                 if (i > 0 && itemData.openSpace > 0) fputc ('\n', f->fFile);
  3276.            SaveTableItem(&itemData, f->fFile,  TRUE);
  3277.         }
  3278.       }
  3279.         fIsVirtual= savevirt;
  3280.     }
  3281. }
  3282.  
  3283.  
  3284.  
  3285.  
  3286.  
  3287. void DRichView::Print()    
  3288. #if (defined(WIN_MAC) || defined (WIN_MSWIN))
  3289.   Boolean   goOn;
  3290.   short      i, item, line,pixels, visBelow;
  3291.   DParagraph*   itemPtr;
  3292.   Boolean   newPage;
  3293.   Nlm_RecT      r, rct;
  3294.   FloatHi           scale;
  3295.   Nlm_WindoW    w;
  3296.  
  3297.   Boolean savevirt= fIsVirtual;
  3298.   fIsVirtual = FALSE;
  3299.     if (fNumItems > 0) {
  3300.         ViewRect( rct);
  3301.     w = Nlm_StartPrinting ();
  3302.     if (w != NULL) {
  3303.       for (i = 0; i < MAXFONTS; i++) {
  3304.         gFontHeights[i].font = NULL;
  3305.         gFontHeights[i].height = 0;
  3306.           }
  3307.       goOn = TRUE;
  3308.       pixels = 0;
  3309.       item = 0;
  3310.       newPage = TRUE;
  3311.       while (item < fNumItems && goOn) {
  3312.         if (newPage) {
  3313.           goOn = Nlm_StartPage ();
  3314.           newPage = FALSE;
  3315.           Nlm_PrintingRect (&r);
  3316.             }
  3317.         if (goOn) {
  3318.           itemPtr = GetParaPtr( item);
  3319.           if (itemPtr) {
  3320.                         DParagraph itemData( itemPtr->fDataPtr, false, itemPtr->numRows, itemPtr, 
  3321.                                                                 itemPtr->fStyleIndex, itemPtr->fNumStyles, false);
  3322.             UpdateItemHeights (&itemData);
  3323.             scale = (FloatHi) (r.right - r.left) / (FloatHi) (rct.right - rct.left);
  3324.                    FormatText(0, &itemData, TRUE);
  3325.  
  3326.             if (pixels != 0)  r.top += itemData.leadHeight;
  3327.                 r.top += itemData.spaceBefore;
  3328.              
  3329.             visBelow = (r.bottom - r.top) / itemData.lineHeight;
  3330.             if ((itemData.keepTogether && visBelow < itemData.numRows) ||
  3331.                 itemData.newPage) {
  3332.               goOn = Nlm_EndPage ();
  3333.               if (goOn)  goOn = Nlm_StartPage ();
  3334.               newPage = FALSE;
  3335.               Nlm_PrintingRect (&r);
  3336.               visBelow = (r.bottom - r.top) / itemData.lineHeight;
  3337.                 }
  3338.             line = 0;
  3339.             while (visBelow + line < itemData.numRows && goOn) {
  3340.                   pixels = DrawStyledItem( &itemData, &r, item+1, line, TRUE, NULL);
  3341.               r.top += pixels;
  3342.                     r.top += itemData.spaceAfter;
  3343.               line += visBelow;
  3344.               goOn = Nlm_EndPage ();
  3345.               if (goOn) Nlm_StartPage ();
  3346.               newPage = FALSE;
  3347.               Nlm_PrintingRect (&r);
  3348.               visBelow = (r.bottom - r.top) / itemData.lineHeight;
  3349.                 }
  3350.             if (visBelow > 0 && goOn) {
  3351.                   pixels = DrawStyledItem( &itemData, &r, item+1, line, TRUE, NULL);
  3352.               r.top += pixels;
  3353.                     r.top += itemData.spaceAfter;
  3354.                 }
  3355.                
  3356.               }
  3357.             }
  3358.         item++;
  3359.         if (r.top >= r.bottom) {
  3360.           goOn = Nlm_EndPage ();
  3361.           newPage = TRUE;
  3362.             }
  3363.           }
  3364.       if ((!newPage) && goOn) 
  3365.         goOn = Nlm_EndPage ();
  3366.        
  3367.       Nlm_EndPrinting (w);
  3368.       for (i = 0; i < MAXFONTS; i++) {
  3369.         gFontHeights [i].font = NULL;
  3370.         gFontHeights [i].height = 0;
  3371.         }
  3372.         }
  3373.         }
  3374.     fIsVirtual= savevirt;
  3375.    
  3376. #else
  3377.     Nlm_Message(MSG_OK,"Printing is not yet defined for this window system");
  3378. #endif
  3379. }
  3380.  
  3381.  
  3382.  
  3383. void  DRichView::SetTabs( short theTabstops) 
  3384.     fTabCount= theTabstops;
  3385. }
  3386.  
  3387.  
  3388. #if 0
  3389. enum docFormats {
  3390.     kUnknownformat,
  3391.     kTextformat,
  3392.     kRTFformat,
  3393.     kPICTformat,
  3394.     kHTMLformat,
  3395.     kMaxDocformat
  3396.     };
  3397. #endif
  3398.  
  3399. void  DRichView::ShowFile( char* filename, Nlm_FonT font) 
  3400. {
  3401.     fDocFormat= DRichHandler::kUnknownformat;
  3402.     DRTFHandler rtfhandler( this, NULL);
  3403.     if ( rtfhandler.ProcessFile( filename) ) 
  3404.         fDocFormat= rtfhandler.Format();
  3405.     else {
  3406.         DPICTHandler picthandler( this, NULL);
  3407.         if ( picthandler.ProcessFile( filename) )
  3408.             fDocFormat= picthandler.Format();
  3409.         else  { 
  3410.           DGIFHandler gifhandler( this, NULL);
  3411.           if ( gifhandler.ProcessFile( filename) ) 
  3412.               fDocFormat= gifhandler.Format(); 
  3413.           else {
  3414.               DHTMLHandler htmlhandler( this, NULL);
  3415.               if ( htmlhandler.ProcessFile( filename) ) 
  3416.                   fDocFormat= htmlhandler.Format(); 
  3417.               else {
  3418. #if 1
  3419.                   DRichHandler texthandler( this, NULL);
  3420.                   if ( texthandler.ProcessFile( filename) ) 
  3421.                       fDocFormat= texthandler.Format(); 
  3422. #else
  3423.                 ShowTextFile( filename, font);
  3424.                   fDocFormat= DRichHandler::kTextformat; 
  3425. #endif
  3426.                   }
  3427.               }
  3428.           }
  3429.         }
  3430. }
  3431.  
  3432.  
  3433. void DRichView::ShowTextFile( char* filename, Nlm_FonT font)
  3434. {    
  3435.     DParagraph    para;
  3436.     DRichStyle    aStyle;
  3437.     if (font) aStyle.font= font;
  3438.     aStyle.last= true;
  3439.   ShowFileFancy( filename, ¶, &aStyle, 1);
  3440. }
  3441.  
  3442.  
  3443.  
  3444.  
  3445.  
  3446. void  DRichView::ShowFileFancy( char* filename, DParagraph* parFormat,  
  3447.                                                                 DRichStyle* styles, short nstyles, short tabStops) 
  3448. {
  3449.   char         ch;
  3450.   short       actual, cnt, leftOver;
  3451.   long         cntr;
  3452.   FILE         *fp;
  3453.   Nlm_RecT     r;
  3454.   Nlm_WindoW   tempPort;
  3455.   char      * text,  * txt;
  3456.   Nlm_FonT         font;
  3457. #ifdef COMP_MPW
  3458.   char*  p;
  3459. #endif
  3460. #if (defined(OS_DOS) || defined (OS_NT))
  3461.   char*  p;
  3462.   char*  q;
  3463. #endif
  3464.     DParagraph    para;
  3465.  
  3466.   if ( filename  && filename [0] != '\0') {
  3467.          fTabCount = tabStops;
  3468.     if (parFormat == NULL) parFormat = ¶
  3469.     Nlm_Reset (fPanel);
  3470.     tempPort = Nlm_SavePort (fPanel);
  3471.         ViewRect( r);
  3472.     if (styles) font= styles->font;
  3473.     if (font == NULL) font = Nlm_programFont; //Nlm_systemFont;
  3474.      
  3475.     text = (char*) MemNew (16000);
  3476.     if (text) {
  3477.       fp = FileOpen (filename, "r");
  3478.       if (fp) {
  3479.         leftOver = 0;
  3480.         cntr = FileLength (filename);
  3481.         cnt = (short) MIN (cntr, 15000L);
  3482.  
  3483.         while (cnt > 0 && cntr > 0) {
  3484.           txt = text + leftOver;
  3485.           actual = (short) FileRead (txt, 1, cnt, fp);
  3486.           if (actual > 0) {
  3487.             cnt = actual;
  3488.             txt [cnt] = '\0';
  3489.             ch = fgetc (fp);
  3490.             while (ch != '\0' && ch != '\n' && cnt < 15900) {
  3491.               txt [cnt] = ch;
  3492.               cnt++;
  3493.               ch = fgetc (fp);
  3494.                 }
  3495.             while ((ch == '\n' || ch == '\r') && cnt < 15900) {
  3496.               txt [cnt] = ch;
  3497.               cnt++;
  3498.               ch = fgetc (fp);
  3499.                 }
  3500.             txt [cnt] = '\0';
  3501. #if (defined(OS_DOS) || defined (OS_NT))
  3502.             p = text;
  3503.             q = text;
  3504.             while (*p) {
  3505.               if (*p == '\r') {
  3506.                 p++;
  3507.               } else {
  3508.                 *q = *p;
  3509.                 p++;
  3510.                 q++;
  3511.               }
  3512.             }
  3513.             *q = '\0';
  3514. #endif
  3515. #ifdef COMP_MPW
  3516.             p = text;
  3517.             while (*p) {
  3518.               if (*p == '\r') {
  3519.                 *p = '\n';
  3520.               }
  3521.               p++;
  3522.             }
  3523. #endif
  3524.             Append( text, parFormat, styles, nstyles, NULL); 
  3525.                 /* dgg -- need to fiddle w/ styles to match to subset of text !! */
  3526.             leftOver = 1;
  3527.             text [0] = ch;
  3528.             cntr -= cnt;
  3529.             cnt = (short) MIN (cntr, 15000L);
  3530.               } 
  3531.           else {
  3532.             cnt = 0;
  3533.             cntr = 0;
  3534.               }
  3535.             }
  3536.         FileClose (fp);
  3537.           }
  3538.       text = (char*) MemFree (text);
  3539.         }
  3540.     if (!fAutoAdjust) AdjustScroll();
  3541.     if (tempPort) Nlm_RestorePort (tempPort);
  3542.       }
  3543. }
  3544.  
  3545.  
  3546.  
  3547.         
  3548.     
  3549.     
  3550. void DRichView::DoubleClick(Nlm_PoinT mouse)
  3551. {
  3552.     short                 item, row, atch;
  3553.     Nlm_RecT        rct;
  3554.     char                wordAt[512];
  3555.     DRichStyle     * styleAt = NULL;
  3556.  
  3557.         // sickly demo
  3558.     wordAt[0]= 0;
  3559.     MapPoint( mouse, item, row, &rct, wordAt, 512, NULL/*styleAt*/);
  3560.     atch= gMapOfs;  
  3561.     SetSelectedText( item, atch, item, atch); 
  3562.     if (fMapStyle) {
  3563.         if (fMapStyle->ispict) {
  3564.             Nlm_PoinT atp;
  3565.             atp.x= mouse.x - fDrawr.left;
  3566.             atp.y= mouse.y - fDrawr.top;
  3567.             // if fMapStyle->ismap, do things w/ gopher link
  3568. #if 0
  3569.             Message(MSG_OK, "dblClik in picture x=%d y=%d, picwd=%d picht=%d", 
  3570.                     atp.x, atp.y, fMapStyle->pixwidth, fMapStyle->pixheight);
  3571. #endif
  3572.             }
  3573.         else {
  3574.             Nlm_InvertRect(&rct);
  3575. #if 0
  3576.             Message(MSG_OK, "dblClik text at prg=%d row=%d sto=%d '%s'",
  3577.                              item, row, fMapStyle->nextofs, wordAt);
  3578. #endif
  3579.             InvalRect( rct);
  3580.             }
  3581.         }
  3582.     //this->Select();
  3583.     this->GetWindow()->Select();
  3584. }
  3585.  
  3586. void DRichView::SingleClick(Nlm_PoinT mouse) 
  3587. {
  3588.     short             item, row, atch;
  3589.     Nlm_RecT        rct;
  3590.     char                wordAt[512];
  3591.  
  3592.     wordAt[0]= 0;
  3593.     MapPoint( mouse, item, row, &rct, wordAt, 512, NULL/*styleAt*/);
  3594.     atch= gMapOfs;  
  3595.     SetSelectedText( item, atch, item, atch); 
  3596. }
  3597.  
  3598. void DRichView::Click(Nlm_PoinT mouse)
  3599. {
  3600.     if (Nlm_dblClick) DoubleClick( mouse);
  3601.     else SingleClick(mouse);        
  3602. }
  3603.     
  3604. void  DRichView::SetAutoAdjust( Boolean autoAdjust) 
  3605. {
  3606.     fAutoAdjust= autoAdjust;
  3607. }
  3608.  
  3609.  
  3610. #if 0
  3611. void DRichView::Show()
  3612. {
  3613.   Nlm_Update(); //!? need since took out vibwnds autoupdate for RestorePort
  3614. }
  3615. #endif
  3616.  
  3617. // this is DPanel form:
  3618. //void DRichView::Scroll( Boolean vertical, DView* scrollee, short newval, short oldval)
  3619.  
  3620. void DRichView::ScrollDoc(Nlm_BaR sb, short newval, short oldval)
  3621. {
  3622.         // Scroll bar callback that takes suppressed partial lines into account
  3623.         // this is good only for vertical==true
  3624.   Boolean      goToEnd;
  3625.   short     barmax, barval, firstShown;
  3626.   short     height,highest,highFree,item, lo1, hi1;
  3627.   short     line, lineInto,lowest,lowFree;
  3628.   short     pixels,pgDn,pgUp,vis;
  3629.   Nlm_RecT     r;
  3630.   DParagraph*  itemPtr;
  3631.     
  3632.     // Nlm_SlatE s= (Nlm_SlatE) fPanel;
  3633.     
  3634.   if (oldval != newval) {
  3635.     if (Nlm_Visible (fPanel) && Nlm_AllParentsVisible (fPanel)) {
  3636.             ViewRect( r);
  3637.       height = r.bottom - r.top;
  3638.       item = GetItemNum ( newval);
  3639.       line = newval - GetLineStart( item);
  3640.       firstShown = item;
  3641.       lineInto = line;
  3642.       lowest = INT2_MAX;
  3643.       highest = INT2_MIN;
  3644.       pgUp = VisLinesAbove ( &r, item, line, lowest, highest) - 1;
  3645.       pgDn = VisLinesBelow ( &r, item, line, lowest, highest) - 1;
  3646.       if (pgDn < 1)  pgDn = 1;
  3647.       if (pgUp < 1)  pgUp = 1;
  3648.       if (lowest < INT2_MAX)  
  3649.         fNumLines = UpdateLineStarts ( lowest);
  3650.       Nlm_Select (fPanel);
  3651.       if ((newval > oldval && newval - pgUp <= oldval) ||
  3652.           (newval < oldval && newval + pgDn >= oldval)) {
  3653.         pixels = PixelsBetween ( &r, newval, oldval, lo1, hi1);
  3654.         if (ABS (pixels) < height) {
  3655.           Nlm_ScrollRect (&r, 0, pixels);
  3656.           if (pixels<0) r.top = r.bottom + pixels; // - 5;
  3657.           else r.bottom = r.top + pixels; // + 5;
  3658.           Nlm_InsetRect (&r, -1, -1);
  3659.           Nlm_InvalRect (&r);
  3660.             } 
  3661.         else {
  3662.           Nlm_InsetRect (&r, -1, -1);
  3663.           Nlm_InvalRect (&r);
  3664.             }
  3665.           } 
  3666.       else {
  3667.         Nlm_InsetRect (&r, -1, -1);
  3668.         Nlm_InvalRect (&r);
  3669.           }
  3670.       lowFree = INT2_MAX;
  3671.       highFree = INT2_MIN;
  3672.       for (item = 0; item < lowest; item++)  
  3673.         FreeCachedItem ( item, lowFree, highFree);
  3674.       for (item = highest + 1; item < fNumItems; item++) 
  3675.         FreeCachedItem ( item, lowFree, highFree);
  3676.       if (lowFree < INT2_MAX) 
  3677.         fNumLines = UpdateLineStarts ( lowFree);
  3678.       
  3679.       barmax = 0;
  3680.       goToEnd = (Boolean) (newval == fBarmax);
  3681.       if (fNumLines > 0 && fNumItems > 0) {
  3682.         itemPtr = GetParaPtr( fNumItems - 1);
  3683.         if (itemPtr) {
  3684.                     ViewRect( r);
  3685.           lowest = INT2_MAX;
  3686.           highest = INT2_MIN;
  3687.           vis = VisLinesAbove ( &r, fNumItems - 1,
  3688.                                itemPtr->numRows - 1, lowest, highest);
  3689.           if (lowest < INT2_MAX)  
  3690.             fNumLines = UpdateLineStarts ( lowest);
  3691.           barmax = fNumLines - vis;
  3692.             }
  3693.           }
  3694.       barval = GetLineStart( firstShown) + lineInto;
  3695.       if (goToEnd) barval = barmax;
  3696.     
  3697.       if (barval > fBarmax) {
  3698.         Nlm_CorrectBarMax (sb, barmax);
  3699.         Nlm_CorrectBarValue (sb, barval);
  3700.           } 
  3701.       else {
  3702.         Nlm_CorrectBarValue (sb, barval);
  3703.         Nlm_CorrectBarMax (sb, barmax);
  3704.           }
  3705.       Nlm_CorrectBarPage (sb, pgUp, pgDn);
  3706.       fBarmax = barmax;
  3707.       Nlm_Update ();
  3708.     }
  3709.   }
  3710. }
  3711.  
  3712.  
  3713.  
  3714. // Performs garbage collection on document data
  3715.  
  3716. void DRichView::ResetDoc()
  3717. {
  3718.     DeleteAll();
  3719.   fNumItems = 0;
  3720.   fNumLines = 0;
  3721.   fBarmax = 0;
  3722.   //DRichView::InitRichView();
  3723. }
  3724.  
  3725.  
  3726.  
  3727.  
  3728.  
  3729.  
  3730.  
  3731.  
  3732.  
  3733. // class DRichFindDialog
  3734.  
  3735. class DRichFindDialog : public DFindDialog {
  3736. public:
  3737.     DRichView* fView;
  3738.     char    * fLastTarget;
  3739.     short        fLastParag, fLastChar;
  3740.     DRichFindDialog(  DRichView* itsView);
  3741.     virtual void DoFind();
  3742.     virtual void BuildDlog();
  3743. };
  3744.  
  3745. DRichFindDialog::DRichFindDialog(  DRichView* itsView) :
  3746.         fView( itsView), fLastTarget(NULL),  fLastParag(-1), fLastChar(-1)
  3747. {
  3748. }
  3749.  
  3750.  
  3751. void DRichFindDialog::BuildDlog()
  3752. {
  3753.     DFindDialog::BuildDlog();
  3754.  
  3755.     DView* av;
  3756.     av= FindSubview(replaceId); if (av) { av->Disable(); } //av->Hide();
  3757.     av= FindSubview(replaceFindId); if (av) { av->Disable();  }
  3758.     av= FindSubview(replaceAllId); if (av) { av->Disable(); }
  3759.     av= FindSubview(cBackwards);     if (av) { av->Disable(); }
  3760.     av= FindSubview(cFullWord); if (av) { av->Disable(); }
  3761.     //av= FindSubview(cCaseSense); if (av) { av->Disable(); }
  3762.     if (fReplaceText) fReplaceText->Disable();
  3763. }
  3764.  
  3765. void DRichFindDialog::DoFind() 
  3766. {
  3767.     const char    *target;
  3768.     Boolean     casesense, back, fullword, found;
  3769.     short            paragat, charat;
  3770.     long            len;
  3771.     
  3772.     target= this->GetFind();
  3773.     if (target && *target) {
  3774.         casesense    = this->CaseSensitive();
  3775.         back= this->Backwards();         // not yet supported
  3776.         fullword= this->FullWord(); // not yet supported
  3777.         paragat= fView->fSelParag - 1; // offset by -1 for real parag# -- MESS !
  3778.         charat= fView->fSelChar;
  3779.         len= StrLen(target);
  3780.         if (fLastTarget && StringCmp(target, fLastTarget)==0 
  3781.          && paragat == fLastParag && charat == fLastChar) {
  3782.             charat += len;
  3783.             found= fView->Find( (char*)target, paragat, charat, paragat, charat, casesense); 
  3784.             }
  3785.         else {
  3786.             if (fLastTarget) MemFree(fLastTarget);
  3787.             fLastTarget= StrDup(target);
  3788.             found= fView->Find( (char*)target, paragat, charat, paragat, charat, casesense); 
  3789.             }
  3790.         fLastParag= paragat;
  3791.         fLastChar = charat;
  3792.         if (found) {
  3793.             fView->SetSelectedText( paragat+1, charat, paragat+1, charat + len);
  3794.             }
  3795.         }
  3796. }                
  3797.  
  3798.  
  3799.  
  3800. //class    DRichTextDoc : public DWindow
  3801.  
  3802.  
  3803.  
  3804. Nlm_RecT DRichTextDoc::gRichDocRect = { 0, 0, 0, 0 };
  3805.  
  3806.  
  3807. DRichTextDoc::DRichTextDoc( long id, Boolean makeRichView, Nlm_FonT itsFont) :
  3808.         DWindow( id, gApplication, document),
  3809.         fRichView(NULL), fFloatingEditText(NULL)
  3810. {     
  3811.     Nlm_PoinT nps;
  3812.     fFont= itsFont;
  3813.     this->GetNextPosition( &nps);
  3814.     fFloatingEditText= (DDialogText*) new DHiddenText(0,this,"");
  3815.     this->SetNextPosition( nps);
  3816.     fFloatingEditText->Hide();
  3817.     //this->SetEditText(fFloatingEditText);
  3818.     
  3819.     if (makeRichView) {
  3820.         this->GetNextPosition( &nps);
  3821.         nps.x= 0; // fix for odd offset
  3822.         this->SetNextPosition( nps);
  3823.         fRichView= new DRichView( 0, this, gPrintManager->PageWidth(), 0);
  3824.         fRichView->SetSlateBorder( true);
  3825.         fRichView->SetResize( DView::matchsuper, DView::relsuper);
  3826.         //fRichView->SetTabs( gTextTabStops);
  3827.         //fRichView->SizeToSuperview( fWindow, true, false); // this needs to adjust for if view has scrollbar !
  3828.         //fSaveHandler= fRichView; //DRichView() installs these handlers !
  3829.         //fPrintHandler= fRichView;
  3830.         }
  3831. }
  3832.  
  3833.                               
  3834. void DRichTextDoc::Open()
  3835. {
  3836.     this->CalcWindowSize();
  3837.     if (!fFindDlog) fFindDlog= new DRichFindDialog( fRichView);
  3838.     fRichView->SizeToSuperview( this, true, false); // this needs to adjust for if view has scrollbar !
  3839.     DWindow::Open();
  3840. }
  3841.  
  3842. void DRichTextDoc::Open( DFile* aFile)
  3843. {
  3844.     if (aFile) fRichView->ShowFile( (char*)aFile->GetName(), fFont);
  3845.     SetTitle( (char*)aFile->GetShortname());
  3846.     Open();
  3847. }
  3848.  
  3849. void  DRichTextDoc::Open( char* filename) 
  3850. {
  3851.     fRichView->ShowFile( filename, fFont);
  3852.     SetTitle( (char*)DFileManager::FilenameFromPath(filename));
  3853.   Open();
  3854. }
  3855.  
  3856. void DRichTextDoc::Close()
  3857. {
  3858.     //if (!Nlm_EmptyRect(&fViewrect)) gRichDocRect= fViewrect;  
  3859.     if (fRichView) fRichView->ViewRect( gRichDocRect);  // GetPosition
  3860.     DWindow::Close();
  3861. }
  3862.  
  3863. void DRichTextDoc::ResizeWin()
  3864. {
  3865.     DWindow::ResizeWin();
  3866.     if (fRichView) fRichView->ViewRect( gRichDocRect);
  3867.     //if (!Nlm_EmptyRect(&fViewrect)) gRichDocRect= fViewrect;  
  3868. }
  3869.  
  3870. Boolean DRichTextDoc::IsMyAction(DTaskMaster* action) 
  3871. {
  3872.     switch(action->Id()) {
  3873.         case DApplication::kUndo:
  3874.             Message(MSG_OK,"DRichTextDoc::Undo not ready.");
  3875.             return true;
  3876.         case DApplication::kCut:
  3877.             Message(MSG_OK,"DRichTextDoc::Cut not ready.");
  3878.             //this->CutText(); 
  3879.             return true;
  3880.             
  3881.         case DApplication::kCopy: {
  3882.             char* theText= NULL;
  3883.             if (fRichView) theText= fRichView->GetSelectedText();
  3884.             if (theText) {
  3885.                 fFloatingEditText->SetText(theText);
  3886.                 fFloatingEditText->SetSelection(0,32000); 
  3887.           fFloatingEditText->CopyText(); 
  3888.           MemFree( theText);
  3889.                 fFloatingEditText->SetText(""); // don't need to keep extra copies around
  3890.                 //Message(MSG_OK,"DRichTextDoc::Copied text selection.");
  3891.           }
  3892.         }
  3893.             return true;
  3894.             
  3895.         case DApplication::kPaste:
  3896.             Message(MSG_OK,"DRichTextDoc::Paste not ready.");
  3897.             //this->PasteText(); 
  3898.             return true;
  3899.         case DApplication::kClear:
  3900.             Message(MSG_OK,"DRichTextDoc::Clear not ready.");
  3901.             //this->ClearText(); 
  3902.             return true;
  3903.         case DApplication::kSelectAll:
  3904.             //Message(MSG_OK,"DRichTextDoc::Select all not ready.");
  3905.             if (fRichView) fRichView->SelectAll();
  3906.             //this->SetSelection(0,0,32000,32000); 
  3907.             return true;
  3908.         default:
  3909.             return DWindow::IsMyAction(action);
  3910.         }
  3911. }
  3912.  
  3913.  
  3914. // class DRichApplication : public DApplication
  3915.  
  3916.  
  3917. DRichApplication::DRichApplication()
  3918. {
  3919.     //fAcceptableFileTypes= "TEXTPICTGIFfRTF "; /* up to 4 types, or null for all types */
  3920.     // ^^ not working, only 1st seen !?
  3921.     //fAcceptableFileTypes= NULL;
  3922. }
  3923.  
  3924.  
  3925. void DRichApplication::OpenDocument(DFile* aFile)
  3926. {
  3927.     if (aFile && aFile->Exists()) {
  3928.         gCursor->watch();
  3929.         DRichTextDoc* aDoc= new DRichTextDoc();
  3930.         aDoc->Open( aFile);
  3931.         gCursor->arrow();
  3932.         }
  3933. }
  3934.  
  3935.  
  3936.