Check-in [dcdd144598]

Not logged in
Overview
SHA1 Hash:dcdd144598475b1ac49d34f9836cd34dab86c606
Date: 2011-02-23 08:12:34
User: kinaba
Comment:Copied from private svn repository.
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes
hide diffs unified diffs patch

Added ConfigManager.cpp version [122ddf24e552b592]

> 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_s > 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_YES > 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>(bu > 168 name = buf; > 169 SendMsgToItem(IDC_EXT, WM_GETTEXT, > 170 countof(buf),reinterpret_cast<LPARAM>(bu > 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_CHECK > 229 SendMsgToItem(IDC_COUNTBYLETTER2, BM_SETCHECK); > 230 } > 231 else > 232 { > 233 SendMsgToItem(IDC_COUNTBYLETTER, BM_SETCHECK); > 234 SendMsgToItem(IDC_COUNTBYLETTER2, BM_SETCHECK, BST_CHECK > 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_.newfile > 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_GETCURS > 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::E > 305 TEXT("type\\")+buf+TEXT("\"") ). > 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_GETCH > 364 > 365 cfg_.newfileCharset_ = cfg_.GetCharSetList()[1+SendMsgToItem(IDC > 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; > 446 } > 447 else > 448 { > 449 // 組み込みのデフォルト設定をロード > 450 dt->vc.SetFont( TEXT("FixedSys"), 14 ); > 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; > 463 } > 464 > 465 // 2.*.layファイルからの読み込み > 466 > 467 TextFileR tf( UTF16LE ); > 468 if( tf.Open( (Path(Path::Exe)+TEXT("type\\")+dt->layfile).c_str() ) ) > 469 { > 470 String fontname; > 471 int fontsize=0; > 472 int x; > 473 bool clfound = false; > 474 > 475 unicode buf[1024], *ptr=buf+3; > 476 while( tf.state() != 0 ) // !EOF > 477 { > 478 size_t len = tf.ReadLine( buf, countof(buf)-1 ); > 479 if( len<=3 || buf[2]!=L'=' ) > 480 continue; > 481 buf[len] = L'\0'; > 482 > 483 switch( (buf[0]<<16)|buf[1] ) > 484 { > 485 case 0x00630074: // ct: COLOR-TEXT > 486 dt->vc.color[TXT] = GetColor(ptr); > 487 break; > 488 case 0x0063006B: // ck: COLOR-KEYWORD > 489 dt->vc.color[KWD] = GetColor(ptr); > 490 break; > 491 case 0x00630062: // cb: COLOR-BACKGROUND > 492 dt->vc.color[BG ] = GetColor(ptr); > 493 break; > 494 case 0x00630063: // cc: COLOR-COMMENT > 495 dt->vc.color[CMT] = GetColor(ptr); > 496 break; > 497 case 0x0063006E: // cn: COLOR-CONTROL > 498 dt->vc.color[CTL] = GetColor(ptr); > 499 break; > 500 case 0x0063006C: // cl: COLOR-LINE > 501 clfound = true; > 502 dt->vc.color[LN] = GetColor(ptr); > 503 break; > 504 case 0x00660074: // ft: FONT > 505 fontname = ptr; > 506 break; > 507 case 0x0073007A: // sz: SIZE > 508 fontsize = GetInt(ptr); > 509 break; > 510 case 0x00740062: // tb: TAB > 511 dt->vc.SetTabStep( GetInt(ptr) ); > 512 break; > 513 case 0x00730063: // sc: SPECIAL-CHAR > 514 x = GetInt(ptr); > 515 dt->vc.sc[scZSP] = (0!=x%10); x/=10; > 516 dt->vc.sc[scHSP] = (0!=x%10); x/=10; > 517 dt->vc.sc[scTAB] = (0!=x%10); x/=10; > 518 dt->vc.sc[scEOL] = (0!=x%10); x/=10; > 519 dt->vc.sc[scEOF] = (0!=x%10); > 520 break; > 521 case 0x00770070: // wp: WRAP-TYPE > 522 dt->wrapType = GetInt(ptr); > 523 break; > 524 case 0x00770077: // ww: WRAP-WIDTH > 525 dt->wrapWidth = GetInt(ptr); > 526 break; > 527 case 0x006C006E: // ln: LINE-NO > 528 dt->showLN = (0!=GetInt(ptr)); > 529 break; > 530 } > 531 } > 532 > 533 if( !clfound ) > 534 dt->vc.color[LN] = dt->vc.color[TXT]; > 535 if( fontname.len()!=0 && fontsize!=0 ) > 536 dt->vc.SetFont( fontname.c_str(), fontsize ); > 537 } > 538 } > 539 > 540 > 541 > 542 //------------------------------------------------------------------------- > 543 // *.ini ファイルからの読み込み/書き込み処理 > 544 //------------------------------------------------------------------------- > 545 > 546 static const TCHAR s_sharedConfigSection[] = TEXT("SharedConfig"); > 547 > 548 void ConfigManager::LoadIni() > 549 { > 550 { > 551 FileW fp; > 552 Path inipath(Path::Exe); > 553 inipath+=Path(Path::ExeName).body(); > 554 inipath+=TEXT(".ini"); > 555 if( !inipath.exist() && fp.Open(inipath.c_str()) ) > 556 { > 557 static const char s_defaultIni[] = > 558 "[DocType]\r\n" > 559 "1=C/C++\r\n" > 560 "2=C#\r\n" > 561 "3=D\r\n" > 562 "4=Java\r\n" > 563 "5=HTML\r\n" > 564 "6=CSS\r\n" > 565 "7=Perl\r\n" > 566 "8=Ruby\r\n" > 567 "9=PHP\r\n" > 568 "10=Python\r\n" > 569 "11=Haskell\r\n" > 570 "12=OCaml\r\n" > 571 "13=INI\r\n" > 572 "14=UnicodeText\r\n" > 573 "\r\n" > 574 "[C/C++]\r\n" > 575 "Pattern=.*(\\.(c|cpp|cxx|cc|h|hpp)|include\\\\[^\\.]+)$ > 576 "Keyword=C.kwd\r\n" > 577 "Layout=program.lay\r\n" > 578 "\r\n" > 579 "[Java]\r\n" > 580 "Pattern=.*\\.java$\r\n" > 581 "Keyword=Java.kwd\r\n" > 582 "Layout=program.lay\r\n" > 583 "\r\n" > 584 "[HTML]\r\n" > 585 "Pattern=.*(\\.html|\\.htm|temporary internet files\\\\. > 586 "Keyword=HTML.kwd\r\n" > 587 "Layout=html.lay\r\n" > 588 "\r\n" > 589 "[CSS]\r\n" > 590 "Pattern=.*\\.css$\r\n" > 591 "Keyword=CSS.kwd\r\n" > 592 "Layout=program.lay\r\n" > 593 "\r\n" > 594 "[PHP]\r\n" > 595 "Pattern=.*\\.(php|php3|php4)$\r\n" > 596 "Keyword=PHP.kwd\r\n" > 597 "Layout=program.lay\r\n" > 598 "\r\n" > 599 "[Python]\r\n" > 600 "Pattern=.*\\.py$\r\n" > 601 "Keyword=Python.kwd\r\n" > 602 "Layout=program.lay\r\n" > 603 "\r\n" > 604 "[Ruby]\r\n" > 605 "Pattern=.*\\.rb$\r\n" > 606 "Keyword=Ruby.kwd\r\n" > 607 "Layout=program.lay\r\n" > 608 "\r\n" > 609 "[D]\r\n" > 610 "Pattern=.*\\.d$\r\n" > 611 "Keyword=D.kwd\r\n" > 612 "Layout=program.lay\r\n" > 613 "\r\n" > 614 "[Haskell]\r\n" > 615 "Pattern=.*\\.l?hs$\r\n" > 616 "Keyword=Haskell.kwd\r\n" > 617 "Layout=program.lay\r\n" > 618 "\r\n" > 619 "[OCaml]\r\n" > 620 "Pattern=.*\\.mli?$\r\n" > 621 "Keyword=OCaml.kwd\r\n" > 622 "Layout=program.lay\r\n" > 623 "\r\n" > 624 "[C#]\r\n" > 625 "Pattern=.*\\.cs$\r\n" > 626 "Keyword=C#.kwd\r\n" > 627 "Layout=program.lay\r\n" > 628 "\r\n" > 629 "[INI]\r\n" > 630 "Pattern=.*\\.ini$\r\n" > 631 "Keyword=ini.kwd\r\n" > 632 "\r\n" > 633 "[Perl]\r\n" > 634 "Pattern=.*\\.(pl|pm|cgi)$\r\n" > 635 "Keyword=perl.kwd\r\n" > 636 "Layout=program.lay\r\n" > 637 "\r\n" > 638 "[UnicodeText]\r\n" > 639 "Layout=unitext.lay\r\n" > 640 "\r\n"; > 641 fp.Write( s_defaultIni, sizeof(s_defaultIni)-1 ); > 642 } > 643 } > 644 > 645 // 共通の設定の読み取りセクション > 646 sharedConfigMode_ = ini_.HasSectionEnabled( s_sharedConfigSection ); > 647 if( sharedConfigMode_ ) > 648 ini_.SetSection( s_sharedConfigSection ); > 649 else > 650 ini_.SetSectionAsUserName(); > 651 > 652 // 共通の設定 > 653 undoLimit_ = ini_.GetInt( TEXT("UndoLimit"), -1 ); > 654 txtFilter_ = ini_.GetStr( TEXT("TxtFilter"), > 655 TEXT("*.txt;*.htm;*.html;*.css;*.js;*.d;*.c;*.cpp;*.cc;*.cxx;*.h > 656 grepExe_ = ini_.GetStr( TEXT("GrepExe"), TEXT("") ); > 657 openSame_ = ini_.GetBool( TEXT("OpenSame"), false ); > 658 countbyunicode_ = ini_.GetBool( TEXT("CountUni"), false ); > 659 showStatusBar_ = ini_.GetBool( TEXT("StatusBar"), true ); > 660 > 661 // wnd > 662 rememberWindowSize_ = ini_.GetBool( TEXT("RememberWindowSize"), false ) > 663 rememberWindowPlace_ = ini_.GetBool( TEXT("RememberWindowPos"), false ); > 664 wndX_ = ini_.GetInt( TEXT("WndX"), CW_USEDEFAULT ); > 665 wndY_ = ini_.GetInt( TEXT("WndY"), CW_USEDEFAULT ); > 666 wndW_ = ini_.GetInt( TEXT("WndW"), CW_USEDEFAULT ); > 667 wndH_ = ini_.GetInt( TEXT("WndH"), CW_USEDEFAULT ); > 668 wndM_ = ini_.GetBool( TEXT("WndM"), false ); > 669 > 670 // TODO: MRU > 671 mrus_ = ini_.GetInt( TEXT("MRU"), 4 ); > 672 mrus_ = Min(Max(0, mrus_), 20); > 673 > 674 // 新規ファイル関係 > 675 newfileCharset_ = ini_.GetInt( TEXT("NewfileCharset"), charSets_.default > 676 if(newfileCharset_ == -1) newfileCharset_ = 1252; // 1.07.4 bugfix > 677 newfileDoctype_ = ini_.GetStr( TEXT("NewfileDoctype"), String() ); > 678 newfileLB_ = (lbcode) ini_.GetInt( TEXT("NewfileLB"), CRLF ); > 679 > 680 // 文書タイプリストの0番以外のクリア > 681 dtList_.DelAfter( ++dtList_.begin() ); > 682 > 683 String s, r; > 684 for( int i=1; true; ++i ) > 685 { > 686 // 文書タイプ名を読み込み > 687 ini_.SetSection( TEXT("DocType") ); > 688 s.SetInt(i); > 689 r = ini_.GetStr( s.c_str(), String() ); > 690 if( r.len() == 0 ) > 691 break; > 692 > 693 // その文書タイプを実際に読み込み > 694 ini_.SetSection( r.c_str() ); > 695 { > 696 DocType d; > 697 d.name = r; > 698 d.layfile = ini_.GetStr( TEXT("Layout"),TEXT("default. > 699 d.kwdfile = ini_.GetStr( TEXT("Keyword"), String() ); > 700 d.pattern = ini_.GetStr( TEXT("Pattern"), String() ); > 701 dtList_.Add( d ); > 702 } > 703 } > 704 } > 705 > 706 void ConfigManager::SaveIni() > 707 { > 708 { > 709 Path inipath(Path::Exe); > 710 inipath+=Path(Path::ExeName).body(); > 711 inipath+=TEXT(".ini"); > 712 if( inipath.isReadOnly() ) > 713 return; > 714 } > 715 > 716 // 共通の設定の書き込みセクション > 717 if( sharedConfigMode_ ) > 718 ini_.SetSection( s_sharedConfigSection ); > 719 else > 720 ini_.SetSectionAsUserName(); > 721 > 722 // 共通の設定 > 723 ini_.PutInt( TEXT("UndoLimit"), undoLimit_ ); > 724 ini_.PutStr( TEXT("TxtFilter"), txtFilter_.c_str() ); > 725 ini_.PutStr( TEXT("GrepExe"), grepExe_.c_str() ); > 726 ini_.PutBool( TEXT("OpenSame"), openSame_ ); > 727 ini_.PutBool( TEXT("CountUni"), countbyunicode_ ); > 728 ini_.PutBool( TEXT("StatusBar"), showStatusBar_ ); > 729 > 730 // Wnd > 731 ini_.PutBool( TEXT("RememberWindowSize"), rememberWindowSize_ ); > 732 ini_.PutBool( TEXT("RememberWindowPos"), rememberWindowPlace_ ); > 733 ini_.PutInt( TEXT("WndX"), wndX_ ); > 734 ini_.PutInt( TEXT("WndY"), wndY_ ); > 735 ini_.PutInt( TEXT("WndW"), wndW_ ); > 736 ini_.PutInt( TEXT("WndH"), wndH_ ); > 737 ini_.PutBool( TEXT("WndM"), wndM_ ); > 738 > 739 // 新規ファイル関係 > 740 ini_.PutInt( TEXT("NewfileCharset"), newfileCharset_ ); > 741 ini_.PutStr( TEXT("NewfileDoctype"), newfileDoctype_.c_str() ); > 742 ini_.PutInt( TEXT("NewfileLB"), newfileLB_ ); > 743 > 744 // MRU > 745 ini_.PutInt( TEXT("MRU"), mrus_ ); > 746 > 747 // DocType > 748 for(DtList::iterator i=++dtList_.begin(); i!=dtList_.end(); ++i ) > 749 { > 750 ini_.SetSection( i->name.c_str() ); > 751 ini_.PutStr( TEXT("Pattern"), i->pattern.c_str() ); > 752 ini_.PutStr( TEXT("Keyword"), i->kwdfile.c_str() ); > 753 ini_.PutStr( TEXT("Layout"), i->layfile.c_str() ); > 754 } > 755 > 756 ulong ct=1; > 757 ini_.SetSection( TEXT("DocType") ); > 758 for(DtList::iterator i=++dtList_.begin(); i!=dtList_.end(); ++i,++ct) > 759 ini_.PutStr( String().SetInt(ct).c_str(), i->name.c_str() ); > 760 ini_.PutStr( String().SetInt(ct).c_str(), TEXT("") ); > 761 } > 762 > 763 > 764 > 765 //------------------------------------------------------------------------- > 766 // [最近使ったファイル]関係 > 767 //------------------------------------------------------------------------- > 768 > 769 namespace { > 770 static const TCHAR* const s_mrulock = TEXT("GreenPad_MRUMutex"); > 771 } > 772 > 773 void ConfigManager::AddMRU( const ki::Path& fname ) > 774 { > 775 Mutex mx(s_mrulock); > 776 > 777 // メモリ内のMRUリストを更新 > 778 { > 779 int i; > 780 for( i=0; i<countof(mru_); ++i ) > 781 if( mru_[i] == fname ) > 782 {++i; break;} > 783 for( --i; i>0; --i ) > 784 mru_[i] = mru_[i-1]; > 785 mru_[0] = fname; > 786 } > 787 > 788 // iniへ保存 > 789 { > 790 ini_.SetSectionAsUserName(); > 791 const String key = TEXT("MRU"); > 792 for( int i=0; i<countof(mru_); ++i ) > 793 ini_.PutPath( > 794 (key+String().SetInt(i+1)).c_str(), mru_[i] ); > 795 } > 796 } > 797 > 798 void ConfigManager::SetUpMRUMenu( HMENU m, UINT id ) > 799 { > 800 Mutex mx(s_mrulock); > 801 > 802 // iniから読み込み > 803 { > 804 ini_.SetSectionAsUserName(); > 805 const String key = TEXT("MRU"); > 806 for( int i=0; i<countof(mru_); ++i ) > 807 mru_[i] = ini_.GetPath( > 808 (key+String().SetInt(i+1)).c_str(), Path() ); > 809 } > 810 > 811 // 全項目を削除 > 812 while( ::DeleteMenu( m, 0, MF_BYPOSITION ) ); > 813 > 814 // メニュー構築 > 815 MENUITEMINFO mi = { sizeof(MENUITEMINFO) }; > 816 mi.fMask = MIIM_ID | MIIM_TYPE; > 817 mi.fType = MFT_STRING; > 818 for( int i=0; i<countof(mru_); ++i ) > 819 { > 820 if( i>=mrus_ || mru_[i].len()==0 ) > 821 { > 822 if( i==0 ) > 823 { > 824 mi.fMask |= MIIM_STATE; > 825 mi.wID = id; > 826 mi.fState = MFS_DISABLED; > 827 mi.dwTypeData = TEXT("no files"); > 828 mi.cch = 0; > 829 ::InsertMenuItem( m, 0, MF_BYPOSITION, &mi ); > 830 } > 831 break; > 832 } > 833 String cpt = mru_[i].CompactIfPossible(60); > 834 mi.wID = id + i; > 835 mi.dwTypeData = const_cast<TCHAR*>(cpt.c_str()); > 836 mi.cch = cpt.len(); > 837 ::InsertMenuItem( m, i, MF_BYPOSITION, &mi ); > 838 } > 839 } > 840 > 841 Path ConfigManager::GetMRU( int no ) const > 842 { > 843 return (0<=no && no<mrus_ ? mru_[no] : Path()); > 844 } > 845 > 846 > 847 //------------------------------------------------------------------------- > 848 // ウインドウサイズ復元処理 > 849 //------------------------------------------------------------------------- > 850 > 851 void ConfigManager::RememberWnd( ki::Window* wnd ) > 852 { > 853 RECT rc; > 854 wnd->getPos(&rc); > 855 WINDOWPLACEMENT wp = {sizeof(wp)}; > 856 ::GetWindowPlacement( wnd->hwnd(), &wp ); > 857 > 858 if( wp.showCmd==SW_SHOWNORMAL || wp.showCmd == SW_MAXIMIZE ) > 859 wndM_ = (wp.showCmd == SW_MAXIMIZE); > 860 if( wp.showCmd==SW_SHOWNORMAL ) > 861 { > 862 wndX_ = rc.left; > 863 wndY_ = rc.top; > 864 wndW_ = rc.right- rc.left; > 865 wndH_ = rc.bottom - rc.top; > 866 } > 867 //if( this->rememberWindowPlace_ || this->rememberWindowSize_ ) > 868 // SaveIni(); > 869 } > 870 > 871 //------------------------------------------------------------------------- > 872 // [文書タイプ]サブメニューの作成 > 873 //------------------------------------------------------------------------- > 874 > 875 void ConfigManager::SetDocTypeMenu( HMENU m, UINT idstart ) > 876 { > 877 // 全項目を削除 > 878 while( ::DeleteMenu( m, 0, MF_BYPOSITION ) ); > 879 > 880 // 順に追加 > 881 MENUITEMINFO mi = { sizeof(MENUITEMINFO) }; > 882 mi.fMask = MIIM_ID | MIIM_STATE | MIIM_TYPE; > 883 mi.fType = MFT_STRING | MFT_RADIOCHECK; > 884 > 885 DtList::iterator i=dtList_.begin(), e=dtList_.end(); > 886 for( int ct=0; i!=e; ++i, ++ct ) > 887 { > 888 mi.wID = idstart + ct; > 889 mi.fState = (i==curDt_ ? MFS_CHECKED : MFS_UNCHECKED); > 890 mi.dwTypeData = const_cast<TCHAR*>(i->name.c_str()); > 891 mi.cch = i->name.len(); > 892 ::InsertMenuItem( m, ct, MF_BYPOSITION, &mi ); > 893 } > 894 } > 895 > 896 void ConfigManager::SetDocTypeByMenu( int pos, HMENU m ) > 897 { > 898 MENUITEMINFO mi = { sizeof(MENUITEMINFO) }; > 899 mi.fMask = MIIM_STATE; > 900 > 901 DtList::iterator i=dtList_.begin(), e=dtList_.end(); > 902 for( int ct=0; i!=e; ++i, ++ct ) > 903 { > 904 mi.fState = (ct==pos ? MFS_CHECKED : MFS_UNCHECKED); > 905 ::SetMenuItemInfo( m, ct, MF_BYPOSITION, &mi ); > 906 if( ct == pos ) > 907 { > 908 curDt_ = i; > 909 LoadLayout( &*curDt_ ); > 910 } > 911 } > 912 } > 913 > 914 void ConfigManager::CheckMenu( HMENU m, int pos ) > 915 { > 916 MENUITEMINFO mi = { sizeof(MENUITEMINFO) }; > 917 mi.fMask = MIIM_STATE; > 918 > 919 DtList::iterator i=dtList_.begin(), e=dtList_.end(); > 920 for( int ct=0; i!=e; ++i, ++ct ) > 921 { > 922 mi.fState = (ct==pos ? MFS_CHECKED : MFS_UNCHECKED); > 923 ::SetMenuItemInfo( m, ct, MF_BYPOSITION, &mi ); > 924 } > 925 } > 926

Added ConfigManager.h version [2b7c9df8032db9a4]

> 1 #ifndef AFX_ONFIGMANAGER_H__9243DE9D_0F70_40F8_8F90_55436B952B37__INCLUDED_ > 2 #define AFX_ONFIGMANAGER_H__9243DE9D_0F70_40F8_8F90_55436B952B37__INCLUDED_ > 3 #include "editwing/editwing.h" > 4 #include "OpenSaveDlg.h" > 5 > 6 > 7 > 8 // アプリケーションメッセージ > 9 #define GPM_MRUCHANGED WM_APP+0 > 10 > 11 //========================================================================= > 12 //@{ @pkg Gp.Main //@} > 13 //@{ > 14 // 設定の一元管理 > 15 // > 16 // SetDocTypeで切り替えると、文書タイプ依存の項目を内部で > 17 // 適切に切り替えたり色々します。 > 18 //@} > 19 //========================================================================= > 20 > 21 class ConfigManager : public ki::Object > 22 { > 23 public: > 24 > 25 ConfigManager(); > 26 ~ConfigManager(); > 27 > 28 //@{ 指定した名前のファイル用の文書タイプをロード //@} > 29 int SetDocType( const ki::Path& fname ); > 30 > 31 //@{ 指定した番号の文書タイプをロード //@} > 32 void SetDocTypeByMenu( int pos, HMENU m ); > 33 > 34 //@{ 指定した名前の文書タイプをロード //@} > 35 void SetDocTypeByName( const ki::String& nam ); > 36 > 37 //@{ メニュー項目作成 //@} > 38 void SetDocTypeMenu( HMENU m, UINT idstart ); > 39 > 40 //@{ メニュー項目のチェック修正 //@} > 41 void CheckMenu( HMENU m, int pos ); > 42 > 43 //@{ 設定ダイアログ表示 //@} > 44 bool DoDialog( const ki::Window& parent ); > 45 > 46 //@{ 生のiniファイル操作オブジェクトを取得 //@} > 47 ki::IniFile& getImpl(); > 48 > 49 public: > 50 > 51 //@{ Undo回数制限値 //@} > 52 int undoLimit() const; > 53 > 54 //@{ 文字数のカウント方法 //@} > 55 bool countByUnicode() const; > 56 > 57 //@{ 開く/保存ダイアログに出すフィルタの設定 //@} > 58 const ki::String& txtFileFilter() const; > 59 > 60 //@{ 文字数指定時の折り返し文字数 //@} > 61 int wrapWidth() const; > 62 > 63 //@{ 折り返し方法 //@} > 64 int wrapType() const; > 65 > 66 //@{ 行番号表示する? //@} > 67 bool showLN() const; > 68 > 69 //@{ 表示色・フォントなど //@} > 70 const editwing::VConfig& vConfig() const; > 71 > 72 //@{ キーワードファイル名(フルパス) //@} > 73 ki::Path kwdFile() const; > 74 > 75 //@{ Grep用外部実行ファイル名 //@} > 76 const ki::Path& grepExe() const; > 77 > 78 //@{ 同じウインドウで開くモード //@} > 79 bool openSame() const; > 80 > 81 //@{ ステータスバー表示 //@} > 82 bool showStatusBar() const; > 83 void ShowStatusBarSwitch(); > 84 > 85 public: > 86 //@{ 新規ファイルの文字コードindex //@} > 87 int GetNewfileCsi() const; > 88 > 89 //@{ 新規ファイルの改行コード //@} > 90 ki::lbcode GetNewfileLB() const; > 91 > 92 public: > 93 //@{ [最近使ったファイル]へ追加 //@} > 94 void AddMRU( const ki::Path& fname ); > 95 > 96 //@{ [最近使ったファイル]メニューの構築 //@} > 97 void SetUpMRUMenu( HMENU m, UINT id ); > 98 > 99 //@{ [最近使ったファイル]取得 //@} > 100 ki::Path GetMRU( int no ) const; > 101 > 102 //@{ 対応文字セットリスト取得 //@} > 103 CharSetList& GetCharSetList(); > 104 > 105 public: > 106 //@{ ウインドウ位置・サイズ復元処理 //@} > 107 int GetWndX() const; > 108 int GetWndY() const; > 109 int GetWndW() const; > 110 int GetWndH() const; > 111 bool GetWndM() const; > 112 void RememberWnd( ki::Window* wnd ); > 113 > 114 private: > 115 > 116 ki::IniFile ini_; > 117 bool sharedConfigMode_; > 118 CharSetList charSets_; > 119 > 120 // 全体的な設定 > 121 int undoLimit_; > 122 ki::String txtFilter_; > 123 ki::Path grepExe_; > 124 bool openSame_; > 125 bool countbyunicode_; > 126 bool showStatusBar_; > 127 bool rememberWindowSize_; > 128 bool rememberWindowPlace_; > 129 > 130 // ウインドウサイズ記憶 > 131 bool wndM_; // maximized? > 132 int wndX_, wndY_, wndW_, wndH_; > 133 > 134 // 文書タイプのリスト > 135 struct DocType > 136 { > 137 // 定義ファイル名など > 138 ki::String name; > 139 ki::String pattern; > 140 ki::String kwdfile; > 141 ki::String layfile; > 142 > 143 // 設定項目 > 144 editwing::VConfig vc; > 145 int wrapType; > 146 int wrapWidth; > 147 bool showLN; > 148 }; > 149 typedef ki::olist<DocType> DtList; > 150 > 151 DtList dtList_; > 152 DtList::iterator curDt_; > 153 > 154 // 最近使ったファイルのリスト > 155 int mrus_; > 156 ki::Path mru_[20]; > 157 > 158 // 新規ファイル関係 > 159 int newfileCharset_; > 160 ki::String newfileDoctype_; > 161 ki::lbcode newfileLB_; > 162 > 163 private: > 164 > 165 void LoadIni(); > 166 void SaveIni(); > 167 void LoadLayout( DocType* dt ); > 168 bool MatchDocType( const unicode* fname, const unicode* pat ); > 169 > 170 private: > 171 > 172 friend struct ConfigDlg; > 173 NOCOPY(ConfigManager); > 174 }; > 175 > 176 > 177 > 178 //------------------------------------------------------------------------- > 179 #ifndef __ccdoc__ > 180 > 181 inline int ConfigManager::undoLimit() const > 182 { return undoLimit_; } > 183 > 184 inline const ki::String& ConfigManager::txtFileFilter() const > 185 { return txtFilter_; } > 186 > 187 inline int ConfigManager::wrapWidth() const > 188 { return curDt_->wrapWidth; } > 189 > 190 inline int ConfigManager::wrapType() const > 191 { return curDt_->wrapType>0 ? wrapWidth() : curDt_->wrapType; } > 192 > 193 inline bool ConfigManager::showLN() const > 194 { return curDt_->showLN; } > 195 > 196 inline const editwing::VConfig& ConfigManager::vConfig() const > 197 { return curDt_->vc; } > 198 > 199 inline ki::Path ConfigManager::kwdFile() const > 200 { return ki::Path(ki::Path::Exe)+TEXT("type\\")+curDt_->kwdfile; } > 201 > 202 inline const ki::Path& ConfigManager::grepExe() const > 203 { return grepExe_; } > 204 > 205 inline bool ConfigManager::openSame() const > 206 { return openSame_; } > 207 > 208 inline bool ConfigManager::showStatusBar() const > 209 { return showStatusBar_; } > 210 > 211 inline void ConfigManager::ShowStatusBarSwitch() > 212 { showStatusBar_ = !showStatusBar_; SaveIni(); } > 213 > 214 inline bool ConfigManager::countByUnicode() const > 215 { return countbyunicode_; } > 216 > 217 inline ki::IniFile& ConfigManager::getImpl() > 218 { return ini_; } > 219 > 220 inline CharSetList& ConfigManager::GetCharSetList() > 221 { return charSets_; } > 222 > 223 inline int ConfigManager::GetNewfileCsi() const > 224 { return charSets_.findCsi( newfileCharset_ ); } > 225 > 226 inline ki::lbcode ConfigManager::GetNewfileLB() const > 227 { return newfileLB_; } > 228 > 229 inline int ConfigManager::GetWndX() const > 230 { return rememberWindowPlace_ ? wndX_ : CW_USEDEFAULT; } > 231 > 232 inline int ConfigManager::GetWndY() const > 233 { return rememberWindowPlace_ ? wndY_ : CW_USEDEFAULT; } > 234 > 235 inline int ConfigManager::GetWndW() const > 236 { return rememberWindowSize_ ? wndW_ : CW_USEDEFAULT; } > 237 > 238 inline int ConfigManager::GetWndH() const > 239 { return rememberWindowSize_ ? wndH_ : CW_USEDEFAULT; } > 240 > 241 inline bool ConfigManager::GetWndM() const > 242 { return rememberWindowSize_ & wndM_; } > 243 > 244 //========================================================================= > 245 > 246 #endif // __ccdoc__ > 247 #endif // AFX_ONFIGMANAGER_H__9243DE9D_0F70_40F8_8F90_55436B952B37__INCLUDED_

Added GpMain.cpp version [72773e35b0a1a949]

> 1 #include "stdafx.h" > 2 #include "rsrc/resource.h" > 3 #include "GpMain.h" > 4 using namespace ki; > 5 using namespace editwing; > 6 > 7 > 8 > 9 //------------------------------------------------------------------------- > 10 // 新規プロセス起動 > 11 //------------------------------------------------------------------------- > 12 > 13 void BootNewProcess( const TCHAR* cmd = TEXT("") ) > 14 { > 15 STARTUPINFO sti; > 16 PROCESS_INFORMATION psi; > 17 ::GetStartupInfo( &sti ); > 18 > 19 String fcmd = Path(Path::ExeName).BeShortStyle(); > 20 fcmd += ' '; > 21 fcmd += cmd; > 22 > 23 if( ::CreateProcess( NULL, const_cast<TCHAR*>(fcmd.c_str()), > 24 NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, > 25 &sti, &psi ) ) > 26 { > 27 ::CloseHandle( psi.hThread ); > 28 ::CloseHandle( psi.hProcess ); > 29 } > 30 } > 31 > 32 > 33 > 34 //------------------------------------------------------------------------- > 35 // ステータスバー制御 > 36 //------------------------------------------------------------------------- > 37 > 38 inline GpStBar::GpStBar() > 39 : str_(NULL) > 40 , lb_(2) > 41 { > 42 } > 43 > 44 inline void GpStBar::SetCsText( const TCHAR* str ) > 45 { > 46 // 文字コード表示領域にSetTextする > 47 SetText( str_=str, 1 ); > 48 } > 49 > 50 inline void GpStBar::SetLbText( int lb ) > 51 { > 52 // 改行コード表示領域にSetTextする > 53 static const TCHAR* const lbstr[] = {TEXT("CR"),TEXT("LF"),TEXT("CRLF")} > 54 SetText( lbstr[lb_=lb], 2 ); > 55 } > 56 > 57 int GpStBar::AutoResize( bool maximized ) > 58 { > 59 // 文字コード表示領域を確保しつつリサイズ > 60 int h = StatusBar::AutoResize( maximized ); > 61 int w[] = { width()-5, width()-5, width()-5 }; > 62 > 63 HDC dc = ::GetDC( hwnd() ); > 64 SIZE s; > 65 if( ::GetTextExtentPoint32( dc, TEXT("BBBBM"), 5, &s ) ) > 66 w[1] = w[2] - s.cx; > 67 if( ::GetTextExtentPoint32( dc, TEXT("BBBBB"), 5, &s ) ) > 68 w[0] = w[1] - s.cx; > 69 ::ReleaseDC( hwnd(), dc ); > 70 > 71 SetParts( countof(w), w ); > 72 SetCsText( str_ ); > 73 SetLbText( lb_ ); > 74 return h; > 75 } > 76 > 77 > 78 > 79 //------------------------------------------------------------------------- > 80 // ディスパッチャ > 81 //------------------------------------------------------------------------- > 82 > 83 LRESULT GreenPadWnd::on_message( UINT msg, WPARAM wp, LPARAM lp ) > 84 { > 85 switch( msg ) > 86 { > 87 // アクティブ化。EditCtrlにフォーカスを。 > 88 case WM_ACTIVATE: > 89 if( LOWORD(wp) != WA_INACTIVE ) > 90 edit_.SetFocus(); > 91 break; > 92 > 93 // サイズ変更。子窓を適当に移動。 > 94 case WM_SIZE: > 95 if( wp==SIZE_MAXIMIZED || wp==SIZE_RESTORED ) > 96 { > 97 int ht = stb_.AutoResize( wp==SIZE_MAXIMIZED ); > 98 edit_.MoveTo( 0, 0, LOWORD(lp), HIWORD(lp)-ht ); > 99 cfg_.RememberWnd(this); > 100 } > 101 break; > 102 > 103 // ウインドウ移動 > 104 case WM_MOVE: > 105 { > 106 RECT rc; > 107 getPos(&rc); > 108 cfg_.RememberWnd(this); > 109 } > 110 break; > 111 > 112 // システムコマンド。終了ボタンとか。 > 113 case WM_SYSCOMMAND: > 114 if( wp==SC_CLOSE || wp==SC_DEFAULT ) > 115 on_exit(); > 116 else > 117 return WndImpl::on_message( msg, wp, lp ); > 118 break; > 119 > 120 // 右クリックメニュー > 121 case WM_CONTEXTMENU: > 122 if( reinterpret_cast<HWND>(wp) == edit_.hwnd() ) > 123 ::TrackPopupMenu( > 124 ::GetSubMenu( ::GetMenu(hwnd()), 1 ), // 編集メニュー表示 > 125 TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON|TPM_RI > 126 LOWORD(lp), HIWORD(lp), 0, hwnd(), NULL ); > 127 else > 128 return WndImpl::on_message( msg, wp, lp ); > 129 break; > 130 > 131 // メニューのグレーアウト処理 > 132 case WM_INITMENU: > 133 case WM_INITMENUPOPUP: > 134 on_initmenu( reinterpret_cast<HMENU>(wp), msg==WM_INITMENUPOPUP > 135 break; > 136 > 137 // D&D > 138 case WM_DROPFILES: > 139 on_drop( reinterpret_cast<HDROP>(wp) ); > 140 break; > 141 > 142 // MRU > 143 case GPM_MRUCHANGED: > 144 SetupMRUMenu(); > 145 break; > 146 > 147 // その他 > 148 default: > 149 return WndImpl::on_message( msg, wp, lp ); > 150 } > 151 > 152 return 0; > 153 } > 154 > 155 bool GreenPadWnd::on_command( UINT id, HWND ctrl ) > 156 { > 157 switch( id ) > 158 { > 159 // Window > 160 case ID_CMD_NEXTWINDOW: on_nextwnd(); break; > 161 case ID_CMD_PREVWINDOW: on_prevwnd(); break; > 162 > 163 // File > 164 case ID_CMD_NEWFILE: on_newfile(); break; > 165 case ID_CMD_OPENFILE: on_openfile(); break; > 166 case ID_CMD_REOPENFILE: on_reopenfile();break; > 167 case ID_CMD_SAVEFILE: on_savefile(); break; > 168 case ID_CMD_SAVEFILEAS: on_savefileas();break; > 169 case ID_CMD_EXIT: on_exit(); break; > 170 > 171 // Edit > 172 case ID_CMD_UNDO: edit_.getDoc().Undo(); break; > 173 case ID_CMD_REDO: edit_.getDoc().Redo(); break; > 174 case ID_CMD_CUT: edit_.getCursor().Cut(); break; > 175 case ID_CMD_COPY: edit_.getCursor().Copy(); break; > 176 case ID_CMD_PASTE: edit_.getCursor().Paste(); break; > 177 case ID_CMD_DELETE: if( edit_.getCursor().isSelected() ) > 178 edit_.getCursor().Del(); break; > 179 case ID_CMD_SELECTALL: edit_.getCursor().Home(true,false); > 180 edit_.getCursor().End(true,true); break; > 181 case ID_CMD_DATETIME: on_datetime(); break; > 182 > 183 // Search > 184 case ID_CMD_FIND: search_.ShowDlg(); break; > 185 case ID_CMD_FINDNEXT: search_.FindNext(); break; > 186 case ID_CMD_FINDPREV: search_.FindPrev(); break; > 187 case ID_CMD_JUMP: on_jump(); break; > 188 case ID_CMD_GREP: on_grep();break; > 189 > 190 // View > 191 case ID_CMD_NOWRAP: edit_.getView().SetWrapType( wrap_=-1 ); break; > 192 case ID_CMD_WRAPWIDTH: edit_.getView().SetWrapType( wrap_=cfg_.wrapWidt > 193 case ID_CMD_WRAPWINDOW: edit_.getView().SetWrapType( wrap_=0 ); break; > 194 case ID_CMD_CONFIG: on_config(); break; > 195 case ID_CMD_STATUSBAR: on_statusBar(); break; > 196 > 197 // DocType > 198 default: if( ID_CMD_DOCTYPE <= id ) { > 199 on_doctype( id - ID_CMD_DOCTYPE ); > 200 break; > 201 } else if( ID_CMD_MRU <= id ) { > 202 on_mru( id - ID_CMD_MRU ); > 203 break; > 204 } > 205 > 206 // Default > 207 return false; > 208 } > 209 return true; > 210 } > 211 > 212 bool GreenPadWnd::PreTranslateMessage( MSG* msg ) > 213 { > 214 // 苦肉の策^^; > 215 if( search_.TrapMsg(msg) ) > 216 return true; > 217 // キーボードショートカット処理 > 218 return 0 != ::TranslateAccelerator( hwnd(), accel_, msg ); > 219 } > 220 > 221 > 222 > 223 //------------------------------------------------------------------------- > 224 // コマンド処理 > 225 //------------------------------------------------------------------------- > 226 > 227 void GreenPadWnd::on_dirtyflag_change( bool ) > 228 { > 229 UpdateWindowName(); > 230 } > 231 > 232 void GreenPadWnd::on_newfile() > 233 { > 234 BootNewProcess(); > 235 } > 236 > 237 void GreenPadWnd::on_openfile() > 238 { > 239 Path fn; > 240 int cs; > 241 if( ShowOpenDlg( &fn, &cs ) ) > 242 Open( fn, cs ); > 243 } > 244 > 245 void GreenPadWnd::on_reopenfile() > 246 { > 247 if( !isUntitled() ) > 248 { > 249 ReopenDlg dlg( charSets_, csi_ ); > 250 dlg.GoModal( hwnd() ); > 251 if( dlg.endcode()==IDOK && AskToSave() ) > 252 OpenByMyself( filename_, charSets_[dlg.csi()].ID, false > 253 } > 254 } > 255 > 256 void GreenPadWnd::on_savefile() > 257 { > 258 Save_showDlgIfNeeded(); > 259 } > 260 > 261 void GreenPadWnd::on_savefileas() > 262 { > 263 if( ShowSaveDlg() ) > 264 { > 265 Save(); > 266 ReloadConfig(); // 文書タイプに応じて表示を更新 > 267 } > 268 } > 269 > 270 void GreenPadWnd::on_exit() > 271 { > 272 search_.SaveToINI( cfg_.getImpl() ); > 273 if( AskToSave() ) > 274 Destroy(); > 275 } > 276 > 277 void GreenPadWnd::on_initmenu( HMENU menu, bool editmenu_only ) > 278 { > 279 LOGGER("GreenPadWnd::ReloadConfig on_initmenu begin"); > 280 MENUITEMINFO mi = { sizeof(MENUITEMINFO), MIIM_STATE }; > 281 > 282 mi.fState = > 283 (edit_.getCursor().isSelected() ? MFS_ENABLED : MFS_DISABLED); > 284 SetMenuItemInfo( menu, ID_CMD_CUT, FALSE, &mi ); > 285 SetMenuItemInfo( menu, ID_CMD_COPY, FALSE, &mi ); > 286 SetMenuItemInfo( menu, ID_CMD_DELETE, FALSE, &mi ); > 287 > 288 mi.fState = > 289 (edit_.getDoc().isUndoAble() ? MFS_ENABLED : MFS_DISABLED); > 290 SetMenuItemInfo( menu, ID_CMD_UNDO, FALSE, &mi ); > 291 > 292 mi.fState = > 293 (edit_.getDoc().isRedoAble() ? MFS_ENABLED : MFS_DISABLED); > 294 SetMenuItemInfo( menu, ID_CMD_REDO, FALSE, &mi ); > 295 > 296 if( editmenu_only ) > 297 { > 298 LOGGER("GreenPadWnd::ReloadConfig on_initmenu end"); > 299 return; > 300 } > 301 > 302 mi.fState = (isUntitled() || edit_.getDoc().isModified() > 303 ? MFS_ENABLED : MFS_DISABLED); > 304 SetMenuItemInfo( menu, ID_CMD_SAVEFILE, FALSE, &mi ); > 305 > 306 mi.fState = > 307 (!isUntitled() ? MFS_ENABLED : MFS_DISABLED); > 308 SetMenuItemInfo( menu, ID_CMD_REOPENFILE, FALSE, &mi ); > 309 > 310 mi.fState = > 311 (cfg_.grepExe().len()>0 ? MFS_ENABLED : MFS_DISABLED); > 312 SetMenuItemInfo( menu, ID_CMD_GREP, FALSE, &mi ); > 313 > 314 UINT id = (wrap_==-1 ? ID_CMD_NOWRAP > 315 : (wrap_>0 ? ID_CMD_WRAPWIDTH : ID_CMD_WRAPWINDOW)); > 316 ::CheckMenuRadioItem( > 317 menu, ID_CMD_NOWRAP, ID_CMD_WRAPWINDOW, id, MF_BYCOMMAND ); > 318 > 319 ::CheckMenuItem( menu, ID_CMD_STATUSBAR, > 320 cfg_.showStatusBar()?MFS_CHECKED:MFS_UNCHECKED ); > 321 LOGGER("GreenPadWnd::ReloadConfig on_initmenu end"); > 322 } > 323 > 324 void GreenPadWnd::on_drop( HDROP hd ) > 325 { > 326 UINT iMax = ::DragQueryFile( hd, 0xffffffff, NULL, 0 ); > 327 for( UINT i=0; i<iMax; ++i ) > 328 { > 329 TCHAR str[MAX_PATH]; > 330 ::DragQueryFile( hd, i, str, countof(str) ); > 331 Open( str, AutoDetect ); > 332 } > 333 ::DragFinish( hd ); > 334 } > 335 > 336 void GreenPadWnd::on_jump() > 337 { > 338 struct JumpDlg : public DlgImpl { > 339 JumpDlg(HWND w) : DlgImpl(IDD_JUMP), w_(w) { GoModal(w); } > 340 void on_init() { > 341 SetCenter(hwnd(),w_); ::SetFocus(item(IDC_LINEBOX)); } > 342 bool on_ok() { > 343 TCHAR str[100]; > 344 ::GetWindowText( item(IDC_LINEBOX), str, countof(str) ); > 345 LineNo = String(str).GetInt(); > 346 return true; > 347 } > 348 int LineNo; HWND w_; > 349 } dlg(hwnd()); > 350 > 351 if( IDOK == dlg.endcode() ) > 352 JumpToLine( dlg.LineNo ); > 353 } > 354 > 355 void GreenPadWnd::on_grep() > 356 { > 357 Path g = cfg_.grepExe(); > 358 if( g.len() != 0 ) > 359 { > 360 Path d; > 361 if( filename_.len() ) > 362 (d = filename_).BeDirOnly().BeBackSlash(false); > 363 else > 364 d = Path(Path::Cur); > 365 > 366 String fcmd; > 367 for( int i=0, e=g.len(); i<e; ++i ) > 368 if( g[i]==TEXT('%') ) > 369 { > 370 if( g[i+1]==TEXT('1') || g[i+1]==TEXT('D') ) // > 371 ++i, fcmd += d; > 372 else if( g[i+1]==TEXT('F') ) > 373 ++i, fcmd += filename_; > 374 else if( g[i+1]==TEXT('N') ) > 375 ++i, fcmd += filename_.name(); > 376 } > 377 else > 378 fcmd += g[i]; > 379 > 380 PROCESS_INFORMATION psi; > 381 STARTUPINFO sti = {sizeof(STARTUPINFO)}; > 382 //sti.dwFlags = STARTF_USESHOWWINDOW; > 383 //sti.wShowWindow = SW_SHOWNORMAL; > 384 if( ::CreateProcess( NULL, const_cast<TCHAR*>(fcmd.c_str()), > 385 NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, > 386 &sti, &psi ) ) > 387 { > 388 ::CloseHandle( psi.hThread ); > 389 ::CloseHandle( psi.hProcess ); > 390 } > 391 } > 392 } > 393 > 394 void GreenPadWnd::on_datetime() > 395 { > 396 TCHAR buf[255], tmp[255]; > 397 ::GetTimeFormat > 398 ( LOCALE_USER_DEFAULT, 0, NULL, TEXT("HH:mm "), buf, countof(buf > 399 ::GetDateFormat > 400 ( LOCALE_USER_DEFAULT, 0, NULL, TEXT("yy/MM/dd"),tmp,countof(tmp > 401 ::lstrcat( buf, tmp ); > 402 edit_.getCursor().Input( buf, ::lstrlen(buf) ); > 403 } > 404 > 405 void GreenPadWnd::on_doctype( int no ) > 406 { > 407 if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),3),4 ) ) > 408 { > 409 cfg_.SetDocTypeByMenu( no, m ); > 410 ReloadConfig( true ); > 411 } > 412 } > 413 > 414 void GreenPadWnd::on_config() > 415 { > 416 if( cfg_.DoDialog(*this) ) > 417 { > 418 SetupSubMenu(); > 419 SetupMRUMenu(); > 420 ReloadConfig(false); > 421 } > 422 } > 423 > 424 static inline void MyShowWnd( HWND wnd ) > 425 { > 426 if( ::IsIconic(wnd) ) > 427 ::ShowWindow( wnd, SW_RESTORE ); > 428 ::BringWindowToTop( wnd ); > 429 } > 430 > 431 void GreenPadWnd::on_nextwnd() > 432 { > 433 if( HWND next = ::FindWindowEx( NULL, hwnd(), className_, NULL ) ) > 434 { > 435 HWND last=next, pos; > 436 while( last != NULL ) > 437 last = ::FindWindowEx( NULL, pos=last, className_, NULL > 438 if( pos != next ) > 439 ::SetWindowPos( hwnd(), pos, > 440 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW > 441 MyShowWnd( next ); > 442 } > 443 } > 444 > 445 void GreenPadWnd::on_prevwnd() > 446 { > 447 HWND pos=NULL, next=::FindWindowEx( NULL,NULL,className_,NULL ); > 448 if( next==hwnd() ) > 449 { > 450 while( next != NULL ) > 451 next = ::FindWindowEx( NULL,pos=next,className_,NULL ); > 452 if( pos!=hwnd()) > 453 MyShowWnd( pos ); > 454 } > 455 else > 456 { > 457 while( next!=hwnd() && next!=NULL ) > 458 next = ::FindWindowEx( NULL,pos=next,className_,NULL ); > 459 if( next!=NULL ) > 460 MyShowWnd( pos ); > 461 } > 462 } > 463 > 464 void GreenPadWnd::on_statusBar() > 465 { > 466 stb_.SetStatusBarVisible( !stb_.isStatusBarVisible() ); > 467 cfg_.ShowStatusBarSwitch(); > 468 > 469 WINDOWPLACEMENT wp = {sizeof(wp)}; > 470 ::GetWindowPlacement( hwnd(), &wp ); > 471 if( wp.showCmd != SW_MINIMIZE ) > 472 { > 473 const int ht = stb_.AutoResize( wp.showCmd == SW_MAXIMIZE ); > 474 RECT rc; > 475 getClientRect(&rc); > 476 edit_.MoveTo( 0, 0, rc.right, rc.bottom-ht ); > 477 } > 478 } > 479 > 480 void GreenPadWnd::on_move( const DPos& c, const DPos& s ) > 481 { > 482 static int busy_cnt = 0; > 483 if( edit_.getDoc().isBusy() && ((++busy_cnt)&0xff) ) > 484 return; > 485 > 486 ulong cad = c.ad; > 487 if( ! cfg_.countByUnicode() ) > 488 { > 489 // ShiftJIS風のByte数カウント > 490 const unicode* cu = edit_.getDoc().tl(c.tl); > 491 const ulong tab = cfg_.vConfig().tabstep; > 492 cad = 0; > 493 for( ulong i=0; i<c.ad; ++i ) > 494 if( cu[i] == L'\t' ) > 495 cad = (cad/tab+1)*tab; > 496 else if( cu[i]<0x80 || 0xff60<=cu[i] && cu[i]<=0xff9f ) > 497 cad = cad + 1; > 498 else > 499 cad = cad + 2; > 500 } > 501 > 502 String str; > 503 str += TEXT('('); > 504 str += String().SetInt(c.tl+1); > 505 str += TEXT(','); > 506 str += String().SetInt(cad+1); > 507 str += TEXT(')'); > 508 if( c != s ) > 509 { > 510 ulong sad = s.ad; > 511 if( ! cfg_.countByUnicode() ) > 512 { > 513 // ShiftJIS風のByte数カウント > 514 const unicode* su = edit_.getDoc().tl(s.tl); > 515 sad = 0; > 516 for( ulong i=0; i<s.ad; ++i ) > 517 sad += (su[i]<0x80 || 0xff60<=su[i] && su[i]<=0x > 518 } > 519 str += TEXT(" - ("); > 520 str += String().SetInt(s.tl+1); > 521 str += TEXT(','); > 522 str += String().SetInt(sad+1); > 523 str += TEXT(')'); > 524 } > 525 stb_.SetText( str.c_str() ); > 526 } > 527 > 528 > 529 > 530 //------------------------------------------------------------------------- > 531 // ユーティリティー > 532 //------------------------------------------------------------------------- > 533 > 534 void GreenPadWnd::JumpToLine( ulong ln ) > 535 { > 536 edit_.getCursor().MoveCur( DPos(ln-1,0), false ); > 537 } > 538 > 539 void GreenPadWnd::SetupSubMenu() > 540 { > 541 if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),3),4 ) ) > 542 { > 543 cfg_.SetDocTypeMenu( m, ID_CMD_DOCTYPE ); > 544 ::DrawMenuBar( hwnd() ); > 545 } > 546 } > 547 > 548 void GreenPadWnd::UpdateWindowName() > 549 { > 550 // タイトルバーに表示される文字列の調整 > 551 // [FileName *] - GreenPad > 552 String name; > 553 name += TEXT('['); > 554 name += isUntitled() ? TEXT("untitled") : filename_.name(); > 555 if( edit_.getDoc().isModified() ) name += TEXT(" *"); > 556 name += TEXT("] - "); > 557 name += String(IDS_APPNAME).c_str(); > 558 > 559 SetText( name.c_str() ); > 560 stb_.SetCsText( charSets_[csi_].shortName ); > 561 stb_.SetLbText( lb_ ); > 562 } > 563 > 564 void GreenPadWnd::SetupMRUMenu() > 565 { > 566 if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),0),8 ) ) > 567 { > 568 cfg_.SetUpMRUMenu( m, ID_CMD_MRU ); > 569 ::DrawMenuBar( hwnd() ); > 570 } > 571 } > 572 > 573 void GreenPadWnd::on_mru( int no ) > 574 { > 575 Path fn = cfg_.GetMRU(no); > 576 if( fn.len() != 0 ) > 577 Open( fn, AutoDetect ); > 578 } > 579 > 580 > 581 > 582 //------------------------------------------------------------------------- > 583 // 設定更新処理 > 584 //------------------------------------------------------------------------- > 585 > 586 void GreenPadWnd::ReloadConfig( bool noSetDocType ) > 587 { > 588 // 文書タイプロード > 589 if( !noSetDocType ) > 590 { > 591 int t = cfg_.SetDocType( filename_ ); > 592 if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),3),4 > 593 cfg_.CheckMenu( m, t ); > 594 } > 595 LOGGER("GreenPadWnd::ReloadConfig DocTypeLoaded"); > 596 > 597 // Undo回数制限 > 598 edit_.getDoc().SetUndoLimit( cfg_.undoLimit() ); > 599 > 600 // 行番号 > 601 bool ln = cfg_.showLN(); > 602 edit_.getView().ShowLineNo( ln ); > 603 > 604 // 折り返し方式 > 605 wrap_ = cfg_.wrapType(); > 606 edit_.getView().SetWrapType( wrap_ ); > 607 > 608 // 色・フォント > 609 VConfig vc = cfg_.vConfig(); > 610 edit_.getView().SetFont( vc ); > 611 LOGGER("GreenPadWnd::ReloadConfig ViewConfigLoaded"); > 612 > 613 // キーワードファイル > 614 Path kwd = cfg_.kwdFile(); > 615 FileR fp; > 616 if( kwd.len()!=0 && fp.Open(kwd.c_str()) ) > 617 edit_.getDoc().SetKeyword((const unicode*)fp.base(),fp.size()/2) > 618 else > 619 edit_.getDoc().SetKeyword(NULL,0); > 620 LOGGER("GreenPadWnd::ReloadConfig KeywordLoaded"); > 621 } > 622 > 623 > 624 > 625 //------------------------------------------------------------------------- > 626 // 開く処理 > 627 //------------------------------------------------------------------------- > 628 > 629 bool GreenPadWnd::ShowOpenDlg( Path* fn, int* cs ) > 630 { > 631 // [Open][Cancel] 開くファイル名指定ダイアログを表示 > 632 String flst[] = { > 633 String(IDS_TXTFILES), > 634 String(cfg_.txtFileFilter()), > 635 String(IDS_ALLFILES), > 636 String(TEXT("*.*")) > 637 }; > 638 aarr<TCHAR> filt = OpenFileDlg::ConnectWithNull(flst,countof(flst)); > 639 > 640 OpenFileDlg ofd( charSets_ ); > 641 bool ok = ofd.DoModal( hwnd(), filt.get(), filename_.c_str() ); > 642 if( ok ) > 643 { > 644 *fn = ofd.filename(); > 645 *cs = charSets_[ofd.csi()].ID; > 646 } > 647 > 648 return ok; > 649 } > 650 > 651 bool GreenPadWnd::Open( const ki::Path& fn, int cs ) > 652 { > 653 if( isUntitled() && !edit_.getDoc().isModified() ) > 654 { > 655 // 無題で無変更だったら自分で開く > 656 return OpenByMyself( fn, cs ); > 657 } > 658 else > 659 { > 660 // 同じ窓で開くモードならそうする > 661 if( cfg_.openSame() ) > 662 return ( AskToSave() ? OpenByMyself( fn, cs ) : true ); > 663 > 664 // そうでなければ他へ回す > 665 String > 666 cmd = TEXT("-c"); > 667 cmd += String().SetInt( cs ); > 668 cmd += TEXT(" \""); > 669 cmd += fn; > 670 cmd += TEXT('\"'); > 671 BootNewProcess( cmd.c_str() ); > 672 return true; > 673 } > 674 } > 675 > 676 bool GreenPadWnd::OpenByMyself( const ki::Path& fn, int cs, bool needReConf ) > 677 { > 678 // ファイルを開けなかったらそこでおしまい。 > 679 aptr<TextFileR> tf( new TextFileR(cs) ); > 680 if( !tf->Open( fn.c_str() ) ) > 681 { > 682 // ERROR! > 683 MsgBox( String(IDS_OPENERROR).c_str() ); > 684 return false; > 685 } > 686 > 687 // 自分内部の管理情報を更新 > 688 if( fn[0]==TEXT('\\') || fn[1]==TEXT(':') ) > 689 filename_ = fn; > 690 else > 691 filename_ = Path( Path::Cur ) + fn; > 692 if( tf->size() ) > 693 { > 694 csi_ = charSets_.findCsi( tf->codepage() ); > 695 if( tf->nolb_found() ) > 696 lb_ = cfg_.GetNewfileLB(); > 697 else > 698 lb_ = tf->linebreak(); > 699 } > 700 else > 701 { // 空ファイルの場合は新規作成と同じ扱い > 702 csi_ = cfg_.GetNewfileCsi(); > 703 lb_ = cfg_.GetNewfileLB(); > 704 } > 705 filename_.BeShortLongStyle(); > 706 > 707 // カレントディレクトリを、ファイルのある位置以外にしておく > 708 // (こうしないと、開いているファイルのあるディレクトリが削除できない) > 709 ::SetCurrentDirectory( Path(filename_).BeDriveOnly().c_str() ); > 710 > 711 // 文書タイプに応じて表示を更新 > 712 if( needReConf ) > 713 ReloadConfig(); > 714 > 715 // 開く > 716 edit_.getDoc().ClearAll(); > 717 edit_.getDoc().OpenFile( tf ); > 718 > 719 // タイトルバー更新 > 720 UpdateWindowName(); > 721 > 722 // [最近使ったファイル]へ追加 > 723 cfg_.AddMRU( filename_ ); > 724 HWND wnd = NULL; > 725 while( NULL!=(wnd=::FindWindowEx( NULL, wnd, className_, NULL )) ) > 726 SendMessage( wnd, GPM_MRUCHANGED, 0, 0 ); > 727 > 728 return true; > 729 } > 730 > 731 > 732 > 733 //------------------------------------------------------------------------- > 734 // 保存処理 > 735 //------------------------------------------------------------------------- > 736 > 737 bool GreenPadWnd::ShowSaveDlg() > 738 { > 739 // [Save][Cancel] 保存先ファイル名指定ダイアログを表示 > 740 > 741 String flst[] = { > 742 String(IDS_ALLFILES), > 743 String(TEXT("*.*")) > 744 }; > 745 aarr<TCHAR> filt = SaveFileDlg::ConnectWithNull( flst, countof(flst) ); > 746 > 747 SaveFileDlg sfd( charSets_, csi_, lb_ ); > 748 if( !sfd.DoModal( hwnd(), filt.get(), filename_.c_str() ) ) > 749 return false; > 750 > 751 filename_ = sfd.filename(); > 752 csi_ = sfd.csi(); > 753 lb_ = sfd.lb(); > 754 > 755 return true; > 756 } > 757 > 758 bool GreenPadWnd::Save_showDlgIfNeeded() > 759 { > 760 bool wasUntitled = isUntitled(); > 761 > 762 // [Save][Cancel] ファイル名未定ならダイアログ表示 > 763 if( isUntitled() ) > 764 if( !ShowSaveDlg() ) > 765 return false; > 766 if( Save() ) > 767 { > 768 if( wasUntitled ) > 769 ReloadConfig(); // 文書タイプに応じて表示を更新 > 770 return true; > 771 } > 772 return false; > 773 } > 774 > 775 bool GreenPadWnd::AskToSave() > 776 { > 777 // 変更されていたら、 > 778 // [Yes][No][Cancel] 保存するかどうか尋ねる。 > 779 // 保存するなら > 780 // [Save][Cancel] ファイル名未定ならダイアログ表示 > 781 > 782 if( edit_.getDoc().isModified() ) > 783 { > 784 int answer = MsgBox( > 785 String(IDS_ASKTOSAVE).c_str(), > 786 String(IDS_APPNAME).c_str(), > 787 MB_YESNOCANCEL|MB_ICONQUESTION > 788 ); > 789 if( answer == IDYES ) return Save_showDlgIfNeeded(); > 790 if( answer == IDCANCEL ) return false; > 791 } > 792 return true; > 793 } > 794 > 795 bool GreenPadWnd::Save() > 796 { > 797 TextFileW tf( charSets_[csi_].ID, lb_ ); > 798 if( tf.Open( filename_.c_str() ) ) > 799 { > 800 // 無事ファイルに保存できた場合 > 801 edit_.getDoc().SaveFile( tf ); > 802 UpdateWindowName(); > 803 // [最近使ったファイル]更新 > 804 cfg_.AddMRU( filename_ ); > 805 HWND wnd = NULL; > 806 while( NULL!=(wnd=::FindWindowEx( NULL, wnd, className_, NULL )) > 807 SendMessage( wnd, GPM_MRUCHANGED, 0, 0 ); > 808 return true; > 809 } > 810 > 811 // Error! > 812 MsgBox( String(IDS_SAVEERROR).c_str() ); > 813 return false; > 814 } > 815 > 816 > 817 > 818 //------------------------------------------------------------------------- > 819 // メインウインドウの初期化 > 820 //------------------------------------------------------------------------- > 821 > 822 GreenPadWnd::ClsName GreenPadWnd::className_ = TEXT("GreenPad MainWnd"); > 823 > 824 GreenPadWnd::GreenPadWnd() > 825 : WndImpl ( className_, WS_OVERLAPPEDWINDOW, WS_EX_ACCEPTFILES ) > 826 , charSets_( cfg_.GetCharSetList() ) > 827 , csi_ ( cfg_.GetNewfileCsi() ) > 828 , lb_ ( cfg_.GetNewfileLB() ) > 829 , search_ ( *this, edit_ ) > 830 { > 831 LOGGER( "GreenPadWnd::Construct begin" ); > 832 > 833 static WNDCLASSEX wc; > 834 wc.hIcon = app().LoadIcon( IDR_MAIN ); > 835 wc.hCursor = app().LoadOemCursor( IDC_ARROW ); > 836 wc.lpszMenuName = MAKEINTRESOURCE( IDR_MAIN ); > 837 wc.lpszClassName = className_; > 838 WndImpl::Register( &wc ); > 839 > 840 ime().EnableGlobalIME( true ); > 841 > 842 LOGGER( "GreenPadWnd::Construct end" ); > 843 } > 844 > 845 void GreenPadWnd::on_create( CREATESTRUCT* cs ) > 846 { > 847 LOGGER("GreenPadWnd::on_create begin"); > 848 > 849 accel_ = app().LoadAccel( IDR_MAIN ); > 850 stb_.Create( hwnd() ); > 851 edit_.Create( NULL, hwnd(), 0, 0, 100, 100 ); > 852 LOGGER("GreenPadWnd::on_create edit created"); > 853 edit_.getDoc().AddHandler( this ); > 854 edit_.getCursor().AddHandler( this ); > 855 stb_.SetStatusBarVisible( cfg_.showStatusBar() ); > 856 > 857 LOGGER("GreenPadWnd::on_create halfway"); > 858 > 859 search_.LoadFromINI( cfg_.getImpl() ); > 860 SetupSubMenu(); > 861 SetupMRUMenu(); > 862 > 863 LOGGER("GreenPadWnd::on_create menu"); > 864 } > 865 > 866 bool GreenPadWnd::StartUp( const Path& fn, int cs, int ln ) > 867 { > 868 LOGGER( "GreenPadWnd::StartUp begin" ); > 869 Create( 0, 0, cfg_.GetWndX(), cfg_.GetWndY(), cfg_.GetWndW(), cfg_.GetWn > 870 LOGGER( "GreenPadWnd::Created" ); > 871 if( fn.len()==0 || !OpenByMyself( fn, cs ) ) > 872 { > 873 LOGGER( "for new file..." ); > 874 > 875 // ファイルを開か(け)なかった場合 > 876 ReloadConfig( fn.len()==0 ); > 877 LOGGER( "GreenPadWnd::StartUp reloadconfig end" ); > 878 UpdateWindowName(); > 879 LOGGER( "GreenPadWnd::StartUp updatewindowname end" ); > 880 } > 881 > 882 // 指定の行へジャンプ > 883 if( ln != -1 ) > 884 JumpToLine( ln ); > 885 > 886 LOGGER( "GreenPadWnd::StartUp end" ); > 887 return true; > 888 } > 889 > 890 void GreenPadWnd::ShowUp2() > 891 { > 892 Window::ShowUp( cfg_.GetWndM() ? SW_MAXIMIZE : SW_SHOW ); > 893 } > 894 > 895 > 896 //------------------------------------------------------------------------- > 897 // スタートアップルーチン > 898 // コマンドラインの解析を行う > 899 //------------------------------------------------------------------------- > 900 > 901 int kmain() > 902 { > 903 LOGGER( "kmain() begin" ); > 904 > 905 Argv arg; > 906 ulong i; > 907 > 908 LOGGER( "argv processed" ); > 909 > 910 //-- まずオプションスイッチを処理 > 911 > 912 int optL = -1; > 913 int optC = 0; > 914 > 915 for( i=1; i<arg.size() && arg[i][0]==TEXT('-'); ++i ) > 916 switch( arg[i][1] ) > 917 { > 918 case TEXT('c'): > 919 optC = String::GetInt( arg[i]+2 ); > 920 break; > 921 case TEXT('l'): > 922 optL = String::GetInt( arg[i]+2 ); > 923 break; > 924 } > 925 > 926 LOGGER( "option processed" ); > 927 > 928 //-- 次にファイル名 > 929 > 930 Path file; > 931 > 932 if( i < arg.size() ) > 933 { > 934 file = arg[i]; > 935 if( !file.isFile() ) > 936 { > 937 ulong j; // ""無しで半スペ入りでもそれなりに対処 > 938 for( j=i+1; j<arg.size(); ++j ) > 939 { > 940 file += ' '; > 941 file += arg[j]; > 942 if( file.isFile() ) > 943 break; > 944 } > 945 > 946 if( j==arg.size() ) > 947 file = arg[i]; > 948 else > 949 i=j; > 950 } > 951 } > 952 > 953 LOGGER( "filename processed" ); > 954 > 955 //-- 余ってる引数があれば、それで新規プロセス起動 > 956 > 957 if( ++i < arg.size() ) > 958 { > 959 String cmd; > 960 for( ; i<arg.size(); ++i ) > 961 { > 962 cmd += TEXT('\"'); > 963 cmd += arg[i]; > 964 cmd += TEXT("\" "); > 965 } > 966 ::BootNewProcess( cmd.c_str() ); > 967 } > 968 > 969 LOGGER( "newprocess booted" ); > 970 > 971 //-- メインウインドウ発進 > 972 > 973 GreenPadWnd wnd; > 974 if( !wnd.StartUp(file,optC,optL) ) > 975 return -1; > 976 > 977 LOGGER( "kmain() startup ok" ); > 978 > 979 //-- メインループ > 980 > 981 wnd.ShowUp2(); > 982 LOGGER( "showup!" ); > 983 wnd.MsgLoop(); > 984 > 985 LOGGER( "fin" ); > 986 return 0; > 987 }

Added GpMain.h version [fb5b8d0bd744fed9]

> 1 #ifndef _GREENPAD_MAIN_H_ > 2 #define _GREENPAD_MAIN_H_ > 3 #include "kilib/kilib.h" > 4 #include "editwing/editwing.h" > 5 #include "OpenSaveDlg.h" > 6 #include "ConfigManager.h" > 7 #include "Search.h" > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg Gp.Main //@} > 13 //@{ > 14 // ステータスバー > 15 //@} > 16 //========================================================================= > 17 > 18 class GpStBar : public ki::StatusBar > 19 { > 20 public: > 21 GpStBar(); > 22 int AutoResize( bool maximized ); > 23 void SetCsText( const TCHAR* str ); > 24 void SetLbText( int lb ); > 25 private: > 26 const TCHAR *str_; > 27 int lb_; > 28 }; > 29 > 30 > 31 > 32 //========================================================================= > 33 //@{ > 34 // メインウインドウ > 35 //@} > 36 //========================================================================= > 37 > 38 class GreenPadWnd > 39 : public ki::WndImpl > 40 , public editwing::doc::DocEvHandler > 41 , public editwing::view::CurEvHandler > 42 { > 43 public: > 44 > 45 GreenPadWnd(); > 46 bool StartUp( const ki::Path& fn, int cs, int ln ); > 47 void ShowUp2(); > 48 > 49 private: > 50 > 51 void UpdateWindowName(); > 52 void ReloadConfig( bool noSetDocType=false ); > 53 > 54 bool ShowOpenDlg( ki::Path* fn, int* cs ); > 55 bool Open( const ki::Path& fn, int cs ); > 56 bool OpenByMyself( const ki::Path& fn, int cs, bool needReConf=true ); > 57 > 58 bool AskToSave(); > 59 bool Save_showDlgIfNeeded(); > 60 bool ShowSaveDlg(); > 61 bool Save(); > 62 > 63 void JumpToLine( ulong ln ); > 64 void SetupSubMenu(); > 65 void SetupMRUMenu(); > 66 > 67 private: > 68 > 69 bool isUntitled() const { return filename_.len()==0; } > 70 > 71 private: > 72 > 73 ConfigManager cfg_; > 74 SearchManager search_; > 75 CharSetList& charSets_; > 76 > 77 editwing::EwEdit edit_; > 78 GpStBar stb_; > 79 HACCEL accel_; > 80 > 81 ki::Path filename_; > 82 int csi_; > 83 int lb_; > 84 int wrap_; > 85 > 86 static ClsName className_; > 87 > 88 private: > 89 > 90 void on_create( CREATESTRUCT* cs ); > 91 LRESULT on_message( UINT msg, WPARAM wp, LPARAM lp ); > 92 bool on_command( UINT id, HWND ctrl ); > 93 void on_newfile(); > 94 void on_openfile(); > 95 void on_reopenfile(); > 96 void on_savefile(); > 97 void on_savefileas(); > 98 void on_exit(); > 99 void on_initmenu( HMENU menu, bool editmenu_only ); > 100 void on_drop( HDROP hd ); > 101 void on_dirtyflag_change( bool ); > 102 void on_move( const editwing::DPos& c, const editwing::DPos& s ); > 103 void on_jump(); > 104 void on_grep(); > 105 void on_config(); > 106 void on_datetime(); > 107 void on_doctype( int no ); > 108 void on_nextwnd(); > 109 void on_prevwnd(); > 110 void on_mru( int no ); > 111 void on_statusBar(); > 112 bool PreTranslateMessage( MSG* msg ); > 113 }; > 114 > 115 > 116 > 117 //========================================================================= > 118 > 119 #endif // _GREENPAD_MAIN_H_

Added Makefile version [c13aa34ac2a18a0a]

> 1 > 2 message: > 3 -@echo Specify one of the following toolset as the target of make: > 4 -@echo make gcc (for MinGW) > 5 -@echo make dmc (for DigitalMars C++) > 6 -@echo make bcc (for Borland C++ Compilers) > 7 -@echo make vcc (for Microsoft Visual C++) > 8 -@echo Please make sure that the "make" program you're using is > 9 -@echo the one from the toolset. > 10 -@echo (GNU make for gcc, nmake for vcc, ... etc.) > 11 > 12 clean: > 13 -@rmdir /Q /S obj 2> nul > 14 -@del /Q release\*.exe 2> nul > 15 > 16 ############################################################################ > 17 > 18 DMAK = make# Hey, why no $(MAKE)???? > 19 > 20 gcc: > 21 $(MAKE) -f Makefiles/gcc.mak > 22 dmc: > 23 $(DMAK) -f Makefiles/dmc.mak > 24 vcc: > 25 $(MAKE) -f Makefiles/vcc.mak > 26 bcc: > 27 $(MAKE) -f Makefiles/bcc.mak

Added Makefiles/bcc.mak version [54eb14d0be4ff787]

> 1 NAME = bcc > 2 OBJ_SUFFIX = obj > 3 > 4 ############################################################################### > 5 TARGET = release\GreenPad_$(NAME).exe > 6 INTDIR = obj\$(NAME) > 7 > 8 all: PRE $(TARGET) > 9 > 10 OBJS = \ > 11 $(INTDIR)\thread.$(OBJ_SUFFIX) \ > 12 $(INTDIR)\log.$(OBJ_SUFFIX) \ > 13 $(INTDIR)\winutil.$(OBJ_SUFFIX) \ > 14 $(INTDIR)\textfile.$(OBJ_SUFFIX) \ > 15 $(INTDIR)\path.$(OBJ_SUFFIX) \ > 16 $(INTDIR)\cmdarg.$(OBJ_SUFFIX) \ > 17 $(INTDIR)\file.$(OBJ_SUFFIX) \ > 18 $(INTDIR)\find.$(OBJ_SUFFIX) \ > 19 $(INTDIR)\ctrl.$(OBJ_SUFFIX) \ > 20 $(INTDIR)\registry.$(OBJ_SUFFIX) \ > 21 $(INTDIR)\window.$(OBJ_SUFFIX) \ > 22 $(INTDIR)\string.$(OBJ_SUFFIX) \ > 23 $(INTDIR)\memory.$(OBJ_SUFFIX) \ > 24 $(INTDIR)\app.$(OBJ_SUFFIX) \ > 25 $(INTDIR)\ip_cursor.$(OBJ_SUFFIX) \ > 26 $(INTDIR)\ip_scroll.$(OBJ_SUFFIX) \ > 27 $(INTDIR)\ip_wrap.$(OBJ_SUFFIX) \ > 28 $(INTDIR)\ip_draw.$(OBJ_SUFFIX) \ > 29 $(INTDIR)\ip_ctrl1.$(OBJ_SUFFIX) \ > 30 $(INTDIR)\ip_text.$(OBJ_SUFFIX) \ > 31 $(INTDIR)\ip_parse.$(OBJ_SUFFIX) \ > 32 $(INTDIR)\GpMain.$(OBJ_SUFFIX) \ > 33 $(INTDIR)\OpenSaveDlg.$(OBJ_SUFFIX) \ > 34 $(INTDIR)\Search.$(OBJ_SUFFIX) \ > 35 $(INTDIR)\RSearch.$(OBJ_SUFFIX) \ > 36 $(INTDIR)\ConfigManager.$(OBJ_SUFFIX) > 37 > 38 LIBS = \ > 39 kernel32.lib \ > 40 user32.lib \ > 41 gdi32.lib \ > 42 shell32.lib \ > 43 advapi32.lib \ > 44 comdlg32.lib \ > 45 comctl32.lib \ > 46 ole32.lib \ > 47 imm32.lib > 48 > 49 PRE: > 50 -@if not exist release mkdir release > 51 -@if not exist obj mkdir obj > 52 -@if not exist $(INTDIR) mkdir $(INTDIR) > 53 ############################################################################### > 54 > 55 RES = $(INTDIR)\gp_rsrc.res > 56 > 57 .autodepend > 58 .path.cpp = .;kilib;editwing > 59 .path.rc = rsrc > 60 > 61 COPT = -c -W -AT -d -O -O1 -Oc -Oi -Ov -x- -RT- -Ve -VM -w-par -w-inl -w-pia -H= > 62 LOPT = -aa -Tpe -x -Iobj\bcc -w-rty > 63 ROPT = -m -c932 -l0x411 > 64 > 65 $(TARGET): $(OBJS) $(RES) > 66 @ilink32 $(LOPT) c0w32.obj $(OBJS), $@,, cw32.lib import32.lib,, $(RES) > 67 -@del release\GreenPad_bcc.tds > 68 > 69 .rc.res: > 70 @brcc32 $(ROPT) -fo$@ $< > 71 > 72 .cpp.obj: > 73 @bcc32 $(COPT) -o$@ $<

Added Makefiles/dmc.mak version [2c6c5918e3b50bf5]

> 1 NAME = dmc > 2 OBJ_SUFFIX = obj > 3 > 4 ############################################################################### > 5 TARGET = release\GreenPad_$(NAME).exe > 6 INTDIR = obj\$(NAME) > 7 > 8 all: PRE $(TARGET) > 9 > 10 OBJS = \ > 11 $(INTDIR)\thread.$(OBJ_SUFFIX) \ > 12 $(INTDIR)\log.$(OBJ_SUFFIX) \ > 13 $(INTDIR)\winutil.$(OBJ_SUFFIX) \ > 14 $(INTDIR)\textfile.$(OBJ_SUFFIX) \ > 15 $(INTDIR)\path.$(OBJ_SUFFIX) \ > 16 $(INTDIR)\cmdarg.$(OBJ_SUFFIX) \ > 17 $(INTDIR)\file.$(OBJ_SUFFIX) \ > 18 $(INTDIR)\find.$(OBJ_SUFFIX) \ > 19 $(INTDIR)\ctrl.$(OBJ_SUFFIX) \ > 20 $(INTDIR)\registry.$(OBJ_SUFFIX) \ > 21 $(INTDIR)\window.$(OBJ_SUFFIX) \ > 22 $(INTDIR)\string.$(OBJ_SUFFIX) \ > 23 $(INTDIR)\memory.$(OBJ_SUFFIX) \ > 24 $(INTDIR)\app.$(OBJ_SUFFIX) \ > 25 $(INTDIR)\ip_cursor.$(OBJ_SUFFIX) \ > 26 $(INTDIR)\ip_scroll.$(OBJ_SUFFIX) \ > 27 $(INTDIR)\ip_wrap.$(OBJ_SUFFIX) \ > 28 $(INTDIR)\ip_draw.$(OBJ_SUFFIX) \ > 29 $(INTDIR)\ip_ctrl1.$(OBJ_SUFFIX) \ > 30 $(INTDIR)\ip_text.$(OBJ_SUFFIX) \ > 31 $(INTDIR)\ip_parse.$(OBJ_SUFFIX) \ > 32 $(INTDIR)\GpMain.$(OBJ_SUFFIX) \ > 33 $(INTDIR)\OpenSaveDlg.$(OBJ_SUFFIX) \ > 34 $(INTDIR)\Search.$(OBJ_SUFFIX) \ > 35 $(INTDIR)\RSearch.$(OBJ_SUFFIX) \ > 36 $(INTDIR)\ConfigManager.$(OBJ_SUFFIX) > 37 > 38 LIBS = \ > 39 kernel32.lib \ > 40 user32.lib \ > 41 gdi32.lib \ > 42 shell32.lib \ > 43 advapi32.lib \ > 44 comdlg32.lib \ > 45 comctl32.lib \ > 46 ole32.lib \ > 47 imm32.lib > 48 > 49 PRE: > 50 -@if not exist release mkdir release > 51 -@if not exist obj mkdir obj > 52 -@if not exist $(INTDIR) mkdir $(INTDIR) > 53 ############################################################################### > 54 > 55 RC = rsrc\gp_rsrc.rc > 56 RES = $(INTDIR)\gp_rsrc.res > 57 > 58 COPT = -Bj -j0 -Ab -w2 -w7 -o -c > 59 LOPT = -Bj -mn -WA -L/su:Windows:4.0/exet:NT/onerror:noexe > 60 ROPT = -j -32 -l0411 > 61 > 62 $(TARGET) : SETI $(OBJS) $(RES) > 63 dmc $(LOPT) -o$(TARGET) $(RES) $(OBJS) $(LIBS) > 64 -@del GreenPad_dmc.map > 65 brc32 $(RES) $(TARGET) > 66 SETI: > 67 @set INCLUDE=kilib;$(INCLUDE) > 68 > 69 OBJ\dmc\gp_rsrc.res : rsrc\gp_rsrc.rc ; brcc32 -m -c932 -l0x411 -fo$@ $ > 70 OBJ\dmc\thread.obj : kilib\thread.cpp ; dmc $(COPT) -o$@ $** > 71 OBJ\dmc\log.obj : kilib\log.cpp ; dmc $(COPT) -o$@ $** > 72 OBJ\dmc\winutil.obj : kilib\winutil.cpp ; dmc $(COPT) -o$@ $** > 73 OBJ\dmc\textfile.obj : kilib\textfile.cpp ; dmc $(COPT) -o$@ $** > 74 OBJ\dmc\path.obj : kilib\path.cpp ; dmc $(COPT) -o$@ $** > 75 OBJ\dmc\cmdarg.obj : kilib\cmdarg.cpp ; dmc $(COPT) -o$@ $** > 76 OBJ\dmc\file.obj : kilib\file.cpp ; dmc $(COPT) -o$@ $** > 77 OBJ\dmc\find.obj : kilib\find.cpp ; dmc $(COPT) -o$@ $** > 78 OBJ\dmc\ctrl.obj : kilib\ctrl.cpp ; dmc $(COPT) -o$@ $** > 79 OBJ\dmc\registry.obj : kilib\registry.cpp ; dmc $(COPT) -o$@ $** > 80 OBJ\dmc\window.obj : kilib\window.cpp ; dmc $(COPT) -o$@ $** > 81 OBJ\dmc\string.obj : kilib\string.cpp ; dmc $(COPT) -o$@ $** > 82 OBJ\dmc\memory.obj : kilib\memory.cpp ; dmc $(COPT) -o$@ $** > 83 OBJ\dmc\app.obj : kilib\app.cpp ; dmc $(COPT) -o$@ $** > 84 OBJ\dmc\ip_cursor.obj : editwing\ip_cursor.cpp ; dmc $(COPT) -o$@ $** > 85 OBJ\dmc\ip_scroll.obj : editwing\ip_scroll.cpp ; dmc $(COPT) -o$@ $** > 86 OBJ\dmc\ip_wrap.obj : editwing\ip_wrap.cpp ; dmc $(COPT) -o$@ $** > 87 OBJ\dmc\ip_draw.obj : editwing\ip_draw.cpp ; dmc $(COPT) -o$@ $** > 88 OBJ\dmc\ip_ctrl1.obj : editwing\ip_ctrl1.cpp ; dmc $(COPT) -o$@ $** > 89 OBJ\dmc\ip_text.obj : editwing\ip_text.cpp ; dmc $(COPT) -o$@ $** > 90 OBJ\dmc\ip_parse.obj : editwing\ip_parse.cpp ; dmc $(COPT) -o$@ $** > 91 OBJ\dmc\GpMain.obj : GpMain.cpp ; dmc $(COPT) -o$@ $** > 92 OBJ\dmc\OpenSaveDlg.obj : OpenSaveDlg.cpp ; dmc $(COPT) -o$@ $** > 93 OBJ\dmc\Search.obj : Search.cpp ; dmc $(COPT) -o$@ $** > 94 OBJ\dmc\RSearch.obj : RSearch.cpp ; dmc $(COPT) -o$@ $** > 95 OBJ\dmc\ConfigManager.obj : ConfigManager.cpp ; dmc $(COPT) -o$@ $**

Added Makefiles/gcc.mak version [3e8f853ea6204f83]

> 1 > 2 NAME = gcc > 3 OBJ_SUFFIX = o > 4 > 5 ############################################################################### > 6 TARGET = release/GreenPad_$(NAME).exe > 7 INTDIR = obj\$(NAME) > 8 > 9 all: PRE $(TARGET) > 10 > 11 OBJS = \ > 12 $(INTDIR)/thread.$(OBJ_SUFFIX) \ > 13 $(INTDIR)/log.$(OBJ_SUFFIX) \ > 14 $(INTDIR)/winutil.$(OBJ_SUFFIX) \ > 15 $(INTDIR)/textfile.$(OBJ_SUFFIX) \ > 16 $(INTDIR)/path.$(OBJ_SUFFIX) \ > 17 $(INTDIR)/cmdarg.$(OBJ_SUFFIX) \ > 18 $(INTDIR)/file.$(OBJ_SUFFIX) \ > 19 $(INTDIR)/find.$(OBJ_SUFFIX) \ > 20 $(INTDIR)/ctrl.$(OBJ_SUFFIX) \ > 21 $(INTDIR)/registry.$(OBJ_SUFFIX) \ > 22 $(INTDIR)/window.$(OBJ_SUFFIX) \ > 23 $(INTDIR)/string.$(OBJ_SUFFIX) \ > 24 $(INTDIR)/memory.$(OBJ_SUFFIX) \ > 25 $(INTDIR)/app.$(OBJ_SUFFIX) \ > 26 $(INTDIR)/ip_cursor.$(OBJ_SUFFIX) \ > 27 $(INTDIR)/ip_scroll.$(OBJ_SUFFIX) \ > 28 $(INTDIR)/ip_wrap.$(OBJ_SUFFIX) \ > 29 $(INTDIR)/ip_draw.$(OBJ_SUFFIX) \ > 30 $(INTDIR)/ip_ctrl1.$(OBJ_SUFFIX) \ > 31 $(INTDIR)/ip_text.$(OBJ_SUFFIX) \ > 32 $(INTDIR)/ip_parse.$(OBJ_SUFFIX) \ > 33 $(INTDIR)/GpMain.$(OBJ_SUFFIX) \ > 34 $(INTDIR)/OpenSaveDlg.$(OBJ_SUFFIX) \ > 35 $(INTDIR)/Search.$(OBJ_SUFFIX) \ > 36 $(INTDIR)/RSearch.$(OBJ_SUFFIX) \ > 37 $(INTDIR)/ConfigManager.$(OBJ_SUFFIX) > 38 > 39 LIBS = \ > 40 -lkernel32 \ > 41 -luser32 \ > 42 -lgdi32 \ > 43 -lshell32 \ > 44 -ladvapi32 \ > 45 -lcomdlg32 \ > 46 -lcomctl32 \ > 47 -lole32 \ > 48 -limm32 > 49 > 50 PRE: > 51 -@if not exist release mkdir release > 52 -@if not exist obj mkdir obj > 53 -@if not exist $(INTDIR) mkdir $(INTDIR) > 54 ############################################################################### > 55 > 56 RES = $(INTDIR)/gp_rsrc.o > 57 > 58 VPATH = editwing:kilib > 59 CXXFLAGS = -mno-cygwin -O2 -idirafter kilib -c --input-charset=cp932 > 60 LOPT = -mwindows -mno-cygwin > 61 > 62 $(TARGET) : $(OBJS) $(RES) > 63 g++ $(LOPT) -o$(TARGET) $(OBJS) $(RES) $(LIBS) > 64 strip -s $(TARGET) > 65 $(INTDIR)/%.o: rsrc/%.rc > 66 windres -l=0x411 -I rsrc $< $@ > 67 $(INTDIR)/%.o: %.cpp > 68 g++ $(CXXFLAGS) -o$@ $<

Added Makefiles/vcc.mak version [50fae54bd44a5597]

> 1 NAME = vcc > 2 OBJ_SUFFIX = obj > 3 > 4 ############################################################################### > 5 TARGET = release\GreenPad_$(NAME).exe > 6 INTDIR = obj\$(NAME) > 7 > 8 all: PRE $(TARGET) > 9 > 10 OBJS = \ > 11 $(INTDIR)\thread.$(OBJ_SUFFIX) \ > 12 $(INTDIR)\log.$(OBJ_SUFFIX) \ > 13 $(INTDIR)\winutil.$(OBJ_SUFFIX) \ > 14 $(INTDIR)\textfile.$(OBJ_SUFFIX) \ > 15 $(INTDIR)\path.$(OBJ_SUFFIX) \ > 16 $(INTDIR)\cmdarg.$(OBJ_SUFFIX) \ > 17 $(INTDIR)\file.$(OBJ_SUFFIX) \ > 18 $(INTDIR)\find.$(OBJ_SUFFIX) \ > 19 $(INTDIR)\ctrl.$(OBJ_SUFFIX) \ > 20 $(INTDIR)\registry.$(OBJ_SUFFIX) \ > 21 $(INTDIR)\window.$(OBJ_SUFFIX) \ > 22 $(INTDIR)\string.$(OBJ_SUFFIX) \ > 23 $(INTDIR)\memory.$(OBJ_SUFFIX) \ > 24 $(INTDIR)\app.$(OBJ_SUFFIX) \ > 25 $(INTDIR)\ip_cursor.$(OBJ_SUFFIX) \ > 26 $(INTDIR)\ip_scroll.$(OBJ_SUFFIX) \ > 27 $(INTDIR)\ip_wrap.$(OBJ_SUFFIX) \ > 28 $(INTDIR)\ip_draw.$(OBJ_SUFFIX) \ > 29 $(INTDIR)\ip_ctrl1.$(OBJ_SUFFIX) \ > 30 $(INTDIR)\ip_text.$(OBJ_SUFFIX) \ > 31 $(INTDIR)\ip_parse.$(OBJ_SUFFIX) \ > 32 $(INTDIR)\GpMain.$(OBJ_SUFFIX) \ > 33 $(INTDIR)\OpenSaveDlg.$(OBJ_SUFFIX) \ > 34 $(INTDIR)\Search.$(OBJ_SUFFIX) \ > 35 $(INTDIR)\RSearch.$(OBJ_SUFFIX) \ > 36 $(INTDIR)\ConfigManager.$(OBJ_SUFFIX) > 37 > 38 LIBS = \ > 39 kernel32.lib \ > 40 user32.lib \ > 41 gdi32.lib \ > 42 shell32.lib \ > 43 advapi32.lib \ > 44 comdlg32.lib \ > 45 comctl32.lib \ > 46 ole32.lib \ > 47 imm32.lib > 48 > 49 PRE: > 50 -@if not exist release mkdir release > 51 -@if not exist obj mkdir obj > 52 -@if not exist $(INTDIR) mkdir $(INTDIR) > 53 ############################################################################### > 54 > 55 RES = $(INTDIR)\gp_rsrc.res > 56 PCH = $(INTDIR)\gp.pch > 57 DEF = /D NDEBUG /D UNICODE /D _UNICODE /D USEGLOBALIME > 58 > 59 COPT = /nologo $(DEF) /O1isyb1 /GA /GF /FD /Zc:wchar_t /Yu"stdafx.h" /Fp$(PCH) / > 60 LOPT = /nologo /manifest:no bufferoverflowU.lib > 61 ROPT = $(DEF) /L 0x411 /I "rsrc" > 62 > 63 $(TARGET): PRE $(PCH) $(OBJS) $(RES) > 64 link $(LOPT) /OUT:$(TARGET) $(OBJS) $(RES) $(LIBS) > 65 > 66 {rsrc}.rc{$(INTDIR)}.res: > 67 rc $(ROPT) /Fo$@ $** > 68 > 69 {.}.cpp{$(INTDIR)}.obj: > 70 cl $(COPT) /Fo$@ $** > 71 {kilib}.cpp{$(INTDIR)}.obj: > 72 cl $(COPT) /Fo$@ $** > 73 {editwing}.cpp{$(INTDIR)}.obj: > 74 cl $(COPT) /Fo$@ $** > 75 $(PCH): kilib\stdafx.cpp > 76 cl $(COPT) /Fo$(INTDIR)\stdafx.obj /Yc"stdafx.h" $**

Added NSearch.h version [b90c4013c91b1e31]

> 1 #ifndef AFX_NSEARCH_H__8336E133_90C5_4059_8605_6066BD37D042__INCLUDED_ > 2 #define AFX_NSEARCH_H__8336E133_90C5_4059_8605_6066BD37D042__INCLUDED_ > 3 #include "Search.h" > 4 > 5 > 6 > 7 //========================================================================= > 8 //@{ @pkg Gp.Search //@} > 9 // BM法検索用ポリシーs > 10 //========================================================================= > 11 > 12 //@{ 大文字小文字を区別するポリシー //@} > 13 struct CaseSensitive > 14 { > 15 static unicode map( unicode c ) > 16 { return c; } > 17 static bool not_equal( unicode c1, unicode c2 ) > 18 { return c1!=c2; } > 19 }; > 20 > 21 //@{ 大文字小文字を区別しないポリシー //@} > 22 struct IgnoreCase > 23 { > 24 static unicode map( unicode c ) > 25 { return (L'a'<=c && c<=L'z' ? c-L'a'+L'A' : c); } > 26 static bool not_equal( unicode c1, unicode c2 ) > 27 { return map(c1)!=map(c2); } > 28 }; > 29 > 30 > 31 > 32 //========================================================================= > 33 //@{ > 34 // BM法による普通の正方向検索 > 35 //@} > 36 //========================================================================= > 37 > 38 template<class ComparisonPolicy> class BMSearch > 39 { > 40 public: > 41 BMSearch( const unicode* key ) > 42 : keylen_( my_lstrlenW(key) ) > 43 , key_( my_lstrcpyW( new unicode[keylen_+1], key ) ) > 44 { > 45 memFF( lastAppearance_, sizeof(lastAppearance_) ); > 46 for( int i=0, e=keylen_; i<e; ++i ) > 47 lastAppearance_[ ComparisonPolicy::map(key[i]) ] = i; > 48 } > 49 > 50 ~BMSearch() > 51 { > 52 delete [] key_; > 53 } > 54 > 55 int Search( const unicode* str, int strlen ) > 56 { > 57 for( int i=0, e=strlen-keylen_, j, t; i<=e; i+=(j>t?j-t:1) ) > 58 { > 59 for( j=keylen_-1; j>=0; --j ) > 60 { > 61 if( ComparisonPolicy::not_equal( key_[j], str[i+ > 62 break; > 63 } > 64 if( j < 0 ) > 65 return i; > 66 t = lastAppearance_[ ComparisonPolicy::map(str[i+j]) ]; > 67 } > 68 return -1; > 69 } > 70 > 71 int keylen() const { return keylen_; } > 72 > 73 private: > 74 int keylen_; > 75 unicode* key_; > 76 int lastAppearance_[65536]; > 77 }; > 78 > 79 > 80 > 81 //========================================================================= > 82 //@{ > 83 // BM法による逆方向検索 > 84 //@} > 85 //========================================================================= > 86 > 87 template<class ComparisonPolicy> class BMSearchRev > 88 { > 89 public: > 90 BMSearchRev( const unicode* key ) > 91 : keylen_( my_lstrlenW(key) ) > 92 , key_( my_lstrcpyW( new unicode[keylen_+1], key ) ) > 93 { > 94 memFF( firstAppearance_, sizeof(firstAppearance_) ); > 95 for( int i=keylen_-1; i>=0; --i ) > 96 firstAppearance_[ ComparisonPolicy::map(key[i]) ] = i; > 97 } > 98 > 99 ~BMSearchRev() > 100 { > 101 delete [] key_; > 102 } > 103 > 104 int Search( const unicode* str, int strlen ) > 105 { > 106 for( int i=strlen-keylen_-1, j, e, t; i>=0; i-=(t>j?t-j:1) ) > 107 { > 108 for( j=0, e=keylen_; j<e; ++j ) > 109 if( ComparisonPolicy::not_equal( key_[j], str[i+ > 110 break; > 111 if( j >= e ) > 112 return i; > 113 t = firstAppearance_[ ComparisonPolicy::map(str[i+j]) ]; > 114 if( t == -1 ) t = keylen_; > 115 } > 116 return -1; > 117 } > 118 > 119 int keylen() const { return keylen_; } > 120 > 121 private: > 122 int keylen_; > 123 unicode* key_; > 124 int firstAppearance_[65536]; > 125 }; > 126 > 127 > 128 > 129 //========================================================================= > 130 //@{ > 131 // Searhcableとしての実装(正方向検索) > 132 //@} > 133 //========================================================================= > 134 > 135 template<class CompalisonPolicy> > 136 class NSearch : public Searchable > 137 { > 138 public: > 139 NSearch( const unicode* key ) : s_(key) {} > 140 > 141 private: > 142 bool Search( > 143 const unicode* str, ulong len, ulong stt, ulong* mbg, ulong* med > 144 { > 145 int n = s_.Search( str+stt, len-stt ); > 146 if( n < 0 ) > 147 return false; > 148 *mbg = stt + n; > 149 *med = stt + n + s_.keylen(); > 150 return true; > 151 } > 152 > 153 private: > 154 BMSearch<CompalisonPolicy> s_; > 155 }; > 156 > 157 > 158 > 159 //========================================================================= > 160 //@{ > 161 // Searhcableとしての実装(逆方向検索) > 162 //@} > 163 //========================================================================= > 164 > 165 template<class CompalisonPolicy> > 166 class NSearchRev : public Searchable > 167 { > 168 public: > 169 NSearchRev( const unicode* key ) : s_(key) {} > 170 > 171 private: > 172 bool Search( > 173 const unicode* str, ulong len, ulong stt, ulong* mbg, ulong* med > 174 { > 175 int n = s_.Search( str, stt+s_.keylen() ); > 176 if( n < 0 ) > 177 return false; > 178 *mbg = n; > 179 *med = n + s_.keylen(); > 180 return true; > 181 } > 182 > 183 private: > 184 BMSearchRev<CompalisonPolicy> s_; > 185 }; > 186 > 187 > 188 > 189 //========================================================================= > 190 > 191 #endif

Added OpenSaveDlg.cpp version [d48f24b36f48652a]

> 1 #include "stdafx.h" > 2 #include "rsrc/resource.h" > 3 #include "kilib/kilib.h" > 4 #include "OpenSaveDlg.h" > 5 using namespace ki; > 6 > 7 > 8 > 9 //------------------------------------------------------------------------ > 10 // 文字コードリスト > 11 //------------------------------------------------------------------------ > 12 > 13 CharSetList::CharSetList() > 14 : list_( 30 ) > 15 { > 16 static const TCHAR* const lnmJp[] = { > 17 TEXT("自動判定"), > 18 TEXT("日本語(ShiftJIS)"), > 19 TEXT("日本語(EUC)"), > 20 TEXT("日本語(ISO-2022-JP)"), > 21 TEXT("UTF-5"), > 22 TEXT("UTF-7"), > 23 TEXT("UTF-8"), > 24 TEXT("UTF-8N"), > 25 TEXT("UTF-16BE(BOM)"), > 26 TEXT("UTF-16LE(BOM)"), > 27 TEXT("UTF-16BE"), > 28 TEXT("UTF-16LE"), > 29 TEXT("UTF-32BE(BOM)"), > 30 TEXT("UTF-32LE(BOM)"), > 31 TEXT("UTF-32BE"), > 32 TEXT("UTF-32LE"), > 33 TEXT("欧米"), > 34 TEXT("中欧"), > 35 TEXT("韓国語(EUC-KR)"), > 36 TEXT("韓国語(ISO-2022-KR)"), > 37 TEXT("韓国語(Johab)"), > 38 TEXT("中国語(GB2312)"), > 39 TEXT("中国語(ISO-2022-CN)"), > 40 TEXT("中国語(HZ)"), > 41 TEXT("中国語(Big5)"), > 42 TEXT("キリル語(Windows)"), > 43 TEXT("キリル語(KOI8-R)"), > 44 TEXT("キリル語(KOI8-U)"), > 45 TEXT("タイ語"), > 46 TEXT("トルコ語"), > 47 TEXT("バルト語"), > 48 TEXT("ベトナム語"), > 49 TEXT("ギリシャ語"), > 50 TEXT("MSDOS(us)") > 51 }; > 52 static const TCHAR* const lnmEn[] = { > 53 TEXT("AutoDetect"), > 54 TEXT("Japanese(ShiftJIS)"), > 55 TEXT("Japanese(EUC)"), > 56 TEXT("Japanese(ISO-2022-JP)"), > 57 TEXT("UTF-5"), > 58 TEXT("UTF-7"), > 59 TEXT("UTF-8"), > 60 TEXT("UTF-8N"), > 61 TEXT("UTF-16BE(BOM)"), > 62 TEXT("UTF-16LE(BOM)"), > 63 TEXT("UTF-16BE"), > 64 TEXT("UTF-16LE"), > 65 TEXT("UTF-32BE(BOM)"), > 66 TEXT("UTF-32LE(BOM)"), > 67 TEXT("UTF-32BE"), > 68 TEXT("UTF-32LE"), > 69 TEXT("Latin-1"), > 70 TEXT("Latin-2"), > 71 TEXT("Korean(EUC-KR)"), > 72 TEXT("Korean(ISO-2022-KR)"), > 73 TEXT("Korean(Johab)"), > 74 TEXT("Chinese(GB2312)"), > 75 TEXT("Chinese(ISO-2022-CN)"), > 76 TEXT("Chinese(HZ)"), > 77 TEXT("Chinese(Big5)"), > 78 TEXT("Cyrillic(Windows)"), > 79 TEXT("Cyrillic(KOI8-R)"), > 80 TEXT("Cyrillic(KOI8-U)"), > 81 TEXT("Thai"), > 82 TEXT("Turkish"), > 83 TEXT("Baltic"), > 84 TEXT("Vietnamese"), > 85 TEXT("Greek"), > 86 TEXT("MSDOS(us)") > 87 }; > 88 static const TCHAR* const snm[] = { > 89 TEXT(""), > 90 TEXT("SJIS"), > 91 TEXT("EUC"), > 92 TEXT("JIS"), > 93 TEXT("UTF5"), > 94 TEXT("UTF7"), > 95 TEXT("UTF8"), > 96 TEXT("UTF8"), > 97 TEXT("U16B"), > 98 TEXT("U16L"), > 99 TEXT("U16B"), > 100 TEXT("U16L"), > 101 TEXT("U32B"), > 102 TEXT("U32L"), > 103 TEXT("U32B"), > 104 TEXT("U32L"), > 105 TEXT("LTN1"), > 106 TEXT("LTN2"), > 107 TEXT("UHC"), > 108 TEXT("I2KR"), > 109 TEXT("Jhb"), > 110 TEXT("GBK"), > 111 TEXT("I2CN"), > 112 TEXT("HZ"), > 113 TEXT("BIG5"), > 114 TEXT("CYRL"), > 115 TEXT("KO8R"), > 116 TEXT("KO8U"), > 117 TEXT("THAI"), > 118 TEXT("TRK"), > 119 TEXT("BALT"), > 120 TEXT("VTNM"), > 121 TEXT("GRK"), > 122 TEXT("DOS") > 123 }; > 124 > 125 // 日本語環境なら日本語表示を選ぶ > 126 const TCHAR* const * lnm = (::GetACP()==932 ? lnmJp : lnmEn); > 127 > 128 // いちいち書くの面倒なので短縮表記(^^; > 129 CsInfo cs; > 130 #define Enroll(_id,_nm) cs.ID=_id, \ > 131 cs.longName=lnm[_nm], cs.shortName=snm[_nm], \ > 132 cs.type=LOAD|SAVE, list_.Add( cs ) > 133 #define EnrollS(_id,_nm) cs.ID=_id, \ > 134 cs.longName=lnm[_nm], cs.shortName=snm[_nm], \ > 135 cs.type=SAVE, list_.Add( cs ) > 136 #define EnrollL(_id,_nm) cs.ID=_id, \ > 137 cs.longName=lnm[_nm], cs.shortName=snm[_nm], \ > 138 cs.type=LOAD, list_.Add( cs ) > 139 > 140 // 適宜登録 > 141 EnrollL( AutoDetect,0 ); > 142 if( ::IsValidCodePage(932) ) Enroll( SJIS, 1 ), > 143 Enroll( EucJP, 2 ), > 144 Enroll( IsoJP, 3 ); > 145 /* if( always ) */ Enroll( UTF5, 4 ); > 146 Enroll( UTF7, 5 ); > 147 Enroll( UTF8, 6 ); > 148 EnrollS( UTF8N, 7 ); > 149 EnrollS( UTF16b, 8 ); > 150 EnrollS( UTF16l, 9 ); > 151 Enroll( UTF16BE, 10 ); > 152 Enroll( UTF16LE, 11 ); > 153 EnrollS( UTF32b, 12 ); > 154 EnrollS( UTF32l, 13 ); > 155 Enroll( UTF32BE, 14 ); > 156 Enroll( UTF32LE, 15 ); > 157 Enroll( Western, 16 ); > 158 if( ::IsValidCodePage(28592) ) Enroll( Central, 17 ); > 159 if( ::IsValidCodePage(949) ) Enroll( UHC, 18 ), > 160 Enroll( IsoKR, 19 ); > 161 if( ::IsValidCodePage(1361) ) Enroll( Johab, 20 ); > 162 if( ::IsValidCodePage(936) ) Enroll( GBK, 21 ), > 163 Enroll( IsoCN, 22 ), > 164 Enroll( HZ , 23 ); > 165 if( ::IsValidCodePage(950) ) Enroll( Big5 , 24 ); > 166 if( ::IsValidCodePage(28595) ) Enroll( Cyrillic, 25 ); > 167 if( ::IsValidCodePage(20866) ) Enroll( Koi8R, 26 ); > 168 if( ::IsValidCodePage(21866) ) Enroll( Koi8U, 27 ); > 169 if( ::IsValidCodePage(874) ) Enroll( Thai, 28 ); > 170 if( ::IsValidCodePage(1254) ) Enroll( Turkish, 29 ); > 171 if( ::IsValidCodePage(1257) ) Enroll( Baltic, 30 ); > 172 if( ::IsValidCodePage(1258) ) Enroll( Vietnamese,31 ); > 173 if( ::IsValidCodePage(28597) ) Enroll( Greek, 32 ); > 174 Enroll( DOSUS, 33 ); > 175 > 176 // 終了 > 177 #undef Enroll > 178 #undef EnrollS > 179 #undef EnrollL > 180 } > 181 > 182 int CharSetList::defaultCs() const > 183 { > 184 return ::GetACP(); > 185 /* > 186 switch( ::GetACP() ) > 187 { > 188 case 932: return SJIS; > 189 case 936: return GBK; > 190 case 949: return UHC; > 191 case 950: return Big5; > 192 default: return Western; > 193 } > 194 */ > 195 } > 196 > 197 ulong CharSetList::defaultCsi() const > 198 { > 199 return findCsi( defaultCs() ); > 200 } > 201 > 202 ulong CharSetList::findCsi( int cs ) const > 203 { > 204 for( ulong i=0,ie=list_.size(); i<ie; ++i ) > 205 if( list_[i].ID == cs ) > 206 return i; > 207 return 0xffffffff; > 208 } > 209 > 210 > 211 > 212 //------------------------------------------------------------------------ > 213 // 「開く」ダイアログ > 214 //------------------------------------------------------------------------ > 215 > 216 namespace > 217 { > 218 // 関数終了時に、カレントディレクトリを元に戻す > 219 class CurrentDirRecovery > 220 { > 221 Path cur_; > 222 public: > 223 CurrentDirRecovery() : cur_(Path::Cur) {} > 224 ~CurrentDirRecovery() { ::SetCurrentDirectory(cur_.c_str()); } > 225 }; > 226 } > 227 > 228 OpenFileDlg* OpenFileDlg::pThis; > 229 > 230 bool OpenFileDlg::DoModal( HWND wnd, const TCHAR* fltr, const TCHAR* fnm ) > 231 { > 232 CurrentDirRecovery cdr; > 233 > 234 if( fnm == NULL ) > 235 filename_[0] = TEXT('\0'); > 236 else > 237 ::lstrcpy( filename_, fnm ); > 238 > 239 OPENFILENAME ofn = {sizeof(ofn)}; > 240 ofn.hwndOwner = wnd; > 241 ofn.hInstance = app().hinst(); > 242 ofn.lpstrFilter = fltr; > 243 ofn.lpstrFile = filename_; > 244 ofn.nMaxFile = countof(filename_); > 245 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_OPENFILEHOOK); > 246 ofn.lpfnHook = OfnHook; > 247 ofn.Flags = OFN_FILEMUSTEXIST | > 248 OFN_HIDEREADONLY | > 249 OFN_EXPLORER | > 250 OFN_ENABLESIZING | > 251 OFN_ENABLEHOOK | > 252 OFN_ENABLETEMPLATE; > 253 > 254 pThis = this; > 255 return ( ::GetOpenFileName(&ofn) != 0 ); > 256 } > 257 > 258 UINT_PTR CALLBACK OpenFileDlg::OfnHook( HWND dlg, UINT msg, WPARAM, LPARAM lp ) > 259 { > 260 if( msg==WM_INITDIALOG ) > 261 { > 262 // コンボボックスを埋めて、「自動選択」を選ぶ > 263 ComboBox cb( dlg, IDC_CODELIST ); > 264 const CharSetList& csl = pThis->csl_; > 265 for( ulong i=0; i<csl.size(); ++i ) > 266 if( csl[i].type & 2 ) // 2:=LOAD > 267 cb.Add( csl[i].longName ); > 268 cb.Select( csl[0].longName ); > 269 } > 270 else if( msg==WM_NOTIFY ) > 271 { > 272 // OKが押されたら、文字コードの選択状況を記録 > 273 if( reinterpret_cast<NMHDR*>(lp)->code==CDN_FILEOK ) > 274 { > 275 ulong j=0, i=ComboBox(dlg,IDC_CODELIST).GetCurSel(); > 276 for(;;++j,--i) > 277 { > 278 while( !(pThis->csl_[j].type & 2) ) // !LOAD > 279 ++j; > 280 if( i==0 ) > 281 break; > 282 } > 283 pThis->csIndex_ = j; > 284 } > 285 } > 286 return FALSE; > 287 } > 288 > 289 > 290 > 291 //------------------------------------------------------------------------ > 292 // 「保存」ダイアログ > 293 //------------------------------------------------------------------------ > 294 > 295 SaveFileDlg* SaveFileDlg::pThis; > 296 > 297 bool SaveFileDlg::DoModal( HWND wnd, const TCHAR* fltr, const TCHAR* fnm ) > 298 { > 299 CurrentDirRecovery cdr; > 300 > 301 if( fnm == NULL ) > 302 filename_[0] = TEXT('\0'); > 303 else > 304 ::lstrcpy( filename_, fnm ); > 305 > 306 OPENFILENAME ofn = {sizeof(ofn)}; > 307 ofn.hwndOwner = wnd; > 308 ofn.hInstance = app().hinst(); > 309 ofn.lpstrFilter = fltr; > 310 ofn.lpstrFile = filename_; > 311 ofn.nMaxFile = countof(filename_); > 312 ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEFILEHOOK); > 313 ofn.lpfnHook = OfnHook; > 314 ofn.Flags = OFN_HIDEREADONLY | > 315 OFN_PATHMUSTEXIST | > 316 OFN_EXPLORER | > 317 OFN_ENABLESIZING | > 318 OFN_ENABLEHOOK | > 319 OFN_ENABLETEMPLATE | > 320 OFN_OVERWRITEPROMPT; > 321 > 322 pThis = this; > 323 return ( ::GetSaveFileName(&ofn) != 0 ); > 324 } > 325 > 326 UINT_PTR CALLBACK SaveFileDlg::OfnHook( HWND dlg, UINT msg, WPARAM, LPARAM lp ) > 327 { > 328 if( msg==WM_INITDIALOG ) > 329 { > 330 // コンボボックスを埋めて、適切なのを選ぶ > 331 { > 332 ComboBox cb( dlg, IDC_CODELIST ); > 333 const CharSetList& csl = pThis->csl_; > 334 > 335 for( ulong i=0; i<csl.size(); ++i ) > 336 if( csl[i].type & 1 ) // 1:=SAVE > 337 cb.Add( csl[i].longName ); > 338 cb.Select( csl[pThis->csIndex_].longName ); > 339 } > 340 { > 341 ComboBox cb( dlg, IDC_CRLFLIST ); > 342 static const TCHAR* const lbList[] = { > 343 TEXT("CR"), > 344 TEXT("LF"), > 345 TEXT("CRLF") > 346 }; > 347 > 348 for( ulong i=0; i<countof(lbList); ++i ) > 349 cb.Add( lbList[i] ); > 350 cb.Select( lbList[pThis->lb_] ); > 351 } > 352 } > 353 else if( msg==WM_NOTIFY ) > 354 { > 355 if( reinterpret_cast<NMHDR*>(lp)->code==CDN_FILEOK ) > 356 { > 357 // OKが押されたら、文字コードの選択状況を記録 > 358 ulong j=0, i=ComboBox(dlg,IDC_CODELIST).GetCurSel(); > 359 for(;;++j,--i) > 360 { > 361 while( !(pThis->csl_[j].type & 1) ) // !SAVE > 362 ++j; > 363 if( i==0 ) > 364 break; > 365 } > 366 pThis->csIndex_ = j; > 367 // 改行コードも > 368 pThis->lb_ = ComboBox(dlg,IDC_CRLFLIST).GetCurSel(); > 369 } > 370 } > 371 return FALSE; > 372 } > 373 > 374 > 375 > 376 //------------------------------------------------------------------------ > 377 // ユーティリティー > 378 //------------------------------------------------------------------------ > 379 > 380 ki::aarr<TCHAR> OpenFileDlg::ConnectWithNull( String lst[], int num ) > 381 { > 382 int TtlLen = 1; > 383 for( int i=0; i<num; ++i ) > 384 TtlLen += (lst[i].len() + 1); > 385 > 386 aarr<TCHAR> a( new TCHAR[TtlLen] ); > 387 > 388 TCHAR* p = a.get(); > 389 for( int i=0; i<num; ++i ) > 390 { > 391 ::lstrcpy( p, lst[i].c_str() ); > 392 p += (lst[i].len() + 1); > 393 } > 394 *p = TEXT('\0'); > 395 > 396 return a; > 397 } > 398 > 399 > 400 > 401 > 402 //------------------------------------------------------------------------ > 403 // 「開き直す」ダイアログ > 404 //------------------------------------------------------------------------ > 405 > 406 ReopenDlg::ReopenDlg( const CharSetList& csl, int csi ) > 407 : DlgImpl(IDD_REOPENDLG), csl_(csl), csIndex_(csi) > 408 { > 409 } > 410 > 411 void ReopenDlg::on_init() > 412 { > 413 // コンボボックスを埋めて、「自動選択」を選ぶ > 414 ComboBox cb( hwnd(), IDC_CODELIST ); > 415 for( ulong i=0; i<csl_.size(); ++i ) > 416 if( csl_[i].type & 1 ) // 2:=SAVE > 417 cb.Add( csl_[i].longName ); > 418 cb.Select( csl_[csIndex_].longName ); > 419 } > 420 > 421 bool ReopenDlg::on_ok() > 422 { > 423 // OKが押されたら、文字コードの選択状況を記録 > 424 ulong j=0, i=ComboBox(hwnd(),IDC_CODELIST).GetCurSel(); > 425 for(;;++j,--i) > 426 { > 427 while( !(csl_[j].type & 1) ) // !SAVE > 428 ++j; > 429 if( i==0 ) > 430 break; > 431 } > 432 csIndex_ = j; > 433 return true; > 434 }

Added OpenSaveDlg.h version [fa92942f039f4d4b]

> 1 #ifndef _GREENPAD_OPENSAVEDLG_H_ > 2 #define _GREENPAD_OPENSAVEDLG_H_ > 3 #include "kilib/ktlarray.h" > 4 #include "kilib/ktlaptr.h" > 5 #include "kilib/string.h" > 6 #include "rsrc/resource.h" > 7 > 8 > 9 > 10 //======================================================================== > 11 //@{ @pkg Gp.Dlg //@} > 12 //@{ > 13 // 利用可能文字コードリスト > 14 //@} > 15 //======================================================================== > 16 > 17 class CharSetList > 18 { > 19 public: > 20 > 21 struct CsInfo > 22 { > 23 int ID; > 24 const TCHAR* longName; > 25 const TCHAR* shortName; > 26 int type; > 27 }; > 28 > 29 public: > 30 > 31 CharSetList(); > 32 const CsInfo& operator[](size_t i) const { return list_[i]; } > 33 ulong size() const { return list_.size(); } > 34 int defaultCs() const; > 35 ulong defaultCsi() const; > 36 ulong findCsi( int cs ) const; > 37 > 38 private: > 39 > 40 enum { SAVE=1, LOAD=2, BOTH=3 }; > 41 ki::storage<CsInfo> list_; > 42 }; > 43 > 44 > 45 > 46 //======================================================================== > 47 //@{ > 48 // 「ファイルを開く」ダイアログ > 49 // > 50 // Windows共通のダイアログの下に、文字コードの選択欄を > 51 // 付け加えたものを表示する。 > 52 //@} > 53 //======================================================================== > 54 > 55 class OpenFileDlg > 56 { > 57 public: > 58 explicit OpenFileDlg( const CharSetList& csl ); > 59 bool DoModal( HWND wnd, const TCHAR* filter, const TCHAR* fnm ); > 60 > 61 public: > 62 const TCHAR* filename() const; > 63 int csi() const; > 64 > 65 public: > 66 static ki::aarr<TCHAR> ConnectWithNull( ki::String lst[], int num ); > 67 > 68 private: > 69 const CharSetList& csl_; > 70 TCHAR filename_[MAX_PATH]; > 71 int csIndex_; > 72 > 73 private: > 74 static OpenFileDlg* pThis; // マルチスレッド禁止! > 75 static UINT_PTR CALLBACK OfnHook( HWND, UINT, WPARAM, LPARAM ); > 76 }; > 77 > 78 > 79 > 80 //------------------------------------------------------------------------ > 81 #ifndef __ccdoc__ > 82 > 83 inline OpenFileDlg::OpenFileDlg( const CharSetList& csl ) > 84 : csl_(csl) {} > 85 > 86 inline const TCHAR* OpenFileDlg::filename() const > 87 { return filename_; } > 88 > 89 inline int OpenFileDlg::csi() const > 90 { return csIndex_; } > 91 > 92 > 93 > 94 #endif // __ccdoc__ > 95 //======================================================================== > 96 //@{ > 97 // 「ファイルを保存」ダイアログ > 98 // > 99 // Windows共通のダイアログの下に、文字コードの選択欄と > 100 // 改行コードの選択欄を付け加えたものを表示する。 > 101 //@} > 102 //======================================================================== > 103 > 104 class SaveFileDlg > 105 { > 106 public: > 107 explicit SaveFileDlg( const CharSetList& csl, int cs, int lb ); > 108 bool DoModal( HWND wnd, const TCHAR* filter, const TCHAR* fnm ); > 109 > 110 public: > 111 const TCHAR* filename() const; > 112 int csi() const; > 113 int lb() const; > 114 > 115 public: > 116 static ki::aarr<TCHAR> ConnectWithNull( ki::String lst[], int num ); > 117 > 118 private: > 119 const CharSetList& csl_; > 120 TCHAR filename_[MAX_PATH]; > 121 int csIndex_; > 122 int lb_; > 123 > 124 private: > 125 static SaveFileDlg* pThis; // マルチスレッド禁止! > 126 static UINT_PTR CALLBACK OfnHook( HWND, UINT, WPARAM, LPARAM ); > 127 }; > 128 > 129 //------------------------------------------------------------------------ > 130 #ifndef __ccdoc__ > 131 > 132 inline SaveFileDlg::SaveFileDlg( const CharSetList& csl, int cs, int lb ) > 133 : csl_(csl), csIndex_(cs), lb_(lb) {} > 134 > 135 inline const TCHAR* SaveFileDlg::filename() const > 136 { return filename_; } > 137 > 138 inline int SaveFileDlg::csi() const > 139 { return csIndex_; } > 140 > 141 inline int SaveFileDlg::lb() const > 142 { return lb_; } > 143 > 144 inline ki::aarr<TCHAR> SaveFileDlg::ConnectWithNull > 145 ( ki::String lst[], int num ) > 146 { return OpenFileDlg::ConnectWithNull( lst, num ); } > 147 > 148 > 149 > 150 #endif // __ccdoc__ > 151 //======================================================================== > 152 //@{ > 153 // 「開き直す」ダイアログ > 154 // > 155 // 文字コード選択欄表示 > 156 //@} > 157 //======================================================================== > 158 > 159 class ReopenDlg : public ki::DlgImpl > 160 { > 161 public: > 162 ReopenDlg( const CharSetList& csl, int csi ); > 163 int csi() const; > 164 > 165 private: > 166 void on_init(); > 167 bool on_ok(); > 168 > 169 private: > 170 const CharSetList& csl_; > 171 int csIndex_; > 172 }; > 173 > 174 //------------------------------------------------------------------------ > 175 #ifndef __ccdoc__ > 176 > 177 inline int ReopenDlg::csi() const > 178 { return csIndex_; } > 179 > 180 > 181 > 182 //======================================================================== > 183 > 184 #endif // __ccdoc__ > 185 #endif // _GREENPAD_OPENSAVEDLG_H_

Added README.txt version [3c18011e76a7b913]

> 1 > 2 =<> > 3 =<> GreenPad ver 1.08+ Source Code > 4 =<> 2008/07/11 > 5 > 6 > 7 Windows用簡易テキストエディタ GreenPad のソースコードです。 > 8 下にあげるいくつかのC++コンパイラでコンパイルできます。 > 9 > 10 Source code for GreenPad - a simple text editor for Windows. > 11 Can be built by the following compilers. > 12 > 13 - Visual C++ .NET 2005 Express Edition > 14 - Visual C++ 2003 Toolkit > 15 - Microsoft Platform SDK for Windows Server 2003 R2 - March 2006 Edition > 16 - Borland C++ BuilderX > 17 - Borland C++ Compiler 5.5.1 > 18 - Digital Mars C++ 8.49 > 19 - MinGW (g++ 3.4.2) > 20 > 21 > 22 > 23 :: Visual C++ .NET 2005 :: > 24 > 25 - "kilib.sln" を開いて、「ビルド」メニューの「ソリューションのビルド」 > 26 > 27 - Open "kilib.sln" and build the main project. > 28 > 29 > 30 > 31 :: Visual C++ @ Command Prompt (Platform SDK / Toolkit 2003) :: > 32 > 33 - ソースコードのルートディレクトリで "nmake vcc" と打つ > 34 > 35 - Type "nmake vcc" at the root directory of the source archive > 36 > 37 > 38 > 39 :: Visual C++ 6.0 :: > 40 > 41 - 対応しなくなりました。 > 42 作者は確認していませんが、一応 kilib.dsw と kilib.dsp を使えば > 43 もしかしたらビルドできるかも。 > 44 > 45 - No longer supported > 46 kilib.dsw and kilib.dsp MAY work. > 47 > 48 > 49 > 50 :: Borland C++ @ Command Prompt (5.5.1 / BuilderX) :: > 51 > 52 - ソースコードのルートディレクトリで "make bcc" と打つ。 > 53 必ずBorland製のmakeコマンドを使用すること > 54 > 55 - Type "make bcc" at the root directory of the source archive > 56 Make sure to use Borland make. > 57 > 58 > 59 > 60 :: Digital Mars C++ :: > 61 > 62 - ソースコードのルートディレクトリで "make dmc" と打つ。 > 63 必ずDigitalmars製のmakeコマンドを使用すること。 > 64 なお、Digital Mars 製のリソースコンパイラは力不足のため、 > 65 リソースのコンパイルに Borland のコンパイラが必要です。 > 66 Borland C++ 5.5 についてくるので入手してください。 > 67 あと、imm32.dll をリンクするため imm32.lib が必要です。 > 68 お手元で生成するか、http://www.kmonos.net/alang/dmc/ から > 69 入手してください。 > 70 > 71 - Type "make dmc" at the root directory of the source archive > 72 Make sure to use Digitalmars make. > 73 Since DM's resource compiler is pretty poor, you additionaly > 74 need Borland's resource compiler to build GreenPad. > 75 You also need imm32.lib to build. You can generate it by > 76 coff2omf command or something, or you can download it from > 77 http://www.kmonos.net/alang/dmc/ . > 78 > 79 > 80 > 81 :: gcc (MinGW) :: > 82 > 83 - ソースコードのルートディレクトリで "make gcc" と打つ。 > 84 必ずGNU製のmakeコマンドを使用すること。 > 85 MinGW に最初から付属してくるリソースコンパイラ windres は > 86 日本語対応でないことがあります。MinGW のページから binutils > 87 を別途ダウンロードして、そちらの windres をご利用下さい。 > 88 > 89 - Type "make gcc" at the root directory of the source archive > 90 Make sure to use GNU make. > 91 MinGW version of windres (resource compiler) seem not to > 92 support Japanese resources. So you need to separately download > 93 binutils from the MinGW page and use the windres in it. > 94 > 95 > 96 > 97 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - > 98 > 99 :: ライセンス / License :: > 100 > 101 NYSL Version 0.9982 http://www.kmonos.net/nysl/ > 102 > 103 A. 本ソフトウェアは Everyone'sWare です。このソフトを手にした一人一人が、 > 104 ご自分の作ったものを扱うのと同じように、自由に利用することが出来ます。 > 105 > 106 A-1. フリーウェアです。作者からは使用料等を要求しません。 > 107 A-2. 有料無料や媒体の如何を問わず、自由に転載・再配布できます。 > 108 A-3. いかなる種類の 改変・他プログラムでの利用 を行っても構いません。 > 109 A-4. 変更したものや部分的に使用したものは、あなたのものになります。 > 110 公開する場合は、あなたの名前の下で行って下さい。 > 111 > 112 B. このソフトを利用することによって生じた損害等について、作者は > 113 責任を負わないものとします。各自の責任においてご利用下さい。 > 114 > 115 C. 著作者人格権は K.INABA に帰属します。著作権は放棄します。 > 116 > 117 D. 以上の3項は、ソース・実行バイナリの双方に適用されます。 > 118 > 119 > 120 --------------------------------------------------------------------------- > 121 by k.inaba( http://www.kmonos.net/ )

Added RSearch.cpp version [e489a8164194c55f]

> 1 > 2 #include "stdafx.h" > 3 #include "RSearch.h" > 4 #include "kilib/ktlaptr.h" > 5 using namespace ki; > 6 > 7 > 8 > 9 //========================================================================= > 10 //@{ > 11 // 文字の種類 > 12 //@} > 13 //========================================================================= > 14 > 15 enum RegToken > 16 { > 17 R_Char, // 普通の文字 > 18 R_Any, // '.' > 19 R_Lcl, // '[' > 20 R_Rcl, // ']' > 21 R_Ncl, // '^' > 22 R_Range, // '-' > 23 R_Lbr, // '(' > 24 R_Rbr, // ')' > 25 R_Bar, // '|' > 26 R_Star, // '*' > 27 R_Plus, // '+' > 28 R_Quest, // '?' > 29 R_End // '\0' > 30 }; > 31 > 32 > 33 > 34 //========================================================================= > 35 //@{ > 36 // トークンに分解 > 37 // > 38 // 行頭を表す^と行末を表す$については上位層で頑張る > 39 //@} > 40 //========================================================================= > 41 > 42 class RegLexer > 43 { > 44 public: > 45 RegLexer( const wchar_t* pat, ulong len ); > 46 RegToken GetToken(); > 47 wchar_t GetChar() { return chr_; } > 48 > 49 private: > 50 const wchar_t* pat_; > 51 const wchar_t* end_; > 52 const wchar_t* sub_; > 53 wchar_t chr_; > 54 }; > 55 > 56 > 57 > 58 //========================================================================= > 59 //@{ > 60 // トークンに分解:実装 > 61 //@} > 62 //========================================================================= > 63 > 64 inline RegLexer::RegLexer( const wchar_t* pat, ulong len ) > 65 : pat_( pat ) > 66 , end_( pat+len ) > 67 , sub_( L"" ) > 68 { > 69 } > 70 > 71 RegToken RegLexer::GetToken() > 72 { > 73 const wchar_t*& x = (*sub_ ? sub_ : pat_); > 74 if( x == end_ ) return R_End; > 75 switch( *x++ ) > 76 { > 77 case L'.': return R_Any; > 78 case L'[': return R_Lcl; > 79 case L']': return R_Rcl; > 80 case L'^': return R_Ncl; > 81 case L'-': return R_Range; > 82 case L'(': return R_Lbr; > 83 case L')': return R_Rbr; > 84 case L'|': return R_Bar; > 85 case L'*': return R_Star; > 86 case L'+': return R_Plus; > 87 case L'?': return R_Quest; > 88 case L'\\': if( x==end_ ) return R_End; switch( *x++ ) { > 89 case L't': chr_=L'\t'; return R_Char; > 90 case L'w': sub_=L"[0-9a-zA-Z_]"; return GetToken(); > 91 case L'W': sub_=L"[^0-9a-zA-Z_]"; return GetToken(); > 92 case L'd': sub_=L"[0-9]"; return GetToken(); > 93 case L'D': sub_=L"[^0-9]"; return GetToken(); > 94 case L's': sub_=L"[\t ]"; return GetToken(); > 95 case L'S': sub_=L"[^\t ]"; return GetToken(); > 96 } // fall through... > 97 default: > 98 chr_ = *(x-1); > 99 return R_Char; > 100 } > 101 } > 102 > 103 > 104 > 105 //========================================================================= > 106 //@{ > 107 // 構文木のノードに振られる値の種類 > 108 //@} > 109 //========================================================================= > 110 > 111 enum RegType > 112 { > 113 N_Char, // 普通の文字 (ch) > 114 N_Class, // [...] など (cls) > 115 N_Concat, // 連接 (left, right) > 116 N_Or, // | (left, right) > 117 N_Closure, // * (left) > 118 N_Closure1, // + (left) > 119 N_01, // ? (left) > 120 N_Empty // 空 (--) > 121 }; > 122 > 123 struct RegClass > 124 { > 125 struct OneRange > 126 { > 127 wchar_t stt; > 128 wchar_t end; > 129 }; > 130 OneRange range; > 131 aptr<RegClass> next; > 132 RegClass( wchar_t s, wchar_t e, RegClass* n ) > 133 { aptr<RegClass> an(n); range.stt=s, range.end=e, next=an; } > 134 }; > 135 > 136 struct RegNode > 137 { > 138 RegType type; // このノードの種類 > 139 wchar_t ch; // 文字 > 140 aptr<RegClass> cls; // 文字集合 > 141 bool cmpcls; // ↑補集合かどうか > 142 dptr<RegNode> left; // 左の子 > 143 dptr<RegNode> right; // 右の子 > 144 }; > 145 > 146 > 147 > 148 //========================================================================= > 149 //@{ > 150 // 構文木作成 > 151 //@} > 152 //========================================================================= > 153 > 154 class RegParser > 155 { > 156 public: > 157 RegParser( const unicode* pat ); > 158 RegNode* root() { return root_.get(); } > 159 bool err() { return err_; } > 160 bool isHeadType() const { return isHeadType_; } > 161 bool isTailType() const { return isTailType_; } > 162 > 163 private: > 164 RegNode* make_empty_leaf(); > 165 RegNode* make_char_leaf( wchar_t c ); > 166 RegNode* make_node( RegType t, RegNode* lft, RegNode* rht ); > 167 void eat_token(); > 168 RegNode* expr(); > 169 RegNode* term(); > 170 RegNode* factor(); > 171 RegNode* primary(); > 172 RegNode* reclass(); > 173 > 174 private: > 175 bool err_; > 176 bool isHeadType_; > 177 bool isTailType_; > 178 dptr<RegNode> root_; > 179 > 180 RegLexer lex_; > 181 RegToken nextToken_; > 182 }; > 183 > 184 > 185 > 186 //========================================================================= > 187 //@{ > 188 // 構文木作成:実装 > 189 //@} > 190 //========================================================================= > 191 > 192 namespace { static int tmp; } > 193 > 194 inline RegParser::RegParser( const unicode* pat ) > 195 : err_ ( false ) > 196 , isHeadType_( *pat==L'^' ) > 197 , isTailType_( (tmp=my_lstrlenW(pat), tmp && pat[tmp-1]==L'$') ) > 198 , lex_( > 199 (isHeadType_ ? pat+1 : pat), > 200 (my_lstrlenW(pat) - (isHeadType_ ? 1 : 0) > 201 - (isTailType_ ? 1 : 0)) ) > 202 { > 203 eat_token(); > 204 root_ = expr(); > 205 } > 206 > 207 inline void RegParser::eat_token() > 208 { > 209 nextToken_ = lex_.GetToken(); > 210 } > 211 > 212 inline RegNode* RegParser::make_empty_leaf() > 213 { > 214 RegNode* node = new RegNode; > 215 node->type = N_Empty; > 216 return node; > 217 } > 218 > 219 inline RegNode* RegParser::make_char_leaf( wchar_t c ) > 220 { > 221 RegNode* node = new RegNode; > 222 node->type = N_Char; > 223 node->ch = c; > 224 return node; > 225 } > 226 > 227 RegNode* RegParser::make_node( RegType t, RegNode* lft, RegNode* rht ) > 228 { > 229 RegNode* node = new RegNode; > 230 node->type = t; > 231 node->left = lft; > 232 node->right= rht; > 233 return node; > 234 } > 235 > 236 RegNode* RegParser::reclass() > 237 { > 238 // CLASS ::= '^'? CHAR (CHAR | -CHAR)* > 239 > 240 bool neg = false; > 241 if( nextToken_ == R_Ncl ) > 242 neg=true, eat_token(); > 243 > 244 RegClass* cls = NULL; > 245 while( nextToken_ == R_Char ) > 246 { > 247 wchar_t ch = lex_.GetChar(); > 248 eat_token(); > 249 if( nextToken_ == R_Range ) > 250 { > 251 eat_token(); > 252 if( nextToken_ != R_Char ) > 253 err_ = true; > 254 else > 255 { > 256 wchar_t ch2 = lex_.GetChar(); > 257 cls = new RegClass( Min(ch,ch2), Max(ch,ch2), cl > 258 eat_token(); > 259 } > 260 } > 261 else > 262 { > 263 cls = new RegClass( ch, ch, cls ); > 264 } > 265 } > 266 > 267 RegNode* node = new RegNode; > 268 node->type = N_Class; > 269 aptr<RegClass> ncls(cls); > 270 node->cls = ncls; > 271 node->cmpcls = neg; > 272 return node; > 273 } > 274 > 275 RegNode* RegParser::primary() > 276 { > 277 // PRIMARY ::= CHAR > 278 // '.' > 279 // '[' CLASS ']' > 280 // '(' REGEXP ')' > 281 > 282 RegNode* node; > 283 switch( nextToken_ ) > 284 { > 285 case R_Char: > 286 node = make_char_leaf( lex_.GetChar() ); > 287 eat_token(); > 288 break; > 289 case R_Any:{ > 290 node = new RegNode; > 291 node->type = N_Class; > 292 aptr<RegClass> ncls(new RegClass( 0, 65535, NULL )); > 293 node->cls = ncls; > 294 node->cmpcls = false; > 295 eat_token(); > 296 }break; > 297 case R_Lcl: > 298 eat_token(); > 299 node = reclass(); > 300 if( nextToken_ == R_Rcl ) > 301 eat_token(); > 302 else > 303 err_ = true; > 304 break; > 305 case R_Lbr: > 306 eat_token(); > 307 node = expr(); > 308 if( nextToken_ == R_Rbr ) > 309 eat_token(); > 310 else > 311 err_ = true; > 312 break; > 313 default: > 314 node = make_empty_leaf(); > 315 err_ = true; > 316 break; > 317 } > 318 return node; > 319 } > 320 > 321 RegNode* RegParser::factor() > 322 { > 323 // FACTOR ::= PRIMARY > 324 // PRIMARY '*' > 325 // PRIMARY '+' > 326 // PRIMARY '?' > 327 > 328 RegNode* node = primary(); > 329 switch( nextToken_ ) > 330 { > 331 case R_Star: node=make_node(N_Closure,node,NULL); eat_token();break; > 332 case R_Plus: node=make_node(N_Closure1,node,NULL);eat_token();break; > 333 case R_Quest:node=make_node(N_01,node,NULL ); eat_token();break; > 334 } > 335 return node; > 336 } > 337 > 338 RegNode* RegParser::term() > 339 { > 340 // TERM ::= EMPTY > 341 // FACTOR TERM > 342 > 343 if( nextToken_ == R_End ) > 344 return make_empty_leaf(); > 345 > 346 RegNode* node = factor(); > 347 if( nextToken_==R_Lbr || nextToken_==R_Lcl > 348 || nextToken_==R_Char|| nextToken_==R_Any ) > 349 node = make_node( N_Concat, node, term() ); > 350 return node; > 351 } > 352 > 353 RegNode* RegParser::expr() > 354 { > 355 // REGEXP ::= TERM > 356 // TERM '|' REGEXP > 357 > 358 RegNode* node = term(); > 359 if( nextToken_ == R_Bar ) > 360 { > 361 eat_token(); > 362 node = make_node( N_Or, node, expr() ); > 363 } > 364 return node; > 365 } > 366 > 367 > 368 > 369 //========================================================================= > 370 //@{ > 371 // 状態遷移 > 372 //@} > 373 //========================================================================= > 374 > 375 struct RegTrans > 376 { > 377 enum { > 378 Epsilon, > 379 Class, > 380 Char > 381 } type; > 382 aptr<RegClass> cls; // この文字集合 > 383 // orEpsilon が来たら > 384 bool cmpcls; > 385 int to; // 状態番号toの状態へ遷移 > 386 > 387 aptr<RegTrans> next; // 連結リスト > 388 /* > 389 template<class Cmp> > 390 bool match_i( wchar_t c, Cmp ) > 391 { > 392 c = Cmp::map(c); > 393 RegClass* p = cls.get(); > 394 while( p ) > 395 if( Cmp::map(p->range.stt)<=c && c<=Cmp::map(p->range.en > 396 return true; > 397 else > 398 p = p->next.get(); > 399 return false; > 400 } > 401 */ > 402 bool match_c( wchar_t c ) > 403 { > 404 for( RegClass* p=cls.get(); p; p=p->next.get() ) > 405 if( p->range.stt<=c && c<=p->range.end ) > 406 return true; > 407 return false; > 408 } > 409 > 410 bool match_i( wchar_t c ) > 411 { > 412 c = IgnoreCase::map(c); > 413 for( RegClass* p=cls.get(); p; p=p->next.get() ) > 414 if( IgnoreCase::map(p->range.stt)<=c > 415 && c<=IgnoreCase::map(p->range.end) ) > 416 return true; > 417 return false; > 418 } > 419 > 420 bool match( wchar_t c, bool caseS ) > 421 { > 422 bool m = caseS ? match_c( c ) : match_i( c ); > 423 return cmpcls ? !m : m; > 424 } > 425 }; > 426 > 427 > 428 > 429 //========================================================================= > 430 //@{ > 431 // 構文木->NFA変換 > 432 //@} > 433 //========================================================================= > 434 > 435 class RegNFA > 436 { > 437 public: > 438 RegNFA( const wchar_t* pat ); > 439 ~RegNFA(); > 440 > 441 int match( const wchar_t* str, int len, bool caseS ); > 442 bool isHeadType() const { return parser.isHeadType(); } > 443 bool isTailType() const { return parser.isTailType(); } > 444 > 445 private: > 446 // マッチング処理 > 447 int dfa_match( const wchar_t* str, int len, bool caseS ); > 448 > 449 struct st_ele { int st, ps; }; > 450 void push(storage<st_ele>& stack, int curSt, int pos); > 451 st_ele pop(storage<st_ele>& stack); > 452 > 453 private: > 454 void add_transition( int from, wchar_t ch, int to ); > 455 void add_transition( int from, aptr<RegClass> cls, bool cmp, int to ); > 456 void add_e_transition( int from, int to ); > 457 int gen_state(); > 458 void gen_nfa( int entry, RegNode* t, int exit ); > 459 > 460 private: > 461 RegParser parser; > 462 storage<RegTrans*> st; > 463 int start, final; > 464 }; > 465 > 466 RegNFA::RegNFA( const wchar_t* pat ) > 467 : parser( pat ) > 468 { > 469 start = gen_state(); > 470 final = gen_state(); > 471 gen_nfa( start, parser.root(), final ); > 472 } > 473 > 474 inline RegNFA::~RegNFA() > 475 { > 476 for( ulong i=0,e=st.size(); i<e; ++i ) > 477 delete st[i]; > 478 } > 479 > 480 inline void RegNFA::add_transition > 481 ( int from, aptr<RegClass> cls, bool cmp, int to ) > 482 { > 483 RegTrans* x = new RegTrans; > 484 aptr<RegTrans> nn( st[from] ); > 485 x->next = nn; > 486 x->to = to; > 487 x->type = RegTrans::Class; > 488 x->cls = cls; > 489 x->cmpcls= cmp; > 490 st[from] = x; > 491 } > 492 > 493 inline void RegNFA::add_transition( int from, wchar_t ch, int to ) > 494 { > 495 aptr<RegClass> cls(new RegClass(ch,ch,NULL)); > 496 add_transition( from, cls, false, to ); > 497 } > 498 > 499 inline void RegNFA::add_e_transition( int from, int to ) > 500 { > 501 RegTrans* x = new RegTrans; > 502 aptr<RegTrans> nn( st[from] ); > 503 x->next = nn; > 504 x->to = to; > 505 x->type = RegTrans::Epsilon; > 506 st[from] = x; > 507 } > 508 > 509 inline int RegNFA::gen_state() > 510 { > 511 st.Add( NULL ); > 512 return st.size() - 1; > 513 } > 514 > 515 void RegNFA::gen_nfa( int entry, RegNode* t, int exit ) > 516 { > 517 switch( t->type ) > 518 { > 519 case N_Char: > 520 // ch > 521 // entry ----> exit > 522 add_transition( entry, t->ch, exit ); > 523 break; > 524 case N_Class: > 525 // cls > 526 // entry -----> exit > 527 add_transition( entry, t->cls, t->cmpcls, exit ); > 528 break; > 529 case N_Concat: { > 530 // left right > 531 // entry ------> step -------> exit > 532 int step = gen_state(); > 533 gen_nfa( entry, t->left.get(), step ); > 534 gen_nfa( step, t->right.get(), exit ); > 535 } break; > 536 case N_Or: > 537 // left > 538 // ------> > 539 // entry ------->--> exit > 540 // right > 541 gen_nfa( entry, t->left.get(), exit ); > 542 gen_nfa( entry, t->right.get(), exit ); > 543 break; > 544 case N_Closure: > 545 // e > 546 // e <------ e > 547 // entry ---> before ------> after ---> exit > 548 // | left ^ > 549 // >------->------------------->------>-| > 550 // e > 551 case N_Closure1: { > 552 // e > 553 // e <------ e > 554 // entry ---> before ------> after ---> exit > 555 // left > 556 int before = gen_state(); > 557 int after = gen_state(); > 558 add_e_transition( entry, before ); > 559 add_e_transition( after, exit ); > 560 add_e_transition( after, before ); > 561 gen_nfa( before, t->left.get(), after ); > 562 if( t->type != N_Closure1 ) > 563 add_e_transition( entry, exit ); > 564 } break; > 565 case N_01: > 566 // e > 567 // ------> > 568 // entry ------> exit > 569 // left > 570 add_e_transition( entry, exit ); > 571 gen_nfa( entry, t->left.get(), exit ); > 572 break; > 573 case N_Empty: > 574 // e > 575 // entry ---> exit > 576 add_e_transition( entry, exit ); > 577 break; > 578 } > 579 } > 580 > 581 > 582 > 583 //========================================================================= > 584 //@{ > 585 // マッチング > 586 //@} > 587 //========================================================================= > 588 > 589 void RegNFA::push(storage<st_ele>& stack, int curSt, int pos) > 590 { > 591 // ε無限ループ防止策。同じ状態には戻らないように… > 592 for( int i=stack.size()-1; i>=0; --i ) > 593 if( stack[i].ps != pos ) > 594 break; > 595 else if( stack[i].st == curSt ) > 596 return; > 597 > 598 st_ele nw = {curSt,pos}; > 599 stack.Add( nw ); > 600 } > 601 > 602 RegNFA::st_ele RegNFA::pop(storage<st_ele>& stack) > 603 { > 604 st_ele se = stack[stack.size()-1]; > 605 stack.ForceSize( stack.size()-1 ); > 606 return se; > 607 } > 608 > 609 int RegNFA::match( const wchar_t* str, int len, bool caseS ) > 610 { > 611 if( parser.err() ) > 612 return -1; // エラー状態なのでmatchとかできません > 613 //if( st.size() <= 31 ) > 614 // return dfa_match(str,len,caseS); // 状態数が少なければDFAを使う、かも > 615 > 616 int matchpos = -1; > 617 > 618 storage<st_ele> stack; > 619 push(stack, start, 0); > 620 while( stack.size() > 0 ) > 621 { > 622 // スタックからpop > 623 st_ele se = pop(stack); > 624 int curSt = se.st; > 625 int pos = se.ps; > 626 > 627 // マッチ成功してたら記録 > 628 if( curSt == final ) // 1==終状態 > 629 if( matchpos < pos ) > 630 matchpos = pos; > 631 > 632 // さらに先の遷移を調べる > 633 if( matchpos < len ) > 634 for( RegTrans* tr=st[curSt]; tr!=NULL; tr=tr->next.get() > 635 if( tr->type == RegTrans::Epsilon ) > 636 push(stack, tr->to, pos); > 637 else if( pos<len && tr->match( str[pos], caseS ) > 638 push(stack, tr->to, pos+1); > 639 } > 640 > 641 return matchpos; > 642 } > 643 > 644 int RegNFA::dfa_match( const wchar_t* str, int len, bool caseS ) > 645 { > 646 int matchpos = -1; > 647 > 648 unsigned int StateSet = (1<<start); > 649 for(int pos=0; StateSet; ++pos) > 650 { > 651 // ε-closure > 652 for(uint DifSS=StateSet; DifSS;) > 653 { > 654 unsigned int NewSS = 0; > 655 for(int s=0; (1u<<s)<=DifSS; ++s) > 656 if( (1u<<s) & DifSS ) > 657 for( RegTrans* tr=st[s]; tr!=NULL; tr=tr > 658 if( tr->type == RegTrans::Epsilo > 659 NewSS |= 1u << tr->to; > 660 DifSS = (NewSS|StateSet) ^ StateSet; > 661 StateSet |= NewSS; > 662 } > 663 > 664 // 受理状態を含んでるかどうか判定 > 665 if( StateSet & (1<<final) ) > 666 matchpos = pos; > 667 > 668 // 文字列の終わりに達した > 669 if( pos == len ) > 670 break; > 671 > 672 // 遷移 > 673 unsigned int NewSS = 0; > 674 for(int s=0; (1u<<s)<=StateSet; ++s) > 675 if( (1u<<s) & StateSet ) > 676 for( RegTrans* tr=st[s]; tr!=NULL; tr=tr->next.g > 677 if( tr->type!=RegTrans::Epsilon && tr->m > 678 NewSS |= 1u << tr->to; > 679 StateSet = NewSS; > 680 } > 681 > 682 return matchpos; > 683 } > 684 > 685 ////////////////////////////////////////////////////////////////////// > 686 > 687 bool reg_match( const wchar_t* pat, const wchar_t* str, bool caseS ) > 688 { > 689 int len = my_lstrlenW(str); > 690 > 691 RegNFA re( pat ); > 692 return len == re.match( str, len, caseS ); > 693 } > 694 > 695 > 696 > 697 //========================================================================= > 698 //@{ > 699 // GreenPad用検索オブジェクト > 700 //@} > 701 //========================================================================= > 702 > 703 RSearch::RSearch( const unicode* key, bool caseS, bool down ) > 704 : re_ ( new RegNFA(key) ) > 705 , caseS_ ( caseS ) > 706 , down_ ( down ) > 707 { > 708 } > 709 > 710 bool RSearch::Search( > 711 const unicode* str, ulong len, ulong stt, ulong* mbg, ulong* med ) > 712 { > 713 if( down_ && re_->isHeadType() && stt>0 ) > 714 return false; > 715 > 716 const int d = (down_ ? 1 : -1); > 717 int s = (!down_ && re_->isHeadType() ? 0 : stt); > 718 const int e = (down_ ? (re_->isHeadType() ? 1 : (long)len) : -1); > 719 > 720 for( ; s!=e; s+=d ) > 721 { > 722 const int L = re_->match( str+s, len-s, caseS_ ); > 723 if( L > 0 ) > 724 { > 725 if( re_->isTailType() && L!=static_cast<int>(len-s) ) > 726 continue; > 727 *mbg = static_cast<ulong>(s); > 728 *med = static_cast<ulong>(s+L); > 729 return true; > 730 } > 731 } > 732 > 733 return false; > 734 } > 735 > 736

Added RSearch.h version [a1c854d162219a9e]

> 1 #ifndef AFX_RSEARCH_H__5A9346D4_3152_4923_8EFC_38264A456364__INCLUDED_ > 2 #define AFX_RSEARCH_H__5A9346D4_3152_4923_8EFC_38264A456364__INCLUDED_ > 3 #include "kilib/ktlaptr.h" > 4 #include "NSearch.h" > 5 > 6 > 7 //========================================================================= > 8 //@{ @pkg Gp.Search //@} > 9 //@{ > 10 // 超簡易正規表現マッチング関数。 > 11 // > 12 // patとstr全体がマッチするならtrue、ダメならfalseを返す > 13 //@} > 14 //========================================================================= > 15 > 16 bool reg_match( const wchar_t* pat, const wchar_t* str, bool caseS ); > 17 > 18 > 19 class RegNFA; > 20 //========================================================================= > 21 //@{ > 22 // Searhcableとしての実装 > 23 //@} > 24 //========================================================================= > 25 > 26 class RSearch : public Searchable > 27 { > 28 public: > 29 RSearch( const unicode* key, bool caseS, bool down ); > 30 > 31 private: > 32 virtual bool Search( const unicode* str, ulong len, ulong stt, > 33 ulong* mbg, ulong* med ); > 34 > 35 private: > 36 ki::dptr<RegNFA> re_; > 37 bool caseS_; > 38 bool down_; > 39 }; > 40 > 41 > 42 > 43 > 44 > 45 #endif

Added Search.cpp version [8394be04b45c45f1]

> 1 > 2 #include "stdafx.h" > 3 #include "rsrc/resource.h" > 4 #include "Search.h" > 5 #include "NSearch.h" > 6 #include "RSearch.h" > 7 using namespace ki; > 8 using namespace editwing; > 9 using view::VPos; > 10 > 11 > 12 > 13 //------------------------------------------------------------------------- > 14 > 15 SearchManager::SearchManager( ki::Window& w, editwing::EwEdit& e ) > 16 : searcher_( NULL ) > 17 , edit_( e ) > 18 , DlgImpl( IDD_FINDREPLACE ) > 19 , bIgnoreCase_( true ) // 1.08 default true > 20 , bRegExp_( false ) > 21 , bDownSearch_( true ) > 22 , mainWnd_( w ) > 23 { > 24 } > 25 > 26 SearchManager::~SearchManager() > 27 { > 28 } > 29 > 30 void SearchManager::SaveToINI( ki::IniFile& ini ) > 31 { > 32 ini.SetSectionAsUserName(); > 33 ini.PutBool( TEXT("SearchIgnoreCase"), bIgnoreCase_ ); > 34 ini.PutBool( TEXT("SearchRegExp"), bRegExp_ ); > 35 } > 36 > 37 void SearchManager::LoadFromINI( ki::IniFile& ini ) > 38 { > 39 ini.SetSectionAsUserName(); > 40 bIgnoreCase_ = ini.GetBool( TEXT("SearchIgnoreCase"), bIgnoreCase_ ); > 41 bRegExp_ = ini.GetBool( TEXT("SearchRegExp"), bRegExp_ ); > 42 } > 43 > 44 //------------------------------------------------------------------------- > 45 // ダイアログ関係 > 46 //------------------------------------------------------------------------- > 47 > 48 void SearchManager::ShowDlg() > 49 { > 50 // GoModal( ::GetParent(edit_.hwnd()) ); > 51 if( isAlive() ) > 52 { > 53 SetFront(); > 54 } > 55 else > 56 { > 57 GoModeless( ::GetParent(edit_.hwnd()) ); > 58 ShowUp(); > 59 } > 60 } > 61 > 62 bool SearchManager::TrapMsg(MSG* msg) > 63 { > 64 if( ! isAlive() || type()==MODAL ) > 65 return false; > 66 return DlgImpl::PreTranslateMessage(msg); > 67 } > 68 > 69 void SearchManager::on_init() > 70 { > 71 if( bIgnoreCase_ ) > 72 SendMsgToItem( IDC_IGNORECASE, BM_SETCHECK, BST_CHECKED ); > 73 if( bRegExp_ ) > 74 SendMsgToItem( IDC_REGEXP, BM_SETCHECK, BST_CHECKED ); > 75 > 76 if( edit_.getCursor().isSelected() ) > 77 { > 78 // 選択されている状態では、基本的にそれをボックスに表示 > 79 ulong dmy; > 80 aarr<unicode> str = edit_.getCursor().getSelectedStr(); > 81 > 82 ulong len=0; > 83 for( ; str[len]!=L'\0' && str[len]!=L'\n'; ++len ); > 84 str[len] = L'\0'; > 85 > 86 if( searcher_.isValid() && > 87 searcher_->Search( str.get(), len, 0, &dmy, &dmy ) ) > 88 { > 89 SendMsgToItem( IDC_FINDBOX, WM_SETTEXT, 0, > 90 reinterpret_cast<LPARAM>(findStr_.c_str()) ); > 91 } > 92 else > 93 { > 94 #ifdef _UNICODE > 95 SendMsgToItem( IDC_FINDBOX, WM_SETTEXT, 0, > 96 reinterpret_cast<LPARAM>(str.get()) ); > 97 #else > 98 ki::aarr<char> ab( new TCHAR[(len+1)*3] ); > 99 ::WideCharToMultiByte( CP_ACP, 0, str.get(), -1, > 100 ab.get(), (len+1)*3, NULL, NULL ); > 101 SendMsgToItem( IDC_FINDBOX, WM_SETTEXT, 0, > 102 reinterpret_cast<LPARAM>(ab.get()) ); > 103 #endif > 104 } > 105 } > 106 else > 107 { > 108 SendMsgToItem( IDC_FINDBOX, WM_SETTEXT, 0, > 109 reinterpret_cast<LPARAM>(findStr_.c_str()) ); > 110 } > 111 > 112 SendMsgToItem( IDC_REPLACEBOX, WM_SETTEXT, 0, > 113 reinterpret_cast<LPARAM>(replStr_.c_str()) ); > 114 > 115 ::SetFocus( item(IDC_FINDBOX) ); > 116 SendMsgToItem( IDC_FINDBOX, EM_SETSEL, 0, > 117 ::GetWindowTextLength(item(IDC_FINDBOX)) ); > 118 } > 119 > 120 void SearchManager::on_destroy() > 121 { > 122 bChanged_ = false; > 123 } > 124 > 125 bool SearchManager::on_command( UINT cmd, UINT id, HWND ctrl ) > 126 { > 127 if( cmd==EN_CHANGE ) > 128 { > 129 // 文字列変更があったことを記憶 > 130 bChanged_ = true; > 131 } > 132 else if( cmd==BN_CLICKED ) > 133 { > 134 switch( id ) > 135 { > 136 // チェックボックスの変更があったことを記憶 > 137 case IDC_IGNORECASE: > 138 case IDC_REGEXP: > 139 bChanged_ = true; > 140 break; > 141 // ボタンが押された場合 > 142 case ID_FINDNEXT: > 143 on_findnext(); > 144 break; > 145 case ID_FINDPREV: > 146 on_findprev(); > 147 break; > 148 case ID_REPLACENEXT: > 149 on_replacenext(); > 150 break; > 151 case ID_REPLACEALL: > 152 on_replaceall(); > 153 break; > 154 } > 155 } > 156 else > 157 { > 158 return false; > 159 } > 160 return true; > 161 } > 162 > 163 void SearchManager::on_findnext() > 164 { > 165 UpdateData(); > 166 ConstructSearcher(); > 167 if( isReady() ) > 168 { > 169 FindNextImpl(); > 170 // End( IDOK ); > 171 } > 172 } > 173 > 174 void SearchManager::on_findprev() > 175 { > 176 UpdateData(); > 177 ConstructSearcher( false ); > 178 if( isReady() ) > 179 FindPrevImpl(); > 180 } > 181 > 182 void SearchManager::on_replacenext() > 183 { > 184 UpdateData(); > 185 ConstructSearcher(); > 186 if( isReady() ) > 187 ReplaceImpl(); > 188 } > 189 > 190 void SearchManager::on_replaceall() > 191 { > 192 UpdateData(); > 193 ConstructSearcher(); > 194 if( isReady() ) > 195 ReplaceAllImpl(); > 196 } > 197 > 198 void SearchManager::UpdateData() > 199 { > 200 // ダイアログから変更点を取り込み > 201 bIgnoreCase_ = > 202 (BST_CHECKED==SendMsgToItem( IDC_IGNORECASE, BM_GETCHECK )); > 203 bRegExp_ = > 204 (BST_CHECKED==SendMsgToItem( IDC_REGEXP, BM_GETCHECK )); > 205 > 206 TCHAR* str; > 207 LRESULT n = SendMsgToItem( IDC_FINDBOX, WM_GETTEXTLENGTH ); > 208 str = new TCHAR[n+1]; > 209 SendMsgToItem( IDC_FINDBOX, WM_GETTEXT, > 210 n+1, reinterpret_cast<LPARAM>(str) ); > 211 findStr_ = str; > 212 delete [] str; > 213 > 214 n = SendMsgToItem( IDC_REPLACEBOX, WM_GETTEXTLENGTH ); > 215 str = new TCHAR[n+1]; > 216 SendMsgToItem( IDC_REPLACEBOX, WM_GETTEXT, > 217 n+1, reinterpret_cast<LPARAM>(str) ); > 218 replStr_ = str; > 219 delete [] str; > 220 } > 221 > 222 void SearchManager::ConstructSearcher( bool down ) > 223 { > 224 bChanged_ = (bChanged_ || (bDownSearch_ != down)); > 225 if( (bChanged_ || !isReady()) && findStr_.len()!=0 ) > 226 { > 227 // 検索者作成 > 228 bDownSearch_ = down; > 229 const unicode *u = findStr_.ConvToWChar(); > 230 > 231 if( bRegExp_ ) > 232 searcher_ = new RSearch( u, !bIgnoreCase_, bDownSearch_ > 233 else > 234 if( bDownSearch_ ) > 235 if( bIgnoreCase_ ) > 236 searcher_ = new NSearch<IgnoreCase>(u); > 237 else > 238 searcher_ = new NSearch<CaseSensitive>(u > 239 else > 240 if( bIgnoreCase_ ) > 241 searcher_ = new NSearchRev<IgnoreCase>(u > 242 else > 243 searcher_ = new NSearchRev<CaseSensitive > 244 > 245 findStr_.FreeWCMem(u); > 246 > 247 // 変更終了フラグ > 248 bChanged_ = false; > 249 } > 250 } > 251 > 252 > 253 > 254 //------------------------------------------------------------------------- > 255 > 256 void SearchManager::FindNext() > 257 { > 258 if( !isReady() ) > 259 { > 260 ShowDlg(); > 261 } > 262 else > 263 { > 264 ConstructSearcher(); > 265 if( isReady() ) > 266 FindNextImpl(); > 267 } > 268 } > 269 > 270 void SearchManager::FindPrev() > 271 { > 272 if( !isReady() ) > 273 { > 274 ShowDlg(); > 275 } > 276 else > 277 { > 278 ConstructSearcher( false ); > 279 if( isReady() ) > 280 FindPrevImpl(); > 281 } > 282 } > 283 > 284 > 285 > 286 //------------------------------------------------------------------------- > 287 // 実際の処理の実装 > 288 //------------------------------------------------------------------------- > 289 > 290 void SearchManager::FindNextImpl() > 291 { > 292 // カーソル位置取得 > 293 const VPos *stt, *end; > 294 edit_.getCursor().getCurPos( &stt, &end ); > 295 > 296 // 選択範囲ありなら、選択範囲先頭の1文字先から検索 > 297 // そうでなければカーソル位置から検索 > 298 DPos s = *stt; > 299 if( *stt != *end ) > 300 if( stt->ad == edit_.getDoc().len(stt->tl) ) > 301 s = DPos( stt->tl+1, 0 ); > 302 else > 303 s = DPos( stt->tl, stt->ad+1 ); > 304 > 305 // 検索 > 306 DPos b, e; > 307 if( FindNextFromImpl( s, &b, &e ) ) > 308 { > 309 // 見つかったら選択 > 310 edit_.getCursor().MoveCur( b, false ); > 311 edit_.getCursor().MoveCur( e, true ); > 312 return; > 313 } > 314 > 315 // 見つからなかった場合 > 316 NotFound(); > 317 } > 318 > 319 void SearchManager::NotFound() > 320 { > 321 //MsgBox( String(IDS_NOTFOUND).c_str() ); > 322 ::MessageBox( NULL, String(IDS_NOTFOUND).c_str(), NULL, MB_OK|MB_TASKMOD > 323 } > 324 > 325 void SearchManager::FindPrevImpl() > 326 { > 327 // カーソル位置取得 > 328 const VPos *stt, *end; > 329 edit_.getCursor().getCurPos( &stt, &end ); > 330 > 331 if( stt->ad!=0 || stt->tl!=0 ) > 332 { > 333 // 選択範囲先頭の1文字前から検索 > 334 DPos s; > 335 if( stt->ad == 0 ) > 336 s = DPos( stt->tl-1, edit_.getDoc().len(stt->tl-1) ); > 337 else > 338 s = DPos( stt->tl, stt->ad-1 ); > 339 > 340 // 検索 > 341 DPos b, e; > 342 if( FindPrevFromImpl( s, &b, &e ) ) > 343 { > 344 // 見つかったら選択 > 345 edit_.getCursor().MoveCur( b, false ); > 346 edit_.getCursor().MoveCur( e, true ); > 347 return; > 348 } > 349 } > 350 > 351 // 見つからなかった場合 > 352 NotFound(); > 353 } > 354 > 355 bool SearchManager::FindNextFromImpl( DPos s, DPos* beg, DPos* end ) > 356 { > 357 // 1行ずつサーチ > 358 doc::Document& d = edit_.getDoc(); > 359 for( ulong mbg,med,e=d.tln(); s.tl<e; ++s.tl, s.ad=0 ) > 360 if( searcher_->Search( > 361 d.tl(s.tl), d.len(s.tl), s.ad, &mbg, &med ) ) > 362 { > 363 beg->tl = end->tl = s.tl; > 364 beg->ad = mbg; > 365 end->ad = med; > 366 return true; // 発見 > 367 } > 368 return false; > 369 } > 370 > 371 bool SearchManager::FindPrevFromImpl( DPos s, DPos* beg, DPos* end ) > 372 { > 373 // 1行ずつサーチ > 374 doc::Document& d = edit_.getDoc(); > 375 for( ulong mbg,med; ; s.ad=d.len(--s.tl) ) > 376 { > 377 if( searcher_->Search( > 378 d.tl(s.tl), d.len(s.tl), s.ad, &mbg, &med ) ) > 379 { > 380 beg->tl = end->tl = s.tl; > 381 beg->ad = mbg; > 382 end->ad = med; > 383 return true; // 発見 > 384 } > 385 if( s.tl==0 ) > 386 break; > 387 } > 388 return false; > 389 } > 390 > 391 void SearchManager::ReplaceImpl() > 392 { > 393 // カーソル位置取得 > 394 const VPos *stt, *end; > 395 edit_.getCursor().getCurPos( &stt, &end ); > 396 > 397 // 選択範囲先頭から検索 > 398 DPos b, e; > 399 if( FindNextFromImpl( *stt, &b, &e ) ) > 400 if( e == *end ) > 401 { > 402 const wchar_t* ustr = replStr_.ConvToWChar(); > 403 const ulong ulen = my_lstrlenW( ustr ); > 404 > 405 // 置換 > 406 edit_.getDoc().Execute( doc::Replace( > 407 b, e, ustr, ulen > 408 ) ); > 409 > 410 replStr_.FreeWCMem( ustr ); > 411 > 412 if( FindNextFromImpl( DPos(b.tl,b.ad+ulen), &b, &e ) ) > 413 { > 414 // 次を選択 > 415 edit_.getCursor().MoveCur( b, false ); > 416 edit_.getCursor().MoveCur( e, true ); > 417 return; > 418 } > 419 } > 420 else > 421 { > 422 // そうでなければとりあえず選択 > 423 edit_.getCursor().MoveCur( b, false ); > 424 edit_.getCursor().MoveCur( e, true ); > 425 return; > 426 } > 427 > 428 // 見つからなかった場合 > 429 NotFound(); > 430 } > 431 > 432 void SearchManager::ReplaceAllImpl() > 433 { > 434 // まず、実行する置換を全てここに登録する > 435 doc::MacroCommand mcr; > 436 > 437 // 置換後文字列 > 438 const wchar_t* ustr = replStr_.ConvToWChar(); > 439 const ulong ulen = my_lstrlenW( ustr ); > 440 > 441 // 文書の頭から検索 > 442 int dif=0; > 443 DPos s(0,0), b, e; > 444 while( FindNextFromImpl( s, &b, &e ) ) > 445 { > 446 if( s.tl != b.tl ) dif = 0; > 447 s = e; > 448 > 449 // 置換コマンドを登録 > 450 b.ad += dif, e.ad += dif; > 451 mcr.Add( new doc::Replace(b,e,ustr,ulen) ); > 452 dif -= e.ad-b.ad-ulen; > 453 } > 454 > 455 if( mcr.size() > 0 ) > 456 { > 457 // ここで連続置換 > 458 edit_.getDoc().Execute( mcr ); > 459 // カーソル移動 > 460 e.ad = b.ad + ulen; > 461 edit_.getCursor().MoveCur( e, false ); > 462 // 閉じる? > 463 End( IDOK ); > 464 } > 465 > 466 TCHAR str[255]; > 467 ::wsprintf( str, String(IDS_REPLACEALLDONE).c_str(), mcr.size() ); > 468 MsgBox( str, String(IDS_APPNAME).c_str(), MB_ICONINFORMATION ); > 469 > 470 replStr_.FreeWCMem( ustr ); > 471 }

Added Search.h version [6119f23431c544ed]

> 1 #ifndef AFX_SEARCH_H__201E0D70_9C20_420A_8600_966D2BA23010__INCLUDED_ > 2 #define AFX_SEARCH_H__201E0D70_9C20_420A_8600_966D2BA23010__INCLUDED_ > 3 #include "editwing/editwing.h" > 4 #include "kilib/window.h" > 5 #include "kilib/memory.h" > 6 #include "kilib/ktlaptr.h" > 7 #include "kilib/string.h" > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg Gp.Search //@} > 13 //@{ > 14 // 検索オブジェクト > 15 //@} > 16 //========================================================================= > 17 > 18 class Searchable : public ki::Object > 19 { > 20 public: > 21 //@{ > 22 // 検索を行う > 23 // @param str 対象文字列 > 24 // @param len 対象文字列の長さ > 25 // @param stt 検索開始index。0なら先頭から > 26 // @param mbg マッチ結果の先頭index > 27 // @param med マッチ結果の終端indexの1個後ろ > 28 // @return マッチしたかどうか > 29 // > 30 // 下方向サーチオブジェクトの場合、stt <= *beg の範囲 > 31 // 上方向サーチオブジェクトの場合、*beg <= stt の範囲を検索 > 32 //@} > 33 virtual bool Search( const unicode* str, ulong len, ulong stt, > 34 ulong* mbg, ulong* med ) = 0; > 35 }; > 36 > 37 > 38 > 39 //========================================================================= > 40 //@{ > 41 // 検索管理人 > 42 // > 43 // 前回検索したときのオプションや検索文字列を覚えておくのが > 44 // このクラスの担当。検索・置換ダイアログの表示等もここで > 45 // やるかもしれない。 > 46 //@} > 47 //========================================================================= > 48 > 49 class SearchManager : ki::DlgImpl > 50 { > 51 typedef editwing::DPos DPos; > 52 > 53 public: > 54 //@{ コンストラクタ。特記事項無し //@} > 55 SearchManager( ki::Window& w, editwing::EwEdit& e ); > 56 > 57 //@{ デストラクタ。特記事項無し //@} > 58 ~SearchManager(); > 59 > 60 //@{ 検索ダイアログ表示 //@} > 61 void ShowDlg(); > 62 > 63 //@{ [次を検索]コマンド //@} > 64 void FindNext(); > 65 > 66 //@{ [前を検索]コマンド //@} > 67 void FindPrev(); > 68 > 69 //@{ 今すぐ検索可能か? //@} > 70 bool isReady() const > 71 { return searcher_.isValid(); } > 72 > 73 //@{ 設定Save //@} > 74 void SaveToINI( ki::IniFile& ini ); > 75 > 76 //@{ 設定Load //@} > 77 void LoadFromINI( ki::IniFile& ini ); > 78 > 79 //@{ 苦肉の策^^; //@} > 80 bool TrapMsg(MSG* msg); > 81 > 82 //@{ 見つかりませんでしたダイアログ //@} > 83 void NotFound(); > 84 > 85 private: > 86 > 87 //@{ [置換]コマンド //@} > 88 void ReplaceImpl(); > 89 > 90 //@{ [全置換]コマンド //@} > 91 void ReplaceAllImpl(); > 92 > 93 private: > 94 > 95 virtual void on_init(); > 96 virtual void on_destroy(); > 97 virtual bool on_command( UINT cmd, UINT id, HWND ctrl ); > 98 void on_findnext(); > 99 void on_findprev(); > 100 void on_replacenext(); > 101 void on_replaceall(); > 102 void UpdateData(); > 103 void ConstructSearcher( bool down=true ); > 104 void FindNextImpl(); > 105 void FindPrevImpl(); > 106 bool FindNextFromImpl( DPos s, DPos* beg, DPos* end ); > 107 bool FindPrevFromImpl( DPos s, DPos* beg, DPos* end ); > 108 > 109 private: > 110 editwing::EwEdit& edit_; > 111 ki::dptr<Searchable> searcher_; > 112 ki::Window& mainWnd_; > 113 > 114 bool bIgnoreCase_; // 大文字小文字を同一視? > 115 bool bRegExp_; // 正規表現? > 116 bool bDownSearch_; // 検索方向 > 117 bool bChanged_; // 前回のsearcher構築時から変更があったらtrue > 118 > 119 ki::String findStr_; > 120 ki::String replStr_; > 121 > 122 private: > 123 NOCOPY(SearchManager); > 124 }; > 125 > 126 > 127 > 128 //========================================================================= > 129 > 130 #endif // AFX_SEARCH_H__201E0D70_9C20_420A_8600_966D2BA23010__INCLUDED_

Added editwing/editwing.h version [cb99f56b2add4e68]

> 1 #ifndef _EDITWING_H_ > 2 #define _EDITWING_H_ > 3 > 4 > 5 > 6 #include "ewCommon.h" > 7 #include "ewCtrl1.h" > 8 > 9 > 10 > 11 #endif // _EDITWING_H_

Added editwing/ewCommon.h version [629245f9abbd51b3]

> 1 #ifndef _EDITWING_COMMON_H_ > 2 #define _EDITWING_COMMON_H_ > 3 #include "../kilib/kilib.h" > 4 #ifndef __ccdoc__ > 5 namespace editwing { > 6 #endif > 7 > 8 > 9 //========================================================================= > 10 // Unicode関係 > 11 //========================================================================= > 12 > 13 inline bool isHighSurrogate(unicode ch) > 14 { > 15 return (0xD800 <= ch && ch <= 0xDBFF); > 16 } > 17 > 18 inline bool isLowSurrogate(unicode ch) > 19 { > 20 return (0xDC00 <= ch && ch <= 0xDFFF); > 21 } > 22 > 23 //========================================================================= > 24 //@{ @pkg editwing.Common //@} > 25 //@{ > 26 // テキスト中の位置情報 > 27 //@} > 28 //========================================================================= > 29 > 30 struct DPos : public ki::Object > 31 { > 32 //@{ バッファ中のアドレス (0〜 ) //@} > 33 ulong ad; > 34 > 35 //@{ 論理行番号 (0〜 ) //@} > 36 ulong tl; > 37 > 38 bool operator == ( const DPos& r ) const > 39 { return (tl==r.tl && ad==r.ad); } > 40 bool operator != ( const DPos& r ) const > 41 { return (tl!=r.tl || ad!=r.ad); } > 42 bool operator < ( const DPos& r ) const > 43 { return (tl<r.tl || (tl==r.tl && ad<r.ad)); } > 44 bool operator > ( const DPos& r ) const > 45 { return (tl>r.tl || (tl==r.tl && ad>r.ad)); } > 46 bool operator <= ( const DPos& r ) const > 47 { return (tl<r.tl || (tl==r.tl && ad<=r.ad)); } > 48 bool operator >= ( const DPos& r ) const > 49 { return (tl>r.tl || (tl==r.tl && ad>=r.ad)); } > 50 > 51 DPos( ulong t, ulong a ) : tl(t), ad(a) {} > 52 DPos() {} > 53 }; > 54 > 55 > 56 > 57 //========================================================================= > 58 //@{ > 59 // 特殊文字を表す定数値 > 60 //@} > 61 //========================================================================= > 62 > 63 enum SpecialChars > 64 { > 65 scEOF = 0, // EOF > 66 scEOL = 1, // 改行 > 67 scTAB = 2, // タブ > 68 scHSP = 3, // 半角スペース > 69 scZSP = 4 // 全角スペース > 70 }; > 71 > 72 > 73 > 74 //========================================================================= > 75 //@{ > 76 // 単語の種類を表す定数値 > 77 //@} > 78 //========================================================================= > 79 > 80 enum TokenType > 81 { > 82 TAB = 0x00, // Tab > 83 WSP = 0x04, // 半角スペース > 84 ALP = 0x08, // 普通の字 > 85 CE = 0x0c, // コメント終了タグ > 86 CB = 0x10, // コメント開始タグ > 87 LB = 0x14, // 行コメント開始タグ > 88 Q1 = 0x18, // 単一引用符 > 89 Q2 = 0x1c // 二重引用符 > 90 }; > 91 > 92 > 93 > 94 //========================================================================= > 95 //@{ > 96 // 色指定箇所を表す定数値 > 97 //@} > 98 //========================================================================= > 99 > 100 enum ColorType > 101 { > 102 TXT = 0, // 文字色 > 103 CMT = 1, // コメント文字色 > 104 KWD = 2, // キーワード文字色 > 105 // = 3, // ( コメントアウトされたキーワード文字色 ) > 106 CTL = 4, // 特殊文字色 > 107 BG = 5, // 背景色 > 108 LN = 6 // 行番号 > 109 }; > 110 > 111 > 112 > 113 //========================================================================= > 114 //@{ > 115 // 折り返し位置を示す定数値 > 116 //@} > 117 //========================================================================= > 118 > 119 enum WrapType > 120 { > 121 NOWRAP = -1, // 折り返し無し > 122 RIGHTEDGE = 0 // 右端 > 123 }; > 124 > 125 > 126 > 127 //========================================================================= > 128 //@{ > 129 // 表示設定 > 130 // > 131 // フォント・色・タブ幅・特殊文字の表示、の情報を保持。 > 132 // ただし、強調単語の指定は Document に対して行う。 > 133 //@} > 134 //========================================================================= > 135 > 136 struct VConfig : public ki::Object > 137 { > 138 //@{ フォント //@} > 139 LOGFONT font; > 140 int fontsize; > 141 > 142 //@{ タブ幅文字数 //@} > 143 int tabstep; > 144 > 145 //@{ 色 //@} > 146 COLORREF color[7]; > 147 > 148 //@{ 特殊文字表示 //@} > 149 bool sc[5]; > 150 > 151 //@{ 危険なデフォルトコンストラクタ //@} > 152 VConfig() {} > 153 > 154 //@{ フォント関係初期化 //@} > 155 VConfig( const TCHAR* fnam, int fsiz ) > 156 { > 157 SetFont( fnam,fsiz ); > 158 tabstep = 4; > 159 color[TXT] = > 160 color[CMT] = > 161 color[KWD] = > 162 color[CTL] = RGB(0,0,0); > 163 color[ BG] = RGB(255,255,255); > 164 color[ LN] = RGB(0,0,0);//255,255,0); > 165 sc[scEOF] = > 166 sc[scEOL] = > 167 sc[scTAB] = > 168 sc[scHSP] = > 169 sc[scZSP] = false; > 170 } > 171 > 172 //@{ フォント関係設定 //@} > 173 void SetFont( const TCHAR* fnam, int fsiz ) > 174 { > 175 fontsize = fsiz; > 176 font.lfWidth = 0; > 177 font.lfEscapement = 0; > 178 font.lfOrientation = 0; > 179 font.lfWeight = FW_DONTCARE; > 180 font.lfItalic = FALSE; > 181 font.lfUnderline = FALSE; > 182 font.lfStrikeOut = FALSE; > 183 font.lfOutPrecision = OUT_DEFAULT_PRECIS; > 184 font.lfClipPrecision = CLIP_DEFAULT_PRECIS; > 185 font.lfQuality = DEFAULT_QUALITY; > 186 font.lfPitchAndFamily = VARIABLE_PITCH|FF_DONTCARE; > 187 font.lfCharSet = DEFAULT_CHARSET; > 188 > 189 ::lstrcpy( font.lfFaceName, fnam ); > 190 > 191 HDC h = ::GetDC( NULL ); > 192 font.lfHeight = -MulDiv(fsiz, ::GetDeviceCaps(h,LOGPIXELSY), 72) > 193 ::ReleaseDC( NULL, h ); > 194 } > 195 > 196 //@{ タブ幅設定 //@} > 197 void SetTabStep( int tab ) > 198 { > 199 tabstep = Max( 1, tab ); > 200 } > 201 }; > 202 > 203 > 204 > 205 //========================================================================= > 206 > 207 } // namespace editwing > 208 #endif // _EDITWING_COMMON_H_

Added editwing/ewCtrl1.h version [3cf45a69ba982b03]

> 1 #ifndef _EDITWING_CTRL1_H_ > 2 #define _EDITWING_CTRL1_H_ > 3 #include "ewDoc.h" > 4 #include "ewView.h" > 5 #ifndef __ccdoc__ > 6 namespace editwing { > 7 #endif > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg editwing.Ctrl //@} > 13 //@{ > 14 // 簡単なエディットコントロール > 15 // > 16 // とりあえず字が表示できて色が変えられてカーソルが動かせて… > 17 // という、Doc/Viewの基本機能をそのまま使った形のもの。 > 18 // ウインドウ分割対応版とかもそのうち作るかもしれない。 > 19 //@} > 20 //========================================================================= > 21 > 22 class EwEdit : public ki::WndImpl > 23 { > 24 public: > 25 > 26 EwEdit(); > 27 ~EwEdit(); > 28 > 29 public: > 30 > 31 //@{ 文書データ操作 //@} > 32 doc::Document& getDoc() { return *doc_; } > 33 > 34 //@{ 表示機能操作 //@} > 35 view::View& getView() { return *view_; } > 36 > 37 //@{ カーソル機能操作 //@} > 38 view::Cursor& getCursor() { return view_->cur(); } > 39 > 40 private: > 41 > 42 ki::dptr<doc::Document> doc_; > 43 ki::dptr<view::View> view_; > 44 static ClsName className_; > 45 > 46 private: > 47 > 48 void on_create( CREATESTRUCT* cs ); > 49 void on_destroy(); > 50 LRESULT on_message( UINT msg, WPARAM wp, LPARAM lp ); > 51 }; > 52 > 53 > 54 > 55 //========================================================================= > 56 > 57 } // namespace editwing > 58 #endif // _EDITWING_CTRL1_H_

Added editwing/ewDoc.h version [f62bdbf2e74c7d8b]

> 1 #ifndef _EDITWING_DOC_H_ > 2 #define _EDITWING_DOC_H_ > 3 #include "ewCommon.h" > 4 #ifndef __ccdoc__ > 5 namespace editwing { > 6 namespace doc { > 7 #endif > 8 > 9 > 10 > 11 class DocImpl; > 12 class DocEvHandler; > 13 class Command; > 14 class Insert; > 15 class Delete; > 16 class Replace; > 17 > 18 > 19 > 20 //========================================================================= > 21 //@{ @pkg editwing.Doc //@} > 22 //@{ > 23 // 文書データ > 24 // > 25 // このクラスは単なるインターフェイスで、内部実装は > 26 // class DocImpl で行う。ので、詳しくはそちらを参照のこと。 > 27 //@} > 28 //========================================================================= > 29 > 30 class Document : public ki::Object > 31 { > 32 public: > 33 > 34 //@{ 何もしないコンストラクタ //@} > 35 Document(); > 36 ~Document(); > 37 > 38 //@{ ファイルを開く //@} > 39 void OpenFile( ki::aptr<ki::TextFileR> tf ); > 40 > 41 //@{ ファイルを保存 //@} > 42 void SaveFile( ki::TextFileW& tf ); > 43 > 44 //@{ 内容破棄 //@} > 45 void ClearAll(); > 46 > 47 //@{ 操作コマンド実行 //@} > 48 void Execute( const Command& cmd ); > 49 > 50 //@{ アンドゥ //@] > 51 void Undo(); > 52 > 53 //@{ リドゥ //@] > 54 void Redo(); > 55 > 56 //@{ アンドゥ回数制限 //@] > 57 void SetUndoLimit( long lim ); > 58 > 59 //@{ 変更フラグをクリア //@} > 60 void ClearModifyFlag(); > 61 > 62 //@{ イベントハンドラ登録 //@} > 63 void AddHandler( DocEvHandler* eh ); > 64 > 65 //@{ イベントハンドラ解除 //@} > 66 void DelHandler( DocEvHandler* eh ); > 67 > 68 //@{ キーワード定義切り替え //@} > 69 void SetKeyword( const unicode* defbuf, ulong siz=0 ); > 70 > 71 public: > 72 > 73 //@{ 内部実装クラス //@} > 74 DocImpl& impl() { return *impl_; } > 75 > 76 //@{ 行数 //@} > 77 ulong tln() const; > 78 > 79 //@{ 行バッファ //@} > 80 const unicode* tl( ulong i ) const; > 81 > 82 //@{ 行文字数 //@} > 83 ulong len( ulong i ) const; > 84 > 85 //@{ 指定範囲のテキストの長さ //@} > 86 ulong getRangeLength( const DPos& stt, const DPos& end ) const; > 87 > 88 //@{ 指定範囲のテキスト //@} > 89 void getText( unicode* buf, const DPos& stt, const DPos& end ) const; > 90 > 91 //@{ アンドゥ可能? //@} > 92 bool isUndoAble() const; > 93 > 94 //@{ リドゥ可能? //@} > 95 bool isRedoAble() const; > 96 > 97 //@{ 変更済み? //@} > 98 bool isModified() const; > 99 > 100 //@{ ビジーフラグ(マクロコマンド実行中のみ成立) //@} > 101 void setBusyFlag( bool b=true ) { busy_ = b; } > 102 bool isBusy() const { return busy_; } > 103 > 104 private: > 105 > 106 // 実装 > 107 ki::dptr<DocImpl> impl_; > 108 bool busy_; > 109 > 110 private: > 111 > 112 NOCOPY(Document); > 113 }; > 114 > 115 > 116 > 117 //========================================================================= > 118 //@{ > 119 // イベントハンドラインターフェイス > 120 // > 121 // ドキュメントから発生するイベント(挿入/削除などなど…)を > 122 // 受け取りたい場合は、このインターフェイスを継承し、適宜ハンドラを > 123 // 書くこと。Viewの再描画処理などもこれを通じて実行されている。 > 124 //@} > 125 //========================================================================= > 126 > 127 class DocEvHandler > 128 { > 129 public: > 130 //@{ > 131 // テキスト内容が変更されたときに発生 > 132 // @param s 変更範囲の先頭 > 133 // @param e 変更範囲の終端(前) > 134 // @param e2 変更範囲の終端(後) > 135 // @param reparsed e2より後ろのコメントアウト状態が変化していたらtrue > 136 // @param nmlcmd 挿入/削除/置換ならtrue、ファイル開き/全置換ならfalse > 137 //@} > 138 virtual void on_text_update( const DPos& s, > 139 const DPos& e, const DPos& e2, bool reparsed, bool nmlcmd ) {} > 140 > 141 //@{ > 142 // キーワードが変更されたときに発生 > 143 //@} > 144 virtual void on_keyword_change() {} > 145 > 146 //@{ > 147 // ダーティフラグが変更されたときに発生 > 148 //@} > 149 virtual void on_dirtyflag_change( bool dirty ) {} > 150 }; > 151 > 152 > 153 > 154 //========================================================================= > 155 //@{ > 156 // 操作コマンドインターフェイス > 157 // > 158 // ドキュメントは、Command から派生したクラスのインスタンスの > 159 // operator() を呼び出すことで、色々な操作を実行する。とりあえず > 160 // 具体的には Insert/Delete/Replace の3つだけ。あとでマクロコマンド用 > 161 // クラスも作るつもりだけど、とりあえずは保留。 > 162 //@} > 163 //========================================================================= > 164 > 165 class Command : public ki::Object > 166 { > 167 protected: > 168 friend class UnReDoChain; > 169 friend class MacroCommand; > 170 virtual Command* operator()( Document& doc ) const = 0; > 171 }; > 172 > 173 > 174 > 175 //========================================================================= > 176 //@{ > 177 // 挿入コマンド > 178 //@} > 179 //========================================================================= > 180 > 181 class Insert : public Command > 182 { > 183 public: > 184 > 185 //@{ > 186 // @param s 挿入位置 > 187 // @param str 挿入文字列 > 188 // @param len 文字列の長さ > 189 // @param del コマンド終了時にdelete [] strしてよいか? > 190 //@} > 191 Insert( const DPos& s, const unicode* str, ulong len, bool del=false ); > 192 ~Insert(); > 193 > 194 private: > 195 > 196 Command* operator()( Document& doc ) const; > 197 DPos stt_; > 198 const unicode* buf_; > 199 ulong len_; > 200 bool del_; > 201 }; > 202 > 203 > 204 > 205 //========================================================================= > 206 //@{ > 207 // 削除コマンド > 208 //@} > 209 //========================================================================= > 210 > 211 class Delete : public Command > 212 { > 213 public: > 214 > 215 //@{ > 216 // @param s 開始位置 > 217 // @param e 終端位置 > 218 //@} > 219 Delete( const DPos& s, const DPos& e ); > 220 > 221 private: > 222 > 223 Command* operator()( Document& doc ) const; > 224 DPos stt_; > 225 DPos end_; > 226 }; > 227 > 228 > 229 > 230 > 231 //========================================================================= > 232 //@{ > 233 // 置換コマンド > 234 //@} > 235 //========================================================================= > 236 > 237 class Replace : public Command > 238 { > 239 public: > 240 > 241 //@{ > 242 // @param s 開始位置 > 243 // @param e 終端位置 > 244 // @param str 挿入文字列 > 245 // @param len 文字列の長さ > 246 // @param del コマンド終了時にdelete [] strしてよいか? > 247 //@} > 248 Replace( const DPos& s, const DPos& e, > 249 const unicode* str, ulong len, bool del=false ); > 250 ~Replace(); > 251 > 252 private: > 253 > 254 Command* operator()( Document& doc ) const; > 255 DPos stt_; > 256 DPos end_; > 257 const unicode* buf_; > 258 ulong len_; > 259 bool del_; > 260 }; > 261 > 262 > 263 > 264 //========================================================================= > 265 //@{ > 266 // マクロコマンド > 267 // > 268 // 複数のコマンドを一つのコマンドとして連続実行する。 > 269 // ただし、Insert/Delete/Replaceを一回行うたびに当然 > 270 // 文字列の位置は変化するのだが、それに関する変換処理は > 271 // 行わない。すなわち、Insert->Delete->Insert みたいな > 272 // 連続処理を書くときは、行数や文字数の変化を考慮しながら > 273 // 値を定めていくことが必要になる。ので、あんまり使えない(^^; > 274 //@} > 275 //========================================================================= > 276 > 277 class MacroCommand : public Command > 278 { > 279 public: > 280 //@{ コマンドの追加 //@} > 281 void Add( Command* cmd ) { arr_.Add(cmd); } > 282 > 283 //@{ コマンド数 //@} > 284 ulong size() const { return arr_.size(); } > 285 > 286 //@ デストラクタ //@} > 287 ~MacroCommand() > 288 { > 289 for( ulong i=0,e=arr_.size(); i<e; ++i ) > 290 delete arr_[i]; > 291 } > 292 > 293 private: > 294 Command* operator()( Document& doc ) const; > 295 ki::storage<Command*> arr_; > 296 }; > 297 > 298 > 299 > 300 //========================================================================= > 301 > 302 }} // namespace editwing::document > 303 #endif // _EDITWING_DOC_H_

Added editwing/ewView.h version [bfa35c0d3f9f6f41]

> 1 #ifndef _EDITWING_VIEW_H_ > 2 #define _EDITWING_VIEW_H_ > 3 #include "ewCommon.h" > 4 #include "ewDoc.h" > 5 #ifndef __ccdoc__ > 6 namespace editwing { > 7 namespace view { > 8 #endif > 9 > 10 > 11 > 12 class Canvas; > 13 class ViewImpl; > 14 class Cursor; > 15 class Caret; > 16 > 17 > 18 > 19 //========================================================================= > 20 //@{ @pkg editwing.View //@} > 21 //@{ > 22 // 描画処理など > 23 // > 24 // このクラスでは、メッセージの分配を行うだけで、実装は > 25 // Canvas/ViewImpl 等で行う。ので、詳しくはそちらを参照のこと。 > 26 //@} > 27 //========================================================================= > 28 > 29 class View : public ki::WndImpl, public doc::DocEvHandler > 30 { > 31 public: > 32 > 33 //@{ 何もしないコンストラクタ //@} > 34 View( doc::Document& d, HWND wnd ); > 35 ~View(); > 36 > 37 //@{ 折り返し方式切替 //@} > 38 void SetWrapType( int wt ); > 39 > 40 //@{ 行番号表示/非表示切替 //@} > 41 void ShowLineNo( bool show ); > 42 > 43 //@{ 表示色・フォント切替 //@} > 44 void SetFont( const VConfig& vc ); > 45 > 46 //@{ 内部実装 //@} > 47 ViewImpl& impl() { return *impl_; } > 48 > 49 //@{ カーソル //@} > 50 Cursor& cur(); > 51 > 52 private: > 53 > 54 doc::DocImpl& doc_; > 55 ki::dptr<ViewImpl> impl_; > 56 static ClsName className_; > 57 > 58 private: > 59 > 60 void on_create( CREATESTRUCT* cs ); > 61 void on_destroy(); > 62 LRESULT on_message( UINT msg, WPARAM wp, LPARAM lp ); > 63 void on_text_update( const DPos& s, const DPos& e, const DPos& e2, bo > 64 void on_keyword_change(); > 65 }; > 66 > 67 > 68 > 69 //========================================================================= > 70 //@{ > 71 // イベントハンドラインターフェイス > 72 // > 73 // カーソルから発生するイベント色々を > 74 //@} > 75 //========================================================================= > 76 > 77 class CurEvHandler > 78 { > 79 friend class Cursor; > 80 virtual void on_move( const DPos& c, const DPos& s ) {} > 81 virtual void on_char( Cursor& cur, unicode wch ); > 82 virtual void on_key( Cursor& cur, int vk, bool sft, bool ctl ); > 83 virtual void on_ime( Cursor& cur, unicode* str, ulong len ); > 84 }; > 85 > 86 > 87 > 88 //========================================================================= > 89 //@{ > 90 // 表示位置情報まで含めたDPos > 91 //@} > 92 //========================================================================= > 93 > 94 struct VPos : public DPos > 95 { > 96 ulong vl; // VLine-Index > 97 ulong rl; // RLine-Index > 98 int vx; // スクロールを考慮しない仮想スクリーン上のx座標(pixel) > 99 int rx; // 文字の並びに左右されてないx座標(pixel) > 100 // == 長い行のしっぽから短い行に [↑] で移動して > 101 // == その後 [↓] で戻れるようなアレです。 > 102 void operator=( const DPos& dp ) { tl=dp.tl, ad=dp.ad; } > 103 > 104 VPos(bool) : DPos(0,0),vl(0),rl(0),vx(0),rx(0) {} > 105 VPos() {} > 106 }; > 107 > 108 > 109 > 110 //========================================================================= > 111 //@{ > 112 // カーソル > 113 //@} > 114 //========================================================================= > 115 > 116 class Cursor : public ki::Object > 117 { > 118 public: > 119 > 120 // 初期化とか > 121 Cursor( HWND wnd, ViewImpl& vw, doc::DocImpl& dc ); > 122 ~Cursor(); > 123 void AddHandler( CurEvHandler* ev ); > 124 void DelHandler( CurEvHandler* ev ); > 125 > 126 // カーソル移動 > 127 void MoveCur( const DPos& dp, bool select ); > 128 > 129 // キーによるカーソル移動 > 130 void Left( bool wide, bool select ); > 131 void Right( bool wide, bool select ); > 132 void Up( bool wide, bool select ); > 133 void Down( bool wide, bool select ); > 134 void Home( bool wide, bool select ); > 135 void End( bool wide, bool select ); > 136 void PageUp( bool select ); > 137 void PageDown( bool select ); > 138 > 139 // テキスト書き換え > 140 void Input( const unicode* str, ulong len ); > 141 void Input( const char* str, ulong len ); > 142 void InputChar( unicode ch ); > 143 void Del(); > 144 void DelBack(); > 145 > 146 // クリップボード > 147 void Cut(); > 148 void Copy(); > 149 void Paste(); > 150 > 151 // 選択テキスト取得 > 152 ki::aarr<unicode> getSelectedStr() const; > 153 > 154 // モード切替 > 155 void SetInsMode( bool bIns ); > 156 void SetROMode( bool bRO ); > 157 > 158 public: > 159 > 160 bool isInsMode() const; > 161 bool isROMode() const; > 162 bool isSelected() const; > 163 bool getCurPos( const VPos** start, const VPos** end ) const; > 164 void ResetPos(); > 165 void on_scroll_begin(); > 166 void on_scroll_end(); > 167 void on_text_update( const DPos& s, const DPos& e, const DPos& e2, bool > 168 void on_setfocus(); > 169 void on_killfocus(); > 170 void on_keydown( int vk, LPARAM flag ); > 171 void on_char( TCHAR ch ); > 172 void on_ime_composition( LPARAM lp ); > 173 void on_lbutton_down( short x, short y, bool shift ); > 174 void on_mouse_move( short x, short y ); > 175 void on_lbutton_up( short x, short y ); > 176 void on_lbutton_dbl( short x, short y ); > 177 bool on_contextmenu( short x, short y ); > 178 void on_timer(); > 179 int on_ime_reconvertstring( RECONVERTSTRING* rs ); > 180 bool on_ime_confirmreconvertstring( RECONVERTSTRING* rs ); > 181 > 182 private: > 183 > 184 doc::DocImpl& doc_; > 185 ViewImpl& view_; > 186 CurEvHandler* pEvHan_; > 187 ki::dptr<Caret> caret_; > 188 > 189 VPos cur_; // カーソル位置 > 190 VPos sel_; // 選択時の軸足位置 > 191 bool bIns_; // 挿入モード? > 192 bool bRO_; // 読取専用? > 193 > 194 UINT_PTR timerID_;// マウスドラッグ制御用の > 195 int keyRepTime_; // タイマー関係 > 196 int dragX_; // 位置 > 197 int dragY_; // 位置 > 198 bool lineSelectMode_; // 行選択モード? > 199 > 200 CurEvHandler defaultHandler_; > 201 > 202 private: > 203 > 204 void MoveByMouse( int x, int y ); > 205 void MoveTo( const VPos& vp, bool sel ); > 206 void Ud( int dy, bool select ); > 207 void UpdateCaretPos(); > 208 void Redraw( const VPos& s, const VPos& e ); > 209 }; > 210 > 211 > 212 > 213 //------------------------------------------------------------------------- > 214 > 215 inline bool Cursor::isSelected() const > 216 { return cur_!=sel_; } > 217 > 218 inline bool Cursor::isInsMode() const > 219 { return bIns_; } > 220 > 221 inline bool Cursor::isROMode() const > 222 { return bRO_; } > 223 > 224 > 225 > 226 //========================================================================= > 227 > 228 }} // namespace editwing::view > 229 #endif // _EDITWING_VIEW_H_

Added editwing/ip_ctrl1.cpp version [3bc18713fe7f8f93]

> 1 #include "stdafx.h" > 2 #include "ewCtrl1.h" > 3 using namespace ki; > 4 using namespace editwing; > 5 > 6 > 7 > 8 //------------------------------------------------------------------------- > 9 // EwEditコントロール作成/破棄 > 10 //------------------------------------------------------------------------- > 11 > 12 EwEdit::ClsName EwEdit::className_ = TEXT("EditWing Control-01"); > 13 > 14 EwEdit::EwEdit() > 15 : WndImpl( className_, WS_CHILD|WS_VISIBLE, WS_EX_CLIENTEDGE ) > 16 { > 17 static bool ClassRegistered = false; > 18 if( !ClassRegistered ) > 19 { > 20 ClassRegistered = true; > 21 > 22 // 初回構築時のみ、クラス登録を行う > 23 WNDCLASSEX wc = {0}; > 24 wc.lpszClassName = className_; > 25 WndImpl::Register( &wc ); > 26 } > 27 } > 28 > 29 EwEdit::~EwEdit() > 30 { > 31 Destroy(); > 32 } > 33 > 34 void EwEdit::on_create( CREATESTRUCT* cs ) > 35 { > 36 doc_ = new doc::Document; > 37 view_ = new view::View( *doc_, hwnd() ); > 38 } > 39 > 40 void EwEdit::on_destroy() > 41 { > 42 view_ = NULL; > 43 doc_ = NULL; > 44 } > 45 > 46 > 47 > 48 //------------------------------------------------------------------------- > 49 // 簡単なメッセージ制御 > 50 //------------------------------------------------------------------------- > 51 > 52 LRESULT EwEdit::on_message( UINT msg, WPARAM wp, LPARAM lp ) > 53 { > 54 switch( msg ) > 55 { > 56 case WM_SETFOCUS: > 57 { > 58 view_->SetFocus(); > 59 break; > 60 } > 61 case WM_SIZE: > 62 { > 63 RECT rc; > 64 getClientRect( &rc ); > 65 view_->MoveTo( 0, 0, rc.right, rc.bottom ); > 66 break; > 67 } > 68 case EM_CANUNDO: return getDoc().isUndoAble(); > 69 case EM_SETREADONLY: getCursor().SetROMode(wp!=FALSE); return TRUE; > 70 case WM_COPY: getCursor().Copy(); return 0; > 71 case WM_CUT: getCursor().Cut(); return 0; > 72 case WM_PASTE: getCursor().Paste(); return 0; > 73 case EM_UNDO: > 74 case WM_UNDO: getDoc().Undo(); return TRUE; > 75 default: > 76 return WndImpl::on_message( msg, wp, lp ); > 77 } > 78 return 0; > 79 /* > 80 EM_CHARFROMPOS > 81 EM_EMPTYUNDOBUFFER: > 82 EM_FMTLINES > 83 EM_GETCUEBANNER > 84 EM_GETFIRSTVISIBLELINE > 85 EM_GETHANDLE > 86 EM_GETIMESTATUS > 87 EM_GETLIMITTEXT > 88 EM_GETLINE > 89 EM_GETLINECOUNT > 90 EM_GETMARGINS > 91 EM_GETMODIFY > 92 EM_GETPASSWORDCHAR > 93 EM_GETRECT > 94 EM_GETSEL > 95 EM_GETTHUMB > 96 EM_GETWORDBREAKPROC > 97 EM_HIDEBALLOONTIP > 98 EM_LIMITTEXT > 99 EM_LINEFROMCHAR > 100 EM_LINEINDEX > 101 EM_LINELENGTH > 102 EM_LINESCROLL > 103 EM_POSFROMCHAR > 104 EM_REPLACESEL > 105 EM_SCROLL > 106 EM_SCROLLCARET > 107 EM_SETCUEBANNER > 108 EM_SETHANDLE > 109 EM_SETIMESTATUS > 110 EM_SETLIMITTEXT > 111 EM_SETMARGINS > 112 EM_SETMODIFY > 113 EM_SETPASSWORDCHAR > 114 EM_SETRECT > 115 EM_SETRECTNP > 116 EM_SETSEL > 117 EM_SETTABSTOPS > 118 EM_SETWORDBREAKPROC > 119 EM_SHOWBALLOONTIP > 120 WM_COMMAND > 121 WM_CTLCOLOREDIT > 122 WM_CTLCOLORSTATIC > 123 */ > 124 }

Added editwing/ip_cursor.cpp version [4947f4ab7f00d23b]

> 1 #include "stdafx.h" > 2 #include "ip_view.h" > 3 using namespace editwing; > 4 using namespace editwing::view; > 5 using doc::Insert; > 6 using doc::Delete; > 7 using doc::Replace; > 8 > 9 > 10 > 11 //========================================================================= > 12 //---- ip_cursor.cpp カーソルコントロール > 13 // > 14 // カレットを表示したりIMEに適当に対応したり色々。 > 15 // ところで疑問なのだが Caret って「カレット」と > 16 // 読むのか「キャレット」と読むのか? > 17 // > 18 //---- ip_text.cpp 文字列操作・他 > 19 //---- ip_parse.cpp キーワード解析 > 20 //---- ip_wrap.cpp 折り返し > 21 //---- ip_scroll.cpp スクロール > 22 //---- ip_draw.cpp 描画・他 > 23 //========================================================================= > 24 > 25 > 26 > 27 //------------------------------------------------------------------------- > 28 // Caret制御用ラッパー > 29 //------------------------------------------------------------------------- > 30 > 31 class editwing::view::Caret : public Object > 32 { > 33 public: > 34 > 35 Caret( HWND wnd ) > 36 : hwnd_( wnd ), created_( false ) {} > 37 > 38 ~Caret() > 39 { Destroy(); } > 40 > 41 void Show() > 42 { if( created_ ) ::ShowCaret( hwnd_ ); } > 43 > 44 void Hide() > 45 { if( created_ ) ::HideCaret( hwnd_ ); } > 46 > 47 void Destroy() > 48 { if( created_ ) ::DestroyCaret(), created_=false; } > 49 > 50 void SetPos( int x, int y ) > 51 { if( created_ ) ::SetCaretPos(x,y), ime().SetPos(hwnd_,x,y); } > 52 > 53 void Create( int H, int W, const LOGFONT& lf ) > 54 { > 55 if( created_ ) > 56 ::DestroyCaret(); > 57 created_ = true; > 58 ::CreateCaret( hwnd_, NULL, W, H ); > 59 ime().SetFont( hwnd_, lf ); > 60 Show(); > 61 } > 62 > 63 bool isAlive() > 64 { return created_; } > 65 > 66 HWND hwnd() > 67 { return hwnd_; } > 68 > 69 private: > 70 > 71 const HWND hwnd_; > 72 bool created_; > 73 }; > 74 > 75 > 76 > 77 //------------------------------------------------------------------------- > 78 // カーソル初期化 > 79 //------------------------------------------------------------------------- > 80 > 81 Cursor::Cursor( HWND wnd, ViewImpl& vw, doc::DocImpl& dc ) > 82 : view_ ( vw ) > 83 , doc_ ( dc ) > 84 , pEvHan_ ( &defaultHandler_ ) > 85 , caret_ ( new Caret(wnd) ) > 86 , bIns_ ( true ) > 87 , bRO_ ( false ) > 88 , timerID_( 0 ) > 89 , lineSelectMode_( false ) > 90 { > 91 // てきとーに情報初期化 > 92 ::SystemParametersInfo( SPI_GETKEYBOARDSPEED, 0, &keyRepTime_, 0 ); > 93 cur_.tl = cur_.ad = cur_.vl = cur_.rl = 0; > 94 cur_.vx = cur_.rx = 0; sel_ = cur_; > 95 } > 96 > 97 Cursor::~Cursor() > 98 { > 99 } > 100 > 101 void Cursor::AddHandler( CurEvHandler* ev ) > 102 { > 103 pEvHan_ = ev; > 104 } > 105 > 106 void Cursor::DelHandler( CurEvHandler* ev ) > 107 { > 108 if( ev == pEvHan_ ) > 109 pEvHan_ = &defaultHandler_; > 110 } > 111 > 112 > 113 > 114 //------------------------------------------------------------------------- > 115 // ヘルパー関数群 > 116 //------------------------------------------------------------------------- > 117 > 118 void Cursor::UpdateCaretPos() > 119 { > 120 // メンバ変数の値を元に、実際にCaretを動かす処理 > 121 int x, y; > 122 view_.GetOrigin( &x, &y ); > 123 x += cur_.vx; > 124 y += cur_.vl * view_.fnt().H(); > 125 > 126 // 行番号ゾーンにCaretがあっても困るので左に追いやる > 127 if( 0<x && x<view_.left() ) > 128 x = -view_.left(); > 129 > 130 // セット > 131 caret_->SetPos( x, y ); > 132 pEvHan_->on_move( cur_, sel_ ); > 133 } > 134 > 135 void Cursor::Redraw( const VPos& s, const VPos& e ) > 136 { > 137 int x, y; // 原点 > 138 view_.GetOrigin( &x, &y ); > 139 > 140 POINT sp = {x+s.vx, y+s.vl*view_.fnt().H()}; > 141 POINT ep = {x+e.vx, y+e.vl*view_.fnt().H()}; > 142 if( s > e ) // Swap > 143 sp.x^=ep.x, ep.x^=sp.x, sp.x^=ep.x, > 144 sp.y^=ep.y, ep.y^=sp.y, sp.y^=ep.y; > 145 ep.x+=2; > 146 > 147 // 手抜き16bitチェック入り… > 148 const long LFT = view_.left(); > 149 const long RHT = view_.right(); > 150 const long TOP = 0; > 151 const int BTM = view_.bottom(); > 152 > 153 if( sp.y == ep.y ) > 154 { > 155 RECT rc = { Max(LFT,sp.x), sp.y, Min(RHT,ep.x), sp.y+view_.fnt() > 156 ::InvalidateRect( caret_->hwnd(), &rc, FALSE ); > 157 } > 158 else > 159 { > 160 RECT rc = { Max(LFT,sp.x), Max(TOP,sp.y), RHT, Min<int>(BTM,sp.y > 161 ::InvalidateRect( caret_->hwnd(), &rc, FALSE ); > 162 RECT re = { LFT, Max(TOP,ep.y), Min(RHT,ep.x), Min<int>(BTM,ep.y > 163 ::InvalidateRect( caret_->hwnd(), &re, FALSE ); > 164 RECT rd = { LFT, Max(TOP,rc.bottom), RHT, Min<int>((long)BTM,re. > 165 ::InvalidateRect( caret_->hwnd(), &rd, FALSE ); > 166 } > 167 } > 168 > 169 bool Cursor::getCurPos( const VPos** start, const VPos** end ) const > 170 { > 171 *start = *end = &cur_; > 172 if( cur_==sel_ )//|| !caret_->isAlive() ) > 173 return false; > 174 if( cur_ < sel_ ) > 175 *end = &sel_; > 176 else > 177 *start = &sel_; > 178 return true; > 179 } > 180 > 181 > 182 > 183 > 184 //------------------------------------------------------------------------- > 185 // Viewからの指令を処理 > 186 //------------------------------------------------------------------------- > 187 > 188 void Cursor::on_setfocus() > 189 { > 190 caret_->Create( view_.fnt().H(), > 191 (bIns_ ? 2 : view_.fnt().W()), view_.fnt().LogFont() ); > 192 UpdateCaretPos(); > 193 } > 194 > 195 void Cursor::on_killfocus() > 196 { > 197 caret_->Destroy(); > 198 Redraw( cur_, sel_ ); > 199 } > 200 > 201 void Cursor::on_scroll_begin() > 202 { > 203 caret_->Hide(); > 204 } > 205 > 206 void Cursor::on_scroll_end() > 207 { > 208 UpdateCaretPos(); > 209 caret_->Show(); > 210 } > 211 > 212 void Cursor::ResetPos() > 213 { > 214 // 設定変更などに対応 > 215 view_.ConvDPosToVPos( cur_, &cur_ ); > 216 view_.ConvDPosToVPos( sel_, &sel_ ); > 217 UpdateCaretPos(); > 218 if( caret_->isAlive() ) > 219 view_.ScrollTo( cur_ ); > 220 } > 221 > 222 void Cursor::on_text_update > 223 ( const DPos& s, const DPos& e, const DPos& e2, bool mCur ) > 224 { > 225 VPos* search_base = NULL; > 226 > 227 if( mCur && s==cur_ && e==sel_ ) > 228 { > 229 search_base = &cur_; > 230 } > 231 else if( mCur && s==sel_ && e==cur_ ) > 232 { > 233 search_base = &sel_; > 234 } > 235 else > 236 { > 237 Redraw( cur_, sel_ ); > 238 if( mCur && caret_->isAlive() ) > 239 { > 240 if( cur_ <= s ) > 241 search_base = &cur_; > 242 } > 243 else > 244 { > 245 if( s < cur_ ) > 246 { > 247 if( cur_ <= e ) > 248 cur_ = e2; > 249 else if( cur_.tl == e.tl ) > 250 cur_.tl=e2.tl, cur_.ad=e2.ad+cur_.ad-e.a > 251 else > 252 cur_.tl=e2.tl-e.tl; > 253 view_.ConvDPosToVPos( cur_, &cur_ ); > 254 } > 255 if( s < sel_ ) > 256 sel_ = cur_; > 257 } > 258 } > 259 > 260 if( mCur ) > 261 { > 262 view_.ConvDPosToVPos( e2, &cur_, search_base ); > 263 sel_ = cur_; > 264 if( caret_->isAlive() ) > 265 view_.ScrollTo( cur_ ); > 266 } > 267 UpdateCaretPos(); > 268 } > 269 > 270 > 271 > 272 //------------------------------------------------------------------------- > 273 // キー入力への対応 > 274 //------------------------------------------------------------------------- > 275 > 276 void CurEvHandler::on_char( Cursor& cur, unicode wch ) > 277 { > 278 cur.InputChar( wch ); > 279 } > 280 > 281 void CurEvHandler::on_ime( Cursor& cur, unicode* str, ulong len ) > 282 { > 283 cur.Input( str, len ); > 284 } > 285 > 286 void CurEvHandler::on_key( Cursor& cur, int vk, bool sft, bool ctl ) > 287 { > 288 switch( vk ) > 289 { > 290 case VK_HOME: cur.Home( ctl, sft ); break; > 291 case VK_END: cur.End( ctl, sft ); break; > 292 case VK_RIGHT: cur.Right( ctl, sft ); break; > 293 case VK_LEFT: cur.Left( ctl, sft ); break; > 294 case VK_UP: cur.Up( ctl, sft ); break; > 295 case VK_DOWN: cur.Down( ctl, sft ); break; > 296 case VK_PRIOR: cur.PageUp( sft ); break; > 297 case VK_NEXT: cur.PageDown( sft ); break; > 298 case VK_DELETE: cur.Del(); break; > 299 case VK_BACK: cur.DelBack(); break; > 300 case VK_INSERT: cur.SetInsMode(!cur.isInsMode()); break; > 301 } > 302 } > 303 > 304 void Cursor::on_char( TCHAR ch ) > 305 { > 306 if( !bRO_ && ch!=0x7f > 307 && ((unsigned)ch>=0x20 || ch==TEXT('\r') || ch==TEXT('\t')) ) > 308 { > 309 #ifdef _UNICODE > 310 pEvHan_->on_char( *this, ch ); > 311 #else > 312 unicode wc = ch; > 313 if( ch & 0x80 ) // 非ASCII文字にはトリビアルでない変換が必要 > 314 ::MultiByteToWideChar( CP_ACP, MB_COMPOSITE, &ch, 1, &wc > 315 pEvHan_->on_char( *this, wc ); > 316 #endif > 317 } > 318 } > 319 > 320 void Cursor::on_ime_composition( LPARAM lp ) > 321 { > 322 view_.ScrollTo( cur_ ); > 323 if( !bRO_ && (lp&GCS_RESULTSTR) ) > 324 { > 325 unicode* str; > 326 ulong len; > 327 ime().GetString( caret_->hwnd(), &str, &len ); > 328 if( str ) > 329 { > 330 pEvHan_->on_ime( *this, str, len ); > 331 delete [] str; > 332 } > 333 } > 334 } > 335 > 336 void Cursor::on_keydown( int vk, LPARAM flag ) > 337 { > 338 bool sft = (::GetKeyState(VK_SHIFT)>>15)!=0; > 339 bool ctl = (::GetKeyState(VK_CONTROL)>>15)!=0; > 340 pEvHan_->on_key( *this, vk, sft, ctl ); > 341 } > 342 > 343 > 344 > 345 //------------------------------------------------------------------------- > 346 // モード切替 > 347 //------------------------------------------------------------------------- > 348 > 349 void Cursor::SetInsMode( bool bIns ) > 350 { > 351 bIns_ = bIns; > 352 on_setfocus(); > 353 } > 354 > 355 void Cursor::SetROMode( bool bRO ) > 356 { > 357 bRO_ = bRO; > 358 } > 359 > 360 > 361 > 362 //------------------------------------------------------------------------- > 363 // 文字入力・削除 > 364 //------------------------------------------------------------------------- > 365 > 366 void Cursor::InputChar( unicode ch ) > 367 { > 368 // 「上書モード & 選択状態でない & 行末でない」なら右一文字選択 > 369 if( !bIns_ && cur_==sel_ && doc_.len(cur_.tl)!=cur_.ad ) > 370 Right( false, true ); > 371 > 372 // 入力 > 373 Input( &ch, 1 ); > 374 } > 375 > 376 void Cursor::Input( const unicode* str, ulong len ) > 377 { > 378 if( cur_==sel_ ) > 379 doc_.Execute( Insert( cur_, str, len ) ); > 380 else > 381 doc_.Execute( Replace( cur_, sel_, str, len ) ); > 382 } > 383 > 384 void Cursor::Input( const char* str, ulong len ) > 385 { > 386 unicode* ustr = new unicode[ len*4 ]; > 387 len = ::MultiByteToWideChar( CP_ACP, 0, str, len, ustr, len*4 ); > 388 Input( ustr, len ); > 389 delete [] ustr; > 390 } > 391 > 392 void Cursor::DelBack() > 393 { > 394 // 選択状態なら BackSpace == Delete > 395 // でなければ、 BackSpace == Left + Delete (手抜き > 396 if( cur_ == sel_ ) > 397 { > 398 if( cur_.tl==0 && cur_.ad==0 ) > 399 return; > 400 Left( false, false ); > 401 } > 402 Del(); > 403 } > 404 > 405 void Cursor::Del() > 406 { > 407 // 選択状態なら cur_ 〜 sel_ を削除 > 408 // でなければ、 cur_ 〜 rightOf(cur_) を削除 > 409 DPos dp = (cur_==sel_ ? doc_.rightOf(cur_) : (DPos)sel_ ); > 410 if( cur_ != dp ) > 411 doc_.Execute( Delete( cur_, dp ) ); > 412 } > 413 > 414 > 415 > 416 //------------------------------------------------------------------------- > 417 // テキスト取得 > 418 //------------------------------------------------------------------------- > 419 > 420 ki::aarr<unicode> Cursor::getSelectedStr() const > 421 { > 422 DPos dm=cur_, dM=sel_; > 423 if( cur_ > sel_ ) > 424 dm=sel_, dM=cur_; > 425 > 426 // テキスト取得 > 427 int len = doc_.getRangeLength( dm, dM ); > 428 ki::aarr<unicode> ub( new unicode[len+1] ); > 429 doc_.getText( ub.get(), dm, dM ); > 430 return ub; > 431 } > 432 > 433 //------------------------------------------------------------------------- > 434 // クリップボード処理 > 435 //------------------------------------------------------------------------- > 436 > 437 void Cursor::Cut() > 438 { > 439 if( cur_ != sel_ ) > 440 { > 441 // コピーして削除 > 442 Copy(); > 443 Del(); > 444 } > 445 } > 446 > 447 void Cursor::Copy() > 448 { > 449 Clipboard clp( caret_->hwnd(), false ); > 450 if( cur_==sel_ || !clp.isOpened() ) > 451 return; > 452 > 453 DPos dm=cur_, dM=sel_; > 454 if( cur_ > sel_ ) > 455 dm=sel_, dM=cur_; > 456 > 457 HGLOBAL h; > 458 unicode* p; > 459 int len = doc_.getRangeLength( dm, dM ); > 460 > 461 if( app().isNT() ) > 462 { > 463 // NT系ならそのままダイレクトに > 464 h = ::GlobalAlloc( GMEM_MOVEABLE, (len+1)*2 ); > 465 doc_.getText( static_cast<unicode*>(::GlobalLock(h)), dm, dM ); > 466 ::GlobalUnlock( h ); > 467 clp.SetData( CF_UNICODETEXT, h ); > 468 } > 469 else > 470 { > 471 // 9x系なら変換が必要 > 472 h = ::GlobalAlloc( GMEM_MOVEABLE, (len+1)*3 ); > 473 p = new unicode[len+1]; > 474 doc_.getText( p, dm, dM ); > 475 ::WideCharToMultiByte( CP_ACP, 0, p, -1, > 476 static_cast<char*>(::GlobalLock(h)), (len+1)*3, NULL, NU > 477 ::GlobalUnlock( h ); > 478 clp.SetData( CF_TEXT, h ); > 479 delete [] p; > 480 } > 481 } > 482 > 483 void Cursor::Paste() > 484 { > 485 Clipboard clp( caret_->hwnd(), true ); > 486 if( clp.isOpened() ) > 487 { > 488 Clipboard::Text txt = clp.GetUnicodeText(); > 489 if( txt.data() != NULL ) > 490 doc_.Execute( > 491 Replace( cur_, sel_, txt.data(), my_lstrlenW(txt > 492 ); > 493 } > 494 } > 495 > 496 > 497 > 498 //------------------------------------------------------------------------- > 499 // カーソル移動 > 500 //------------------------------------------------------------------------- > 501 > 502 void Cursor::MoveCur( const DPos& dp, bool select ) > 503 { > 504 VPos vp; > 505 view_.ConvDPosToVPos( dp, &vp ); > 506 MoveTo( vp, select ); > 507 } > 508 > 509 void Cursor::MoveTo( const VPos& vp, bool sel ) > 510 { > 511 if( sel ) > 512 { > 513 // 選択状態が変わる範囲を再描画 > 514 Redraw( vp, cur_ ); > 515 } > 516 else > 517 { > 518 // 選択解除される範囲を再描画 > 519 if( cur_ != sel_ ) > 520 Redraw( cur_, sel_ ); > 521 sel_ = vp; > 522 } > 523 cur_ = vp; > 524 UpdateCaretPos(); > 525 view_.ScrollTo( cur_ ); > 526 } > 527 > 528 void Cursor::Home( bool wide, bool select ) > 529 { > 530 VPos np; > 531 np.ad = np.vx = np.rx = np.rl = 0; > 532 if( wide ) // 文書の頭へ > 533 np.tl = np.vl = 0; > 534 else // 行の頭へ > 535 { > 536 // 1.07.4 --> 1.08 :: Virtual Home > 537 // np.tl = cur_.tl, np.vl = cur_.vl-cur_.rl; > 538 > 539 if( cur_.rl == 0 ) > 540 np.tl = cur_.tl, np.vl = cur_.vl-cur_.rl; > 541 else > 542 view_.ConvDPosToVPos( doc_.rightOf(DPos(cur_.tl, view_.r > 543 } > 544 MoveTo( np, select ); > 545 } > 546 > 547 void Cursor::End( bool wide, bool select ) > 548 { > 549 VPos np; > 550 if( wide ) // 文書の末尾へ > 551 { > 552 np.tl = doc_.tln()-1; > 553 np.vl = view_.vln()-1; > 554 } > 555 else // 行の末尾へ > 556 { > 557 // 1.07.4 --> 1.08 :: Virtual End > 558 // np.tl = cur_.tl; > 559 // np.vl = cur_.vl + view_.rln(np.tl) - 1 - cur_.rl; > 560 > 561 view_.ConvDPosToVPos( DPos(cur_.tl, view_.rlend(cur_.tl,cur_.rl) > 562 MoveTo( np, select ); > 563 return; > 564 } > 565 np.ad = doc_.len(np.tl); > 566 np.rl = view_.rln(np.tl)-1; > 567 np.rx = np.vx = view_.GetLastWidth( np.tl ); > 568 > 569 MoveTo( np, select ); > 570 } > 571 > 572 void Cursor::Ud( int dy, bool select ) > 573 { > 574 // はみ出す場合は、先頭行/終端行で止まるように制限 > 575 VPos np = cur_; > 576 if( (signed)np.vl + dy < 0 ) > 577 dy = -(signed)np.vl; > 578 else if( np.vl + dy >= view_.vln() ) > 579 dy = view_.vln()-np.vl-1; > 580 > 581 np.vl += dy; > 582 np.rl += dy; > 583 if( dy<0 ) // 上へ戻る場合 > 584 { > 585 // ジャンプ先論理行の行頭へDash! > 586 while( (signed)np.rl < 0 ) > 587 np.rl += view_.rln(--np.tl); > 588 } > 589 else if( dy>0 ) // 下へ進む場合 > 590 { > 591 // ジャンプ先論理行の行頭へDash! > 592 while( (signed)np.rl > 0 ) > 593 np.rl -= view_.rln(np.tl++); > 594 if( (signed)np.rl < 0 ) > 595 np.rl += view_.rln(--np.tl); //行き過ぎ修正〜 > 596 } > 597 > 598 // x座標決定にかかる > 599 const unicode* str = doc_.tl(np.tl); > 600 > 601 // 右寄せになってる。不自然? > 602 np.ad = (np.rl==0 ? 0 : view_.rlend(np.tl,np.rl-1)+1); > 603 np.vx = (np.rl==0 ? 0 : view_.fnt().W(&str[np.ad-1])); > 604 while( np.vx < np.rx && np.ad < view_.rlend(np.tl,np.rl) ) > 605 { > 606 // 左寄せにしてみた。 > 607 ulong newvx; > 608 if( str[np.ad] == L'\t' ) > 609 newvx = view_.fnt().nextTab(np.vx); > 610 else > 611 newvx = np.vx + view_.fnt().W(&str[np.ad]); > 612 if( newvx > ulong(np.rx) ) > 613 break; > 614 np.vx = newvx; > 615 ++np.ad; > 616 } > 617 > 618 MoveTo( np, select ); > 619 } > 620 > 621 void Cursor::Up( bool wide, bool select ) > 622 { > 623 Ud( wide?-3:-1, select ); > 624 } > 625 > 626 void Cursor::Down( bool wide, bool select ) > 627 { > 628 Ud( wide?3:1, select ); > 629 } > 630 > 631 void Cursor::PageUp( bool select ) > 632 { > 633 Ud( -view_.cy()/view_.fnt().H(), select ); > 634 } > 635 > 636 void Cursor::PageDown( bool select ) > 637 { > 638 Ud( view_.cy()/view_.fnt().H(), select ); > 639 } > 640 > 641 void Cursor::Left( bool wide, bool select ) > 642 { > 643 VPos np; > 644 if( cur_!=sel_ && !select ) > 645 np = Min( cur_, sel_ ), np.rx = np.vx; > 646 else > 647 view_.ConvDPosToVPos( doc_.leftOf(cur_,wide), &np, &cur_ ); > 648 MoveTo( np, select ); > 649 } > 650 > 651 void Cursor::Right( bool wide, bool select ) > 652 { > 653 VPos np; > 654 if( cur_!=sel_ && !select ) > 655 np = Max( cur_, sel_ ), np.rx = np.vx; > 656 else > 657 view_.ConvDPosToVPos( doc_.rightOf(cur_,wide), &np, &cur_ ); > 658 MoveTo( np, select ); > 659 } > 660 > 661 > 662 > 663 //------------------------------------------------------------------------- > 664 // マウス入力への対応 > 665 //------------------------------------------------------------------------- > 666 > 667 void Cursor::on_lbutton_dbl( short x, short y ) > 668 { > 669 // 行番号ゾーンの場合は特に何もしない > 670 if( view_.lna()-view_.fnt().F() < x ) > 671 // 行末の場合も特に何もしない > 672 if( cur_.ad != doc_.len(cur_.tl) ) > 673 { > 674 VPos np; > 675 view_.ConvDPosToVPos( doc_.wordStartOf(cur_), &np, &cur_ > 676 MoveTo( np, false ); > 677 Right( true, true ); > 678 } > 679 } > 680 > 681 bool Cursor::on_contextmenu( short x, short y ) > 682 { > 683 // Not Tracked > 684 return false; > 685 } > 686 > 687 void Cursor::on_lbutton_down( short x, short y, bool shift ) > 688 { > 689 if( !shift ) > 690 { > 691 // これまでの選択範囲をクリア > 692 Redraw( cur_, sel_ ); > 693 > 694 // 行番号ゾーンのクリックだったら、行選択モードに > 695 lineSelectMode_ = ( x < view_.lna()-view_.fnt().F() ); > 696 > 697 // 選択開始位置を調整 > 698 view_.GetVPos( x, y, &sel_ ); > 699 if( lineSelectMode_ ) > 700 view_.ConvDPosToVPos( DPos(sel_.tl,0), &sel_, &sel_ ); > 701 cur_ = sel_; > 702 } > 703 > 704 // 移動! > 705 MoveByMouse( dragX_=x, dragY_=y ); > 706 > 707 // マウス位置の追跡開始 > 708 timerID_ = ::SetTimer( caret_->hwnd(), 178116, keyRepTime_, NULL ); > 709 ::SetCapture( caret_->hwnd() ); > 710 } > 711 > 712 void Cursor::on_lbutton_up( short x, short y ) > 713 { > 714 // 追跡解除 > 715 if( timerID_ != 0 ) > 716 { > 717 ::ReleaseCapture(); > 718 ::KillTimer( caret_->hwnd(), timerID_ ); > 719 timerID_ = 0; > 720 } > 721 } > 722 > 723 void Cursor::on_mouse_move( short x, short y ) > 724 { > 725 if( timerID_ != 0 ) > 726 { > 727 // View内部ならMouseMoveに反応 > 728 POINT pt = { dragX_=x, dragY_=y }; > 729 if( PtInRect( &view_.zone(), pt ) ) > 730 MoveByMouse( dragX_, dragY_ ); > 731 } > 732 } > 733 > 734 void Cursor::on_timer() > 735 { > 736 // View外部ならTimerに反応 > 737 POINT pt = { dragX_, dragY_ }; > 738 if( !PtInRect( &view_.zone(), pt ) ) > 739 MoveByMouse( dragX_, dragY_ ); > 740 } > 741 > 742 void Cursor::MoveByMouse( int x, int y ) > 743 { > 744 VPos vp; > 745 view_.GetVPos( x, y, &vp, lineSelectMode_ ); > 746 MoveTo( vp, true ); > 747 } > 748 > 749 //------------------------------------------------------------------------- > 750 // 再変換 > 751 //------------------------------------------------------------------------- > 752 > 753 int Cursor::on_ime_reconvertstring( RECONVERTSTRING* rs ) > 754 { > 755 if( ! isSelected() || cur_.tl != sel_.tl ) > 756 return 0; > 757 > 758 #ifdef _UNICODE > 759 aarr<unicode> str = getSelectedStr(); > 760 #else > 761 aarr<char> str; > 762 { > 763 aarr<unicode> ub = getSelectedStr(); > 764 ulong len; > 765 for(len=0; ub[len]; ++len); > 766 ki::aarr<char> nw( new TCHAR[(len+1)*3] ); > 767 str = nw; > 768 ::WideCharToMultiByte( CP_ACP, 0, ub.get(), -1, > 769 str.get(), (len+1)*3, NULL, NULL ); > 770 } > 771 #endif > 772 const ulong len = ::lstrlen(str.get()); > 773 if( rs != NULL ) > 774 { > 775 rs->dwSize = sizeof(RECONVERTSTRING) + (len+1)*sizeof > 776 rs->dwVersion = 0; > 777 rs->dwStrOffset = sizeof(RECONVERTSTRING); > 778 rs->dwStrLen = len; > 779 rs->dwCompStrOffset = 0; > 780 rs->dwCompStrLen = len; > 781 rs->dwTargetStrOffset = 0; > 782 rs->dwTargetStrLen = len; > 783 memmove( ((char*)rs)+rs->dwStrOffset, str.get(), (len+1)*sizeof( > 784 > 785 if( sel_ < cur_ ) > 786 { > 787 DPos psel_ = sel_; > 788 MoveCur( cur_, false ); > 789 MoveCur( psel_, true ); > 790 } > 791 } > 792 return sizeof(RECONVERTSTRING) + (len+1)*sizeof(TCHAR); > 793 } > 794 > 795 bool Cursor::on_ime_confirmreconvertstring( RECONVERTSTRING* rs ) > 796 { > 797 return false; > 798 } > 799

Added editwing/ip_doc.h version [8369bb0837c81915]

> 1 #ifndef _EDITWING_IP_DOC_H_ > 2 #define _EDITWING_IP_DOC_H_ > 3 #include "ewDoc.h" > 4 using namespace ki; > 5 #ifndef __ccdoc__ > 6 namespace editwing { > 7 namespace doc { > 8 #endif > 9 > 10 > 11 > 12 //@{ @pkg editwing.Doc.Impl //@} > 13 class Parser; > 14 > 15 > 16 > 17 //========================================================================= > 18 //@{ > 19 // 行バッファ構造体 > 20 // > 21 // UCS-2ベタの形式でテキストデータを保持する。またそれと同時に、 > 22 // キーワードファイルによって指定された強調語を区別するための > 23 // 解析処理結果用バッファも管理する。文字データに終端NULは > 24 // 付けないが、解析作業の高速化のため、終端 U+007f が入る。 > 25 //@} > 26 //========================================================================= > 27 > 28 class Line : public Object > 29 { > 30 public: > 31 > 32 //@{ 指定テキストで初期化 //@} > 33 Line( const unicode* str, ulong len ) > 34 : alen_( 10>len ? 10 : len ) > 35 , len_ ( len ) > 36 , str_ ( static_cast<unicode*>( mem().Alloc((alen_+1)*2+alen_) ) > 37 , flg_ ( reinterpret_cast<uchar*>(str_+alen_+1) ) > 38 , commentBitReady_( false ) > 39 , isLineHeadCommented_( 0 ) > 40 { > 41 memmove( str_, str, len*2 ); > 42 str_[ len ] = 0x007f; > 43 } > 44 > 45 ~Line() > 46 { > 47 mem().DeAlloc( str_, (alen_+1)*2+alen_ ); > 48 } > 49 > 50 //@{ テキスト挿入(指定位置に指定サイズ) //@} > 51 void InsertAt( ulong at, const unicode* buf, ulong siz ) > 52 { > 53 if( len_+siz > alen_ ) > 54 { > 55 // バッファ拡張 > 56 ulong psiz = (alen_+1)*2+alen_; > 57 alen_ = Max( alen_<<1, len_+siz ); > 58 unicode* tmpS = > 59 static_cast<unicode*>( mem().Alloc((alen > 60 uchar* tmpF = > 61 reinterpret_cast<uchar*>(tmpS+alen_+1); > 62 // コピー > 63 memmove( tmpS, str_, at*2 ); > 64 memmove( tmpS+at+siz, str_+at, (len_-at+1)*2 ); > 65 memmove( tmpF, flg_, at ); > 66 // 古いのを削除 > 67 mem().DeAlloc( str_, psiz ); > 68 str_ = tmpS; > 69 flg_ = tmpF; > 70 } > 71 else > 72 { > 73 memmove( str_+at+siz, str_+at, (len_-at+1)*2 ); > 74 memmove( flg_+at+siz, flg_+at, (len_-at) ); > 75 } > 76 memmove( str_+at, buf, siz*sizeof(unicode) ); > 77 len_ += siz; > 78 } > 79 > 80 //@{ テキスト挿入(末尾に) //@} > 81 void InsertToTail( const unicode* buf, ulong siz ) > 82 { > 83 InsertAt( len_, buf, siz ); > 84 } > 85 > 86 //@{ テキスト削除(指定位置から指定サイズ) //@} > 87 void RemoveAt( ulong at, ulong siz ) > 88 { > 89 memmove( str_+at, str_+at+siz, (len_-siz-at+1)*2 ); > 90 memmove( flg_+at, flg_+at+siz, (len_-siz-at) ); > 91 len_ -= siz; > 92 } > 93 > 94 //@{ テキスト削除(指定位置から末尾まで) //@} > 95 void RemoveToTail( ulong at ) > 96 { > 97 if( at < len_ ) > 98 str_[ len_=at ] = 0x007f; > 99 } > 100 > 101 //@{ バッファにコピー(指定位置から指定サイズ) //@} > 102 ulong CopyAt( ulong at, ulong siz, unicode* buf ) > 103 { > 104 memmove( buf, str_+at, siz*sizeof(unicode) ); > 105 return siz; > 106 } > 107 > 108 //@{ バッファにコピー(指定位置から末尾まで) //@} > 109 ulong CopyToTail( ulong at, unicode* buf ) > 110 { > 111 return CopyAt( at, len_-at, buf ); > 112 } > 113 > 114 //@{ 長さ //@} > 115 ulong size() const > 116 { return len_; } > 117 > 118 //@{ テキスト //@} > 119 unicode* str() > 120 { return str_; } > 121 > 122 //@{ テキスト(const) //@} > 123 const unicode* str() const > 124 { return str_; } > 125 > 126 //@{ 解析結果 //@} > 127 uchar* flg() > 128 { return flg_; } > 129 > 130 //@{ 解析結果(const) //@} > 131 const uchar* flg() const > 132 { return flg_; } > 133 > 134 // ask > 135 bool isCmtBitReady() const > 136 { return commentBitReady_; } > 137 uchar isLineHeadCmt() const > 138 { return isLineHeadCommented_; } > 139 // for doc > 140 uchar TransitCmt( uchar start ) > 141 { > 142 isLineHeadCommented_ = start; > 143 commentBitReady_ = false; > 144 return (commentTransition_>>start)&1; > 145 } > 146 // for parser > 147 void SetTransitFlag( uchar flag ) > 148 { commentTransition_ = flag; } > 149 void CommentBitUpdated() > 150 { commentBitReady_ = true; } > 151 > 152 private: > 153 ulong alen_; > 154 ulong len_; > 155 unicode* str_; > 156 uchar* flg_; > 157 > 158 uchar isLineHeadCommented_; > 159 uchar commentTransition_; > 160 bool commentBitReady_; > 161 }; > 162 > 163 > 164 > 165 //========================================================================= > 166 //@{ > 167 // Unicodeテキスト切り分け君 > 168 // > 169 // 行単位で処理を行うことが多いので、その行毎に分ける処理を > 170 // 切り出した。getLine() するたびに、指定したポインタと整数変数へ > 171 // 先頭から順に行のデータを格納して行く。 > 172 //@} > 173 //========================================================================= > 174 > 175 class UniReader > 176 { > 177 public: > 178 > 179 //@{ 読みとり元バッファを与えて初期化 //@} > 180 UniReader( > 181 const unicode* str, ulong len, > 182 const unicode** ansstr, ulong* anslen ) > 183 : ptr_ ( str ) > 184 , end_ ( str+len ) > 185 , ans_ ( ansstr ) > 186 , aln_ ( anslen ) > 187 , empty_( false ) {} > 188 > 189 //@{ 読み終わったかどうかチェック //@} > 190 bool isEmpty() > 191 { return empty_; } > 192 > 193 //@{ 一行取得 //@} > 194 void getLine() > 195 { > 196 // 次の改行の位置を取得 > 197 const unicode *p=ptr_, *e=end_; > 198 for( ; p<e; ++p ) > 199 if( *p == L'\r' || *p == L'\n' ) > 200 break; > 201 // 記録 > 202 *ans_ = ptr_; > 203 *aln_ = int(p-ptr_); > 204 // 改行コードスキップ > 205 if( p == e ) > 206 empty_ = true; > 207 else > 208 if( *(p++)==L'\r'&& p<e && *p==L'\n' ) > 209 ++p; > 210 ptr_ = p; > 211 } > 212 > 213 private: > 214 bool empty_; > 215 const unicode *ptr_, *end_, **ans_; > 216 ulong *aln_; > 217 }; > 218 > 219 > 220 > 221 //========================================================================= > 222 //@{ > 223 // Undo/Redo用に、Commandオブジェクトを保存しておくクラス > 224 //@} > 225 //========================================================================= > 226 > 227 class UnReDoChain : public Object > 228 { > 229 public: > 230 > 231 //@{ コンストラクタ //@} > 232 UnReDoChain(); > 233 > 234 //@{ デストラクタ //@} > 235 ~UnReDoChain(); > 236 > 237 //@{ Undo実行 //@} > 238 void Undo( Document& doc ); > 239 > 240 //@{ Redo実行 //@} > 241 void Redo( Document& doc ); > 242 > 243 //@{ 新しいコマンドを実行 //@} > 244 void NewlyExec( const Command& cmd, Document& doc ); > 245 > 246 //@{ 初期状態に戻す //@} > 247 void Clear(); > 248 > 249 //@{ 保存位置フラグを現在位置にセット //@} > 250 void SavedHere(); > 251 > 252 //@{ Undo/Redoの回数制限を指定。-1 = Infinite //@} > 253 void SetLimit( long lim ); > 254 > 255 public: > 256 > 257 //@{ Undo操作が可能か? //@} > 258 bool isUndoAble() const; > 259 > 260 //@{ Redo操作が可能か? //@} > 261 bool isRedoAble() const; > 262 > 263 //@{ 保存後、変更されているか? //@} > 264 bool isModified() const; > 265 > 266 private: > 267 > 268 struct Node : public Object > 269 { > 270 Node(); > 271 Node( Command*, Node*, Node* ); > 272 ~Node(); > 273 void ResetCommand( Command* cmd ); > 274 ulong ChainDelete(Node*& savedPos_ref); > 275 Node *next_, *prev_; > 276 Command *cmd_; > 277 }; > 278 > 279 private: > 280 > 281 Node headTail_; > 282 Node* savedPos_; > 283 Node* lastOp_; > 284 ulong num_; > 285 ulong limit_; > 286 > 287 private: > 288 > 289 NOCOPY(UnReDoChain); > 290 }; > 291 > 292 > 293 > 294 //------------------------------------------------------------------------- > 295 #ifndef __ccdoc__ > 296 > 297 inline void UnReDoChain::SavedHere() > 298 { savedPos_ = lastOp_; } > 299 > 300 inline bool UnReDoChain::isUndoAble() const > 301 { return (lastOp_ != &headTail_); } > 302 > 303 inline bool UnReDoChain::isRedoAble() const > 304 { return (lastOp_->next_ != &headTail_); } > 305 > 306 inline bool UnReDoChain::isModified() const > 307 { return (lastOp_ != savedPos_); } > 308 > 309 > 310 > 311 #endif // __ccdoc__ > 312 //========================================================================= > 313 //@{ > 314 // Documentクラスの実装部分 > 315 //@} > 316 //========================================================================= > 317 > 318 class DocImpl : public Object, EzLockable, Runnable > 319 { > 320 public: > 321 > 322 DocImpl( Document& theDoc ); > 323 ~DocImpl(); > 324 > 325 //@{ 操作コマンド実行 //@} > 326 void Execute( const Command& cmd ); > 327 > 328 //@{ キーワード定義切り替え //@} > 329 void SetKeyword( const unicode* defbuf, ulong siz ); > 330 > 331 //@{ イベントハンドラ登録 //@} > 332 void AddHandler( DocEvHandler* eh ); > 333 > 334 //@{ イベントハンドラ解除 //@} > 335 void DelHandler( DocEvHandler* eh ); > 336 > 337 //@{ ファイルを開く //@} > 338 void OpenFile( aptr<TextFileR> tf ); > 339 > 340 //@{ ファイルを保存 //@} > 341 void SaveFile( TextFileW& tf ); > 342 > 343 //@{ 内容破棄 //@} > 344 void ClearAll(); > 345 > 346 //@{ アンドゥ //@] > 347 void Undo(); > 348 > 349 //@{ リドゥ //@] > 350 void Redo(); > 351 > 352 //@{ アンドゥ回数制限 //@] > 353 void SetUndoLimit( long lim ); > 354 > 355 //@{ 変更フラグをクリア //@} > 356 void ClearModifyFlag(); > 357 > 358 public: > 359 > 360 //@{ 行数 //@} > 361 ulong tln() const; > 362 > 363 //@{ 行バッファ //@} > 364 const unicode* tl( ulong i ) const; > 365 > 366 //@{ 行解析結果バッファ //@} > 367 const uchar* pl( ulong i ) const; > 368 > 369 //@{ 行文字数 //@} > 370 ulong len( ulong i ) const; > 371 > 372 //@{ 指定範囲のテキストの長さ //@} > 373 ulong getRangeLength( const DPos& stt, const DPos& end ); > 374 > 375 //@{ 指定範囲のテキスト //@} > 376 void getText( unicode* buf, const DPos& stt, const DPos& end ); > 377 > 378 //@{ 指定位置の単語の先頭を取得 //@} > 379 DPos wordStartOf( const DPos& dp ) const; > 380 > 381 //@{ 指定位置の一つ左の位置を取得 //@} > 382 DPos leftOf( const DPos& dp, bool wide=false ) const; > 383 > 384 //@{ 指定位置の一つ右の位置を取得 //@} > 385 DPos rightOf( const DPos& dp, bool wide=false ) const; > 386 > 387 //@{ アンドゥ可能? //@} > 388 bool isUndoAble() const; > 389 > 390 //@{ リドゥ可能? //@} > 391 bool isRedoAble() const; > 392 > 393 //@{ 変更済み? //@} > 394 bool isModified() const; > 395 > 396 private: > 397 > 398 Document& doc_; // 自分 > 399 aptr<Parser> parser_; // 文字列解析役 > 400 gapbufobj<Line> text_; // テキストデータ > 401 mutable storage<DocEvHandler*> pEvHan_; // イベント通知先 > 402 UnReDoChain urdo_; // アンドゥリドゥ > 403 > 404 aptr<TextFileR> currentOpeningFile_; > 405 > 406 private: > 407 > 408 // 変更通知 > 409 void Fire_KEYWORDCHANGE(); > 410 void Fire_MODIFYFLAGCHANGE(); > 411 void Fire_TEXTUPDATE( const DPos& s, > 412 const DPos& e, const DPos& e2, bool reparsed, bool nmlcmd ); > 413 > 414 // ヘルパー関数 > 415 bool ReParse( ulong s, ulong e ); > 416 void SetCommentBit( const Line& x ) const; > 417 void CorrectPos( DPos& pos ); > 418 void CorrectPos( DPos& stt, DPos& end ); > 419 > 420 // 挿入・削除作業 > 421 bool InsertingOperation( > 422 DPos& stt, const unicode* str, ulong len, DPos& undoend ); > 423 bool DeletingOperation( > 424 DPos& stt, DPos& end, unicode*& undobuf, ulong& undosiz ); > 425 > 426 // パラレルリード > 427 virtual void StartThread(); > 428 > 429 private: > 430 > 431 NOCOPY(DocImpl); > 432 friend class Insert; > 433 friend class Delete; > 434 friend class Replace; > 435 }; > 436 > 437 > 438 > 439 //------------------------------------------------------------------------- > 440 > 441 inline ulong DocImpl::tln() const > 442 { return text_.size(); } > 443 > 444 inline const unicode* DocImpl::tl( ulong i ) const > 445 { return text_[i].str(); } > 446 > 447 inline ulong DocImpl::len( ulong i ) const > 448 { return text_[i].size(); } > 449 > 450 inline const uchar* DocImpl::pl( ulong i ) const > 451 { > 452 const Line& x = text_[i]; > 453 if( !x.isCmtBitReady() ) > 454 SetCommentBit( x ); > 455 return x.flg(); > 456 } > 457 > 458 > 459 > 460 //========================================================================= > 461 > 462 }} // namespace editwing::doc > 463 #endif // _EDITWING_IP_DOC_H_

Added editwing/ip_draw.cpp version [b299730b30885144]

> 1 #include "stdafx.h" > 2 #include "ip_view.h" > 3 using namespace editwing; > 4 using namespace editwing::view; > 5 > 6 > 7 > 8 //========================================================================= > 9 //---- ip_draw.cpp 描画・他 > 10 // > 11 // 折り返しとか色とかを考慮しつつ、実際に描画処理を > 12 // 行うのがここ。あとメッセージディスパッチャなども > 13 // ついでにこのファイルに。^^; > 14 // > 15 //---- ip_text.cpp 文字列操作・他 > 16 //---- ip_parse.cpp キーワード解析 > 17 //---- ip_wrap.cpp 折り返し > 18 //---- ip_scroll.cpp スクロール > 19 //---- ip_cursor.cpp カーソルコントロール > 20 //========================================================================= > 21 > 22 > 23 > 24 //------------------------------------------------------------------------- > 25 // Viewの初期化・解放 > 26 //------------------------------------------------------------------------- > 27 > 28 View::ClsName > 29 View::className_ = TEXT("EditWing View"); > 30 > 31 View::View( doc::Document& d, HWND wnd ) > 32 : WndImpl( className_, WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_HSCROLL ) > 33 , doc_ ( d.impl() ) > 34 { > 35 static bool ClassRegistered = false; > 36 if( !ClassRegistered ) > 37 { > 38 // 初回構築時のみ、クラス登録を行う > 39 ClassRegistered = true; > 40 WNDCLASSEX wc = {0}; > 41 wc.lpszClassName = className_; > 42 wc.style = CS_DBLCLKS | CS_OWNDC; > 43 wc.hCursor = app().LoadOemCursor( IDC_IBEAM ); > 44 > 45 // GlobalIMEを有効にする > 46 ATOM a = WndImpl::Register( &wc ); > 47 ime().FilterWindows( &a, 1 ); > 48 } > 49 > 50 // 窓作成 > 51 Create( NULL, wnd ); > 52 } > 53 > 54 View::~View() > 55 { > 56 // 窓破棄 > 57 Destroy(); > 58 } > 59 > 60 void View::on_create( CREATESTRUCT* cs ) > 61 { > 62 impl_ = new ViewImpl( *this, doc_ ); > 63 doc_.AddHandler( this ); > 64 } > 65 > 66 void View::on_destroy() > 67 { > 68 doc_.DelHandler( this ); > 69 impl_ = NULL; > 70 } > 71 > 72 > 73 > 74 //------------------------------------------------------------------------- > 75 // サブオブジェクトにそのまま回す > 76 //------------------------------------------------------------------------- > 77 > 78 void View::SetWrapType( int wt ) > 79 { impl_->SetWrapType( wt ); } > 80 > 81 void View::ShowLineNo( bool show ) > 82 { impl_->ShowLineNo( show ); } > 83 > 84 void View::SetFont( const VConfig& vc ) > 85 { impl_->SetFont( vc ); } > 86 > 87 void View::on_keyword_change() > 88 { ::InvalidateRect( hwnd(), NULL, FALSE ); } > 89 > 90 void View::on_text_update > 91 ( const DPos& s, const DPos& e, const DPos& e2, bool bAft, bool mCur ) > 92 { impl_->on_text_update( s, e, e2, bAft, mCur ); } > 93 > 94 Cursor& View::cur() > 95 { return impl_->cur(); } > 96 > 97 LRESULT View::on_message( UINT msg, WPARAM wp, LPARAM lp ) > 98 { > 99 switch( msg ) > 100 { > 101 case WM_PAINT:{ > 102 PAINTSTRUCT ps; > 103 ::BeginPaint( hwnd(), &ps ); > 104 impl_->on_paint( ps ); > 105 ::EndPaint( hwnd(), &ps ); > 106 }break; > 107 > 108 case WM_SIZE: > 109 impl_->on_view_resize( LOWORD(lp), HIWORD(lp) ); > 110 break; > 111 > 112 case WM_HSCROLL: > 113 impl_->on_hscroll( LOWORD(wp) ); > 114 break; > 115 > 116 case WM_VSCROLL: > 117 impl_->on_vscroll( LOWORD(wp) ); > 118 break; > 119 > 120 case WM_MOUSEWHEEL: > 121 impl_->on_wheel( HIWORD(wp) ); > 122 break; > 123 > 124 case WM_SETFOCUS: > 125 cur().on_setfocus(); > 126 break; > 127 > 128 case WM_KILLFOCUS: > 129 cur().on_killfocus(); > 130 break; > 131 > 132 case WM_TIMER: > 133 cur().on_timer(); > 134 break; > 135 > 136 case WM_KEYDOWN: > 137 cur().on_keydown( (int)wp, lp ); > 138 break; > 139 > 140 case WM_CHAR: > 141 cur().on_char( (TCHAR)wp ); > 142 break; > 143 > 144 case WM_LBUTTONDOWN: > 145 cur().on_lbutton_down( LOWORD(lp), HIWORD(lp), (wp&MK_SHIFT)!=0 > 146 break; > 147 > 148 case WM_LBUTTONUP: > 149 cur().on_lbutton_up( LOWORD(lp), HIWORD(lp) ); > 150 break; > 151 > 152 case WM_LBUTTONDBLCLK: > 153 cur().on_lbutton_dbl( LOWORD(lp), HIWORD(lp) ); > 154 break; > 155 > 156 case WM_MOUSEMOVE: > 157 cur().on_mouse_move( LOWORD(lp), HIWORD(lp) ); > 158 break; > 159 > 160 case WM_CONTEXTMENU: > 161 if( !cur().on_contextmenu( LOWORD(lp), HIWORD(lp) ) ) > 162 return WndImpl::on_message( msg, wp, lp ); > 163 break; > 164 > 165 case WM_IME_REQUEST: > 166 switch( wp ) > 167 { > 168 case IMR_RECONVERTSTRING: > 169 return cur().on_ime_reconvertstring( > 170 reinterpret_cast<RECONVERTSTRING*>(lp) ); > 171 case IMR_CONFIRMRECONVERTSTRING: > 172 return cur().on_ime_confirmreconvertstring( > 173 reinterpret_cast<RECONVERTSTRING*>(lp) ); > 174 } > 175 break; > 176 > 177 case WM_IME_STARTCOMPOSITION: > 178 cur().on_ime_composition( 0 ); > 179 return WndImpl::on_message( msg, wp, lp ); > 180 > 181 case WM_IME_COMPOSITION: > 182 cur().on_ime_composition( lp ); > 183 if( lp&GCS_RESULTSTR ) > 184 break; > 185 // fall through... > 186 > 187 default: > 188 return WndImpl::on_message( msg, wp, lp ); > 189 } > 190 return 0; > 191 } > 192 > 193 > 194 > 195 //------------------------------------------------------------------------- > 196 // 線を引くとか四角く塗るとか、そーいう基本的な処理 > 197 //------------------------------------------------------------------------- > 198 > 199 Painter::Painter( HDC hdc, const VConfig& vc ) > 200 : dc_ ( hdc ) > 201 , font_ ( ::CreateFontIndirect( &vc.font ) ) > 202 , pen_ ( ::CreatePen( PS_SOLID, 0, vc.color[CTL] ) ) > 203 , brush_ ( ::CreateSolidBrush( vc.color[BG] ) ) > 204 , widthTable_( new int[65536] ) > 205 { > 206 // 制御文字を描画するか否か?のフラグを記憶 > 207 for( int i=0; i<countof(scDraw_); ++i ) > 208 scDraw_[i] = vc.sc[i]; > 209 > 210 // 文字色を記憶 > 211 for( int i=0; i<countof(colorTable_); ++i ) > 212 colorTable_[i] = vc.color[i]; > 213 colorTable_[3] = vc.color[CMT]; > 214 > 215 // DCにセット > 216 ::SelectObject( dc_, font_ ); > 217 ::SelectObject( dc_, pen_ ); > 218 ::SelectObject( dc_, brush_ ); > 219 ::SetBkMode( dc_, TRANSPARENT ); > 220 ::SetMapMode( dc_, MM_TEXT ); > 221 > 222 // 文字幅テーブル初期化(ASCII範囲の文字以外は遅延処理) > 223 memFF( widthTable_, 65536*sizeof(int) ); > 224 ::GetCharWidthW( dc_, L' ', L'~', widthTable_+L' ' ); > 225 widthTable_[L'\t'] = W() * Max(1,vc.tabstep); > 226 // 下位サロゲートは文字幅ゼロ > 227 mem00( widthTable_+0xDC00, (0xE000 - 0xDC00)*sizeof(int) ); > 228 > 229 // 数字の最大幅を計算 > 230 figWidth_ = 0; > 231 for( unicode ch=L'0'; ch<=L'9'; ++ch ) > 232 if( figWidth_ < widthTable_[ch] ) > 233 figWidth_ = widthTable_[ch]; > 234 > 235 // 高さの情報 > 236 TEXTMETRIC met; > 237 ::GetTextMetrics( dc_, &met ); > 238 height_ = met.tmHeight; > 239 > 240 // LOGFONT > 241 ::GetObject( font_, sizeof(LOGFONT), &logfont_ ); > 242 } > 243 > 244 Painter::~Painter() > 245 { > 246 // 適当な別オブジェクトをくっつけて自分を解放する > 247 ::SelectObject( dc_, ::GetStockObject( OEM_FIXED_FONT ) ); > 248 ::SelectObject( dc_, ::GetStockObject( BLACK_PEN ) ); > 249 ::SelectObject( dc_, ::GetStockObject( WHITE_BRUSH ) ); > 250 ::DeleteObject( font_ ); > 251 ::DeleteObject( pen_ ); > 252 ::DeleteObject( brush_ ); > 253 delete [] widthTable_; > 254 } > 255 > 256 inline void Painter::CharOut( unicode ch, int x, int y ) > 257 { > 258 ::TextOutW( dc_, x, y, &ch, 1 ); > 259 } > 260 > 261 inline void Painter::StringOut > 262 ( const unicode* str, int len, int x, int y ) > 263 { > 264 ::TextOutW( dc_, x, y, str, len ); > 265 } > 266 > 267 inline void Painter::SetColor( int i ) > 268 { > 269 ::SetTextColor( dc_, colorTable_[i] ); > 270 } > 271 > 272 inline void Painter::Fill( const RECT& rc ) > 273 { > 274 ::FillRect( dc_, &rc, brush_ ); > 275 } > 276 > 277 inline void Painter::Invert( const RECT& rc ) > 278 { > 279 ::InvertRect( dc_, &rc ); > 280 } > 281 > 282 inline void Painter::DrawLine( int x1, int y1, int x2, int y2 ) > 283 { > 284 ::MoveToEx( dc_, x1, y1, NULL ); > 285 ::LineTo( dc_, x2, y2 ); > 286 } > 287 > 288 inline void Painter::SetClip( const RECT& rc ) > 289 { > 290 ::IntersectClipRect( dc_, rc.left, rc.top, rc.right, rc.bottom ); > 291 } > 292 > 293 inline void Painter::ClearClip() > 294 { > 295 ::SelectClipRgn( dc_, NULL ); > 296 } > 297 > 298 void Painter::DrawHSP( int x, int y, int times ) > 299 { > 300 // 半角スペース記号(ホチキスの芯型)を描く > 301 const int w=Wc(L' '), h=H(); > 302 POINT pt[4] = { > 303 { x , y+h-4 }, > 304 { x , y+h-2 }, > 305 { x+w-3, y+h-2 }, > 306 { x+w-3, y+h-5 } > 307 }; > 308 while( times-- ) > 309 { > 310 if( 0 <= pt[3].x ) > 311 ::Polyline( dc_, pt, countof(pt) ); > 312 pt[0].x += w; > 313 pt[1].x += w; > 314 pt[2].x += w; > 315 pt[3].x += w; > 316 } > 317 } > 318 > 319 void Painter::DrawZSP( int x, int y, int times ) > 320 { > 321 // 全角スペース記号(平たい四角)を描く > 322 const int w=Wc(0x3000/*L' '*/), h=H(); > 323 POINT pt[4] = { > 324 { x , y+h-4 }, > 325 { x , y+h-2 }, > 326 { x+w-3, y+h-2 }, > 327 { x+w-3, y+h-4 } > 328 }; > 329 while( times-- ) > 330 { > 331 if( 0 <= pt[3].x ) > 332 ::Polygon( dc_, pt, countof(pt) ); > 333 pt[0].x += w; > 334 pt[1].x += w; > 335 pt[2].x += w; > 336 pt[3].x += w; > 337 } > 338 } > 339 > 340 > 341 > 342 //------------------------------------------------------------------------- > 343 // 再描画したい範囲を Invalidate する。 > 344 //------------------------------------------------------------------------- > 345 > 346 void ViewImpl::ReDraw( ReDrawType r, const DPos* s ) > 347 { > 348 // まずスクロールバーを更新 > 349 UpdateScrollBar(); > 350 > 351 switch( r ) > 352 { > 353 case ALL: // 全画面 > 354 > 355 ::InvalidateRect( hwnd_, NULL, FALSE ); > 356 break; > 357 > 358 case LNAREA: // 行番号表示域のみ > 359 > 360 if( lna() > 0 ) > 361 { > 362 RECT rc = { 0, 0, lna(), bottom() }; > 363 ::InvalidateRect( hwnd_, &rc, FALSE ); > 364 } > 365 break; > 366 > 367 case LINE: // 指定した行の後半 > 368 case AFTER: // 指定した行以下全部 > 369 > 370 { > 371 DPos st = ( s->ad==0 ? *s : doc_.leftOf(*s,true) ); > 372 InvalidateView( st, r==AFTER ); > 373 } > 374 } > 375 } > 376 > 377 > 378 > 379 //------------------------------------------------------------------------- > 380 // WM_PAINTハンドラ > 381 //------------------------------------------------------------------------- > 382 > 383 void ViewImpl::on_paint( const PAINTSTRUCT& ps ) > 384 { > 385 // 描画範囲の情報を詳しく取得 > 386 Painter& p = cvs_.getPainter(); > 387 VDrawInfo v( ps.rcPaint ); > 388 GetDrawPosInfo( v ); > 389 > 390 if( ps.rcPaint.right <= lna() ) > 391 { > 392 // case A: 行番号表示域のみ更新 > 393 DrawLNA( v, p ); > 394 } > 395 else if( lna() <= ps.rcPaint.left ) > 396 { > 397 // case B: テキスト表示域のみ更新 > 398 DrawTXT( v, p ); > 399 } > 400 else > 401 { > 402 // case C: 両方更新 > 403 DrawLNA( v, p ); > 404 p.SetClip( cvs_.zone() ); > 405 DrawTXT( v, p ); > 406 p.ClearClip(); > 407 } > 408 } > 409 > 410 > 411 > 412 //------------------------------------------------------------------------- > 413 // 行番号ゾーン描画 > 414 //------------------------------------------------------------------------- > 415 > 416 void ViewImpl::DrawLNA( const VDrawInfo& v, Painter& p ) > 417 { > 418 // > 419 // 文字列のまま足し算を行うルーチン > 420 // > 421 struct strint { > 422 strint( ulong num ) { > 423 int i=11; > 424 while( num ) digit[--i] = (unicode)(L'0'+(num%10)), num/ > 425 while( i ) digit[--i] = L' '; > 426 } > 427 void operator++() { > 428 int i=10; > 429 do > 430 if( digit[i] == L'9' ) > 431 digit[i] = L'0'; > 432 else > 433 { ++digit[i]; return; } > 434 while( digit[--i] != L' ' ); > 435 digit[i] = L'1'; > 436 } > 437 void Output( Painter& f, int x, int y ) { > 438 for( unicode* p=digit+10; *p!=L' '; --p,x-=f.F() ) > 439 f.CharOut( *p, x, y ); > 440 } > 441 unicode digit[11]; > 442 }; > 443 > 444 // 背面消去 > 445 RECT rc = { v.rc.left, v.rc.top, lna(), v.rc.bottom }; > 446 p.Fill( rc ); > 447 > 448 if( v.rc.top < v.YMAX ) > 449 { > 450 // 境界線表示 > 451 int line = lna() - p.F()/2; > 452 p.DrawLine( line, v.rc.top, line, v.YMAX ); > 453 p.SetColor( LN ); > 454 > 455 // 行番号表示 > 456 strint n = v.TLMIN+1; > 457 int y = v.YMIN; > 458 int edge = lna() - p.F()*2; > 459 for( ulong i=v.TLMIN; y<v.YMAX; ++i,++n ) > 460 { > 461 n.Output( p, edge, y ); > 462 y += p.H() * rln(i); > 463 } > 464 } > 465 } > 466 > 467 > 468 > 469 //------------------------------------------------------------------------- > 470 // テキスト描画 > 471 //------------------------------------------------------------------------- > 472 > 473 inline void ViewImpl::Inv( int y, int xb, int xe, Painter& p ) > 474 { > 475 RECT rc = { > 476 Max( left(), xb ), y, > 477 Min( right(), xe ), y+p.H()-1 > 478 }; > 479 p.Invert( rc ); > 480 } > 481 > 482 void ViewImpl::DrawTXT( const VDrawInfo v, Painter& p ) > 483 { > 484 // 定数1 > 485 // const int TAB = p.T(); > 486 const int H = p.H(); > 487 const ulong TLM = doc_.tln()-1; > 488 > 489 // 作業用変数1 > 490 RECT a = { 0, v.YMIN, 0, v.YMIN+p.H() }; > 491 int clr = -1; > 492 register int x, x2; > 493 register ulong i, i2; > 494 > 495 // 論理行単位のLoop > 496 for( ulong tl=v.TLMIN; a.top<v.YMAX; ++tl ) > 497 { > 498 // 定数2 > 499 const unicode* str = doc_.tl(tl); > 500 const uchar* flg = doc_.pl(tl); > 501 const int rYMAX = Min<int>( v.YMAX, a.top+rln(tl)*H ); > 502 > 503 // 作業用変数2 > 504 ulong stt=0, end, t, n; > 505 > 506 // 表示行単位のLoop > 507 for( ulong rl=0; a.top<rYMAX; ++rl,a.top+=H,a.bottom+=H,stt=end > 508 { > 509 // 作業用変数3 > 510 end = rlend(tl,rl); > 511 if( a.bottom<=v.YMIN ) > 512 continue; > 513 > 514 // テキストデータ描画 > 515 for( x2=x=0,i2=i=stt; x<=v.XMAX && i<end; x=x2,i=i2 ) > 516 { > 517 // n := 次のTokenの頭 > 518 t = (flg[i]>>5); > 519 n = i + t; > 520 if( n >= end ) > 521 n = end; > 522 else if( t==7 || t==0 ) > 523 while( n<end && (flg[n]>>5)==0 ) > 524 ++n; > 525 > 526 // x2, i2 := このTokenの右端 > 527 i2 ++; > 528 x2 = (str[i]==L'\t' ? p.nextTab(x2) : x2+p.W(&st > 529 // if( x2 <= v.XMIN ) > 530 // x=x2, i=i2; > 531 while( i2<n && x2<=v.XMAX ) > 532 x2 += p.W( &str[i2++] ); > 533 > 534 // 再描画すべき範囲と重なっていない > 535 if( x2<=v.XMIN ) > 536 continue; > 537 > 538 // x, i := このトークンの左端 > 539 if( x<v.XMIN ) > 540 { > 541 // tabの分が戻りすぎ? > 542 x = x2, i = i2; > 543 while( v.XMIN<x ) > 544 x -= p.W( &str[--i] ); > 545 } > 546 > 547 // 背景塗りつぶし > 548 a.left = x + v.XBASE; > 549 a.right = x2 + v.XBASE; > 550 p.Fill( a ); > 551 > 552 // 描画 > 553 switch( str[i] ) > 554 { > 555 case L'\t': > 556 if( p.sc(scTAB) ) > 557 { > 558 p.SetColor( clr=CTL ); > 559 for( ; i<i2; ++i, x=p.nextTab(x) > 560 p.CharOut( L'>', x+v.XBA > 561 } > 562 break; > 563 case L' ': > 564 if( p.sc(scHSP) ) > 565 p.DrawHSP( x+v.XBASE, a.top, i2- > 566 break; > 567 case 0x3000://L' ': > 568 if( p.sc(scZSP) ) > 569 p.DrawZSP( x+v.XBASE, a.top, i2- > 570 break; > 571 default: > 572 if( clr != (flg[i]&3) ) > 573 p.SetColor( clr=(flg[i]&3) ); > 574 p.StringOut( str+i, i2-i, x+v.XBASE, a.t > 575 //p.StringOut( str+i, i2-i, x+v.XBASE, a > 576 // 何故だか2度描きしないとうまくいかん… > 577 break; > 578 } > 579 } > 580 > 581 // 選択範囲だったら反転 > 582 if( v.SYB<=a.top && a.top<=v.SYE ) > 583 Inv( a.top, a.top==v.SYB?v.SXB:(v.XBASE), > 584 a.top==v.SYE?v.SXE:(v.XBASE+x), p ); > 585 > 586 // 行末より後ろの余白を背景色塗 > 587 if( x<v.XMAX ) > 588 { > 589 a.left = v.XBASE + Max( v.XMIN, x ); > 590 a.right= v.XBASE + v.XMAX; > 591 p.Fill( a ); > 592 } > 593 } > 594 > 595 // 行末記号描画反転 > 596 SpecialChars sc = (tl==TLM ? scEOF : scEOL); > 597 if( i==doc_.len(tl) && -32768<x+v.XBASE ) > 598 { > 599 if( p.sc(sc) ) > 600 { > 601 static const unicode* const sstr[] = { L"[EOF]", > 602 static const int slen[] = { 5, 1 }; > 603 p.SetColor( clr=CTL ); > 604 p.StringOut( sstr[sc], slen[sc], x+v.XBASE, a.to > 605 } > 606 if( v.SYB<a.top && a.top<=v.SYE && sc==scEOL ) > 607 Inv( a.top-H, x+v.XBASE, x+v.XBASE+p.Wc(L'/'), p > 608 } > 609 } > 610 > 611 // EOF後余白を背景色塗 > 612 if( a.top < v.rc.bottom ) > 613 { > 614 a.left = v.rc.left; > 615 a.right = v.rc.right; > 616 a.bottom = v.rc.bottom; > 617 p.Fill( a ); > 618 } > 619 }

Added editwing/ip_parse.cpp version [81bbb0c1ba6ccbac]

> 1 #include "stdafx.h" > 2 #include "ip_doc.h" > 3 using namespace editwing; > 4 using namespace editwing::doc; > 5 > 6 > 7 > 8 //========================================================================= > 9 //---- ip_parse.cpp キーワード解析 > 10 // > 11 // キーワード定義ファイルに従って、保持する文字列を > 12 // 適切に切り分ける作業がここ。 > 13 // > 14 //---- ip_text.cpp 文字列操作・他 > 15 //---- ip_wrap.cpp 折り返し > 16 //---- ip_scroll.cpp スクロール > 17 //---- ip_draw.cpp 描画・他 > 18 //---- ip_cursor.cpp カーソルコントロール > 19 //========================================================================= > 20 > 21 > 22 > 23 //========================================================================= > 24 // > 25 // 解析結果データ仕様 > 26 // これだけ色々姑息な手段を持ち込んで本当に > 27 // 速くなっているのかどうかは不明…(^^; > 28 // > 29 // ----------------------------------------------- > 30 // > 31 // Line::isLineHeadCommented_ > 32 // 0: 行頭がブロックコメントの内部ではない > 33 // 1: 行頭がブロックコメントの内部 > 34 // > 35 // ----------------------------------------------- > 36 // > 37 // Line::commentTransition_ > 38 // 00: 行末は常にコメントの外 > 39 // 01: 行頭と行末はコメント状態が逆転 > 40 // 10: 行頭と行末はコメント状態が同じ > 41 // 11: 行末は常にコメントの中 > 42 // > 43 // ----------------------------------------------- > 44 // > 45 // 以上二つのフラグを元に、前の行の情報から今の行の情報を > 46 // this.head = (prev.trans >> prev.head)&1; > 47 // で順次計算していくことが出来る。 > 48 // この計算の際に内部バッファの状態まで書き換えるのは > 49 // コストがでかすぎるので、次に示すフラグを見ながら > 50 // 描画寸前に適宜調整する。 > 51 // > 52 // ----------------------------------------------- > 53 // > 54 // Line::commentBitReady_ > 55 // コメントビットが調整済みかどうか > 56 // > 57 // ----------------------------------------------- > 58 // > 59 // Line::str_[] > 60 // UCS-2ベタで、文字列データがそのまま格納される。 > 61 // ただし、パーサの高速化のために最終文字の後ろに > 62 // 0x007fが付加される。 > 63 // > 64 // ----------------------------------------------- > 65 // > 66 // Line::flg_ > 67 // 一文字毎に、下のような8bitのフラグを割り当てる > 68 // | aaabbbcd | > 69 // > 70 // ----------------------------------------------- > 71 // > 72 // aaa == "PosInToken" > 73 // 0: トークンの途中 > 74 // 1-6: トークンの頭。次の頭は1-6文字先。 > 75 // 7: トークンの頭。次の頭は7文字以上先。 > 76 // > 77 // ----------------------------------------------- > 78 // > 79 // bbb == "TokenType" > 80 // 0: TAB: タブ文字 > 81 // 1: WSP: ホワイトスペース > 82 // 2: TXT: 普通の文字 > 83 // 3: CE: コメント開始タグ > 84 // 4: CB: コメント終了タグ > 85 // 5: LB: 行コメント開始タグ > 86 // 6: Q1: '' 引用符1 > 87 // 7: Q2: "" 引用符2 > 88 // > 89 // ----------------------------------------------- > 90 // > 91 // c == "isKeyword?" > 92 // 0: キーワードではない > 93 // 1: キーワード > 94 // > 95 // ----------------------------------------------- > 96 // > 97 // d == "inComment?" > 98 // 0: コメントの中ではない > 99 // 1: コメントの中 > 100 // > 101 // ----------------------------------------------- > 102 > 103 > 104 > 105 namespace { > 106 //------------------------------------------------------------------------- > 107 // コメントの中なのか外なのか等を判定するためのオートマトン > 108 // > 109 // /* が出たらその後ろはコメントで */ が出たらその後ろはノーマルゾーン > 110 // …という単純な規則では上手く行かない。例えば str"/*"str なんてものが > 111 // 出現した場合に困ってしまう。そこで、 > 112 // ・普通のテキスト > 113 // ・ブロックコメントの中 > 114 // ・行コメントの中 > 115 // ・一重引用符の中 > 116 // ・二重引用符の中 > 117 // の5種類の状態に分けて、それぞれの場合について、どの記号が出たら > 118 // 次にどの状態に移るのか…を処理する必要がある。その状態変化の規則を > 119 // 5x5の2次元配列で与えて管理する。 > 120 //------------------------------------------------------------------------- > 121 > 122 enum CommentDFASymbol{ sCB, sCE, sLB, sQ1, sQ2, sXXX }; > 123 struct CommentDFA > 124 { > 125 // <状態> > 126 // 最下位bitが、現在コメント内かどうかのフラグになります。 > 127 // ブロックコメント中かどうかは (state>>1)&(state) で。 > 128 // 000: normal text 011: in BlockComment > 129 // 001: in LineComment 100: in Quote2 > 130 // 010: in Quote1 > 131 // > 132 // <シンボル> > 133 // C++で言うと下の通り > 134 // 値はTokenTypeフラグとシンクロするようになってます。 > 135 // 000: CE */ 011: Q1 ' > 136 // 001: CB /* 100: Q2 " > 137 // 010: LB // > 138 > 139 // 初期状態を指定。コメント内かコメント外か > 140 CommentDFA( bool inComment ) > 141 : state( inComment ? 3 : 0 ) {} > 142 > 143 // 入力符号を与えて状態遷移 > 144 void transit( int sym ) > 145 { state = tr_table[state][sym]; } > 146 > 147 // 現在の状態 > 148 int state; > 149 > 150 // 状態遷移テーブル > 151 static const int tr_table[5][5]; > 152 }; > 153 > 154 const int CommentDFA::tr_table[5][5] = { > 155 {0,3,1,2,4}, > 156 {1,1,1,1,1}, > 157 {2,2,2,0,2}, > 158 {0,3,3,3,3}, > 159 {4,4,4,4,0}, > 160 }; > 161 > 162 > 163 > 164 //------------------------------------------------------------------------- > 165 // 単純な、キーワード格納構造体。 > 166 // ChainHashの要素にするためnextポインタがつけてあります。 > 167 //------------------------------------------------------------------------- > 168 > 169 struct Keyword : public Object > 170 { > 171 unicode* str; > 172 const ulong len; > 173 Keyword* next; > 174 > 175 Keyword( const unicode* s, ulong l ) > 176 : str( new unicode[l+1] ) > 177 , len( l ) > 178 , next( NULL ) > 179 { memmove( str, s, l*sizeof(unicode) ); } > 180 > 181 ~Keyword() > 182 { delete [] str; } > 183 }; > 184 > 185 > 186 > 187 //------------------------------------------------------------------------- > 188 // サポート関数。Unicodeテキスト同士の比較 > 189 //------------------------------------------------------------------------- > 190 > 191 static bool compare_s(const unicode* a,const unicode* b,ulong l) > 192 { > 193 // 大文字小文字を区別 > 194 while( l-- ) > 195 if( *a++ != *b++ ) > 196 return false; > 197 return true; > 198 } > 199 > 200 static bool compare_i(const unicode* a,const unicode* b,ulong l) > 201 { > 202 // 大文字小文字を区別しない(雑) > 203 while( l-- ) > 204 if( ((*a++) ^ (*b++)) & 0xdf ) > 205 return false; > 206 return true; > 207 } > 208 > 209 > 210 > 211 //------------------------------------------------------------------------- > 212 // 与えられた記号文字列から、コメント開始等の意味のあるトークンを > 213 // 切り出してくるための構造。 > 214 //------------------------------------------------------------------------- > 215 > 216 class TagMap > 217 { > 218 Keyword* tag_[3]; // 0:CE 1:CB 2:LB > 219 bool esc_, q1_, q2_, map_[128]; > 220 > 221 public: > 222 > 223 TagMap( const unicode* cb, ulong cblen, > 224 const unicode* ce, ulong celen, > 225 const unicode* lb, ulong lblen, > 226 bool q1, bool q2, bool esc ) > 227 : q1_ ( q1 ) > 228 , q2_ ( q2 ) > 229 , esc_( esc ) > 230 { > 231 // '/' で始まる記号は使われているか…? > 232 // みたいな、1文字目のみのチェックに使う表を作成 > 233 tag_[0] = tag_[1] = tag_[2] = NULL; > 234 mem00( map_, sizeof(map_) ); > 235 map_[L'\''] = q1; > 236 map_[L'\"'] = q2; > 237 map_[L'\\'] = esc; > 238 if( celen!=0 ){ map_[*ce]=true; tag_[0]=new Keyword(ce,celen); } > 239 if( cblen!=0 ){ map_[*cb]=true; tag_[1]=new Keyword(cb,cblen); } > 240 if( lblen!=0 ){ map_[*lb]=true; tag_[2]=new Keyword(lb,lblen); } > 241 } > 242 > 243 ~TagMap() > 244 { > 245 // キーワード解放 > 246 delete tag_[0]; > 247 delete tag_[1]; > 248 delete tag_[2]; > 249 } > 250 > 251 bool does_esc() > 252 { > 253 // \ によるエスケープをするかどうか > 254 return esc_; > 255 } > 256 > 257 ulong SymbolLoop( > 258 const unicode* str, ulong len, ulong& mlen, int& sym ) > 259 { > 260 // 有意味な記号にマッチするまでループ > 261 // 返値に、マッチするまでに飛ばした文字数、 > 262 // mlen,symに、マッチした記号の情報を返す > 263 > 264 int i; > 265 ulong ans=0; > 266 for( sym=sXXX, mlen=1; ans<len; ++ans ) > 267 if( map_[str[ans]] ) > 268 { > 269 for( i=2; i>=0; --i ) > 270 if( tag_[i]!=NULL > 271 && tag_[i]->len <= len-ans > 272 && compare_s( > 273 tag_[i]->str, str+ans, tag_[i]-> > 274 { > 275 sym = i; > 276 mlen = tag_[i]->len; > 277 goto symbolfound; > 278 } > 279 if( str[ans] == L'\'' ) // 一重引用符 > 280 { > 281 if( q1_ ) > 282 { > 283 sym = sQ1; > 284 goto symbolfound; > 285 } > 286 } > 287 else if( str[ans] == L'\"' ) // 二重引用符 > 288 { > 289 if( q2_ ) > 290 { > 291 sym = sQ2; > 292 goto symbolfound; > 293 } > 294 } > 295 else if( str[ans] == L'\\' ) // \ の後の文字はSkip > 296 { > 297 if( esc_ && ans+1<len ) > 298 ++ans; > 299 } > 300 } > 301 > 302 symbolfound: > 303 return ans; > 304 } > 305 }; > 306 > 307 > 308 > 309 //------------------------------------------------------------------------- > 310 // 与えられた文字列がキーワードかどうか高速判定するためのハッシュ表 > 311 //------------------------------------------------------------------------- > 312 > 313 class KeywordMap > 314 { > 315 Keyword* backet_[4096]; > 316 storage<Keyword*> dustbox_; > 317 bool (*compare_)(const unicode*,const unicode*,ulong); > 318 > 319 public: > 320 > 321 KeywordMap( bool bCaseSensitive ) > 322 : compare_( bCaseSensitive ? compare_s : compare_i ) > 323 { > 324 // ハッシュ表初期化 > 325 mem00( backet_, sizeof(backet_) ); > 326 } > 327 > 328 ~KeywordMap() > 329 { > 330 // 解放 > 331 for( ulong i=0; i<dustbox_.size(); ++i ) > 332 delete dustbox_[i]; > 333 } > 334 > 335 void AddKeyword( const unicode* str, ulong len ) > 336 { > 337 // データ登録 > 338 Keyword* x = new Keyword(str,len); > 339 int h = hash(str,len); > 340 > 341 if( backet_[h] == NULL ) > 342 { > 343 // ハッシュテーブルが空の場合 > 344 backet_[h] = x; > 345 } > 346 else > 347 { > 348 // チェイン末尾に繋ぐ場合 > 349 Keyword *q=backet_[h],*p=backet_[h]->next; > 350 while( p!=NULL ) > 351 q=p, p=p->next; > 352 q->next = x; > 353 } > 354 > 355 // データクリア用のリストにも入れておく > 356 dustbox_.Add(x); > 357 } > 358 > 359 ulong isKeyword( const unicode* str, ulong len ) > 360 { > 361 // 登録されているキーワードと一致するか? > 362 for( Keyword* p=backet_[hash(str,len)]; p!=NULL; p=p->next ) > 363 if( p->len==len && compare_( p->str, str, len ) ) > 364 return 2; > 365 return 0; > 366 } > 367 > 368 private: > 369 > 370 static int hash( const unicode* a, ulong al ) > 371 { > 372 // 12bitに潰すめっちゃ雑なハッシュ関数 > 373 // ルーチン分けるの面倒なので、大文字小文字は常に区別されない。(^^; > 374 int h=0,i=0; > 375 while( al-- ) > 376 { > 377 h ^= ((*(a++)&0xdf)<<i); > 378 i = (i+5)&7; > 379 } > 380 return h&4095; > 381 } > 382 }; > 383 > 384 > 385 > 386 //------------------------------------------------------------------------- > 387 // 以上の道具立てでもって、テキストの解析を行うParser > 388 //------------------------------------------------------------------------- > 389 } > 390 > 391 class editwing::doc::Parser > 392 { > 393 KeywordMap kwd_; > 394 TagMap tag_; > 395 > 396 public: > 397 // 初期化1 > 398 Parser( > 399 const unicode* cb, ulong cblen, > 400 const unicode* ce, ulong celen, > 401 const unicode* lb, ulong lblen, > 402 bool q1, bool q2, bool esc, > 403 bool casesensitive > 404 ) > 405 : tag_( cb, cblen, ce, celen, lb, lblen, q1, q2, esc ) > 406 , kwd_( casesensitive ) > 407 { > 408 } > 409 > 410 // 初期化2:キーワード追加 > 411 void AddKeyword( const unicode* str, ulong len ) > 412 { > 413 kwd_.AddKeyword( str, len ); > 414 } > 415 > 416 // 行データ解析 > 417 uchar Parse( Line& line, uchar cmst ) > 418 { > 419 line.TransitCmt( cmst ); > 420 > 421 // ASCII振り分けテーブル。 > 422 // シフト無しでTokenTypeに流用出来るようにするため、 > 423 // 値が4飛びになってます > 424 enum { T=0, W=4, A=8, S=12, O=0 }; > 425 static const uchar letter_type[128] = { > 426 O,O,O,O,O,O,O,O,O,T,O,O,O,O,O,O, > 427 O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O, > 428 W,S,S,S,S,S,S,S,S,S,S,S,S,S,S,S, > 429 A,A,A,A,A,A,A,A,A,A,S,S,S,S,S,S, > 430 S,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A, > 431 A,A,A,A,A,A,A,A,A,A,A,S,S,S,S,A, > 432 S,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A, > 433 A,A,A,A,A,A,A,A,A,A,A,S,S,S,S,O, > 434 }; > 435 > 436 // PosInToken算出用の距離エンコーダ( 5bitシフト済み ) > 437 // ( _d>7 ? 7<<5 : _d<<5 ) > 438 #define tkenc(_d) ( (_d)>7 ? 0xe0 : (_d)<<5 ) > 439 > 440 // コメント状態遷移追跡用オートマトン > 441 CommentDFA dfa[2] = {CommentDFA(false), CommentDFA(true)}; > 442 int& cmtState = dfa[line.isLineHeadCmt()].state; > 443 int commentbit = cmtState&1; > 444 > 445 // 作業領域 > 446 int sym; > 447 ulong j, k, um, m; > 448 uchar t, f; > 449 > 450 // ループ〜 > 451 const unicode* str = line.str(); > 452 uchar* flg = line.flg(); > 453 ulong ie = line.size(); > 454 for( ulong i=0; i<ie; i=j ) > 455 { > 456 j = i; > 457 > 458 // ASCII文字でない場合 > 459 if( str[i] >= 0x007f ) > 460 { > 461 f = (ALP | commentbit); > 462 if( str[i] == 0x3000 )//L' ' ) > 463 while( str[++j] == 0x3000 ) > 464 flg[j] = f; > 465 else > 466 while( str[++j] >= 0x80 && str[j]!=0x300 > 467 flg[j] = f; > 468 flg[i] = static_cast<uchar>(tkenc(j-i) | f); > 469 } > 470 // ASCII文字の場合?? > 471 else > 472 { > 473 t = letter_type[str[i]]; > 474 if( t==S && tag_.does_esc() ) > 475 do > 476 if( j+1<ie && str[j]==L'\\' ) > 477 j++; > 478 while( str[++j]<0x7f && S==letter_type[s > 479 else > 480 while( str[++j]<0x7f && t==letter_type[s > 481 > 482 f = (t | commentbit); > 483 > 484 switch( t ) > 485 { > 486 // アルファベット&数字 > 487 case A: > 488 f |= kwd_.isKeyword( str+i, j-i ); > 489 // fall... > 490 > 491 // タブ・制御文字 > 492 case T: > 493 // fall... > 494 > 495 // 半角空白 > 496 case W: > 497 for( k=i+1; k<j; ++k ) > 498 flg[k] = f; > 499 flg[i] = (uchar)(tkenc(j-i)|f); > 500 break; > 501 > 502 // 記号 > 503 case S: > 504 k = i; > 505 while( k < j ) > 506 { > 507 // マッチしなかった部分 > 508 um = tag_.SymbolLoop( str+k, j-k > 509 f = (0x20 | ALP | commentbit); > 510 while( um-- ) > 511 flg[k++] = f; > 512 if( k >= j ) > 513 break; > 514 > 515 // マッチした部分 > 516 f = (CE | commentbit); > 517 dfa[0].transit( sym ); > 518 dfa[1].transit( sym ); > 519 commentbit = cmtState&1; > 520 if( sym != 0 ) // 0:comment end > 521 f = (((sym+3)<<2) | comm > 522 flg[k++] = (uchar)(tkenc(m)|f); > 523 while( --m ) > 524 flg[k++] = f; > 525 } > 526 break; > 527 } > 528 } > 529 } > 530 > 531 // transitフラグ更新 > 532 line.SetTransitFlag( > 533 (dfa[1].state & (dfa[1].state<<1)) | > 534 ((dfa[0].state>>1) & dfa[0].state) > 535 ); > 536 line.CommentBitUpdated(); > 537 return line.TransitCmt( cmst ); > 538 } > 539 > 540 // コメントビットを正しく調整 > 541 void SetCommentBit( Line& line ) > 542 { > 543 CommentDFA dfa( line.isLineHeadCmt()==1 ); > 544 ulong commentbit = dfa.state&1; > 545 > 546 // ループ〜 > 547 const unicode* str = line.str(); > 548 uchar* flg = line.flg(); > 549 ulong j,k,ie = line.size(); > 550 for( ulong i=0; i<ie; i=j ) > 551 { > 552 // Tokenの終端を得る > 553 k = (flg[i]>>5); > 554 j = i + k; > 555 if( j >= ie ) > 556 j = ie; > 557 else if( k==7 ) // || k==0 ) > 558 while( (flg[j]>>5)==0 && j<ie ) > 559 ++j; > 560 > 561 k = (flg[i] & 0x1c); > 562 if( k <= CE ) > 563 { > 564 for( ; i<j; ++i ) > 565 flg[i] = (uchar)((flg[i] & 0xfe) | comme > 566 } > 567 if( k >= CE ) > 568 { > 569 dfa.transit( (k>>2)-3 ); > 570 commentbit = dfa.state&1; > 571 if( k != CE ) > 572 for( ; i<j; ++i ) > 573 flg[i] = (uchar)((flg[i] & 0xfe) > 574 } > 575 } > 576 > 577 line.CommentBitUpdated(); > 578 } > 579 }; > 580 > 581 > 582 > 583 //------------------------------------------------------------------------- > 584 // 定義ファイル読みとり処理とか > 585 //------------------------------------------------------------------------- > 586 > 587 DocImpl::DocImpl( Document& theDoc ) > 588 : doc_ ( theDoc ) > 589 , pEvHan_ ( 2 ) > 590 { > 591 text_.Add( new Line(L"",0) ); // 最初は一行だけ > 592 SetKeyword( NULL, 0 ); // キーワード無し > 593 } > 594 > 595 DocImpl::~DocImpl() > 596 { > 597 // このファイルにデストラクタを入れておかないと、 > 598 // delete parser_ が出来なくなる。^^; > 599 } > 600 > 601 void DocImpl::SetKeyword( const unicode* defbuf, ulong siz ) > 602 { > 603 // BOMがあったらスキップ > 604 if( siz!=0 && *defbuf==0xfeff ) > 605 ++defbuf, --siz; > 606 > 607 // 読み込み準備 > 608 const unicode* str; > 609 ulong len; > 610 UniReader r( defbuf, siz, &str, &len ); > 611 bool flags[] = {false,false,false,false}; > 612 const unicode* tags[] = {NULL,NULL,NULL}; > 613 ulong taglen[] = {0,0,0}; > 614 > 615 if( siz != 0 ) > 616 { > 617 // 1行目:フラグ > 618 // case? q1? q2? esc? > 619 r.getLine(); > 620 for( ulong i=0; i<len; ++i ) > 621 flags[i] = (str[i]==L'1'); > 622 > 623 // 2〜4行目 > 624 // ブロコメ開始記号、ブロコメ終了記号、行コメ記号 > 625 for( int j=0; j<3; ++j ) > 626 { > 627 r.getLine(); > 628 tags[j] = str; > 629 taglen[j] = len; > 630 } > 631 } > 632 > 633 // パーサー作成 > 634 aptr<Parser> np( new Parser( > 635 tags[0], taglen[0], tags[1], taglen[1], tags[2], taglen[2], > 636 flags[1], flags[2], flags[3], flags[0] ) ); > 637 parser_ = np; > 638 > 639 // 5行目以降:キーワードリスト > 640 while( !r.isEmpty() ) > 641 { > 642 r.getLine(); > 643 if( len != 0 ) > 644 parser_->AddKeyword( str, len ); > 645 } > 646 > 647 // 全行解析し直し > 648 ReParse( 0, tln()-1 ); > 649 > 650 // 変更通知 > 651 Fire_KEYWORDCHANGE(); > 652 } > 653 > 654 bool DocImpl::ReParse( ulong s, ulong e ) > 655 { > 656 ulong i; > 657 uchar cmt = text_[s].isLineHeadCmt(); > 658 > 659 // まずは変更範囲を再解析 > 660 for( i=s; i<=e; ++i ) > 661 cmt = parser_->Parse( text_[i], cmt ); > 662 > 663 // コメントアウト状態に変化がなかったらここでお終い。 > 664 if( i==tln() || text_[i].isLineHeadCmt()==cmt ) > 665 return false; > 666 > 667 // 例えば、/* が入力された場合などは、下の方の行まで > 668 // コメントアウト状態の変化を伝達する必要がある。 > 669 do > 670 cmt = text_[i++].TransitCmt( cmt ); > 671 while( i<tln() && text_[i].isLineHeadCmt()!=cmt ); > 672 return true; > 673 } > 674 > 675 void DocImpl::SetCommentBit( const Line& x ) const > 676 { > 677 parser_->SetCommentBit( const_cast<Line&>(x) ); > 678 }

Added editwing/ip_scroll.cpp version [a2aa2ab09e9c8e83]

> 1 #include "stdafx.h" > 2 #include "ip_view.h" > 3 using namespace editwing; > 4 using namespace editwing::view; > 5 > 6 > 7 > 8 //========================================================================= > 9 //---- ip_scroll.cpp スクロール > 10 // > 11 // ウインドウサイズはスクロールバーの位置によって > 12 // 描画位置を適当に更新していく処理がここ。 > 13 // > 14 //---- ip_text.cpp 文字列操作・他 > 15 //---- ip_parse.cpp キーワード解析 > 16 //---- ip_wrap.cpp 折り返し > 17 //---- ip_draw.cpp 描画・他 > 18 //---- ip_cursor.cpp カーソルコントロール > 19 //========================================================================= > 20 > 21 > 22 > 23 //------------------------------------------------------------------------- > 24 // 描画領域サイズ管理 > 25 //------------------------------------------------------------------------- > 26 > 27 namespace > 28 { > 29 static int Log10( ulong n ) > 30 { > 31 const static ulong power_of_ten[] = > 32 { 1, 10, 100, 1000, 10000, 100000, 1000000, > 33 10000000, 100000000, 1000000000 }; // 10^0 〜 10^9 > 34 int c=3; > 35 if( power_of_ten[9] <= n ) > 36 c=10; > 37 else > 38 while( power_of_ten[c] <= n ) > 39 c++; > 40 return c; // 3<=c<=10 s.t. 10^(c-1) <= n < 10^c > 41 } > 42 } > 43 > 44 bool Canvas::CalcLNAreaWidth() > 45 { > 46 const int prev = txtZone_.left; > 47 if( showLN_ ) > 48 { > 49 txtZone_.left = (1 + figNum_) * font_->F(); > 50 if( txtZone_.left+font_->W() >= txtZone_.right ) > 51 txtZone_.left = 0; // 行番号ゾーンがデカすぎるときは表示しない > 52 } > 53 else > 54 { > 55 txtZone_.left = 0; > 56 } > 57 > 58 return (prev != txtZone_.left); > 59 } > 60 > 61 void Canvas::CalcWrapWidth() > 62 { > 63 switch( wrapType_ ) > 64 { > 65 case NOWRAP: > 66 wrapWidth_ = 0xffffffff; > 67 break; > 68 case RIGHTEDGE: > 69 wrapWidth_ = txtZone_.right - txtZone_.left - 3; > 70 break; //Caretの分-3補正 > 71 default: > 72 wrapWidth_ = wrapType_ * font_->W(); > 73 break; > 74 } > 75 } > 76 > 77 Canvas::Canvas( const View& vw ) > 78 : wrapType_ ( -1 ) > 79 , showLN_ ( false ) > 80 , wrapWidth_( 0xffffffff ) > 81 , figNum_ ( 3 ) > 82 , font_ ( new Painter( ::GetDC(vw.hwnd()), > 83 VConfig(TEXT("FixedSys"),14) ) ) > 84 { > 85 vw.getClientRect( &txtZone_ ); > 86 } > 87 > 88 bool Canvas::on_view_resize( int cx, int cy ) > 89 { > 90 txtZone_.right = cx; > 91 txtZone_.bottom = cy; > 92 > 93 CalcLNAreaWidth(); > 94 if( wrapType_ == RIGHTEDGE ) > 95 { > 96 CalcWrapWidth(); > 97 return true; > 98 } > 99 return false; > 100 } > 101 > 102 void Canvas::on_font_change( const VConfig& vc ) > 103 { > 104 HDC dc = font_->getDC(); > 105 font_ = NULL; // 先にデストラクタを呼ばねばならない… > 106 // ってうわー格好悪ぃーーー(T_T) > 107 font_ = new Painter( dc, vc ); > 108 > 109 CalcLNAreaWidth(); > 110 CalcWrapWidth(); > 111 } > 112 > 113 void Canvas::on_config_change( int wrap, bool showln ) > 114 { > 115 showLN_ = showln; > 116 wrapType_ = wrap; > 117 > 118 CalcLNAreaWidth(); > 119 CalcWrapWidth(); > 120 } > 121 > 122 bool Canvas::on_tln_change( ulong tln ) > 123 { > 124 figNum_ = Log10( tln ); // 桁数計算 > 125 > 126 if( CalcLNAreaWidth() ) > 127 { > 128 if( wrapType_ == RIGHTEDGE ) > 129 CalcWrapWidth(); > 130 return true; > 131 } > 132 return false; > 133 } > 134 > 135 > 136 > 137 //------------------------------------------------------------------------- > 138 // スクロールバー計算ルーチン > 139 //------------------------------------------------------------------------- > 140 // rl (横スクロール情報) > 141 // max: view.txt.txtwidth() > 142 // page: view.cx() > 143 // pos: 0〜max-page > 144 > 145 // ud (縦スクロール情報) > 146 // max: view.txt.vln() + page - 1 > 147 // page: view.cy() / view.fnt.H() > 148 // delta: 0〜view.fnt.H() > 149 // pos: 0〜max-page (topの行番号) > 150 > 151 bool ViewImpl::ReSetScrollInfo() > 152 { > 153 const int prevRlPos = rlScr_.nPos; > 154 const ulong cx = cvs_.zone().right - cvs_.zone().left; > 155 const ulong cy = cvs_.zone().bottom; > 156 > 157 // 横は変な値にならないよう補正するだけでよい > 158 // rlScr_.nPage = cx + 1; > 159 // rlScr_.nMax = Max( textCx_, cx ); > 160 // rlScr_.nPos = Min<int>( rlScr_.nPos, rlScr_.nMax-rlScr_.nPage+1 ); > 161 rlScr_.nPage = cx + 1; > 162 rlScr_.nMax = Max( textCx_+3, cx ); > 163 rlScr_.nPos = Min<int>( rlScr_.nPos, rlScr_.nMax-rlScr_.nPage+1 ); > 164 > 165 // 縦はnPageとnMaxはとりあえず補正 > 166 // nPosは場合によって直し方が異なるので別ルーチンにて > 167 udScr_.nPage = cy / cvs_.getPainter().H() + 1; > 168 udScr_.nMax = vln() + udScr_.nPage - 2; > 169 > 170 // 横スクロールが起きたらtrue > 171 return (prevRlPos != rlScr_.nPos); > 172 } > 173 > 174 void ViewImpl::ForceScrollTo( ulong tl ) > 175 { > 176 udScr_.nPos = tl2vl(tl); > 177 udScr_tl_ = tl; > 178 udScr_vrl_ = 0; > 179 } > 180 > 181 ulong ViewImpl::tl2vl( ulong tl ) const > 182 { > 183 if( vln() == doc_.tln() ) > 184 return tl; > 185 > 186 ulong vl=0; > 187 for( ulong i=0; i<tl; ++i ) > 188 vl += rln(i); > 189 return vl; > 190 } > 191 > 192 void ViewImpl::UpdateScrollBar() > 193 { > 194 ::SetScrollInfo( hwnd_, SB_HORZ, &rlScr_, TRUE ); > 195 ::SetScrollInfo( hwnd_, SB_VERT, &udScr_, TRUE ); > 196 } > 197 > 198 ReDrawType ViewImpl::TextUpdate_ScrollBar > 199 ( const DPos& s, const DPos& e, const DPos& e2 ) > 200 { > 201 const ulong prevUdMax = udScr_.nMax; > 202 const bool rlScrolled = ReSetScrollInfo(); > 203 const long vl_dif = (udScr_.nMax - prevUdMax); > 204 ReDrawType ans = > 205 (vl_dif!=0 || s.tl!=e2.tl ? AFTER : LINE); > 206 > 207 if( udScr_tl_ < s.tl ) > 208 { > 209 // パターン1:現在の画面上端より下で更新された場合 > 210 // スクロールしない > 211 } > 212 else if( udScr_tl_ == s.tl ) > 213 { > 214 // パターン2:現在の画面上端と同じ行で更新された場合 > 215 // 出来るだけ同じ位置を表示し続けようと試みる。 > 216 > 217 if( static_cast<ulong>(udScr_.nPos) >= vln() ) > 218 { > 219 // パターン2-1:しかしそこはすでにEOFよりも下だ! > 220 // しゃーないので一番下の行を表示 > 221 udScr_.nPos = vln()-1; > 222 udScr_tl_ = doc_.tln()-1; > 223 udScr_vrl_ = rln(udScr_tl_)-1; > 224 ans = ALL; > 225 } > 226 else > 227 { > 228 // パターン2-2: > 229 // スクロール無し > 230 while( udScr_vrl_ >= rln(udScr_tl_) ) > 231 { > 232 udScr_vrl_ -= rln(udScr_tl_); > 233 udScr_tl_++; > 234 } > 235 } > 236 } > 237 else > 238 { > 239 // パターン3:現在の画面上端より上で更新された場合 > 240 // 表示内容を変えないように頑張る > 241 > 242 if( e.tl < udScr_tl_ ) > 243 { > 244 // パターン3-1:変更範囲の終端も、現在行より上の場合 > 245 // 行番号は変わるが表示内容は変わらないで済む > 246 udScr_.nPos += vl_dif; > 247 udScr_tl_ += (e2.tl - e.tl); > 248 ans = LNAREA; > 249 } > 250 else > 251 { > 252 // パターン3-2: > 253 // どうしよーもないので適当な位置にスクロール > 254 ForceScrollTo( e2.tl ); > 255 ans = ALL; > 256 } > 257 } > 258 > 259 // どんな再描画をすればよいか返す > 260 return (rlScrolled ? ALL : ans); > 261 } > 262 > 263 void ViewImpl::ScrollTo( const VPos& vp ) > 264 { > 265 // 横フォーカス > 266 int dx=0; > 267 if( vp.vx < (signed)rlScr_.nPos ) > 268 { > 269 dx = vp.vx - rlScr_.nPos; > 270 } > 271 else > 272 { > 273 const int W = cvs_.getPainter().W(); > 274 if( rlScr_.nPos + (signed)(rlScr_.nPage-W) <= vp.vx ) > 275 dx = vp.vx - (rlScr_.nPos + rlScr_.nPage) + W; > 276 } > 277 > 278 // 縦フォーカス > 279 int dy=0; > 280 if( vp.vl < (unsigned)udScr_.nPos ) > 281 dy = vp.vl - udScr_.nPos; > 282 else if( udScr_.nPos + (udScr_.nPage-1) <= vp.vl ) > 283 dy = vp.vl - (udScr_.nPos + udScr_.nPage) + 2; > 284 > 285 // スクロール > 286 if( dy!=0 ) UpDown( dy, dx==0 ); > 287 if( dx!=0 ) ScrollView( dx, 0, true ); > 288 } > 289 > 290 void ViewImpl::GetDrawPosInfo( VDrawInfo& v ) const > 291 { > 292 const int H = cvs_.getPainter().H(); > 293 > 294 long most_under = (vln()-udScr_.nPos)*H; > 295 if( most_under <= v.rc.top ) > 296 { > 297 v.YMIN = v.rc.top; > 298 v.YMAX = most_under; > 299 } > 300 else > 301 { > 302 int y = -(signed)udScr_vrl_; > 303 ulong tl = udScr_tl_; > 304 int top = v.rc.top / H; > 305 while( y + (signed)rln(tl) <= top ) > 306 y += rln( tl++ ); > 307 > 308 // 縦座標 > 309 v.YMIN = y * H; > 310 v.YMAX = Min( v.rc.bottom, most_under ); > 311 v.TLMIN = tl; > 312 > 313 // 横座標 > 314 v.XBASE = left() - rlScr_.nPos; > 315 v.XMIN = v.rc.left - v.XBASE; > 316 v.XMAX = v.rc.right - v.XBASE; > 317 > 318 // 選択範囲 > 319 v.SXB = v.SXE = v.SYB = v.SYE = 0x7fffffff; > 320 > 321 const VPos *bg, *ed; > 322 if( cur_.getCurPos( &bg, &ed ) ) > 323 { > 324 v.SXB = bg->vx - rlScr_.nPos + left(); > 325 v.SXE = ed->vx - rlScr_.nPos + left(); > 326 v.SYB = (bg->vl - udScr_.nPos) * H; > 327 v.SYE = (ed->vl - udScr_.nPos) * H; > 328 } > 329 } > 330 } > 331 > 332 void ViewImpl::ScrollView( int dx, int dy, bool update ) > 333 { > 334 // スクロール開始通知 > 335 cur_.on_scroll_begin(); > 336 > 337 const RECT* clip = (dy==0 ? &cvs_.zone() : NULL); > 338 const int H = cvs_.getPainter().H(); > 339 > 340 // スクロールバー更新 > 341 if( dx != 0 ) > 342 { > 343 // 範囲チェック > 344 if( rlScr_.nPos+dx < 0 ) > 345 dx = -rlScr_.nPos; > 346 else if( rlScr_.nMax-(signed)rlScr_.nPage < rlScr_.nPos+dx ) > 347 dx = rlScr_.nMax-rlScr_.nPage-rlScr_.nPos+1; > 348 > 349 rlScr_.nPos += dx; > 350 ::SetScrollInfo( hwnd_, SB_HORZ, &rlScr_, TRUE ); > 351 dx = -dx; > 352 } > 353 if( dy != 0 ) > 354 { > 355 // 範囲チェック…は前処理で終わってる。 > 356 > 357 udScr_.nPos += dy; > 358 ::SetScrollInfo( hwnd_, SB_VERT, &udScr_, TRUE ); > 359 dy *= -H; > 360 } > 361 if( dx!=0 || dy!=0 ) > 362 { > 363 if( -dx>=right() || dx>=right() > 364 || -dy>=bottom() || dy>=bottom() ) > 365 { > 366 // 全画面再描画 > 367 // ちょうど65536の倍数くらいスクロールしたときに、 > 368 // ScrollWindowEx on Win9x だと再描画が変なのを回避。 > 369 ::InvalidateRect( hwnd_, NULL, FALSE ); > 370 } > 371 else > 372 { > 373 // 再描画の不要な領域をスクロール > 374 ::ScrollWindowEx( hwnd_, dx, dy, NULL, > 375 clip, NULL, NULL, SW_INVALIDATE ); > 376 > 377 // 即時再描画? > 378 if( update ) > 379 { > 380 // 縦スクロールは高速化したいので一工夫 > 381 if( dy != 0 ) > 382 { > 383 // 再描画の必要な領域を自分で計算 > 384 RECT rc = {0,0,right(),bottom()}; > 385 if( dy < 0 ) rc.top = rc.bottom + dy; > 386 else rc.bottom = dy; > 387 > 388 // インテリマウスの中ボタンクリックによる > 389 // オートスクロール用カーソルの下の部分を先に描く > 390 // 2回に分けることで、小さな矩形部分二つで済むので高速 > 391 ::ValidateRect( hwnd_, &rc ); > 392 ::UpdateWindow( hwnd_ ); > 393 ::InvalidateRect( hwnd_, &rc, FALSE ); > 394 } > 395 ::UpdateWindow( hwnd_ ); > 396 } > 397 } > 398 } > 399 > 400 // スクロール終了通知 > 401 cur_.on_scroll_end(); > 402 } > 403 > 404 void ViewImpl::on_hscroll( int code ) > 405 { > 406 // 変化量を計算 > 407 int dx; > 408 switch( code ) > 409 { > 410 default: return; > 411 case SB_LINELEFT: dx= -cvs_.getPainter().W(); break; > 412 case SB_LINERIGHT: dx= +cvs_.getPainter().W(); break; > 413 case SB_PAGELEFT: dx= -(cx()>>1); break; > 414 case SB_PAGERIGHT: dx= +(cx()>>1); break; > 415 case SB_THUMBTRACK: > 416 { > 417 SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS }; > 418 ::GetScrollInfo( hwnd_, SB_HORZ, &si ); > 419 dx = si.nTrackPos - rlScr_.nPos; > 420 break; > 421 } > 422 case SB_LEFT: dx = -rlScr_.nPos; break; > 423 case SB_RIGHT: dx = rlScr_.nMax+1-(signed)rlScr_.nPage-rlScr_.nPos; br > 424 } > 425 > 426 // スクロール > 427 ScrollView( dx, 0, code!=SB_THUMBTRACK ); > 428 } > 429 > 430 void ViewImpl::on_vscroll( int code ) > 431 { > 432 // 変化量を計算 > 433 int dy; > 434 switch( code ) > 435 { > 436 default: return; > 437 case SB_LINEUP: dy= -1; break; > 438 case SB_LINEDOWN: dy= +1; break; > 439 case SB_PAGEUP: dy= -(cy() / cvs_.getPainter().H()); break; > 440 case SB_PAGEDOWN: dy= +(cy() / cvs_.getPainter().H()); break; > 441 case SB_THUMBTRACK: > 442 { > 443 SCROLLINFO si = { sizeof(SCROLLINFO), SIF_TRACKPOS }; > 444 ::GetScrollInfo( hwnd_, SB_VERT, &si ); > 445 dy = si.nTrackPos - udScr_.nPos; > 446 break; > 447 } > 448 case SB_TOP: dy = -udScr_.nPos; break; > 449 case SB_BOTTOM: dy = udScr_.nMax+1-(signed)udScr_.nPage-udScr_.nPos; b > 450 } > 451 > 452 // スクロール > 453 UpDown( dy, code==SB_THUMBTRACK ); > 454 } > 455 > 456 void ViewImpl::on_wheel( short delta ) > 457 { > 458 // スクロール > 459 UpDown( -delta / WHEEL_DELTA * 3, false ); > 460 } > 461 > 462 void ViewImpl::UpDown( int dy, bool thumb ) > 463 { > 464 // 1.udScr_.nPos + dy が正常範囲に収まるように補正 > 465 if( udScr_.nPos+dy < 0 ) > 466 dy = -udScr_.nPos; > 467 else if( udScr_.nMax+1-(signed)udScr_.nPage < udScr_.nPos+dy ) > 468 dy = udScr_.nMax+1-udScr_.nPage-udScr_.nPos; > 469 if( dy==0 ) > 470 return; > 471 > 472 // 2−1.折り返し無しの場合は一気にジャンプ出来る > 473 if( !wrapexists() ) > 474 { > 475 udScr_tl_ = udScr_.nPos + dy; > 476 } > 477 > 478 // 2−2.でなけりゃ、現在位置からの相対サーチ > 479 // ScrollBarを連続的にドラッグせず一度に一気に飛んだ場合は > 480 // 1行目や最終行からの相対サーチの方が有効な可能性があるが、 > 481 // その場合は多少速度が遅くなっても描画が引っかかることはないのでOK > 482 else > 483 { > 484 int rl = dy + udScr_vrl_; > 485 ulong tl = udScr_tl_; > 486 > 487 if( dy<0 ) // 上へ戻る場合 > 488 { > 489 // ジャンプ先論理行の行頭へDash! > 490 while( rl < 0 ) > 491 rl += rln(--tl); > 492 } > 493 else if( dy>0 ) // 下へ進む場合 > 494 { > 495 // ジャンプ先論理行の行頭へDash! > 496 while( rl > 0 ) > 497 rl -= rln(tl++); > 498 if( rl < 0 ) > 499 rl += rln(--tl); //行き過ぎ修正 > 500 } > 501 udScr_tl_ = tl; > 502 udScr_vrl_= static_cast<ulong>(rl); > 503 } > 504 > 505 // 4.画面をスクロール > 506 ScrollView( 0, dy, !thumb ); > 507 } > 508 > 509 void ViewImpl::InvalidateView( const DPos& dp, bool afterall ) const > 510 { > 511 const int H = cvs_.getPainter().H(); > 512 > 513 // 表示域より上での更新 > 514 if( dp.tl < udScr_tl_ ) > 515 { > 516 if( afterall ) > 517 ::InvalidateRect( hwnd_, NULL, FALSE ); > 518 return; > 519 } > 520 > 521 // 開始y座標計算 > 522 int r=0, yb=-(signed)udScr_vrl_; > 523 for( int t=udScr_tl_, ybe=cy()/H; (unsigned)t<dp.tl; yb+=rln(t++) ) > 524 if( yb >= ybe ) > 525 return; > 526 for( ; dp.ad>rlend(dp.tl,r); ++r,++yb ); > 527 yb = H * Max( yb, -100 ); // 上にはみ出し過ぎないよう調整 > 528 if( yb >= cy() ) > 529 return; > 530 > 531 // 1行目を再描画 > 532 int rb = (r==0 ? 0 : rlend(dp.tl,r-1)); > 533 int xb = left() + Max( 0UL, > 534 CalcLineWidth(doc_.tl(dp.tl)+rb,dp.ad-rb) -rlScr_.nPos ); > 535 if( xb < right() ) > 536 { > 537 RECT rc={xb,yb,right(),yb+H}; > 538 ::InvalidateRect( hwnd_, &rc, FALSE ); > 539 } > 540 > 541 // 残り > 542 int ye; > 543 yb += H; > 544 if( afterall ) > 545 xb=0, ye=cy(); > 546 else > 547 xb=left(), ye=Min(cy(),yb+(int)(H*(rln(dp.tl)-r-1))); > 548 if( yb < ye ) > 549 { > 550 RECT rc={xb,yb,right(),ye}; > 551 ::InvalidateRect( hwnd_, &rc, FALSE ); > 552 } > 553 }

Added editwing/ip_text.cpp version [0cf9b5928d0aca8a]

> 1 #include "stdafx.h" > 2 #include "ip_doc.h" > 3 using namespace editwing; > 4 using namespace editwing::doc; > 5 > 6 > 7 > 8 //========================================================================= > 9 //---- ip_text.cpp 文字列操作・他 > 10 // > 11 // 文字列を挿入したり削除したり…という辺りの処理が > 12 // このファイルにまとめてある。外向けのインターフェイスの > 13 // 実装もついでにここで。 > 14 // > 15 //---- ip_parse.cpp キーワード解析 > 16 //---- ip_wrap.cpp 折り返し > 17 //---- ip_scroll.cpp スクロール > 18 //---- ip_draw.cpp 描画・他 > 19 //---- ip_cursor.cpp カーソルコントロール > 20 //========================================================================= > 21 > 22 > 23 > 24 //------------------------------------------------------------------------- > 25 // 公開インターフェイス > 26 //------------------------------------------------------------------------- > 27 > 28 Document::Document() : busy_(false) > 29 { impl_ = new DocImpl( *this ); } > 30 > 31 Document::~Document() > 32 {} > 33 > 34 void Document::Execute( const Command& c ) > 35 { impl_->Execute( c ); } > 36 > 37 void Document::SetKeyword( const unicode* b, ulong s ) > 38 { impl_->SetKeyword( b, s ); } > 39 > 40 void Document::AddHandler( DocEvHandler* h ) > 41 { impl_->AddHandler( h ); } > 42 > 43 void Document::DelHandler( DocEvHandler* h ) > 44 { impl_->DelHandler( h ); } > 45 > 46 void Document::OpenFile( aptr<TextFileR> t ) > 47 { impl_->OpenFile( t ); } > 48 > 49 void Document::SaveFile( TextFileW& t ) > 50 { impl_->SaveFile( t ); } > 51 > 52 void Document::ClearAll() > 53 { impl_->ClearAll(); } > 54 > 55 ulong Document::tln() const > 56 { return impl_->tln(); } > 57 > 58 const unicode* Document::tl( ulong i ) const > 59 { return impl_->tl( i ); } > 60 > 61 ulong Document::len( ulong i ) const > 62 { return impl_->len( i ); } > 63 > 64 ulong Document::getRangeLength( const DPos& s, const DPos& e ) const > 65 { return impl_->getRangeLength( s, e ); } > 66 > 67 void Document::getText( unicode* b, const DPos& s, const DPos& e ) const > 68 { impl_->getText( b, s, e ); } > 69 > 70 bool Document::isUndoAble() const > 71 { return impl_->isUndoAble(); } > 72 > 73 bool Document::isRedoAble() const > 74 { return impl_->isRedoAble(); } > 75 > 76 bool Document::isModified() const > 77 { return impl_->isModified(); } > 78 > 79 void Document::ClearModifyFlag() > 80 { impl_->ClearModifyFlag(); } > 81 > 82 void Document::Undo() > 83 { impl_->Undo(); } > 84 > 85 void Document::Redo() > 86 { impl_->Redo(); } > 87 > 88 void Document::SetUndoLimit( long lim ) > 89 { impl_->SetUndoLimit( lim ); } > 90 > 91 > 92 > 93 //------------------------------------------------------------------------- > 94 // イベントハンドラ処理 > 95 //------------------------------------------------------------------------- > 96 > 97 void DocImpl::AddHandler( DocEvHandler* eh ) > 98 { > 99 // ハンドラ追加 > 100 pEvHan_.Add( eh ); > 101 } > 102 > 103 void DocImpl::DelHandler( DocEvHandler* eh ) > 104 { > 105 // 後ろから見て行って… > 106 const int last = pEvHan_.size() - 1; > 107 > 108 // …見つけたら削除 > 109 for( int i=last; i>=0; --i ) > 110 if( pEvHan_[i] == eh ) > 111 { > 112 pEvHan_[i] = pEvHan_[last]; > 113 pEvHan_.ForceSize( last ); > 114 break; > 115 } > 116 } > 117 > 118 void DocImpl::Fire_TEXTUPDATE > 119 ( const DPos& s, const DPos& e, const DPos& e2, bool reparsed, bool nmlc > 120 { > 121 AutoLock lk(this); > 122 > 123 // 全部にイベント通知 > 124 for( ulong i=0, ie=pEvHan_.size(); i<ie; ++i ) > 125 pEvHan_[i]->on_text_update( s, e, e2, reparsed, nmlcmd ); > 126 } > 127 > 128 void DocImpl::Fire_KEYWORDCHANGE() > 129 { > 130 AutoLock lk(this); > 131 > 132 // 全部にイベント通知 > 133 for( ulong i=0, ie=pEvHan_.size(); i<ie; ++i ) > 134 pEvHan_[i]->on_keyword_change(); > 135 } > 136 > 137 void DocImpl::Fire_MODIFYFLAGCHANGE() > 138 { > 139 AutoLock lk(this); > 140 > 141 // 全部にイベント通知 > 142 bool b = urdo_.isModified(); > 143 for( ulong i=0, ie=pEvHan_.size(); i<ie; ++i ) > 144 pEvHan_[i]->on_dirtyflag_change( b ); > 145 } > 146 > 147 > 148 > 149 //------------------------------------------------------------------------- > 150 // UnDo,ReDo 処理 > 151 //------------------------------------------------------------------------- > 152 > 153 UnReDoChain::Node::Node( Command* c, Node* p, Node* n ) > 154 : cmd_ ( c ) > 155 , prev_( p ) > 156 , next_( n ) > 157 { > 158 } > 159 > 160 UnReDoChain::Node::Node() > 161 { > 162 next_ = prev_ = this; > 163 cmd_ = NULL; > 164 } > 165 > 166 UnReDoChain::Node::~Node() > 167 { > 168 delete cmd_; > 169 } > 170 > 171 void UnReDoChain::Node::ResetCommand( Command* cmd ) > 172 { > 173 delete cmd_; > 174 cmd_ = cmd; > 175 } > 176 > 177 UnReDoChain::UnReDoChain() > 178 : lastOp_ ( &headTail_ ) > 179 , savedPos_( &headTail_ ) > 180 , num_ ( 0 ) > 181 , limit_ ( static_cast<ulong>(-1) ) > 182 { > 183 } > 184 > 185 UnReDoChain::~UnReDoChain() > 186 { > 187 Clear(); > 188 } > 189 > 190 ulong UnReDoChain::Node::ChainDelete(Node*& savedPos_ref) > 191 { > 192 if( cmd_ == NULL ) > 193 return 0; > 194 if( savedPos_ref == this ) > 195 savedPos_ref = NULL; > 196 dptr<Node> d(this); > 197 return 1 + next_->ChainDelete(savedPos_ref); > 198 } > 199 > 200 void UnReDoChain::Clear() > 201 { > 202 headTail_.next_->ChainDelete(savedPos_); > 203 headTail_.next_ = headTail_.prev_ = lastOp_ = savedPos_ = &headTail_; > 204 num_ = 0; > 205 } > 206 > 207 void UnReDoChain::SetLimit( long lim ) > 208 { > 209 limit_ = Max( 1UL, ulong(lim) ); > 210 } > 211 > 212 inline void UnReDoChain::Undo( Document& doc ) > 213 { > 214 lastOp_->ResetCommand( (*lastOp_->cmd_)(doc) ); > 215 lastOp_ = lastOp_->prev_; > 216 } > 217 > 218 inline void UnReDoChain::Redo( Document& doc ) > 219 { > 220 lastOp_ = lastOp_->next_; > 221 lastOp_->ResetCommand( (*lastOp_->cmd_)(doc) ); > 222 } > 223 > 224 void UnReDoChain::NewlyExec( const Command& cmd, Document& doc ) > 225 { > 226 Command* nCmd = cmd(doc); > 227 if( nCmd != NULL ) > 228 { > 229 num_ -= (lastOp_->next_->ChainDelete(savedPos_) - 1); > 230 lastOp_ = lastOp_->next_ = new Node(nCmd,lastOp_,&headTail_); > 231 > 232 while( limit_ < num_ ) > 233 { > 234 // 回数制限を越えたので、古い物を削除 > 235 Node* old = headTail_.next_; > 236 headTail_.next_ = old->next_; > 237 old->next_->prev_ = &headTail_; > 238 if( old != &headTail_ ) > 239 delete old; > 240 if( savedPos_ == &headTail_ ) > 241 savedPos_ = NULL; > 242 else if( savedPos_ == old ) > 243 savedPos_ = &headTail_; > 244 --num_; > 245 } > 246 } > 247 } > 248 > 249 > 250 > 251 bool DocImpl::isUndoAble() const > 252 { return urdo_.isUndoAble(); } > 253 > 254 bool DocImpl::isRedoAble() const > 255 { return urdo_.isRedoAble(); } > 256 > 257 bool DocImpl::isModified() const > 258 { return urdo_.isModified(); } > 259 > 260 void DocImpl::SetUndoLimit( long lim ) > 261 { urdo_.SetLimit( lim ); } > 262 > 263 void DocImpl::ClearModifyFlag() > 264 { > 265 bool b = urdo_.isModified(); > 266 urdo_.SavedHere(); > 267 if( b != urdo_.isModified() ) > 268 Fire_MODIFYFLAGCHANGE(); > 269 } > 270 > 271 void DocImpl::Undo() > 272 { > 273 if( urdo_.isUndoAble() ) > 274 { > 275 bool b = urdo_.isModified(); > 276 urdo_.Undo(doc_); > 277 if( b != urdo_.isModified() ) > 278 Fire_MODIFYFLAGCHANGE(); > 279 } > 280 } > 281 > 282 void DocImpl::Redo() > 283 { > 284 if( urdo_.isRedoAble() ) > 285 { > 286 bool b = urdo_.isModified(); > 287 urdo_.Redo(doc_); > 288 if( b != urdo_.isModified() ) > 289 Fire_MODIFYFLAGCHANGE(); > 290 } > 291 } > 292 > 293 void DocImpl::Execute( const Command& cmd ) > 294 { > 295 bool b = urdo_.isModified(); > 296 urdo_.NewlyExec( cmd, doc_ ); > 297 if( b != urdo_.isModified() ) > 298 Fire_MODIFYFLAGCHANGE(); > 299 } > 300 > 301 > 302 > 303 //------------------------------------------------------------------------- > 304 // カーソル移動ヘルパー > 305 //------------------------------------------------------------------------- > 306 > 307 DPos DocImpl::leftOf( const DPos& dp, bool wide ) const > 308 { > 309 if( dp.ad == 0 ) > 310 { > 311 // 行の先頭だが、ファイルの先頭ではない場合 > 312 // 一つ前の行の行末へ > 313 if( dp.tl > 0 ) > 314 return DPos( dp.tl-1, len(dp.tl-1) ); > 315 return dp; > 316 } > 317 else if( !wide ) > 318 { > 319 // 行の途中で、普通に1文字戻る場合 > 320 const unicode* l = tl(dp.tl); > 321 if( dp.ad>=2 && isLowSurrogate(l[dp.ad-1]) && isHighSurrogate(l[ > 322 return DPos( dp.tl, dp.ad-2 ); > 323 return DPos( dp.tl, dp.ad-1 ); > 324 } > 325 else > 326 { > 327 // 行の途中で、1単語分戻る場合 > 328 const uchar* f = pl(dp.tl); > 329 ulong s = dp.ad-1; > 330 while( (f[s]>>5)==0 && 0<=s ) > 331 --s; > 332 return DPos( dp.tl, s ); > 333 } > 334 } > 335 > 336 DPos DocImpl::rightOf( const DPos& dp, bool wide ) const > 337 { > 338 if( dp.ad == len(dp.tl) ) > 339 { > 340 // 行末だが、ファイルの終わりではない場合 > 341 // 一つ後の行の先頭へ > 342 if( dp.tl < tln()-1 ) > 343 return DPos( dp.tl+1, 0 ); > 344 return dp; > 345 } > 346 else if( !wide ) > 347 { > 348 // 行の途中で、普通に1文字進む場合 > 349 const unicode* l = tl(dp.tl); > 350 // 番兵 0x007f が l の末尾にいるので長さチェックは不要 > 351 if( isHighSurrogate(l[dp.ad]) && isLowSurrogate(l[dp.ad+1]) ) > 352 return DPos( dp.tl, dp.ad+2 ); > 353 return DPos( dp.tl, dp.ad+1 ); > 354 } > 355 else > 356 { > 357 // 行の途中で、普通に1単語進む場合 > 358 const uchar* f = pl(dp.tl); > 359 const ulong e = len(dp.tl); > 360 ulong s = dp.ad; > 361 const ulong t = (f[s]>>5); > 362 s += t; > 363 if( s >= e ) > 364 s = e; > 365 else if( t==7 || t==0 ) > 366 while( (f[s]>>5)==0 && s<e ) > 367 ++s; > 368 return DPos( dp.tl, s ); > 369 } > 370 } > 371 > 372 DPos DocImpl::wordStartOf( const DPos& dp ) const > 373 { > 374 if( dp.ad == 0 ) > 375 { > 376 // 行の先頭 > 377 return dp; > 378 } > 379 else > 380 { > 381 // 行の途中 > 382 const uchar* f = pl(dp.tl); > 383 ulong s = dp.ad; > 384 while( (f[s]>>5)==0 && 0<=s ) > 385 --s; > 386 return DPos( dp.tl, s ); > 387 } > 388 } > 389 > 390 > 391 > 392 //------------------------------------------------------------------------- > 393 // 挿入・削除等の作業用関数群 > 394 //------------------------------------------------------------------------- > 395 > 396 ulong DocImpl::getRangeLength( const DPos& s, const DPos& e ) > 397 { > 398 // とりあえず全部足す > 399 ulong ans=0, tl=s.tl, te=e.tl; > 400 for( ; tl<=te; ++tl ) > 401 ans += len(tl); > 402 // 先頭行の分を引く > 403 ans -= s.ad; > 404 // 最終行の分を引く > 405 ans -= len(te) - e.ad; > 406 // 改行コード(CRLF)の分を加える > 407 ans += (e.tl-s.tl) * 2; > 408 // おしまい > 409 return ans; > 410 } > 411 > 412 void DocImpl::getText( unicode* buf, const DPos& s, const DPos& e ) > 413 { > 414 if( s.tl == e.tl ) > 415 { > 416 // 一行だけの場合 > 417 text_[s.tl].CopyAt( s.ad, e.ad-s.ad, buf ); > 418 buf[e.ad-s.ad] = L'\0'; > 419 } > 420 else > 421 { > 422 // 先頭行の後ろをコピー > 423 buf += text_[s.tl].CopyToTail( s.ad, buf ); > 424 *buf++ = L'\r', *buf++ = L'\n'; > 425 // 途中をコピー > 426 for( ulong i=s.tl+1; i<e.tl; i++ ) > 427 { > 428 buf += text_[i].CopyToTail( 0, buf ); > 429 *buf++ = L'\r', *buf++ = L'\n'; > 430 } > 431 // 終了行の先頭をコピー > 432 buf += text_[e.tl].CopyAt( 0, e.ad, buf ); > 433 *buf = L'\0'; > 434 } > 435 } > 436 > 437 void DocImpl::CorrectPos( DPos& pos ) > 438 { > 439 // 正常範囲に収まるように修正 > 440 pos.tl = Min( pos.tl, tln()-1 ); > 441 pos.ad = Min( pos.ad, len(pos.tl) ); > 442 } > 443 > 444 void DocImpl::CorrectPos( DPos& s, DPos& e ) > 445 { > 446 // 必ずs<=eになるように修正 > 447 if( s > e ) > 448 { > 449 ulong t; > 450 t=s.ad, s.ad=e.ad, e.ad=t; > 451 t=s.tl, s.tl=e.tl, e.tl=t; > 452 } > 453 } > 454 > 455 bool DocImpl::DeletingOperation > 456 ( DPos& s, DPos& e, unicode*& undobuf, ulong& undosiz ) > 457 { > 458 AutoLock lk( this ); > 459 > 460 // 位置補正 > 461 CorrectPos( s ); > 462 CorrectPos( e ); > 463 CorrectPos( s, e ); > 464 > 465 // 削除される量をカウント > 466 undosiz = getRangeLength( s, e ); > 467 > 468 // Undo操作用バッファ確保 > 469 undobuf = new unicode[undosiz+1]; > 470 getText( undobuf, s, e ); > 471 > 472 // 削除る > 473 if( s.tl == e.tl ) > 474 { > 475 // 一行内削除 > 476 text_[s.tl].RemoveAt( s.ad, e.ad-s.ad ); > 477 } > 478 else > 479 { > 480 // 先頭行の後ろを削除 > 481 text_[s.tl].RemoveToTail( s.ad ); > 482 // 終了行の残り部分をくっつける > 483 text_[s.tl].InsertToTail( tl(e.tl)+e.ad, len(e.tl)-e.ad ); > 484 // いらん行を削除 > 485 text_.RemoveAt( s.tl+1, e.tl-s.tl ); > 486 } > 487 > 488 // 再解析 > 489 return ReParse( s.tl, s.tl ); > 490 } > 491 > 492 bool DocImpl::InsertingOperation > 493 ( DPos& s, const unicode* str, ulong len, DPos& e ) > 494 { > 495 AutoLock lk( this ); > 496 > 497 // 位置補正 > 498 CorrectPos( s ); > 499 > 500 // よーい、どん! > 501 e.ad = s.ad; > 502 e.tl = s.tl; > 503 > 504 // 指定文字列を改行で切り分ける準備 > 505 const unicode* lineStr; > 506 ulong lineLen; > 507 UniReader r( str, len, &lineStr, &lineLen ); > 508 > 509 // 一行目… > 510 r.getLine(); > 511 text_[e.tl].InsertAt( e.ad, lineStr, lineLen ); > 512 e.ad += lineLen; > 513 > 514 if( !r.isEmpty() ) > 515 { > 516 // 二行目〜最終行 > 517 do > 518 { > 519 r.getLine(); > 520 text_.InsertAt( ++e.tl, new Line(lineStr,lineLen) ); > 521 } while( !r.isEmpty() ); > 522 > 523 // 一行目の最後尾に残ってた文字列を最終行へ > 524 Line& fl = text_[s.tl]; > 525 Line& ed = text_[e.tl]; > 526 const ulong ln = fl.size()-e.ad; > 527 if( ln ) > 528 { > 529 ed.InsertToTail( fl.str()+e.ad, ln ); > 530 fl.RemoveToTail( e.ad ); > 531 } > 532 > 533 // 終了位置記録 > 534 e.ad = lineLen; > 535 } > 536 > 537 // 再解析 > 538 return ReParse( s.tl, e.tl ); > 539 } > 540 > 541 > 542 > 543 //------------------------------------------------------------------------- > 544 // 挿入コマンド > 545 //------------------------------------------------------------------------- > 546 > 547 Insert::Insert( const DPos& s, const unicode* str, ulong len, bool del ) > 548 : stt_( s ) > 549 , buf_( str ) > 550 , len_( len ) > 551 , del_( del ) > 552 { > 553 } > 554 > 555 Insert::~Insert() > 556 { > 557 if( del_ ) > 558 delete const_cast<unicode*>(buf_); > 559 } > 560 > 561 Command* Insert::operator()( Document& d ) const > 562 { > 563 DocImpl& di = d.impl(); > 564 > 565 // 挿入 > 566 DPos s=stt_, e; > 567 bool aa = di.InsertingOperation( s, buf_, len_, e ); > 568 > 569 // イベント発火 > 570 di.Fire_TEXTUPDATE( s, s, e, aa, true ); > 571 > 572 // 逆操作オブジェクトを返す > 573 return new Delete( s, e ); > 574 } > 575 > 576 > 577 > 578 //------------------------------------------------------------------------- > 579 // 削除コマンド > 580 //------------------------------------------------------------------------- > 581 > 582 Delete::Delete( const DPos& s, const DPos& e ) > 583 : stt_( s ) > 584 , end_( e ) > 585 { > 586 } > 587 > 588 Command* Delete::operator()( Document& d ) const > 589 { > 590 DocImpl& di = d.impl(); > 591 > 592 // 削除 > 593 unicode* buf; > 594 ulong siz; > 595 DPos s = stt_, e=end_; > 596 bool aa = di.DeletingOperation( s, e, buf, siz ); > 597 > 598 // イベント発火 > 599 di.Fire_TEXTUPDATE( s, e, s, aa, true ); > 600 > 601 // 逆操作オブジェクトを返す > 602 return new Insert( s, buf, siz, true ); > 603 } > 604 > 605 > 606 > 607 //------------------------------------------------------------------------- > 608 // 置換コマンド > 609 //------------------------------------------------------------------------- > 610 > 611 Replace::Replace( > 612 const DPos& s, const DPos& e, const unicode* str, ulong len, bool del ) > 613 : stt_( s ) > 614 , end_( e ) > 615 , buf_( str ) > 616 , len_( len ) > 617 , del_( del ) > 618 { > 619 } > 620 > 621 Replace::~Replace() > 622 { > 623 if( del_ ) > 624 delete const_cast<unicode*>(buf_); > 625 } > 626 > 627 Command* Replace::operator()( Document& d ) const > 628 { > 629 DocImpl& di = d.impl(); > 630 > 631 // 削除 > 632 unicode* buf; > 633 ulong siz; > 634 DPos s=stt_, e=end_; > 635 bool aa = di.DeletingOperation( s, e, buf, siz ); > 636 > 637 // 挿入 > 638 DPos e2; > 639 aa = (di.InsertingOperation( s, buf_, len_, e2 ) || aa); > 640 > 641 // イベント発火 > 642 di.Fire_TEXTUPDATE( s, e, e2, aa, true ); > 643 > 644 // 逆操作オブジェクトを返す > 645 return new Replace( s, e2, buf, siz, true ); > 646 } > 647 > 648 > 649 > 650 //------------------------------------------------------------------------- > 651 // マクロコマンド > 652 //------------------------------------------------------------------------- > 653 > 654 Command* MacroCommand::operator()( Document& doc ) const > 655 { > 656 doc.setBusyFlag(); > 657 > 658 MacroCommand* undo = new MacroCommand; > 659 undo->arr_.ForceSize( size() ); > 660 for( ulong i=0,e=arr_.size(); i<e; ++i ) > 661 undo->arr_[e-i-1] = (*arr_[i])(doc); > 662 > 663 doc.setBusyFlag(false); > 664 return undo; > 665 } > 666 > 667 > 668 > 669 //------------------------------------------------------------------------- > 670 // ファイルに保存 > 671 //------------------------------------------------------------------------- > 672 > 673 void DocImpl::SaveFile( TextFileW& tf ) > 674 { > 675 urdo_.SavedHere(); > 676 for( ulong i=0,iLast=tln()-1; i<=iLast; ++i ) > 677 tf.WriteLine( tl(i), len(i), i==iLast ); > 678 } > 679 > 680 > 681 > 682 //------------------------------------------------------------------------- > 683 // バッファの内容を全部破棄(暫定) > 684 //------------------------------------------------------------------------- > 685 > 686 void DocImpl::ClearAll() > 687 { > 688 // 全部削除 > 689 Execute( Delete( DPos(0,0), DPos(0xffffffff,0xffffffff) ) ); > 690 > 691 // Undo-Redoチェインをクリア > 692 urdo_.Clear(); > 693 urdo_.SavedHere(); > 694 Fire_MODIFYFLAGCHANGE(); > 695 } > 696 > 697 > 698 > 699 //------------------------------------------------------------------------- > 700 // ファイルを開く(暫定) > 701 //------------------------------------------------------------------------- > 702 > 703 void DocImpl::OpenFile( aptr<TextFileR> tf ) > 704 { > 705 // ToDo: マルチスレッド化 > 706 //currentOpeningFile_ = tf; > 707 //thd().Run( *this ); > 708 > 709 // 挿入 > 710 DPos e(0,0); > 711 > 712 unicode buf[1024]; > 713 for( ulong i=0; tf->state(); ) > 714 { > 715 if( size_t L = tf->ReadLine( buf, countof(buf) ) ) > 716 { > 717 DPos p(i,0xffffffff); > 718 InsertingOperation( p, buf, (ulong)L, e ); > 719 i = tln() - 1; > 720 } > 721 if( tf->state() == 1 ) > 722 { > 723 DPos p(i++,0xffffffff); > 724 InsertingOperation( p, L"\n", 1, e ); > 725 } > 726 } > 727 > 728 // イベント発火 > 729 Fire_TEXTUPDATE( DPos(0,0), DPos(0,0), e, true, false ); > 730 } > 731 > 732 > 733 void DocImpl::StartThread() > 734 { > 735 /* > 736 // ToDo: > 737 aptr<TextFileR> tf = currentOpeningFile_; > 738 > 739 // 挿入 > 740 unicode buf[1024]; > 741 while( !isExitRequested() && tf->state() ) > 742 { > 743 ulong i, j; > 744 DPos s(i=tln()-1, j=len(i)), e; > 745 if( ulong L = tf->ReadLine( buf, countof(buf) ) ) > 746 InsertingOperation( s, buf, L, e ); > 747 if( tf->state() == 1 ) > 748 InsertingOperation( DPos(i,0xffffffff), L"\n", 1, e ); > 749 > 750 // イベント発火 > 751 Fire_TEXTUPDATE( s, s, e, true, false ); > 752 } > 753 */ > 754 } > 755

Added editwing/ip_view.h version [a25d583a35063324]

> 1 #ifndef _EDITWING_IP_VIEW_H_ > 2 #define _EDITWING_IP_VIEW_H_ > 3 #include "ewView.h" > 4 #include "ip_doc.h" > 5 using namespace ki; > 6 #ifndef __ccdoc__ > 7 namespace editwing { > 8 namespace view { > 9 #endif > 10 > 11 > 12 > 13 using doc::DocImpl; > 14 > 15 > 16 > 17 //========================================================================= > 18 //@{ @pkg editwing.View.Impl //@} > 19 //@{ > 20 // 描画基本ルーチン > 21 // > 22 // 利用するには、Canvasオブジェクトから getPainter して使います。 > 23 // 画面用デバイスコンテキストのレイヤです。きちんと書いておけば印刷機能を > 24 // 追加するときに楽なのかもしれませんが、そんなことを考える計画性が > 25 // あるはずもなく極めて適当に…。 > 26 //@} > 27 //========================================================================= > 28 > 29 class Painter : public Object > 30 { > 31 public: > 32 > 33 ~Painter(); > 34 > 35 //@{ 指定位置に一文字出力 //@} > 36 void CharOut( unicode ch, int x, int y ); > 37 > 38 //@{ 指定位置に文字列を出力 //@} > 39 void StringOut( const unicode* str, int len, int x, int y ); > 40 > 41 //@{ 文字色切り替え //@} > 42 void SetColor( int i ); > 43 > 44 //@{ 背景色で塗りつぶし //@} > 45 void Fill( const RECT& rc ); > 46 > 47 //@{ 反転 //@} > 48 void Invert( const RECT& rc ); > 49 > 50 //@{ 線を引く //@} > 51 void DrawLine( int x1, int y1, int x2, int y2 ); > 52 > 53 //@{ クリップ領域設定 //@} > 54 void SetClip( const RECT& rc ); > 55 > 56 //@{ クリップ領域解除 //@} > 57 void ClearClip(); > 58 > 59 //@{ 半角スペース用記号描画 //@} > 60 void DrawHSP( int x, int y, int times ); > 61 > 62 //@{ 全角スペース用記号描画 //@} > 63 void DrawZSP( int x, int y, int times ); > 64 > 65 public: > 66 > 67 //@{ 高さ(pixel) //@} > 68 int H() const { return height_; } > 69 > 70 //@{ 数字幅(pixel) //@} > 71 int F() const { return figWidth_; } > 72 > 73 //@{ 文字幅(pixel) //@} > 74 int Wc( unicode ch ) const > 75 { > 76 if( widthTable_[ ch ] == -1 ) > 77 ::GetCharWidthW( dc_, ch, ch, widthTable_+ch ); > 78 return widthTable_[ ch ]; > 79 } > 80 int W( const unicode* pch ) const // 1.08 サロゲートペア回避 > 81 { > 82 unicode ch = *pch; > 83 if( widthTable_[ ch ] == -1 ) > 84 { > 85 if( isHighSurrogate(ch) ) > 86 { > 87 SIZE sz; > 88 if( ::GetTextExtentPoint32W( dc_, pch, 2 > 89 return sz.cx; > 90 int w = 0; > 91 ::GetCharWidthW( dc_, ch, ch, &w ); > 92 return w; > 93 } > 94 ::GetCharWidthW( dc_, ch, ch, widthTable_+ch ); > 95 } > 96 return widthTable_[ ch ]; > 97 } > 98 > 99 //@{ 標準文字幅(pixel) //@} > 100 int W() const { return widthTable_[ L'x' ]; } > 101 > 102 //@{ 次のタブ揃え位置を計算 //@} > 103 //int nextTab(int x) const { int t=T(); return (x/t+1)*t; } > 104 int nextTab(int x) const { int t=T(); return ((x+4)/t+1)*t; } > 105 private: int T() const { return widthTable_[ L'\t' ]; } public: > 106 > 107 //@{ 現在のフォント情報 //@} > 108 const LOGFONT& LogFont() const { return logfont_; } > 109 > 110 //@{ 特別文字を描画するか否か //@} > 111 bool sc( int i ) const { return scDraw_[i]; } > 112 > 113 private: > 114 > 115 const HDC dc_; > 116 const HFONT font_; > 117 const HPEN pen_; > 118 const HBRUSH brush_; > 119 int height_; > 120 int* widthTable_; > 121 int figWidth_; > 122 LOGFONT logfont_; > 123 COLORREF colorTable_[7]; > 124 bool scDraw_[5]; > 125 > 126 private: > 127 > 128 Painter( HDC hdc, const VConfig& vc ); > 129 HDC getDC() { return dc_; } > 130 friend class Canvas; > 131 NOCOPY(Painter); > 132 }; > 133 > 134 > 135 > 136 //========================================================================= > 137 //@{ > 138 // 描画可能領域 > 139 // > 140 // ウインドウサイズの変更や折り返しの有無やフォントの設定などに > 141 // 対応して、描画領域のサイズを適当に管理します。やることは > 142 // とりあえずそれだけ。 > 143 //@} > 144 //========================================================================= > 145 > 146 class Canvas : public Object > 147 { > 148 public: > 149 > 150 Canvas( const View& vw ); > 151 > 152 //@{ Viewの大きさ変更イベント処理 > 153 // @return 折り返し幅が変わったらtrue //@} > 154 bool on_view_resize( int cx, int cy ); > 155 > 156 //@{ 行数変更イベント処理 > 157 // @return テキスト領域の幅が変わったらtrue //@} > 158 bool on_tln_change( ulong tln ); > 159 > 160 //@{ フォント変更イベント処理 //@} > 161 void on_font_change( const VConfig& vc ); > 162 > 163 //@{ 設定変更イベント処理 //@} > 164 void on_config_change( int wrap, bool showln ); > 165 > 166 public: > 167 > 168 //@{ [行番号を表示するか否か] //@} > 169 bool showLN() const { return showLN_; } > 170 > 171 //@{ [-1:折り返し無し 0:窓右端 else:指定文字数] //@} > 172 int wrapType() const { return wrapType_; } > 173 > 174 //@{ 折り返し幅(pixel) //@} > 175 ulong wrapWidth() const { return wrapWidth_; } > 176 > 177 //@{ 表示領域の位置(pixel) //@} > 178 const RECT& zone() const { return txtZone_; } > 179 > 180 //@{ 描画用オブジェクト //@} > 181 Painter& getPainter() const { return *font_; } > 182 > 183 private: > 184 > 185 int wrapType_; // [ -1:折り返し無し 0:窓右端 else:指定文字数 ] > 186 bool showLN_; // [ 行番号を表示するか否か ] > 187 > 188 dptr<Painter> font_; // 描画用オブジェクト > 189 ulong wrapWidth_; // 折り返し幅(pixel) > 190 RECT txtZone_; // テキスト表示域の位置(pixel) > 191 int figNum_; // 行番号の桁数 > 192 > 193 private: > 194 > 195 bool CalcLNAreaWidth(); > 196 void CalcWrapWidth(); > 197 > 198 private: > 199 > 200 NOCOPY(Canvas); > 201 }; > 202 > 203 > 204 > 205 //========================================================================= > 206 //@{ > 207 // 行毎の折り返し情報 > 208 //@} > 209 //========================================================================= > 210 > 211 struct WLine : public storage<ulong> > 212 { > 213 // [0] : その行の折り返し無しでの横幅を格納 > 214 // [1-n] : n行目の終端のindexを格納。 > 215 // > 216 // 例えば "aaabbb" という論理行を "aaab" "bb" と折るなら > 217 // {48, 4, 6} などという長さ3の配列となる。 > 218 > 219 WLine() : storage<ulong>(2) {} > 220 ulong& width() { return (*this)[0]; } > 221 ulong width() const { return (*this)[0]; } > 222 ulong rln() const { return size()-1; } > 223 }; > 224 > 225 > 226 > 227 //========================================================================= > 228 //@{ > 229 // 再描画範囲を指定するためのフラグ > 230 //@} > 231 //========================================================================= > 232 > 233 enum ReDrawType > 234 { > 235 LNAREA, // 行番号ゾーンのみ > 236 LINE, // 変更のあった一行のみ > 237 AFTER, // 変更のあった行以下全部 > 238 ALL // 全画面 > 239 }; > 240 > 241 > 242 > 243 //========================================================================= > 244 //@{ > 245 // 描画処理を細かく指定する構造体 > 246 //@} > 247 //========================================================================= > 248 > 249 struct VDrawInfo > 250 { > 251 const RECT rc; // 再描画範囲 > 252 int XBASE; // 一番左の文字のx座標 > 253 int XMIN; // テキスト再描画範囲左端 > 254 int XMAX; // テキスト再描画範囲右端 > 255 int YMIN; // テキスト再描画範囲上端 > 256 int YMAX; // テキスト再描画範囲下端 > 257 ulong TLMIN; // テキスト再描画範囲上端論理行番号 > 258 int SXB, SXE; // 選択範囲のx座標 > 259 int SYB, SYE; // 選択範囲のy座標 > 260 > 261 explicit VDrawInfo( const RECT& r ) : rc(r) {} > 262 }; > 263 > 264 > 265 > 266 //========================================================================= > 267 //@{ > 268 // 折り返しedテキストの管理・表示等 > 269 // > 270 // Canvasクラスによって計算された領域サイズを参考に、テキストの > 271 // 折り返し処理を実行する。ここで、スクロール制御、描画処理など > 272 // 主要な処理は全て実行することになる。 > 273 //@} > 274 //========================================================================= > 275 > 276 class ViewImpl : public Object > 277 { > 278 public: > 279 > 280 ViewImpl( View& vw, DocImpl& dc ); > 281 > 282 //@{ 折り返し方式切替 //@} > 283 void SetWrapType( int wt ); > 284 > 285 //@{ 行番号表示/非表示切替 //@} > 286 void ShowLineNo( bool show ); > 287 > 288 //@{ 表示色・フォント切替 //@} > 289 void SetFont( const VConfig& vc ); > 290 > 291 //@{ テキスト領域のサイズ変更イベント //@} > 292 void on_view_resize( int cx, int cy ); > 293 > 294 void DoResize( bool wrapWidthChanged ); > 295 void DoConfigChange(); > 296 > 297 //@{ テキストデータの更新イベント //@} > 298 void on_text_update( const DPos& s, > 299 const DPos& e, const DPos& e2, bool bAft, bool mCur ); > 300 > 301 //@{ 描画処理 //@} > 302 void on_paint( const PAINTSTRUCT& ps ); > 303 > 304 public: > 305 > 306 //@{ 全表示行数 //@} > 307 ulong vln() const { return vlNum_; } > 308 > 309 //@{ 一行の表示行数 //@} > 310 ulong rln( ulong tl ) const { return wrap_[tl].rln(); } > 311 > 312 //@{ 折り返し位置 //@} > 313 ulong rlend( ulong tl, ulong rl ) const { return wrap_[tl][rl+1]; } > 314 > 315 //@{ 一個でも折り返しが存在するか否か //@} > 316 bool wrapexists() const { return doc_.tln() != vln(); } > 317 > 318 //@{ カーソル //@} > 319 Cursor& cur() { return cur_; } > 320 > 321 //@{ フォント //@} > 322 const Painter& fnt() const { return cvs_.getPainter(); } > 323 > 324 > 325 void on_hscroll( int code ); > 326 void on_vscroll( int code ); > 327 void on_wheel( short delta ); > 328 > 329 void GetVPos( int x, int y, VPos* vp, bool linemode=false ) const; > 330 void GetOrigin( int* x, int* y ) const; > 331 void ConvDPosToVPos( DPos dp, VPos* vp, const VPos* base=NULL ) const; > 332 void ScrollTo( const VPos& vp ); > 333 int GetLastWidth( ulong tl ) const; > 334 > 335 public: > 336 > 337 const RECT& zone() const { return cvs_.zone(); } > 338 int left() const { return cvs_.zone().left; } > 339 int right() const { return cvs_.zone().right; } > 340 int bottom()const { return cvs_.zone().bottom; } > 341 int lna() const { return cvs_.zone().left; } > 342 int cx() const { return cvs_.zone().right - cvs_.zone().left; } > 343 int cxAll() const { return cvs_.zone().right; } > 344 int cy() const { return cvs_.zone().bottom; } > 345 > 346 private: > 347 > 348 const DocImpl& doc_; > 349 Canvas cvs_; > 350 Cursor cur_; > 351 gapbufobj<WLine> wrap_; > 352 ulong vlNum_; > 353 ulong textCx_; > 354 > 355 private: > 356 > 357 void DrawLNA( const VDrawInfo& v, Painter& p ); > 358 void DrawTXT( const VDrawInfo v, Painter& p ); > 359 void Inv( int y, int xb, int xe, Painter& p ); > 360 > 361 void CalcEveryLineWidth(); > 362 ulong CalcLineWidth( const unicode* txt, ulong len ) const; > 363 void ModifyWrapInfo( const unicode* txt, ulong len, WLine& wl, ulong stt > 364 void ReWrapAll(); > 365 int ReWrapSingle( const DPos& s ); > 366 int InsertMulti( ulong ti_s, ulong ti_e ); > 367 int DeleteMulti( ulong ti_s, ulong ti_e ); > 368 void UpdateTextCx(); > 369 void ReDraw( ReDrawType r, const DPos* s=NULL ); > 370 > 371 private: > 372 > 373 HWND hwnd_; > 374 SCROLLINFO rlScr_; // 横スクロール情報(pixel単位) > 375 SCROLLINFO udScr_; // 縦スクロール情報(行単位) > 376 ulong udScr_tl_; // 一番上に表示される論理行のTLine_Index > 377 ulong udScr_vrl_; // 一番上に表示される表示行のVRLine_Index > 378 > 379 private: > 380 > 381 bool ReSetScrollInfo(); > 382 void ForceScrollTo( ulong tl ); > 383 void UpdateScrollBar(); > 384 ReDrawType TextUpdate_ScrollBar( const DPos& s, const DPos& e, const DPo > 385 > 386 ulong tl2vl( ulong tl ) const; > 387 void GetDrawPosInfo( VDrawInfo& v ) const; > 388 void InvalidateView( const DPos& dp, bool afterall ) const; > 389 void ScrollView( int dx, int dy, bool update ); > 390 void UpDown( int dy, bool thumb ); > 391 }; > 392 > 393 > 394 > 395 //------------------------------------------------------------------------- > 396 > 397 inline void ViewImpl::on_view_resize( int cx, int cy ) > 398 { DoResize( cvs_.on_view_resize( cx, cy ) ); } > 399 > 400 inline void ViewImpl::SetWrapType( int wt ) > 401 { cvs_.on_config_change( wt, cvs_.showLN() ); > 402 DoConfigChange(); } > 403 > 404 inline void ViewImpl::ShowLineNo( bool show ) > 405 { cvs_.on_config_change( cvs_.wrapType(), show ); > 406 DoConfigChange(); } > 407 > 408 inline void ViewImpl::SetFont( const VConfig& vc ) > 409 { cvs_.on_font_change( vc ); > 410 cur_.on_setfocus(); > 411 CalcEveryLineWidth(); // 行幅再計算 > 412 DoConfigChange(); } > 413 > 414 inline void ViewImpl::GetOrigin( int* x, int* y ) const > 415 { *x = left()-rlScr_.nPos, *y = -udScr_.nPos*cvs_.getPainter().H(); } > 416 > 417 > 418 > 419 //========================================================================= > 420 > 421 }} // namespace editwing::view > 422 #endif // _EDITWING_IP_VIEW_H_

Added editwing/ip_wrap.cpp version [efe9189ceabe7b50]

> 1 #include "stdafx.h" > 2 #include "ip_view.h" > 3 using namespace editwing; > 4 using namespace editwing::view; > 5 > 6 > 7 > 8 //========================================================================= > 9 //---- ip_wrap.cpp 折り返し > 10 // > 11 // Documentで文字列データが更新されるのを受けて > 12 // Viewでは折り返し位置情報を更新する。その処理がココ。 > 13 // > 14 //---- ip_text.cpp 文字列操作・他 > 15 //---- ip_parse.cpp キーワード解析 > 16 //---- ip_scroll.cpp スクロール > 17 //---- ip_draw.cpp 描画・他 > 18 //---- ip_cursor.cpp カーソルコントロール > 19 //========================================================================= > 20 > 21 > 22 > 23 //------------------------------------------------------------------------- > 24 // 初期化 > 25 //------------------------------------------------------------------------- > 26 > 27 ViewImpl::ViewImpl( View& vw, DocImpl& dc ) > 28 : doc_ ( dc ) > 29 , cvs_ ( vw ) > 30 , cur_ ( vw.hwnd(), *this, dc ) > 31 , hwnd_ ( vw.hwnd() ) > 32 , vlNum_ ( 0 ) > 33 , textCx_( 0 ) > 34 { > 35 // 適当に折り返し情報初期化 > 36 InsertMulti( 0, doc_.tln()-1 ); > 37 > 38 // 適当にスクロール情報初期化 > 39 udScr_.cbSize = rlScr_.cbSize = sizeof(udScr_); > 40 udScr_.fMask = rlScr_.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; > 41 udScr_.nMin = rlScr_.nMin = 0; > 42 udScr_.nPos = rlScr_.nPos = 0; > 43 udScr_.fMask |= SIF_DISABLENOSCROLL; > 44 udScr_tl_ = udScr_vrl_ = 0; > 45 ReSetScrollInfo(); > 46 } > 47 > 48 > 49 > 50 //------------------------------------------------------------------------- > 51 // 状態変更への対応 > 52 //------------------------------------------------------------------------- > 53 > 54 void ViewImpl::DoResize( bool wrapWidthChanged ) > 55 { > 56 // 折り返し位置再計算 > 57 if( wrapWidthChanged ) > 58 { > 59 ReWrapAll(); > 60 UpdateTextCx(); > 61 } > 62 > 63 // スクロール情報変更 > 64 ReSetScrollInfo(); > 65 if( wrapWidthChanged ) > 66 ForceScrollTo( udScr_tl_ ); > 67 > 68 // 再描画 > 69 ReDraw( ALL ); > 70 cur_.ResetPos(); > 71 } > 72 > 73 void ViewImpl::DoConfigChange() > 74 { > 75 // 折り返し位置再計算 > 76 ReWrapAll(); > 77 UpdateTextCx(); > 78 > 79 // スクロール情報変更 > 80 ReSetScrollInfo(); > 81 ForceScrollTo( udScr_tl_ ); > 82 > 83 // 再描画 > 84 ReDraw( ALL ); > 85 cur_.ResetPos(); > 86 } > 87 > 88 void ViewImpl::on_text_update > 89 ( const DPos& s, const DPos& e, const DPos& e2, bool bAft, bool mCur ) > 90 { > 91 // まず、折り返し位置再計算 > 92 > 93 // 置換範囲の先頭行を調整 > 94 int r3 = 0, r2 = 1, r1 = ReWrapSingle( s ); > 95 > 96 // 残りを調整 > 97 if( s.tl != e.tl ) > 98 r2 = DeleteMulti( s.tl+1, e.tl ); > 99 if( s.tl != e2.tl ) > 100 r3 = InsertMulti( s.tl+1, e2.tl ); > 101 > 102 // この変更で横幅が… > 103 // if( "長くなったなてはいない" AND "短くなっちゃった可能性あり" ) > 104 // 横幅再計算(); > 105 if( !(r1==2 || r3==1) && (r1==0 || r2==0) ) > 106 UpdateTextCx(); > 107 > 108 // スクロールバー修正 > 109 ReDrawType t = TextUpdate_ScrollBar( s, e, e2 ); > 110 bool doResize = false; > 111 > 112 // 行数に変化があって、行番号表示域の幅を変えなきゃならん時 > 113 if( e.tl!=e2.tl && cvs_.on_tln_change( doc_.tln() ) ) > 114 { > 115 doResize = true; > 116 } > 117 else if( bAft && t!=ALL ) > 118 { > 119 t = AFTER; > 120 } > 121 > 122 // カーソル移動 > 123 cur_.on_text_update( s, e, e2, mCur ); > 124 > 125 // 再描画 > 126 if( doResize ) > 127 DoResize( true ); > 128 else > 129 { > 130 if( e.tl != e2.tl ) // 行番号領域再描画の必要があるとき > 131 ReDraw( LNAREA, 0 ); > 132 ReDraw( t, &s ); > 133 } > 134 } > 135 > 136 > 137 > 138 //------------------------------------------------------------------------- > 139 // 折り返し位置計算補助ルーチン > 140 //------------------------------------------------------------------------- > 141 > 142 void ViewImpl::UpdateTextCx() > 143 { > 144 if( cvs_.wrapType() == NOWRAP ) > 145 { > 146 // 折り返しなしなら、数えてみないと横幅はわからない > 147 ulong cx=0; > 148 for( ulong i=0, ie=doc_.tln(); i<ie; ++i ) > 149 if( cx < wrap_[i].width() ) > 150 cx = wrap_[i].width(); > 151 textCx_ = cx; > 152 } > 153 else > 154 { > 155 // 折り返しありなら、横幅:=折り返し幅とする > 156 textCx_ = cvs_.wrapWidth(); > 157 } > 158 } > 159 > 160 ulong ViewImpl::CalcLineWidth( const unicode* txt, ulong len ) const > 161 { > 162 // 行を折り返さずに書いたときの横幅を計算する > 163 // ほとんどの行が折り返し無しで表示されるテキストの場合、 > 164 // この値を計算しておくことで、処理の高速化が可能。 > 165 const Painter& p = cvs_.getPainter(); > 166 > 167 ulong w=0; > 168 for( ulong i=0; i<len; ++i ) > 169 if( txt[i] == L'\t' ) > 170 w = p.nextTab(w); > 171 else > 172 w += p.W( &txt[i] ); > 173 return w; > 174 } > 175 > 176 void ViewImpl::CalcEveryLineWidth() > 177 { > 178 // 全ての行に対してCalcLineWidthを実行 > 179 // …するだけ。 > 180 for( ulong i=0, ie=doc_.tln(); i<ie; ++i ) > 181 wrap_[i].width() = CalcLineWidth( doc_.tl(i), doc_.len(i) ); > 182 } > 183 > 184 void ViewImpl::ModifyWrapInfo( > 185 const unicode* txt, ulong len, WLine& wl, ulong stt ) > 186 { > 187 // 設定幅での折り返しを実行する。 > 188 // 行の途中からの変更の場合、sttが開始addressを指している > 189 const Painter& p = cvs_.getPainter(); > 190 const ulong ww = cvs_.wrapWidth(); > 191 > 192 while( stt < len ) > 193 { > 194 ulong i, w; > 195 for( w=0,i=stt; i<len; ++i ) > 196 { > 197 if( txt[i] == L'\t' ) > 198 w = p.nextTab(w); > 199 else > 200 w += p.W( &txt[i] ); > 201 > 202 if( w>ww ) > 203 break; // 幅が設定値を超えた所でおしまい > 204 } > 205 wl.Add( stt = (i==stt?i+1:i) ); > 206 } > 207 } > 208 > 209 int ViewImpl::GetLastWidth( ulong tl ) const > 210 { > 211 if( rln(tl)==1 ) > 212 return wrap_[tl][0]; > 213 > 214 ulong beg = rlend(tl,rln(tl)-2); > 215 return CalcLineWidth( doc_.tl(tl)+beg, doc_.len(tl)-beg ); > 216 } > 217 > 218 void ViewImpl::ReWrapAll() > 219 { > 220 // 折り返し幅に変更があった場合に、全ての行の > 221 // 折り返し位置情報を変更する。 > 222 const ulong ww = cvs_.wrapWidth(); > 223 > 224 ulong vln=0; > 225 for( ulong i=0, ie=doc_.tln(); i<ie; ++i ) > 226 { > 227 WLine& wl = wrap_[i]; > 228 wl.ForceSize(1); > 229 > 230 if( wl.width() < ww ) > 231 { > 232 // 設定した折り返し幅より短い場合は一行で済む。 > 233 wl.Add( doc_.len(i) ); > 234 ++vln; > 235 } > 236 else > 237 { > 238 // 複数行になる場合 > 239 ModifyWrapInfo( doc_.tl(i), doc_.len(i), wl, 0 ); > 240 vln += wl.rln(); > 241 } > 242 } > 243 vlNum_ = vln; > 244 } > 245 > 246 > 247 > 248 //------------------------------------------------------------------------- > 249 // 折り返し位置計算メインルーチン > 250 //------------------------------------------------------------------------- > 251 > 252 int ViewImpl::ReWrapSingle( const DPos& s ) > 253 { > 254 // 指定した一行のみ折り返しを修正。 > 255 // > 256 // 返値は > 257 // 2: "折り返しあり" or "この行が横に一番長くなった" > 258 // 1: "この行以外のどこかが最長" > 259 // 0: "さっきまでこの行は最長だったが短くなっちゃった" > 260 // で、上位ルーチンにm_TextCx修正の必要性を伝える。 > 261 // > 262 // 昔は再描画範囲の計算のために、表示行数の変化を返していたが、 > 263 // これは上位ルーチン側で vln() を比較すれば済むし、 > 264 // むしろその方が効率的であるため廃止した。 > 265 > 266 > 267 // 旧情報保存 > 268 WLine& wl = wrap_[s.tl]; > 269 const ulong oldVRNum = wl.rln(); > 270 const ulong oldWidth = wl.width(); > 271 > 272 // 横幅更新 > 273 wl.width() = CalcLineWidth( doc_.tl(s.tl), doc_.len(s.tl) ); > 274 > 275 if( wl.width() < cvs_.wrapWidth() ) > 276 { > 277 // 設定した折り返し幅より短い場合は一行で済む。 > 278 wl[1] = doc_.len(s.tl); > 279 wl.ForceSize( 2 ); > 280 } > 281 else > 282 { > 283 // 複数行になる場合 > 284 ulong vr=1, stt=0; > 285 while( wl[vr] < s.ad ) // while( vr行目は変更箇所より手前 ) > 286 stt = wl[ vr++ ]; // stt = 次の行の行頭のアドレス > 287 > 288 // 変更箇所以降のみ修正 > 289 wl.ForceSize( vr ); > 290 ModifyWrapInfo( doc_.tl(s.tl), doc_.len(s.tl), wl, stt ); > 291 } > 292 > 293 // 表示行の総数を修正 > 294 vlNum_ += ( wl.rln() - oldVRNum ); > 295 > 296 // 折り返しなしだと総横幅の更新が必要 > 297 if( cvs_.wrapType() == NOWRAP ) > 298 if( textCx_ <= wl.width() ) > 299 { > 300 textCx_ = wl.width(); > 301 return 2; > 302 } > 303 else if( textCx_ == oldWidth ) > 304 { > 305 return 0; > 306 } > 307 else > 308 { > 309 return 1; > 310 } > 311 return 2; > 312 } > 313 > 314 int ViewImpl::InsertMulti( ulong ti_s, ulong ti_e ) > 315 { > 316 // 指定した分だけ新しく行情報を追加。 > 317 // &折り返し情報もきちんと計算 > 318 // > 319 // 返値は > 320 // 1: "折り返しあり" or "この行が横に一番長くなった" > 321 // 0: "この行以外のどこかが最長" > 322 // 詳しくは ReWrapSingle() を見よ。 > 323 > 324 ulong dy=0, cx=0; > 325 for( ulong i=ti_s; i<=ti_e; ++i ) > 326 { > 327 WLine* pwl = new WLine; > 328 pwl->Add( CalcLineWidth( doc_.tl(i), doc_.len(i) ) ); > 329 > 330 if( pwl->width() < cvs_.wrapWidth() ) > 331 { > 332 // 設定した折り返し幅より短い場合は一行で済む。 > 333 pwl->Add( doc_.len(i) ); > 334 dy++; > 335 if( cx < pwl->width() ) > 336 cx = pwl->width(); > 337 } > 338 else > 339 { > 340 // 複数行になる場合 > 341 ModifyWrapInfo( doc_.tl(i), doc_.len(i), *pwl, 0 ); > 342 dy += pwl->rln(); > 343 } > 344 > 345 wrap_.InsertAt( i, pwl ); > 346 } > 347 > 348 // 表示行の総数を修正 > 349 vlNum_ += dy; > 350 > 351 // 折り返しなしだと総横幅の更新が必要 > 352 if( cvs_.wrapType() == NOWRAP ) > 353 { > 354 if( textCx_ <= cx ) > 355 { > 356 textCx_ = cx; > 357 return 1; > 358 } > 359 return 0; > 360 } > 361 return 1; > 362 } > 363 > 364 int ViewImpl::DeleteMulti( ulong ti_s, ulong ti_e ) > 365 { > 366 // 指定した範囲の行情報を削除 > 367 // > 368 // 返値は > 369 // 1: "折り返しあり" or "この行以外のどこかが最長" > 370 // 0: "さっきまでこの行は最長だったが短くなっちゃった" > 371 // 詳しくは ReWrapSingle() を見よ。 > 372 > 373 bool widthChanged = false; > 374 ulong dy = 0; > 375 > 376 // 情報収集しながら削除 > 377 for( ulong cx=textCx_, i=ti_s; i<=ti_e; ++i ) > 378 { > 379 WLine& wl = wrap_[i]; > 380 dy += wl.rln(); > 381 if( cx == wl.width() ) > 382 widthChanged = true; > 383 } > 384 wrap_.RemoveAt( ti_s, (ti_e-ti_s+1) ); > 385 > 386 // 表示行の総数を修正 > 387 vlNum_ -= dy; > 388 > 389 // 折り返しなしだと総横幅の更新が必要 > 390 return ( cvs_.wrapType()==NOWRAP && widthChanged ) ? 0 : 1; > 391 } > 392 > 393 > 394 > 395 //------------------------------------------------------------------------- > 396 // 座標値変換 > 397 //------------------------------------------------------------------------- > 398 > 399 void ViewImpl::ConvDPosToVPos( DPos dp, VPos* vp, const VPos* base ) const > 400 { > 401 // 補正 > 402 dp.tl = Min( dp.tl, doc_.tln()-1 ); > 403 dp.ad = Min( dp.ad, doc_.len(dp.tl) ); > 404 > 405 // 変換の基準点が指定されていなければ、原点を基準とする > 406 VPos topPos(false); // 0クリア > 407 if( base == NULL ) > 408 base = &topPos; > 409 > 410 // とりあえずbase行頭の値を入れておく > 411 ulong vl = base->vl - base->rl; > 412 ulong rl = 0; > 413 int vx; > 414 > 415 // 同じ行内だった場合 > 416 //if( dp.tl == base->tl ) > 417 //{ > 418 // 例えば [→] を押したときなど、右隣の文字の横幅を > 419 // 足すだけで次の位置は算出できる。これを使って普通の > 420 // カーソル移動はずっと高速化できるはずであるが、 > 421 // とりあえず面倒くさいので、今のところ略。 > 422 //} > 423 > 424 // 違う行だった場合 > 425 //else > 426 { > 427 // vlを合わせる > 428 ulong tl = base->tl; > 429 if( tl > dp.tl ) // 目的地が基準より上にある場合 > 430 do > 431 vl -= rln(--tl); > 432 while( tl > dp.tl ); > 433 else if( tl < dp.tl ) // 目的地が基準より下にある場合 > 434 do > 435 vl += rln(tl++); > 436 while( tl < dp.tl ); > 437 > 438 // rlを合わせる > 439 ulong stt=0; > 440 while( wrap_[tl][rl+1] < dp.ad ) > 441 stt = wrap_[tl][++rl]; > 442 vl += rl; > 443 > 444 // x座標計算 > 445 vx = CalcLineWidth( doc_.tl(tl)+stt, dp.ad-stt ); > 446 } > 447 > 448 vp->tl = dp.tl; > 449 vp->ad = dp.ad; > 450 vp->vl = vl; > 451 vp->rl = rl; > 452 vp->rx = vp->vx = vx; > 453 } > 454 > 455 void ViewImpl::GetVPos( int x, int y, VPos* vp, bool linemode ) const > 456 { > 457 // x座標補正 > 458 > 459 x = x - lna() + rlScr_.nPos; > 460 > 461 // まず行番号計算 > 462 > 463 int tl = udScr_tl_; > 464 int vl = udScr_.nPos - udScr_vrl_; > 465 int rl = y / fnt().H() + udScr_vrl_; > 466 if( rl >= 0 ) // View上端より下の場合、下方向を調べる > 467 while( tl < (int)doc_.tln() && (int)rln(tl) <= rl ) > 468 { > 469 vl += rln(tl); > 470 rl -= rln(tl); > 471 ++tl; > 472 } > 473 else // View上端より上の場合、上方向を調べる > 474 while( 0<=tl && rl<0 ) > 475 { > 476 vl -= rln(tl); > 477 rl += rln(tl); > 478 --tl; > 479 } > 480 > 481 if( tl == (int)doc_.tln() ) // EOFより下に行ってしまう場合の補正 > 482 { > 483 --tl, vl-=rln(tl), rl=rln(tl)-1; > 484 if( linemode ) > 485 x = 0x4fffffff; > 486 } > 487 else if( tl == -1 ) // ファイル頭より上に行ってしまう場合の補正 > 488 { > 489 tl = vl = rl = 0; > 490 if( linemode ) > 491 x = 0; > 492 } > 493 else > 494 { > 495 if( linemode ) // 行選択モードの場合 > 496 { > 497 if( tl == (int)doc_.tln()-1 ) > 498 rl=rln(tl)-1, x=0x4fffffff; > 499 else > 500 vl+=rln(tl), rl=0, ++tl, x=0; > 501 } > 502 } > 503 > 504 vp->tl = tl; > 505 vp->vl = vl + rl; > 506 vp->rl = rl; > 507 > 508 // 次に、横位置を計算 > 509 > 510 if( rl < static_cast<int>(wrap_[tl].rln()) ) > 511 { > 512 const unicode* str = doc_.tl(tl); > 513 const ulong adend = rlend(tl,rl); > 514 ulong ad = (rl==0 ? 0 : rlend(tl,rl-1)); > 515 int vx = (rl==0 ? 0 : fnt().W(&str[ad++])); > 516 > 517 while( ad<adend ) > 518 { > 519 int nvx = (str[ad]==L'\t' > 520 ? fnt().nextTab(vx) > 521 : vx + fnt().W(&str[ad]) > 522 ); > 523 if( x+2 < nvx ) > 524 break; > 525 vx = nvx; > 526 ++ad; > 527 } > 528 > 529 vp->ad = ad; > 530 vp->rx = vp->vx = vx; > 531 } > 532 else > 533 { > 534 vp->ad = vp->rx = vp->vx = 0; > 535 } > 536 }

Added kilib.dsp version [76b8624a35f5bd7a]

> 1 # Microsoft Developer Studio Project File - Name="kilib" - Package Owner=<4> > 2 # Microsoft Developer Studio Generated Build File, Format Version 6.00 > 3 # ** 編集しないでください ** > 4 > 5 # TARGTYPE "Win32 (x86) Application" 0x0101 > 6 > 7 CFG=kilib - Win32 Debug > 8 !MESSAGE これは有効なメイクファイルではありません。 このプロジェクトをビルドするためには NMAKE を使用してください。 > 9 !MESSAGE [メイクファイルのエクスポート] コマンドを使用して実行してください > 10 !MESSAGE > 11 !MESSAGE NMAKE /f "kilib.mak". > 12 !MESSAGE > 13 !MESSAGE NMAKE の実行時に構成を指定できます > 14 !MESSAGE コマンド ライン上でマクロの設定を定義します。例: > 15 !MESSAGE > 16 !MESSAGE NMAKE /f "kilib.mak" CFG="kilib - Win32 Debug" > 17 !MESSAGE > 18 !MESSAGE 選択可能なビルド モード: > 19 !MESSAGE > 20 !MESSAGE "kilib - Win32 Release" ("Win32 (x86) Application" 用) > 21 !MESSAGE "kilib - Win32 Debug" ("Win32 (x86) Application" 用) > 22 !MESSAGE "kilib - Win32 Unicode Release" ("Win32 (x86) Application" 用) > 23 !MESSAGE > 24 > 25 # Begin Project > 26 # PROP AllowPerConfigDependencies 0 > 27 # PROP Scc_ProjName "" > 28 # PROP Scc_LocalPath "" > 29 CPP=cl.exe > 30 MTL=midl.exe > 31 RSC=rc.exe > 32 > 33 !IF "$(CFG)" == "kilib - Win32 Release" > 34 > 35 # PROP BASE Use_MFC 0 > 36 # PROP BASE Use_Debug_Libraries 0 > 37 # PROP BASE Output_Dir "Release" > 38 # PROP BASE Intermediate_Dir "Release" > 39 # PROP BASE Target_Dir "" > 40 # PROP Use_MFC 0 > 41 # PROP Use_Debug_Libraries 0 > 42 # PROP Output_Dir "release" > 43 # PROP Intermediate_Dir "OBJ/vc/rel" > 44 # PROP Ignore_Export_Lib 0 > 45 # PROP Target_Dir "" > 46 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBC > 47 # ADD CPP /nologo /Gr /Zp4 /W3 /Gi /Og /Oi /Os /Oy /Ob1 /D "WIN32" /D "NDEBUG" / > 48 # SUBTRACT CPP /Gf > 49 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 > 50 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 > 51 # ADD BASE RSC /l 0x411 /d "NDEBUG" > 52 # ADD RSC /l 0x411 /d "NDEBUG" > 53 BSC32=bscmake.exe > 54 # ADD BASE BSC32 /nologo > 55 # ADD BSC32 /nologo > 56 LINK32=link.exe > 57 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib ad > 58 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi3 > 59 # SUBTRACT LINK32 /pdb:none > 60 > 61 !ELSEIF "$(CFG)" == "kilib - Win32 Debug" > 62 > 63 # PROP BASE Use_MFC 0 > 64 # PROP BASE Use_Debug_Libraries 1 > 65 # PROP BASE Output_Dir "Debug" > 66 # PROP BASE Intermediate_Dir "Debug" > 67 # PROP BASE Target_Dir "" > 68 # PROP Use_MFC 0 > 69 # PROP Use_Debug_Libraries 1 > 70 # PROP Output_Dir "OBJ/" > 71 # PROP Intermediate_Dir "OBJ/vc/debug" > 72 # PROP Ignore_Export_Lib 0 > 73 # PROP Target_Dir "" > 74 # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" > 75 # ADD CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS > 76 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 > 77 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 > 78 # ADD BASE RSC /l 0x411 /d "_DEBUG" > 79 # ADD RSC /l 0x411 /d "_DEBUG" > 80 BSC32=bscmake.exe > 81 # ADD BASE BSC32 /nologo > 82 # ADD BSC32 /nologo > 83 LINK32=link.exe > 84 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib ad > 85 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi3 > 86 > 87 !ELSEIF "$(CFG)" == "kilib - Win32 Unicode Release" > 88 > 89 # PROP BASE Use_MFC 0 > 90 # PROP BASE Use_Debug_Libraries 0 > 91 # PROP BASE Output_Dir "kilib___Win32_Unicode_Release" > 92 # PROP BASE Intermediate_Dir "kilib___Win32_Unicode_Release" > 93 # PROP BASE Ignore_Export_Lib 0 > 94 # PROP BASE Target_Dir "" > 95 # PROP Use_MFC 0 > 96 # PROP Use_Debug_Libraries 0 > 97 # PROP Output_Dir "release" > 98 # PROP Intermediate_Dir "OBJ/vc/reluni" > 99 # PROP Ignore_Export_Lib 0 > 100 # PROP Target_Dir "" > 101 # ADD BASE CPP /nologo /Gr /Zp4 /W3 /Gi /Og /Oi /Os /Oy /Ob1 /D "WIN32" /D "NDEB > 102 # SUBTRACT BASE CPP /Gf > 103 # ADD CPP /nologo /Gr /Zp4 /W3 /Gi /Og /Oi /Os /Oy /Ob1 /D "WIN32" /D "NDEBUG" / > 104 # SUBTRACT CPP /Gf > 105 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 > 106 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 > 107 # ADD BASE RSC /l 0x411 /d "NDEBUG" > 108 # ADD RSC /l 0x411 /d "NDEBUG" > 109 BSC32=bscmake.exe > 110 # ADD BASE BSC32 /nologo > 111 # ADD BSC32 /nologo > 112 LINK32=link.exe > 113 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib ad > 114 # SUBTRACT BASE LINK32 /pdb:none > 115 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi3 > 116 # SUBTRACT LINK32 /pdb:none > 117 > 118 !ENDIF > 119 > 120 # Begin Target > 121 > 122 # Name "kilib - Win32 Release" > 123 # Name "kilib - Win32 Debug" > 124 # Name "kilib - Win32 Unicode Release" > 125 # Begin Group "Source Files" > 126 > 127 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > 128 # Begin Source File > 129 > 130 SOURCE=.\ConfigManager.cpp > 131 # End Source File > 132 # Begin Source File > 133 > 134 SOURCE=.\GpMain.cpp > 135 # End Source File > 136 # Begin Source File > 137 > 138 SOURCE=.\OpenSaveDlg.cpp > 139 # End Source File > 140 # Begin Source File > 141 > 142 SOURCE=.\RSearch.cpp > 143 # End Source File > 144 # Begin Source File > 145 > 146 SOURCE=.\Search.cpp > 147 # End Source File > 148 # End Group > 149 # Begin Group "Header Files" > 150 > 151 # PROP Default_Filter "h;hpp;hxx;hm;inl" > 152 # Begin Source File > 153 > 154 SOURCE=.\ConfigManager.h > 155 # End Source File > 156 # Begin Source File > 157 > 158 SOURCE=.\GpMain.h > 159 # End Source File > 160 # Begin Source File > 161 > 162 SOURCE=.\NSearch.h > 163 # End Source File > 164 # Begin Source File > 165 > 166 SOURCE=.\OpenSaveDlg.h > 167 # End Source File > 168 # Begin Source File > 169 > 170 SOURCE=.\RSearch.h > 171 # End Source File > 172 # Begin Source File > 173 > 174 SOURCE=.\Search.h > 175 # End Source File > 176 # End Group > 177 # Begin Group "Resource Files" > 178 > 179 # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" > 180 # Begin Source File > 181 > 182 SOURCE=.\rsrc\exefile.ico > 183 # End Source File > 184 # Begin Source File > 185 > 186 SOURCE=.\rsrc\gp_rsrc.rc > 187 # End Source File > 188 # Begin Source File > 189 > 190 SOURCE=.\rsrc\manifest.xml > 191 # End Source File > 192 # Begin Source File > 193 > 194 SOURCE=.\rsrc\resource.h > 195 # End Source File > 196 # End Group > 197 # Begin Group "kilib" > 198 > 199 # PROP Default_Filter "" > 200 # Begin Group "Source" > 201 > 202 # PROP Default_Filter "cpp" > 203 # Begin Source File > 204 > 205 SOURCE=.\kilib\app.cpp > 206 # End Source File > 207 # Begin Source File > 208 > 209 SOURCE=.\kilib\cmdarg.cpp > 210 # End Source File > 211 # Begin Source File > 212 > 213 SOURCE=.\kilib\ctrl.cpp > 214 # End Source File > 215 # Begin Source File > 216 > 217 SOURCE=.\kilib\file.cpp > 218 # End Source File > 219 # Begin Source File > 220 > 221 SOURCE=.\kilib\find.cpp > 222 # End Source File > 223 # Begin Source File > 224 > 225 SOURCE=.\kilib\log.cpp > 226 # End Source File > 227 # Begin Source File > 228 > 229 SOURCE=.\kilib\memory.cpp > 230 # End Source File > 231 # Begin Source File > 232 > 233 SOURCE=.\kilib\path.cpp > 234 # End Source File > 235 # Begin Source File > 236 > 237 SOURCE=.\kilib\registry.cpp > 238 # End Source File > 239 # Begin Source File > 240 > 241 SOURCE=.\kilib\stdafx.cpp > 242 # ADD CPP /Yc"stdafx.h" > 243 # End Source File > 244 # Begin Source File > 245 > 246 SOURCE=.\kilib\string.cpp > 247 # End Source File > 248 # Begin Source File > 249 > 250 SOURCE=.\kilib\textfile.cpp > 251 # End Source File > 252 # Begin Source File > 253 > 254 SOURCE=.\kilib\thread.cpp > 255 # End Source File > 256 # Begin Source File > 257 > 258 SOURCE=.\kilib\window.cpp > 259 # End Source File > 260 # Begin Source File > 261 > 262 SOURCE=.\kilib\winutil.cpp > 263 # End Source File > 264 # End Group > 265 # Begin Group "Header" > 266 > 267 # PROP Default_Filter "h" > 268 # Begin Source File > 269 > 270 SOURCE=.\kilib\app.h > 271 # End Source File > 272 # Begin Source File > 273 > 274 SOURCE=.\kilib\cmdarg.h > 275 # End Source File > 276 # Begin Source File > 277 > 278 SOURCE=.\kilib\ctrl.h > 279 # End Source File > 280 # Begin Source File > 281 > 282 SOURCE=.\kilib\file.h > 283 # End Source File > 284 # Begin Source File > 285 > 286 SOURCE=.\kilib\find.h > 287 # End Source File > 288 # Begin Source File > 289 > 290 SOURCE=.\kilib\log.h > 291 # End Source File > 292 # Begin Source File > 293 > 294 SOURCE=.\kilib\memory.h > 295 # End Source File > 296 # Begin Source File > 297 > 298 SOURCE=.\kilib\path.h > 299 # End Source File > 300 # Begin Source File > 301 > 302 SOURCE=.\kilib\registry.h > 303 # End Source File > 304 # Begin Source File > 305 > 306 SOURCE=.\kilib\string.h > 307 # End Source File > 308 # Begin Source File > 309 > 310 SOURCE=.\kilib\textfile.h > 311 # End Source File > 312 # Begin Source File > 313 > 314 SOURCE=.\kilib\thread.h > 315 # End Source File > 316 # Begin Source File > 317 > 318 SOURCE=.\kilib\types.h > 319 # End Source File > 320 # Begin Source File > 321 > 322 SOURCE=.\kilib\window.h > 323 # End Source File > 324 # Begin Source File > 325 > 326 SOURCE=.\kilib\winutil.h > 327 # End Source File > 328 # End Group > 329 # Begin Group "KTL" > 330 > 331 # PROP Default_Filter "" > 332 # Begin Source File > 333 > 334 SOURCE=.\kilib\ktlaptr.h > 335 # End Source File > 336 # Begin Source File > 337 > 338 SOURCE=.\kilib\ktlarray.h > 339 # End Source File > 340 # Begin Source File > 341 > 342 SOURCE=.\kilib\ktlgap.h > 343 # End Source File > 344 # End Group > 345 # Begin Source File > 346 > 347 SOURCE=.\kilib\kilib.h > 348 # End Source File > 349 # Begin Source File > 350 > 351 SOURCE=.\kilib\stdafx.h > 352 # End Source File > 353 # End Group > 354 # Begin Group "editwing" > 355 > 356 # PROP Default_Filter "" > 357 # Begin Group "public" > 358 > 359 # PROP Default_Filter "" > 360 # Begin Source File > 361 > 362 SOURCE=.\editwing\ewCommon.h > 363 # End Source File > 364 # Begin Source File > 365 > 366 SOURCE=.\editwing\ewCtrl1.h > 367 # End Source File > 368 # Begin Source File > 369 > 370 SOURCE=.\editwing\ewDoc.h > 371 # End Source File > 372 # Begin Source File > 373 > 374 SOURCE=.\editwing\ewView.h > 375 # End Source File > 376 # End Group > 377 # Begin Group "private" > 378 > 379 # PROP Default_Filter "" > 380 # Begin Source File > 381 > 382 SOURCE=.\editwing\ip_ctrl1.cpp > 383 # End Source File > 384 # Begin Source File > 385 > 386 SOURCE=.\editwing\ip_cursor.cpp > 387 # End Source File > 388 # Begin Source File > 389 > 390 SOURCE=.\editwing\ip_doc.h > 391 # End Source File > 392 # Begin Source File > 393 > 394 SOURCE=.\editwing\ip_draw.cpp > 395 # End Source File > 396 # Begin Source File > 397 > 398 SOURCE=.\editwing\ip_parse.cpp > 399 # End Source File > 400 # Begin Source File > 401 > 402 SOURCE=.\editwing\ip_scroll.cpp > 403 # End Source File > 404 # Begin Source File > 405 > 406 SOURCE=.\editwing\ip_text.cpp > 407 # End Source File > 408 # Begin Source File > 409 > 410 SOURCE=.\editwing\ip_view.h > 411 # End Source File > 412 # Begin Source File > 413 > 414 SOURCE=.\editwing\ip_wrap.cpp > 415 # End Source File > 416 # End Group > 417 # Begin Source File > 418 > 419 SOURCE=.\editwing\editwing.h > 420 # End Source File > 421 # End Group > 422 # End Target > 423 # End Project

Added kilib.dsw version [c4ca1b453ed7697f]

> 1 Microsoft Developer Studio Workspace File, Format Version 6.00 > 2 # 警告: このワークスペース ファイル を編集または削除しないでください! > 3 > 4 ############################################################################### > 5 > 6 Project: "kilib"=.\kilib.dsp - Package Owner=<4> > 7 > 8 Package=<5> > 9 {{{ > 10 }}} > 11 > 12 Package=<4> > 13 {{{ > 14 }}} > 15 > 16 ############################################################################### > 17 > 18 Global: > 19 > 20 Package=<5> > 21 {{{ > 22 }}} > 23 > 24 Package=<3> > 25 {{{ > 26 }}} > 27 > 28 ############################################################################### > 29

Added kilib.sln version [ccff6918dad9ce62]

> 1 サソ > 2 Microsoft Visual Studio Solution File, Format Version 9.00 > 3 # Visual Studio 2005 > 4 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kilib", "kilib.vcproj", "{9 > 5 EndProject > 6 Global > 7 GlobalSection(SolutionConfigurationPlatforms) = preSolution > 8 Debug|Win32 = Debug|Win32 > 9 Release|Win32 = Release|Win32 > 10 Unicode Release|Win32 = Unicode Release|Win32 > 11 EndGlobalSection > 12 GlobalSection(ProjectConfigurationPlatforms) = postSolution > 13 {910E868F-4E52-4D55-9C4E-4563F5934517}.Debug|Win32.ActiveCfg = D > 14 {910E868F-4E52-4D55-9C4E-4563F5934517}.Debug|Win32.Build.0 = Deb > 15 {910E868F-4E52-4D55-9C4E-4563F5934517}.Release|Win32.ActiveCfg = > 16 {910E868F-4E52-4D55-9C4E-4563F5934517}.Release|Win32.Build.0 = R > 17 {910E868F-4E52-4D55-9C4E-4563F5934517}.Unicode Release|Win32.Act > 18 {910E868F-4E52-4D55-9C4E-4563F5934517}.Unicode Release|Win32.Bui > 19 EndGlobalSection > 20 GlobalSection(SolutionProperties) = preSolution > 21 HideSolutionNode = FALSE > 22 EndGlobalSection > 23 EndGlobal

Added kilib.vcproj version [29090dda11bda79d]

> 1 <?xml version="1.0" encoding="shift_jis"?> > 2 <VisualStudioProject > 3 ProjectType="Visual C++" > 4 Version="8.00" > 5 Name="kilib" > 6 ProjectGUID="{910E868F-4E52-4D55-9C4E-4563F5934517}" > 7 RootNamespace="kilib" > 8 > > 9 <Platforms> > 10 <Platform > 11 Name="Win32" > 12 /> > 13 </Platforms> > 14 <ToolFiles> > 15 </ToolFiles> > 16 <Configurations> > 17 <Configuration > 18 Name="Unicode Release|Win32" > 19 OutputDirectory=".\release" > 20 IntermediateDirectory=".\OBJ/vc/reluni" > 21 ConfigurationType="1" > 22 InheritedPropertySheets="$(VCInstallDir)VCProjectDefault > 23 UseOfMFC="0" > 24 ATLMinimizesCRunTimeLibraryUsage="false" > 25 CharacterSet="1" > 26 WholeProgramOptimization="1" > 27 > > 28 <Tool > 29 Name="VCPreBuildEventTool" > 30 /> > 31 <Tool > 32 Name="VCCustomBuildTool" > 33 /> > 34 <Tool > 35 Name="VCXMLDataGeneratorTool" > 36 /> > 37 <Tool > 38 Name="VCWebServiceProxyGeneratorTool" > 39 /> > 40 <Tool > 41 Name="VCMIDLTool" > 42 PreprocessorDefinitions="NDEBUG" > 43 MkTypLibCompatible="true" > 44 SuppressStartupBanner="true" > 45 TargetEnvironment="1" > 46 TypeLibraryName=".\release/kilib.tlb" > 47 /> > 48 <Tool > 49 Name="VCCLCompilerTool" > 50 Optimization="3" > 51 InlineFunctionExpansion="1" > 52 EnableIntrinsicFunctions="true" > 53 FavorSizeOrSpeed="2" > 54 OmitFramePointers="true" > 55 EnableFiberSafeOptimizations="true" > 56 WholeProgramOptimization="false" > 57 PreprocessorDefinitions="WIN32,NDEBUG,_WINDOWS,U > 58 StringPooling="true" > 59 ExceptionHandling="0" > 60 RuntimeLibrary="0" > 61 StructMemberAlignment="0" > 62 BufferSecurityCheck="false" > 63 EnableFunctionLevelLinking="true" > 64 TreatWChar_tAsBuiltInType="true" > 65 RuntimeTypeInfo="false" > 66 UsePrecompiledHeader="2" > 67 PrecompiledHeaderThrough="stdafx.h" > 68 PrecompiledHeaderFile=".\OBJ/vc/reluni/kilib.pch > 69 AssemblerListingLocation=".\OBJ/vc/reluni/" > 70 ObjectFile=".\OBJ/vc/reluni/" > 71 ProgramDataBaseFileName=".\OBJ/vc/reluni/" > 72 WarningLevel="3" > 73 SuppressStartupBanner="true" > 74 DebugInformationFormat="0" > 75 CallingConvention="1" > 76 /> > 77 <Tool > 78 Name="VCManagedResourceCompilerTool" > 79 /> > 80 <Tool > 81 Name="VCResourceCompilerTool" > 82 PreprocessorDefinitions="NDEBUG" > 83 Culture="1041" > 84 /> > 85 <Tool > 86 Name="VCPreLinkEventTool" > 87 /> > 88 <Tool > 89 Name="VCLinkerTool" > 90 AdditionalOptions="/MACHINE:I386 /merge:.rdata=. > 91 AdditionalDependencies="kernel32.lib user32.lib > 92 OutputFile="release/GreenPad.exe" > 93 LinkIncremental="1" > 94 SuppressStartupBanner="true" > 95 GenerateManifest="false" > 96 IgnoreAllDefaultLibraries="true" > 97 GenerateDebugInformation="false" > 98 ProgramDatabaseFile=".\release/GreenPad.pdb" > 99 GenerateMapFile="true" > 100 MapFileName=".\OBJ/vc/reluni/GreenPad.map" > 101 SubSystem="2" > 102 OptimizeReferences="2" > 103 EnableCOMDATFolding="2" > 104 OptimizeForWindows98="1" > 105 LinkTimeCodeGeneration="0" > 106 /> > 107 <Tool > 108 Name="VCALinkTool" > 109 /> > 110 <Tool > 111 Name="VCManifestTool" > 112 /> > 113 <Tool > 114 Name="VCXDCMakeTool" > 115 /> > 116 <Tool > 117 Name="VCBscMakeTool" > 118 /> > 119 <Tool > 120 Name="VCFxCopTool" > 121 /> > 122 <Tool > 123 Name="VCAppVerifierTool" > 124 /> > 125 <Tool > 126 Name="VCWebDeploymentTool" > 127 /> > 128 <Tool > 129 Name="VCPostBuildEventTool" > 130 /> > 131 </Configuration> > 132 <Configuration > 133 Name="Debug|Win32" > 134 OutputDirectory=".\OBJ" > 135 IntermediateDirectory=".\OBJ/vc/debug" > 136 ConfigurationType="1" > 137 InheritedPropertySheets="$(VCInstallDir)VCProjectDefault > 138 UseOfMFC="0" > 139 ATLMinimizesCRunTimeLibraryUsage="false" > 140 CharacterSet="1" > 141 > > 142 <Tool > 143 Name="VCPreBuildEventTool" > 144 /> > 145 <Tool > 146 Name="VCCustomBuildTool" > 147 /> > 148 <Tool > 149 Name="VCXMLDataGeneratorTool" > 150 /> > 151 <Tool > 152 Name="VCWebServiceProxyGeneratorTool" > 153 /> > 154 <Tool > 155 Name="VCMIDLTool" > 156 PreprocessorDefinitions="_DEBUG" > 157 MkTypLibCompatible="true" > 158 SuppressStartupBanner="true" > 159 TargetEnvironment="1" > 160 TypeLibraryName=".\OBJ/kilib.tlb" > 161 /> > 162 <Tool > 163 Name="VCCLCompilerTool" > 164 Optimization="0" > 165 PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,S > 166 RuntimeLibrary="1" > 167 UsePrecompiledHeader="2" > 168 PrecompiledHeaderThrough="stdafx.h" > 169 PrecompiledHeaderFile=".\OBJ/vc/debug/kilib.pch" > 170 AssemblerListingLocation=".\OBJ/vc/debug/" > 171 ObjectFile=".\OBJ/vc/debug/" > 172 ProgramDataBaseFileName=".\OBJ/vc/debug/" > 173 BrowseInformation="1" > 174 WarningLevel="3" > 175 SuppressStartupBanner="true" > 176 DebugInformationFormat="4" > 177 /> > 178 <Tool > 179 Name="VCManagedResourceCompilerTool" > 180 /> > 181 <Tool > 182 Name="VCResourceCompilerTool" > 183 PreprocessorDefinitions="_DEBUG" > 184 Culture="1041" > 185 /> > 186 <Tool > 187 Name="VCPreLinkEventTool" > 188 /> > 189 <Tool > 190 Name="VCLinkerTool" > 191 AdditionalOptions="/MACHINE:I386" > 192 AdditionalDependencies="kernel32.lib user32.lib > 193 OutputFile="OBJ/GreenPad.exe" > 194 LinkIncremental="2" > 195 SuppressStartupBanner="true" > 196 GenerateManifest="false" > 197 IgnoreAllDefaultLibraries="false" > 198 GenerateDebugInformation="true" > 199 ProgramDatabaseFile=".\OBJ/GreenPad.pdb" > 200 SubSystem="2" > 201 /> > 202 <Tool > 203 Name="VCALinkTool" > 204 /> > 205 <Tool > 206 Name="VCManifestTool" > 207 /> > 208 <Tool > 209 Name="VCXDCMakeTool" > 210 /> > 211 <Tool > 212 Name="VCBscMakeTool" > 213 /> > 214 <Tool > 215 Name="VCFxCopTool" > 216 /> > 217 <Tool > 218 Name="VCAppVerifierTool" > 219 /> > 220 <Tool > 221 Name="VCWebDeploymentTool" > 222 /> > 223 <Tool > 224 Name="VCPostBuildEventTool" > 225 /> > 226 </Configuration> > 227 <Configuration > 228 Name="Release|Win32" > 229 OutputDirectory=".\release" > 230 IntermediateDirectory=".\OBJ/vc/rel" > 231 ConfigurationType="1" > 232 InheritedPropertySheets="$(VCInstallDir)VCProjectDefault > 233 UseOfMFC="0" > 234 ATLMinimizesCRunTimeLibraryUsage="false" > 235 CharacterSet="2" > 236 WholeProgramOptimization="1" > 237 > > 238 <Tool > 239 Name="VCPreBuildEventTool" > 240 /> > 241 <Tool > 242 Name="VCCustomBuildTool" > 243 /> > 244 <Tool > 245 Name="VCXMLDataGeneratorTool" > 246 /> > 247 <Tool > 248 Name="VCWebServiceProxyGeneratorTool" > 249 /> > 250 <Tool > 251 Name="VCMIDLTool" > 252 PreprocessorDefinitions="NDEBUG" > 253 MkTypLibCompatible="true" > 254 SuppressStartupBanner="true" > 255 TargetEnvironment="1" > 256 TypeLibraryName=".\release/kilib.tlb" > 257 /> > 258 <Tool > 259 Name="VCCLCompilerTool" > 260 Optimization="3" > 261 InlineFunctionExpansion="1" > 262 EnableIntrinsicFunctions="true" > 263 FavorSizeOrSpeed="2" > 264 OmitFramePointers="true" > 265 EnableFiberSafeOptimizations="true" > 266 WholeProgramOptimization="false" > 267 PreprocessorDefinitions="WIN32,NDEBUG,_WINDOWS,S > 268 StringPooling="true" > 269 ExceptionHandling="0" > 270 RuntimeLibrary="0" > 271 StructMemberAlignment="0" > 272 BufferSecurityCheck="false" > 273 EnableFunctionLevelLinking="true" > 274 RuntimeTypeInfo="false" > 275 UsePrecompiledHeader="2" > 276 PrecompiledHeaderThrough="stdafx.h" > 277 PrecompiledHeaderFile=".\OBJ/vc/rel/kilib.pch" > 278 AssemblerListingLocation=".\OBJ/vc/rel/" > 279 ObjectFile=".\OBJ/vc/rel/" > 280 ProgramDataBaseFileName=".\OBJ/vc/rel/" > 281 WarningLevel="3" > 282 SuppressStartupBanner="true" > 283 Detect64BitPortabilityProblems="false" > 284 DebugInformationFormat="0" > 285 CallingConvention="1" > 286 /> > 287 <Tool > 288 Name="VCManagedResourceCompilerTool" > 289 /> > 290 <Tool > 291 Name="VCResourceCompilerTool" > 292 PreprocessorDefinitions="NDEBUG" > 293 Culture="1041" > 294 /> > 295 <Tool > 296 Name="VCPreLinkEventTool" > 297 /> > 298 <Tool > 299 Name="VCLinkerTool" > 300 AdditionalOptions="/MACHINE:I386 /merge:.rdata=. > 301 AdditionalDependencies="kernel32.lib user32.lib > 302 OutputFile="release/GreenPad.exe" > 303 LinkIncremental="1" > 304 SuppressStartupBanner="true" > 305 GenerateManifest="false" > 306 IgnoreAllDefaultLibraries="true" > 307 GenerateDebugInformation="false" > 308 ProgramDatabaseFile=".\release/GreenPad.pdb" > 309 GenerateMapFile="true" > 310 MapFileName=".\OBJ/vc/rel/GreenPad.map" > 311 SubSystem="2" > 312 OptimizeReferences="2" > 313 EnableCOMDATFolding="2" > 314 OptimizeForWindows98="1" > 315 LinkTimeCodeGeneration="0" > 316 EntryPointSymbol="" > 317 /> > 318 <Tool > 319 Name="VCALinkTool" > 320 /> > 321 <Tool > 322 Name="VCManifestTool" > 323 EmbedManifest="true" > 324 /> > 325 <Tool > 326 Name="VCXDCMakeTool" > 327 /> > 328 <Tool > 329 Name="VCBscMakeTool" > 330 /> > 331 <Tool > 332 Name="VCFxCopTool" > 333 /> > 334 <Tool > 335 Name="VCAppVerifierTool" > 336 /> > 337 <Tool > 338 Name="VCWebDeploymentTool" > 339 /> > 340 <Tool > 341 Name="VCPostBuildEventTool" > 342 /> > 343 </Configuration> > 344 </Configurations> > 345 <References> > 346 </References> > 347 <Files> > 348 <Filter > 349 Name="Source Files" > 350 Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > 351 > > 352 <File > 353 RelativePath=".\ConfigManager.cpp" > 354 > > 355 </File> > 356 <File > 357 RelativePath=".\GpMain.cpp" > 358 > > 359 </File> > 360 <File > 361 RelativePath="kilib\log.cpp" > 362 > > 363 </File> > 364 <File > 365 RelativePath=".\OpenSaveDlg.cpp" > 366 > > 367 </File> > 368 <File > 369 RelativePath=".\RSearch.cpp" > 370 > > 371 </File> > 372 <File > 373 RelativePath=".\Search.cpp" > 374 > > 375 </File> > 376 </Filter> > 377 <Filter > 378 Name="Header Files" > 379 Filter="h;hpp;hxx;hm;inl" > 380 > > 381 <File > 382 RelativePath=".\ConfigManager.h" > 383 > > 384 </File> > 385 <File > 386 RelativePath=".\GpMain.h" > 387 > > 388 </File> > 389 <File > 390 RelativePath="kilib\log.h" > 391 > > 392 </File> > 393 <File > 394 RelativePath=".\NSearch.h" > 395 > > 396 </File> > 397 <File > 398 RelativePath=".\OpenSaveDlg.h" > 399 > > 400 </File> > 401 <File > 402 RelativePath=".\RSearch.h" > 403 > > 404 </File> > 405 <File > 406 RelativePath=".\Search.h" > 407 > > 408 </File> > 409 </Filter> > 410 <Filter > 411 Name="Resource Files" > 412 Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe > 413 > > 414 <File > 415 RelativePath=".\rsrc\exefile.ico" > 416 > > 417 </File> > 418 <File > 419 RelativePath=".\rsrc\gp_rsrc.rc" > 420 > > 421 </File> > 422 <File > 423 RelativePath=".\rsrc\manifest.xml" > 424 > > 425 </File> > 426 <File > 427 RelativePath=".\rsrc\resource.h" > 428 > > 429 </File> > 430 </Filter> > 431 <Filter > 432 Name="kilib" > 433 > > 434 <File > 435 RelativePath=".\kilib\kilib.h" > 436 > > 437 </File> > 438 <File > 439 RelativePath=".\kilib\stdafx.h" > 440 > > 441 </File> > 442 <Filter > 443 Name="Source" > 444 Filter="cpp" > 445 > > 446 <File > 447 RelativePath=".\kilib\app.cpp" > 448 > > 449 </File> > 450 <File > 451 RelativePath=".\kilib\cmdarg.cpp" > 452 > > 453 </File> > 454 <File > 455 RelativePath=".\kilib\ctrl.cpp" > 456 > > 457 </File> > 458 <File > 459 RelativePath=".\kilib\file.cpp" > 460 > > 461 </File> > 462 <File > 463 RelativePath=".\kilib\find.cpp" > 464 > > 465 </File> > 466 <File > 467 RelativePath=".\kilib\memory.cpp" > 468 > > 469 <FileConfiguration > 470 Name="Unicode Release|Win32" > 471 > > 472 <Tool > 473 Name="VCCLCompilerTool" > 474 Optimization="1" > 475 EnableIntrinsicFunctions > 476 WholeProgramOptimization > 477 /> > 478 </FileConfiguration> > 479 <FileConfiguration > 480 Name="Release|Win32" > 481 > > 482 <Tool > 483 Name="VCCLCompilerTool" > 484 Optimization="1" > 485 EnableIntrinsicFunctions > 486 /> > 487 </FileConfiguration> > 488 </File> > 489 <File > 490 RelativePath=".\kilib\path.cpp" > 491 > > 492 </File> > 493 <File > 494 RelativePath=".\kilib\registry.cpp" > 495 > > 496 </File> > 497 <File > 498 RelativePath=".\kilib\stdafx.cpp" > 499 > > 500 <FileConfiguration > 501 Name="Unicode Release|Win32" > 502 > > 503 <Tool > 504 Name="VCCLCompilerTool" > 505 EnableIntrinsicFunctions > 506 UsePrecompiledHeader="1" > 507 /> > 508 </FileConfiguration> > 509 <FileConfiguration > 510 Name="Debug|Win32" > 511 > > 512 <Tool > 513 Name="VCCLCompilerTool" > 514 UsePrecompiledHeader="1" > 515 /> > 516 </FileConfiguration> > 517 <FileConfiguration > 518 Name="Release|Win32" > 519 > > 520 <Tool > 521 Name="VCCLCompilerTool" > 522 UsePrecompiledHeader="1" > 523 /> > 524 </FileConfiguration> > 525 </File> > 526 <File > 527 RelativePath=".\kilib\string.cpp" > 528 > > 529 </File> > 530 <File > 531 RelativePath=".\kilib\textfile.cpp" > 532 > > 533 </File> > 534 <File > 535 RelativePath=".\kilib\thread.cpp" > 536 > > 537 </File> > 538 <File > 539 RelativePath=".\kilib\window.cpp" > 540 > > 541 </File> > 542 <File > 543 RelativePath=".\kilib\winutil.cpp" > 544 > > 545 </File> > 546 </Filter> > 547 <Filter > 548 Name="Header" > 549 Filter="h" > 550 > > 551 <File > 552 RelativePath=".\kilib\app.h" > 553 > > 554 </File> > 555 <File > 556 RelativePath=".\kilib\cmdarg.h" > 557 > > 558 </File> > 559 <File > 560 RelativePath=".\kilib\ctrl.h" > 561 > > 562 </File> > 563 <File > 564 RelativePath=".\kilib\file.h" > 565 > > 566 </File> > 567 <File > 568 RelativePath=".\kilib\find.h" > 569 > > 570 </File> > 571 <File > 572 RelativePath=".\kilib\memory.h" > 573 > > 574 </File> > 575 <File > 576 RelativePath=".\kilib\path.h" > 577 > > 578 </File> > 579 <File > 580 RelativePath=".\kilib\registry.h" > 581 > > 582 </File> > 583 <File > 584 RelativePath=".\kilib\string.h" > 585 > > 586 </File> > 587 <File > 588 RelativePath=".\kilib\textfile.h" > 589 > > 590 </File> > 591 <File > 592 RelativePath=".\kilib\thread.h" > 593 > > 594 </File> > 595 <File > 596 RelativePath=".\kilib\types.h" > 597 > > 598 </File> > 599 <File > 600 RelativePath=".\kilib\window.h" > 601 > > 602 </File> > 603 <File > 604 RelativePath=".\kilib\winutil.h" > 605 > > 606 </File> > 607 </Filter> > 608 <Filter > 609 Name="KTL" > 610 > > 611 <File > 612 RelativePath=".\kilib\ktlaptr.h" > 613 > > 614 </File> > 615 <File > 616 RelativePath=".\kilib\ktlarray.h" > 617 > > 618 </File> > 619 <File > 620 RelativePath=".\kilib\ktlgap.h" > 621 > > 622 </File> > 623 </Filter> > 624 </Filter> > 625 <Filter > 626 Name="editwing" > 627 > > 628 <File > 629 RelativePath=".\editwing\editwing.h" > 630 > > 631 </File> > 632 <Filter > 633 Name="public" > 634 > > 635 <File > 636 RelativePath=".\editwing\ewCommon.h" > 637 > > 638 </File> > 639 <File > 640 RelativePath=".\editwing\ewCtrl1.h" > 641 > > 642 </File> > 643 <File > 644 RelativePath=".\editwing\ewDoc.h" > 645 > > 646 </File> > 647 <File > 648 RelativePath=".\editwing\ewView.h" > 649 > > 650 </File> > 651 </Filter> > 652 <Filter > 653 Name="private" > 654 > > 655 <File > 656 RelativePath=".\editwing\ip_ctrl1.cpp" > 657 > > 658 </File> > 659 <File > 660 RelativePath=".\editwing\ip_cursor.cpp" > 661 > > 662 </File> > 663 <File > 664 RelativePath=".\editwing\ip_doc.h" > 665 > > 666 </File> > 667 <File > 668 RelativePath=".\editwing\ip_draw.cpp" > 669 > > 670 </File> > 671 <File > 672 RelativePath=".\editwing\ip_parse.cpp" > 673 > > 674 </File> > 675 <File > 676 RelativePath=".\editwing\ip_scroll.cpp" > 677 > > 678 </File> > 679 <File > 680 RelativePath=".\editwing\ip_text.cpp" > 681 > > 682 </File> > 683 <File > 684 RelativePath=".\editwing\ip_view.h" > 685 > > 686 </File> > 687 <File > 688 RelativePath=".\editwing\ip_wrap.cpp" > 689 > > 690 </File> > 691 </Filter> > 692 </Filter> > 693 </Files> > 694 <Globals> > 695 </Globals> > 696 </VisualStudioProject>

Added kilib/app.cpp version [280129b06e0f3905]

> 1 #include "stdafx.h" > 2 #include "app.h" > 3 #include "log.h" > 4 #include "memory.h" > 5 #include "thread.h" > 6 #include "window.h" > 7 #include "string.h" > 8 using namespace ki; > 9 > 10 > 11 > 12 //========================================================================= > 13 > 14 App* App::pUniqueInstance_; > 15 > 16 inline App::App() > 17 : exitcode_ (-1) > 18 , loadedModule_(0) > 19 , hInst_ (::GetModuleHandle(NULL)) > 20 { > 21 // 唯一のインスタンスは私です。 > 22 pUniqueInstance_ = this; > 23 } > 24 > 25 #pragma warning( disable : 4722 ) // 警告:デストラクタに値が戻りません > 26 App::~App() > 27 { > 28 // ロード済みモジュールがあれば閉じておく > 29 if( loadedModule_ & COM ) > 30 ::CoUninitialize(); > 31 if( loadedModule_ & OLE ) > 32 ::OleUninitialize(); > 33 > 34 // 終〜了〜 > 35 ::ExitProcess( exitcode_ ); > 36 } > 37 > 38 inline void App::SetExitCode( int code ) > 39 { > 40 // 終了コードを設定 > 41 exitcode_ = code; > 42 } > 43 > 44 void App::InitModule( imflag what ) > 45 { > 46 // 初期化済みでなければ初期化する > 47 if( !(loadedModule_ & what) ) > 48 switch( what ) > 49 { > 50 case CTL: ::InitCommonControls(); break; > 51 case COM: ::CoInitialize( NULL ); break; > 52 case OLE: ::OleInitialize( NULL );break; > 53 } > 54 > 55 // 今回初期化したモノを記憶 > 56 loadedModule_ |= what; > 57 } > 58 > 59 void App::Exit( int code ) > 60 { > 61 // 終了コードを設定して > 62 SetExitCode( code ); > 63 > 64 // 自殺 > 65 this->~App(); > 66 } > 67 > 68 > 69 > 70 //------------------------------------------------------------------------- > 71 > 72 const OSVERSIONINFO& App::osver() > 73 { > 74 static OSVERSIONINFO s_osVer; > 75 if( s_osVer.dwOSVersionInfoSize == 0 ) > 76 { > 77 // 初回だけは情報取得 > 78 s_osVer.dwOSVersionInfoSize = sizeof( s_osVer ); > 79 ::GetVersionEx( &s_osVer ); > 80 } > 81 return s_osVer; > 82 } > 83 > 84 bool App::isNewTypeWindows() > 85 { > 86 static const OSVERSIONINFO& v = osver(); > 87 return ( > 88 ( v.dwPlatformId==VER_PLATFORM_WIN32_NT && v.dwMajorVersion>=5 ) > 89 || ( v.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS && > 90 v.dwMajorVersion*100+v.dwMinorVersion>=410 ) > 91 ); > 92 } > 93 > 94 bool App::isWin95() > 95 { > 96 static const OSVERSIONINFO& v = osver(); > 97 return ( > 98 v.dwPlatformId==VER_PLATFORM_WIN32_WINDOWS && > 99 v.dwMajorVersion==4 && > 100 v.dwMinorVersion==0 > 101 ); > 102 } > 103 > 104 bool App::isNT() > 105 { > 106 static const OSVERSIONINFO& v = osver(); > 107 return v.dwPlatformId==VER_PLATFORM_WIN32_NT; > 108 } > 109 > 110 > 111 > 112 //========================================================================= > 113 > 114 extern int kmain(); > 115 > 116 namespace ki > 117 { > 118 void APIENTRY Startup() > 119 { > 120 // Startup : > 121 // プログラム開始すると、真っ先にここに来ます。 > 122 > 123 // C++のローカルオブジェクトの破棄順序の仕様に > 124 // 自信がないので(^^;、スコープを利用して順番を強制 > 125 // たぶん宣言の逆順だとは思うんだけど… > 126 > 127 LOGGER( "StartUp" ); > 128 App myApp; > 129 { > 130 LOGGER( "StartUp app ok" ); > 131 ThreadManager myThr; > 132 { > 133 LOGGER( "StartUp thr ok" ); > 134 MemoryManager myMem; > 135 { > 136 LOGGER( "StartUp mem ok" ); > 137 IMEManager myIME; > 138 { > 139 LOGGER( "StartUp ime ok" ); > 140 String::LibInit(); > 141 { > 142 const int r = kmain(); > 143 myApp.SetExitCode( r ); > 144 } > 145 } > 146 } > 147 } > 148 } > 149 } > 150 } > 151 > 152 #ifdef SUPERTINY > 153 > 154 extern "C" int __cdecl _purecall(){return 0;} > 155 #ifdef _DEBUG > 156 int main(){return 0;} > 157 #endif > 158 #pragma comment(linker, "/entry:\"Startup\"") > 159 > 160 #else > 161 > 162 // VS2005でビルドしてもWin95で動くようにするため > 163 #if _MSC_VER >= 1400 > 164 extern "C" BOOL WINAPI _imp__IsDebuggerPresent() { return FALSE; > 165 #endif > 166 > 167 int APIENTRY WinMain( HINSTANCE, HINSTANCE, LPSTR, int ) > 168 { > 169 ki::Startup(); > 170 return 0; > 171 } > 172 > 173 #endif

Added kilib/app.h version [6f13d2b44d31dee8]

> 1 #ifndef _KILIB_APP_H_ > 2 #define _KILIB_APP_H_ > 3 #include "types.h" > 4 #include "log.h" > 5 #ifndef __ccdoc__ > 6 namespace ki { > 7 #endif > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg ki.Core //@} > 13 //@{ > 14 // アプリケーション全体の統括 > 15 // > 16 // アプリ起動/終了用処理を担当します。 > 17 // 旧kilibと違って、ユーザー側のアプリケーションクラスを > 18 // ここから派生させることは出来ません。ユーザーのコードは、 > 19 // 必ず kmain() というグローバル関数から実行開始されます。 > 20 // このAppクラス自体は、主にHINSTANCEの管理を行うだけ。 > 21 //@} > 22 //========================================================================= > 23 > 24 class App > 25 { > 26 public: > 27 > 28 enum imflag { CTL=1, COM=2, OLE=4 }; > 29 > 30 //@{ > 31 // 種々のモジュールを初期化する > 32 // > 33 // これで初期化しておくと、App終了時に自動で > 34 // 終了処理が行われるので簡単便利でございます。 > 35 // @param what CTL(コモンコントロール)、COM、OLE > 36 //@} > 37 void InitModule( imflag what ); > 38 > 39 //@{ プロセス強制終了 //@} > 40 void Exit( int code ); > 41 > 42 //@{ リソース //@} > 43 HACCEL LoadAccel( LPCTSTR name ); > 44 > 45 //@{ リソース //@} > 46 HACCEL LoadAccel( UINT id ); > 47 > 48 //@{ リソース //@} > 49 HBITMAP LoadBitmap( LPCTSTR name ); > 50 > 51 //@{ リソース //@} > 52 HBITMAP LoadBitmap( UINT id ); > 53 > 54 //@{ リソース(OBM_XXXX) //@} > 55 HBITMAP LoadOemBitmap( LPCTSTR obm ); > 56 > 57 //@{ リソース //@} > 58 HCURSOR LoadCursor( LPCTSTR name ); > 59 > 60 //@{ リソース //@} > 61 HCURSOR LoadCursor( UINT id ); > 62 > 63 //@{ リソース(IDC_XXXX) //@} > 64 HCURSOR LoadOemCursor( LPCTSTR idc ); > 65 > 66 //@{ リソース //@} > 67 HICON LoadIcon( LPCTSTR name ); > 68 > 69 //@{ リソース //@} > 70 HICON LoadIcon( UINT id ); > 71 > 72 //@{ リソース(IDI_XXXX) //@} > 73 HICON LoadOemIcon( LPCTSTR idi ); > 74 > 75 //@{ リソース //@} > 76 HMENU LoadMenu( LPCTSTR name ); > 77 > 78 //@{ リソース //@} > 79 HMENU LoadMenu( UINT id ); > 80 > 81 //@{ リソース //@} > 82 int LoadString( UINT id, LPTSTR buf, int siz ); > 83 > 84 public: > 85 > 86 //@{ インスタンスハンドル //@} > 87 HINSTANCE hinst() const; > 88 > 89 //@{ Windowsのバージョン //@} > 90 static const OSVERSIONINFO& osver(); > 91 static bool isWin95(); > 92 static bool isNT(); > 93 static bool isNewTypeWindows(); > 94 > 95 private: > 96 > 97 App(); > 98 ~App(); > 99 void SetExitCode( int code ); > 100 > 101 private: > 102 > 103 int exitcode_; > 104 ulong loadedModule_; > 105 const HINSTANCE hInst_; > 106 static App* pUniqueInstance_; > 107 > 108 private: > 109 > 110 friend void APIENTRY Startup(); > 111 friend inline App& app(); > 112 NOCOPY(App); > 113 }; > 114 > 115 > 116 > 117 //------------------------------------------------------------------------- > 118 > 119 //@{ 唯一のアプリ情報オブジェクトを返す //@} > 120 inline App& app() > 121 { return *App::pUniqueInstance_; } > 122 > 123 inline HACCEL App::LoadAccel( LPCTSTR name ) > 124 { return ::LoadAccelerators( hInst_, name ); } > 125 > 126 inline HACCEL App::LoadAccel( UINT id ) > 127 { return ::LoadAccelerators( hInst_, MAKEINTRESOURCE(id) ); } > 128 > 129 inline HBITMAP App::LoadBitmap( LPCTSTR name ) > 130 { return ::LoadBitmap( hInst_, name ); } > 131 > 132 inline HBITMAP App::LoadBitmap( UINT id ) > 133 { return ::LoadBitmap( hInst_, MAKEINTRESOURCE(id) ); } > 134 > 135 inline HBITMAP App::LoadOemBitmap( LPCTSTR obm ) > 136 { return ::LoadBitmap( NULL, obm ); } > 137 > 138 inline HCURSOR App::LoadCursor( LPCTSTR name ) > 139 { return ::LoadCursor( hInst_, name ); } > 140 > 141 inline HCURSOR App::LoadCursor( UINT id ) > 142 { return ::LoadCursor( hInst_, MAKEINTRESOURCE(id) ); } > 143 > 144 inline HCURSOR App::LoadOemCursor( LPCTSTR idc ) > 145 { return ::LoadCursor( NULL, idc ); } > 146 > 147 inline HICON App::LoadIcon( LPCTSTR name ) > 148 { return ::LoadIcon( hInst_, name ); } > 149 > 150 inline HICON App::LoadIcon( UINT id ) > 151 { return ::LoadIcon( hInst_, MAKEINTRESOURCE(id) ); } > 152 > 153 inline HICON App::LoadOemIcon( LPCTSTR idi ) > 154 { return ::LoadIcon( NULL, idi ); } > 155 > 156 inline HMENU App::LoadMenu( LPCTSTR name ) > 157 { return ::LoadMenu( hInst_, name ); } > 158 > 159 inline HMENU App::LoadMenu( UINT id ) > 160 { return ::LoadMenu( hInst_, MAKEINTRESOURCE(id) ); } > 161 > 162 inline int App::LoadString( UINT id, LPTSTR buf, int siz ) > 163 { return ::LoadString( hInst_, id, buf, siz ); } > 164 > 165 inline HINSTANCE App::hinst() const > 166 { return hInst_; } > 167 > 168 > 169 > 170 //========================================================================= > 171 > 172 } // namespace ki > 173 #endif // _KILIB_APP_H_

Added kilib/cmdarg.cpp version [ea1908bbabe7d2df]

> 1 #include "stdafx.h" > 2 #include "cmdarg.h" > 3 #include "string.h" > 4 using namespace ki; > 5 > 6 > 7 > 8 //========================================================================= > 9 > 10 Argv::Argv( const TCHAR* cmd ) > 11 { > 12 TCHAR *p, endc; > 13 > 14 buf_ = (p=new TCHAR[::lstrlen(cmd)+1]); > 15 ::lstrcpy( p, cmd ); > 16 > 17 while( *p != TEXT('\0') ) > 18 { > 19 // 引数を区切る空白をスキップ > 20 while( *p == TEXT(' ') ) > 21 ++p; > 22 > 23 // " だったら、その旨記録してさらに一個進める > 24 if( *p == TEXT('\"') ) > 25 endc=TEXT('\"'), ++p; > 26 else > 27 endc=TEXT(' '); > 28 > 29 // 文字列終端なら終了 > 30 if( *p == TEXT('\0') ) > 31 break; > 32 > 33 // 引数リストへ保存 > 34 arg_.Add( p ); > 35 > 36 // 引数の終わりへ… > 37 while( *p!=endc && *p!=TEXT('\0') ) > 38 ++p; > 39 > 40 // 終わりは'\0'にすることによって、引数を区切る > 41 if( *p != TEXT('\0') ) > 42 *p++ = TEXT('\0'); > 43 } > 44 }

Added kilib/cmdarg.h version [d905908ecc5c2d31]

> 1 #ifndef _KILIB_CMDARG_H_ > 2 #define _KILIB_CMDARG_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #include "ktlaptr.h" > 6 #include "ktlarray.h" > 7 #ifndef __ccdoc__ > 8 namespace ki { > 9 #endif > 10 > 11 > 12 > 13 //========================================================================= > 14 //@{ @pkg ki.StdLib //@} > 15 //@{ > 16 // コマンドライン文字列の分割 > 17 // > 18 // ただ単にスペースと二重引用符を考慮して区切るだけです。 > 19 //@} > 20 //========================================================================= > 21 > 22 class Argv : public Object > 23 { > 24 public: > 25 > 26 //@{ 指定された文字列を分割する //@} > 27 Argv( const TCHAR* cmd = GetCommandLine() ); > 28 > 29 //@{ 引数Get //@} > 30 const TCHAR* operator[]( ulong i ) const; > 31 > 32 //@{ 引数の個数 //@} > 33 ulong size() const; > 34 > 35 private: > 36 > 37 darr<TCHAR> buf_; > 38 storage<const TCHAR*> arg_; > 39 > 40 private: > 41 > 42 NOCOPY(Argv); > 43 }; > 44 > 45 > 46 > 47 //------------------------------------------------------------------------- > 48 #ifndef __ccdoc__ > 49 > 50 inline const TCHAR* Argv::operator []( ulong i ) const > 51 { return arg_[i]; } > 52 > 53 inline ulong Argv::size() const > 54 { return arg_.size(); } > 55 > 56 > 57 > 58 //========================================================================= > 59 > 60 #endif // __ccdoc__ > 61 } // namespace ki > 62 #endif // _KILIB_CMDARG_H_

Added kilib/ctrl.cpp version [6c0d29e2f223490b]

> 1 #include "stdafx.h" > 2 #include "app.h" > 3 #include "ctrl.h" > 4 using namespace ki; > 5 > 6 > 7 > 8 //========================================================================= > 9 > 10 StatusBar::StatusBar() > 11 { > 12 app().InitModule( App::CTL ); > 13 } > 14 > 15 bool StatusBar::Create( HWND parent ) > 16 { > 17 HWND h = ::CreateStatusWindow( > 18 WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP, > 19 TEXT(""), parent, 1787 ); > 20 if( h == NULL ) > 21 return false; > 22 > 23 SetStatusBarVisible(); > 24 SetHwnd( h ); > 25 AutoResize( false ); > 26 return true; > 27 } > 28 > 29 int StatusBar::AutoResize( bool maximized ) > 30 { > 31 // サイズ自動変更 > 32 SendMsg( WM_SIZE ); > 33 > 34 // 変更後のサイズを取得 > 35 RECT rc; > 36 getPos( &rc ); > 37 width_ = rc.right - rc.left; > 38 if( !maximized ) > 39 width_ -= 15; > 40 return (isStatusBarVisible() ? rc.bottom - rc.top : 0); > 41 } > 42 > 43 bool StatusBar::PreTranslateMessage( MSG* ) > 44 { > 45 // 何もしない > 46 return false; > 47 } > 48 > 49 > 50 > 51 //========================================================================= > 52 > 53 void ComboBox::Select( const TCHAR* str ) > 54 { > 55 // SELECTSTRING は先頭が合ってる物に全てにマッチするので使えない。 > 56 // おそらくインクリメンタルサーチとかに使うべきものなのだろう。 > 57 size_t i = > 58 SendMsg( CB_FINDSTRINGEXACT, ~0, reinterpret_cast<LPARAM>(str) ) > 59 if( i != CB_ERR ) > 60 SendMsg( CB_SETCURSEL, i ); > 61 } > 62 > 63 bool ComboBox::PreTranslateMessage( MSG* ) > 64 { > 65 return false; > 66 }

Added kilib/ctrl.h version [21ba63c586f76d54]

> 1 #ifndef _KILIB_CTRL_H_ > 2 #define _KILIB_CTRL_H_ > 3 #include "window.h" > 4 #ifndef __ccdoc__ > 5 namespace ki { > 6 #endif > 7 > 8 > 9 > 10 //========================================================================= > 11 //@{ @pkg ki.Window //@} > 12 //@{ > 13 // ステータスバー > 14 //@} > 15 //========================================================================= > 16 > 17 class StatusBar : public Window > 18 { > 19 public: > 20 > 21 StatusBar(); > 22 bool Create( HWND parent ); > 23 int AutoResize( bool maximized ); > 24 void SetText( const TCHAR* str, int part=0 ); > 25 void SetTipText( const TCHAR* tip, int part=0 ); > 26 void SetParts( int n, int* parts ); > 27 void SetStatusBarVisible(bool b=true); > 28 > 29 public: > 30 > 31 int width() const; > 32 bool isStatusBarVisible() const; > 33 > 34 private: > 35 > 36 virtual bool PreTranslateMessage( MSG* ); > 37 > 38 private: > 39 > 40 int width_; > 41 bool visible_; > 42 }; > 43 > 44 > 45 > 46 //------------------------------------------------------------------------- > 47 #ifndef __ccdoc__ > 48 > 49 inline int StatusBar::width() const > 50 { return width_; } > 51 > 52 inline bool StatusBar::isStatusBarVisible() const > 53 { return visible_; } > 54 > 55 inline void StatusBar::SetParts( int n, int* parts ) > 56 { SendMsg( SB_SETPARTS, n, reinterpret_cast<LPARAM>(parts) ); } > 57 > 58 inline void StatusBar::SetText( const TCHAR* str, int part ) > 59 { SendMsg( SB_SETTEXT, part, reinterpret_cast<LPARAM>(str) ); } > 60 > 61 inline void StatusBar::SetStatusBarVisible(bool b) > 62 { ::ShowWindow( hwnd(), b?SW_SHOW:SW_HIDE ); visible_=b; } > 63 > 64 > 65 > 66 #endif // __ccdoc__ > 67 //========================================================================= > 68 //@{ > 69 // コンボボックス > 70 //@} > 71 //========================================================================= > 72 > 73 class ComboBox : public Window > 74 { > 75 public: > 76 explicit ComboBox( HWND cb ); > 77 explicit ComboBox( HWND dlg, UINT id ); > 78 void Add( const TCHAR* str ); > 79 void Select( const TCHAR* str ); > 80 int GetCurSel(); > 81 private: > 82 virtual bool PreTranslateMessage( MSG* ); > 83 }; > 84 > 85 > 86 > 87 //------------------------------------------------------------------------- > 88 #ifndef __ccdoc__ > 89 > 90 inline ComboBox::ComboBox( HWND cb ) > 91 { SetHwnd(cb); } > 92 > 93 inline ComboBox::ComboBox( HWND dlg, UINT id ) > 94 { SetHwnd( ::GetDlgItem(dlg,id) ); } > 95 > 96 inline void ComboBox::Add( const TCHAR* str ) > 97 { SendMsg( CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str) ); } > 98 > 99 inline int ComboBox::GetCurSel() > 100 { return (int) SendMsg( CB_GETCURSEL ); } > 101 > 102 > 103 > 104 //========================================================================= > 105 > 106 #endif // __ccdoc__ > 107 } // namespace ki > 108 #endif // _KILIB_CTRL_H_

Added kilib/file.cpp version [41942e064e293875]

> 1 #include "stdafx.h" > 2 #include "file.h" > 3 using namespace ki; > 4 > 5 > 6 > 7 //========================================================================= > 8 > 9 FileR::FileR() > 10 : handle_ ( INVALID_HANDLE_VALUE ) > 11 , fmo_ ( NULL ) > 12 , basePtr_( NULL ) > 13 { > 14 } > 15 > 16 FileR::~FileR() > 17 { > 18 Close(); > 19 } > 20 > 21 bool FileR::Open( const TCHAR* fname ) > 22 { > 23 Close(); > 24 > 25 // ファイルを読みとり専用で開く > 26 handle_ = ::CreateFile( > 27 fname, GENERIC_READ, > 28 FILE_SHARE_READ|FILE_SHARE_WRITE, > 29 NULL, OPEN_EXISTING, > 30 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL > 31 ); > 32 if( handle_ == INVALID_HANDLE_VALUE ) > 33 return false; > 34 > 35 // サイズを取得 > 36 size_ = ::GetFileSize( handle_, NULL ); > 37 > 38 if( size_==0 ) > 39 { > 40 // 0バイトのファイルはマッピング出来ないので適当に回避 > 41 basePtr_ = &size_; > 42 } > 43 else > 44 { > 45 // マッピングオブジェクトを作る > 46 fmo_ = ::CreateFileMapping( > 47 handle_, NULL, PAGE_READONLY, 0, 0, NULL ); > 48 if( fmo_ == NULL ) > 49 { > 50 ::CloseHandle( handle_ ); > 51 handle_ = INVALID_HANDLE_VALUE; > 52 return false; > 53 } > 54 > 55 // ビュー > 56 basePtr_ = ::MapViewOfFile( fmo_, FILE_MAP_READ, 0, 0, 0 ); > 57 if( basePtr_ == NULL ) > 58 { > 59 ::CloseHandle( fmo_ ); > 60 ::CloseHandle( handle_ ); > 61 handle_ = INVALID_HANDLE_VALUE; > 62 return false; > 63 } > 64 } > 65 return true; > 66 } > 67 > 68 void FileR::Close() > 69 { > 70 if( handle_ != INVALID_HANDLE_VALUE ) > 71 { > 72 // ヘンテコマッピングをしてなければここで解放 > 73 if( basePtr_ != &size_ ) > 74 ::UnmapViewOfFile( const_cast<void*>(basePtr_) ); > 75 basePtr_ = NULL; > 76 > 77 if( fmo_ != NULL ) > 78 ::CloseHandle( fmo_ ); > 79 fmo_ = NULL; > 80 > 81 ::CloseHandle( handle_ ); > 82 handle_ = INVALID_HANDLE_VALUE; > 83 } > 84 } > 85 > 86 > 87 > 88 //========================================================================= > 89 > 90 FileW::FileW() > 91 : BUFSIZE( 65536 ) > 92 , handle_( INVALID_HANDLE_VALUE ) > 93 , buf_ ( new uchar[BUFSIZE] ) > 94 { > 95 } > 96 > 97 FileW::~FileW() > 98 { > 99 Close(); > 100 delete [] buf_; > 101 } > 102 > 103 inline void FileW::Flush() > 104 { > 105 DWORD dummy; > 106 ::WriteFile( handle_, buf_, bPos_, &dummy, NULL ); > 107 bPos_ = 0; > 108 } > 109 > 110 bool FileW::Open( const TCHAR* fname, bool creat ) > 111 { > 112 Close(); > 113 > 114 // ファイルを書き込み専用で開く > 115 handle_ = ::CreateFile( fname, > 116 GENERIC_WRITE, FILE_SHARE_READ, NULL, > 117 creat ? CREATE_ALWAYS : OPEN_EXISTING, > 118 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); > 119 if( handle_ == INVALID_HANDLE_VALUE ) > 120 return false; > 121 > 122 bPos_ = 0; > 123 return true; > 124 } > 125 > 126 void FileW::Close() > 127 { > 128 if( handle_ != INVALID_HANDLE_VALUE ) > 129 { > 130 Flush(); > 131 ::CloseHandle( handle_ ); > 132 handle_ = INVALID_HANDLE_VALUE; > 133 } > 134 } > 135 > 136 void FileW::Write( const void* dat, ulong siz ) > 137 { > 138 const uchar* udat = static_cast<const uchar*>(dat); > 139 > 140 while( (BUFSIZE-bPos_) <= siz ) > 141 { > 142 memmove( buf_+bPos_, udat, BUFSIZE-bPos_ ); > 143 siz -= (BUFSIZE-bPos_); > 144 udat += (BUFSIZE-bPos_); > 145 bPos_ = BUFSIZE; > 146 Flush(); > 147 } > 148 > 149 memmove( buf_+bPos_, udat, siz ); > 150 bPos_ += siz; > 151 } > 152 > 153 void FileW::WriteC( uchar ch ) > 154 { > 155 if( (BUFSIZE-bPos_) <= 1 ) > 156 Flush(); > 157 > 158 buf_[bPos_++] = ch; > 159 } > 160

Added kilib/file.h version [f917f310296a724b]

> 1 #ifndef _KILIB_FILE_H_ > 2 #define _KILIB_FILE_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #ifndef __ccdoc__ > 6 namespace ki { > 7 #endif > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg ki.StdLib //@} > 13 //@{ > 14 // 簡易ファイル読込 > 15 // > 16 // ファイルマッピングを用いるので、扱いが簡単でわりと高速です。 > 17 // ただし困ったことに、4GBまでしか開けません。 > 18 //@} > 19 //========================================================================= > 20 > 21 class FileR : public Object > 22 { > 23 public: > 24 > 25 FileR(); > 26 ~FileR(); > 27 > 28 //@{ > 29 // 開く > 30 // @param fname ファイル名 > 31 // @return 開けたかどうか > 32 //@} > 33 bool Open( const TCHAR* fname ); > 34 > 35 //@{ > 36 // 閉じる > 37 //@} > 38 void Close(); > 39 > 40 public: > 41 > 42 //@{ ファイルサイズ //@} > 43 ulong size() const; > 44 > 45 //@{ ファイル内容をマップしたアドレス取得 //@} > 46 const uchar* base() const; > 47 > 48 private: > 49 > 50 HANDLE handle_; > 51 HANDLE fmo_; > 52 ulong size_; > 53 const void* basePtr_; > 54 > 55 private: > 56 > 57 NOCOPY(FileR); > 58 }; > 59 > 60 > 61 > 62 //------------------------------------------------------------------------- > 63 > 64 inline ulong FileR::size() const > 65 { return size_; } > 66 > 67 inline const uchar* FileR::base() const > 68 { return static_cast<const uchar*>(basePtr_); } > 69 > 70 > 71 > 72 //========================================================================= > 73 //@{ > 74 // 簡易ファイル書き込み > 75 // > 76 // てきとーにバッファリングしつつ。 > 77 //@} > 78 //========================================================================= > 79 > 80 class FileW : public Object > 81 { > 82 public: > 83 > 84 FileW(); > 85 ~FileW(); > 86 > 87 //@{ 開く //@} > 88 bool Open( const TCHAR* fname, bool creat=true ); > 89 > 90 //@{ 閉じる //@} > 91 void Close(); > 92 > 93 //@{ 書く //@} > 94 void Write( const void* buf, ulong siz ); > 95 > 96 //@{ 一文字書く //@} > 97 void WriteC( uchar ch ); > 98 > 99 public: > 100 > 101 void Flush(); > 102 > 103 private: > 104 > 105 const int BUFSIZE; > 106 HANDLE handle_; > 107 uchar* const buf_; > 108 ulong bPos_; > 109 > 110 private: > 111 > 112 NOCOPY(FileW); > 113 }; > 114 > 115 > 116 > 117 //========================================================================= > 118 > 119 } // namespace ki > 120 #endif // _KILIB_FILE_H_

Added kilib/find.cpp version [b12e88bb918155c8]

> 1 #include "stdafx.h" > 2 #include "find.h" > 3 using namespace ki; > 4 > 5 > 6 > 7 //========================================================================= > 8 > 9 namespace { > 10 static inline bool isDots(const TCHAR* p) > 11 { > 12 return (*p=='.' && (p[1]=='\0' || (p[1]=='.' && p[2]=='\0'))); > 13 } > 14 } > 15 > 16 bool FindFile::FindFirst( const TCHAR* wild, WIN32_FIND_DATA* pfd ) > 17 { > 18 HANDLE xh = ::FindFirstFile( wild, pfd ); > 19 if( xh==INVALID_HANDLE_VALUE ) > 20 return false; > 21 while( isDots(pfd->cFileName) ) > 22 if( !::FindNextFile( xh, pfd ) ) > 23 { > 24 ::FindClose( xh ); > 25 return false; > 26 } > 27 ::FindClose( xh ); > 28 return true; > 29 } > 30 > 31 void FindFile::Close() > 32 { > 33 first_ = true; > 34 if( han_ != INVALID_HANDLE_VALUE ) > 35 ::FindClose( han_ ), han_ = INVALID_HANDLE_VALUE; > 36 } > 37 > 38 bool FindFile::Begin( const TCHAR* wild ) > 39 { > 40 Close(); > 41 > 42 han_ = ::FindFirstFile( wild, &fd_ ); > 43 if( han_ == INVALID_HANDLE_VALUE ) > 44 return false; > 45 > 46 while( isDots(fd_.cFileName) ) > 47 if( !::FindNextFile( han_, &fd_ ) ) > 48 { > 49 Close(); > 50 return false; > 51 } > 52 return true; > 53 } > 54 > 55 bool FindFile::Next( WIN32_FIND_DATA* pfd ) > 56 { > 57 if( han_ == INVALID_HANDLE_VALUE ) > 58 return false; > 59 > 60 if( first_ ) > 61 { > 62 first_ = false; > 63 memmove( pfd, &fd_, sizeof(fd_) ); > 64 return true; > 65 } > 66 if( !::FindNextFile( han_, pfd ) ) > 67 return false; > 68 while( isDots(fd_.cFileName) ) > 69 if( !::FindNextFile( han_, pfd ) ) > 70 return false; > 71 return true; > 72 } > 73 > 74 #undef isDots

Added kilib/find.h version [3273f24ee839c505]

> 1 #ifndef _KILIB_FIND_H_ > 2 #define _KILIB_FIND_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #include "path.h" > 6 #ifndef __ccdoc__ > 7 namespace ki { > 8 #endif > 9 > 10 > 11 > 12 //========================================================================= > 13 //@{ @pkg ki.WinUtil //@} > 14 //@{ > 15 // ファイル検索 > 16 // > 17 // Win32 APIのFindFirstFile等を用いて、ディレクトリ内の > 18 // ファイルリストアップを行います。 > 19 //@} > 20 //========================================================================= > 21 > 22 class FindFile : public Object > 23 { > 24 public: > 25 > 26 //@{ コンストラクタ //@} > 27 FindFile(); > 28 > 29 //@{ デストラクタ //@} > 30 ~FindFile(); > 31 > 32 //@{ 検索終了処理 //@} > 33 void Close(); > 34 > 35 public: //-- 外向きインターフェイス -------------------------- > 36 > 37 bool Begin( const TCHAR* wild ); > 38 bool Next( WIN32_FIND_DATA* pfd ); > 39 > 40 public: > 41 > 42 //@{ static版。マッチする最初のファイルを取得 //@} > 43 static bool FindFirst( const TCHAR* wild, WIN32_FIND_DATA* pfd ); > 44 > 45 private: > 46 > 47 HANDLE han_; > 48 bool first_; > 49 WIN32_FIND_DATA fd_; > 50 > 51 private: > 52 > 53 NOCOPY(FindFile); > 54 }; > 55 > 56 > 57 > 58 //------------------------------------------------------------------------- > 59 > 60 inline FindFile::FindFile() > 61 : han_( INVALID_HANDLE_VALUE ) {} > 62 > 63 inline FindFile::~FindFile() > 64 { Close(); } > 65 > 66 > 67 > 68 //========================================================================= > 69 > 70 } // namespace ki > 71 #endif // _KILIB_FIND_H_

Added kilib/kilib.h version [28c7016319731f23]

> 1 #ifndef _KILIB_KILIB_H_ > 2 #define _KILIB_KILIB_H_ > 3 > 4 #include "types.h" > 5 #include "app.h" > 6 #include "thread.h" > 7 #include "memory.h" > 8 #include "window.h" > 9 #include "string.h" > 10 #include "cmdarg.h" > 11 #include "path.h" > 12 #include "file.h" > 13 #include "ctrl.h" > 14 #include "textfile.h" > 15 #include "winutil.h" > 16 #include "find.h" > 17 #include "registry.h" > 18 #include "log.h" > 19 > 20 #include "ktlaptr.h" > 21 #include "ktlarray.h" > 22 #include "ktlgap.h" > 23 > 24 #endif // _KILIB_KILIB_H_

Added kilib/ktlaptr.h version [287ca367e86ae8f1]

> 1 #ifndef _KILIB_KTL_APTR_H_ > 2 #define _KILIB_KTL_APTR_H_ > 3 #include "types.h" > 4 #ifdef _MSC_VER > 5 #pragma warning( disable : 4284 ) // 警告:->のリターン型がうにゃうにゃ > 6 #pragma warning( disable : 4150 ) // 警告:deleteの定義がうにょうにょ > 7 #endif > 8 #ifndef __ccdoc__ > 9 namespace ki { > 10 #endif > 11 > 12 > 13 > 14 //========================================================================= > 15 //@{ @pkg ki.KTL //@} > 16 //@{ > 17 // 自動ポインタ > 18 // > 19 // 私の期待する範囲では概ね std::auto_ptr と同じ動作をすると思う…。 > 20 // 車輪の最発明ばんざーい! > 21 //@} > 22 //========================================================================= > 23 > 24 template<class T> > 25 class aptr > 26 { > 27 public: > 28 > 29 //@{ コンストラクタ //@} > 30 explicit aptr( T* p = NULL ) > 31 : obj_( p ) {} > 32 > 33 //@{ デストラクタ //@} > 34 ~aptr() > 35 { delete obj_; } > 36 > 37 //@{ 所有権移動 //@} > 38 aptr( aptr<T>& r ) > 39 : obj_ ( r.release() ) {} > 40 > 41 //@{ 所有権移動 //@} > 42 aptr<T>& operator=( aptr<T>& r ) > 43 { > 44 if( obj_ != r.obj_ ) > 45 { > 46 delete obj_; > 47 obj_ = r.release(); > 48 } > 49 return *this; > 50 } > 51 > 52 public: > 53 > 54 //@{ 間接演算子 //@} > 55 T& operator*() const > 56 { return *obj_; } > 57 > 58 //@{ メンバ参照 //@} > 59 T* operator->() const > 60 { return obj_; } > 61 > 62 //@{ ポインタ取得 //@} > 63 T* get() const > 64 { return obj_; } > 65 > 66 //@{ 所有権解放 //@} > 67 T* release() > 68 { > 69 T* ptr = obj_; > 70 obj_ = NULL; > 71 return ptr; > 72 } > 73 > 74 //@{ 有効かどうか //@} > 75 bool isValid() const > 76 { > 77 return (obj_ != NULL); > 78 } > 79 > 80 private: > 81 > 82 mutable T* obj_; > 83 }; > 84 > 85 > 86 > 87 //========================================================================= > 88 //@{ > 89 // 自動ポインタ(配列版) > 90 //@} > 91 //========================================================================= > 92 > 93 template<class T> > 94 class aarr > 95 { > 96 public: > 97 > 98 //@{ コンストラクタ //@} > 99 explicit aarr( T* p = NULL ) > 100 : obj_( p ) {} > 101 > 102 //@{ デストラクタ //@} > 103 ~aarr() > 104 { delete [] obj_; } > 105 > 106 //@{ 所有権移動 何故かbccで上手く行かない部分があるのでconst付き //@} > 107 aarr( const aarr<T>& r ) > 108 : obj_ ( const_cast<aarr<T>&>(r).release() ) {} > 109 > 110 //@{ 所有権移動 //@} > 111 aarr<T>& operator=( aarr<T>& r ) > 112 { > 113 if( obj_ != r.obj_ ) > 114 { > 115 delete [] obj_; > 116 obj_ = r.release(); > 117 } > 118 return *this; > 119 } > 120 > 121 public: > 122 > 123 //@{ ポインタ取得 //@} > 124 T* get() const > 125 { return obj_; } > 126 > 127 //@{ 所有権解放 //@} > 128 T* release() > 129 { > 130 T* ptr = obj_; > 131 obj_ = NULL; > 132 return ptr; > 133 } > 134 > 135 //@{ 有効かどうか //@} > 136 bool isValid() const > 137 { > 138 return (obj_ != NULL); > 139 } > 140 > 141 public: > 142 > 143 //@{ 配列要素アクセス //@} > 144 T& operator[]( int i ) const > 145 { return obj_[i]; } > 146 > 147 private: > 148 > 149 mutable T* obj_; > 150 }; > 151 > 152 > 153 > 154 //========================================================================= > 155 //@{ > 156 // 削除権専有ポインタ > 157 // > 158 // 「リソースの獲得はコンストラクタで・解放はデストラクタで」を > 159 // 徹底できるならこんなの使わずに、迷わず const auto_ptr を用いる > 160 // べきです。べきですが、メンバ初期化リストで this を使うとVC++の > 161 // コンパイラに怒られるのが気持悪いので、ついこっちを使ってコンストラクタ > 162 // 関数内で初期化してしまうのでふ…(^^; > 163 //@} > 164 //========================================================================= > 165 > 166 template<class T> > 167 class dptr > 168 { > 169 public: > 170 > 171 //@{ コンストラクタ //@} > 172 explicit dptr( T* p = NULL ) > 173 : obj_( p ) {} > 174 > 175 //@{ デストラクタ //@} > 176 ~dptr() > 177 { delete obj_; } > 178 > 179 //@{ 新しいオブジェクトを所有。古いのは削除 //@} > 180 void operator=( T* p ) > 181 { > 182 delete obj_; // 古いのは削除 > 183 obj_ = p; > 184 } > 185 > 186 //@{ 有効かどうか //@} > 187 bool isValid() const > 188 { > 189 return (obj_ != NULL); > 190 } > 191 > 192 public: > 193 > 194 //@{ 間接演算子 //@} > 195 T& operator*() const > 196 { return *obj_; } > 197 > 198 //@{ メンバ参照 //@} > 199 T* operator->() const > 200 { return obj_; } > 201 > 202 //@{ ポインタ取得 //@} > 203 T* get() const > 204 { return obj_; } > 205 > 206 private: > 207 > 208 T* obj_; > 209 > 210 private: > 211 > 212 NOCOPY(dptr<T>); > 213 }; > 214 > 215 > 216 > 217 //========================================================================= > 218 //@{ > 219 // 削除権専有ポインタ(配列版) > 220 //@} > 221 //========================================================================= > 222 > 223 template<class T> > 224 class darr > 225 { > 226 public: > 227 > 228 //@{ コンストラクタ //@} > 229 explicit darr( T* p = NULL ) > 230 : obj_( p ) {} > 231 > 232 //@{ デストラクタ //@} > 233 ~darr() > 234 { delete [] obj_; } > 235 > 236 //@{ 新しいオブジェクトを所有。古いのは削除 //@} > 237 void operator=( T* p ) > 238 { > 239 delete [] obj_; // 古いのは削除 > 240 obj_ = p; > 241 } > 242 > 243 //@{ 有効かどうか //@} > 244 bool isValid() const > 245 { > 246 return (obj_ != NULL); > 247 } > 248 > 249 public: > 250 > 251 //@{ 配列要素アクセス //@} > 252 T& operator[]( int i ) const > 253 { return obj_[i]; } > 254 > 255 private: > 256 > 257 T* obj_; > 258 > 259 private: > 260 > 261 NOCOPY(darr<T>); > 262 }; > 263 > 264 > 265 > 266 //========================================================================= > 267 > 268 #ifdef _MSC_VER > 269 #pragma warning( default : 4150 ) > 270 #pragma warning( default : 4284 ) > 271 #endif > 272 } // namespace ki > 273 #endif // _KILIB_KTL_APTR_H_

Added kilib/ktlarray.h version [4098f71530c2f376]

> 1 #ifndef _KILIB_KTL_ARRAY_H_ > 2 #define _KILIB_KTL_ARRAY_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #ifndef __ccdoc__ > 6 namespace ki { > 7 #endif > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg ki.KTL //@} > 13 //@{ > 14 // 基本型専用の可変長配列 > 15 // > 16 // 非常に簡素な作りです。アクセスは好きなところへ自由に可能ですが、 > 17 // 要素の追加・削除は末尾に対してのみ。ビット毎のコピーだとか、 > 18 // 色々エキセントリックな作業をしてますので、そういうことをして良い > 19 // 型以外には使わないでください。 > 20 //@} > 21 //========================================================================= > 22 > 23 template <typename T> > 24 class storage : public Object > 25 { > 26 public: > 27 > 28 //@{ > 29 // コンストラクタ > 30 // > 31 // @param alloc_size > 32 // 最初に確保する"メモリの"サイズ。 > 33 // "配列の"サイズではないことに注意。 > 34 //@} > 35 explicit storage( ulong allocSize=20 ) > 36 : alen_( Max( allocSize, 1UL ) ) > 37 , len_ ( 0 ) > 38 , buf_ ( static_cast<T*>(mem().Alloc(alen_*sizeof(T))) ) > 39 {} > 40 > 41 ~storage() > 42 { mem().DeAlloc( buf_, alen_*sizeof(T) ); } > 43 > 44 //@{ 末尾に要素を追加 //@} > 45 void Add( const T& obj ) > 46 { > 47 if( len_ >= alen_ ) > 48 ReAllocate( alen_<<2 ); > 49 buf_[ len_++ ] = obj; > 50 } > 51 > 52 //@{ > 53 // 配列サイズを強制変更 > 54 // > 55 // 縮小/拡大のどちらも可能。コンストラクタと違い、 > 56 // 指定した値に基づき最大indexが変化します。 > 57 // @param new_size 新しいサイズ。 > 58 //@} > 59 void ForceSize( ulong newSize ) > 60 { > 61 if( newSize > alen_ ) > 62 ReAllocate( newSize ); > 63 len_ = newSize; > 64 } > 65 > 66 public: > 67 > 68 //@{ 要素数 //@} > 69 ulong size() const > 70 { return len_; } > 71 > 72 //@{ 要素取得 //@} > 73 T& operator[]( size_t i ) > 74 { return buf_[i]; } > 75 > 76 //@{ 要素取得(const) //@} > 77 const T& operator[]( size_t i ) const > 78 { return buf_[i]; } > 79 > 80 //@{ 配列先頭のポインタを返す //@} > 81 const T* head() const > 82 { return buf_; } > 83 > 84 private: > 85 > 86 void ReAllocate( ulong siz ) > 87 { > 88 ulong p = alen_*sizeof(T); > 89 T* newbuf = static_cast<T*> > 90 (mem().Alloc( (alen_=siz)*sizeof(T) )); > 91 memmove( newbuf, buf_, len_*sizeof(T) ); > 92 mem().DeAlloc( buf_, p ); > 93 buf_ = newbuf; > 94 } > 95 > 96 private: > 97 > 98 ulong alen_; > 99 ulong len_; > 100 T* buf_; > 101 > 102 private: > 103 > 104 NOCOPY(storage<T>); > 105 }; > 106 > 107 > 108 > 109 //========================================================================= > 110 //@{ > 111 // オブジェクト型にも使える単方向リスト > 112 // > 113 // ほとんど何も出来ません。出来るのは末尾への追加と、独自の > 114 // iteratorによるシーケンシャルなアクセスのみ。 > 115 //@} > 116 //========================================================================= > 117 > 118 template <class T> > 119 class olist : public Object > 120 { > 121 private: > 122 > 123 struct Node { > 124 Node( const T& obj ) > 125 : obj_ ( obj ), next_( NULL ) {} > 126 ~Node() > 127 { delete next_; } > 128 Node* Add( Node* pN ) > 129 { return next_==NULL ? next_=pN : next_->Add(pN); } > 130 T obj_; > 131 Node* next_; > 132 }; > 133 > 134 public: > 135 > 136 struct iterator { > 137 iterator( Node* p=NULL ) : ptr_(p) {} > 138 T& operator*() { return ptr_->obj_; } > 139 T* operator->() const { return &ptr_->obj_; } > 140 bool operator==( const iterator& i ) { return i.ptr_==ptr_; } > 141 bool operator!=( const iterator& i ) { return i.ptr_!=ptr_; } > 142 iterator& operator++() { ptr_=ptr_->next_; return *this; } > 143 private: > 144 Node* ptr_; > 145 }; > 146 > 147 public: > 148 > 149 //@{ コンストラクタ //@} > 150 olist() > 151 : top_( NULL ) {} > 152 > 153 //@{ デストラクタ //@} > 154 ~olist() > 155 { empty(); } > 156 > 157 //@{ 空にする //@} > 158 void empty() > 159 { delete top_; top_ = NULL; } > 160 > 161 //@{ 先頭 //@} > 162 iterator begin() > 163 { return iterator(top_); } > 164 > 165 //@{ 末尾 //@} > 166 iterator end() > 167 { return iterator(); } > 168 > 169 //@{ 末尾に要素を追加 //@} > 170 void Add( const T& obj ) > 171 { > 172 Node* pN = new Node( obj ); > 173 (top_ == NULL) ? top_=pN : top_->Add( pN ); > 174 } > 175 > 176 //@{ 指定要素を削除 //@} > 177 void Del( iterator d ) > 178 { > 179 if( d != end() ) > 180 { > 181 Node *p=top_, *q=NULL; > 182 for( ; p!=NULL; q=p,p=p->next_ ) > 183 if( &p->obj_ == &*d ) > 184 break; > 185 if( q != NULL ) > 186 q->next_ = p->next_; > 187 else > 188 top_ = p->next_; > 189 p->next_ = NULL; > 190 delete p; > 191 } > 192 } > 193 > 194 //@{ 指定要素以降全てを削除 //@} > 195 void DelAfter( iterator d ) > 196 { > 197 if( d != end() ) > 198 if( d == begin() ) > 199 { > 200 empty(); > 201 } > 202 else > 203 { > 204 Node *p=top_, *q=NULL; > 205 for( ; p!=NULL; q=p,p=p->next_ ) > 206 if( &p->obj_ == &*d ) > 207 break; > 208 delete p; > 209 q->next_ = NULL; > 210 } > 211 } > 212 > 213 private: > 214 > 215 Node* top_; > 216 NOCOPY(olist<T>); > 217 }; > 218 > 219 > 220 > 221 //========================================================================= > 222 > 223 } // namespace ki > 224 #endif // _KILIB_KTL_ARRAY_H_

Added kilib/ktlgap.h version [871ef62fc27e27a1]

> 1 #ifndef _KILIB_KTL_GAP_H_ > 2 #define _KILIB_KTL_GAP_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #ifndef __ccdoc__ > 6 namespace ki { > 7 #endif > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg ki.KTL //@} > 13 //@{ > 14 // 基本型専用ギャップバッファ > 15 // > 16 // 小耳に挟んだギャップバッファというもの。 > 17 // ものすごい勘違いをして別物ができているかもしれませんが、 > 18 // 細かいことはあまり気にしないでください。 > 19 // 配列のようにランダムアクセス可能で、 > 20 // 同一箇所への連続した挿入/削除が速いというデータ構造です。 > 21 // ( 下の図で言うと、gap_startへの挿入/削除にはデータの移動が必要ない ) > 22 // <pre> > 23 //@@ D <--0 > 24 //@@ D > 25 //@@ | <--gap_start > 26 //@@ | > 27 //@@ D <--gap_end > 28 //@@ D > 29 //@@ <--array_end > 30 // </pre> > 31 // メモリイメージをそのままコピーしてる実装なので、 > 32 // プリミティブ型以外では絶対に使わないこと。 > 33 //@} > 34 //========================================================================= > 35 > 36 template<class T> > 37 class gapbuf : public Object > 38 { > 39 public: > 40 > 41 //@{ > 42 // コンストラクタ > 43 // @param alloc_size > 44 // 最初に確保する"メモリの"サイズ。 > 45 // "配列の"サイズではないことに注意。 > 46 //@} > 47 explicit gapbuf( ulong alloc_size=40 ) > 48 : alen_( Max(alloc_size, 10UL) ) > 49 , gs_ ( 0 ) > 50 , ge_ ( alen_ ) > 51 , buf_ ( new T[alen_] ) > 52 {} > 53 ~gapbuf() > 54 { delete [] buf_; } > 55 > 56 //@{ 要素挿入 //@} > 57 void InsertAt( ulong i, const T& x ) > 58 { > 59 MakeGapAt( i ); > 60 buf_[gs_++] = x; > 61 > 62 if( gs_==ge_ ) > 63 Reallocate( alen_<<1 ); > 64 } > 65 > 66 //@{ 要素挿入(複数) //@} > 67 void InsertAt( ulong i, const T* x, ulong len ) > 68 { > 69 MakeGapAt( size() ); > 70 MakeGapAt( i ); > 71 if( ge_-gs_ <= len ) > 72 Reallocate( Max(alen_+len+1, alen_<<1) ); > 73 > 74 memmove( buf_+gs_, x, len*sizeof(T) ); > 75 gs_ += len; > 76 } > 77 > 78 //@{ 末尾に要素を追加 //@} > 79 void Add( const T& x ) > 80 { InsertAt( size(), x ); } > 81 > 82 //@{ 末尾に要素を追加(複数) //@} > 83 void Add( const T* x, ulong len ) > 84 { InsertAt( size(), x, len ); } > 85 > 86 //@{ 要素削除 //@} > 87 void RemoveAt( ulong i, ulong len=1 ) > 88 { > 89 if( i <= gs_ && gs_ <= i+len ) > 90 { > 91 // この場合はメモリ移動の必要がない > 92 // まず前半を削除 > 93 len -= (gs_-i); > 94 gs_ = i; > 95 } > 96 else > 97 { > 98 MakeGapAt( i ); > 99 } > 100 > 101 // 後半を削除 > 102 ge_ += len; > 103 } > 104 > 105 //@{ 要素削除(全部) //@} > 106 void RemoveAll() > 107 { RemoveAt( 0, size() ); } > 108 > 109 //@{ 要素削除(指定index以降全部) //@} > 110 void RemoveToTail( ulong i ) > 111 { RemoveAt( i, size()-i ); } > 112 > 113 //@{ 要素コピー(指定index以降全部) //@} > 114 ulong CopyToTail( ulong i, T* x ) > 115 { return CopyAt( i, size()-i, x ); } > 116 > 117 //@{ 要素コピー //@} > 118 ulong CopyAt( ulong i, ulong len, T* x ) > 119 { > 120 ulong copyed=0; > 121 if( i < gs_ ) > 122 { > 123 // 前半 > 124 copyed += Min( len, gs_-i ); > 125 memmove( x, buf_+i, copyed*sizeof(T) ); > 126 x += copyed; > 127 len -= copyed; > 128 i += copyed; > 129 } > 130 > 131 // 後半 > 132 memmove( x, buf_+(i-gs_)+ge_, len*sizeof(T) ); > 133 return copyed + len; > 134 } > 135 > 136 public: > 137 > 138 //@{ 要素数 //@} > 139 ulong size() const > 140 { return alen_ - (ge_-gs_); } > 141 > 142 //@{ 要素取得 //@} > 143 T& operator[]( ulong i ) > 144 { return buf_[ ( i<gs_ ) ? i : i+(ge_-gs_) ]; } > 145 > 146 //@{ 要素取得(const) //@} > 147 const T& operator[]( ulong i ) const > 148 { return buf_[ ( i<gs_ ) ? i : i+(ge_-gs_) ]; } > 149 > 150 protected: > 151 > 152 ulong alen_; > 153 ulong gs_; > 154 ulong ge_; > 155 T* buf_; > 156 > 157 protected: > 158 > 159 void MakeGapAt( ulong i ) > 160 { > 161 if( i<gs_ ) > 162 { > 163 ge_ -= (gs_-i); > 164 memmove( buf_+ge_, buf_+i, (gs_-i)*sizeof(T) ); > 165 } > 166 else if( i>gs_ ) > 167 { > 168 int j = i+(ge_-gs_); > 169 memmove( buf_+gs_, buf_+ge_, (j-ge_)*sizeof(T) ) > 170 ge_ = j; > 171 } > 172 gs_ = i; > 173 } > 174 > 175 void Reallocate( ulong newalen ) > 176 { > 177 T *tmp = new T[newalen], *old=buf_; > 178 const ulong tail = alen_-ge_; > 179 > 180 memmove( tmp, old, gs_*sizeof(T) ); > 181 memmove( tmp+newalen-tail, old+ge_, tail*sizeof(T) ); > 182 delete [] old; > 183 > 184 buf_ = tmp; > 185 ge_ = newalen-tail; > 186 alen_ = newalen; > 187 } > 188 > 189 private: > 190 > 191 NOCOPY(gapbuf<T>); > 192 }; > 193 > 194 > 195 > 196 //========================================================================= > 197 //@{ > 198 // gapbuf + smartptr のふり > 199 // > 200 // 要素削除時にdeleteを実行しっちゃったりするバージョン。 > 201 // 任意オブジェクトをギャップバッファで使いたいときは > 202 // これでてきとーに代用すべし。 > 203 //@} > 204 //========================================================================= > 205 > 206 template<class T> > 207 class gapbufobj : public gapbuf<T*> > 208 { > 209 public: > 210 > 211 explicit gapbufobj( ulong alloc_size=40 ) > 212 : gapbuf<T*>( alloc_size ) > 213 { } > 214 > 215 void RemoveAt( ulong i, ulong len=1 ) > 216 { > 217 ulong& gs_ = gapbuf<T*>::gs_; > 218 ulong& ge_ = gapbuf<T*>::ge_; > 219 T**& buf_= gapbuf<T*>::buf_; > 220 > 221 if( i <= gs_ && gs_ <= i+len ) > 222 { > 223 // 前半を削除 > 224 for( ulong j=i, ed=gs_; j<ed; ++j ) > 225 delete buf_[j]; > 226 > 227 len -= (gs_-i); > 228 gs_ = i; > 229 } > 230 else > 231 { > 232 gapbuf<T*>::MakeGapAt( i ); > 233 } > 234 > 235 // 後半を削除 > 236 for( ulong j=ge_, ed=ge_+len; j<ed; ++j ) > 237 delete buf_[j]; > 238 ge_ = ge_+len; > 239 } > 240 > 241 ~gapbufobj() > 242 { RemoveAt( 0, gapbuf<T*>::size() ); } > 243 > 244 void RemoveAll( ulong i ) > 245 { RemoveAt( 0, gapbuf<T*>::size() ); } > 246 > 247 void RemoveToTail( ulong i ) > 248 { RemoveAt( i, gapbuf<T*>::size()-i ); } > 249 > 250 public: > 251 > 252 T& operator[]( ulong i ) > 253 { return *gapbuf<T*>::operator[](i); } > 254 > 255 const T& operator[]( ulong i ) const > 256 { return *gapbuf<T*>::operator[](i); } > 257 > 258 private: > 259 > 260 NOCOPY(gapbufobj<T>); > 261 }; > 262 > 263 > 264 > 265 //========================================================================= > 266 > 267 } // namespace ki > 268 #endif // _KILIB_KTL_GAP_H_

Added kilib/log.cpp version [56a918c7773d65a4]

> 1 #include "stdafx.h" > 2 #include "log.h" > 3 #include "app.h" > 4 #include "string.h" > 5 using namespace ki; > 6 > 7 > 8 > 9 //========================================================================= > 10 > 11 void Logger::WriteLine( const String& str ) > 12 { > 13 WriteLine( str.c_str(), str.len()*sizeof(TCHAR) ); > 14 } > 15 > 16 void Logger::WriteLine( const TCHAR* str ) > 17 { > 18 WriteLine( str, ::lstrlen(str)*sizeof(TCHAR) ); > 19 } > 20 > 21 void Logger::WriteLine( const TCHAR* str, int siz ) > 22 { > 23 #ifdef DO_LOGGING > 24 // Fileクラス自体のデバッグに使うかもしれないので、 > 25 // Fileクラスを使用することは出来ない。API直叩き > 26 static bool st_firsttime = true; > 27 DWORD dummy; > 28 > 29 // ファイル名 > 30 TCHAR fname[MAX_PATH]; > 31 ::GetModuleFileName( ::GetModuleHandle(NULL), fname, countof(fname) ); > 32 ::lstrcat( fname, TEXT("_log") ); > 33 > 34 // ファイルを書き込み専用で開く > 35 HANDLE h = ::CreateFile( fname, > 36 GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, > 37 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL ); > 38 if( h == INVALID_HANDLE_VALUE ) > 39 return; > 40 > 41 // 初回限定処理 > 42 if( st_firsttime ) > 43 { > 44 ::SetEndOfFile( h ); > 45 #ifdef _UNICODE > 46 ::WriteFile( h, "\xff\xfe", 2, &dummy, NULL ); > 47 #endif > 48 st_firsttime = false; > 49 } > 50 else > 51 { > 52 ::SetFilePointer( h, 0, NULL, FILE_END ); > 53 } > 54 > 55 // 書く > 56 ::WriteFile( h, str, siz, &dummy, NULL ); > 57 ::WriteFile( h, TEXT("\r\n"), sizeof(TEXT("\r")), &dummy, NULL ); > 58 > 59 // 閉じる > 60 ::CloseHandle( h ); > 61 > 62 #endif > 63 }

Added kilib/log.h version [41bb51ff408369b0]

> 1 #ifndef _KILIB_LOG_H_ > 2 #define _KILIB_LOG_H_ > 3 #include "types.h" > 4 #ifndef __ccdoc__ > 5 namespace ki { > 6 #endif > 7 > 8 > 9 > 10 class String; > 11 > 12 //========================================================================= > 13 //@{ @pkg ki.Core //@} > 14 //@{ > 15 // ログ取り機能(デバッグ用) > 16 // > 17 // アプリ起動/終了用処理を担当します。 > 18 // 旧kilibと違って、ユーザー側のアプリケーションクラスを > 19 // ここから派生させることは出来ません。ユーザーのコードは、 > 20 // 必ず kmain() というグローバル関数から実行開始されます。 > 21 // このAppクラス自体は、主にHINSTANCEの管理を行うだけ。 > 22 //@} > 23 //========================================================================= > 24 > 25 class Logger > 26 { > 27 public: > 28 > 29 Logger() {} > 30 void WriteLine( const String& str ); > 31 void WriteLine( const TCHAR* str ); > 32 void WriteLine( const TCHAR* str, int siz ); > 33 > 34 private: > 35 > 36 NOCOPY(Logger); > 37 }; > 38 > 39 #ifdef DO_LOGGING > 40 #define LOGGER(str) Logger().WriteLine(TEXT(str)) > 41 #else > 42 #define LOGGER(x) > 43 #endif > 44 > 45 //========================================================================= > 46 > 47 } // namespace ki > 48 #endif // _KILIB_LOG_H_

Added kilib/memory.cpp version [4b76ca1a670e139d]

> 1 #include "stdafx.h" > 2 #include "memory.h" > 3 using namespace ki; > 4 > 5 > 6 > 7 //========================================================================= > 8 > 9 #ifdef SUPERTINY > 10 > 11 static HANDLE g_heap; > 12 > 13 #ifndef _DEBUG > 14 > 15 void* __cdecl operator new( size_t siz ) > 16 { > 17 return ::HeapAlloc( g_heap, HEAP_GENERATE_EXCEPTIONS, si > 18 } > 19 > 20 void __cdecl operator delete( void* ptr ) > 21 { > 22 ::HeapFree( g_heap, 0, ptr ); > 23 } > 24 > 25 #else > 26 > 27 // デバッグ用に回数計測版(^^; > 28 static int allocCounter = 0; > 29 void* __cdecl operator new( size_t siz ) > 30 { > 31 ++allocCounter; > 32 return ::HeapAlloc( g_heap, HEAP_GENERATE_EXCEPTIONS, si > 33 } > 34 void __cdecl operator delete( void* ptr ) > 35 { > 36 ::HeapFree( g_heap, 0, ptr ); > 37 if( ptr != NULL ) > 38 --allocCounter; > 39 } > 40 > 41 #endif > 42 > 43 extern "C" > 44 void* __cdecl memset( void* buf, int ch, size_t n ) > 45 { > 46 BYTE v = BYTE(ch&0xff); > 47 BYTE* ptr = (BYTE*)buf; > 48 DWORD vvvv = (v<<24) | (v<<16) | (v<<8) | v; > 49 for(;n>3;n-=4,ptr+=4) *(DWORD*)ptr = vvvv; > 50 for(;n;--n,++ptr) *ptr = v; > 51 return buf; > 52 } > 53 > 54 void* __cdecl memmove( void* dst, const void* src, size_t cnt ) > 55 { > 56 __asm { > 57 mov esi, [src] ;U esi = const void* src > 58 mov edx, [cnt] ;V edx = void* cnt > 59 mov edi, [dst] ;U edi = ulong dst > 60 mov ebx, edx ;V > 61 mov eax, 03h ;U eax = const ulong 3 (for masking > 62 add ebx, esi ;V ebx = const void* src+cnt > 63 > 64 cmp edi, esi ; > 65 jbe CopyUp ; > 66 cmp edi, ebx ; if( src < dst < src+cnt ) > 67 jb CopyDown ; downward copy > 68 > 69 CopyUp: > 70 cmp edx, eax ; if( cnt<=3 ) > 71 jbe MiniCopy ; byte by byte copy > 72 > 73 mov ebx, edi ;U > 74 mov ecx, eax ;V > 75 and ebx, eax ;U ebx = (dst&3) > 76 inc ecx ;V > 77 sub ecx, ebx ; ecx = (4-(dst&3)) > 78 and ecx, eax ; ecx = {dst%4 0->0 1->3 2->2 3->1} > 79 sub edx, ecx ; > 80 rep movsb ;N BYTE MOVE (align dst) > 81 > 82 mov ecx, edx ; > 83 shr ecx, 2 ; ecx = [rest bytes]/4 > 84 and edx, eax ; edx = [rest bytes]%4 > 85 rep movsd ;N DWORD MOVE > 86 jmp MiniCopy ; > 87 > 88 CopyDown: > 89 std ; > 90 lea esi,[esi+edx-1] ; > 91 lea edi,[edi+edx-1] ; > 92 > 93 cmp edx, 4 ; if( cnt<=4 ) > 94 jbe MiniCopy ; byte by byte copy > 95 > 96 mov ecx, edi ; > 97 and ecx, eax ; > 98 inc ecx ; ecx = {dst%4 0->1 1->2 2->3 3->4} > 99 sub edx, ecx ; > 100 rep movsb ;N BYTE MOVE (align dst @ dword) > 101 > 102 sub edi, eax ;U > 103 mov ecx, edx ;V > 104 sub esi, eax ;U > 105 shr ecx, 2 ;V ecx = [rest bytes]/4 > 106 and edx, eax ; edx = [rest bytes]%4 > 107 rep movsd ;N DWORD MOVE > 108 add edi, eax ;U > 109 add esi, eax ;V > 110 > 111 MiniCopy: > 112 mov ecx, edx ; > 113 rep movsb ;N BYTE MOVE > 114 > 115 cld ;U > 116 mov eax, [dst] ;V return dst > 117 } > 118 return dst; > 119 } > 120 > 121 #endif > 122 > 123 > 124 > 125 #ifdef USE_ORIGINAL_MEMMAN > 126 //========================================================================= > 127 // 効率的なメモリ管理を目指すアロケータ > 128 //========================================================================= > 129 > 130 // > 131 // メモリブロック > 132 // 「sizバイト * num個」分の領域を一括確保するのが仕事 > 133 // > 134 // 空きブロックには、先頭バイトに [次の空きブロックのindex] を格納。 > 135 // これを用いて、先頭への出し入れのみが可能な単方向リストとして扱う。 > 136 // > 137 > 138 struct ki::MemBlock > 139 { > 140 public: > 141 void Construct( byte siz, byte num ); > 142 void Destruct(); > 143 void* Alloc( byte siz ); > 144 void DeAlloc( void* ptr, byte siz ); > 145 bool isAvail(); > 146 bool isEmpty( byte num ); > 147 bool hasThisPtr( void* ptr, size_t len ); > 148 private: > 149 byte* buf_; > 150 byte first_, avail_; > 151 }; > 152 > 153 void MemBlock::Construct( byte siz, byte num ) > 154 { > 155 // 確保 > 156 buf_ = ::new byte[siz*num]; > 157 first_ = 0; > 158 avail_ = num; > 159 > 160 // 連結リスト初期化 > 161 for( byte i=0,*p=buf_; i<num; p+=siz ) > 162 *p = ++i; > 163 } > 164 > 165 inline void MemBlock::Destruct() > 166 { > 167 // 解放 > 168 ::delete [] buf_; > 169 } > 170 > 171 void* MemBlock::Alloc( byte siz ) > 172 { > 173 // メモリ切り出し > 174 // ( avail==0 等のチェックは上位層に任せる ) > 175 byte* blk = buf_ + siz*first_; > 176 first_ = *blk; > 177 --avail_; > 178 return blk; > 179 } > 180 > 181 void MemBlock::DeAlloc( void* ptr, byte siz ) > 182 { > 183 // メモリ戻す > 184 // ( 変なポインタ渡されたらだ〜め〜 ) > 185 byte* blk = static_cast<byte*>(ptr); > 186 *blk = first_; > 187 first_ = static_cast<byte>((blk-buf_)/siz); > 188 ++avail_; > 189 } > 190 > 191 inline bool MemBlock::isAvail() > 192 { > 193 // 空きがある? > 194 return (avail_ != 0); > 195 } > 196 > 197 inline bool MemBlock::isEmpty( byte num ) > 198 { > 199 // 完全に空? > 200 return (avail_ == num); > 201 } > 202 > 203 inline bool MemBlock::hasThisPtr( void* ptr, size_t len ) > 204 { > 205 // このブロックのポインタ? > 206 return ( buf_<=ptr && ptr<buf_+len ); > 207 } > 208 > 209 > 210 > 211 //------------------------------------------------------------------------- > 212 > 213 // > 214 // 固定サイズ確保人 > 215 // 「sizバイト」の領域を毎回確保するのが仕事 > 216 // > 217 // メモリブロックのリストを保持し、空いているブロックを使って > 218 // メモリ要求に応えていく。空きがなくなったら新しくMemBlockを > 219 // 作ってリストに加える。 > 220 // > 221 // 最後にメモリ割り当て/解放を行ったBlockをそれぞれ記憶しておき、 > 222 // 最初にそこを調べることで高速化を図る。 > 223 // > 224 > 225 void MemoryManager::FixedSizeMemBlockPool::Construct( byte siz ) > 226 { > 227 // メモリマネージャが初期化されるまでは、 > 228 // 普通のauto_ptrも使わない方が無難… > 229 struct AutoDeleter > 230 { > 231 AutoDeleter( MemBlock* p ) : ptr_(p) {} > 232 ~AutoDeleter() { ::delete [] ptr_; } > 233 void Release() { ptr_ = NULL; } > 234 MemBlock* ptr_; > 235 }; > 236 > 237 // メモリブロック情報域をちょこっと確保 > 238 AutoDeleter a( blocks_ = ::new MemBlock[4] ); > 239 > 240 // ブロックサイズ等計算 > 241 int npb = BLOCK_SIZ/siz; > 242 numPerBlock_ = static_cast<byte>( Min( npb, 255 ) ); > 243 fixedSize_ = siz; > 244 > 245 // 一個だけブロック作成 > 246 blocks_[0].Construct( fixedSize_, numPerBlock_ ); > 247 > 248 a.Release(); > 249 lastA_ = 0; > 250 lastDA_ = 0; > 251 blockNum_ = 1; > 252 blockNumReserved_ = 4; > 253 } > 254 > 255 void MemoryManager::FixedSizeMemBlockPool::Destruct() > 256 { > 257 // 各ブロックを解放 > 258 for( int i=0; i<blockNum_; ++i ) > 259 blocks_[i].Destruct(); > 260 > 261 // ブロック情報保持領域のメモリも解放 > 262 ::delete [] blocks_; > 263 blockNum_ = 0; > 264 } > 265 > 266 void* MemoryManager::FixedSizeMemBlockPool::Alloc() > 267 { > 268 // ここでlastA_がValidかどうかチェックしないとまずい。 > 269 // DeAllocされてなくなってるかもしらないので。 > 270 > 271 // 前回メモリを切り出したブロックに > 272 // まだ空きがあるかどうかチェック > 273 if( !blocks_[lastA_].isAvail() ) > 274 { > 275 // 無かった場合、リストの末尾から順に線形探索 > 276 for( int i=blockNum_;; ) > 277 { > 278 if( blocks_[--i].isAvail() ) > 279 { > 280 // 空きブロック発見〜! > 281 lastA_ = i; > 282 break; > 283 } > 284 if( i == 0 ) > 285 { > 286 // 全部埋まってた... > 287 if( blockNum_ == blockNumReserved_ ) > 288 { > 289 // しかも作業領域も満杯なので拡張 > 290 MemBlock* nb = ::new MemBlock[ blockNum_ > 291 memmove( nb, blocks_, sizeof(MemBlock)*( > 292 ::delete [] blocks_; > 293 blocks_ = nb; > 294 blockNumReserved_ *= 2; > 295 } > 296 > 297 // 新しくブロック構築 > 298 blocks_[ blockNum_ ].Construct( fixedSize_, numP > 299 lastA_ = blockNum_++; > 300 break; > 301 } > 302 } > 303 } > 304 > 305 // ブロックから切り出し割り当て > 306 return blocks_[lastA_].Alloc( fixedSize_ ); > 307 } > 308 > 309 void MemoryManager::FixedSizeMemBlockPool::DeAlloc( void* ptr ) > 310 { > 311 // 該当ブロックを探索 > 312 const int mx=blockNum_, ln=fixedSize_*numPerBlock_; > 313 for( int u=lastDA_, d=lastDA_-1;; ) > 314 { > 315 if( u>=0 ) > 316 if( blocks_[u].hasThisPtr(ptr,ln) ) > 317 { > 318 lastDA_ = u; > 319 break; > 320 } > 321 else if( u==mx ) > 322 { > 323 u = -1; > 324 } > 325 else > 326 { > 327 ++u; > 328 } > 329 if( d>=0 ) > 330 if( blocks_[d].hasThisPtr(ptr,ln) ) > 331 { > 332 lastDA_ = d; > 333 break; > 334 } > 335 else > 336 { > 337 --d; > 338 } > 339 } > 340 > 341 // 解放を実行 > 342 blocks_[lastDA_].DeAlloc( ptr, fixedSize_ ); > 343 > 344 // この削除でブロックが完全に空になった場合 > 345 if( blocks_[lastDA_].isEmpty( numPerBlock_ ) ) > 346 { > 347 // しかも一番後ろのブロックでなかったら > 348 int end = blockNum_-1; > 349 if( lastDA_ != end ) > 350 { > 351 // 一番後ろが空だったら解放 > 352 if( blocks_[end].isEmpty( numPerBlock_ ) ) > 353 { > 354 blocks_[end].Destruct(); > 355 --blockNum_; > 356 if( lastA_ > --end ) > 357 lastA_ = end; > 358 } > 359 > 360 // 後ろと交換 > 361 MemBlock tmp( blocks_[lastDA_] ); > 362 blocks_[lastDA_] = blocks_[end]; > 363 blocks_[end] = tmp; > 364 } > 365 } > 366 } > 367 > 368 inline bool MemoryManager::FixedSizeMemBlockPool::isValid() > 369 { > 370 // 既に使用開始されているか? > 371 return (blockNum_ != 0); > 372 } > 373 > 374 > 375 > 376 //------------------------------------------------------------------------- > 377 > 378 // > 379 // 最上位層 > 380 // 指定サイズにあった FixedSizeMemBlockPool に処理をまわす > 381 // > 382 // lokiの実装では固定サイズアロケータも、必要に応じて > 383 // 動的確保していたが、それは面倒なのでやめました。(^^; > 384 // 最初に64個確保したからと言って、そんなにメモリも喰わないし…。 > 385 // > 386 > 387 MemoryManager* MemoryManager::pUniqueInstance_; > 388 > 389 MemoryManager::MemoryManager() > 390 { > 391 g_heap = ::GetProcessHeap(); > 392 > 393 // メモリプールをZEROクリア > 394 mem00( pools_, sizeof(pools_) ); > 395 > 396 // 唯一のインスタンスは私です > 397 pUniqueInstance_ = this; > 398 } > 399 > 400 MemoryManager::~MemoryManager() > 401 { > 402 // 構築済みメモリプールを全て解放 > 403 for( int i=0; i<SMALL_MAX; ++i ) > 404 if( pools_[i].isValid() ) > 405 pools_[i].Destruct(); > 406 > 407 #if defined(SUPERTINY) && defined(_DEBUG) > 408 // リーク検出用 > 409 if( allocCounter != 0 ) > 410 ::MessageBox( NULL, TEXT("MemoryLeak!"), NULL, MB_OK ); > 411 #endif > 412 } > 413 > 414 > 415 void* MemoryManager::Alloc( size_t siz ) > 416 { > 417 #if defined(SUPERTINY) && defined(_DEBUG) > 418 ++allocCounter; > 419 #endif > 420 > 421 // サイズが零か大きすぎるなら > 422 // デフォルトの new 演算子に任せる > 423 uint i = static_cast<uint>( siz-1 ); > 424 if( i >= SMALL_MAX ) > 425 return ::operator new( siz ); > 426 > 427 // マルチスレッド対応 > 428 AutoLock al(this); > 429 > 430 // このサイズのメモリ確保が初めてなら > 431 // ここでメモリプールを作成する。 > 432 if( !pools_[i].isValid() ) > 433 pools_[i].Construct( static_cast<byte>(siz) ); > 434 > 435 // ここで割り当て > 436 return pools_[i].Alloc(); > 437 } > 438 > 439 void MemoryManager::DeAlloc( void* ptr, size_t siz ) > 440 { > 441 #if defined(SUPERTINY) && defined(_DEBUG) > 442 --allocCounter; > 443 #endif > 444 > 445 // サイズが零か大きすぎるなら > 446 // デフォルトの delete 演算子に任せる > 447 uint i = static_cast<uint>( siz-1 ); > 448 if( i >= SMALL_MAX ) > 449 { > 450 ::operator delete( ptr ); > 451 return; // VCで return void が出来ないとは… > 452 } > 453 > 454 // マルチスレッド対応 > 455 AutoLock al(this); > 456 > 457 // ここで解放 > 458 pools_[i].DeAlloc( ptr ); > 459 } > 460 > 461 #else // USE_ORIGNAL_MEMMAN > 462 > 463 MemoryManager* MemoryManager::pUniqueInstance_; > 464 > 465 MemoryManager::MemoryManager() > 466 { > 467 g_heap = ::GetProcessHeap(); > 468 > 469 // 唯一のインスタンスは私です > 470 pUniqueInstance_ = this; > 471 } > 472 > 473 MemoryManager::~MemoryManager() > 474 { > 475 #if defined(SUPERTINY) && defined(_DEBUG) > 476 // リーク検出用 > 477 if( allocCounter != 0 ) > 478 ::MessageBox( NULL, TEXT("MemoryLeak!"), NULL, MB_OK ); > 479 #endif > 480 } > 481 > 482 void* MemoryManager::Alloc( size_t siz ) > 483 { > 484 return ::operator new(siz); > 485 } > 486 > 487 void MemoryManager::DeAlloc( void* ptr, size_t siz ) > 488 { > 489 ::operator delete(ptr); > 490 } > 491 > 492 #endif

Added kilib/memory.h version [191649d03470b28c]

> 1 #ifndef _KILIB_MEMORY_H_ > 2 #define _KILIB_MEMORY_H_ > 3 #include "types.h" > 4 #include "thread.h" > 5 #ifndef __ccdoc__ > 6 namespace ki { > 7 #endif > 8 > 9 > 10 // W版ではHeapAllocを直接呼び出すバージョンを使う > 11 //#if !defined(_UNICODE) && defined(SUPERTINY) > 12 // #define USE_ORIGINAL_MEMMAN > 13 //#endif > 14 > 15 // 小規模と見なすオブジェクトの最大サイズ > 16 #define SMALL_MAX 64 > 17 // 一度に確保するヒープブロックのサイズ > 18 #define BLOCK_SIZ 4096 > 19 // 内部実装 > 20 struct MemBlock; > 21 > 22 > 23 > 24 //========================================================================= > 25 //@{ @pkg ki.Memory //@} > 26 //@{ > 27 // メモリ割り当て・解放機構 > 28 // > 29 // SUPERTINYオプションを付けてコンパイルすると、標準の > 30 // mallocやfreeを使えなくなるため、HeapAlloc等のAPIを > 31 // 直接呼び出す必要が出てきます。しかし、こいつらを本当に > 32 // 毎回直に呼んでいると、遅い。もうアホかと、バカかと、 > 33 // って勢いで遅い。そこで、主にnewで動的に小規模メモリを > 34 // 確保することに主眼を据えた簡単なアロケータを使うことにしました。 > 35 // > 36 // <a href="http://cseng.aw.com/book/0,3828,0201704315,00.html">loki</a> > 37 // ライブラリほぼそのまんまな実装です。 > 38 //@} > 39 //========================================================================= > 40 > 41 class MemoryManager : public EzLockable > 42 { > 43 public: > 44 > 45 //@{ メモリ割り当て //@} > 46 void* Alloc( size_t siz ); > 47 > 48 //@{ メモリ解放 //@} > 49 void DeAlloc( void* ptr, size_t siz ); > 50 > 51 #ifdef USE_ORIGINAL_MEMMAN > 52 private: > 53 struct FixedSizeMemBlockPool > 54 { > 55 void Construct( byte siz ); > 56 void Destruct(); > 57 void* Alloc(); > 58 void DeAlloc( void* ptr ); > 59 bool isValid(); > 60 private: > 61 MemBlock* blocks_; > 62 int blockNum_; > 63 int blockNumReserved_; > 64 byte fixedSize_; > 65 byte numPerBlock_; > 66 int lastA_; > 67 int lastDA_; > 68 }; > 69 FixedSizeMemBlockPool pools_[ SMALL_MAX ]; > 70 #endif > 71 > 72 private: > 73 > 74 MemoryManager(); > 75 ~MemoryManager(); > 76 > 77 private: > 78 > 79 static MemoryManager* pUniqueInstance_; > 80 > 81 private: > 82 > 83 friend void APIENTRY Startup(); > 84 friend inline MemoryManager& mem(); > 85 NOCOPY(MemoryManager); > 86 }; > 87 > 88 > 89 > 90 //------------------------------------------------------------------------- > 91 > 92 //@{ 唯一のメモリ管理オブジェクトを返す //@} > 93 inline MemoryManager& mem() > 94 { return *MemoryManager::pUniqueInstance_; } > 95 > 96 //@{ ゼロ埋め作業 //@} > 97 inline void mem00( void* ptrv, int siz ) > 98 { BYTE* ptr = (BYTE*)ptrv; > 99 for(;siz>3;siz-=4,ptr+=4) *(DWORD*)ptr = 0x00000000; > 100 for(;siz;--siz,++ptr) *ptr = 0x00; } > 101 > 102 //@{ FF埋め作業 //@} > 103 inline void memFF( void* ptrv, int siz ) > 104 { BYTE* ptr = (BYTE*)ptrv; > 105 for(;siz>3;siz-=4,ptr+=4) *(DWORD*)ptr = 0xffffffff; > 106 for(;siz;--siz,++ptr) *ptr = 0xff; } > 107 > 108 > 109 > 110 //========================================================================= > 111 //@{ > 112 // 標準基底クラス > 113 // > 114 // JavaのObject や MFCのCObject みたいに使う…わけではなく、 > 115 // 単にここから派生すると自動で operator new/delete が高速版に > 116 // なるので便利だよ、という使い方のための基底クラスです。 > 117 //@} > 118 //========================================================================= > 119 > 120 class Object > 121 { > 122 #ifdef USE_ORIGINAL_MEMMAN > 123 public: > 124 > 125 static void* operator new( size_t siz ) > 126 { return mem().Alloc( siz ); } > 127 > 128 static void operator delete( void* ptr, size_t siz ) > 129 { mem().DeAlloc( ptr, siz ); } > 130 #endif > 131 > 132 protected: > 133 virtual ~Object() > 134 {} > 135 }; > 136 > 137 > 138 > 139 //========================================================================= > 140 > 141 } // namespace ki > 142 #endif // _KILIB_MEMORY_H_

Added kilib/path.cpp version [a6dcd62277a4d8c5]

> 1 #include "stdafx.h" > 2 #include "path.h" > 3 using namespace ki; > 4 > 5 > 6 > 7 //========================================================================= > 8 > 9 Path& Path::BeSpecialPath( int nPATH, bool bs ) > 10 { > 11 TCHAR* buf = AllocMem( MAX_PATH+1 ); > 12 > 13 switch( nPATH ) > 14 { > 15 case Win: ::GetWindowsDirectory( buf, MAX_PATH ); break; > 16 case Sys: ::GetSystemDirectory( buf, MAX_PATH ); break; > 17 case Tmp: ::GetTempPath( MAX_PATH, buf ); break; > 18 case Cur: ::GetCurrentDirectory( MAX_PATH, buf ); break; > 19 case Exe: > 20 case ExeName: ::GetModuleFileName( NULL, buf, MAX_PATH ); break; > 21 default: > 22 *buf = TEXT('\0'); > 23 { > 24 LPITEMIDLIST il; > 25 if( NOERROR==::SHGetSpecialFolderLocation( NULL, nPATH, > 26 { > 27 ::SHGetPathFromIDList( il, buf ); > 28 ::CoTaskMemFree( il ); > 29 } > 30 } > 31 } > 32 > 33 UnlockMem(); > 34 if( nPATH != ExeName ) > 35 { > 36 if( nPATH == Exe ) > 37 BeDirOnly(); > 38 BeBackSlash( bs ); > 39 } > 40 return *this; > 41 } > 42 > 43 Path& Path::BeBackSlash( bool add ) > 44 { > 45 // 最後の一文字を得る > 46 const TCHAR* last=c_str(); > 47 for( const TCHAR *p=last; *p!=TEXT('\0'); p=next(p) ) > 48 last = p; > 49 > 50 if( *last==TEXT('\\') || *last==TEXT('/') ) > 51 { > 52 if( !add ) > 53 TrimRight( 1 ); > 54 } > 55 else if( add && *last!=TEXT('\0') ) > 56 { > 57 *this += TEXT('\\'); > 58 } > 59 > 60 return *this; > 61 } > 62 > 63 Path& Path::BeDirOnly() > 64 { > 65 const TCHAR* lastslash = c_str()-1; > 66 for( const TCHAR* p=lastslash+1; *p!=TEXT('\0'); p=next(p) ) > 67 if( *p==TEXT('\\') || *p==TEXT('/') ) > 68 lastslash = p; > 69 > 70 TrimRight( len() - ulong((lastslash+1)-c_str()) ); > 71 return *this; > 72 } > 73 > 74 Path& Path::BeDriveOnly() > 75 { > 76 if( len() > 2 ) > 77 { > 78 const TCHAR* p = c_str()+2; > 79 for( ; *p!=TEXT('\0'); p=next(p) ) > 80 if( *p==TEXT('\\') || *p==TEXT('/') ) > 81 break; > 82 if( *p!=TEXT('\0') ) > 83 TrimRight( len() - ulong((p+1)-c_str()) ); > 84 } > 85 return *this; > 86 } > 87 > 88 Path& Path::BeShortStyle() > 89 { > 90 TCHAR* buf = ReallocMem( len()+1 ); > 91 ::GetShortPathName( buf, buf, len()+1 ); > 92 UnlockMem(); > 93 return *this; > 94 } > 95 > 96 Path& Path::BeShortLongStyle() > 97 { > 98 WIN32_FIND_DATA fd; > 99 HANDLE h = ::FindFirstFile( c_str(), &fd ); > 100 if( h == INVALID_HANDLE_VALUE ) > 101 return *this; > 102 ::FindClose( h ); > 103 > 104 TCHAR t; > 105 TCHAR* buf = ReallocMem( MAX_PATH*2 ); > 106 TCHAR* nam = const_cast<TCHAR*>(name(buf)); > 107 > 108 if( nam != buf ) > 109 t = *(nam-1), *(nam-1) = TEXT('\0'); > 110 ::lstrcpy( nam, fd.cFileName ); > 111 if( nam != buf ) > 112 *(nam-1) = t; > 113 > 114 UnlockMem(); > 115 return *this; > 116 } > 117 > 118 String Path::CompactIfPossible( int Mx ) > 119 { > 120 HMODULE hshl = ::LoadLibrary( TEXT("shlwapi.dll") ); > 121 if( !hshl ) return *this; > 122 > 123 typedef BOOL (STDAPICALLTYPE *PCPE_t)( LPTSTR, LPCTSTR, UINT, DWORD ); > 124 #ifdef _UNICODE > 125 PCPE_t MyPathCompactPathEx = (PCPE_t)::GetProcAddress( hshl, "PathCompac > 126 #else > 127 PCPE_t MyPathCompactPathEx = (PCPE_t)::GetProcAddress( hshl, "PathCompac > 128 #endif > 129 if( !MyPathCompactPathEx ) return *this; > 130 > 131 TCHAR* buf = new TCHAR[Mx+2]; > 132 MyPathCompactPathEx( buf, c_str(), Mx+1, 0 ); > 133 ::FreeLibrary( hshl ); > 134 > 135 String ans = buf; > 136 delete [] buf; > 137 return ans; > 138 } > 139 > 140 const TCHAR* Path::name( const TCHAR* str ) > 141 { > 142 const TCHAR* ans = str - 1; > 143 for( const TCHAR* p=str; *p!=TEXT('\0'); p=next(p) ) > 144 if( *p==TEXT('\\') || *p==TEXT('/') ) > 145 ans = p; > 146 return (ans+1); > 147 } > 148 > 149 const TCHAR* Path::ext( const TCHAR* str ) > 150 { > 151 const TCHAR *ans = NULL, *p; > 152 for( p=name(str); *p!=TEXT('\0'); p=next(p) ) > 153 if( *p==TEXT('.') ) > 154 ans = p; > 155 return ans ? (ans+1) : p; > 156 } > 157 > 158 const TCHAR* Path::ext_all( const TCHAR* str ) > 159 { > 160 const TCHAR* p; > 161 for( p=name(str); *p!=TEXT('\0'); p=next(p) ) > 162 if( *p==TEXT('.') ) > 163 return (p+1); > 164 return p; > 165 } > 166 > 167 Path Path::body() const > 168 { > 169 const TCHAR* nm = name(); > 170 const TCHAR* ex = ext() - 1; > 171 TCHAR t = *ex; > 172 *const_cast<TCHAR*>(ex) = TEXT('\0'); > 173 Path ans = nm; > 174 *const_cast<TCHAR*>(ex) = t; > 175 return ans; > 176 } > 177 > 178 Path Path::body_all() const > 179 { > 180 const TCHAR* nm = name(); > 181 const TCHAR* ex = ext_all() - 1; > 182 TCHAR t = *ex; > 183 *const_cast<TCHAR*>(ex) = TEXT('\0'); > 184 Path ans = nm; > 185 *const_cast<TCHAR*>(ex) = t; > 186 return ans; > 187 } > 188

Added kilib/path.h version [7bb4e3d9e7ec55cc]

> 1 #ifndef _KILIB_PATH_H_ > 2 #define _KILIB_PATH_H_ > 3 #include "types.h" > 4 #include "string.h" > 5 #ifndef __ccdoc__ > 6 namespace ki { > 7 #endif > 8 > 9 > 10 > 11 //========================================================================= > 12 //@{ @pkg ki.StdLib //@} > 13 //@{ > 14 // ファイル名処理 > 15 // > 16 // 基本的には文字列ですが、特にファイル名として扱うときに便利な > 17 // クラスです。名前部分のみ取り出しとか拡張子のみ取り出しとか、 > 18 // 属性を取ってくるとか色々。 > 19 //@} > 20 //========================================================================= > 21 > 22 class Path : public String > 23 { > 24 public: > 25 > 26 Path() {} > 27 > 28 //@{ 別のPathのコピー //@} > 29 Path( const Path& s ) : String( s ){} > 30 Path( const String& s ) : String( s ){} > 31 Path( const TCHAR* s, long siz=-1 ) : String( s, siz ){} > 32 > 33 //@{ 単純代入 //@} > 34 Path& operator=( const Path& s ) > 35 { return static_cast<Path&>(String::operator=(s)); } > 36 Path& operator=( const String& s ) > 37 { return static_cast<Path&>(String::operator=(s)); } > 38 Path& operator=( const TCHAR* s ) > 39 { return static_cast<Path&>(String::operator=(s)); } > 40 > 41 //@{ 加算代入 //@} > 42 Path& operator+=( const Path& s ) > 43 { return static_cast<Path&>(String::operator+=(s)); } > 44 Path& operator+=( const String& s ) > 45 { return static_cast<Path&>(String::operator+=(s)); } > 46 Path& operator+=( const TCHAR* s ) > 47 { return static_cast<Path&>(String::operator+=(s)); } > 48 Path& operator+=( TCHAR c ) > 49 { return static_cast<Path&>(String::operator+=(c)); } > 50 > 51 //@{ 特殊パス取得して初期化 //@} > 52 explicit Path( int nPATH, bool bs=true ) > 53 { BeSpecialPath( nPATH, bs ); } > 54 > 55 //@{ 特殊パス取得 //@} > 56 Path& BeSpecialPath( int nPATH, bool bs=true ); > 57 > 58 //@{ 特殊パス指定用定数 //@} > 59 enum { Win=0x1787, Sys, Tmp, Exe, Cur, ExeName, > 60 Snd=CSIDL_SENDTO, Dsk=CSIDL_DESKTOPDIRECTORY }; > 61 > 62 //@{ 最後にバックスラッシュを入れる(true)/入れない(false) //@} > 63 Path& BeBackSlash( bool add ); > 64 > 65 //@{ ドライブ名ないしルートのみ //@} > 66 Path& BeDriveOnly(); > 67 > 68 //@{ ディレクトリ名のみ //@} > 69 Path& BeDirOnly(); > 70 > 71 //@{ 短いパス名 //@} > 72 Path& BeShortStyle(); > 73 > 74 //@{ ファイル名だけは確実に長く //@} > 75 Path& BeShortLongStyle(); > 76 > 77 //@{ ...とかを入れて短く //@} > 78 String CompactIfPossible(int Mx); > 79 > 80 //@{ ディレクトリ情報以外 //@} > 81 const TCHAR* name() const; > 82 > 83 //@{ 最後の拡張子 //@} > 84 const TCHAR* ext() const; > 85 > 86 //@{ 最初の.以降全部と見なした拡張子 //@} > 87 const TCHAR* ext_all() const; > 88 > 89 //@{ ディレクトリ情報と最後の拡張子を除いた名前部分 //@} > 90 Path body() const; > 91 > 92 //@{ ディレクトリ情報と最初の.以降全部を除いた名前部分 //@} > 93 Path body_all() const; > 94 > 95 public: > 96 > 97 //@{ ファイルかどうか //@} > 98 bool isFile() const; > 99 > 100 //@{ ディレクトリかどうか //@} > 101 bool isDirectory() const; > 102 > 103 //@{ 存在するかどうか。isFile() || isDirectory() //@} > 104 bool exist() const; > 105 > 106 //@{ 読み取り専用かどうか //@} > 107 bool isReadOnly() const; > 108 > 109 public: > 110 > 111 static const TCHAR* name( const TCHAR* str ); > 112 static const TCHAR* ext( const TCHAR* str ); > 113 static const TCHAR* ext_all( const TCHAR* str ); > 114 }; > 115 > 116 > 117 > 118 //------------------------------------------------------------------------- > 119 > 120 inline bool Path::isFile() const > 121 { return 0==(::GetFileAttributes(c_str())&FILE_ATTRIBUTE_DIRECTORY); } > 122 > 123 inline bool Path::isDirectory() const > 124 { DWORD x=::GetFileAttributes(c_str()); > 125 return x!=0xffffffff && (x&FILE_ATTRIBUTE_DIRECTORY)!=0; } > 126 > 127 inline bool Path::exist() const > 128 { return 0xffffffff != ::GetFileAttributes(c_str()); } > 129 > 130 inline bool Path::isReadOnly() const > 131 { DWORD x=::GetFileAttributes(c_str()); > 132 return x!=0xffffffff && (x&FILE_ATTRIBUTE_READONLY)!=0; } > 133 > 134 inline const TCHAR* Path::name() const > 135 { return name(c_str()); } > 136 > 137 inline const TCHAR* Path::ext() const > 138 { return ext(c_str()); } > 139 > 140 inline const TCHAR* Path::ext_all() const > 141 { return ext_all(c_str()); } > 142 > 143 > 144 > 145 //========================================================================= > 146 > 147 } // namespace ki > 148 #endif // _KILIB_PATH_H_

Added kilib/registry.cpp version [19acfb259dd8987f]

> 1 #include "stdafx.h" > 2 #include "registry.h" > 3 using namespace ki; > 4 > 5 > 6 > 7 //========================================================================= > 8 > 9 void IniFile::SetFileName( const TCHAR* ini, bool exepath ) > 10 { > 11 iniName_ = > 12 (exepath ? iniName_.BeSpecialPath(Path::Exe) : Path(TEXT(""))); > 13 if( ini != NULL ) > 14 iniName_ += ini; > 15 else > 16 iniName_ += (Path(Path::ExeName).body()+=TEXT(".ini")); > 17 } > 18 > 19 void IniFile::SetSectionAsUserName() > 20 { > 21 TCHAR usr[256]; > 22 DWORD siz = countof(usr); > 23 if( !::GetUserName( usr, &siz ) ) > 24 ::lstrcpy( usr, TEXT("Default") ); > 25 SetSection( usr ); > 26 } > 27 > 28 bool IniFile::HasSectionEnabled( const TCHAR* section ) const > 29 { > 30 return (0!=::GetPrivateProfileInt( > 31 section, TEXT("Enable"), 0, iniName_.c_str() )); > 32 } > 33 > 34 int IniFile::GetInt ( const TCHAR* key, int defval ) const > 35 { > 36 return ::GetPrivateProfileInt( > 37 section_.c_str(), key, defval, iniName_.c_str() ); > 38 } > 39 > 40 bool IniFile::GetBool( const TCHAR* key, bool defval ) const > 41 { > 42 return (0!=::GetPrivateProfileInt( > 43 section_.c_str(), key, defval?1:0, iniName_.c_str() )); > 44 } > 45 > 46 String IniFile::GetStr ( const TCHAR* key, const String& defval ) const > 47 { > 48 RawString str; > 49 ulong l=256, s; > 50 for(;;) > 51 { > 52 TCHAR* x = str.AllocMem(l); > 53 s = ::GetPrivateProfileString( section_.c_str(), key, > 54 defval.c_str(), x, l, iniName_.c_str() ); > 55 if( s < l-1 ) > 56 break; > 57 l <<= 1; > 58 } > 59 str.UnlockMem(); > 60 return str; > 61 } > 62 > 63 Path IniFile::GetPath( const TCHAR* key, const Path& defval ) const > 64 { > 65 #ifdef _UNICODE > 66 String s = GetStr( key, defval ); > 67 if( s.len()==0 || s[0]!='#' ) > 68 return s; > 69 > 70 // UTF-decoder > 71 String buf; > 72 for(uint i=0; 4*i+4<s.len(); ++i) > 73 { > 74 unsigned short v = 0; > 75 for(int j=1; j<=4; ++j) > 76 { > 77 int ch = s[4*i+j]; > 78 if( '0'<=ch && ch<='9' ) v = 16*v + ch-'0'; > 79 if( 'a'<=ch && ch<='z' ) v = 16*v + ch-'a'+10; > 80 if( 'A'<=ch && ch<='Z' ) v = 16*v + ch-'A'+10; > 81 } > 82 buf += (wchar_t) v; > 83 } > 84 return buf; > 85 #else > 86 return GetStr( key, defval ); > 87 #endif > 88 } > 89 > 90 > 91 bool IniFile::PutStr ( const TCHAR* key, const TCHAR* val ) > 92 { > 93 if( val[0]==TEXT('"') && val[::lstrlen(val)-1]==TEXT('"') ) > 94 { > 95 // 両端に " があると勝手に削られるので対処 > 96 String nval; > 97 nval += TEXT('"'); > 98 nval += val; > 99 nval += TEXT('"'); > 100 return (FALSE != ::WritePrivateProfileString( > 101 section_.c_str(), key, nval.c_str(), iniName_.c_str() ) > 102 } > 103 else > 104 { > 105 return (FALSE != ::WritePrivateProfileString( > 106 section_.c_str(), key, val, iniName_.c_str() ) ); > 107 } > 108 } > 109 > 110 bool IniFile::PutInt ( const TCHAR* key, int val ) > 111 { > 112 TCHAR buf[20]; > 113 ::wsprintf( buf, TEXT("%d"), val ); > 114 return PutStr( key, buf ); > 115 } > 116 > 117 bool IniFile::PutBool( const TCHAR* key, bool val ) > 118 { > 119 return PutStr( key, val ? TEXT("1") : TEXT("0") ); > 120 } > 121 > 122 bool IniFile::PutPath( const TCHAR* key, const Path& val ) > 123 { > 124 #ifdef _UNICODE > 125 BOOL err = FALSE; > 126 ::WideCharToMultiByte( CP_ACP, 0, val.c_str(), -1, NULL, 0, NULL, &err ) > 127 if( !err ) > 128 return PutStr( key , val.c_str() ); > 129 > 130 // UTF-encoder > 131 const TCHAR* hex = TEXT("0123456789abcdef"); > 132 String buf = TEXT("#"); > 133 for(int i=0; i!=val.len(); ++i) > 134 { > 135 unsigned short u = (unsigned short) val[i]; > 136 buf += hex[(u>>12) & 0xf]; > 137 buf += hex[(u>> 8) & 0xf]; > 138 buf += hex[(u>> 4) & 0xf]; > 139 buf += hex[(u>> 0) & 0xf]; > 140 } > 141 return PutStr( key, buf.c_str() ); > 142 #else > 143 return PutStr( key, val.c_str() ); > 144 #endif > 145 } > 146 > 147

Added kilib/registry.h version [017afe9c288f9f71]

> 1 #ifndef _KILIB_REGISTRY_H_ > 2 #define _KILIB_REGISTRY_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #include "path.h" > 6 #ifndef __ccdoc__ > 7 namespace ki { > 8 #endif > 9 > 10 > 11 > 12 //========================================================================= > 13 //@{ @pkg ki.WinUtil //@} > 14 //@{ > 15 // INIファイル読み込み > 16 // > 17 //@} > 18 //========================================================================= > 19 > 20 class IniFile : public Object > 21 { > 22 public: > 23 > 24 //@{ コンストラクタ //@} > 25 IniFile( const TCHAR* ini=NULL, bool exeppath=true ); > 26 > 27 //@{ iniファイル名を設定 //@} > 28 void SetFileName( const TCHAR* ini=NULL, bool exepath=true ); > 29 > 30 //@{ セクション名を設定 //@} > 31 void SetSection( const TCHAR* section ); > 32 > 33 //@{ セクション名をユーザー名に設定 //@} > 34 void SetSectionAsUserName(); > 35 > 36 //@{ ある特定の名前のセクションがあるかどうか? //@} > 37 bool HasSectionEnabled( const TCHAR* section ) const; > 38 > 39 //@{ 整数値読み込み //@} > 40 int GetInt ( const TCHAR* key, int defval ) const; > 41 //@{ 真偽値読み込み //@} > 42 bool GetBool( const TCHAR* key, bool defval ) const; > 43 //@{ 文字列読み込み //@} > 44 String GetStr ( const TCHAR* key, const String& defval ) const; > 45 //@{ パス文字列読み込み //@} > 46 Path GetPath ( const TCHAR* key, const Path& defval ) const; > 47 > 48 //@{ 整数値書き込み //@} > 49 bool PutInt ( const TCHAR* key, int val ); > 50 //@{ 真偽値書き込み //@} > 51 bool PutBool( const TCHAR* key, bool val ); > 52 //@{ 文字列書き込み //@} > 53 bool PutStr ( const TCHAR* key, const TCHAR* val ); > 54 //@{ パス書き込み //@} > 55 bool PutPath( const TCHAR* key, const Path& val ); > 56 > 57 private: > 58 > 59 Path iniName_; > 60 String section_; > 61 char m_StrBuf[256]; > 62 }; > 63 > 64 > 65 > 66 //------------------------------------------------------------------------- > 67 > 68 inline IniFile::IniFile( const TCHAR* ini, bool exepath ) > 69 { SetFileName( ini, exepath ); } > 70 > 71 inline void IniFile::SetSection( const TCHAR* section ) > 72 { section_ = section; } > 73 > 74 > 75 > 76 > 77 //========================================================================= > 78 > 79 } // namespace ki > 80 #endif // _KILIB_REGISTRY_H_

Added kilib/stdafx.cpp version [93c3ae4d1bf237d8]

> 1 #include "stdafx.h"

Added kilib/stdafx.h version [bb450c1d9108af87]

> 1 #ifndef _KILIB_STDAFX_H_ > 2 #define _KILIB_STDAFX_H_ > 3 > 4 #undef WINVER > 5 #define WINVER 0x0400 > 6 #undef _WIN32_IE > 7 #define _WIN32_IE 0x0200 > 8 #undef _WIN32_WINNT > 9 #define _WIN32_WINNT 0x0400 > 10 > 11 #define OEMRESOURCE > 12 #define NOMINMAX > 13 #ifdef SUPERTINY > 14 #define memset memset_default > 15 #endif > 16 > 17 #include <windows.h> > 18 #include <shlobj.h> > 19 #include <commdlg.h> > 20 #include <commctrl.h> > 21 #include <imm.h> > 22 // dimm.hが無くてエラーになる場合、プロジェクトの設定でUSEGLOBALIMEの定義を > 23 // 削除するか、最新の Platform SDK を導入すればビルドが通るようになります。 > 24 #ifdef USEGLOBALIME > 25 #include <dimm.h> > 26 #endif > 27 > 28 #ifdef SUPERTINY > 29 #undef memset > 30 #endif > 31 > 32 #ifndef WM_MOUSEWHEEL > 33 #define WM_MOUSEWHEEL 0x020A > 34 #endif > 35 #ifndef OFN_ENABLESIZING > 36 #define OFN_ENABLESIZING 0x00800000 > 37 #endif > 38 #ifndef IMR_RECONVERTSTRING > 39 #define IMR_RECONVERTSTRING 0x0004 > 40 #define IMR_CONFIRMRECONVERTSTRING 0x0005 > 41 typedef struct tagRECONVERTSTRING { > 42 DWORD dwSize; > 43 DWORD dwVersion; > 44 DWORD dwStrLen; > 45 DWORD dwStrOffset; > 46 DWORD dwCompStrLen; > 47 DWORD dwCompStrOffset; > 48 DWORD dwTargetStrLen; > 49 DWORD dwTargetStrOffset; > 50 } RECONVERTSTRING, *PRECONVERTSTRING, NEAR *NPRECONVERTSTRING, FAR *LPRECONVERTS > 51 #endif > 52 #ifndef WM_IME_REQUEST > 53 #define WM_IME_REQUEST 0x0288 > 54 #endif > 55 > 56 #ifdef _MSC_VER > 57 #pragma warning( disable: 4355 ) > 58 #endif > 59 > 60 #ifdef __DMC__ > 61 #define SetWindowLongPtr SetWindowLong > 62 #define GetWindowLongPtr GetWindowLong > 63 #define UINT_PTR UINT > 64 #define LONG_PTR LONG > 65 #define GWLP_WNDPROC GWL_WNDPROC > 66 #define GWLP_USERDATA GWL_USERDATA > 67 #endif > 68 > 69 #endif // _KILIB_STDAFX_H_

Added kilib/string.cpp version [9d4f2283a9450bb3]

> 1 #include "stdafx.h" > 2 #include "app.h" > 3 #include "memory.h" > 4 #include "string.h" > 5 using namespace ki; > 6 > 7 > 8 > 9 //========================================================================= > 10 > 11 String::StringData* String::nullData_; > 12 char String::lb_[256]; > 13 > 14 void String::LibInit() > 15 { > 16 static int nullstr_image[4]; > 17 nullstr_image[0] = 1; > 18 nullstr_image[1] = 1; > 19 nullstr_image[2] = 4; > 20 nullData_ = reinterpret_cast<StringData*>(nullstr_image); > 21 > 22 #if !defined(_UNICODE) && defined(_MBCS) > 23 for( int c=0; c<256; ++c ) > 24 lb_[c] = (::IsDBCSLeadByte(c) ? 2 : 1); > 25 #endif > 26 } > 27 > 28 > 29 > 30 //------------------------------------------------------------------------- > 31 > 32 String::String( const TCHAR* s, long len ) > 33 { > 34 // 長さ指定が無い場合は計算 > 35 if( len==-1 ) > 36 len = ::lstrlen(s); > 37 > 38 if( len==0 ) > 39 { > 40 // 0文字用の特殊バッファ > 41 SetData( null() ); > 42 } > 43 else > 44 { > 45 // 新規バッファ作成 > 46 data_ = static_cast<StringData*> > 47 (mem().Alloc( sizeof(StringData)+(len+1)*sizeof(TCHAR) )); > 48 data_->ref = 1; > 49 data_->len = len+1; > 50 data_->alen = len+1; > 51 memmove( data_+1, s, (len+1)*sizeof(TCHAR) ); > 52 } > 53 } > 54 > 55 inline void String::ReleaseData() > 56 { > 57 if( --data_->ref <= 0 ) > 58 mem().DeAlloc( > 59 data_, sizeof(StringData)+sizeof(TCHAR)*data_->alen ); > 60 } > 61 > 62 String::~String() > 63 { > 64 ReleaseData(); > 65 } > 66 > 67 TCHAR* String::ReallocMem( ulong minimum=0 ) > 68 { > 69 return AllocMemHelper( minimum, c_str(), len()+1 ); > 70 } > 71 > 72 String& String::SetString( const TCHAR* str, ulong siz ) > 73 { > 74 TCHAR* buf = AllocMem( siz+1 ); > 75 > 76 memmove( buf, str, siz*sizeof(TCHAR) ); > 77 buf[siz] = TEXT('\0'); > 78 > 79 UnlockMem( siz ); > 80 return *this; > 81 } > 82 > 83 String& String::CatString( const TCHAR* str, ulong siz ) > 84 { > 85 const int plen = len(); > 86 TCHAR* buf = ReallocMem( plen + siz + 1 ); > 87 > 88 memmove( buf+plen, str, siz*sizeof(TCHAR) ); > 89 buf[plen+siz] = TEXT('\0'); > 90 > 91 UnlockMem( plen+siz ); > 92 return *this; > 93 } > 94 > 95 TCHAR* String::AllocMemHelper( ulong minimum, const TCHAR* str, ulong siz ) > 96 { > 97 if( data_->ref > 1 || data_->alen < minimum ) > 98 { > 99 minimum = Max( minimum, data_->alen ); > 100 > 101 StringData* pNew = static_cast<StringData*> > 102 (mem().Alloc( sizeof(StringData)+minimum*sizeof(TCHAR) ) > 103 pNew->ref = 1; > 104 pNew->alen = minimum; > 105 pNew->len = siz; > 106 memmove( pNew->buf(), str, siz*sizeof(TCHAR) ); > 107 > 108 ReleaseData(); > 109 data_ = pNew; > 110 } > 111 > 112 return data_->buf(); > 113 } > 114 > 115 String& String::operator = ( const String& obj ) > 116 { > 117 if( data() != obj.data() ) > 118 { > 119 ReleaseData(); > 120 SetData( obj.data() ); > 121 } > 122 return *this; > 123 } > 124 > 125 #ifdef _UNICODE > 126 String& String::operator = ( const char* s ) > 127 { > 128 long len = ::MultiByteToWideChar( CP_ACP, 0, s, -1, NULL, 0 ); > 129 ::MultiByteToWideChar( CP_ACP, 0, s, -1, AllocMem(len+1), len+1 ); > 130 #else > 131 String& String::operator = ( const wchar_t* s ) > 132 { > 133 long len = ::WideCharToMultiByte(CP_ACP,0,s,-1,NULL,0,NULL,NULL); > 134 ::WideCharToMultiByte(CP_ACP,0,s,-1,AllocMem(len+1),len+1,NULL,NULL); > 135 #endif > 136 UnlockMem( len ); > 137 return *this; > 138 } > 139 > 140 String& String::Load( UINT rsrcID ) > 141 { > 142 const int step=256; > 143 > 144 // 256バイトの固定長バッファへまず読んでみる > 145 TCHAR tmp[step], *buf; > 146 int red = app().LoadString( rsrcID, tmp, countof(tmp) ); > 147 if( countof(tmp) - red > 2 ) > 148 return (*this = tmp); > 149 > 150 // 少しずつ増やして対応してみる > 151 int siz = step; > 152 do > 153 { > 154 siz+= step; > 155 buf = AllocMem( siz ); > 156 red = app().LoadString( rsrcID, buf, siz ); > 157 } while( siz - red <= 2 ); > 158 > 159 buf[red] = TEXT('\0'); > 160 UnlockMem( red ); > 161 return *this; > 162 } > 163 > 164 void String::TrimRight( ulong siz ) > 165 { > 166 if( siz >= len() ) > 167 { > 168 ReleaseData(); > 169 SetData( null() ); > 170 } > 171 else > 172 { > 173 // 文字列バッファの参照カウントを確実に1にする > 174 ReallocMem(); > 175 > 176 // 指定文字数分削る > 177 data_->len -= siz; > 178 data_->buf()[data_->len-1] = TEXT('\0'); > 179 } > 180 } > 181 > 182 int String::GetInt( const TCHAR* x ) > 183 { > 184 int n=0; > 185 bool minus = (*x==TEXT('-')); > 186 for( const TCHAR* p=(minus?x+1:x); *p!=TEXT('\0'); p=next(p) ) > 187 { > 188 if( *p<TEXT('0') || TEXT('9')<*p ) > 189 return 0; > 190 n = (10*n) + (*p-TEXT('0')); > 191 } > 192 return minus ? -n : n; > 193 } > 194 > 195 String& String::SetInt( int n ) > 196 { > 197 if( n==0 ) > 198 { > 199 *this = TEXT("0"); > 200 } > 201 else > 202 { > 203 bool minus = (n<0); > 204 if( minus ) > 205 n= -n; > 206 > 207 TCHAR tmp[20]; > 208 tmp[19] = TEXT('\0'); > 209 int i; > 210 > 211 for( i=18; i>=0; --i ) > 212 { > 213 tmp[i] = TEXT('0') + n%10; > 214 n /= 10; > 215 if( n==0 ) > 216 break; > 217 } > 218 > 219 if( minus ) > 220 tmp[--i] = TEXT('-'); > 221 > 222 *this = tmp+i; > 223 } > 224 return *this; > 225 } > 226 > 227 const wchar_t* String::ConvToWChar() const > 228 { > 229 #ifdef _UNICODE > 230 return c_str(); > 231 #else > 232 int ln = ::MultiByteToWideChar( CP_ACP, 0, c_str(), -1 , 0, 0 ); > 233 wchar_t* p = new wchar_t[ln+1]; > 234 ::MultiByteToWideChar( CP_ACP, 0, c_str(), -1 , p, ln+1 ); > 235 return p; > 236 #endif > 237 } > 238

Added kilib/string.h version [9ee1f8a2b0ea71f4]

> 1 #ifndef _KILIB_STRING_H_ > 2 #define _KILIB_STRING_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #include "ktlaptr.h" > 6 #ifndef __ccdoc__ > 7 namespace ki { > 8 #endif > 9 #ifdef _UNICODE > 10 #define XTCHAR char > 11 #else > 12 #define XTCHAR wchar_t > 13 #endif > 14 > 15 > 16 > 17 //========================================================================= > 18 //@{ @pkg ki.StdLib //@} > 19 //@{ > 20 // 文字列処理 > 21 // > 22 // かなりMFCのCStringをパクってます。とりあえず operator= による > 23 // 単純代入にはほとんどコストがかからないようにしました。SubStr()の > 24 // 時もコピーしないようにしようかとも思ったんですが、そこまでは > 25 // 要らないだろうという気もするので…。 > 26 //@} > 27 //========================================================================= > 28 > 29 class String : public Object > 30 { > 31 public: > 32 > 33 //@{ 空文字列作成 //@} > 34 String(); > 35 ~String(); > 36 > 37 //@{ 別のStringのコピー //@} > 38 String( const String& obj ); > 39 > 40 //@{ 別の文字配列のコピー //@} > 41 String( const TCHAR* str, long siz=-1 ); > 42 > 43 //@{ リソースから作成 //@} > 44 explicit String( UINT rsrcID ); > 45 > 46 //@{ 大文字小文字を区別する比較 //@} > 47 bool operator==( LPCTSTR s ) const; > 48 bool operator==( const String& obj ) const; > 49 > 50 //@{ 大文字小文字を区別しない比較 //@} > 51 bool isSame( LPCTSTR s ) const; > 52 bool isSame( const String& obj ) const; > 53 > 54 //@{ 単純代入 //@} > 55 String& operator=( const String& obj ); > 56 String& operator=( const TCHAR* s ); > 57 String& operator=( const XTCHAR* s ); > 58 > 59 //@{ 加算代入 //@} > 60 String& operator+=( const String& obj ); > 61 String& operator+=( const TCHAR* s ); > 62 String& operator+=( TCHAR c ); > 63 > 64 //@{ リソースロード //@} > 65 String& Load( UINT rsrcID ); > 66 > 67 //@{ 右を削る //@} > 68 void TrimRight( ulong siz ); > 69 > 70 //@{ intから文字列へ変換 //@} > 71 String& SetInt( int n ); > 72 > 73 //@{ 文字列からintへ変換 //@} > 74 int GetInt(); > 75 > 76 public: > 77 > 78 //@{ 文字列バッファを返す //@} > 79 const TCHAR* c_str() const; > 80 > 81 //@{ 長さ //@} > 82 ulong len() const; > 83 > 84 //@{ 要素 //@} > 85 const TCHAR operator[](int n) const; > 86 > 87 //@{ ワイド文字列に変換して返す //@} > 88 const wchar_t* ConvToWChar() const; > 89 > 90 //@{ ConvToWCharの返値バッファの解放 //@} > 91 void FreeWCMem( const wchar_t* wc ) const; > 92 > 93 public: > 94 > 95 //@{ 次の一文字 //@} > 96 static TCHAR* next( TCHAR* p ); > 97 static const TCHAR* next( const TCHAR* p ); > 98 > 99 //@{ 2バイト文字の先頭かどうか? //@} > 100 static bool isLB( TCHAR c ); > 101 > 102 //@{ 文字列からintへ変換 //@} > 103 static int GetInt( const TCHAR* p ); > 104 > 105 protected: > 106 > 107 // 書き込み可能なバッファを、終端含めて最低でもminimum文字分用意する > 108 TCHAR* AllocMem( ulong minimum ); > 109 TCHAR* ReallocMem( ulong minimum ); > 110 > 111 // 書き込み終了後、長さを再設定 > 112 void UnlockMem( long siz=-1 ); > 113 > 114 private: > 115 > 116 struct StringData > 117 { > 118 long ref; // 参照カウンタ > 119 ulong len; // 終端'\0'を含める長さ > 120 ulong alen; // 割り当てられているメモリのサイズ > 121 TCHAR* buf() const // TCHAR buf[alen] > 122 { return reinterpret_cast<TCHAR*>( > 123 const_cast<StringData*>(this+1) > 124 ); } > 125 }; > 126 > 127 private: > 128 > 129 TCHAR* AllocMemHelper( ulong minimum, const TCHAR* str, ulong siz ); > 130 String& CatString( const TCHAR* str, ulong siz ); > 131 String& SetString( const TCHAR* str, ulong siz ); > 132 void SetData( StringData* d ); > 133 void ReleaseData(); > 134 static StringData* null(); > 135 StringData* data() const; > 136 > 137 private: > 138 > 139 StringData* data_; > 140 static StringData* nullData_; > 141 static char lb_[256]; > 142 > 143 private: > 144 > 145 static void LibInit(); > 146 friend void APIENTRY Startup(); > 147 }; > 148 > 149 > 150 > 151 //------------------------------------------------------------------------- > 152 #ifndef __ccdoc__ > 153 > 154 // 初期化 > 155 inline String::String() > 156 { SetData( null() ); } > 157 // 初期化 > 158 inline String::String( UINT rsrcID ) > 159 { SetData( null() ), Load( rsrcID ); } > 160 // 初期化 > 161 inline String::String( const String& obj ) > 162 { SetData( obj.data() ); } > 163 > 164 // ポインタ計算サポート > 165 #if !defined(_UNICODE) && defined(_MBCS) > 166 inline TCHAR* String::next( TCHAR* p ) > 167 { return p + lb_[*(uchar*)p]; } > 168 inline const TCHAR* String::next( const TCHAR* p ) > 169 { return p + lb_[*(const uchar*)p]; } > 170 inline bool String::isLB( TCHAR c ) > 171 { return lb_[(uchar)c]==2; } > 172 #else // _UNICODE or _SBCS > 173 inline TCHAR* String::next( TCHAR* p ) > 174 { return p + 1; } > 175 inline const TCHAR* String::next( const TCHAR* p ) > 176 { return p + 1; } > 177 inline bool String::isLB( TCHAR c ) > 178 { return false; } > 179 #endif > 180 > 181 // 内部メモリ確保 > 182 inline TCHAR* String::AllocMem( ulong minimum ) > 183 { return AllocMemHelper( minimum, TEXT(""), 1 ); } > 184 // 内部メモリ固定 > 185 inline void String::UnlockMem( long siz ) > 186 { data_->len = 1 + (siz==-1 ? ::lstrlen(c_str()) : siz); } > 187 > 188 // 0文字データ > 189 inline String::StringData* String::null() > 190 { return nullData_; } > 191 // 内部データ構造 > 192 inline String::StringData* String::data() const > 193 { return data_; } > 194 // 初期化 > 195 inline void String::SetData( String::StringData* d ) > 196 { data_=d, data_->ref++; } > 197 > 198 // 属性 > 199 inline const TCHAR* String::c_str() const > 200 { return data_->buf(); } > 201 // 属性 > 202 inline ulong String::len() const > 203 { return data_->len-1; } > 204 // 要素 > 205 inline const TCHAR String::operator[](int n) const > 206 { return data_->buf()[n]; } > 207 > 208 // 比較 > 209 inline bool String::operator==( LPCTSTR s ) const > 210 { return 0==::lstrcmp( c_str(), s ); } > 211 // 比較 > 212 inline bool String::operator==( const String& obj ) const > 213 { return (data_==obj.data_ ? true : operator==( obj.c_str() )); } > 214 // 比較 > 215 inline bool String::isSame( LPCTSTR s ) const > 216 { return 0==::lstrcmpi( c_str(), s ); } > 217 // 比較 > 218 inline bool String::isSame( const String& obj ) const > 219 { return (data_==obj.data_ ? true : operator==( obj.c_str() )); } > 220 > 221 // 要コピー代入 > 222 inline String& String::operator = ( const TCHAR* s ) > 223 { return SetString( s, ::lstrlen(s) ); } > 224 // 合成 > 225 inline String& String::operator += ( const String& obj ) > 226 { return CatString( obj.c_str(), obj.len() ); } > 227 // 合成 > 228 inline String& String::operator += ( const TCHAR* s ) > 229 { return CatString( s, ::lstrlen(s) ); } > 230 // 合成 > 231 inline String& String::operator += ( TCHAR c ) > 232 { return CatString( &c, 1 ); } > 233 > 234 // 変換 > 235 inline int String::GetInt() > 236 { return GetInt( data_->buf() ); } > 237 > 238 //@{ String + String //@} > 239 inline const String operator+( const String& a, const String& b ) > 240 { return String(a) += b; } > 241 //@{ String + TCHAR* //@} > 242 inline const String operator+( const String& a, const TCHAR* b ) > 243 { return String(a) += b; } > 244 //@{ TCHAR* + String //@} > 245 inline const String operator+( const TCHAR* a, const String& b ) > 246 { return String(a) += b; } > 247 > 248 // ConvToWCharの返値バッファの解放 > 249 inline void String::FreeWCMem( const wchar_t* wc ) const > 250 #ifdef _UNICODE > 251 {} > 252 #else // _MBCS or _SBCS > 253 { delete [] const_cast<wchar_t*>(wc); } > 254 #endif > 255 > 256 > 257 > 258 #endif // __ccdoc__ > 259 #undef XTCHAR > 260 //========================================================================= > 261 //@{ > 262 // 文字列処理+α > 263 // > 264 // Stringクラス内のバッファ確保関数を呼べるようにした版Stringです。 > 265 //@} > 266 //========================================================================= > 267 > 268 struct RawString : public String > 269 { > 270 TCHAR* AllocMem( ulong m ) { return String::AllocMem(m); } > 271 void UnlockMem() { String::UnlockMem(); } > 272 }; > 273 > 274 } // namespace ki > 275 > 276 > 277 //========================================================================= > 278 //@{ > 279 // 文字列処理+α2 > 280 // > 281 // Wide文字版関数を自前で > 282 //@} > 283 //========================================================================= > 284 > 285 #ifdef _UNICODE > 286 #define my_lstrlenW ::lstrlenW > 287 #define my_lstrcpyW ::lstrcpyW > 288 #else > 289 inline static > 290 unicode* my_lstrcpyW( unicode* const d, const unicode* s ) > 291 { > 292 for(unicode* n=d; *n++=*s++;); > 293 return d; > 294 } > 295 > 296 inline static > 297 int my_lstrlenW( const unicode* const d ) > 298 { > 299 const unicode* n; > 300 for(n=d; *n; ++n); > 301 return static_cast<int>(n-d); > 302 } > 303 #endif > 304 > 305 > 306 > 307 //========================================================================= > 308 > 309 #endif // _KILIB_STRING_H_

Added kilib/textfile.cpp version [9c2e5d73acf07249]

> 1 #include "stdafx.h" > 2 #include "app.h" > 3 #include "textfile.h" > 4 #include "ktlarray.h" > 5 using namespace ki; > 6 > 7 > 8 > 9 //========================================================================= > 10 // テキストファイル読み出し共通インターフェイス > 11 //========================================================================= > 12 > 13 struct ki::TextFileRPimpl : public Object > 14 { > 15 inline TextFileRPimpl() > 16 : state(EOL) {} > 17 > 18 virtual size_t ReadLine( unicode* buf, ulong siz ) > 19 = 0; > 20 > 21 enum { EOF=0, EOL=1, EOB=2 } state; > 22 }; > 23 > 24 > 25 > 26 //------------------------------------------------------------------------- > 27 // Unicode系用のベースクラス > 28 // UTF-8以外はそんなに出会わないだろうから遅くてもよしとする。 > 29 //------------------------------------------------------------------------- > 30 > 31 struct rBasicUTF : public ki::TextFileRPimpl > 32 { > 33 virtual unicode PeekC() = 0; > 34 virtual unicode GetC() {unicode ch=PeekC(); Skip(); return ch;} > 35 virtual void Skip() = 0; > 36 virtual bool Eof() = 0; > 37 > 38 size_t ReadLine( unicode* buf, ulong siz ) > 39 { > 40 state = EOF; > 41 > 42 // 改行が出るまで読む > 43 unicode *w=buf, *e=buf+siz; > 44 while( !Eof() ) > 45 { > 46 *w = GetC(); > 47 if( *w==L'\r' || *w==L'\n' ) > 48 { > 49 state = EOL; > 50 break; > 51 } > 52 else if( *w!=0xfeff && ++w==e ) > 53 { > 54 state = EOB; > 55 break; > 56 } > 57 } > 58 > 59 // 改行コードスキップ処理 > 60 if( state == EOL ) > 61 if( *w==L'\r' && !Eof() && PeekC()==L'\n' ) > 62 Skip(); > 63 > 64 // 読んだ文字数 > 65 return w-buf; > 66 } > 67 }; > 68 > 69 > 70 > 71 //------------------------------------------------------------------------- > 72 // UCS2ベタ/UCS4ベタ。それぞれUTF16, UTF32の代わりとして使う。 > 73 // ついでに同じtemplateで、ISO-8859-1も処理してしまう。^^; > 74 //------------------------------------------------------------------------- > 75 > 76 template<typename T> > 77 struct rUCS : public rBasicUTF > 78 { > 79 rUCS( const uchar* b, ulong s, bool bigendian ) > 80 : fb( reinterpret_cast<const T*>(b) ) > 81 , fe( reinterpret_cast<const T*>(b+(s/sizeof(T))*sizeof(T)) ) > 82 , be( bigendian ) {} > 83 > 84 const T *fb, *fe; > 85 const bool be; > 86 > 87 // エンディアン変換 > 88 inline byte swap( byte val ) { return val; } > 89 inline dbyte swap( dbyte val ) { return (val<<8) |(val>>8); } > 90 inline qbyte swap( qbyte val ) { return ((val>>24)&0xff | > 91 (val>>8)&0xff00 | > 92 > 93 > 94 > 95 virtual void Skip() { ++fb; } > 96 virtual bool Eof() { return fb==fe; } > 97 virtual unicode PeekC() { return (unicode)(be ? swap(*fb) : *fb); } > 98 }; > 99 > 100 typedef rUCS< byte> rWest; > 101 typedef rUCS<dbyte> rUtf16; > 102 > 103 // UTF-32読み込み > 104 struct rUtf32 : public rUCS<qbyte> > 105 { > 106 rUtf32( const uchar* b, ulong s, bool bigendian ) > 107 : rUCS<qbyte>(b,s,bigendian) > 108 , state(0) {} > 109 > 110 int state; > 111 qbyte curChar() { return be ? swap(*fb) : *fb; } > 112 bool inBMP(qbyte c) { return c<0x10000; } > 113 > 114 virtual unicode PeekC() > 115 { > 116 qbyte c = curChar(); > 117 if( inBMP(c) ) > 118 return (unicode)c; > 119 return (unicode)(state==0 ? 0xD800 + (((c-0x10000) >> 10)&0x3ff) > 120 : 0xDC00 + ( (c-0x10000) &0x > 121 } > 122 > 123 virtual void Skip() > 124 { > 125 if( inBMP(curChar()) ) > 126 ++fb; > 127 else if( state==0 ) > 128 state=1; > 129 else > 130 ++fb, state=0; > 131 } > 132 }; > 133 > 134 > 135 > 136 //------------------------------------------------------------------------- > 137 // UTF-5 > 138 // 0- F : 1bbbb > 139 // 10- FF : 1bbbb 0bbbb > 140 // 100-FFF : 1bbbb 0bbbb 0bbbb > 141 // というように、16進での一桁を一文字で表していくフォーマット。 > 142 // 各 0bbbb は '0', '1', ... '9', 'A', ... 'F' > 143 // 各 1bbbb は 'G', 'H', ... 'P', 'Q', ... 'V' の字で表現。 > 144 //------------------------------------------------------------------------- > 145 > 146 struct rUtf5 : public rBasicUTF > 147 { > 148 rUtf5( const uchar* b, ulong s ) > 149 : fb( b ) > 150 , fe( b+s ) {} > 151 > 152 const uchar *fb, *fe; > 153 > 154 // 16進文字から整数値へ変換 > 155 inline byte conv( uchar x ) > 156 { > 157 if( '0'<=x && x<='9' ) return x-'0'; > 158 else return x-'A'+0x0A; > 159 } > 160 > 161 void Skip() { do ++fb; while( fb<fe && *fb<'G' ); } > 162 bool Eof() { return fb==fe; } > 163 unicode PeekC() > 164 { > 165 unicode ch = (*fb-'G'); > 166 for( const uchar* p=fb+1; p<fe && *p<'G'; ++p ) > 167 ch = (ch<<4)|conv(*p); > 168 return ch; > 169 } > 170 }; > 171 > 172 > 173 > 174 //------------------------------------------------------------------------- > 175 // UTF-7 > 176 // ASCII範囲の字はそのまま。それ以外はUTF-16の値をbase64エンコード > 177 // して出力。エンコードされた部分は + と - で挟まれる。また '+' と > 178 // いう字自体を表現するために "+-" という形式を用いる。 > 179 //------------------------------------------------------------------------- > 180 > 181 namespace > 182 { > 183 static const uchar u7c[128]={ > 184 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x > 185 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x > 186 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3e,0xff,0xff,0x > 187 0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0xff,0xff,0xff,0xff,0x > 188 0xff,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x > 189 0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xff,0xff,0xff,0x > 190 0xff,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x > 191 0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0xff,0xff,0x > 192 } > 193 > 194 struct rUtf7 : public rBasicUTF > 195 { > 196 rUtf7( const uchar* b, ulong s ) > 197 : fb( b ) > 198 , fe( b+s ) > 199 , rest( -1 ) { fillbuf(); } > 200 > 201 const uchar *fb, *fe; > 202 unicode buf[3]; // b64を8文字毎に読んでバッファに溜めておく > 203 int rest; // バッファの空き > 204 bool inB64; // base64エリア内ならtrue > 205 > 206 void Skip() { if(--rest==0) fillbuf(); } > 207 bool Eof() { return fb==fe && rest==0; } > 208 unicode PeekC() { return buf[rest-1]; } > 209 > 210 void fillbuf() > 211 { > 212 if( fb<fe ) > 213 if( !inB64 ) > 214 if( *fb=='+' ) > 215 if( fb+1<fe && fb[1]=='-' ) > 216 rest=1, buf[0]=L'+', fb+=2; // > 217 else > 218 ++fb, inB64=true, fillbuf(); // > 219 else > 220 rest=1, buf[0]=*fb++; // 普通の字 > 221 else > 222 { > 223 // 何文字デコードできるか数える > 224 int N=0, E=Max(int(fb-fe),8); > 225 while( N<E && fb[N]<0x80 && u7c[fb[N]]!=0xff ) > 226 ++N; > 227 > 228 // デコード > 229 buf[0]=buf[1]=buf[2]=0; > 230 switch( N ) > 231 { > 232 case 8: buf[2]|= u7c[fb[7]]; > 233 case 7: buf[2]|=(u7c[fb[6]]<< 6); > 234 case 6: buf[2]|=(u7c[fb[5]]<<12), buf[1]|=(u7c[f > 235 case 5: buf[1]|=(u7c[fb[4]]<< 2); > 236 case 4: buf[1]|=(u7c[fb[3]]<< 8); > 237 case 3: buf[1]|=(u7c[fb[2]]<<14), buf[0]|=(u7c[f > 238 case 2: buf[0]|=(u7c[fb[1]]<< 4); > 239 case 1: buf[0]|=(u7c[fb[0]]<<10); > 240 unicode t; > 241 rest = 1; > 242 if( N==8 ) > 243 rest=3, t=buf[0], buf[0]=buf[2], > 244 else if( N>=6 ) > 245 rest=2, t=buf[0], buf[0]=buf[1], > 246 } > 247 > 248 // 使った分進む > 249 if( N<E ) > 250 { > 251 inB64=false; > 252 if( fb[N]=='-' ) > 253 ++fb; > 254 } > 255 fb += N; > 256 if( N==0 ) > 257 fillbuf(); > 258 } > 259 } > 260 }; > 261 > 262 > 263 > 264 //------------------------------------------------------------------------- > 265 // UTF8/MBCS > 266 // CR,LFが1バイト文字としてきちんと出てくるので、 > 267 // 切り分けが簡単な形式をここでまとめて扱う。UTF8以外の変換は > 268 // Windowsに全て任せている。 > 269 //------------------------------------------------------------------------- > 270 > 271 namespace > 272 { > 273 typedef char* (WINAPI * uNextFunc)(WORD,const char*,DWORD); > 274 > 275 static const byte mask[] = { 0, 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; > 276 static inline int GetMaskIndex(uchar n) > 277 { > 278 if( uchar(n+2) < 0xc2 ) return 1; // 00〜10111111, fe, ff > 279 if( n < 0xe0 ) return 2; // 110xxxxx > 280 if( n < 0xf0 ) return 3; // 1110xxxx > 281 if( n < 0xf8 ) return 4; // 11110xxx > 282 if( n < 0xfc ) return 5; // 111110xx > 283 return 6; // 1111110x > 284 } > 285 > 286 static char* WINAPI CharNextUtf8( WORD, const char* p, DWORD ) > 287 { > 288 return const_cast<char*>( p+GetMaskIndex(uchar(*p)) ); > 289 } > 290 > 291 // Win95対策。 > 292 // http://support.microsoft.com/default.aspx?scid=%2Fisapi%2Fgomscom%2 > 293 // MSDNにはWin95以降でサポートと書いてあるのにCP_UTF8は > 294 // 使えないらしいので、自前の変換関数で。 > 295 typedef int (WINAPI * uConvFunc)(UINT,DWORD,const char*,int,wchar_t*,int > 296 static int WINAPI Utf8ToWideChar( UINT, DWORD, const char* sb, int ss, w > 297 { > 298 const uchar *p = reinterpret_cast<const uchar*>(sb); > 299 const uchar *e = reinterpret_cast<const uchar*>(sb+ss); > 300 wchar_t *w = wb; // バッファサイズチェック無し(仕様) > 301 > 302 for( int t; p<e; ++w ) > 303 { > 304 t = GetMaskIndex(*p); > 305 qbyte qch = (*p++ & mask[t]); > 306 while( p<e && --t ) > 307 qch<<=6, qch|=(*p++)&0x3f; > 308 if(qch<0x10000) > 309 *w = (wchar_t)qch; > 310 else > 311 *w++ = (wchar_t)(0xD800 + (((qch-0x10000)>>10)&0 > 312 *w = (wchar_t)(0xDC00 + (((qch-0x10000) )&0 > 313 } > 314 return int(w-wb); > 315 } > 316 } > 317 > 318 struct rMBCS : public TextFileRPimpl > 319 { > 320 // ファイルポインタ&コードページ > 321 const char* fb; > 322 const char* fe; > 323 const int cp; > 324 uNextFunc next; > 325 uConvFunc conv; > 326 > 327 // 初期設定 > 328 rMBCS( const uchar* b, ulong s, int c ) > 329 : fb( reinterpret_cast<const char*>(b) ) > 330 , fe( reinterpret_cast<const char*>(b+s) ) > 331 , cp( c==UTF8 ? UTF8N : c ) > 332 , next( cp==UTF8N ? CharNextUtf8 : CharNextExA ) > 333 , conv( cp==UTF8N && app().isWin95() > 334 ? Utf8ToWideChar : MultiByteToWideChar ) > 335 { > 336 if( cp==UTF8N && fe-fb>=3 > 337 && b[0]==0xef && b[1]==0xbb && b[2]==0xbf ) > 338 fb += 3; // BOMスキップ > 339 } > 340 > 341 size_t ReadLine( unicode* buf, ulong siz ) > 342 { > 343 // バッファの終端か、ファイルの終端の近い方まで読み込む > 344 const char *p, *end = Min( fb+siz/2, fe ); > 345 state = (end==fe ? EOF : EOB); > 346 > 347 // 改行が出るまで進む > 348 for( p=fb; p<end; ) > 349 if( *p=='\r' || *p=='\n' ) > 350 { > 351 state = EOL; > 352 break; > 353 } > 354 else if( (*p) & 0x80 ) > 355 { > 356 p = next(cp,p,0); > 357 } > 358 else > 359 { > 360 ++p; > 361 } > 362 > 363 // Unicodeへ変換 > 364 #ifndef _UNICODE > 365 ulong len = conv( cp, 0, fb, p-fb, buf, siz ); > 366 #else > 367 ulong len = ::MultiByteToWideChar( cp, 0, fb, int(p-fb), buf, si > 368 #endif > 369 // 改行コードスキップ処理 > 370 if( state == EOL ) > 371 if( *(p++)=='\r' && p<fe && *p=='\n' ) > 372 ++p; > 373 fb = p; > 374 > 375 // 終了 > 376 return len; > 377 } > 378 }; > 379 > 380 > 381 > 382 //------------------------------------------------------------------------- > 383 // ISO-2022 の適当な実装 > 384 // > 385 // コードページとして、G0, G1, G2, G3 の四面を持つ。 > 386 // それぞれ決まったエスケープシーケンスによって、 > 387 // さまざまな文字集合を各面に呼び出すことが出来る。 > 388 // とりあえず現在のバージョンで対応しているふりなのは > 389 // 次の通り。()内に、そのいい加減っぷりを示す。 > 390 // > 391 // <<いつでも>> > 392 // 1B 28 42 : G0へ ASCII > 393 // 1B 28 4A : G0へ JIS X 0201 ローマ字 (のかわりにASCII) > 394 // 1B 29 4A : G1へ JIS X 0201 ローマ字 (のかわりにASCII) > 395 // 1B 2A 4A : G2へ JIS X 0201 ローマ字 (のかわりにASCII) > 396 // 1B 3B 4A : G3へ JIS X 0201 ローマ字 (のかわりにASCII) > 397 // 1B 2E 41 : G2へ ISO-8859-1 > 398 // <<CP932が有効な場合>> > 399 // 1B 28 49 : G0へ JIS X 0201 カナ > 400 // 1B 29 49 : G1へ JIS X 0201 カナ > 401 // 1B 2A 49 : G2へ JIS X 0201 カナ > 402 // 1B 2B 49 : G3へ JIS X 0201 カナ > 403 // 1B 24 40 : G0へ JIS X 0208(1978) > 404 // 1B 24 42 : G0へ JIS X 0208(1983) (年度は区別しない) > 405 // <<CP936が有効な場合>> > 406 // 1B 24 41 : G0へ GB 2312 > 407 // 1B 24 29 41 : G1へ GB 2312 > 408 // 1B 24 2A 41 : G2へ GB 2312 > 409 // 1B 24 2B 41 : G3へ GB 2312 > 410 // <<CP949が有効な場合>> > 411 // 1B 24 28 43 : G0へ KS X 1001 > 412 // 1B 24 29 43 : G1へ KS X 1001 > 413 // 1B 24 2A 43 : G2へ KS X 1001 > 414 // 1B 24 2B 43 : G3へ KS X 1001 > 415 // > 416 // 各面に呼び出した文字集合は、 > 417 // GL (0x21〜0xfe) GR (0xa0〜0xff) > 418 // のどちらかへマップすることで、実際のバイト値となる。 > 419 // マップ命令となるバイト列は、次の通り > 420 // > 421 // 0F : GL へG0を呼び出し > 422 // 0E : GL へG1を呼び出し > 423 // 1B 7E : GR へG1を呼び出し > 424 // 8E : GL/GR両方 へG2を一瞬だけ呼び出し。1B 4E も同義 > 425 // 8F : GL/GR両方 へG3を一瞬だけ呼び出し。1B 4F も同義 > 426 // > 427 //------------------------------------------------------------------------- > 428 > 429 enum CodeSet { ASCII, LATIN, KANA, JIS, KSX, GB }; > 430 > 431 struct rIso2022 : public TextFileRPimpl > 432 { > 433 // Helper: JIS X 0208 => SJIS > 434 void jis2sjis( uchar k, uchar t, char* s ) > 435 { > 436 if(k>=0x3f) s[0] = (char)(((k+1)>>1)+0xc0); > 437 else s[0] = (char)(((k+1)>>1)+0x80); > 438 if( k&1 ) s[1] = (char)((t>>6) ? t+0x40 : t+0x3f); > 439 else s[1] = (char)(t+0x9e); > 440 } > 441 > 442 // ファイルポインタ > 443 const uchar* fb; > 444 const uchar* fe; > 445 bool fixed; // ESCによる切り替えを行わないならtrue > 446 bool mode_hz; // HZの場合。 > 447 > 448 // 作業変数 > 449 CodeSet *GL, *GR, G[4]; > 450 int gWhat; // 次の字は 1:GL/GR 2:G2 3:G3 で出力 > 451 ulong len; > 452 > 453 // 初期化 > 454 rIso2022( const uchar* b, ulong s, bool f, bool hz, > 455 CodeSet g0, CodeSet g1, CodeSet g2=ASCII, CodeSet g3=ASCII ) > 456 : fb( b ) > 457 , fe( b+s ) > 458 , fixed( f ) > 459 , mode_hz( hz ) > 460 , GL( &G[0] ) > 461 , GR( &G[1] ) > 462 , gWhat( 1 ) > 463 { > 464 G[0]=g0, G[1]=g1, G[2]=g2, G[3]=g3; > 465 } > 466 > 467 void DoSwitching( const uchar*& p ) > 468 { > 469 if( fixed ) > 470 { > 471 if( p[0]==0x24 && p[1]!=0x40 && p[1]!=0x41 && p[1]!=0x42 > 472 && p+2 < fe && (p[2]==0x41 || p[2]==0x43) ) > 473 ++p; > 474 } > 475 else > 476 { > 477 if( p[1]==0x4A ) > 478 G[ (p[0]-0x28)%4 ] = ASCII; // 1B [28-2B > 479 else if( p[1]==0x49 ) > 480 G[ (p[0]-0x28)%4 ] = KANA; // 1B [28-2B > 481 else if( *reinterpret_cast<const dbyte*>(p)==0x4228 ) > 482 G[ 0 ] = ASCII; // 1B 28 42 > 483 else if( *reinterpret_cast<const dbyte*>(p)==0x412E ) > 484 G[ 2 ] = LATIN; // 1B 2E 41 > 485 else if( p[0]==0x24 ) > 486 if( p[1]==0x40 || p[1]==0x42 ) > 487 G[ 0 ] = JIS; // 1B 24 > 488 else if( p[1]==0x41 ) > 489 G[ 0 ] = GB; // 1B 24 > 490 else if( p+2 < fe ) > 491 if( p[2]==0x41 ) > 492 G[ ((*++p)-0x28)%4 ] = GB; // 1 > 493 else if( p[2]==0x43 ) > 494 G[ ((*++p)-0x28)%4 ] = KSX; // 1 > 495 } > 496 ++p; > 497 } > 498 > 499 void DoOutput( unicode*& buf, const uchar*& p ) > 500 { > 501 // 文字集合取り出し > 502 CodeSet cs = > 503 (gWhat==2 ? G[2] : > 504 (gWhat==3 ? G[3] : > 505 (*p&0x80 ? *GR : *GL))); > 506 > 507 char c[2]; > 508 ulong wt=1; > 509 switch( cs ) > 510 { > 511 case ASCII: > 512 *buf = (*p)&0x7f; > 513 break; > 514 case LATIN: > 515 *buf = (*p)|0x80; > 516 break; > 517 case KANA: > 518 c[0] = (*p)|0x80; > 519 wt = ::MultiByteToWideChar( > 520 932, MB_PRECOMPOSED, c, 1, buf, 2 ); > 521 break; > 522 case GB: > 523 case KSX: > 524 c[0] = (* p)|0x80; > 525 c[1] = (*++p)|0x80; > 526 wt = ::MultiByteToWideChar( > 527 (cs==GB?936:949), MB_PRECOMPOSED, c, 2, buf, 2 ) > 528 break; > 529 case JIS: > 530 jis2sjis( (p[0]&0x7f)-0x20, (p[1]&0x7f)-0x20, c ); > 531 ++p; > 532 wt = ::MultiByteToWideChar( > 533 932, MB_PRECOMPOSED, c, 2, buf, 2 ); > 534 break; > 535 } > 536 buf+=wt; > 537 len+=wt; > 538 } > 539 > 540 size_t ReadLine( unicode* buf, ulong siz ) > 541 { > 542 len=0; > 543 > 544 // バッファの終端か、ファイルの終端の近い方まで読み込む > 545 const uchar *p, *end = Min( fb+siz/2, fe ); > 546 state = (end==fe ? EOF : EOB); > 547 > 548 // 改行が出るまで進む > 549 for( p=fb; p<end; ++p ) > 550 switch( *p ) > 551 { > 552 case '\r': > 553 case '\n': state = EOL; goto outofloop; > 554 case 0x0F: GL = &G[0]; break; > 555 case 0x0E: GL = &G[1]; break; > 556 case 0x8E: gWhat = 2; break; > 557 case 0x8F: gWhat = 3; break; > 558 case 0x1B: > 559 if( p+1<fe ) { > 560 ++p; if( *p==0x7E ) GR = &G[1]; > 561 else if( *p==0x4E ) gWhat = 2; > 562 else if( *p==0x4F ) gWhat = 3; > 563 else if( p+1<fe ) DoSwitching(p); > 564 }break; > 565 case 0x7E: if( mode_hz && p+1<fe ) { > 566 ++p; if( *p==0x7D ){ GL = &G[0]; break; > 567 else if( *p==0x7B ){ GL = &G[1]; break; > 568 } // fall through... > 569 default: DoOutput( buf, p ); gWhat=1; break; > 570 } > 571 outofloop: > 572 > 573 // 改行コードスキップ処理 > 574 if( state == EOL ) > 575 if( *(p++)=='\r' && p<fe && *p=='\n' ) > 576 ++p; > 577 fb = p; > 578 > 579 // 終了 > 580 return len; > 581 } > 582 }; > 583 > 584 > 585 > 586 //------------------------------------------------------------------------- > 587 // 自動判定などなど > 588 //------------------------------------------------------------------------- > 589 > 590 TextFileR::TextFileR( int charset ) > 591 : cs_( charset ) > 592 , nolbFound_(true) > 593 { > 594 } > 595 > 596 TextFileR::~TextFileR() > 597 { > 598 Close(); > 599 } > 600 > 601 size_t TextFileR::ReadLine( unicode* buf, ulong siz ) > 602 { > 603 return impl_->ReadLine( buf, siz ); > 604 } > 605 > 606 int TextFileR::state() const > 607 { > 608 return impl_->state; > 609 } > 610 > 611 void TextFileR::Close() > 612 { > 613 fp_.Close(); > 614 } > 615 > 616 bool TextFileR::Open( const TCHAR* fname ) > 617 { > 618 // ファイルを開く > 619 if( !fp_.Open(fname) ) > 620 return false; > 621 const uchar* buf = fp_.base(); > 622 const ulong siz = fp_.size(); > 623 > 624 // 必要なら自動判定 > 625 cs_ = AutoDetection( cs_, buf, Min<ulong>(siz,16<<10) ); // 先頭16KB > 626 > 627 // 対応するデコーダを作成 > 628 switch( cs_ ) > 629 { > 630 case Western: impl_ = new rWest(buf,siz,true); break; > 631 case UTF16b: > 632 case UTF16BE: impl_ = new rUtf16(buf,siz,true); break; > 633 case UTF16l: > 634 case UTF16LE: impl_ = new rUtf16(buf,siz,false); break; > 635 case UTF32b: > 636 case UTF32BE: impl_ = new rUtf32(buf,siz,true); break; > 637 case UTF32l: > 638 case UTF32LE: impl_ = new rUtf32(buf,siz,false); break; > 639 case UTF5: impl_ = new rUtf5(buf,siz); break; > 640 case UTF7: impl_ = new rUtf7(buf,siz); break; > 641 case EucJP: impl_ = new rIso2022(buf,siz,true,false,ASCII,JIS,KANA); b > 642 case IsoJP: impl_ = new rIso2022(buf,siz,false,false,ASCII,KANA); brea > 643 case IsoKR: impl_ = new rIso2022(buf,siz,true,false,ASCII,KSX); break; > 644 case IsoCN: impl_ = new rIso2022(buf,siz,true,false,ASCII,GB); break; > 645 case HZ: impl_ = new rIso2022(buf,siz,true,true, ASCII,GB); break; > 646 default: impl_ = new rMBCS(buf,siz,cs_); break; > 647 } > 648 > 649 return true; > 650 } > 651 > 652 int TextFileR::AutoDetection( int cs, const uchar* ptr, ulong siz ) > 653 { > 654 //-- まず、文字の出現回数の統計を取る > 655 > 656 int freq[256]; > 657 bool bit8 = false; > 658 mem00( freq, sizeof(freq) ); > 659 for( ulong i=0; i<siz; ++i ) > 660 { > 661 if( ptr[i] >= 0x80 ) > 662 bit8 = true; > 663 ++freq[ ptr[i] ]; > 664 } > 665 > 666 //-- 改行コード決定 (UTF16/32/7のとき問題あり。UTF5に至っては判定不可…) > 667 > 668 if( freq['\r'] > freq['\n']*2 ) lb_ = CR; > 669 else if( freq['\n'] > freq['\r']*2 ) lb_ = LF; > 670 else lb_ = CRLF; > 671 nolbFound_ = freq['\r']==0 && freq['\n']==0; > 672 > 673 //-- デフォルトコード > 674 > 675 int defCs = ::GetACP(); > 676 > 677 //-- 小さすぎる場合はここで終了 > 678 > 679 if( siz <= 4 ) > 680 return cs==AutoDetect ? defCs : cs; > 681 > 682 //-- 明示指定がある場合はここで終了 > 683 > 684 ulong bom4 = (ptr[0]<<24) + (ptr[1]<<16) + (ptr[2]<<8) + (ptr[3]); > 685 ulong bom2 = (ptr[0]<<8) + (ptr[1]); > 686 > 687 if( cs==UTF8 || cs==UTF8N ) > 688 cs = (bom4>>8==0xefbbbf ? UTF8 : UTF8N); > 689 else if( cs==UTF32b || cs==UTF32BE ) > 690 cs = (bom4==0x0000feff ? UTF32b : UTF32BE); > 691 else if( cs==UTF32l || cs==UTF32LE ) > 692 cs = (bom4==0xfffe0000 ? UTF32l : UTF32LE); > 693 else if( cs==UTF16b || cs==UTF16BE ) > 694 cs = (bom2==0xfeff ? UTF16b : UTF16BE); > 695 else if( cs==UTF16l || cs==UTF16LE ) > 696 cs = (bom2==0xfffe ? UTF16l : UTF16LE); > 697 > 698 if( cs != AutoDetect ) > 699 return cs; > 700 > 701 //-- BOMチェック・7bitチェック > 702 > 703 bool Jp = ::IsValidCodePage(932)!=FALSE; > 704 > 705 if( (bom4>>8) == 0xefbbbf ) cs = UTF8; > 706 else if( bom4 == 0x0000feff ) cs = UTF32b; > 707 else if( bom4 == 0xfffe0000 ) cs = UTF32l; > 708 else if( bom2 == 0xfeff ) cs = UTF16b; > 709 else if( bom2 == 0xfffe ) cs = UTF16l; > 710 else if( bom4 == 0x1b242943 && ::IsValidCodePage(949) ) cs = IsoKR; > 711 else if( bom4 == 0x1b242941 && ::IsValidCodePage(936) ) cs = IsoCN; > 712 else if( Jp && !bit8 && freq[0x1b]>0 ) cs = IsoJP; > 713 > 714 if( cs != AutoDetect ) > 715 return cs; > 716 > 717 //-- UTF-5 チェック > 718 > 719 ulong u5sum = 0; > 720 for( uchar c='0'; c<='9'; ++c ) u5sum += freq[c]; > 721 for( uchar c='A'; c<='V'; ++c ) u5sum += freq[c]; > 722 if( siz == u5sum ) > 723 return UTF5; > 724 > 725 //-- 暫定版 UTF-8 / 日本語EUC チェック > 726 > 727 cs = defCs; > 728 > 729 // 改行コードがLFか、ある程度の大きさか、でないと > 730 // 無条件で ANSI-CP と見なしてしまう。 > 731 if( bit8 && (siz>4096 || lb_==1 > 732 || freq[0xfd]>0 || freq[0xfe]>0 || freq[0xff]>0 || freq[0x80]>0) ) > 733 { > 734 // UHCやGBKはEUC-JPと非常に混同しやすいので、そっちがデフォルトの場合は > 735 // EUC-JP自動判定を切る > 736 if( Jp && ::GetACP()!=UHC && ::GetACP()!=GBK && ::GetACP()!=Big5 > 737 { > 738 // EUCとしておかしい値が無いかチェック > 739 bool be=true; > 740 for( int k=0x90; k<=0xa0; ++k )if( freq[k]>0 ){be=false; > 741 for( int k=0x7f; k<=0x8d; ++k )if( freq[k]>0 ){be=false; > 742 if( be ) > 743 return EucJP; > 744 } > 745 { > 746 // UTF8として読めるかどうかチェック > 747 bool b8=true; > 748 int mi=1; > 749 for( ulong i=0; i<siz && b8; ++i ) > 750 if( --mi ) > 751 { > 752 if( ptr[i]<0x80 || ptr[i]>=0xc0 ) > 753 b8 = false; > 754 } > 755 else > 756 { > 757 mi = 1; > 758 if( ptr[i] > 0x7f ) > 759 { > 760 mi = GetMaskIndex( ptr[i] ); > 761 if( mi == 1 )//ptr[i] >= 0xfe ) > 762 b8 = false; > 763 } > 764 } > 765 if( b8 ) > 766 return UTF8N; > 767 } > 768 } > 769 > 770 //-- 判定結果 > 771 > 772 return cs; > 773 } > 774 > 775 > 776 > 777 //========================================================================= > 778 // テキストファイル出力共通インターフェイス > 779 //========================================================================= > 780 > 781 struct ki::TextFileWPimpl : public Object > 782 { > 783 virtual void WriteLine( const unicode* buf, ulong siz ) > 784 { while( siz-- ) WriteChar( *buf++ ); } > 785 > 786 virtual void WriteLB( const unicode* buf, ulong siz ) > 787 { WriteLine( buf, siz ); } > 788 > 789 virtual void WriteChar( unicode ch ) > 790 {} > 791 > 792 ~TextFileWPimpl() > 793 { delete [] buf_; } > 794 > 795 protected: > 796 > 797 TextFileWPimpl( FileW& w ) > 798 : fp_ (w) > 799 , bsiz_ (65536) > 800 , buf_ (new char[bsiz_]) {} > 801 > 802 void ReserveMoreBuffer() > 803 { > 804 char* nBuf = new char[bsiz_<<=1]; > 805 delete [] buf_; > 806 buf_ = nBuf; > 807 } > 808 > 809 FileW& fp_; > 810 ulong bsiz_; > 811 char* buf_; > 812 }; > 813 > 814 > 815 > 816 //------------------------------------------------------------------------- > 817 // Unicodeテキスト > 818 //------------------------------------------------------------------------- > 819 > 820 struct wUtf16LE : public TextFileWPimpl > 821 { > 822 wUtf16LE( FileW& w, bool bom ) : TextFileWPimpl(w) > 823 { if(bom){ unicode ch=0xfeff; fp_.Write(&ch,2); } } > 824 void WriteLine( const unicode* buf, ulong siz ) {fp_.Write(buf,siz*2);} > 825 }; > 826 > 827 struct wUtf16BE : public TextFileWPimpl > 828 { > 829 wUtf16BE( FileW& w, bool bom ) : TextFileWPimpl(w) > 830 { if(bom) WriteChar(0xfeff); } > 831 void WriteChar( unicode ch ) { fp_.WriteC(ch>>8), fp_.WriteC(ch&0xff); } > 832 }; > 833 > 834 struct wUtf32LE : public TextFileWPimpl > 835 { > 836 wUtf32LE( FileW& w, bool bom ) : TextFileWPimpl(w) > 837 { if(bom) {unicode c=0xfeff; WriteLine(&c,1);} } > 838 // void WriteChar( unicode ch ) > 839 // { fp_.WriteC(ch&0xff), fp_.WriteC(ch>>8), fp_.WriteC(0), fp_.Wri > 840 virtual void WriteLine( const unicode* buf, ulong siz ) > 841 { > 842 while( siz-- ) > 843 { > 844 unicode c = *buf++; > 845 qbyte cc = c; > 846 if( (0xD800<=c && c<=0xDBFF) && siz>0 ) // trail char が正しいかどうかは > 847 { > 848 unicode c2 = *buf++; siz--; > 849 cc = 0x10000 + (((c-0xD800)&0x3ff)<<10) + ((c2-0 > 850 } > 851 for(int i=0; i<=3; ++i) > 852 fp_.WriteC( (uchar)(cc>>(8*i)) ); > 853 } > 854 } > 855 }; > 856 > 857 struct wUtf32BE : public TextFileWPimpl > 858 { > 859 wUtf32BE( FileW& w, bool bom ) : TextFileWPimpl(w) > 860 { if(bom) {unicode c=0xfeff; WriteLine(&c,1);} } > 861 // void WriteChar( unicode ch ) > 862 // { fp_.WriteC(0), fp_.WriteC(0), fp_.WriteC(ch>>8), fp_.WriteC(ch > 863 virtual void WriteLine( const unicode* buf, ulong siz ) > 864 { > 865 while( siz-- ) > 866 { > 867 unicode c = *buf++; > 868 qbyte cc = c; > 869 if( (0xD800<=c && c<=0xDBFF) && siz>0 ) // trail char が正しいかどうかは > 870 { > 871 unicode c2 = *buf++; siz--; > 872 cc = 0x10000 + (((c-0xD800)&0x3ff)<<10) + ((c2-0 > 873 } > 874 for(int i=3; i>=0; --i) > 875 fp_.WriteC( (uchar)(cc>>(8*i)) ); > 876 } > 877 } > 878 }; > 879 > 880 struct wWest : public TextFileWPimpl > 881 { > 882 wWest( FileW& w ) : TextFileWPimpl(w) {} > 883 void WriteChar( unicode ch ) { fp_.WriteC(ch>0xff ? '?' : (uchar)ch); } > 884 }; > 885 > 886 struct wUtf5 : public TextFileWPimpl > 887 { > 888 wUtf5( FileW& w ) : TextFileWPimpl(w) {} > 889 void WriteChar( unicode ch ) > 890 { > 891 static const char conv[] = { > 892 '0','1','2','3','4','5','6','7', > 893 '8','9','A','B','C','D','E','F' }; > 894 if(ch<0x10) > 895 { > 896 fp_.WriteC(ch+'G'); > 897 } > 898 else if(ch<0x100) > 899 { > 900 fp_.WriteC((ch>>4)+'G'); > 901 fp_.WriteC(conv[ch&0xf]); > 902 } > 903 else if(ch<0x1000) > 904 { > 905 fp_.WriteC((ch>>8)+'G'); > 906 fp_.WriteC(conv[(ch>>4)&0xf]); > 907 fp_.WriteC(conv[ch&0xf]); > 908 } > 909 else > 910 { > 911 fp_.WriteC((ch>>12)+'G'); > 912 fp_.WriteC(conv[(ch>>8)&0xf]); > 913 fp_.WriteC(conv[(ch>>4)&0xf]); > 914 fp_.WriteC(conv[ch&0xf]); > 915 } > 916 } > 917 }; > 918 > 919 > 920 > 921 //------------------------------------------------------------------------- > 922 // Win95対策の自前UTF8/UTF7処理 > 923 //------------------------------------------------------------------------- > 924 #ifndef _UNICODE > 925 > 926 struct wUTF8 : public TextFileWPimpl > 927 { > 928 wUTF8( FileW& w, int cp ) > 929 : TextFileWPimpl(w) > 930 { > 931 if( cp == UTF8 ) // BOM書き込み > 932 fp_.Write( "\xEF\xBB\xBF", 3 ); > 933 } > 934 > 935 void WriteLine( const unicode* str, ulong len ) > 936 { > 937 // 0000-0000-0xxx-xxxx | 0xxxxxxx > 938 // 0000-0xxx-xxyy-yyyy | 110xxxxx 10yyyyyy > 939 // xxxx-yyyy-yyzz-zzzz | 1110xxxx 10yyyyyy 10zzzzzz > 940 // x-xxyy-yyyy-zzzz-zzww-wwww | 11110xxx 10yyyyyy 10zzzzzz 10www > 941 // ... > 942 while( len-- ) > 943 { > 944 qbyte ch = *str; > 945 if( (0xD800<=ch&&ch<=0xDBFF) && len ) > 946 ch = 0x10000 + (((ch-0xD800)&0x3ff)<<10) + ((*++ > 947 > 948 if( ch <= 0x7f ) > 949 fp_.WriteC( static_cast<uchar>(ch) ); > 950 else if( ch <= 0x7ff ) > 951 fp_.WriteC( 0xc0 | static_cast<uchar>(ch>>6) ), > 952 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) ) > 953 else if( ch<= 0xffff ) > 954 fp_.WriteC( 0xe0 | static_cast<uchar>(ch>>12) ), > 955 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x > 956 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) ) > 957 else if( ch<= 0x1fffff ) > 958 fp_.WriteC( 0xf0 | static_cast<uchar>(ch>>18) ), > 959 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>12)&0 > 960 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x > 961 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) ) > 962 else if( ch<= 0x3ffffff ) > 963 fp_.WriteC( 0xf8 | static_cast<uchar>(ch>>24) ), > 964 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>18)&0 > 965 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>12)&0 > 966 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x > 967 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) ) > 968 else > 969 fp_.WriteC( 0xfc | static_cast<uchar>(ch>>30) ), > 970 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>24)&0 > 971 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>18)&0 > 972 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>12)&0 > 973 fp_.WriteC( 0x80 | static_cast<uchar>((ch>>6)&0x > 974 fp_.WriteC( 0x80 | static_cast<uchar>(ch&0x3f) ) > 975 ++str; > 976 } > 977 } > 978 }; > 979 > 980 > 981 > 982 struct wUTF7 : public TextFileWPimpl > 983 { > 984 wUTF7( FileW& w ) : TextFileWPimpl(w) {} > 985 > 986 void WriteLine( const unicode* str, ulong len ) > 987 { > 988 static const uchar mime[64] = { > 989 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', > 990 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', > 991 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', > 992 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'} > 993 > 994 // XxxxxxYyyyyyZzzz | zzWwwwwwUuuuuuVv | vvvvTtttttSsssss > 995 bool mode_m = false; > 996 while( len ) > 997 { > 998 if( *str <= 0x7f ) > 999 { > 1000 fp_.WriteC( static_cast<uchar>(*str) ); > 1001 if( *str == L'+' ) > 1002 fp_.WriteC( '-' ); > 1003 ++str, --len; > 1004 } > 1005 else > 1006 { > 1007 if(!mode_m) fp_.WriteC( '+' ), mode_m=true; > 1008 unicode tx[3] = {0,0,0}; > 1009 int n=0; > 1010 tx[0] = *str, ++str, --len, ++n; > 1011 if( len && *str>0x7f ) > 1012 { > 1013 tx[1] = *str, ++str, --len, ++n; > 1014 if( len && *str>0x7f ) > 1015 tx[2] = *str, ++str, --len, ++n; > 1016 } > 1017 { > 1018 fp_.WriteC( mime[ tx[0]>>10 ] ); > 1019 fp_.WriteC( mime[ (tx[0]>>4)&0x3f ] ); > 1020 fp_.WriteC( mime[ (tx[0]<<2|tx[1]>>14)&0 > 1021 if( n>=2 ) > 1022 { > 1023 fp_.WriteC( mime[ (tx[1]>>8)&0x3 > 1024 fp_.WriteC( mime[ (tx[1]>>2)&0x3 > 1025 fp_.WriteC( mime[ (tx[1]<<4|tx[2 > 1026 if( n>=3 ) > 1027 { > 1028 fp_.WriteC( mime[ (tx[2] > 1029 fp_.WriteC( mime[ tx[2]& > 1030 } > 1031 } > 1032 } > 1033 if( len && *str<=0x7f ) > 1034 fp_.WriteC( '-' ), mode_m = false; > 1035 } > 1036 } > 1037 } > 1038 }; > 1039 > 1040 > 1041 > 1042 #endif > 1043 //------------------------------------------------------------------------- > 1044 // Windows頼りの変換 > 1045 //------------------------------------------------------------------------- > 1046 > 1047 struct wMBCS : public TextFileWPimpl > 1048 { > 1049 wMBCS( FileW& w, int cp ) > 1050 : TextFileWPimpl(w), cp_(cp) > 1051 { > 1052 if( cp == UTF8 ) > 1053 { > 1054 // BOM書き込み > 1055 cp_ = UTF8N; > 1056 fp_.Write( "\xEF\xBB\xBF", 3 ); > 1057 } > 1058 } > 1059 > 1060 void WriteLine( const unicode* str, ulong len ) > 1061 { > 1062 // WideCharToMultiByte API を利用した変換 > 1063 int r; > 1064 while( > 1065 0==(r=::WideCharToMultiByte(cp_,0,str,len,buf_,bsiz_,NUL > 1066 && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER ) > 1067 ReserveMoreBuffer(); > 1068 > 1069 // ファイルへ書き込み > 1070 fp_.Write( buf_, r ); > 1071 } > 1072 > 1073 int cp_; > 1074 }; > 1075 > 1076 > 1077 > 1078 //------------------------------------------------------------------------- > 1079 // ISO-2022 サブセットその1。 > 1080 // ASCIIともう一つしか文字集合を使わないもの > 1081 //------------------------------------------------------------------------- > 1082 > 1083 struct wIso2022 : public TextFileWPimpl > 1084 { > 1085 wIso2022( FileW& w, int cp ) > 1086 : TextFileWPimpl(w), hz_(cp==HZ) > 1087 { > 1088 switch( cp ) > 1089 { > 1090 case IsoKR: > 1091 fp_.Write( "\x1B\x24\x29\x43", 4 ); > 1092 cp_ = UHC; > 1093 break; > 1094 > 1095 case IsoCN: > 1096 fp_.Write( "\x1B\x24\x29\x41", 4 ); > 1097 // fall through... > 1098 default: > 1099 cp_ = GBK; > 1100 break; > 1101 } > 1102 } > 1103 > 1104 void WriteLine( const unicode* str, ulong len ) > 1105 { > 1106 // まず WideCharToMultiByte API を利用して変換 > 1107 int r; > 1108 while( > 1109 0==(r=::WideCharToMultiByte(cp_,0,str,len,buf_,bsiz_,NUL > 1110 && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER ) > 1111 ReserveMoreBuffer(); > 1112 > 1113 bool ascii = true; > 1114 for( int i=0; i<r; ++i ) > 1115 if( buf_[i] & 0x80 ) > 1116 { > 1117 // 非ASCII部分は最上位ビットを落としてから出力 > 1118 if( ascii ) > 1119 { > 1120 if( hz_ ) > 1121 fp_.WriteC( 0x7E ), fp_.WriteC( > 1122 else > 1123 fp_.WriteC( 0x0E ); > 1124 ascii = false; > 1125 } > 1126 fp_.WriteC( buf_[i++] & 0x7F ); > 1127 fp_.WriteC( buf_[i] & 0x7F ); > 1128 } > 1129 else > 1130 { > 1131 // ASCII部分はそのまま出力 > 1132 if( !ascii ) > 1133 { > 1134 if( hz_ ) > 1135 fp_.WriteC( 0x7E ), fp_.WriteC( > 1136 else > 1137 fp_.WriteC( 0x0F ); > 1138 ascii = true; > 1139 } > 1140 fp_.WriteC( buf_[i] ); > 1141 > 1142 // ただしHZの場合、0x7E は 0x7E 0x7E と表す > 1143 if( hz_ && buf_[i]==0x7E ) > 1144 fp_.WriteC( 0x7E ); > 1145 } > 1146 > 1147 // 最後は確実にASCIIに戻す > 1148 if( !ascii ) > 1149 if( hz_ ) > 1150 fp_.WriteC( 0x7E ), fp_.WriteC( 0x7D ); > 1151 else > 1152 fp_.WriteC( 0x0F ); > 1153 } > 1154 > 1155 int cp_; > 1156 bool hz_; > 1157 }; > 1158 > 1159 > 1160 > 1161 > 1162 //------------------------------------------------------------------------- > 1163 // ISO-2022 サブセットその2。日本語EUC > 1164 //------------------------------------------------------------------------- > 1165 > 1166 // Helper: SJIS ==> JIS X 0208 > 1167 static void sjis2jis( uchar s1, uchar s2, char* k ) > 1168 { > 1169 if( ((s1==0xfa || s1==0xfb) && s2>=0x40) || (s1==0xfc && (s2&0xf0)==0x40 > 1170 { > 1171 // IBM外字のマッピング > 1172 static const WORD IBM_sjis2kuten[] = { > 1173 /*fa40*/0x5c51,0x5c52,0x5c53,0x5c54,0x5c55,0x5c56,0x5c57,0x5c58,0x5c59,0x5c5a,0x > 1174 /*fa50*/0x0d1b,0x0d1c,0x0d1d,0x0d1e,0x022c,0x5c5c,0x5c5d,0x5c5e,0x0d4a,0x0d42,0x > 1175 /*fa60*/0x5905,0x5906,0x5907,0x5908,0x5909,0x590a,0x590b,0x590c,0x590d,0x590e,0x > 1176 /*fa70*/0x5915,0x5916,0x5917,0x5918,0x5919,0x591a,0x591b,0x591c,0x591d,0x591e,0x > 1177 /*fa80*/0x5924,0x5925,0x5926,0x5927,0x5928,0x5929,0x592a,0x592b,0x592c,0x592d,0x > 1178 /*fa90*/0x5934,0x5935,0x5936,0x5937,0x5938,0x5939,0x593a,0x593b,0x593c,0x593d,0x > 1179 /*faa0*/0x5944,0x5945,0x5946,0x5947,0x5948,0x5949,0x594a,0x594b,0x594c,0x594d,0x > 1180 /*fab0*/0x5954,0x5955,0x5956,0x5957,0x5958,0x5959,0x595a,0x595b,0x595c,0x595d,0x > 1181 /*fac0*/0x5a06,0x5a07,0x5a08,0x5a09,0x5a0a,0x5a0b,0x5a0c,0x5a0d,0x5a0e,0x5a0f,0x > 1182 /*fad0*/0x5a16,0x5a17,0x5a18,0x5a19,0x5a1a,0x5a1b,0x5a1c,0x5a1d,0x5a1e,0x5a1f,0x > 1183 /*fae0*/0x5a26,0x5a27,0x5a28,0x5a29,0x5a2a,0x5a2b,0x5a2c,0x5a2d,0x5a2e,0x5a2f,0x > 1184 /*faf0*/0x5a36,0x5a37,0x5a38,0x5a39,0x5a3a,0x5a3b,0x5a3c,0x5a3d,0x5a3e,0x5a3f,0x > 1185 /*fb40*/0x5a43,0x5a44,0x5a45,0x5a46,0x5a47,0x5a48,0x5a49,0x5a4a,0x5a4b,0x5a4c,0x > 1186 /*fb50*/0x5a53,0x5a54,0x5a55,0x5a56,0x5a57,0x5a58,0x5a59,0x5a5a,0x5a5b,0x5a5c,0x > 1187 /*fb60*/0x5b05,0x5b06,0x5b07,0x5b08,0x5b09,0x5b0a,0x5b0b,0x5b0c,0x5b0d,0x5b0e,0x > 1188 /*fb70*/0x5b15,0x5b16,0x5b17,0x5b18,0x5b19,0x5b1a,0x5b1b,0x5b1c,0x5b1d,0x5b1e,0x > 1189 /*fb80*/0x5b24,0x5b25,0x5b26,0x5b27,0x5b28,0x5b29,0x5b2a,0x5b2b,0x5b2c,0x5b2d,0x > 1190 /*fb90*/0x5b34,0x5b35,0x5b36,0x5b37,0x5b38,0x5b39,0x5b3a,0x5b3b,0x5b3c,0x5b3d,0x > 1191 /*fba0*/0x5b44,0x5b45,0x5b46,0x5b47,0x5b48,0x5b49,0x5b4a,0x5b4b,0x5b4c,0x5b4d,0x > 1192 /*fbb0*/0x5b54,0x5b55,0x5b56,0x5b57,0x5b58,0x5b59,0x5b5a,0x5b5b,0x5b5c,0x5b5d,0x > 1193 /*fbc0*/0x5c06,0x5c07,0x5c08,0x5c09,0x5c0a,0x5c0b,0x5c0c,0x5c0d,0x5c0e,0x5c0f,0x > 1194 /*fbd0*/0x5c16,0x5c17,0x5c18,0x5c19,0x5c1a,0x5c1b,0x5c1c,0x5c1d,0x5c1e,0x5c1f,0x > 1195 /*fbe0*/0x5c26,0x5c27,0x5c28,0x5c29,0x5c2a,0x5c2b,0x5c2c,0x5c2d,0x5c2e,0x5c2f,0x > 1196 /*fbf0*/0x5c36,0x5c37,0x5c38,0x5c39,0x5c3a,0x5c3b,0x5c3c,0x5c3d,0x5c3e,0x5c3f,0x > 1197 /*fc40*/0x5c43,0x5c44,0x5c45,0x5c46,0x5c47,0x5c48,0x5c49,0x5c4a,0x5c4b,0x5c4c,0x > 1198 }; > 1199 k[0] = IBM_sjis2kuten[ (s1-0xfa)*12*16 + (s2-0x40) ]>>8; > 1200 k[1] = IBM_sjis2kuten[ (s1-0xfa)*12*16 + (s2-0x40) ]&0xff; > 1201 } > 1202 else > 1203 { > 1204 // その他 > 1205 if( s2>=0x9f ) > 1206 { > 1207 if( s1>=0xe0 ) k[0] = ((s1-0xc0)<<1); > 1208 else k[0] = ((s1-0x80)<<1); > 1209 k[1] = s2-0x9e; > 1210 } > 1211 else > 1212 { > 1213 if( s1>=0xe0 ) k[0] = ((s1-0xc0)<<1)-1; > 1214 else k[0] = ((s1-0x80)<<1)-1; > 1215 > 1216 if( s2 & 0x80 ) k[1] = s2-0x40; > 1217 else k[1] = s2-0x3f; > 1218 } > 1219 } > 1220 > 1221 k[0] += 0x20; > 1222 k[1] += 0x20; > 1223 } > 1224 > 1225 struct wEucJp : public TextFileWPimpl > 1226 { > 1227 wEucJp( FileW& w ) > 1228 : TextFileWPimpl(w) {} > 1229 > 1230 void WriteLine( const unicode* str, ulong len ) > 1231 { > 1232 // まず WideCharToMultiByte API を利用して変換 > 1233 int r; > 1234 while( > 1235 0==(r=::WideCharToMultiByte(932,0,str,len,buf_,bsiz_,NUL > 1236 && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER ) > 1237 ReserveMoreBuffer(); > 1238 > 1239 for( int i=0; i<r; ++i ) > 1240 if( buf_[i] & 0x80 ) > 1241 { > 1242 if( 0xA1<=(uchar)buf_[i] && (uchar)buf_[i]<=0xDF > 1243 { > 1244 // カナ > 1245 fp_.WriteC( 0x8E ); > 1246 fp_.WriteC( buf_[i] ); > 1247 } > 1248 else > 1249 { > 1250 // JIS X 0208 > 1251 sjis2jis( buf_[i], buf_[i+1], buf_+i ); > 1252 fp_.WriteC( buf_[i++] | 0x80 ); > 1253 fp_.WriteC( buf_[i] | 0x80 ); > 1254 } > 1255 } > 1256 else > 1257 { > 1258 // ASCII部分はそのまま出力 > 1259 fp_.WriteC( buf_[i] ); > 1260 } > 1261 } > 1262 }; > 1263 > 1264 > 1265 > 1266 //------------------------------------------------------------------------- > 1267 // ISO-2022 サブセットその3。ISO-2022-JP > 1268 //------------------------------------------------------------------------- > 1269 > 1270 struct wIsoJp : public TextFileWPimpl > 1271 { > 1272 wIsoJp( FileW& w ) > 1273 : TextFileWPimpl(w) > 1274 { > 1275 fp_.Write( "\x1b\x28\x42", 3 ); > 1276 } > 1277 > 1278 void WriteLine( const unicode* str, ulong len ) > 1279 { > 1280 // まず WideCharToMultiByte API を利用して変換 > 1281 int r; > 1282 while( > 1283 0==(r=::WideCharToMultiByte(932,0,str,len,buf_,bsiz_,NUL > 1284 && ::GetLastError()==ERROR_INSUFFICIENT_BUFFER ) > 1285 ReserveMoreBuffer(); > 1286 > 1287 enum { ROMA, KANJI, KANA } state = ROMA; > 1288 for( int i=0; i<r; ++i ) > 1289 if( buf_[i] & 0x80 ) > 1290 { > 1291 if( 0xA1<=(uchar)buf_[i] && (uchar)buf_[i]<=0xDF > 1292 { > 1293 // カナ > 1294 if( state != KANA ) > 1295 fp_.Write( "\x1b\x28\x49", 3 ), > 1296 fp_.WriteC( buf_[i] & 0x7f ); > 1297 } > 1298 else > 1299 { > 1300 // JIS X 0208 > 1301 if( state != KANJI ) > 1302 fp_.Write( "\x1b\x24\x42", 3 ), > 1303 sjis2jis( buf_[i], buf_[i+1], buf_+i ); > 1304 fp_.WriteC( buf_[i++] ); > 1305 fp_.WriteC( buf_[i] ); > 1306 } > 1307 } > 1308 else > 1309 { > 1310 // ASCII部分はそのまま出力 > 1311 if( state != ROMA ) > 1312 fp_.Write( "\x1b\x28\x42", 3 ), state = > 1313 fp_.WriteC( buf_[i] ); > 1314 } > 1315 > 1316 if( state != ROMA ) > 1317 fp_.Write( "\x1b\x28\x42", 3 ), state = ROMA; > 1318 } > 1319 }; > 1320 > 1321 > 1322 > 1323 > 1324 //------------------------------------------------------------------------- > 1325 // 書き込みルーチンの準備等々 > 1326 //------------------------------------------------------------------------- > 1327 > 1328 TextFileW::TextFileW( int charset, int linebreak ) > 1329 : cs_( charset ), lb_(linebreak) > 1330 { > 1331 } > 1332 > 1333 TextFileW::~TextFileW() > 1334 { > 1335 Close(); > 1336 } > 1337 > 1338 void TextFileW::Close() > 1339 { > 1340 impl_ = NULL; > 1341 fp_.Close(); > 1342 } > 1343 > 1344 void TextFileW::WriteLine( const unicode* buf, ulong siz, bool lastline ) > 1345 { > 1346 impl_->WriteLine( buf, siz ); > 1347 if( !lastline ) > 1348 { > 1349 static const ulong lbLst[] = {0x0D, 0x0A, 0x000A000D}; > 1350 static const ulong lbLen[] = { 1, 1, 2}; > 1351 impl_->WriteLB( > 1352 reinterpret_cast<const unicode*>(&lbLst[lb_]), lbLen[lb_ > 1353 } > 1354 } > 1355 > 1356 bool TextFileW::Open( const TCHAR* fname ) > 1357 { > 1358 if( !fp_.Open( fname, true ) ) > 1359 return false; > 1360 > 1361 switch( cs_ ) > 1362 { > 1363 case Western: impl_ = new wWest( fp_ ); break; > 1364 case UTF5: impl_ = new wUtf5( fp_ ); break; > 1365 case UTF16l: > 1366 case UTF16LE: impl_ = new wUtf16LE( fp_, cs_==UTF16l ); break; > 1367 case UTF16b: > 1368 case UTF16BE: impl_ = new wUtf16BE( fp_, cs_==UTF16b ); break; > 1369 case UTF32l: > 1370 case UTF32LE: impl_ = new wUtf32LE( fp_, cs_==UTF32l ); break; > 1371 case UTF32b: > 1372 case UTF32BE: impl_ = new wUtf32BE( fp_, cs_==UTF32b ); break; > 1373 case EucJP: impl_ = new wEucJp( fp_ ); break; > 1374 case IsoJP: impl_ = new wIsoJp( fp_ ); break; > 1375 case IsoKR: impl_ = new wIso2022( fp_, cs_ ); break; > 1376 case IsoCN: impl_ = new wIso2022( fp_, cs_ ); break; > 1377 case HZ: impl_ = new wIso2022( fp_, cs_ ); break; > 1378 case UTF8: > 1379 case UTF8N: > 1380 default: > 1381 #ifndef _UNICODE > 1382 if( app().isWin95() && (cs_==UTF8 || cs_==UTF8N) ) > 1383 impl_ = new wUTF8( fp_, cs_ ); > 1384 else if( app().isWin95() && cs_==UTF7 ) > 1385 impl_ = new wUTF7( fp_ ); > 1386 else > 1387 #endif > 1388 impl_ = new wMBCS( fp_, cs_ ); > 1389 break; > 1390 } > 1391 return true; > 1392 }

Added kilib/textfile.h version [64224a920accbcb6]

> 1 #ifndef _KILIB_TEXTFILE_H_ > 2 #define _KILIB_TEXTFILE_H_ > 3 #include "types.h" > 4 #include "ktlaptr.h" > 5 #include "memory.h" > 6 #include "file.h" > 7 #ifndef __ccdoc__ > 8 namespace ki { > 9 #endif > 10 > 11 > 12 > 13 //========================================================================= > 14 //@{ @pkg ki.StdLib //@} > 15 //@{ > 16 // 利用可能コードセット > 17 // > 18 // ただし、ここでリストアップされたもののうち、Windowsにちゃんと > 19 // 言語サポートがインストールされているものだけが実際には対応可能。 > 20 // 値が-100より小さいコードは、そのすぐ上にあるコードページの言語 > 21 // サポートを利用して変換を行うため、それに依存する。 > 22 //@} > 23 //========================================================================= > 24 > 25 enum charset { > 26 AutoDetect = 0, // 自動判定 > 27 // SJIS/EucJP/IsoJP/IsoKR/IsoCN > 28 // UTF5/UTF8/UTF8N/UTF16b/UTF16l/UTF3 > 29 // を判定する。他は知らない。(^^; > 30 > 31 Western = 1252, // 欧米 (Windows1252 >> ISO-8859-1) > 32 Turkish = 1254, // トルコ語 (Windows1254 >> ISO-8859-9) > 33 Hebrew = 1255, // ヘブライ語(Windows1255 >> ISO-8859-8) > 34 Arabic = 1256, // アラビア語(Windows1256 〜 ISO-8859-6) > 35 Baltic = 1257, // バルト語 (Windows1257 >> ISO-8859-13) > 36 Vietnamese = 1258, // ベトナム語(Windows1258 != VISCII) > 37 Central = 1250, // 中央ヨーロッパ(Windows1250 〜 ISO-8859-2) > 38 Greek = 1253, // ギリシャ語(Windows1253 〜 ISO-8859-7) > 39 Thai = 874, // タイ語 > 40 > 41 Cyrillic = 1251, // キリル語(Windows1251 != ISO-8859-5) > 42 Koi8R = 20866,// キリル語(KOI8-R) > 43 Koi8U = 21866,// キリル語(KOI8-U ウクライナ系) > 44 > 45 UHC = 949, // 韓国語1 (Unified Hangle Code >> EUC-KR) > 46 IsoKR = -950, // 韓国語2 (ISO-2022-KR) > 47 Johab = 1361, // 韓国語3 (Johab) > 48 > 49 GBK = 936, // 中国語1 (簡体字 GBK >> EUC-CN) > 50 IsoCN = -936, // 中国語2 (簡体字 ISO-2022-CN) > 51 HZ = -937, // 中国語3 (簡体字 HZ-GB2312) > 52 Big5 = 950, // 中国語4 (繁体字 Big5) > 53 > 54 SJIS = 932, // 日本語1 (Shift_JIS) > 55 EucJP = -932, // 日本語2 (日本語EUC) > 56 IsoJP = -933, // 日本語3 (ISO-2022-JP) > 57 > 58 UTF5 = -2, // Unicode (UTF-5) : BOM無し > 59 UTF7 = 65000,// Unicode (UTF-7) : BOM無し > 60 UTF8 =-65001,// Unicode (UTF-8) : BOM有り > 61 UTF8N = 65001,// Unicode (UTF-8N) : BOM無し > 62 UTF16b = -3, // Unicode (UTF-16) : BOM有り BE > 63 UTF16l = -4, // Unicode (UTF-16) : BOM有り LE > 64 UTF16BE = -5, // Unicode (UTF-16BE): BOM無し > 65 UTF16LE = -6, // Unicode (UTF-16LE): BOM無し > 66 UTF32b = -7, // Unicode (UTF-32) : BOM有り BE > 67 UTF32l = -8, // Unicode (UTF-32) : BOM有り LE > 68 UTF32BE = -9, // Unicode (UTF-32BE): BOM無し > 69 UTF32LE = -10, // Unicode (UTF-32LE): BOM無し > 70 > 71 DOSUS = 437 // DOSLatinUS (CP437) > 72 }; > 73 > 74 //========================================================================= > 75 //@{ > 76 // 改行コード > 77 //@} > 78 //========================================================================= > 79 > 80 enum lbcode { > 81 CR = 0, > 82 LF = 1, > 83 CRLF = 2 > 84 }; > 85 > 86 struct TextFileRPimpl; > 87 struct TextFileWPimpl; > 88 > 89 > 90 > 91 //========================================================================= > 92 //@{ > 93 // テキストファイル読込 > 94 // > 95 // ファイルを指定された文字コードで解釈し、Unicode文字列として > 96 // 一行毎に返す。文字コードや改行コードの自動判定も可能。 > 97 //@} > 98 //========================================================================= > 99 > 100 class TextFileR : public Object > 101 { > 102 public: > 103 > 104 //@{ コンストラクタ(コード指定)//@} > 105 TextFileR( int charset=AutoDetect ); > 106 > 107 //@{ デストラクタ //@} > 108 ~TextFileR(); > 109 > 110 //@{ 開く //@} > 111 bool Open( const TCHAR* fname ); > 112 > 113 //@{ 閉じる //@} > 114 void Close(); > 115 > 116 //@{ > 117 // 読み込み (読んだ長さを返す) > 118 // > 119 // 少なくとも20くらいのサイズを確保したバッファを指定してください。 > 120 //@} > 121 size_t ReadLine( unicode* buf, ulong siz ); > 122 > 123 public: > 124 > 125 //@{ 読んでるファイルのコードページ //@} > 126 int codepage() const; > 127 > 128 //@{ 改行コード (0:CR, 1:LF, 2:CRLF) //@} > 129 int linebreak() const; > 130 > 131 //@{ 読み込み状況 (0:EOF, 1:EOL, 2:EOB) //@} > 132 int state() const; > 133 > 134 //@{ ファイルサイズ //@} > 135 ulong size() const; > 136 > 137 //@{ 改行が一個も見つからなかったフラグ //@} > 138 bool nolb_found() const; > 139 private: > 140 > 141 dptr<TextFileRPimpl> impl_; > 142 FileR fp_; > 143 int cs_; > 144 int lb_; > 145 bool nolbFound_; > 146 > 147 private: > 148 > 149 int AutoDetection( int cs, const uchar* ptr, ulong siz ); > 150 > 151 private: > 152 > 153 NOCOPY(TextFileR); > 154 }; > 155 > 156 > 157 > 158 //------------------------------------------------------------------------- > 159 > 160 inline int TextFileR::codepage() const > 161 { return cs_; } > 162 > 163 inline int TextFileR::linebreak() const > 164 { return lb_; } > 165 > 166 inline ulong TextFileR::size() const > 167 { return fp_.size(); } > 168 > 169 inline bool TextFileR::nolb_found() const > 170 { return nolbFound_; } > 171 > 172 > 173 //========================================================================= > 174 //@{ > 175 // テキストファイル書込 > 176 // > 177 // Unicode文字列を受け取り、指定された文字コードに変換しながら出力する。 > 178 //@} > 179 //========================================================================= > 180 > 181 class TextFileW : public Object > 182 { > 183 public: > 184 > 185 //@{ コンストラクタ(文字,改行コード指定)//@} > 186 TextFileW( int charset, int linebreak ); > 187 ~TextFileW(); > 188 > 189 //@{ 開く //@} > 190 bool Open( const TCHAR* fname ); > 191 > 192 //@{ 閉じる //@} > 193 void Close(); > 194 > 195 //@{ 一行書き出し //@} > 196 void WriteLine( const unicode* buf, ulong siz, bool lastline ); > 197 > 198 private: > 199 > 200 dptr<TextFileWPimpl> impl_; > 201 FileW fp_; > 202 const int cs_; > 203 const int lb_; > 204 > 205 private: > 206 > 207 NOCOPY(TextFileW); > 208 }; > 209 > 210 > 211 > 212 //========================================================================= > 213 > 214 } // namespace ki > 215 #endif // _KILIB_TEXTFILE_H_

Added kilib/thread.cpp version [1216ad374a35c8fc]

> 1 #include "stdafx.h" > 2 #include "thread.h" > 3 using namespace ki; > 4 > 5 > 6 > 7 //========================================================================= > 8 > 9 ThreadManager* ThreadManager::pUniqueInstance_; > 10 > 11 ThreadManager::ThreadManager() > 12 : threadNum_(0) > 13 { > 14 // 唯一のインスタンスは私です。 > 15 pUniqueInstance_ = this; > 16 } > 17 > 18 //========================================================================= > 19 > 20 DWORD WINAPI ThreadManager::ThreadStubFunc(void* param) > 21 { > 22 Runnable* r = static_cast<Runnable*>(param); > 23 r->StartThread(); > 24 r->FinalizeThread(); > 25 return 0; > 26 } > 27 > 28 void ThreadManager::Run( Runnable& r ) > 29 { > 30 r.PleaseExit(); > 31 > 32 DWORD id; > 33 r.hThread_ = ::CreateThread( > 34 NULL, 0, &ThreadStubFunc, &r, CREATE_SUSPENDED, &id ); > 35 r.hEvent_ = ::CreateEvent( NULL, TRUE, FALSE, NULL ); > 36 ::ResumeThread( r.hThread_ ); > 37 } > 38 > 39 //========================================================================= > 40 > 41 Runnable::Runnable() > 42 : hThread_( NULL ) > 43 , hEvent_ ( NULL ) > 44 { > 45 } > 46 > 47 Runnable::~Runnable() > 48 { > 49 PleaseExit(); // あくまで最終手段 > 50 } > 51 > 52 bool Runnable::isRunning() const > 53 { > 54 return hThread_ != NULL; > 55 } > 56 > 57 bool Runnable::isExitRequested() const > 58 { > 59 return WAIT_OBJECT_0 == ::WaitForSingleObject( hEvent_, 0 ); > 60 } > 61 > 62 void Runnable::FinalizeThread() > 63 { > 64 ::CloseHandle( hThread_ ); > 65 hThread_ = NULL; > 66 ::CloseHandle( hEvent_ ); > 67 hEvent_ = NULL; > 68 } > 69 > 70 void Runnable::PleaseExit() > 71 { > 72 if( HANDLE ht = hThread_ ) > 73 { > 74 ::SetEvent( hEvent_ ); > 75 ::WaitForSingleObject( ht, INFINITE ); > 76 } > 77 }

Added kilib/thread.h version [ad2ee82f907cec8e]

> 1 #ifndef _KILIB_THREAD_H_ > 2 #define _KILIB_THREAD_H_ > 3 #include "types.h" > 4 #ifndef __ccdoc__ > 5 namespace ki { > 6 #endif > 7 > 8 > 9 > 10 //========================================================================= > 11 //@{ @pkg ki.Core //@} > 12 //@{ > 13 // マルチスレッドの管理 > 14 // > 15 // まだ何もしません > 16 //@} > 17 //========================================================================= > 18 > 19 > 20 class ThreadManager > 21 { > 22 public: > 23 //@{ 実行可能オブジェクトをに起動をかける //@} > 24 void Run( class Runnable& r ); > 25 > 26 //@{ 複数スレッドが走っているかどうか? //@} > 27 bool isMT() const; > 28 > 29 private: > 30 > 31 ThreadManager(); > 32 > 33 private: > 34 > 35 int threadNum_; > 36 static ThreadManager* pUniqueInstance_; > 37 > 38 private: > 39 > 40 static DWORD WINAPI ThreadStubFunc(void*); > 41 > 42 private: > 43 > 44 friend void APIENTRY Startup(); > 45 friend inline ThreadManager& thd(); > 46 NOCOPY(ThreadManager); > 47 }; > 48 > 49 > 50 > 51 //------------------------------------------------------------------------- > 52 > 53 //@{ 唯一のスレッド管理オブジェクトを返す //@} > 54 inline ThreadManager& thd() > 55 { return *ThreadManager::pUniqueInstance_; } > 56 > 57 inline bool ThreadManager::isMT() const > 58 { return 0 != threadNum_; } > 59 > 60 > 61 > 62 //========================================================================= > 63 //@{ > 64 // 実行可能オブジェクト基底 > 65 //@} > 66 //========================================================================= > 67 > 68 class Runnable > 69 { > 70 protected: > 71 Runnable(); > 72 virtual ~Runnable(); > 73 > 74 virtual void StartThread() = 0; > 75 void PleaseExit(); > 76 bool isExitRequested() const; > 77 bool isRunning() const; > 78 > 79 private: > 80 void FinalizeThread(); > 81 friend class ThreadManager; > 82 HANDLE hEvent_; > 83 HANDLE hThread_; > 84 }; > 85 > 86 > 87 > 88 //========================================================================= > 89 //@{ > 90 // マルチスレッド・ポリシー1 > 91 // > 92 // このクラスから派生すると、AutoLock クラスを使えるようになります。 > 93 // このクラスに this ポインタを渡すことで排他状態に入り、デストラクタで > 94 // 抜け出せるようになります。NoLockable::AutoLock は実際は何もしません。 > 95 //@} > 96 //========================================================================= > 97 > 98 class NoLockable > 99 { > 100 protected: > 101 struct AutoLock > 102 { > 103 AutoLock( NoLockable* host ) {} > 104 }; > 105 }; > 106 > 107 > 108 > 109 //========================================================================= > 110 //@{ > 111 // マルチスレッド・ポリシー2 > 112 // > 113 // このクラスから派生すると、AutoLock クラスを使えるようになります。 > 114 // このクラスに this ポインタを渡すことで排他状態に入り、デストラクタで > 115 // 抜け出せるようになります。EzLockable::AutoLock は、シングルスレッドで > 116 // 動作するときがほとんどというアプリケーション向けに、高速だけれど > 117 // 不完全な排他制御を行います。2本目のスレッド立ち上げの瞬間が危ない。 > 118 //@} > 119 //========================================================================= > 120 > 121 class EzLockable > 122 { > 123 protected: > 124 EzLockable() > 125 { ::InitializeCriticalSection( &csection_ ); } > 126 ~EzLockable() > 127 { ::DeleteCriticalSection( &csection_ ); } > 128 > 129 struct AutoLock > 130 { > 131 AutoLock( EzLockable* host ) > 132 { > 133 if( NULL != (pCs_=(thd().isMT() ? &host->csection_ : NUL > 134 ::EnterCriticalSection( pCs_ ); > 135 } > 136 ~AutoLock() > 137 { > 138 if( pCs_ ) > 139 ::LeaveCriticalSection( pCs_ ); > 140 } > 141 private: > 142 NOCOPY(AutoLock); > 143 CRITICAL_SECTION* pCs_; > 144 }; > 145 > 146 private: > 147 CRITICAL_SECTION csection_; > 148 #ifdef __DMC__ > 149 friend struct EzLockable::AutoLock; > 150 #else > 151 friend struct AutoLock; > 152 #endif > 153 }; > 154 > 155 > 156 > 157 //========================================================================= > 158 //@{ > 159 // マルチスレッド・ポリシー3 > 160 // > 161 // このクラスから派生すると、AutoLock クラスを使えるようになります。 > 162 // このクラスに this ポインタを渡すことで排他状態に入り、デストラクタで > 163 // 抜け出せるようになります。Lockable::AutoLock は、完全な排他制御を > 164 // 行います。万全を期すならかならずこのクラスを用いましょう。 > 165 //@} > 166 //========================================================================= > 167 > 168 class Lockable > 169 { > 170 protected: > 171 Lockable() > 172 { ::InitializeCriticalSection( &csection_ ); } > 173 ~Lockable() > 174 { ::DeleteCriticalSection( &csection_ ); } > 175 > 176 struct AutoLock > 177 { > 178 AutoLock( Lockable* host ) > 179 { > 180 pCs_ = &host->csection_; > 181 ::EnterCriticalSection( pCs_ ); > 182 } > 183 ~AutoLock() > 184 { > 185 ::LeaveCriticalSection( pCs_ ); > 186 } > 187 private: > 188 NOCOPY(AutoLock); > 189 CRITICAL_SECTION* pCs_; > 190 }; > 191 friend struct AutoLock; > 192 > 193 private: > 194 CRITICAL_SECTION csection_; > 195 }; > 196 > 197 > 198 > 199 //========================================================================= > 200 > 201 } // namespace ki > 202 #endif // _KILIB_THREAD_H_

Added kilib/types.h version [49179567f8607bc7]

> 1 #ifndef _KILIB_TYPES_H_ > 2 #define _KILIB_TYPES_H_ > 3 > 4 > 5 > 6 //========================================================================= > 7 //@{ @pkg ki.Types //@} > 8 //========================================================================= > 9 > 10 // 変数のサイズを明示的に指示するときに使う名前 > 11 typedef unsigned char byte; > 12 typedef unsigned short dbyte; > 13 typedef unsigned long qbyte; > 14 typedef wchar_t unicode; > 15 > 16 // unsigned って毎回打つの面倒 > 17 typedef unsigned char uchar; > 18 typedef unsigned short ushort; > 19 typedef unsigned int uint; > 20 typedef unsigned long ulong; > 21 > 22 // 配列の要素数 > 23 #define countof(_array) (sizeof(_array)/sizeof(_array[0])) > 24 > 25 // 大きい方、小さい方 > 26 template<typename T> inline T Min(T x,T y) { return (x<y ? x : y); } > 27 template<typename T> inline T Max(T x,T y) { return (y<x ? x : y); } > 28 > 29 // 古いC++処理系でも、forで使う変数のスコープを強制的に制限 > 30 #if defined(_MSC_VER) || defined(__DMC__) > 31 #define for if(0);else for > 32 #endif > 33 > 34 // コピー禁止オブジェクト > 35 #define NOCOPY(T) T( const T& ); T& operator=( const T& ) > 36 > 37 > 38 > 39 #endif // _KILIB_TYPES_H_

Added kilib/window.cpp version [db5de2240a19512a]

> 1 #include "stdafx.h" > 2 #include "app.h" > 3 #include "window.h" > 4 using namespace ki; > 5 > 6 > 7 > 8 //========================================================================= > 9 // IMEに関するあれこれ > 10 //========================================================================= > 11 > 12 IMEManager* IMEManager::pUniqueInstance_; > 13 > 14 IMEManager::IMEManager() > 15 #ifdef USEGLOBALIME > 16 : immApp_( NULL ) > 17 , immMsg_( NULL ) > 18 #endif > 19 { > 20 #ifdef USEGLOBALIME > 21 // 色々面倒なのでWin95ではGlobalIME無し > 22 if( !app().isWin95() ) > 23 { > 24 app().InitModule( App::OLE ); > 25 if( S_OK == ::CoCreateInstance( > 26 CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SE > 27 IID_IActiveIMMApp, (void**)&immApp_ ) ) > 28 { > 29 immApp_->QueryInterface( > 30 IID_IActiveIMMMessagePumpOwner, (void**) > 31 } > 32 } > 33 #endif > 34 > 35 // 唯一のインスタンスは私です > 36 pUniqueInstance_ = this; > 37 } > 38 > 39 IMEManager::~IMEManager() > 40 { > 41 #ifdef USEGLOBALIME > 42 if( immMsg_ != NULL ) > 43 immMsg_->Release(); > 44 if( immApp_ != NULL ) > 45 immApp_->Release(); > 46 #endif > 47 } > 48 > 49 void IMEManager::EnableGlobalIME( bool enable ) > 50 { > 51 #ifdef USEGLOBALIME > 52 if( immApp_ ) > 53 if( enable ) immApp_->Activate( TRUE ); > 54 else immApp_->Deactivate(); > 55 #endif > 56 } > 57 > 58 void IMEManager::FilterWindows( ATOM* lst, UINT siz ) > 59 { > 60 #ifdef USEGLOBALIME > 61 if( immApp_ ) > 62 immApp_->FilterClientWindows( lst, siz ); > 63 #endif > 64 } > 65 > 66 inline void IMEManager::TranslateMsg( MSG* msg ) > 67 { > 68 #ifdef USEGLOBALIME > 69 if( immMsg_ ) > 70 if( S_OK == immMsg_->OnTranslateMessage( msg ) ) > 71 return; > 72 #endif > 73 ::TranslateMessage( msg ); > 74 } > 75 > 76 inline LRESULT IMEManager::DefProc( HWND h, UINT m, WPARAM w, LPARAM l ) > 77 { > 78 #ifdef USEGLOBALIME > 79 if( immApp_ ) > 80 { > 81 LRESULT res; > 82 if( S_OK == immApp_->OnDefWindowProc( h,m,w,l,&res ) ) > 83 return res; > 84 } > 85 #endif > 86 return ::DefWindowProc( h, m, w, l ); > 87 } > 88 > 89 inline void IMEManager::MsgLoopBegin() > 90 { > 91 #ifdef USEGLOBALIME > 92 if( immMsg_ ) > 93 immMsg_->Start(); > 94 #endif > 95 } > 96 > 97 inline void IMEManager::MsgLoopEnd() > 98 { > 99 #ifdef USEGLOBALIME > 100 if( immMsg_ ) > 101 immMsg_->End(); > 102 #endif > 103 } > 104 > 105 void IMEManager::SetFont( HWND wnd, const LOGFONT& lf ) > 106 { > 107 HIMC ime; > 108 LOGFONT* plf = const_cast<LOGFONT*>(&lf); > 109 > 110 #ifdef USEGLOBALIME > 111 if( immApp_ ) > 112 { > 113 immApp_->GetContext( wnd, &ime ); > 114 #ifdef _UNICODE > 115 immApp_->SetCompositionFontW( ime, plf ); > 116 #else > 117 immApp_->SetCompositionFontA( ime, plf ); > 118 #endif > 119 immApp_->ReleaseContext( wnd, ime ); > 120 } > 121 else > 122 #endif > 123 { > 124 ime = ::ImmGetContext( wnd ); > 125 ::ImmSetCompositionFont( ime, plf ); > 126 ::ImmReleaseContext( wnd, ime ); > 127 } > 128 } > 129 > 130 void IMEManager::SetPos( HWND wnd, int x, int y ) > 131 { > 132 HIMC ime; > 133 COMPOSITIONFORM cf; > 134 cf.dwStyle = CFS_POINT; > 135 cf.ptCurrentPos.x = x; > 136 cf.ptCurrentPos.y = y; > 137 > 138 #ifdef USEGLOBALIME > 139 if( immApp_ ) > 140 { > 141 immApp_->GetContext( wnd, &ime ); > 142 immApp_->SetCompositionWindow( ime, &cf ); > 143 immApp_->ReleaseContext( wnd, ime ); > 144 } > 145 else > 146 #endif > 147 { > 148 ime = ::ImmGetContext( wnd ); > 149 ::ImmSetCompositionWindow( ime, &cf ); > 150 ::ImmReleaseContext( wnd, ime ); > 151 } > 152 } > 153 > 154 void IMEManager::GetString( HWND wnd, unicode** str, ulong* len ) > 155 { > 156 *str = NULL; > 157 HIMC ime; > 158 > 159 #ifdef USEGLOBALIME > 160 if( immApp_ ) > 161 { > 162 long s=0; > 163 immApp_->GetContext( wnd, &ime ); > 164 immApp_->GetCompositionStringW( ime, GCS_RESULTSTR, 0, &s, NULL > 165 *str = new unicode[ (*len=s/2)+1 ]; > 166 immApp_->GetCompositionStringW( ime, GCS_RESULTSTR, s, &s, *str > 167 immApp_->ReleaseContext( wnd, ime ); > 168 } > 169 else > 170 #endif > 171 { > 172 ime = ::ImmGetContext( wnd ); > 173 long s = ::ImmGetCompositionStringW( ime,GCS_RESULTSTR,NULL,0 ); > 174 > 175 #ifndef _UNICODE > 176 if( s <= 0 ) > 177 { > 178 s = ::ImmGetCompositionStringA(ime,GCS_RESULTSTR > 179 if( s > 0 ) > 180 { > 181 char* tmp = new char[s]; > 182 *str = new unicode[*len=s*2]; > 183 ::ImmGetCompositionStringA( ime,GCS_RESU > 184 *len = ::MultiByteToWideChar( > 185 CP_ACP, MB_PRECOMPOSED, tmp, s, > 186 delete [] tmp; > 187 } > 188 } > 189 else > 190 #endif > 191 { > 192 *str = new unicode[ (*len=s/2)+1 ]; > 193 ::ImmGetCompositionStringW( ime, GCS_RESULTSTR, > 194 } > 195 > 196 ::ImmReleaseContext( wnd, ime ); > 197 } > 198 } > 199 > 200 > 201 > 202 //========================================================================= > 203 // Windowに関するあれこれ > 204 //========================================================================= > 205 > 206 Window::Window() > 207 : wnd_ (NULL) > 208 , isLooping_(false) > 209 { > 210 } > 211 > 212 void Window::SetHwnd( HWND wnd ) > 213 { > 214 wnd_ = wnd; > 215 } > 216 > 217 void Window::MsgLoop() > 218 { > 219 // thisをメインウインドウとして、 > 220 // メインメッセージループを回す > 221 isLooping_ = true; > 222 ime().MsgLoopBegin(); > 223 > 224 for( MSG msg; ::GetMessage( &msg, NULL, 0, 0 ); ) > 225 if( !PreTranslateMessage( &msg ) ) > 226 { > 227 ime().TranslateMsg( &msg ); > 228 ::DispatchMessage( &msg ); > 229 } > 230 > 231 ime().MsgLoopEnd(); > 232 isLooping_ = false; > 233 } > 234 > 235 void Window::ProcessMsg() > 236 { > 237 // こっちはグローバル関数。 > 238 // 未処理メッセージを一掃 > 239 > 240 ime().MsgLoopBegin(); > 241 for( MSG msg; ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ); ) > 242 { > 243 ime().TranslateMsg( &msg ); > 244 ::DispatchMessage( &msg ); > 245 } > 246 ime().MsgLoopEnd(); > 247 } > 248 > 249 > 250 > 251 //------------------------------------------------------------------------- > 252 > 253 void Window::SetCenter( HWND hwnd, HWND rel ) > 254 { > 255 // 自分のサイズを取得 > 256 RECT rc,pr; > 257 ::GetWindowRect( hwnd, &rc ); > 258 > 259 // 親の位置、ないしは全画面の位置を取得 > 260 if( rel != NULL ) > 261 ::GetWindowRect( rel, &pr ); > 262 else > 263 ::SystemParametersInfo( SPI_GETWORKAREA, 0, &pr, 0 ); > 264 > 265 // 中央を計算 > 266 ::SetWindowPos( hwnd, 0, > 267 pr.left + ( (pr.right-pr.left)-(rc.right-rc.left) )/2, > 268 pr.top + ( (pr.bottom-pr.top)-(rc.bottom-rc.top) )/2, > 269 0, 0, SWP_NOSIZE|SWP_NOZORDER ); > 270 } > 271 > 272 void Window::SetFront( HWND hwnd ) > 273 { > 274 // kazubon氏の TClock のソースを参考にしました。感謝! > 275 > 276 if( app().isNewTypeWindows() ) > 277 { > 278 DWORD pid; > 279 HWND fore= ::GetForegroundWindow(); > 280 DWORD th1 = ::GetWindowThreadProcessId( fore, &pid ); > 281 DWORD th2 = ::GetCurrentThreadId(); > 282 ::AttachThreadInput( th2, th1, TRUE ); > 283 ::SetForegroundWindow( hwnd ); > 284 ::AttachThreadInput( th2, th1, FALSE ); > 285 ::BringWindowToTop( hwnd ); > 286 } > 287 else > 288 { > 289 ::SetForegroundWindow( hwnd ); > 290 } > 291 } > 292 > 293 //========================================================================= > 294 > 295 WndImpl::WndImpl( LPCTSTR className, DWORD style, DWORD styleEx ) > 296 : className_( className ) > 297 , style_ ( style ) > 298 , styleEx_ ( styleEx ) > 299 , thunk_ ( static_cast<byte*>( > 300 ::VirtualAlloc( NULL, THUNK_SIZE, MEM_COMMIT, PAGE_EXECU > 301 { > 302 } > 303 > 304 WndImpl::~WndImpl() > 305 { > 306 // ウインドウを破棄し忘れてたら閉じる > 307 // …が、この時点で既に vtable は破棄されかかっているので > 308 // 正しい on_destroy が呼ばれる保証は全くない。あくまで > 309 // 緊急脱出用(^^; と考えること。 > 310 Destroy(); > 311 ::VirtualFree( thunk_, 0, MEM_RELEASE ); > 312 } > 313 > 314 void WndImpl::Destroy() > 315 { > 316 if( hwnd() != NULL ) > 317 ::DestroyWindow( hwnd() ); > 318 } > 319 > 320 ATOM WndImpl::Register( WNDCLASSEX* cls ) > 321 { > 322 // WndImpl派生クラスで使うWndClassを登録。 > 323 // プロシージャはkilib謹製のものに書き換えちゃいます。 > 324 cls->cbSize = sizeof(WNDCLASSEX); > 325 cls->hInstance = app().hinst(); > 326 cls->lpfnWndProc = StartProc; > 327 return ::RegisterClassEx( cls ); > 328 } > 329 > 330 struct ThisAndParam > 331 { > 332 // ユーザ指定のパラメータ以外にも渡したいモノが少々… > 333 WndImpl* pThis; > 334 void* pParam; > 335 }; > 336 > 337 bool WndImpl::Create( > 338 LPCTSTR wndName, HWND parent, int x, int y, int w, int h, void* param ) > 339 { > 340 // ここでthisポインタを忍び込ませておく > 341 ThisAndParam z = { this, param }; > 342 > 343 LOGGER("WndImpl::Create before CreateWindowEx API call"); > 344 > 345 return (NULL != ::CreateWindowEx( > 346 styleEx_, className_, wndName, style_, > 347 x, y, w, h, parent, NULL, app().hinst(), &z > 348 )); > 349 } > 350 > 351 > 352 > 353 //------------------------------------------------------------------------- > 354 > 355 LRESULT CALLBACK WndImpl::StartProc( > 356 HWND wnd, UINT msg, WPARAM wp, LPARAM lp ) > 357 { > 358 // WM_CREATE以外はスルーの方針で > 359 if( msg != WM_CREATE ) > 360 return ::DefWindowProc( wnd, msg, wp, lp ); > 361 > 362 LOGGER("WndImpl::StartProc WM_CREATE kitaaaaa!!"); > 363 > 364 // 忍ばせて置いたthisポインタを取り出し > 365 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lp); > 366 ThisAndParam* pz = static_cast<ThisAndParam*>(cs->lpCreateParams); > 367 WndImpl* pThis = pz->pThis; > 368 cs->lpCreateParams = pz->pParam; > 369 > 370 // サンク > 371 pThis->SetUpThunk( wnd ); > 372 > 373 // WM_CREATE用メッセージを呼ぶ > 374 pThis->on_create( cs ); > 375 return 0; > 376 } > 377 > 378 void WndImpl::SetUpThunk( HWND wnd ) > 379 { > 380 SetHwnd( wnd ); > 381 > 382 // ここで動的にx86の命令列 > 383 // | mov dword ptr [esp+4] this > 384 // | jmp MainProc > 385 // あるいはAMD64の命令列 > 386 // | mov rcx this > 387 // | mov rax MainProc > 388 // | jmp rax > 389 // を生成し、メッセージプロシージャとして差し替える。 > 390 // > 391 // これで次回からは、第一引数が hwnd のかわりに > 392 // thisポインタになった状態でMainProcが呼ばれる > 393 // …と見なしたプログラムが書ける。 > 394 // > 395 // 参考資料:ATLのソース > 396 > 397 #ifdef _M_AMD64 > 398 *reinterpret_cast<dbyte*> (thunk_+ 0) = 0xb948; > 399 *reinterpret_cast<WndImpl**>(thunk_+ 2) = this; > 400 *reinterpret_cast<dbyte*> (thunk_+10) = 0xb848; > 401 *reinterpret_cast<void**> (thunk_+12) = MainProc; > 402 *reinterpret_cast<dbyte*> (thunk_+20) = 0xe0ff; > 403 #else > 404 *reinterpret_cast<qbyte*> (thunk_+0) = 0x042444C7; > 405 *reinterpret_cast<WndImpl**>(thunk_+4) = this; > 406 *reinterpret_cast< byte*> (thunk_+8) = 0xE9; > 407 *reinterpret_cast<qbyte*> (thunk_+9) = > 408 reinterpret_cast<byte*>((void*)MainProc)-(thunk_+13); > 409 #endif > 410 > 411 ::FlushInstructionCache( ::GetCurrentProcess(), thunk_, THUNK_SIZE ); > 412 ::SetWindowLongPtr( wnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&thunk > 413 } > 414 > 415 LRESULT CALLBACK WndImpl::MainProc( > 416 WndImpl* ptr, UINT msg, WPARAM wp, LPARAM lp ) > 417 { > 418 if( msg == WM_COMMAND ) > 419 { > 420 if( !ptr->on_command( LOWORD(wp), (HWND)lp ) ) > 421 return ::DefWindowProc( ptr->hwnd(), msg, wp, lp ); > 422 } > 423 else if( msg == WM_DESTROY ) > 424 { > 425 ptr->on_destroy(); > 426 ::SetWindowLongPtr( ptr->hwnd(), GWLP_WNDPROC, > 427 reinterpret_cast<LONG_PTR>(StartProc) ); > 428 if( ptr->isMainWnd() ) > 429 ::PostQuitMessage( 0 ); > 430 ptr->SetHwnd(NULL); > 431 } > 432 else > 433 { > 434 return ptr->on_message( msg, wp, lp ); > 435 } > 436 > 437 return 0; > 438 } > 439 > 440 > 441 > 442 //------------------------------------------------------------------------- > 443 > 444 void WndImpl::on_create( CREATESTRUCT* cs ) > 445 { > 446 // 何もしない > 447 } > 448 > 449 void WndImpl::on_destroy() > 450 { > 451 // 何もしない > 452 } > 453 > 454 bool WndImpl::on_command( UINT, HWND ) > 455 { > 456 // 何もしない > 457 return false; > 458 } > 459 > 460 LRESULT WndImpl::on_message( UINT msg, WPARAM wp, LPARAM lp ) > 461 { > 462 // 何もしない > 463 return ime().DefProc( hwnd(), msg, wp, lp ); > 464 } > 465 > 466 bool WndImpl::PreTranslateMessage( MSG* ) > 467 { > 468 // 何もしない > 469 return false; > 470 } > 471 > 472 > 473 > 474 //========================================================================= > 475 > 476 DlgImpl::DlgImpl( UINT id ) > 477 : rsrcID_( id ) > 478 { > 479 } > 480 > 481 DlgImpl::~DlgImpl() > 482 { > 483 // ウインドウを破棄し忘れてたら閉じる > 484 if( hwnd() != NULL ) > 485 End( IDCANCEL ); > 486 } > 487 > 488 void DlgImpl::End( UINT code ) > 489 { > 490 endCode_ = code; > 491 > 492 if( type() == MODAL ) > 493 ::EndDialog( hwnd(), code ); > 494 else > 495 ::DestroyWindow( hwnd() ); > 496 } > 497 > 498 void DlgImpl::GoModal( HWND parent ) > 499 { > 500 type_ = MODAL; > 501 ::DialogBoxParam( app().hinst(), MAKEINTRESOURCE(rsrcID_), parent, > 502 (DLGPROC)MainProc, reinterpret_cast<LPARAM>(this) ); > 503 } > 504 > 505 void DlgImpl::GoModeless( HWND parent ) > 506 { > 507 type_ = MODELESS; > 508 ::CreateDialogParam( app().hinst(), MAKEINTRESOURCE(rsrcID_), parent, > 509 (DLGPROC)MainProc, reinterpret_cast<LPARAM>(this) ); > 510 } > 511 > 512 > 513 > 514 //------------------------------------------------------------------------- > 515 > 516 BOOL CALLBACK DlgImpl::MainProc( > 517 HWND dlg, UINT msg, WPARAM wp, LPARAM lp ) > 518 { > 519 if( msg == WM_INITDIALOG ) > 520 { > 521 ::SetWindowLongPtr( dlg, GWLP_USERDATA, lp ); > 522 > 523 DlgImpl* ptr = reinterpret_cast<DlgImpl*>(lp); > 524 ptr->SetHwnd( dlg ); > 525 ptr->on_init(); > 526 return FALSE; > 527 } > 528 > 529 DlgImpl* ptr = > 530 reinterpret_cast<DlgImpl*>(::GetWindowLongPtr(dlg,GWLP_USERDATA) > 531 > 532 if( ptr != NULL ) > 533 switch( msg ) > 534 { > 535 case WM_COMMAND: > 536 switch( LOWORD(wp) ) > 537 { > 538 case IDOK: > 539 if( ptr->on_ok() ) > 540 ptr->End( IDOK ); > 541 return TRUE; > 542 > 543 case IDCANCEL: > 544 if( ptr->on_cancel() ) > 545 ptr->End( IDCANCEL ); > 546 return TRUE; > 547 > 548 default: > 549 return ptr->on_command( HIWORD(wp), LOWORD(wp), > 550 reinterpret_cast<HWND>(lp) ) ? TRUE : FA > 551 } > 552 > 553 case WM_DESTROY: > 554 ptr->on_destroy(); > 555 if( ptr->isMainWnd() ) > 556 ::PostQuitMessage( 0 ); > 557 ptr->SetHwnd(NULL); > 558 break; > 559 > 560 default: > 561 return ptr->on_message( msg, wp, lp ) ? TRUE : FALSE; > 562 } > 563 > 564 return FALSE; > 565 } > 566 > 567 > 568 > 569 //------------------------------------------------------------------------- > 570 > 571 void DlgImpl::on_init() > 572 { > 573 // 何もしない > 574 } > 575 > 576 void DlgImpl::on_destroy() > 577 { > 578 // 何もしない > 579 } > 580 > 581 bool DlgImpl::on_ok() > 582 { > 583 // 何もしない > 584 return true; > 585 } > 586 > 587 bool DlgImpl::on_cancel() > 588 { > 589 // 何もしない > 590 return true; > 591 } > 592 > 593 bool DlgImpl::on_command( UINT, UINT, HWND ) > 594 { > 595 // 何もしない > 596 return false; > 597 } > 598 > 599 bool DlgImpl::on_message( UINT, WPARAM, LPARAM ) > 600 { > 601 // 何もしない > 602 return false; > 603 } > 604 > 605 bool DlgImpl::PreTranslateMessage( MSG* msg ) > 606 { > 607 // モードレスの時用。ダイアログメッセージ処理。 > 608 return (FALSE != ::IsDialogMessage( hwnd(), msg )); > 609 }

Added kilib/window.h version [c9c601b3ae11f0e7]

> 1 #ifndef _KILIB_WINDOW_H_ > 2 #define _KILIB_WINDOW_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #include "ktlaptr.h" > 6 #ifndef __ccdoc__ > 7 namespace ki { > 8 #endif > 9 > 10 > 11 > 12 // タイムアウト付きMsgBoxの返値 > 13 #define IDTIMEOUT 0 > 14 > 15 > 16 > 17 //========================================================================= > 18 //@{ @pkg ki.Window //@} > 19 //@{ > 20 // 窓操作用クラス > 21 // > 22 // 外側から、ダイアログやコントロールやプロパティシートや > 23 // 普通のウインドウを全部まとめて共通に扱うためのインターフェイス。 > 24 // 実際の実装は、下位クラス XxxImpl で行われている。 > 25 //@} > 26 //========================================================================= > 27 > 28 class Window : public Object > 29 { > 30 public: > 31 > 32 //@{ メインメッセージループ //@} > 33 void MsgLoop(); > 34 > 35 //@{ メッセージを送って処理されるまで待機 //@} > 36 LRESULT SendMsg( UINT msg, WPARAM wp=0, LPARAM lp=0 ); > 37 > 38 //@{ メッセージを送ってすぐ帰る //@} > 39 BOOL PostMsg( UINT msg, WPARAM wp=0, LPARAM lp=0 ); > 40 > 41 //@{ > 42 // 自動消滅機能付きメッセージボックス > 43 // @param msg 表示する文字列 > 44 // @param caption ダイアログの題名 > 45 // @param type Win32SDKの説明を見てね > 46 //@} > 47 int MsgBox( LPCTSTR msg, LPCTSTR caption=NULL, UINT type=MB_OK ) const; > 48 > 49 //@{ テキスト設定 //@} > 50 void SetText( const TCHAR* str ); > 51 > 52 //@{ 表示 //@} > 53 void ShowUp( int sw=SW_SHOW ); > 54 > 55 //@{ 移動 //@} > 56 void MoveTo( int l, int t, int r, int b ); > 57 > 58 //@{ フォーカス //@} > 59 void SetFocus(); > 60 > 61 //@{ 最前面へGo! //@} > 62 void SetFront(); > 63 > 64 //@{ 画面中央へGo! //@} > 65 void SetCenter(); > 66 > 67 public: > 68 > 69 //@{ ウインドウハンドル //@} > 70 HWND hwnd() const; > 71 > 72 //@{ 位置・サイズ //@} > 73 void getPos( RECT* rc ) const; > 74 > 75 //@{ サイズ //@} > 76 void getClientRect( RECT* rc ) const; > 77 > 78 //@{ メインループを回してるウインドウかどうか //@} > 79 bool isMainWnd() const; > 80 > 81 //@{ 生きてる? //@} > 82 bool isAlive() const; > 83 > 84 public: > 85 > 86 //@{ 未処理メッセージを適当に処理 //@} > 87 static void ProcessMsg(); > 88 > 89 //@{ 最前面へGo! //@} > 90 static void SetFront( HWND hwnd ); > 91 > 92 //@{ > 93 // 画面中央へGo! > 94 // @param hwnd 動かすウインドウ > 95 // @param rel 基準にするウインドウ > 96 //@} > 97 static void SetCenter( HWND hwnd, HWND rel=NULL ); > 98 > 99 protected: > 100 > 101 // 何もしないコンストラクタ > 102 Window(); > 103 > 104 // Hwndをセット > 105 void SetHwnd( HWND wnd ); > 106 > 107 // アクセラレータを通すとかダイアログメッセージの処理とか > 108 virtual bool PreTranslateMessage( MSG* ) = 0; > 109 > 110 private: > 111 > 112 HWND wnd_; > 113 bool isLooping_; > 114 > 115 private: > 116 > 117 NOCOPY(Window); > 118 }; > 119 > 120 > 121 > 122 //------------------------------------------------------------------------- > 123 #ifndef __ccdoc__ > 124 > 125 inline LRESULT Window::SendMsg( UINT msg, WPARAM wp, LPARAM lp ) > 126 { return ::SendMessage( wnd_, msg, wp, lp ); } > 127 > 128 inline BOOL Window::PostMsg( UINT msg, WPARAM wp, LPARAM lp ) > 129 { return ::PostMessage( wnd_, msg, wp, lp ); } > 130 > 131 inline int Window::MsgBox( LPCTSTR m, LPCTSTR c, UINT y ) const > 132 { return ::MessageBox( wnd_, m, c, y ); } > 133 > 134 inline void Window::ShowUp( int sw ) > 135 { ::ShowWindow( wnd_, sw ), ::UpdateWindow( wnd_ ); } > 136 > 137 inline void Window::SetText( const TCHAR* str ) > 138 { ::SetWindowText( wnd_, str ); } > 139 > 140 inline void Window::MoveTo( int l, int t, int r, int b ) > 141 { ::MoveWindow( wnd_, l, t, r-l, b-t, TRUE ); } > 142 > 143 inline void Window::SetFocus() > 144 { ::SetFocus( wnd_ ); } > 145 > 146 inline void Window::SetFront() > 147 { SetFront( wnd_ ); } > 148 > 149 inline void Window::SetCenter() > 150 { SetCenter( wnd_ ); } > 151 > 152 inline HWND Window::hwnd() const > 153 { return wnd_; } > 154 > 155 inline bool Window::isMainWnd() const > 156 { return isLooping_; } > 157 > 158 inline void Window::getPos( RECT* rc ) const > 159 { ::GetWindowRect( wnd_, rc ); } > 160 > 161 inline void Window::getClientRect( RECT* rc ) const > 162 { ::GetClientRect( wnd_, rc ); } > 163 > 164 inline bool Window::isAlive() const > 165 { return FALSE != ::IsWindow( wnd_ ); } > 166 > 167 > 168 > 169 #endif // __ccdoc__ > 170 //========================================================================= > 171 //@{ > 172 // IME制御マネージャ > 173 // > 174 // Global IME をサポートするには、ウインドウメッセージの処理を > 175 // 根本的に入れ替える必要がある。そこで、処理をこのクラスにまとめ > 176 // Windowクラスと連携処理を行うことで、ライブラリの外からは一切 > 177 // 気にせず処理をできるようにしておく。なお、Global IMEに対応 > 178 // するにはバージョンの新しいPlatform SDKが必要なため > 179 // マクロ USEGLOBALIME が定義されていなければその辺は処理しない。 > 180 //@} > 181 //========================================================================= > 182 > 183 class IMEManager > 184 { > 185 public: > 186 > 187 //@{ フォント指定 //@} > 188 void SetFont( HWND wnd, const LOGFONT& lf ); > 189 > 190 //@{ 位置指定 //@} > 191 void SetPos( HWND wnd, int x, int y ); > 192 > 193 //@{ 確定文字列ゲット。受け取ったら delete すること。 //@} > 194 void GetString( HWND wnd, unicode** str, ulong* len ); > 195 > 196 //@{ GlobalIMEを利用可能状態にする //@} > 197 void EnableGlobalIME( bool enable ); > 198 > 199 //@{ GlobalIMEを使えるWindowのリストを登録 //@} > 200 void FilterWindows( ATOM* lst, UINT siz ); > 201 > 202 private: > 203 > 204 IMEManager(); > 205 ~IMEManager(); > 206 void TranslateMsg( MSG* msg ); > 207 LRESULT DefProc( HWND wnd, UINT msg, WPARAM wp, LPARAM lp ); > 208 void MsgLoopBegin(); > 209 void MsgLoopEnd(); > 210 > 211 private: > 212 > 213 #ifdef USEGLOBALIME > 214 IActiveIMMApp* immApp_; > 215 IActiveIMMMessagePumpOwner* immMsg_; > 216 #endif > 217 static IMEManager* pUniqueInstance_; > 218 > 219 private: > 220 > 221 friend class Window; > 222 friend class WndImpl; > 223 friend void APIENTRY Startup(); > 224 friend inline IMEManager& ime(); > 225 NOCOPY(IMEManager); > 226 }; > 227 > 228 > 229 > 230 //------------------------------------------------------------------------- > 231 > 232 //@{ 唯一のIME管理オブジェクトを返す //@} > 233 inline IMEManager& ime() > 234 { return *IMEManager::pUniqueInstance_; } > 235 > 236 > 237 > 238 //========================================================================= > 239 //@{ > 240 // 普通のウインドウ実装 > 241 // > 242 // 派生クラスを定義して、コンストラクタの引数で WndImpl に > 243 // WNDCLASS名やスタイルを渡し、初回なら WNDCLASS を Register > 244 // して、あとは適当なタイミングで Create() という使い方を想定。 > 245 // > 246 // HWNDからWndImpl*への変換はx86/x86-64専用のサンクで行っています。 > 247 // ので、他のアーキテクチャではこのままでは動作しません。移植 > 248 // する場合は、GWL_USERDATA を使うなり clsExtra に入れるなりで > 249 // もう少し汎用性のある方法に適宜変えてください。 > 250 //@} > 251 //========================================================================= > 252 > 253 class WndImpl : public Window > 254 { > 255 enum { THUNK_SIZE = 22 }; > 256 > 257 public: > 258 > 259 //@{ ウインドウ作成 //@} > 260 bool Create( LPCTSTR wndName=NULL, HWND parent=NULL, > 261 int x =CW_USEDEFAULT, int y =CW_USEDEFAULT, > 262 int width =CW_USEDEFAULT, int height =CW_USEDEFAULT, > 263 void* param=NULL ); > 264 > 265 //@{ ウインドウ破棄 //@} > 266 void Destroy(); > 267 > 268 protected: > 269 > 270 //@{ > 271 // コンストラクタ > 272 // @param className ウインドウクラス名 > 273 // @param style 標準スタイル > 274 // @param styleEx 標準拡張スタイル > 275 //@} > 276 WndImpl( LPCTSTR className, DWORD style, DWORD styleEx=0 ); > 277 ~WndImpl(); > 278 > 279 //@{ クラス名用の型 //@} > 280 typedef const TCHAR* const ClsName; > 281 > 282 //@{ ウインドウクラス登録 //@} > 283 static ATOM Register( WNDCLASSEX* cls ); > 284 > 285 // てけとーに実装して反応してください。 > 286 // on_commandは、処理しなかったらfalseを返すこと。 > 287 // on_messageは、処理しなかったらWndImpl::on_messageを呼び出すこと。 > 288 // PreTranslateMessageは、処理してもしなくても中で呼び出すこと。 > 289 virtual void on_create( CREATESTRUCT* cs ); > 290 virtual void on_destroy(); > 291 virtual bool on_command( UINT id, HWND ctrl ); > 292 virtual LRESULT on_message( UINT msg, WPARAM wp, LPARAM lp ); > 293 virtual bool PreTranslateMessage( MSG* msg ); > 294 > 295 private: > 296 > 297 static LRESULT CALLBACK StartProc( HWND, UINT, WPARAM, LPARAM ); > 298 static LRESULT CALLBACK MainProc( WndImpl*, UINT, WPARAM, LPARAM ); > 299 void SetUpThunk( HWND wnd ); > 300 > 301 private: > 302 > 303 LPCTSTR className_; > 304 const DWORD style_, styleEx_; > 305 byte* thunk_; > 306 }; > 307 > 308 > 309 > 310 //========================================================================= > 311 //@{ > 312 // ダイアログ実装 > 313 // > 314 // 派生クラスを定義して、コンストラクタの引数で DlgImpl に > 315 // リソースIDを渡し、後は適当なタイミングで GoModal なり > 316 // Modeless なり、という使い方を想定。 > 317 // > 318 // HWNDからDlgImpl*への変換は GWL_USERDATA で行っています。 > 319 // ので、それは使わないようにしましょう。 > 320 //@} > 321 //========================================================================= > 322 > 323 class DlgImpl : public Window > 324 { > 325 public: > 326 > 327 enum dlgtype { MODAL, MODELESS }; > 328 > 329 //@{ モーダルで実行 //@} > 330 void GoModal( HWND parent=NULL ); > 331 > 332 //@{ モードレスで作成 //@} > 333 void GoModeless( HWND parent=NULL ); > 334 > 335 //@{ 強制的に終わらせる //@} > 336 void End( UINT code ); > 337 > 338 public: > 339 > 340 //@{ モーダルかモードレスか //@} > 341 dlgtype type() const; > 342 > 343 //@{ 終了コード取得 //@} > 344 UINT endcode() const; > 345 > 346 protected: > 347 > 348 //@{ コンストラクタ //@} > 349 DlgImpl( UINT id ); > 350 ~DlgImpl(); > 351 > 352 //@{ 子アイテムID→HWND変換 //@} > 353 HWND item( UINT id ) const; > 354 > 355 //@{ アイテムに対してメッセージ送信 //@} > 356 LRESULT SendMsgToItem( UINT id, UINT msg, WPARAM wp=0, LPARAM lp=0 ); > 357 > 358 //@{ アイテムに対してメッセージ送信(ポインタ送る版) //@} > 359 LRESULT SendMsgToItem( UINT id, UINT msg, void* lp ); > 360 > 361 //@{ アイテムに対してメッセージ送信(文字列送る版) //@} > 362 LRESULT SendMsgToItem( UINT id, UINT msg, const TCHAR* lp ); > 363 > 364 // てけとーに実装して反応してください。 > 365 // on_ok/on_cancelは、終了して良いならtrueを返すこと。 > 366 // on_cmd/on_msgは、処理済みならtrueを返すこと。 > 367 virtual void on_init(); > 368 virtual void on_destroy(); > 369 virtual bool on_ok(); > 370 virtual bool on_cancel(); > 371 virtual bool on_command( UINT cmd, UINT id, HWND ctrl ); > 372 virtual bool on_message( UINT msg, WPARAM wp, LPARAM lp ); > 373 virtual bool PreTranslateMessage( MSG* msg ); > 374 > 375 private: > 376 > 377 static BOOL CALLBACK MainProc( HWND, UINT, WPARAM, LPARAM ); > 378 > 379 private: > 380 > 381 dlgtype type_; > 382 UINT endCode_; > 383 const UINT rsrcID_; > 384 }; > 385 > 386 > 387 > 388 //------------------------------------------------------------------------- > 389 #ifndef __ccdoc__ > 390 > 391 inline DlgImpl::dlgtype DlgImpl::type() const > 392 { return type_; } > 393 > 394 inline UINT DlgImpl::endcode() const > 395 { return endCode_; } > 396 > 397 inline HWND DlgImpl::item( UINT id ) const > 398 { return ::GetDlgItem( hwnd(), id ); } > 399 > 400 inline LRESULT DlgImpl::SendMsgToItem > 401 ( UINT id, UINT msg, WPARAM wp, LPARAM lp ) > 402 { return ::SendDlgItemMessage( hwnd(), id, msg, wp, lp ); } > 403 > 404 inline LRESULT DlgImpl::SendMsgToItem( UINT id, UINT msg, void* lp ) > 405 { return ::SendDlgItemMessage( hwnd(), id, msg, 0, > 406 reinterpret_cast<LPARAM>(lp) ); } > 407 > 408 inline LRESULT DlgImpl::SendMsgToItem( UINT id, UINT msg, const TCHAR* lp ) > 409 { return ::SendDlgItemMessage( hwnd(), id, msg, 0, > 410 reinterpret_cast<LPARAM>(lp) ); } > 411 > 412 > 413 > 414 //========================================================================= > 415 > 416 #endif // __ccdoc__ > 417 } // namespace ki > 418 #endif // _KILIB_WINDOW_H_

Added kilib/winutil.cpp version [c65458ae7512b751]

> 1 #include "stdafx.h" > 2 #include "app.h" > 3 #include "winutil.h" > 4 using namespace ki; > 5 > 6 > 7 > 8 //========================================================================= > 9 > 10 Clipboard::Clipboard( HWND owner, bool read ) > 11 : opened_( false ) > 12 { > 13 if( ::OpenClipboard(owner) ) > 14 if( read || ::EmptyClipboard() ) > 15 opened_ = true; > 16 else > 17 ::CloseClipboard(); > 18 } > 19 > 20 Clipboard::~Clipboard() > 21 { > 22 if( opened_ ) > 23 ::CloseClipboard(); > 24 } > 25 > 26 Clipboard::Text Clipboard::GetUnicodeText() const > 27 { > 28 if( app().isNT() ) > 29 { > 30 // NTなら直接Unicodeでとれる > 31 HANDLE h = GetData( CF_UNICODETEXT ); > 32 if( h != NULL ) > 33 { > 34 unicode* ustr = static_cast<unicode*>( ::GlobalLock( h ) > 35 return Text( ustr, Text::GALLOC ); > 36 } > 37 } > 38 else > 39 { > 40 // 9xなら変換が必要 > 41 HANDLE h = GetData( CF_TEXT ); > 42 if( h != NULL ) > 43 { > 44 char* cstr = static_cast<char*>( ::GlobalLock( h ) ); > 45 int Lu = ::lstrlenA( cstr ) * 3; > 46 unicode* ustr = new unicode[Lu]; > 47 ::MultiByteToWideChar( CP_ACP, 0, cstr, -1, ustr, Lu ); > 48 ::GlobalUnlock( h ); > 49 return Text( ustr, Text::NEW ); > 50 } > 51 } > 52 > 53 return Text( NULL, Text::NEW ); > 54 }

Added kilib/winutil.h version [882f1cfcdc84a351]

> 1 #ifndef _KILIB_WINUTIL_H_ > 2 #define _KILIB_WINUTIL_H_ > 3 #include "types.h" > 4 #include "memory.h" > 5 #include "ktlaptr.h" > 6 #ifndef __ccdoc__ > 7 namespace ki { > 8 #endif > 9 > 10 > 11 > 12 //========================================================================= > 13 //@{ @pkg ki.WinUtil //@} > 14 //@{ > 15 // クリップボード管理 > 16 // > 17 // OpenClipboard や CloseClipboard 辺りの呼び出しを適当に自動化します。 > 18 //@} > 19 //========================================================================= > 20 > 21 class Clipboard : public Object > 22 { > 23 public: > 24 > 25 //@{ 開く //@} > 26 Clipboard( HWND owner, bool read=true ); > 27 > 28 //@{ 閉じる //@} > 29 ~Clipboard(); > 30 > 31 //@{ データ読み込み //@} > 32 HANDLE GetData( UINT uFormat ) const; > 33 > 34 //@{ 指定フォーマットのデータがクリップボード上にあるか? //@} > 35 bool IsAvail( UINT uFormat ) const; > 36 > 37 //@{ 指定フォーマットのデータがクリップボード上にあるか?(複数) //@} > 38 bool IsAvail( UINT uFormats[], int num ) const; > 39 > 40 //@{ テキスト情報保持クラス //@} > 41 class Text { > 42 friend class Clipboard; > 43 > 44 mutable unicode* str_; > 45 enum Tp { NEW, GALLOC } mem_; > 46 > 47 Text( unicode* s, Tp m ) : str_(s), mem_(m) {} > 48 void operator=( const Text& ); > 49 > 50 public: > 51 Text( const Text& t ) > 52 : str_(t.str_), mem_(t.mem_) { t.str_=NULL; } > 53 ~Text() > 54 { > 55 if( str_ != NULL ) > 56 if( mem_==NEW ) delete [] str_; > 57 else GlobalUnlock( str_ ); > 58 } > 59 const unicode* data() const { return str_; } > 60 }; > 61 > 62 //@{ テキスト読み込み //@} > 63 Text GetUnicodeText() const; > 64 > 65 //@{ データ書き込み //@} > 66 bool SetData( UINT uFormat, HANDLE hData ); > 67 > 68 //@{ 独自フォーマットの登録 //@} > 69 static UINT RegisterFormat( const TCHAR* name ); > 70 > 71 public: > 72 > 73 //@{ 正常に開かれているかチェック //@} > 74 bool isOpened() const; > 75 > 76 private: > 77 > 78 bool opened_; > 79 > 80 private: > 81 > 82 NOCOPY(Clipboard); > 83 }; > 84 > 85 > 86 > 87 //------------------------------------------------------------------------- > 88 > 89 inline bool Clipboard::isOpened() const > 90 { return opened_; } > 91 > 92 inline HANDLE Clipboard::GetData( UINT uFormat ) const > 93 { return ::GetClipboardData( uFormat ); } > 94 > 95 inline bool Clipboard::SetData( UINT uFormat, HANDLE hData ) > 96 { return NULL != ::SetClipboardData( uFormat, hData ); } > 97 > 98 inline bool Clipboard::IsAvail( UINT uFormat ) const > 99 { return false!=::IsClipboardFormatAvailable(uFormat); } > 100 > 101 inline bool Clipboard::IsAvail( UINT uFormats[], int num ) const > 102 { return -1!=::GetPriorityClipboardFormat(uFormats,num); } > 103 > 104 inline UINT Clipboard::RegisterFormat( const TCHAR* name ) > 105 { return ::RegisterClipboardFormat(name); } > 106 > 107 > 108 > 109 //========================================================================= > 110 //@{ > 111 // 排他制御 > 112 // > 113 // 名前付きMutexを扱います > 114 //@} > 115 //========================================================================= > 116 > 117 class Mutex : public Object > 118 { > 119 public: > 120 Mutex( const TCHAR* name ); > 121 ~Mutex(); > 122 > 123 private: > 124 const HANDLE mtx_; > 125 > 126 private: > 127 NOCOPY(Mutex); > 128 }; > 129 > 130 > 131 > 132 //------------------------------------------------------------------------- > 133 > 134 inline Mutex::Mutex( const TCHAR* name ) > 135 : mtx_( ::CreateMutex( NULL, TRUE, name ) ) {} > 136 > 137 inline Mutex::~Mutex() > 138 { if( mtx_ != NULL ) ::ReleaseMutex( mtx_ ), ::CloseHandle( mtx_ ); } > 139 > 140 > 141 > 142 //========================================================================= > 143 > 144 } // namespace ki > 145 #endif // _KILIB_WINUTIL_H_

Added release/readme.en.txt version [97fc802499438f8f]

> 1 > 2 > 3 =<> > 4 =<> GreenPad ver 1.08+ > 5 =<> 2008/07/11 > 6 > 7 > 8 <<What's This?>> > 9 > 10 GreenPad is a tiny text editor for Windows. > 11 > 12 It aims to be a handy Notepad replacement with minimal but > 13 complete features, not to be a rich, bloated monsterous > 14 editor. GreenPad supports: > 15 * Unicode 2.0 > 16 * Proportional Fonts > 17 * Syntax Highlighting > 18 * Searching with Regular Expressions > 19 while keeping the size of .exe very small (around 50KB!). > 20 > 21 Freeware, distributed under the NYSL licence. > 22 The source code is available at: http://www.kmonos.net/lib/gp.en.html > 23 > 24 > 25 <<What's New in 1.08>> > 26 > 27 * Fixed: Several potential access violations bugs > 28 * Partial support for surrogate pairs (proper rendering and carret moves, > 29 reading/writing UTF-32 and UTF-8 text beyond BMP). > 30 * Changed the tab-order of the Find/Replace dialog. > 31 * Changed the behavior of [Home] and [End] key to be more compatible with Note > 32 > 33 <<Keyboard Shortcuts>> > 34 > 35 Ctrl+R Reopen > 36 Shift+Ctrl+S Save as... > 37 Ctrl+Y Redo > 38 F5 Insert date & time > 39 > 40 Ctrl+F Find > 41 F3 Find next > 42 Shift+F3 Find prev > 43 Ctrl+H Replace > 44 Ctrl+J Jump to line # > 45 Ctrl+G Grep > 46 > 47 Ctrl+1 No Wrapping > 48 Ctrl+2 Wrap by specified width > 49 Ctrl+3 Wrap by the size of window > 50 > 51 Ctrl+Up Curosr Up 3 lines > 52 Ctrl+Dn Curosr Down 3 lines > 53 > 54 and Windows-common shortcuts ( Ctrl+S to save, Ctrl+C to copy, ... ) > 55 > 56 > 57 <<Q&A>> > 58 > 59 * How to change fonts and colors ? > 60 > 61 In the types/ dir, you'll see some .lay files. Please edit them manually. > 62 ========================================================= > 63 ct=Color of Text (RGB) > 64 ck=Color of Keyword > 65 cb=Color of BackGround > 66 cc=Color of ControlCharactor > 67 cn=Color of commeNt > 68 cl=Color of Line no. > 69 ft=FonT name > 70 sz=font SiZe > 71 tb=TaB width > 72 sc=11000 > 73 wp=WraP type (-1: no wrap 0: right edge 1: ww chars ) > 74 ww=Wrap Width > 75 ln=show LineNo. > 76 ========================================================= > 77 Year, editing manually, is very inconvinient. > 78 I'll create GUI configurator someday ... > 79 > 80 * How to create syntax hilighting modes? > 81 > 82 Write you own .kwd files and put them into the types/ directory. > 83 The format of .kwd files is as follows: > 84 ========================================================= > 85 1111 # Four Boolean Flags, 0:false 1:true (explained later) > 86 /* # beginning symbol for block-comments > 87 */ # ending symbol for block-comments > 88 // # beggining symbol for one-line comments > 89 auto # the list of keywords follows... > 90 bool > 91 _Bool > 92 break > 93 case > 94 ... > 95 ========================================================= > 96 The meanings of the four flags are, from left to right: > 97 - CaseSensitive (if set to 1, keywords are treated as case-sensiti > 98 - EnableSingleQuotation (if set to 1, keywords inside '...' is not highlig > 99 - EnableDoubleQuoatation (if set to 1, keywords inside "..." is not highlig > 100 - EnableEscapeSequences (if set to 1, "..\".." is teated as a single strin > 101 Usually, 0111 or 1111 is recommended. > 102 > 103 * Which regular expressions can be used? > 104 > 105 Here is the complete list of the regular expressions available in GreenPad: > 106 ========================================================= > 107 quanitification: > 108 ? : 0 or 1 > 109 * : 0 or more > 110 + : 1 or more > 111 > 112 alternation: > 113 a|b > 114 > 115 grouping(parentheses) > 116 > 117 special escape characters: > 118 \t : tab > 119 \\ : '\' itself > 120 \[ : '[' > 121 > 122 positional match: > 123 ^ : start of line > 124 $ : end of line > 125 > 126 character classes: > 127 [abc] : matches a single character 'a', 'b', or 'c' > 128 [^abc] : matches any single character other than 'a', 'b', or 'c' > 129 [d-h] : matches 'd', 'e', 'f', 'g', 'h' > 130 \w : [0-9a-zA-Z_] > 131 \W : [^0-9a-zA-Z_] > 132 \d : [0-9] > 133 \D : [^0-9] > 134 \s : [\t ] > 135 \S : [^\t ] > 136 ========================================================= > 137 There are some limitations: > 138 * GreenPad does searching line by line, thus > 139 you cannot search "aaa\nbbb" or something like it. > 140 * No forward/backward references. > 141 * No shortest matches (every * is greedy) > 142 > 143 * External Grep Program ? > 144 > 145 You can enter some GUI grep program here. For example, > 146 C:\Software\Gj\GrepJuice.exe "%D" > 147 is set in my environment. > 148 %D is automatically replaced by the current directory > 149 %F is replaced with the full path of the current file. > 150 %N is replaced with the name (without path info) of the current file. > 151 > 152 * Command Line Options ? > 153 > 154 greenpad ([-l LineNumber] [-c CharacterSet] filename)* > 155 > 156 For example: > 157 greenpad -l543 -c932 aaaa.txt > 158 opens a file named "aaaa.txt" assuming the Shift_JIS encoding, > 159 and brings its 543rd line to the view area. CharacterSet number > 160 supported by default is: > 161 iso-8859-1 = -1 > 162 UTF5 = -2 > 163 UTF8 = -65001 > 164 UTF16BE = -5 > 165 UTF16LE = -6 > 166 UTF32BE = -9 > 167 UTF32LE = -10 > 168 If you have installed "Language Support" for your Windows, > 169 the character sets of installed languages become > 170 readable/writable in GreenPad. You should consult with > 171 the "area and language option" control panel to get the > 172 CharacterSet numbet for those languages. Note however that > 173 for some east asian encodings, special CharacterSet numbers > 174 are assigned for a technical reason. > 175 EUC-JP = -932 > 176 iso-2022-jp = -933 > 177 iso-2022-kr = -950 > 178 iso-2022-cn = -936 > 179 GB2312 = -937 > 180 > 181 * How to share GreenPad's configurations between users of same machine? > 182 > 183 Usually, GreenPad saves and loads its configuration for each > 184 machine user account. However, sometimes you want to use only one > 185 setting for one GreenPad.exe. (for example, when you have GreenPad > 186 in an emergency floppy disk and log in different users accounts.) > 187 > 188 In this case, you should add the following two lines to GreenPad.ini > 189 file: > 190 [SharedConfig] > 191 Enable=1 > 192 then GreenPad will be executed in user-independent-settings-mode. > 193 > 194 > 195 <<Acknowledgements>> > 196 > 197 * The icon image of GreenPad is the work of > 198 SB( http://homepage3.nifty.com/scriba/ ). Thanks. > 199 > 200 > 201 <<License>> > 202 > 203 NYSL Version 0.9982 http://www.kmonos.net/nysl/ > 204 > 205 A. This software is "Everyone'sWare". It means: > 206 Anybody who has this software can use it as if you're > 207 the author. > 208 > 209 A-1. Freeware. No fee is required. > 210 A-2. You can freely redistribute this software. > 211 A-3. You can freely modify this software. And the source > 212 may be used in any software with no limitation. > 213 A-4. When you release a modified version to public, you > 214 must publish it with your name. > 215 > 216 B. The author is not responsible for any kind of damages or loss > 217 while using or misusing this software, which is distributed > 218 "AS IS". No warranty of any kind is expressed or implied. > 219 You use AT YOUR OWN RISK. > 220 > 221 C. Copyrighted to k.inaba. > 222 > 223 D. Above three clauses are applied both to source and binary > 224 form of this software. > 225 > 226 > 227 --------------------------------------------------------------------------- > 228 by k.inaba( http://www.kmonos.net/ )

Added release/readme.txt version [70e72f2bca2bf1ca]

> 1 > 2 =<> > 3 =<> GreenPad ver 1.08+ > 4 =<> 2008/07/11 > 5 > 6 > 7 <<これは何?>> > 8 > 9 Windows上で動作する、テキストエディタです。 > 10 なんでもできる高機能エディタではなく、メモ帳の代わりとして > 11 使えるような、最低限の機能は備えつつ高速に動作する簡易テキ > 12 ストエディタを目指して開発されています。 > 13 > 14 NYSLライセンスに従うフリーウェアです。ソースコードが > 15 http://www.kmonos.net/lib/gp.html > 16 で公開されています。 > 17 > 18 最新版での更新内容は、 > 19 ・S版で「開く」「保存」ダイアログが出なくなっていたバグ修正 > 20 ・タイトルバーをクリックしたときシステムメニューが出ないバグ修正 > 21 ・環境によってステータスバーにカーソル位置表示が出ないバグ修正 > 22 です。 > 23 > 24 > 25 <<1.08+ での更新内容>> > 26 > 27 * A版が起動しなくなっていたバグを修正 > 28 (U版には変更ありません) > 29 > 30 > 31 <<1.08 での主な更新内容>> > 32 > 33 * メモリアクセス違反で強制終了するバグを何カ所か修正 > 34 * サロゲートペアに少し対応(描画やカーソル移動でサロゲートペアを分解しないようになった > 35 && UTF-32 と UTF-8 ファイルのBMP外文字の読み書きに対応) > 36 注: BMP外の文字は、対応するフォント(XANO明朝 等)を指定した時のみ描画されます。 > 37 * 検索/置換ダイアログのタブ順変更 > 38 * Home/End キーを論理行ではなく表示行単位の動作に変更 > 39 > 40 > 41 <<特徴>> > 42 > 43 ・内部処理はUnicode > 44 ・プロポーショナルフォントが使える > 45 ・キーワード色分けが出来る > 46 ・文字コードはいわゆる SJIS, EUC, JIS, UTF8, UTF7, UTF16 などの > 47 他にも、Windowsがサポートしていればそれに合わせて色々対応 > 48 ・改行コードは CRLF/CR/LF に対応 > 49 ・出来る限りの無限Undo可能 > 50 ・ショボめの正規表現検索機能内蔵 > 51 ・exeのサイズがわりと小さい > 52 ・選択時に行と行の間に隙間が見えるのは作者の趣味 > 53 > 54 > 55 <<使い方>> > 56 > 57 基本的な使い方は、Windowsの標準的なテキスト編集方法と > 58 同じです。適当に勢いで使ってください。 > 59 > 60 Windowsの一般的なものではないかもしれないキーボード > 61 ショートカットは次の通りです。 > 62 | > 63 | Ctrl+R 開き直す > 64 | Shift+Ctrl+S 別名保存 > 65 | > 66 | Ctrl+Y Redo > 67 | F5 日時の挿入 > 68 | > 69 | Ctrl+F 検索 > 70 | Ctrl+H 置換 > 71 | Ctrl+J ジャンプ > 72 | F3 次を検索 > 73 | Shift+F3 前を検索 > 74 | Ctrl+G Grep > 75 | > 76 | Ctrl+1 折り返しなし > 77 | Ctrl+2 指定幅折り返し > 78 | Ctrl+3 右端折り返し > 79 | > 80 | Ctrl+↑ 3行単位でカーソル移動 > 81 | Ctrl+↓ 3行単位でカーソル移動 > 82 | > 83 | Shift+変換 選択範囲を再変換 > 84 | Ctrl+BS 確定取消 > 85 > 86 検索には正規表現がちょびっと使えます。 > 87 対応している正規表現は以下のとおりです。 > 88 | > 89 | c 普通の字は、その文字自身を意味する > 90 | \t タブ文字 > 91 | \w [0-9a-zA-Z_] と同義。英数字 > 92 | \W [^0-9a-zA-Z_] と同義。英数字以外 > 93 | \d [0-9] と同義。数字 > 94 | \D [^0-9] と同義。数字以外 > 95 | \s [\t ] と同義。空白文字 > 96 | \S [^\t ] と同義。空白文字以外 > 97 | \その他 \\ なら \、\[ なら [ という一文字 > 98 | ^ 行の先頭 > 99 | $ 行の末尾 > 100 | . 任意の一文字 > 101 | [...] [] 内に含まれる任意の1文字。A-Z や あ-ん のような範囲指定も可。 > 102 | [^...] [] 内に含まれない任意の1文字。範囲指定も可。 > 103 | > 104 | r* 正規表現 r を0回以上繰返したもの > 105 | r+ 正規表現 r を1回以上繰返したもの > 106 | r? 正規表現 r の0回または1回 > 107 | r1r2 正規表現 r1 に続いて r2 が現れることを表す > 108 | r1|r2 正規表現 r1 または r2 を表す > 109 | (r) 正規表現 r を表す. > 110 | > 111 | 例 > 112 | 第[1-9]号 "第1号"とか"第2号"とかにマッチ > 113 | <[^>]+> XMLのタグとかにマッチ > 114 | (。|!|?)$ 行末の。か!か?にマッチ > 115 | > 116 | 前方参照とか最短一致とか置換に\1とかそういったことは、 > 117 | 残念ながら一切できません。改行を挟んだ検索などもでき > 118 | ません。ゴメンナサイ。 > 119 > 120 > 121 <<Q&A>> > 122 > 123 ・どうやってフォントとかを変えればよいの? > 124 | 下のほうの*.kwdや*.layの書式に従って、設定ファイルを編集してください。 > 125 | 機会があったら設定変更画面も用意しますので…スミマセン > 126 > 127 ・Unicode対応なはずなのに日本語以外の字が表示できないよ? > 128 | 対応するフォントが必要です。Unicode 2.0をフルに > 129 | 使えるフォントとしては MS Office 付属の "Arial Unicode" や、 > 130 | "BDF UM+" ( http://www.kaoriya.net/#FONT ) など。 > 131 | メニューの「文書タイプ」>「UnicodeText」を選ぶと、 > 132 | Arial Unicode を使ってテキストを表示します。その他のUnicodeフォントは、 > 133 | GreenPad フォルダの types\unicode.lay を書き換えるなどしてご利用下さい。 > 134 > 135 ・右から左に書くタイプの言語がうまく表示できない。 > 136 | ごめんなさいGreenPadでは無理です。 > 137 > 138 ・設定の「外部Grepプログラム」欄には何を入れればよいのでしょう? > 139 | "Grep"用のプログラムがインストールされていると、ここに > 140 | 入力しておくことでGreenPadから起動できます。例として私の環境では > 141 | C:\Software\Getia\getia.exe "%D" > 142 | となっています。外部ツールの起動時に、 > 143 | %D は「現在開いているファイルのあるフォルダ」 > 144 | %F は「現在開いているファイルのフルパス名」 > 145 | %N は「現在開いているファイルの名前部分」 > 146 | に置き換わります。ちなみに作者のおすすめGrepプログラムは > 147 | getia (http://site-clue.statice.jp/soft_getia.php) > 148 | です。 > 149 > 150 ・コマンドラインオプションは? > 151 | -l : 行番号指定 > 152 | -c : 文字コード指定 > 153 | の2つがあります。 > 154 | > 155 | greenpad -l543 -c932 aaaa.txt > 156 | で、強制的にShiftJISで、aaaa.txtを開き、 > 157 | 543行目を一番上にした状態で起動します。 > 158 | > 159 | greenpad aaaa.txt -l543 -c932 > 160 | ではダメです。オプションはファイル名より前に。 > 161 | > 162 | greenpad -l123 aaaa.txt -l456 bbbb.txt > 163 | とやって2つのファイルを開くことは可能 > 164 | > 165 | -cの後ろの数字は、下にあげる"文字コード番号"を指定します。 > 166 > 167 ・文字コード番号? > 168 | WinXPならコントロールパネルの > 169 | 「言語と地域のオプション」の「詳細設定」の「コードページ > 170 | 変換テーブル」の数字を指定するとだいたい上手く行くと思います。 > 171 | ただし、一部のコードにはGreenPad内で特別に負の数を割り振って > 172 | いますので、以下の値を使ってください。 > 173 | > 174 | SJIS = 932, // 日本語1 (Shift_JIS) > 175 | EucJP = -932, // 日本語2 (日本語EUC) > 176 | IsoJP = -933, // 日本語3 (ISO-2022-JP) > 177 | > 178 | Western = -1, // 欧米 (Windows1252 >> ISO-8859-1) > 179 | IsoKR = -950, // 韓国語2 (ISO-2022-KR) > 180 | IsoCN = -936, // 中国語2 (簡体字 ISO-2022-CN) > 181 | HZ = -937, // 中国語3 (簡体字 HZ-GB2312) > 182 | UTF5 = -2, // Unicode (UTF-5) : BOM無し > 183 | UTF8 =-65001,// Unicode (UTF-8) : BOM有り > 184 | UTF16b = -3, // Unicode (UTF-16) : BOM有り BE > 185 | UTF16l = -4, // Unicode (UTF-16) : BOM有り LE > 186 | UTF16BE = -5, // Unicode (UTF-16BE): BOM無し > 187 | UTF16LE = -6, // Unicode (UTF-16LE): BOM無し > 188 | UTF32b = -7, // Unicode (UTF-32) : BOM有り BE > 189 | UTF32l = -8, // Unicode (UTF-32) : BOM有り LE > 190 | UTF32BE = -9, // Unicode (UTF-32BE): BOM無し > 191 | UTF32LE = -10, // Unicode (UTF-32LE): BOM無し > 192 > 193 ・キーワードファイル (*.kwd) の書き方は? > 194 | > 195 | UCS-2をLittleEndianでベタ書きしたファイルでなければならない。 > 196 | 改行コードはなんでもいいけど LF にすると若干高速に読めるかも。 > 197 | BOMはあってもなくても可。つけておくことを推奨。 > 198 | > 199 | 1行目: flag ========================== > 200 | > 201 | 0 or 1 が4つ並ぶ。順に、1ならば > 202 | ・ キーワードは大文字小文字を区別 > 203 | ・ '' の中ではコメント記号は無効 > 204 | ・ "" の中ではコメント記号は無効 > 205 | ・ \ 記号によるエスケープを行う > 206 | を意味する。 > 207 | > 208 | 2行目: ブロックコメント開始記号 ====== > 209 | > 210 | /* とかそんな風に書く。 > 211 | ブロックコメントを使わないなら空行にしておく。 > 212 | > 213 | 3行目: ブロックコメント終了記号 ====== > 214 | > 215 | */ とかそんな風に書く。 > 216 | ブロックコメントを使わないなら空行にしておく。 > 217 | > 218 | 4行目: 行コメント開始記号 ============ > 219 | > 220 | // とかそんな風に書く。 > 221 | 行コメントを使わないなら空行にしておく。 > 222 | > 223 | 5行目以降: キーワード ================ > 224 | > 225 | 強調表示したい単語をひたすら書き連ねる > 226 | > 227 | ※ キーワードとして使えるのは、 > 228 | ※ 数字、アルファベット(大小)、下線 > 229 | ※ からなる単語のみ。border-width とか #include とかはダメ。 > 230 | ※ __int64 などは可。 > 231 | > 232 | ※ コメント記号としては、 > 233 | ※ キーワードに使える文字・空白文字 > 234 | ※ を除いたASCII文字のみが使える。 begin とかはダメ。 > 235 > 236 ・レイアウトファイル (*.lay) の書き方は? > 237 | UCS-2をLittleEndianでベタ書きしたファイルでなければならない。 > 238 | 任意の文字コードを使えるように変更することもすぐに可能なので、 > 239 | 気が向いたら変えるかもしれない。ので、BOMはつけておくことを推奨。 > 240 | > 241 | ct=文字色 > 242 | ck=キーワード色 > 243 | cb=背景色 > 244 | cc=コメント色 > 245 | cn=EOFや改行マークの色 > 246 | cl=行番号の色 > 247 | ft=フォント名 > 248 | sz=フォントサイズ > 249 | tb=タブ幅 > 250 | sc=特殊文字を表示するなら1(左から順に、EOF,改行,タブ,半角空白,全角空白) > 251 | wp=折り返し方式(-1:無し 0:右端 1:指定文字数) > 252 | ww=折り返し文字数(wp=1の時に利用) > 253 | ln=行番号表示(1:ON 0:OFF) > 254 | > 255 | 項目を省略すると、その項目に関しては default.lay の > 256 | 内容が読み込まれる。default.lay も無いときは exe 内に > 257 | 内蔵してあるデフォルトの設定が読み込まれる。 > 258 > 259 ・初期設定ファイル (*.ini) の書き方は? > 260 | 設定ダイアログで設定するとここに書き込まれます。 > 261 | Windowsのごく普通のINIファイル。ANSI-CP (日本ならShift_JIS)+CRLF で > 262 | 書かねばならない。例として、次のような感じになる。 > 263 | > 264 | ------------------------------------------------------------------ > 265 | [ユーザー名] > 266 | UndoLimit= // アンドゥ回数制限。-1 なら制限無し > 267 | TxtFilter= // [開く]ダイアログ用のフィルタ。*.xxx の形で、; で区切ること > 268 | OpenSame= // 同じウインドウで開くなら1、でなければ0。 > 269 | CountUni= // 俗に言う半角全角を区別せず、横の桁数を数える > 270 | GrepExe= // Grep用に使う外部アプリ起動のコマンドを入れる。 > 271 | // %1があればそこをカレントフォルダ名に置き換える。 > 272 | MRU= // [最近開いたファイル] に表示する個数。最大8個 > 273 | MRU#= // [最近開いたファイル] を保存 > 274 | SearchIgnoreCase= // 検索の時大文字小文字の違いを無視するかどうか > 275 | SearchRegExp= // 正規表現検索するかどうか > 276 | NewfileCharset= // 新規作成したファイルの文字コード > 277 | NewfileLB= // 新規作成したファイルの改行コード > 278 | NewfileDoctype= // 新規作成したファイルの文書タイプ > 279 | RememberWindowSize= // ウインドウサイズを再開時に再現するなら1 > 280 | RememberWindowPos= // ウインドウ位置を再開時に再現するなら1 > 281 | WndX= > 282 | WndY= > 283 | WndW= > 284 | WndH= > 285 | WndM= // 記憶されたウインドウサイズや位置 > 286 | > 287 | [DocType] > 288 | 1= > 289 | 2= // 文書タイプの名前を列挙。連番なら幾つまで並べてもOK > 290 | > 291 | [文書タイプ名] > 292 | Pattern= // この文書タイプを自動適用するファイル名を正規表現で > 293 | // (ファイル名全体にマッチするように) > 294 | Keyword= // キーワードファイルの名前 > 295 | Layout= // レイアウトファイルの名前 > 296 | ------------------------------------------------------------------ > 297 | > 298 | ユーザーごとに設定を変えたりしたくない場合は、次のように、 > 299 | SharedConfigというセクションと、Enable=1 という行を書いておく。 > 300 | > 301 | ------------------------------------------------------------------ > 302 | [SharedConfig] > 303 | Enable=1 > 304 | ------------------------------------------------------------------ > 305 | > 306 | こうすると、設定項目はすべてこのSharedConfigセクションから読み書き > 307 | されるようになる。設定済みGreenPadをiniと合わせて色々な環境へ > 308 | 持ち運びたいときに便利。 > 309 > 310 > 311 <<謝辞>> > 312 > 313 ・アイコンはSB氏 ( http://homepage3.nifty.com/scriba/ ) に > 314 制作していただきました。感謝。 > 315 > 316 > 317 <<更新履歴>> > 318 > 319 2008/04/29 【ver 1.08】 > 320   ・再変換しようとすると強制終了するバグを修正 > 321 2008/04/17 > 322   ・U版ではメモリ管理をWindowsに完全に任せるように変更 > 323   ・検索文字列が「見つかりませんでした」ダイアログをモーダルにしました > 324 2008/04/05 【ver 1.08 beta】 > 325 ・強制終了するバグをいくつか修正 > 326 ・BMP外の文字(サロゲートペアで表現される文字)にごまかしごまかし対応 > 327 ・新たに、UTF-32 の読み書き、Win95 での UTF-8 の読み書きでBMP外の文字をサ|ート > 328 ・カーソル移動がちゃんとサロゲートペアを1文字として扱うようにしました > 329 ・描画時の文字幅もちゃんとなったはず > 330 ・検索ダイアログのタブ移動順を変更 > 331 ・Home/End キーでは物理行ではなく表示行単位の移動としました > 332 2006/12/04 【ver 1.07.4】 > 333 ・ISO-8859-1 が標準文字コードの環境で、保存時にファイルが消える致命的なバグC正 > 334 2006/11/30 > 335 ・Win95で動作するように修正 > 336 2006/11/25 【ver 1.07.3】 > 337 ・英語版で Save As... メニューのショートカットが変だったのを修正 > 338 ・時々文字が描画されないことがある問題に対処 > 339 2006/11/22 【ver 1.07.2】 > 340 ・Win98 でウインドウ位置やサイズを保存できてなかったバグ修正 > 341 2006/11/17 【ver 1.07.1】 > 342 ・16x16 のアイコンを入れるようにした > 343 ・コンパイル/リンクオプション調整 > 344 2006/11/13 > 345 ・デフォルト設定の、Javaモード判定用正規表現が間違ってたので修正 > 346 ・内部文字列バッファはWORD整列してメモリ確保するよう修正 > 347 2006/11/09 【ver 1.07】 > 348 ・Undoと文字入力の組み合わせによって、保存ができないタイミングがあったバグ修正 > 349 ・バージョン情報の「ファイル名」を「GreenPad」に変更 > 350 ・スクロールバーの右クリックのメニューの"最上部"、"最下部"が動くように修正 > 351 ・正規表現検索でスタック食いつぶして落ちることはないように修正 > 352 ・外部Grep起動コマンドに %D(ディレクトリ名), %F(フルパス), %N(ファイル名) > 353 を使えるようにした。従来の%1(ディレクトリ名)も互換性のために残してあります。 > 354 ・改行がないファイルの保存時改行コードは、新規ファイルの場合にそろえるように修正 > 355 ・中国語/韓国語環境では、EUC-JPの自動判定を行わないようにした(GBやUHCの誤判阮h止) > 356 ・添付予約語ファイルをいくつか追加 > 357 2005/11/27 【ver 1.06.2】 > 358 ・キリル語、ギリシャ語、中央ヨーロッパ語として使うコードページを修正 > 359 ・日韓中以外の言語環境でも、ANSIコードページをデフォルトとして使うように変更 > 360 2005/10/23 【ver 1.06.1】 > 361 ・S版で「開く」「保存」ダイアログが出なくなっていたバグ修正 > 362 ・タイトルバーをクリックしたときシステムメニューが出ないバグ修正 > 363 ・環境によってステータスバーにカーソル位置表示が出ないバグ修正 > 364 2005/10/21 > 365 ・S版で、外部Grepを呼び出せなくなっていたバグ修正 > 366 2005/10/20 【ver 1.06】 > 367 ・前回終了時のウインドウの位置とサイズを復元する機能を追加 > 368 ・d.kwdを最新の言語仕様に追従。その他kwdファイルの整理 > 369 2005/10/18 > 370 ・新規ファイルのデフォルト文字コードや文書タイプの設定を追加 > 371 ・iniファイルに、ユーザ毎に設定を分けないSharedConfigモード追加 > 372 ・Windows x64 版対応 > 373 ・MinGW でリソース以外はコンパイル可能にした > 374 ・DigitalMars C++ でちゃんとコンパイル可能にした > 375 2005/05/26 > 376 ・HALさんのdelphi/asm/b2e用kwdを添付。 > 377 2005/03/11 > 378 ・U版でファイルの保存時に、指定より一個親のフォルダに > 379 保存してしまうことがあったバグを修正。 > 380 2004/07/29 【ver 1.05】 > 381 ・Windows XP SP2 の Execution Protection 下でも実行できるように修正したつも閨B > 382 ・開いているファイルのあるディレクトリを外から削除できるように修正。 > 383 ・日本語/英語以外のファイル名も「最近のファイル」で扱えるようにした。 > 384 2004/06/20 > 385 ・全置換をUndoする際にも↓と同じ問題が残っていたので修正。 > 386 ・HALさんによるdelphi用のkwd/layを添付。 > 387 2004/06/13 > 388 ・改行を削除して複数行を繋げた際に行番号表示がおかしくなるバグ修正 > 389 ・[開く]や[保存]ダイアログで文字コード関係のボックスにTABキーで移動可能にしス。 > 390 ・全置換の際にカーソル位置の更新をステータスバーに毎回反映してて > 391 遅かったバグを修正(つまり、ステータスバーの更新頻度を下げた。) > 392 2003/09/27 > 393 ・カーソル上下移動時の右寄せを左寄せに変えた > 394 2003/05/13 【ver 1.04.2】 > 395 ・関係ないメニューでステータスバーON/OFFしてしまうバグ修正…(^^;; > 396 2003/05/09 【ver 1.04】 > 397 ・ファイル履歴最大を20件にしたつもりが7件だったバグ修正。 > 398 ・横位置を文字数で表示モードでない場合、TABの扱いが不自然だったバグ修正。 > 399 ・ステータスバーON/OFF > 400 ・WM_COPY, WM_CUT, WM_PASTE, WM_UNDO, EM_UNDO, EM_CANUNDO, EM_SETREADONLY > 401 に反応するようにしたつもり。肝心なGETSEL/SETSEL系はチト面倒いので後回し。 > 402 2003/02/10 > 403 ・BDF UM+ ( http://www.kaoriya.net/#FONT ) というフォントがあるそうです。 > 404 2003/02/08 【ver 1.03】 > 405 ・ファイル履歴が2件までしか記録出来なくなってたバグ修正。 > 406 ・Arial Unicode が自由にダウンロードできなくなったらしいので、 > 407 Unicodeモードのフォントを Bitstream Cyberbit に変えようとしたところ、 > 408 こちらも有料になってしまったらしい。他にフリーのUnicode2.0フルの > 409 フォントなんて知らないよー。(T_T) > 410 2003/01/21 > 411 ・UTF-8判別ルーチンの強化 > 412 2003/01/18 > 413 ・TAB幅調整 > 414 ( これ↓のWin2k以前の仕様に対処する方法が思いつかない。。。 ) > 415 ( http://www.microsoft.com/japan/msdn/windows/windowsxp/FixedPitchFont.asp > 416 2002/12/21 > 417 ・検索ダイアログ開きっぱなしモード(改) > 418 2002/12/14 【ver 1.02】 > 419 ・検索ダイアログ開きっぱなしモード > 420 ・検索ダイアログの設定保存 > 421 ・選択中文字列を検索ダイアログへ反映 > 422 ・選択範囲再変換機能搭載 > 423 2002/12/09 > 424 ・英語版ReadMeを書いてみた。 > 425 2002/12/08 > 426 ・設定項目の中に両端に""がある文字列を正しく保存出来ないバグ修正 > 427 ・GreenPad.iniを開くとGreenPad.iniの末尾にゴミがくっつくことがある問題修正 > 428 >読み込みオープン中のファイルをWritePrivateXXXで弄るとマズかったみたいB > 429 ・行番号色変更を可能にした。 > 430 ・外部Grepの起動フォルダが正しくないことがあったバグ修正 > 431 2002/09/22 【ver 1.01】 > 432 ・Win95で通常の検索が出来ないバグ修正 > 433 ・アイコン変更 > 434 ・C++の文書タイプ用パターンの修正 > 435 ・perl/php/css用のキーワードファイルを標準添付 > 436 2002/07/26 【ver 1.00】 > 437 ・文字数カウントをSJISでのバイト数でも行えるように。 > 438 2002/07/20 > 439 ・WinNT4でも実行時に変化するメニュー項目が壊滅してたのを修正。 > 440 2002/07/17 > 441 ・Win95で、実行時に変化するメニュー項目が全滅してたのを修正。 > 442 ・Win95で、UTF-8の読み書き、UTF-7の書きが出来なくなってたのを修正。 > 443 2002/07/15 > 444 ・Win9x系で全くファイルを開けなくなってたのを修正 > 445 2002/07/14 > 446 ・排他処理をゆるくした > 447 ・[最近のファイル] メニューをようやく実装 > 448 2002/07/11 > 449 ・「同じウィンドウで開く」実装 > 450 ・ステータスバーに改行コードを表示するようにした > 451 2002/07/09 > 452 ・正規表現の\wと\Wが逆だったのを修正 > 453 ・Win9xでのコピー&ペーストが致命的にバグってたのを修正 > 454 ・メニューのチェック表示をラジオボタン的に > 455 ・GreenPad.iniの改行コードがCRのみになっちゃうバグ修正 > 456 2002/07/06 > 457 ・設定ダイアログ完成。 > 458 ・RC1に向け色々整備開始。 > 459 2002/07/02 > 460 ・文書タイプ部分の設定ダイアログとかiniへの保存とか。 > 461 2002/07/01 > 462 ・設定ダイアログの共通項目保存部分完成。あとは文書タイプ。 > 463 2002/06/30 > 464 ・設定ダイアログ作り始め > 465 ・外部grep呼び出し機能追加。 > 466 2002/06/29 > 467 ・英語版リソース追加 > 468 2002/06/24 > 469 ・行頭を表す正規表現^が正しく働いてなかったので修正 > 470 2002/06/19 > 471 ・layout変更の際にカーソルサイズを変更してなかったバグ修正 > 472 2002/06/17 > 473 ・Ctrl+Tab / Ctrl+Shift+Tab に対応 > 474 ・ステータスバーにカーソル座標を表示するようにした > 475 2002/06/05 > 476 ・正規表現検索の方も完成。 > 477 2002/06/04 > 478 ・文書タイプ選択でのRegExp利用版を完成させる。 > 479 2002/06/03 > 480 ・正規表現のマッチングルーチン暫定版完成。 > 481 2002/06/01 > 482 ・「見つかりませんでした」を出すようにした。 > 483 ・上書き保存時に文書タイプが戻ってしまうバグ修正 > 484 ・文書タイプメニューのチェックマーク位置が正しくなるように修正 > 485 ・タイプ選択ルーチンを暫定的に拡張子マッチングにしてみた。 > 486 2002/05/23 > 487 ・検索メニューがグレーアウトしてたバグ修正 > 488 ・置換機能実装。 > 489 ・全置換も実装。あとは、見つからなかったときのメッセージを出すとかやらないと。 > 490 2002/05/21 > 491 ・単純な前後検索(CaseIgnoreも可)は実装できた。 > 492 [前を検索]などのUIはも少し考える必要がありそうだ。 > 493 2002/05/18 > 494 ・[検索]用のフレーム作成。単純検索は、あとはカーソルとの連携のみ。 > 495 ・この版からCVSを導入してみた。 > 496 ・Gp本体部分のccdoc用ソースコメントもpkg化。 > 497 2002/05/06 > 498 ・[開く][保存] ダイアログの初期ディレクトリが変だったので修正 > 499 ・[表示>文書タイプ] メニュー > 500 2002/05/05 > 501 ・[開く]メニューまわりのソースの再構成。少しすっきりした。 > 502 ・開き直す、の時は文書タイプの読み直しを行わないようにした。 > 503 ・Undoに回数制限をかけたときのdirty flagの動作が変だったので修正 > 504 ・8.3形式で渡されても名前部分だけは内部でLFNに変換するようにした。 > 505 ・MLU以外の項目を全てiniから読み出すようにした。ただし Pattern は > 506 まだ読み出すだけで使っていない。ここには正規表現を使いたいので。 > 507 ・テスト用にb2e.kwdとini.kwdを作ってみたりする。 > 508 2002/05/04 > 509 ・grep。-l オプションにて、 > 510 PGrep( http://osaka.cool.ne.jp/parasa/ ) > 511 JGREP( http://www.hi-ho.ne.jp/jun_miura/jgrep.htm ) > 512 GrepJuice( http://hp.vector.co.jp/authors/VA016609/ ) > 513 の外部ビューワとして利用できることを確認。 > 514 ・名前を付けて保存、のタイミングで文書タイプのReloadを行うようにした > 515 ・DigitalMars の smake 用の makefile をまともなものに書き直し > 516 2002/05/03 > 517 ・*.iniファイルの項目決定&読み込みルーチン作成 > 518 ・検索とかのダイアログだけ作ってみた > 519 ・Insertキーに反応するようにした。 > 520 ・Ctrl+BackSpace で確定取り消し…というのをIMEが勝手に > 521 やってくれるらしい。面白い。(^^) > 522 ・-l## オプション(開くときに指定行番号へジャンプ)実装 > 523 ・ついでに行番号ジャンプダイアログも実装 > 524 ・F5で日時挿入機能実装 > 525 2002/04/28 > 526 ・*.layファイルのフォーマット決定&読み込みルーチン作成 > 527 ・c.kwd と html.kwd を書き直し > 528 ・ソースにVC.NET用のプロジェクトファイルを追加 > 529 こっちの方がexeのサイズが小さくなることが判明。(^^; > 530 2002/04/27 > 531 ・4バイト以下のファイルを自動判定で読むとバグるのを修正 > 532 ・未保存を表す * の表示制御を適切に行うようにした。 > 533 ・文書タイプ別設定のフレームワークづくり > 534 ・折り返し方法切り替えのメニューとかつけてみた > 535 ・ウインドウへファイルをD&Dしたら開くようにした > 536 2002/04/25 > 537 ・BM法による検索ルーチンを作ったけど取り込んでない。 > 538 2002/04/24: > 539 ・[開く][保存]ダイアログにデフォルトで現在のファイル名が表示されるよーに。 > 540 ・[開く][保存]ダイアログに「テキスト形式のファイル」って項目を。 > 541 ・新規作成した時点では[保存]できなくなってたバグ修正。 > 542 2002/04/23 > 543 ・[ファイル][編集] メニューのグレーアウト制御 > 544 ・未保存ファイルを破棄しようとしてるときの問い合わせ処理全般 > 545 ・ダブルクリックで単語選択 > 546 ・Undo/Redoの回数制限機能 > 547 2002/04/22 > 548 ・簡易クリップボード制御ライブラリをGpに統合 > 549 ・Undo/Redo (回数無制限) > 550 ・ファイル保存時のメモリ確保に関する致命的バグ修正 > 551 ・単語が消える問題に、二重TextOutによる応急処置 > 552 2001/08/05 - 2002/04/21 > 553 ・(記録が残っていません。残念。) > 554 2001/08/04 > 555 ・開発スタート > 556 > 557 > 558 <<ライセンス>> > 559 > 560 NYSL Version 0.9982 http://www.kmonos.net/nysl/ > 561 > 562 A. 本ソフトウェアは Everyone'sWare です。このソフトを手にした一人一人が、 > 563 ご自分の作ったものを扱うのと同じように、自由に利用することが出来ます。 > 564 > 565 A-1. フリーウェアです。作者からは使用料等を要求しません。 > 566 A-2. 有料無料や媒体の如何を問わず、自由に転載・再配布できます。 > 567 A-3. いかなる種類の 改変・他プログラムでの利用 を行っても構いません。 > 568 A-4. 変更したものや部分的に使用したものは、あなたのものになります。 > 569 公開する場合は、あなたの名前の下で行って下さい。 > 570 > 571 B. このソフトを利用することによって生じた損害等について、作者は > 572 責任を負わないものとします。各自の責任においてご利用下さい。 > 573 > 574 C. 著作者人格権は k.inaba に帰属します。著作権は放棄します。 > 575 > 576 D. 以上の3項は、ソース・実行バイナリの双方に適用されます。 > 577 > 578 > 579 --------------------------------------------------------------------------- > 580 by k.inaba( http://www.kmonos.net/ )

Added release/type/C#.kwd version [ad426b7003c7466c]

cannot compute difference between binary files

Added release/type/C.kwd version [af5b5763401f9d62]

cannot compute difference between binary files

Added release/type/CSS.kwd version [154488afcdbc18cf]

cannot compute difference between binary files

Added release/type/D.kwd version [8f34ed709c56bfbe]

cannot compute difference between binary files

Added release/type/Delphi.kwd version [c2b8286ecff6ab7e]

cannot compute difference between binary files

Added release/type/Erlang.kwd version [fa674a7d7f5f2803]

cannot compute difference between binary files

Added release/type/HTML.kwd version [bcc48d5df9d738c6]

cannot compute difference between binary files

Added release/type/Haskell.kwd version [58ba6e7e25f5c6e7]

cannot compute difference between binary files

Added release/type/Java.kwd version [87d699ad82619471]

cannot compute difference between binary files

Added release/type/JavaScript.kwd version [3c80a2a95488f95a]

cannot compute difference between binary files

Added release/type/Lua.kwd version [8bdaec83a8614208]

cannot compute difference between binary files

Added release/type/OCaml.kwd version [9ae1c109a3b252d4]

cannot compute difference between binary files

Added release/type/PHP.kwd version [6502bc631bcbd487]

cannot compute difference between binary files

Added release/type/Perl.kwd version [2911b36abc38e4c0]

cannot compute difference between binary files

Added release/type/Python.kwd version [2a6051770f815127]

cannot compute difference between binary files

Added release/type/Ruby.kwd version [58c95a5eee341111]

cannot compute difference between binary files

Added release/type/asm.kwd version [f49cec2d93a24170]

cannot compute difference between binary files

Added release/type/b2e.kwd version [0191f97695669abc]

cannot compute difference between binary files

Added release/type/default.lay version [1e9cfd4ecec22dc3]

cannot compute difference between binary files

Added release/type/html.lay version [047516c168f611e7]

cannot compute difference between binary files

Added release/type/ini.kwd version [cd344f7f535888c7]

cannot compute difference between binary files

Added release/type/program.lay version [f08df96cba17006c]

cannot compute difference between binary files

Added release/type/unitext.lay version [edf43401b0a93fce]

cannot compute difference between binary files

Added rsrc/exefile.ico version [cf5ae6cc2663d634]

cannot compute difference between binary files

Added rsrc/gp_rsrc.rc version [eace87903f72cbef]

> 1 > 2 #include "resource.h" > 3 #ifndef DS_SETFOREGROUND > 4 #define DS_SETFOREGROUND 0x200L > 5 #endif > 6 #ifndef RT_MANIFEST > 7 #define RT_MANIFEST 24 > 8 #endif > 9 > 10 #include <winresrc.h> > 11 #include <winuser.h> > 12 #define IDC_STATIC (-1) > 13 > 14 ///////////////////////////////////////////////////////////////////////////// > 15 // 日本語 resources > 16 > 17 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) > 18 #ifdef _WIN32 > 19 LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT > 20 #pragma code_page(932) > 21 #endif //_WIN32 > 22 > 23 ///////////////////////////////////////////////////////////////////////////// > 24 // > 25 // RT_MANIFEST > 26 // > 27 > 28 1 RT_MANIFEST "manifest.xml" > 29 > 30 ///////////////////////////////////////////////////////////////////////////// > 31 // > 32 // Version > 33 // > 34 > 35 VS_VERSION_INFO VERSIONINFO > 36 FILEVERSION 0,0,4,0 > 37 PRODUCTVERSION 0,1,8,0 > 38 FILEFLAGSMASK 0x3fL > 39 #ifdef _DEBUG > 40 FILEFLAGS 0x1L > 41 #else > 42 FILEFLAGS 0x0L > 43 #endif > 44 FILEOS 0x4L > 45 FILETYPE 0x1L > 46 FILESUBTYPE 0x0L > 47 BEGIN > 48 BLOCK "StringFileInfo" > 49 BEGIN > 50 BLOCK "041104b0" > 51 BEGIN > 52 VALUE "CompanyName", "kMonos.NET\0" > 53 VALUE "FileDescription", "GreenPad\0" > 54 VALUE "FileVersion", "#42\0" > 55 VALUE "InternalName", "kilib\0" > 56 VALUE "LegalCopyright", "Written by k.inaba 2002-2008.\0" > 57 VALUE "OriginalFilename", "GreenPad.exe\0" > 58 VALUE "ProductName", "GreenPad\0" > 59 VALUE "ProductVersion", "1.08.0\0" > 60 END > 61 END > 62 BLOCK "VarFileInfo" > 63 BEGIN > 64 VALUE "Translation", 0x411, 1200 > 65 END > 66 END > 67 > 68 ///////////////////////////////////////////////////////////////////////////// > 69 // > 70 // Icon > 71 // > 72 > 73 // Icon with lowest ID value placed first to ensure application icon > 74 // remains consistent on all systems. > 75 IDR_MAIN ICON "exefile.ico" > 76 > 77 ///////////////////////////////////////////////////////////////////////////// > 78 // > 79 // Menu > 80 // > 81 > 82 IDR_MAIN MENU > 83 BEGIN > 84 POPUP "ファイル(&F)" > 85 BEGIN > 86 MENUITEM "新規作成(&N)\tCtrl+N", ID_CMD_NEWFILE > 87 MENUITEM SEPARATOR > 88 MENUITEM "開く(&O)...\tCtrl+O", ID_CMD_OPENFILE > 89 MENUITEM "開き直す(&R)...\tCtrl+R", ID_CMD_REOPENFILE > 90 MENUITEM SEPARATOR > 91 MENUITEM "保存(&S)\tCtrl+S", ID_CMD_SAVEFILE > 92 MENUITEM "別名で保存(&A)...\tCtrl+Shift+S", ID_CMD_SAVEFILEAS > 93 MENUITEM SEPARATOR > 94 POPUP "最近のファイル(&M)" > 95 BEGIN > 96 MENUITEM "(no files)", ID_MENUITEM40029, GRAYED > 97 END > 98 MENUITEM SEPARATOR > 99 MENUITEM "終了(&X)", ID_CMD_EXIT > 100 END > 101 POPUP "編集(&E)" > 102 BEGIN > 103 MENUITEM "元に戻す(&U)\tCtrl+Z", ID_CMD_UNDO > 104 MENUITEM "やり直す(&R)\tCtrl+Y", ID_CMD_REDO > 105 MENUITEM SEPARATOR > 106 MENUITEM "切り取り(&X)\tCtrl+X", ID_CMD_CUT > 107 MENUITEM "コピー(&C)\tCtrl+C", ID_CMD_COPY > 108 MENUITEM "貼り付け(&P)\tCtrl+V", ID_CMD_PASTE > 109 MENUITEM "削除(&D)\tDel", ID_CMD_DELETE > 110 MENUITEM SEPARATOR > 111 MENUITEM "全てを選択(&A)\tCtrl+A", ID_CMD_SELECTALL > 112 MENUITEM SEPARATOR > 113 MENUITEM "日時の挿入(&T)\tF5", ID_CMD_DATETIME > 114 END > 115 POPUP "検索(&S)" > 116 BEGIN > 117 MENUITEM "検索・置換(&F)\tCtrl+F", ID_CMD_FIND > 118 MENUITEM "次を検索(&N)\tF3", ID_CMD_FINDNEXT > 119 MENUITEM "前を検索(&P)\tShift+F3", ID_CMD_FINDPREV > 120 MENUITEM SEPARATOR > 121 MENUITEM "指定行へジャンプ(&J)\tCtrl+J", ID_CMD_JUMP > 122 MENUITEM SEPARATOR > 123 MENUITEM "Grep(&G)...\tCtrl+G", ID_CMD_GREP > 124 END > 125 POPUP "表示(&V)" > 126 BEGIN > 127 MENUITEM "折り返さない(&N)\tCtrl+1", ID_CMD_NOWRAP > 128 MENUITEM "指定幅で折り返し(&W)\tCtrl+2", ID_CMD_WRAPWIDTH > 129 MENUITEM "右端で折り返し(&R)\tCtrl+3", ID_CMD_WRAPWINDOW > 130 MENUITEM SEPARATOR > 131 POPUP "文書タイプ(&T)" > 132 BEGIN > 133 MENUITEM "(なし)", ID_MENUITEM40025, GRAYED > 134 END > 135 MENUITEM "設定(&S)...", ID_CMD_CONFIG > 136 MENUITEM SEPARATOR > 137 MENUITEM "ステータス バー(&B)", ID_CMD_STATUSBAR > 138 END > 139 END > 140 > 141 > 142 ///////////////////////////////////////////////////////////////////////////// > 143 // > 144 // Dialog > 145 // > 146 > 147 IDD_OPENFILEHOOK DIALOGEX 0, 0, 187, 34 > 148 STYLE DS_SETFONT | DS_3DLOOK | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS > 149 FONT 9, "MS Pゴシック" > 150 BEGIN > 151 LTEXT "",1119,0,0,187,13,SS_SUNKEN | NOT WS_VISIBLE | NOT > 152 WS_GROUP > 153 LTEXT "文字コード(&C):",IDC_STATIC,7,18,42,8 > 154 COMBOBOX IDC_CODELIST,66,16,111,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 155 WS_TABSTOP > 156 END > 157 > 158 IDD_SAVEFILEHOOK DIALOGEX 0, 0, 187, 55 > 159 STYLE DS_SETFONT | DS_3DLOOK | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS > 160 FONT 9, "MS Pゴシック" > 161 BEGIN > 162 LTEXT "",1119,0,0,187,13,SS_SUNKEN | NOT WS_VISIBLE | NOT > 163 WS_GROUP > 164 LTEXT "文字コード(&C):",IDC_STATIC,7,18,42,8 > 165 COMBOBOX IDC_CODELIST,66,16,111,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 166 WS_TABSTOP > 167 LTEXT "改行コード(&L):",IDC_STATIC,7,37,41,8 > 168 COMBOBOX IDC_CRLFLIST,66,35,60,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 169 WS_TABSTOP > 170 END > 171 > 172 IDD_REOPENDLG DIALOG 0, 0, 187, 54 > 173 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_VISIBLE | > 174 WS_CLIPSIBLINGS | WS_CAPTION > 175 CAPTION "開き直す" > 176 FONT 9, "MS Pゴシック" > 177 BEGIN > 178 LTEXT "文字コード(&C):",IDC_STATIC,9,13,42,8 > 179 COMBOBOX IDC_CODELIST,59,11,111,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 180 WS_TABSTOP > 181 PUSHBUTTON "OK",IDOK,66,32,56,14 > 182 PUSHBUTTON "キャンセル",IDCANCEL,125,32,56,14 > 183 END > 184 > 185 IDD_FINDREPLACE DIALOG 0, 0, 316, 84 > 186 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | > 187 WS_CAPTION | WS_SYSMENU > 188 CAPTION "検索・置換" > 189 FONT 9, "MS ゴシック" > 190 BEGIN > 191 LTEXT "検索文字列(&T):",IDC_STATIC,5,10,61,8 > 192 EDITTEXT IDC_FINDBOX,68,8,122,13,ES_AUTOHSCROLL > 193 LTEXT "置換文字列(&W):",IDC_STATIC,5,31,61,8 > 194 EDITTEXT IDC_REPLACEBOX,68,28,122,13,ES_AUTOHSCROLL > 195 DEFPUSHBUTTON "次を検索(&F)",ID_FINDNEXT,195,8,56,14 > 196 PUSHBUTTON "置換(&R)",ID_REPLACENEXT,195,27,56,14 > 197 PUSHBUTTON "前を検索(&E)",ID_FINDPREV,256,8,55,14 > 198 PUSHBUTTON "全置換(&A)",ID_REPLACEALL,255,27,56,14 > 199 GROUPBOX "オプション(&O)",IDC_STATIC,12,47,213,27 > 200 CONTROL "大文字小文字を区別しない(&I)",IDC_IGNORECASE,"Button", > 201 BS_AUTOCHECKBOX | WS_TABSTOP,22,59,124,10 > 202 CONTROL "正規表現(&X)",IDC_REGEXP,"Button",BS_AUTOCHECKBOX | > 203 WS_TABSTOP,153,58,60,10 > 204 PUSHBUTTON "閉じる",IDCANCEL,244,59,37,14 > 205 END > 206 > 207 IDD_JUMP DIALOG 0, 0, 131, 43 > 208 STYLE DS_ABSALIGN | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | > 209 WS_CAPTION | WS_SYSMENU > 210 CAPTION "指定行へジャンプ" > 211 FONT 9, "MS Pゴシック" > 212 BEGIN > 213 DEFPUSHBUTTON "&Go!",IDOK,87,12,25,14 > 214 EDITTEXT IDC_LINEBOX,14,13,40,12,ES_AUTOHSCROLL | ES_NUMBER > 215 LTEXT "行目へ",IDC_STATIC,61,15,22,8 > 216 END > 217 > 218 IDD_CONFIG DIALOGEX 0, 0, 287, 236 > 219 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU > 220 CAPTION "エディタ設定" > 221 FONT 9, "MS Pゴシック" > 222 BEGIN > 223 GROUPBOX "共通設定",IDC_STATIC,7,11,273,102 > 224 LTEXT "[元に戻す]上限(&U):",IDC_STATIC,24,24,56,8 > 225 CONTROL "無限",IDC_UNDOLIM1,"Button",BS_AUTORADIOBUTTON | > 226 WS_GROUP | WS_TABSTOP,86,23,33,10 > 227 CONTROL "",IDC_UNDOLIM2,"Button",BS_AUTORADIOBUTTON,122,23,11,8 > 228 EDITTEXT IDC_UNDO_CT,134,21,24,12,ES_AUTOHSCROLL | ES_NUMBER > 229 LTEXT "回",IDC_STATIC,162,24,8,8 > 230 LTEXT "横位置の表示(&L):",IDC_STATIC,29,37,51,8 > 231 CONTROL "文字数",IDC_COUNTBYLETTER,"Button",BS_AUTORADIOBUTTON | > 232 WS_GROUP | WS_TABSTOP,86,36,33,10 > 233 CONTROL "表示位置",IDC_COUNTBYLETTER2,"Button", > 234 BS_AUTORADIOBUTTON | WS_TABSTOP,122,35,38,10 > 235 LTEXT "ファイル履歴件数(&H):",IDC_STATIC,19,50,62,8 > 236 EDITTEXT IDC_LATEST_NUM,86,48,32,12,ES_AUTOHSCROLL | ES_NUMBER > 237 LTEXT "ファイル・フィルタ(&F):",IDC_STATIC,21,66,60,8 > 238 EDITTEXT IDC_TXTFILT,86,63,182,12,ES_AUTOHSCROLL > 239 LTEXT "外部Grep(&G):",IDC_STATIC,42,81,39,8 > 240 EDITTEXT IDC_EXTGREP,86,78,182,12,ES_AUTOHSCROLL > 241 LTEXT "新規ファイルのモード(&N):",IDC_STATIC,9,95,73,8 > 242 COMBOBOX IDC_NEWCS,86,92,76,162,CBS_DROPDOWNLIST | WS_VSCROLL | > 243 WS_TABSTOP > 244 COMBOBOX IDC_NEWLB,164,92,39,162,CBS_DROPDOWNLIST | WS_VSCROLL | > 245 WS_TABSTOP > 246 COMBOBOX IDC_NEWDT,204,92,65,164,CBS_DROPDOWNLIST | WS_VSCROLL | > 247 WS_TABSTOP > 248 CONTROL "同じウインドウで開く(&R)",IDC_OPENSAME,"Button", > 249 BS_AUTOCHECKBOX | WS_TABSTOP,181,25,83,10 > 250 CONTROL "ウインドウサイズを記憶(&S)",IDC_REMSIZE,"Button", > 251 BS_AUTOCHECKBOX | WS_TABSTOP,181,35,92,10 > 252 CONTROL "ウインドウ位置を記憶(&P)",IDC_REMPLACE,"Button", > 253 BS_AUTOCHECKBOX | WS_TABSTOP,181,45,86,10 > 254 GROUPBOX "文書タイプ別設定",IDC_STATIC,7,118,274,92 > 255 LISTBOX IDC_DOCTYPELIST,15,133,88,53,LBS_NOINTEGRALHEIGHT | > 256 WS_VSCROLL | WS_TABSTOP > 257 PUSHBUTTON "追加",IDC_NEWDOCTYPE,17,191,29,14 > 258 PUSHBUTTON "削除",IDC_DELDOCTYPE,48,191,29,14 > 259 LTEXT "パターン:",IDC_STATIC,114,138,27,8 > 260 EDITTEXT IDC_DT_PAT,146,135,127,12,ES_AUTOHSCROLL > 261 LTEXT "キーワード:",IDC_STATIC,108,155,34,8 > 262 COMBOBOX IDC_PAT_KWD,146,152,75,172,CBS_DROPDOWNLIST | CBS_SORT | > 263 CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP > 264 PUSHBUTTON "編集",IDC_EDITKWD,231,152,19,14 > 265 LTEXT "レイアウト:",IDC_STATIC,111,172,31,8 > 266 COMBOBOX IDC_PAT_LAY,146,169,75,172,CBS_DROPDOWNLIST | CBS_SORT | > 267 CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP > 268 PUSHBUTTON "編集",IDC_EDITLAY,231,169,19,14 > 269 DEFPUSHBUTTON "OK",IDOK,175,214,50,14 > 270 PUSHBUTTON "キャンセル",IDCANCEL,230,214,50,14 > 271 END > 272 > 273 IDD_ADDDOCTYPE DIALOG 0, 0, 123, 67 > 274 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU > 275 CAPTION "文書タイプの追加" > 276 FONT 9, "MS Pゴシック" > 277 BEGIN > 278 LTEXT "名前(&N):",IDC_STATIC,17,11,27,8 > 279 EDITTEXT IDC_NAME,46,8,69,12,ES_AUTOHSCROLL > 280 LTEXT "拡張子(&E):",IDC_STATIC,10,25,34,8 > 281 EDITTEXT IDC_EXT,46,24,69,12,ES_AUTOHSCROLL > 282 DEFPUSHBUTTON "OK",IDOK,33,43,34,14 > 283 PUSHBUTTON "キャンセル",IDCANCEL,71,43,33,14 > 284 END > 285 > 286 > 287 ///////////////////////////////////////////////////////////////////////////// > 288 // > 289 // Accelerator > 290 // > 291 > 292 IDR_MAIN ACCELERATORS > 293 BEGIN > 294 "1", ID_CMD_NOWRAP, VIRTKEY, CONTROL, NOINVERT > 295 "2", ID_CMD_WRAPWIDTH, VIRTKEY, CONTROL, NOINVERT > 296 "3", ID_CMD_WRAPWINDOW, VIRTKEY, CONTROL, NOINVERT > 297 "A", ID_CMD_SELECTALL, VIRTKEY, CONTROL, NOINVERT > 298 "C", ID_CMD_COPY, VIRTKEY, CONTROL, NOINVERT > 299 "F", ID_CMD_FIND, VIRTKEY, CONTROL, NOINVERT > 300 "G", ID_CMD_GREP, VIRTKEY, CONTROL, NOINVERT > 301 "H", ID_CMD_FIND, VIRTKEY, CONTROL, NOINVERT > 302 "J", ID_CMD_JUMP, VIRTKEY, CONTROL, NOINVERT > 303 "N", ID_CMD_NEWFILE, VIRTKEY, CONTROL, NOINVERT > 304 "O", ID_CMD_OPENFILE, VIRTKEY, CONTROL, NOINVERT > 305 "R", ID_CMD_REOPENFILE, VIRTKEY, CONTROL, NOINVERT > 306 "S", ID_CMD_SAVEFILE, VIRTKEY, CONTROL, NOINVERT > 307 "S", ID_CMD_SAVEFILEAS, VIRTKEY, SHIFT, CONTROL, > 308 NOINVERT > 309 "V", ID_CMD_PASTE, VIRTKEY, CONTROL, NOINVERT > 310 VK_DELETE, ID_CMD_CUT, VIRTKEY, SHIFT, NOINVERT > 311 VK_F3, ID_CMD_FINDNEXT, VIRTKEY, NOINVERT > 312 VK_F3, ID_CMD_FINDPREV, VIRTKEY, SHIFT, NOINVERT > 313 VK_F4, ID_CMD_EXIT, VIRTKEY, CONTROL, NOINVERT > 314 VK_F5, ID_CMD_DATETIME, VIRTKEY, NOINVERT > 315 VK_INSERT, ID_CMD_COPY, VIRTKEY, CONTROL, NOINVERT > 316 VK_INSERT, ID_CMD_PASTE, VIRTKEY, SHIFT, NOINVERT > 317 VK_RETURN, ID_CMD_REOPENFILE, VIRTKEY, ALT, NOINVERT > 318 VK_TAB, ID_CMD_NEXTWINDOW, VIRTKEY, CONTROL, NOINVERT > 319 VK_TAB, ID_CMD_PREVWINDOW, VIRTKEY, SHIFT, CONTROL, > 320 NOINVERT > 321 "X", ID_CMD_CUT, VIRTKEY, CONTROL, NOINVERT > 322 "Y", ID_CMD_REDO, VIRTKEY, CONTROL, NOINVERT > 323 "Z", ID_CMD_UNDO, VIRTKEY, CONTROL, NOINVERT > 324 END > 325 > 326 > 327 ///////////////////////////////////////////////////////////////////////////// > 328 // > 329 // DESIGNINFO > 330 // > 331 > 332 #ifdef APSTUDIO_INVOKED > 333 GUIDELINES DESIGNINFO > 334 BEGIN > 335 IDD_FINDREPLACE, DIALOG > 336 BEGIN > 337 LEFTMARGIN, 7 > 338 RIGHTMARGIN, 309 > 339 TOPMARGIN, 7 > 340 BOTTOMMARGIN, 77 > 341 END > 342 > 343 IDD_JUMP, DIALOG > 344 BEGIN > 345 LEFTMARGIN, 7 > 346 RIGHTMARGIN, 124 > 347 TOPMARGIN, 7 > 348 BOTTOMMARGIN, 36 > 349 END > 350 > 351 IDD_CONFIG, DIALOG > 352 BEGIN > 353 LEFTMARGIN, 7 > 354 RIGHTMARGIN, 280 > 355 TOPMARGIN, 7 > 356 BOTTOMMARGIN, 228 > 357 END > 358 > 359 IDD_ADDDOCTYPE, DIALOG > 360 BEGIN > 361 LEFTMARGIN, 7 > 362 RIGHTMARGIN, 116 > 363 TOPMARGIN, 7 > 364 BOTTOMMARGIN, 60 > 365 END > 366 END > 367 #endif // APSTUDIO_INVOKED > 368 > 369 > 370 ///////////////////////////////////////////////////////////////////////////// > 371 // > 372 // String Table > 373 // > 374 > 375 STRINGTABLE > 376 BEGIN > 377 IDS_ASKTOSAVE "現在の文書を保存しますか?" > 378 IDS_APPNAME "GreenPad" > 379 IDS_SAVEERROR "ファイルの保存に失敗しました。" > 380 IDS_ALLFILES "全てのファイル(*.*)" > 381 IDS_TXTFILES "テキスト形式のファイル" > 382 IDS_OPENERROR "ファイルを開くのに失敗しました。" > 383 IDS_DEFAULT "(標準)" > 384 IDS_NOTFOUND "見つかりませんでした。" > 385 IDS_REPLACEALLDONE "%d箇所置換しました。" > 386 IDS_OKTODEL "を削除してよろしいですか?" > 387 END > 388 > 389 #endif // 日本語 resources > 390 ///////////////////////////////////////////////////////////////////////////// > 391 > 392 > 393 ///////////////////////////////////////////////////////////////////////////// > 394 // 英語 (米国) resources > 395 > 396 #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) > 397 #ifdef _WIN32 > 398 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US > 399 #pragma code_page(1252) > 400 #endif //_WIN32 > 401 > 402 ///////////////////////////////////////////////////////////////////////////// > 403 // > 404 // Menu > 405 // > 406 > 407 IDR_MAIN MENU > 408 BEGIN > 409 POPUP "&File" > 410 BEGIN > 411 MENUITEM "&New File\tCtrl+N", ID_CMD_NEWFILE > 412 MENUITEM SEPARATOR > 413 MENUITEM "&Open...\tCtrl+O", ID_CMD_OPENFILE > 414 MENUITEM "&ReOpen...\tCtrl+R", ID_CMD_REOPENFILE > 415 MENUITEM SEPARATOR > 416 MENUITEM "&Save\tCtrl+S", ID_CMD_SAVEFILE > 417 MENUITEM "Save &As...\tCtrl+Shift+S", ID_CMD_SAVEFILEAS > 418 MENUITEM SEPARATOR > 419 POPUP "R&ecent Files" > 420 BEGIN > 421 MENUITEM "(no files)", ID_MENUITEM40030, GRAYED > 422 END > 423 MENUITEM "E&xit", ID_CMD_EXIT > 424 END > 425 POPUP "&Edit" > 426 BEGIN > 427 MENUITEM "&Undo\tCtrl+Z", ID_CMD_UNDO > 428 MENUITEM "&Redo\tCtrl+Y", ID_CMD_REDO > 429 MENUITEM SEPARATOR > 430 MENUITEM "Cut\tCtrl+&X", ID_CMD_CUT > 431 MENUITEM "&Copy\tCtrl+C", ID_CMD_COPY > 432 MENUITEM "&Paste\tCtrl+V", ID_CMD_PASTE > 433 MENUITEM "&Delete\tDel", ID_CMD_DELETE > 434 MENUITEM SEPARATOR > 435 MENUITEM "Select &All\tCtrl+A", ID_CMD_SELECTALL > 436 MENUITEM SEPARATOR > 437 MENUITEM "Insert Date&&&Time\tF5", ID_CMD_DATETIME > 438 END > 439 POPUP "&Search" > 440 BEGIN > 441 MENUITEM "&Find\tCtrl+F", ID_CMD_FIND > 442 MENUITEM "Find &Next\tF3", ID_CMD_FINDNEXT > 443 MENUITEM "Find &Prev\tShift+F3", ID_CMD_FINDPREV > 444 MENUITEM SEPARATOR > 445 MENUITEM "&Jump to Line\tCtrl+J", ID_CMD_JUMP > 446 MENUITEM SEPARATOR > 447 MENUITEM "&Grep...\tCtrl+G", ID_CMD_GREP > 448 END > 449 POPUP "&View" > 450 BEGIN > 451 MENUITEM "&No wrapping\tCtrl+1", ID_CMD_NOWRAP > 452 MENUITEM "&Wrap at #th letter\tCtrl+2", ID_CMD_WRAPWIDTH > 453 MENUITEM "Wrap at &Right Edge\tCtrl+3", ID_CMD_WRAPWINDOW > 454 MENUITEM SEPARATOR > 455 POPUP "&Document Type" > 456 BEGIN > 457 MENUITEM "dummy", ID_MENUITEM40025 > 458 END > 459 MENUITEM "&Settings...", ID_CMD_CONFIG > 460 MENUITEM SEPARATOR > 461 MENUITEM "Status&Bar", ID_CMD_STATUSBAR > 462 END > 463 END > 464 > 465 > 466 ///////////////////////////////////////////////////////////////////////////// > 467 // > 468 // Dialog > 469 // > 470 > 471 IDD_SAVEFILEHOOK DIALOGEX 0, 0, 187, 55 > 472 STYLE DS_SETFONT | DS_3DLOOK | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS > 473 FONT 9, "MS Sans Serif" > 474 BEGIN > 475 LTEXT "",1119,0,0,187,13,SS_SUNKEN | NOT WS_VISIBLE | NOT > 476 WS_GROUP > 477 LTEXT "&Charactor Encode:",IDC_STATIC,7,18,58,8 > 478 COMBOBOX IDC_CODELIST,69,16,108,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 479 WS_TABSTOP > 480 LTEXT "&Line-end:",IDC_STATIC,7,37,41,8 > 481 COMBOBOX IDC_CRLFLIST,69,35,57,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 482 WS_TABSTOP > 483 END > 484 > 485 IDD_REOPENDLG DIALOG 0, 0, 187, 54 > 486 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | WS_VISIBLE | > 487 WS_CLIPSIBLINGS | WS_CAPTION > 488 CAPTION "ReOpen File" > 489 FONT 9, "MS Sans Serif" > 490 BEGIN > 491 LTEXT "&Charactor Encode:",IDC_STATIC,9,13,54,8 > 492 COMBOBOX IDC_CODELIST,72,11,105,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 493 WS_TABSTOP > 494 PUSHBUTTON "OK",IDOK,66,32,56,14 > 495 PUSHBUTTON "Cancel",IDCANCEL,125,32,56,14 > 496 END > 497 > 498 IDD_OPENFILEHOOK DIALOGEX 0, 0, 187, 34 > 499 STYLE DS_SETFONT | DS_3DLOOK | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS > 500 FONT 9, "MS Sans Serif" > 501 BEGIN > 502 LTEXT "",1119,0,0,187,13,SS_SUNKEN | NOT WS_VISIBLE | NOT > 503 WS_GROUP > 504 LTEXT "&Charactor Encode:",IDC_STATIC,7,18,54,8 > 505 COMBOBOX IDC_CODELIST,66,16,111,103,CBS_DROPDOWNLIST | WS_VSCROLL | > 506 WS_TABSTOP > 507 END > 508 > 509 IDD_JUMP DIALOG 0, 0, 131, 43 > 510 STYLE DS_ABSALIGN | DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | > 511 WS_CAPTION | WS_SYSMENU > 512 CAPTION "Jump To" > 513 FONT 9, "MS Sans Serif" > 514 BEGIN > 515 DEFPUSHBUTTON "&Go!",IDOK,83,13,25,14 > 516 EDITTEXT IDC_LINEBOX,34,14,40,12,ES_AUTOHSCROLL | ES_NUMBER > 517 LTEXT "&Line",IDC_STATIC,17,16,13,8 > 518 END > 519 > 520 IDD_FINDREPLACE DIALOG 0, 0, 282, 84 > 521 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | > 522 WS_CAPTION | WS_SYSMENU > 523 CAPTION "Find & Replace" > 524 FONT 9, "MS Sans Serif" > 525 BEGIN > 526 LTEXT "&Text to Find:",IDC_STATIC,7,10,38,8 > 527 EDITTEXT IDC_FINDBOX,56,7,123,13,ES_AUTOHSCROLL > 528 DEFPUSHBUTTON "&Find",ID_FINDNEXT,185,8,43,14 > 529 PUSHBUTTON "Find&Prev",ID_FINDPREV,232,8,43,14 > 530 LTEXT "Replace &with:",IDC_STATIC,7,31,40,8 > 531 EDITTEXT IDC_REPLACEBOX,56,28,123,13,ES_AUTOHSCROLL > 532 PUSHBUTTON "&Replace",ID_REPLACENEXT,185,27,43,14 > 533 PUSHBUTTON "Replace&All",ID_REPLACEALL,232,27,43,14 > 534 GROUPBOX "&Options",IDC_STATIC,12,47,181,27 > 535 CONTROL "&Ignore Case",IDC_IGNORECASE,"Button",BS_AUTOCHECKBOX | > 536 WS_TABSTOP,22,59,51,10 > 537 CONTROL "Regular E&xpression",IDC_REGEXP,"Button", > 538 BS_AUTOCHECKBOX | WS_TABSTOP,114,58,73,10 > 539 PUSHBUTTON "Close",IDCANCEL,244,59,29,14 > 540 END > 541 > 542 IDD_ADDDOCTYPE DIALOG 0, 0, 123, 67 > 543 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU > 544 CAPTION "New DocType" > 545 FONT 9, "MS Sans Serif" > 546 BEGIN > 547 LTEXT "&Name:",IDC_STATIC,22,11,19,8 > 548 EDITTEXT IDC_NAME,46,8,69,12,ES_AUTOHSCROLL > 549 LTEXT "&Extension:",IDC_STATIC,10,25,34,8 > 550 EDITTEXT IDC_EXT,46,24,69,12,ES_AUTOHSCROLL > 551 DEFPUSHBUTTON "OK",IDOK,33,43,34,14 > 552 PUSHBUTTON "Cancel",IDCANCEL,71,43,33,14 > 553 END > 554 > 555 IDD_CONFIG DIALOGEX 0, 0, 287, 236 > 556 STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU > 557 CAPTION "Config" > 558 FONT 9, "MS Sans Serif" > 559 BEGIN > 560 GROUPBOX "Common",IDC_STATIC,7,7,273,106 > 561 LTEXT "&Undo:",IDC_STATIC,62,21,25,8 > 562 CONTROL "Infinite",IDC_UNDOLIM1,"Button",BS_AUTORADIOBUTTON | > 563 WS_GROUP | WS_TABSTOP,88,20,33,10 > 564 CONTROL "",IDC_UNDOLIM2,"Button",BS_AUTORADIOBUTTON,124,20,11,8 > 565 EDITTEXT IDC_UNDO_CT,135,18,24,12,ES_AUTOHSCROLL | ES_NUMBER > 566 LTEXT "times",IDC_STATIC,163,21,17,8 > 567 LTEXT "&Column by:",IDC_STATIC,46,33,40,8 > 568 CONTROL "Letters",IDC_COUNTBYLETTER,"Button",BS_AUTORADIOBUTTON | > 569 WS_GROUP | WS_TABSTOP,88,32,33,10 > 570 CONTROL "Positions",IDC_COUNTBYLETTER2,"Button", > 571 BS_AUTORADIOBUTTON | WS_TABSTOP,124,32,49,10 > 572 LTEXT "M&RU File Num:",IDC_STATIC,34,45,52,8 > 573 EDITTEXT IDC_LATEST_NUM,88,43,32,12,ES_AUTOHSCROLL | ES_NUMBER > 574 LTEXT "TextFile &Filter:",IDC_STATIC,36,63,44,8 > 575 EDITTEXT IDC_TXTFILT,88,59,176,12,ES_AUTOHSCROLL > 576 LTEXT "Extrenal &Grep Program:",IDC_STATIC,12,77,77,8 > 577 EDITTEXT IDC_EXTGREP,88,75,176,12,ES_AUTOHSCROLL > 578 LTEXT "&New File Mode:",IDC_STATIC,34,93,53,8 > 579 COMBOBOX IDC_NEWCS,88,90,76,167,CBS_DROPDOWNLIST | WS_VSCROLL | > 580 WS_TABSTOP > 581 COMBOBOX IDC_NEWLB,166,90,39,166,CBS_DROPDOWNLIST | WS_VSCROLL | > 582 WS_TABSTOP > 583 COMBOBOX IDC_NEWDT,206,90,65,165,CBS_DROPDOWNLIST | WS_VSCROLL | > 584 WS_TABSTOP > 585 CONTROL "Open in Same &Window",IDC_OPENSAME,"Button", > 586 BS_AUTOCHECKBOX | WS_TABSTOP,186,17,90,10 > 587 CONTROL "Remember Window &Size",IDC_REMSIZE,"Button", > 588 BS_AUTOCHECKBOX | WS_TABSTOP,186,27,92,10 > 589 CONTROL "Remember Window &Pos",IDC_REMPLACE,"Button", > 590 BS_AUTOCHECKBOX | WS_TABSTOP,186,38,90,10 > 591 GROUPBOX "Document Types",IDC_STATIC,6,118,274,92 > 592 LISTBOX IDC_DOCTYPELIST,14,133,89,53,LBS_NOINTEGRALHEIGHT | > 593 WS_VSCROLL | WS_TABSTOP > 594 PUSHBUTTON "Add",IDC_NEWDOCTYPE,17,191,29,14 > 595 PUSHBUTTON "Del",IDC_DELDOCTYPE,50,191,29,14 > 596 LTEXT "Pattern:",IDC_STATIC,117,138,23,8 > 597 EDITTEXT IDC_DT_PAT,149,135,123,12,ES_AUTOHSCROLL > 598 LTEXT "Keyword:",IDC_STATIC,114,155,27,8 > 599 COMBOBOX IDC_PAT_KWD,149,152,72,172,CBS_DROPDOWNLIST | CBS_SORT | > 600 CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP > 601 PUSHBUTTON "edit",IDC_EDITKWD,229,151,19,14 > 602 LTEXT "Layout: ",IDC_STATIC,118,172,24,8 > 603 COMBOBOX IDC_PAT_LAY,149,169,72,172,CBS_DROPDOWNLIST | CBS_SORT | > 604 CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP > 605 PUSHBUTTON "edit",IDC_EDITLAY,229,169,19,14 > 606 DEFPUSHBUTTON "OK",IDOK,175,215,50,14 > 607 PUSHBUTTON "Cancel",IDCANCEL,230,215,50,14 > 608 END > 609 > 610 > 611 ///////////////////////////////////////////////////////////////////////////// > 612 // > 613 // DESIGNINFO > 614 // > 615 > 616 #ifdef APSTUDIO_INVOKED > 617 GUIDELINES DESIGNINFO > 618 BEGIN > 619 IDD_JUMP, DIALOG > 620 BEGIN > 621 LEFTMARGIN, 7 > 622 RIGHTMARGIN, 124 > 623 TOPMARGIN, 7 > 624 BOTTOMMARGIN, 36 > 625 END > 626 > 627 IDD_FINDREPLACE, DIALOG > 628 BEGIN > 629 LEFTMARGIN, 7 > 630 RIGHTMARGIN, 275 > 631 TOPMARGIN, 7 > 632 BOTTOMMARGIN, 77 > 633 END > 634 > 635 IDD_ADDDOCTYPE, DIALOG > 636 BEGIN > 637 LEFTMARGIN, 7 > 638 RIGHTMARGIN, 116 > 639 TOPMARGIN, 7 > 640 BOTTOMMARGIN, 60 > 641 END > 642 > 643 IDD_CONFIG, DIALOG > 644 BEGIN > 645 LEFTMARGIN, 7 > 646 RIGHTMARGIN, 280 > 647 TOPMARGIN, 7 > 648 BOTTOMMARGIN, 229 > 649 END > 650 END > 651 #endif // APSTUDIO_INVOKED > 652 > 653 > 654 ///////////////////////////////////////////////////////////////////////////// > 655 // > 656 // String Table > 657 // > 658 > 659 STRINGTABLE > 660 BEGIN > 661 IDS_ASKTOSAVE "Do you want to Save the current file ?" > 662 IDS_APPNAME "GreenPad" > 663 IDS_SAVEERROR "Could not save the file." > 664 IDS_ALLFILES "All Files(*.*)" > 665 IDS_TXTFILES "Text Files" > 666 IDS_OPENERROR "Could not open the file." > 667 IDS_DEFAULT "(default)" > 668 IDS_NOTFOUND "Not Found." > 669 IDS_REPLACEALLDONE "%d times Replaced." > 670 IDS_OKTODEL " will be removed. OK?" > 671 END > 672 > 673 #endif // 英語 (米国) resources > 674 /////////////////////////////////////////////////////////////////////////////

Added rsrc/manifest.xml version [adc8ffd4825a9049]

> 1 <?xml version="1.0" standalone="yes"?> > 2 <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><depend

Added rsrc/resource.h version [feca3a05cea60d4e]

> 1 //{{NO_DEPENDENCIES}} > 2 // Microsoft Visual C++ generated include file. > 3 // Used by kilib.rc > 4 // > 5 #define IDS_ASKTOSAVE 1 > 6 #define IDS_APPNAME 2 > 7 #define IDS_SAVEERROR 3 > 8 #define ID_FINDNEXT 3 > 9 #define IDS_ALLFILES 4 > 10 #define ID_REPLACENEXT 4 > 11 #define IDS_TXTFILES 5 > 12 #define ID_REPLACEALL 5 > 13 #define IDS_OPENERROR 6 > 14 #define IDS_DEFAULT 7 > 15 #define IDS_NOTFOUND 8 > 16 #define IDS_REPLACEALLDONE 9 > 17 #define IDS_OKTODEL 10 > 18 #define IDR_MAIN 103 > 19 #define IDD_OPENFILEHOOK 105 > 20 #define IDD_SAVEFILEHOOK 106 > 21 #define IDD_REOPENDLG 107 > 22 #define IDD_FINDREPLACE 108 > 23 #define IDD_JUMP 109 > 24 #define IDD_CONFIG 110 > 25 #define IDD_ADDDOCTYPE 111 > 26 #define IDC_CODELIST 1002 > 27 #define IDC_CRLFLIST 1003 > 28 #define IDC_FINDBOX 1004 > 29 #define IDC_REPLACE 1005 > 30 #define IDC_REPLACEBOX 1005 > 31 #define IDC_IGNORECASE 1006 > 32 #define IDC_REGEXP 1007 > 33 #define IDC_LINEBOX 1007 > 34 #define IDC_BACKSEARCH 1008 > 35 #define ID_FINDPREV 1008 > 36 #define IDC_LATEST_NUM 1010 > 37 #define IDC_UNDOLIM1 1011 > 38 #define IDC_UNDOLIM2 1012 > 39 #define IDC_UNDO_CT 1013 > 40 #define IDC_TXTFILT 1014 > 41 #define IDC_EXTGREP 1015 > 42 #define IDC_DT_PAT 1018 > 43 #define IDC_PAT_KWD 1019 > 44 #define IDC_DOCTYPELIST 1020 > 45 #define IDC_NEWDOCTYPE 1021 > 46 #define IDC_PAT_LAY 1022 > 47 #define IDC_DELDOCTYPE 1023 > 48 #define IDC_EDITKWD 1024 > 49 #define IDC_EDITLAY 1025 > 50 #define IDC_NAME 1025 > 51 #define IDC_EXT 1026 > 52 #define IDC_OPENSAME 1026 > 53 #define IDC_COUNTBYLETTER 1027 > 54 #define IDC_NEWCS 1028 > 55 #define IDC_NEWLB 1029 > 56 #define IDC_OPENSAME2 1030 > 57 #define IDC_REMSIZE 1030 > 58 #define IDC_OPENSAME3 1031 > 59 #define IDC_REMPLACE 1031 > 60 #define IDC_COUNTBYLETTER2 1032 > 61 #define IDC_NEWLB2 1033 > 62 #define IDC_NEWDT 1033 > 63 #define ID_CMD_REOPENFILE 40002 > 64 #define ID_CMD_PROPERTY 40003 > 65 #define ID_CMD_NEWFILE 40004 > 66 #define ID_CMD_OPENFILE 40005 > 67 #define ID_CMD_SAVEFILE 40006 > 68 #define ID_CMD_SAVEFILEAS 40007 > 69 #define ID_CMD_EXIT 40008 > 70 #define ID_CMD_UNDO 40009 > 71 #define ID_CMD_REDO 40010 > 72 #define ID_CMD_CUT 40011 > 73 #define ID_CMD_COPY 40012 > 74 #define ID_CMD_PASTE 40013 > 75 #define ID_CMD_DELETE 40014 > 76 #define ID_CMD_SELECTALL 40015 > 77 #define ID_CMD_FIND 40016 > 78 #define ID_CMD_FINDNEXT 40017 > 79 #define ID_CMD_FINDPREV 40018 > 80 #define ID_CMD_NOWRAP 40019 > 81 #define ID_CMD_WRAPWIDTH 40020 > 82 #define ID_CMD_WRAPWINDOW 40021 > 83 #define ID_CMD_CONFIG 40022 > 84 #define ID_CMD_JUMP 40023 > 85 #define ID_CMD_DATETIME 40024 > 86 #define ID_MENUITEM40025 40025 > 87 #define ID_CMD_NEXTWINDOW 40026 > 88 #define ID_CMD_PREVWINDOW 40027 > 89 #define ID_CMD_GREP 40028 > 90 #define ID_MENUITEM40029 40029 > 91 #define ID_MENUITEM40030 40030 > 92 #define ID_CMD_STATUSBAR 40032 > 93 #define ID_CMD_MRU 40200 > 94 #define ID_CMD_DOCTYPE 40300 > 95 > 96 // Next default values for new objects > 97 // > 98 #ifdef APSTUDIO_INVOKED > 99 #ifndef APSTUDIO_READONLY_SYMBOLS > 100 #define _APS_NEXT_RESOURCE_VALUE 113 > 101 #define _APS_NEXT_COMMAND_VALUE 40033 > 102 #define _APS_NEXT_CONTROL_VALUE 1029 > 103 #define _APS_NEXT_SYMED_VALUE 102 > 104 #endif > 105 #endif