home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / intldemo.pak / INTLDEMO.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  30KB  |  1,116 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //   intldemo.cpp
  4. //
  5. //  Program to demonstrate much of the functionality afforded with the
  6. //  setlocale function and the locale libraries. Also demonstrates programming
  7. //  a UI to be language-independent, and allow switching of the language at
  8. //  run-time.
  9. //----------------------------------------------------------------------------
  10. #include <owl\owlpch.h>
  11. #include <owl\decframe.h>
  12. #include <owl\statusba.h>
  13. #include <owl\dialog.h>
  14. #include <owl\mdi.h>
  15. #include <owl\applicat.h>
  16. #include <owl\dc.h>
  17. #include <owl\menu.h>
  18. #include <owl\button.h>
  19. #include <owl\listbox.h>
  20. #include <locale.h>
  21. #include <io.h>
  22. #include <time.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <dir.h>
  27. #include <ctype.h>
  28. #include <math.h>
  29. #include <bwcc.h>
  30. #include <cstring.h>
  31.  
  32. #include "intldemo.h"
  33.  
  34. #define ID_LOCALEWINDOW 101
  35. // language identifiers as defined in winnt.h
  36. #define LANG_ENGLISH 0x09
  37. #define LANG_FRENCH  0x0c
  38. #define LANG_GERMAN  0x07
  39.  
  40. #pragma warn -inl // functions containing ... are not expanded inline
  41.  
  42. char* formatVal(char*, long);
  43.  
  44. // override string's comparison routines
  45. //
  46. int string::compare(const string& s) const throw()
  47. {
  48.   return strcoll(c_str(), s.c_str());
  49. }
  50.  
  51. //----------------------------------------------------------------------------
  52. // Class to convert a file's date/time value into a struct tm.
  53. //
  54. class DosTime {
  55.   private:
  56.     struct filetime
  57.     {
  58.       int ftime;
  59.       int fdate;
  60.     };
  61.  
  62.     union dosfiletime
  63.     {
  64.       filetime ft;
  65.       struct ftime ftime;
  66.     };
  67.  
  68.     dosfiletime dft;
  69.     struct date date;
  70.     struct time time;
  71.  
  72.   public:
  73.     DosTime(int ftime, int fdate)
  74.     {
  75.       dft.ft.ftime = ftime;
  76.       dft.ft.fdate = fdate;
  77.  
  78.       time.ti_sec = dft.ftime.ft_tsec * 2;
  79.       time.ti_min = dft.ftime.ft_min;
  80.       time.ti_hour = dft.ftime.ft_hour;
  81.       time.ti_hund = 0;
  82.  
  83.       date.da_day = dft.ftime.ft_day;
  84.       date.da_mon = dft.ftime.ft_month;
  85.       date.da_year = dft.ftime.ft_year + 1980;
  86.     }
  87.  
  88.     struct tm *tmvalue()
  89.     {
  90.       time_t t;
  91.       t = dostounix(&date, &time);
  92.       return localtime (&t);
  93.     }
  94. };
  95.  
  96. //----------------------------------------------------------------------------
  97. //  TFileViewer
  98. //
  99. //  Simple file viewer. Displays up to 100 chars of each of the first 100 lines
  100. //  of a file in a listbox. Allows sorting by lines.
  101. //
  102. class TFileViewer : public TDialog {
  103.   public:
  104.     TFileViewer(TWindow* parent, TModule* module, char* fileName, TResId resourceId = ID_FILEVIEWER);
  105.  
  106.     void SetupWindow()
  107.     {
  108.       TDialog::SetupWindow();
  109.       SetCaption(caption);
  110.       delete [] caption;
  111.       for (int i = 0; i < stringArray.GetItemsInContainer(); i++)
  112.       {
  113.         lBox -> AddString(stringArray[i]->c_str());
  114.       }
  115.     }
  116.  
  117.     void CmSort(UINT)
  118.     {
  119.       lBox -> ClearList();
  120.       for (int i = 0; i < sStringArray.GetItemsInContainer(); i++)
  121.       {
  122.         lBox -> AddString(sStringArray[i]->c_str());
  123.       }
  124.       lBox -> SetSelIndex(0);
  125.     }
  126.  
  127.   protected:
  128.     enum {maxLines = 100, maxLineLength = 100};
  129.     TListBox *lBox;
  130.     TIArrayAsVector<string> stringArray;
  131.     TISArrayAsVector<string> sStringArray;
  132.     char *caption;
  133.     int nLines;
  134.  
  135.   DECLARE_RESPONSE_TABLE(TFileViewer);
  136. };
  137.  
  138. DEFINE_RESPONSE_TABLE1(TFileViewer, TDialog)
  139.    EV_CHILD_NOTIFY_ALL_CODES(ID_SORTBUT, CmSort),
  140. END_RESPONSE_TABLE;
  141.  
  142.  
  143. TFileViewer::TFileViewer(TWindow* parent, TModule* module, char* fileName, TResId resourceId)
  144.   : TDialog(parent, resourceId, module),
  145.     stringArray(maxLines), sStringArray(maxLines)
  146. {
  147.   sStringArray.OwnsElements(0);
  148.   ifstream f(fileName);
  149.   nLines = 0;
  150.   if (!f.fail())
  151.   {
  152.     caption = strdup(fileName);
  153.     while(!f.eof() && nLines < maxLines)
  154.     {
  155.       char buf[maxLineLength];
  156.       f.get(buf, sizeof buf - 1);
  157.       string *s = new string(buf);
  158.       stringArray.Add(s);
  159.       sStringArray.Add(s);
  160.       // if we're not at the end of the line, try to jump to the next line
  161.       if (f.get() != '\n')
  162.         f.ignore(100, '\n');
  163.     }
  164.     f.close();
  165.   }
  166.   lBox = new TListBox(this, ID_FILELISTBOX, module);
  167. }
  168.  
  169.  
  170. //----------------------------------------------------------------------------
  171. //  TFileListBox
  172. //
  173. // Derivation of ListBox to display file information. Note we are using our own
  174. // sort functions rather than Windows' default sorting. This allows different
  175. // instances of the program to demonstrate the different sorting/collating
  176. // sequences of different locales.
  177. //
  178. class TFileListBox : public TListBox
  179. {
  180.   public:
  181.     TFileListBox(TWindow * parent, int ResourceId, TModule* Module) :
  182.       TListBox(parent, ResourceId, Module),
  183.       FRArray(100, 0, 10), SFRArray(100, 0, 10), currCase(upper), currSort(unsorted)
  184.     {
  185.       module = Module;
  186.       SFRArray.OwnsElements(0);
  187.     }
  188.  
  189.     void SetupWindow()
  190.     {
  191.       TListBox::SetupWindow();
  192.       SetWindowFont(font, 0);
  193.       GetDirList();
  194.       FillListBox();
  195.       SetSelIndex(0);
  196.     }
  197.  
  198.     void ToLower();
  199.  
  200.     void FillListBox();
  201.  
  202.     void GetDirList();
  203.  
  204.     void EvLButtonDblClk(UINT, TPoint&);
  205.  
  206.     void Sort()
  207.     {
  208.       currSort = (currSort == sorted) ? unsorted : sorted;
  209.       char buf[MAXFILE + MAXEXT + 1];
  210.       GetSelString(buf, sizeof buf);
  211.       FillListBox();
  212.       SetSelString(buf, 0);
  213.     }
  214.  
  215.     void ChangeDir();
  216.  
  217.     void View()
  218.     {
  219.       if (GetSelIndex() >= 0) {
  220.         char buf[100];
  221.         GetSelString(buf, sizeof buf);
  222.  
  223.         if (strstr(buf, "<DIR>"))
  224.           ChangeDir();
  225.         else {
  226.           char* s = strchr(buf, ' ');
  227.           if (s)
  228.             *s = 0;
  229.           TFileViewer(Parent, module, buf).Execute();
  230.         }
  231.       }
  232.     }
  233.  
  234.   private:
  235.     // Structure containing file information to be displayed in the
  236.     // FileListBox.
  237.     //
  238.     struct FileRec
  239.     {
  240.       char name[13], datetime[100],  sizeStr[30];
  241.       long fsize;
  242.       char attrib;
  243.  
  244.       // functions used by sorted arrays
  245.       int operator<(const FileRec& r) const
  246.       {
  247.         return (strcoll(name, r.name) < 0) ? 1 : 0;
  248.       }
  249.  
  250.       int operator==(const FileRec& r) const
  251.       {
  252.         return (strcoll(name, r.name) == 0) ? 1 : 0;
  253.       }
  254.     };
  255.  
  256.     // Font to display the filelistbox - we want a non-proportional
  257.     // font for formatting reasons
  258.     class FileListFont : public TFont
  259.     {
  260.       private:
  261.         int HeightInPixels(int pointSize)
  262.         {
  263.           TScreenDC  dc;
  264.           return MulDiv(-pointSize, dc.GetDeviceCaps(LOGPIXELSY), 72);
  265.         }
  266.  
  267.       public:
  268.         FileListFont() : TFont ("Courier New", HeightInPixels(8)) {}
  269.     };
  270.  
  271.     int isSorted;
  272.     int nFiles;
  273.     TIArrayAsVector<FileRec> FRArray;
  274.     TISArrayAsVector<FileRec> SFRArray;
  275.     enum cases {upper, lower};
  276.     cases currCase;
  277.     enum sorting {sorted, unsorted};
  278.     sorting currSort;
  279.     TModule* module;
  280.     FileListFont font;
  281.  
  282.   DECLARE_RESPONSE_TABLE(TFileListBox);
  283. };
  284.  
  285. DEFINE_RESPONSE_TABLE1(TFileListBox, TListBox)
  286.    EV_WM_LBUTTONDBLCLK,
  287. END_RESPONSE_TABLE;
  288.  
  289. void TFileListBox::EvLButtonDblClk(UINT, TPoint&)
  290. {
  291.   View();   // view the file or directory
  292. }
  293.  
  294. void TFileListBox::GetDirList()
  295. {
  296.   SFRArray.Flush();
  297.   FRArray.Flush();
  298.   struct ffblk ffblk;
  299.   struct tm *tm;
  300.   DosTime *dt;
  301.   nFiles = 0;
  302.   int done = findfirst("*.*", &ffblk, 0x3f);
  303.   while (!done)
  304.   {
  305.     FileRec* f = new FileRec;
  306.     OemToAnsiBuff(ffblk.ff_name, ffblk.ff_name, strlen(ffblk.ff_name));
  307.     if (currCase == lower)
  308.     {
  309.       strlwr(ffblk.ff_name);
  310.     }
  311.     strcpy(f->name, ffblk.ff_name);
  312.     dt = new DosTime(ffblk.ff_ftime, ffblk.ff_fdate);
  313.     tm = dt->tmvalue();
  314.     delete dt;
  315.     f->attrib = ffblk.ff_attrib;
  316.     f->fsize = ffblk.ff_fsize;
  317.     formatVal(f->sizeStr, ffblk.ff_fsize);
  318.     strftime(f->datetime, 100, "%c", tm);
  319.     FRArray.Add(f);
  320.     SFRArray.Add(f);
  321.     done = findnext(&ffblk);
  322.   }
  323. }
  324.  
  325. void TFileListBox::ChangeDir()
  326. {
  327.   char buf[MAXFILE + MAXEXT + 1];
  328.   if (GetSelString(buf, sizeof buf))
  329.   {
  330.     for (int i = 0; i < sizeof buf; i++)
  331.       if (buf[i] == ' ')
  332.       {
  333.         buf[i] = 0;
  334.         break;
  335.       }
  336.     if (!chdir(buf))
  337.     {
  338.       GetDirList();
  339.       FillListBox();
  340.     }
  341.   }
  342. }
  343.  
  344.  
  345. void TFileListBox::ToLower()
  346. {
  347.   int selection = GetSelIndex();
  348.   if (currCase == upper)
  349.   {
  350.     for (int i = 0; i < FRArray.GetItemsInContainer(); i++)
  351.       strlwr(FRArray[i] -> name);
  352.     currCase = lower;
  353.     FillListBox();
  354.   }
  355.   else
  356.   {
  357.     for (int i = 0; i < FRArray.GetItemsInContainer(); i++)
  358.       strupr(FRArray[i] -> name);
  359.     currCase = upper;
  360.     FillListBox();
  361.   }
  362.   SetSelIndex(selection);
  363. }
  364.  
  365. void TFileListBox::FillListBox()
  366. {
  367.   char lbformat[] = "%-14.14s\t%-7s\t%10s";
  368.   char s[120];
  369.   SetRedraw(FALSE);
  370.   // Japanese Windows 3.0 repaints horribly with SETREDRAW switched on!
  371.   ClearList();
  372.   int i;
  373.   switch(currSort)
  374.   {
  375.     case sorted:
  376.       for (i = 0; i < SFRArray.GetItemsInContainer(); i++)
  377.       {
  378.         sprintf(s, lbformat, SFRArray[i]->name, SFRArray[i]->datetime,
  379.           ((SFRArray[i]->attrib & FA_DIREC) ? ("<DIR>") : (SFRArray[i]->sizeStr)));
  380.         AddString(s);
  381.       }
  382.       break;
  383.  
  384.     case unsorted:
  385.       for (i = 0; i < FRArray.GetItemsInContainer(); i++)
  386.       {
  387.         sprintf(s, lbformat, FRArray[i]->name, FRArray[i]->datetime,
  388.           ((FRArray[i]->attrib & FA_DIREC) ? ("<DIR>") : (FRArray[i]->sizeStr)));
  389.         AddString(s);
  390.       }
  391.       break;
  392.   }
  393.   SetRedraw(TRUE);
  394. }
  395.  
  396. //----------------------------------------------------------------------------
  397. // Dialog box containing the FileListBox.
  398. //
  399. class TFileListDialog : public TDialog
  400. {
  401.   public:
  402.     TFileListDialog(TWindow * parent, TModule* Module, int ResourceId = ID_FILELISTBOX)
  403.       :TDialog(parent, ResourceId, Module)
  404.     {
  405.       ListBox =  new TFileListBox(this, ID_FILELISTBOX, Module);
  406.       viewButton = new TButton(this, ID_VIEWBUTTON, Module);
  407.       startDir = strdup(getcwd(0, MAXPATH));
  408.     }
  409.  
  410.     virtual ~TFileListDialog()
  411.     {
  412.       chdir(startDir);
  413.       delete [] startDir;
  414.     }
  415.  
  416.     void Sort(UINT)
  417.     {
  418.       ListBox -> Sort();
  419.     }
  420.  
  421.     void ToLower(UINT)
  422.     {
  423.       ListBox -> ToLower();
  424.     }
  425.  
  426.     void View(UINT)
  427.     {
  428.       ListBox -> View();
  429.     }
  430.  
  431.     void Help(UINT)
  432.     {
  433.     }
  434.  
  435.   private:
  436.     TFileListBox* ListBox;
  437.     TButton*      viewButton;
  438.     char*         startDir;
  439.  
  440.   DECLARE_RESPONSE_TABLE(TFileListDialog);
  441. };
  442.  
  443. DEFINE_RESPONSE_TABLE1(TFileListDialog, TDialog)
  444.   EV_CHILD_NOTIFY_ALL_CODES(ID_SORTBUT, Sort),
  445.   EV_CHILD_NOTIFY_ALL_CODES(ID_TOLOWERBUT, ToLower),
  446.   EV_CHILD_NOTIFY_ALL_CODES(ID_VIEWBUTTON, View),
  447.   EV_CHILD_NOTIFY_ALL_CODES(IDHELP, Help),
  448. END_RESPONSE_TABLE;
  449.  
  450.  
  451. //----------------------------------------------------------------------------
  452. // Popup window displaying the current locale values. Note that the locale or
  453. // language can be changed from the main window while we are being displayed,
  454. // and we will update accordingly.
  455. //
  456. class TLocaleValueWindow : public TFrameWindow
  457. {
  458.   public:
  459.     TLocaleValueWindow(lconv *pconv, short cx, short cy, TModule* pResModule,
  460.       TWindow* parent, LPSTR title = 0) :
  461.     TFrameWindow(parent, title)
  462.     {
  463.       conv = pconv;
  464.       cxChar = cx;
  465.       cyChar = cy;
  466.       pResourceModule = pResModule;
  467.  
  468.       Attr.H = cyChar * 22;
  469.       Attr.W = cxChar * 60;
  470.       Attr.Style = Attr.Style | WS_THICKFRAME | WS_SYSMENU;
  471.     }
  472.  
  473.     void SetupWindow()
  474.     {
  475.       TFrameWindow::SetupWindow();
  476.  
  477.       char szTitle[100];
  478.       pResourceModule -> LoadString(STR_LOCALETITLE, szTitle, 100);
  479.       SetCaption(szTitle);
  480.     }
  481.  
  482.     // Called by the parent after the language or locale has been changed to keep
  483.     // us in synch
  484.     void ResetValues(lconv *pconv, short cx, short cy, TModule* pResModule)
  485.     {
  486.       conv = pconv;
  487.       cxChar = cx;
  488.       cyChar = cy;
  489.       pResourceModule = pResModule;
  490.       char szTitle[100];
  491.       pResourceModule -> LoadString(STR_LOCALETITLE, szTitle, 100);
  492.       SetCaption(szTitle);
  493.     }
  494.  
  495.     virtual void Paint(TDC&, BOOL, TRect&);
  496.  
  497.   protected:
  498.     int max(int a, int b)
  499.     {
  500.       if (a > b)
  501.         return a;
  502.       return b;
  503.     }
  504.  
  505.     void EvClose()
  506.     {
  507.       // Tell the parent that we're finished.
  508.       Parent -> SendMessage(WM_VALWNDCLOSE, 0, 0);
  509.       TFrameWindow::EvClose();
  510.     }
  511.  
  512.   private:
  513.     TModule* pResourceModule;
  514.     short cxChar, cyChar;
  515.     lconv *conv;
  516.  
  517.   DECLARE_RESPONSE_TABLE(TLocaleValueWindow);
  518. };
  519.  
  520. DEFINE_RESPONSE_TABLE1(TLocaleValueWindow, TFrameWindow)
  521.    EV_WM_CLOSE,
  522. END_RESPONSE_TABLE;
  523.  
  524.  
  525. void TLocaleValueWindow::Paint(TDC& hdc, BOOL, TRect&)
  526. {
  527.   short t, i;
  528.   char buf[100];
  529.   int maxWidth = 0;
  530.   char yesStr[10], noStr[10];
  531.  
  532.   hdc.SelectStockObject ( SYSTEM_FIXED_FONT );
  533.  
  534.   hdc.SetTextColor(RGB(0, 0, 255));
  535.  
  536.   for (t = STR_DECIMALPOINT, i = 1; t <= STR_N_SIGN_POSN; t++, i++)
  537.   {
  538.    pResourceModule -> LoadString(t, buf, 100);
  539.    hdc.TextOut(cxChar + 10, cyChar * i, buf,strlen(buf));
  540.    maxWidth = max(maxWidth, strlen(buf));
  541.   }
  542.  
  543.   pResourceModule -> LoadString(STR_YES, yesStr, 9);
  544.   pResourceModule -> LoadString(STR_NO, noStr, 9);
  545.  
  546.   hdc.SetTextColor(RGB(255, 0, 0));
  547.   maxWidth *= cxChar;
  548.   maxWidth += (5 * cxChar);
  549.   i = 1;
  550.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> decimal_point, strlen(conv -> decimal_point));
  551.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> thousands_sep, strlen(conv -> thousands_sep));
  552.   sprintf(buf, "%d", *conv -> grouping);
  553.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  554.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> int_curr_symbol, strlen(conv -> int_curr_symbol));
  555.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> currency_symbol, strlen(conv -> currency_symbol));
  556.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> mon_decimal_point, strlen(conv ->  mon_decimal_point));
  557.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> mon_thousands_sep, strlen(conv ->  mon_thousands_sep));
  558.   sprintf(buf, "%d", *conv -> mon_grouping);
  559.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  560.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> positive_sign, strlen(conv ->  positive_sign));
  561.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> negative_sign, strlen(conv -> negative_sign));
  562.  
  563.   sprintf(buf, "%d", conv -> int_frac_digits);
  564.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  565.   sprintf(buf, "%d", conv -> frac_digits);
  566.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  567.  
  568.   char scratch[10];
  569.   sprintf(buf, "%s", (conv -> p_cs_precedes == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  570.    (conv -> p_cs_precedes == 1) ? yesStr : noStr);
  571.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  572.   sprintf(buf, "%s", (conv -> p_sep_by_space == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  573.    (conv -> p_sep_by_space == 1) ? yesStr : noStr);
  574.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  575.   sprintf(buf, "%s", (conv -> n_cs_precedes == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  576.    (conv -> n_cs_precedes == 1) ? yesStr : noStr);
  577.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  578.   sprintf(buf, "%s", (conv -> n_sep_by_space == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  579.    (conv -> n_sep_by_space == 1) ? yesStr : noStr);
  580.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  581.   sprintf(buf, "%d", conv -> p_sign_posn);
  582.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  583.   sprintf(buf, "%d", conv -> n_sign_posn);
  584.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  585. }
  586.  
  587. //----------------------------------------------------------------------------
  588. // Main window, containing a display of all 256 ANSI chars highlighted according
  589. // to the current classification function.
  590. //
  591. #define L_CHARSTRING 20
  592.  
  593. class TLocaleWindow : public TWindow
  594. {
  595.   public:
  596.    TLocaleWindow(TWindow* parent = 0, const char* title = 0)
  597.    : TWindow(parent, title)
  598.    {
  599.     Attr.Id = ID_LOCALEWINDOW;
  600.     classification = alpha;
  601.     classificationmacros[0] = isalnum;
  602.     classificationmacros[1] = isalpha;
  603.     classificationmacros[2] = isascii;
  604.     classificationmacros[3] = iscntrl;
  605.     classificationmacros[4] = isdigit;
  606.     classificationmacros[5] = isgraph;
  607.     classificationmacros[6] = islower;
  608.     classificationmacros[7] = isprint;
  609.     classificationmacros[8] = ispunct;
  610.     classificationmacros[9] = isspace;
  611.     classificationmacros[10] = isupper;
  612.     classificationmacros[11] = isxdigit;
  613.  
  614.     strcpy(macronames[0], "isalnum()");
  615.     strcpy(macronames[1], "isalpha()");
  616.     strcpy(macronames[2], "isascii()");
  617.     strcpy(macronames[3], "iscntrl()");
  618.     strcpy(macronames[4], "isdigit()");
  619.     strcpy(macronames[5], "isgraph()");
  620.     strcpy(macronames[6], "islower()");
  621.     strcpy(macronames[7], "isprint()");
  622.     strcpy(macronames[8], "ispunct()");
  623.     strcpy(macronames[9], "isspace()");
  624.     strcpy(macronames[10], "isupper()");
  625.     strcpy(macronames[11], "isxdigit()");
  626.    }
  627.  
  628.    void SetupWindow()
  629.    {
  630.     TWindow::SetupWindow();
  631.     TWindowDC dc(HWindow);
  632.     dc.SelectStockObject(SYSTEM_FIXED_FONT);
  633.     TEXTMETRIC tm;
  634.     dc.GetTextMetrics (tm);
  635.     cxChar = tm.tmAveCharWidth;
  636.     cyChar = tm.tmHeight + tm.tmExternalLeading;
  637.     SetFocus();
  638.    }
  639.  
  640.    enum classifications {alnum = CM_ISALNUM, alpha, ascii, cntrl, digit, graph, lower, print, punct, space, upper, xdigit};
  641.  
  642.    int ChangeClassification(classifications newClassification)
  643.    {
  644.     CheckMenuItem(Parent -> GetMenu(), classification, MF_UNCHECKED);
  645.     classification = newClassification;
  646.     CheckMenuItem(Parent -> GetMenu(), classification, MF_CHECKED);
  647.  
  648.     Invalidate(TRUE);
  649.     return 0;
  650.    }
  651.  
  652.    void ChangeUI(TModule *pResModule)
  653.    {
  654.     CheckMenuItem(Parent -> GetMenu(), classification, MF_CHECKED);
  655.     pResModule -> LoadString(STR_CHARACTER, characterString, L_CHARSTRING);
  656.    }
  657.  
  658.    void EvMouseMove(UINT /*modKeys*/, TPoint &point)
  659.    {
  660.     char buf[50];
  661.     point.x -= boxTopLeft.x;
  662.     point.y -= boxTopLeft.y;
  663.     if (((point.x > 0) && (point.x < boxBottomRight.x - 4))
  664.       && ((point.y > 0) && (point.y < boxBottomRight.y)))
  665.     {
  666.       int ch = (((point.y / cellHeight) * 16) + (point.x /cellWidth));
  667.       sprintf(buf, "%s %4d  :  %4c  :  %#x", characterString, ch, (ch == 0) ? 1 : ch, ch, ch);
  668.     }
  669.     else
  670.     {
  671.       buf[0] = 0;
  672.     }
  673.     TYPESAFE_DOWNCAST(Parent -> ChildWithId(IDW_STATUSBAR), TStatusBar)->SetText(buf);
  674.    }
  675.  
  676.    void CMIsAlnum()
  677.    {
  678.     if (classification != alnum)
  679.       ChangeClassification(alnum);
  680.    }
  681.  
  682.    void CMIsAlpha()
  683.    {
  684.     if (classification != alpha)
  685.       ChangeClassification(alpha);
  686.    }
  687.  
  688.    void CMIsAscii()
  689.     {
  690.       if (classification != ascii)
  691.         ChangeClassification(ascii);
  692.     }
  693.  
  694.     void CMIsCntrl()
  695.     {
  696.       if (classification != cntrl)
  697.         ChangeClassification(cntrl);
  698.     }
  699.  
  700.     void CMIsDigit()
  701.     {
  702.       if (classification != digit)
  703.         ChangeClassification(digit);
  704.     }
  705.  
  706.     void CMIsGraph()
  707.     {
  708.       if (classification != graph)
  709.         ChangeClassification(graph);
  710.     }
  711.  
  712.     void CMIsLower()
  713.     {
  714.       if (classification != lower)
  715.         ChangeClassification(lower);
  716.     }
  717.  
  718.     void CMIsPrint()
  719.     {
  720.       if (classification != print)
  721.         ChangeClassification(print);
  722.     }
  723.  
  724.     void CMIsPunct()
  725.     {
  726.       if (classification != punct)
  727.         ChangeClassification(punct);
  728.     }
  729.  
  730.     void CMIsSpace()
  731.     {
  732.       if (classification != space)
  733.         ChangeClassification(space);
  734.     }
  735.  
  736.     void CMIsUpper()
  737.     {
  738.       if (classification != upper)
  739.         ChangeClassification(upper);
  740.     }
  741.  
  742.     void CMIsXDigit()
  743.     {
  744.       if (classification != xdigit)
  745.       ChangeClassification(xdigit);
  746.    }
  747.  
  748.    virtual void Paint(TDC&, BOOL, TRect&);
  749.  
  750.   protected:
  751.    int trueColor(TDC& hdc)
  752.    // Sets colour to display characters for which the classification function
  753.    // returns TRUE
  754.    {
  755.     hdc.SetTextColor(RGB(255, 0, 255));
  756.     hdc.SetBkColor(RGB(0, 220, 0));
  757.     return 0;
  758.    }
  759.  
  760.    int falseColor(TDC& hdc)
  761.    // Sets colour to display characters for which the classification function
  762.    // returns FALSE
  763.    {
  764.     hdc.SetTextColor(RGB(200, 200, 200));
  765.     hdc.SetBkColor(RGB(255, 255, 255));
  766.     return 0;
  767.    }
  768.  
  769.   private:
  770.    classifications classification;
  771.    short cxChar, cyChar;
  772.    int (*classificationmacros[12])(int);
  773.    int cellWidth, cellHeight;
  774.    char macronames[12][12];
  775.    TPoint boxTopLeft, boxBottomRight;
  776.    char characterString[L_CHARSTRING];
  777.  
  778.   DECLARE_RESPONSE_TABLE(TLocaleWindow);
  779. };
  780.  
  781. DEFINE_RESPONSE_TABLE1(TLocaleWindow, TWindow)
  782.   EV_WM_MOUSEMOVE,
  783.   EV_COMMAND(CM_ISALNUM, CMIsAlnum),
  784.   EV_COMMAND(CM_ISALPHA, CMIsAlpha),
  785.   EV_COMMAND(CM_ISASCII, CMIsAscii),
  786.   EV_COMMAND(CM_ISCNTRL, CMIsCntrl),
  787.   EV_COMMAND(CM_ISDIGIT, CMIsDigit),
  788.   EV_COMMAND(CM_ISGRAPH, CMIsGraph),
  789.   EV_COMMAND(CM_ISLOWER, CMIsLower),
  790.   EV_COMMAND(CM_ISPRINT, CMIsPrint),
  791.   EV_COMMAND(CM_ISPUNCT, CMIsPunct),
  792.   EV_COMMAND(CM_ISSPACE, CMIsSpace),
  793.   EV_COMMAND(CM_ISUPPER, CMIsUpper),
  794.   EV_COMMAND(CM_ISXDIGIT, CMIsXDigit),
  795. END_RESPONSE_TABLE;
  796.  
  797. void TLocaleWindow::Paint(TDC& hdc, BOOL, TRect&)
  798. {
  799.   char buf[100];
  800.   int maxWidth = 0;
  801.  
  802.   hdc.SelectStockObject(SYSTEM_FIXED_FONT);
  803.  
  804.   hdc.SetTextColor(RGB(0, 0, 0));
  805.   hdc.TextOut((30 * cxChar), (cyChar / 2), macronames[classification - alnum], strlen(macronames[classification - CM_ISALNUM]));
  806.   maxWidth = (10 * cxChar);
  807.  
  808.   #define COLUMNS 16
  809.   #define ROWS 16
  810.  
  811.   char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  812.  
  813.   //Display the codepoint values around the character set.
  814.   for (int i = 0; i < ROWS; i++)
  815.  {
  816.    sprintf(buf, "%c", hexChars[i]);
  817.    hdc.TextOut(maxWidth + ((i * 3) * cxChar), cyChar * 2 , buf, 1);
  818.    hdc.TextOut((maxWidth - (3 * cxChar)), cyChar * (i + 3), buf, 1);
  819.  }
  820.  
  821.   // display the character set in a ROWS x COLUMNS grid, with colours set by
  822.   // trueColor() and falseColor() according to the return value of the current
  823.   // classification function.
  824.   for (i = 0; i < ROWS; i++)
  825.    for (int j = 0; j < COLUMNS; j++)
  826.    {
  827.     int c = ((i * COLUMNS) + j);
  828.     sprintf(buf, "%c",  c);
  829.     classificationmacros[classification - alnum](c) ? trueColor(hdc) : falseColor(hdc);
  830.     if (c < 256) // in case we use different values for row/column.
  831.       hdc.TextOut(maxWidth + ((j * 3) * cxChar), cyChar * (i + 3), buf, 1);
  832.    }
  833.  
  834.  
  835.   // Draw a box round the characters.
  836.   #define X1  (maxWidth - 6)
  837.   #define Y1  ((3 * cyChar) - 2)
  838.   #define X2  ((maxWidth - 2) + (cxChar * (COLUMNS * 3)))
  839.   #define Y2  (((3 * cyChar) - 2) + (cyChar  * ROWS))
  840.  
  841.   boxTopLeft.x = X1;
  842.   boxTopLeft.y = Y1;
  843.   boxBottomRight.x = X2 - X1;
  844.   boxBottomRight.y = Y2 - Y1;
  845.  
  846.   cellWidth = (boxBottomRight.x / COLUMNS);
  847.   cellHeight = (boxBottomRight.y / ROWS);
  848.  
  849.   hdc.SelectObject(CreatePen(PS_SOLID, 1, RGB(0, 127, 127)));
  850.  
  851.   hdc.MoveTo(X1, Y1);
  852.   hdc.LineTo(X1, Y2);
  853.   hdc.LineTo(X2, Y2);
  854.   hdc.LineTo(X2, Y1);
  855.   hdc.LineTo(X1, Y1);
  856.  
  857.   for (i = 0; i < ROWS; i++)
  858.   {
  859.    hdc.MoveTo(X1, Y1 + (i * cyChar));
  860.    hdc.LineTo(X2, Y1 + (i * cyChar));
  861.   }
  862.  
  863.   for (i = 0; i < COLUMNS; i++)
  864.   {
  865.    hdc.MoveTo(X1 + ((i * 3) * cxChar), Y1);
  866.    hdc.LineTo(X1 + ((i * 3) * cxChar), Y2);
  867.   }
  868.   hdc.RestorePen();
  869. }
  870.  
  871.  
  872. //----------------------------------------------------------------------------
  873. //
  874. //
  875. //
  876. class TLocaleFrame : public TDecoratedFrame
  877. {
  878.    enum languages {langEnglish = CM_LANGUAGEENGLISH, langFrench, langGerman};
  879.    enum locales {locC = CM_LOCALEC, locUS, locUK, locFrench, locGerman};
  880.  
  881.   public:
  882.    TLocaleFrame(TWindow* client)
  883.    :TDecoratedFrame((TWindow*)0, (char*)0, client, TRUE)
  884.    {
  885.     pResourceModule = new TModule("APIENG.DLL");
  886.     tMenu = new TMenu(pResourceModule -> LoadMenu("MAINMENU"), AutoDelete);
  887.     valueWin = 0;
  888.     if (!HMENU(*tMenu))
  889.       throw "Error loading menu";
  890.  
  891.     locale = locC;
  892.     language = langEnglish;
  893.  
  894.     TWindowDC dc(HWindow);
  895.     dc.SelectStockObject(SYSTEM_FIXED_FONT);
  896.     TEXTMETRIC tm;
  897.     dc.GetTextMetrics (tm);
  898.     cxChar = tm.tmAveCharWidth;
  899.     cyChar = tm.tmHeight + tm.tmExternalLeading;
  900.     Attr.H = (cyChar * 25);
  901.     Attr.W = (cxChar * 80);
  902.    }
  903.  
  904.    virtual ~TLocaleFrame()
  905.    {
  906.     delete tMenu;
  907.     delete pResourceModule;
  908.    }
  909.  
  910.    void SetupWindow()
  911.    {
  912.     TDecoratedFrame::SetupWindow();
  913.  
  914.  
  915.     char szTitle[100];
  916.     pResourceModule -> LoadString(STR_APPNAME, szTitle, 100);
  917.     SetCaption(szTitle);
  918.     SetMenu(*tMenu);
  919.     tMenu -> CheckMenuItem(locale, MF_CHECKED);
  920.     tMenu -> CheckMenuItem(language, MF_CHECKED);
  921.     TYPESAFE_DOWNCAST(GetClientWindow(), TLocaleWindow) -> ChangeUI(pResourceModule);
  922.     conv = localeconv();
  923.    }
  924.  
  925.    void EvEnterIdle(UINT source, HWND hWndDlg)
  926.    {
  927.     //TDecoratedFrame::EvEnterIdle loads the help hint string, so
  928.     // we change the instance here so it gets it from pResourceModule
  929.     TModule* module = GetModule();
  930.     SetModule(pResourceModule);
  931.     TDecoratedFrame::EvEnterIdle(source, hWndDlg);
  932.     SetModule(module);
  933.    }
  934.  
  935.    void CMEnglishLanguage()
  936.    {
  937.     ChangeUI("apieng.dll", "English", langEnglish, LANG_ENGLISH);
  938.    }
  939.  
  940.    void CMFrenchLanguage()
  941.    {
  942.     ChangeUI("apifra.dll", "French", langFrench, LANG_FRENCH);
  943.    }
  944.  
  945.    void CMGermanLanguage()
  946.    {
  947.     ChangeUI("apiger.dll", "German", langGerman, LANG_GERMAN);
  948.    }
  949.  
  950.  
  951.    void CMFileList()
  952.    {
  953.     TFileListDialog(this, pResourceModule).Execute();
  954.    }
  955.  
  956.    void CMCLocale()
  957.    {
  958.     if (locale != locC)
  959.       ChangeLocale(LC_ALL, "C", locC);
  960.    }
  961.  
  962.    void CMUSLocale()
  963.    {
  964.     if (locale != locUS)
  965.       ChangeLocale(LC_ALL, "en_US.WIN1252", locUS);
  966.    }
  967.  
  968.    void CMUKLocale()
  969.    {
  970.     if (locale != locUK)
  971.       ChangeLocale(LC_ALL, "en_GB.WIN1252", locUK);
  972.    }
  973.  
  974.    void CMFrenchLocale()
  975.    {
  976.     if (locale != locFrench)
  977.       ChangeLocale(LC_ALL, "fr_FR.WIN1252", locFrench);
  978.    }
  979.  
  980.    void CMGermanLocale()
  981.    {
  982.     if (locale != locGerman)
  983.       ChangeLocale(LC_ALL, "de_DE.WIN1252", locGerman);
  984.    }
  985.  
  986.    void CMShowValues()
  987.    {
  988.     if (!valueWin)
  989.     {
  990.       valueWin = new TLocaleValueWindow(conv, cxChar,
  991.        cyChar, pResourceModule, this);
  992.  
  993.       valueWin -> Create();
  994.       valueWin -> Show(SW_SHOW);
  995.     }
  996.     else
  997.       valueWin -> SetFocus();
  998.    }
  999.  
  1000.    LRESULT WMValWndClose(WPARAM, LPARAM)
  1001.    {
  1002.     valueWin = 0;
  1003.     return 0;
  1004.    }
  1005.  
  1006.   protected:
  1007.    int ChangeUI(char* DLLName, char* langName, languages newLanguage, UINT countryCode)
  1008.    {
  1009.     delete pResourceModule;
  1010.     pResourceModule = new TModule(DLLName);
  1011.     delete tMenu;
  1012.     tMenu = new TMenu(pResourceModule -> LoadMenu("MAINMENU"), AutoDelete);
  1013.     SetMenu(*tMenu);
  1014.     tMenu -> CheckMenuItem(locale, MF_CHECKED);
  1015.     TYPESAFE_DOWNCAST(GetClientWindow(), TLocaleWindow) -> ChangeUI(pResourceModule);
  1016.  
  1017.     char szTitle[100];
  1018.     pResourceModule -> LoadString(STR_APPNAME, szTitle, 100);
  1019.     SetCaption(szTitle);
  1020.  
  1021.     Invalidate(TRUE);
  1022.     RedrawValueWindow();
  1023.     tMenu -> CheckMenuItem(language, MF_UNCHECKED);
  1024.     language = newLanguage;
  1025.     tMenu -> CheckMenuItem(language, MF_CHECKED);
  1026.     BWCCIntlTerm();
  1027.     BWCCIntlInit(countryCode);
  1028.     return 1;
  1029.    }
  1030.  
  1031.    char *ChangeLocale(int category, char *localeType, locales newLocale)
  1032.    {
  1033.     tMenu -> CheckMenuItem(locale, MF_UNCHECKED);
  1034.     locale = newLocale;
  1035.     tMenu -> CheckMenuItem(locale, MF_CHECKED);
  1036.  
  1037.     char *c = setlocale(category, localeType);
  1038.     conv = localeconv();
  1039.     Invalidate(TRUE);
  1040.     RedrawValueWindow();
  1041.     ChildWithId(ID_LOCALEWINDOW) -> Invalidate(TRUE);
  1042.     return c;
  1043.    }
  1044.  
  1045.    void RedrawValueWindow()
  1046.    {
  1047.     if (valueWin)
  1048.     {
  1049.       valueWin -> ResetValues(conv, cxChar,
  1050.        cyChar, pResourceModule);
  1051.       valueWin -> Invalidate(TRUE);
  1052.     }
  1053.    }
  1054.  
  1055.   private:
  1056.    languages language;
  1057.    locales   locale;
  1058.    TModule*  pResourceModule;
  1059.    TMenu*    tMenu;
  1060.    TLocaleValueWindow* valueWin;
  1061.    short     cxChar, cyChar, scrX, scrY;
  1062.    lconv*    conv;
  1063.  
  1064.   DECLARE_RESPONSE_TABLE(TLocaleFrame);
  1065. };
  1066.  
  1067. DEFINE_RESPONSE_TABLE1(TLocaleFrame, TDecoratedFrame)
  1068.   EV_WM_ENTERIDLE,
  1069.   EV_COMMAND(CM_FILELIST, CMFileList),
  1070.   EV_COMMAND(CM_LOCALEC, CMCLocale),
  1071.   EV_COMMAND(CM_LOCALEUS, CMUSLocale),
  1072.   EV_COMMAND(CM_LOCALEUK, CMUKLocale),
  1073.   EV_COMMAND(CM_LOCALEFRENCH, CMFrenchLocale),
  1074.   EV_COMMAND(CM_LOCALEGERMAN, CMGermanLocale),
  1075.   EV_COMMAND(CM_LANGUAGEENGLISH, CMEnglishLanguage),
  1076.   EV_COMMAND(CM_LANGUAGEFRENCH, CMFrenchLanguage),
  1077.   EV_COMMAND(CM_LANGUAGEGERMAN, CMGermanLanguage),
  1078.   EV_COMMAND(CM_SHOWVALUES, CMShowValues),
  1079.   EV_MESSAGE(WM_VALWNDCLOSE, WMValWndClose),
  1080. END_RESPONSE_TABLE;
  1081.  
  1082.  
  1083. //----------------------------------------------------------------------------
  1084. //
  1085. //
  1086. //
  1087. class TLocaleApplication : public TApplication
  1088. {
  1089.   public:
  1090.    TLocaleApplication():TApplication("Intl demo program")
  1091.    {
  1092.    }
  1093.  
  1094.    void InitMainWindow()
  1095.    {
  1096.     try
  1097.     {
  1098.       TLocaleFrame* frame = new TLocaleFrame(new TLocaleWindow);
  1099.       TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed);
  1100.       frame->Insert(*sb, TDecoratedFrame::Bottom);
  1101.       MainWindow = frame;
  1102.         MainWindow->SetIcon(this, "World_Icon");
  1103.         EnableBWCC(TRUE, LANG_ENGLISH);
  1104.       }
  1105.       catch(const char *s)
  1106.       {
  1107.         BWCCMessageBox(0, s, "Intldemo", MB_OK);
  1108.       }
  1109.     }
  1110. };
  1111.  
  1112. int OwlMain(int /*argc*/, char* /*argv*/ [])
  1113. {
  1114.   return TLocaleApplication().Run();
  1115. }
  1116.