home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 5.ddi / WEXAMPLE.ZIP / TODOLIST.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  16.6 KB  |  688 lines

  1. //---------------------------------------------------------------------
  2. //
  3. //  TODOLIST.CPP - part of TODO example program
  4. //
  5. //      Copyright (c) 1991, 1992 by Borland International
  6. //      All Rights Reserved.
  7. //
  8. //---------------------------------------------------------------------
  9.  
  10.  
  11. #define STRICT
  12.  
  13. #if !defined( __STRSTREAM_H )
  14. #include <strstream.h>
  15. #endif  // __STRSTREAM_H
  16.  
  17. #if !defined( __FSTREAM_H )
  18. #include <fstream.h>
  19. #endif  // __FSTREAM_H
  20.  
  21. #if !defined( __CTYPE_H )
  22. #include <ctype.h>
  23. #endif  // __CTYPE_H
  24.  
  25. #if !defined( __TODOLIST_H )
  26. #include "TodoList.h"
  27. #endif  // __TODOLIST_H
  28.  
  29. #if !defined( __TODODEFS_H )
  30. #include "TodoDefs.h"
  31. #endif  // __TODODEFS_H
  32.  
  33. #if !defined( __TODODLGS_H )
  34. #include "TodoDlgs.h"
  35. #endif  // __TODODLGS_H
  36.  
  37. #include <string.h>
  38. //---------------------------------------------------------------------
  39. //
  40. //  member functions and static data for class TdDate
  41. //
  42. //---------------------------------------------------------------------
  43.  
  44. static char *MonthNames[] =
  45.     {
  46.     "January",
  47.     "February",
  48.     "March",
  49.     "April",
  50.     "May",
  51.     "June",
  52.     "July",
  53.     "August",
  54.     "September",
  55.     "October",
  56.     "November",
  57.     "December"
  58.     };
  59.  
  60. //---------------------------------------------------------------------
  61. //
  62. //  TdDate::TdDate( const char *str );
  63. //
  64. //  constructor that takes a text string.  It's not very bright.
  65. //
  66. //  Format:
  67. //
  68. //      mmm[m*] d[d], yyyy
  69. //
  70. //      mmm must match the first three characters of a valid month
  71. //          name.  Any contiguous characters after these are ignored.
  72. //      dd  must be in the range 1..31.
  73. //      yyyy isn't checked.
  74. //
  75. //  If an invalid date is entered, TdDate will get the current system
  76. //  date.
  77. //
  78. //---------------------------------------------------------------------
  79.  
  80. TdDate::TdDate( const char *str ) : Date()
  81. {
  82.     unsigned M = 0;
  83.     while( M < 12 && strnicmp( str, MonthNames[M], 3 ) != 0 )
  84.         M++;
  85.     if( M >= 12 )
  86.         return;
  87.  
  88.     while( !isspace( *str ) )   // skip month name
  89.         str++;
  90.     while( isspace( *str ) )    // skip trailing whitespace
  91.     str++;
  92.  
  93.     unsigned D, Y;
  94.     istrstream is( (char *)str );
  95.     is >> D;
  96.     if( D < 1 || D > 31 )
  97.         return;
  98.  
  99.     is.get();                   // skip the comma
  100.  
  101.     is >> Y;
  102.     SetMonth( M + 1 );  // 1-based months!
  103.     SetDay( D );
  104.     SetYear( Y );
  105. }
  106.  
  107. //---------------------------------------------------------------------
  108. //
  109. //  member functions for class TodoEntry
  110. //
  111. //---------------------------------------------------------------------
  112.  
  113. int TodoEntry::isEqual( const Object& o ) const
  114. {
  115.     return dateDue == ((const TodoEntry&)o).dateDue;
  116. }
  117.  
  118. int TodoEntry::isLessThan( const Object& o ) const
  119. {
  120.     return dateDue < ((const TodoEntry&)o).dateDue;
  121. }
  122.  
  123. classType TodoEntry::isA() const
  124. {
  125.     return TodoEntryClass;
  126. }
  127.  
  128. char *TodoEntry::nameOf() const
  129. {
  130.     return "Todo Entry";
  131. }
  132.  
  133. hashValueType TodoEntry::hashValue() const
  134. {
  135.     return dateDue.hashValue();
  136. }
  137.  
  138. //---------------------------------------------------------------------
  139. //
  140. //  void TodoEntry::printOn( ostream& os ) const;
  141. //
  142. //  puts a TodoEntry onto an ostream in text form.
  143. //
  144. //---------------------------------------------------------------------
  145.  
  146. void TodoEntry::printOn( ostream& os ) const
  147. {
  148.     char temp[ 256 ];
  149.     ostrstream tstr( temp, sizeof temp );
  150.     tstr << priority
  151.          << '\t'
  152.          << dateCreated
  153.          << '\t'
  154.          << dateDue
  155.          << '\t'
  156.      << ( (text == 0) ? "" : text )
  157.          << ends;
  158.     os << temp;
  159. }
  160.  
  161. //---------------------------------------------------------------------
  162. //
  163. //  istream& operator >> ( istream& is, TodoEntry& td );
  164. //  ostream& operator << ( ostream& os, TodoEntry& td );
  165. //
  166. //  inserter and extractor for TodoEntry.  These work together to
  167. //  write entries out to a stream and read them back in.
  168. //
  169. //---------------------------------------------------------------------
  170.  
  171. istream& operator >> ( istream& is, TodoEntry& td )
  172. {
  173.     is >> td.priority;
  174.     int m, d, y;
  175.     if( is >> m >> d >> y )
  176.     td.dateDue = Date( m, d, y );
  177.     if( is >> m >> d >> y )
  178.     td.dateCreated = Date( m, d, y );
  179.     char text[ 128 ];
  180.     if( is.getline( text, sizeof text ) )
  181.         td.text = strdup( text );
  182.     td.dirty = FALSE;
  183.     return is;
  184. }
  185.  
  186. ostream& operator << ( ostream& os, TodoEntry& td )
  187. {
  188.     os << td.priority << " "
  189.        << td.dateDue.Month() << " " << td.dateDue.Day() << " "
  190.        << td.dateDue.Year() << " "
  191.        << td.dateCreated.Month() << " " << td.dateCreated.Day() << " "
  192.        << td.dateCreated.Year() << " " << td.text << endl;
  193.     if( os )
  194.         td.dirty = FALSE;
  195.     return os;
  196. }
  197.  
  198. //---------------------------------------------------------------------
  199. //
  200. //  member functions for class TodoList.
  201. //
  202. //---------------------------------------------------------------------
  203.  
  204. void TodoList::add( Object& o )
  205. {
  206.     dirty = TRUE;               // mark that the list has been modified
  207.     SortedArray::add( o );      // add the entry
  208. }
  209.  
  210. void TodoList::detach( Object& o, DeleteType d )
  211. {
  212.     dirty = TRUE;               // mark that the list has been modified
  213.     SortedArray::detach( o, d );// remove the entry
  214. }
  215.  
  216. int TodoList::indexOf( const TodoEntry& tde )
  217. {
  218.     for( int i = 0; i < getItemsInContainer(); i++ )
  219.         if( (*this)[i] == tde )
  220.             return i;
  221.     return -1;
  222. }
  223.  
  224. BOOL TodoList::modified()
  225. {
  226.     if( dirty == TRUE )         // if we've added or deleted entries
  227.         return TRUE;            // we've been modified
  228.                                 // otherwise, if any entry has been
  229.                                 // modified, the list has been modified.
  230.  
  231.     ContainerIterator& ci = initIterator();
  232.     while( ci != 0 )
  233.         {
  234.     TodoEntry& ent = (TodoEntry&)ci++;
  235.         if( ent != NOOBJECT && ent.modified() == TRUE )
  236.             {
  237.             delete &ci;
  238.             return TRUE;
  239.             }
  240.         }
  241.     delete &ci;
  242.     return FALSE;
  243. }
  244.  
  245. void TodoList::clear()
  246. {
  247.     int count = getItemsInContainer();
  248.     for( int i = 0; i < count; i++ )
  249.         if( (*this)[i] != NOOBJECT )
  250.         destroy( i );
  251. }
  252.  
  253. //---------------------------------------------------------------------
  254. //
  255. //  istream& operator >> ( istream& is, TodoList& tl );
  256. //  ostream& operator << ( ostream& os, TodoList& tl );
  257. //
  258. //  inserter and extractor for TodoList.  These work together to
  259. //  write lists out to a stream and read them back in.
  260. //
  261. //---------------------------------------------------------------------
  262.  
  263. istream& operator >> ( istream& is, TodoList& tl )
  264. {
  265.     do  {
  266.         TodoEntry td;
  267.         is >> td;
  268.         if( !is.eof() )
  269.             {
  270.             tl.add( *(new TodoEntry( td )) );
  271.             tl.dirty = FALSE;
  272.             }
  273.     } while( !is.eof() );
  274.     return is;
  275. }
  276.  
  277. ostream& operator << ( ostream& os, TodoList& tl )
  278. {
  279.     ContainerIterator& ci = tl.initIterator();
  280.     while( ci != 0 )
  281.         {
  282.         TodoEntry& ent = (TodoEntry&)(ci++);
  283.         if( ent != NOOBJECT )
  284.             os << ent;
  285.         }
  286.     if( os )
  287.         tl.dirty = FALSE;
  288.     delete &ci;
  289.     return os;
  290. }
  291.  
  292. //---------------------------------------------------------------------
  293. //
  294. //  member functions for class ListBox.
  295. //
  296. //---------------------------------------------------------------------
  297.  
  298. //---------------------------------------------------------------------
  299. //
  300. //  const ListBox& ListBox::operator = ( const TodoList& tdl );
  301. //
  302. //  copies the contents of a TodoList into a ListBox.
  303. //
  304. //---------------------------------------------------------------------
  305.  
  306. const ListBox& ListBox::operator = ( const TodoList& tdl )
  307. {
  308.     assert( hListBox != 0 );
  309.  
  310.     clear();
  311.  
  312.     ContainerIterator& ci = tdl.initIterator();
  313.     while( ci != 0 )
  314.     {
  315.     Object& cur = ci++;
  316.     if( cur != NOOBJECT )
  317.         {
  318.         char buf[100];      // write the entry into a string
  319.                 // and insert that string into
  320.                 // the list box
  321.  
  322.         ostrstream( buf, 100 ) << cur << ends;
  323.         SendMessage( hListBox, LB_ADDSTRING, NULL, (LONG)(LPSTR)buf );
  324.         }
  325.     }
  326.     select( 0 );
  327.  
  328.     return *this;
  329. }
  330.  
  331. void ListBox::insert( int i, const TodoEntry& tde )
  332. {
  333.     char temp[100];
  334.     ostrstream( temp, sizeof( temp ) ) << (Object&)tde << ends;
  335.  
  336.     SendMessage( hListBox, LB_INSERTSTRING, i, (LONG)(LPSTR)temp );
  337.     select( i );
  338. }
  339.  
  340. void ListBox::create( HWND owner, HWND hInst, const RECT &wrect )
  341. {
  342.     hListBox = CreateWindow( "ListBox", NULL,
  343.                  LBS_NOTIFY | WS_BORDER | WS_VSCROLL | LBS_USETABSTOPS | WS_CHILD | WS_VISIBLE,
  344.                  wrect.left,
  345.                  wrect.top,
  346.                  wrect.right - wrect.left,
  347.                  wrect.bottom - wrect.top,
  348.                 (HWND)owner,
  349.                 (HMENU)IDC_LISTBOX,
  350.                 (HINSTANCE)hInst,
  351.                  NULL
  352.                );
  353.  
  354.     int tabs[] = { 10, 100, 200 };
  355.     SendMessage( hListBox,
  356.                  LB_SETTABSTOPS,
  357.                  sizeof(tabs)/sizeof(*tabs),
  358.                  (LONG)(LPSTR)tabs
  359.                 );
  360.     focus();
  361. }
  362.  
  363. //---------------------------------------------------------------------
  364. //
  365. //  member functions for class TodoWindow.
  366. //
  367. //  these are mostly self-explanatory.
  368. //
  369. //---------------------------------------------------------------------
  370.  
  371. BOOL TodoWindow::registerClass()
  372. {
  373.     WNDCLASS wc;
  374.  
  375.     wc.style = 0;
  376.     wc.lpfnWndProc = Window::wndProc;
  377.     wc.cbClsExtra = 0;
  378.     wc.cbWndExtra = 0;
  379.     wc.hInstance =(HINSTANCE) hInst;
  380.     wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
  381.     wc.hCursor = LoadCursor( NULL, IDC_ARROW );
  382.     wc.hbrBackground =(HBRUSH) GetStockObject( WHITE_BRUSH );
  383.     wc.lpszMenuName = "TodoMenu";
  384.     wc.lpszClassName = "TodoClass";
  385.  
  386.     return RegisterClass( &wc );
  387. }
  388.  
  389. BOOL TodoWindow::createWindow()
  390. {
  391.     hWindow = CreateWindow(
  392.         "TodoClass",
  393.         "Todo List",
  394.         WS_OVERLAPPEDWINDOW,
  395.         CW_USEDEFAULT,
  396.         CW_USEDEFAULT,
  397.         CW_USEDEFAULT,
  398.         CW_USEDEFAULT,
  399.         NULL,
  400.         NULL,
  401.         (HINSTANCE)hInst,
  402.         NULL
  403.         );
  404.     if( hWnd() == 0 )
  405.         return FALSE;
  406.  
  407.     insert();                   // insert this window into the window list
  408.  
  409.     RECT wrect;
  410.     GetClientRect( (HWND)hWnd(), (LPRECT) &wrect);
  411.     listBox.create( (HWND)hWnd(), (HWND)hInst, wrect );
  412.                                 // build a list box in the client rectangle
  413.     listBox = tdl;              // copy the Todo list into the list box
  414.  
  415.     ShowWindow( (HWND)hWnd(), show );
  416.     UpdateWindow( (HWND)hWnd() );
  417.     return TRUE;
  418. }
  419.  
  420. void TodoWindow::aboutBox()
  421. {
  422.     AboutBox ab( (HWND)hWnd() );
  423.     ab.run();
  424. }
  425.  
  426. void TodoWindow::editBox()
  427. {
  428.     int cur = listBox.current();
  429.     if( cur == -1 )
  430.         {
  431.         newEntry();             // if there's nothing in the list,
  432.         return;                 // need to create an entry
  433.         }
  434.  
  435.     EditBox ed( (HWND)hWnd(), (TodoEntry&)tdl[ cur ] );
  436.     ed.run();
  437.  
  438.     listBox.replace( cur, (TodoEntry&)tdl[ cur ] );
  439. }
  440.  
  441. void TodoWindow::newEntry()
  442. {
  443.     TodoEntry *tde = new TodoEntry();
  444.     EditBox ed( (HWND)hWnd(), *tde );
  445.  
  446.     if( ed.run() != 0 )         // ed.run() returns 0 if terminated by
  447.         delete tde;             // OK, 1 if terminated by Cancel.
  448.     else
  449.         {
  450.         tdl.add( *tde );
  451.         listBox.insert( tdl.indexOf( *tde ), *tde );
  452.         }
  453. }
  454.  
  455. void TodoWindow::delEntry()
  456. {
  457.     int cur = listBox.current();
  458.     if( cur == -1 )             // if there's nothing in the list, there's
  459.         return;                 // nothing to delete.
  460.     tdl.destroy( cur );
  461.     listBox.remove( cur );
  462.     listBox.select( cur );
  463. }
  464.  
  465. void TodoWindow::moveListBox()
  466. {
  467.     RECT wrect;
  468.     GetClientRect( (HWND)hWnd(), (LPRECT) &wrect);
  469.  
  470.     listBox.move( wrect );
  471. }
  472.  
  473. //---------------------------------------------------------------------
  474. //
  475. //  void TodoWindow::checkSave();
  476. //
  477. //  checks whether the Todo list has been modified.  If it has, asks
  478. //  the user whether to save the list or not, and if it is to be saved,
  479. //  writes it to a file.
  480. //
  481. //---------------------------------------------------------------------
  482.  
  483. void TodoWindow::checkSave()
  484. {
  485.     if( tdl.modified() == TRUE && saveBox() == TRUE )
  486.         {
  487.         if( fileName == 0 )
  488.             if( getFileName( "Write to:", FALSE ) == FALSE )
  489.                 return;
  490.         writeFile();
  491.         }
  492. }
  493.  
  494. void TodoWindow::newList()
  495. {
  496.     checkSave();                // dump the current list
  497.     tdl.clear();
  498.     listBox.clear();
  499.     delete fileName;
  500.     fileName = 0;               // mark that there's no file
  501. }
  502.  
  503. void TodoWindow::openFile()
  504. {
  505.     checkSave();                // dump the current list
  506.     tdl.clear();
  507.     listBox.clear();
  508.     if( getFileName( "Read from:", TRUE ) == TRUE )
  509.         readFile();             // read new data from the specified file
  510. }
  511.  
  512. void TodoWindow::saveFile()
  513. {
  514.     if( fileName == 0 )
  515.         if( getFileName( "Write to:", FALSE ) == FALSE )
  516.             return;
  517.     writeFile();
  518. }
  519.  
  520. void TodoWindow::saveFileAs()
  521. {
  522.     if( getFileName( "Write to:", FALSE ) == TRUE )
  523.         writeFile();
  524. }
  525.  
  526. BOOL TodoWindow::getFileName( const char *caption, BOOL me )
  527. {
  528.     char curdir[ MAXDIR ];
  529.     getcwd( curdir, sizeof curdir );
  530.     FileBox fb( (HWND)hWnd(), caption, curdir, "*.tdo", me );
  531.  
  532.     if( fb.run() != 0 )
  533.         return FALSE;
  534.  
  535.     delete fileName;
  536.     fileName = strdup( fb.getPath() );
  537.     return TRUE;
  538. }
  539.  
  540. void TodoWindow::readFile()
  541. {
  542.     ifstream in( fileName );    // open the input file
  543.     assert( in );
  544.     in >> tdl;                  // read the Todo list
  545.     listBox = tdl;              // build the list box
  546. }
  547.  
  548. void TodoWindow::writeFile()
  549. {
  550.     ofstream out( fileName );
  551.     assert( out );
  552.     out << tdl;
  553. }
  554.  
  555. BOOL TodoWindow::saveBox()
  556. {
  557.     if( MessageBox( (HWND)hWnd(),
  558.             "Save Changes",
  559.             "Current List Modified",
  560.             MB_YESNO | MB_ICONQUESTION
  561.         ) == IDYES )
  562.         return TRUE;
  563.     else
  564.         return FALSE;
  565. }
  566.  
  567. //---------------------------------------------------------------------
  568. //
  569. //  BOOL TodoWindow::processCommand( WPARAM wParam, LPARAM lParam );
  570. //
  571. //  dispatches commands to the appropriate member functions.
  572. //
  573. //---------------------------------------------------------------------
  574.  
  575. BOOL TodoWindow::processCommand( WPARAM wParam, LPARAM lParam )
  576. {
  577.     switch( wParam )
  578.         {
  579.  
  580.         case IDM_QUIT:
  581.         SendMessage((HWND)hWnd(), WM_CLOSE, 0, 0L);
  582.             return TRUE;
  583.  
  584.         case IDM_NEW_LIST:
  585.             newList();
  586.             return TRUE;
  587.  
  588.         case IDM_OPEN:
  589.             openFile();
  590.             return TRUE;
  591.  
  592.         case IDM_SAVE:
  593.             saveFile();
  594.             return TRUE;
  595.  
  596.         case IDM_SAVEAS:
  597.             saveFileAs();
  598.             return TRUE;
  599.  
  600.         case IDM_EDIT:
  601.             editBox();
  602.             return TRUE;
  603.  
  604.         case IDM_NEW_ENTRY:
  605.             newEntry();
  606.             return TRUE;
  607.  
  608.         case IDM_DEL_ENTRY:
  609.             delEntry();
  610.             return TRUE;
  611.  
  612.         case IDM_ABOUT:
  613.             aboutBox();
  614.             return TRUE;
  615.  
  616.         case IDC_LISTBOX:
  617.             if( HIWORD( lParam ) == LBN_DBLCLK )
  618.                 {
  619.                 editBox();
  620.                 return TRUE;
  621.                 }
  622.             else
  623.                 return FALSE;
  624.         default:
  625.             return FALSE;
  626.         }
  627. }
  628.  
  629. //---------------------------------------------------------------------
  630. //
  631. //  LONG TodoWindow::dispatch( UINT msg, WPARAM wParam, LPARAM lParam );
  632. //
  633. //  dispatches messages to the appropriate member functions.
  634. //
  635. //---------------------------------------------------------------------
  636.  
  637. LONG TodoWindow::dispatch( UINT msg, WPARAM wParam, LPARAM lParam )
  638. {
  639.     switch( msg )
  640.         {
  641.         case WM_COMMAND:
  642.  
  643.             if( processCommand( wParam, lParam ) == TRUE )
  644.                 {
  645.                 listBox.focus();
  646.                 return 0;
  647.                 }
  648.             break;
  649.  
  650.         case WM_MOVE:
  651.         case WM_SIZE:
  652.  
  653.             moveListBox();
  654.             return 0;
  655.  
  656.         case WM_QUERYENDSESSION:
  657.             return TRUE;
  658.  
  659.         case WM_CLOSE:
  660.  
  661.             checkSave();
  662.         DestroyWindow( (HWND)hWnd() );
  663.             return 0;
  664.  
  665.         case WM_DESTROY:
  666.         case WM_QUIT:
  667.  
  668.             PostQuitMessage( 0 );
  669.             break;
  670.         }
  671.         return Window::dispatch( msg, wParam, lParam );
  672. }
  673.  
  674. //---------------------------------------------------------------------
  675. //
  676. //  int PASCAL WinMain( HINSTANCE, HINSTANCE, LPSTR, int );
  677. //
  678. //  the main entry point for the program.
  679. //
  680. //---------------------------------------------------------------------
  681.  
  682. int PASCAL WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  683. {
  684.     TodoWindow td;
  685.     td.create();
  686.     return td.run();
  687. }
  688.