home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c081_7 / 2.ddi / WEXAMPLE.ZIP / TODOLIST.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-13  |  16.9 KB  |  681 lines

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