]>
git.saurik.com Git - wxWidgets.git/blob - demos/poem/wxpoem.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     A small C++ program which displays a random poem on 
   4 //              execution. It also allows search for poems containing a 
   6 //              It requires winpoem.dat and creates winpoem.idx. 
   7 //              Original version (WinPoem) written in 1994. 
   8 //              This has not been rewritten in a long time so 
   9 //              beware, inelegant code! 
  10 // Author:      Julian Smart 
  13 // Copyright:   (c) 1998 Julian Smart 
  14 // Licence:     wxWindows licence 
  15 ///////////////////////////////////////////////////////////////////////////// 
  17 // For compilers that support precompilation, includes "wx.h". 
  18 #include "wx/wxprec.h" 
  30 #include "corner1.xpm" 
  31 #include "corner2.xpm" 
  32 #include "corner3.xpm" 
  33 #include "corner4.xpm" 
  36 #define         buf_size 10000 
  37 #define         DEFAULT_POETRY_DAT "wxpoem" 
  38 #define         DEFAULT_POETRY_IND "wxpoem" 
  39 #define         DEFAULT_CHAR_HEIGHT 18 
  40 #define         DEFAULT_FONT "Swiss" 
  41 #define         DEFAULT_X_POS 0 
  42 #define         DEFAULT_Y_POS 0 
  43 #define         BORDER_SIZE 30 
  44 #define         THIN_LINE_BORDER 10 
  45 #define         THICK_LINE_BORDER 16 
  46 #define         THICK_LINE_WIDTH 2 
  47 #define         SHADOW_OFFSET 1 
  51 static wxChar   
*poem_buffer
;          // Storage for each poem 
  52 static wxChar   line
[150];                      // Storage for a line 
  53 static int      pages
[30];                      // For multipage poems - 
  54                                                 // store the start of each page 
  55 static long     last_poem_start 
= 0;            // Start of last found poem 
  56 static long     last_find 
= -1;                 // Point in file of last found 
  58 static bool     search_ok 
= false;              // Search was successful 
  59 static bool     same_search 
= false;            // Searching on same string 
  61 static long     poem_index
[600];                     // Index of poem starts 
  62 static long     nitems 
= 0;                     // Number of poems 
  63 static int      char_height 
= DEFAULT_CHAR_HEIGHT
; // Actual height 
  64 static int      index_ptr 
= -1;                 // Pointer into index 
  65 static int      poem_height
, poem_width
;        // Size of poem 
  66 static int      XPos
;                           // Startup X position 
  67 static int      YPos
;                           // Startup Y position 
  68 static int      pointSize 
= 12;                 // Font size 
  70 static wxChar   
*index_filename 
= NULL
;            // Index filename 
  71 static wxChar   
*data_filename 
= NULL
;             // Data filename 
  72 static wxChar   error_buf
[300];                 // Error message buffer 
  73 static bool     loaded_ok 
= false;              // Poem loaded ok 
  74 static bool     index_ok 
= false;               // Index loaded ok 
  76 static bool     paging 
= false;                 // Are we paging? 
  77 static int      current_page 
= 0;               // Currently viewed page 
  80 wxBitmap        
*backingBitmap 
= NULL
; 
  82 void            PoetryError(wxChar 
*, wxChar 
*caption
=_T("wxPoem Error")); 
  83 void            PoetryNotify(wxChar 
*Msg
, wxChar 
*caption
=_T("wxPoem")); 
  85 bool            LoadPoem(wxChar 
*, long); 
  87 int             LoadIndex(wxChar 
*); 
  89 void            FindMax(int *max_thing
, int thing
); 
  92     #include "wx/dataobj.h" 
  93     #include "wx/clipbrd.h" 
  97     STDAPI_(__int64
) CeGetRandomSeed(); 
 102 MainWindow 
*TheMainWindow 
= NULL
; 
 105 void MainWindow::CreateFonts() 
 107     m_normalFont 
= wxTheFontList
->FindOrCreateFont(pointSize
, wxSWISS
, wxNORMAL
, wxNORMAL
); 
 108     m_boldFont 
=   wxTheFontList
->FindOrCreateFont(pointSize
, wxSWISS
, wxNORMAL
, wxBOLD
); 
 109     m_italicFont 
= wxTheFontList
->FindOrCreateFont(pointSize
, wxSWISS
, wxITALIC
, wxNORMAL
); 
 112 BEGIN_EVENT_TABLE(MainWindow
, wxFrame
) 
 113     EVT_CLOSE(MainWindow::OnCloseWindow
) 
 114     EVT_CHAR(MainWindow::OnChar
) 
 115     EVT_MENU(wxID_ANY
, MainWindow::OnPopup
) 
 118 MainWindow::MainWindow(wxFrame 
*frame
, wxWindowID id
, const wxString
& title
, 
 119      const wxPoint
& pos
, const wxSize
& size
, long style
): 
 120      wxFrame(frame
, id
, title
, pos
, size
, style
) 
 122     m_corners
[0] = m_corners
[1] = m_corners
[2] = m_corners
[3] = NULL
; 
 129     m_corners
[0] = new wxIcon( corner1_xpm 
); 
 130     m_corners
[1] = new wxIcon( corner2_xpm 
); 
 131     m_corners
[2] = new wxIcon( corner3_xpm 
); 
 132     m_corners
[3] = new wxIcon( corner4_xpm 
); 
 135 MainWindow::~MainWindow() 
 137     for (int i
=0;i
<4;i
++) 
 146 // Read the poetry buffer, either for finding the size 
 147 // or for writing to a bitmap (not to the window directly, 
 148 // since that displays messily) 
 149 // If DrawIt is true, we draw, otherwise we just determine the 
 150 // size the window should be. 
 151 void MainWindow::ScanBuffer(wxDC 
*dc
, bool DrawIt
, int *max_x
, int *max_y
) 
 153     int i 
= pages
[current_page
]; 
 159     bool page_break 
= false; 
 166         y 
= (*max_y 
- poem_height
)/2; 
 171     if (DrawIt 
&& wxColourDisplay()) 
 173         dc
->SetBrush(*wxLIGHT_GREY_BRUSH
); 
 174         dc
->SetPen(*wxGREY_PEN
); 
 175         dc
->DrawRectangle(0, 0, width
, height
); 
 176         dc
->SetBackgroundMode(wxTRANSPARENT
); 
 179     // See what ACTUAL char height is 
 181         dc
->SetFont(*m_normalFont
); 
 184     dc
->GetTextExtent(_T("X"), &xx
, &yy
); 
 185     char_height 
= (int)yy
; 
 187     if (current_page 
== 0) 
 189         m_title 
= wxEmptyString
; 
 191     else if (!m_title
.empty()) 
 193         dc
->SetFont(* m_boldFont
); 
 194         dc
->GetTextExtent(m_title
, &xx
, &yy
); 
 195         FindMax(&curr_width
, (int)xx
); 
 199             int x 
= (width 
- xx
)/2; 
 200             dc
->SetFont(* m_boldFont
); 
 202             // Change text to BLACK! 
 203             dc
->SetTextForeground(* wxBLACK
); 
 204             dc
->DrawText(m_title
, x
, y
); 
 205             // Change text to WHITE! 
 206             dc
->SetTextForeground(* wxWHITE
); 
 207             dc
->DrawText(m_title
, x
-SHADOW_OFFSET
, y
-SHADOW_OFFSET
); 
 213     while (ch 
!= 0 && !page_break
) 
 216 #if defined(__WXMSW__) || defined(__WXMAC__) 
 217         while (((ch 
= poem_buffer
[i
]) != 13) && (ch 
!= 0)) 
 219         while (((ch 
= poem_buffer
[i
]) != 10) && (ch 
!= 0)) 
 222             line
[j
] = (wxChar
)ch
; 
 227 #if defined(__WXMSW__) || defined(__WXMAC__) 
 235 #if defined(__WXMSW__) || defined(__WXMAC__) 
 236             // Add another to skip the linefeed 
 239             // If a single newline on its own, put a space in 
 261                         dc
->SetFont(* m_boldFont
); 
 265                         m_title 
<< _T(" (cont'd)"); 
 267                         dc
->GetTextExtent(line_ptr
, &xx
, &yy
); 
 268                         FindMax(&curr_width
, (int)xx
); 
 272                             int x 
= (width 
- xx
)/2; 
 273                             dc
->SetFont(* m_boldFont
); 
 275                             // Change text to BLACK! 
 276                             dc
->SetTextForeground(* wxBLACK
); 
 277                             dc
->DrawText(line_ptr
, x
, y
); 
 279                             // Change text to WHITE! 
 280                             dc
->SetTextForeground(* wxWHITE
); 
 281                             dc
->DrawText(line_ptr
, x
-SHADOW_OFFSET
, y
-SHADOW_OFFSET
); 
 282                             dc
->SetTextForeground(* wxWHITE
); 
 288                         dc
->SetFont(* m_italicFont
); 
 290                         dc
->GetTextExtent(line_ptr
, &xx
, &yy
); 
 291                         FindMax(&curr_width
, (int)xx
); 
 295                             int x 
= (width 
- xx
)/2; 
 296                             dc
->SetTextForeground(* wxBLACK
); 
 297                             dc
->DrawText(line_ptr
, x
, y
); 
 301                     // Default: just ignore this line 
 308                 dc
->SetFont(* m_normalFont
); 
 310                 dc
->GetTextExtent(line
, &xx
, &yy
); 
 311                 FindMax(&curr_width
, (int)xx
); 
 315                     int x 
= (int)((width 
- xx
)/2.0); 
 316                     dc
->SetFont(* m_normalFont
); 
 317                     dc
->SetTextForeground(* wxBLACK
); 
 318                     dc
->DrawText(line
, x
, y
); 
 328         wxChar 
*cont 
= _T("(cont'd)"); 
 330         dc
->SetFont(* m_normalFont
); 
 332         dc
->GetTextExtent(cont
, &xx
, &yy
); 
 333         FindMax(&curr_width
, (int)xx
); 
 336             int x 
= (int)((width 
- xx
)/2.0); 
 337             dc
->SetFont(* m_normalFont
); 
 338             dc
->SetTextForeground(* wxBLACK
); 
 339             dc
->DrawText(cont
, x
, y
); 
 344     *max_x 
= (int)curr_width
; 
 345     *max_y 
= (int)(y
-char_height
); 
 348         pages
[current_page
+1] = i
; 
 354         // Draw dark grey thick border 
 355         if (wxColourDisplay()) 
 357             dc
->SetBrush(*wxGREY_BRUSH
); 
 358             dc
->SetPen(*wxGREY_PEN
); 
 361             dc
->DrawRectangle(0, 0, THIN_LINE_BORDER
, height
); 
 363             dc
->DrawRectangle(THIN_LINE_BORDER
, 0, width
-THIN_LINE_BORDER
, THIN_LINE_BORDER
); 
 365             dc
->DrawRectangle(width
-THIN_LINE_BORDER
, THIN_LINE_BORDER
, width
, height
-THIN_LINE_BORDER
); 
 367             dc
->DrawRectangle(THIN_LINE_BORDER
, height
-THIN_LINE_BORDER
, width
-THIN_LINE_BORDER
, height
); 
 370         // Have grey background, plus 3-d border - 
 371         // One black rectangle. 
 372         // Inside this, left and top sides - dark grey. Bottom and right - 
 375         // Change pen to black 
 376         dc
->SetPen(*wxBLACK_PEN
); 
 377         dc
->DrawLine(THIN_LINE_BORDER
, THIN_LINE_BORDER
, width
-THIN_LINE_BORDER
, THIN_LINE_BORDER
); 
 378         dc
->DrawLine(width
-THIN_LINE_BORDER
, THIN_LINE_BORDER
, width
-THIN_LINE_BORDER
, height
-THIN_LINE_BORDER
); 
 379         dc
->DrawLine(width
-THIN_LINE_BORDER
, height
-THIN_LINE_BORDER
, THIN_LINE_BORDER
, height
-THIN_LINE_BORDER
); 
 380         dc
->DrawLine(THIN_LINE_BORDER
, height
-THIN_LINE_BORDER
, THIN_LINE_BORDER
, THIN_LINE_BORDER
); 
 382         // Right and bottom white lines - 'grey' (black!) if 
 383         // we're running on a mono display. 
 384         if (wxColourDisplay()) 
 385             dc
->SetPen(*wxWHITE_PEN
); 
 387             dc
->SetPen(*wxBLACK_PEN
); 
 389         dc
->DrawLine(width
-THICK_LINE_BORDER
, THICK_LINE_BORDER
, 
 390                      width
-THICK_LINE_BORDER
, height
-THICK_LINE_BORDER
); 
 391         dc
->DrawLine(width
-THICK_LINE_BORDER
, height
-THICK_LINE_BORDER
, 
 392                      THICK_LINE_BORDER
, height
-THICK_LINE_BORDER
); 
 394         // Left and top grey lines 
 395         dc
->SetPen(*wxBLACK_PEN
); 
 396         dc
->DrawLine(THICK_LINE_BORDER
, height
-THICK_LINE_BORDER
, 
 397                      THICK_LINE_BORDER
, THICK_LINE_BORDER
); 
 398         dc
->DrawLine(THICK_LINE_BORDER
, THICK_LINE_BORDER
, 
 399                      width
-THICK_LINE_BORDER
, THICK_LINE_BORDER
); 
 402         dc
->DrawIcon(* m_corners
[0], 0, 0); 
 403         dc
->DrawIcon(* m_corners
[1], int(width
-32), 0); 
 405         int y2 
= height 
- 32; 
 407         dc
->DrawIcon(* m_corners
[2], 0, y2
); 
 408         dc
->DrawIcon(* m_corners
[3], x2
, y2
); 
 412 // Get an index (randomly generated) and load the poem 
 413 void MainWindow::GetIndexLoadPoem(void) 
 416         index_ptr 
= GetIndex(); 
 419         loaded_ok 
= LoadPoem(data_filename
, -1); 
 422 // Find the size of the poem and resize the window accordingly 
 423 void MainWindow::Resize(void) 
 425     wxClientDC 
dc(canvas
); 
 428     ScanBuffer(& dc
, false, &poem_width
, &poem_height
); 
 429     int x 
= poem_width 
+ (2*BORDER_SIZE
); 
 430     int y 
= poem_height 
+ (2*BORDER_SIZE
); 
 434     // In case client size isn't what we set it to... 
 436     GetClientSize(&xx
, &yy
); 
 439     if (backingBitmap
) delete backingBitmap
; 
 440     backingBitmap 
= new wxBitmap(x
, yy
); 
 441     memDC
.SelectObject(* backingBitmap
); 
 444     ScanBuffer(&memDC
, true, &xx
, &yy
); 
 448 void FindMax(int *max_thing
, int thing
) 
 450     if (thing 
> *max_thing
) 
 455 void MainWindow::NextPage(void) 
 468 void MainWindow::PreviousPage(void) 
 470     if (current_page 
> 0) 
 477 // Search for a string 
 478 void MainWindow::Search(bool ask
) 
 482     if (ask 
|| m_searchString
.empty()) 
 484         wxString s 
= wxGetTextFromUser( _T("Enter search string"), _T("Search"), m_searchString
); 
 502     if (!m_searchString
.empty() && search_ok
) 
 504         position 
= DoSearch(); 
 507             loaded_ok 
= LoadPoem(data_filename
, position
); 
 513             PoetryNotify(_T("Search string not found.")); 
 520     poem_buffer 
= new wxChar
[buf_size
]; 
 522     // Seed the random number generator 
 524     srand((unsigned) CeGetRandomSeed()); 
 528     (void)time(¤t_time
); 
 529     srand((unsigned int)current_time
); 
 535     TheMainWindow 
= new MainWindow(NULL
, 
 540                                    wxCAPTION
|wxMINIMIZE_BOX
|wxSYSTEM_MENU
|wxCLOSE_BOX
|wxFULL_REPAINT_ON_RESIZE
 
 543     TheMainWindow
->canvas 
= new MyCanvas(TheMainWindow
); 
 547         index_filename 
= wxStrcpy(new wxChar
[wxStrlen(argv
[1]) + 1], argv
[1]); 
 548         data_filename 
= wxStrcpy(new wxChar
[wxStrlen(argv
[1]) + 1], argv
[1]); 
 552         index_filename 
= _T(DEFAULT_POETRY_IND
); 
 553         data_filename 
= _T(DEFAULT_POETRY_DAT
); 
 557     TheMainWindow
->GetIndexLoadPoem(); 
 558     TheMainWindow
->Resize(); 
 559     TheMainWindow
->Show(true); 
 567         delete backingBitmap
; 
 569     delete[] poem_buffer
; 
 574 void MainWindow::OnCloseWindow(wxCloseEvent
& WXUNUSED(event
)) 
 580 void MainWindow::OnChar(wxKeyEvent
& event
) 
 582     canvas
->OnChar(event
); 
 585 BEGIN_EVENT_TABLE(MyCanvas
, wxWindow
) 
 586     EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent
) 
 587     EVT_CHAR(MyCanvas::OnChar
) 
 588     EVT_PAINT(MyCanvas::OnPaint
) 
 591 // Define a constructor for my canvas 
 592 MyCanvas::MyCanvas(wxFrame 
*frame
): 
 593           wxWindow(frame
, wxID_ANY
) 
 595     m_popupMenu 
= new wxMenu
; 
 596     m_popupMenu
->Append(POEM_NEXT
, _T("Next poem/page")); 
 597     m_popupMenu
->Append(POEM_PREVIOUS
, _T("Previous page")); 
 598     m_popupMenu
->AppendSeparator(); 
 599     m_popupMenu
->Append(POEM_SEARCH
, _T("Search")); 
 600     m_popupMenu
->Append(POEM_NEXT_MATCH
, _T("Next match")); 
 601     m_popupMenu
->Append(POEM_COPY
, _T("Copy to clipboard")); 
 602     m_popupMenu
->Append(POEM_MINIMIZE
, _T("Minimize")); 
 603     m_popupMenu
->AppendSeparator(); 
 604     m_popupMenu
->Append(POEM_BIGGER_TEXT
, _T("Bigger text")); 
 605     m_popupMenu
->Append(POEM_SMALLER_TEXT
, _T("Smaller text")); 
 606     m_popupMenu
->AppendSeparator(); 
 607     m_popupMenu
->Append(POEM_ABOUT
, _T("About wxPoem")); 
 608     m_popupMenu
->AppendSeparator(); 
 609     m_popupMenu
->Append(POEM_EXIT
, _T("Exit")); 
 612 MyCanvas::~MyCanvas() 
 614     // Note: this must be done before the main window/canvas are destroyed 
 615     // or we get an error (no parent window for menu item button) 
 620 // Define the repainting behaviour 
 621 void MyCanvas::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 628         TheMainWindow
->GetClientSize(&xx
, &yy
); 
 630         dc
.DrawBitmap(* backingBitmap
, 0, 0); 
 633         memDC
.SelectObject(* backingBitmap
); 
 634         dc
.Blit(0, 0, backingBitmap
->GetWidth(), backingBitmap
->GetHeight(), &memDC
, 0, 0); 
 639 void MyCanvas::OnMouseEvent(wxMouseEvent
& event
) 
 641     static int startPosX
, startPosY
, startFrameX
, startFrameY
; 
 644     event
.GetPosition(&x
, &y
); 
 646     if (event
.RightDown()) 
 648         // Versions from wxWin 1.67 are probably OK 
 649         PopupMenu(m_popupMenu
, (int)x
, (int)y 
); 
 651     else if (event
.LeftDown()) 
 653         this->CaptureMouse(); 
 656         ClientToScreen(&x1
, &y1
); 
 659         GetParent()->GetPosition(&startFrameX
, &startFrameY
); 
 661     else if (event
.LeftUp()) 
 663         if (GetCapture() == this) this->ReleaseMouse(); 
 665     else if (event
.Dragging() && event
.LeftIsDown()) 
 669         ClientToScreen(&x1
, &y1
); 
 671         int dX 
= x1 
- startPosX
; 
 672         int dY 
= y1 
- startPosY
; 
 673         GetParent()->Move(startFrameX 
+ dX
, startFrameY 
+ dY
); 
 677 // Process characters 
 678 void MyCanvas::OnChar(wxKeyEvent
& event
) 
 680     switch (event
.GetKeyCode()) 
 685             TheMainWindow
->Search(false); 
 691             TheMainWindow
->Search(true); 
 698             TheMainWindow
->NextPage(); 
 702             TheMainWindow
->Close(true); 
 709 int LoadIndex(wxChar 
*file_name
) 
 716     if (file_name 
== NULL
) 
 719     wxSprintf(buf
, _T("%s.idx"), file_name
); 
 721     index_file 
= wxFopen(buf
, _T("r")); 
 722     if (index_file 
== NULL
) 
 725     wxFscanf(index_file
, _T("%ld"), &nitems
); 
 727     for (int i 
= 0; i 
< nitems
; i
++) 
 729         wxFscanf(index_file
, _T("%ld"), &data
); 
 730         poem_index
[i
] = data
; 
 741     int indexn 
= (int)(rand() % nitems
); 
 743     if ((indexn 
< 0) || (indexn 
> nitems
)) 
 744     { PoetryError(_T("No such poem!")); 
 752 void MainWindow::ReadPreferences() 
 755     wxGetResource(_T("wxPoem"), _T("FontSize"), &pointSize
); 
 756     wxGetResource(_T("wxPoem"), _T("X"), &XPos
); 
 757     wxGetResource(_T("wxPoem"), _T("Y"), &YPos
); 
 761 // Write preferences to disk 
 762 void MainWindow::WritePreferences() 
 765     TheMainWindow
->GetPosition(&XPos
, &YPos
); 
 767     wxWriteResource(_T("wxPoem"), _T("FontSize"), pointSize
); 
 768     wxWriteResource(_T("wxPoem"), _T("X"), XPos
); 
 769     wxWriteResource(_T("wxPoem"), _T("Y"), YPos
); 
 774 // Load a poem from given file, at given point in file. 
 775 // If position is > -1, use this for the position in the 
 776 // file, otherwise use index[index_ptr] to find the correct position. 
 777 bool LoadPoem(wxChar 
*file_name
, long position
) 
 788     if (file_name 
== NULL
) 
 790       wxSprintf(error_buf
, _T("Error in Poem loading.")); 
 791       PoetryError(error_buf
); 
 795     wxSprintf(buf
, _T("%s.dat"), file_name
); 
 796     data_file 
= wxFopen(buf
, _T("r")); 
 798     if (data_file 
== NULL
) 
 800       wxSprintf(error_buf
, _T("Data file %s not found."), buf
); 
 801       PoetryError(error_buf
); 
 808         data 
= poem_index
[index_ptr
]; 
 810     fseek(data_file
, data
, SEEK_SET
); 
 814     while ((ch 
!= EOF
) && (ch 
!= '#')) 
 816         ch 
= getc(data_file
); 
 817         // Add a linefeed so it will copy to the clipboard ok 
 824         poem_buffer
[i
] = (wxChar
)ch
; 
 829             wxSprintf(error_buf
, _T("%s"), _T("Poetry buffer exceeded.")); 
 830             PoetryError(error_buf
); 
 835     poem_buffer
[i
-1] = 0; 
 840 long MainWindow::DoSearch(void) 
 842     if (m_searchString
.empty()) 
 850     long previous_poem_start
; 
 853     size_t search_length 
= m_searchString
.length(); 
 857         find_start 
= last_find 
+ 1; 
 858         previous_poem_start 
= last_poem_start
; 
 864         previous_poem_start 
= -1; 
 868         wxSprintf(buf
, _T("%s.dat"), data_filename
); 
 870     file 
= wxFopen(buf
, _T("r")); 
 871     if (! (data_filename 
&& file
)) 
 873         wxSprintf(error_buf
, _T("Poetry data file %s not found\n"), buf
); 
 874         PoetryError(error_buf
); 
 878     fseek(file
, find_start
, SEEK_SET
); 
 880     while ((ch 
!= EOF
) && !found
) 
 883         ch 
= wxTolower(ch
);   // Make lower case 
 885         // Only match if we're looking at a different poem 
 886         // (no point in displaying the same poem again) 
 887         if ((ch 
== m_searchString
[i
]) && (last_poem_start 
!= previous_poem_start
)) 
 890                 last_find 
= ftell(file
); 
 891             if (i 
== search_length
-1) 
 903             last_poem_start 
= ftell(file
); 
 914         return last_poem_start
; 
 920 // Set up poetry filenames, preferences, load the index 
 921 // Load index (or compile it if none found) 
 924     index_ok 
= (LoadIndex(index_filename
) != 0); 
 925     if (!index_ok 
|| (nitems 
== 0)) 
 927         PoetryError(_T("Index file not found; will compile new one"), _T("wxPoem")); 
 928         index_ok 
= Compile(); 
 933 void PoetryError(wxChar 
*msg
, wxChar 
*caption
) 
 935     wxMessageBox(msg
, caption
, wxOK
|wxICON_EXCLAMATION
); 
 938 // Notification (change icon to something appropriate!) 
 939 void PoetryNotify(wxChar 
*Msg
, wxChar 
*caption
) 
 941     wxMessageBox(Msg
, caption
, wxOK 
| wxICON_INFORMATION
); 
 944 // Build up and save an index into the poetry data file, for 
 945 // rapid random access 
 954         wxSprintf(buf
, _T("%s.dat"), data_filename
); 
 956     file 
= wxFopen(buf
, _T("r")); 
 957     if (! (data_filename 
&& file
)) 
 959         wxSprintf(error_buf
, _T("Poetry data file %s not found\n"), buf
); 
 960         PoetryError(error_buf
); 
 967     poem_index
[nitems
] = 0; 
 979             poem_index
[nitems
] = data
; 
 986       wxSprintf(buf
, _T("%s.idx"), index_filename
); 
 988     file 
= wxFopen(buf
, _T("w")); 
 989     if (! (data_filename 
&& file
)) 
 991         wxSprintf(error_buf
, _T("Poetry index file %s cannot be created\n"), buf
); 
 992         PoetryError(error_buf
); 
 996     wxFprintf(file
, _T("%ld\n\n"), nitems
); 
 997     for (j 
= 0; j 
< nitems
; j
++) 
 998         wxFprintf(file
, _T("%ld\n"), poem_index
[j
]); 
1001     PoetryNotify(_T("Poetry index compiled.")); 
1005 void MainWindow::OnPopup(wxCommandEvent
& event
) 
1007     switch (event
.GetId()) 
1010             // Another poem/page 
1011             TheMainWindow
->NextPage(); 
1015             TheMainWindow
->PreviousPage(); 
1018             // Search - with dialog 
1019             TheMainWindow
->Search(true); 
1021         case POEM_NEXT_MATCH
: 
1022             // Search - without dialog (next match) 
1023             TheMainWindow
->Search(false); 
1026             TheMainWindow
->Iconize(true); 
1030             wxTheClipboard
->UsePrimarySelection(); 
1031             if (wxTheClipboard
->Open()) 
1035                 s
.Replace( _T("@P"),wxEmptyString
); 
1036                 s
.Replace( _T("@A "),wxEmptyString
); 
1037                 s
.Replace( _T("@A"),wxEmptyString
); 
1038                 s
.Replace( _T("@T "),wxEmptyString
); 
1039                 s
.Replace( _T("@T"),wxEmptyString
); 
1040                 wxTextDataObject 
*data 
= new wxTextDataObject( s
.c_str() ); 
1041                 if (!wxTheClipboard
->SetData( data 
)) 
1042                     wxMessageBox(_T("Error while copying to the clipboard.")); 
1046                 wxMessageBox(_T("Error opening the clipboard.")); 
1048             wxTheClipboard
->Close(); 
1051         case POEM_BIGGER_TEXT
: 
1054             TheMainWindow
->Resize(); 
1056         case POEM_SMALLER_TEXT
: 
1061                 TheMainWindow
->Resize(); 
1065             (void)wxMessageBox(_T("wxPoem Version 1.1\nJulian Smart (c) 1995"), 
1066                                _T("About wxPoem"), wxOK
, TheMainWindow
); 
1070             TheMainWindow
->Close(true);