home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 10.ddi / INTLDEMO.PAK / INTLDEMO.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  30.0 KB  |  1,148 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. #if 0
  328.   char buf[MAXFILE + MAXEXT + 1], fullPath[MAXPATH];
  329.   if (GetSelString(buf, sizeof buf))
  330.     getcwd(fullPath, sizeof fullPath);
  331.   if (strstr(buf, ".."))
  332.   {
  333.     char *ptr = fullPath;
  334.     while(strchr(ptr, '\\')) ptr ++;
  335.     *(--ptr) = 0;
  336.     if (strlen(fullPath) == 2)
  337.     {
  338.       strcat(fullPath, "\\"); // \ is needed on the root, otherwise not.
  339.     }
  340.   }
  341.   else
  342.   {
  343.     if (fullPath[strlen(fullPath) - 1] != '\\')
  344.       strcat(fullPath, "\\");
  345.     strcat(fullPath, buf);
  346.     for (int i = 0; i < MAXPATH; i++)
  347.       if (fullPath[i] == ' ')
  348.       {
  349.         fullPath[i] = 0;
  350.         i = MAXPATH;
  351.       }
  352.   }
  353.   if (!chdir(fullPath))
  354.   {
  355.     GetDirList();
  356.     FillListBox();
  357.   }
  358. #endif
  359.   char buf[MAXFILE + MAXEXT + 1];
  360.   if (GetSelString(buf, sizeof buf))
  361.   {
  362.     for (int i = 0; i < sizeof buf; i++)
  363.       if (buf[i] == ' ')
  364.       {
  365.         buf[i] = 0;
  366.         break;
  367.       }
  368.     if (!chdir(buf))
  369.     {
  370.       GetDirList();
  371.       FillListBox();
  372.     }
  373.   }
  374. }
  375.  
  376.  
  377. void TFileListBox::ToLower()
  378. {
  379.   int selection = GetSelIndex();
  380.   if (currCase == upper)
  381.   {
  382.     for (int i = 0; i < FRArray.GetItemsInContainer(); i++)
  383.       strlwr(FRArray[i] -> name);
  384.     currCase = lower;
  385.     FillListBox();
  386.   }
  387.   else
  388.   {
  389.     for (int i = 0; i < FRArray.GetItemsInContainer(); i++)
  390.       strupr(FRArray[i] -> name);
  391.     currCase = upper;
  392.     FillListBox();
  393.   }
  394.   SetSelIndex(selection);
  395. }
  396.  
  397. void TFileListBox::FillListBox()
  398. {
  399.   char lbformat[] = "%-14.14s\t%-7s\t%10s";
  400.   char s[120];
  401.   SetRedraw(FALSE);
  402.   // Japanese Windows 3.0 repaints horribly with SETREDRAW switched on!
  403.   ClearList();
  404.   int i;
  405.   switch(currSort)
  406.   {
  407.     case sorted:
  408.       for (i = 0; i < SFRArray.GetItemsInContainer(); i++)
  409.       {
  410.         sprintf(s, lbformat, SFRArray[i]->name, SFRArray[i]->datetime,
  411.           ((SFRArray[i]->attrib & FA_DIREC) ? ("<DIR>") : (SFRArray[i]->sizeStr)));
  412.         AddString(s);
  413.       }
  414.       break;
  415.  
  416.     case unsorted:
  417.       for (i = 0; i < FRArray.GetItemsInContainer(); i++)
  418.       {
  419.         sprintf(s, lbformat, FRArray[i]->name, FRArray[i]->datetime,
  420.           ((FRArray[i]->attrib & FA_DIREC) ? ("<DIR>") : (FRArray[i]->sizeStr)));
  421.         AddString(s);
  422.       }
  423.       break;
  424.   }
  425.   SetRedraw(TRUE);
  426. }
  427.  
  428. //----------------------------------------------------------------------------
  429. // Dialog box containing the FileListBox.
  430. //
  431. class TFileListDialog : public TDialog
  432. {
  433.   public:
  434.     TFileListDialog(TWindow * parent, TModule* Module, int ResourceId = ID_FILELISTBOX)
  435.       :TDialog(parent, ResourceId, Module)
  436.     {
  437.       ListBox =  new TFileListBox(this, ID_FILELISTBOX, Module);
  438.       viewButton = new TButton(this, ID_VIEWBUTTON, Module);
  439.       startDir = strdup(getcwd(0, MAXPATH));
  440.     }
  441.  
  442.     virtual ~TFileListDialog()
  443.     {
  444.       chdir(startDir);
  445.       delete [] startDir;
  446.     }
  447.  
  448.     void Sort(UINT)
  449.     {
  450.       ListBox -> Sort();
  451.     }
  452.  
  453.     void ToLower(UINT)
  454.     {
  455.       ListBox -> ToLower();
  456.     }
  457.  
  458.     void View(UINT)
  459.     {
  460.       ListBox -> View();
  461.     }
  462.  
  463.     void Help(UINT)
  464.     {
  465.     }
  466.  
  467.   private:
  468.     TFileListBox* ListBox;
  469.     TButton*      viewButton;
  470.     char*         startDir;
  471.  
  472.   DECLARE_RESPONSE_TABLE(TFileListDialog);
  473. };
  474.  
  475. DEFINE_RESPONSE_TABLE1(TFileListDialog, TDialog)
  476.   EV_CHILD_NOTIFY_ALL_CODES(ID_SORTBUT, Sort),
  477.   EV_CHILD_NOTIFY_ALL_CODES(ID_TOLOWERBUT, ToLower),
  478.   EV_CHILD_NOTIFY_ALL_CODES(ID_VIEWBUTTON, View),
  479.   EV_CHILD_NOTIFY_ALL_CODES(IDHELP, Help),
  480. END_RESPONSE_TABLE;
  481.  
  482.  
  483. //----------------------------------------------------------------------------
  484. // Popup window displaying the current locale values. Note that the locale or
  485. // language can be changed from the main window while we are being displayed,
  486. // and we will update accordingly.
  487. //
  488. class TLocaleValueWindow : public TFrameWindow
  489. {
  490.   public:
  491.     TLocaleValueWindow(lconv *pconv, short cx, short cy, TModule* pResModule,
  492.       TWindow* parent, LPSTR title = 0) :
  493.     TFrameWindow(parent, title)
  494.     {
  495.       conv = pconv;
  496.       cxChar = cx;
  497.       cyChar = cy;
  498.       pResourceModule = pResModule;
  499.  
  500.       Attr.H = cyChar * 22;
  501.       Attr.W = cxChar * 60;
  502.       Attr.Style = Attr.Style | WS_THICKFRAME | WS_SYSMENU;
  503.     }
  504.  
  505.     void SetupWindow()
  506.     {
  507.       TFrameWindow::SetupWindow();
  508.  
  509.       char szTitle[100];
  510.       pResourceModule -> LoadString(STR_LOCALETITLE, szTitle, 100);
  511.       SetCaption(szTitle);
  512.     }
  513.  
  514.     // Called by the parent after the language or locale has been changed to keep
  515.     // us in synch
  516.     void ResetValues(lconv *pconv, short cx, short cy, TModule* pResModule)
  517.     {
  518.       conv = pconv;
  519.       cxChar = cx;
  520.       cyChar = cy;
  521.       pResourceModule = pResModule;
  522.       char szTitle[100];
  523.       pResourceModule -> LoadString(STR_LOCALETITLE, szTitle, 100);
  524.       SetCaption(szTitle);
  525.     }
  526.  
  527.     virtual void Paint(TDC&, BOOL, TRect&);
  528.  
  529.   protected:
  530.     int max(int a, int b)
  531.     {
  532.       if (a > b)
  533.         return a;
  534.       return b;
  535.     }
  536.  
  537.     void EvClose()
  538.     {
  539.       // Tell the parent that we're finished.
  540.       Parent -> SendMessage(WM_VALWNDCLOSE, 0, 0);
  541.       TFrameWindow::EvClose();
  542.     }
  543.  
  544.   private:
  545.     TModule* pResourceModule;
  546.     short cxChar, cyChar;
  547.     lconv *conv;
  548.  
  549.   DECLARE_RESPONSE_TABLE(TLocaleValueWindow);
  550. };
  551.  
  552. DEFINE_RESPONSE_TABLE1(TLocaleValueWindow, TFrameWindow)
  553.    EV_WM_CLOSE,
  554. END_RESPONSE_TABLE;
  555.  
  556.  
  557. void TLocaleValueWindow::Paint(TDC& hdc, BOOL, TRect&)
  558. {
  559.   short t, i;
  560.   char buf[100];
  561.   int maxWidth = 0;
  562.   char yesStr[10], noStr[10];
  563.  
  564.   hdc.SelectStockObject ( SYSTEM_FIXED_FONT );
  565.  
  566.   hdc.SetTextColor(RGB(0, 0, 255));
  567.  
  568.   for (t = STR_DECIMALPOINT, i = 1; t <= STR_N_SIGN_POSN; t++, i++)
  569.   {
  570.    pResourceModule -> LoadString(t, buf, 100);
  571.    hdc.TextOut(cxChar + 10, cyChar * i, buf,strlen(buf));
  572.    maxWidth = max(maxWidth, strlen(buf));
  573.   }
  574.  
  575.   pResourceModule -> LoadString(STR_YES, yesStr, 9);
  576.   pResourceModule -> LoadString(STR_NO, noStr, 9);
  577.  
  578.   hdc.SetTextColor(RGB(255, 0, 0));
  579.   maxWidth *= cxChar;
  580.   maxWidth += (5 * cxChar);
  581.   i = 1;
  582.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> decimal_point, strlen(conv -> decimal_point));
  583.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> thousands_sep, strlen(conv -> thousands_sep));
  584.   sprintf(buf, "%d", *conv -> grouping);
  585.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  586.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> int_curr_symbol, strlen(conv -> int_curr_symbol));
  587.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> currency_symbol, strlen(conv -> currency_symbol));
  588.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> mon_decimal_point, strlen(conv ->  mon_decimal_point));
  589.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> mon_thousands_sep, strlen(conv ->  mon_thousands_sep));
  590.   sprintf(buf, "%d", *conv -> mon_grouping);
  591.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  592.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> positive_sign, strlen(conv ->  positive_sign));
  593.   hdc.TextOut(maxWidth, cyChar * (i ++), conv -> negative_sign, strlen(conv -> negative_sign));
  594.  
  595.   sprintf(buf, "%d", conv -> int_frac_digits);
  596.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  597.   sprintf(buf, "%d", conv -> frac_digits);
  598.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  599.  
  600.   char scratch[10];
  601.   sprintf(buf, "%s", (conv -> p_cs_precedes == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  602.    (conv -> p_cs_precedes == 1) ? yesStr : noStr);
  603.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  604.   sprintf(buf, "%s", (conv -> p_sep_by_space == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  605.    (conv -> p_sep_by_space == 1) ? yesStr : noStr);
  606.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  607.   sprintf(buf, "%s", (conv -> n_cs_precedes == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  608.    (conv -> n_cs_precedes == 1) ? yesStr : noStr);
  609.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  610.   sprintf(buf, "%s", (conv -> n_sep_by_space == CHAR_MAX) ? itoa(CHAR_MAX, scratch, 10) :
  611.    (conv -> n_sep_by_space == 1) ? yesStr : noStr);
  612.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  613.   sprintf(buf, "%d", conv -> p_sign_posn);
  614.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  615.   sprintf(buf, "%d", conv -> n_sign_posn);
  616.   hdc.TextOut(maxWidth, cyChar * (i ++), buf, strlen(buf));
  617. }
  618.  
  619. //----------------------------------------------------------------------------
  620. // Main window, containing a display of all 256 ANSI chars highlighted according
  621. // to the current classification function.
  622. //
  623. #define L_CHARSTRING 20
  624.  
  625. class TLocaleWindow : public TWindow
  626. {
  627.   public:
  628.    TLocaleWindow(TWindow* parent = 0, const char* title = 0)
  629.    : TWindow(parent, title)
  630.    {
  631.     Attr.Id = ID_LOCALEWINDOW;
  632.     classification = alpha;
  633.     classificationmacros[0] = isalnum;
  634.     classificationmacros[1] = isalpha;
  635.     classificationmacros[2] = isascii;
  636.     classificationmacros[3] = iscntrl;
  637.     classificationmacros[4] = isdigit;
  638.     classificationmacros[5] = isgraph;
  639.     classificationmacros[6] = islower;
  640.     classificationmacros[7] = isprint;
  641.     classificationmacros[8] = ispunct;
  642.     classificationmacros[9] = isspace;
  643.     classificationmacros[10] = isupper;
  644.     classificationmacros[11] = isxdigit;
  645.  
  646.     strcpy(macronames[0], "isalnum()");
  647.     strcpy(macronames[1], "isalpha()");
  648.     strcpy(macronames[2], "isascii()");
  649.     strcpy(macronames[3], "iscntrl()");
  650.     strcpy(macronames[4], "isdigit()");
  651.     strcpy(macronames[5], "isgraph()");
  652.     strcpy(macronames[6], "islower()");
  653.     strcpy(macronames[7], "isprint()");
  654.     strcpy(macronames[8], "ispunct()");
  655.     strcpy(macronames[9], "isspace()");
  656.     strcpy(macronames[10], "isupper()");
  657.     strcpy(macronames[11], "isxdigit()");
  658.    }
  659.  
  660.    void SetupWindow()
  661.    {
  662.     TWindow::SetupWindow();
  663.     TWindowDC dc(HWindow);
  664.     dc.SelectStockObject(SYSTEM_FIXED_FONT);
  665.     TEXTMETRIC tm;
  666.     dc.GetTextMetrics (tm);
  667.     cxChar = tm.tmAveCharWidth;
  668.     cyChar = tm.tmHeight + tm.tmExternalLeading;
  669.     SetFocus();
  670.    }
  671.  
  672.    enum classifications {alnum = CM_ISALNUM, alpha, ascii, cntrl, digit, graph, lower, print, punct, space, upper, xdigit};
  673.  
  674.    int ChangeClassification(classifications newClassification)
  675.    {
  676.     CheckMenuItem(Parent -> GetMenu(), classification, MF_UNCHECKED);
  677.     classification = newClassification;
  678.     CheckMenuItem(Parent -> GetMenu(), classification, MF_CHECKED);
  679.  
  680.     Invalidate(TRUE);
  681.     return 0;
  682.    }
  683.  
  684.    void ChangeUI(TModule *pResModule)
  685.    {
  686.     CheckMenuItem(Parent -> GetMenu(), classification, MF_CHECKED);
  687.     pResModule -> LoadString(STR_CHARACTER, characterString, L_CHARSTRING);
  688.    }
  689.  
  690.    void EvMouseMove(UINT /*modKeys*/, TPoint &point)
  691.    {
  692.     char buf[50];
  693.     point.x -= boxTopLeft.x;
  694.     point.y -= boxTopLeft.y;
  695.     if (((point.x > 0) && (point.x < boxBottomRight.x - 4))
  696.       && ((point.y > 0) && (point.y < boxBottomRight.y)))
  697.     {
  698.       int ch = (((point.y / cellHeight) * 16) + (point.x /cellWidth));
  699.       sprintf(buf, "%s %4d  :  %4c  :  %#x", characterString, ch, (ch == 0) ? 1 : ch, ch, ch);
  700.     }
  701.     else
  702.     {
  703.       buf[0] = 0;
  704.     }
  705.     TYPESAFE_DOWNCAST(Parent -> ChildWithId(IDW_STATUSBAR), TStatusBar)->SetText(buf);
  706.    }
  707.  
  708.    void CMIsAlnum()
  709.    {
  710.     if (classification != alnum)
  711.       ChangeClassification(alnum);
  712.    }
  713.  
  714.    void CMIsAlpha()
  715.    {
  716.     if (classification != alpha)
  717.       ChangeClassification(alpha);
  718.    }
  719.  
  720.    void CMIsAscii()
  721.     {
  722.       if (classification != ascii)
  723.         ChangeClassification(ascii);
  724.     }
  725.  
  726.     void CMIsCntrl()
  727.     {
  728.       if (classification != cntrl)
  729.         ChangeClassification(cntrl);
  730.     }
  731.  
  732.     void CMIsDigit()
  733.     {
  734.       if (classification != digit)
  735.         ChangeClassification(digit);
  736.     }
  737.  
  738.     void CMIsGraph()
  739.     {
  740.       if (classification != graph)
  741.         ChangeClassification(graph);
  742.     }
  743.  
  744.     void CMIsLower()
  745.     {
  746.       if (classification != lower)
  747.         ChangeClassification(lower);
  748.     }
  749.  
  750.     void CMIsPrint()
  751.     {
  752.       if (classification != print)
  753.         ChangeClassification(print);
  754.     }
  755.  
  756.     void CMIsPunct()
  757.     {
  758.       if (classification != punct)
  759.         ChangeClassification(punct);
  760.     }
  761.  
  762.     void CMIsSpace()
  763.     {
  764.       if (classification != space)
  765.         ChangeClassification(space);
  766.     }
  767.  
  768.     void CMIsUpper()
  769.     {
  770.       if (classification != upper)
  771.         ChangeClassification(upper);
  772.     }
  773.  
  774.     void CMIsXDigit()
  775.     {
  776.       if (classification != xdigit)
  777.       ChangeClassification(xdigit);
  778.    }
  779.  
  780.    virtual void Paint(TDC&, BOOL, TRect&);
  781.  
  782.   protected:
  783.    int trueColor(TDC& hdc)
  784.    // Sets colour to display characters for which the classification function
  785.    // returns TRUE
  786.    {
  787.     hdc.SetTextColor(RGB(255, 0, 255));
  788.     hdc.SetBkColor(RGB(0, 220, 0));
  789.     return 0;
  790.    }
  791.  
  792.    int falseColor(TDC& hdc)
  793.    // Sets colour to display characters for which the classification function
  794.    // returns FALSE
  795.    {
  796.     hdc.SetTextColor(RGB(200, 200, 200));
  797.     hdc.SetBkColor(RGB(255, 255, 255));
  798.     return 0;
  799.    }
  800.  
  801.   private:
  802.    classifications classification;
  803.    short cxChar, cyChar;
  804.    int (*classificationmacros[12])(int);
  805.    int cellWidth, cellHeight;
  806.    char macronames[12][12];
  807.    TPoint boxTopLeft, boxBottomRight;
  808.    char characterString[L_CHARSTRING];
  809.  
  810.   DECLARE_RESPONSE_TABLE(TLocaleWindow);
  811. };
  812.  
  813. DEFINE_RESPONSE_TABLE1(TLocaleWindow, TWindow)
  814.   EV_WM_MOUSEMOVE,
  815.   EV_COMMAND(CM_ISALNUM, CMIsAlnum),
  816.   EV_COMMAND(CM_ISALPHA, CMIsAlpha),
  817.   EV_COMMAND(CM_ISASCII, CMIsAscii),
  818.   EV_COMMAND(CM_ISCNTRL, CMIsCntrl),
  819.   EV_COMMAND(CM_ISDIGIT, CMIsDigit),
  820.   EV_COMMAND(CM_ISGRAPH, CMIsGraph),
  821.   EV_COMMAND(CM_ISLOWER, CMIsLower),
  822.   EV_COMMAND(CM_ISPRINT, CMIsPrint),
  823.   EV_COMMAND(CM_ISPUNCT, CMIsPunct),
  824.   EV_COMMAND(CM_ISSPACE, CMIsSpace),
  825.   EV_COMMAND(CM_ISUPPER, CMIsUpper),
  826.   EV_COMMAND(CM_ISXDIGIT, CMIsXDigit),
  827. END_RESPONSE_TABLE;
  828.  
  829. void TLocaleWindow::Paint(TDC& hdc, BOOL, TRect&)
  830. {
  831.   char buf[100];
  832.   int maxWidth = 0;
  833.  
  834.   hdc.SelectStockObject(SYSTEM_FIXED_FONT);
  835.  
  836.   hdc.SetTextColor(RGB(0, 0, 0));
  837.   hdc.TextOut((30 * cxChar), (cyChar / 2), macronames[classification - alnum], strlen(macronames[classification - CM_ISALNUM]));
  838.   maxWidth = (10 * cxChar);
  839.  
  840.   #define COLUMNS 16
  841.   #define ROWS 16
  842.  
  843.   char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  844.  
  845.   //Display the codepoint values around the character set.
  846.   for (int i = 0; i < ROWS; i++)
  847.  {
  848.    sprintf(buf, "%c", hexChars[i]);
  849.    hdc.TextOut(maxWidth + ((i * 3) * cxChar), cyChar * 2 , buf, 1);
  850.    hdc.TextOut((maxWidth - (3 * cxChar)), cyChar * (i + 3), buf, 1);
  851.  }
  852.  
  853.   // display the character set in a ROWS x COLUMNS grid, with colours set by
  854.   // trueColor() and falseColor() according to the return value of the current
  855.   // classification function.
  856.   for (i = 0; i < ROWS; i++)
  857.    for (int j = 0; j < COLUMNS; j++)
  858.    {
  859.     int c = ((i * COLUMNS) + j);
  860.     sprintf(buf, "%c",  c);
  861.     classificationmacros[classification - alnum](c) ? trueColor(hdc) : falseColor(hdc);
  862.     if (c < 256) // in case we use different values for row/column.
  863.       hdc.TextOut(maxWidth + ((j * 3) * cxChar), cyChar * (i + 3), buf, 1);
  864.    }
  865.  
  866.  
  867.   // Draw a box round the characters.
  868.   #define X1  (maxWidth - 6)
  869.   #define Y1  ((3 * cyChar) - 2)
  870.   #define X2  ((maxWidth - 2) + (cxChar * (COLUMNS * 3)))
  871.   #define Y2  (((3 * cyChar) - 2) + (cyChar  * ROWS))
  872.  
  873.   boxTopLeft.x = X1;
  874.   boxTopLeft.y = Y1;
  875.   boxBottomRight.x = X2 - X1;
  876.   boxBottomRight.y = Y2 - Y1;
  877.  
  878.   cellWidth = (boxBottomRight.x / COLUMNS);
  879.   cellHeight = (boxBottomRight.y / ROWS);
  880.  
  881.   hdc.SelectObject(CreatePen(PS_SOLID, 1, RGB(0, 127, 127)));
  882.  
  883.   hdc.MoveTo(X1, Y1);
  884.   hdc.LineTo(X1, Y2);
  885.   hdc.LineTo(X2, Y2);
  886.   hdc.LineTo(X2, Y1);
  887.   hdc.LineTo(X1, Y1);
  888.  
  889.   for (i = 0; i < ROWS; i++)
  890.   {
  891.    hdc.MoveTo(X1, Y1 + (i * cyChar));
  892.    hdc.LineTo(X2, Y1 + (i * cyChar));
  893.   }
  894.  
  895.   for (i = 0; i < COLUMNS; i++)
  896.   {
  897.    hdc.MoveTo(X1 + ((i * 3) * cxChar), Y1);
  898.    hdc.LineTo(X1 + ((i * 3) * cxChar), Y2);
  899.   }
  900.   hdc.RestorePen();
  901. }
  902.  
  903.  
  904. //----------------------------------------------------------------------------
  905. //
  906. //
  907. //
  908. class TLocaleFrame : public TDecoratedFrame
  909. {
  910.    enum languages {langEnglish = CM_LANGUAGEENGLISH, langFrench, langGerman};
  911.    enum locales {locC = CM_LOCALEC, locUS, locUK, locFrench, locGerman};
  912.  
  913.   public:
  914.    TLocaleFrame(TWindow* client)
  915.    :TDecoratedFrame((TWindow*)0, (char*)0, client, TRUE)
  916.    {
  917.     pResourceModule = new TModule("APIENG.DLL");
  918.     tMenu = new TMenu(pResourceModule -> LoadMenu("MAINMENU"), AutoDelete);
  919.     valueWin = 0;
  920.     if (!HMENU(*tMenu))
  921.       throw "Error loading menu";
  922.  
  923.     locale = locC;
  924.     language = langEnglish;
  925.  
  926.     TWindowDC dc(HWindow);
  927.     dc.SelectStockObject(SYSTEM_FIXED_FONT);
  928.     TEXTMETRIC tm;
  929.     dc.GetTextMetrics (tm);
  930.     cxChar = tm.tmAveCharWidth;
  931.     cyChar = tm.tmHeight + tm.tmExternalLeading;
  932.     Attr.H = (cyChar * 25);
  933.     Attr.W = (cxChar * 80);
  934.    }
  935.  
  936.    virtual ~TLocaleFrame()
  937.    {
  938.     delete tMenu;
  939.     delete pResourceModule;
  940.    }
  941.  
  942.    void SetupWindow()
  943.    {
  944.     TDecoratedFrame::SetupWindow();
  945.  
  946.  
  947.     char szTitle[100];
  948.     pResourceModule -> LoadString(STR_APPNAME, szTitle, 100);
  949.     SetCaption(szTitle);
  950.     SetMenu(*tMenu);
  951.     tMenu -> CheckMenuItem(locale, MF_CHECKED);
  952.     tMenu -> CheckMenuItem(language, MF_CHECKED);
  953.     TYPESAFE_DOWNCAST(GetClientWindow(), TLocaleWindow) -> ChangeUI(pResourceModule);
  954.     conv = localeconv();
  955.    }
  956.  
  957.    void EvEnterIdle(UINT source, HWND hWndDlg)
  958.    {
  959.     //TDecoratedFrame::EvEnterIdle loads the help hint string, so
  960.     // we change the instance here so it gets it from pResourceModule
  961.     TModule* module = GetModule();
  962.     SetModule(pResourceModule);
  963.     TDecoratedFrame::EvEnterIdle(source, hWndDlg);
  964.     SetModule(module);
  965.    }
  966.  
  967.    void CMEnglishLanguage()
  968.    {
  969.     ChangeUI("apieng.dll", "English", langEnglish, LANG_ENGLISH);
  970.    }
  971.  
  972.    void CMFrenchLanguage()
  973.    {
  974.     ChangeUI("apifra.dll", "French", langFrench, LANG_FRENCH);
  975.    }
  976.  
  977.    void CMGermanLanguage()
  978.    {
  979.     ChangeUI("apiger.dll", "German", langGerman, LANG_GERMAN);
  980.    }
  981.  
  982.  
  983.    void CMFileList()
  984.    {
  985.     TFileListDialog(this, pResourceModule).Execute();
  986.    }
  987.  
  988.    void CMCLocale()
  989.    {
  990.     if (locale != locC)
  991.       ChangeLocale(LC_ALL, "C", locC);
  992.    }
  993.  
  994.    void CMUSLocale()
  995.    {
  996.     if (locale != locUS)
  997.       ChangeLocale(LC_ALL, "en_US.WIN1252", locUS);
  998.    }
  999.  
  1000.    void CMUKLocale()
  1001.    {
  1002.     if (locale != locUK)
  1003.       ChangeLocale(LC_ALL, "en_UK.WIN1252", locUK);
  1004.    }
  1005.  
  1006.    void CMFrenchLocale()
  1007.    {
  1008.     if (locale != locFrench)
  1009.       ChangeLocale(LC_ALL, "fr_FR.WIN1252", locFrench);
  1010.    }
  1011.  
  1012.    void CMGermanLocale()
  1013.    {
  1014.     if (locale != locGerman)
  1015.       ChangeLocale(LC_ALL, "de_DE.WIN1252", locGerman);
  1016.    }
  1017.  
  1018.    void CMShowValues()
  1019.    {
  1020.     if (!valueWin)
  1021.     {
  1022.       valueWin = new TLocaleValueWindow(conv, cxChar,
  1023.        cyChar, pResourceModule, this);
  1024.  
  1025.       valueWin -> Create();
  1026.       valueWin -> Show(SW_SHOW);
  1027.     }
  1028.     else
  1029.       valueWin -> SetFocus();
  1030.    }
  1031.  
  1032.    LRESULT WMValWndClose(WPARAM, LPARAM)
  1033.    {
  1034.     valueWin = 0;
  1035.     return 0;
  1036.    }
  1037.  
  1038.   protected:
  1039.    int ChangeUI(char* DLLName, char* langName, languages newLanguage, UINT countryCode)
  1040.    {
  1041.     delete pResourceModule;
  1042.     pResourceModule = new TModule(DLLName);
  1043.     delete tMenu;
  1044.     tMenu = new TMenu(pResourceModule -> LoadMenu("MAINMENU"), AutoDelete);
  1045.     SetMenu(*tMenu);
  1046.     tMenu -> CheckMenuItem(locale, MF_CHECKED);
  1047.     TYPESAFE_DOWNCAST(GetClientWindow(), TLocaleWindow) -> ChangeUI(pResourceModule);
  1048.  
  1049.     char szTitle[100];
  1050.     pResourceModule -> LoadString(STR_APPNAME, szTitle, 100);
  1051.     SetCaption(szTitle);
  1052.  
  1053.     Invalidate(TRUE);
  1054.     RedrawValueWindow();
  1055.     tMenu -> CheckMenuItem(language, MF_UNCHECKED);
  1056.     language = newLanguage;
  1057.     tMenu -> CheckMenuItem(language, MF_CHECKED);
  1058.     BWCCIntlTerm();
  1059.     BWCCIntlInit(countryCode);
  1060.     return 1;
  1061.    }
  1062.  
  1063.    char *ChangeLocale(int category, char *localeType, locales newLocale)
  1064.    {
  1065.     tMenu -> CheckMenuItem(locale, MF_UNCHECKED);
  1066.     locale = newLocale;
  1067.     tMenu -> CheckMenuItem(locale, MF_CHECKED);
  1068.  
  1069.     char *c = setlocale(category, localeType);
  1070.     conv = localeconv();
  1071.     Invalidate(TRUE);
  1072.     RedrawValueWindow();
  1073.     ChildWithId(ID_LOCALEWINDOW) -> Invalidate(TRUE);
  1074.     return c;
  1075.    }
  1076.  
  1077.    void RedrawValueWindow()
  1078.    {
  1079.     if (valueWin)
  1080.     {
  1081.       valueWin -> ResetValues(conv, cxChar,
  1082.        cyChar, pResourceModule);
  1083.       valueWin -> Invalidate(TRUE);
  1084.     }
  1085.    }
  1086.  
  1087.   private:
  1088.    languages language;
  1089.    locales   locale;
  1090.    TModule*  pResourceModule;
  1091.    TMenu*    tMenu;
  1092.    TLocaleValueWindow* valueWin;
  1093.    short     cxChar, cyChar, scrX, scrY;
  1094.    lconv*    conv;
  1095.  
  1096.   DECLARE_RESPONSE_TABLE(TLocaleFrame);
  1097. };
  1098.  
  1099. DEFINE_RESPONSE_TABLE1(TLocaleFrame, TDecoratedFrame)
  1100.   EV_WM_ENTERIDLE,
  1101.   EV_COMMAND(CM_FILELIST, CMFileList),
  1102.   EV_COMMAND(CM_LOCALEC, CMCLocale),
  1103.   EV_COMMAND(CM_LOCALEUS, CMUSLocale),
  1104.   EV_COMMAND(CM_LOCALEUK, CMUKLocale),
  1105.   EV_COMMAND(CM_LOCALEFRENCH, CMFrenchLocale),
  1106.   EV_COMMAND(CM_LOCALEGERMAN, CMGermanLocale),
  1107.   EV_COMMAND(CM_LANGUAGEENGLISH, CMEnglishLanguage),
  1108.   EV_COMMAND(CM_LANGUAGEFRENCH, CMFrenchLanguage),
  1109.   EV_COMMAND(CM_LANGUAGEGERMAN, CMGermanLanguage),
  1110.   EV_COMMAND(CM_SHOWVALUES, CMShowValues),
  1111.   EV_MESSAGE(WM_VALWNDCLOSE, WMValWndClose),
  1112. END_RESPONSE_TABLE;
  1113.  
  1114.  
  1115. //----------------------------------------------------------------------------
  1116. //
  1117. //
  1118. //
  1119. class TLocaleApplication : public TApplication
  1120. {
  1121.   public:
  1122.    TLocaleApplication():TApplication("Intl demo program")
  1123.    {
  1124.    }
  1125.  
  1126.    void InitMainWindow()
  1127.    {
  1128.     try
  1129.     {
  1130.       TLocaleFrame* frame = new TLocaleFrame(new TLocaleWindow);
  1131.       TStatusBar* sb = new TStatusBar(frame, TGadget::Recessed);
  1132.       frame->Insert(*sb, TDecoratedFrame::Bottom);
  1133.       MainWindow = frame;
  1134.         MainWindow->SetIcon(this, "World_Icon");
  1135.         EnableBWCC(TRUE, LANG_ENGLISH);
  1136.       }
  1137.       catch(const char *s)
  1138.       {
  1139.         BWCCMessageBox(0, s, "Intldemo", MB_OK);
  1140.       }
  1141.     }
  1142. };
  1143.  
  1144. int OwlMain(int /*argc*/, char* /*argv*/ [])
  1145. {
  1146.   return TLocaleApplication().Run();
  1147. }
  1148.