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