rtoss - Blame information for rev 159

Subversion Repositories:
Rev:
Rev Author Line No. Line
89 roytam 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;
90 roytam 67         if( ::GetTextExtentPoint32( dc, TEXT("BBBWW"), 5, &s ) )
89 roytam 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_RIGHTBUTTON,
95 roytam 126                                 static_cast<SHORT>(LOWORD(lp)), static_cast<SHORT>(HIWORD(lp)), 0, hwnd(), NULL );
89 roytam 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  
90 roytam 147         // NOTIFY
148         case WM_NOTIFY:
149                 if( ((NMHDR*)lp)->code == NM_DBLCLK )
150                         if( wp == 1787 ) // Status Bar ID
151                                 on_reopenfile();
152                 break;
153  
89 roytam 154         // その他
155         default:
156                 return WndImpl::on_message( msg, wp, lp );
157         }
158  
159         return 0;
160 }
161  
162 bool GreenPadWnd::on_command( UINT id, HWND ctrl )
163 {
164         switch( id )
165         {
166         // Window
167         case ID_CMD_NEXTWINDOW: on_nextwnd(); break;
168         case ID_CMD_PREVWINDOW: on_prevwnd(); break;
169  
170         // File
171         case ID_CMD_NEWFILE:    on_newfile();   break;
172         case ID_CMD_OPENFILE:   on_openfile();  break;
173         case ID_CMD_REOPENFILE: on_reopenfile();break;
174         case ID_CMD_SAVEFILE:   on_savefile();  break;
175         case ID_CMD_SAVEFILEAS: on_savefileas();break;
156 roytam 176         case ID_CMD_PRINT:      on_print();     break;
155 roytam 177         case ID_CMD_SAVEEXIT:   if(Save_showDlgIfNeeded()) on_exit();  break;
156 roytam 178         case ID_CMD_DISCARDEXIT: Destroy();     break;
89 roytam 179         case ID_CMD_EXIT:       on_exit();      break;
180  
181         // Edit
182         case ID_CMD_UNDO:       edit_.getDoc().Undo();              break;
183         case ID_CMD_REDO:       edit_.getDoc().Redo();              break;
184         case ID_CMD_CUT:        edit_.getCursor().Cut();            break;
185         case ID_CMD_COPY:       edit_.getCursor().Copy();           break;
186         case ID_CMD_PASTE:      edit_.getCursor().Paste();          break;
187         case ID_CMD_DELETE: if( edit_.getCursor().isSelected() )
188                                 edit_.getCursor().Del();            break;
189         case ID_CMD_SELECTALL:  edit_.getCursor().Home(true,false);
190                                 edit_.getCursor().End(true,true);   break;
191         case ID_CMD_DATETIME:   on_datetime();                      break;
158 roytam 192         case ID_CMD_RECONV:     on_reconv();                        break;
193         case ID_CMD_TOGGLEIME:  on_toggleime();                     break;
89 roytam 194  
195         // Search
196         case ID_CMD_FIND:       search_.ShowDlg();  break;
197         case ID_CMD_FINDNEXT:   search_.FindNext(); break;
198         case ID_CMD_FINDPREV:   search_.FindPrev(); break;
199         case ID_CMD_JUMP:       on_jump(); break;
200         case ID_CMD_GREP:       on_grep();break;
201  
202         // View
203         case ID_CMD_NOWRAP:     edit_.getView().SetWrapType( wrap_=-1 ); break;
204         case ID_CMD_WRAPWIDTH:  edit_.getView().SetWrapType( wrap_=cfg_.wrapWidth() ); break;
205         case ID_CMD_WRAPWINDOW: edit_.getView().SetWrapType( wrap_=0 ); break;
206         case ID_CMD_CONFIG:     on_config();    break;
207         case ID_CMD_STATUSBAR:  on_statusBar(); break;
208  
209         // DocType
210         default: if( ID_CMD_DOCTYPE <= id ) {
211                         on_doctype( id - ID_CMD_DOCTYPE );
212                         break;
213                 } else if( ID_CMD_MRU <= id ) {
214                         on_mru( id - ID_CMD_MRU );
215                         break;
216                 }
217  
218         // Default
219                 return false;
220         }
221         return true;
222 }
223  
224 bool GreenPadWnd::PreTranslateMessage( MSG* msg )
225 {
226         // 苦肉の策^^;
227         if( search_.TrapMsg(msg) )
228                 return true;
229         // キ[ボ[ドショ[トカット処理
230         return 0 != ::TranslateAccelerator( hwnd(), accel_, msg );
231 }
232  
233  
234  
235 //-------------------------------------------------------------------------
236 // コマンド処理
237 //-------------------------------------------------------------------------
238  
239 void GreenPadWnd::on_dirtyflag_change( bool )
240 {
241         UpdateWindowName();
242 }
243  
244 void GreenPadWnd::on_newfile()
245 {
246         BootNewProcess();
247 }
248  
249 void GreenPadWnd::on_openfile()
250 {
251         Path fn;
252         int  cs;
253         if( ShowOpenDlg( &fn, &cs ) )
254                 Open( fn, cs );
255 }
256  
257 void GreenPadWnd::on_reopenfile()
258 {
259         if( !isUntitled() )
260         {
261                 ReopenDlg dlg( charSets_, csi_ );
262                 dlg.GoModal( hwnd() );
263                 if( dlg.endcode()==IDOK && AskToSave() )
264                         OpenByMyself( filename_, charSets_[dlg.csi()].ID, false );
265         }
266 }
267  
268 void GreenPadWnd::on_savefile()
269 {
270         Save_showDlgIfNeeded();
271 }
272  
273 void GreenPadWnd::on_savefileas()
274 {
275         if( ShowSaveDlg() )
276         {
277                 Save();
278                 ReloadConfig(); // 文書タイプに応じて表示を更新
279         }
280 }
281  
156 roytam 282 void GreenPadWnd::on_print()
283 {
284         TCHAR tmp[128];
285  
286         doc::Document& d = edit_.getDoc();
287         const unicode* buf;
288         ulong dpStart = 0, len = 0;
289         short procCopies = 0, totalCopies = 0;
290  
291         PRINTDLG thePrintDlg = { sizeof(thePrintDlg) };
292         thePrintDlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION | PD_HIDEPRINTTOFILE;
293         thePrintDlg.nCopies = 1;
294  
295         if (PrintDlg(&thePrintDlg) == 0) {
296                 // cancelled
297                 return;
298         }
299  
300         totalCopies = thePrintDlg.nCopies;
301  
302         // タイトルに表示される文字列の調整
303         // FileName * - GreenPad
304         String name;
305         name += isUntitled() ? TEXT("untitled") : filename_.name();
306         if( edit_.getDoc().isModified() ) name += TEXT(" *");
307         name += TEXT(" - ");
308         name += String(IDS_APPNAME).c_str();
309  
310         // Set DOCINFO structure
311         DOCINFO di = { sizeof(DOCINFO) };
312         di.lpszDocName = name.c_str();
313         di.lpszOutput = (LPTSTR) NULL;
314         di.lpszDatatype = (LPTSTR) NULL;
315         di.fwType = 0;
157 roytam 316         RECT rctmp = { 0, 0, 0, 0 };
156 roytam 317  
318         int nError = ::StartDoc(thePrintDlg.hDC, &di);
319         if (nError == SP_ERROR)
320         {
321                 ::wsprintf(tmp,TEXT("StartDoc Error #%d - please check printer."),::GetLastError());
322                 ::MessageBox( NULL, tmp, String(IDS_APPNAME).c_str(), MB_OK|MB_TASKMODAL );
323                 return;
324                 // Handle the error intelligently
325         }
326         ::StartPage(thePrintDlg.hDC);
327  
328         // Get Printer Caps
329         int cWidthPels, cHeightPels, cLineHeight;
330         cWidthPels = ::GetDeviceCaps(thePrintDlg.hDC, HORZRES);
331         cHeightPels = ::GetDeviceCaps(thePrintDlg.hDC, VERTRES);
332  
333         // Get Line height
157 roytam 334         rctmp.right = cWidthPels;
335         rctmp.bottom = cHeightPels;
336         ::DrawTextW(thePrintDlg.hDC, L"#", 1, &rctmp, DT_CALCRECT|DT_LEFT|DT_WORDBREAK|DT_EXPANDTABS|DT_EDITCONTROL);
337         cLineHeight = rctmp.bottom-rctmp.top;
156 roytam 338  
157 roytam 339         RECT rcPrinter = { 5, 5, cWidthPels - 10, cHeightPels - 10 };
156 roytam 340  
157 roytam 341         int nThisLineHeight, nChars = 0, nHi = 0, nLo = 0;
342         const unicode* uStart;
343  
156 roytam 344         // Process with multiple copies
345         do {
346                 if(procCopies)
347                 {
348                         ::StartPage(thePrintDlg.hDC);
349                         rcPrinter.top = 5;
350                         rcPrinter.left = 5;
351                         rcPrinter.right = cWidthPels - 10;
352                         rcPrinter.bottom = cHeightPels - 10;
353                 }
157 roytam 354                 // Print
355                 for( ulong e=d.tln(), dpStart=0; dpStart<e; )
156 roytam 356                 {
357                         len = d.len(dpStart);
358                         buf = d.tl(dpStart);
359                         if(!len)
360                         {       // Empty Line
361                                 rcPrinter.top += cLineHeight;
157 roytam 362                                 ++dpStart;
156 roytam 363                         }
364                         else
365                         {
157 roytam 366                                 rctmp = rcPrinter;
367                                 nHi = len;
368                                 nLo = 0;
369                                 if(!nChars)
370                                 {
371                                         uStart = buf;
372                                         nChars = len;
373                                 }
374                                 else
375                                 {
376                                         uStart += nChars;
377                                         nHi = nChars = len-nChars;
378                                 }
379  
380                                 while (nLo < nHi) { // Find maximum number of chars can be printed
381                                         rctmp.top = rcPrinter.top;
382                                         nThisLineHeight = ::DrawTextW(thePrintDlg.hDC, uStart, nChars, &rctmp, DT_CALCRECT|DT_WORDBREAK|DT_NOCLIP|DT_EXPANDTABS|DT_NOPREFIX|DT_EDITCONTROL);
383                                         if (rcPrinter.top+nThisLineHeight < rcPrinter.bottom)
384                                                 nLo = nChars;
385                                         if (rcPrinter.top+nThisLineHeight > rcPrinter.bottom)
386                                                 nHi = nChars;
387                                         if (nLo == nHi - 1)
388                                                 nChars = nHi = nLo;
389                                         if (nLo < nHi)
390                                                 nChars = nLo + (nHi - nLo)/2;
391                                 }
392                                 rcPrinter.top += ::DrawTextW(thePrintDlg.hDC, uStart, nChars, &rcPrinter, DT_WORDBREAK|DT_NOCLIP|DT_EXPANDTABS|DT_NOPREFIX|DT_EDITCONTROL);
393                                 if(uStart+nChars == buf+len) // Line end
394                                 {
395                                         nChars = 0;
396                                         ++dpStart;
397                                 }
156 roytam 398                         }
399  
400                         // turn to new page
401                         if( (dpStart<e) && (rcPrinter.top + cLineHeight + 5 > rcPrinter.bottom) )
402                         {
403                                 ::EndPage(thePrintDlg.hDC);
404                                 ::StartPage(thePrintDlg.hDC);
405                                 rcPrinter.top = 5;
406                                 rcPrinter.left = 5;
407                                 rcPrinter.right = cWidthPels - 10;
408                                 rcPrinter.bottom = cHeightPels - 10;
409                         }
410                 }
411  
412                 ::EndPage(thePrintDlg.hDC);
413         } while(++procCopies < totalCopies);
414  
415         // Close Printer
416         ::EndDoc(thePrintDlg.hDC);
417         ::DeleteDC(thePrintDlg.hDC);
418  
419         /*
420         ::GlobalUnlock(thePrintDlg.hDevNames);
421         ::GlobalUnlock(thePrintDlg.hDevMode);
422  
423         // 解放する。
424         ::GlobalFree(thePrintDlg.hDevNames);
425         ::GlobalFree(thePrintDlg.hDevMode);
426         */
427 }
428  
89 roytam 429 void GreenPadWnd::on_exit()
430 {
431         search_.SaveToINI( cfg_.getImpl() );
432         if( AskToSave() )
433                 Destroy();
434 }
435  
436 void GreenPadWnd::on_initmenu( HMENU menu, bool editmenu_only )
437 {
124 roytam 438 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
89 roytam 439         LOGGER("GreenPadWnd::ReloadConfig on_initmenu begin");
122 roytam 440         if(app().isNewShell())
441         {
442                 MENUITEMINFO mi = { sizeof(MENUITEMINFO), MIIM_STATE };
89 roytam 443  
122 roytam 444                 mi.fState =
445                         (edit_.getCursor().isSelected() ? MFS_ENABLED : MFS_DISABLED);
446                 ::SetMenuItemInfo( menu, ID_CMD_CUT, FALSE, &mi );
447                 ::SetMenuItemInfo( menu, ID_CMD_COPY, FALSE, &mi );
448                 ::SetMenuItemInfo( menu, ID_CMD_DELETE, FALSE, &mi );
89 roytam 449  
122 roytam 450                 mi.fState =
451                         (edit_.getDoc().isUndoAble() ? MFS_ENABLED : MFS_DISABLED);
452                 ::SetMenuItemInfo( menu, ID_CMD_UNDO, FALSE, &mi );
89 roytam 453  
122 roytam 454                 mi.fState =
159 roytam 455                         (edit_.getCursor().isSelected() && ime().IsIME() && ime().CanReconv() ? MFS_ENABLED : MFS_DISABLED);
158 roytam 456                 ::SetMenuItemInfo( menu, ID_CMD_RECONV, FALSE, &mi );
457                 mi.fState =
458                         (ime().IsIME() ? MFS_ENABLED : MFS_DISABLED);
459                 ::SetMenuItemInfo( menu, ID_CMD_TOGGLEIME, FALSE, &mi );
460  
461                 mi.fState =
122 roytam 462                         (edit_.getDoc().isRedoAble() ? MFS_ENABLED : MFS_DISABLED);
463                 ::SetMenuItemInfo( menu, ID_CMD_REDO, FALSE, &mi );
89 roytam 464  
122 roytam 465                 if( editmenu_only )
466                 {
467                         LOGGER("GreenPadWnd::ReloadConfig on_initmenu end");
468                         return;
469                 }
470  
471                 mi.fState = (isUntitled() || edit_.getDoc().isModified()
472                         ? MFS_ENABLED : MFS_DISABLED);
473                 ::SetMenuItemInfo( menu, ID_CMD_SAVEFILE, FALSE, &mi );
474  
475                 mi.fState =
476                         (!isUntitled() ? MFS_ENABLED : MFS_DISABLED);
477                 ::SetMenuItemInfo( menu, ID_CMD_REOPENFILE, FALSE, &mi );
478  
479                 mi.fState =
480                         (cfg_.grepExe().len()>0 ? MFS_ENABLED : MFS_DISABLED);
481                 ::SetMenuItemInfo( menu, ID_CMD_GREP, FALSE, &mi );
482  
483                 UINT id = (wrap_==-1 ? ID_CMD_NOWRAP
484                         : (wrap_>0 ? ID_CMD_WRAPWIDTH : ID_CMD_WRAPWINDOW));
485                 ::CheckMenuRadioItem(
486                         menu, ID_CMD_NOWRAP, ID_CMD_WRAPWINDOW, id, MF_BYCOMMAND );
487         }
488         else
124 roytam 489 #endif
89 roytam 490         {
122 roytam 491                 ::EnableMenuItem( menu, ID_CMD_CUT, MF_BYCOMMAND|(edit_.getCursor().isSelected() ? MF_ENABLED : MF_GRAYED) );
492                 ::EnableMenuItem( menu, ID_CMD_COPY, MF_BYCOMMAND|(edit_.getCursor().isSelected() ? MF_ENABLED : MF_GRAYED) );
493                 ::EnableMenuItem( menu, ID_CMD_DELETE, MF_BYCOMMAND|(edit_.getCursor().isSelected() ? MF_ENABLED : MF_GRAYED) );
494                 ::EnableMenuItem( menu, ID_CMD_UNDO, MF_BYCOMMAND|(edit_.getDoc().isUndoAble() ? MF_ENABLED : MF_GRAYED) );
495                 ::EnableMenuItem( menu, ID_CMD_REDO, MF_BYCOMMAND|(edit_.getDoc().isRedoAble() ? MF_ENABLED : MF_GRAYED) );
159 roytam 496                 ::EnableMenuItem( menu, ID_CMD_RECONV, MF_BYCOMMAND|(edit_.getCursor().isSelected() && ime().IsIME() && ime().CanReconv() ? MF_ENABLED : MF_GRAYED) );
158 roytam 497                 ::EnableMenuItem( menu, ID_CMD_TOGGLEIME, MF_BYCOMMAND|(ime().IsIME() ? MF_ENABLED : MF_GRAYED) );
89 roytam 498  
122 roytam 499                 if( editmenu_only )
500                 {
501                         LOGGER("GreenPadWnd::ReloadConfig on_initmenu end");
502                         return;
503                 }
89 roytam 504  
122 roytam 505                 ::EnableMenuItem( menu, ID_CMD_SAVEFILE, MF_BYCOMMAND|(isUntitled() || edit_.getDoc().isModified() ? MF_ENABLED : MF_GRAYED) );
506                 ::EnableMenuItem( menu, ID_CMD_REOPENFILE, MF_BYCOMMAND|(!isUntitled() ? MF_ENABLED : MF_GRAYED) );
507                 ::EnableMenuItem( menu, ID_CMD_GREP, MF_BYCOMMAND|(cfg_.grepExe().len()>0 ? MF_ENABLED : MF_GRAYED) );
89 roytam 508  
122 roytam 509                 ::CheckMenuItem( menu, ID_CMD_NOWRAP, MF_BYCOMMAND|(wrap_==-1?MF_CHECKED:MF_UNCHECKED));
510                 ::CheckMenuItem( menu, ID_CMD_WRAPWIDTH, MF_BYCOMMAND|(wrap_>0?MF_CHECKED:MF_UNCHECKED));
511                 ::CheckMenuItem( menu, ID_CMD_WRAPWINDOW, MF_BYCOMMAND|(wrap_==0?MF_CHECKED:MF_UNCHECKED));
512         }
89 roytam 513  
124 roytam 514 #if defined(TARGET_VER) && TARGET_VER==310
515         ::EnableMenuItem( menu, ID_CMD_STATUSBAR, MF_BYCOMMAND|MF_GRAYED );
516 #else
89 roytam 517         ::CheckMenuItem( menu, ID_CMD_STATUSBAR,
122 roytam 518                 cfg_.showStatusBar()?MF_CHECKED:MF_UNCHECKED );
124 roytam 519 #endif
89 roytam 520         LOGGER("GreenPadWnd::ReloadConfig on_initmenu end");
521 }
522  
523 void GreenPadWnd::on_drop( HDROP hd )
524 {
525         UINT iMax = ::DragQueryFile( hd, 0xffffffff, NULL, 0 );
526         for( UINT i=0; i<iMax; ++i )
527         {
528                 TCHAR str[MAX_PATH];
529                 ::DragQueryFile( hd, i, str, countof(str) );
530                 Open( str, AutoDetect );
531         }
532         ::DragFinish( hd );
533 }
534  
535 void GreenPadWnd::on_jump()
536 {
537         struct JumpDlg : public DlgImpl {
538                 JumpDlg(HWND w) : DlgImpl(IDD_JUMP), w_(w) { GoModal(w); }
539                 void on_init() {
540                         SetCenter(hwnd(),w_); ::SetFocus(item(IDC_LINEBOX)); }
541                 bool on_ok() {
542                         TCHAR str[100];
543                         ::GetWindowText( item(IDC_LINEBOX), str, countof(str) );
544                         LineNo = String(str).GetInt();
545                         return true;
546                 }
547                 int LineNo; HWND w_;
548         } dlg(hwnd());
549  
550         if( IDOK == dlg.endcode() )
551                 JumpToLine( dlg.LineNo );
552 }
553  
554 void GreenPadWnd::on_grep()
555 {
556         Path g = cfg_.grepExe();
557         if( g.len() != 0 )
558         {
559                 Path d;
560                 if( filename_.len() )
561                         (d = filename_).BeDirOnly().BeBackSlash(false);
562                 else
563                         d = Path(Path::Cur);
564  
565                 String fcmd;
566                 for( int i=0, e=g.len(); i<e; ++i )
567                         if( g[i]==TEXT('%') )
568                         {
569                                 if( g[i+1]==TEXT('1') || g[i+1]==TEXT('D') ) // '1' for bkwd compat
570                                         ++i, fcmd += d;
571                                 else if( g[i+1]==TEXT('F') )
572                                         ++i, fcmd += filename_;
573                                 else if( g[i+1]==TEXT('N') )
574                                         ++i, fcmd += filename_.name();
575                         }
576                         else
577                                 fcmd += g[i];
578  
579                 PROCESS_INFORMATION psi;
580                 STARTUPINFO         sti = {sizeof(STARTUPINFO)};
581                 //sti.dwFlags = STARTF_USESHOWWINDOW;
582                 //sti.wShowWindow = SW_SHOWNORMAL;
583                 if( ::CreateProcess( NULL, const_cast<TCHAR*>(fcmd.c_str()),
584                                 NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL,
585                                 &sti, &psi ) )
586                 {
587                         ::CloseHandle( psi.hThread );
588                         ::CloseHandle( psi.hProcess );
589                 }
590         }
591 }
592  
593 void GreenPadWnd::on_datetime()
594 {
94 roytam 595         String g = cfg_.dateFormat();
89 roytam 596         TCHAR buf[255], tmp[255];
597         ::GetTimeFormat
94 roytam 598                 ( LOCALE_USER_DEFAULT, 0, NULL, g.len()?const_cast<TCHAR*>(g.c_str()):TEXT("HH:mm yyyy/MM/dd"), buf, countof(buf));
89 roytam 599         ::GetDateFormat
94 roytam 600                 ( LOCALE_USER_DEFAULT, 0, NULL, buf, tmp,countof(tmp));
601         edit_.getCursor().Input( tmp, ::lstrlen(tmp) );
89 roytam 602 }
603  
604 void GreenPadWnd::on_doctype( int no )
605 {
606         if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),3),4 ) )
607         {
608                 cfg_.SetDocTypeByMenu( no, m );
609                 ReloadConfig( true );
610         }
611 }
612  
613 void GreenPadWnd::on_config()
614 {
615         if( cfg_.DoDialog(*this) )
616         {
617                 SetupSubMenu();
618                 SetupMRUMenu();
619                 ReloadConfig(false);
620         }
621 }
622  
623 static inline void MyShowWnd( HWND wnd )
624 {
625         if( ::IsIconic(wnd) )
626                 ::ShowWindow( wnd, SW_RESTORE );
627         ::BringWindowToTop( wnd );
628 }
629  
630 void GreenPadWnd::on_nextwnd()
631 {
124 roytam 632 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
89 roytam 633         if( HWND next = ::FindWindowEx( NULL, hwnd(), className_, NULL ) )
634         {
635                 HWND last=next, pos;
636                 while( last != NULL )
637                         last = ::FindWindowEx( NULL, pos=last, className_, NULL );
638                 if( pos != next )
639                         ::SetWindowPos( hwnd(), pos,
640                                 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW );
641                 MyShowWnd( next );
642         }
124 roytam 643 #endif
89 roytam 644 }
645  
646 void GreenPadWnd::on_prevwnd()
647 {
124 roytam 648 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
89 roytam 649         HWND pos=NULL, next=::FindWindowEx( NULL,NULL,className_,NULL );
650         if( next==hwnd() )
651         {
652                 while( next != NULL )
653                         next = ::FindWindowEx( NULL,pos=next,className_,NULL );
654                 if( pos!=hwnd())
655                         MyShowWnd( pos );
656         }
657         else
658         {
659                 while( next!=hwnd() && next!=NULL )
660                         next = ::FindWindowEx( NULL,pos=next,className_,NULL );
661                 if( next!=NULL )
662                         MyShowWnd( pos );
663         }
124 roytam 664 #endif
89 roytam 665 }
666  
667 void GreenPadWnd::on_statusBar()
668 {
669         stb_.SetStatusBarVisible( !stb_.isStatusBarVisible() );
670         cfg_.ShowStatusBarSwitch();
671  
672         WINDOWPLACEMENT wp = {sizeof(wp)};
673         ::GetWindowPlacement( hwnd(), &wp );
674         if( wp.showCmd != SW_MINIMIZE )
675         {
676                 const int ht = stb_.AutoResize( wp.showCmd == SW_MAXIMIZE );
677                 RECT rc;
678                 getClientRect(&rc);
679                 edit_.MoveTo( 0, 0, rc.right, rc.bottom-ht );
680         }
681 }
682  
683 void GreenPadWnd::on_move( const DPos& c, const DPos& s )
684 {
685         static int busy_cnt = 0;
686         if( edit_.getDoc().isBusy() && ((++busy_cnt)&0xff) )
687                 return;
688  
689         ulong cad = c.ad;
690         if( ! cfg_.countByUnicode() )
691         {
692                 // ShiftJIS風のByte数カウント
693                 const unicode* cu = edit_.getDoc().tl(c.tl);
694                 const ulong tab = cfg_.vConfig().tabstep;
695                 cad = 0;
696                 for( ulong i=0; i<c.ad; ++i )
697                         if( cu[i] == L'\t' )
698                                 cad = (cad/tab+1)*tab;
699                         else if( cu[i]<0x80 || 0xff60<=cu[i] && cu[i]<=0xff9f )
700                                 cad = cad + 1;
701                         else
702                                 cad = cad + 2;
703         }
704  
705         String str;
706         str += TEXT('(');
707         str += String().SetInt(c.tl+1);
708         str += TEXT(',');
709         str += String().SetInt(cad+1);
710         str += TEXT(')');
711         if( c != s )
712         {
713                 ulong sad = s.ad;
714                 if( ! cfg_.countByUnicode() )
715                 {
716                         // ShiftJIS風のByte数カウント
717                         const unicode* su = edit_.getDoc().tl(s.tl);
718                         sad = 0;
719                         for( ulong i=0; i<s.ad; ++i )
720                                 sad += (su[i]<0x80 || 0xff60<=su[i] && su[i]<=0xff9f ? 1 : 2);
721                 }
722                 str += TEXT(" - (");
723                 str += String().SetInt(s.tl+1);
724                 str += TEXT(',');
725                 str += String().SetInt(sad+1);
726                 str += TEXT(')');
727         }
728         stb_.SetText( str.c_str() );
729 }
730  
158 roytam 731 void GreenPadWnd::on_reconv()
732 {
733         edit_.getCursor().Reconv();
734 }
735 void GreenPadWnd::on_toggleime()
736 {
737         edit_.getCursor().ToggleIME();
738 }
89 roytam 739  
740 //-------------------------------------------------------------------------
741 // ユ[ティリティ[
742 //-------------------------------------------------------------------------
743  
744 void GreenPadWnd::JumpToLine( ulong ln )
745 {
746         edit_.getCursor().MoveCur( DPos(ln-1,0), false );
747 }
748  
749 void GreenPadWnd::SetupSubMenu()
750 {
751         if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),3),4 ) )
752         {
753                 cfg_.SetDocTypeMenu( m, ID_CMD_DOCTYPE );
754                 ::DrawMenuBar( hwnd() );
755         }
756 }
757  
758 void GreenPadWnd::UpdateWindowName()
759 {
760         // タイトルバ[に表示される文字列の調整
761         // [FileName *] - GreenPad
762         String name;
763         name += TEXT('[');
764         name += isUntitled() ? TEXT("untitled") : filename_.name();
765         if( edit_.getDoc().isModified() ) name += TEXT(" *");
766         name += TEXT("] - ");
767         name += String(IDS_APPNAME).c_str();
768  
769         SetText( name.c_str() );
104 roytam 770         stb_.SetCsText( csi_==0xffffffff?TEXT("UNKN"):charSets_[csi_].shortName );
89 roytam 771         stb_.SetLbText( lb_ );
772 }
773  
774 void GreenPadWnd::SetupMRUMenu()
775 {
776         if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),0),8 ) )
777         {
778                 cfg_.SetUpMRUMenu( m, ID_CMD_MRU );
779                 ::DrawMenuBar( hwnd() );
780         }
781 }
782  
783 void GreenPadWnd::on_mru( int no )
784 {
785         Path fn = cfg_.GetMRU(no);
786         if( fn.len() != 0 )
787                 Open( fn, AutoDetect );
788 }
789  
790  
791  
792 //-------------------------------------------------------------------------
793 // 設定更新処理
794 //-------------------------------------------------------------------------
795  
796 void GreenPadWnd::ReloadConfig( bool noSetDocType )
797 {
798         // 文書タイプロ[ド
799         if( !noSetDocType )
800         {
801                 int t = cfg_.SetDocType( filename_ );
802                 if( HMENU m = ::GetSubMenu( ::GetSubMenu(::GetMenu(hwnd()),3),4 ) )
803                         cfg_.CheckMenu( m, t );
804         }
805         LOGGER("GreenPadWnd::ReloadConfig DocTypeLoaded");
806  
807         // Undo回数制限
808         edit_.getDoc().SetUndoLimit( cfg_.undoLimit() );
809  
810         // 行番号
811         bool ln = cfg_.showLN();
812         edit_.getView().ShowLineNo( ln );
813  
814         // 折り返し方式
815         wrap_ = cfg_.wrapType();
816         edit_.getView().SetWrapType( wrap_ );
817  
818         // 色・フォント
819         VConfig vc = cfg_.vConfig();
820         edit_.getView().SetFont( vc );
821         LOGGER("GreenPadWnd::ReloadConfig ViewConfigLoaded");
822  
823         // キ[ワ[ドファイル
824         Path kwd = cfg_.kwdFile();
825         FileR fp;
826         if( kwd.len()!=0 && fp.Open(kwd.c_str()) )
827                 edit_.getDoc().SetKeyword((const unicode*)fp.base(),fp.size()/2);
828         else
829                 edit_.getDoc().SetKeyword(NULL,0);
830         LOGGER("GreenPadWnd::ReloadConfig KeywordLoaded");
831 }
832  
833  
834  
835 //-------------------------------------------------------------------------
836 // 開く処理
837 //-------------------------------------------------------------------------
838  
839 bool GreenPadWnd::ShowOpenDlg( Path* fn, int* cs )
840 {
841         // [Open][Cancel] 開くファイル名指定ダイアログを表示
842         String flst[] = {
843                 String(IDS_TXTFILES),
844                 String(cfg_.txtFileFilter()),
845                 String(IDS_ALLFILES),
846                 String(TEXT("*.*"))
847         };
848         aarr<TCHAR> filt = OpenFileDlg::ConnectWithNull(flst,countof(flst));
849  
850         OpenFileDlg ofd( charSets_ );
851         bool ok = ofd.DoModal( hwnd(), filt.get(), filename_.c_str() );
852         if( ok )
853         {
854                 *fn = ofd.filename();
855                 *cs = charSets_[ofd.csi()].ID;
856         }
857  
858         return ok;
859 }
860  
861 bool GreenPadWnd::Open( const ki::Path& fn, int cs )
862 {
863         if( isUntitled() && !edit_.getDoc().isModified() )
864         {
865                 // 無題で無変更だったら自分で開く
866                 return OpenByMyself( fn, cs );
867         }
868         else
869         {
870                 // 同じ窓で開くモ[ドならそうする
871                 if( cfg_.openSame() )
872                         return ( AskToSave() ? OpenByMyself( fn, cs ) : true );
873  
874                 // そうでなければ他へ回す
875                 String
876                         cmd  = TEXT("-c");
877                         cmd += String().SetInt( cs );
878                         cmd += TEXT(" \"");
879                         cmd += fn;
880                         cmd += TEXT('\"');
881                 BootNewProcess( cmd.c_str() );
882                 return true;
883         }
884 }
885  
886 bool GreenPadWnd::OpenByMyself( const ki::Path& fn, int cs, bool needReConf )
887 {
888         // ファイルを開けなかったらそこでおしまい。
889         aptr<TextFileR> tf( new TextFileR(cs) );
890         if( !tf->Open( fn.c_str() ) )
891         {
892                 // ERROR!
893                 MsgBox( String(IDS_OPENERROR).c_str() );
894                 return false;
895         }
896  
897         // 自分内部の管理情報を更新
898         if( fn[0]==TEXT('\\') || fn[1]==TEXT(':') )
899                 filename_ = fn;
900         else
901                 filename_ = Path( Path::Cur ) + fn;
902         if( tf->size() )
903         {
904                 csi_      = charSets_.findCsi( tf->codepage() );
905                 if( tf->nolb_found() )
906                         lb_       = cfg_.GetNewfileLB();
907                 else
908                         lb_       = tf->linebreak();
909         }
910         else
911         { // 空ファイルの場合は新規作成と同じ扱い
912                 csi_      = cfg_.GetNewfileCsi();
913                 lb_       = cfg_.GetNewfileLB();
914         }
915         filename_.BeShortLongStyle();
916  
917         // カレントディレクトリを、ファイルのある位置以外にしておく
918         // (こうしないと、開いているファイルのあるディレクトリが削除できない)
919         ::SetCurrentDirectory( Path(filename_).BeDriveOnly().c_str() );
920  
921         // 文書タイプに応じて表示を更新
922         if( needReConf )
923                 ReloadConfig();
924  
925         // 開く
926         edit_.getDoc().ClearAll();
927         edit_.getDoc().OpenFile( tf );
928  
929         // タイトルバ[更新
930         UpdateWindowName();
931  
932         // [最近使ったファイル]へ追加
933         cfg_.AddMRU( filename_ );
934         HWND wnd = NULL;
124 roytam 935 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
89 roytam 936         while( NULL!=(wnd=::FindWindowEx( NULL, wnd, className_, NULL )) )
937                 SendMessage( wnd, GPM_MRUCHANGED, 0, 0 );
124 roytam 938 #endif
89 roytam 939  
940         return true;
941 }
942  
943  
944  
945 //-------------------------------------------------------------------------
946 // 保存処理
947 //-------------------------------------------------------------------------
948  
949 bool GreenPadWnd::ShowSaveDlg()
950 {
951         // [Save][Cancel] 保存先ファイル名指定ダイアログを表示
952  
953         String flst[] = {
954                 String(IDS_ALLFILES),
955                 String(TEXT("*.*"))
956         };
957         aarr<TCHAR> filt = SaveFileDlg::ConnectWithNull( flst, countof(flst) );
958  
959         SaveFileDlg sfd( charSets_, csi_, lb_ );
960         if( !sfd.DoModal( hwnd(), filt.get(), filename_.c_str() ) )
961                 return false;
962  
963         filename_ = sfd.filename();
964         csi_      = sfd.csi();
965         lb_       = sfd.lb();
966  
967         return true;
968 }
969  
970 bool GreenPadWnd::Save_showDlgIfNeeded()
971 {
972         bool wasUntitled = isUntitled();
973  
974         // [Save][Cancel] ファイル名未定ならダイアログ表示
975         if( isUntitled() )
976                 if( !ShowSaveDlg() )
977                         return false;
978         if( Save() )
979         {
980                 if( wasUntitled )
981                         ReloadConfig(); // 文書タイプに応じて表示を更新
982                 return true;
983         }
984         return false;
985 }
986  
987 bool GreenPadWnd::AskToSave()
988 {
989         // 変更されていたら、
990         // [Yes][No][Cancel] 保存するかどうか尋ねる。
991         // 保存するなら
992         // [Save][Cancel]    ファイル名未定ならダイアログ表示
993  
994         if( edit_.getDoc().isModified() )
995         {
996                 int answer = MsgBox(
997                         String(IDS_ASKTOSAVE).c_str(),
998                         String(IDS_APPNAME).c_str(),
999                         MB_YESNOCANCEL|MB_ICONQUESTION
1000                 );
1001                 if( answer == IDYES )    return Save_showDlgIfNeeded();
1002                 if( answer == IDCANCEL ) return false;
1003         }
1004         return true;
1005 }
1006  
1007 bool GreenPadWnd::Save()
1008 {
1009         TextFileW tf( charSets_[csi_].ID, lb_ );
1010         if( tf.Open( filename_.c_str() ) )
1011         {
1012                 // 無事ファイルに保存できた場合
1013                 edit_.getDoc().SaveFile( tf );
1014                 UpdateWindowName();
1015                 // [最近使ったファイル]更新
1016                 cfg_.AddMRU( filename_ );
1017                 HWND wnd = NULL;
124 roytam 1018 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
89 roytam 1019                 while( NULL!=(wnd=::FindWindowEx( NULL, wnd, className_, NULL )) )
1020                         SendMessage( wnd, GPM_MRUCHANGED, 0, 0 );
124 roytam 1021 #endif
89 roytam 1022                 return true;
1023         }
1024  
1025         // Error!
1026         MsgBox( String(IDS_SAVEERROR).c_str() );
1027         return false;
1028 }
1029  
1030  
1031  
1032 //-------------------------------------------------------------------------
1033 // メインウインドウの初期化
1034 //-------------------------------------------------------------------------
1035  
1036 GreenPadWnd::ClsName GreenPadWnd::className_ = TEXT("GreenPad MainWnd");
1037  
1038 GreenPadWnd::GreenPadWnd()
1039         : WndImpl  ( className_, WS_OVERLAPPEDWINDOW, WS_EX_ACCEPTFILES )
1040         , charSets_( cfg_.GetCharSetList() )
1041         , csi_     ( cfg_.GetNewfileCsi() )
1042         , lb_      ( cfg_.GetNewfileLB() )
1043         , search_  ( *this, edit_ )
1044 {
1045         LOGGER( "GreenPadWnd::Construct begin" );
1046  
123 roytam 1047 #if !defined(TARGET_VER) || TARGET_VER>350
89 roytam 1048         static WNDCLASSEX wc;
123 roytam 1049 #else
1050         static WNDCLASS wc;
1051 #endif
89 roytam 1052         wc.hIcon         = app().LoadIcon( IDR_MAIN );
1053         wc.hCursor       = app().LoadOemCursor( IDC_ARROW );
1054         wc.lpszMenuName  = MAKEINTRESOURCE( IDR_MAIN );
1055         wc.lpszClassName = className_;
1056         WndImpl::Register( &wc );
1057  
1058         ime().EnableGlobalIME( true );
1059  
1060         LOGGER( "GreenPadWnd::Construct end" );
1061 }
1062  
1063 void GreenPadWnd::on_create( CREATESTRUCT* cs )
1064 {
1065         LOGGER("GreenPadWnd::on_create begin");
1066  
1067         accel_ = app().LoadAccel( IDR_MAIN );
1068         stb_.Create( hwnd() );
1069         edit_.Create( NULL, hwnd(), 0, 0, 100, 100 );
1070         LOGGER("GreenPadWnd::on_create edit created");
1071         edit_.getDoc().AddHandler( this );
1072         edit_.getCursor().AddHandler( this );
124 roytam 1073 #if !defined(TARGET_VER) || (defined(TARGET_VER) && TARGET_VER>310)
89 roytam 1074         stb_.SetStatusBarVisible( cfg_.showStatusBar() );
124 roytam 1075 #elif defined(TARGET_VER) && TARGET_VER==310
1076         stb_.SetStatusBarVisible( false );
1077 #endif
89 roytam 1078  
1079         LOGGER("GreenPadWnd::on_create halfway");
1080  
1081         search_.LoadFromINI( cfg_.getImpl() );
1082         SetupSubMenu();
1083         SetupMRUMenu();
1084  
1085         LOGGER("GreenPadWnd::on_create menu");
1086 }
1087  
1088 bool GreenPadWnd::StartUp( const Path& fn, int cs, int ln )
1089 {
1090         LOGGER( "GreenPadWnd::StartUp begin" );
1091         Create( 0, 0, cfg_.GetWndX(), cfg_.GetWndY(), cfg_.GetWndW(), cfg_.GetWndH(), 0 );
1092         LOGGER( "GreenPadWnd::Created" );
1093         if( fn.len()==0 || !OpenByMyself( fn, cs ) )
1094         {
1095                 LOGGER( "for new file..." );
1096  
1097                 // ファイルを開か(け)なかった場合
1098                 ReloadConfig( fn.len()==0 );
1099                 LOGGER( "GreenPadWnd::StartUp reloadconfig end" );
1100                 UpdateWindowName();
1101                 LOGGER( "GreenPadWnd::StartUp updatewindowname end" );
1102         }
1103  
1104         // 指定の行へジャンプ
1105         if( ln != -1 )
1106                 JumpToLine( ln );
1107  
1108         LOGGER( "GreenPadWnd::StartUp end" );
1109         return true;
1110 }
1111  
1112 void GreenPadWnd::ShowUp2()
1113 {
1114         Window::ShowUp( cfg_.GetWndM() ? SW_MAXIMIZE : SW_SHOW );
1115 }
1116  
1117  
1118 //-------------------------------------------------------------------------
1119 // スタ[トアップル[チン
1120 //      コマンドラインの解析を行う
1121 //-------------------------------------------------------------------------
1122  
1123 int kmain()
1124 {
1125         LOGGER( "kmain() begin" );
1126  
1127         Argv  arg;
1128         ulong   i;
1129  
1130         LOGGER( "argv processed" );
1131  
1132   //-- まずオプションスイッチを処理
1133  
1134         int optL = -1;
1135         int optC = 0;
1136  
1137         for( i=1; i<arg.size() && arg[i][0]==TEXT('-'); ++i )
1138                 switch( arg[i][1] )
1139                 {
1140                 case TEXT('c'):
1141                         optC = String::GetInt( arg[i]+2 );
1142                         break;
1143                 case TEXT('l'):
1144                         optL = String::GetInt( arg[i]+2 );
1145                         break;
1146                 }
1147  
1148         LOGGER( "option processed" );
1149  
1150   //-- 次にファイル名
1151  
1152         Path file;
1153  
1154         if( i < arg.size() )
1155         {
1156                 file = arg[i];
1157                 if( !file.isFile() )
1158                 {
1159                         ulong j; // ""無しで半スペ入りでもそれなりに対処
1160                         for( j=i+1; j<arg.size(); ++j )
1161                         {
1162                                 file += ' ';
1163                                 file += arg[j];
1164                                 if( file.isFile() )
1165                                         break;
1166                         }
1167  
1168                         if( j==arg.size() )
1169                                 file = arg[i];
1170                         else
1171                                 i=j;
1172                 }
1173         }
1174  
1175         LOGGER( "filename processed" );
1176  
1177   //-- ]ってる引数があれば、それで新規プロセス起動
1178  
1179         if( ++i < arg.size() )
1180         {
1181                 String cmd;
1182                 for( ; i<arg.size(); ++i )
1183                 {
1184                         cmd += TEXT('\"');
1185                         cmd += arg[i];
1186                         cmd += TEXT("\" ");
1187                 }
1188                 ::BootNewProcess( cmd.c_str() );
1189         }
1190  
1191         LOGGER( "newprocess booted" );
1192  
1193   //-- メインウインドウ発進
1194  
1195         GreenPadWnd wnd;
1196         if( !wnd.StartUp(file,optC,optL) )
1197                 return -1;
1198  
1199         LOGGER( "kmain() startup ok" );
1200  
1201   //-- メインル[プ
1202  
1203         wnd.ShowUp2();
1204         LOGGER( "showup!" );
1205         wnd.MsgLoop();
1206  
1207         LOGGER( "fin" );
1208         return 0;
1209 }