wxWidgets/demos/poem/wxpoem.cpp
Maarten Bent 6315ae04fb Fix reading poems from file in wxPoem demo
When using ftell to get the position in the file, it should be opened in binary mode.
Regenerate the poem index file with the correct start positions.
Use the wxICON macro for creating the icon, so .ico is used on Windows.
2017-11-25 17:52:07 +01:00

1071 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"
#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
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;
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
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);
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;
}
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];
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);
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;
}
}