]> git.saurik.com Git - wxWidgets.git/blob - samples/console/console.cpp
1. fixes for DrawRotatedText(), drawing sample extended to show it
[wxWidgets.git] / samples / console / console.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/console/console.cpp
3 // Purpose: a sample console (as opposed to GUI) progam using wxWindows
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 04.10.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include <stdio.h>
21
22 #include <wx/string.h>
23 #include <wx/file.h>
24 #include <wx/app.h>
25
26 // ----------------------------------------------------------------------------
27 // conditional compilation
28 // ----------------------------------------------------------------------------
29
30 // what to test?
31
32 //#define TEST_ARRAYS
33 //#define TEST_LOG
34 #define TEST_MIME
35 //#define TEST_STRINGS
36 //#define TEST_THREADS
37 //#define TEST_TIME
38 //#define TEST_LONGLONG
39
40 // ============================================================================
41 // implementation
42 // ============================================================================
43
44 // ----------------------------------------------------------------------------
45 // MIME types
46 // ----------------------------------------------------------------------------
47
48 #ifdef TEST_MIME
49
50 #include <wx/mimetype.h>
51
52 static void TestMimeEnum()
53 {
54 wxMimeTypesManager mimeTM;
55 wxArrayString mimetypes;
56
57 size_t count = mimeTM.EnumAllFileTypes(mimetypes);
58
59 printf("*** All %u known filetypes: ***\n", count);
60
61 wxArrayString exts;
62 wxString desc;
63
64 for ( size_t n = 0; n < count; n++ )
65 {
66 wxFileType *filetype = mimeTM.GetFileTypeFromMimeType(mimetypes[n]);
67 if ( !filetype )
68 continue;
69 filetype->GetDescription(&desc);
70 filetype->GetExtensions(exts);
71
72 wxString extsAll;
73 for ( size_t e = 0; e < exts.GetCount(); e++ )
74 {
75 if ( e > 0 )
76 extsAll << _T(", ");
77 extsAll += exts[e];
78 }
79
80 printf("\t%s: %s (%s)\n", mimetypes[n], desc, extsAll);
81 }
82 }
83
84 #endif // TEST_MIME
85
86 // ----------------------------------------------------------------------------
87 // long long
88 // ----------------------------------------------------------------------------
89
90 #ifdef TEST_LONGLONG
91
92 #include <wx/longlong.h>
93 #include <wx/timer.h>
94
95 static void TestSpeed()
96 {
97 static const long max = 100000000;
98 long n;
99
100 {
101 wxStopWatch sw;
102
103 long l = 0;
104 for ( n = 0; n < max; n++ )
105 {
106 l += n;
107 }
108
109 printf("Summing longs took %ld milliseconds.\n", sw.Time());
110 }
111
112 {
113 wxStopWatch sw;
114
115 __int64 l = 0;
116 for ( n = 0; n < max; n++ )
117 {
118 l += n;
119 }
120
121 printf("Summing __int64s took %ld milliseconds.\n", sw.Time());
122 }
123
124 {
125 wxStopWatch sw;
126
127 wxLongLong l;
128 for ( n = 0; n < max; n++ )
129 {
130 l += n;
131 }
132
133 printf("Summing wxLongLongs took %ld milliseconds.\n", sw.Time());
134 }
135 }
136
137 static void TestDivision()
138 {
139 #define MAKE_LL(x1, x2, x3, x4) wxLongLong((x1 << 16) | x2, (x3 << 16) | x3)
140
141 // seed pseudo random generator
142 //srand((unsigned)time(NULL));
143
144 size_t nTested = 0;
145 for ( size_t n = 0; n < 10000; n++ )
146 {
147 // get a random wxLongLong (shifting by 12 the MSB ensures that the
148 // multiplication will not overflow)
149 wxLongLong ll = MAKE_LL((rand() >> 12), rand(), rand(), rand());
150
151 wxASSERT( (ll * 1000l)/1000l == ll );
152
153 nTested++;
154 }
155
156 printf("\n*** Tested %u divisions/multiplications: ok\n", nTested);
157
158 #undef MAKE_LL
159 }
160
161 #endif // TEST_LONGLONG
162
163 // ----------------------------------------------------------------------------
164 // date time
165 // ----------------------------------------------------------------------------
166
167 #ifdef TEST_TIME
168
169 #include <wx/datetime.h>
170
171 // this test miscellaneous static wxDateTime functions
172 static void TestTimeStatic()
173 {
174 puts("\n*** wxDateTime static methods test ***");
175
176 // some info about the current date
177 int year = wxDateTime::GetCurrentYear();
178 printf("Current year %d is %sa leap one and has %d days.\n",
179 year,
180 wxDateTime::IsLeapYear(year) ? "" : "not ",
181 wxDateTime::GetNumberOfDays(year));
182
183 wxDateTime::Month month = wxDateTime::GetCurrentMonth();
184 printf("Current month is '%s' ('%s') and it has %d days\n",
185 wxDateTime::GetMonthName(month, TRUE).c_str(),
186 wxDateTime::GetMonthName(month).c_str(),
187 wxDateTime::GetNumberOfDays(month));
188
189 // leap year logic
190 static const size_t nYears = 5;
191 static const size_t years[2][nYears] =
192 {
193 // first line: the years to test
194 { 1990, 1976, 2000, 2030, 1984, },
195
196 // second line: TRUE if leap, FALSE otherwise
197 { FALSE, TRUE, TRUE, FALSE, TRUE }
198 };
199
200 for ( size_t n = 0; n < nYears; n++ )
201 {
202 int year = years[0][n];
203 bool should = years[1][n] != 0;
204
205 printf("Year %d is %sa leap year (should be: %s)\n",
206 year,
207 wxDateTime::IsLeapYear(year) ? "" : "not ",
208 should ? "yes" : "no");
209
210 wxASSERT( should == wxDateTime::IsLeapYear(year) );
211 }
212 }
213
214 // test constructing wxDateTime objects
215 static void TestTimeSet()
216 {
217 puts("\n*** wxDateTime construction test ***");
218
219 printf("Current time:\t%s\n", wxDateTime::Now().Format().c_str());
220 printf("Unix epoch:\t%s\n", wxDateTime((time_t)0).Format().c_str());
221 printf("Today noon:\t%s\n", wxDateTime(12, 0).Format().c_str());
222 printf("May 29, 1976:\t%s\n", wxDateTime(29, wxDateTime::May, 1976).Format().c_str());
223 }
224
225 // test time zones stuff
226 static void TestTimeZones()
227 {
228 puts("\n*** wxDateTime timezone test ***");
229
230 wxDateTime now = wxDateTime::Now();
231
232 printf("Current GMT time:\t%s\n", now.ToGMT().Format().c_str());
233 printf("Unix epoch (GMT):\t%s\n", wxDateTime((time_t)0).MakeGMT().Format().c_str());
234 printf("Current time in Paris:\t%s\n", now.ToTimezone(wxDateTime::CET).Format().c_str());
235 printf(" Moscow:\t%s\n", now.ToTimezone(wxDateTime::MSK).Format().c_str());
236 printf(" New York:\t%s\n", now.ToTimezone(wxDateTime::EST).Format().c_str());
237 }
238
239 // test some minimal support for the dates outside the standard range
240 static void TestTimeRange()
241 {
242 puts("\n*** wxDateTime out-of-standard-range dates test ***");
243
244 printf("Unix epoch:\t%s\n",
245 wxDateTime(2440587.5).Format().c_str());
246 printf("Feb 29, 0: \t%s\n",
247 wxDateTime(29, wxDateTime::Feb, 0).Format().c_str());
248 printf("JDN 0: \t%s\n",
249 wxDateTime(0.0).Format().c_str());
250 printf("Jan 1, 1AD:\t%s\n",
251 wxDateTime(1, wxDateTime::Jan, 1).Format().c_str());
252 printf("May 29, 2099:\t%s\n",
253 wxDateTime(29, wxDateTime::May, 2099).Format().c_str());
254 }
255
256 // test conversions to JDN &c
257 static void TestTimeJDN()
258 {
259 puts("\n*** wxDateTime to JDN test ***");
260
261 struct Date
262 {
263 wxDateTime::wxDateTime_t day;
264 wxDateTime::Month month;
265 int year;
266 double jdn;
267 };
268
269 static const Date testDates[] =
270 {
271 { 21, wxDateTime::Jan, 2222, 2532648.5 },
272 { 29, wxDateTime::May, 1976, 2442927.5 },
273 { 1, wxDateTime::Jan, 1970, 2440587.5 },
274 { 1, wxDateTime::Jan, 1900, 2415020.5 },
275 { 15, wxDateTime::Oct, 1582, 2299160.5 },
276 { 4, wxDateTime::Oct, 1582, 2299149.5 },
277 { 1, wxDateTime::Mar, 1, 1721484.5 },
278 { 1, wxDateTime::Jan, 1, 1721425.5 },
279 { 31, wxDateTime::Dec, 0, 1721424.5 },
280 { 1, wxDateTime::Jan, 0, 1721059.5 },
281 { 12, wxDateTime::Aug, -1234, 1270573.5 },
282 { 12, wxDateTime::Aug, -4000, 260313.5 },
283 { 24, wxDateTime::Nov, -4713, -0.5 },
284 };
285
286 for ( size_t n = 0; n < WXSIZEOF(testDates); n++ )
287 {
288 const Date& d = testDates[n];
289 wxDateTime dt(d.day, d.month, d.year);
290 double jdn = dt.GetJulianDayNumber();
291
292 printf("JDN of %s %02d, %4d%s is:\t%f",
293 wxDateTime::GetMonthName(d.month).c_str(),
294 d.day,
295 wxDateTime::ConvertYearToBC(d.year),
296 d.year > 0 ? "AD" : "BC",
297 jdn);
298 if ( jdn == d.jdn )
299 {
300 puts(" (ok)");
301 }
302 else
303 {
304 printf(" (ERROR: should be %f, delta = %f)\n",
305 d.jdn, jdn - d.jdn);
306 }
307 }
308 }
309
310 #endif // TEST_TIME
311
312 // ----------------------------------------------------------------------------
313 // threads
314 // ----------------------------------------------------------------------------
315
316 #ifdef TEST_THREADS
317
318 #include <wx/thread.h>
319
320 static size_t gs_counter = (size_t)-1;
321 static wxCriticalSection gs_critsect;
322 static wxCondition gs_cond;
323
324 class MyJoinableThread : public wxThread
325 {
326 public:
327 MyJoinableThread(size_t n) : wxThread(wxTHREAD_JOINABLE)
328 { m_n = n; Create(); }
329
330 // thread execution starts here
331 virtual ExitCode Entry();
332
333 private:
334 size_t m_n;
335 };
336
337 wxThread::ExitCode MyJoinableThread::Entry()
338 {
339 unsigned long res = 1;
340 for ( size_t n = 1; n < m_n; n++ )
341 {
342 res *= n;
343
344 // it's a loooong calculation :-)
345 Sleep(100);
346 }
347
348 return (ExitCode)res;
349 }
350
351 class MyDetachedThread : public wxThread
352 {
353 public:
354 MyDetachedThread(size_t n, char ch)
355 {
356 m_n = n;
357 m_ch = ch;
358 m_cancelled = FALSE;
359
360 Create();
361 }
362
363 // thread execution starts here
364 virtual ExitCode Entry();
365
366 // and stops here
367 virtual void OnExit();
368
369 private:
370 size_t m_n; // number of characters to write
371 char m_ch; // character to write
372
373 bool m_cancelled; // FALSE if we exit normally
374 };
375
376 wxThread::ExitCode MyDetachedThread::Entry()
377 {
378 {
379 wxCriticalSectionLocker lock(gs_critsect);
380 if ( gs_counter == (size_t)-1 )
381 gs_counter = 1;
382 else
383 gs_counter++;
384 }
385
386 for ( size_t n = 0; n < m_n; n++ )
387 {
388 if ( TestDestroy() )
389 {
390 m_cancelled = TRUE;
391
392 break;
393 }
394
395 putchar(m_ch);
396 fflush(stdout);
397
398 wxThread::Sleep(100);
399 }
400
401 return 0;
402 }
403
404 void MyDetachedThread::OnExit()
405 {
406 wxLogTrace("thread", "Thread %ld is in OnExit", GetId());
407
408 wxCriticalSectionLocker lock(gs_critsect);
409 if ( !--gs_counter && !m_cancelled )
410 gs_cond.Signal();
411 }
412
413 void TestDetachedThreads()
414 {
415 puts("\n*** Testing detached threads ***");
416
417 static const size_t nThreads = 3;
418 MyDetachedThread *threads[nThreads];
419 size_t n;
420 for ( n = 0; n < nThreads; n++ )
421 {
422 threads[n] = new MyDetachedThread(10, 'A' + n);
423 }
424
425 threads[0]->SetPriority(WXTHREAD_MIN_PRIORITY);
426 threads[1]->SetPriority(WXTHREAD_MAX_PRIORITY);
427
428 for ( n = 0; n < nThreads; n++ )
429 {
430 threads[n]->Run();
431 }
432
433 // wait until all threads terminate
434 gs_cond.Wait();
435
436 puts("");
437 }
438
439 void TestJoinableThreads()
440 {
441 puts("\n*** Testing a joinable thread (a loooong calculation...) ***");
442
443 // calc 10! in the background
444 MyJoinableThread thread(10);
445 thread.Run();
446
447 printf("\nThread terminated with exit code %lu.\n",
448 (unsigned long)thread.Wait());
449 }
450
451 void TestThreadSuspend()
452 {
453 puts("\n*** Testing thread suspend/resume functions ***");
454
455 MyDetachedThread *thread = new MyDetachedThread(15, 'X');
456
457 thread->Run();
458
459 // this is for this demo only, in a real life program we'd use another
460 // condition variable which would be signaled from wxThread::Entry() to
461 // tell us that the thread really started running - but here just wait a
462 // bit and hope that it will be enough (the problem is, of course, that
463 // the thread might still not run when we call Pause() which will result
464 // in an error)
465 wxThread::Sleep(300);
466
467 for ( size_t n = 0; n < 3; n++ )
468 {
469 thread->Pause();
470
471 puts("\nThread suspended");
472 if ( n > 0 )
473 {
474 // don't sleep but resume immediately the first time
475 wxThread::Sleep(300);
476 }
477 puts("Going to resume the thread");
478
479 thread->Resume();
480 }
481
482 puts("Waiting until it terminates now");
483
484 // wait until the thread terminates
485 gs_cond.Wait();
486
487 puts("");
488 }
489
490 void TestThreadDelete()
491 {
492 // As above, using Sleep() is only for testing here - we must use some
493 // synchronisation object instead to ensure that the thread is still
494 // running when we delete it - deleting a detached thread which already
495 // terminated will lead to a crash!
496
497 puts("\n*** Testing thread delete function ***");
498
499 MyDetachedThread *thread0 = new MyDetachedThread(30, 'W');
500
501 thread0->Delete();
502
503 puts("\nDeleted a thread which didn't start to run yet.");
504
505 MyDetachedThread *thread1 = new MyDetachedThread(30, 'Y');
506
507 thread1->Run();
508
509 wxThread::Sleep(300);
510
511 thread1->Delete();
512
513 puts("\nDeleted a running thread.");
514
515 MyDetachedThread *thread2 = new MyDetachedThread(30, 'Z');
516
517 thread2->Run();
518
519 wxThread::Sleep(300);
520
521 thread2->Pause();
522
523 thread2->Delete();
524
525 puts("\nDeleted a sleeping thread.");
526
527 MyJoinableThread thread3(20);
528 thread3.Run();
529
530 thread3.Delete();
531
532 puts("\nDeleted a joinable thread.");
533
534 MyJoinableThread thread4(2);
535 thread4.Run();
536
537 wxThread::Sleep(300);
538
539 thread4.Delete();
540
541 puts("\nDeleted a joinable thread which already terminated.");
542
543 puts("");
544 }
545
546 #endif // TEST_THREADS
547
548 // ----------------------------------------------------------------------------
549 // arrays
550 // ----------------------------------------------------------------------------
551
552 #ifdef TEST_ARRAYS
553
554 void PrintArray(const char* name, const wxArrayString& array)
555 {
556 printf("Dump of the array '%s'\n", name);
557
558 size_t nCount = array.GetCount();
559 for ( size_t n = 0; n < nCount; n++ )
560 {
561 printf("\t%s[%u] = '%s'\n", name, n, array[n].c_str());
562 }
563 }
564
565 #endif // TEST_ARRAYS
566
567 // ----------------------------------------------------------------------------
568 // strings
569 // ----------------------------------------------------------------------------
570
571 #ifdef TEST_STRINGS
572
573 #include "wx/timer.h"
574
575 void TestString()
576 {
577 wxStopWatch sw;
578
579 wxString a, b, c;
580
581 a.reserve (128);
582 b.reserve (128);
583 c.reserve (128);
584
585 for (int i = 0; i < 1000000; ++i)
586 {
587 a = "Hello";
588 b = " world";
589 c = "! How'ya doin'?";
590 a += b;
591 a += c;
592 c = "Hello world! What's up?";
593 if (c != a)
594 c = "Doh!";
595 }
596
597 printf ("TestString elapsed time: %ld\n", sw.Time());
598 }
599
600 void TestPChar()
601 {
602 wxStopWatch sw;
603
604 char a [128];
605 char b [128];
606 char c [128];
607
608 for (int i = 0; i < 1000000; ++i)
609 {
610 strcpy (a, "Hello");
611 strcpy (b, " world");
612 strcpy (c, "! How'ya doin'?");
613 strcat (a, b);
614 strcat (a, c);
615 strcpy (c, "Hello world! What's up?");
616 if (strcmp (c, a) == 0)
617 strcpy (c, "Doh!");
618 }
619
620 printf ("TestPChar elapsed time: %ld\n", sw.Time());
621 }
622
623 #endif // TEST_STRINGS
624
625 // ----------------------------------------------------------------------------
626 // entry point
627 // ----------------------------------------------------------------------------
628
629 int main(int argc, char **argv)
630 {
631 if ( !wxInitialize() )
632 {
633 fprintf(stderr, "Failed to initialize the wxWindows library, aborting.");
634 }
635
636 #ifdef TEST_STRINGS
637 TestPChar();
638 TestString();
639 #endif // TEST_STRINGS
640
641 #ifdef TEST_ARRAYS
642 wxArrayString a1;
643 a1.Add("tiger");
644 a1.Add("cat");
645 a1.Add("lion");
646 a1.Add("dog");
647 a1.Add("human");
648 a1.Add("ape");
649
650 puts("*** Initially:");
651
652 PrintArray("a1", a1);
653
654 wxArrayString a2(a1);
655 PrintArray("a2", a2);
656
657 wxSortedArrayString a3(a1);
658 PrintArray("a3", a3);
659
660 puts("*** After deleting a string from a1");
661 a1.Remove(2);
662
663 PrintArray("a1", a1);
664 PrintArray("a2", a2);
665 PrintArray("a3", a3);
666
667 puts("*** After reassigning a1 to a2 and a3");
668 a3 = a2 = a1;
669 PrintArray("a2", a2);
670 PrintArray("a3", a3);
671 #endif // TEST_ARRAYS
672
673 #ifdef TEST_LOG
674 wxString s;
675 for ( size_t n = 0; n < 8000; n++ )
676 {
677 s << (char)('A' + (n % 26));
678 }
679
680 wxString msg;
681 msg.Printf("A very very long message: '%s', the end!\n", s.c_str());
682
683 // this one shouldn't be truncated
684 printf(msg);
685
686 // but this one will because log functions use fixed size buffer
687 // (note that it doesn't need '\n' at the end neither - will be added
688 // by wxLog anyhow)
689 wxLogMessage("A very very long message 2: '%s', the end!", s.c_str());
690 #endif // TEST_LOG
691
692 #ifdef TEST_THREADS
693 int nCPUs = wxThread::GetCPUCount();
694 printf("This system has %d CPUs\n", nCPUs);
695 if ( nCPUs != -1 )
696 wxThread::SetConcurrency(nCPUs);
697
698 if ( argc > 1 && argv[1][0] == 't' )
699 wxLog::AddTraceMask("thread");
700
701 if ( 1 )
702 TestDetachedThreads();
703 if ( 1 )
704 TestJoinableThreads();
705 if ( 1 )
706 TestThreadSuspend();
707 if ( 1 )
708 TestThreadDelete();
709
710 #endif // TEST_THREADS
711
712 #ifdef TEST_LONGLONG
713 if ( 0 )
714 TestSpeed();
715 if ( 1 )
716 TestDivision();
717 #endif // TEST_LONGLONG
718
719 #ifdef TEST_MIME
720 TestMimeEnum();
721 #endif // TEST_MIME
722
723 #ifdef TEST_TIME
724 TestTimeStatic();
725 TestTimeSet();
726 TestTimeZones();
727 TestTimeRange();
728 TestTimeJDN();
729 #endif // TEST_TIME
730
731 wxUninitialize();
732
733 return 0;
734 }