rtoss - Blame information for rev 146

Subversion Repositories:
Rev:
Rev Author Line No. Line
89 roytam 1  
2 #include "stdafx.h"
3 #include "ConfigManager.h"
4 #include "rsrc/resource.h"
5 #include "RSearch.h"
6 using namespace ki;
7 using namespace editwing;
8  
9  
10  
11 void BootNewProcess( const TCHAR* cmd ); // in GpMain.cpp
12  
13 //-------------------------------------------------------------------------
14 // 設定項目管理。
15 // SetDocTypeで切り替えると、文書タイプ依存の項目を自動で
16 // 入れ替えたり色々。
17 //-------------------------------------------------------------------------
18  
19 ConfigManager::ConfigManager()
20 {
21         // デフォルトのレイアウト設定は何よりも先に読んでおく
22         DocType d;
23         d.name.Load( IDS_DEFAULT );
24         d.layfile   = TEXT("default.lay");
25         LoadLayout( &d );
26         dtList_.Add( d );
27         curDt_ = dtList_.begin();
28  
29         // ini読み込み
30         LoadIni();
31         SetDocTypeByName( newfileDoctype_ );
32 }
33  
34 ConfigManager::~ConfigManager()
35 {
36         // ini保存
37         SaveIni();
38 }
39  
40 void ConfigManager::SetDocTypeByName( const ki::String& nam )
41 {
42         curDt_             = dtList_.begin();
43         DtList::iterator b = dtList_.begin();
44         DtList::iterator e = dtList_.end();
45         for( ; b!=e; ++b )
46                 if( b->name == nam )
47                 {
48                         curDt_ = b;
49                         break;
50                 }
51         LoadLayout( &*curDt_ );
52 }
53  
54 int ConfigManager::SetDocType( const Path& fname )
55 {
56         const unicode* uname = fname.ConvToWChar();
57  
58         int ct = 1;
59         DtList::iterator i=dtList_.begin(), e=dtList_.end();
60         if( fname.len() > 0 )
61         {
62                 for( ++i; i!=e; ++i, ++ct )
63                         if( i->pattern.len() > 0 )
64                         {
65                                 const unicode* upat = i->pattern.ConvToWChar();
66                                 bool b = MatchDocType( uname, upat );
67                                 i->pattern.FreeWCMem( upat );
68                                 if( b ) break;
69                         }
70                 if( i == e )
71                         ct=0, i=dtList_.begin(); // 適切なのが見つからなければ[標準]。
72         }
73         else
74         {
75                 ct = 0;
76         }
77  
78         SetDocTypeByName( i->name );
79  
80         fname.FreeWCMem( uname );
81         return ct;
82 }
83  
84 bool ConfigManager::MatchDocType
85         ( const unicode* fname, const unicode* pat )
86 {
87         // pattern と fname とのマッチをとって判定…
88         return reg_match( pat, fname, false );
89 }
90  
91  
92  
93 //-------------------------------------------------------------------------
94 // 設定ダイアログ関連
95 //-------------------------------------------------------------------------
96  
97 struct ConfigDlg : public ki::DlgImpl
98 {
99 private:
100         typedef ConfigManager::DtList::iterator DTI;
101         ulong curSel_;
102         void SaveDt()
103         {
104                 DTI p=myDtl_.begin(), e=myDtl_.end();
105                 for( ulong ct=0; p!=e && ct!=curSel_; ++ct,++p );
106                 if( p==e ) return;
107  
108                 TCHAR buf[256];
109                 SendMsgToItem(IDC_DT_PAT, WM_GETTEXT,
110                         countof(buf),reinterpret_cast<LPARAM>(buf));
111                 p->pattern = buf;
112  
113                 SendMsgToItem(IDC_PAT_KWD, CB_GETLBTEXT,
114                         SendMsgToItem(IDC_PAT_KWD, CB_GETCURSEL),
115                         reinterpret_cast<LPARAM>(buf) );
116                 p->kwdfile = buf;
117  
118                 SendMsgToItem(IDC_PAT_LAY, CB_GETLBTEXT,
119                         SendMsgToItem(IDC_PAT_LAY, CB_GETCURSEL),
120                         reinterpret_cast<LPARAM>(buf) );
121                 p->layfile = buf;
122         }
123         void SelDt(ulong i)
124         {
125                 DTI p=myDtl_.begin(), e=myDtl_.end();
126                 for( ulong ct=0; p!=e && ct!=i; ++ct,++p );
127                 if( p==e ) return;
128  
129                 curSel_ = i;
130                 SendMsgToItem(IDC_DT_PAT, WM_SETTEXT, p->pattern.c_str());
131                 if( p->kwdfile.len()==0 )
132                         SendMsgToItem(IDC_PAT_KWD, CB_SETCURSEL);
133                 else
134                         SendMsgToItem(IDC_PAT_KWD,CB_SELECTSTRING,p->kwdfile.c_str());
135                 SendMsgToItem(IDC_PAT_LAY,CB_SELECTSTRING,p->layfile.c_str());
136         }
137         void on_deldoctype()
138         {
139                 ulong ct;
140                 DTI p=myDtl_.begin(), e=myDtl_.end();
141                 for( ct=0; p!=e && ct!=curSel_; ++ct,++p );
142                 if( p==e ) return;
143  
144                 String msg = TEXT("[");
145                 msg += p->name, msg += TEXT("]"), msg += String(IDS_OKTODEL);
146                 if( IDNO ==
147                         MsgBox( msg.c_str(), String(IDS_APPNAME).c_str(), MB_YESNO ) )
148                         return;
149  
150                 myDtl_.Del(p);
151                 SendMsgToItem( IDC_DOCTYPELIST, LB_DELETESTRING, ct );
152                 SelDt(0);
153                 if( ct+1 == (ulong)SendMsgToItem(IDC_NEWDT,CB_GETCURSEL) )
154                         SendMsgToItem( IDC_NEWDT, CB_SETCURSEL );
155                 SendMsgToItem( IDC_NEWDT, CB_DELETESTRING, ct+1 );
156         }
157         void on_newdoctype()
158         {
159                 struct NewDocTypeDlg : public DlgImpl
160                 {
161                         NewDocTypeDlg(HWND wnd)
162                                 : DlgImpl(IDD_ADDDOCTYPE) { GoModal(wnd); }
163                         virtual bool on_ok()
164                         {
165                                 TCHAR buf[MAX_PATH];
166                                 SendMsgToItem(IDC_NAME, WM_GETTEXT,
167                                         countof(buf),reinterpret_cast<LPARAM>(buf));
168                                 name = buf;
169                                 SendMsgToItem(IDC_EXT, WM_GETTEXT,
170                                         countof(buf),reinterpret_cast<LPARAM>(buf));
171                                 ext=buf;
172                                 return true;
173                         }
174                         String name;
175                         String ext;
176                 } dlg( hwnd() );
177                 if( IDOK == dlg.endcode() )
178                 {
179                         ConfigManager::DocType ndt;
180                         TCHAR buf[200];
181                         SendMsgToItem(IDC_PAT_KWD, CB_GETLBTEXT,
182                                 SendMsgToItem(IDC_PAT_KWD, CB_GETCURSEL),
183                                 reinterpret_cast<LPARAM>(buf) );
184                         ndt.kwdfile = buf;
185                         SendMsgToItem(IDC_PAT_LAY, CB_GETLBTEXT,
186                                 SendMsgToItem(IDC_PAT_LAY, CB_GETCURSEL),
187                                 reinterpret_cast<LPARAM>(buf) );
188                         ndt.layfile = buf;
189                         ndt.name = dlg.name;
190                         ndt.pattern = TEXT(".*\\.")+dlg.ext+TEXT("$");
191                         myDtl_.Add(ndt);
192                         SendMsgToItem( IDC_DOCTYPELIST, LB_ADDSTRING,
193                                 ndt.name.c_str() );
194                         SendMsgToItem( IDC_NEWDT, CB_ADDSTRING,
195                                 ndt.name.c_str() );
196                 }
197         }
198  
199 public:
200         ConfigDlg( ConfigManager& cfg, HWND wnd )
201                 : cfg_( cfg )
202                 , DlgImpl( IDD_CONFIG )
203                 , curSel_( 0xffffffff )
204         {
205                 for( DTI i=++cfg_.dtList_.begin(); i!=cfg_.dtList_.end(); ++i )
206                         myDtl_.Add( *i );
207                 GoModal( wnd );
208         }
209  
210 private:
211         void on_init()
212         {
213                 SendMsgToItem(IDC_LATEST_NUM, WM_SETTEXT,
214                         String().SetInt(cfg_.mrus_).c_str() );
215                 if( cfg_.undoLimit() == -1 )
216                 {
217                         SendMsgToItem(IDC_UNDOLIM1, BM_SETCHECK, BST_CHECKED);
218                         SendMsgToItem(IDC_UNDO_CT, WM_SETTEXT, TEXT("20") );
219                 }
220                 else
221                 {
222                         SendMsgToItem(IDC_UNDOLIM2, BM_SETCHECK, BST_CHECKED);
223                         SendMsgToItem(IDC_UNDO_CT, WM_SETTEXT,
224                                 String().SetInt(cfg_.undoLimit()).c_str() );
225                 }
226                 if( cfg_.countByUnicode() )
227                 {
228                         SendMsgToItem(IDC_COUNTBYLETTER,  BM_SETCHECK, BST_CHECKED);
229                         SendMsgToItem(IDC_COUNTBYLETTER2, BM_SETCHECK);
230                 }
231                 else
232                 {
233                         SendMsgToItem(IDC_COUNTBYLETTER,  BM_SETCHECK);
234                         SendMsgToItem(IDC_COUNTBYLETTER2, BM_SETCHECK, BST_CHECKED);
235                 }
236  
237                 SendMsgToItem(IDC_TXTFILT, WM_SETTEXT,
238                         cfg_.txtFileFilter().c_str() );
239                 SendMsgToItem(IDC_EXTGREP, WM_SETTEXT,
240                         cfg_.grepExe().c_str() );
241  
242                 if( cfg_.openSame() )
243                         SendMsgToItem(IDC_OPENSAME, BM_SETCHECK, BST_CHECKED);
244                 if( cfg_.rememberWindowSize_ )
245                         SendMsgToItem(IDC_REMSIZE, BM_SETCHECK, BST_CHECKED);
246                 if( cfg_.rememberWindowPlace_ )
247                         SendMsgToItem(IDC_REMPLACE, BM_SETCHECK, BST_CHECKED);
248  
249                 CharSetList& csl = cfg_.GetCharSetList();
250                 for(ulong i=1; i<csl.size(); ++i)
251                         SendMsgToItem( IDC_NEWCS, CB_ADDSTRING, csl[i].longName );
252                 SendMsgToItem( IDC_NEWCS, CB_SETCURSEL, csl.findCsi(cfg_.newfileCharset_)-1 );
253                 SendMsgToItem( IDC_NEWLB, CB_ADDSTRING, TEXT("CR") );
254                 SendMsgToItem( IDC_NEWLB, CB_ADDSTRING, TEXT("LF") );
255                 SendMsgToItem( IDC_NEWLB, CB_ADDSTRING, TEXT("CRLF") );
256                 SendMsgToItem( IDC_NEWLB, CB_SETCURSEL, cfg_.newfileLB_ );
257  
258                 ulong nfd_idx=0, nfd_cnt=1;
259                 SendMsgToItem( IDC_NEWDT, CB_ADDSTRING,
260                         cfg_.dtList_.begin()->name.c_str() );
261                 for( DTI i=myDtl_.begin(), e=myDtl_.end(); i!=e; ++i,++nfd_cnt )
262                 {
263                         SendMsgToItem( IDC_DOCTYPELIST, LB_ADDSTRING,
264                                 i->name.c_str() );
265                         SendMsgToItem( IDC_NEWDT, CB_ADDSTRING,
266                                 i->name.c_str() );
267                         if( i->name == cfg_.newfileDoctype_ )
268                                 nfd_idx = nfd_cnt;
269                 }
270                 SendMsgToItem( IDC_NEWDT, CB_SETCURSEL, nfd_idx );
271  
272                 FindFile f;
273                 WIN32_FIND_DATA fd;
274                 f.Begin( (Path(Path::Exe)+=TEXT("type\\*.kwd")).c_str() );
275                 SendMsgToItem( IDC_PAT_KWD, CB_ADDSTRING, TEXT("") );
276                 while( f.Next(&fd) )
277                         SendMsgToItem( IDC_PAT_KWD, CB_ADDSTRING, fd.cFileName );
278                 f.Begin( (Path(Path::Exe)+=TEXT("type\\*.lay")).c_str() );
279                 while( f.Next(&fd) )
280                         SendMsgToItem( IDC_PAT_LAY, CB_ADDSTRING, fd.cFileName );
281  
282                 SelDt(0);
283  
284                 SetCenter( hwnd(), ::GetParent(hwnd()) );
285         }
286  
287         bool on_command( UINT cmd, UINT id, HWND ctrl )
288         {
289                 switch( cmd )
290                 {
291                 case LBN_SELCHANGE:
292                         SaveDt();
293                         SelDt( (ulong)SendMsgToItem( IDC_DOCTYPELIST, LB_GETCURSEL ) );
294                         break;
295                 default:
296                         TCHAR buf[256];
297                         switch( id )
298                         {
299                         case IDC_EDITKWD:
300                                 SendMsgToItem(IDC_PAT_KWD, CB_GETLBTEXT,
301                                         SendMsgToItem(IDC_PAT_KWD, CB_GETCURSEL),
302                                         reinterpret_cast<LPARAM>(buf) );
303                                 if( buf[0] != TEXT('\0') )
304                                         BootNewProcess( (TEXT("\"")+Path(Path::Exe)+
305                                                 TEXT("type\\")+buf+TEXT("\"") ).c_str());
306                                 break;
307                         case IDC_EDITLAY:
308                                 SendMsgToItem(IDC_PAT_LAY, CB_GETLBTEXT,
309                                         SendMsgToItem(IDC_PAT_LAY, CB_GETCURSEL),
310                                         reinterpret_cast<LPARAM>(buf) );
311                                 BootNewProcess( (TEXT("\"")+Path(Path::Exe)+
312                                         TEXT("type\\")+buf+TEXT("\"") ).c_str());
313                                 break;
314                         case IDC_NEWDOCTYPE:
315                                 on_newdoctype();
316                                 break;
317                         case IDC_DELDOCTYPE:
318                                 on_deldoctype();
319                                 break;
320                         default:
321                                 return false;
322                         }
323                         break;
324                 }
325                 return true;
326         }
327  
328         bool on_ok()
329         {
330                 TCHAR buf[100];
331                 SendMsgToItem(IDC_LATEST_NUM, WM_GETTEXT,
332                         countof(buf),reinterpret_cast<LPARAM>(buf));
333                 cfg_.mrus_ = String::GetInt(buf);
334                 cfg_.mrus_ = Min(Max(0, cfg_.mrus_), 20);
335  
336                 if( BST_CHECKED == SendMsgToItem(IDC_UNDOLIM1, BM_GETCHECK) )
337                 {
338                         cfg_.undoLimit_ = -1;
339                 }
340                 else
341                 {
342                         SendMsgToItem(IDC_UNDO_CT, WM_GETTEXT,
343                                 countof(buf),reinterpret_cast<LPARAM>(buf));
344                         cfg_.undoLimit_ = String::GetInt(buf);
345                 }
346  
347                 SendMsgToItem(IDC_TXTFILT, WM_GETTEXT,
348                         countof(buf),reinterpret_cast<LPARAM>(buf));
349                 cfg_.txtFilter_ = buf;
350  
351                 SendMsgToItem(IDC_EXTGREP, WM_GETTEXT,
352                         countof(buf),reinterpret_cast<LPARAM>(buf));
353                 cfg_.grepExe_ = buf;
354  
355                 cfg_.openSame_ =
356                         ( BST_CHECKED==SendMsgToItem(IDC_OPENSAME, BM_GETCHECK) );
357                 cfg_.rememberWindowSize_ =
358                         ( BST_CHECKED==SendMsgToItem(IDC_REMSIZE, BM_GETCHECK) );
359                 cfg_.rememberWindowPlace_ =
360                         ( BST_CHECKED==SendMsgToItem(IDC_REMPLACE, BM_GETCHECK) );
361  
362                 cfg_.countbyunicode_ =
363                         ( BST_CHECKED==SendMsgToItem(IDC_COUNTBYLETTER, BM_GETCHECK) );
364  
365                 cfg_.newfileCharset_ = cfg_.GetCharSetList()[1+SendMsgToItem(IDC_NEWCS, CB_GETCURSEL)].ID;
366                 cfg_.newfileLB_ = (lbcode) SendMsgToItem(IDC_NEWLB, CB_GETCURSEL);
367                 size_t nfd_idx=SendMsgToItem(IDC_NEWDT, CB_GETCURSEL), nfd_cnt=1;
368                 cfg_.newfileDoctype_ = String();
369  
370                 SaveDt();
371                 cfg_.dtList_.DelAfter( ++cfg_.dtList_.begin() );
372                 for( DTI i=myDtl_.begin(), e=myDtl_.end(); i!=e; ++i, ++nfd_cnt )
373                 {
374                         cfg_.dtList_.Add( *i );
375                         if( nfd_idx == nfd_cnt )
376                                 cfg_.newfileDoctype_ = i->name;
377                 }
378                 return true;
379         }
380  
381 private:
382         ConfigManager& cfg_;
383         ConfigManager::DtList myDtl_;
384 };
385  
386 bool ConfigManager::DoDialog( const ki::Window& parent )
387 {
388         LoadIni();
389         {
390                 ConfigDlg dlg(*this, parent.hwnd());
391                 if( IDOK != dlg.endcode() )
392                         return false;
393                 curDt_ = dtList_.begin(); // とりあえず
394         }
395         SaveIni();
396         return true;
397 }
398  
399  
400  
401 //-------------------------------------------------------------------------
402 // *.lay ファイルからの読み込み処理
403 //-------------------------------------------------------------------------
404  
405 namespace {
406         static ulong ToByte( unicode* str )
407         {
408                 ulong c = str[0];
409                          if( L'a' <= str[0] ) c -= (L'a' - 10);
410                 else if( L'A' <= str[0] ) c -= (L'A' - 10);
411                 else                      c -=  L'0';
412                 c = c*16 + str[1];
413                          if( L'a' <= str[1] ) c -= (L'a' - 10);
414                 else if( L'A' <= str[1] ) c -= (L'A' - 10);
415                 else                      c -=  L'0';
416                 return c;
417         }
418         static ulong GetColor( unicode* str )
419         {
420                 return ToByte(str) + (ToByte(str+2)<<8) + (ToByte(str+4)<<16);
421         }
422         static int GetInt( unicode* str )
423         {
424                 int c = 0;
425                 int s = 1;
426                 if( *str == L'-' )
427                         s=-1, ++str;
428                 for( ; *str!=L'\0'; ++str )
429                         c = c * 10 + *str - L'0';
430                 return c*s;
431         }
432 }
433  
434 void ConfigManager::LoadLayout( ConfigManager::DocType* dt )
435 {
436   // 1.省略値として…
437  
438         DtList::iterator ref = dtList_.begin();
439         if( ref != dtList_.end() )
440         {
441                 // default.layがロ[ドされていればそれを使う
442                 dt->vc        = ref->vc;
443                 dt->wrapWidth = ref->wrapWidth;
444                 dt->wrapType  = ref->wrapType;
445                 dt->showLN    = ref->showLN;
109 roytam 446                 dt->fontCS    = ref->fontCS;
89 roytam 447         }
448         else
449         {
450                 // 組み込みのデフォルト設定をロ[ド
451                 dt->vc.SetTabStep( 4 );
452                 dt->vc.color[TXT] = RGB(0,0,0);
453                 dt->vc.color[KWD] = RGB(0,90,230);
454                 dt->vc.color[CMT] = RGB(0,0,0);
455                 dt->vc.color[BG]  = RGB(255,255,255);
456                 dt->vc.color[CTL] = RGB(240,200,240);
457                 dt->vc.color[LN]  = RGB(0,0,0);
458                 dt->vc.sc[scEOF]  = dt->vc.sc[scEOL]=true;
459                 dt->vc.sc[scHSP]  = dt->vc.sc[scZSP]=dt->vc.sc[scTAB]=false;
460                 dt->wrapWidth  = 80;
461                 dt->wrapType   = -1;
462                 dt->showLN     = false;
109 roytam 463                 dt->fontCS     = DEFAULT_CHARSET;
464                 dt->vc.SetFont( TEXT("FixedSys"), 14, dt->fontCS );
89 roytam 465         }
466  
467   // 2.*.layファイルからの読み込み
468  
469         TextFileR tf( UTF16LE );
470         if( tf.Open( (Path(Path::Exe)+TEXT("type\\")+dt->layfile).c_str() ) )
471         {
472                 String fontname;
473                 int    fontsize=0;
474                 int    x;
475                 bool   clfound = false;
476  
477                 unicode buf[1024], *ptr=buf+3;
478                 while( tf.state() != 0 ) // !EOF
479                 {
480                         size_t len = tf.ReadLine( buf, countof(buf)-1 );
481                         if( len<=3 || buf[2]!=L'=' )
482                                 continue;
483                         buf[len] = L'\0';
484  
485                         switch( (buf[0]<<16)|buf[1] )
486                         {
487                         case 0x00630074: // ct: COLOR-TEXT
488                                 dt->vc.color[TXT] = GetColor(ptr);
489                                 break;
490                         case 0x0063006B: // ck: COLOR-KEYWORD
491                                 dt->vc.color[KWD] = GetColor(ptr);
492                                 break;
493                         case 0x00630062: // cb: COLOR-BACKGROUND
494                                 dt->vc.color[BG ] = GetColor(ptr);
495                                 break;
496                         case 0x00630063: // cc: COLOR-COMMENT
497                                 dt->vc.color[CMT] = GetColor(ptr);
498                                 break;
499                         case 0x0063006E: // cn: COLOR-CONTROL
500                                 dt->vc.color[CTL] = GetColor(ptr);
501                                 break;
502                         case 0x0063006C: // cl: COLOR-LINE
503                                 clfound = true;
504                                 dt->vc.color[LN] = GetColor(ptr);
505                                 break;
506                         case 0x00660074: // ft: FONT
507                                 fontname = ptr;
508                                 break;
509                         case 0x0073007A: // sz: SIZE
510                                 fontsize = GetInt(ptr);
511                                 break;
109 roytam 512                         case 0x00630073: // cs: FONT-CHAR-SET
513                                 dt->fontCS = GetInt(ptr);
514                                 break;
89 roytam 515                         case 0x00740062: // tb: TAB
516                                 dt->vc.SetTabStep( GetInt(ptr) );
517                                 break;
518                         case 0x00730063: // sc: SPECIAL-CHAR
519                                 x = GetInt(ptr);
520                                 dt->vc.sc[scZSP] = (0!=x%10); x/=10;
521                                 dt->vc.sc[scHSP] = (0!=x%10); x/=10;
522                                 dt->vc.sc[scTAB] = (0!=x%10); x/=10;
523                                 dt->vc.sc[scEOL] = (0!=x%10); x/=10;
524                                 dt->vc.sc[scEOF] = (0!=x%10);
525                                 break;
526                         case 0x00770070: // wp: WRAP-TYPE
527                                 dt->wrapType = GetInt(ptr);
528                                 break;
529                         case 0x00770077: // ww: WRAP-WIDTH
530                                 dt->wrapWidth = GetInt(ptr);
531                                 break;
532                         case 0x006C006E: // ln: LINE-NO
533                                 dt->showLN = (0!=GetInt(ptr));
534                                 break;
535                         }
536                 }
537  
538                 if( !clfound )
539                         dt->vc.color[LN] = dt->vc.color[TXT];
540                 if( fontname.len()!=0 && fontsize!=0 )
109 roytam 541                         dt->vc.SetFont( fontname.c_str(), fontsize, dt->fontCS );
89 roytam 542         }
543 }
544  
545  
546  
547 //-------------------------------------------------------------------------
548 // *.ini ファイルからの読み込み/書き込み処理
549 //-------------------------------------------------------------------------
550  
551 static const TCHAR s_sharedConfigSection[] = TEXT("SharedConfig");
552  
553 void ConfigManager::LoadIni()
554 {
555         {
556                 FileW fp;
557                 Path inipath(Path::Exe);
558                 inipath+=Path(Path::ExeName).body();
559                 inipath+=TEXT(".ini");
560                 if( !inipath.exist() && fp.Open(inipath.c_str()) )
561                 {
562                         static const char s_defaultIni[] =
563                         "[DocType]\r\n"
564                         "1=C/C++\r\n"
565                         "2=C#\r\n"
566                         "3=D\r\n"
567                         "4=Java\r\n"
568                         "5=HTML\r\n"
569                         "6=CSS\r\n"
570                         "7=Perl\r\n"
571                         "8=Ruby\r\n"
572                         "9=PHP\r\n"
573                         "10=Python\r\n"
574                         "11=Haskell\r\n"
575                         "12=OCaml\r\n"
576                         "13=INI\r\n"
577                         "14=UnicodeText\r\n"
578                         "\r\n"
579                         "[C/C++]\r\n"
580                         "Pattern=.*(\\.(c|cpp|cxx|cc|h|hpp)|include\\\\[^\\.]+)$\r\n"
581                         "Keyword=C.kwd\r\n"
582                         "Layout=program.lay\r\n"
583                         "\r\n"
584                         "[Java]\r\n"
585                         "Pattern=.*\\.java$\r\n"
586                         "Keyword=Java.kwd\r\n"
587                         "Layout=program.lay\r\n"
588                         "\r\n"
589                         "[HTML]\r\n"
590                         "Pattern=.*(\\.html|\\.htm|temporary internet files\\\\.+)$\r\n"
591                         "Keyword=HTML.kwd\r\n"
592                         "Layout=html.lay\r\n"
593                         "\r\n"
594                         "[CSS]\r\n"
595                         "Pattern=.*\\.css$\r\n"
596                         "Keyword=CSS.kwd\r\n"
597                         "Layout=program.lay\r\n"
598                         "\r\n"
599                         "[PHP]\r\n"
600                         "Pattern=.*\\.(php|php3|php4)$\r\n"
601                         "Keyword=PHP.kwd\r\n"
602                         "Layout=program.lay\r\n"
603                         "\r\n"
604                         "[Python]\r\n"
605                         "Pattern=.*\\.py$\r\n"
606                         "Keyword=Python.kwd\r\n"
607                         "Layout=program.lay\r\n"
608                         "\r\n"
609                         "[Ruby]\r\n"
610                         "Pattern=.*\\.rb$\r\n"
611                         "Keyword=Ruby.kwd\r\n"
612                         "Layout=program.lay\r\n"
613                         "\r\n"
614                         "[D]\r\n"
615                         "Pattern=.*\\.d$\r\n"
616                         "Keyword=D.kwd\r\n"
617                         "Layout=program.lay\r\n"
618                         "\r\n"
619                         "[Haskell]\r\n"
620                         "Pattern=.*\\.l?hs$\r\n"
621                         "Keyword=Haskell.kwd\r\n"
622                         "Layout=program.lay\r\n"
623                         "\r\n"
624                         "[OCaml]\r\n"
625                         "Pattern=.*\\.mli?$\r\n"
626                         "Keyword=OCaml.kwd\r\n"
627                         "Layout=program.lay\r\n"
628                         "\r\n"
629                         "[C#]\r\n"
630                         "Pattern=.*\\.cs$\r\n"
631                         "Keyword=C#.kwd\r\n"
632                         "Layout=program.lay\r\n"
633                         "\r\n"
634                         "[INI]\r\n"
635                         "Pattern=.*\\.ini$\r\n"
636                         "Keyword=ini.kwd\r\n"
637                         "\r\n"
638                         "[Perl]\r\n"
639                         "Pattern=.*\\.(pl|pm|cgi)$\r\n"
640                         "Keyword=perl.kwd\r\n"
641                         "Layout=program.lay\r\n"
642                         "\r\n"
643                         "[UnicodeText]\r\n"
644                         "Layout=unitext.lay\r\n"
645                         "\r\n";
646                         fp.Write( s_defaultIni, sizeof(s_defaultIni)-1 );
647                 }
648         }
649  
650         // 共通の設定の読み取りセクション
651         sharedConfigMode_ = ini_.HasSectionEnabled( s_sharedConfigSection );
652         if( sharedConfigMode_ )
653                 ini_.SetSection( s_sharedConfigSection );
654         else
655                 ini_.SetSectionAsUserName();
656  
657         // 共通の設定
658         undoLimit_ = ini_.GetInt( TEXT("UndoLimit"), -1 );
659         txtFilter_ = ini_.GetStr( TEXT("TxtFilter"),
660                 TEXT("*.txt;*.htm;*.html;*.css;*.js;*.d;*.c;*.cpp;*.cc;*.cxx;*.h;*.hpp;*.php;*.php3;*.ini") );
661         grepExe_   = ini_.GetStr( TEXT("GrepExe"), TEXT("") );
662         openSame_  = ini_.GetBool( TEXT("OpenSame"), false );
663         countbyunicode_ = ini_.GetBool( TEXT("CountUni"), false );
124 roytam 664 #if defined(TARGET_VER) && TARGET_VER==310
665         showStatusBar_ = false;
666 #else
89 roytam 667         showStatusBar_ = ini_.GetBool( TEXT("StatusBar"), true );
124 roytam 668 #endif
89 roytam 669  
94 roytam 670         dateFormat_   = ini_.GetStr( TEXT("DateFormat"), TEXT("HH:mm yyyy/MM/dd") );
671  
89 roytam 672         // wnd
673         rememberWindowSize_  = ini_.GetBool( TEXT("RememberWindowSize"), false );
674         rememberWindowPlace_ = ini_.GetBool( TEXT("RememberWindowPos"), false );
675         wndX_ = ini_.GetInt( TEXT("WndX"), CW_USEDEFAULT );
676         wndY_ = ini_.GetInt( TEXT("WndY"), CW_USEDEFAULT );
677         wndW_ = ini_.GetInt( TEXT("WndW"), CW_USEDEFAULT );
678         wndH_ = ini_.GetInt( TEXT("WndH"), CW_USEDEFAULT );
679         wndM_ = ini_.GetBool( TEXT("WndM"), false );
680  
681         // TODO: MRU
682         mrus_ = ini_.GetInt( TEXT("MRU"), 4 );
683         mrus_ = Min(Max(0, mrus_), 20);
684  
685         // 新規ファイル関係
686         newfileCharset_ = ini_.GetInt( TEXT("NewfileCharset"), charSets_.defaultCs() );
687         if(newfileCharset_ == -1) newfileCharset_ = 1252; // 1.07.4 bugfix
146 roytam 688         if(!::IsValidCodePage(newfileCharset_)) newfileCharset_ = ::GetACP();
89 roytam 689         newfileDoctype_ = ini_.GetStr( TEXT("NewfileDoctype"), String() );
690         newfileLB_      = (lbcode) ini_.GetInt( TEXT("NewfileLB"), CRLF );
691  
692         // 文書タイプリストの0番以外のクリア
693         dtList_.DelAfter( ++dtList_.begin() );
694  
695         String s, r;
696         for( int i=1; true; ++i )
697         {
698                 // 文書タイプ名を読み込み
699                 ini_.SetSection( TEXT("DocType") );
700                 s.SetInt(i);
701                 r = ini_.GetStr( s.c_str(), String() );
702                 if( r.len() == 0 )
703                         break;
704  
705                 // その文書タイプを実際に読み込み
706                 ini_.SetSection( r.c_str() );
707                 {
708                         DocType d;
709                         d.name      = r;
710                         d.layfile   = ini_.GetStr( TEXT("Layout"),TEXT("default.lay"));
711                         d.kwdfile   = ini_.GetStr( TEXT("Keyword"), String() );
712                         d.pattern   = ini_.GetStr( TEXT("Pattern"), String() );
713                         dtList_.Add( d );
714                 }
715         }
716 }
717  
718 void ConfigManager::SaveIni()
719 {
720         {
721                 Path inipath(Path::Exe);
722                 inipath+=Path(Path::ExeName).body();
723                 inipath+=TEXT(".ini");
724                 if( inipath.isReadOnly() )
725                         return;
726         }
727  
728         // 共通の設定の書き込みセクション
729         if( sharedConfigMode_ )
730                 ini_.SetSection( s_sharedConfigSection );
731         else
732                 ini_.SetSectionAsUserName();
733  
734         // 共通の設定
735         ini_.PutInt( TEXT("UndoLimit"), undoLimit_ );
736         ini_.PutStr( TEXT("TxtFilter"), txtFilter_.c_str() );
737         ini_.PutStr( TEXT("GrepExe"), grepExe_.c_str() );
738         ini_.PutBool( TEXT("OpenSame"), openSame_ );
739         ini_.PutBool( TEXT("CountUni"), countbyunicode_ );
740         ini_.PutBool( TEXT("StatusBar"), showStatusBar_ );
741  
94 roytam 742         ini_.PutStr( TEXT("DateFormat"), dateFormat_.c_str() );
743  
89 roytam 744         // Wnd
745         ini_.PutBool( TEXT("RememberWindowSize"), rememberWindowSize_ );
746         ini_.PutBool( TEXT("RememberWindowPos"), rememberWindowPlace_ );
747         ini_.PutInt( TEXT("WndX"), wndX_ );
748         ini_.PutInt( TEXT("WndY"), wndY_ );
749         ini_.PutInt( TEXT("WndW"), wndW_ );
750         ini_.PutInt( TEXT("WndH"), wndH_ );
751         ini_.PutBool( TEXT("WndM"), wndM_ );
752  
753         // 新規ファイル関係
754         ini_.PutInt( TEXT("NewfileCharset"), newfileCharset_ );
755         ini_.PutStr( TEXT("NewfileDoctype"), newfileDoctype_.c_str() );
756         ini_.PutInt( TEXT("NewfileLB"),      newfileLB_      );
757  
758         // MRU
759         ini_.PutInt( TEXT("MRU"), mrus_ );
760  
761         // DocType
762         for(DtList::iterator i=++dtList_.begin(); i!=dtList_.end(); ++i )
763         {
764                 ini_.SetSection( i->name.c_str() );
765                 ini_.PutStr( TEXT("Pattern"), i->pattern.c_str() );
766                 ini_.PutStr( TEXT("Keyword"), i->kwdfile.c_str() );
767                 ini_.PutStr( TEXT("Layout"), i->layfile.c_str() );
768         }
769  
770         ulong ct=1;
771         ini_.SetSection( TEXT("DocType") );
772         for(DtList::iterator i=++dtList_.begin(); i!=dtList_.end(); ++i,++ct)
773                 ini_.PutStr( String().SetInt(ct).c_str(), i->name.c_str() );
774         ini_.PutStr( String().SetInt(ct).c_str(), TEXT("") );
775 }
776  
777  
778  
779 //-------------------------------------------------------------------------
780 // [最近使ったファイル]関係
781 //-------------------------------------------------------------------------
782  
783 namespace {
784         static const TCHAR* const s_mrulock = TEXT("GreenPad_MRUMutex");
785 }
786  
787 void ConfigManager::AddMRU( const ki::Path& fname )
788 {
789         Mutex mx(s_mrulock);
790  
791         // メモリ内のMRUリストを更新
792         {
793                 int i;
794                 for( i=0; i<countof(mru_); ++i )
795                         if( mru_[i] == fname )
796                         {++i; break;}
797                 for( --i; i>0; --i )
798                         mru_[i] = mru_[i-1];
799                 mru_[0] = fname;
800         }
801  
802         // iniへ保存
803         {
804                 ini_.SetSectionAsUserName();
805                 const String key = TEXT("MRU");
806                 for( int i=0; i<countof(mru_); ++i )
807                         ini_.PutPath(
808                                 (key+String().SetInt(i+1)).c_str(), mru_[i] );
809         }
810 }
811  
812 void ConfigManager::SetUpMRUMenu( HMENU m, UINT id )
813 {
814         Mutex mx(s_mrulock);
815  
816         // iniから読み込み
817         {
818                 ini_.SetSectionAsUserName();
819                 const String key = TEXT("MRU");
820                 for( int i=0; i<countof(mru_); ++i )
821                         mru_[i] = ini_.GetPath(
822                                 (key+String().SetInt(i+1)).c_str(), Path() );
823         }
824  
825         // 全項目を削除
826         while( ::DeleteMenu( m, 0, MF_BYPOSITION ) );
827  
828         // メニュ[構築
125 roytam 829 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
830         if(app().isNewShell())
89 roytam 831         {
110 roytam 832                 MENUITEMINFO mi = { sizeof(MENUITEMINFO) };
833                 mi.fMask = MIIM_ID | MIIM_TYPE;
834                 mi.fType = MFT_STRING;
835                 for( int i=0; i<countof(mru_); ++i )
89 roytam 836                 {
110 roytam 837                         if( i>=mrus_ || mru_[i].len()==0 )
89 roytam 838                         {
110 roytam 839                                 if( i==0 )
840                                 {
841                                         mi.fMask     |= MIIM_STATE;
842                                         mi.wID        = id;
843                                         mi.fState     = MFS_DISABLED;
844                                         mi.dwTypeData = TEXT("no files");
845                                         mi.cch        = 0;
846                                         ::InsertMenuItem( m, 0, MF_BYPOSITION, &mi );
847                                 }
848                                 break;
89 roytam 849                         }
110 roytam 850                         String cpt = mru_[i].CompactIfPossible(60);
851                         mi.wID        = id + i;
852                         mi.dwTypeData = const_cast<TCHAR*>(cpt.c_str());
853                         mi.cch        = cpt.len();
854                         ::InsertMenuItem( m, i, MF_BYPOSITION, &mi );
89 roytam 855                 }
856         }
110 roytam 857         else
125 roytam 858 #endif
859         {
110 roytam 860                 for( int i=0; i<countof(mru_); ++i )
861                 {
862                         if( i>=mrus_ || mru_[i].len()==0 )
863                         {
864                                 if( i==0 )
865                                 {
866                                         ::InsertMenu( m, i, MF_BYPOSITION|MF_GRAYED, id, TEXT("no files") );
867                                 }
868                                 break;
869                         }
870                         String cpt = mru_[i].CompactIfPossible(60);
871                         ::InsertMenu( m, i, MF_BYPOSITION, id + i, const_cast<TCHAR*>(cpt.c_str()) );
872                 }
125 roytam 873         }
89 roytam 874 }
875  
876 Path ConfigManager::GetMRU( int no ) const
877 {
878         return (0<=no && no<mrus_ ? mru_[no] : Path());
879 }
880  
881  
882 //-------------------------------------------------------------------------
883 // ウインドウサイズ復元処理
884 //-------------------------------------------------------------------------
885  
886 void ConfigManager::RememberWnd( ki::Window* wnd )
887 {
888         RECT rc;
889         wnd->getPos(&rc);
890         WINDOWPLACEMENT wp = {sizeof(wp)};
891         ::GetWindowPlacement( wnd->hwnd(), &wp );
892  
893         if( wp.showCmd==SW_SHOWNORMAL || wp.showCmd == SW_MAXIMIZE )
894                 wndM_ = (wp.showCmd == SW_MAXIMIZE);
895         if( wp.showCmd==SW_SHOWNORMAL )
896         {
897                 wndX_ = rc.left;
898                 wndY_ = rc.top;
899                 wndW_ = rc.right- rc.left;
900                 wndH_ = rc.bottom - rc.top;
901         }
902         //if( this->rememberWindowPlace_ || this->rememberWindowSize_ )
903         //      SaveIni();
904 }
905  
906 //-------------------------------------------------------------------------
907 // [文書タイプ]サブメニュ[の作成
908 //-------------------------------------------------------------------------
909  
910 void ConfigManager::SetDocTypeMenu( HMENU m, UINT idstart )
911 {
912         // 全項目を削除
913         while( ::DeleteMenu( m, 0, MF_BYPOSITION ) );
914  
125 roytam 915 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
916         if(app().isNewShell())
103 roytam 917         {
918                 // 順に追加
919                 MENUITEMINFO mi = { sizeof(MENUITEMINFO) };
920                 mi.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE;
921                 mi.fType = MFT_STRING | MFT_RADIOCHECK;
89 roytam 922  
103 roytam 923                 DtList::iterator i=dtList_.begin(), e=dtList_.end();
924                 for( int ct=0; i!=e; ++i, ++ct )
925                 {
926                         mi.wID        = idstart + ct;
927                         mi.fState     = (i==curDt_ ? MFS_CHECKED : MFS_UNCHECKED);
928                         mi.dwTypeData = const_cast<TCHAR*>(i->name.c_str());
929                         mi.cch        = i->name.len();
930                         ::InsertMenuItem( m, ct, MF_BYPOSITION, &mi );
931                 }
932         }
933         else
125 roytam 934 #endif
935         {
103 roytam 936                 DtList::iterator i=dtList_.begin(), e=dtList_.end();
937                 for( int ct=0; i!=e; ++i, ++ct )
938                 {
939                         ::InsertMenu( m, ct, MF_BYPOSITION|(i==curDt_ ? MFS_CHECKED : MFS_UNCHECKED), idstart + ct, const_cast<TCHAR*>(i->name.c_str()) );
940                 }
125 roytam 941         }
89 roytam 942 }
943  
944 void ConfigManager::SetDocTypeByMenu( int pos, HMENU m )
945 {
125 roytam 946 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
947         if(app().isNewShell())
103 roytam 948         {
949                 MENUITEMINFO mi = { sizeof(MENUITEMINFO) };
950                 mi.fMask  = MIIM_STATE;
89 roytam 951  
103 roytam 952                 DtList::iterator i=dtList_.begin(), e=dtList_.end();
953                 for( int ct=0; i!=e; ++i, ++ct )
954                 {
955                         mi.fState     = (ct==pos ? MFS_CHECKED : MFS_UNCHECKED);
956                         ::SetMenuItemInfo( m, ct, MF_BYPOSITION, &mi );
957                         if( ct == pos )
958                         {
959                                 curDt_ = i;
960                                 LoadLayout( &*curDt_ );
961                         }
962                 }
963         }
964         else
125 roytam 965 #endif
966         {
103 roytam 967                 int ct=0;
968                 DtList::iterator i=dtList_.begin(), e=dtList_.end();
969                 for( ; i!=e; ++i, ++ct )
89 roytam 970                 {
103 roytam 971                         if( ct == pos )
972                         {
973                                 curDt_ = i;
974                                 LoadLayout( &*curDt_ );
975                                 ::CheckMenuItem( m, ct, MF_BYPOSITION|MF_CHECKED);
976                         }
977                         else
978                         {
979                                 ::CheckMenuItem( m, ct, MF_BYPOSITION|MF_UNCHECKED);
980                         }
89 roytam 981                 }
125 roytam 982         }
89 roytam 983 }
984  
985 void ConfigManager::CheckMenu( HMENU m, int pos )
986 {
125 roytam 987 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
988         if(app().isNewShell())
103 roytam 989         {
990                 MENUITEMINFO mi = { sizeof(MENUITEMINFO) };
991                 mi.fMask  = MIIM_STATE;
89 roytam 992  
103 roytam 993                 DtList::iterator i=dtList_.begin(), e=dtList_.end();
994                 for( int ct=0; i!=e; ++i, ++ct )
995                 {
996                         mi.fState     = (ct==pos ? MFS_CHECKED : MFS_UNCHECKED);
997                         ::SetMenuItemInfo( m, ct, MF_BYPOSITION, &mi );
998                 }
999         }
1000         else
125 roytam 1001 #endif
1002         {
103 roytam 1003                 int ct=0;
1004                 DtList::iterator i=dtList_.begin(), e=dtList_.end();
1005                 for( ; i!=e; ++i, ++ct )
1006                 {
1007                         if( ct == pos )
1008                         {
1009                                 ::CheckMenuItem( m, ct, MF_BYPOSITION|MF_CHECKED);
1010                         }
1011                         else
1012                         {
1013                                 ::CheckMenuItem( m, ct, MF_BYPOSITION|MF_UNCHECKED);
1014                         }
1015                 }
125 roytam 1016         }
89 roytam 1017 }
1018