home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / DOCVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  19.4 KB  |  877 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1993 by Borland International
  3. //   source\owl\docview.cpp
  4. //   Implements classes TDocument, TView, TWindowView
  5. //----------------------------------------------------------------------------
  6. #pragma hdrignore SECTION
  7. #include <owl\owlpch.h>
  8. #include <owl\docmanag.h>
  9. #include <owl\docview.rc>
  10. #include <string.h>
  11.  
  12. DIAG_DECLARE_GROUP(OwlDocView);        // General Doc/View diagnostic group
  13.  
  14. #if !defined(SECTION) || SECTION == 1
  15.  
  16. const UINT MinUniqueViewId = 0x8000;
  17. UINT TView::NextViewId = MinUniqueViewId;
  18.  
  19. //
  20. //  class TDocument
  21. //  ----- ---------
  22. //
  23.  
  24. TDocument*
  25. TDocument::List::Next(const TDocument* doc)
  26. {
  27.   return doc ? doc->NextDoc : DocList;
  28. }
  29.  
  30. BOOL
  31. TDocument::List::Insert(TDocument* doc)
  32. {
  33.   TDocument* pdoc;
  34.   for (pdoc = DocList; pdoc; pdoc = pdoc->NextDoc)
  35.     if (pdoc == doc)
  36.       return FALSE;
  37.   doc->NextDoc = DocList;
  38.   DocList = doc;
  39.   return TRUE;
  40. }
  41.  
  42. BOOL
  43. TDocument::List::Remove(TDocument* doc)
  44. {
  45.   TDocument** ppdoc;
  46.   for (ppdoc = &DocList; *ppdoc; ppdoc = &(*ppdoc)->NextDoc){
  47.     if (*ppdoc == doc) {
  48.       *ppdoc = doc->NextDoc;
  49.       return TRUE;
  50.     }
  51.   }
  52.   return FALSE;
  53. }
  54.  
  55. void
  56. TDocument::List::Destroy()
  57. {
  58.   while(DocList)
  59.     delete DocList;   // removes it entry from destructor
  60. }
  61.  
  62. TDocument::TDocument(TDocument* parent)
  63.                   : ParentDoc(parent), NextDoc(0), OpenMode(0),
  64.                     Title(0), Template(0), ViewList(0), Tag(0), StreamList(0),
  65.                     DocPath(0), DirtyFlag(FALSE)
  66. {
  67.   if (parent) {
  68.     DocManager = parent->DocManager;
  69.     parent->ChildDoc.Insert(this);
  70.   } else {
  71.     TApplication* app = GetApplicationObject();
  72.     if ((DocManager = app->DocManager) == 0)
  73.       THROW( TXOwl(IDS_NODOCMANAGER) );  // no doc manager to catch this one
  74.     DocManager->DocList.Insert(this);
  75.   }
  76. }
  77.  
  78. TDocument::~TDocument()
  79. {
  80.   ChildDoc.Destroy();    // destroy children first, otherwise unnecessary
  81.   Close();               // force close (not virtual at this point!)
  82.  
  83.   //  delete all attached views, data has already been flushed
  84.   //
  85.   SetTemplate(0);   // unref tpl, prevent self autodelete when deleting views
  86.   TView* pview;
  87.   for (pview = ViewList; pview != 0; pview = pview->NextView) {
  88.     DocManager->PostEvent(dnClose, *pview);
  89.     delete pview;
  90.   }
  91.  
  92.   //  delete all streams, should only be present if abort or coding error
  93.   //
  94.   while(StreamList)
  95.     delete StreamList;
  96.  
  97.   // detach from parent and doc manager
  98.   //
  99.   if (ParentDoc) {
  100.     ParentDoc->ChildDoc.Remove(this);
  101.   } else {
  102.     DocManager->PostEvent(dnClose, *this);
  103.     DocManager->DocList.Remove(this);
  104.   }
  105.  
  106.   delete Title;
  107.   delete DocPath;
  108. }
  109.  
  110. static char* PropNames[] = {
  111.   "Document Class",  // DocumentClass
  112.   "Template Name",   // TemplateName
  113.   "View Count",      // ViewCount
  114.   "Storage Path",    // StoragePath
  115.   "Document Title",  // DocTitle
  116. };
  117.  
  118. static int PropFlags[] = {
  119.   pfGetText|pfConstant,  // DocumentClass
  120.   pfGetText,             // TemplateName
  121.   pfGetBinary|pfGetText, // ViewCount
  122.   pfGetText|pfSettable,  // StoragePath
  123.   pfGetText|pfSettable,  // DocTitle
  124. };
  125.  
  126. const char*
  127. TDocument::PropertyName(int index)
  128. {
  129.   if (index <= PrevProperty)
  130.     return 0;
  131.   else if (index < NextProperty)
  132.     return PropNames[index-PrevProperty-1];
  133.   else
  134.     return 0;
  135. }
  136.  
  137. int
  138. TDocument::PropertyFlags(int index)
  139. {
  140.   if (index <= PrevProperty)
  141.     return 0;
  142.   else if (index < NextProperty)
  143.     return PropFlags[index-PrevProperty-1];
  144.   else
  145.     return 0;
  146. }
  147.  
  148. int
  149. TDocument::FindProperty(const char far* name)
  150. {
  151.   int i;
  152.   for (i=0; i < NextProperty-PrevProperty-1; i++)
  153.     if (strcmp(PropNames[i], name) == 0)
  154.       return i+PrevProperty+1;
  155.   return 0;
  156. }
  157.  
  158. int
  159. TDocument::GetProperty(int prop, void far* dest, int textlen)
  160. {
  161.   const char far* src;
  162.   switch(prop)
  163.   {
  164.     case DocumentClass:
  165.       src = _TYPENAME(this);
  166.       break;
  167.     case TemplateName:
  168.       src = Template ? Template->Description : 0;
  169.       break;
  170.     case ViewCount:
  171.     {
  172.       char buf[4];
  173.       int cnt;
  174.       TView* pview;
  175.       for (pview=ViewList, cnt=0; pview != 0; pview=pview->NextView, cnt++) ;
  176.       if (!textlen) {
  177.         *(int far*)dest = cnt;
  178.         return sizeof(int);
  179.       }
  180.       wsprintf(buf, "%d", cnt);
  181.       src = buf;
  182.       break;
  183.     }
  184.     case StoragePath:
  185.       src = DocPath;
  186.       break;
  187.     case DocTitle:
  188.       src = Title;
  189.       break;
  190.     default:
  191.       return 0;
  192.   }
  193.   if (!textlen)
  194.     return 0;
  195.   int srclen = src ? strlen(src) : 0;
  196.   if (textlen > srclen)
  197.     textlen = srclen;
  198.   if (textlen)
  199.     memcpy(dest, src, textlen);
  200.   *((char far*)dest + textlen) = 0;
  201.   return srclen;
  202. }
  203.  
  204. BOOL
  205. TDocument::SetProperty(int prop, const void far* src)
  206. {
  207.   switch(prop)
  208.   {
  209.     case DocTitle:
  210.       SetTitle((const char far*)src);
  211.       break;
  212.     case StoragePath:
  213.       return SetDocPath((const char far*)src);
  214.     default:
  215.       return FALSE;
  216.   }
  217.   return TRUE;
  218. }
  219.  
  220. TDocument&
  221. TDocument::RootDocument()
  222. {
  223.   TDocument* pdoc = this;
  224.   while(pdoc->ParentDoc)
  225.     pdoc = pdoc->ParentDoc;
  226.   return *pdoc; 
  227. }
  228.  
  229. void
  230. TDocument::SetDocManager(TDocManager& dm)
  231. {
  232.   if (!ParentDoc) {
  233.     if (DocManager)  // test needed for TDocManager::Streamer::Read()
  234.       DocManager->DocList.Remove(this);
  235.     dm.DocList.Insert(this);
  236.   }
  237.   DocManager = &dm;
  238. }
  239.  
  240. BOOL
  241. TDocument::SetDocPath(LPCSTR path)
  242. {
  243.   char title[256];
  244.   delete DocPath;
  245.   DocPath = path ? strnewdup(path) : 0;
  246.   if (path == 0 || ::GetFileTitle(path, title, sizeof(title)) != 0) {
  247.     if (DocManager->Application->LoadString(IDS_UNTITLED, title, sizeof(title)) == 0)
  248.       title[0] = 0;
  249.   }
  250.   SetTitle(title);
  251.   return TRUE;  // derived classes may validate path
  252. }
  253.  
  254. void
  255. TDocument::SetTitle(LPCSTR title)
  256. {
  257.   delete Title;
  258.   Title = title ? strnewdup(title) : 0;
  259.   ReindexFrames();
  260. }
  261.  
  262. BOOL
  263. TDocument::SetTemplate(TDocTemplate* tpl)
  264. {
  265.   if (Template)
  266.     DocManager->UnRefTemplate(*Template);
  267.   if (tpl)
  268.     DocManager->RefTemplate(*tpl);
  269.   Template = tpl;
  270.   return TRUE;
  271. }
  272.  
  273. void
  274. TDocument::ReindexFrames()
  275. {
  276.   TView* pview;
  277.   int seq;
  278.  
  279.   for (seq = -1, pview = ViewList; pview != 0; pview = pview->NextView) {
  280.          seq -= pview->SetDocTitle(Title, seq);  // decrement if title displayed
  281.          if (seq == -3)   // need only check if more than one title displayed
  282.       break;
  283.   }
  284.   if (seq == -1)
  285.     return;
  286.   seq = (seq == -2 ? 0 : 1);
  287.   for (pview = ViewList; pview != 0; pview = pview->NextView) {
  288.     seq += pview->SetDocTitle(Title, seq);  // increment if title displayed
  289.   }
  290. }
  291.  
  292. void
  293. TDocument::AttachStream(TStream& strm)
  294. {
  295.   strm.NextStream = StreamList;
  296.   StreamList = &strm;
  297. }
  298.  
  299. void
  300. TDocument::DetachStream(TStream& strm)
  301. {
  302.   TStream** plist = &StreamList;
  303.   for ( ; *plist; plist = &(*plist)->NextStream) {
  304.     if (*plist == &strm){
  305.       *plist = strm.NextStream;
  306.       return;
  307.     }
  308.   }
  309. }
  310.  
  311. TStream*
  312. TDocument::NextStream(const TStream* strm)
  313. {
  314.   return strm ? strm->NextStream : StreamList;
  315. }
  316.  
  317. TView*
  318. TDocument::NextView(const TView* view)
  319. {
  320.   return view ? view->NextView : ViewList;
  321. }
  322.  
  323. void
  324. TDocument::AttachView(TView& view)
  325. {
  326.   TView** ppview;
  327.  
  328.   for (ppview = &ViewList; *ppview; ppview = &(*ppview)->NextView)
  329.   ;
  330.   *ppview = &view;    // insert at end of list
  331.   view.NextView = 0;
  332.   view.Doc = this;
  333.   NotifyViews(vnViewOpened, (long)&view, &view);
  334. }
  335.  
  336. TView*
  337. TDocument::InitView(TView* view)
  338. {
  339.   if (!view)           // test if new TView failed
  340.       return 0;
  341.   if (!view->IsOK()){  // test if constructor failed
  342.       delete view;
  343.       return 0;
  344.   }
  345.   DocManager->PostEvent(dnCreate, *view);
  346.   if (!view->IsOK()){      // if failed in creation
  347.       delete view;
  348.       return 0;
  349.   }
  350.   ReindexFrames();
  351.   if (++TView::NextViewId < MinUniqueViewId)
  352.     TView::NextViewId = MinUniqueViewId;
  353.   return view;
  354. }
  355.  
  356. BOOL
  357. TDocument::DetachView(TView& view)
  358. {
  359.   TView** plist = &ViewList;
  360.   for ( ; *plist; plist = &(*plist)->NextView) {
  361.     if (*plist == &view){
  362.       *plist = view.NextView;
  363.       NotifyViews(vnViewClosed, (long)&view, &view);
  364.       if (!ViewList){     // all views for this doc are now gone
  365.          if (Template && (Template->Flags & dtAutoDelete)) {
  366.            if (IsOpen())
  367.              Close();      // close the document streams
  368.            return view.IsOK();   // delete doc UNLESS failure in creation
  369.          }
  370.       } else {
  371.         ReindexFrames();
  372.       }
  373.       break;
  374.     }
  375.   }
  376.   return FALSE;
  377. }
  378.  
  379. BOOL
  380. TDocument::Commit(BOOL force)
  381. {
  382.   TDocument* pdoc = 0;
  383.   while ((pdoc = ChildDoc.Next(pdoc)) != 0) {
  384.     if (!pdoc->Commit(force))
  385.       return FALSE;
  386.   }
  387.   // should we test here for DocPath==0 , or should caller have checked?
  388.   return NotifyViews(vnCommit, force);
  389. }
  390.  
  391. BOOL
  392. TDocument::Revert(BOOL clear)
  393. {
  394.   TDocument* pdoc = 0;
  395.   while ((pdoc = ChildDoc.Next(pdoc)) != 0) {
  396.     if (!pdoc->Revert(clear))
  397.       return FALSE;
  398.   }
  399.   return NotifyViews(vnRevert, clear);
  400. }
  401.  
  402. BOOL
  403. TDocument::NotifyViews(int event, long item, TView* exclude)
  404. {
  405.   BOOL answer = TRUE;
  406.   TEventHandler::TEventInfo eventInfo(WM_OWLNOTIFY, event);
  407.  
  408.   TDocument* pdoc = 0;
  409.   while ((pdoc = ChildDoc.Next(pdoc)) != 0)  
  410.     answer &= pdoc->NotifyViews(event, item, exclude);
  411.  
  412.   TView* pview;
  413.   for (pview = ViewList; pview != 0; pview = pview->NextView)
  414.     if (pview != exclude && pview->Find(eventInfo))
  415.       answer &= (int)pview->Dispatch(eventInfo, 0, item);
  416.   return answer;
  417. }
  418.  
  419. TView*
  420. TDocument::QueryViews(int event, long item, TView* exclude)
  421. {
  422.   TView* pview;
  423.   TDocument* pdoc = 0;
  424.   while ((pdoc = ChildDoc.Next(pdoc)) != 0)
  425.     if ((pview = pdoc->QueryViews(event, item, exclude)) != 0)
  426.       return pview;
  427.  
  428.   TEventHandler::TEventInfo eventInfo(WM_OWLNOTIFY, event);
  429.   for (pview = ViewList; pview != 0; pview = pview->NextView)
  430.     if (pview != exclude && pview->Find(eventInfo)
  431.                          && pview->Dispatch(eventInfo, 0, item))
  432.       return pview;    // return first acknowledger
  433.  
  434.   return 0;            // if no takers
  435. }
  436.  
  437. BOOL
  438. TDocument::IsDirty()
  439. {
  440.   if (DirtyFlag)
  441.     return TRUE;
  442.  
  443.   TDocument* pdoc = 0;
  444.   while ((pdoc = ChildDoc.Next(pdoc)) != 0)
  445.     if (pdoc->IsDirty())
  446.       return TRUE;
  447.  
  448.   return (QueryViews(vnIsDirty) != 0);
  449. }
  450.  
  451. BOOL
  452. TDocument::HasFocus(HWND hwnd)
  453. {
  454.   TDocument* pdoc = 0;
  455.   while ((pdoc = ChildDoc.Next(pdoc)) != 0)
  456.     if (pdoc->HasFocus(hwnd))
  457.       return TRUE;
  458.  
  459.   return (QueryViews(vnIsWindow, (long)hwnd) != 0);
  460. }
  461.  
  462. BOOL
  463. TDocument::CanClose()
  464. {
  465.   TDocument* pdoc = 0;
  466.   while ((pdoc = ChildDoc.Next(pdoc)) != 0)
  467.     if (!pdoc->CanClose())
  468.       return FALSE;
  469.  
  470.   return DocManager->FlushDoc(*this);  // do the UI in the doc manager
  471. }
  472.  
  473. BOOL
  474. TDocument::Close()
  475. {
  476.   TDocument* pdoc = 0;
  477.   while ((pdoc = ChildDoc.Next(pdoc)) != 0)
  478.     if (!pdoc->Close())
  479.       return FALSE;
  480.  
  481.   return TRUE;
  482. }
  483.  
  484. UINT
  485. TDocument::PostError(UINT sid, UINT choice)
  486. {
  487.   return DocManager->PostDocError(*this, sid, choice);
  488. }
  489.  
  490.  
  491. //
  492. //  class TView
  493. //  ----- -----
  494. //
  495.  
  496. TView::TView(TDocument& doc) : Tag(0), ViewMenu(0)
  497. {
  498.   ViewId = NextViewId;
  499.   doc.AttachView(*this);
  500. }
  501.  
  502. TView::~TView()
  503. {
  504.   delete ViewMenu;
  505.   if (Doc->DetachView(*this)) {
  506.     delete Doc;
  507.   }
  508. }
  509.  
  510. void
  511. TView::SetViewMenu(TMenuDescr* menu)
  512. {
  513.   ViewMenu = menu;
  514.   TDocTemplate* tpl = Doc->GetTemplate();
  515.   if (tpl && *ViewMenu->Module == *tpl->GetModule())
  516.     ViewMenu->Module = tpl->GetModule();// force same module alias as template
  517. }
  518.  
  519. static char* TView_PropertyNames[] = {
  520.   "View Class",      // ViewClass
  521.   "View Name",       // ViewName
  522. };
  523.  
  524. static int TView_PropertyFlags[] = {
  525.   pfGetText|pfConstant,  // ViewClass
  526.   pfGetText|pfConstant,  // ViewName
  527. };
  528.  
  529. const char*
  530. TView::PropertyName(int index)
  531. {
  532.   if (index <= PrevProperty)
  533.     return 0;
  534.   else if (index < NextProperty)
  535.     return TView_PropertyNames[index-PrevProperty-1];
  536.   else
  537.     return 0;
  538. }
  539.  
  540. int
  541. TView::PropertyFlags(int index)
  542. {
  543.   if (index <= PrevProperty)
  544.     return 0;
  545.   else if (index < NextProperty)
  546.     return TView_PropertyFlags[index-PrevProperty-1];
  547.   else
  548.     return 0;
  549. }
  550.  
  551. int
  552. TView::FindProperty(const char far* name)
  553. {
  554.   int i;
  555.   for (i=0; i < NextProperty-PrevProperty-1; i++)
  556.     if (strcmp(TView_PropertyNames[i], name) == 0)
  557.       return i+PrevProperty+1;
  558.   return 0;
  559. }
  560.  
  561. int
  562. TView::GetProperty(int prop, void far* dest, int textlen)
  563. {
  564.   const char far* src;
  565.   switch(prop)
  566.   {
  567.     case ViewClass:
  568.       src = _TYPENAME(this);
  569.       break;
  570.     case ViewName:
  571.       src = GetViewName();
  572.       break;
  573.     default:
  574.       return 0;
  575.   }
  576.   if (!textlen)
  577.     return 0;
  578.   int srclen = src ? strlen(src) : 0;
  579.   if (textlen > srclen)
  580.     textlen = srclen;
  581.   if (textlen)
  582.     memcpy(dest, src, textlen);
  583.   *((char far*)dest + textlen) = 0;
  584.   return srclen;
  585. }
  586.  
  587.  
  588. //
  589. //  class TWindowView
  590. //  ----- -----------
  591. //
  592.  
  593. DEFINE_RESPONSE_TABLE1(TWindowView, TWindow)
  594.   EV_VN_ISWINDOW,
  595. END_RESPONSE_TABLE;
  596.  
  597.  
  598. //
  599. //  class TDateTime (eventually)
  600. //  ----- ---------
  601. //
  602. int FormatFileTime(FILETIME* pft, void far* dest, int textlen)
  603. {
  604.   char buf[40];
  605.   int len;
  606.  
  607.   if (!textlen) {
  608.     *(FILETIME FAR*)dest = *pft;
  609.     return sizeof(FILETIME);
  610.   }
  611. #if defined(__WIN32__)
  612.   SYSTEMTIME dt;
  613.   FileTimeToSystemTime(pft, &dt);
  614.   len = wsprintf(buf,"%d/%d/%d %02d:%02d:%02d.%02d",
  615.                  dt.wMonth, dt.wDay, dt.wYear,
  616.                  dt.wHour, dt.wMinute, dt.wSecond, dt.wMilliseconds/10);
  617. #else
  618.   struct time filet;
  619.   struct date filed;
  620.   if (!(FileTimeToDateTime(pft, &filed, &filet)))
  621.     return FALSE;
  622.   len = wsprintf(buf,"%d/%d/%d %02d:%02d:%02d.%02d",
  623.                  filed.da_mon,filed.da_day,filed.da_year,
  624.                  filet.ti_hour,filet.ti_min,filet.ti_sec,filet.ti_hund);
  625. #endif
  626.   if (textlen > len)
  627.     textlen = len;
  628.   memcpy(dest, buf, textlen);
  629.   *((char far*)dest + textlen) = 0;
  630.   return len;
  631. }
  632.  
  633. #if !defined(__WIN32__)
  634. //
  635. // Win32/OLE2 compatible FILETIME support for 16-bit applications
  636. //    these functions to be incorporated into TDateTime class
  637. //
  638.  
  639. int FormatDateTime(struct date filed, struct time filet, void far* dest, int textlen)
  640. {
  641.   char buf[40];
  642.   if (!textlen) {
  643.     DateTimeToFileTime(&filed, &filet, (FILETIME FAR*)dest);
  644.     return sizeof(FILETIME);
  645.   }
  646.   int len = wsprintf(buf,"%d/%d/%d %02d:%02d:%02d.%02d",
  647.                     filed.da_mon,filed.da_day,filed.da_year,
  648.                     filet.ti_hour,filet.ti_min,filet.ti_sec,filet.ti_hund);
  649.   if (textlen > len)
  650.     textlen = len;
  651.   memcpy(dest, buf, textlen);
  652.   *((char far*)dest + textlen) = 0;
  653.   return len;
  654. }
  655.  
  656. // Convert date and time structures to 64-bit FILETIME structure
  657. //  multiply seconds by 10^7 and adjust offset to Jan. 1, 1601
  658. //  adjustment from Jan.1, 1970 = 116,444,736,000,000,000 = 0x019DB1DED53E8000
  659. //  This code is for Win32 and OLE2 compatibility when using Win16
  660.  
  661. #include <dos.h>
  662.  
  663. void DateTimeToFileTime(struct date* dosd, struct time* dost, FILETIME FAR* pft)
  664. {
  665.   union {
  666.     long udt;
  667.     int  w[2];
  668.   } u;
  669.   u.udt = dostounix(dosd, dost);
  670.   _BL = dost->ti_hund;
  671.   _AX = u.w[0];
  672.   _CX = u.w[1];
  673.   asm mov  di,200
  674.   asm mul  di
  675.   asm mov  bh,0
  676.   asm add  bx,bx
  677.   asm add  ax,bx
  678.   asm adc  dl,dh
  679.   asm xchg ax,cx
  680.   asm mov  bx,dx
  681.   asm mul  di
  682.   asm add  bx,ax
  683.   asm mov  si,0
  684.   asm adc  si,dx
  685.   asm les  di,pft
  686.   asm mov  ax,50000
  687.   asm xchg ax,cx
  688.   asm mul  cx
  689.   asm add  ax,0x8000
  690.   asm adc  dx,0
  691.   asm mov  es:[di],ax
  692.   asm xchg ax,dx
  693.   asm xchg ax,bx
  694.   asm mul  cx
  695.   asm add  ax,bx
  696.   asm adc  dx,0
  697.   asm add  ax,0xD53E
  698.   asm adc  dx,0
  699.   asm mov  es:[di+2],ax
  700.   asm xchg ax,dx
  701.   asm xchg ax,si
  702.   asm mul  cx
  703.   asm add  ax,si
  704.   asm adc  dx,0
  705.   asm add  ax,0xB1DE
  706.   asm adc  dx,0x019D
  707.   asm mov  es:[di+4],ax
  708.   asm mov  es:[di+6],dx
  709. }
  710.  
  711.  
  712. // Convert FILETIME structure to date and time structures
  713.  
  714. BOOL FileTimeToDateTime(FILETIME FAR* pft, struct date* dosd, struct time* dost)
  715. {
  716.   union {
  717.     long udt;
  718.     int  w[2];
  719.   } u;
  720.   asm les  di,pft
  721.   asm mov  dx,es:[di+6]
  722.   asm mov  ax,es:[di+4]
  723.   asm sub  ax,0xB1DE
  724.   asm sbb  dx,0x019D
  725.   asm jnc OK
  726.   return FALSE;
  727. OK:
  728.   asm mov  cx,50000
  729.   asm div  cx
  730.   asm xchg bx,ax
  731.   asm mov  ax,es:[di+2]
  732.   asm sub  ax,0xD53E
  733.   asm sbb  dx,0
  734.   asm div  cx
  735.   asm xchg si,ax
  736.   asm mov  ax,es:[di]
  737.   asm sub  ax,(0x8000-5000)
  738.   asm sbb  dx,0
  739.   asm div  cx
  740.   asm mov  dx,bx
  741.   asm xchg ax,si
  742.   asm mov  cx,200
  743.   asm div  cx
  744.   asm xchg ax,si
  745.   asm div  cx
  746.   asm shr  dx,1
  747.   asm push dx
  748.   u.w[0] = _AX;
  749.   u.w[1] = _SI;
  750.   unixtodos(u.udt, dosd, dost);
  751.   asm pop  ax
  752.   dost->ti_hund = _AL;
  753.   return TRUE;
  754. }
  755. #endif //!defined(__WIN32__)
  756.  
  757. //
  758. // dispatchers for view notifications
  759. //
  760.  
  761. LRESULT _OWLFUNC
  762. B_long_Dispatch(GENERIC& generic, int (GENERIC::*pmf)(long), WPARAM, LPARAM a)
  763. {
  764.   return (generic.*pmf)(a);
  765. }
  766.  
  767. LRESULT _OWLFUNC
  768. B_int_Dispatch(GENERIC& generic, int (GENERIC::*pmf)(int), WPARAM, LPARAM a)
  769. {
  770.   return (generic.*pmf)((int)a);
  771. }
  772.  
  773. LRESULT _OWLFUNC
  774. B_void_Dispatch(GENERIC& generic, int (GENERIC::*pmf)(), WPARAM, LPARAM)
  775. {
  776.   return (generic.*pmf)();
  777. }
  778.  
  779. LRESULT _OWLFUNC
  780. B_pointer_Dispatch(GENERIC& generic, int(GENERIC::*pmf)(void*),WPARAM,LPARAM a)
  781. {
  782.   return (generic.*pmf)((void*)a);
  783. }
  784.  
  785. #endif
  786. #if !defined(SECTION) || SECTION == 2
  787.  
  788.  
  789. IMPLEMENT_ABSTRACT_STREAMABLE(TView);
  790.  
  791. void*
  792. TView::Streamer::Read(ipstream& is, uint32 /*version*/) const
  793. {
  794.   TView* o = GetObject();
  795.   BOOL hasViewMenu = is.readByte();
  796.   if (hasViewMenu) {
  797.     o->ViewMenu = new TMenuDescr;
  798.     is >> *o->ViewMenu;
  799.   } else
  800.     o->ViewMenu = 0;
  801.   is >> o->ViewId;
  802.   is >> o->Doc;
  803.   is >> o->NextView;
  804.   return o;
  805. }
  806.  
  807. void
  808. TView::Streamer::Write(opstream& os) const
  809. {
  810.   TView* o = GetObject();
  811.   os.writeByte(o->ViewMenu ? (char)1 : (char)0);
  812.   if (o->ViewMenu)
  813.     os << *o->ViewMenu;
  814.   os << o->ViewId;
  815.   os << o->Doc;
  816.   os << o->NextView;
  817. }
  818.  
  819.  
  820. IMPLEMENT_ABSTRACT_STREAMABLE(TDocument);
  821.  
  822. void*
  823. TDocument::Streamer::Read(ipstream& is, uint32 /*version*/) const
  824. {
  825.   TDocument* o = GetObject();
  826.  
  827.   o->NextDoc = 0;
  828.   o->StreamList = 0;
  829.   o->DocManager = 0;
  830.   o->DirtyFlag = FALSE;
  831.  
  832.   is >> o->OpenMode;
  833.   o->DocPath = is.freadString();
  834.   o->Title   = is.freadString();
  835.   is >> o->Template;  // static templates must have been already streamed
  836.   is >> o->ParentDoc;
  837.   o->ViewList = 0;    // must init, does not get set until after view streamed
  838.   is >> o->ViewList;
  839.   is >> TView::NextViewId;  // static, but must get set by at least 1 document
  840.  
  841.   return o;
  842. }
  843.  
  844. void
  845. TDocument::Streamer::Write(opstream& os) const
  846. {
  847.   TDocument* o = GetObject();
  848.  
  849.   while (!o->CanClose())   // can't permit cancel here
  850.     ;
  851.   os << o->OpenMode;
  852.   os.fwriteString(o->DocPath);
  853.   os.fwriteString(o->Title);
  854.   os << o->Template;       // templates already streamed, must be so if static
  855.   os << o->ParentDoc;
  856.   os << o->ViewList;       // each view streams out the next
  857.   os << TView::NextViewId; // insure that this static var gets set on reload
  858. }
  859.  
  860. IMPLEMENT_STREAMABLE2(TWindowView, TWindow, TView);
  861. void*
  862. TWindowView::Streamer::Read(ipstream& is, uint32 /*version*/) const
  863. {
  864.   ReadBaseObject((TWindow*)GetObject(), is);
  865.   ReadBaseObject((TView*)GetObject(), is);
  866.   return GetObject();
  867. }
  868.  
  869. void
  870. TWindowView::Streamer::Write(opstream& os) const
  871. {
  872.   WriteBaseObject((TWindow*)GetObject(), os);
  873.   WriteBaseObject((TView*)GetObject(), os);
  874. }
  875.  
  876. #endif
  877.