Changeset 142

Show
Ignore:
Timestamp:
Sat Jul 26 10:14:15 2008
Author:
mbutscher
Message:

branches/stable-1.8:

* Better handling of malformed regular expressions in

search fields
* Support for all uppercase and lowercase letters in the
Unicode set for creating camel-case wiki words
independent of OS language

Files:

Legend:

Unmodified
Added
Removed
Modified
  • branches/stable-1.8/WikidPadStarter.py

    r141 r142  
    25 25 # (2, 0, 200, 0) is 2.0final  
    26 26  
    27   VERSION_TUPLE = ("wikidPad", 1, 8, 113, 1)  
      27 VERSION_TUPLE = ("wikidPad", 1, 8, 114, 0)  
    27 27  
    28   VERSION_STRING = "wikidPad 1.8rc13_1"  
      28 VERSION_STRING = "wikidPad 1.8rc14"  
    28 28  
    29 29 if not hasattr(sys, 'frozen'):  
  • branches/stable-1.8/extensions/WikiSyntax.py

    r113 r142  
    3 3  
    4 4 import pwiki.srePersistent as re  
    5   from pwiki.StringOps import mbcsDec  
      5 from pwiki.StringOps import mbcsDec, UPPERCASE, LOWERCASE  
    5 5  
    6 6 locale.setlocale(locale.LC_ALL, '')  
    7 7  
    8    
    9 8 # String containing the delimiter between the title of a wiki word (to show in  
    10 9 # HTML and the real word, as e.g. [title | WikiWord]  
     
    76 75 # TODO To unicode  
    77 76  
    78   UPPERCASE = mbcsDec(string.uppercase)[0]  
    79   LOWERCASE = mbcsDec(string.lowercase)[0]  
      77 # UPPERCASE = mbcsDec(string.uppercase)[0]  
      78 # LOWERCASE = mbcsDec(string.lowercase)[0]  
    80 79 LETTERS = UPPERCASE + LOWERCASE  
    81 80  
  • branches/stable-1.8/wikidpad_unicode.iss

    r141 r142  
    39 39 SolidCompression=true  
    40 40 AppName=WikidPad  
    41   AppVerName=WikidPad 1.8rc13  
      41 AppVerName=WikidPad 1.8rc14  
    41 41 DefaultDirName={pf}\WikidPad  
    42 42 DefaultGroupName=WikidPad  
    43 43 AppID={{22A83C29-58A8-4CAB-8EDC-918D74F8429E}  
    44   VersionInfoVersion=1.8.113.1  
    45   VersionInfoTextVersion=WikidPad 1.8rc13  
      44 VersionInfoVersion=1.8.114.0  
      45 VersionInfoTextVersion=WikidPad 1.8rc14  
    46 46 LicenseFile=C:\DATEN\Projekte\Wikidpad\Current\license.txt  
    47 47 AllowNoIcons=true  
    48 48 ShowLanguageDialog=yes  
    49 49 Compression=lzma/ultra  
    50   OutputBaseFilename=WikidPad-1.8rc13  
      50 OutputBaseFilename=WikidPad-1.8rc14  
    50 50 InternalCompressLevel=ultra  
    51   AppCopyright=© 2005-2007 Jason Horman, Michael Butscher, Gerhard Reitmayr  
      51 AppCopyright=© 2005-2008 Jason Horman, Michael Butscher, Gerhard Reitmayr  
    51 51 UsePreviousAppDir=true  
    52 52 [Components]  
  • branches/stable-1.8/WikidPadHelp/data/ChangeLog.wiki

    r139 r142  
    2 2  
    3 3  
      4 Jul. 26, 2008 (1.8rc14)  
      5  
      6     * Better handling of malformed regular expressions  
      7       in search fields  
      8     * Support for all uppercase and lowercase letters in the  
      9       Unicode set for creating camel-case wiki words independent  
      10       of OS language  
      11  
      12  
      13  
    4 14 Jan. 25, 2008 (1.8rc13)  
    5 15  
  • branches/stable-1.8/lib/pwiki/wikidata/compact_sqlite/DbStructure.py

    r139 r142  
    872 872             searchOp.booleanOp = True  
    873 873  
      874             try:  
      875                 # Raises exception if search is invalid  
      876                 searchOp.rebuildSearchOpTree()  
      877             except:  
      878                 continue  
      879  
    874 880             datablock = searchOp.getPackedSettings()  
    875 881  
  • branches/stable-1.8/lib/pwiki/wikidata/original_gadfly/DbStructure.py

    r139 r142  
    617 617             searchOp.booleanOp = True  
    618 618  
      619             try:  
      620                 # Raises exception if search is invalid  
      621                 searchOp.rebuildSearchOpTree()  
      622             except:  
      623                 continue  
      624  
    619 625             datablock = searchOp.getPackedSettings()  
    620 626  
  • branches/stable-1.8/lib/pwiki/SearchAndReplaceDialogs.py

    r133 r142  
    191 191         self.Update()  
    192 192  
      193     def ensureNotShowSearching(self):  
      194         """  
      195         This function is called after a search operation and a call to  
      196         showFound may have happened. If it did not happen,  
      197         the list is cleared.  
      198         """  
      199         if self.isShowingSearching:  
      200             # This can only happend if showFound wasn't called  
      201             self.showFound(None, None, None)  
      202  
    193 203  
    194 204     def showFound(self, sarOp, found, wikiDocument):  
     
    265 275         self.SetItemCount(len(self.foundinfo))  
    266 276         self.Refresh()  
    267            
      277  
    267 277  
    268 278     def GetSelectedWord(self):  
     
    477 487             self.Thaw()  
    478 488             self.SetCursor(wx.NullCursor)  
      489             self.ctrls.htmllbPages.ensureNotShowSearching()  
    479 490  
    480 491  
    481 492     def OnSearchWiki(self, evt):  
    482           self._refreshPageList()  
    483           if not self.ctrls.htmllbPages.IsEmpty():  
    484               self.ctrls.htmllbPages.SetFocus()  
    485               self.ctrls.htmllbPages.SetSelection(0)  
    486                
      493         try:  
      494             self._refreshPageList()  
      495             if not self.ctrls.htmllbPages.IsEmpty():  
      496                 self.ctrls.htmllbPages.SetFocus()  
      497                 self.ctrls.htmllbPages.SetSelection(0)  
      498         except re.error, e:  
      499             self.pWiki.displayErrorMessage(u'Error in regular expression',  
      500                     unicode(e))  
      501  
      502  
    487 503     def OnSetPageList(self, evt):  
    488 504         """  
     
    521 537     def _findNext(self):  
    522 538         if self.listNeedsRefresh:  
    523               # Refresh list and start from beginning  
    524               self._refreshPageList()  
      539             try:  
      540                 # Refresh list and start from beginning  
      541                 self._refreshPageList()  
      542             except re.error, e:  
      543                 self.pWiki.displayErrorMessage(u'Error in regular expression',  
      544                         unicode(e))  
      545                 return  
    525 546              
    526 547         if self.ctrls.htmllbPages.GetCount() == 0:  
    527 548             return  
    528                
    529           while True:             
    530                    
    531               #########self.ctrls.lb.SetSelection(self.listPosNext)  
    532                
    533               wikiWord = guiToUni(self.ctrls.htmllbPages.GetSelectedWord())  
    534                
    535               if not wikiWord:  
    536                   self.ctrls.htmllbPages.SetSelection(0)  
    537                   wikiWord = guiToUni(self.ctrls.htmllbPages.GetSelectedWord())  
    538 549  
    539               if self.pWiki.getCurrentWikiWord() != wikiWord:  
    540                   self.pWiki.openWikiPage(wikiWord)  
    541                   nextOnPage = False  
    542               else:  
    543                   nextOnPage = True  
    544    
    545               searchOp = self.buildSearchReplaceOperation()  
    546               searchOp.replaceOp = False  
    547               if nextOnPage:  
    548                   pagePosNext = self.pWiki.getActiveEditor().executeSearch(searchOp,  
    549                           -2)[1]  
    550               else:  
    551                   pagePosNext = self.pWiki.getActiveEditor().executeSearch(searchOp,  
    552                           0)[1]  
    553                    
    554               if pagePosNext != -1:  
    555                   return  # Found  
      550         try:  
      551             while True:             
      552                 #########self.ctrls.lb.SetSelection(self.listPosNext)  
    556 553                  
    557               if self.ctrls.htmllbPages.GetSelection() == \  
    558                       self.ctrls.htmllbPages.GetCount() - 1:  
    559                   # Nothing more found on the last page in list, so back to  
    560                   # begin of list and stop  
    561                   self.ctrls.htmllbPages.SetSelection(0)  
    562                   return  
      554                 wikiWord = guiToUni(self.ctrls.htmllbPages.GetSelectedWord())  
    563 555                  
    564               # Otherwise: Go to next page in list             
    565               self.ctrls.htmllbPages.SetSelection(  
    566                       self.ctrls.htmllbPages.GetSelection() + 1)  
      556                 if not wikiWord:  
      557                     self.ctrls.htmllbPages.SetSelection(0)  
      558                     wikiWord = guiToUni(self.ctrls.htmllbPages.GetSelectedWord())  
      559      
      560                 if self.pWiki.getCurrentWikiWord() != wikiWord:  
      561                     self.pWiki.openWikiPage(wikiWord)  
      562                     nextOnPage = False  
      563                 else:  
      564                     nextOnPage = True  
      565      
      566                 searchOp = self.buildSearchReplaceOperation()  
      567                 searchOp.replaceOp = False  
      568                 if nextOnPage:  
      569                     pagePosNext = self.pWiki.getActiveEditor().executeSearch(searchOp,  
      570                             -2)[1]  
      571                 else:  
      572                     pagePosNext = self.pWiki.getActiveEditor().executeSearch(searchOp,  
      573                             0)[1]  
      574                      
      575                 if pagePosNext != -1:  
      576                     return  # Found  
      577                      
      578                 if self.ctrls.htmllbPages.GetSelection() == \  
      579                         self.ctrls.htmllbPages.GetCount() - 1:  
      580                     # Nothing more found on the last page in list, so back to  
      581                     # begin of list and stop  
      582                     self.ctrls.htmllbPages.SetSelection(0)  
      583                     return  
      584                      
      585                 # Otherwise: Go to next page in list             
      586                 self.ctrls.htmllbPages.SetSelection(  
      587                         self.ctrls.htmllbPages.GetSelection() + 1)  
      588         except re.error, e:  
      589             self.pWiki.displayErrorMessage(u'Error in regular expression',  
      590                     unicode(e))  
    567 591  
    568 592  
     
    582 606             return  
    583 607  
    584           self._refreshPageList()  
    585            
    586           if self.ctrls.htmllbPages.GetCount() == 0:  
    587               return  
      608         try:  
      609             self._refreshPageList()  
    588 610              
    589           # self.pWiki.saveCurrentDocPage()  
    590            
    591           sarOp = self.buildSearchReplaceOperation()  
    592           sarOp.replaceOp = True  
    593            
    594           # wikiData = self.pWiki.getWikiData()  
    595           wikiDocument = self.pWiki.getWikiDocument()  
    596    
    597           for i in xrange(self.ctrls.htmllbPages.GetCount()):  
    598               self.ctrls.htmllbPages.SetSelection(i)  
    599               wikiWord = guiToUni(self.ctrls.htmllbPages.GetSelectedWord())  
    600               wikiPage = wikiDocument.getWikiPageNoError(wikiWord)  
      611             if self.ctrls.htmllbPages.GetCount() == 0:  
      612                 return  
      613                  
      614             # self.pWiki.saveCurrentDocPage()  
      615              
      616             sarOp = self.buildSearchReplaceOperation()  
      617             sarOp.replaceOp = True  
      618              
      619             # wikiData = self.pWiki.getWikiData()  
      620             wikiDocument = self.pWiki.getWikiDocument()  
      621      
      622             for i in xrange(self.ctrls.htmllbPages.GetCount()):  
      623                 self.ctrls.htmllbPages.SetSelection(i)  
      624                 wikiWord = guiToUni(self.ctrls.htmllbPages.GetSelectedWord())  
      625                 wikiPage = wikiDocument.getWikiPageNoError(wikiWord)  
    601 626 #                 text = wikiData.getContent(wikiWord)  
    602               text = wikiPage.getLiveTextNoTemplate()  
    603               if text is None:  
    604                   continue  
    605    
    606               charStartPos = 0  
    607    
    608               while True:  
    609                   try:  
    610                       found = sarOp.searchText(text, charStartPos)  
    611                       start, end = found[:2]  
    612                   except:  
    613                       # Regex error -> Stop searching  
    614                       return  
      627                 text = wikiPage.getLiveTextNoTemplate()  
      628                 if text is None:  
      629                     continue  
      630      
      631                 charStartPos = 0  
      632      
      633                 while True:  
      634                     try:  
      635                         found = sarOp.searchText(text, charStartPos)  
      636                         start, end = found[:2]  
      637                     except:  
      638                         # Regex error -> Stop searching  
      639                         return  
      640                          
      641                     if start is None: break  
    615 642                      
    616                   if start is None: break  
    617                    
    618                   repl = sarOp.replace(text, found)  
    619                   text = text[:start] + repl + text[end:]  # TODO Faster?  
    620                   charStartPos = start + len(repl)  
    621    
      643                     repl = sarOp.replace(text, found)  
      644                     text = text[:start] + repl + text[end:]  # TODO Faster?  
      645                     charStartPos = start + len(repl)  
      646      
    622 647 #                 wikiData.setContent(wikiWord, text)  
    623               wikiPage.replaceLiveText(text)  
    624                
      648                 wikiPage.replaceLiveText(text)  
      649                  
    625 650 #             # Reopen current word because its content could have been overwritten before  
    626 651 #             self.pWiki.openWikiPage(self.pWiki.getCurrentWikiWord(),  
    627 652 #                     addToHistory=False, forceReopen=True)  
    628                    
    629           self._refreshPageList()  
      653                      
      654             self._refreshPageList()  
      655  
      656         except re.error, e:  
      657             self.pWiki.displayErrorMessage(u'Error in regular expression',  
      658                     unicode(e))  
    630 659  
    631 660  
     
    634 663     def OnSaveSearch(self, evt):  
    635 664         sarOp = self.buildSearchReplaceOperation()  
      665         try:  
      666             sarOp.rebuildSearchOpTree()  
      667         except re.error, e:  
      668             self.pWiki.displayErrorMessage(u'Error in regular expression',  
      669                     unicode(e))  
      670             return  
    636 671          
    637 672         if len(sarOp.searchStr) > 0:  
     
    715 750     def OnLoadAndRunSearch(self, evt):  
    716 751         if self._loadSearch():  
    717               self._refreshPageList()  
      752             try:  
      753                 self._refreshPageList()  
      754             except re.error, e:  
      755                 self.pWiki.displayErrorMessage(u'Error in regular expression',  
      756                         unicode(e))  
      757  
    718 758  
    719 759     def _loadSearch(self):  
     
    858 898         sarOp = self._buildSearchOperation()  
    859 899         sarOp.replaceOp = False  
    860           self._nextSearch(sarOp)  
    861    
    862           self.firstFind = False  
      900         try:  
      901             self._nextSearch(sarOp)  
      902             self.firstFind = False  
      903         except re.error, e:  
      904             self.pWiki.displayErrorMessage(u'Error in regular expression',  
      905                     unicode(e))  
    863 906  
    864 907  
     
    1019 1062             except re.error, e:  
    1020 1063                 wx.MessageBox("Bad regular expression '%s':\n%s" %  
    1021                           (pattern, unicode(e)), u"Regular expression error",  
      1064                         (pattern, unicode(e)), u"Error in regular expression",  
    1021 1064                         wx.OK, self)  
    1022 1065                 return None  
     
    1328 1371         """  
    1329 1372         self.searchText = text  
    1330           self._refreshPageList()  
      1373         try:  
      1374             self._refreshPageList()  
      1375         except re.error, e:  
      1376             self.mainControl.displayErrorMessage(u'Error in regular expression',  
      1377                     unicode(e))  
    1331 1378  
    1332 1379  
     
    1353 1400             self.Thaw()  
    1354 1401             self.SetCursor(wx.NullCursor)  
      1402             self.resultBox.ensureNotShowSearching()  
      1403  
  • branches/stable-1.8/lib/pwiki/StringOps.py

    r139 r142  
    923 923     return compactToBinCompact(difflibToCompact(ops, b))  
    924 924  
      925  
      926 # ---------- Unicode constants ----------  
      927  
      928 # UPPERCASE = None  
      929 # LOWERCASE = None  
      930 #  
      931 # def _fillConsts():  
      932 #     global UPPERCASE, LOWERCASE  
      933 #     from unicodedata import category  
      934 #       
      935 #     uc = []  
      936 #     lc = []  
      937 #       
      938 #     for i in xrange(0, 0x10000):  
      939 #         c = unichr(i)  
      940 #         if category(c) == "Ll":  
      941 #             lc.append(c)  
      942 #         elif category(c) == "Lu":  
      943 #             uc.append(c)  
      944 #       
      945 #     UPPERCASE = u"".join(uc)  
      946 #     LOWERCASE = u"".join(lc)  
      947 #  
      948 # _fillConsts()  
      949  
      950  
      951 # Interestingly it isn't noticeably faster to set the constants directly than  
      952 # calculating it at each start, but it doesn't need "unicodedata.pyd"  
      953  
      954 LOWERCASE = u'abcdefghijklmnopqrstuvwxyz\xaa\xb5\xba\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\u0101\u0103\u0105\u0107\u0109\u010b\u010d\u010f\u0111\u0113\u0115\u0117\u0119\u011b\u011d\u011f\u0121\u0123\u0125\u0127\u0129\u012b\u012d\u012f\u0131\u0133\u0135\u0137\u0138\u013a\u013c\u013e\u0140\u0142\u0144\u0146\u0148\u0149\u014b\u014d\u014f\u0151\u0153\u0155\u0157\u0159\u015b\u015d\u015f\u0161\u0163\u0165\u0167\u0169\u016b\u016d\u016f\u0171\u0173\u0175\u0177\u017a\u017c\u017e\u017f\u0180\u0183\u0185\u0188\u018c\u018d\u0192\u0195\u0199\u019a\u019b\u019e\u01a1\u01a3\u01a5\u01a8\u01aa\u01ab\u01ad\u01b0\u01b4\u01b6\u01b9\u01ba\u01bd\u01be\u01bf\u01c6\u01c9\u01cc\u01ce\u01d0\u01d2\u01d4\u01d6\u01d8\u01da\u01dc\u01dd\u01df\u01e1\u01e3\u01e5\u01e7\u01e9\u01eb\u01ed\u01ef\u01f0\u01f3\u01f5\u01f9\u01fb\u01fd\u01ff\u0201\u0203\u0205\u0207\u0209\u020b\u020d\u020f\u0211\u0213\u0215\u0217\u0219\u021b\u021d\u021f\u0223\u0225\u0227\u0229\u022b\u022d\u022f\u0231\u0233\u0250\u0251\u0252\u0253\u0254\u0255\u0256\u0257\u0258\u0259\u025a\u025b\u025c\u025d\u025e\u025f\u0260\u0261\u0262\u0263\u0264\u0265\u0266\u0267\u0268\u0269\u026a\u026b\u026c\u026d\u026e\u026f\u0270\u0271\u0272\u0273\u0274\u0275\u0276\u0277\u0278\u0279\u027a\u027b\u027c\u027d\u027e\u027f\u0280\u0281\u0282\u0283\u0284\u0285\u0286\u0287\u0288\u0289\u028a\u028b\u028c\u028d\u028e\u028f\u0290\u0291\u0292\u0293\u0294\u0295\u0296\u0297\u0298\u0299\u029a\u029b\u029c\u029d\u029e\u029f\u02a0\u02a1\u02a2\u02a3\u02a4\u02a5\u02a6\u02a7\u02a8\u02a9\u02aa\u02ab\u02ac\u02ad\u0390\u03ac\u03ad\u03ae\u03af\u03b0\u03b1\u03b2\u03b3\u03b4\u03b5\u03b6\u03b7\u03b8\u03b9\u03ba\u03bb\u03bc\u03bd\u03be\u03bf\u03c0\u03c1\u03c2\u03c3\u03c4\u03c5\u03c6\u03c7\u03c8\u03c9\u03ca\u03cb\u03cc\u03cd\u03ce\u03d0\u03d1\u03d5\u03d6\u03d7\u03d9\u03db\u03dd\u03df\u03e1\u03e3\u03e5\u03e7\u03e9\u03eb\u03ed\u03ef\u03f0\u03f1\u03f2\u03f3\u03f5\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f\u0450\u0451\u0452\u0453\u0454\u0455\u0456\u0457\u0458\u0459\u045a\u045b\u045c\u045d\u045e\u045f\u0461\u0463\u0465\u0467\u0469\u046b\u046d\u046f\u0471\u0473\u0475\u0477\u0479\u047b\u047d\u047f\u0481\u048b\u048d\u048f\u0491\u0493\u0495\u0497\u0499\u049b\u049d\u049f\u04a1\u04a3\u04a5\u04a7\u04a9\u04ab\u04ad\u04af\u04b1\u04b3\u04b5\u04b7\u04b9\u04bb\u04bd\u04bf\u04c2\u04c4\u04c6\u04c8\u04ca\u04cc\u04ce\u04d1\u04d3\u04d5\u04d7\u04d9\u04db\u04dd\u04df\u04e1\u04e3\u04e5\u04e7\u04e9\u04eb\u04ed\u04ef\u04f1\u04f3\u04f5\u04f9\u0501\u0503\u0505\u0507\u0509\u050b\u050d\u050f\u0561\u0562\u0563\u0564\u0565\u0566\u0567\u0568\u0569\u056a\u056b\u056c\u056d\u056e\u056f\u0570\u0571\u0572\u0573\u0574\u0575\u0576\u0577\u0578\u0579\u057a\u057b\u057c\u057d\u057e\u057f\u0580\u0581\u0582\u0583\u0584\u0585\u0586\u0587\u1e01\u1e03\u1e05\u1e07\u1e09\u1e0b\u1e0d\u1e0f\u1e11\u1e13\u1e15\u1e17\u1e19\u1e1b\u1e1d\u1e1f\u1e21\u1e23\u1e25\u1e27\u1e29\u1e2b\u1e2d\u1e2f\u1e31\u1e33\u1e35\u1e37\u1e39\u1e3b\u1e3d\u1e3f\u1e41\u1e43\u1e45\u1e47\u1e49\u1e4b\u1e4d\u1e4f\u1e51\u1e53\u1e55\u1e57\u1e59\u1e5b\u1e5d\u1e5f\u1e61\u1e63\u1e65\u1e67\u1e69\u1e6b\u1e6d\u1e6f\u1e71\u1e73\u1e75\u1e77\u1e79\u1e7b\u1e7d\u1e7f\u1e81\u1e83\u1e85\u1e87\u1e89\u1e8b\u1e8d\u1e8f\u1e91\u1e93\u1e95\u1e96\u1e97\u1e98\u1e99\u1e9a\u1e9b\u1ea1\u1ea3\u1ea5\u1ea7\u1ea9\u1eab\u1ead\u1eaf\u1eb1\u1eb3\u1eb5\u1eb7\u1eb9\u1ebb\u1ebd\u1ebf\u1ec1\u1ec3\u1ec5\u1ec7\u1ec9\u1ecb\u1ecd\u1ecf\u1ed1\u1ed3\u1ed5\u1ed7\u1ed9\u1edb\u1edd\u1edf\u1ee1\u1ee3\u1ee5\u1ee7\u1ee9\u1eeb\u1eed\u1eef\u1ef1\u1ef3\u1ef5\u1ef7\u1ef9\u1f00\u1f01\u1f02\u1f03\u1f04\u1f05\u1f06\u1f07\u1f10\u1f11\u1f12\u1f13\u1f14\u1f15\u1f20\u1f21\u1f22\u1f23\u1f24\u1f25\u1f26\u1f27\u1f30\u1f31\u1f32\u1f33\u1f34\u1f35\u1f36\u1f37\u1f40\u1f41\u1f42\u1f43\u1f44\u1f45\u1f50\u1f51\u1f52\u1f53\u1f54\u1f55\u1f56\u1f57\u1f60\u1f61\u1f62\u1f63\u1f64\u1f65\u1f66\u1f67\u1f70\u1f71\u1f72\u1f73\u1f74\u1f75\u1f76\u1f77\u1f78\u1f79\u1f7a\u1f7b\u1f7c\u1f7d\u1f80\u1f81\u1f82\u1f83\u1f84\u1f85\u1f86\u1f87\u1f90\u1f91\u1f92\u1f93\u1f94\u1f95\u1f96\u1f97\u1fa0\u1fa1\u1fa2\u1fa3\u1fa4\u1fa5\u1fa6\u1fa7\u1fb0\u1fb1\u1fb2\u1fb3\u1fb4\u1fb6\u1fb7\u1fbe\u1fc2\u1fc3\u1fc4\u1fc6\u1fc7\u1fd0\u1fd1\u1fd2\u1fd3\u1fd6\u1fd7\u1fe0\u1fe1\u1fe2\u1fe3\u1fe4\u1fe5\u1fe6\u1fe7\u1ff2\u1ff3\u1ff4\u1ff6\u1ff7\u2071\u207f\u210a\u210e\u210f\u2113\u212f\u2134\u2139\u213d\u2146\u2147\u2148\u2149\ufb00\ufb01\ufb02\ufb03\ufb04\ufb05\ufb06\ufb13\ufb14\ufb15\ufb16\ufb17\uff41\uff42\uff43\uff44\uff45\uff46\uff47\uff48\uff49\uff4a\uff4b\uff4c\uff4d\uff4e\uff4f\uff50\uff51\uff52\uff53\uff54\uff55\uff56\uff57\uff58\uff59\uff5a'  
      955 UPPERCASE = u'ABCDEFGHIJKLMNOPQRSTUVWXYZ\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xd9\xda\xdb\xdc\xdd\xde\u0100\u0102\u0104\u0106\u0108\u010a\u010c\u010e\u0110\u0112\u0114\u0116\u0118\u011a\u011c\u011e\u0120\u0122\u0124\u0126\u0128\u012a\u012c\u012e\u0130\u0132\u0134\u0136\u0139\u013b\u013d\u013f\u0141\u0143\u0145\u0147\u014a\u014c\u014e\u0150\u0152\u0154\u0156\u0158\u015a\u015c\u015e\u0160\u0162\u0164\u0166\u0168\u016a\u016c\u016e\u0170\u0172\u0174\u0176\u0178\u0179\u017b\u017d\u0181\u0182\u0184\u0186\u0187\u0189\u018a\u018b\u018e\u018f\u0190\u0191\u0193\u0194\u0196\u0197\u0198\u019c\u019d\u019f\u01a0\u01a2\u01a4\u01a6\u01a7\u01a9\u01ac\u01ae\u01af\u01b1\u01b2\u01b3\u01b5\u01b7\u01b8\u01bc\u01c4\u01c7\u01ca\u01cd\u01cf\u01d1\u01d3\u01d5\u01d7\u01d9\u01db\u01de\u01e0\u01e2\u01e4\u01e6\u01e8\u01ea\u01ec\u01ee\u01f1\u01f4\u01f6\u01f7\u01f8\u01fa\u01fc\u01fe\u0200\u0202\u0204\u0206\u0208\u020a\u020c\u020e\u0210\u0212\u0214\u0216\u0218\u021a\u021c\u021e\u0220\u0222\u0224\u0226\u0228\u022a\u022c\u022e\u0230\u0232\u0386\u0388\u0389\u038a\u038c\u038e\u038f\u0391\u0392\u0393\u0394\u0395\u0396\u0397\u0398\u0399\u039a\u039b\u039c\u039d\u039e\u039f\u03a0\u03a1\u03a3\u03a4\u03a5\u03a6\u03a7\u03a8\u03a9\u03aa\u03ab\u03d2\u03d3\u03d4\u03d8\u03da\u03dc\u03de\u03e0\u03e2\u03e4\u03e6\u03e8\u03ea\u03ec\u03ee\u03f4\u0400\u0401\u0402\u0403\u0404\u0405\u0406\u0407\u0408\u0409\u040a\u040b\u040c\u040d\u040e\u040f\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0460\u0462\u0464\u0466\u0468\u046a\u046c\u046e\u0470\u0472\u0474\u0476\u0478\u047a\u047c\u047e\u0480\u048a\u048c\u048e\u0490\u0492\u0494\u0496\u0498\u049a\u049c\u049e\u04a0\u04a2\u04a4\u04a6\u04a8\u04aa\u04ac\u04ae\u04b0\u04b2\u04b4\u04b6\u04b8\u04ba\u04bc\u04be\u04c0\u04c1\u04c3\u04c5\u04c7\u04c9\u04cb\u04cd\u04d0\u04d2\u04d4\u04d6\u04d8\u04da\u04dc\u04de\u04e0\u04e2\u04e4\u04e6\u04e8\u04ea\u04ec\u04ee\u04f0\u04f2\u04f4\u04f8\u0500\u0502\u0504\u0506\u0508\u050a\u050c\u050e\u0531\u0532\u0533\u0534\u0535\u0536\u0537\u0538\u0539\u053a\u053b\u053c\u053d\u053e\u053f\u0540\u0541\u0542\u0543\u0544\u0545\u0546\u0547\u0548\u0549\u054a\u054b\u054c\u054d\u054e\u054f\u0550\u0551\u0552\u0553\u0554\u0555\u0556\u10a0\u10a1\u10a2\u10a3\u10a4\u10a5\u10a6\u10a7\u10a8\u10a9\u10aa\u10ab\u10ac\u10ad\u10ae\u10af\u10b0\u10b1\u10b2\u10b3\u10b4\u10b5\u10b6\u10b7\u10b8\u10b9\u10ba\u10bb\u10bc\u10bd\u10be\u10bf\u10c0\u10c1\u10c2\u10c3\u10c4\u10c5\u1e00\u1e02\u1e04\u1e06\u1e08\u1e0a\u1e0c\u1e0e\u1e10\u1e12\u1e14\u1e16\u1e18\u1e1a\u1e1c\u1e1e\u1e20\u1e22\u1e24\u1e26\u1e28\u1e2a\u1e2c\u1e2e\u1e30\u1e32\u1e34\u1e36\u1e38\u1e3a\u1e3c\u1e3e\u1e40\u1e42\u1e44\u1e46\u1e48\u1e4a\u1e4c\u1e4e\u1e50\u1e52\u1e54\u1e56\u1e58\u1e5a\u1e5c\u1e5e\u1e60\u1e62\u1e64\u1e66\u1e68\u1e6a\u1e6c\u1e6e\u1e70\u1e72\u1e74\u1e76\u1e78\u1e7a\u1e7c\u1e7e\u1e80\u1e82\u1e84\u1e86\u1e88\u1e8a\u1e8c\u1e8e\u1e90\u1e92\u1e94\u1ea0\u1ea2\u1ea4\u1ea6\u1ea8\u1eaa\u1eac\u1eae\u1eb0\u1eb2\u1eb4\u1eb6\u1eb8\u1eba\u1ebc\u1ebe\u1ec0\u1ec2\u1ec4\u1ec6\u1ec8\u1eca\u1ecc\u1ece\u1ed0\u1ed2\u1ed4\u1ed6\u1ed8\u1eda\u1edc\u1ede\u1ee0\u1ee2\u1ee4\u1ee6\u1ee8\u1eea\u1eec\u1eee\u1ef0\u1ef2\u1ef4\u1ef6\u1ef8\u1f08\u1f09\u1f0a\u1f0b\u1f0c\u1f0d\u1f0e\u1f0f\u1f18\u1f19\u1f1a\u1f1b\u1f1c\u1f1d\u1f28\u1f29\u1f2a\u1f2b\u1f2c\u1f2d\u1f2e\u1f2f\u1f38\u1f39\u1f3a\u1f3b\u1f3c\u1f3d\u1f3e\u1f3f\u1f48\u1f49\u1f4a\u1f4b\u1f4c\u1f4d\u1f59\u1f5b\u1f5d\u1f5f\u1f68\u1f69\u1f6a\u1f6b\u1f6c\u1f6d\u1f6e\u1f6f\u1fb8\u1fb9\u1fba\u1fbb\u1fc8\u1fc9\u1fca\u1fcb\u1fd8\u1fd9\u1fda\u1fdb\u1fe8\u1fe9\u1fea\u1feb\u1fec\u1ff8\u1ff9\u1ffa\u1ffb\u2102\u2107\u210b\u210c\u210d\u2110\u2111\u2112\u2115\u2119\u211a\u211b\u211c\u211d\u2124\u2126\u2128\u212a\u212b\u212c\u212d\u2130\u2131\u2133\u213e\u213f\u2145\uff21\uff22\uff23\uff24\uff25\uff26\uff27\uff28\uff29\uff2a\uff2b\uff2c\uff2d\uff2e\uff2f\uff30\uff31\uff32\uff33\uff34\uff35\uff36\uff37\uff38\uff39\uff3a'