]> git.saurik.com Git - wxWidgets.git/blame - demos/poem/wxpoem.cpp
Fix compilation error due to recent typedef changes
[wxWidgets.git] / demos / poem / wxpoem.cpp
CommitLineData
3013b6f4
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: wxpoem.cpp
3// Purpose: A small C++ program which displays a random poem on
4// execution. It also allows search for poems containing a
5// string.
6// It requires winpoem.dat and creates winpoem.idx.
7// Original version (WinPoem) written in 1994.
8// This has not been rewritten in a long time so
9// beware, inelegant code!
10// Author: Julian Smart
11// Created: 12/12/98
12// RCS-ID: $Id$
13// Copyright: (c) 1998 Julian Smart
14// Licence: wxWindows licence
15/////////////////////////////////////////////////////////////////////////////
16
17#ifdef __GNUG__
18#pragma implementation "wxpoem.h"
19#endif
20
21// For compilers that support precompilation, includes "wx.h".
22#include "wx/wxprec.h"
23
24#ifdef __BORLANDC__
25#pragma hdrstop
26#endif
27
28#ifndef WX_PRECOMP
88ac883a 29#include "wx/wx.h"
3013b6f4
JS
30#endif
31
3013b6f4
JS
32#include "wxpoem.h"
33
7d92395d 34#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXX11__)
bbf73190
RR
35#include "corner1.xpm"
36#include "corner2.xpm"
37#include "corner3.xpm"
38#include "corner4.xpm"
39#endif
40
3013b6f4
JS
41#define buf_size 10000
42#define DEFAULT_POETRY_DAT "wxpoem"
43#define DEFAULT_POETRY_IND "wxpoem"
44#define DEFAULT_CHAR_HEIGHT 18
45#define DEFAULT_FONT "Swiss"
46#define DEFAULT_X_POS 0
47#define DEFAULT_Y_POS 0
48#define BORDER_SIZE 30
49#define THIN_LINE_BORDER 10
50#define THICK_LINE_BORDER 16
51#define THICK_LINE_WIDTH 2
52#define SHADOW_OFFSET 1
53#define X_SIZE 30
54#define Y_SIZE 20
55
6bb934d6
JS
56static wxChar *poem_buffer; // Storage for each poem
57static wxChar line[150]; // Storage for a line
58static wxChar title[150]; // Remember the title
59static wxChar *search_string = NULL; // The search string
3013b6f4
JS
60static int pages[30]; // For multipage poems -
61 // store the start of each page
62static long last_poem_start = 0; // Start of last found poem
63static long last_find = -1; // Point in file of last found
64 // search string
17d31882
DS
65static bool search_ok = false; // Search was successful
66static bool same_search = false; // Searching on same string
3013b6f4
JS
67
68static long poem_index[600]; // Index of poem starts
69static long nitems = 0; // Number of poems
3013b6f4
JS
70static int char_height = DEFAULT_CHAR_HEIGHT; // Actual height
71static int index_ptr = -1; // Pointer into index
72static int poem_height, poem_width; // Size of poem
73static int XPos; // Startup X position
74static int YPos; // Startup Y position
75static int pointSize = 12; // Font size
76
6bb934d6
JS
77static wxChar *index_filename = NULL; // Index filename
78static wxChar *data_filename = NULL; // Data filename
79static wxChar error_buf[300]; // Error message buffer
17d31882
DS
80static bool loaded_ok = false; // Poem loaded ok
81static bool index_ok = false; // Index loaded ok
3013b6f4 82
17d31882 83static bool paging = false; // Are we paging?
3013b6f4
JS
84static int current_page = 0; // Currently viewed page
85
86wxIcon *Corner1 = NULL;
87wxIcon *Corner2 = NULL;
88wxIcon *Corner3 = NULL;
89wxIcon *Corner4 = NULL;
90
91// Fonts
92wxFont *NormalFont = NULL;
93wxFont *BoldFont = NULL;
94wxFont *ItalicFont = NULL;
95
96// Pens
97wxPen *GreyPen = NULL;
98wxPen *DarkGreyPen = NULL;
99wxPen *WhitePen = NULL;
100
101// Backing bitmap
102wxBitmap *backingBitmap = NULL;
103
6bb934d6
JS
104void PoetryError(wxChar *, wxChar *caption=_T("wxPoem Error"));
105void PoetryNotify(wxChar *Msg, wxChar *caption=_T("wxPoem"));
3013b6f4 106void TryLoadIndex();
6bb934d6 107bool LoadPoem(wxChar *, long);
3013b6f4 108int GetIndex();
6bb934d6 109int LoadIndex(wxChar *);
3013b6f4
JS
110bool Compile(void);
111void WritePreferences();
112void ReadPreferences();
113void FindMax(int *max_thing, int thing);
114void CreateFonts();
3013b6f4 115
17d31882
DS
116#if wxUSE_CLIPBOARD
117 #include "wx/dataobj.h"
118 #include "wx/clipbrd.h"
119#endif
3013b6f4 120
a6f28223
JS
121#ifdef __WXWINCE__
122 STDAPI_(__int64) CeGetRandomSeed();
123#endif
124
3013b6f4
JS
125IMPLEMENT_APP(MyApp)
126
127MainWindow *TheMainWindow = NULL;
128
129// Create the fonts
130void CreateFonts()
131{
132 NormalFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxNORMAL, wxNORMAL);
133 BoldFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxNORMAL, wxBOLD);
134 ItalicFont = wxTheFontList->FindOrCreateFont(pointSize, wxSWISS, wxITALIC, wxNORMAL);
135}
136
137BEGIN_EVENT_TABLE(MainWindow, wxFrame)
138 EVT_CLOSE(MainWindow::OnCloseWindow)
139 EVT_CHAR(MainWindow::OnChar)
17d31882 140 EVT_MENU(wxID_ANY, MainWindow::OnPopup)
3013b6f4
JS
141END_EVENT_TABLE()
142
143MainWindow::MainWindow(wxFrame *frame, wxWindowID id, const wxString& title,
144 const wxPoint& pos, const wxSize& size, long style):
145 wxFrame(frame, id, title, pos, size, style)
146{
147}
148
149// Read the poetry buffer, either for finding the size
150// or for writing to a bitmap (not to the window directly,
151// since that displays messily)
152// If DrawIt is true, we draw, otherwise we just determine the
153// size the window should be.
154void MainWindow::ScanBuffer(wxDC *dc, bool DrawIt, int *max_x, int *max_y)
155{
156 int i = pages[current_page];
157 int ch = -1;
3013b6f4
JS
158 int y = 0;
159 int j;
6bb934d6 160 wxChar *line_ptr;
3013b6f4 161 int curr_width = 0;
17d31882 162 bool page_break = false;
3013b6f4
JS
163
164 int width = 0;
165 int height = 0;
166
167 if (DrawIt)
168 {
169 y = (*max_y - poem_height)/2;
170 width = *max_x;
171 height = *max_y;
172 }
173
174 if (DrawIt && wxColourDisplay())
175 {
176 dc->SetBrush(*wxLIGHT_GREY_BRUSH);
177 dc->SetPen(*GreyPen);
178 dc->DrawRectangle(0, 0, width, height);
179 dc->SetBackgroundMode(wxTRANSPARENT);
180 }
181
182 // See what ACTUAL char height is
183 dc->SetFont(* NormalFont);
184 long xx;
185 long yy;
f37c24e0 186 dc->GetTextExtent(_T("X"), &xx, &yy);
3013b6f4
JS
187 char_height = (int)yy;
188
189 if (current_page == 0)
190 title[0] = 0;
191 else if (title[0] != 0)
192 {
193 dc->SetFont(* BoldFont);
194 dc->GetTextExtent(title, &xx, &yy);
195 FindMax(&curr_width, (int)xx);
196
197 if (DrawIt)
198 {
c4b77901 199 int x = (width - xx)/2;
3013b6f4
JS
200 dc->SetFont(* BoldFont);
201
202 // Change text to BLACK!
203 dc->SetTextForeground(* wxBLACK);
204 dc->DrawText(title, x, y);
205 // Change text to WHITE!
206 dc->SetTextForeground(* wxWHITE);
207 dc->DrawText(title, x-SHADOW_OFFSET, y-SHADOW_OFFSET);
208 }
209 y += char_height;
210 y += char_height;
211 }
212
213 while (ch != 0 && !page_break)
214 {
215 j = 0;
685aded8 216#if defined(__WXMSW__) || defined(__WXMAC__)
3013b6f4
JS
217 while (((ch = poem_buffer[i]) != 13) && (ch != 0))
218#else
219 while (((ch = poem_buffer[i]) != 10) && (ch != 0))
220#endif
221 {
222 line[j] = ch;
223 j ++;
224 i ++;
225 }
226
685aded8 227#if defined(__WXMSW__) || defined(__WXMAC__)
3013b6f4
JS
228 if (ch == 13)
229#else
230 if (ch == 10)
231#endif
232 {
233 ch = -1;
234 i ++;
6688f23d 235#if defined(__WXMSW__) || defined(__WXMAC__)
3013b6f4
JS
236 // Add another to skip the linefeed
237 i ++;
238#endif
239 // If a single newline on its own, put a space in
240 if (j == 0)
241 {
242 line[j] = ' ';
243 j ++;
244 line[j] = 0;
245 }
246 }
247
248 if (j > 0)
249 {
250 line[j] = 0;
251 if (line[0] == '@')
252 {
253 switch (line[1])
254 {
255 case 'P':
17d31882
DS
256 paging = true;
257 page_break = true;
3013b6f4
JS
258 break;
259
260 case 'T':
261 dc->SetFont(* BoldFont);
262 line_ptr = line+3;
263
6bb934d6
JS
264 wxStrcpy(title, line_ptr);
265 wxStrcat(title, _T(" (cont'd)"));
3013b6f4
JS
266
267 dc->GetTextExtent(line_ptr, &xx, &yy);
268 FindMax(&curr_width, (int)xx);
269
270 if (DrawIt)
271 {
c4b77901 272 int x = (width - xx)/2;
3013b6f4
JS
273 dc->SetFont(* BoldFont);
274
275 // Change text to BLACK!
276 dc->SetTextForeground(* wxBLACK);
277 dc->DrawText(line_ptr, x, y);
278
279 // Change text to WHITE!
280 dc->SetTextForeground(* wxWHITE);
281 dc->DrawText(line_ptr, x-SHADOW_OFFSET, y-SHADOW_OFFSET);
282 dc->SetTextForeground(* wxWHITE);
283 }
284 break;
285
286 case 'A':
287 line_ptr = line+3;
288 dc->SetFont(* ItalicFont);
289
290 dc->GetTextExtent(line_ptr, &xx, &yy);
291 FindMax(&curr_width, (int)xx);
292
293 if (DrawIt)
294 {
c4b77901 295 int x = (width - xx)/2;
3013b6f4
JS
296 dc->SetTextForeground(* wxBLACK);
297 dc->DrawText(line_ptr, x, y);
298 }
299 break;
300
301 // Default: just ignore this line
302 default:
303 y -= char_height;
304 }
305 }
306 else
307 {
308 dc->SetFont(* NormalFont);
309
310 dc->GetTextExtent(line, &xx, &yy);
311 FindMax(&curr_width, (int)xx);
f5d01a1c 312
3013b6f4
JS
313 if (DrawIt)
314 {
315 int x = (int)((width - xx)/2.0);
316 dc->SetFont(* NormalFont);
317 dc->SetTextForeground(* wxBLACK);
bbf73190 318 dc->DrawText(line, x, y);
3013b6f4
JS
319 }
320 }
321 }
322 y += char_height;
323 }
324
325 // Write (cont'd)
326 if (page_break)
327 {
6bb934d6 328 wxChar *cont = _T("(cont'd)");
3013b6f4
JS
329
330 dc->SetFont(* NormalFont);
331
332 dc->GetTextExtent(cont, &xx, &yy);
333 FindMax(&curr_width, (int)xx);
334 if (DrawIt)
335 {
336 int x = (int)((width - xx)/2.0);
337 dc->SetFont(* NormalFont);
338 dc->SetTextForeground(* wxBLACK);
bbf73190 339 dc->DrawText(cont, x, y);
3013b6f4
JS
340 }
341 y += 2*char_height;
342 }
343
344 *max_x = (int)curr_width;
345 *max_y = (int)(y-char_height);
346
347 if (page_break)
348 pages[current_page+1] = i;
349 else
17d31882 350 paging = false;
3013b6f4
JS
351
352 if (DrawIt)
353 {
354 // Draw dark grey thick border
355 if (wxColourDisplay())
356 {
357 dc->SetBrush(*wxGREY_BRUSH);
358 dc->SetPen(*wxGREY_PEN);
359
360 // Left side
361 dc->DrawRectangle(0, 0, THIN_LINE_BORDER, height);
362 // Top side
363 dc->DrawRectangle(THIN_LINE_BORDER, 0, width-THIN_LINE_BORDER, THIN_LINE_BORDER);
364 // Right side
365 dc->DrawRectangle(width-THIN_LINE_BORDER, THIN_LINE_BORDER, width, height-THIN_LINE_BORDER);
366 // Bottom side
367 dc->DrawRectangle(THIN_LINE_BORDER, height-THIN_LINE_BORDER, width-THIN_LINE_BORDER, height);
368 }
369 // Draw border
370 // Have grey background, plus 3-d border -
371 // One black rectangle.
372 // Inside this, left and top sides - dark grey. Bottom and right -
373 // white.
374
375 // Change pen to black
376 dc->SetPen(*wxBLACK_PEN);
377 dc->DrawLine(THIN_LINE_BORDER, THIN_LINE_BORDER, width-THIN_LINE_BORDER, THIN_LINE_BORDER);
378 dc->DrawLine(width-THIN_LINE_BORDER, THIN_LINE_BORDER, width-THIN_LINE_BORDER, height-THIN_LINE_BORDER);
379 dc->DrawLine(width-THIN_LINE_BORDER, height-THIN_LINE_BORDER, THIN_LINE_BORDER, height-THIN_LINE_BORDER);
380 dc->DrawLine(THIN_LINE_BORDER, height-THIN_LINE_BORDER, THIN_LINE_BORDER, THIN_LINE_BORDER);
f5d01a1c 381
3013b6f4
JS
382 // Right and bottom white lines - 'grey' (black!) if
383 // we're running on a mono display.
384 if (wxColourDisplay())
385 dc->SetPen(*WhitePen);
386 else
387 dc->SetPen(*DarkGreyPen);
388
389 dc->DrawLine(width-THICK_LINE_BORDER, THICK_LINE_BORDER,
390 width-THICK_LINE_BORDER, height-THICK_LINE_BORDER);
391 dc->DrawLine(width-THICK_LINE_BORDER, height-THICK_LINE_BORDER,
392 THICK_LINE_BORDER, height-THICK_LINE_BORDER);
393
394 // Left and top grey lines
395 dc->SetPen(*DarkGreyPen);
396 dc->DrawLine(THICK_LINE_BORDER, height-THICK_LINE_BORDER,
397 THICK_LINE_BORDER, THICK_LINE_BORDER);
398 dc->DrawLine(THICK_LINE_BORDER, THICK_LINE_BORDER,
399 width-THICK_LINE_BORDER, THICK_LINE_BORDER);
400
bbf73190 401//#ifdef __WXMSW__
3013b6f4 402 // Draw icons
bbf73190
RR
403 dc->DrawIcon(* Corner1, 0, 0);
404 dc->DrawIcon(* Corner2, int(width-32), 0);
3013b6f4
JS
405
406 int y2 = height - 32;
407 int x2 = (width-32);
bbf73190
RR
408 dc->DrawIcon(* Corner3, 0, y2);
409 dc->DrawIcon(* Corner4, x2, y2);
410//#endif
3013b6f4
JS
411 }
412}
413
414// Get an index (randomly generated) and load the poem
415void MainWindow::GetIndexLoadPoem(void)
416{
417 if (index_ok)
418 index_ptr = GetIndex();
419
420 if (index_ptr > -1)
421 loaded_ok = LoadPoem(data_filename, -1);
422}
423
424// Find the size of the poem and resize the window accordingly
425void MainWindow::Resize(void)
426{
427 wxClientDC dc(canvas);
428
429 // Get the poem size
17d31882 430 ScanBuffer(& dc, false, &poem_width, &poem_height);
3013b6f4
JS
431 int x = poem_width + (2*BORDER_SIZE);
432 int y = poem_height + (2*BORDER_SIZE);
433
434 SetClientSize(x, y);
435
436 // In case client size isn't what we set it to...
437 int xx, yy;
438 GetClientSize(&xx, &yy);
439
440 wxMemoryDC memDC;
441 if (backingBitmap) delete backingBitmap;
442 backingBitmap = new wxBitmap(x, yy);
443 memDC.SelectObject(* backingBitmap);
444
445 memDC.Clear();
17d31882 446 TheMainWindow->ScanBuffer(&memDC, true, &xx, &yy);
3013b6f4
JS
447}
448
449// Which is more?
450void FindMax(int *max_thing, int thing)
451{
452 if (thing > *max_thing)
453 *max_thing = thing;
454}
455
456// Next page/poem
457void MainWindow::NextPage(void)
458{
459 if (paging)
460 current_page ++;
461 else
462 {
463 current_page = 0;
464 GetIndexLoadPoem();
465 }
466 Resize();
467}
468
469// Previous page
470void MainWindow::PreviousPage(void)
471{
472 if (current_page > 0)
473 {
474 current_page --;
475 Resize();
476 }
477}
478
479// Search for a string
480void MainWindow::Search(bool ask)
481{
482 long position;
483
484 if (ask || !search_string)
485 {
6bb934d6
JS
486 wxString s = wxGetTextFromUser( _T("Enter search string"), _T("Search"), (const wxChar*) search_string);
487 if (s != wxEmptyString)
3013b6f4 488 {
17d31882 489 s.MakeLower();
3013b6f4
JS
490 if (search_string) delete[] search_string;
491 search_string = copystring(s);
17d31882
DS
492 search_ok = true;
493 } else search_ok = false;
3013b6f4
JS
494 }
495 else
496 {
17d31882
DS
497 same_search = true;
498 search_ok = true;
3013b6f4
JS
499 }
500
501 if (search_string && search_ok)
502 {
503 position = DoSearch();
504 if (position > -1)
505 {
506 loaded_ok = LoadPoem(data_filename, position);
507 Resize();
508 }
509 else
510 {
511 last_poem_start = 0;
6bb934d6 512 PoetryNotify(_T("Search string not found."));
3013b6f4
JS
513 }
514 }
515}
516
3013b6f4
JS
517bool MyApp::OnInit()
518{
6bb934d6 519 poem_buffer = new wxChar[buf_size];
f5d01a1c 520
6bb934d6
JS
521 GreyPen = new wxPen(_T("LIGHT GREY"), THICK_LINE_WIDTH, wxSOLID);
522 DarkGreyPen = new wxPen(_T("GREY"), THICK_LINE_WIDTH, wxSOLID);
523 WhitePen = new wxPen(_T("WHITE"), THICK_LINE_WIDTH, wxSOLID);
3013b6f4 524
3013b6f4
JS
525 CreateFonts();
526
527 ReadPreferences();
528
529 // Seed the random number generator
a6f28223
JS
530#ifdef __WXWINCE__
531 srand((unsigned) CeGetRandomSeed());
532#else
3013b6f4
JS
533 time_t current_time;
534
535 (void)time(&current_time);
536 srand((unsigned int)current_time);
a6f28223 537#endif
3013b6f4
JS
538
539// randomize();
540 pages[0] = 0;
541
c4b77901
JS
542 TheMainWindow = new MainWindow(NULL,
543 wxID_ANY,
544 _T("wxPoem"),
545 wxPoint(XPos, YPos),
17d31882 546 wxDefaultSize,
c4b77901
JS
547 wxCAPTION|wxMINIMIZE_BOX|wxSYSTEM_MENU|wxCLOSE_BOX|wxFULL_REPAINT_ON_RESIZE
548 );
3013b6f4 549
17d31882 550 TheMainWindow->SetIcon(wxICON(wxpoem));
3013b6f4 551
b23386b2 552 TheMainWindow->canvas = new MyCanvas(TheMainWindow, 501, wxDefaultPosition, wxDefaultSize);
3013b6f4 553
3013b6f4
JS
554 if (argc > 1)
555 {
556 index_filename = copystring(argv[1]);
557 data_filename = copystring(argv[1]);
558 }
559 else
560 {
6bb934d6
JS
561 index_filename = _T(DEFAULT_POETRY_IND);
562 data_filename = _T(DEFAULT_POETRY_DAT);
3013b6f4
JS
563 }
564 TryLoadIndex();
565
566#ifdef __WXMSW__
6bb934d6
JS
567 Corner1 = new wxIcon(_T("icon_1"));
568 Corner2 = new wxIcon(_T("icon_2"));
569 Corner3 = new wxIcon(_T("icon_3"));
570 Corner4 = new wxIcon(_T("icon_4"));
3013b6f4 571#endif
7d92395d 572#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXX11__)
bbf73190
RR
573 Corner1 = new wxIcon( corner1_xpm );
574 Corner2 = new wxIcon( corner2_xpm );
575 Corner3 = new wxIcon( corner3_xpm );
576 Corner4 = new wxIcon( corner4_xpm );
577#endif
3013b6f4
JS
578
579 TheMainWindow->GetIndexLoadPoem();
580 TheMainWindow->Resize();
17d31882 581 TheMainWindow->Show(true);
3013b6f4 582
17d31882 583 return true;
3013b6f4
JS
584}
585
586int MyApp::OnExit()
587{
588 if (backingBitmap)
589 delete backingBitmap;
3013b6f4
JS
590 delete GreyPen;
591 delete DarkGreyPen;
592 delete WhitePen;
593
3013b6f4
JS
594 delete Corner1;
595 delete Corner2;
596 delete Corner3;
597 delete Corner4;
bbf73190 598
a98f98ac
JS
599 delete[] poem_buffer;
600 if (search_string)
601 delete[] search_string;
3013b6f4
JS
602
603 return 0;
604}
605
bbf73190 606void MainWindow::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
3013b6f4
JS
607{
608 WritePreferences();
609 this->Destroy();
610}
611
612void MainWindow::OnChar(wxKeyEvent& event)
613{
614 canvas->OnChar(event);
615}
616
b23386b2 617BEGIN_EVENT_TABLE(MyCanvas, wxWindow)
3013b6f4
JS
618 EVT_MOUSE_EVENTS(MyCanvas::OnMouseEvent)
619 EVT_CHAR(MyCanvas::OnChar)
620 EVT_PAINT(MyCanvas::OnPaint)
621END_EVENT_TABLE()
622
623// Define a constructor for my canvas
624MyCanvas::MyCanvas(wxFrame *frame, wxWindowID id, const wxPoint& pos, const wxSize& size):
b23386b2 625 wxWindow(frame, id, pos, size)
3013b6f4 626{
17d31882
DS
627 popupMenu = new wxMenu;
628 popupMenu->Append(POEM_NEXT, _T("Next poem/page"));
629 popupMenu->Append(POEM_PREVIOUS, _T("Previous page"));
630 popupMenu->AppendSeparator();
631 popupMenu->Append(POEM_SEARCH, _T("Search"));
632 popupMenu->Append(POEM_NEXT_MATCH, _T("Next match"));
633 popupMenu->Append(POEM_COPY, _T("Copy to clipboard"));
634 popupMenu->Append(POEM_MINIMIZE, _T("Minimize"));
635 popupMenu->AppendSeparator();
636 popupMenu->Append(POEM_BIGGER_TEXT, _T("Bigger text"));
637 popupMenu->Append(POEM_SMALLER_TEXT, _T("Smaller text"));
638 popupMenu->AppendSeparator();
639 popupMenu->Append(POEM_ABOUT, _T("About wxPoem"));
640 popupMenu->AppendSeparator();
641 popupMenu->Append(POEM_EXIT, _T("Exit"));
642}
643
644MyCanvas::~MyCanvas()
645{
646 // Note: this must be done before the main window/canvas are destroyed
647 // or we get an error (no parent window for menu item button)
648 delete popupMenu;
649 popupMenu = NULL;
3013b6f4
JS
650}
651
652// Define the repainting behaviour
bbf73190 653void MyCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
3013b6f4
JS
654{
655 wxPaintDC dc(this);
656
657 if (backingBitmap)
658 {
659 int xx, yy;
660 TheMainWindow->GetClientSize(&xx, &yy);
f5d01a1c 661
59db9cfa
JS
662 dc.DrawBitmap(* backingBitmap, 0, 0);
663#if 0
3013b6f4
JS
664 wxMemoryDC memDC;
665 memDC.SelectObject(* backingBitmap);
666 dc.Blit(0, 0, backingBitmap->GetWidth(), backingBitmap->GetHeight(), &memDC, 0, 0);
59db9cfa 667#endif
3013b6f4
JS
668 }
669}
670
671void MyCanvas::OnMouseEvent(wxMouseEvent& event)
672{
3013b6f4
JS
673 static int startPosX, startPosY, startFrameX, startFrameY;
674
508379ee
VZ
675 long x, y;
676 event.GetPosition(&x, &y);
3013b6f4
JS
677
678 if (event.RightDown())
679 {
680 // Versions from wxWin 1.67 are probably OK
bbf73190 681 PopupMenu(popupMenu, (int)x, (int)y );
3013b6f4
JS
682 }
683 else if (event.LeftDown())
684 {
685 this->CaptureMouse();
686 int x1 = (int)x;
687 int y1 = (int)y;
688 ClientToScreen(&x1, &y1);
689 startPosX = x1;
690 startPosY = y1;
691 GetParent()->GetPosition(&startFrameX, &startFrameY);
692 }
693 else if (event.LeftUp())
17d31882
DS
694 {
695 if (GetCapture() == this) this->ReleaseMouse();
696 }
3013b6f4
JS
697 else if (event.Dragging() && event.LeftIsDown())
698 {
699 int x1 = (int)x;
700 int y1 = (int)y;
701 ClientToScreen(&x1, &y1);
f5d01a1c 702
3013b6f4
JS
703 int dX = x1 - startPosX;
704 int dY = y1 - startPosY;
705 GetParent()->Move(startFrameX + dX, startFrameY + dY);
706 }
707}
708
709// Process characters
710void MyCanvas::OnChar(wxKeyEvent& event)
711{
babd36de 712 switch (event.GetKeyCode())
3013b6f4
JS
713 {
714 case 'n':
715 case 'N':
716 // Next match
17d31882 717 TheMainWindow->Search(false);
3013b6f4
JS
718 break;
719 case 's':
720 case 'S':
721 // New search
17d31882 722 TheMainWindow->Search(true);
3013b6f4
JS
723 break;
724 case WXK_SPACE:
17d31882
DS
725 case WXK_RIGHT:
726 case WXK_DOWN:
3013b6f4
JS
727 // Another poem
728 TheMainWindow->NextPage();
729 break;
17d31882
DS
730 case WXK_ESCAPE:
731 TheMainWindow->Close(true);
3013b6f4
JS
732 default:
733 break;
734 }
735 }
736
737// Load index file
6bb934d6 738int LoadIndex(wxChar *file_name)
3013b6f4
JS
739{
740 long data;
741 FILE *index_file;
742
6bb934d6 743 wxChar buf[100];
3013b6f4 744
6bb934d6 745 if (file_name == NULL)
3013b6f4 746 return 0;
6bb934d6
JS
747
748 wxSprintf(buf, _T("%s.idx"), file_name);
749
750 index_file = wxFopen(buf, _T("r"));
751 if (index_file == NULL)
752 return 0;
753
754 wxFscanf(index_file, _T("%ld"), &nitems);
3013b6f4 755
c4b77901 756 for (int i = 0; i < nitems; i++)
3013b6f4 757 {
6bb934d6 758 wxFscanf(index_file, _T("%ld"), &data);
3013b6f4
JS
759 poem_index[i] = data;
760 }
6bb934d6 761
3013b6f4
JS
762 fclose(index_file);
763
764 return 1;
3013b6f4
JS
765}
766
767// Get index
768int GetIndex()
769{
c4b77901 770 int indexn = (int)(rand() % nitems);
3013b6f4
JS
771
772 if ((indexn < 0) || (indexn > nitems))
6bb934d6 773 { PoetryError(_T("No such poem!"));
3013b6f4
JS
774 return -1;
775 }
776 else
777 return indexn;
778}
779
780// Read preferences
781void ReadPreferences()
782{
f37c24e0 783#if wxUSE_RESOURCES
6bb934d6
JS
784 wxGetResource(_T("wxPoem"), _T("FontSize"), &pointSize);
785 wxGetResource(_T("wxPoem"), _T("X"), &XPos);
786 wxGetResource(_T("wxPoem"), _T("Y"), &YPos);
f37c24e0 787#endif
3013b6f4
JS
788}
789
790// Write preferences to disk
791void WritePreferences()
792{
793#ifdef __WXMSW__
794 TheMainWindow->GetPosition(&XPos, &YPos);
f37c24e0 795#if wxUSE_RESOURCES
6bb934d6
JS
796 wxWriteResource(_T("wxPoem"), _T("FontSize"), pointSize);
797 wxWriteResource(_T("wxPoem"), _T("X"), XPos);
798 wxWriteResource(_T("wxPoem"), _T("Y"), YPos);
f37c24e0
MB
799#endif
800#endif
3013b6f4
JS
801}
802
803// Load a poem from given file, at given point in file.
804// If position is > -1, use this for the position in the
805// file, otherwise use index[index_ptr] to find the correct position.
6bb934d6 806bool LoadPoem(wxChar *file_name, long position)
3013b6f4 807{
bbf73190
RR
808// int j = 0;
809// int indexn = 0;
6bb934d6 810 wxChar buf[100];
3013b6f4
JS
811 long data;
812 FILE *data_file;
813
17d31882 814 paging = false;
3013b6f4
JS
815 current_page = 0;
816
6bb934d6 817 if (file_name == NULL)
3013b6f4 818 {
6bb934d6 819 wxSprintf(error_buf, _T("Error in Poem loading."));
3013b6f4 820 PoetryError(error_buf);
17d31882 821 return false;
3013b6f4 822 }
6bb934d6
JS
823
824 wxSprintf(buf, _T("%s.dat"), file_name);
825 data_file = wxFopen(buf, _T("r"));
826
827 if (data_file == NULL)
3013b6f4 828 {
6bb934d6
JS
829 wxSprintf(error_buf, _T("Data file %s not found."), buf);
830 PoetryError(error_buf);
17d31882 831 return false;
6bb934d6
JS
832 }
833
3013b6f4
JS
834 if (position > -1)
835 data = position;
836 else
837 data = poem_index[index_ptr];
838
839 fseek(data_file, data, SEEK_SET);
840
c4b77901
JS
841 int ch = 0;
842 int i = 0;
3013b6f4
JS
843 while ((ch != EOF) && (ch != '#'))
844 {
845 ch = getc(data_file);
846 // Add a linefeed so it will copy to the clipboard ok
847 if (ch == 10)
848 {
849 poem_buffer[i] = 13;
850 i++;
851 }
852
853 poem_buffer[i] = ch;
854 i ++;
855
856 if (i == buf_size)
857 {
6bb934d6 858 wxSprintf(error_buf, _T("%s"), _T("Poetry buffer exceeded."));
3013b6f4 859 PoetryError(error_buf);
17d31882 860 return false;
3013b6f4
JS
861 }
862 }
863 fclose(data_file);
864 poem_buffer[i-1] = 0;
17d31882 865 return true;
3013b6f4
JS
866}
867
868// Do the search
869long MainWindow::DoSearch(void)
870{
871 if (!search_string)
17d31882 872 return false;
3013b6f4
JS
873
874 FILE *file;
875 long i = 0;
876 int ch = 0;
6bb934d6 877 wxChar buf[100];
3013b6f4
JS
878 long find_start;
879 long previous_poem_start;
880
17d31882 881 bool found = false;
6bb934d6 882 int search_length = wxStrlen(search_string);
3013b6f4
JS
883
884 if (same_search)
885 {
886 find_start = last_find + 1;
887 previous_poem_start = last_poem_start;
888 }
889 else
890 {
891 find_start = 0;
892 last_poem_start = 0;
893 previous_poem_start = -1;
894 }
895
896 if (data_filename)
6bb934d6 897 wxSprintf(buf, _T("%s.dat"), data_filename);
3013b6f4 898
6bb934d6
JS
899 file = wxFopen(buf, _T("r"));
900 if (! (data_filename && file))
3013b6f4 901 {
6bb934d6 902 wxSprintf(error_buf, _T("Poetry data file %s not found\n"), buf);
3013b6f4 903 PoetryError(error_buf);
17d31882 904 return false;
3013b6f4
JS
905 }
906
907 fseek(file, find_start, SEEK_SET);
908
909 while ((ch != EOF) && !found)
910 {
911 ch = getc(file);
17d31882 912 ch = wxTolower(ch); // Make lower case
3013b6f4
JS
913
914 // Only match if we're looking at a different poem
915 // (no point in displaying the same poem again)
916 if ((ch == search_string[i]) && (last_poem_start != previous_poem_start))
917 {
918 if (i == 0)
919 last_find = ftell(file);
920 if (i == search_length-1)
17d31882 921 found = true;
3013b6f4
JS
922 i ++;
923 }
924 else
925 i = 0;
926
927 if (ch == '#')
928 {
929 ch = getc(file);
930 last_poem_start = ftell(file);
931 }
932 }
933 fclose(file);
934 if (ch == EOF)
935 last_find = -1;
936
937 if (found)
938 {
939 return last_poem_start;
940 }
941 else
942 return -1;
943}
944
945// Set up poetry filenames, preferences, load the index
946// Load index (or compile it if none found)
947void TryLoadIndex()
948{
a98f98ac 949 index_ok = (LoadIndex(index_filename) != 0);
3013b6f4
JS
950 if (!index_ok || (nitems == 0))
951 {
6bb934d6 952 PoetryError(_T("Index file not found; will compile new one"), _T("wxPoem"));
3013b6f4
JS
953 index_ok = Compile();
954 }
955}
956
957// Error message
6bb934d6 958void PoetryError(wxChar *msg, wxChar *caption)
3013b6f4
JS
959{
960 wxMessageBox(msg, caption, wxOK|wxICON_EXCLAMATION);
961}
962
963// Notification (change icon to something appropriate!)
6bb934d6 964void PoetryNotify(wxChar *Msg, wxChar *caption)
3013b6f4
JS
965{
966 wxMessageBox(Msg, caption, wxOK | wxICON_INFORMATION);
967}
968
969// Build up and save an index into the poetry data file, for
970// rapid random access
971bool Compile(void)
972{
973 FILE *file;
3013b6f4 974 int j;
c4b77901 975 int ch;
6bb934d6 976 wxChar buf[100];
3013b6f4
JS
977
978 if (data_filename)
6bb934d6 979 wxSprintf(buf, _T("%s.dat"), data_filename);
3013b6f4 980
6bb934d6
JS
981 file = wxFopen(buf, _T("r"));
982 if (! (data_filename && file))
3013b6f4 983 {
6bb934d6 984 wxSprintf(error_buf, _T("Poetry data file %s not found\n"), buf);
3013b6f4 985 PoetryError(error_buf);
17d31882 986 return false;
3013b6f4
JS
987 }
988
989 nitems = 0;
990
991 // Do first one (?)
992 poem_index[nitems] = 0;
993 nitems ++;
994
995 // Do rest
c4b77901
JS
996
997 do {
3013b6f4 998 ch = getc(file);
3013b6f4
JS
999 if (ch == '#')
1000 {
1001 ch = getc(file);
1002 long data;
1003 data = ftell(file);
1004 poem_index[nitems] = data;
1005 nitems ++;
1006 }
c4b77901 1007 } while (ch != EOF);
3013b6f4
JS
1008 fclose(file);
1009
1010 if (index_filename)
6bb934d6
JS
1011 wxSprintf(buf, _T("%s.idx"), index_filename);
1012
1013 file = wxFopen(buf, _T("w"));
1014 if (! (data_filename && file))
3013b6f4 1015 {
6bb934d6 1016 wxSprintf(error_buf, _T("Poetry index file %s cannot be created\n"), buf);
3013b6f4 1017 PoetryError(error_buf);
17d31882 1018 return false;
3013b6f4
JS
1019 }
1020
6bb934d6 1021 wxFprintf(file, _T("%ld\n\n"), nitems);
3013b6f4 1022 for (j = 0; j < nitems; j++)
6bb934d6 1023 wxFprintf(file, _T("%ld\n"), poem_index[j]);
f5d01a1c 1024
3013b6f4 1025 fclose(file);
6bb934d6 1026 PoetryNotify(_T("Poetry index compiled."));
17d31882 1027 return true;
3013b6f4
JS
1028}
1029
508379ee 1030void MainWindow::OnPopup(wxCommandEvent& event)
3013b6f4 1031{
b412f9be 1032 switch (event.GetId())
3013b6f4
JS
1033 {
1034 case POEM_NEXT:
1035 // Another poem/page
1036 TheMainWindow->NextPage();
1037 break;
1038 case POEM_PREVIOUS:
1039 // Previous page
1040 TheMainWindow->PreviousPage();
1041 break;
1042 case POEM_SEARCH:
1043 // Search - with dialog
17d31882 1044 TheMainWindow->Search(true);
3013b6f4
JS
1045 break;
1046 case POEM_NEXT_MATCH:
1047 // Search - without dialog (next match)
17d31882 1048 TheMainWindow->Search(false);
3013b6f4
JS
1049 break;
1050 case POEM_MINIMIZE:
17d31882 1051 TheMainWindow->Iconize(true);
3013b6f4 1052 break;
17d31882 1053#if wxUSE_CLIPBOARD
3013b6f4 1054 case POEM_COPY:
17d31882
DS
1055 wxTheClipboard->UsePrimarySelection();
1056 if (wxTheClipboard->Open())
1057 {
1058 static wxString s;
1059 s = poem_buffer;
1060 s.Replace( _T("@P"),_T(""));
1061 s.Replace( _T("@A "),_T(""));
1062 s.Replace( _T("@A"),_T(""));
1063 s.Replace( _T("@T "),_T(""));
1064 s.Replace( _T("@T"),_T(""));
1065 wxTextDataObject *data = new wxTextDataObject( s.c_str() );
1066 if (!wxTheClipboard->SetData( data ))
1067 wxMessageBox(_T("Error while copying to the clipboard."));
1068 }
1069 else
1070 {
1071 wxMessageBox(_T("Error opening the clipboard."));
1072 }
1073 wxTheClipboard->Close();
3013b6f4
JS
1074 break;
1075#endif
1076 case POEM_COMPILE:
1077 // Compile index
1078 Compile();
1079 break;
1080 case POEM_BIGGER_TEXT:
1081 {
1082 pointSize ++;
1083 CreateFonts();
1084 TheMainWindow->Resize();
1085 break;
1086 }
1087 case POEM_SMALLER_TEXT:
1088 {
1089 if (pointSize > 2)
1090 {
1091 pointSize --;
1092 CreateFonts();
1093 TheMainWindow->Resize();
1094 }
1095 break;
1096 }
3013b6f4
JS
1097 case POEM_ABOUT:
1098 {
6bb934d6
JS
1099 (void)wxMessageBox(_T("wxPoem Version 1.1\nJulian Smart (c) 1995"),
1100 _T("About wxPoem"), wxOK, TheMainWindow);
3013b6f4
JS
1101 break;
1102 }
1103 case POEM_EXIT:
1104 // Exit
17d31882 1105 TheMainWindow->Close(true);
3013b6f4
JS
1106 break;
1107 default:
1108 break;
1109 }
1110}