| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078 | 
							- /////////////////////////////////////////////////////////////////////////////
 
- // Name:        wxpoem.cpp
 
- // Purpose:     A small C++ program which displays a random poem on
 
- //              execution. It also allows search for poems containing a
 
- //              string.
 
- //              It requires winpoem.dat and creates winpoem.idx.
 
- //              Original version (WinPoem) written in 1994.
 
- //              This has not been rewritten in a long time so
 
- //              beware, inelegant code!
 
- // Author:      Julian Smart
 
- // Created:     12/12/98
 
- // Copyright:   (c) 1998 Julian Smart
 
- // Licence:     wxWindows licence
 
- /////////////////////////////////////////////////////////////////////////////
 
- // For compilers that support precompilation, includes "wx.h".
 
- #include "wx/wxprec.h"
 
- #ifdef __BORLANDC__
 
- #pragma hdrstop
 
- #endif
 
- #ifndef WX_PRECOMP
 
- #include "wx/wx.h"
 
- #endif
 
- #include "wxpoem.h"
 
- #include "corner1.xpm"
 
- #include "corner2.xpm"
 
- #include "corner3.xpm"
 
- #include "corner4.xpm"
 
- #include "wxpoem.xpm"
 
- #define         BUFFER_SIZE 10000
 
- #define         DEFAULT_POETRY_DAT "wxpoem"
 
- #define         DEFAULT_POETRY_IND "wxpoem"
 
- #define         DEFAULT_CHAR_HEIGHT 18
 
- #define         DEFAULT_FONT "Swiss"
 
- #define         DEFAULT_X_POS 0
 
- #define         DEFAULT_Y_POS 0
 
- #define         BORDER_SIZE 30
 
- #define         THIN_LINE_BORDER 10
 
- #define         THICK_LINE_BORDER 16
 
- #define         THICK_LINE_WIDTH 2
 
- #define         SHADOW_OFFSET 1
 
- #define         X_SIZE 30
 
- #define         Y_SIZE 20
 
- static wxChar   *poem_buffer;                   // Storage for each poem
 
- static wxChar   line[150];                      // Storage for a line
 
- static int      pages[30];                      // For multipage poems -
 
-                                                 // store the start of each page
 
- static long     last_poem_start = 0;            // Start of last found poem
 
- static long     last_find = -1;                 // Point in file of last found
 
-                                                 // search string
 
- static bool     search_ok = false;              // Search was successful
 
- static bool     same_search = false;            // Searching on same string
 
- static long     poem_index[600];                     // Index of poem starts
 
- static long     nitems = 0;                     // Number of poems
 
- static int      char_height = DEFAULT_CHAR_HEIGHT; // Actual height
 
- static int      index_ptr = -1;                 // Pointer into index
 
- static int      poem_height, poem_width;        // Size of poem
 
- static int      XPos;                           // Startup X position
 
- static int      YPos;                           // Startup Y position
 
- static int      pointSize = 12;                 // Font size
 
- static const wxChar   *index_filename = NULL;            // Index filename
 
- static const wxChar   *data_filename = NULL;             // Data filename
 
- static wxChar   error_buf[300];                 // Error message buffer
 
- static bool     loaded_ok = false;              // Poem loaded ok
 
- static bool     index_ok = false;               // Index loaded ok
 
- static bool     paging = false;                 // Are we paging?
 
- static int      current_page = 0;               // Currently viewed page
 
- // Backing bitmap
 
- wxBitmap        *backingBitmap = NULL;
 
- void            PoetryError(const wxChar *, const wxChar *caption=wxT("wxPoem Error"));
 
- void            PoetryNotify(const wxChar *Msg, const wxChar *caption=wxT("wxPoem"));
 
- void            TryLoadIndex();
 
- bool            LoadPoem(const wxChar *, long);
 
- int             GetIndex();
 
- int             LoadIndex(const wxChar *);
 
- bool            Compile(void);
 
- void            FindMax(int *max_thing, int thing);
 
- #if wxUSE_CLIPBOARD
 
-     #include "wx/dataobj.h"
 
-     #include "wx/clipbrd.h"
 
- #endif
 
- #ifdef __WXWINCE__
 
-     STDAPI_(__int64) CeGetRandomSeed();
 
- #endif
 
- IMPLEMENT_APP(MyApp)
 
- MainWindow *TheMainWindow = NULL;
 
- // Create the fonts
 
- void MainWindow::CreateFonts()
 
- {
 
-     m_normalFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxNORMAL, wxNORMAL);
 
-     m_boldFont =   wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxNORMAL, wxBOLD);
 
-     m_italicFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxITALIC, wxNORMAL);
 
- }
 
- BEGIN_EVENT_TABLE(MainWindow, wxFrame)
 
-     EVT_CLOSE(MainWindow::OnCloseWindow)
 
-     EVT_CHAR(MainWindow::OnChar)
 
-     EVT_MENU(wxID_ANY, MainWindow::OnPopup)
 
- END_EVENT_TABLE()
 
- MainWindow::MainWindow(wxFrame *frame, wxWindowID id, const wxString& title,
 
-      const wxPoint& pos, const wxSize& size, long style):
 
-      wxFrame(frame, id, title, pos, size, style)
 
- {
 
-     m_corners[0] = m_corners[1] = m_corners[2] = m_corners[3] = NULL;
 
-     ReadPreferences();
 
-     CreateFonts();
 
-     SetIcon(wxpoem_xpm);
 
-     m_corners[0] = new wxIcon( corner1_xpm );
 
-     m_corners[1] = new wxIcon( corner2_xpm );
 
-     m_corners[2] = new wxIcon( corner3_xpm );
 
-     m_corners[3] = new wxIcon( corner4_xpm );
 
- }
 
- MainWindow::~MainWindow()
 
- {
 
-     for (int i=0;i<4;i++)
 
-     {
 
-         if(m_corners[i])
 
-         {
 
-             delete m_corners[i];
 
-         }
 
-     }
 
- }
 
- // Read the poetry buffer, either for finding the size
 
- // or for writing to a bitmap (not to the window directly,
 
- // since that displays messily)
 
- // If DrawIt is true, we draw, otherwise we just determine the
 
- // size the window should be.
 
- void MainWindow::ScanBuffer(wxDC *dc, bool DrawIt, int *max_x, int *max_y)
 
- {
 
-     int i = pages[current_page];
 
-     int ch = -1;
 
-     int y = 0;
 
-     int j;
 
-     wxChar *line_ptr;
 
-     int curr_width = 0;
 
-     bool page_break = false;
 
-     int width = 0;
 
-     int height = 0;
 
-     if (DrawIt)
 
-     {
 
-         y = (*max_y - poem_height)/2;
 
-         width = *max_x;
 
-         height = *max_y;
 
-     }
 
-     if (DrawIt && wxColourDisplay())
 
-     {
 
-         dc->SetBrush(*wxLIGHT_GREY_BRUSH);
 
-         dc->SetPen(*wxGREY_PEN);
 
-         dc->DrawRectangle(0, 0, width, height);
 
-         dc->SetBackgroundMode(wxTRANSPARENT);
 
-     }
 
-     // See what ACTUAL char height is
 
-     if(m_normalFont)
 
-         dc->SetFont(*m_normalFont);
 
-     wxCoord xx;
 
-     wxCoord yy;
 
-     dc->GetTextExtent(wxT("X"), &xx, &yy);
 
-     char_height = (int)yy;
 
-     if (current_page == 0)
 
-     {
 
-         m_title = wxEmptyString;
 
-     }
 
-     else if (!m_title.empty())
 
-     {
 
-         dc->SetFont(* m_boldFont);
 
-         dc->GetTextExtent(m_title, &xx, &yy);
 
-         FindMax(&curr_width, (int)xx);
 
-         if (DrawIt)
 
-         {
 
-             int x = (width - xx)/2;
 
-             dc->SetFont(* m_boldFont);
 
-             // Change text to BLACK!
 
-             dc->SetTextForeground(* wxBLACK);
 
-             dc->DrawText(m_title, x, y);
 
-             // Change text to WHITE!
 
-             dc->SetTextForeground(* wxWHITE);
 
-             dc->DrawText(m_title, x-SHADOW_OFFSET, y-SHADOW_OFFSET);
 
-         }
 
-         y += char_height;
 
-         y += char_height;
 
-     }
 
-     while (ch != 0 && !page_break)
 
-     {
 
-         j = 0;
 
- #if defined(__WXMSW__) || defined(__WXMAC__)
 
-         while (((ch = poem_buffer[i]) != 13) && (ch != 0))
 
- #else
 
-         while (((ch = poem_buffer[i]) != 10) && (ch != 0))
 
- #endif
 
-         {
 
-             line[j] = (wxChar)ch;
 
-             j ++;
 
-             i ++;
 
-         }
 
- #if defined(__WXMSW__) || defined(__WXMAC__)
 
-         if (ch == 13)
 
- #else
 
-         if (ch == 10)
 
- #endif
 
-         {
 
-             ch = -1;
 
-             i ++;
 
- #if defined(__WXMSW__) || defined(__WXMAC__)
 
-             // Add another to skip the linefeed
 
-             i ++;
 
- #endif
 
-             // If a single newline on its own, put a space in
 
-             if (j == 0)
 
-             {
 
-                 line[j] = ' ';
 
-                 j ++;
 
-                 line[j] = 0;
 
-             }
 
-         }
 
-         if (j > 0)
 
-         {
 
-             line[j] = 0;
 
-             if (line[0] == '@')
 
-             {
 
-                 switch (line[1])
 
-                 {
 
-                     case 'P':
 
-                         paging = true;
 
-                         page_break = true;
 
-                         break;
 
-                     case 'T':
 
-                         dc->SetFont(* m_boldFont);
 
-                         line_ptr = line+3;
 
-                         m_title = line_ptr;
 
-                         m_title << wxT(" (cont'd)");
 
-                         dc->GetTextExtent(line_ptr, &xx, &yy);
 
-                         FindMax(&curr_width, (int)xx);
 
-                         if (DrawIt)
 
-                         {
 
-                             int x = (width - xx)/2;
 
-                             dc->SetFont(* m_boldFont);
 
-                             // Change text to BLACK!
 
-                             dc->SetTextForeground(* wxBLACK);
 
-                             dc->DrawText(line_ptr, x, y);
 
-                             // Change text to WHITE!
 
-                             dc->SetTextForeground(* wxWHITE);
 
-                             dc->DrawText(line_ptr, x-SHADOW_OFFSET, y-SHADOW_OFFSET);
 
-                             dc->SetTextForeground(* wxWHITE);
 
-                         }
 
-                         break;
 
-                     case 'A':
 
-                         line_ptr = line+3;
 
-                         dc->SetFont(* m_italicFont);
 
-                         dc->GetTextExtent(line_ptr, &xx, &yy);
 
-                         FindMax(&curr_width, (int)xx);
 
-                         if (DrawIt)
 
-                         {
 
-                             int x = (width - xx)/2;
 
-                             dc->SetTextForeground(* wxBLACK);
 
-                             dc->DrawText(line_ptr, x, y);
 
-                         }
 
-                         break;
 
-                     // Default: just ignore this line
 
-                     default:
 
-                     y -= char_height;
 
-                 }
 
-             }
 
-             else
 
-             {
 
-                 dc->SetFont(* m_normalFont);
 
-                 dc->GetTextExtent(line, &xx, &yy);
 
-                 FindMax(&curr_width, (int)xx);
 
-                 if (DrawIt)
 
-                 {
 
-                     int x = (int)((width - xx)/2.0);
 
-                     dc->SetFont(* m_normalFont);
 
-                     dc->SetTextForeground(* wxBLACK);
 
-                     dc->DrawText(line, x, y);
 
-                 }
 
-             }
 
-         }
 
-         y += char_height;
 
-     }
 
-     // Write (cont'd)
 
-     if (page_break)
 
-     {
 
-         const wxChar *cont = wxT("(cont'd)");
 
-         dc->SetFont(* m_normalFont);
 
-         dc->GetTextExtent(cont, &xx, &yy);
 
-         FindMax(&curr_width, (int)xx);
 
-         if (DrawIt)
 
-         {
 
-             int x = (int)((width - xx)/2.0);
 
-             dc->SetFont(* m_normalFont);
 
-             dc->SetTextForeground(* wxBLACK);
 
-             dc->DrawText(cont, x, y);
 
-         }
 
-         y += 2*char_height;
 
-     }
 
-     *max_x = (int)curr_width;
 
-     *max_y = (int)(y-char_height);
 
-     if (page_break)
 
-         pages[current_page+1] = i;
 
-     else
 
-         paging = false;
 
-     if (DrawIt)
 
-     {
 
-         // Draw dark grey thick border
 
-         if (wxColourDisplay())
 
-         {
 
-             dc->SetBrush(*wxGREY_BRUSH);
 
-             dc->SetPen(*wxGREY_PEN);
 
-             // Left side
 
-             dc->DrawRectangle(0, 0, THIN_LINE_BORDER, height);
 
-             // Top side
 
-             dc->DrawRectangle(THIN_LINE_BORDER, 0, width-THIN_LINE_BORDER, THIN_LINE_BORDER);
 
-             // Right side
 
-             dc->DrawRectangle(width-THIN_LINE_BORDER, THIN_LINE_BORDER, width, height-THIN_LINE_BORDER);
 
-             // Bottom side
 
-             dc->DrawRectangle(THIN_LINE_BORDER, height-THIN_LINE_BORDER, width-THIN_LINE_BORDER, height);
 
-         }
 
-         // Draw border
 
-         // Have grey background, plus 3-d border -
 
-         // One black rectangle.
 
-         // Inside this, left and top sides - dark grey. Bottom and right -
 
-         // white.
 
-         // Change pen to black
 
-         dc->SetPen(*wxBLACK_PEN);
 
-         dc->DrawLine(THIN_LINE_BORDER, THIN_LINE_BORDER, width-THIN_LINE_BORDER, THIN_LINE_BORDER);
 
-         dc->DrawLine(width-THIN_LINE_BORDER, THIN_LINE_BORDER, width-THIN_LINE_BORDER, height-THIN_LINE_BORDER);
 
-         dc->DrawLine(width-THIN_LINE_BORDER, height-THIN_LINE_BORDER, THIN_LINE_BORDER, height-THIN_LINE_BORDER);
 
-         dc->DrawLine(THIN_LINE_BORDER, height-THIN_LINE_BORDER, THIN_LINE_BORDER, THIN_LINE_BORDER);
 
-         // Right and bottom white lines - 'grey' (black!) if
 
-         // we're running on a mono display.
 
-         if (wxColourDisplay())
 
-             dc->SetPen(*wxWHITE_PEN);
 
-         else
 
-             dc->SetPen(*wxBLACK_PEN);
 
-         dc->DrawLine(width-THICK_LINE_BORDER, THICK_LINE_BORDER,
 
-                      width-THICK_LINE_BORDER, height-THICK_LINE_BORDER);
 
-         dc->DrawLine(width-THICK_LINE_BORDER, height-THICK_LINE_BORDER,
 
-                      THICK_LINE_BORDER, height-THICK_LINE_BORDER);
 
-         // Left and top grey lines
 
-         dc->SetPen(*wxBLACK_PEN);
 
-         dc->DrawLine(THICK_LINE_BORDER, height-THICK_LINE_BORDER,
 
-                      THICK_LINE_BORDER, THICK_LINE_BORDER);
 
-         dc->DrawLine(THICK_LINE_BORDER, THICK_LINE_BORDER,
 
-                      width-THICK_LINE_BORDER, THICK_LINE_BORDER);
 
-         // Draw icons
 
-         dc->DrawIcon(* m_corners[0], 0, 0);
 
-         dc->DrawIcon(* m_corners[1], int(width-32), 0);
 
-         int y2 = height - 32;
 
-         int x2 = (width-32);
 
-         dc->DrawIcon(* m_corners[2], 0, y2);
 
-         dc->DrawIcon(* m_corners[3], x2, y2);
 
-     }
 
- }
 
- // Get an index (randomly generated) and load the poem
 
- void MainWindow::GetIndexLoadPoem(void)
 
- {
 
-     if (index_ok)
 
-         index_ptr = GetIndex();
 
-     if (index_ptr > -1)
 
-         loaded_ok = LoadPoem(data_filename, -1);
 
- }
 
- // Find the size of the poem and resize the window accordingly
 
- void MainWindow::Resize(void)
 
- {
 
-     wxClientDC dc(canvas);
 
-     // Get the poem size
 
-     ScanBuffer(& dc, false, &poem_width, &poem_height);
 
-     int x = poem_width + (2*BORDER_SIZE);
 
-     int y = poem_height + (2*BORDER_SIZE);
 
-     SetClientSize(x, y);
 
-     // In case client size isn't what we set it to...
 
-     int xx, yy;
 
-     GetClientSize(&xx, &yy);
 
-     wxMemoryDC memDC;
 
-     if (backingBitmap) delete backingBitmap;
 
-     backingBitmap = new wxBitmap(x, yy);
 
-     memDC.SelectObject(* backingBitmap);
 
-     memDC.Clear();
 
-     ScanBuffer(&memDC, true, &xx, &yy);
 
- }
 
- // Which is more?
 
- void FindMax(int *max_thing, int thing)
 
- {
 
-     if (thing > *max_thing)
 
-         *max_thing = thing;
 
- }
 
- // Next page/poem
 
- void MainWindow::NextPage(void)
 
- {
 
-     if (paging)
 
-         current_page ++;
 
-     else
 
-     {
 
-         current_page = 0;
 
-         GetIndexLoadPoem();
 
-     }
 
-     Resize();
 
- }
 
- // Previous page
 
- void MainWindow::PreviousPage(void)
 
- {
 
-     if (current_page > 0)
 
-     {
 
-         current_page --;
 
-         Resize();
 
-     }
 
- }
 
- // Search for a string
 
- void MainWindow::Search(bool ask)
 
- {
 
-     long position;
 
-     if (ask || m_searchString.empty())
 
-     {
 
-         wxString s = wxGetTextFromUser( wxT("Enter search string"), wxT("Search"), m_searchString);
 
-         if (!s.empty())
 
-         {
 
-             s.MakeLower();
 
-             m_searchString = s;
 
-             search_ok = true;
 
-         }
 
-         else
 
-         {
 
-             search_ok = false;
 
-         }
 
-     }
 
-     else
 
-     {
 
-         same_search = true;
 
-         search_ok = true;
 
-     }
 
-     if (!m_searchString.empty() && search_ok)
 
-     {
 
-         position = DoSearch();
 
-         if (position > -1)
 
-         {
 
-             loaded_ok = LoadPoem(data_filename, position);
 
-             Resize();
 
-         }
 
-         else
 
-         {
 
-             last_poem_start = 0;
 
-             PoetryNotify(wxT("Search string not found."));
 
-         }
 
-     }
 
- }
 
- bool MyApp::OnInit()
 
- {
 
-     poem_buffer = new wxChar[BUFFER_SIZE];
 
-     // Seed the random number generator
 
- #ifdef __WXWINCE__
 
-     srand((unsigned) CeGetRandomSeed());
 
- #else
 
-     time_t current_time;
 
-     (void)time(¤t_time);
 
-     srand((unsigned int)current_time);
 
- #endif
 
- //    randomize();
 
-     pages[0] = 0;
 
-     TheMainWindow = new MainWindow(NULL,
 
-                                    wxID_ANY,
 
-                                    wxT("wxPoem"),
 
-                                    wxPoint(XPos, YPos),
 
-                                    wxDefaultSize,
 
-                                    wxCAPTION|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxCLOSE_BOX|wxFULL_REPAINT_ON_RESIZE
 
-                                    );
 
-     TheMainWindow->canvas = new MyCanvas(TheMainWindow);
 
-     if (argc > 1)
 
-     {
 
-         index_filename = wxStrcpy(new wxChar[wxStrlen(argv[1]) + 1], argv[1]);
 
-         data_filename = wxStrcpy(new wxChar[wxStrlen(argv[1]) + 1], argv[1]);
 
-     }
 
-     else
 
-     {
 
-         index_filename = wxT(DEFAULT_POETRY_IND);
 
-         data_filename = wxT(DEFAULT_POETRY_DAT);
 
-     }
 
-     TryLoadIndex();
 
-     TheMainWindow->GetIndexLoadPoem();
 
-     TheMainWindow->Resize();
 
-     TheMainWindow->Show(true);
 
-     return true;
 
- }
 
- int MyApp::OnExit()
 
- {
 
-     if (backingBitmap)
 
-         delete backingBitmap;
 
-     delete[] poem_buffer;
 
-     return 0;
 
- }
 
- void MainWindow::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
 
- {
 
-     WritePreferences();
 
-     this->Destroy();
 
- }
 
- void MainWindow::OnChar(wxKeyEvent& event)
 
- {
 
-     canvas->OnChar(event);
 
- }
 
- BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
 
-     EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
 
-     EVT_CHAR(MyCanvas::OnChar)
 
-     EVT_PAINT(MyCanvas::OnPaint)
 
- END_EVENT_TABLE()
 
- // Define a constructor for my canvas
 
- MyCanvas::MyCanvas(wxFrame *frame):
 
-           wxWindow(frame, wxID_ANY)
 
- {
 
-     m_popupMenu = new wxMenu;
 
-     m_popupMenu->Append(POEM_NEXT, wxT("Next poem/page"));
 
-     m_popupMenu->Append(POEM_PREVIOUS, wxT("Previous page"));
 
-     m_popupMenu->AppendSeparator();
 
-     m_popupMenu->Append(POEM_SEARCH, wxT("Search"));
 
-     m_popupMenu->Append(POEM_NEXT_MATCH, wxT("Next match"));
 
-     m_popupMenu->Append(POEM_COPY, wxT("Copy to clipboard"));
 
-     m_popupMenu->Append(POEM_MINIMIZE, wxT("Minimize"));
 
-     m_popupMenu->AppendSeparator();
 
-     m_popupMenu->Append(POEM_BIGGER_TEXT, wxT("Bigger text"));
 
-     m_popupMenu->Append(POEM_SMALLER_TEXT, wxT("Smaller text"));
 
-     m_popupMenu->AppendSeparator();
 
-     m_popupMenu->Append(POEM_ABOUT, wxT("About wxPoem"));
 
-     m_popupMenu->AppendSeparator();
 
-     m_popupMenu->Append(POEM_EXIT, wxT("Exit"));
 
- }
 
- MyCanvas::~MyCanvas()
 
- {
 
-     // Note: this must be done before the main window/canvas are destroyed
 
-     // or we get an error (no parent window for menu item button)
 
-     delete m_popupMenu;
 
-     m_popupMenu = NULL;
 
- }
 
- // Define the repainting behaviour
 
- void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
 
- {
 
-     wxPaintDC dc(this);
 
-     if (backingBitmap)
 
-     {
 
-         int xx, yy;
 
-         TheMainWindow->GetClientSize(&xx, &yy);
 
-         dc.DrawBitmap(* backingBitmap, 0, 0);
 
- #if 0
 
-         wxMemoryDC memDC;
 
-         memDC.SelectObject(* backingBitmap);
 
-         dc.Blit(0, 0, backingBitmap->GetWidth(), backingBitmap->GetHeight(), &memDC, 0, 0);
 
- #endif
 
-   }
 
- }
 
- void MyCanvas::OnMouseEvent(wxMouseEvent& event)
 
- {
 
-     static int startPosX, startPosY, startFrameX, startFrameY;
 
-     long x, y;
 
-     event.GetPosition(&x, &y);
 
-     if (event.RightDown())
 
-     {
 
-         // Versions from wxWin 1.67 are probably OK
 
-         PopupMenu(m_popupMenu, (int)x, (int)y );
 
-     }
 
-     else if (event.LeftDown())
 
-     {
 
-         this->CaptureMouse();
 
-         int x1 = (int)x;
 
-         int y1 = (int)y;
 
-         ClientToScreen(&x1, &y1);
 
-         startPosX = x1;
 
-         startPosY = y1;
 
-         GetParent()->GetPosition(&startFrameX, &startFrameY);
 
-     }
 
-     else if (event.LeftUp())
 
-     {
 
-         if (GetCapture() == this) this->ReleaseMouse();
 
-     }
 
-     else if (event.Dragging() && event.LeftIsDown())
 
-     {
 
-         int x1 = (int)x;
 
-         int y1 = (int)y;
 
-         ClientToScreen(&x1, &y1);
 
-         int dX = x1 - startPosX;
 
-         int dY = y1 - startPosY;
 
-         GetParent()->Move(startFrameX + dX, startFrameY + dY);
 
-     }
 
- }
 
- // Process characters
 
- void MyCanvas::OnChar(wxKeyEvent& event)
 
- {
 
-     switch (event.GetKeyCode())
 
-     {
 
-         case 'n':
 
-         case 'N':
 
-             // Next match
 
-             TheMainWindow->Search(false);
 
-             break;
 
-         case 's':
 
-         case 'S':
 
-             // New search
 
-             TheMainWindow->Search(true);
 
-             break;
 
-         case WXK_SPACE:
 
-         case WXK_RIGHT:
 
-         case WXK_DOWN:
 
-             // Another poem
 
-             TheMainWindow->NextPage();
 
-             break;
 
-         case WXK_ESCAPE:
 
-             TheMainWindow->Close(true);
 
-         default:
 
-             break;
 
-     }
 
- }
 
- // Load index file
 
- int LoadIndex(const wxChar *file_name)
 
- {
 
-     long data;
 
-     FILE *index_file;
 
-     wxChar buf[100];
 
-     if (file_name == NULL)
 
-         return 0;
 
-     wxSprintf(buf, wxT("%s.idx"), file_name);
 
-     index_file = wxFopen(buf, wxT("r"));
 
-     if (index_file == NULL)
 
-         return 0;
 
-     wxFscanf(index_file, wxT("%ld"), &nitems);
 
-     for (int i = 0; i < nitems; i++)
 
-     {
 
-         wxFscanf(index_file, wxT("%ld"), &data);
 
-         poem_index[i] = data;
 
-     }
 
-     fclose(index_file);
 
-     return 1;
 
- }
 
- // Get index
 
- int GetIndex()
 
- {
 
-     int indexn = (int)(rand() % nitems);
 
-     if ((indexn < 0) || (indexn > nitems))
 
-     { PoetryError(wxT("No such poem!"));
 
-       return -1;
 
-     }
 
-     else
 
-       return indexn;
 
- }
 
- // Read preferences
 
- void MainWindow::ReadPreferences()
 
- {
 
- /* TODO: convert this code to use wxConfig
 
- #if wxUSE_RESOURCES
 
-     wxGetResource(wxT("wxPoem"), wxT("FontSize"), &pointSize);
 
-     wxGetResource(wxT("wxPoem"), wxT("X"), &XPos);
 
-     wxGetResource(wxT("wxPoem"), wxT("Y"), &YPos);
 
- #endif
 
- */
 
- }
 
- // Write preferences to disk
 
- void MainWindow::WritePreferences()
 
- {
 
- #ifdef __WXMSW__
 
-     TheMainWindow->GetPosition(&XPos, &YPos);
 
- /* TODO: convert this code to use wxConfig
 
- #if wxUSE_RESOURCES
 
-     wxWriteResource(wxT("wxPoem"), wxT("FontSize"), pointSize);
 
-     wxWriteResource(wxT("wxPoem"), wxT("X"), XPos);
 
-     wxWriteResource(wxT("wxPoem"), wxT("Y"), YPos);
 
- #endif
 
- */
 
- #endif
 
- }
 
- // Load a poem from given file, at given point in file.
 
- // If position is > -1, use this for the position in the
 
- // file, otherwise use index[index_ptr] to find the correct position.
 
- bool LoadPoem(const wxChar *file_name, long position)
 
- {
 
- //    int j = 0;
 
- //    int indexn = 0;
 
-     wxChar buf[100];
 
-     long data;
 
-     FILE *data_file;
 
-     paging = false;
 
-     current_page = 0;
 
-     if (file_name == NULL)
 
-     {
 
-       wxSprintf(error_buf, wxT("Error in Poem loading."));
 
-       PoetryError(error_buf);
 
-       return false;
 
-     }
 
-     wxSprintf(buf, wxT("%s.dat"), file_name);
 
-     data_file = wxFopen(buf, wxT("r"));
 
-     if (data_file == NULL)
 
-     {
 
-       wxSprintf(error_buf, wxT("Data file %s not found."), buf);
 
-       PoetryError(error_buf);
 
-       return false;
 
-     }
 
-     if (position > -1)
 
-         data = position;
 
-     else
 
-         data = poem_index[index_ptr];
 
-     fseek(data_file, data, SEEK_SET);
 
-     int ch = 0;
 
-     int i = 0;
 
-     while ((ch != EOF) && (ch != '#'))
 
-     {
 
-         ch = getc(data_file);
 
-         // Add a linefeed so it will copy to the clipboard ok
 
-         if (ch == 10)
 
-         {
 
-             poem_buffer[i] = 13;
 
-             i++;
 
-         }
 
-         poem_buffer[i] = (wxChar)ch;
 
-         i ++;
 
-         if (i == BUFFER_SIZE)
 
-         {
 
-             wxSprintf(error_buf, wxT("%s"), wxT("Poetry buffer exceeded."));
 
-             PoetryError(error_buf);
 
-             return false;
 
-         }
 
-     }
 
-     fclose(data_file);
 
-     poem_buffer[i-1] = 0;
 
-     return true;
 
- }
 
- // Do the search
 
- long MainWindow::DoSearch(void)
 
- {
 
-     if (m_searchString.empty())
 
-         return false;
 
-     FILE *file;
 
-     size_t i = 0;
 
-     int ch = 0;
 
-     wxChar buf[100];
 
-     long find_start;
 
-     long previous_poem_start;
 
-     bool found = false;
 
-     size_t search_length = m_searchString.length();
 
-     if (same_search)
 
-     {
 
-         find_start = last_find + 1;
 
-         previous_poem_start = last_poem_start;
 
-     }
 
-     else
 
-     {
 
-         find_start = 0;
 
-         last_poem_start = 0;
 
-         previous_poem_start = -1;
 
-     }
 
-     if (data_filename)
 
-         wxSprintf(buf, wxT("%s.dat"), data_filename);
 
-     file = wxFopen(buf, wxT("r"));
 
-     if (! (data_filename && file))
 
-     {
 
-         wxSprintf(error_buf, wxT("Poetry data file %s not found\n"), buf);
 
-         PoetryError(error_buf);
 
-         return false;
 
-     }
 
-     fseek(file, find_start, SEEK_SET);
 
-     while ((ch != EOF) && !found)
 
-     {
 
-         ch = getc(file);
 
-         ch = wxTolower(ch);   // Make lower case
 
-         // Only match if we're looking at a different poem
 
-         // (no point in displaying the same poem again)
 
-         if ((m_searchString[i] == ch) && (last_poem_start != previous_poem_start))
 
-         {
 
-             if (i == 0)
 
-                 last_find = ftell(file);
 
-             if (i == search_length-1)
 
-                 found = true;
 
-             i ++;
 
-         }
 
-         else
 
-         {
 
-             i = 0;
 
-         }
 
-         if (ch == '#')
 
-         {
 
-             ch = getc(file);
 
-             last_poem_start = ftell(file);
 
-         }
 
-     }
 
-     fclose(file);
 
-     if (ch == EOF)
 
-     {
 
-         last_find = -1;
 
-     }
 
-     if (found)
 
-     {
 
-         return last_poem_start;
 
-     }
 
-     return -1;
 
- }
 
- // Set up poetry filenames, preferences, load the index
 
- // Load index (or compile it if none found)
 
- void TryLoadIndex()
 
- {
 
-     index_ok = (LoadIndex(index_filename) != 0);
 
-     if (!index_ok || (nitems == 0))
 
-     {
 
-         PoetryError(wxT("Index file not found; will compile new one"), wxT("wxPoem"));
 
-         index_ok = Compile();
 
-     }
 
- }
 
- // Error message
 
- void PoetryError(const wxChar *msg, const wxChar *caption)
 
- {
 
-     wxMessageBox(msg, caption, wxOK|wxICON_EXCLAMATION);
 
- }
 
- // Notification (change icon to something appropriate!)
 
- void PoetryNotify(const wxChar *Msg, const wxChar *caption)
 
- {
 
-     wxMessageBox(Msg, caption, wxOK | wxICON_INFORMATION);
 
- }
 
- // Build up and save an index into the poetry data file, for
 
- // rapid random access
 
- bool Compile(void)
 
- {
 
-     FILE *file;
 
-     int j;
 
-     int ch;
 
-     wxChar buf[100];
 
-     if (data_filename)
 
-         wxSprintf(buf, wxT("%s.dat"), data_filename);
 
-     file = wxFopen(buf, wxT("r"));
 
-     if (! (data_filename && file))
 
-     {
 
-         wxSprintf(error_buf, wxT("Poetry data file %s not found\n"), buf);
 
-         PoetryError(error_buf);
 
-         return false;
 
-     }
 
-     nitems = 0;
 
-     // Do first one (?)
 
-     poem_index[nitems] = 0;
 
-     nitems ++;
 
-     // Do rest
 
-     do {
 
-         ch = getc(file);
 
-         if (ch == '#')
 
-         {
 
-             ch = getc(file);
 
-             long data;
 
-             data = ftell(file);
 
-             poem_index[nitems] = data;
 
-             nitems ++;
 
-         }
 
-     } while (ch != EOF);
 
-     fclose(file);
 
-     if (index_filename)
 
-       wxSprintf(buf, wxT("%s.idx"), index_filename);
 
-     file = wxFopen(buf, wxT("w"));
 
-     if (! (data_filename && file))
 
-     {
 
-         wxSprintf(error_buf, wxT("Poetry index file %s cannot be created\n"), buf);
 
-         PoetryError(error_buf);
 
-         return false;
 
-     }
 
-     wxFprintf(file, wxT("%ld\n\n"), nitems);
 
-     for (j = 0; j < nitems; j++)
 
-         wxFprintf(file, wxT("%ld\n"), poem_index[j]);
 
-     fclose(file);
 
-     PoetryNotify(wxT("Poetry index compiled."));
 
-     return true;
 
- }
 
- void MainWindow::OnPopup(wxCommandEvent& event)
 
- {
 
-     switch (event.GetId())
 
-     {
 
-         case POEM_NEXT:
 
-             // Another poem/page
 
-             TheMainWindow->NextPage();
 
-             break;
 
-         case POEM_PREVIOUS:
 
-             // Previous page
 
-             TheMainWindow->PreviousPage();
 
-             break;
 
-         case POEM_SEARCH:
 
-             // Search - with dialog
 
-             TheMainWindow->Search(true);
 
-             break;
 
-         case POEM_NEXT_MATCH:
 
-             // Search - without dialog (next match)
 
-             TheMainWindow->Search(false);
 
-             break;
 
-         case POEM_MINIMIZE:
 
-             TheMainWindow->Iconize(true);
 
-             break;
 
- #if wxUSE_CLIPBOARD
 
-         case POEM_COPY:
 
-             wxTheClipboard->UsePrimarySelection();
 
-             if (wxTheClipboard->Open())
 
-             {
 
-                 static wxString s;
 
-                 s = poem_buffer;
 
-                 s.Replace( wxT("@P"),wxEmptyString);
 
-                 s.Replace( wxT("@A "),wxEmptyString);
 
-                 s.Replace( wxT("@A"),wxEmptyString);
 
-                 s.Replace( wxT("@T "),wxEmptyString);
 
-                 s.Replace( wxT("@T"),wxEmptyString);
 
-                 wxTextDataObject *data = new wxTextDataObject( s.c_str() );
 
-                 if (!wxTheClipboard->SetData( data ))
 
-                     wxMessageBox(wxT("Error while copying to the clipboard."));
 
-             }
 
-             else
 
-             {
 
-                 wxMessageBox(wxT("Error opening the clipboard."));
 
-             }
 
-             wxTheClipboard->Close();
 
-             break;
 
- #endif
 
-         case POEM_BIGGER_TEXT:
 
-             pointSize ++;
 
-             CreateFonts();
 
-             TheMainWindow->Resize();
 
-             break;
 
-         case POEM_SMALLER_TEXT:
 
-             if (pointSize > 2)
 
-             {
 
-                 pointSize --;
 
-                 CreateFonts();
 
-                 TheMainWindow->Resize();
 
-             }
 
-             break;
 
-         case POEM_ABOUT:
 
-             (void)wxMessageBox(wxT("wxPoem Version 1.1\nJulian Smart (c) 1995"),
 
-                                wxT("About wxPoem"), wxOK, TheMainWindow);
 
-             break;
 
-         case POEM_EXIT:
 
-             // Exit
 
-             TheMainWindow->Close(true);
 
-             break;
 
-         default:
 
-             break;
 
-     }
 
- }
 
 
  |