wxWidgets/demos/poem/wxpoem.cpp
Julian Smart 59db9cfaa7 Replaced Blit with DrawBitmap in wxPoem to make it run with wxX11
Added some XSyncs because it seems the only way to make
dialog sizing work


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14560 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2002-03-12 10:56:39 +00:00

1157 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
// RCS-ID: $Id$
// Copyright: (c) 1998 Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifdef __GNUG__
#pragma implementation "wxpoem.h"
#endif
// 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 "wx/help.h"
#include "wxpoem.h"
#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__)
#include "corner1.xpm"
#include "corner2.xpm"
#include "corner3.xpm"
#include "corner4.xpm"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef __WINDOWS__
#include <windows.h>
#ifdef DrawText
#undef DrawText
#endif
#endif
#define buf_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 char *poem_buffer; // Storage for each poem
static char line[150]; // Storage for a line
static char title[150]; // Remember the title
static char *search_string = NULL; // The search string
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 char *index_filename = NULL; // Index filename
static char *data_filename = NULL; // Data filename
static char 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
wxIcon *Corner1 = NULL;
wxIcon *Corner2 = NULL;
wxIcon *Corner3 = NULL;
wxIcon *Corner4 = NULL;
// Fonts
wxFont *NormalFont = NULL;
wxFont *BoldFont = NULL;
wxFont *ItalicFont = NULL;
// Pens
wxPen *GreyPen = NULL;
wxPen *DarkGreyPen = NULL;
wxPen *WhitePen = NULL;
// Backing bitmap
wxBitmap *backingBitmap = NULL;
void PoetryError(char *, char *caption="wxPoem Error");
void PoetryNotify(char *Msg, char *caption="wxPoem");
void TryLoadIndex();
bool LoadPoem(char *, long);
int GetIndex();
int LoadIndex(char *);
bool Compile(void);
void WritePreferences();
void ReadPreferences();
void FindMax(int *max_thing, int thing);
void CreateFonts();
#ifdef __WXMSW__
void CopyToClipboard(HWND, char *);
#endif
wxMenu *popupMenu = NULL;
#if wxUSE_HELP
wxHelpController *HelpController = NULL;
#endif // wxUSE_HELP
IMPLEMENT_APP(MyApp)
MainWindow *TheMainWindow = NULL;
// Create the fonts
void CreateFonts()
{
NormalFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxNORMAL, wxNORMAL);
BoldFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxNORMAL, wxBOLD);
ItalicFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxITALIC, wxNORMAL);
}
BEGIN_EVENT_TABLE(MainWindow, wxFrame)
EVT_CLOSE(MainWindow::OnCloseWindow)
EVT_CHAR(MainWindow::OnChar)
EVT_MENU(-1, 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)
{
}
MainWindow::~MainWindow()
{
// 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 popupMenu;
popupMenu = NULL;
}
// 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 x = 10;
int y = 0;
int j;
char *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(*GreyPen);
dc->DrawRectangle(0, 0, width, height);
dc->SetBackgroundMode(wxTRANSPARENT);
}
// See what ACTUAL char height is
dc->SetFont(* NormalFont);
long xx;
long yy;
dc->GetTextExtent("X", &xx, &yy);
char_height = (int)yy;
if (current_page == 0)
title[0] = 0;
else if (title[0] != 0)
{
dc->SetFont(* BoldFont);
dc->GetTextExtent(title, &xx, &yy);
FindMax(&curr_width, (int)xx);
if (DrawIt)
{
x = (width - xx)/2;
dc->SetFont(* BoldFont);
// Change text to BLACK!
dc->SetTextForeground(* wxBLACK);
dc->DrawText(title, x, y);
// Change text to WHITE!
dc->SetTextForeground(* wxWHITE);
dc->DrawText(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] = ch;
j ++;
i ++;
}
#if defined(__WXMSW__) || defined(__WXMAC__)
if (ch == 13)
#else
if (ch == 10)
#endif
{
ch = -1;
i ++;
#ifdef __WXMSW__
// 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(* BoldFont);
line_ptr = line+3;
strcpy(title, line_ptr);
strcat(title, " (cont'd)");
dc->GetTextExtent(line_ptr, &xx, &yy);
FindMax(&curr_width, (int)xx);
if (DrawIt)
{
x = (width - xx)/2;
dc->SetFont(* 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(* ItalicFont);
dc->GetTextExtent(line_ptr, &xx, &yy);
FindMax(&curr_width, (int)xx);
if (DrawIt)
{
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(* NormalFont);
dc->GetTextExtent(line, &xx, &yy);
FindMax(&curr_width, (int)xx);
if (DrawIt)
{
int x = (int)((width - xx)/2.0);
dc->SetFont(* NormalFont);
dc->SetTextForeground(* wxBLACK);
dc->DrawText(line, x, y);
}
}
}
y += char_height;
}
// Write (cont'd)
if (page_break)
{
char *cont = "(cont'd)";
dc->SetFont(* NormalFont);
dc->GetTextExtent(cont, &xx, &yy);
FindMax(&curr_width, (int)xx);
if (DrawIt)
{
int x = (int)((width - xx)/2.0);
dc->SetFont(* 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(*WhitePen);
else
dc->SetPen(*DarkGreyPen);
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(*DarkGreyPen);
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);
//#ifdef __WXMSW__
// Draw icons
dc->DrawIcon(* Corner1, 0, 0);
dc->DrawIcon(* Corner2, int(width-32), 0);
int y2 = height - 32;
int x2 = (width-32);
dc->DrawIcon(* Corner3, 0, y2);
dc->DrawIcon(* Corner4, x2, y2);
//#endif
}
}
// 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();
TheMainWindow->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 || !search_string)
{
wxString s = wxGetTextFromUser("Enter search string", "Search", (const char*) search_string);
if (s != "")
{
if (search_string) delete[] search_string;
search_string = copystring(s);
search_ok = TRUE;
} else search_ok = FALSE;
}
else
{
same_search = TRUE;
search_ok = TRUE;
}
if (search_string && search_ok)
{
position = DoSearch();
if (position > -1)
{
loaded_ok = LoadPoem(data_filename, position);
Resize();
}
else
{
last_poem_start = 0;
PoetryNotify("Search string not found.");
}
}
}
// Copy a string to the clipboard
#ifdef __WXMSW__
void CopyToClipboard(HWND handle, char *s)
{
int length = strlen(s);
HANDLE hGlobalMemory = GlobalAlloc(GHND, (DWORD) length + 1);
if (hGlobalMemory)
{
#ifdef __WINDOWS_386__
LPSTR lpGlobalMemory = MK_FP32(GlobalLock(hGlobalMemory));
#else
LPSTR lpGlobalMemory = (LPSTR)GlobalLock(hGlobalMemory);
#endif
int i, j = 0;
for (i = 0; i < length; i ++)
{
if (s[i] == '@')
{
i++;
switch (s[i])
{
case 'P':
break;
case 'T':
case 'A':
default:
i ++;
break;
}
}
else
{
lpGlobalMemory[j] = s[i];
j ++;
}
}
GlobalUnlock(hGlobalMemory);
OpenClipboard(handle);
EmptyClipboard();
SetClipboardData(CF_TEXT, hGlobalMemory);
CloseClipboard();
}
}
#endif
bool MyApp::OnInit()
{
poem_buffer = new char[buf_size];
GreyPen = new wxPen("LIGHT GREY", THICK_LINE_WIDTH, wxSOLID);
DarkGreyPen = new wxPen("GREY", THICK_LINE_WIDTH, wxSOLID);
WhitePen = new wxPen("WHITE", THICK_LINE_WIDTH, wxSOLID);
#if wxUSE_HELP
HelpController = new wxHelpController();
HelpController->Initialize("wxpoem");
#endif // wxUSE_HELP
CreateFonts();
ReadPreferences();
// 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, 500, "wxPoem", wxPoint(XPos, YPos), wxSize(100, 100), wxCAPTION|wxMINIMIZE_BOX|wxSYSTEM_MENU);
#ifdef wx_x
TheMainWindow->SetIcon(Icon("wxpoem"));
#endif
TheMainWindow->canvas = new MyCanvas(TheMainWindow, 501, wxDefaultPosition, wxDefaultSize);
popupMenu = new wxMenu;
popupMenu->Append(POEM_NEXT, "Next poem/page");
popupMenu->Append(POEM_PREVIOUS, "Previous page");
popupMenu->AppendSeparator();
popupMenu->Append(POEM_SEARCH, "Search");
popupMenu->Append(POEM_NEXT_MATCH, "Next match");
popupMenu->Append(POEM_COPY, "Copy to clipboard");
popupMenu->Append(POEM_MINIMIZE, "Minimize");
popupMenu->AppendSeparator();
popupMenu->Append(POEM_BIGGER_TEXT, "Bigger text");
popupMenu->Append(POEM_SMALLER_TEXT, "Smaller text");
popupMenu->AppendSeparator();
popupMenu->Append(POEM_ABOUT, "About wxPoem");
popupMenu->AppendSeparator();
popupMenu->Append(POEM_EXIT, "Exit");
if (argc > 1)
{
index_filename = copystring(argv[1]);
data_filename = copystring(argv[1]);
}
else
{
index_filename = DEFAULT_POETRY_IND;
data_filename = DEFAULT_POETRY_DAT;
}
TryLoadIndex();
#ifdef __WXMSW__
Corner1 = new wxIcon("icon_1");
Corner2 = new wxIcon("icon_2");
Corner3 = new wxIcon("icon_3");
Corner4 = new wxIcon("icon_4");
#endif
#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__)
Corner1 = new wxIcon( corner1_xpm );
Corner2 = new wxIcon( corner2_xpm );
Corner3 = new wxIcon( corner3_xpm );
Corner4 = new wxIcon( corner4_xpm );
#endif
TheMainWindow->GetIndexLoadPoem();
TheMainWindow->Resize();
TheMainWindow->Show(TRUE);
return TRUE;
}
int MyApp::OnExit()
{
if (backingBitmap)
delete backingBitmap;
#if wxUSE_HELP
delete HelpController;
#endif // wxUSE_HELP
delete GreyPen;
delete DarkGreyPen;
delete WhitePen;
delete Corner1;
delete Corner2;
delete Corner3;
delete Corner4;
// Causes crash since they're deleted by the global font list
#if 0
delete NormalFont;
delete BoldFont;
delete ItalicFont;
#endif
delete[] poem_buffer;
if (search_string)
delete[] search_string;
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, wxWindowID id, const wxPoint& pos, const wxSize& size):
wxWindow(frame, id, pos, size)
{
}
// 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(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())
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.KeyCode())
{
case 'n':
case 'N':
// Next match
TheMainWindow->Search(FALSE);
break;
case 's':
case 'S':
// New search
TheMainWindow->Search(TRUE);
break;
case WXK_SPACE:
// Another poem
TheMainWindow->NextPage();
break;
case 27:
TheMainWindow->Close(TRUE);
default:
break;
}
}
// Load index file
int LoadIndex(char *file_name)
{
long data;
FILE *index_file;
int i = 0;
char buf[100];
if (file_name)
sprintf(buf, "%s.idx", file_name);
if (! (file_name && (index_file = fopen(buf, "r"))))
return 0;
else
{
fscanf(index_file, "%ld", &nitems);
for (i = 0; i < nitems; i++)
{
fscanf(index_file, "%ld", &data);
poem_index[i] = data;
}
fclose(index_file);
return 1;
}
}
// Get index
int GetIndex()
{
int indexn = 0;
indexn = (int)(rand() % nitems);
if ((indexn < 0) || (indexn > nitems))
{ PoetryError("No such poem!");
return -1;
}
else
return indexn;
}
// Read preferences
void ReadPreferences()
{
wxGetResource("wxPoem", "FontSize", &pointSize);
wxGetResource("wxPoem", "X", &XPos);
wxGetResource("wxPoem", "Y", &YPos);
}
// Write preferences to disk
void WritePreferences()
{
#ifdef __WXMSW__
TheMainWindow->GetPosition(&XPos, &YPos);
wxWriteResource("wxPoem", "FontSize", pointSize);
wxWriteResource("wxPoem", "X", XPos);
wxWriteResource("wxPoem", "Y", YPos);
#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(char *file_name, long position)
{
int ch = 0;
int i = 0;
// int j = 0;
// int indexn = 0;
char buf[100];
long data;
FILE *data_file;
paging = FALSE;
current_page = 0;
if (file_name)
sprintf(buf, "%s.dat", file_name);
if (! (file_name && (data_file = fopen(buf, "r"))))
{
sprintf(error_buf, "Data file %s not found.", buf);
PoetryError(error_buf);
return FALSE;
}
else
{
if (position > -1)
data = position;
else
data = poem_index[index_ptr];
fseek(data_file, data, SEEK_SET);
ch = 0;
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] = ch;
i ++;
if (i == buf_size)
{
sprintf(error_buf, "%s", "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 (!search_string)
return FALSE;
FILE *file;
long i = 0;
int ch = 0;
char buf[100];
long find_start;
long previous_poem_start;
bool found = FALSE;
int search_length = strlen(search_string);
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)
sprintf(buf, "%s.dat", data_filename);
if (! (data_filename && (file = fopen(buf, "r"))))
{
sprintf(error_buf, "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 |= 0x0020; // Make lower case
// Only match if we're looking at a different poem
// (no point in displaying the same poem again)
if ((ch == search_string[i]) && (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;
}
else
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("Index file not found; will compile new one", "wxPoem");
index_ok = Compile();
}
}
// Error message
void PoetryError(char *msg, char *caption)
{
wxMessageBox(msg, caption, wxOK|wxICON_EXCLAMATION);
}
// Notification (change icon to something appropriate!)
void PoetryNotify(char *Msg, char *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;
long i = 0;
int j;
int ch = 0;
char buf[100];
if (data_filename)
sprintf(buf, "%s.dat", data_filename);
if (! (data_filename && (file = fopen(buf, "r"))))
{
sprintf(error_buf, "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
while (ch != EOF)
{
ch = getc(file);
i ++;
if (ch == '#')
{
ch = getc(file);
long data;
data = ftell(file);
poem_index[nitems] = data;
nitems ++;
}
}
fclose(file);
if (index_filename)
sprintf(buf, "%s.idx", index_filename);
if (! (data_filename && (file = fopen(buf, "w"))))
{
sprintf(error_buf, "Poetry index file %s cannot be created\n", buf);
PoetryError(error_buf);
return FALSE;
}
fprintf(file, "%ld\n\n", nitems);
for (j = 0; j < nitems; j++)
fprintf(file, "%ld\n", poem_index[j]);
fclose(file);
PoetryNotify("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;
#ifdef __WXMSW__
case POEM_COPY:
// Copy current poem to the clipboard
CopyToClipboard((HWND) TheMainWindow->GetHWND(), poem_buffer);
break;
#endif
case POEM_COMPILE:
// Compile index
Compile();
break;
case POEM_BIGGER_TEXT:
{
pointSize ++;
CreateFonts();
TheMainWindow->Resize();
break;
}
case POEM_SMALLER_TEXT:
{
if (pointSize > 2)
{
pointSize --;
CreateFonts();
TheMainWindow->Resize();
}
break;
}
case POEM_HELP_CONTENTS:
{
#if wxUSE_HELP
HelpController->LoadFile("wxpoem");
HelpController->DisplayContents();
#endif // wxUSE_HELP
break;
}
case POEM_ABOUT:
{
(void)wxMessageBox("wxPoem Version 1.1\nJulian Smart (c) 1995",
"About wxPoem", wxOK, TheMainWindow);
break;
}
case POEM_EXIT:
// Exit
TheMainWindow->Close(TRUE);
break;
default:
break;
}
}