home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1999 March / VPR9903A.BIN / APUPDATE / VC / Tx300d / TX300D.LZH / SEARCH.C < prev    next >
C/C++ Source or Header  |  1997-06-13  |  127KB  |  4,856 lines

  1. // WZ EDITOR 標準機能 検索
  2. // Copyright 1995-96 TY
  3. // WZ2.0新型検索ダイアログ: thanks y.mikomeさん
  4.  
  5. //{###検索・置換}
  6.  
  7. //2.92 検索置換リストを拡張し、複数の文字列の検索・置換を一度に行えるようにした
  8. //2.92 通常の検索・置換操作の延長で、複数文字列検索置換を行えるようにした
  9. //2.92 Grepでも使用できる
  10. //2.99C 970324 wndtxCallNext -> wndtxCallNextEx
  11. //2.99C 970324 wndtxCallBoth -> wndtxCallBothEx
  12.  
  13. //2.99D 970331 TXCMDBASE対応
  14.  
  15. //1.00D search.tllを利用する場合、
  16. // 予め#include "dialog.h"しておかなければならなかったが不要にした
  17. #export
  18. #include "dialog.h"
  19. #endexport
  20.  
  21. #include <windows.h>
  22. #include <windowsx.h>
  23.  
  24. #define IDD_PREV            2001
  25. #define IDD_NEXT            2002
  26. #define IDD_ALL                2003
  27. #define IDD_AREA            2004
  28. #define IDD_TOREPLACE        2005
  29. #define IDD_SEARCH            2006
  30. #define IDD_CASE            2007
  31. #define IDD_ZENHAN            2008
  32. #define IDD_WORD            2009
  33. #define IDD_RE                2010
  34. #define IDD_NOESC            2011
  35. #define IDD_ALLTEXT            2012
  36. #define IDD_MODETOP            2013
  37. #define IDD_MODEEND            2016
  38. #define IDD_OPTION            2017
  39. #define IDD_REPLACE            2019
  40. #define IDD_ADD                2020
  41. #define IDD_EDIT            2021
  42. #define IDD_DEL                2022
  43. #define IDD_ADDCATEGORY        2023
  44. #define IDD_COPY            2024
  45. #define IDD_PASTE            2025
  46. #define IDD_SEARCHLOOK        2026    //2.95 970130 
  47. #define IDD_SEARCHSPECIAL    2027    //2.97 970225 
  48. #define IDD_TARGET            2028    //2.97 970225 
  49. #define IDD_NOSYMBOL        2029    //2.98 970309 
  50. #define IDD_TITLENAME        2030    //3.00A2 970506 
  51. // grep.cと共通値
  52. #define IDD_SZFIND            3000
  53. #define IDD_SZREPLACE        3001
  54. #define IDD_REFERSEARCHLIST    3002
  55. //
  56. #define IDD_MODEREPLACETOP    3100
  57. #define IDD_MODEREPLACEEND    3109
  58.  
  59. #define bitequ(dst,flag,bit)    if (flag) {(dst) |= (bit);} else {(dst) &= ~(bit);}
  60.  
  61. static mchar _szIdSearchlist[] = "\\検索リスト:";
  62. static BYTE _lchIdSearchlist = 9;
  63. //次だと、うまくいかない。TX-Cの仕様
  64. //static BYTE _lchIdSearchlist = sizeof(_szIdSearchlist) - 1;
  65.  
  66. extern "tx" {
  67.     //1.00F キーボードマクロに検索ダイアログを開いた検索を記録できるようにした
  68.     // 入力された検索文字列自体は記録せず、"txSearchContinue"のように記録します。
  69. BOOL TXAPI keymacroDoing(void);
  70. BOOL TXAPI keymacroPop(void);
  71. BOOL TXAPI keymacroAdd(WZCMD wzcmd);
  72. }
  73.  
  74. typedef struct {
  75.     BYTE modeDirection;
  76.         #define DIR_PREV    0
  77.         #define DIR_NEXT    1
  78.     BYTE modeReplace;
  79.         #define REPLACE_1        0
  80.         #define REPLACE_ALL        1
  81.         #define REPLACE_AREA    2
  82. } SEARCHCONTEXT;
  83.  
  84. static SEARCHCONTEXT _context;
  85. static SEARCHOPT _searchopt;
  86.  
  87. BOOL TXAPI txuiSearchSetForEx(tx *text,mchar *szcaption,txstr _szfind,DWORD* searchmode);
  88. void uiJumpAddress(TX* text);
  89.  
  90. SEARCHMODE TXAPI searchmodeFromSearchopt(SEARCHOPT* opt)
  91. {
  92. // text->fSearchWordなどの検索オプション指定をsearchmode書式に変換して返します
  93. //1.00H2 で追加
  94.     DWORD searchmode = 0;
  95.     searchmode |= SEARCH_NOSENSECASE * (!opt->fSearchSenseCase);
  96.     searchmode |= SEARCH_NOSENSEZENHAN * (!opt->fSearchSenseZenhan);
  97.     searchmode |= SEARCH_WORD * (opt->fSearchWord != 0);
  98.     searchmode |= SEARCH_AREA * (opt->fSearchArea != 0);
  99.     searchmode |= SEARCH_CUR * (opt->fSearchCur != 0);
  100.     searchmode |= SEARCH_NOESC * (opt->fSearchEscapeNo != 0);
  101.     searchmode |= SEARCH_NOSYMBOL * (opt->fSearchNoSymbol != 0);//2.98 970309 
  102.     searchmode |= SEARCH_RE * (opt->fSearchRE != 0);
  103.     searchmode |= SEARCH_ALLTEXT * (opt->fSearchAllText != 0);//1.01A 
  104.     searchmode |= REPLACE_CONFIRM * (opt->fReplaceConfirm != 0);//2.92 
  105.     if (opt->fCategory) {
  106.         switch(opt->category) {
  107.             case SEARCHCATEGORY_NORMAL: {
  108.                 bitequ(searchmode,FALSE,SEARCH_NOSENSEZENHAN);
  109.                 bitequ(searchmode,FALSE,SEARCH_WORD);
  110.                 bitequ(searchmode,FALSE,SEARCH_RE);
  111.                 break;
  112.             }
  113.             case SEARCHCATEGORY_WORD: {
  114.                 bitequ(searchmode,FALSE,SEARCH_NOSENSEZENHAN);
  115.                 bitequ(searchmode,TRUE,SEARCH_WORD);
  116.                 bitequ(searchmode,FALSE,SEARCH_RE);
  117.                 break;
  118.             }
  119.             case SEARCHCATEGORY_RE: {
  120.                 bitequ(searchmode,FALSE,SEARCH_NOSENSEZENHAN);
  121.                 bitequ(searchmode,FALSE,SEARCH_WORD);
  122.                 bitequ(searchmode,TRUE,SEARCH_RE);
  123.                 break;
  124.             }
  125.             case SEARCHCATEGORY_FUZZY: {
  126.                 bitequ(searchmode,TRUE,SEARCH_NOSENSEZENHAN);
  127.                 bitequ(searchmode,FALSE,SEARCH_WORD);
  128.                 bitequ(searchmode,FALSE,SEARCH_RE);
  129.                 bitequ(searchmode,TRUE,SEARCH_NOSENSECASE);
  130.                 break;
  131.             }
  132.         }
  133.     }
  134.     return searchmode;
  135. }
  136.  
  137. //1.01A 
  138. // optを全クリアするので注意してください
  139. void TXAPI searchmodeToSearchopt(SEARCHMODE searchmode,SEARCHOPT* opt)
  140. {
  141.     //1.96 clear
  142.     memset(opt,0,sizeof(SEARCHOPT));
  143.     //
  144.     opt->fSearchSenseCase = !((searchmode & SEARCH_NOSENSECASE) != 0);
  145.     opt->fSearchSenseZenhan = !((searchmode & SEARCH_NOSENSEZENHAN) != 0);
  146.     opt->fSearchWord = ((searchmode & SEARCH_WORD) != 0);
  147.     opt->fSearchArea = ((searchmode & SEARCH_AREA) != 0);
  148.     opt->fSearchCur = ((searchmode & SEARCH_CUR) != 0);
  149.     opt->fSearchEscapeNo = ((searchmode & SEARCH_NOESC) != 0);
  150.     opt->fSearchNoSymbol = ((searchmode & SEARCH_NOSYMBOL) != 0);//2.98 970310 
  151.     opt->fSearchRE = ((searchmode & SEARCH_RE) != 0);
  152.     opt->fSearchAllText = ((searchmode & SEARCH_ALLTEXT) != 0);
  153.     opt->fReplaceConfirm = ((searchmode & REPLACE_CONFIRM) != 0);//2.92 
  154.     //1.96 
  155.     opt->category = SEARCHCATEGORY_NORMAL;
  156.     if (searchmode & SEARCH_WORD) opt->category = SEARCHCATEGORY_WORD;
  157.     if (searchmode & SEARCH_RE) opt->category = SEARCHCATEGORY_RE;
  158.     if (searchmode & SEARCH_NOSENSEZENHAN) opt->category = SEARCHCATEGORY_FUZZY;
  159. }
  160.  
  161. static mchar _szNormal[] = "通常";
  162. static mchar _szWord[] = "単語";
  163. static mchar _szRe[] = "正規";
  164. static mchar _szFuzzy[] = "曖昧";
  165. static mchar _szNoSenseCase[] = "大小文字同一視";
  166. static mchar _szNoEsc[] = \"'\'は通常文字";
  167. static mchar _szNoSymbol[] = "空白と記号をスキップ";//2.98 970309 
  168.  
  169. SEARCHMODE TXAPI searchmodeFromSzstr(mchar* szstr)
  170. {
  171. //1.96 文字列をSEARCHMODEに変換
  172.     SEARCHOPT opt;
  173.     memset(&opt,0,sizeof(SEARCHOPT));
  174.     opt.fCategory = TRUE;
  175.     opt.fSearchSenseCase = TRUE;
  176.     //
  177.     opt.category = SEARCHCATEGORY_NORMAL;
  178.     if (strstr(szstr,_szWord)) {
  179.         opt.category = SEARCHCATEGORY_WORD;
  180.     } else if (strstr(szstr,_szRe)) {
  181.         opt.category = SEARCHCATEGORY_RE;
  182.     } else if (strstr(szstr,_szFuzzy)) {
  183.         opt.category = SEARCHCATEGORY_FUZZY;
  184.     }
  185.     //
  186.     if (strstr(szstr,_szNoSenseCase)) opt.fSearchSenseCase = FALSE;
  187.     if (strstr(szstr,_szNoEsc)) opt.fSearchEscapeNo = TRUE;
  188.     if (strstr(szstr,_szNoSymbol)) opt.fSearchNoSymbol = TRUE;//2.98 970309 
  189.     //
  190.     return searchmodeFromSearchopt(&opt);
  191. }
  192.  
  193. void TXAPI searchmodeToSzstr(SEARCHMODE searchmode,txstr szstr)
  194. {
  195. //1.96 searchmodeを文字列に変換
  196.     SEARCHOPT opt;
  197.     searchmodeToSearchopt(searchmode,&opt);
  198.     //
  199.     szstr = "";
  200.     switch(opt.category) {
  201.         case SEARCHCATEGORY_NORMAL: szstr += _szNormal + " ";break;
  202.         case SEARCHCATEGORY_WORD: szstr += _szWord + " ";break;
  203.         case SEARCHCATEGORY_RE: szstr += _szRe + " ";break;
  204.         case SEARCHCATEGORY_FUZZY: szstr += _szFuzzy + " ";break;
  205.     }
  206.     if (!opt.fSearchSenseCase) szstr += _szNoSenseCase + " ";
  207.     if (opt.fSearchEscapeNo) szstr += _szNoEsc + " ";
  208.     if (opt.fSearchNoSymbol) szstr += _szNoSymbol + " ";//2.98 970309 
  209. }
  210.  
  211. //##エラー
  212.  
  213. err_title
  214. {
  215.     statprintf("見出しが見つかりません");
  216.     if (text->fbeep) MessageBeep(MB_ICONEXCLAMATION);
  217. }
  218.  
  219. err
  220. {
  221.     SHARE* sh = text->share;
  222.     if (text->fClipSearch && !text->fClipMouse) {
  223.         //2.99 970314 再検索でtxSelectQuitしなくなったため
  224.         txSelectQuit(text);
  225.     }
  226.     if (sh->argSearchAll.szFind[0]) {
  227.         //2.96 970201 全WZで検索中
  228.     } else if (sh->fResultSearchAlltext) {
  229.         if (sh->fResultSearchAlltext == 2) {
  230.             statprintf("全WZ検索:一周しました");
  231.         } else {
  232.             statprintf("全WZ検索:ファイルが閉じられたので、中止しました");
  233.         }
  234.         sh->fResultSearchAlltext = 0;
  235.         if (text->fbeep) MessageBeep(MB_ICONEXCLAMATION);
  236.     } else {
  237.         statprintf("文字列が見つかりません");
  238.         if (text->fbeep) MessageBeep(MB_ICONEXCLAMATION);
  239.     }
  240. }
  241.  
  242. err_clear
  243. {
  244.     statprintf("");
  245. }
  246.  
  247. // from search/replace
  248. static txstr szfind;
  249. static txstr szreplace;
  250. static HDIALOG _hdreplace;
  251. static BOOL _fReplace;    //1.01A 前回の置換・検索は置換だったか?
  252.  
  253. //##検索/置換ダイアログ
  254.  
  255. static void histsearchAdd(mchar* szfind,DWORD searchmode,BOOL fNoSearchmode)
  256. {
  257.     if (szfind[0]) {
  258.         wzlock(LOCK_HIST);
  259.         HSTRBLK sb = histToStrblk(HIST_SEARCH);
  260.         sbAddHist(sb,szfind);
  261.         if (!fNoSearchmode) {
  262.             //2.00C3 余計な検索モードが記憶されないようにした。
  263.             // 記憶されると、誤動作することがある。
  264.             searchmode &= (SEARCH_FORWARD|SEARCH_PREV|SEARCH_NOESC|SEARCH_NOSENSECASE|SEARCH_NOSENSEZENHAN|SEARCH_WORD|SEARCH_RE|SEARCH_ALLTEXT|SEARCH_NOSYMBOL);
  265.             //
  266.             sbWriteCustdata(sb,sbGetCount(sb) - 1,searchmode);
  267.         }
  268.         wzunlock(LOCK_HIST);
  269.     }
  270. }
  271.  
  272. static void _dialogSearchOption(HDIALOG hd,tx *text,SEARCHOPT* searchopt,SEARCHMODE exmode)
  273. {
  274.     BOOL fCompact = ((exmode & SEARCH_DIALOGCOMPACT) != 0);
  275.     if (exmode & SEARCH_OLDDIALOG) {
  276.         dialogGroup(hd,"文字の区別");
  277.             dialogControlID(hd,IDD_CASE);
  278.             dialogCheck(hd,"大文字と小文字を区別(&C)",&searchopt->fSearchSenseCase);
  279.             dialogControlID(hd,IDD_ZENHAN);
  280.             dialogCheck(hd,"全角と半角文字を区別(&Z)",&searchopt->fSearchSenseZenhan);
  281.         dialogGroupEnd(hd);
  282.         
  283.         dialogGroup(hd,"検索モード");
  284.             dialogControlID(hd,IDD_WORD);
  285.             dialogCheck(hd,"ワードサーチ(&W)",&searchopt->fSearchWord);
  286.             dialogControlID(hd,IDD_RE);
  287.             dialogCheck(hd,"正規表現(&E)",&searchopt->fSearchRE);
  288.             dialogControlID(hd,IDD_NOESC);
  289.             dialogCheck(hd,\"\を通常文字とみなす(&Y)",&searchopt->fSearchEscapeNo);
  290.             if (exmode & SEARCH_ALLTEXT) {
  291.                 dialogControlID(hd,IDD_ALLTEXT);
  292.                 dialogCheck(hd,"全WZを対象(&T)",&searchopt->fSearchAllText);//1.01A 
  293.             }
  294.         dialogGroupEnd(hd);
  295.     } else {
  296.         searchopt->fCategory = TRUE;
  297.         int xRight= dialogGetGroupRight(hd);
  298.         dialogSetGroupRight(hd,0);
  299.         DTRECT r;
  300.         
  301.         if (fCompact) {//2.97 970225 
  302.             dialogSetIntXY(hd,0,0);
  303.             dialogGetPos(hd,&r);
  304.             dialogCaption(hd,"モード:");
  305.             r.x += DTCX * 6;
  306.             dialogSetPos(hd,&r);
  307.         } else {
  308.             dialogGroup(hd,"モード");
  309.         }
  310.         dialogControlRadioV(hd);
  311.         dialogControlID(hd,IDD_MODETOP);
  312.         dialogControlHelp(hd,-292);
  313.         dialogRadioIDI(hd,&searchopt->category,"通常(&M)","単語(&W)","正規(&E)","曖昧(&X)");
  314.         if (fCompact) {
  315.             r.x += DTCX * 14;
  316.             dialogSetPos(hd,&r);
  317.         } else {
  318.             dialogGroupEndGetRect(hd,&r);
  319.             dialogGroupLFV(hd);
  320.             dialogSetGroupRight(hd,xRight);
  321.         }
  322.         //
  323.         if (fCompact) {//2.97 970225 
  324.         } else {
  325.             dialogSetGroupBottom(hd,r.y + r.cy);//1.99C 
  326.             dialogGroup(hd,"オプション");
  327.         }
  328.         dialogControlReverseBool(hd);
  329.         dialogControlID(hd,IDD_CASE);
  330.         dialogControlHelp(hd,186);
  331.         dialogCheck(hd,"大小文字同一視(&C)",&searchopt->fSearchSenseCase);
  332.         //
  333.         dialogControlID(hd,IDD_NOESC);
  334.         dialogControlHelp(hd,187);
  335.         dialogCheck(hd,\"\を通常文字(&Y)",&searchopt->fSearchEscapeNo);
  336.         //2.98 970309 テキスト中の改行や空白・記号を無視して、純粋な文字(英数時、ひらがなカタカナ漢字)の検索を行うオプションを追加
  337.         dialogControlID(hd,IDD_NOSYMBOL);
  338.         dialogControlHelp(hd,413);
  339.         dialogCheck(hd,"空白と記号をスキップ(&O)",&searchopt->fSearchNoSymbol);
  340.         //
  341.         if (exmode & SEARCH_ALLTEXT) {
  342.             //1.01A 
  343.             dialogControlID(hd,IDD_ALLTEXT);
  344.             dialogControlHelp(hd,188);
  345.             dialogCheck(hd,"全WZを対象(&T)",&searchopt->fSearchAllText);
  346.         }
  347.         if (exmode & REPLACE_CONFIRM) {//1.99A "確認"をつけるか制御可能にした
  348.             dialogControlEnable(hd,((exmode & SEARCH_REPLACE)!= 0));
  349.             dialogControlHelp(hd,189);
  350.             dialogCheck(hd,"確認(&K)",&searchopt->fReplaceConfirm);
  351.         }
  352.         if (fCompact) {
  353.             dialogResetInt(hd);
  354.             if (exmode & SEARCH_DIALOGSLIST) {//2.97 970225 
  355.                 r.x += DTCX * 21;
  356.                 dialogSetPos(hd,&r);
  357.                 //
  358.                 dialogControlID(hd,IDD_REFERSEARCHLIST);
  359.                 dialogControlHelp(hd,203);
  360.                 dialogButton(hd,"リスト(&L)...",NULL,9);
  361.             }
  362.         } else {
  363.             dialogGroupEnd(hd);
  364.             dialogSetGroupBottom(hd,0);//1.99C 
  365.         }
  366.         dialogLF(hd);
  367.     }
  368. }
  369.  
  370. void TXAPI dialogSearchOption(HDIALOG hd,SEARCHOPT* searchopt,SEARCHMODE exmode)
  371. {
  372. // ダイアログハンドルhdに検索オプションコントロールを追加します。
  373. // 置換用のときはexmodeにSEARCH_REPLACEを指定してください。
  374. //1.96仕様変更
  375.     if (textf->modeSearchDialog == 0) {//2.99C 970324 text1->textf
  376.         exmode |= SEARCH_OLDDIALOG;
  377.     }
  378.     _dialogSearchOption(hd,textf,searchopt,exmode);//2.99C 970324 text1->textf
  379. }
  380.  
  381. #define MODEOPTION_NONE        0
  382. #define MODEOPTION_WITH        1
  383. #define MODEOPTION_ONLY        2
  384.  
  385. //1.96 モードレスダイアログ
  386. static HWND _hwndSearch;
  387. static TX* _txSearch;   //2.90 text1以外がモードレス検索できなかった、
  388.                         //プログラムも各種変更した
  389. static BOOL _hwndSearchIsReplace;//2.97 970225 
  390. #if 0//2.99D 970402 
  391. static int _fFocusSub;//2.99C 970325 
  392. #endif
  393. //1.99G 位置記憶
  394. //2.97 970225 検索と置換別々に記憶
  395. static BOOL _fWindowPos[3];
  396. static int _x[3];
  397. static int _y[3];
  398. //1.99G ネスティング
  399. static int _modeSearch;
  400.  
  401. static void mtSetContext(TX* text,BOOL fSub)
  402. {
  403. //2.99D 970402 new
  404.     txOp(text,TXOP_MTSETCONTEXT,fSub,0);
  405. }
  406.  
  407. static void mtReadContext(TX* text,BOOL fSub)
  408. {
  409. //2.99D 970402 new
  410.     txOp(text,TXOP_MTREADCONTEXT,fSub,0);
  411. }
  412.  
  413. static void dialogSearch(HDIALOG hd,tx *text,BOOL modeOption,SEARCHMODE exmode)
  414. {
  415.     BOOL fCompact = ((exmode & SEARCH_DIALOGCOMPACT) != 0);    //2.97 970225 
  416.     if (exmode & SEARCH_REPLACE) {
  417.         dialogSetGroupRight(hd,DTCX * 42);
  418.         if (fCompact) {//2.97 970225 
  419.             dialogSetH(hd);
  420.             dialogControlHelp(hd,190);
  421.             dialogControlHistRead(hd,HIST_SEARCH);
  422.             dialogControlID(hd,IDD_SZFIND);
  423.             dialogStr(hd,"検索(&S):",szfind,10,35);
  424.             dialogLFSetV(hd);
  425.             
  426.             dialogControlHelp(hd,191);
  427.             dialogControlHistRead(hd,HIST_SEARCH);
  428.             dialogControlID(hd,IDD_SZREPLACE);
  429.             dialogStr(hd,"置換(&I):",szreplace,10,35);
  430.         } else {
  431.             dialogGroup(hd,"置換(&S)");
  432.                 dialogControlHelp(hd,190);
  433.                 dialogControlGuide(hd,"を",3);
  434.                 dialogControlHistRead(hd,HIST_SEARCH);
  435.                 dialogControlID(hd,IDD_SZFIND);
  436.                 dialogStr(hd,NULL,szfind,0,35);
  437.                 
  438.                 dialogControlHelp(hd,191);
  439.                 dialogControlGuide(hd,"へ",3);
  440.                 dialogControlHistRead(hd,HIST_SEARCH);
  441.                 dialogControlID(hd,IDD_SZREPLACE);//2.00B 
  442.                 dialogStr(hd,NULL,szreplace,0,35);
  443.                 
  444.                 dialogSpace(hd);
  445.                 if (!text->modeSearchDialog) {//拡張オプション
  446.                     dialogCheck(hd,"確認(&K)",&_searchopt.fReplaceConfirm);
  447.                 }
  448.             dialogGroupEnd(hd);
  449.         }
  450.     } else {
  451.         dialogSetGroupRight(hd,DTCX * 40);
  452.         if (modeOption == MODEOPTION_ONLY) {
  453.         } else if (modeOption == MODEOPTION_WITH || text->modeSearchDialog) {//拡張オプション
  454.             if (fCompact) {//2.97 970225 
  455.                 dialogSetH(hd);
  456.                 dialogControlHelp(hd,190);
  457.                 dialogControlHistRead(hd,HIST_SEARCH);
  458.                 dialogControlID(hd,IDD_SZFIND);
  459.                 dialogStr(hd,"検索(&S):",szfind,10,35);
  460.                 dialogLFSetV(hd);
  461.             } else {
  462.                 dialogGroup(hd,"検索(&S)");//1.99C 
  463.                     dialogControlHelp(hd,190);
  464.                     dialogControlHistRead(hd,HIST_SEARCH);
  465.                     dialogControlID(hd,IDD_SZFIND);
  466.                     dialogStr(hd,NULL,szfind,0,37);
  467.                 dialogGroupEnd(hd);
  468.             }
  469.         } else {
  470.             if (fCompact) {//2.97 970225 
  471.                 dialogControlHelp(hd,190);
  472.                 dialogControlHistRead(hd,HIST_SEARCH);
  473.                 dialogControlID(hd,IDD_SZFIND);
  474.                 dialogStr(hd,"検索(&S):",szfind,10,35);
  475.             } else {
  476.                 dialogGroup(hd,"検索(&S)");
  477.                     dialogSetH(hd);
  478.                     dialogControlHelp(hd,190);
  479.                     dialogControlHistRead(hd,HIST_SEARCH);
  480.                     dialogControlID(hd,IDD_SZFIND);
  481.                     dialogStr(hd,NULL,szfind,0,35);
  482.                     dialogLF(hd);
  483.                     dialogSetV(hd);
  484.                 dialogGroupEnd(hd);
  485.             }
  486.         }
  487.     }
  488.     if (modeOption != MODEOPTION_NONE) {
  489.         searchmodeToSearchopt(text->searchmode,&_searchopt);
  490.         if (text->modeSearchDialog == 0) exmode |= SEARCH_OLDDIALOG;
  491.         if (!(exmode & SEARCH_ALLTEXT)) {
  492.             //1.99A SEARCH_ALLTEXTが無効の場合は、
  493.             // text->searchmodeでのSEARCH_ALLTEXTが有効な場合があるので、
  494.             // クリアしてやる
  495.             _searchopt.fSearchAllText = FALSE;
  496.         }
  497.         _dialogSearchOption(hd,text,&_searchopt,exmode);
  498.     }
  499. }
  500.  
  501. static mchar *_szcaption;
  502.  
  503. #if 1    //2.99D 970330 for DEBUGWIN err
  504.  
  505. static void _searchClose(BOOL fDestroyWindow)
  506. {
  507.     if (_hwndSearch) {
  508.         HWND hwnd = _hwndSearch;
  509.         _hwndSearch = NULL;
  510.         {//1.99G 入力されていた検索文字列などの状態をとっておく
  511.             HDIALOG hd = dialogFromHwnd(hwnd);
  512.             dialogRead(hd);
  513.             //
  514.             SEARCHMODE searchmode = searchmodeFromSearchopt(&_searchopt);
  515.             histsearchAdd(szfind,searchmode,FALSE);
  516.         }
  517.         //2.99A 970320 モードレス検索ダイアログでもIMEの状態を変更したら、テキストウィンドウにもその状態を引き継ぐ
  518.         text->fImeWasOn = imeGetOpen();
  519.         //
  520.         if (fDestroyWindow) {
  521.             dialogFree(hwnd);    // dialogFreeでDestroyWindowもされる。
  522.         } else {
  523.             dialogUnlink(hwnd);
  524.         }
  525.         _txSearch = NULL;
  526.     }
  527. }
  528.  
  529. static void searchClosed(void)
  530. {
  531.     _searchClose(FALSE);
  532. }
  533.  
  534. static void searchClose(void)
  535. {
  536.     _searchClose(TRUE);
  537. }
  538.  
  539. #else
  540.  
  541. static void searchClose(void)
  542. {
  543.     if (_hwndSearch) {
  544.         HWND hwnd = _hwndSearch;
  545.         _hwndSearch = NULL;
  546.         {//1.99G 入力されていた検索文字列などの状態をとっておく
  547.             HDIALOG hd = dialogFromHwnd(hwnd);
  548.             dialogRead(hd);
  549.             //
  550.             SEARCHMODE searchmode = searchmodeFromSearchopt(&_searchopt);
  551.             histsearchAdd(szfind,searchmode,FALSE);
  552.         }
  553.         //2.99A 970320 モードレス検索ダイアログでもIMEの状態を変更したら、テキストウィンドウにもその状態を引き継ぐ
  554.         text->fImeWasOn = imeGetOpen();
  555.         //
  556. #if 0//2.99D 970330 dialogFreeでDestroyWindowもされる。
  557.         DestroyWindow(hwnd);
  558. #endif
  559.         dialogFree(hwnd);
  560.         _txSearch = NULL;
  561.     }
  562. }
  563.  
  564. #endif
  565.  
  566. static BOOL searchExec(TX* text,int id,int *pRet,int mode)
  567. {
  568.     int ret = 0;
  569.     *pRet = 0;
  570.     if (id) {
  571.         if (mode & SEARCHDLG_MODELESS) {
  572.             err_clear();
  573.         }
  574.         text->searchmode = searchmodeFromSearchopt(&_searchopt);
  575. //information("%d %d",_searchopt.fSearchcategory,_searchopt.searchcategory);
  576.         if ((text->searchmode & SEARCH_WORD) && (text->searchmode & SEARCH_NOSENSEZENHAN)) {
  577.             attention("[全角と半角文字を区別]がOFFのときは、ワードサーチできません");
  578.             return FALSE;
  579.         }
  580.         //
  581.         SEARCHMODE searchmode = text->searchmode;
  582.         if (mode & SEARCHDLG_REPLACE) {
  583.             BOOL fSearchlist = !strncmp(szfind,_szIdSearchlist,_lchIdSearchlist);
  584.             if (szfind == "") {
  585.                 attention("検索文字列を指定してください");
  586.                 return FALSE;
  587.             }
  588.             if (!szreplace[0] && !fSearchlist) {
  589.                 HDIALOG hd = dialog("置換 - 確認");
  590.                 mchar buff[CCHLINE];
  591.                 
  592.                 dialogCaption(hd,"置換文字列が指定されていません。");
  593.                 sprintf(buff,"見つけた\"%s\"を全て削除します。",szfind);
  594.                 dialogCaption(hd,buff);
  595.                 dialogCaption(hd,"よろしいですか?");
  596.                 if (!dialogOpen(hd)) return FALSE;
  597.             }
  598.             if (id == IDD_AREA) {
  599.                 searchmode |= SEARCH_AREA;
  600.             } else {
  601.                 searchmode &= ~SEARCH_AREA;
  602.             }
  603.             searchmode |= REPLACE_CONFIRM * (_searchopt.fReplaceConfirm);
  604.             searchmode |= SEARCH_ALL * (id == IDD_ALL);
  605.             searchmode |= SEARCH_PREV * (id == IDD_PREV);
  606.             // for return FALSE
  607.             wzlock(LOCK_SEARCHALL);
  608.             text->share->replace.searchmode = searchmode;
  609.             strcpy(text->share->replace.szFind,szfind);
  610.             strcpy(text->share->replace.szReplace,szreplace);
  611.             wzunlock(LOCK_SEARCHALL);
  612.             //1.99G 置換がヒストリに記憶されなかった
  613.             histsearchAdd(szfind,searchmode,FALSE);
  614.             histsearchAdd(szreplace,0,TRUE);// 置換文字列はsearchmodeを記録しない
  615.             //1.99G SEARCH_SELECTを追加
  616.             ret = txReplaceEx(text,szfind,szreplace,searchmode|SEARCH_SELECT);
  617. ///            ret = txReplaceEx(text,szfind,szreplace,searchmode|SEARCH_SELECT|REPLACE_CONFIRMMODAL);
  618.         } else {
  619.             histsearchAdd(szfind,searchmode,FALSE);
  620.             if (mode & SEARCHDLG_VZ) {
  621.                 if (mode & SEARCHDLG_CAPTION) {
  622.                     ret = !(szfind == "");
  623.                 } else {
  624.                     text->pagingmode = 'S';
  625.                     if (szfind == "") {
  626.                         // 検索モードから抜ける
  627.                         txSwitchPagingMode(text);
  628.                     } else {
  629.                         SendMessage(text->hwndbase,WM_TXSB_SETUPTEXT,HSL_PAGE,0);
  630.                         ret = TRUE;
  631.                     }
  632.                 }
  633.             } else {
  634.                 BOOL fPrev = FALSE;
  635.                 txMarkCur(text);
  636.                 if (mode & SEARCHDLG_MINI) {
  637.                     if (mode & SEARCHDLG_PREV) {
  638.                         fPrev = TRUE;
  639.                     }
  640.                 } else {
  641.                     if (id == IDD_PREV) {
  642.                         fPrev = TRUE;
  643.                     }
  644.                 }
  645.                 if (fPrev) {
  646.                     ret = txSearchEx(text,szfind,searchmode|SEARCH_PREV);
  647.                     if (keymacroDoing()) keymacroAdd(wzcmdFromSzcmd("txSearchContinuePrev"));//1.00F
  648.                 } else {
  649.                     ret = txSearchEx(text,szfind,searchmode);
  650.                     if (keymacroDoing()) keymacroAdd(wzcmdFromSzcmd("txSearchContinue"));//1.00F
  651.                 }
  652.             }
  653.             if (!ret) {
  654.                 err();
  655.             }
  656.         }
  657.     }
  658.     *pRet = ret;
  659.     return TRUE;
  660. }
  661.  
  662. #if 1//3.00B1 970613 汎用化
  663.  
  664. //2.00B [欧文]表示では、検索ダイアログの検索文字列と置換文字列のフォントをテキストのフォントと同じにした
  665.  
  666. // wndSetFontAsText()でTRUEが返ったら、hctrlをDestroyする前に必ずこれを実行すること
  667. BOOL TXAPI wndSetFontAsText(HWND hctrl,TX* text)
  668. {
  669.     BOOL ret = FALSE;
  670.     if (text->fCurWestern || text->share->config.fSearchSetFont) {
  671.         if (hctrl) {
  672.             LOGFONT lf;
  673.             structClear(lf);
  674.             FONTSTYLE* fs = &text->tfonttx[FONTTX_TEXT].fs;
  675.             {
  676.                 HFONT hfont0 = (HFONT)SendMessage(hctrl,WM_GETFONT,0,0);
  677.                 if (hfont0 && GetObject(hfont0,sizeof(lf),&lf)) {
  678.                     // OK
  679.                 }
  680.             }
  681.             if (text->fCurWestern) {
  682.                 strcpy(lf.lfFaceName,fs->tlfFaceName[IFONT_ANK]);
  683.                 if (lf.lfFaceName[0] == 0) strcpy(lf.lfFaceName,"Arial");
  684.             } else {
  685.                 strcpy(lf.lfFaceName,fs->tlfFaceName[IFONT_STD]);
  686.             }
  687.             // for WZ32 : 通常は、FixedSysの高さよりもエディトボックスの高さの方が小さい
  688.             if (!stricmp(lf.lfFaceName,"FixedSys")) strcpy(lf.lfFaceName,"MS ゴシック");
  689. #if 0        // これだとWindows3.1で文字の下が切れるので、GetObjectするようにした
  690.             RECT r;
  691.             GetClientRect(hctrl,&r);
  692.             lf.lfHeight = rectCy(&r) - 1;// -2するとWZ32+欧文TimesNewRomanで小さ過ぎ
  693.                                          // -1しないとWZ16+FixedSysで'_'が見えない
  694. #endif
  695.             //
  696.             lf.lfWeight = FW_NORMAL;
  697.             lf.lfPitchAndFamily = DEFAULT_PITCH;
  698.             if (text->fCurWestern) {
  699.                 lf.lfCharSet = DEFAULT_CHARSET;
  700.             } else {
  701.                 lf.lfCharSet = SHIFTJIS_CHARSET;
  702.             }
  703.             HFONT hfont;
  704.             if (hfont = CreateFontIndirect(&lf)) {
  705.                 ret = TRUE;
  706.                 SendMessage(hctrl,WM_SETFONT,(WPARAM)hfont,0);
  707.             }
  708.         }
  709.     }
  710.     return ret;
  711. }
  712.  
  713. //2.00B 
  714. // wndSetFontAsText()でTRUEが返ったら、hctrlをDestroyする前に必ずこれを実行すること
  715. void TXAPI wndSetFontAsTextDelete(HWND hctrl)
  716. {
  717.     if (hctrl) {
  718.         HFONT hfont = (HFONT)SendMessage(hctrl,WM_GETFONT,0,0);
  719.         if (hfont) {
  720. //beep();wait(500);
  721.             DeleteObject(hfont);
  722.         }
  723.     }
  724. }
  725.  
  726. #else
  727.  
  728. //2.00B [欧文]表示では、検索ダイアログの検索文字列と置換文字列のフォントをテキストのフォントと同じにした
  729. static void SetFont(HWND hwnd,int id)
  730. {
  731.     if (text->fCurWestern || text->share->config.fSearchSetFont) {
  732.         HWND hctrl = GetDlgItem(hwnd,id);
  733.         if (hctrl) {
  734. #if 1//3.00A2 970504 「欧文+日本語」で「検索ダイアログをテキストフォントと同じ」にしても欧文フォントでの検索ができなかった
  735.             LOGFONT lf;
  736.             structClear(lf);
  737.             FONTSTYLE* fs = &text->tfonttx[FONTTX_TEXT].fs;
  738.             {
  739.                 HFONT hfont0 = (HFONT)SendMessage(hctrl,WM_GETFONT,0,0);
  740.                 if (hfont0 && GetObject(hfont0,sizeof(lf),&lf)) {
  741.                     // OK
  742.                 }
  743.             }
  744.             if (text->fCurWestern) {
  745.                 strcpy(lf.lfFaceName,fs->tlfFaceName[IFONT_ANK]);
  746.                 if (lf.lfFaceName[0] == 0) strcpy(lf.lfFaceName,"Arial");
  747.             } else {
  748.                 strcpy(lf.lfFaceName,fs->tlfFaceName[IFONT_STD]);
  749.             }
  750.             // for WZ32 : 通常は、FixedSysの高さよりもエディトボックスの高さの方が小さい
  751.             if (!stricmp(lf.lfFaceName,"FixedSys")) strcpy(lf.lfFaceName,"MS ゴシック");
  752. #if 0        // これだとWindows3.1で文字の下が切れるので、GetObjectするようにした
  753.             RECT r;
  754.             GetClientRect(hctrl,&r);
  755.             lf.lfHeight = rectCy(&r) - 1;// -2するとWZ32+欧文TimesNewRomanで小さ過ぎ
  756.                                          // -1しないとWZ16+FixedSysで'_'が見えない
  757. #endif
  758.             //
  759.             lf.lfWeight = FW_NORMAL;
  760.             lf.lfPitchAndFamily = DEFAULT_PITCH;
  761.             if (text->fCurWestern) {
  762.                 lf.lfCharSet = DEFAULT_CHARSET;
  763.             } else {
  764.                 lf.lfCharSet = SHIFTJIS_CHARSET;
  765.             }
  766.             HFONT hfont;
  767.             if (hfont = CreateFontIndirect(&lf)) {
  768.                 text->fSearchSetFont = TRUE;
  769.                 SendMessage(hctrl,WM_SETFONT,(WPARAM)hfont,0);
  770.             }
  771. #else
  772.             HFONT hfont = (HFONT)SendMessage(hctrl,WM_GETFONT,0,0);
  773.             LOGFONT lf;
  774.             if (hfont == NULL) {
  775.                 hfont = GetStockObject(GetSystemFontNo());
  776.             }
  777. //information("%d",hfont);
  778.             if (GetObject(hfont,sizeof(lf),&lf)) {
  779.                 FONTSTYLE* fs = &text->tfonttx[FONTTX_TEXT].fs;
  780.                 strcpy(lf.lfFaceName,fs->tlfFaceName[IFONT_STD]);
  781.                 lf.lfWeight = FW_NORMAL;
  782.                 lf.lfPitchAndFamily = DEFAULT_PITCH;
  783.                 if (text->fCurWestern) {
  784.                     lf.lfCharSet = DEFAULT_CHARSET;
  785.                 } else {
  786.                     lf.lfCharSet = SHIFTJIS_CHARSET;
  787.                 }
  788.                 if (hfont = CreateFontIndirect(&lf)) {
  789.                     text->fSearchSetFont = TRUE;
  790.                     SendMessage(hctrl,WM_SETFONT,(WPARAM)hfont,0);
  791.                 }
  792.             }
  793. #endif
  794.         }
  795.     }
  796. }
  797.  
  798. //2.00B 
  799. static void ResetFont(HWND hwnd,int id)
  800. {
  801.     HWND hctrl = GetDlgItem(hwnd,id);
  802.     if (hctrl) {
  803.         HFONT hfont = (HFONT)SendMessage(hctrl,WM_GETFONT,0,0);
  804.         if (hfont) {
  805.             DeleteObject(hfont);
  806.         }
  807.     }
  808. }
  809.  
  810. #endif
  811.  
  812. static int searchlistOpen(BOOL fRefer,txstr szSelected);
  813.  
  814. #define IDD_LIST    100
  815. extern "edit" BOOL TXAPI TXCMDBASE txClipboardCopy(TX* text);
  816.  
  817. static BOOL searchdlgGetID(void)
  818. {
  819. // 検索ダイアログのモードを返す
  820. // 0:検索,1:置換,2:検索閲覧
  821.     if (_hwndSearch) {
  822.         return _hwndSearchIsReplace;
  823.     }
  824.     return 2;
  825. }
  826.  
  827. #if 0
  828.  
  829. static void varSetXY(TX* text,int index,int x,int y)
  830. {
  831.     txVarSet(text,"\m.x"+numtostr(index),x);
  832.     txVarSet(text,"\m.y"+numtostr(index),y);
  833. }
  834.  
  835. static int varGetX(TX* text,int index)
  836. {
  837.     return txVarGet(text,"\m.x"+numtostr(index));
  838. }
  839.  
  840. static int varGetY(TX* text,int index)
  841. {
  842.     return txVarGet(text,"\m.y"+numtostr(index));
  843. }
  844.  
  845. #endif
  846.  
  847. static void wndMoveUncursor(HWND hwnd)
  848. {
  849.     //2.00E3 モードレス検索ダイアログの初期位置が邪魔にならないようにした
  850.     int im = searchdlgGetID();
  851.     RECT rSearch;
  852.     GetWindowRect(hwnd,&rSearch);
  853.     RECT rText;
  854.     GetWindowRect(text->hwndtext,&rText);
  855.     _x[im] = rText.right - rectCx(&rSearch);
  856.     _y[im] = rText.bottom - rectCy(&rSearch);
  857.     SetWindowPos(hwnd,NULL,_x[im],_y[im],0,0,SWP_NOSIZE);
  858. }
  859.  
  860. BOOL dlgprocSearchlook(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  861. {
  862.     HDIALOG hd = dialogFromHwnd(hwnd);
  863.     switch(message) {
  864.         case WM_INITDIALOG: {
  865.             wndMoveUncursor(hwnd);
  866.             PostMessage(hwnd,WM_TXUSER,0,0);
  867.             break;
  868.         }
  869.         case WM_COMMAND: {
  870.             int id = WM_COMMAND_GetId(wParam);
  871.             int notify = WM_COMMAND_GetNotify(wParam,lParam);
  872.             switch(id) {
  873.                 case IDD_LIST: {
  874.                     if (notify == LBN_SELCHANGE) {
  875.                         HWND hctrl = GetDlgItem(hwnd,IDD_LIST);
  876.                         int isel = ListBox_GetCurSel(hctrl);
  877.                         if (isel != LB_ERR) {
  878.                             txstr sz(ListBox_GetTextLen(hctrl,isel)+1);
  879.                             if (sz) {
  880.                                 ListBox_GetText(hctrl,isel,sz);
  881.                                 if (atoi(sz)) {
  882.                                     txJumpPara(text,atoi(sz));
  883.                                 }
  884.                             }
  885.                         }
  886.                     } else if (notify == LBN_DBLCLK) {
  887.                         FORWARD_WM_COMMAND(hwnd,IDOK,NULL,NULL,PostMessage);
  888.                         break;
  889.                     }
  890.                     break;
  891.                 }
  892.                 case IDD_COPY: {
  893.                     txClipboardCopy(text);
  894.                     break;
  895.                 }
  896.                 case IDD_SEARCH: {
  897.                     txstr szFind;
  898.                     SEARCHMODE searchmode;
  899.                     HSTRBLK sb = sbFromHist(HIST_SEARCH);
  900.                     int n = sbGetCount(sb);
  901.                     if (n) {
  902.                         szFind = sbRead(sb,n-1);
  903.                         searchmode = sbReadCustdata(sb,n-1);
  904.                     }
  905.                     if (txuiSearchSetForEx(text,"検索文字列",szFind,&searchmode)) {
  906.                         histsearchAdd(szFind,searchmode,FALSE);
  907.                         PostMessage(hwnd,WM_TXUSER,0,0);
  908.                     }
  909.                     return TRUE;
  910.                 }
  911.             }
  912.             break;
  913.         }
  914.         case WM_TXUSER: {
  915.             HSTRBLK sb = sbFromHist(HIST_SEARCH);
  916.             int n = sbGetCount(sb);
  917.             if (!n) break;
  918.             mchar* szFind = sbRead(sb,n-1);
  919.             DWORD searchmode = sbReadCustdata(sb,n-1);
  920.             //
  921.             TX _text0;
  922.             TX* text0 = &_text0;
  923.             if (txInit(text0,NULL)) {
  924.                 int n = 0;
  925.                 txstr szPara;
  926.                 txSetUndispEx(text);
  927.                 txJumpFileTop(text);
  928.                 while(1) {
  929.                     if (txSearchEx(text,szFind,searchmode)) {
  930.                         n++;
  931.                         txGetPara(text,szPara);
  932.                         txInsertf(text0,"%5d: ",text->npara);
  933.                         txInsert(text0,strGetWordTop(szPara));
  934.                         txInsertReturn(text0);
  935.                         if (!txNextPara(text)) break;
  936.                     } else {
  937.                         break;
  938.                     }
  939.                 }
  940.                 if (n == 0) {
  941.                     txInsertLine(text0,"%s は見つかりません",szFind);
  942.                 }
  943.                 txSetDispEx(text);
  944.                 {//2.99 970319 検索閲覧:検索文字列と件数を表示
  945.                     txstr buff;
  946.                     buff += "検索閲覧 - ";
  947.                     buff += szFind;
  948.                     buff += " : ";
  949.                     buff += inttostr(n);
  950.                     buff += "件";
  951.                     SetWindowText(hwnd,buff);
  952.                 }
  953.                 //
  954.                 HWND hctrl = GetDlgItem(hwnd,IDD_LIST);
  955.                 listboxFromText(hctrl,text0);
  956.                 //
  957. //                int isel = ListBox_GetCurSel(hctrl);
  958. //                if (isel < 0) ListBox_SetCurSel(hctrl,0);
  959. //                SetFocus(hctrl);
  960.                 //
  961.                 txClose(text0);
  962.             }
  963.             break;
  964.         }
  965.     }
  966.     return FALSE;
  967. }
  968.  
  969. BOOL TXCMDBASE searchLook(TX* text)
  970. {
  971. // 検索閲覧
  972. // 前回指定した検索文字列でテキスト全体を検索し、結果を一覧で表示する
  973. //2.95 970130 新コマンド
  974.     txMarkCur(text);
  975.     text->fNoMarkCur++;
  976.     {
  977.         //2.99D 970331 検索閲覧では下線、検索文字列の表示を強制ON
  978.         BOOL fDispUnder0 = text->fDispUnder;
  979.         BOOL fDispFindEnable0 = text->fDispFindEnable;
  980.         BOOL fDispFind0 = text->fDispFind;
  981.         text->fDispUnder = TRUE;
  982.         text->fDispFindEnable = TRUE;
  983.         if (!text->fDispFind) text->fDispFind = COLORING_COLOR_UNDER;
  984.         txFlush(text);
  985.         //
  986.         IFILE adr = txGetAddress(text);
  987.         HDIALOG hd = dialog("検索閲覧");
  988.         dialogSetHookEx(hd,"\m.dlgprocSearchlook");
  989.         dialogControlID(hd,IDD_LIST);
  990.         dialogList(hd,NULL,NULL,60,10);
  991.         //
  992.         dialogLFV(hd);
  993.         //
  994.         dialogControlID(hd,IDOK);
  995.         dialogCmdDefault(hd,"ジャンプ(&J)",16);
  996.         dialogControlID(hd,IDD_COPY);
  997.         dialogCmd(hd,"コピー(&C)",16);
  998.         dialogControlID(hd,IDD_SEARCH);
  999.         dialogCmd(hd,"検索文字列(&S)...",16);
  1000.         dialogCancel(hd,16);
  1001.         //
  1002.         if (dialogOpen(hd) != IDOK) {
  1003.             txJumpAddress(text,adr);
  1004.         }
  1005.         //2.99D 970331 
  1006.         text->fDispUnder = fDispUnder0;
  1007.         text->fDispFindEnable = fDispFindEnable0;
  1008.         text->fDispFind = fDispFind0;
  1009.         txFlush(text);
  1010.     }
  1011.     text->fNoMarkCur--;
  1012.     return TRUE;
  1013. }
  1014.  
  1015. BOOL dlgprocSearch(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  1016. {
  1017.     HDIALOG hd = dialogFromHwnd(hwnd);
  1018.     int mode = dialogGetCustdata(hd);
  1019.     
  1020.     switch(message) {
  1021.         case WM_INITDIALOG: {
  1022. #if 1//2.99C 970323 
  1023.             EnableDlgItem(hwnd,IDD_MODEREPLACETOP + 2,textf->fClip);
  1024. #else
  1025.             HWND hctrl = GetDlgItem(hwnd,IDD_MODEREPLACETOP + 2);
  1026.             if (hctrl) EnableWindow(hctrl,textf->fClip);
  1027. #endif
  1028. #if 1//3.00B1 970613 
  1029.             text->fSearchSetFont = wndSetFontAsText(GetDlgItem(hwnd,IDD_SZFIND),textf);
  1030.             text->fReplaceSetFont = wndSetFontAsText(GetDlgItem(hwnd,IDD_SZREPLACE),textf);
  1031. #else
  1032.             SetFont(hwnd,IDD_SZFIND);
  1033.             SetFont(hwnd,IDD_SZREPLACE);
  1034. #endif
  1035.             if (_hwndSearch) {
  1036.                 int im = searchdlgGetID();
  1037.                 if (_fWindowPos[im]) {
  1038.                     SetWindowPos(hwnd,NULL,_x[im],_y[im],0,0,SWP_NOSIZE);
  1039.                 } else {
  1040.                     wndMoveUncursor(hwnd);
  1041.                 }
  1042.             }
  1043.             break;
  1044.         }
  1045.         case WM_DESTROY: {
  1046. #if 1//3.00B1 970613 
  1047.             if (text->fSearchSetFont) {
  1048.                 text->fSearchSetFont = FALSE;
  1049.                 wndSetFontAsTextDelete(GetDlgItem(hwnd,IDD_SZFIND));
  1050.             }
  1051.             if (text->fReplaceSetFont) {
  1052.                 text->fReplaceSetFont = FALSE;
  1053.                 wndSetFontAsTextDelete(GetDlgItem(hwnd,IDD_SZREPLACE));
  1054.             }
  1055. #else
  1056.             if (text->fSearchSetFont) {//2.99D 970330 検索ダイアログでフォントをセットしてないときも解放していた
  1057.                 text->fSearchSetFont = FALSE;
  1058.                 ResetFont(hwnd,IDD_SZFIND);
  1059.                 ResetFont(hwnd,IDD_SZREPLACE);
  1060.             }
  1061. #endif
  1062.             break;
  1063.         }
  1064.         case WM_COMMAND: {
  1065.             int id = WM_COMMAND_GetId(wParam);
  1066.             int notify = WM_COMMAND_GetNotify(wParam,lParam);
  1067.             
  1068.             switch(id) {
  1069.                 case IDD_SZFIND: {
  1070.                     if (text->fVzTextBoxHist && notify == EN_CHANGE) {
  1071.                         PostMessage(hwnd,WM_TXUSER,0,0);
  1072.                     } else if (!text->fVzTextBoxHist &&
  1073.                         (notify == CBN_EDITCHANGE||notify == CBN_SELCHANGE)
  1074.                     ) {
  1075.                         PostMessage(hwnd,WM_TXUSER,0,0);
  1076.                     }
  1077.                     break;
  1078.                 }
  1079.                 case IDD_OPTION: {
  1080.                     // flush _searchopt
  1081.                     SendMessage(hwnd,WM_TXUSER,0,0);
  1082.                     //
  1083.                     HDIALOG hd = dialog("検索オプション");
  1084. #if 1//1.99A 
  1085.                     {
  1086.                         //1.99A モードレス版ではSEARCH_ALLTEXTできない仕様
  1087.                         DWORD exmode = 0;
  1088.                         if (!_hwndSearch) {
  1089.                             exmode |= SEARCH_ALLTEXT | REPLACE_CONFIRM;
  1090.                         }
  1091.                         dialogSearch(hd,text,MODEOPTION_ONLY,exmode);
  1092.                     }
  1093. #else
  1094.                     dialogSearch(hd,text,FALSE,2);
  1095. #endif
  1096.                     dialogOpen(hd);
  1097.                     return TRUE;
  1098.                 }
  1099.                 case IDD_REFERSEARCHLIST: {
  1100.                     #if 1//2.92 
  1101.                     txstr szSearchlist;
  1102.                     if (searchlistOpen(TRUE,szSearchlist)) {
  1103.                         szSearchlist = _szIdSearchlist + szSearchlist;
  1104.                         SetDlgItemText(hwnd,IDD_SZFIND,szSearchlist);
  1105.                     }
  1106.                     #else
  1107.                     PostMessage(hwnd,WM_COMMAND,IDCANCEL,0);
  1108.                     PostMessage(text->hwndbase,WM_COMMAND,IDM_WZCMDTOP + wzcmdRegister("\m.uiSearchList"),0);
  1109.                     #endif
  1110.                     return TRUE;
  1111.                 }
  1112.                 case IDD_NOESC: {
  1113.                     PostMessage(hwnd,WM_TXUSER,id,0);
  1114.                     break;
  1115.                 }
  1116.                 case IDD_SEARCHLOOK: {
  1117.                     dialogRead(hd);
  1118.                     //
  1119.                     SEARCHMODE searchmode = searchmodeFromSearchopt(&_searchopt);
  1120.                     histsearchAdd(szfind,searchmode,FALSE);
  1121.                     //
  1122.                     callPost("\m.searchLook");
  1123.                     return FALSE;
  1124.                 }
  1125.                 case IDD_SEARCHSPECIAL: {
  1126.                     callPost("\m.uiJumpEx");
  1127.                     PostMessage(hwnd,WM_COMMAND,IDCANCEL,0);
  1128.                     return FALSE;
  1129.                 }
  1130.             }
  1131.             if (_hwndSearch) {
  1132.                 switch(id) {
  1133.                     case IDCANCEL: {
  1134. #if 1//2.99D 970330 for DEBUGWIN err
  1135.                         searchClosed();
  1136. #else
  1137.                         searchClose();
  1138. #endif
  1139.                         return FALSE;
  1140.                     }
  1141.                     case IDOK:
  1142. //2.00B             case IDD_PREV:
  1143. //2.00B             case IDD_NEXT:
  1144.                     case IDD_ALL:
  1145.                     case IDD_AREA: {
  1146.                         dialogRead(hd);
  1147.                         int ret;
  1148.                         searchExec(_txSearch,id,&ret,mode);
  1149.                         return TRUE;
  1150.                     }
  1151.                     case IDD_PREV:    //2.00B 
  1152.                     case IDD_NEXT:    //2.00B 
  1153.                     case IDD_SEARCH:
  1154.                     case IDD_REPLACE: {
  1155.                         TX* text = _txSearch;//2.90 
  1156.                         dialogRead(hd);
  1157.                         SEARCHMODE searchmode = searchmodeFromSearchopt(&_searchopt);
  1158.                         if (id == IDD_PREV) {
  1159.                             searchmode |= SEARCH_PREV;
  1160.                             _context.modeDirection = DIR_PREV;
  1161.                             id = IDD_SEARCH;
  1162.                         } else if (id == IDD_NEXT) {
  1163.                             _context.modeDirection = DIR_NEXT;
  1164.                             id = IDD_SEARCH;
  1165.                         } else if (_context.modeDirection == DIR_PREV) {
  1166.                             searchmode |= SEARCH_PREV;
  1167.                         }
  1168. #if 0//2.99D 970402 
  1169.                         if (_fFocusSub == 1) SetFocus(text->hwndbase);//2.99C 970325 分割下側のウィンドウでモードレス検索できなかった
  1170. #endif
  1171.                         if (id == IDD_SEARCH) {
  1172.                             histsearchAdd(szfind,searchmode,FALSE);//1.99A 検索ヒストリに追加されてなかった
  1173.                             #if 1//1.99G 再検索で検索オプションが受け継がれなかった
  1174.                             text->searchmode = searchmode;
  1175.                             #endif
  1176.                             if (txSearchEx(text,szfind,searchmode|SEARCH_SELECT)) {
  1177.                                 //1.99A 見つけた文字列を表示させるためSEARCH_SELECTする
  1178.                                 err_clear();
  1179.                                 if (_hwndSearch) {
  1180.                                     //2.97 970225 モードレス検索ダイアログで検索結果がダイアログで隠れるのを改良
  1181.                                     POINT p;
  1182.                                     p.y = txOp(text,TXOP_LYTOY,text->ly + 1,0);
  1183.                                     ClientToScreen(text->hwndtext,&p);
  1184.                                     RECT r;
  1185.                                     GetWindowRect(hwnd,&r);
  1186.                                     if (p.y > r.top) {
  1187.                                         txSetLyCenter(text);
  1188.                                     }
  1189.                                 }
  1190.                             } else {
  1191.                                 err();
  1192.                             }
  1193.                         } else {
  1194. #if 1//2.99C 970324 ファイル全体に対してモードレス置換すると確認ダイアログが出ることがあった
  1195.                             searchmode &= ~REPLACE_CONFIRM;
  1196. #endif
  1197.                             searchmode |= SEARCH_CUR;
  1198.                             switch(_context.modeReplace) {
  1199.                                 case REPLACE_ALL: searchmode |= SEARCH_ALL;break;
  1200.                                 case REPLACE_AREA: searchmode |= SEARCH_AREA;break;
  1201.                                 default: searchmode |= REPLACE_ONCE;break;
  1202.                             }
  1203.                             if (searchmode & REPLACE_ONCE) {
  1204.                                 // カーソル位置を置換箇所に移動する
  1205.                                 txSearchEx(text,szfind,searchmode);
  1206.                             }
  1207.                             int n = txReplaceEx(text,szfind,szreplace,searchmode);
  1208.                             if (searchmode & REPLACE_ONCE) {
  1209.                                 // 次を検索
  1210.                                 if (txSearchEx(text,szfind,searchmode|SEARCH_SELECT)) {
  1211.                                     err_clear();
  1212.                                 } else {
  1213.                                     err();
  1214.                                 }
  1215.                             }
  1216.                         }
  1217. #if 0//2.99D 970402 
  1218.                         if (_fFocusSub == 1) SetFocus(hwnd);//2.99C 970325 分割下側のウィンドウでモードレス検索できなかった
  1219. #endif
  1220.                         return TRUE;
  1221.                     }
  1222.                     case IDD_TOREPLACE: {
  1223.                         dialogRead(hd);
  1224.                         searchClose();
  1225.                         PostMessage(text->hwndbase,
  1226.                             WM_COMMAND,
  1227.                             IDM_WZCMDTOP + wzcmdRegister("\m.uiReplaceModeless"),
  1228.                             0
  1229.                         );
  1230.                         return TRUE;
  1231.                     }
  1232.                 }
  1233.             }
  1234.             break;
  1235.         }
  1236.         case WM_CLOSE: {
  1237. #if 1//2.99F 970404 2.99Dでモードレス検索・置換ダイアログで×でダイアログを閉じれなかった
  1238.             // ダイアログプロシジャーはWM_CLOSEを処理しない
  1239.             searchClose();
  1240.             break;
  1241. #else
  1242.     #if 1//2.99D 970330 for DEBUGWIN err
  1243.             searchClosed();
  1244.             break;
  1245.     #else
  1246.             searchClose();
  1247.             break;
  1248.     #endif
  1249. #endif
  1250.         }
  1251.         case WM_TXUSER: {
  1252.             HSTRBLK sb = histToStrblk(HIST_SEARCH);
  1253.             mchar buff[CCHWORD];
  1254.             GetDlgItemText(hwnd,IDD_SZFIND,buff,CCHWORD);
  1255.             //
  1256.             BOOL f = sbGetSenseCase(sb);
  1257.             sbSetSenseCase(sb,TRUE);// 大文字 小文字を区別
  1258.             int i = sbiSearch(sb,buff);
  1259.             if (
  1260.                 i != -1 && !text->share->config.fNoMemorySearchOption &&
  1261.                 wParam != IDD_NOESC    //3.00A3 970508 「\を通常文字」が変更できないことがあった
  1262.             ) {
  1263.                 dialogRead(hd);
  1264.                 DWORD searchmode = sbReadCustdata(sb,i);
  1265.                 //
  1266.                 BOOL fCategory = _searchopt.fCategory;
  1267.                 searchmodeToSearchopt(searchmode,&_searchopt);
  1268.                 _searchopt.fCategory = fCategory;
  1269.                 //
  1270.                 dialogWriteItem(hd,IDD_CASE);
  1271.                 dialogWriteItem(hd,IDD_NOSYMBOL);
  1272.                 dialogWriteItem(hd,IDD_ZENHAN);
  1273.                 dialogWriteItem(hd,IDD_WORD);
  1274.                 dialogWriteItem(hd,IDD_RE);
  1275.                 dialogWriteItem(hd,IDD_NOESC);
  1276.                 dialogWriteItem(hd,IDD_ALLTEXT);
  1277.                 {
  1278.                     int id;
  1279.                     for (id = IDD_MODETOP;id <= IDD_MODEEND;id++) {
  1280.                         dialogWriteItem(hd,id);
  1281.                     }
  1282.                 }
  1283.             }
  1284.             sbSetSenseCase(sb,f);// 大文字 小文字を区別を元に戻す
  1285.             //2.92 
  1286.             {
  1287.                 BOOL f = (strncmp(buff,_szIdSearchlist,_lchIdSearchlist) != 0);
  1288.                 if (IsDlgButtonChecked(hwnd,IDD_NOESC)) f = TRUE;
  1289. #if 1//2.99D 970330 
  1290.                 EnableDlgItem(hwnd,IDD_MODETOP,f);
  1291.                 EnableDlgItem(hwnd,IDD_MODETOP+1,f);
  1292.                 EnableDlgItem(hwnd,IDD_MODETOP+2,f);
  1293.                 EnableDlgItem(hwnd,IDD_MODETOP+3,f);
  1294.                 EnableDlgItem(hwnd,IDD_CASE,f);
  1295.                 EnableDlgItem(hwnd,IDD_NOSYMBOL,f);
  1296.                 EnableDlgItem(hwnd,IDD_SZREPLACE,f);
  1297. #else
  1298.                 EnableWindow(GetDlgItem(hwnd,IDD_MODETOP),f);
  1299.                 EnableWindow(GetDlgItem(hwnd,IDD_MODETOP+1),f);
  1300.                 EnableWindow(GetDlgItem(hwnd,IDD_MODETOP+2),f);
  1301.                 EnableWindow(GetDlgItem(hwnd,IDD_MODETOP+3),f);
  1302.                 EnableWindow(GetDlgItem(hwnd,IDD_CASE),f);
  1303.                 EnableWindow(GetDlgItem(hwnd,IDD_NOSYMBOL),f);
  1304.                 EnableWindow(GetDlgItem(hwnd,IDD_SZREPLACE),f);
  1305. #endif
  1306.             }
  1307.             break;
  1308.         }
  1309.         case WM_MOVE: {
  1310.             // 位置を覚える
  1311.             if (_hwndSearch) {
  1312.                 int im = searchdlgGetID();
  1313.                 _fWindowPos[im] = TRUE;
  1314.                 WINDOWPLACEMENT wplace;
  1315.                 wplace.length = sizeof(WINDOWPLACEMENT);
  1316.                 GetWindowPlacement(hwnd,(LPWINDOWPLACEMENT)&wplace);
  1317.                 _x[im] = wplace.rcNormalPosition.left;
  1318.                 _y[im] = wplace.rcNormalPosition.top;
  1319.             }
  1320.             break;
  1321.         }
  1322.         case WM_ACTIVATE: {//2.99C 970323 置換ダイアログの"範囲内"改善
  1323.             BOOL fActive = LOWORD(wParam);
  1324.             if (fActive != WA_INACTIVE) {
  1325.                 EnableDlgButtonEx(hwnd,IDD_MODEREPLACETOP + 2,textf->fClip,IDD_MODEREPLACETOP);
  1326.             }
  1327.             break;
  1328.         }
  1329.     }
  1330.     return FALSE;
  1331. }
  1332.  
  1333. //_search.cからも呼ばれる
  1334. //ネストは不可能
  1335. int search(int mode)
  1336. {
  1337.     BOOL fReplace = ((mode & SEARCHDLG_REPLACE) != 0);
  1338.     BOOL fModeless = ((mode & SEARCHDLG_MODELESS) != 0);
  1339.     BOOL fButton = text->share->config.fSearchButton;
  1340.     _fReplace = fReplace;//1.01A 
  1341.     if (text->fDispFindAtSearch) {//2.99C 970323 
  1342.         text->fDispFindEnable = TRUE;
  1343.     }
  1344. #if 1
  1345.     //1.99G 検索モードレスを開いてて置換が選択されたときに対応
  1346.     // 現在ダイアログを開いているとき以前とモードが違えばダイアログを作り直す
  1347.     if (_hwndSearch) {
  1348.         if (_modeSearch == mode) {
  1349.             SetActiveWindow(_hwndSearch);
  1350.             SetFocus(_hwndSearch);
  1351.             return 0;
  1352.         } else {
  1353.             searchClose();
  1354.         }
  1355.     }
  1356.     _modeSearch = mode;
  1357. #else
  1358.     if (_hwndSearch) {
  1359.         SetActiveWindow(_hwndSearch);
  1360.         SetFocus(_hwndSearch);
  1361.         return 0;
  1362.     }
  1363. #endif
  1364. #if 0//2.00E4 
  1365.     memset(&_context,0,sizeof(_context));
  1366. #endif
  1367.     
  1368.     int ret = 0;
  1369.     
  1370.     if (keymacroDoing()) {
  1371.         keymacroPop();
  1372.     }
  1373.     
  1374.     if (text->modeSearchDialog == 2 && !fReplace) mode |= SEARCHDLG_MINI;
  1375. #if 1//1.00B 範囲選択時の検索文字列取得を改善
  1376.     if (text->fClip == CLIP_BOX) {
  1377.         attention("箱範囲指定中は検索/置換できません");
  1378.         return 0;
  1379.     }
  1380.     if (!(mode & SEARCHDLG_SZFIND)) {
  1381.         if (text->fBinedit) {
  1382.             if (txIsClipInPara(text)) {
  1383.                 szfind = "\\xx";
  1384.                 txstr sz;
  1385.                 int cb = txGetWord(text,sz);
  1386.                 for (mchar*p = sz;cb--;p++) {
  1387.                     mchar buff[10];
  1388.                     sprintf(buff,"%02X",*p);
  1389.                     szfind += buff;
  1390.                 }
  1391.             } else {
  1392.                 sprintf(szfind,"\\xx%02X",text->buff[text->cur]);
  1393.             }
  1394.         } else {
  1395.             if (txIsClipInPara(text)) {
  1396.                 txGetWord(text,szfind);
  1397.             } else {
  1398.                 if (text->share->config.fSearchGetText && !isspace(txGetChar(text))) {
  1399.                     txGetWord(text,szfind);
  1400.                 }
  1401.             }
  1402.         }
  1403.     }
  1404. #else
  1405.     if (!isspace(getchar)) txGetWord(text,szfind);
  1406. #endif
  1407.     #if 1//2.92 
  1408.     if (mode & SEARCHDLG_CONFIRM) text->searchmode |= REPLACE_CONFIRM;
  1409.     #else
  1410.     _fReplaceConfirm = (mode & SEARCHDLG_CONFIRM);
  1411.     #endif
  1412.     while(1) {
  1413.         int cx = 16;
  1414.         int id;
  1415.         HDIALOG hd;
  1416.         
  1417.         //1.00C 検索/置換ダイアログはカーソル位置に出る様に改良
  1418.         if (mode & SEARCHDLG_CAPTION) {
  1419.         } else if (fReplace) {
  1420.             _szcaption = "置換";
  1421.         } else if (mode & SEARCHDLG_VZ) {
  1422.             _szcaption = "検索 - VZ";
  1423.         } else if ((mode & SEARCHDLG_MINI) && (mode & SEARCHDLG_PREV)) {
  1424.             _szcaption = "検索 - カーソル以前";
  1425.         } else {
  1426.             _szcaption = "検索";
  1427.         }
  1428.         _hdreplace = hd = _dialog(
  1429.             _szcaption,
  1430.             EXDS_POSCURSOR|!(mode & SEARCHDLG_MINI) * EXDS_BIG,
  1431.             NULL
  1432.         );
  1433.         dialogSetCustdata(hd,mode);
  1434.         dialogSetHookEx(hd,"\m.dlgprocSearch");
  1435.         dialogSetContexthelp(hd,TRUE);
  1436.         {
  1437.             //1.99A モードレス版ではSEARCH_ALLTEXTできない仕様
  1438.             DWORD exmode = fModeless ? 0 : SEARCH_ALLTEXT;
  1439.             if (fReplace) {
  1440.                 exmode |= SEARCH_REPLACE;
  1441.                 if (!fModeless) exmode |= REPLACE_CONFIRM;
  1442.             }
  1443.             dialogSearch(
  1444.                 hd,text,
  1445.                 (mode & SEARCHDLG_MINI) ? MODEOPTION_NONE : MODEOPTION_WITH,
  1446.                 exmode|SEARCH_DIALOGCOMPACT|SEARCH_DIALOGSLIST
  1447.             );
  1448.         }
  1449.         if (mode & SEARCHDLG_MINI) {
  1450.             dialogLFV(hd);
  1451.             dialogOK(hd,6);
  1452.             dialogLFV(hd);
  1453.             dialogControlID(hd,IDD_OPTION);
  1454.             dialogCmd(hd,"オプション(&O)...",cx);
  1455.             dialogSetNoButton(hd);
  1456.         } else if (mode & SEARCHDLG_VZ) {
  1457.             if (fReplace) {
  1458.                 dialogLFV(hd);
  1459.                 dialogOK(hd,cx);
  1460.                 dialogCancel(hd,cx);
  1461.                 dialogSpaceV(hd);
  1462.             }
  1463.         } else {
  1464.             dialogLFV(hd);
  1465.             
  1466.             dialogIndent(hd,2);
  1467.             
  1468.             if (fModeless) {
  1469. #if 0//2.00E4 モードレス検索ダイアログでカーソル以前/以降を覚える様にした
  1470.                 _context.modeDirection = DIR_NEXT;
  1471. #endif
  1472.                 dialogSetIntXY(hd,0,0);
  1473.                 if (!fButton) {
  1474.                     dialogControlRadioV(hd);
  1475.                     dialogControlHelp(hd,-303);
  1476.                     dialogRadioIDB(hd,&_context.modeDirection,"上へ(&P)","下へ(&N)");
  1477.                     if (fReplace) {
  1478.                         dialogHeadline(hd,NULL,12);
  1479.                     } else {
  1480.                         dialogLFV(hd);
  1481.                     }
  1482.                 }
  1483.                 if (fReplace) {
  1484.                     if (!text->fClip && _context.modeReplace == REPLACE_AREA) {
  1485.                         _context.modeReplace = REPLACE_1;
  1486.                     }
  1487.                     dialogControlRadioV(hd);
  1488.                     dialogControlID(hd,IDD_MODEREPLACETOP);
  1489.                     dialogControlHelp(hd,-305);
  1490.                     dialogRadioIDB(hd,&_context.modeReplace,"1つ置換(&1)","全て(&2)","範囲内(&3)");
  1491.                     dialogLFV(hd);
  1492.                 }
  1493.                 dialogResetInt(hd);
  1494.                 //
  1495.                 if (fButton) {
  1496.                     dialogControlID(hd,IDD_PREV);
  1497.                     dialogControlHelp(hd,192);
  1498.                     dialogCmd(hd,"上へ(&P)",cx);
  1499.                     dialogControlID(hd,IDD_NEXT);
  1500.                     dialogControlHelp(hd,193);
  1501.                     dialogCmdDefault(hd,"下へ(&N)",cx);
  1502.                 } else {
  1503.                     dialogControlID(hd,IDD_SEARCH);
  1504.                     dialogControlHelp(hd,195);
  1505.                     dialogCmdDefault(hd,"次を検索",cx);
  1506.                 }
  1507.                 dialogControlID(hd,IDCANCEL);
  1508.                 dialogCancel(hd,cx);
  1509.                 if (fReplace) {
  1510.                     dialogSpaceV(hd);
  1511.                     dialogControlID(hd,IDD_REPLACE);
  1512.                     dialogControlHelp(hd,197);
  1513.                     dialogCmd(hd,"置換(&R)",cx);
  1514.                 }
  1515. #if 0//2.97 970225 
  1516.                 dialogHelpID(hd,cx,"wz",fReplace ? IDH_REPLACE : IDH_SEARCH);
  1517.                 //
  1518.                 dialogSpace(hd);
  1519.                 dialogControlID(hd,IDD_REFERSEARCHLIST);
  1520.                 dialogControlHelp(hd,203);
  1521.                 dialogCmd(hd,"検索リスト(&L)...",cx);
  1522.                 //
  1523.                 if (!fReplace) {
  1524.                     dialogControlID(hd,IDD_TOREPLACE);
  1525.                     dialogControlHelp(hd,198);
  1526.                     dialogCmd(hd,"置換(&R) >>",cx);
  1527.                 }
  1528. #endif
  1529.             } else {
  1530.                 if (mode & SEARCHDLG_PREV) {
  1531.                     dialogControlID(hd,IDD_PREV);
  1532.                     dialogControlHelp(hd,192);
  1533.                     dialogCmdDefault(hd,"上へ(&P)",cx);
  1534.                     dialogControlID(hd,IDD_NEXT);
  1535.                     dialogControlHelp(hd,193);
  1536.                     dialogCmd(hd,"下へ(&N)",cx);
  1537.                 } else {
  1538.                     if (fReplace) {
  1539.                         dialogControlEnable(hd,!text->fClip || txIsClipInPara(text));
  1540.                         dialogControlHelp(hd,199);
  1541.                     } else {
  1542.                         dialogControlHelp(hd,192);
  1543.                     }
  1544.                     dialogControlID(hd,IDD_PREV);
  1545.                     dialogCmd(hd,"上へ(&P)",cx);
  1546.                     
  1547.                     if (fReplace) {
  1548.                         dialogControlEnable(hd,!text->fClip || txIsClipInPara(text));
  1549.                         dialogControlHelp(hd,200);
  1550.                     } else {
  1551.                         dialogControlHelp(hd,193);
  1552.                     }
  1553.                     dialogControlID(hd,IDD_NEXT);
  1554.                     dialogCmdDefault(hd,"下へ(&N)",cx);
  1555.                 }
  1556.                 if (fReplace) {
  1557.                     dialogSpace(hd);
  1558.                     
  1559.                     dialogControlEnable(hd,text->fClip);
  1560.                     if (text->fClip && !txIsClipInPara(text)) {
  1561.                         dialogControlID(hd,IDD_AREA);
  1562.                         dialogControlHelp(hd,202);
  1563.                         dialogCmdDefault(hd,"範囲内(&B)",cx);
  1564.                     } else {
  1565.                         dialogControlID(hd,IDD_AREA);
  1566.                         dialogControlHelp(hd,202);
  1567.                         dialogCmd(hd,"範囲内(&B)",cx);
  1568.                     }
  1569.                     
  1570.                     dialogControlEnable(hd,!text->fClip || txIsClipInPara(text));
  1571.                     dialogControlID(hd,IDD_ALL);
  1572.                     dialogControlHelp(hd,201);
  1573.                     dialogCmd(hd,"全て(&A)",cx);
  1574.                 }
  1575.                 dialogCancel(hd,cx);
  1576. #if 0//2.97 970225 
  1577.                 dialogHelpID(hd,cx,"wz",fReplace ? IDH_REPLACE : IDH_SEARCH);
  1578.                 dialogSpaceV(hd);
  1579.                 dialogControlID(hd,IDD_REFERSEARCHLIST);
  1580.                 dialogControlHelp(hd,203);
  1581.                 dialogCmd(hd,"検索リスト(&L)...",cx);
  1582. #endif
  1583.             }
  1584. #if 0
  1585.             //2.95 970130 
  1586.             dialogControlID(hd,IDD_SEARCHLOOK);
  1587.             dialogCmd(hd,"検索閲覧(&O) >>",cx);
  1588. #endif
  1589.             //2.97 970225 
  1590.             if (!fReplace) {
  1591.                 dialogControlID(hd,IDD_SEARCHSPECIAL);
  1592.                 dialogCmd(hd,"ジャンプ(&U) >>",cx);
  1593.             }
  1594.         }
  1595.         //2.99 970320 検索ダイアログではIMEの制御をしないようにした。
  1596.         // つかいにくかった
  1597.         if (fModeless) {
  1598.             text->fNoImeControl++;//2.99 970320 
  1599.             //1.99G for Window Pos 記憶に必要である。
  1600.             // dialogCreate中に呼び出されるWM_INITDIALOGでは
  1601.             // まだdialogCreateの結果が_hwndSearchに代入されていないため
  1602. #if 0    //2.99D 970402 これだけではだめで、根本的に直した
  1603.             _fFocusSub = txIsFocusSub(text);//2.99C 970325 
  1604. #endif
  1605.             _hwndSearch = TRUE;
  1606.             txMarkCur(text);//2.99 970320 モードレス検索で検索開始地点がマーク0に記憶されなかった
  1607.             _txSearch = text;//2.90 
  1608.             _hwndSearchIsReplace = fReplace;//2.97 970225 
  1609.             //
  1610.             _hwndSearch = dialogCreate(hd);
  1611.             text->fNoImeControl--;//2.99 970320 
  1612.             return TRUE;
  1613.         } else {
  1614.             text->fNoImeControl++;//2.99 970320 
  1615.             id = dialogOpen(hd);
  1616.             text->fNoImeControl--;//2.99 970320 
  1617.             if (id == IDD_SEARCHLOOK) id = 0;
  1618.             if (id == IDD_SEARCHSPECIAL) id = 0;
  1619.             if (id) {
  1620.                 if (!searchExec(text,id,&ret,mode)) continue;
  1621.             } else {
  1622.                 if (text->pagingmode == 'S') txSwitchPagingMode(text);
  1623.             }
  1624.             _hdreplace = NULL;
  1625.             return ret;
  1626.         }
  1627.     }
  1628. }
  1629.  
  1630. // thanks y.mikomeさん
  1631. static int _txkeySearchContinue(TX* text,BOOL fPrev)
  1632. {
  1633.     if (text->fDispFindAtSearch) {//2.99C 970323 
  1634.         text->fDispFindEnable = TRUE;
  1635.     }
  1636.     if (text->fClipMouse && !text->fClipSearch && txIsClipInPara(text)) {
  1637.         // 選択されているときは、その文字列で再検索する。
  1638.         txstr szStr;
  1639.         txGetWord(text,szStr);
  1640.         histsearchAdd(szStr,0,TRUE);
  1641.         if (fPrev) txJumpSelectTop(text);
  1642.         txSelectQuit(text);
  1643.         txMarkCur(text);
  1644.     }
  1645.     if (fPrev) {
  1646.         return txSearchContinuePrev(text);
  1647.     } else {
  1648.         return txSearchContinue(text);
  1649.     }
  1650. }
  1651.  
  1652. //2.99 970314 txkeyプレフィックスを追加
  1653. BOOL TXCMDBASE txkeySearchContinuePrev(TX* text)
  1654. {
  1655. // 上方向への再検索
  1656. //2.97 970225 new
  1657. //2.99A 970321 {#MS} +{F4} ^%Y -> {#MS} +{F3} ^{PageUp}
  1658. //{#MS} +{F3} ^%Y ^{PageUp}
  1659. //{#MI} +{F5}
  1660.     return _txkeySearchContinue(text,TRUE);
  1661. }
  1662.  
  1663. //2.99 970314 txkeyプレフィックスを追加
  1664. //2.99I 970405 MS.KEY +{F4}を外した。このキーには文字列の補完を割り当てた
  1665. BOOL TXCMDBASE txkeySearchContinue(TX* text)
  1666. {
  1667. // 下方向への再検索
  1668. //2.97 970225 new
  1669. //2.99A 970321 {#MS} {F4} +^Y -> {#MS} {F3} +{F4} +^Y ^{PageDown}
  1670. //{#MS} {F3} +^Y ^{PageDown}
  1671. //{#MI} {F5}
  1672.     return _txkeySearchContinue(text,FALSE);
  1673. }
  1674.  
  1675. BOOL TXAPI txuiSearchSetFor(tx *text,mchar *szcaption,txstr _szfind)
  1676. {
  1677. //検索ダイアログボックスを出す
  1678. //文字列が入力されたかどうか返す
  1679. //_szfindに入力された文字列をセットします。
  1680. //1.00Cで追加
  1681.     _szcaption = szcaption;
  1682.     BOOL ret = search(SEARCHDLG_VZ|SEARCHDLG_CAPTION);
  1683.     if (ret) {
  1684.         _szfind = szfind;
  1685.     }
  1686.     return ret;
  1687. }
  1688.  
  1689. BOOL TXAPI txuiSearchSetForEx(tx *text,mchar *szcaption,txstr _szfind,DWORD* searchmode)
  1690. {
  1691. //検索ダイアログボックスを出す
  1692. //文字列が入力されたかどうか返す
  1693. //_szfindに入力された文字列をセットします。
  1694. //*searchmodeに指定された検索オプションをセットします。
  1695. //1.91A で追加
  1696. #if 1//1.92 
  1697.     SEARCHMODE searchmode0 = text->searchmode;
  1698.     _szcaption = szcaption;
  1699.     szfind = _szfind;//2.90 _szfindをデフォルトで表示するようにした
  1700.     text->searchmode = *searchmode;
  1701.     BOOL ret = search(SEARCHDLG_VZ|SEARCHDLG_CAPTION|SEARCHDLG_SZFIND);
  1702.     if (ret) {
  1703.         _szfind = szfind;
  1704.         *searchmode = text->searchmode;
  1705.     }
  1706.     text->searchmode = searchmode0;
  1707.     return ret;
  1708. #else
  1709.     DWORD searchmodeTemp = searchmodeFromText(text);
  1710.     _szcaption = szcaption;
  1711.     searchmodeToText(text,*searchmode);
  1712.     BOOL ret = search(SEARCHDLG_VZ|SEARCHDLG_CAPTION|SEARCHDLG_SZFIND);
  1713.     if (ret) {
  1714.         _szfind = szfind;
  1715.         *searchmode = searchmodeFromText(text);
  1716.     }
  1717.     searchmodeToText(text,searchmodeTemp);
  1718.     return ret;
  1719. #endif
  1720. }
  1721.  
  1722. vzuiSearch
  1723. {
  1724. // VZ互換検索ダイアログ
  1725. //1.00Cで追加
  1726.     search(SEARCHDLG_VZ|SEARCHDLG_MINI);
  1727. }
  1728.  
  1729. uiSearchModeless
  1730. {
  1731. // モードレス検索ダイアログ
  1732. //1.96で追加
  1733. #if 1//1.99G 
  1734.     #if 1//2.00B モードレス検索/置換ダイアログで、選択された単語やカーソル位置の単語を検索文字列の初期値にセットするようにした
  1735.     search(SEARCHDLG_MODELESS);
  1736.     #else
  1737.     search(SEARCHDLG_MODELESS|SEARCHDLG_SZFIND);
  1738.     #endif
  1739. #else
  1740.     search(SEARCHDLG_MODELESS);
  1741. #endif
  1742. }
  1743.  
  1744. uiReplaceModeless
  1745. {
  1746. // モードレス置換ダイアログ
  1747. //1.96で追加
  1748.     #if 1//2.00B 
  1749.     search(SEARCHDLG_REPLACE|SEARCHDLG_CONFIRM|SEARCHDLG_MODELESS);
  1750.     #else
  1751.     search(SEARCHDLG_REPLACE|SEARCHDLG_CONFIRM|SEARCHDLG_MODELESS|SEARCHDLG_SZFIND);
  1752.     #endif
  1753. }
  1754.  
  1755. BOOL TXAPI TXCMD txuiSearchMini(tx *text)
  1756. {
  1757. // 検索(小さいダイアログ版)
  1758. //1.00Cで追加
  1759.     return search(SEARCHDLG_MINI);
  1760. }
  1761.  
  1762. BOOL TXAPI TXCMD txuiSearchPrevMini(tx *text)
  1763. {
  1764. // 前方検索(小さいダイアログ版)
  1765. //1.00Cで追加
  1766.     return search(SEARCHDLG_MINI|SEARCHDLG_PREV);
  1767. }
  1768.  
  1769. BOOL TXCMDBASE txkeySearch(TX* text)
  1770. {
  1771. // モーダル/モードレス切り替え可能な検索ダイアログ
  1772. //2.99A 970320 new
  1773. //2.99A 970321 {#MS} ^F new
  1774. //{#MS} ^F
  1775.     if (text->share->config.fSearchModeless) {
  1776.         return uiSearchModeless();
  1777.     } else {
  1778.         return txuiSearch(text);
  1779.     }
  1780. }
  1781.  
  1782. BOOL TXCMDBASE txkeyReplace(TX* text)
  1783. {
  1784. // モーダル/モードレス切り替え可能な置換ダイアログ
  1785. //2.99A 970320 new
  1786. //2.99A 970321 {#MS} ^H ^R new
  1787. //{#MS} ^H ^R
  1788.     if (text->share->config.fSearchModeless) {
  1789.         return uiReplaceModeless();
  1790.     } else {
  1791.         return txuiReplace(text);
  1792.     }
  1793. }
  1794.  
  1795. //## grep
  1796.  
  1797. BOOL TXCMDBASE grep(TX* text)
  1798. {
  1799.     // WZ Grepを起動します
  1800.     // 1.00Fで追加
  1801.     //{#EMACS} +{F6}
  1802.     txstr szfind;
  1803.     if (txIsClipInPara(text)) txGetWord(text,szfind);
  1804. #if 1//2.99D 970330 sw
  1805.     if (szfind == "") {
  1806.         macroFork("grep /i-");
  1807.     } else {
  1808.         macroFork("grep /i- -s\x0C" + szfind + "\x0C");
  1809.     }
  1810. #else
  1811.     //2.94 970121 "/I"追加
  1812.     if (szfind == "") {
  1813.         macroFork("grep /I");
  1814.     } else {
  1815.         macroFork("grep /I -s\x0C" + szfind + "\x0C");
  1816.     }
  1817. #endif
  1818.     return TRUE;
  1819. }
  1820.  
  1821. //## 特殊文字の検索
  1822.  
  1823. static BOOL _txSearchPlug(TX* text,int idplug,IFILE adr)
  1824. {
  1825.     CHARATR charatr;
  1826.     charatrRead(text,adr,&charatr);
  1827.     if (charatr.fLink) {
  1828.         if (plugatrGetModePlug(text,charatrGetPlug(charatr)) == idplug) {
  1829.             return TRUE;
  1830.         }
  1831.     }
  1832.     return FALSE;
  1833. }
  1834.  
  1835. static BOOL txSearchPlug(TX* text,int idplug,SEARCHMODE searchmode,mchar* szArg1,mchar* szArg2)
  1836. {
  1837. // szArg1,szArg2が""でなければ次の絞り込み検索を行う。
  1838. //    idplug            szArg1            szArg2
  1839. //    PLUG_IMG:        図のファイル名
  1840. //    PLUG_FOOTNOTE    脚注の内容
  1841. //    PLUG_RUBY        ルビの漢字        ルビのよみがな
  1842. //    PLUG_LINK        リンク先のファイル名    キャプション
  1843. //    PLUG_PROOF        校正の内容        校正者
  1844. //    PLUG_HTML_TAG    タグの内容
  1845. //2.99 970313 改良
  1846.     IFILE adr = txGetAddress(text);
  1847.     IFILE adrCurscreen = txGetAddressCurscreen(text);
  1848. //information("%d",idplug);
  1849.     if (idplug == PLUG_TAB) {
  1850.         //2.99 970313 選択するようにした
  1851.         BOOL fNow = (txIsCurParaIncludeTable(text) != NULL);//カーソル位置がTRUEなら、次の表を検索
  1852.         BOOL ret = FALSE;
  1853.         txSetUndisp(text);
  1854.         if (searchmode & SEARCH_PREV) {
  1855.             while(1) {
  1856.                 if (!txPrevPara(text)) break;
  1857.                 if (txIsCurParaIncludeTable(text)) {
  1858.                     if (!fNow) {
  1859.                         ret = TRUE;
  1860.                         break;
  1861.                     }
  1862.                 } else {
  1863.                     fNow = FALSE;
  1864.                 }
  1865.             }
  1866.         } else {
  1867.             while(1) {
  1868.                 if (!txNextPara(text)) break;
  1869.                 if (txIsCurParaIncludeTable(text)) {
  1870.                     if (!fNow) {
  1871.                         ret = TRUE;
  1872.                         break;
  1873.                     }
  1874.                 } else {
  1875.                     fNow = FALSE;
  1876.                 }
  1877.             }
  1878.         }
  1879.         if (ret) {
  1880.             // 表の末尾行へ
  1881.             while(1) {
  1882.                 if (!txIsCurParaIncludeTable(text)) {
  1883.                     break;
  1884.                 }
  1885.                 if (!txNextPara(text)) break;
  1886.             }
  1887.             txSelectEx(text,CLIP_SEARCH);
  1888.             // 表の先頭行へ
  1889.             while(1) {
  1890.                 if (!txPrevPara(text)) break;
  1891.                 if (!txIsCurParaIncludeTable(text)) {
  1892.                     txNextPara(text);
  1893.                     break;
  1894.                 }
  1895.             }
  1896.             if (text->fJumpCursorCenter) txSetLyCenter(text);
  1897.         } else {
  1898.             txSelectQuit(text);
  1899.             txJumpAddress(text,adr);
  1900.             txSetLyCurscreen(text,adrCurscreen);
  1901.         }
  1902.         txSetDisp(text);
  1903.         return ret;
  1904.     } else {
  1905.         mchar szFind[2] = {CHAR_PLUG,0};
  1906.         BOOL ret = FALSE;
  1907.         txSetUndisp(text);
  1908.         while(1) {
  1909.             if (txSearchEx(text,szFind,searchmode)) {
  1910.                 if (_txSearchPlug(text,idplug,txGetAddress(text))) {
  1911.                     LPVOID ph = txGetCurPlug(text);
  1912.                     BOOL f = TRUE;
  1913.                     switch(idplug) {
  1914.                         case PLUG_IMG: {
  1915.                             PLUGIMG* plug = ph;
  1916.                             if (szArg1 && szArg1[0]) {
  1917.                                 f = (stristr(plug->szfilename,szArg1) != NULL);
  1918.                             }
  1919.                             break;
  1920.                         }
  1921.                         case PLUG_HTML_TAG: {
  1922.                             PLUGHTMLTAG* plug = ph;
  1923.                             if (szArg1 && szArg1[0]) {
  1924.                                 f = (stristr(plug->szTag,szArg1) != NULL);
  1925.                             }
  1926.                             break;
  1927.                         }
  1928.                         case PLUG_FOOTNOTE: {
  1929.                             PLUGFOOTNOTE* plug = ph;
  1930.                             if (szArg1 && szArg1[0]) {
  1931.                                 f = (stristr(plug->szFootnote,szArg1) != NULL);
  1932.                             }
  1933.                             break;
  1934.                         }
  1935.                         case PLUG_RUBY: {
  1936.                             PLUGRUBY* plug = ph;
  1937.                             if (szArg1 && szArg1[0]) {
  1938.                                 f = (stristr(plug->szTarget,szArg1) != NULL);
  1939.                             }
  1940.                             if (szArg2 && szArg2[0] && f) {
  1941.                                 f = (stristr(plug->szRuby,szArg2) != NULL);
  1942.                             }
  1943.                             break;
  1944.                         }
  1945.                         case PLUG_LINK: {
  1946.                             PLUGLINK* plug = ph;
  1947.                             if (szArg1 && szArg1[0]) {
  1948.                                 f = (stristr(plug->szfilename,szArg1) != NULL);
  1949.                             }
  1950.                             if (szArg2 && szArg2[0] && f) {
  1951.                                 f = (stristr(plug->szCaption,szArg2) != NULL);
  1952.                             }
  1953.                             break;
  1954.                         }
  1955.                         case PLUG_PROOF: {
  1956.                             PLUGPROOF* plug = ph;
  1957.                             if (szArg1 && szArg1[0]) {
  1958.                                 f = (stristr(plug->szTarget_szProof,szArg1) != NULL);
  1959.                                 if (!f) f = (stristr(plug->szTarget_szProof + plug->ichProof,szArg1) != NULL);
  1960.                             }
  1961.                             if (szArg2 && szArg2[0] && f) {
  1962.                                 f = (stristr(plug->szReader,szArg2) != NULL);
  1963.                             }
  1964.                             break;
  1965.                         }
  1966.                     }
  1967.                     if (f) {
  1968.                         ret = TRUE;
  1969.                         txRight(text);
  1970.                         txSelectEx(text,CLIP_SEARCH);
  1971.                         txLeft(text);
  1972.                         if (text->fJumpCursorCenter) txSetLyCenter(text);
  1973.                         break;
  1974.                     }
  1975.                 }
  1976.                 searchmode &= ~SEARCH_CUR;
  1977.             } else {
  1978.                 break;
  1979.             }
  1980.         }
  1981.         if (!ret) {
  1982.             txSelectQuit(text);
  1983.             txJumpAddress(text,adr);
  1984.             txSetLyCurscreen(text,adrCurscreen);
  1985.         }
  1986.         txSetDisp(text);
  1987.         return ret;
  1988.     }
  1989.     return FALSE;
  1990. }
  1991.  
  1992. static BOOL _txSearchCharatr(TX* text,int tag,IFILE adr)
  1993. {
  1994.     CHARATR charatr;
  1995.     charatrRead(text,adr,&charatr);
  1996.     switch(tag) {
  1997.         case TAG_B: return charatr.fBold;
  1998.         case TAG_I: return charatr.fItalic;
  1999.         case TAG_U: return charatr.fUnderline;
  2000.     }
  2001.     return FALSE;
  2002. }
  2003.  
  2004. static BOOL txSearchCharatr(TX* text,int tag,SEARCHMODE searchmode,LPARAM arg)
  2005. {
  2006.     //2.99 970313 選択するようにした
  2007.     IFILE adr = txGetAddress(text);
  2008.     IFILE adr0 = adr;
  2009.     IFILE adrCurscreen = txGetAddressCurscreen(text);
  2010.     BOOL fNow = _txSearchCharatr(text,tag,adr);//カーソル位置がTRUEなら、次の文字列を検索
  2011.     BOOL ret = FALSE;
  2012.     txSetUndisp(text);
  2013.     if (searchmode & SEARCH_PREV) {
  2014.         for (;adr--;) {
  2015.             if (_txSearchCharatr(text,tag,adr)) {
  2016.                 if (!fNow) {
  2017.                     txJumpAddress(text,adr + 1);
  2018.                     txSelectEx(text,CLIP_SEARCH);
  2019.                     // 文字列の先頭へ
  2020.                     for (;;) {
  2021.                         if (adr == 0) break;
  2022.                         adr--;
  2023.                         if (!_txSearchCharatr(text,tag,adr)) {
  2024.                             adr++;
  2025.                             break;
  2026.                         }
  2027.                     }
  2028.                     txJumpAddress(text,adr);
  2029.                     ret = TRUE;
  2030.                     break;
  2031.                 }
  2032.             } else {
  2033.                 fNow = FALSE;
  2034.             }
  2035.         }
  2036.     } else {
  2037.         IFILE size = txGetTextSize(text);
  2038.         for (adr++;adr < size;adr++) {
  2039.             if (_txSearchCharatr(text,tag,adr)) {
  2040.                 if (!fNow) {
  2041.                     IFILE adrTop = adr;
  2042.                     // 文字列の末尾+1へ
  2043.                     for (;adr < size;adr++) {
  2044.                         if (!_txSearchCharatr(text,tag,adr)) {
  2045.                             break;
  2046.                         }
  2047.                     }
  2048.                     txJumpAddress(text,adr);
  2049.                     txSelectEx(text,CLIP_SEARCH);
  2050.                     //
  2051.                     txJumpAddress(text,adrTop);
  2052.                     ret = TRUE;
  2053.                     break;
  2054.                 }
  2055.             } else {
  2056.                 fNow = FALSE;
  2057.             }
  2058.         }
  2059.     }
  2060.     if (ret) {
  2061.         if (text->fJumpCursorCenter) txSetLyCenter(text);
  2062.         txSetDisp(text);
  2063.         return TRUE;
  2064.     } else {
  2065.         txSelectQuit(text);
  2066.         txJumpAddress(text,adr0);
  2067.         txSetLyCurscreen(text,adrCurscreen);
  2068.         txSetDisp(text);
  2069.         return FALSE;
  2070.     }
  2071. }
  2072.  
  2073. #define IDD_PREV            2001
  2074. #define IDD_NEXT            2002
  2075. #define IDD_CAPTION1        2500
  2076. #define IDD_CONTENT1        2501
  2077. #define IDD_CAPTION2        2502
  2078. #define IDD_CONTENT2        2503
  2079. #define IDD_MOVEWINDOW        2504    //2.99 970312 
  2080.  
  2081. #define JUMPID_LINE            0
  2082. #define JUMPID_PAGE            1
  2083. #define JUMPID_EDITED        2        //3.00B1 970521 
  2084. #define JUMPID_IMG            3
  2085. #define JUMPID_TAB            4
  2086. #define JUMPID_FOOTNOTE        5
  2087. #define JUMPID_BOLD            6
  2088. #define JUMPID_UNDERLINE    7
  2089. #define JUMPID_ITALIC        8
  2090. #define JUMPID_TITLE        9
  2091. #define JUMPID_OLE            10
  2092. #define JUMPID_RUBY            11
  2093. #define JUMPID_LINK            12
  2094. #define JUMPID_HR            13
  2095. #define JUMPID_PROOF        14
  2096. #define JUMPID_FONT            15
  2097. #define JUMPID_TAG            16
  2098. #define JUMPID_PAIRTAG        17
  2099.  
  2100. static int _modeFindSpecial = 0;
  2101. static txstr _szFindSpecial1;
  2102. static txstr _szFindSpecial2;
  2103.  
  2104. static mchar _szCaptionNext[] = "次へ(&N)";
  2105.  
  2106. static void initContent(void)
  2107. {
  2108.     _szFindSpecial1 = "";
  2109.     _szFindSpecial2 = "";
  2110.     if (_modeFindSpecial == JUMPID_LINE) {
  2111.         int nline = txVarGet(text,"\m.nline");
  2112.         if (nline == 0) nline = 1;
  2113.         sprintf(_szFindSpecial1,"%d",nline);
  2114.     } else if (_modeFindSpecial == JUMPID_PAGE) {
  2115.         // 詳細モードでは頁指定ジャンプ
  2116.         // 簡易頁表示では、頁・行複合指定ジャンプ
  2117.         NPAGE npage = 0;
  2118.         if (text->editmode == 2) {
  2119.             npage = txNpageFromNpageclm(text,text->npage);
  2120.         } else if (text->fLineD && text->height) {
  2121.             npage = (text->nline / text->height) + 1;
  2122.         }
  2123.         if (npage) sprintf(_szFindSpecial1,"%d",npage);
  2124.         //
  2125.         int npageline = txVarGet(text,"\m.npageline");
  2126.         if (npageline == 0) npageline = 1;
  2127.         sprintf(_szFindSpecial2,"%d",npageline);
  2128.     }
  2129. }
  2130.  
  2131. BOOL paraatrtextReadFedited(TX* text,NPARA npara)
  2132. {
  2133. //3.00B1 970521 new
  2134.     if (text->editmode) {
  2135.         PARAATR paraatr;
  2136.         paraatrRead(text,npara,¶atr);
  2137.         return paraatr.fEdited;
  2138.     } else {
  2139.         PARAATR_TEXT_CONTEXT* ptc = text->paraatrtextcontext;
  2140.         BOOL fEdited = FALSE;
  2141.         if (ptc && ptc->buff) {
  2142.             if (npara < ptc->cur0) {
  2143.                 fEdited = ptc->buff[npara].fEdited;
  2144.             } else {
  2145.                 npara += ptc->cur - ptc->cur0;
  2146.                 if (npara < ptc->size) {
  2147.                     fEdited = ptc->buff[npara].fEdited;
  2148.                 }
  2149.             }
  2150.         }
  2151.         return fEdited;
  2152.     }
  2153. }
  2154.  
  2155. BOOL TXAPI TXCMD txSearchEditedPrev(TX* text)
  2156. {
  2157. // 前の変更行へジャンプ
  2158. //{#RET}ジャンプしたかどうかを返す
  2159. //3.00B1 970522 new
  2160.     NPARA npara = text->npara - 1;
  2161.     for (;npara >= 1;npara--) {
  2162.         if (paraatrtextReadFedited(text,npara)) {
  2163.             txJumpNpara(text,npara);
  2164.             return TRUE;
  2165.         }
  2166.     }
  2167.     return FALSE;
  2168. }
  2169.  
  2170. BOOL TXAPI TXCMD txSearchEdited(TX* text)
  2171. {
  2172. // 次の変更行へジャンプ
  2173. //{#RET}ジャンプしたかどうかを返す
  2174. //3.00B1 970522 new
  2175.     NPARA nparaSize = 0;
  2176.     if (text->editmode) {
  2177.         nparaSize = txRecordGetCount(text->txparaatr);
  2178.     } else {
  2179.         PARAATR_TEXT_CONTEXT* ptc = text->paraatrtextcontext;
  2180.         if (ptc) {
  2181.             nparaSize = ptc->size;
  2182.         }
  2183.     }
  2184.     {
  2185.         NPARA npara = text->npara + 1;
  2186.         for (;npara < nparaSize;npara++) {
  2187.             if (paraatrtextReadFedited(text,npara)) {
  2188.                 txJumpNpara(text,npara);
  2189.                 return TRUE;
  2190.             }
  2191.         }
  2192.     }
  2193.     return FALSE;
  2194. }
  2195.  
  2196. BOOL dlgprocSearchSpecial(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  2197. {
  2198.     HDIALOG hd = dialogFromHwnd(hwnd);
  2199.     switch(message) {
  2200.         case WM_INITDIALOG: {
  2201.             PostMessage(hwnd,WM_TXUSER,TRUE,0);
  2202.             break;
  2203.         }
  2204.         case WM_COMMAND: {
  2205.             int id = WM_COMMAND_GetId(wParam);
  2206.             int notify = WM_COMMAND_GetNotify(wParam,lParam);
  2207.             switch(id) {
  2208.                 case IDD_TARGET: {
  2209.                     if (notify == LBN_SELCHANGE) PostMessage(hwnd,WM_TXUSER,0,0);
  2210.                     break;
  2211.                 }
  2212.                 case IDD_MOVEWINDOW: {
  2213.                     wndMoveUncursor(hwnd);
  2214.                     return TRUE;
  2215.                 }
  2216.                 case IDD_NEXT:
  2217.                 case IDD_PREV: {
  2218.                     SEARCHMODE mode = (id == IDD_PREV) ? SEARCH_PREV : 0;
  2219.                     BOOL ret = FALSE;
  2220.                     dialogRead(hd);
  2221.                     switch(_modeFindSpecial) {
  2222.                         case JUMPID_LINE:
  2223.                         case JUMPID_PAGE:
  2224.                         case JUMPID_PAIRTAG: PostMessage(hwnd,WM_COMMAND,IDOK,0);return TRUE;
  2225.                         case JUMPID_EDITED: {    //3.00B1 970521 
  2226.                             if (mode & SEARCH_PREV) {
  2227.                                 ret = txSearchEditedPrev(text);
  2228.                             } else {
  2229.                                 ret = txSearchEdited(text);
  2230.                             }
  2231.                             break;
  2232.                         }
  2233.                         case JUMPID_IMG:ret = txSearchPlug(text,PLUG_IMG,mode,_szFindSpecial1,_szFindSpecial2);break;
  2234.                         case JUMPID_TAB:ret = txSearchPlug(text,PLUG_TAB,mode,_szFindSpecial1,_szFindSpecial2);break;
  2235.                         case JUMPID_FOOTNOTE:ret = txSearchPlug(text,PLUG_FOOTNOTE,mode,_szFindSpecial1,_szFindSpecial2);break;
  2236.                         case JUMPID_BOLD:ret = txSearchCharatr(text,TAG_B,mode,0);break;
  2237.                         case JUMPID_UNDERLINE:ret = txSearchCharatr(text,TAG_U,mode,0);break;
  2238.                         case JUMPID_ITALIC:ret = txSearchCharatr(text,TAG_I,mode,0);break;
  2239.                         case JUMPID_TITLE: {
  2240.                             IFILE adr = txGetAddress(text);
  2241.                             IFILE adrCurscreen = txGetAddressCurscreen(text);
  2242.                             txSetUndisp(text);
  2243.                             if (mode & SEARCH_PREV) {
  2244.                                 ret = txSearchTitlePrev(text);
  2245.                             } else {
  2246.                                 ret = txSearchTitle(text);
  2247.                             }
  2248.                             if (ret) {
  2249.                                 txJumpParaEnd(text);
  2250.                                 txSelectEx(text,CLIP_SEARCH);
  2251.                                 txJumpParaTop(text);
  2252.                             } else {
  2253.                                 txSelectQuit(text);
  2254.                                 txJumpAddress(text,adr);
  2255.                                 txSetLyCurscreen(text,adrCurscreen);
  2256.                             }
  2257.                             txSetDisp(text);
  2258.                             break;
  2259.                         }
  2260.                         case JUMPID_OLE:ret = txSearchPlug(text,PLUG_OLE,mode,_szFindSpecial1,_szFindSpecial2);break;
  2261.                         case JUMPID_RUBY:ret = txSearchPlug(text,PLUG_RUBY,mode,_szFindSpecial1,_szFindSpecial2);break;
  2262.                         case JUMPID_LINK:ret = txSearchPlug(text,PLUG_LINK,mode,_szFindSpecial1,_szFindSpecial2);break;
  2263.                         case JUMPID_HR:ret = txSearchPlug(text,PLUG_HR,mode,_szFindSpecial1,_szFindSpecial2);break;
  2264.                         case JUMPID_PROOF:ret = txSearchPlug(text,PLUG_PROOF,mode,_szFindSpecial1,_szFindSpecial2);break;//2.98 970305 
  2265.                         case JUMPID_FONT:ret = txSearchPlug(text,PLUG_FONT,mode,_szFindSpecial1,_szFindSpecial2);break;//2.98 970305 
  2266.                         case JUMPID_TAG:ret = txSearchPlug(text,PLUG_HTML_TAG,mode,_szFindSpecial1,_szFindSpecial2);break;//2.98 970305 
  2267.                     }
  2268.                     statprintf(ret ? "" : "見つかりません");
  2269.                     return TRUE;
  2270.                 }
  2271.             }
  2272.             break;
  2273.         }
  2274.         case WM_TXUSER: {
  2275.             HWND hcaption1 = GetDlgItem(hwnd,IDD_CAPTION1);
  2276.             HWND hcaption2 = GetDlgItem(hwnd,IDD_CAPTION2);
  2277.             HWND hctrl1 = GetDlgItem(hwnd,IDD_CONTENT1);
  2278.             HWND hctrl2 = GetDlgItem(hwnd,IDD_CONTENT2);
  2279.             BOOL fEnableButton1 = TRUE;
  2280.             BOOL fEnableButton2 = TRUE;
  2281.             mchar* szCaption1 = "";
  2282.             mchar* szCaption2 = "";
  2283.             //
  2284.             dialogRead(hd);
  2285.             // button caption
  2286.             switch(_modeFindSpecial) {
  2287.                 case JUMPID_LINE:
  2288.                 case JUMPID_PAGE:
  2289.                 case JUMPID_PAIRTAG: {
  2290.                     SetDlgItemText(hwnd,IDD_NEXT,"ジャンプ(&N)");
  2291.                     fEnableButton2 = FALSE;
  2292.                     break;
  2293.                 }
  2294.                 default: {
  2295.                     SetDlgItemText(hwnd,IDD_NEXT,_szCaptionNext);
  2296.                     break;
  2297.                 }
  2298.             }
  2299.             // textmode enable item
  2300.             switch(_modeFindSpecial) {
  2301.                 case JUMPID_LINE: {
  2302.                     szCaption1 = text->fLineD ? "表示行番号(&C):" : "段落行番号(&C):";
  2303.                     break;
  2304.                 }
  2305.                 case JUMPID_PAGE: {
  2306.                     szCaption1 = "ページ(&C):";
  2307.                     szCaption2 = "行(&D):";
  2308.                     break;
  2309.                 }
  2310.                 case JUMPID_EDITED: {//3.00B1 970521 
  2311.                     if (!text->fDispLineEdit) {
  2312.                         fEnableButton1 = FALSE;
  2313.                         fEnableButton2 = FALSE;
  2314.                     }
  2315.                     break;
  2316.                 }
  2317.                 default: {
  2318.                     if (text->editmode == 0) {// 不可
  2319.                         szCaption1 = "テキストモードでは実行できません";
  2320.                         fEnableButton1 = FALSE;
  2321.                         fEnableButton2 = FALSE;
  2322.                     }
  2323.                     break;
  2324.                 }
  2325.             }
  2326.             // textmode disable item
  2327.             if (text->editmode) {
  2328.                 switch(_modeFindSpecial) {
  2329.                     case JUMPID_IMG: {
  2330.                         szCaption1 = "図のファイル名(&C):";
  2331.                         break;
  2332.                     }
  2333.                     case JUMPID_FOOTNOTE: {
  2334.                         szCaption1 = "脚注の内容(&C):";
  2335.                         break;
  2336.                     }
  2337.                     case JUMPID_RUBY: {
  2338.                         szCaption1 = "ルビの漢字(&C):";
  2339.                         szCaption2 = "ルビのよみがな(&D):";
  2340.                         break;
  2341.                     }
  2342.                     case JUMPID_LINK: {
  2343.                         szCaption1 = "リンク先のファイル名(&C):";
  2344.                         szCaption2 = "キャプション(&D):";
  2345.                         break;
  2346.                     }
  2347.                     case JUMPID_PROOF: {//2.98 970305 
  2348.                         szCaption1 = "校正の内容(&C):";
  2349.                         szCaption2 = "校正者(&D):";
  2350.                         break;
  2351.                     }
  2352.                     case JUMPID_TAG: {//2.98 970305 
  2353.                         if (text->fHTML) {
  2354.                             szCaption1 = "タグの内容(&C):";
  2355.                         } else {
  2356.                             fEnableButton1 = FALSE;
  2357.                             fEnableButton2 = FALSE;
  2358.                         }
  2359.                         break;
  2360.                     }
  2361.                     case JUMPID_PAIRTAG: {//2.99 970313 
  2362.                         if (!text->fHTML) {
  2363.                             fEnableButton1 = FALSE;
  2364.                         }
  2365.                         break;
  2366.                     }
  2367.                 }
  2368.             }
  2369.             initContent();
  2370.             SetWindowText(hcaption1,szCaption1);
  2371.             SetWindowText(hcaption2,szCaption2);
  2372.             SetWindowText(hctrl1,_szFindSpecial1);
  2373.             SetWindowText(hctrl2,_szFindSpecial2);
  2374. #if 1//2.99D 970330 
  2375.             EnableDlgItem(hwnd,IDD_NEXT,fEnableButton1);
  2376.             EnableDlgItem(hwnd,IDD_PREV,fEnableButton2);
  2377. #else
  2378.             EnableWindow(GetDlgItem(hwnd,IDD_NEXT),fEnableButton1);
  2379.             EnableWindow(GetDlgItem(hwnd,IDD_PREV),fEnableButton2);
  2380. #endif
  2381.             //
  2382.             if (_modeFindSpecial == JUMPID_PAGE) {
  2383.                 EnableWindow(hctrl1,(_szFindSpecial1[0] != 0));
  2384.                 EnableWindow(hctrl2,(text->editmode < 2));
  2385.             } else {
  2386.                 EnableWindow(hctrl1,(szCaption1[0] != 0));
  2387.                 EnableWindow(hctrl2,(szCaption2[0] != 0));
  2388.             }
  2389.             //
  2390.             if (wParam) {
  2391.                 // at WM_INITDIALOG
  2392.                 if (IsWindowEnabled(hctrl1)) {
  2393.                     SetFocus(hctrl1);
  2394.                     Edit_SetSel(hctrl1,0,-1);
  2395.                 }
  2396.             }
  2397.         }
  2398.     }
  2399.     return FALSE;
  2400. }
  2401.  
  2402. extern "html" BOOL TXCMD TXAPI txHtmlJumpPairTag(TX* text);
  2403.  
  2404. BOOL TXCMDBASE uiJumpEx(TX* text)
  2405. {
  2406. // ジャンプ
  2407. // 行、ページへのジャンプ、図や表、脚注、太字などを検索します。
  2408. //2.99 970312 特殊検索から変更し、行/ページジャンプを統合
  2409. //2.99A 970321 {#MS} {F5} new
  2410. //{#MS} {F5}
  2411.     if (text->fBinedit) {
  2412.         uiJumpAddress(text);
  2413.     } else {
  2414.         HDIALOG hd = dialogbig("ジャンプ");    //2.99D 970330 dialogbig化
  2415.         dialogSetHookEx(hd,"\m.dlgprocSearchSpecial");
  2416.         //
  2417.         dialogControlID(hd,IDD_TARGET);
  2418.         dialogControlListbox(hd,_fwin40 ? 7 : 6);//2.99C 970326 WZ32で小さすぎた
  2419.         dialogSelectID(
  2420.             hd,"移動先(&O):",&_modeFindSpecial,16,16,
  2421.             "行","ページ","変更行",    //3.00B1 970521 ジャンプの移動先に"変更行"を追加
  2422.             "図","表","脚注","太字","下線","斜体","見出し","オブジェクト",
  2423.             "ルビ","ハイパーリンク","水平線","校正","特殊文字",
  2424.             "HTMLタグ","HTMLペアタグ"
  2425.         );
  2426.         if (text->editmode == 0) {
  2427. #if 1//3.00B1 970521 
  2428.             switch(_modeFindSpecial) {
  2429.                 case JUMPID_LINE:
  2430.                 case JUMPID_PAGE:
  2431.                 case JUMPID_EDITED: break;
  2432.                 default: _modeFindSpecial = JUMPID_LINE;
  2433.             }
  2434. #else
  2435.             if (_modeFindSpecial != JUMPID_LINE && _modeFindSpecial != JUMPID_PAGE) {
  2436.                 _modeFindSpecial = JUMPID_LINE;
  2437.             }
  2438. #endif
  2439.         }
  2440.         dialogCmdLFV(hd);
  2441.         //
  2442.         dialogSpaceV(hd);
  2443.         dialogSpaceV(hd);
  2444.         dialogSetIntXY(hd,0,1);
  2445.             dialogControlID(hd,IDD_CAPTION1);
  2446.             dialogCaptionDynamic(hd,NULL,32);
  2447.             dialogControlID(hd,IDD_CONTENT1);
  2448.             dialogStr(hd,NULL,_szFindSpecial1,0,32);
  2449.                 dialogSpaceV(hd);
  2450.                 dialogSpaceV(hd);
  2451.             dialogControlID(hd,IDD_CAPTION2);
  2452.             dialogCaptionDynamic(hd,NULL,32);
  2453.             dialogControlID(hd,IDD_CONTENT2);
  2454.             dialogStr(hd,NULL,_szFindSpecial2,0,32);
  2455.         dialogResetInt(hd);
  2456.         //
  2457.         int lxg = 16;
  2458.         dialogLFV(hd);
  2459.         dialogControlID(hd,IDD_NEXT);
  2460.         dialogCmdDefault(hd,"次へ(&N)",lxg);
  2461.         dialogControlID(hd,IDD_PREV);
  2462.         dialogCmd(hd,"前へ(&P)",lxg);
  2463.         dialogControlID(hd,IDCANCEL);
  2464.         dialogCmd(hd,"閉じる",lxg);
  2465.         dialogControlID(hd,IDD_MOVEWINDOW);
  2466.         dialogCmd(hd,"ウィンドウ移動(&M)",lxg);
  2467.         if (dialogOpen(hd) == IDOK) {
  2468.             switch(_modeFindSpecial) {
  2469.                 case JUMPID_LINE: {
  2470.                     int nline = atoi(_szFindSpecial1);
  2471.                     txJumpModal(text,nline);
  2472.                     txVarSet(text,"\m.nline",nline);
  2473.                     break;
  2474.                 }
  2475.                 case JUMPID_PAGE: {
  2476.                     int npage = atoi(_szFindSpecial1);
  2477.                     int npageline = atoi(_szFindSpecial2);
  2478.                     if (npage) {
  2479.                         if (text->editmode == 2) {
  2480.                             txJumpPage(text,npage);
  2481.                         } else {
  2482.                             txJumpModal(text,(npage - 1) * text->height + npageline);
  2483.                         }
  2484.                     } else {
  2485.                         txJumpModal(text,npageline);
  2486.                     }
  2487.                     txVarSet(text,"\m.npageline",npageline);
  2488.                     break;
  2489.                 }
  2490.                 case JUMPID_PAIRTAG: {
  2491.                     txHtmlJumpPairTag(text);
  2492.                     break;
  2493.                 }
  2494.             }
  2495.         }
  2496.     }
  2497.     return TRUE;
  2498. }
  2499.  
  2500. //##検索リスト
  2501.  
  2502. #include "outline.h"
  2503.  
  2504. typedef struct {
  2505.     mchar szFind[CCHWORD];
  2506.     mchar szReplace[CCHWORD];
  2507.     mchar szMode[CCHWORD];
  2508.     SEARCHMODE searchmode;
  2509.     IFILE adrFind;
  2510.     WORD fFind:1;            //3.00A2 970506 
  2511.     SIGNED_WORD lchFind;    //3.00A2 970506 int->SIGNED_WORD
  2512.     SIGNED_WORD ly;            //3.00A2 970506 int->SIGNED_WORD
  2513. } SEARCHSET;
  2514.  
  2515. static BOOL txGetSearchset(TX* text,SEARCHSET* ss,BOOL _fFirst)
  2516. {
  2517. // 一回で終わる場合は2を返す
  2518.     BOOL ret = FALSE;
  2519.     BOOL fOnce = FALSE;
  2520.     BOOL fFirst = TRUE;
  2521.     structClear(*ss);
  2522.     while(1) {
  2523.         txstr szline;
  2524.         txGetPara(text,szline);
  2525.         if (strmatch(szline,text->tsztitle[1])) {
  2526.             // "..."を仮定
  2527.             if (!fFirst) break;
  2528.             if (_fFirst && !fOnce) fOnce = TRUE;
  2529.         } else if (strmatch(szline,text->tsztitle[0])) {
  2530.             // ".."を仮定
  2531.             if (!fFirst) break;
  2532.             if (!_fFirst) break;
  2533.             fOnce = 2;
  2534.         } else {
  2535.             fFirst = FALSE;
  2536.             int lch;
  2537.             if (lch = strmatch(szline,"find=")) {
  2538.                 ret = TRUE;
  2539.                 strcpymax(ss->szFind,&szline[lch],cchof(ss->szFind));
  2540.             } else if (lch = strmatch(szline,"to=")) {
  2541.                 ret = TRUE;
  2542.                 strcpymax(ss->szReplace,&szline[lch],cchof(ss->szReplace));
  2543.             } else if (lch = strmatch(szline,"mode=")) {
  2544.                 ret = TRUE;
  2545.                 strcpymax(ss->szMode,&szline[lch],cchof(ss->szMode));
  2546.                 ss->searchmode = searchmodeFromSzstr(ss->szMode);
  2547.             }
  2548.         }
  2549.         if (!txNextPara(text)) break;
  2550.     }
  2551.     if (fOnce == TRUE && ret) {
  2552. //information("!!!");
  2553.         return 2;
  2554.     }
  2555.     return ret;
  2556. }
  2557.  
  2558. static int SearchMulti(TX* text,TX* txArg,SEARCHMODE searchmode,TXSEARCHLISTARG* arg)
  2559. {
  2560.     txSetUndisp(text);
  2561.     IFILE adr = txGetAddress(text);
  2562.     int ly = text->ly;
  2563.     //
  2564.     BOOL fPrev = ((searchmode & SEARCH_PREV) != 0);
  2565.     #define MAX_SSN    50
  2566.     SEARCHSET tss[MAX_SSN];
  2567.     memset(tss,0,sizeof(tss));
  2568.     int n = 0;
  2569.     int i;
  2570.     BOOL fFirst = TRUE;
  2571. //txstr sz;txGetPara(txArg,sz);information(sz);
  2572.     for (i = 0;i < MAX_SSN;i++,fFirst = FALSE) {
  2573.         SEARCHSET *ss = tss + i;
  2574.         n = i + 1;
  2575.         int ret = txGetSearchset(txArg,ss,fFirst);
  2576.         if (!ret) break;
  2577. //information("%s %lX",ss->szFind,ss->searchmode|searchmode);
  2578.         if (ss->lchFind = txSearchEx(text,ss->szFind,ss->searchmode|searchmode)) {
  2579.             ss->fFind = TRUE;//3.00A2 970506 
  2580.             ss->adrFind = txGetAddress(text);
  2581.             ss->lchFind--;
  2582.             ss->ly = text->ly;
  2583. //information("ret:%d n:%d lchFind:%d adrFind:%ld %s %lX",ret,n,ss->lchFind,ss->adrFind,ss->szFind,ss->searchmode|searchmode);
  2584.         }
  2585.         txJumpAddress(text,adr);
  2586.         txSetLy(text,ly);
  2587.         if (ret == 2) break;
  2588.     }
  2589.     IFILE adrFind = 0;
  2590.     int iFind = -1;
  2591. #if 1//3.00A2 970506 検索リスト:テキスト先頭でマッチするときに、NOT FOUNDになることがあった
  2592.     if (fPrev) {
  2593.         for (i = 0;i < n;i++) {
  2594.             SEARCHSET *ss = tss + i;
  2595.             if (ss->fFind && (adrFind == 0 || ss->adrFind > adrFind)) {
  2596.                 adrFind = ss->adrFind;
  2597.                 iFind = i;
  2598.             }
  2599.         }
  2600.     } else {
  2601.         for (i = 0;i < n;i++) {
  2602.             SEARCHSET *ss = tss + i;
  2603.             if (ss->fFind && (adrFind == 0 || ss->adrFind < adrFind)) {
  2604.                 adrFind = ss->adrFind;
  2605.                 iFind = i;
  2606.             }
  2607.         }
  2608.     }
  2609. #else
  2610.     if (fPrev) {
  2611.         for (i = 0;i < n;i++) {
  2612.             SEARCHSET *ss = tss + i;
  2613.             if (ss->adrFind && (adrFind == 0 || ss->adrFind > adrFind)) {
  2614.                 adrFind = ss->adrFind;
  2615.                 iFind = i;
  2616.             }
  2617.         }
  2618.     } else {
  2619.         for (i = 0;i < n;i++) {
  2620.             SEARCHSET *ss = tss + i;
  2621.             if (ss->adrFind && (adrFind == 0 || ss->adrFind < adrFind)) {
  2622.                 adrFind = ss->adrFind;
  2623.                 iFind = i;
  2624.             }
  2625.         }
  2626.     }
  2627. #endif
  2628.     if (iFind == -1) {
  2629.     } else {
  2630.         SEARCHSET *ss = tss + iFind;
  2631.         if (arg) {
  2632.             arg->searchmode = ss->searchmode;
  2633.             if (arg->szReplace) strcpymax(arg->szReplace,ss->szReplace,arg->cchReplace);
  2634. //information("%s %lX",arg->szReplace,arg->searchmode);
  2635.         }
  2636.         if (ss->searchmode & SEARCH_RE) {
  2637.             // vwxwのタグや、マッチ長をセットする
  2638.             txJumpAddress(text,ss->adrFind);
  2639.             SEARCHMODE mode = ss->searchmode;
  2640.             mode &= ~SEARCH_PREV;
  2641.             mode |= SEARCH_CUR;
  2642. //information("%s %lX",ss->szFind,mode);
  2643.             txSearchEx(text,ss->szFind,mode);
  2644.         }
  2645.         txJumpAddress(text,ss->adrFind);
  2646.         txSetLy(text,ss->ly);
  2647.         txSetDisp(text);
  2648. //information("%d",ss->lchFind);
  2649.         return ss->lchFind + 1;
  2650.     }
  2651.     txSetDisp(text);
  2652.     return 0;
  2653. }
  2654.  
  2655. extern "edit" BOOL TXAPI txConvertDic(TX* text);
  2656.  
  2657. static void txInitSearchDic(TX* text)
  2658. {
  2659.     txInitText(text);
  2660.     mchar szfilename[CCHPATHNAME];
  2661.     pathFullConfig(szfilename,"search.dic");
  2662.     txSetFileName(text,szfilename);
  2663.     txOpenText(text);
  2664.     //2.00E2 設定がなくても正常に動作するように
  2665.     strcpy(text->tsztitle[0],"..");
  2666.     strcpy(text->tsztitle[1],"...");
  2667.     strcpy(text->tsztitle[2],"");
  2668.     //2.92 
  2669.     txConvertDic(text);
  2670. }
  2671.  
  2672. int TXAPI txSearchlistEx(TX* _text,mchar* szFind,TXSEARCHLISTARG* arg)
  2673. {
  2674. //2.92 検索リストのszFindエントリの内容の検索を実行
  2675.     int ret = 0;
  2676.     TX _txdic;
  2677.     TX *text = &_txdic;
  2678.     txInitSearchDic(text);
  2679.     txstr sz = text->tsztitle[0];
  2680.     sz += szFind;
  2681.     if (txSearchEx(text,sz,SEARCH_CUR|SEARCH_PARATOP)) {
  2682. //txstr sz;txGetPara(text,sz);information(sz);
  2683.         ret = SearchMulti(_text,text,arg->searchmode,arg);
  2684.     } else {
  2685.         txJumpFileTop(text);
  2686.         txstr sz = text->tsztitle[1];
  2687.         sz += szFind;
  2688.         if (txSearchEx(text,sz,SEARCH_CUR|SEARCH_PARATOP)) {
  2689. //txstr sz;txGetPara(text,sz);information(sz);
  2690.             ret = SearchMulti(_text,text,arg->searchmode,arg);
  2691.         }
  2692.     }
  2693.     txClose(text);//3.00B1 970613 置換リストで大量に置換するとメモリ不足になった
  2694.     return ret;
  2695. }
  2696.  
  2697. static mchar* getSzfind(TX* text,txstr szstr)
  2698. {
  2699.     txGetPara(text,szstr);
  2700.     if (strmatch(szstr,text->tsztitle[1])) {
  2701.         // "..."を仮定
  2702.         return &szstr[strlen(text->tsztitle[1])];
  2703.     } else if (strmatch(szstr,text->tsztitle[0])) {
  2704.         // ".."を仮定
  2705.         return &szstr[strlen(text->tsztitle[0])];
  2706.     }
  2707.     return "";
  2708. }
  2709.  
  2710. BOOL dlgprocListAdd(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  2711. {
  2712. //3.00A2 970506 new
  2713.     switch(message) {
  2714.         case WM_COMMAND: {
  2715.             int id = WM_COMMAND_GetId(wParam);
  2716.             int notify = WM_COMMAND_GetNotify(wParam,lParam);
  2717.             if (id == IDOK) {
  2718.                 mchar buff[CCHWORD];
  2719.                 GetDlgItemText(hwnd,IDD_TITLENAME,buff,cchof(buff));
  2720.                 if (strchr(buff,'\\')) {
  2721.                     //3.00A2 970506 置換リストの「グループ名」・「タイトル」に \ が使えないので、\が使われた時はエラーメッセージを出す様にした。
  2722.                     information("グループ名およびタイトルに \\ は使えません。\n全角 ¥ を使うか、別の文字を使ってください");
  2723.                     return TRUE;
  2724.                 }
  2725.             }
  2726.             break;
  2727.         }
  2728.     }
  2729.     return FALSE;
  2730. }
  2731.  
  2732. static void listOp(HWND hwnd,int id)
  2733. {
  2734. //2.92 マルチ検索/置換対応
  2735.     TX* text = outlineGetTx(hwnd);
  2736.     dialogRead(dialogFromHwnd(hwnd));
  2737.     TX body;
  2738.     TX* work = &body;
  2739.     txInitText(work);
  2740.     txCopyConfig(work,text);
  2741.     txOpenText(work);
  2742.     if (id != IDD_PASTE) {
  2743.         outlineCopy(hwnd);
  2744. #if 1//2.99D 970330 
  2745.         EnableDlgItem(hwnd,IDD_PASTE,TRUE);
  2746. #else
  2747.         EnableWindow(GetDlgItem(hwnd,IDD_PASTE),TRUE);
  2748. #endif
  2749.         txPaste(work);
  2750.         txJumpFileTop(work);
  2751.     }
  2752.     //
  2753.     txstr szstr;
  2754.     HEADLINE hl;
  2755.     outlineGetCurheadline(hwnd,&hl);
  2756.     szstr = hl.szstr;
  2757.     //
  2758.     switch(id) {
  2759.         case IDD_PASTE: {
  2760.             {
  2761.                 long cur = outlineGetCursel(hwnd);
  2762.                 if (hl.npara == 0) {
  2763.                     txJumpFileTop(text);
  2764.                 } else {
  2765.                     txJumpPara(text,hl.npara);
  2766.                 }
  2767.                 txPaste(text);
  2768.                 outlineFlush(hwnd);
  2769.                 outlineSetCursel(hwnd,cur);
  2770.             }
  2771.             break;
  2772.         }
  2773.         case IDD_EDIT:
  2774.         case IDD_ADD:
  2775.         case IDD_ADDCATEGORY: {
  2776.             SEARCHSET ss;
  2777.             txGetSearchset(work,&ss,TRUE);
  2778.             SEARCHOPT searchopt;
  2779.             //
  2780.             if (!(hl.nest == 1 || hl.nest == 2)) break;
  2781.             //
  2782.             BOOL fEdit = (id == IDD_EDIT);
  2783.             BOOL fCategory = (id == IDD_ADDCATEGORY || (fEdit && hl.nest == 1));
  2784.             HDIALOG hd;
  2785.             if (fEdit) {
  2786.                 if (fCategory) {
  2787.                     hd = dialog("グループ名の変更");
  2788.                 } else {
  2789.                     hd = dialog("検索リストの編集");
  2790.                 }
  2791.             } else {
  2792.                 if (fCategory) {
  2793.                     hd = dialog("グループの追加");
  2794.                 } else {
  2795.                     hd = dialog("検索リストに追加");
  2796.                 }
  2797.             }
  2798.             dialogSetHookEx(hd,"\m.dlgprocListAdd");//3.00A2 970506 
  2799.             dialogSetContexthelp(hd,TRUE);
  2800.             dialogControlHelp(hd,185);
  2801.             dialogControlID(hd,IDD_TITLENAME);//3.00A2 970506 
  2802.             if (fCategory) {
  2803.                 dialogStr(hd,"グループ名(&T):",szstr,12,32);
  2804.             } else {
  2805.                 dialogStr(hd,"タイトル(&T):",szstr,8,32);
  2806.             }
  2807.             dialogSpaceV(hd);
  2808.             if (!fCategory) {
  2809.                 dialogSetGroupRight(hd,DTCX * 42);
  2810.                 dialogGroup(hd,"検索文字列と置換文字列(&S)");
  2811.                     dialogControlHelp(hd,190);
  2812.                     dialogControlHistRead(hd,HIST_SEARCH);
  2813.                     dialogStrC(hd,"検索:",ss.szFind,7,cchof(ss.szFind),30);
  2814.                     dialogControlHelp(hd,191);
  2815.                     dialogControlHistRead(hd,HIST_SEARCH);
  2816.                     dialogStrC(hd,"置換:",ss.szReplace,7,cchof(ss.szReplace),30);
  2817.                 dialogGroupEnd(hd);
  2818.                 //
  2819.                 searchmodeToSearchopt(ss.searchmode,&searchopt);
  2820.                 //
  2821.                 dialogSearchOption(hd,&searchopt,0);
  2822.             }
  2823.             if (dialogOpen(hd)) {
  2824.                 if (!fCategory) {
  2825.                     SEARCHMODE searchmode = searchmodeFromSearchopt(&searchopt);
  2826.                     {
  2827.                         txstr szmode;
  2828.                         searchmodeToSzstr(searchmode,szmode);
  2829.                         strcpymax(ss.szMode,szmode,cchof(ss.szMode));
  2830.                     }
  2831.                 }
  2832.                 //
  2833.                 long cur = outlineGetCursel(hwnd);
  2834.                 if (fEdit && !fCategory) {
  2835.                     outlineClear(hwnd);
  2836.                 }
  2837.                 if (hl.npara == 0) {
  2838.                     txJumpFileTop(text);
  2839.                 } else {
  2840.                     txJumpPara(text,hl.npara);
  2841.                 }
  2842.                 if (fCategory) {
  2843.                     if (fEdit) {
  2844.                         txDeletePara(text);
  2845.                     }
  2846.                 } else {
  2847.                     if (id == IDD_ADD) {
  2848.                         HEADLINE hl;
  2849.                         outlineGetHeadline(hwnd,&hl,cur+1);
  2850.                         hl.npara == 0 ? txJumpFileTop(text) : txJumpPara(text,hl.npara);
  2851.                         cur++;
  2852.                     }
  2853.                 }
  2854.                 txInsertLine(text,"%s%s",text->tsztitle[0+!fCategory],szstr);
  2855.                 if (!fCategory) {
  2856.                     txInsertLine(text,"find=%s",ss.szFind);
  2857.                     txInsertLine(text,"to=%s",ss.szReplace);
  2858.                     txInsertLine(text,"mode=%s",ss.szMode);
  2859.                 }
  2860.                 //
  2861.                 outlineFlush(hwnd);
  2862.                 outlineSetCursel(hwnd,cur);
  2863.             }
  2864.             break;
  2865.         }
  2866.         case IDD_DEL: {
  2867.             int ret = MessageBox(
  2868.                 hwnd,
  2869.                 szstr + "\nを削除します。よろしいですか?",
  2870.                 "検索リストから削除",
  2871.                 MB_ICONQUESTION|MB_YESNOCANCEL
  2872.             );
  2873.             if (ret == IDYES) {
  2874.                 long cur = outlineGetCursel(hwnd);
  2875.                 outlineClear(hwnd);
  2876.                 outlineFlush(hwnd);
  2877.                 outlineSetCursel(hwnd,cur);
  2878.             }
  2879.             break;
  2880.         }
  2881.         case IDD_SEARCH: {
  2882.             SEARCHMODE searchmode = 0;
  2883.             if (_context.modeDirection == DIR_PREV) searchmode |= SEARCH_PREV;
  2884.             txstr szstr;
  2885.             if (txSearchEx(textf,_szIdSearchlist+getSzfind(work,szstr),searchmode)) {
  2886.                 err_clear();
  2887.             } else {
  2888.                 err();
  2889.             }
  2890.             break;
  2891.         }
  2892.         case IDD_REPLACE: {
  2893.             SEARCHMODE searchmode = 0;
  2894.             if (_context.modeDirection == DIR_PREV) searchmode |= SEARCH_PREV;
  2895.             switch(_context.modeReplace) {
  2896.                 case REPLACE_ALL: searchmode |= SEARCH_ALL;break;
  2897.                 case REPLACE_AREA: searchmode |= SEARCH_AREA;break;
  2898.                 default: searchmode |= REPLACE_ONCE;break;
  2899.             }
  2900.             int n;
  2901.             txstr szstr;
  2902.             if (n = txReplaceEx(textf,_szIdSearchlist+getSzfind(work,szstr),NULL,searchmode)) {
  2903.                 // OK
  2904.             } else {
  2905.                 err();
  2906.             }
  2907.             break;
  2908.         }
  2909.     }
  2910.     txClose(work);
  2911. }
  2912.  
  2913. typedef struct {
  2914.     mchar szstr[CCHWORD];
  2915. } SEARCHLISTCONTEXT;
  2916. SEARCHLISTCONTEXT _contextsl;
  2917.  
  2918. BOOL dlgprocList(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  2919. {
  2920.     switch(message) {
  2921.         case WM_INITDIALOG: {
  2922. #if 1//2.99C 970323 
  2923.             EnableDlgItem(hwnd,IDD_MODEREPLACETOP + 2,textf->fClip);
  2924.             EnableDlgItem(hwnd,IDD_PASTE,FALSE);
  2925. #else
  2926.             EnableWindow(GetDlgItem(hwnd,IDD_MODEREPLACETOP + 2),textf->fClip);
  2927.             EnableWindow(GetDlgItem(hwnd,IDD_PASTE),FALSE);
  2928. #endif
  2929.             break;
  2930.         }
  2931.         case WM_COMMAND: {
  2932.             int id = WM_COMMAND_GetId(wParam);
  2933.             int notify = WM_COMMAND_GetNotify(wParam,lParam);
  2934.             switch(id) {
  2935.                 case IDOK: {
  2936.                     HEADLINE hl;
  2937.                     outlineGetCurheadline(hwnd,&hl);
  2938.                     strcpymax(_contextsl.szstr,hl.szstr,cchof(_contextsl.szstr));
  2939.                     break;
  2940.                 }
  2941.                 case IDD_COPY:
  2942.                 case IDD_PASTE:
  2943.                 case IDD_ADD:
  2944.                 case IDD_ADDCATEGORY:
  2945.                 case IDD_DEL:
  2946.                 case IDD_EDIT:
  2947.                 case IDD_REPLACE:
  2948.                 case IDD_SEARCH: {
  2949.                     listOp(hwnd,id);
  2950.                     return TRUE;
  2951.                 }
  2952.             }
  2953.             break;
  2954.         }
  2955.         case CON_SELCHANGED: {
  2956.             long cur = outlineGetCursel(hwnd);
  2957.             HEADLINE hl;
  2958.             BOOL fEof = !outlineGetHeadline(hwnd,&hl,cur+1);
  2959. #if 1//2.99D 970330 
  2960.             EnableDlgItem(hwnd,IDD_ADD,!fEof);
  2961.             EnableDlgItem(hwnd,IDD_DEL,!fEof);
  2962.             EnableDlgItem(hwnd,IDD_EDIT,!fEof);
  2963.             EnableDlgItem(hwnd,IDD_COPY,!fEof);
  2964.             EnableDlgItem(hwnd,IDD_SEARCH,!fEof);
  2965.             EnableDlgItem(hwnd,IDD_REPLACE,!fEof);
  2966. #else
  2967.             EnableWindow(GetDlgItem(hwnd,IDD_ADD),!fEof);
  2968.             EnableWindow(GetDlgItem(hwnd,IDD_DEL),!fEof);
  2969.             EnableWindow(GetDlgItem(hwnd,IDD_EDIT),!fEof);
  2970.             EnableWindow(GetDlgItem(hwnd,IDD_COPY),!fEof);
  2971.             EnableWindow(GetDlgItem(hwnd,IDD_SEARCH),!fEof);
  2972.             EnableWindow(GetDlgItem(hwnd,IDD_REPLACE),!fEof);
  2973. #endif
  2974.             break;
  2975.         }
  2976.         case WM_ACTIVATE: {//2.99C 970323 
  2977.             BOOL fActive = LOWORD(wParam);
  2978.             if (fActive != WA_INACTIVE) {
  2979.                 EnableDlgButtonEx(hwnd,IDD_MODEREPLACETOP + 2,textf->fClip,IDD_MODEREPLACETOP);
  2980.             }
  2981.             break;
  2982.         }
  2983.     }
  2984.     return FALSE;
  2985. }
  2986.  
  2987. static int searchlistOpen(BOOL fRefer,txstr szSelected)
  2988. {
  2989.     BOOL ret = FALSE;
  2990.     TX _txdic;
  2991.     TX *text = &_txdic;
  2992.     txInitSearchDic(text);
  2993.     // add EOF
  2994.     txJumpFileEnd(text);
  2995.     txInsertLine(text,"%s(end)",text->tsztitle[0]);
  2996.     text->fEdit = FALSE;
  2997.     //
  2998.     HDIALOG hd = _dialog("検索リスト",EXDS_POSCURSOR|EXDS_BIG,NULL);
  2999.     dialogSetContexthelp(hd,TRUE);
  3000.     int cx = 16;
  3001.     
  3002.     dialogCaption(hd,"一覧(&L):");
  3003.     DTRECT r;
  3004.     dialogGetPos(hd,&r);
  3005.     r.cx = DTCX * 30;
  3006.     r.cy = DTCY * 12;
  3007.     dialogControlHelp(hd,204);
  3008. #if 1//2.92 
  3009.     dialogAddTitle(hd,&r);
  3010. #else
  3011.     __dialogAddItem(hd,"LISTBOX",NULL,IDD_TITLELIST,&r,LBS_NOTIFY|WS_BORDER|WS_VSCROLL|WS_HSCROLL|WS_CHILD|WS_VISIBLE|WS_TABSTOP);
  3012. #endif
  3013.     _dialogAddControlInfo(hd,IDD_TITLELIST);
  3014.     dialogLFV(hd);
  3015.     
  3016.     dialogCaption(hd,NULL);
  3017.     cx = 17;
  3018.     dialogControlID(hd,IDD_ADD);
  3019.     dialogControlHelp(hd,204);
  3020.     dialogCmd(hd,"追加(&A)...",cx);
  3021.     dialogControlID(hd,IDD_ADDCATEGORY);
  3022.     dialogControlHelp(hd,204);
  3023.     dialogCmd(hd,"グループの追加(&B)...",cx);
  3024.     dialogControlID(hd,IDD_EDIT);
  3025.     dialogControlHelp(hd,204);
  3026.     dialogCmd(hd,"修正(&E)...",cx);
  3027.     dialogControlID(hd,IDD_DEL);
  3028.     dialogControlHelp(hd,204);
  3029.     dialogCmd(hd,"削除(&D)...",cx);
  3030.     dialogSpaceV(hd);
  3031.     dialogControlID(hd,IDD_COPY);
  3032.     dialogControlHelp(hd,204);
  3033.     dialogCmd(hd,"コピー(&C)",cx);
  3034.     dialogControlID(hd,IDD_PASTE);
  3035.     dialogControlHelp(hd,204);
  3036.     dialogCmd(hd,"貼り付け(&T)",cx);
  3037.     dialogLF(hd);
  3038.     
  3039.     dialogCaption(hd,"内容:");
  3040.     dialogGetPos(hd,&r);
  3041.     r.cx = DTCX * 40;
  3042.     r.cy = DTCY * 4;
  3043.     dialogControlHelp(hd,205);
  3044.     __dialogAddItem(hd,"LISTBOX",NULL,IDD_TITLEVIEW,&r,LBS_NOTIFY|WS_BORDER|WS_VSCROLL|WS_HSCROLL|WS_CHILD|WS_VISIBLE|WS_TABSTOP);
  3045.     _dialogAddControlInfo(hd,IDD_TITLEVIEW);
  3046.     
  3047.     if (fRefer) {
  3048.         dialogLFV(hd);
  3049.         dialogSpaceH(hd);
  3050.         dialogSpaceH(hd);
  3051.         dialogSpaceH(hd);
  3052.         dialogOK(hd,cx);
  3053.         dialogCancel(hd,cx);
  3054.         dialogSpaceV(hd);
  3055.     } else {
  3056.         dialogLFV(hd);
  3057.         dialogSpaceH(hd);
  3058.         dialogSpaceH(hd);
  3059.         dialogSpaceH(hd);
  3060.         cx = 16;
  3061. //        dialogControlRadioV(hd);
  3062.         _context.modeDirection = DIR_NEXT;
  3063.         dialogControlHelp(hd,-303);
  3064.         dialogRadioIDB(hd,&_context.modeDirection,"上へ(&P)","下へ(&N)");
  3065.         //
  3066.         dialogControlID(hd,IDD_SEARCH);
  3067.         dialogControlHelp(hd,195);
  3068.         dialogCmdDefault(hd,"次を検索(&S)",cx);
  3069.         dialogSpaceV(hd);
  3070.         
  3071.         dialogControlRadioV(hd);
  3072.         _context.modeReplace = textf->fClip ? REPLACE_AREA : REPLACE_1;
  3073.         dialogControlID(hd,IDD_MODEREPLACETOP);
  3074.         dialogControlHelp(hd,-305);
  3075.         dialogRadioIDB(hd,&_context.modeReplace,"1つ置換(&1)","全て(&2)","範囲内(&3)");
  3076.         //
  3077.         dialogControlID(hd,IDD_REPLACE);
  3078.         dialogControlHelp(hd,197);
  3079.         dialogCmd(hd,"置換(&R)",cx);
  3080.         dialogSpaceV(hd);
  3081.         
  3082.         dialogControlID(hd,IDCANCEL);
  3083.         dialogCancel(hd,cx);
  3084.     }
  3085.     CHOOSEOUTLINE co;
  3086.     memset(&co,0,sizeof(CHOOSEOUTLINE));
  3087.     co.text = text;
  3088.     co.szhook = "\m.dlgprocList";
  3089.     co.iselFirst = 0;
  3090.     co.fNoTitleHead = TRUE;
  3091.     if (dialogSelectTitle(hd,&co)) {
  3092.         ret = TRUE;
  3093.         if (fRefer) {
  3094.             szSelected = _contextsl.szstr;
  3095.         }
  3096.     }
  3097.     if (text->fEdit) {
  3098.         // del EOF
  3099.         txJumpFileEnd(text);
  3100.         txPrevPara(text);
  3101.         txDeletePara(text);
  3102.         //
  3103.         txSave(text);
  3104.     }
  3105.     txClose(text);
  3106.     return ret;
  3107. }
  3108.  
  3109. uiSearchList
  3110. {
  3111. // 検索リスト
  3112. // 決まった置換や検索をリストで選んで実行します
  3113. //1.96で追加
  3114.     return searchlistOpen(FALSE,NULL);
  3115. }
  3116.  
  3117. //##複数テキストの検索・置換
  3118.  
  3119. vzuiSearchMulti
  3120. {
  3121. // VZの[複数テキストで検索・置換]ライクなコマンド
  3122. //1.01A で追加
  3123. //{#VZ} +{F6}
  3124.     if (_fReplace) {
  3125.         wzlock(LOCK_SEARCHALL);
  3126.         text->share->replace.searchmode |= SEARCH_ALLTEXT;
  3127.         wzunlock(LOCK_SEARCHALL);
  3128.         txReplaceContinue(text);
  3129.     } else {
  3130.         txSearchContinue(text);
  3131.     }
  3132. }
  3133.  
  3134. uiSearchFunctionC
  3135. {
  3136. // 関数名を指定して、Cの関数定義を検索します
  3137. //2.90で追加
  3138.     BOOL ret = FALSE;
  3139.     HDIALOG hd = dialog("C関数定義の検索");
  3140.     txstr szstr;
  3141.     dialogControlHist(hd,HIST_SEARCH);
  3142.     dialogStr(hd,"関数名(&N)",szstr,10,30);
  3143.     if (dialogOpen(hd)) {
  3144.         txSetUndispEx(text);
  3145.         txJumpFileTop(text);
  3146.         while(1) {
  3147.             txSearchEx(text,"^[A-Za-z_][^/]*[^;]$",SEARCH_RE|SEARCH_NOSELECT);
  3148.             txJumpParaTop(text);
  3149.             NPARA npara = text->npara;
  3150.             if (!txSearchEx(text,szstr,SEARCH_CUR|SEARCH_NOSELECT)) break;
  3151.             if (text->npara == npara) {
  3152.                 ret = TRUE;
  3153.                 break;
  3154.             }
  3155.             txJumpNpara(text,npara);
  3156.             if (!txNextPara(text)) break;
  3157.         }
  3158.         if (ret) {
  3159.             txSetDisp(text);
  3160.         } else {
  3161.             txSetDispEx(text);
  3162.         }
  3163.     }
  3164.     if (!ret) statprintf("見つかりませんでした");
  3165.     return ret;
  3166. }
  3167.  
  3168. //2.96 970201 WZ.EXEから移動
  3169. // 旧API
  3170.  
  3171. int TXAPI TXHIGH txSearch(tx *text,mchar *find)
  3172. {
  3173.     // findをカーソル位置の次から検索
  3174.     // 検索ヒストリは変更しません
  3175.     //1.00H2 検索オプションはtext->searchmodeを参照します
  3176.     //{#RET}見つかればカーソルを移動し0以外の値、
  3177.     // 見つからなければ0を返す
  3178.     #if 1//2.96 970201 
  3179.         return txSearchEx(text,find,text->searchmode);
  3180.     #else
  3181.         #if 1//1.92
  3182.         return SearchNext(text,find,text->searchmode);
  3183.         #else
  3184.         return SearchNext(text,find,searchmodeFromText(text));
  3185.         #endif
  3186.     #endif
  3187. }
  3188.  
  3189. int TXAPI TXHIGH txSearchPrev(tx *text,mchar *find)
  3190. {
  3191.     // findをカーソル位置からテキスト先頭まで検索
  3192.     // ※txSearchContinuePrevには影響しません。
  3193.     //{#RET}見つかればカーソルを移動し0以外の値、
  3194.     // 見つからなければ0を返す
  3195.     #if 1//2.96 970201 
  3196.         return txSearchEx(text,find,text->searchmode|SEARCH_PREV);
  3197.     #else
  3198.         #if 1//1.92
  3199.         return SearchPrev(text,find,text->searchmode|SEARCH_PREV);
  3200.         #else
  3201.         return SearchPrev(text,find,searchmodeFromText(text)|SEARCH_PREV);
  3202.         #endif
  3203.     #endif
  3204. }
  3205.  
  3206. //1.91A jump.cから移動
  3207. //{###ジャンプ}
  3208.  
  3209. #include "wintxx.h"
  3210. #include "dialog.h"
  3211.  
  3212. void uiJumpAddress(TX* text)
  3213. {
  3214.     txstr str;
  3215.     static int adr = 0;
  3216.     HDIALOG hd = dialog("ジャンプ");
  3217.     sprintf(str,"%08lX",adr);
  3218.     dialogStr(hd,"アドレス(&A):",str,10,12);
  3219.     if (dialogOpen(hd)) {
  3220.         mchar*p = str;
  3221.         adr = 0;
  3222.         for (;*p;p++) {
  3223.             mchar c = toupper(*p);
  3224.             if (isdigit(c)) {
  3225.                 adr *= 16;
  3226.                 adr += c - '0';
  3227.             } else if ('A' <= c && c <= 'F') {
  3228.                 adr *= 16;
  3229.                 adr += c - 'A' + 10;
  3230.             } else {
  3231.                 break;
  3232.             }
  3233.         }
  3234.         txJumpAddress(text,adr);
  3235.     }
  3236. }
  3237.  
  3238. BOOL TXCMDBASE uiJump(TX* text)
  3239. {
  3240.     // 指定行ジャンプ
  3241.     // ジャンプダイアログを開いて、指定された行番号にジャンプします
  3242.     if (text->fBinedit) {
  3243.         uiJumpAddress(text);
  3244.     } else {
  3245.         int nline = txVarGet(text,"\m.nline");
  3246.         if (nline == 0) nline = 1;
  3247.         HDIALOG hd = dialog("ジャンプ");
  3248.         dialogInt(hd,"行番号(&N):",&nline,10,7);
  3249. //        dialogSetHelp(hd,"wz txuiJump");
  3250.         if (dialogOpen(hd)) {
  3251.             txJumpModal(text,nline);
  3252.             txVarSet(text,"\m.nline",nline);
  3253.         }
  3254.     }
  3255.     return TRUE;
  3256. }
  3257.  
  3258. //2.99 970312 uiJumpPageを元に戻した
  3259. //2.95 970131 改良 テキストモードでもheightを使ってページ数を計算
  3260. // thanks y.mikomeさん
  3261. BOOL TXCMDBASE uiJumpPage(TX* text)
  3262. {
  3263.     // 指定頁,行ジャンプ
  3264.     // 詳細モードでは頁指定ジャンプ
  3265.     // 簡易頁表示では、頁・行複合指定ジャンプ
  3266.     // それ以外では行指定ジャンプ
  3267.     HDIALOG hd = dialog("ジャンプ");
  3268.     NPAGE npage = 0;
  3269.     if (text->editmode == 2) {
  3270.         npage = txNpageFromNpageclm(text,text->npage);
  3271.     } else if (text->fLineD && text->height) {
  3272.         npage = (text->nline / text->height) + 1;
  3273.     }
  3274.     dialogControlEnable(hd,(npage != 0));
  3275.     dialogIntW(hd,"ページ(&P):",&npage,10,7);
  3276.     int line = txVarGet(text,"\m.npageline");
  3277.     if (line == 0) line = 1;
  3278.     dialogControlEnable(hd,(text->editmode < 2));
  3279.     dialogInt(hd,"行番号(&N):",&line,10,7);
  3280.     if (dialogOpen(hd)) {
  3281.         if (npage) {
  3282.             if (text->editmode == 2) {
  3283.                 txJumpPage(text,npage);
  3284.             } else {
  3285.                 txJumpModal(text,(npage - 1) * text->height + line);
  3286.             }
  3287.         } else {
  3288.             txJumpModal(text,line);
  3289.         }
  3290.         txVarSet(text,"\m.npageline",line);
  3291.     }
  3292.     return TRUE;
  3293. }
  3294.  
  3295. err_brace
  3296. {
  3297.     statprintf("括弧が見つかりません");
  3298.     if (text->fbeep) MessageBeep(MB_ICONEXCLAMATION);
  3299. }
  3300.  
  3301. BOOL TXCMDBASE vzSetLySwitch(TX* text)
  3302. {
  3303.     // 表示位置変更
  3304.     // カーソル位置を画面上端、中央、下端の順に切り替えます。
  3305.     // 編集位置は変わりません。
  3306.     //{#VZIBM} +{Home}
  3307.     //{#VZ98} {Clr}
  3308.     //{#EMACS} +{Home}
  3309.     int y = text->lcywindow - 3;
  3310.     y /= 2;
  3311.     if (text->ly==y) {
  3312.         txSetLy(text,text->lcywindow-2);
  3313.     } else {
  3314.         if (text->ly==1){
  3315.             txSetLy(text,y);
  3316.         } else {
  3317.             txSetLy(text,1);
  3318.         }
  3319.     }
  3320.     return TRUE;
  3321. }
  3322.  
  3323. otherJumpLineTop
  3324. {
  3325. // 次画面で行頭に移動します
  3326. //1.00Cで追加
  3327.     return wndtxCallNextEx("txJumpLineTop");
  3328. }
  3329.  
  3330. otherJumpLineEnd
  3331. {
  3332. // 次画面で行末に移動します
  3333. //1.00Cで追加
  3334.     return wndtxCallNextEx("txJumpLineEnd");
  3335. }
  3336.  
  3337. otherJumpFileTopLine
  3338. {
  3339. // 次画面でテキストの先頭表示行へジャンプ
  3340. //1.00Cで追加
  3341.     return wndtxCallNextEx("txJumpFileTopLine");
  3342. }
  3343.  
  3344. otherJumpFileEndLine
  3345. {
  3346. // 次画面でテキストの末尾表示行へジャンプ
  3347. //1.00Cで追加
  3348.     return wndtxCallNextEx("txJumpFileEndLine");
  3349. }
  3350.  
  3351. //{###カーソル移動}
  3352.  
  3353. //## 範囲選択してカーソル移動
  3354. //2.99D 970331 範囲選択してカーソル移動するコマンド追加
  3355.  
  3356. //2.99D 970331 new
  3357. static int _txkeySelect(TX* text,mchar* szBaseCmd)
  3358. {
  3359. // 選択して右へ
  3360.     int modeEditor0 = text->modeEditor;
  3361.     int fKeyVkShift0 = text->fKeyVkShift;
  3362.     text->modeEditor = ME_WIN;
  3363.     text->fKeyVkShift = 2;
  3364.     int ret = txCall(text,szBaseCmd);
  3365.     text->modeEditor = modeEditor0;
  3366.     text->fKeyVkShift = fKeyVkShift0;
  3367.     return ret;
  3368. }
  3369.  
  3370. //2.99D 970331 new
  3371. int TXCMD txkeySelectRight(TX* text)
  3372. {
  3373. // 選択して右へ
  3374.     return _txkeySelect(text,"txkeyRight");
  3375. }
  3376.  
  3377. //2.99D 970331 new
  3378. int TXCMD txkeySelectLeft(TX* text)
  3379. {
  3380. // 選択して左へ
  3381.     return _txkeySelect(text,"txkeyLeft");
  3382. }
  3383.  
  3384. //2.99D 970331 new
  3385. int TXCMD txkeySelectUp(TX* text)
  3386. {
  3387. // 選択して上へ
  3388.     return _txkeySelect(text,"txkeyUp");
  3389. }
  3390.  
  3391. //2.99D 970331 new
  3392. int TXCMD txkeySelectDown(TX* text)
  3393. {
  3394. // 選択して下へ
  3395.     return _txkeySelect(text,"txkeyDown");
  3396. }
  3397.  
  3398. otherUp
  3399. {
  3400. // 次画面のカーソルを1行上に移動します
  3401. //1.00Cで追加
  3402.     return wndtxCallNextEx("txUp");
  3403. }
  3404.  
  3405. otherDown
  3406. {
  3407. // 次画面のカーソルを1行下に移動します
  3408. //1.00Cで追加
  3409.     return wndtxCallNextEx("txDown");
  3410. }
  3411.  
  3412. otherPrevRoll
  3413. {
  3414. // 次画面を1行ロールアップします
  3415. //1.00Cで追加
  3416.     return wndtxCallNextEx("txPrevRoll");
  3417. }
  3418.  
  3419. otherNextRoll
  3420. {
  3421. // 次画面を1行ロールダウンします
  3422. //1.00Cで追加
  3423.     return wndtxCallNextEx("txNextRoll");
  3424. }
  3425.  
  3426. otherNextPage
  3427. {
  3428. // 次画面をページダウンします
  3429. //1.00Cで追加
  3430.     return wndtxCallNextEx("txNextPage");
  3431. }
  3432.  
  3433. otherNextPageVz
  3434. {
  3435. // 次画面をページダウン(VZライク)します
  3436. //1.00Cで追加
  3437.     return wndtxCallNextEx("txNextPageVz");
  3438. }
  3439.  
  3440. otherNextPageMi
  3441. {
  3442. // 次画面をページダウン(MIFESライク)します
  3443. //1.00Cで追加
  3444.     return wndtxCallNextEx("txNextPageMi");
  3445. }
  3446.  
  3447. otherPrevPage
  3448. {
  3449. // 次画面をページアップします
  3450. //1.00Cで追加
  3451.     return wndtxCallNextEx("txPrevPage");
  3452. }
  3453.  
  3454. otherPrevPageVz
  3455. {
  3456. // 次画面をページアップ(VZライク)します
  3457. //1.00Cで追加
  3458.     return wndtxCallNextEx("txPrevPageVz");
  3459. }
  3460.  
  3461. otherPrevPageMi
  3462. {
  3463. // 次画面をページアップ(MIFESライク)します
  3464. //1.00Cで追加
  3465.     return wndtxCallNextEx("txPrevPageMi");
  3466. }
  3467.  
  3468.  
  3469. bothUp
  3470. {
  3471. // 次画面と同時にカーソル1行上に移動します
  3472. //1.00Cで追加
  3473.     return wndtxCallBothEx("txUp");
  3474. }
  3475.  
  3476. bothDown
  3477. {
  3478. // 次画面と同時にカーソルを1行下に移動します
  3479. //1.00Cで追加
  3480.     return wndtxCallBothEx("txDown");
  3481. }
  3482.  
  3483. bothPrevRoll
  3484. {
  3485. // 次画面と同時に1行ロールアップします
  3486. //1.00Cで追加
  3487.     return wndtxCallBothEx("txPrevRoll");
  3488. }
  3489.  
  3490. bothNextRoll
  3491. {
  3492. // 次画面と同時に1行ロールダウンします
  3493. //1.00Cで追加
  3494.     return wndtxCallBothEx("txNextRoll");
  3495. }
  3496.  
  3497. bothNextPage
  3498. {
  3499. // 次画面と同時にページダウンします
  3500. //1.00Cで追加
  3501.     return wndtxCallBothEx("txNextPage");
  3502. }
  3503.  
  3504. bothNextPageVz
  3505. {
  3506. // 次画面と同時にページダウン(VZライク)します
  3507. //1.00Cで追加
  3508.     return wndtxCallBothEx("txNextPageVz");
  3509. }
  3510.  
  3511. bothNextPageMi
  3512. {
  3513. // 次画面と同時にページダウン(MIFESライク)します
  3514. //1.00Cで追加
  3515.     return wndtxCallBothEx("txNextPageMi");
  3516. }
  3517.  
  3518. bothPrevPage
  3519. {
  3520. // 次画面と同時にページアップします
  3521. //1.00Cで追加
  3522.     return wndtxCallBothEx("txPrevPage");
  3523. }
  3524.  
  3525. bothPrevPageVz
  3526. {
  3527. // 次画面と同時にページアップ(VZライク)します
  3528. //1.00Cで追加
  3529.     return wndtxCallBothEx("txPrevPageVz");
  3530. }
  3531.  
  3532. bothPrevPageMi
  3533. {
  3534. // 次画面と同時にページアップ(MIFESライク)します
  3535. //1.00Cで追加
  3536.     return wndtxCallBothEx("txPrevPageMi");
  3537. }
  3538.  
  3539. //{###ジャンプ}
  3540.  
  3541. //##しおり
  3542.  
  3543. #define IDD_UMLIST        100
  3544. #define IDD_JUMP        101
  3545. #define IDD_REGISTER    102
  3546. #define IDD_KILL        103
  3547.  
  3548. static void markFlush(TX* text,HWND hwnd)
  3549. {
  3550. //3.00A2 970506 引数にtext追加
  3551.     HWND hctrl = GetDlgItem(hwnd,IDD_UMLIST);
  3552.     SendMessage(hctrl,LB_RESETCONTENT,0,0);
  3553. #if 1
  3554.     txSetUndispEx(text);
  3555.     txstr szline;
  3556.     int i;
  3557.     for (i = 1;i < MAXMARK;i++) {
  3558.         txJumpAddress(text,text->mark[i]);
  3559.         txGetPara(text,szline);
  3560.         mchar szbuff[CCHWORD];
  3561.         reReplace(szbuff,CCHWORD,strGetWordTop(szline),"\t"," ",SEARCH_ALL);
  3562.         mchar buff[40];
  3563.         sprintf(buff,"%d) %d:\t",i,text->npara);
  3564.         SendMessage(hctrl,LB_ADDSTRING,0,(LPARAM)(mchar*)(buff + szbuff));
  3565.     }
  3566.     txSetDispEx(text);
  3567. #else
  3568.     #if 0    //3.00A3 970508 tszmark廃止
  3569.     if (text->tszmark) {
  3570.         int i;
  3571.         for (i = 0;i < MAXMARK;i++) {
  3572.             mchar szbuff[CCHMARK * 2];
  3573.             strcpy(szbuff,text->tszmark + CCHMARK * i);
  3574.             strtoesc(szbuff);
  3575.             //
  3576.             mchar szdst[CCHMARK * 2];
  3577.             reReplace(szdst,CCHMARK * 2,szbuff,\"\\s"," ",SEARCH_ALL);
  3578.             strcpy(szbuff,szdst);
  3579.             reReplace(szdst,CCHMARK * 2,szbuff,\"\\t"," ",SEARCH_ALL);
  3580.             //
  3581.             SendMessage(hctrl,LB_ADDSTRING,0,(LPARAM)(mchar*)(inttostr(i) + ": " + szdst));
  3582.         }
  3583.         SendMessage(hctrl,LB_SETCURSEL,0,0);
  3584.     }
  3585.     #endif
  3586. #endif
  3587. }
  3588.  
  3589. BOOL dlgprocMark(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  3590. {
  3591.     HDIALOG hd = dialogFromHwnd(hwnd);//3.00A2 970506 
  3592.     TX* text = (TX*)dialogGetCustdata(hd);//3.00A2 970506 
  3593.     switch(message) {
  3594.         case WM_INITDIALOG: {
  3595.             markFlush(text,hwnd);
  3596.             if (txVarIsExist(text,"\m.iMark")) {
  3597.                 ListBox_SetCurSel(GetDlgItem(hwnd,IDD_UMLIST),txVarGet(text,"\m.iMark"));
  3598.             }
  3599. //            SendDlgItemMessage(hwnd,IDD_UMLIST,LB_SETTABSTOPS,1,10);
  3600.             break;
  3601.         }
  3602.         case WM_COMMAND: {
  3603.             HDIALOG hd = dialogFromHwnd(hwnd);
  3604.             int id = WM_COMMAND_GetId(wParam);
  3605.             int notify = WM_COMMAND_GetNotify(wParam,lParam);
  3606.             
  3607.             switch(id) {
  3608.                 case IDD_UMLIST: {
  3609.                     if (notify == LBN_DBLCLK) {
  3610.                         FORWARD_WM_COMMAND(hwnd,IDD_JUMP,NULL,NULL,PostMessage);
  3611.                         break;
  3612.                     }
  3613.                     #if 0
  3614.                     if (notify == LBN_SELCHANGE) {
  3615.                         HWND hctrl = GetDlgItem(hwnd,id);
  3616.                         int isel = ListBox_GetCurSel(hctrl);
  3617.                         if (isel != LB_ERR) {
  3618.                             txJumpAddress(text,text->mark[isel+1]);
  3619.                         }
  3620.                         break;
  3621.                     }
  3622.                     #endif
  3623.                     break;
  3624.                 }
  3625.                 case IDD_JUMP: {
  3626.                     HWND hctrl = GetDlgItem(hwnd,IDD_UMLIST);
  3627.                     int i = ListBox_GetCurSel(hctrl);
  3628.                     if (i != LB_ERR) {
  3629.                         txVarSet(text,"\m.iMark",i);
  3630.                         txJumpMarkN(text,i + 1);
  3631.                     }
  3632.                     break;
  3633. //                    return TRUE;
  3634.                 }
  3635.                 case IDD_REGISTER: {
  3636.                     HWND hctrl = GetDlgItem(hwnd,IDD_UMLIST);
  3637.                     int i = ListBox_GetCurSel(hctrl);
  3638.                     if (i != LB_ERR) {
  3639.                         txVarSet(text,"\m.iMark",i);
  3640.                         txMarkN(text,i + 1);
  3641.                         markFlush(text,hwnd);
  3642.                         SendMessage(hctrl,LB_SETCURSEL,i,0);
  3643.                     }
  3644.                     break;
  3645. //                    return TRUE;
  3646.                 }
  3647.             }
  3648.             break;
  3649.         }
  3650.     }
  3651.     return FALSE;
  3652. }
  3653.  
  3654. //2.95 970130 しおり改良
  3655. //2.99G 970405 MS.KEY割り当て
  3656. BOOL TXCMDBASE uiMark(TX* text)
  3657. {
  3658. // しおり
  3659. //{#MS} ^{F5}
  3660.     IFILE adr = txGetAddress(text);
  3661.     txMarkCur(text);
  3662.     text->fNoMarkCur++;
  3663.     //
  3664.     int cx = 12;
  3665.     HDIALOG hd = dialog("しおり");
  3666.     dialogSetContexthelp(hd,TRUE);
  3667.     dialogSetHookEx(hd,"\m.dlgprocMark");
  3668.     dialogSetCustdata(hd,text);//3.00A2 970506 
  3669.     
  3670.     DTRECT r;
  3671.     dialogGetPos(hd,&r);
  3672.     r.cx = DTCX * 60;
  3673.     r.cy = DTCY * 6;    //2.99C 970326 4->6 WZ32で小さすぎた
  3674.     __dialogAddItem(hd,"LISTBOX",NULL,IDD_UMLIST,&r,LBS_NOTIFY|LBS_USETABSTOPS|WS_BORDER|WS_VSCROLL|WS_HSCROLL|WS_CHILD|WS_VISIBLE|WS_TABSTOP);
  3675.     dialogControlHelp(hd,217);
  3676.     _dialogAddControlInfo(hd,IDD_UMLIST);
  3677.     dialogSetPosY(hd,r.y + r.cy);
  3678.     
  3679.     dialogLFV(hd);
  3680.     
  3681.     dialogControlID(hd,IDD_JUMP);
  3682.     dialogControlHelp(hd,218);
  3683.     dialogCmdDefault(hd,"ジャンプ(&J)",cx);
  3684.     //
  3685.     dialogControlID(hd,IDD_REGISTER);
  3686.     dialogControlHelp(hd,219);
  3687.     dialogCmd(hd,"はさむ(&R)",cx);
  3688.     //
  3689.     dialogSpaceV(hd);
  3690.     dialogControlID(hd,IDCANCEL);
  3691.     dialogButtonCmd(hd,"キャンセル",NULL,cx);
  3692.     
  3693.     if (!dialogOpen(hd)) {
  3694.         txJumpAddress(text,adr);
  3695.     }
  3696.     text->fNoMarkCur--;
  3697.     return TRUE;
  3698. }
  3699.  
  3700. //旧:usermenu.umcMiJump
  3701. menuJumpMi
  3702. {
  3703. #WZKEY
  3704. // MiJumpメニュー
  3705. //{#MI} {F3}
  3706.     call("menu.ジャンプ(MIFESライク)");
  3707. }
  3708.  
  3709. //旧:usermenu.umcMiSearch
  3710. menuSearchMi
  3711. {
  3712. #WZKEY
  3713. // MiSearchメニュー
  3714. //{#MI} +{F3}
  3715.     call("menu.検索(MIFESライク)");
  3716. }
  3717.  
  3718. //旧:usermenu.umcMiMark
  3719. menuMarkMi
  3720. {
  3721. #WZKEY
  3722. // MiMarkメニュー
  3723. //{#MI} ^J
  3724.     call("menu.マーク(MIFESライク)");
  3725. }
  3726.  
  3727. // testdata
  3728. // ください。下さいな。下さいだ。
  3729.  
  3730. //2.00E4 
  3731. void __new(void)
  3732. {
  3733.     _context.modeDirection = DIR_NEXT;
  3734. }
  3735.  
  3736. //{###カーソル移動}
  3737.  
  3738. //##キー割り当てコマンド(WIN,VZ,MI,WIN範囲選択 共通)
  3739. //2.90 
  3740.  
  3741. int TXCMDBASE txkeyLeftWord(TX* text)
  3742. {
  3743. // 1つ前の単語へ(ユーザインターフェース)
  3744. // ユーザインターフェースの設定によって動作が変わります
  3745. //{#MS} ^{Left} +^{Left}
  3746. //{#VZ} +{Left} ^A
  3747. //{#MI} ^A
  3748.     txkeySelectWin(text);
  3749.     if (text->fClip) {
  3750.         //2.96 970210 txkeyLeftWord 選択時は単語を取得しやすい移動にした
  3751.         IFILE adr = txGetAddress(text);
  3752.         int ret = txJumpWordTopMi(text);
  3753.         if (adr == txGetAddress(text)) {
  3754.             return txLeftWordMi(text);
  3755.         }
  3756.         return ret;
  3757.     }
  3758. #if 1//2.96 970210 MS.KEYの単語移動をMIFESライクにした
  3759.     if (text->modeEditor == ME_VZ) return txLeftWord(text);
  3760.     return txLeftWordMi(text);
  3761. #else
  3762.     if (text->modeEditor == ME_MI) return txLeftWordMi(text);
  3763.     return txLeftWord(text);
  3764. #endif
  3765. }
  3766.  
  3767. int TXCMDBASE txkeyRightWord(TX* text)
  3768. {
  3769. // 1つ後の単語へ(ユーザインターフェース)
  3770. // ユーザインターフェースの設定によって動作が変わります
  3771. //{#MS} ^{Right} +^{Right}
  3772. //{#VZ} +{Right} ^F
  3773. //{#MI} ^F
  3774.     txkeySelectWin(text);
  3775.     if (text->fClip) {
  3776.         //2.96 970210 txkeyRightWord 選択時は単語を取得しやすい移動にした
  3777.         IFILE adr = txGetAddress(text);
  3778.         int ret = txJumpWordEndMi(text);
  3779.         if (adr == txGetAddress(text)) {
  3780.             return txRightWordMi(text);
  3781.         }
  3782.         return ret;
  3783.     }
  3784. #if 1//2.96 970210 
  3785.     if (text->modeEditor == ME_VZ) return txRightWord(text);
  3786.     return txRightWordMi(text);
  3787. #else
  3788.     if (text->modeEditor == ME_MI) return txRightWordMi(text);
  3789.     return txRightWord(text);
  3790. #endif
  3791. }
  3792.  
  3793. int TXCMDBASE txkeyPrevPage(TX* text)
  3794. {
  3795. // ページアップ(ユーザインターフェース)
  3796. // ユーザインターフェースの設定によって動作が変わります
  3797. // txPrevHalfPage
  3798. //{#MS} {PageUp} +{PageUp}
  3799. //{#VZ98} ^R +{Up}
  3800. //{#VZIBM} ^R {PageUp}
  3801. //{#MI} +{Up}
  3802. //{#EMACS} {PageUp}
  3803.     txkeySelectWin(text);
  3804. #if 1//3.00A 970427 VZ.KEYでページング単位が半画面のとき、検索ジャンプができなかった
  3805.     if (text->modeEditor == ME_VZ) return txPrevPageVz(text);
  3806.     if (text->fHalfPage && !text->fPageTurn) return txPrevHalfPage(text);//2.99F 970404 txkeyNextPage:ハーフページで頁めくりオフならハーフページ移動するようにした
  3807.     if (text->modeEditor == ME_MI) return txPrevPageMi(text);
  3808.     return txPrevPage(text);
  3809. #else
  3810.     if (text->fHalfPage && !text->fPageTurn) return txPrevHalfPage(text);//2.99F 970404 txkeyNextPage:ハーフページで頁めくりオフならハーフページ移動するようにした
  3811.     if (text->modeEditor == ME_MI) return txPrevPageMi(text);
  3812.     if (text->modeEditor == ME_VZ) return txPrevPageVz(text);
  3813.     return txPrevPage(text);
  3814. #endif
  3815. }
  3816.  
  3817. int TXCMDBASE txkeyNextPage(TX* text)
  3818. {
  3819. // ページダウン(ユーザインターフェース)
  3820. // ユーザインターフェースの設定によって動作が変わります
  3821. // txNextHalfPage
  3822. //{#MS} {PageDown} +{PageDown}
  3823. //{#VZ98} ^C +{Down}
  3824. //{#VZIBM} ^C {PageDown}
  3825. //{#MI} +{Down}
  3826. //{#EMACS} {PageDown} ^V
  3827.     txkeySelectWin(text);
  3828. #if 1//3.00A 970427 VZ.KEYでページング単位が半画面のとき、検索ジャンプができなかった
  3829.     if (text->modeEditor == ME_VZ) return txNextPageVz(text);
  3830.     if (text->fHalfPage && !text->fPageTurn) return txNextHalfPage(text);//2.99F 970404 txkeyNextPage:ハーフページで頁めくりオフならハーフページ移動するようにした
  3831.     if (text->modeEditor == ME_MI) return txNextPageMi(text);
  3832.     return txNextPage(text);
  3833. #else
  3834.     if (text->fHalfPage && !text->fPageTurn) return txNextHalfPage(text);//2.99F 970404 txkeyNextPage:ハーフページで頁めくりオフならハーフページ移動するようにした
  3835.     if (text->modeEditor == ME_MI) return txNextPageMi(text);
  3836.     if (text->modeEditor == ME_VZ) return txNextPageVz(text);
  3837.     return txNextPage(text);
  3838. #endif
  3839. }
  3840.  
  3841. int TXCMDBASE txkeyPrevHalfPage(TX* text)
  3842. {
  3843. // ハーフページアップ(ユーザインターフェース)
  3844. // ユーザインターフェースの設定によって動作が変わります
  3845. //{#MI} {PageUp} ^R
  3846.     txkeySelectWin(text);
  3847. #if 0//2.99 970313 
  3848.     if (text->modeEditor == ME_MI) return txPrevPageMi(text);
  3849.     if (text->modeEditor == ME_VZ) return txPrevPageVz(text);
  3850. #endif
  3851.     return txPrevHalfPage(text);
  3852. }
  3853.  
  3854. int TXCMDBASE txkeyNextHalfPage(TX* text)
  3855. {
  3856. // ハーフページダウン(ユーザインターフェース)
  3857. // ユーザインターフェースの設定によって動作が変わります
  3858. //{#MI} {PageDown} ^C
  3859.     txkeySelectWin(text);
  3860. #if 0//2.99 970313 
  3861.     if (text->modeEditor == ME_MI) return txNextPageMi(text);
  3862.     if (text->modeEditor == ME_VZ) return txNextPageVz(text);
  3863. #endif
  3864.     return txNextHalfPage(text);
  3865. }
  3866.  
  3867. int TXCMDBASE txkeyJumpLineTop(TX* text)
  3868. {
  3869. // 表示行の先頭へジャンプ(ユーザインターフェース)
  3870. // ユーザインターフェースの設定によって動作が変わります
  3871. //{#MS} {Home} +{Home}
  3872. //{#VZ98} ^Q[ %{Left}
  3873. //{#VZIBM} ^Q[ {Home}
  3874. //{#MI} ^QS +{Left}
  3875. //{#EMACS} {Home}
  3876.     txkeySelectWin(text);
  3877.     return txJumpLineTop(text);
  3878. }
  3879.  
  3880. int TXCMDBASE txkeyJumpLineTail(TX* text)
  3881. {
  3882. // 表示行の末尾文字の後ろへジャンプ(ユーザインターフェース)
  3883. // ユーザインターフェースの設定によって動作が変わります
  3884. //{#MS} {End} +{End}
  3885. //{#VZ98} ^Q] %{Right}
  3886. //{#VZIBM} ^Q] {End}
  3887. //{#MI} ^QD +{Right}
  3888. //{#EMACS} {End}
  3889.     txkeySelectWin(text);
  3890.     return txJumpLineTail(text);
  3891. }
  3892.  
  3893. int TXCMDBASE txkeyJumpParaTop(TX* text)
  3894. {
  3895. // 段落の先頭へジャンプ(ユーザインターフェース)
  3896. // ユーザインターフェースの設定によって動作が変わります
  3897. //{#VZ} ^QS ^{Left} 
  3898. //{#EMACS} ^A ^{Left}
  3899.     txkeySelectWin(text);
  3900.     return txJumpParaTop(text);
  3901. }
  3902.  
  3903. int TXCMDBASE txkeyJumpParaEnd(TX* text)
  3904. {
  3905. // 段落の末尾へジャンプ(ユーザインターフェース)
  3906. // ユーザインターフェースの設定によって動作が変わります
  3907. //{#VZ} ^QD ^{Right}
  3908. //{#EMACS} ^E ^{Right}
  3909.     txkeySelectWin(text);
  3910.     return txJumpParaEnd(text);
  3911. }
  3912.  
  3913. int TXCMDBASE txkeyJumpScreenTop(TX* text)
  3914. {
  3915. // 画面の上端へジャンプ(ユーザインターフェース)
  3916. // ユーザインターフェースの設定によって動作が変わります
  3917. //2.99A 970321 {#MS} ^{PageUp} +^{PageUp} -> {#MS} +^{PageUp}
  3918. //{#MS} +^{PageUp}
  3919. //{#VZ98} ^{Up} ^QE
  3920. //{#VZIBM} ^{Up} ^QE ^{Home}
  3921. //{#MI} ^{PageUp}
  3922.     txkeySelectWin(text);
  3923.     return txJumpScreenTop(text);
  3924. }
  3925.  
  3926. int TXCMDBASE txkeyJumpScreenEnd(TX* text)
  3927. {
  3928. // 画面の下端へジャンプ(ユーザインターフェース)
  3929. // ユーザインターフェースの設定によって動作が変わります
  3930. //2.99A 970321 {#MS} ^{PageDown} +^{PageDown} -> {#MS} +^{PageDown}
  3931. //{#MS} +^{PageDown}
  3932. //{#VZ98} ^{Down} ^QX
  3933. //{#VZIBM} ^{Down} ^QX ^{End}
  3934. //{#MI} ^{PageDown}
  3935.     txkeySelectWin(text);
  3936.     return txJumpScreenEnd(text);
  3937. }
  3938.  
  3939. int TXCMDBASE txkeyJumpWordTop(TX* text)
  3940. {
  3941. // 語の先頭へジャンプ(ユーザインターフェース)
  3942. // ユーザインターフェースの設定によって動作が変わります
  3943.     txkeySelectWin(text);
  3944.     if (text->modeEditor == ME_VZ) return txJumpWordTop(text);
  3945.     return txJumpWordTopMi(text);
  3946. }
  3947.  
  3948. int TXCMDBASE txkeyJumpWordTail(TX* text)
  3949. {
  3950. // 語の末尾の次の文字へジャンプ(ユーザインターフェース)
  3951. // ユーザインターフェースの設定によって動作が変わります
  3952.     txkeySelectWin(text);
  3953.     if (text->modeEditor == ME_VZ) return txJumpWordEnd(text);
  3954.     return txJumpWordEndMi(text);
  3955. }
  3956.  
  3957. //{###ジャンプ}
  3958.  
  3959. int TXCMDBASE txkeyJumpFileTop(TX* text)
  3960. {
  3961. // テキストの先頭へジャンプ(ユーザインターフェース)
  3962. // ユーザインターフェースの設定によって動作が変わります
  3963. //{#MS} ^{Home} +^{Home}
  3964.     txkeySelectWin(text);
  3965.     return txJumpFileTop(text);
  3966. }
  3967.  
  3968. int TXCMDBASE txkeyJumpFileEnd(TX* text)
  3969. {
  3970. // テキストの末尾へジャンプ(ユーザインターフェース)
  3971. // ユーザインターフェースの設定によって動作が変わります
  3972. //{#MS} ^{End} +^{End}
  3973.     txkeySelectWin(text);
  3974.     return txJumpFileEnd(text);
  3975. }
  3976.  
  3977. //{###ジャンプ}
  3978.  
  3979. //##タグジャンプ
  3980. //1.97で作り直した
  3981. //1.97 行番号指定なし、検索文字列指定に対応
  3982. //2.92 TX-C化、大改良
  3983.  
  3984. // テキストバッファポインタpから行末まで、存在するファイル名の記述があれば
  3985. // szfilenameに取得してファイル名の末尾の次の文字へのテキストバッファポインタを返す
  3986. // なければNULLを返す
  3987. static mchar* tagjumpGetFilename(mchar* p,mchar szfilename[CCHPATHNAME])
  3988. {
  3989.     mchar path[CCHPATHNAME];
  3990.     
  3991.     if (text->modeTagJump != TAGJUMP_VZ && strmatch(p,"・")) {
  3992.         //2.92 grep形式。高速化のため直ぐに判別
  3993.         p += 2;
  3994.         while(isspace(*p)) p++;
  3995.         if (isdigit(*p)) return NULL;
  3996.     }
  3997.     while(1) {
  3998.         BOOL fdq = FALSE;
  3999.         mchar *top;
  4000.         
  4001.         // get top
  4002.         while(1) {
  4003.             mchar c = *p;
  4004.             
  4005.             if (c == 0x0A || c == 0x1A || c == 0) {
  4006.                 return NULL;
  4007.             } else if (c <= ' ' || c == '(' || c == ')' || c == ':') {
  4008.                 p++;
  4009.             } else {
  4010.                 break;
  4011.             }
  4012.         }
  4013.         top = p;
  4014.         // get tail
  4015.         while(1) {
  4016.             mchar c = *p;
  4017.             
  4018.             if (c == 0x0A || c == 0x1A || c == 0) {
  4019. #if 1//3.00A2 970504 「ファイル名+改行」でもタグジャンプするようにした(従来は「ファイル名+スペース+改行」でタグジャンプした)。
  4020.                 break;
  4021. #else
  4022.                 return NULL;
  4023. #endif
  4024.             } else if (c == '"') {
  4025.                 fdq ^= 1;
  4026.                 p++;
  4027.             } else if (c < ' ' || (c == ' ' && !fdq) || c == '(' || c == ')') {
  4028.                 break;
  4029.             } else if (c == ':' && isdigit(p[1])) {
  4030.                 //2.00E "D:\WZ\TEST.C:256 void function()"の様な"ファイル名:行番号"形式のタグジャンプができなかった
  4031.                 break;
  4032.             } else {
  4033.                 p++;
  4034.             }
  4035.         }
  4036.         if (p > top && p[-1] == ':') p--;//1.00C タグジャンプを「ファイル名: 行番号」に対応させた
  4037.         {
  4038.             IBUFF len = p - top;
  4039.             
  4040.             if (len < CCHPATHNAME) {
  4041.                 strcpylen(szfilename,top,len);
  4042.                 if (text->modeTagJump != TAGJUMP_VZ && iskanji(szfilename[0])) {
  4043.                     //2.92 標準では、漢字はファイル名としては認識しない
  4044.                     break;
  4045.                 }
  4046.                 pathFormLong(szfilename);//1.00H2 タグジャンプのロングファイル名対応
  4047.                 // wzpathAutoは若干時間がかかる
  4048.                 wzpathAuto(szfilename);//1.00F ジャンプ先ファイル名の指定がフルパスでないタグジャンプがうまくいかないことがあった
  4049.                 if (fileIsExist(szfilename)) {
  4050.                     return p;
  4051.                 }
  4052.             }
  4053.         }
  4054.         if (text->modeTagJump != TAGJUMP_VZ) {
  4055.             break;//2.92 
  4056.         }
  4057.     }
  4058.     return NULL;
  4059. }
  4060.  
  4061. static NLINE tagjumpGetNline(mchar* p,int* pLx,mchar szFind[CCHWORD])
  4062. {
  4063.     int a = 0;
  4064.     
  4065.     szFind[0] = 0;
  4066.     while(1) {
  4067.         mchar c = *p;
  4068.         int a0 = a;
  4069.         a = 0;
  4070.         
  4071.         if (c == 0x0A || c == 0) {
  4072.             return 0;
  4073.         } else if (c == '"') {
  4074.             strcpylenmax(szFind,p,strGetWordLen(p),CCHWORD);
  4075.             pathFormLong(szFind);
  4076.             {
  4077.                 mchar* p = strchrs(szFind," \t");
  4078.                 if (p) {
  4079.                     // 空白やタブは検索できない
  4080.                     *p = 0;
  4081.                 }
  4082.             }
  4083.             return 0;
  4084.         } else if (!a0 && isdigit(c)) {
  4085.             IFILE line = 0;
  4086.             IBUFF lch = 0;
  4087.             
  4088.             while(1) {
  4089.                 mchar c = *p;
  4090.                 
  4091.                 if (isdigit(c)) {
  4092.                     line *= 10;
  4093.                     line += c - '0';
  4094.                     p++;
  4095.                 } else {
  4096.                     break;
  4097.                 }
  4098.             }
  4099.             if (*p == ',') {
  4100.                 lch = atoi(p + 1);
  4101.             }
  4102.             if (pLx) *pLx = lch;
  4103.             return line;
  4104.         } else if (iskanji(c)) {
  4105.             p += 2;
  4106.         } else {
  4107.             if (isalpha(c)) {
  4108.                 a = 1;
  4109.             }
  4110.             p++;
  4111.         }
  4112.     }
  4113. }
  4114.  
  4115. BOOL TXAPI txJumpTagExec(TX* text,mchar* szfilename,NPARA nline,int lx,mchar* szFind)
  4116. {
  4117. // npara == 0            指定なし
  4118. // lx < 0                指定なし
  4119. // !szFind||!szFind[0]    指定なし
  4120. #if 1//2.94 970121 
  4121.     mchar sw[30];
  4122.     if (szFind && szFind[0]) {
  4123.         sprintf(sw,"/s%s",szFind);
  4124.         forkstd(szfilename,sw);
  4125.     } else if (nline) {
  4126.     #if 1//2.99D 970330 sw
  4127.         if (lx >= 0) {
  4128.             sprintf(sw,"/k /J%ld,%d /Yc",nline,lx);
  4129.         } else {
  4130.             //3.00B1 970519 lx < 0に対応してなかった
  4131.             sprintf(sw,"/k /J%ld /Yc",nline);
  4132.         }
  4133.     #else
  4134.         if (lx >= 0) sprintf(sw,"/P /J%ld,%d /Yc",nline,lx);
  4135.     #endif
  4136. //information("%s",sw);
  4137.         forkstd(szfilename,sw);
  4138.     } else {
  4139.         forkstd(szfilename,NULL);
  4140.     }
  4141.     return TRUE;
  4142. #else
  4143.     HWND hwnd = isopen(szfilename);
  4144.     if (hwnd) {
  4145.         if (szFind && szFind[0]) {
  4146.             if (nline) SendMessageOther(hwnd,WM_TXJUMPPARA,0,nline);
  4147.             {
  4148.                 REPLACEARGEX arg;
  4149.                 structClear(arg);
  4150.                 arg.searchmode = SEARCH_CUR;
  4151.                 strcpy(arg.szFind,szFind);
  4152.                 wndtxSendMem(hwnd,WM_TXSEARCHEX,0,&arg,sizeof(arg));
  4153.             }
  4154.         } else if (nline) {
  4155.             SendMessageOther(hwnd,WM_TXJUMPPARA,0,nline);
  4156.             wndtxCall(hwnd,"txJumpParaTop");
  4157.             if (lx >= 0) SendMessageOther(hwnd,WM_TXRIGHTBYTES,lx,0);
  4158.             wndtxCall(hwnd,"txSetLyCenter");
  4159.         } else {
  4160.             wndtxSetActive(hwnd);
  4161.         }
  4162.     } else {
  4163.         mchar sw[30];
  4164.         if (szFind && szFind[0]) {
  4165.             sprintf(sw,"--s%s",szFind);
  4166.             forkstd(szfilename,sw);
  4167.         } else if (nline) {
  4168.     #if 1//2.99D 970330 sw
  4169.             if (lx >= 0) sprintf(sw,"/k --J%ld,%d --Yc",nline,lx);
  4170.     #else
  4171.             if (lx >= 0) sprintf(sw,"--P --J%ld,%d --Yc",nline,lx);
  4172.     #endif
  4173.             forkstd(szfilename,sw);
  4174.         } else {
  4175.             forkstd(szfilename,NULL);
  4176.         }
  4177.     }
  4178.     return TRUE;
  4179. #endif
  4180. }
  4181.  
  4182. void tagjumpreturnAdd(mchar* szfilename,IFILE adr);
  4183.  
  4184. BOOL TXAPI TXCMDBASE txJumpTagEx(tx *text)
  4185. {
  4186. // タグジャンプ
  4187. //{#VZ} +{F10}
  4188. //{#MI} {F10}
  4189. //{#EMACS} +{F10}
  4190.     if (txJumpLink(text)) return TRUE;//2.99 970320 タグジャンプでリンクのジャンプができなかった
  4191.     tagjumpreturnAdd(text->szfilename,txGetAddress(text));//3.00B1 970612 「タグジャンプから戻る」対応
  4192.     mchar szfilename[CCHPATHNAME];
  4193.     txstr szpara(CCHLINE*4);
  4194.     txGetPara(text,szpara);
  4195.     {
  4196.         mchar* p = szpara;
  4197.         p = tagjumpGetFilename(p,szfilename);
  4198.         if (!p) {
  4199.             //2.92 grep結果のタグジャンプ及び"ファイル名"へのジャンプを標準タグジャンプでサポート
  4200.             if (call("grep.Jump")) return TRUE;
  4201.             return txJumpURL(text);
  4202.         }
  4203.         {
  4204.             mchar szFind[CCHWORD];
  4205.             int lx = -1;
  4206.             NLINE nline = tagjumpGetNline(p,&lx,szFind);
  4207.             return txJumpTagExec(text,szfilename,nline,lx,szFind);
  4208.         }
  4209.     }
  4210.     return FALSE;
  4211. }
  4212.  
  4213. //{###ファイル}
  4214.  
  4215. //##その他
  4216.  
  4217. //2.98 970305 「検索|次画面と検索を開始」を追加
  4218. BOOL TXCMDBASE textCmpStart(TX* text)
  4219. {
  4220. // ファイルの比較を開始。
  4221. // 両画面の先頭にジャンプし、比較を開始する。
  4222. //2.98 970305 new
  4223.     if (text->text2) {
  4224.         txJumpFileTop(text->text2);
  4225.     } else {
  4226.         HWND next = wndtxGetNextEditor();
  4227.         if (next) wndtxCall(next,"txJumpFileTop");
  4228.     }
  4229.     txJumpFileTop(text);
  4230.     txCmp(text);
  4231.     return TRUE;
  4232. }
  4233.  
  4234. //{###ジャンプ}
  4235.  
  4236. //3.00B1 970612 「ダイナミックタグジャンプ」を製品に標準装備
  4237.  
  4238. //970519 1.0 start
  4239. //970612 1.1 WZ3.00B 標準装備
  4240.  
  4241. #define SZTITLE    "ダイナミックタグジャンプ"
  4242.  
  4243. #include "_filer.h"
  4244.  
  4245. //## Abort Window
  4246.  
  4247. #define IDD_SEARCHINFO        100
  4248.  
  4249. static BOOL _fUserAbort;
  4250. static HWND _hwndAbort;
  4251.  
  4252. static BOOL abortProc(void)
  4253. {
  4254.     MSG msg;
  4255.     while(!_fUserAbort && _hwndAbort && PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  4256.         if (!IsDialogMessage(_hwndAbort,&msg)) {
  4257.             TranslateMessage(&msg);
  4258.             DispatchMessage(&msg);
  4259.         }
  4260.     }
  4261.     return !_fUserAbort;
  4262. }
  4263.  
  4264. BOOL dlgprocAbort(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  4265. {
  4266.     switch(message) {
  4267.         case WM_INITDIALOG: {
  4268.             _fUserAbort = FALSE;
  4269.             break;
  4270.         }
  4271.         case WM_COMMAND: {
  4272.             if (LOWORD(wParam) == IDCANCEL) {
  4273.                 _fUserAbort = TRUE;
  4274.                 return TRUE;
  4275.             }
  4276.             break;
  4277.         }
  4278.     }
  4279.     return FALSE;
  4280. }
  4281.  
  4282. static void abortNew(HDIALOG hd)
  4283. {
  4284.     if (!_hwndAbort) {
  4285.         _hwndAbort = dialogCreate(hd);
  4286.     }
  4287.     _fUserAbort = FALSE;
  4288. }
  4289.  
  4290. static void abortDelete(void)
  4291. {
  4292.     if (_hwndAbort) {
  4293.         dialogFree(_hwndAbort);
  4294.         _hwndAbort = NULL;
  4295.     }
  4296. }
  4297.  
  4298. //## 汎用関数
  4299.  
  4300. static int _txInsertWithQuote(TX* text,mchar* szInsert)
  4301. {
  4302.     int ret;
  4303.     txInsertChar(text,'"');
  4304.     ret = txInsert(text,szInsert);
  4305.     txInsertChar(text,'"');
  4306.     return ret;
  4307. }
  4308.  
  4309. static int _txInsertInt(TX* text,long data)
  4310. {
  4311.     mchar buff[20];
  4312.     sprintf(buff,"%ld",data);
  4313.     return txInsert(text,buff);
  4314. }
  4315.  
  4316. static void _txLimitNpara(TX* text,NPARA nparaMax,NPARA nparaNew)
  4317. {
  4318.     txJumpFileEnd(text);
  4319.     if (text->npara > nparaMax) {
  4320.         // overflow : delete old entry
  4321.         txJumpNpara(text,nparaNew);
  4322.         txSelectEx(text,CLIP_CHAR);
  4323.         txJumpFileEnd(text);
  4324.         txSelectDelete(text);
  4325.     }
  4326. }
  4327.  
  4328. //## タグジャンプから戻る
  4329.  
  4330. static TX* tagjumpreturnOpen(void)
  4331. {
  4332.     mchar szfilename[CCHPATHNAME];
  4333.     pathFullConfig(szfilename,"tagjmpre.dic");
  4334.     return textopen(szfilename);
  4335. }
  4336.  
  4337. void tagjumpreturnAdd(mchar* szfilename,IFILE adr)
  4338. {
  4339.     TX* text = tagjumpreturnOpen();
  4340.     if (text) {
  4341.         _txInsertWithQuote(text,szfilename);
  4342.         txInsertChar(text,' ');
  4343.         _txInsertInt(text,adr);
  4344.         txInsertReturn(text);
  4345.         //
  4346.         _txLimitNpara(text,20,16);
  4347.         //
  4348.         txSave(text);
  4349.     }
  4350.     textclose(text);
  4351. }
  4352.  
  4353. tagjumpreturn
  4354. {
  4355. // ダイナミックタグジャンプから戻る
  4356.     TX* text = tagjumpreturnOpen();
  4357.     if (text) {
  4358.         txstr szline;
  4359.         txGetPara(text,szline);
  4360.         mchar* p = strGetWordTop(szline);
  4361.         int len = strGetWordLen(p);
  4362.         if (len) {
  4363.             mchar szfilename[CCHPATHNAME];
  4364.             sstrcpylen(szfilename,p,len);
  4365.             pathFormLong(szfilename);
  4366.             //
  4367.             p += len;
  4368.             p = strGetWordTop(p);
  4369.             IFILE adr = atoi(p);
  4370.             //
  4371.             mchar sw[30];
  4372.             sprintf(sw,"/k /Ja%ld /Yc",adr);
  4373.             forkstd(szfilename,sw);
  4374.             //
  4375.             txDeletePara(text);
  4376.             txSave(text);
  4377.         }
  4378.     }
  4379.     textclose(text);
  4380. }
  4381.  
  4382. //## Dynamic Tag Jump
  4383.  
  4384. static mchar _szTitleCfuncRe[] = "^[A-Za-z_][^/]*[^;]$";
  4385. typedef struct {
  4386.     TX* cache;
  4387.     mchar szfind[CCHWORD];
  4388.     // cache match
  4389.     NPARA nparaCache;
  4390. } FJCONTEXT;
  4391.  
  4392. permanent BOOL p_fSearchSubDirectory = FALSE;
  4393. permanent txstr p_szmask = "*.c;*.cpp;*.h;*.hpp";
  4394.  
  4395. static void cacheAdd(FJCONTEXT* context,mchar* szfind,mchar* szfilename,NPARA npara)
  4396. {
  4397.     TX* text = context->cache;
  4398.     txJumpFileTop(text);
  4399.     txInsertChar(text,'"');txInsert(text,szfilename);txInsert(text,"\" ");
  4400.     txInsertf(text,"%ld ",npara);
  4401.     txInsertChar(text,'"');txInsert(text,szfind);txInsertChar(text,'"');
  4402.     txInsertReturn(text);
  4403. }
  4404.  
  4405. #define SEARCHFILE_CACHEMATCH    1    // context->szfindがcontext->nparaCacheにあるか調べる
  4406. #define SEARCHFILE_CACHEFLUSH    2    // context->szfindがszfilenameの何行にあるかをcontext->nparaCacheに返す
  4407. #define SEARCHFILE_STATIC        3    // context->szfindがtextの何行にあるかをcontext->nparaCacheに返す
  4408.  
  4409. static int searchtext(TX* text,FJCONTEXT* context,int mode)
  4410. {
  4411.     int nFind = 0;
  4412.     //
  4413.     txstr szline;
  4414.     if (_hwndAbort) {
  4415.         SetDlgItemText(_hwndAbort,IDD_SEARCHINFO,pathGetFileName(text->szfilename));
  4416.     }
  4417.     if (mode == SEARCHFILE_CACHEMATCH) {
  4418.         txJumpNpara(text,context->nparaCache);
  4419.     }
  4420.     //
  4421.     for(int i = 0;i < 2;i++) {
  4422.         IFILE adr0 = -1;
  4423.         SEARCHMODE searchmode = 0;
  4424.         searchmode |= SEARCH_CUR;        // 最初は、カーソル位置(ファイル先頭)から検索
  4425.         while(1) {
  4426.             if (!abortProc()) break;
  4427.             int find = 0;
  4428.             if (i == 0) {
  4429.                 find = txSearchEx(text,_szTitleCfuncRe,searchmode|SEARCH_RE);
  4430.             } else {
  4431.                 find = txSearchEx(text,"^[\t ]*#[\t ]*define[\t ]+[A-Za-z_0-9]+[\t ]*(",searchmode|SEARCH_RE);
  4432.             }
  4433.             if (find) {
  4434.                 {// 無限に同じ所にマッチしないように
  4435.                     IFILE adr = txGetAddress(text);
  4436.                     if (adr == adr0) break;
  4437.                     adr0 = adr;
  4438.                 }
  4439.                 searchmode &= ~SEARCH_CUR;        // 次からは、カーソル位置の次の文字から検索
  4440.                 //
  4441.                 txGetPara(text,szline);
  4442.                 if (mode) {
  4443.                     // context->szfindとマッチするか調べる
  4444.                     mchar* p = stristr(szline,context->szfind);
  4445.                     if (p) {
  4446.                         mchar* pp = strprev(szline,p);
  4447.                         if (!isalpha(*pp)) {
  4448.                             mchar* pn = p + strlen(context->szfind);
  4449.                             if (!isalnum(*pn)) {
  4450.                                 if (mode == SEARCHFILE_STATIC) {
  4451.                                     context->nparaCache = text->npara;
  4452.                                     nFind++;
  4453.                                     break;
  4454.                                 } else if (mode == SEARCHFILE_CACHEMATCH) {
  4455.                                     if (text->npara == context->nparaCache) {
  4456.                                         nFind++;
  4457.                                         cacheAdd(context,context->szfind,text->szfilename,text->npara);
  4458.                                     }
  4459.                                     break;
  4460.                                 } else {
  4461.                                     context->nparaCache = text->npara;
  4462.                                     cacheAdd(context,context->szfind,text->szfilename,text->npara);
  4463.                                     nFind++;
  4464.                                     break;
  4465.                                 }
  4466. //                            findAdd(context,text->szfilename,text->npara,szline);
  4467. //information("%s %d : %s",szfilename,text->npara,szline);
  4468.                             }
  4469.                         }
  4470.                     }
  4471.                 } else {
  4472.                     // 関数定義を抜き出してデータを作成する
  4473.                     if (stristrword(szline,"static")) {
  4474.                         // static関数は含めない
  4475.                     } else {
  4476.                         mchar* p;
  4477.                         if (p = reSearch(szline,"[A-Za-z_][A-Za-z_0-9]* *([^/]*)",0)) {// "func(arg)"だけでなく"func (arg)"にも対応
  4478.                             int lch = strchr(p,'(') - p;
  4479.                             mchar szfunc[CCHWORD];
  4480.                             sstrcpylen(szfunc,p,lch);
  4481.                             // del tail space
  4482.                             lch = strGetWordLen(szfunc);
  4483.                             szfunc[lch] = 0;
  4484.                             //
  4485.                             cacheAdd(context,szfunc,text->szfilename,text->npara);
  4486.                             nFind++;
  4487.                         }
  4488. //printf("%s\n",szfunc);
  4489.                     }
  4490.                 }
  4491.             } else {
  4492.                 break;
  4493.             }
  4494.         }
  4495.     }
  4496.     return nFind;
  4497. }
  4498.  
  4499. static int searchfile(mchar *szfilename,mchar *szfind,FJCONTEXT* context,int mode)
  4500. {
  4501.     int nFind = 0;
  4502.     // cache flush
  4503.     // szfilenameと同じファイル名のファイルを除く
  4504.     if (mode == 0) {
  4505.         TX* text = context->cache;
  4506.         txJumpFileTop(text);
  4507.         //
  4508.         txstr szfind = "\"";
  4509.         szfind += szfilename;
  4510.         szfind += "\" ";
  4511.         //
  4512.         SEARCHMODE searchmode = SEARCH_PARATOP|SEARCH_NOSENSECASE|SEARCH_NOESC|SEARCH_CUR;
  4513.         while(1) {
  4514.             if (txSearchEx(text,szfind,searchmode)) {
  4515.                 txDeletePara(text);
  4516.                 txJumpParaTop(text);
  4517.             } else {
  4518.                 break;
  4519.             }
  4520.         }
  4521.     }
  4522.     // skip backup file
  4523.     {
  4524.         mchar* sz = pathGetFileName(szfilename);
  4525.         if (sz[0] == '$' && sz[1] == '~') return 0;
  4526.         sz = pathGetExt(szfilename);
  4527.         if (sz[0] == '~') return 0;
  4528.     }
  4529.     //
  4530.     TX textBody;
  4531.     TX* text = &textBody;
  4532.     txInitText(text);
  4533.     txSetFileName(text,szfilename);
  4534.     if (txIsBinary(text)) return 0;    // 開く前にファイル名でチェック
  4535.     text->fSilent = TRUE;            // 不要なattentionを出さない
  4536.     text->fLineD = FALSE;            // 論理行モード
  4537.     text->fViewMode = TRUE;
  4538.     text->fNoCursor = TRUE;
  4539.     text->fKcAuto = text->share->config.fKcAuto;
  4540.     txOpenText(text);
  4541.     //
  4542.     if (!txIsBinary(text)) {
  4543.         nFind = searchtext(text,context,mode);
  4544.     }
  4545.     txClose(text);
  4546.     return nFind;
  4547. }
  4548.  
  4549. static void searchpath(mchar *szpath,mchar *szfind,SEARCHMODE searchmode,FJCONTEXT* context)
  4550. {
  4551.     #ifdef __FLAT__
  4552.     WIN32_FIND_DATA ffd;
  4553.     #else
  4554.     FILEFIND filefind;
  4555.     #endif
  4556.     mchar szfilename[CCHPATHNAME];
  4557.     
  4558.     // 通常ファイル
  4559.     strcpy(szfilename,szpath);
  4560.     #ifdef __FLAT__
  4561.     {
  4562.         HANDLE hfind = FindFirstFile(szpath,&ffd);
  4563.         if (hfind != INVALID_HANDLE_VALUE) {
  4564.             do {
  4565.                 if (!abortProc()) break;
  4566.                 if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue;
  4567.                 pathSetFileName(szfilename,ffd.cFileName);
  4568.                 searchfile(szfilename,szfind,context,0);
  4569.             } while(FindNextFile(hfind,&ffd));
  4570.             FindClose(hfind);
  4571.         }
  4572.     }
  4573.     #else
  4574.     if (!fileFindFirst(szpath,FA_NORMAL,&filefind)) {
  4575.         do {
  4576.             if (!abortProc()) break;
  4577.             pathSetFileName(szfilename,filefind.name);
  4578.             searchfile(szfilename,szfind,context,0);
  4579.         } while (!fileFindNext(&filefind));
  4580.     }
  4581.     #endif
  4582.     // サブディレクトリ
  4583.     if (searchmode & GREP_DIRECTORY) {
  4584.         strcpy(szfilename,szpath);
  4585.         pathSetFileName(szfilename,"*.*");
  4586.         #ifdef __FLAT__
  4587.             {
  4588.                 HANDLE hfind = FindFirstFile(szfilename,&ffd);
  4589.                 if (hfind != INVALID_HANDLE_VALUE) {
  4590.                     do {
  4591.                         if (!abortProc()) break;
  4592.                         if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  4593.                             if (ffd.cFileName[0] != '.') {
  4594.                                 txstr szsubpath(CCHPATHNAME);
  4595.                                 szsubpath = szpath;
  4596.                                 pathSetFileName(szsubpath,ffd.cFileName + "\\" + pathGetFileName(szsubpath));
  4597. //                                information("[%s]",szsubpath);
  4598.                                 searchpath(szsubpath,szfind,searchmode,context);
  4599.                             }
  4600.                         }
  4601.                     } while(FindNextFile(hfind,&ffd));
  4602.                     FindClose(hfind);
  4603.                 }
  4604.             }
  4605.         #else
  4606.         if (!fileFindFirst(szfilename,FA_DIREC,&filefind)) {
  4607.             do {
  4608.                 if (!abortProc()) break;
  4609.                 if (filefind.attrib & FA_DIREC) {
  4610.                     if (filefind.name[0] != '.') {
  4611.                         txstr szsubpath(CCHPATHNAME);
  4612.                         szsubpath = szpath;
  4613.                         pathSetFileName(szsubpath,filefind.name + "\\" + pathGetFileName(szsubpath));
  4614. //                        information("[%s]",szsubpath);
  4615.                         searchpath(szsubpath,szfind,searchmode,context);
  4616.                     }
  4617.                 }
  4618.             } while (!fileFindNext(&filefind));
  4619.         }
  4620.         #endif
  4621.     }
  4622. }
  4623.  
  4624. static void dtagjumpDelete(FJCONTEXT* context)
  4625. {
  4626. // destructor
  4627.     abortDelete();
  4628.     if (context->cache) {
  4629.         TX* text = context->cache;
  4630.         if (text->fEdit) txSave(text);
  4631.         textclose(text);
  4632.         context->cache = NULL;
  4633.     }
  4634. }
  4635.  
  4636. static BOOL dtagjumpExec(FJCONTEXT* context,txstr szline)
  4637. {
  4638.     TX* text = context->cache;
  4639.     mchar szfilename[CCHPATHNAME];
  4640.     mchar* p = szline;
  4641.     int len;
  4642.     p = strGetWordTop(p);
  4643.     len = strGetWordLen(p);
  4644.     sstrcpylen(szfilename,p,len);
  4645.     p += len;p = strGetWordTop(p);
  4646.     NPARA npara = atoi(p);
  4647.     pathFormLong(szfilename);
  4648. //information("%s %d",szfilename,npara);
  4649.     // check cache
  4650.     txDeletePara(text);// delete cache entry
  4651.     //
  4652.     context->nparaCache = npara;
  4653.     if (searchfile(szfilename,context->szfind,context,SEARCHFILE_CACHEMATCH)) {
  4654.         // OK
  4655.     } else {
  4656.         // Cacheミス
  4657.         if (searchfile(szfilename,context->szfind,context,SEARCHFILE_CACHEFLUSH)) {
  4658.             // ファイル内での位置が変わっただけ
  4659.             npara = context->nparaCache;
  4660.         } else {
  4661.             // 別ファイルへ移動した
  4662.             return FALSE;
  4663.         }
  4664.     }
  4665.     // jump
  4666.     tagjumpreturnAdd(textf->szfilename,txGetAddress(textf));
  4667.     mchar sw[30];
  4668.     sprintf(sw,"/k /J%ld /Yc",npara);
  4669.     forkstd(szfilename,sw);
  4670.     return TRUE;
  4671. }
  4672.  
  4673. static int dtagjumpCache(FJCONTEXT* context)
  4674. {
  4675.     BOOL ret = IDNO;
  4676.     txstr sz = " \"";
  4677.     sz += context->szfind;
  4678.     sz += "\"";
  4679. //information("[%s]",sz);
  4680.     TX* text = textopen(NULL);
  4681.     if (text) {
  4682.         txstr szline(CCHPATHNAME + 100);
  4683.         int nFind = 0;
  4684.         txJumpFileTop(context->cache);
  4685.         while(1) {
  4686.             if (txSearchEx(context->cache,sz,0)) {
  4687.                 txGetPara(context->cache,szline);
  4688.                 txInsert(text,szline);txInsertReturn(text);
  4689.                 nFind++;
  4690.             } else {
  4691.                 break;
  4692.             }
  4693.         }
  4694.         if (nFind) {
  4695.             if (nFind == 1) {
  4696.                 if (dtagjumpExec(context,szline)) {
  4697.                     ret = IDOK;
  4698.                 }
  4699.             } else {
  4700.                 HDIALOG hd = dialog(SZTITLE + " - ジャンプ先選択");
  4701.                 txJumpFileTop(text);
  4702.                 dialogList(hd,NULL,text,60,10);
  4703.                 if (dialogOpen(hd)) {
  4704.                     txGetPara(text,szline);
  4705.                     //
  4706.                     int n = text->npara;
  4707.                     txJumpFileTop(context->cache);
  4708.                     while(n--) {
  4709.                         if (!txSearchEx(context->cache,sz,0)) {
  4710.                             break;
  4711.                         }
  4712.                     }
  4713.                     //
  4714.                     if (dtagjumpExec(context,szline)) {
  4715.                         ret = IDOK;
  4716.                     }
  4717.                 } else {
  4718.                     ret = IDCANCEL;
  4719.                 }
  4720.             }
  4721.         }
  4722.     }
  4723.     textclose(text);
  4724.     return ret;
  4725. }
  4726.  
  4727. // "a:\wz\*.c;*.cpp"対応
  4728. static void searchpathMultiMask(FJCONTEXT* context,mchar* _szpath)
  4729. {
  4730.     mchar szpath[CCHPATHNAME];
  4731.     mchar *szfile = pathGetFileName(_szpath);
  4732.     strcpy(szpath,_szpath);
  4733.     while(1) {
  4734.         mchar *p;
  4735.         if (p = strchr(szfile,';')) {
  4736.             *p = 0;
  4737.         }
  4738.         pathSetFileName(szpath,szfile);
  4739.         searchpath(szpath,"",p_fSearchSubDirectory ? GREP_DIRECTORY : 0,context);
  4740.         if (p) {
  4741.             *p = ';';
  4742.             szfile = p + 1;
  4743.         } else {
  4744.             break;
  4745.         }
  4746.     }
  4747. }
  4748.  
  4749. static BOOL dtagjumpSearch(FJCONTEXT* context)
  4750. {
  4751.     HDIALOG hd = dialog(SZTITLE + " - 検索");
  4752.     txstr szpath = text->szfilename;
  4753.     pathForm(szpath);
  4754.     dialogControlHelp(hd,240);
  4755.     dialogControlRefer(hd,"-d *.*");
  4756.     dialogStr(hd,"検索フォルダ(&F):",szpath,14,37);
  4757.     //
  4758.     dialogStr(hd,"検索マスク(&M):",p_szmask,14,16);
  4759.     //
  4760.     dialogCheck(hd,"サブフォルダも検索(&U)",&p_fSearchSubDirectory);
  4761.     //
  4762.     if (dialogOpen(hd)) {
  4763.         HDIALOG hd = dialog(SZTITLE + " - 検索中");
  4764.         dialogSetHookEx(hd,"\m.dlgprocAbort");
  4765.         dialogControlStyle(hd,WS_CHILD|WS_VISIBLE|SS_CENTER);
  4766.         dialogControlID(hd,IDD_SEARCHINFO);
  4767.         dialogCaptionDynamic(hd,"",30);
  4768.         dialogControlStyle(hd,0);
  4769.         dialogSetPosLX(hd,10);
  4770.         dialogCancel(hd,10);
  4771.         abortNew(hd);
  4772.         //
  4773.         pathSetDir(szpath);
  4774.         szpath += p_szmask;
  4775.         searchpathMultiMask(context,szpath);
  4776.         //
  4777.         abortDelete();
  4778.         return TRUE;
  4779.     }
  4780.     return FALSE;
  4781. }
  4782.  
  4783. dtagjump
  4784. {
  4785. // ダイナミックタグジャンプ
  4786. // C言語の関数定義部、マクロ関数定義部へダイレクトにジャンプすることができます。
  4787. // 関数定義を参照したい関数名にカーソルを合わせてこのコマンドを実行するとジャンプします。
  4788. // 同一ファイル内でも別ファイルでもジャンプできます。
  4789. // みつからない場合は検索ダイアログが出ますので検索してください。
  4790. // 関数定義部分が移動しても自動的に追随します。
  4791. // #defineによるマクロ関数定義にもジャンプできます。
  4792.     FJCONTEXT contextBody;
  4793.     structClear(contextBody);
  4794.     FJCONTEXT* context = &contextBody;
  4795.     // get find function name
  4796.     {
  4797.         txstr szfind;
  4798.         txGetWordWhole(text,szfind);
  4799.         sstrcpy(context->szfind,szfind);
  4800. //        information(context->szfind);
  4801.     }
  4802.     // cache
  4803.     {
  4804.         mchar szfilename[CCHPATHNAME];
  4805.         pathFullConfig(szfilename,"dtgcache.dic");
  4806.         context->cache = textopen(szfilename);
  4807.         if (!context->cache) {
  4808.             dtagjumpDelete(context);
  4809.             return FALSE;
  4810.         }
  4811.     }
  4812.     if (dtagjumpCache(context) != IDNO) {
  4813.         dtagjumpDelete(context);
  4814.         return TRUE;
  4815.     }
  4816.     // static function
  4817.     {
  4818.         IFILE adr = txGetAddress(text);
  4819.         txSetUndispEx(text);
  4820.         txJumpFileTop(text);
  4821.         if (searchtext(text,context,SEARCHFILE_STATIC)) {
  4822.             tagjumpreturnAdd(text->szfilename,adr);
  4823.             txJumpNpara(text,context->nparaCache);
  4824.             txSetDisp(text);
  4825.             dtagjumpDelete(context);
  4826.             return TRUE;
  4827.         } else {
  4828.             txSetDispEx(text);
  4829.         }
  4830.     }
  4831.     //
  4832.     {
  4833.         int q = question("関数定義 %s は見つかりませんでした\n検索しますか?",context->szfind);
  4834.         if (q != IDYES) {
  4835.             dtagjumpDelete(context);
  4836.             return FALSE;
  4837.         }
  4838.     }
  4839.     //
  4840.     if (dtagjumpSearch(context)) {
  4841.         if (dtagjumpCache(context) == IDNO) {
  4842.             information("関数定義 %s は見つかりませんでした",context->szfind);
  4843.         }
  4844.     }
  4845.     // destruct
  4846.     dtagjumpDelete(context);
  4847.     return TRUE;
  4848. }
  4849.  
  4850. void testFunction(void)
  4851. {
  4852. }
  4853.  
  4854. //    testFunction();
  4855.  
  4856.