wxWidgets/demos/poem/wxpoem.cpp

1063 lines
28 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// 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"
#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
wxIMPLEMENT_APP(MyApp);
MainWindow *TheMainWindow = NULL;
// Create the fonts
void MainWindow::CreateFonts()
{
m_normalFont = wxTheFontList->FindOrCreateFont(wxFontInfo(pointSize).Family(wxFONTFAMILY_SWISS));
m_boldFont = wxTheFontList->FindOrCreateFont(wxFontInfo(pointSize).Family(wxFONTFAMILY_SWISS).Bold());
m_italicFont = wxTheFontList->FindOrCreateFont(wxFontInfo(pointSize).Family(wxFONTFAMILY_SWISS).Italic());
}
wxBEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_CLOSE(MainWindow::OnCloseWindow)
EVT_CHAR(MainWindow::OnChar)
EVT_MENU(wxID_ANY, MainWindow::OnPopup)
wxEND_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(wxICON(wxpoem));
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;
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;
dc->SetBrush(*wxLIGHT_GREY_BRUSH);
dc->SetPen(*wxGREY_PEN);
dc->DrawRectangle(0, 0, width, height);
dc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
}
// 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)
{
int j;
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
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.
dc->SetPen(*wxWHITE_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)
{
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)
{
long position;
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
time_t current_time;
(void)time(&current_time);
srand((unsigned int)current_time);
// 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);
}
wxBEGIN_EVENT_TABLE(MyCanvas, wxWindow)
EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
EVT_CHAR(MyCanvas::OnChar)
EVT_PAINT(MyCanvas::OnPaint)
wxEND_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);
break;
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("rb"));
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;
}
buf[0] = 0;
if (data_filename)
wxSprintf(buf, wxT("%s.dat"), data_filename);
file = wxFopen(buf, wxT("rb"));
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];
buf[0] = 0;
if (data_filename)
wxSprintf(buf, wxT("%s.dat"), data_filename);
file = wxFopen(buf, wxT("rb"));
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);
buf[0] = 0;
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;
}
}