home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 May / Pcwk5b98.iso / Borland / Cplus45 / BC45 / OWL1.PAK / FILEWND.CPP < prev    next >
Text File  |  1995-08-29  |  10KB  |  393 lines

  1. // ObjectWindows - (C) Copyright 1992 by Borland International
  2.  
  3. /* --------------------------------------------------------
  4.   FILEWND.CPP
  5.   Defines type TFileWindow, a text editor which can read
  6.   and write to a file.
  7.   -------------------------------------------------------- */
  8.  
  9. #include <string.h>
  10. #include <stdio.h>
  11. #include <alloc.h>
  12. #include "filewnd.h"
  13.  
  14. #define Min(a, b)     ((a) < (b) ? (a) : (b))
  15.  
  16. /* Constructor for a TFileWindow.  Initializes its data members using
  17.   passed parameters and default values. */
  18. TFileWindow::TFileWindow(PTWindowsObject AParent,LPSTR ATitle,
  19.                          LPSTR AFileName, PTModule AModule)
  20.              :   TEditWindow(AParent, ATitle, AModule)
  21. {
  22.   IsNewFile = TRUE;
  23.   FileName = _fstrdup(AFileName ? AFileName : "");
  24. }
  25.  
  26. /* Dispose of the file name. */
  27. TFileWindow::~TFileWindow()
  28. {
  29.   if ( FileName )
  30.     farfree(FileName);
  31. }
  32.  
  33. /* Performs setup for a TFileWindow, appending 'Untitled' to its caption */
  34. void TFileWindow::SetupWindow()
  35. {
  36.   TEditWindow::SetupWindow();
  37.   SetFileName(FileName);
  38.   if ( FileName[0] != '\0')
  39.     if ( !Read() )
  40.       SetFileName("");
  41. }
  42.  
  43. /* Sets the file name of the window and updates the caption. */
  44. void TFileWindow::SetFileName(LPSTR AFileName)
  45. {
  46.   char NewCaption[81];
  47.   LPSTR P[2];
  48.  
  49.   if ( FileName != AFileName )
  50.   {
  51.     farfree(FileName);
  52.     FileName = _fstrdup(AFileName ? AFileName : "");
  53.   }
  54.   P[0] = Title;
  55.   if ( FileName[0] == '\0' )
  56.     P[1] = "(Untitled)";
  57.   else
  58.     P[1] = AFileName;
  59.   if ( Title == NULL || Title[0] == '\0' )
  60.     SetWindowText(HWindow, P[1]);
  61.   else
  62.   {
  63.     wvsprintf(NewCaption, "%s - %s", (LPSTR)P);
  64.     SetWindowText(HWindow, NewCaption);
  65.   }
  66. }
  67.  
  68. /* Begins the edit of a new file, after determining that it is Ok to
  69.   clear the TEdit's text. */
  70. void TFileWindow::NewFile()
  71. {
  72.   if ( CanClear() )
  73.   {
  74.     Editor->Clear();
  75.     InvalidateRect(Editor->HWindow, NULL, FALSE);
  76.     Editor->ClearModify();
  77.     IsNewFile = TRUE;
  78.     SetFileName(NULL);
  79.   }
  80. }
  81.  
  82. /* Replaces the current file with the given file. */
  83. void TFileWindow::ReplaceWith(LPSTR AFileName)
  84. {
  85.   char OldName[MAXPATH];
  86.  
  87.   _fstrcpy(OldName, FileName);
  88.   SetFileName(AFileName);
  89.   if ( Read() )
  90.     InvalidateRect(Editor->HWindow, NULL, FALSE);
  91.   else
  92.     SetFileName(OldName);
  93. }
  94.  
  95. /* Brings up a dialog allowing the user to open a file into this
  96.   window.  Same as selecting File|Open from the menus. */
  97. void TFileWindow::Open()
  98. {
  99.   char TmpName[MAXPATH];
  100.  
  101.   if ( CanClear() && (GetModule()->ExecDialog(
  102.          new TFileDialog(this, SD_FILEOPEN,
  103.                          _fstrcpy(TmpName, "*.*"), GetModule())) == IDOK) )
  104.     ReplaceWith(TmpName);
  105. }
  106.  
  107. static HANDLE LocalReAllocDS(HANDLE hMem, WORD wBytes, WORD wFlags,
  108.                                                                  WORD TheDS)
  109. {
  110.   WORD SavedDS;
  111.   HANDLE ReturnValue;
  112.  
  113.   SavedDS = _DS;
  114.   _DS = TheDS;
  115.   ReturnValue = LocalReAlloc(hMem, wBytes, wFlags);
  116.   _DS = SavedDS;
  117.   return ReturnValue;
  118. }
  119.  
  120. static LPSTR LocalLockDS(HANDLE hMem, WORD TheDS)
  121. {
  122.   WORD SavedDS;
  123.   LPSTR ReturnValue;
  124.  
  125.   SavedDS = _DS;
  126.   _DS = TheDS;
  127.   ReturnValue = (LPSTR)LocalLock(hMem);
  128.   _DS = SavedDS;
  129.   return ReturnValue;
  130. }
  131.  
  132. static BOOL LocalUnlockDS(HANDLE hMem, WORD TheDS)
  133. {
  134.   WORD SavedDS;
  135.   BOOL ReturnValue;
  136.  
  137.   SavedDS = _DS;
  138.   _DS = TheDS;
  139.   ReturnValue = LocalUnlock(hMem);
  140.   _DS = SavedDS;
  141.   return ReturnValue;
  142. }
  143.  
  144. /* Reads the contents of a previously-specified file into the TEdit
  145.   child control. */
  146. BOOL TFileWindow::Read()
  147. {
  148.   long CharsToRead;
  149.   UINT HEditorBuffer;
  150.   LPSTR EditorBuffer;
  151.   WORD EditorsDS;
  152.   char S[MAXPATH + 33];
  153.   int AFile;
  154.   BOOL Success = FALSE;
  155.  
  156.   AFile = _lopen(FileName, OF_READ);
  157.   if ( AFile != -1 )
  158.   {
  159.     CharsToRead = _llseek(AFile, 0L, 2);
  160.     _llseek(AFile, 0L, 0);
  161.     if ( CharsToRead < MaxInt && CharsToRead > 0 )
  162.     {
  163.       Editor->Clear();
  164.  
  165.       // attempt to reallocate Editor's buffer to the size of the file
  166.       HEditorBuffer = SendMessage(Editor->HWindow, EM_GETHANDLE, 0, 0L);
  167.       EditorsDS = FP_SEG(GlobalLock((Editor->GetModule())->hInstance));
  168.       if ( LocalReAllocDS((HANDLE)HEditorBuffer, (WORD)(CharsToRead+1),
  169.                           LHND, EditorsDS) != NULL )
  170.       {
  171.         // read the file into EditorBuffer
  172.     EditorBuffer = (LPSTR)LocalLockDS((HANDLE)HEditorBuffer, EditorsDS);
  173.         if ( _lread(AFile, EditorBuffer, (WORD)CharsToRead) == CharsToRead )
  174.         {
  175.           // NULL terminate Editor's buffer
  176.           EditorBuffer[(WORD)CharsToRead] = '\0';
  177.       LocalUnlockDS((HANDLE)HEditorBuffer, EditorsDS);
  178.  
  179.       SendMessage(Editor->HWindow, EM_SETHANDLE, HEditorBuffer, 0L);
  180.           Success = TRUE;
  181.  
  182.           IsNewFile = FALSE;
  183.           Editor->ClearModify();
  184.           Editor->SetSelection(0,0);
  185.         }
  186.       }
  187.       GlobalUnlock((Editor->GetModule())->hInstance);
  188.     }
  189.     _lclose(AFile);
  190.   }
  191.   if ( !Success )
  192.   {
  193.     wsprintf(S, "Unable to read file \"%s\" from disk", FileName);
  194.     MessageBox(HWindow, S, GetModule()->Name, MB_ICONEXCLAMATION | MB_OK);
  195.   }
  196.   return Success;
  197. }
  198.  
  199. /* Saves the contents of the TEdit child control into the file currently
  200.   being editted.  Returns true if the file was saved or
  201.   Editor->IsModified returns FALSE (contents already saved). */
  202. BOOL TFileWindow::Save()
  203. {
  204.   if ( Editor->IsModified() )
  205.   {
  206.     if ( IsNewFile )
  207.       return SaveAs();
  208.     else
  209.     {
  210.       if ( Write() )
  211.         return TRUE;
  212.       else
  213.         return FALSE;
  214.     }
  215.   }
  216.   else       // Editor's contents haven't been changed. No need to write.
  217.     return TRUE;
  218. }
  219.  
  220. /* Saves the contents of the TEdit child control into a file whose name
  221.   is retrieved from the user, through execution of a "Save" file
  222.   dialog. Returns true if the file was saved. */
  223. BOOL TFileWindow::SaveAs()
  224. {
  225.   char TmpName[MAXPATH];
  226.   char OldName[MAXPATH];
  227.   OFSTRUCT TmpOfStruct;
  228.   char S[MAXPATH+20];
  229.  
  230.   _fstrcpy(OldName, FileName);
  231.   if ( FileName )
  232.     _fstrcpy(TmpName, FileName);
  233.   else
  234.     TmpName[0] = '\0';
  235.   if ( GetModule()->ExecDialog( new TFileDialog
  236.             (this, SD_FILESAVE, TmpName, GetModule())) == IDOK )
  237.   {
  238.     if ( OpenFile(TmpName, &TmpOfStruct, OF_EXIST) != -1 )
  239.     {
  240.       wsprintf(S, "Replace Current \"%s\"?", (LPSTR)TmpName);
  241.       if ( MessageBox(HWindow, S, "File Changed",
  242.                           MB_YESNO | MB_ICONQUESTION) == IDNO )
  243.       {
  244.         SetFileName(OldName);
  245.         return FALSE;
  246.       }
  247.     }
  248.     SetFileName(TmpName);
  249.     if ( Write() )
  250.       return TRUE;
  251.     else
  252.     {
  253.       SetFileName(OldName);
  254.       return FALSE;
  255.     }
  256.   }
  257.   return FALSE;
  258. }
  259.  
  260. /* Writes the contents of the TEdit child control to a
  261.    previously-specified file. */
  262. BOOL TFileWindow::Write()
  263. {
  264.   const BufferSize = 1024;
  265.  
  266.   long CharsToWrite, CharsWritten = 0;
  267.   int BlockSize;
  268.   Pchar ABuffer;
  269.   char S[MAXPATH + 33];
  270.   int NumLines;
  271.   int AFile;
  272.  
  273.   AFile = _lcreat(FileName, 0);
  274.   if ( AFile == -1 )
  275.   {
  276.     wsprintf(S, "Unable to write file \"%s\" to disk", FileName);
  277.     MessageBox(HWindow, S, GetModule()->Name, MB_ICONEXCLAMATION | MB_OK);
  278.     return FALSE;
  279.   }
  280.   else
  281.   {
  282.     NumLines = Editor->GetNumLines();
  283.     CharsToWrite = Editor->GetLineIndex(NumLines-1) +
  284.                    Editor->GetLineLength(NumLines-1);
  285.     ABuffer = new char[BufferSize+1 + 2*NumLines];
  286.     if ( !ABuffer )
  287.       return FALSE;
  288.     else
  289.     {
  290.       while ( CharsWritten < CharsToWrite )
  291.       {
  292.         BlockSize = (int)Min((CharsToWrite - CharsWritten), BufferSize);
  293.         Editor->GetSubText(ABuffer, (int)CharsWritten,
  294.           (int)(CharsWritten + BlockSize));
  295.         if (_lwrite(AFile, ABuffer, strlen(ABuffer)) == (WORD)-1)
  296.         {
  297.         delete ABuffer;
  298.             _lclose(AFile);
  299.             return FALSE;
  300.         }
  301.         CharsWritten += BlockSize;
  302.       }
  303.       IsNewFile = FALSE;
  304.       Editor->ClearModify();
  305.       delete ABuffer;
  306.     }
  307.     _lclose(AFile);
  308.   }
  309.   return TRUE;
  310. }
  311.  
  312. /* Returns a BOOL value indicating whether or not it is Ok to clear
  313.   the TEdit's text.  Returns TRUE if the text has not been changed, or
  314.   if the user Oks the clearing of the text. */
  315. BOOL TFileWindow::CanClear()
  316. {
  317.   char S[MAXPATH+28];
  318.   int Rslt;
  319.  
  320.   if ( Editor->IsModified() )
  321.   {
  322.     if ( !FileName || (FileName[0]=='\0'))
  323.       _fstrcpy(S, "Untitled file has changed.  Save?");
  324.     else
  325.       wsprintf(S, "File \"%s\" has changed.  Save?", FileName);
  326.     Rslt = MessageBox(HWindow, S, "File Changed",
  327.                           MB_YESNOCANCEL | MB_ICONQUESTION);
  328.     if ( Rslt == IDYES )
  329.       return Save();
  330.     else
  331.       return Rslt != IDCANCEL;
  332.   }
  333.   return TRUE;
  334. }
  335.  
  336. /* Returns a BOOL value indicating whether or not it is Ok to close
  337.   the TEdit's text.  Returns the result of a call to CanClear. */
  338. BOOL TFileWindow::CanClose()
  339. {
  340.   return CanClear();
  341. }
  342.  
  343. /* Responds to an incoming "New" command (with a CM_FILENEW command
  344.   identifier) by calling NewFile. */
  345. void TFileWindow::CMFileNew(TMessage&)
  346. {
  347.   NewFile();
  348. }
  349.     
  350. /* Responds to an incoming "Open" command (with a CM_FILEOPEN command
  351.   identifier) by calling Open(). */
  352. void TFileWindow::CMFileOpen(TMessage&)
  353. {
  354.   Open();
  355. }
  356.  
  357. /* Responds to an incoming "Save" command (with a CM_FILESAVE
  358.    command identifier) by calling Save. */
  359. void TFileWindow::CMFileSave(TMessage&)
  360. {
  361.   Save();
  362. }
  363. /* Responds to an incoming "SaveAs" command (with a CM_FILESAVEAS
  364.    command identifier) by calling SaveAs. */
  365. void TFileWindow::CMFileSaveAs(TMessage&)
  366. {
  367.   SaveAs();
  368. }
  369.  
  370. /* Reads an instance of TFileWindow from the passed ipstream. */
  371. void *TFileWindow::read(ipstream& is)
  372. {
  373.   TEditWindow::read(is);
  374.   FileName = is.freadString();
  375.   IsNewFile = ( FileName[0] == '\0' );
  376.   return this;
  377. }
  378.  
  379. /* Writes the TFileWindow to the passed opstream. */
  380. void TFileWindow::write(opstream& os)
  381. {
  382.   TEditWindow::write(os);
  383.   os.fwriteString(FileName);
  384. }
  385.  
  386. TStreamable *TFileWindow::build()
  387. {
  388.   return new TFileWindow(streamableInit);
  389. }
  390.  
  391. TStreamableClass RegFileWindow("TFileWindow", TFileWindow::build,
  392.                         __DELTA(TFileWindow));
  393.