home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1998 August / VPR9808B.BIN / APUPDATE / VC / Tx300d / TX300D.LZH / HTML.C < prev    next >
C/C++ Source or Header  |  1997-06-12  |  85KB  |  3,190 lines

  1. // HTML support
  2. // (c)1997 TY
  3. // 970219 start
  4.  
  5. //2.99D 970331 TXCMDBASE対応
  6.  
  7. #include <windows.h>
  8. #include <windowsx.h>
  9. #include "dialog.h"
  10. #include "outline.h"
  11.  
  12. //{###HTML}
  13. //HTMLファイル専用の編集機能を提供します。
  14.  
  15. static BOOL htmlFlushCurTag(TX* text);
  16. static BOOL txHtmlFlushArea(TX* textTarget,IFILE adrTop,IFILE adrEnd,int tag,BOOL fSelect);
  17.  
  18. //## tag base op.
  19.  
  20. int TXAPI tagFromStr(mchar* p)
  21. {
  22.     return txOp(text,TXOP_TAGFROMSTR,(WPARAM)p,0);
  23. }
  24.  
  25. mchar* TXAPI tagToStr(int tag)
  26. {
  27.     return (mchar*)txOp(text,TXOP_TAGTOSTR,tag,0);
  28. }
  29.  
  30. mchar* TXAPI tagPrint(mchar* dst,int tag)
  31. {
  32.     *dst++ = '<';
  33.     strcpy(dst,tagToStr(tag));dst += strlen(dst);
  34.     return dst;
  35. }
  36.  
  37. mchar* TXAPI tagPrintEx(tx* text,int tag,long atr,int tagmode,mchar *buff)
  38. {
  39.     BOOL fColor = FALSE;
  40.     static mchar szNull[] = "";
  41.     if (tag == TAG_H) {
  42.         if (1 <= atr && atr <= 6) {
  43.             mchar* dst = buff;
  44.             *dst++ = '<';
  45.             if (tagmode == TAG_END) *dst++ = '/';
  46.             *dst++ = 'H';
  47.             *dst++ = atr + '0';
  48.             *dst++ = '>';
  49.             *dst = 0;
  50.             return buff;
  51.         }
  52.     }
  53.     if (1 <= tag && tag < TAG_N) {
  54.         mchar* dst = buff;
  55.         *dst++ = '<';
  56.         if (tagmode == TAG_END) {
  57.             *dst++ = '/';
  58.         }
  59.         strcpy(dst,tagToStr(tag));dst += strlen(dst);
  60.         *dst++ = '>';
  61.         *dst = 0;
  62.         return buff;
  63.     }
  64.     return "";
  65. }
  66.  
  67. BOOL TXAPI tagIsParaatr(int tag)
  68. {
  69.     switch(tag) {
  70.         case TAG_P:
  71.         case TAG_H:
  72.         case TAG_UL:
  73. //        case TAG_PRE:
  74.         case TAG_OL:
  75.         case TAG_DL:
  76.         case TAG_BLOCKQUOTE:
  77.         case TAG_LEFT:
  78.         case TAG_CENTER:
  79.         case TAG_RIGHT: return TRUE;
  80.     }
  81.     return FALSE;
  82. }
  83.  
  84. //##tag atr
  85. // 以下、タグの直後に置く
  86. // [説明].説明
  87. // [S]....シングルタグ
  88. // [NN]...Netscape専用
  89. // [IE]...IE専用
  90. // [!IE]...IEではだめ
  91. // 以下、タグの直前に置く
  92. // [I]....タグ挿入専用
  93. // [R]....タグのプロパティ専用
  94. //2.99E 970403 アトリビュート毎にIE,NNを区別することはまだできていない、今後対応する予定
  95. // とりあえず、対応していないブラウザでもアトリビュートは指定できるようにした。
  96. static mchar* _tszfh[] = {
  97. ".見出し",
  98.     "H1 [見出し1] ALIGN=<LEFT|CENTER|RIGHT>",
  99.     "H2 [見出し2] ALIGN=<LEFT|CENTER|RIGHT>",
  100.     "H3 [見出し3] ALIGN=<LEFT|CENTER|RIGHT>",
  101.     "H4 [見出し4] ALIGN=<LEFT|CENTER|RIGHT>",
  102.     "H5 [見出し5] ALIGN=<LEFT|CENTER|RIGHT>",
  103.     "H6 [見出し6] ALIGN=<LEFT|CENTER|RIGHT>",
  104. ".段落体裁",
  105.     "DIV [複数の段落を揃える] ALIGN=<LEFT|RIGHT|CENTER|JUSTIFY>",
  106.     "PRE [テキストをそのまま表示] WIDTH=<VALUE>",
  107.     "P [段落を揃える] ALIGN=<LEFT|CENTER|RIGHT>",
  108.     "[I] P [段落を作る] [S]",
  109.     "BR [改行する] [S] CLEAR=<LEFT|RIGHT|ALL>",
  110.     "NOBR [改行しない]",//2.99C 970326 シングルタグではない
  111.     "WBR [改行のヒント] [S]",
  112.     "BLOCKQUOTE [引用]",
  113.     "CENTER [中央揃え]",
  114.     "MULTICOL [段組] [NN] COLS=<VALUE> GUTTER=<VALUE> WIDTH=<VALUE>",
  115.     "SPACER [スペースを空ける] [S] [NN] TYPE=<horizontal|vertical|block> SIZE=<VALUE> WIDTH=<VALUE> HEIGHT=<VALUE> ALIGN=<top|middle|bottom|left|right>",//NN //2.99C 970326 align修正
  116. ".水平線",
  117.     "HR [水平線] [S] ALIGN=<LEFT|RIGHT|CENTER> SIZE=<VALUE> WIDTH=<VALUE_PERCENT> NOSHADE COLOR=<COLOR>",    ////2.99E 970403 COLORはIEのみとする予定
  118. ".文字装飾",
  119.     "BIG [大きい文字]",
  120.     "SMALL [小さい文字]",
  121.     "FONT [文字のサイズと色] SIZE=<7|6|5|4|3|2|1|+4|+3|+2|+1|-1|-2|-3|-4> COLOR=<COLOR>",// "FACE=<STR>",// FACE:NN
  122.     "BASEFONT [文字のサイズの基準] [S] SIZE=<7|6|5|4|3|2|1>",
  123.     "B [太字]",
  124.     "I [斜線]",
  125.     "EM [強調]",
  126.     "STRONG [最強調]",
  127.     "TT [タイプライタ書体]",
  128.     "CITE [引用書体]",
  129.     "CODE [プログラムコード書体]",
  130.     "DFN [定義書体]",
  131.     "KBD [キーボード書体]",
  132.     "SAMP [サンプル書体]",
  133.     "U [下線]",
  134.     "S [打ち消し線]",
  135.     "STRIKE [打ち消し線]",//2.99C 970326 new
  136.     "VAR [変数名を表現する書体]",
  137.     "ADDRESS [アドレスを表現する書体]",
  138.     "BLINK [文字を点滅] [NN]",
  139.     "SUP [上つき]",
  140.     "SUB [下つき]",
  141.     "MARQUEE [文字のスクロール] [IE] DIRECTION=<LEFT|RIGHT> BEHAVIOR=<SCROLL|SLIDE|ALTERNATE> LOOP=<VALUE_LOOP> SCROLLAMOUNT=<VALUE> SCROLLDELAY=<VALUE> BGCOLOR=<COLOR> WIDTH=<VALUE> HEIGHT=<VALUE> ALIGN=<TOP|MIDDLE|BOTTOM> HSPACE=<VALUE> VSPACE=<VALUE>",
  142. ".リンク",
  143.     "A [リンク] HREF=<URL> TARGET=<STR:_self|_blank|_parent|_top|title|main|contents> NAME=<STR>",//2.99C 970325 INPUT_STRWITHSEL化
  144.     "BASE [基準URLを指定] [S] HREF=<URL> TARGET=<STR:_self|_blank|_parent|_top|title|main|contents>",//2.99C 970325 INPUT_STRWITHSEL化
  145. ".画像",//2.97A 970302 ".図"だとアウトライン表示うまくない
  146.     "IMG [画像] [S] SRC=<URL> ALIGN=<TOP|BOTTOM|MIDDLE|LEFT|RIGHT> ALT=<STR> WIDTH=<VALUE> HEIGHT=<VALUE> BORDER=<VALUE> HSPACE=<VALUE> VSPACE=<VALUE> LOWSRC=<URL> ISMAP USEMAP=<URL>",
  147.     "IMG_DYNSRC [ムービーやVRML] [S] [IE] dynsrc=<URL> start=<fileopen|mouseover>  controls=<VALUE_BOOL> loop=<VALUE_LOOP> loopdelay=<VALUE> src=<URL> alt=<STR>",//2.99C 970326 
  148.     "MAP [マップ名の定義] NAME=<STR>",
  149.     "AREA [領域の定義] [S] SHAPE=<RECT|CIRCLE|POLYGON> COORDS=<STR> HREF=<URL> NOHREF",
  150. ".箇条書き",
  151.     "UL [箇条書き] COMPACT TYPE=<DISC|CIRCLE|SQUARE>",
  152.     "LI [箇条書き項目] [S] TYPE=<DISC|CIRCLE|SQUARE|A|a|I|i|1> VALUE=<VALUE>",// ULかOLかで、TYPEの値異なる
  153.     "OL [番号付き箇条書き] COMPACT TYPE=<A|a|I|i|1> START=<VALUE>",
  154.     "DL [定義型] COMPACT",    //// COMPACTはNNのみにする予定
  155.     "DD [定義型の見出し] [S]",//2.99 970319 
  156.     "DT [定義型の説明] [S]",//2.99 970319 
  157.     "MENU COMPACT",
  158.     "DIR COMPACT",
  159. ".文書情報",
  160.     "BODY [本文] BACKGROUND=<URL> BGCOLOR=<COLOR> TEXT=<COLOR> LINK=<COLOR> VLINK=<COLOR> ALINK=<COLOR>",
  161.     "TITLE [タイトル]",
  162.     "HTML",
  163.     "HEAD [ファイル情報]",
  164. //    "ISINDEX PROMPT=<STR>",
  165.     "LINK REV=<STR> REL=<STR> HREF=<URL>",
  166.     "[R] WZHTMLNEW ページタイトル=<STR> 背景画像=<URL> 背景色=<COLOR> テキスト色=<COLOR>  ホットテキスト色=<COLOR> 参照済み色=<COLOR> クリック時の色=<COLOR> 基準フォントサイズ=<7|6|5|4|3|2|1> ターゲットフレーム=<STR:_self|_blank|_parent|_top|title|main|contents> 基準URL=<URL>",//2.99C 970326 
  167. ".フォーム",
  168.     "FORM [入力フォームの定義] ACTION=<URL> METHOD=<POST|GET> ENCTYPE=<MULTIPART|FORM-DATA>",
  169.     "INPUT [入力エリアとボタン] [S] TYPE=<text|password|checkbox|radio|image|hidden|submit|reset> NAME=<STR> VALUE=<STR> CHECKED SIZE=<VALUE> MAXLENGTH=<VALUE>",//2.98 970307 TYPEは小文字。大文字だと認識しないブラウザがある。
  170. #if 1//2.99 970319 <select>...</select>、<option>はシングルタグ
  171.     "SELECT [選択メニュー] NAME=<STR> SIZE=<VALUE> MULTIPLE",
  172.     "OPTION [選択肢] [S] SELECTED",
  173. #else
  174.     "SELECT [選択メニュー] [S] NAME=<STR> SIZE=<VALUE> MULTIPLE",
  175.     "OPTION [選択肢] SELECTED",
  176. #endif
  177.     "TEXTAREA [テキスト入力エリア] ROWS=<VALUE> COLS=<VALUE> NAME=<STR> WRAP=<OFF|VIRTUAL|PHYSICAL>",
  178. ".表",
  179.     "TABLE [表] BORDER=<VALUE_BOOL> CELLSPACING=<VALUE> CELLPADDING=<VALUE> WIDTH=<VALUE_PERCENT> align=<left|right> bgcolor=<COLOR>",//2.99C 970326 align,bgcolor追加
  180.     "TD [要素] ALIGN=<LEFT|RIGHT|CENTER> VALIGN=<TOP|MIDDLE|BOTTOM> NOWRAP COLSPAN=<VALUE> ROWSPAN=<VALUE> WIDTH=<VALUE_PERCENT> BGCOLOR=<COLOR>",
  181.     "TH [見出し要素] ALIGN=<LEFT|RIGHT|CENTER> VALIGN=<TOP|MIDDLE|BOTTOM> NOWRAP COLSPAN=<VALUE> ROWSPAN=<VALUE> WIDTH=<VALUE_PERCENT> BGCOLOR=<COLOR>",
  182.     "TR [改行] [S] ALIGN=<LEFT|RIGHT|CENTER> VALIGN=<TOP|MIDDLE|BOTTOM> bgcolor=<color>",//2.99C 970326 bgcolor追加
  183.     "[I] TR [改行]",
  184.     "CAPTION [名前] ALIGN=<TOP|BOTTOM>",
  185.     "COL [セルオプション] [S] [NN] align=<center|left|right> span=<VALUE>",//2.99C 970326 
  186. #if 1//2.99E 970403 
  187.     "COLGROUP [セルオプション] [S] [!IE] halign=<center|left|right> valigin=<middle|top|bottom> span=<VALUE> width=<VALUE>",//2.99C 970326 
  188. #else
  189.     "COLGROUP [セルオプション] [S] [NN] halign=<center|left|right> valigin=<middle|top|bottom> span=<VALUE> width=<VALUE>",//2.99C 970326 
  190. #endif
  191. ".フレーム",
  192.     "FRAMESET [フレーム] FRAMEBORDER=<yes|no> BORDER=<VALUE> BORDERCOLOR=<COLOR>",// ROWS,COLS 未対応    //// BORDERCOLORはNNのみ
  193.     "FRAME [フレームの内容] [S] SRC=<URL> NAME=<STR> TARGET=<STR:_blank|_self|_parent|_top> MARGINWIDTH=<VALUE> MARGINHEIGHT=<VALUE> SCROLLING=<YES|NO|AUTO> NORESIZE FRAMEBORDER=<yes|no> BORDERCOLOR=<COLOR>",//2.99C 970326 name->target
  194.     "NOFRAME [フレーム非対応ブラウザ用body]",//2.99C 970326 
  195.     "IFRAME [フローティングフレーム] [IE] width=<VALUE> height=<VALUE> src=<URL>",//2.99C 970326 
  196. ".オブジェクト、アプレット、スクリプト",
  197.     "APPLET [アプレット] CODE=<STR> PARAM NAME=<STR> CODEBASE=<URL> NAME=<STR> ALT=<STR> ALIGN=<LEFT|RIGHT|CENTER> WIDTH=<VALUE> HEIGHT=<VALUE> HSPACE=<VALUE> VSPACE=<VALUE>",
  198.     "PARAM [パラメータ] [S] NAME=<STR> VALUE=<VALUE>",
  199.     "EMBED [プラグイン] [S] SRC=<URL> WIDTH=<VALUE> HEIGHT=<VALUE>",
  200.     "NOEMBED [EMBEDタグに対応していないブラウザへの表示]",//2.99C 970326 シングルタグではない
  201.     "OBJECT [オブジェクト] CLASSID=<STR> CODEBASE=<URL> WIDTH=<VALUE> HEIGHT=<VALUE> NAME=<STR> ID=<STR>",
  202.     "SCRIPT [スクリプト] LANGUAGE=<STR>",
  203. ".その他",
  204.     "BGSOUND [BGM] [S] [IE] SRC=<URL> LOOP=<VALUE_LOOP>",
  205.     "COMMENT [コメント] [IE]",//2.99C 970326 
  206.     NULL,
  207. };
  208.  
  209. static mchar* _getcaption(mchar* szAtr)
  210. {
  211.     if (!stricmp(szAtr,"align")) return "整列";
  212.     if (!stricmp(szAtr,"alink")) return "リンク中";
  213.     if (!stricmp(szAtr,"alt")) return "代替文章";
  214.     if (!stricmp(szAtr,"compact")) return "コンパクト";
  215.     if (!stricmp(szAtr,"height")) return "高さ";
  216.     if (!stricmp(szAtr,"noshade")) return "影なし";
  217.     if (!stricmp(szAtr,"size")) return "サイズ";
  218.     if (!stricmp(szAtr,"vlink")) return "読込済リンク";
  219.     if (!stricmp(szAtr,"width")) return "幅";
  220.     return szAtr;
  221. }
  222.  
  223. static int getaccesskey(int ic)
  224. {
  225.     int ret = ic + 'A';
  226.     if (ret >= 'H') ret++;    //2.99D 970402 'H'はヘルプのために空ける
  227.     if (ret <= 'Z') return ret;
  228.     ret = ret - ('Z'+1) + '0';
  229.     if (ret <= '9') return ret;
  230.     return ' ';
  231. }
  232.  
  233. static mchar* getcaption(mchar* szAtr,int ic)
  234. {
  235.     static mchar buff[CCHWORD];
  236.     sprintf(buff,"%s(&%c)",_getcaption(szAtr),getaccesskey(ic));
  237.     return buff;
  238. }
  239.  
  240. static mchar* getcaptionc(mchar* szAtr,int ic)
  241. {
  242.     static mchar buff[CCHWORD];
  243.     sprintf(buff,"%s(&%c):",_getcaption(szAtr),getaccesskey(ic));
  244.     return buff;
  245. }
  246.  
  247. static mchar* getcaptionref(mchar* szAtr,int ic)
  248. {
  249.     static mchar buff[CCHWORD];
  250.     sprintf(buff,"%s(&%c)...",_getcaption(szAtr),getaccesskey(ic));
  251.     return buff;
  252. }
  253.  
  254. #define INPUT_COLOR            1
  255. #define INPUT_URL            2
  256. #define INPUT_SELSTR        3    // like as <LEFT|CENTER|RIGHT>
  257. #define INPUT_VALUE            4
  258. #define INPUT_VALUE_PERCENT    5
  259. #define INPUT_BOOL            6
  260. #define INPUT_STR            7
  261. #define INPUT_VALUE_BOOL    8    //2.97A 970228 0,1ならINPUT_BOOL、2以上ならINPUT_VALUE
  262. #define INPUT_VALUE_LOOP    9    //2.97A 970302 INFINITE
  263. #define INPUT_STRWITHSEL    10    //2.99C 970325 new INPUT_STR + 規定値
  264.  
  265. static mchar* strdup(mchar* sz)
  266. {
  267.     int len = strlen(sz);
  268.     mchar* p = malloc(len + 1);
  269.     if (p) {
  270.         strcpylen(p,sz,len);
  271.         return p;
  272.     }
  273.     return NULL;
  274. }
  275.  
  276. typedef struct {
  277.     mchar szAtr[32];
  278.     mchar szfilename[CCHPATHNAME];
  279.     COLORREF rgb;
  280.     BYTE fExist;        // 存在したか?
  281.     BYTE fPercent;        // %指定?
  282.     BYTE fInfinite;        // INFINITE?
  283.     BYTE flag;
  284.     int idi;
  285.     int idColorButton;        //2.99C 970325 
  286.     int idDelColorButton;    //2.99C 970325 
  287.     mchar szSelStr[CCHWORD];
  288.     HSTRBLK sbSelStr;
  289.     DWORD value;
  290. } ATRDATA;
  291.  
  292. static void inputFromSz(ATRDATA* data)
  293. {
  294.     mchar* sz = data->szSelStr;
  295.     data->idi = 0;//2.99C 970325 
  296.     if (!stricmp(sz,"<COLOR>")) {
  297.         data->idi = INPUT_COLOR;
  298.         return;
  299.     }
  300.     if (!stricmp(sz,"<URL>")) {
  301.         data->idi = INPUT_URL;
  302.         return;
  303.     }
  304.     if (!stricmp(sz,"<VALUE>")) {
  305.         data->idi = INPUT_VALUE;
  306.         return;
  307.     }
  308.     if (!stricmp(sz,"<VALUE_BOOL>")) {
  309.         data->idi = INPUT_VALUE_BOOL;
  310.         return;
  311.     }
  312.     if (!stricmp(sz,"<VALUE_LOOP>")) {
  313.         data->idi = INPUT_VALUE_LOOP;
  314.         return;
  315.     }
  316.     if (!stricmp(sz,"<VALUE_PERCENT>")) {
  317.         data->idi = INPUT_VALUE_PERCENT;
  318.         return;
  319.     }
  320.     if (!stricmp(sz,"<STR>")) {
  321.         data->idi = INPUT_STR;
  322.         return;
  323.     }
  324.     if (!strnicmp(sz,"<STR:",5)) {//2.99C 970325 
  325.         data->idi = INPUT_STRWITHSEL;
  326.     }
  327.     if (
  328.         data->idi == INPUT_STRWITHSEL ||//2.99C 970325 
  329.         (sz[0] == '<' && strchr(sz,'|'))
  330.     ) {
  331.         mchar* szs;
  332.         if (data->idi == INPUT_STRWITHSEL) {
  333.             //2.99C 970325 
  334.             szs = strdup(sz + 5);
  335.         } else {
  336.             szs = strdup(sz + 1);
  337.             data->idi = INPUT_SELSTR;
  338.         }
  339.         if (szs) {
  340.             mchar* sz = szs;
  341.             // delete tail '>'
  342.             int len = strlen(szs);
  343.             if (len && szs[len - 1] == '>') szs[len-1] = 0;
  344.             //
  345.             data->sbSelStr = sbNewAlloc(strlen(sz) + 100);
  346.             if (data->sbSelStr) {
  347.                 if (data->idi != INPUT_STRWITHSEL) {
  348.                     sbAdd(data->sbSelStr,"標準");
  349.                 }
  350.                 while(1) {
  351.                     mchar* p = strchr(sz,'|');
  352.                     if (!*sz) break;
  353.                     if (p) {
  354.                         *p = 0;
  355.                         p++;
  356.                     } else {
  357.                         p = sz + strlen(sz);
  358.                     }
  359.                     sbAdd(data->sbSelStr,sz);
  360.                     sz = p;
  361.                 }
  362.                 if (data->idi == INPUT_STRWITHSEL) {
  363.                     sbReverse(data->sbSelStr);
  364.                 }
  365.             }
  366.             free(szs);
  367.         }
  368.         return;
  369.     }
  370. }
  371.  
  372. static int hextonum(mchar c)
  373. {
  374.     if (isdigit(c)) return c - '0';
  375.     if ('A' <= c && c <= 'F') return c - 'A' + 10;
  376.     if ('a' <= c && c <= 'f') return c - 'a' + 10;
  377.     return -1;
  378. }
  379.  
  380. static DWORD _tcolor[] = {
  381.     0x000000,0xFFFFFF,0xFF0000,0x00FF00,
  382.     0x0000FF,0xFF00FF,0xFFFF00,0x00FFFF,
  383.     0x000080,0x008080,0x008000,0x800000,
  384.     0x800080,0x808000,0x808080,0xC0C0C0,
  385. };
  386.  
  387. static mchar* _tszcolor[] = {//2.99C 970325 
  388.     "black(黒)",
  389.     "white(白)",
  390.     "red(赤)",
  391.     "lime(黄緑)",
  392.     "blue(青)",
  393.     "fuchsia(ピンク)",
  394.     "yellow(黄色)",
  395.     "aqua(水色)",
  396.     "navy(紺)",
  397.     "teal(深緑)",
  398.     "green(緑)",
  399.     "maroon(茶)",
  400.     "purple(紫)",
  401.     "olive(うぐいす色)",
  402.     "gray(灰色)",
  403.     "silver(銀色)",
  404. };
  405.  
  406. static COLORREF rgbFromIndex(UINT i)
  407. {
  408.     if (i >= 16) return 0;
  409.     DWORD col = _tcolor[i];
  410.     return RGB(col>>16,(col>>8)&0xFF,col&0xFF);
  411. }
  412.  
  413. //2.99C 970325 new
  414. static COLORREF rgbFromSz(mchar* szColor)
  415. {
  416.     mchar* p = szColor;
  417.     if (*p == '#') {
  418.         p++;
  419.         int r,g,b;
  420.         r = hextonum(*p++) << 4;
  421.         r |= hextonum(*p++);
  422.         g = hextonum(*p++) << 4;
  423.         g |= hextonum(*p++);
  424.         b = hextonum(*p++) << 4;
  425.         b |= hextonum(*p++);
  426.         return RGB(r,g,b);
  427.     } else {
  428.         int lch = strlen(szColor);
  429.         for (int i = 0;i < 16;i++) {
  430.             if (!strnicmp(_tszcolor[i],szColor,lch)) {
  431.                 mchar c = _tszcolor[i][lch];
  432.                 if (c == 0 || c == '(') {
  433.                     return rgbFromIndex(i);
  434.                 }
  435.             }
  436.         }
  437.     }
  438.     return 0;
  439. }
  440.  
  441. static int rgbToIndex(COLORREF rgb)
  442. {
  443.     int r = GetRValue(rgb);
  444.     int g = GetGValue(rgb);
  445.     int b = GetBValue(rgb);
  446.     DWORD col = MAKELONG(MAKEWORD(b,g),MAKEWORD(r,0));
  447.     for (int i = 0;i < 16;i++) {
  448.         if (_tcolor[i] == col) return i;
  449.     }
  450.     return -1;
  451. }
  452.  
  453. static void rgbPrint(COLORREF rgb,mchar* buff)
  454. {
  455. //2.99C 970325 new
  456.     mchar*dst = buff;
  457.     *dst++ = '#';
  458.     sprintf(dst,"%02X%02X%02X",GetRValue(rgb),GetGValue(rgb),GetBValue(rgb));dst += strlen(dst);
  459.     *dst = 0;
  460. }
  461.  
  462. static BOOL atrMatch(mchar* szfh,ATRDATA* data,HSTRBLK sbColor)
  463. {
  464. // szfh:<>で括られたSZFH
  465.     mchar* p = szfh;
  466.     p += strGetWordLen(p);
  467.     while(1) {
  468.         p = strGetWordTop(p);
  469.         int len = strGetWordLen(p);
  470.         if (!len) break;
  471.         mchar szAtr[CCHWORD];
  472.         mchar szContent[CCHWORD] = {0};
  473.         sstrcpylen(szAtr,p,len);
  474.         p += len;
  475.         if (*p == 0 && len && p[-1] == '>') {
  476.             // 末尾の'>'を消去
  477.             szAtr[len-1] = 0;
  478.         }
  479.         {
  480.             mchar* q = strchr(szAtr,'=');
  481.             if (q) {
  482.                 *q = 0;
  483.                 sstrcpy(szContent,q + 1);
  484.             }
  485.         }
  486. //information("[%s][%s]",szAtr,data->szAtr);
  487.         if (!stricmp(szAtr,data->szAtr)) {
  488.             data->fExist = TRUE;
  489.             if (szContent[0]) {    // '='に続けて指定あり
  490.                 pathFormLong(szContent);
  491.                 mchar* p = szContent;
  492. //information("[%s] %d",data->szAtr,data->idi);
  493.                 switch(data->idi) {
  494.                     case INPUT_COLOR: {
  495. #if 1//2.99C 970325 
  496.                         data->rgb = rgbFromSz(szContent);
  497. #else
  498.                         if (*p == '#') {
  499.                             p++;
  500.                             int r,g,b;
  501.                             r = hextonum(*p++) << 4;
  502.                             r |= hextonum(*p++);
  503.                             g = hextonum(*p++) << 4;
  504.                             g |= hextonum(*p++);
  505.                             b = hextonum(*p++) << 4;
  506.                             b |= hextonum(*p++);
  507.                             data->rgb = RGB(r,g,b);
  508.                         } else {
  509.                             if (sbColor) {
  510.                                 int lch = strlen(szContent);
  511.                                 for (int i = 2;i < 2 + 16;i++) {
  512.                                     mchar* sz = sbRead(sbColor,i);
  513.                                     if (!strnicmp(sz,szContent,lch) && sz[lch] == '(') {
  514.                                         data->rgb = rgbFromIndex(i - 2);
  515.                                         break;
  516.                                     }
  517.                                 }
  518.                             }
  519.                         }
  520. #endif
  521.                         break;
  522.                     }
  523.                     case INPUT_SELSTR:
  524.                     case INPUT_URL:
  525.                     case INPUT_STRWITHSEL://2.99C 970325 
  526.                     case INPUT_STR: {
  527.                         sstrcpy(data->szfilename,szContent);
  528.                         break;
  529.                     }
  530.                     case INPUT_VALUE_LOOP: {
  531.                         if (!stricmp(szContent,"INFINITE")) {
  532.                             data->fInfinite = TRUE;
  533.                         } else {
  534.                             data->value = atoi(szContent);
  535.                         }
  536.                         break;
  537.                     }
  538.                     case INPUT_VALUE_BOOL:
  539.                     case INPUT_VALUE: {
  540.                         data->value = atoi(szContent);
  541.                         break;
  542.                     }
  543.                     case INPUT_VALUE_PERCENT: {
  544.                         data->value = atoi(szContent);
  545.                         data->fPercent = (strchr(szContent,'%') != NULL);
  546.                         break;
  547.                     }
  548.                 }
  549.             } else {    // '='なし
  550.                 if (data->idi == INPUT_BOOL) {
  551.                     data->flag = TRUE;
  552.                 } else if (data->idi == INPUT_VALUE_BOOL) {
  553.                     data->value = 1;
  554.                 }
  555.             }
  556. //            information(szContent);
  557.             return TRUE;
  558.         }
  559.     }
  560.     return FALSE;
  561. }
  562.  
  563. static BOOL atrCheckSupport(mchar* szfh,ATRDATA* tdata,int ndata,txstr szReport)
  564. {
  565. // szfh:<>で括られたSZFH
  566.     mchar* p = szfh;
  567.     p += strGetWordLen(p);
  568.     while(1) {
  569.         p = strGetWordTop(p);
  570.         int len = strGetWordLen(p);
  571.         if (!len) break;
  572.         mchar szAtr[CCHWORD];
  573.         sstrcpylen(szAtr,p,len);
  574.         p += len;
  575.         if (*p == 0 && len && p[-1] == '>') {
  576.             // 末尾の'>'を消去
  577.             szAtr[len-1] = 0;
  578.         }
  579.         {
  580.             mchar* q = strchr(szAtr,'=');
  581.             if (q) *q = 0;
  582.         }
  583.         {
  584.             BOOL fFound = FALSE;
  585.             for (int i = 0;i < ndata;i++) {
  586.                 if (!stricmp(szAtr,tdata[i].szAtr)) {
  587.                     fFound = TRUE;
  588.                     break;
  589.                 }
  590.             }
  591.             if (!fFound) {
  592.                 if (szReport[0]) {
  593.                     szReport += ",";
  594.                 } else {
  595.                     szReport = "アトリビュート ";
  596.                 }
  597.                 szReport += szAtr;
  598.             }
  599.         }
  600.     }
  601.     if (szReport[0]) {
  602.         szReport += " は未対応です";
  603. //        information(szReport);
  604.         return FALSE;
  605.     }
  606.     return TRUE;
  607. }
  608.  
  609. #define IDD_SELCOLORTOP        100
  610. #define IDD_SELCOLOREND        199
  611. #define IDD_VALUETOP        200
  612. #define IDD_VALUEEND        299
  613. #define IDD_DELCOLORTOP        300//2.99C 970325 
  614. #define IDD_DELCOLOREND        399
  615. #define IDD_REFERIMGSIZE    400
  616.  
  617. //2.99C 970325 
  618. typedef struct {
  619.     HSTRBLK sbColor;
  620.     ATRDATA* tdata;
  621.     int ndata;
  622. } EDITCONTEXT;
  623.  
  624. static mchar _szColorStd[] = "標準色";
  625.  
  626. BOOL dlgprocEdit(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  627. {
  628.     switch(message) {
  629.         case WM_INITDIALOG: {
  630.             break;
  631.         }
  632.         case WM_COMMAND: {
  633.             int id = WM_COMMAND_GetId(wParam);
  634.             int notify = WM_COMMAND_GetNotify(wParam,lParam);
  635.             HDIALOG hd = dialogFromHwnd(hwnd);
  636.             EDITCONTEXT* context = (LPVOID)dialogGetCustdata(hd);
  637.             ATRDATA* data = context->tdata;
  638.             if (IDD_SELCOLORTOP <= id && id <= IDD_SELCOLOREND) {
  639.                 if (id & 0x01) {
  640. #if 1
  641.                     for (int i = 0;i < context->ndata;i++,data++) {
  642.                         if (data->idColorButton == id) {
  643.                             dialogRead(hd);
  644.                             data->rgb = rgbFromSz(data->szfilename);
  645.                             if (txccGetColor(text,&data->rgb,"色の選択")) {
  646.                                 rgbPrint(data->rgb,data->szfilename);
  647.                                 sbAddHist(context->sbColor,data->szfilename);
  648.                                 dialogWrite(hd);
  649.                             }
  650.                             break;
  651.                         }
  652.                     }
  653.                     return TRUE;
  654. #else
  655.                     ComboBox_SetCurSel(GetDlgItem(hwnd,id - 1),1);
  656. #endif
  657.                 }
  658.             } else if (IDD_VALUETOP <= id && id <= IDD_VALUEEND) {
  659.                 if (!(id & 0x00) && notify == EN_CHANGE) {
  660.                     mchar szbuff[CCHWORD];
  661.                     Edit_GetText(GetDlgItem(hwnd,id),szbuff,cchof(szbuff));
  662.                     Button_SetCheck(GetDlgItem(hwnd,id + 1),!szbuff[0]);
  663.                 }
  664.             } else if (IDD_DELCOLORTOP <= id && id <= IDD_DELCOLOREND) {//2.99C 970325 
  665.                 for (int i = 0;i < context->ndata;i++,data++) {
  666.                     if (data->idDelColorButton == id) {
  667.                         dialogRead(hd);
  668.                         if (
  669.                             !stricmp(data->szfilename,_szColorStd) ||
  670.                             strchr(data->szfilename,'(')    //2.99D 970331 基本16色も削除できないようにした
  671.                         ) {
  672.                             // 標準色は削除できない
  673.                             information("標準色、基本16色は削除できません");//2.99D 970331 message
  674.                         } else {
  675.                             sbDel(context->sbColor,data->szfilename);
  676.                             strcpy(data->szfilename,_szColorStd);
  677.                             dialogWrite(hd);
  678.                         }
  679.                         break;
  680.                     }
  681.                 }
  682.             } else if (id == IDD_REFERIMGSIZE) {
  683.                 //2.99C 970325 GIFのイメージのサイズが取得できるようにした
  684.                 int width,height;
  685.                 BOOL fOK = FALSE;
  686.                 dialogRead(hd);
  687.                 for (int i = 0;i < context->ndata;i++,data++) {
  688.                     if (!stricmp(data->szAtr,"SRC")) {
  689.                         mchar szfilename[CCHPATHNAME];
  690.                         strcpy(szfilename,data->szfilename);
  691.                         pathSetMode(szfilename,text->szfilename,NULL,PATH_ABSOLUTEDRIVE);
  692.                         if (!pathIsExt(szfilename,".gif")) {
  693.                             information("%s\nこのファイルのイメージサイズは取得できません。\nGIF形式のファイルだけイメージサイズが取得できます。",szfilename);
  694.                         } else {
  695.                             HFILE hfile = hfileOpen(szfilename);
  696.                             if (hfile == HFILE_ERROR) {
  697.                                 information("%s\nが開けません。",szfilename);
  698.                             } else {
  699.                                 mchar buff[0x500];
  700.                                 int lch = hfileRead(hfile,buff,0x500);
  701.                                 mchar* p = buff;
  702.                                 for (;lch--;p++) {
  703.                                     if (*p == ',' && lch >= 8) {
  704.                                         p++;
  705.                                         p += 4;
  706.                                         width = *(WORD*)p;p += 2;
  707.                                         height = *(WORD*)p;
  708.                                         fOK = TRUE;
  709.                                         break;
  710.                                     }
  711.                                 }
  712.                                 //
  713.                                 hfileClose(hfile);
  714.                             }
  715.                         }
  716.                         break;
  717.                     }
  718.                 }
  719.                 if (fOK) {
  720.                     for (int i = 0;i < context->ndata;i++,data++) {
  721.                         if (!stricmp(data->szAtr,"WIDTH")) {
  722.                             data->value = width;
  723.                         } else if (!stricmp(data->szAtr,"HEIGHT")) {
  724.                             data->value = height;
  725.                         }
  726.                     }
  727.                     dialogWrite(hd);
  728.                 }
  729.             }
  730.             break;
  731.         }
  732.     }
  733.     return FALSE;
  734. }
  735.  
  736. #define MAX_ATRDATA    20
  737. typedef struct {
  738.     ATRDATA tdata[MAX_ATRDATA];
  739.     int ndata;
  740. } TAGEDITATRARG;
  741.  
  742. static void dialogAddOkCancelHtmlhelp(HDIALOG hd,mchar* szTagName)
  743. {
  744.     dialogCmdLFV(hd);
  745.     dialogOK(hd,10);
  746.     dialogCancel(hd,10);
  747.     if (*szTagName == '/') szTagName++;
  748. //information("htmlwz " + szTagName);
  749.     //2.99F 970404 htmlwz.hlp 16bitにも対応
  750.     //2.99F 970404 text->szexedirをつけないとヘルプひらけないことがある
  751.     //2.99F 970404 ".hlp"がないとWindows3.1で開かない
  752.     //2.99F 970404 ""で括るとWinHelpで開けないが、strGetWordLenで切れちゃう。dialog.cを改良した
  753.     //2.99F 970404 WinNT4.0では32bitのヘルプ開けないので16bitで開く
  754.     if ((_fwin40 && _platform == WINDOWS95) || _fwinnt351) {
  755.         dialogHelpID(hd,10,"\"" + text->szexedir + "htmlwz.hlp\" " + szTagName,IDH_HTMLTAG);
  756.     } else {
  757.         dialogHelpID(hd,10,"\"" + text->szexedir + "htmlwz16.hlp\" " + szTagName,IDH_HTMLTAG);
  758.     }
  759. }
  760.  
  761. static BOOL tagEditAtr(TX* text,mchar* szTag,txstr szResult,TAGEDITATRARG* ana)
  762. {
  763. // szTagを編集して結果をszResultに返す。
  764. // charatr等のセットは行わない。
  765. //    information(szTag);
  766. //2.99C 970326 anaを指定すると解析/入力結果を返す
  767.     BOOL ret = FALSE;
  768.     BOOL fErr = FALSE;
  769.     txstr szErr;
  770.     mchar szTagName[CCHWORD];
  771.     mchar* szfh = NULL;
  772.     int tag = tagFromStr(szTag);//2.99 970319 
  773.     mchar* p = szTag + 1;
  774.     int lenTag = strGetWordLen(p);
  775.     if (strchrs(szTag,"\x0D\x0A")) {//2.99B 970322 
  776.         information("このタグには改行コードが含まれているので編集できません。\nテキストモードで編集してください。");
  777.         return FALSE;
  778.     }
  779.     if (!strcmp(szTag,"<!--") || !strcmp(szTag,"-->")) {
  780.         information("コメントタグの編集はできません。");
  781.         return FALSE;
  782.     }
  783.     if (
  784.         //2.99B 970322 
  785.         lenTag >= cchof(szTagName) ||
  786.         strlen(szTag) + 10 > 500    //2.99C 970326 CCHPATHNAMEだと足りなかった
  787.     ) {
  788.         information("このタグは長すぎて編集できません。\nテキストモードで編集してください。");
  789.         return FALSE;
  790.     }
  791.     if (lenTag && p[lenTag-1] == '>') lenTag--;// アトリビュートなしの場合
  792.     sstrcpylen(szTagName,p,lenTag);//2.99B 970322 strcpy->sstrcpy
  793.     //2.99C 970326 
  794.     int lenTagCmp = lenTag;
  795.     mchar szTagNameCmp[CCHWORD];
  796.     sstrcpy(szTagNameCmp,szTagName);
  797.     if (tag == TAG_IMG) {
  798.         //2.99C 970326 IMG_DYNSRC対応
  799.         if (stristr(szTag,"dynsrc")) {
  800.             sstrcpy(szTagNameCmp,"IMG_DYNSRC");
  801.             lenTagCmp = strlen(szTagNameCmp);
  802.         }
  803.     }
  804.     {
  805.         mchar* p;
  806.         for (int i = 0;p = _tszfh[i];i++) {
  807.             //2.97A 970302 
  808.             if (*p == '.') continue;
  809.             if (*p == '[') {
  810.                 if (!strnicmp(p,"[R]",3)) {
  811.                     // "[R]"ならOK
  812.                     p += 3;
  813.                     p = strGetWordTop(p);
  814.                 } else {
  815.                     continue;
  816.                 }
  817.             }
  818.             //
  819.             int len = strGetWordLen(p);
  820.             if (lenTagCmp == len && !strnicmp(szTagNameCmp,p,lenTag)) {//2.99C 970326 szTagName->szTagNameCmp,lenTag->lenTagCmp
  821.                 szfh = p;
  822.                 break;
  823.             }
  824.         }
  825.         if (!szfh) {
  826.             szErr = szTag + "のアトリビュートには対応していません";
  827.             fErr = TRUE;
  828.         }
  829.     }
  830.     p = szfh;
  831.     //
  832.     txstr szTitle;
  833.     if (!stricmp(szTagName,"WZHTMLNEW")) {
  834.         szTitle = "新規作成 - HTML";
  835.     } else {
  836.         szTitle = szTagName;
  837.         szTitle += " タグのアトリビュート";
  838.     }
  839.     HDIALOG hd = dialog(szTitle);
  840.     EDITCONTEXT context;
  841.     structClear(context);
  842.     dialogSetCustdata(hd,(DWORD)&context);
  843.     dialogSetHookEx(hd,"\m.dlgprocEdit");
  844.     int idSelColor = IDD_SELCOLORTOP;
  845.     int idDelColor = IDD_DELCOLORTOP;
  846.     int idValue = IDD_VALUETOP;
  847.     //
  848.     ATRDATA tdata[MAX_ATRDATA];
  849.     memset(tdata,0,sizeof(tdata));
  850.     context.tdata = tdata;
  851.     //2.99C 970325 色にヒストリを付けたので全面改良
  852.     static mchar _szhistColor[] = "rgbHtml";
  853.     HSTRBLK sbColor = historyOpen(_szhistColor,2048);
  854.     context.sbColor = sbColor;
  855.     // skip tag
  856.     if (p) p += strGetWordLen(p);
  857.     int n = 0;
  858.     if (!fErr) {
  859.         int ic = 0;
  860.         for (int i = 0;;i++) {
  861.             if (i == MAX_ATRDATA) {
  862.                 szErr = "タグ ";
  863.                 szErr += szTagName;
  864.                 szErr += " のアトリビュートデータが複雑すぎます";
  865.                 fErr = TRUE;
  866.                 break;
  867.             }
  868.             ATRDATA* data = &tdata[i];
  869.             p = strGetWordTop(p);
  870.             int len = strGetWordLen(p);
  871.             if (!len) break;
  872.             mchar szbuff[CCHWORD];
  873.             sstrcpylen(szbuff,p,len);
  874.             p += len;
  875.             if (szbuff[0] == '[') {
  876.                 //2.97A 970302 []内は無視
  877.                 i--;
  878.                 continue;
  879.             }
  880.             {
  881.                 mchar* q = strchr(szbuff,'=');
  882.                 if (q) {
  883.                     *q = 0;
  884.                     sstrcpy(data->szSelStr,q + 1);
  885.                     inputFromSz(data);
  886.                 } else {
  887.                     data->idi = INPUT_BOOL;
  888.                 }
  889.                 sstrcpy(data->szAtr,szbuff);
  890.             }
  891.             atrMatch(szTag,data,sbColor);
  892.             switch(data->idi) {
  893.                 case INPUT_COLOR: {
  894.                     if (sbColor) {
  895.                         dialogSetH(hd);
  896.                         if (data->fExist) {
  897.                             int icolor = rgbToIndex(data->rgb);
  898.                             if (icolor >= 0) {
  899.                                 strcpy(data->szfilename,_tszcolor[icolor]);
  900.                             } else {
  901.                                 rgbPrint(data->rgb,data->szfilename);
  902.                                 sbAddHist(sbColor,data->szfilename);//2.99F 970403 色のヒストリに存在しない色がアトリビュート指定されていたときに取り込む様にした。
  903.                             }
  904.                         } else {
  905.                             strcpy(data->szfilename,_szColorStd);
  906.                         }
  907.                         dialogControlID(hd,idSelColor++);
  908.                         dialogSelectStrH(hd,getcaptionc(data->szAtr,ic++),data->szfilename,CCHPATHNAME32,20,20,sbColor);
  909. #if 1//2.99C 970325 
  910.                         data->idColorButton = idSelColor;
  911.                         dialogControlID(hd,idSelColor++);
  912.                         dialogButton(hd,getcaptionref("参照",ic++),NULL,11);
  913.                         //
  914.                         data->idDelColorButton = idDelColor;
  915.                         dialogControlID(hd,idDelColor++);
  916.                         dialogButton(hd,getcaption("ヒストリから削除",ic++),NULL,16);
  917. #else
  918.                         dialogControlID(hd,idSelColor++);
  919.                         dialogColor(hd,getcaptionref("参照",ic++),data->szAtr,&data->rgb,11,NULL);
  920. #endif
  921.                         dialogSetV(hd);
  922.                         dialogLF(hd);
  923.                     }
  924.                     break;
  925.                 }
  926.                 case INPUT_URL: {
  927. #if 1//3.00A3 970508 <A>や<IMG>タグのアトリビュートで、相対/ドライブ名なし/...の選択ができるようにした。
  928.                     dialogControlRefer(hd,"-html *.*");
  929. #else
  930.     #if 1//3.00A 970502 INPUT_URLの参照マスクを"*.*"にした
  931.                     dialogControlRefer(hd,"-r *.*");
  932.     #else
  933.                     dialogControlRefer(hd,"-r *.gif");
  934.     #endif
  935. #endif
  936.                     dialogStrC(hd,getcaptionc(data->szAtr,ic++),data->szfilename,20,CCHPATHNAME32,30);
  937.                     break;
  938.                 }
  939.                 case INPUT_STR: {
  940.                     dialogStrC(hd,getcaptionc(data->szAtr,ic++),data->szfilename,20,CCHPATHNAME32,30);
  941.                     break;
  942.                 }
  943.                 case INPUT_STRWITHSEL: {//2.99C 970325 
  944.                     dialogControlHist(hd,data->sbSelStr);
  945.                     dialogStrC(hd,getcaptionc(data->szAtr,ic++),data->szfilename,20,CCHPATHNAME32,30);
  946.                     break;
  947.                 }
  948.                 case INPUT_SELSTR: {
  949.                     if (data->sbSelStr) {
  950.                         dialogSelectStrH(hd,getcaptionc(data->szAtr,ic++),data->szfilename,CCHPATHNAME32,20,20,data->sbSelStr);
  951.                     }
  952.                     break;
  953.                 }
  954.                 case INPUT_VALUE_PERCENT:
  955.                 case INPUT_VALUE_BOOL:
  956.                 case INPUT_VALUE_LOOP:
  957.                 case INPUT_VALUE: {
  958.                     dialogSetH(hd);
  959.                         BOOL fReferImgSize = FALSE;//2.99C 970325 
  960.                         dialogControlID(hd,idValue++);
  961.                         if (tag == TAG_IMG && !stricmp(data->szAtr,"WIDTH")) fReferImgSize = TRUE;//2.99C 970325 
  962.                         dialogInt(hd,getcaptionc(data->szAtr,ic++),&data->value,20,5);
  963.                         //
  964.                         dialogControlReverseBool(hd);
  965.                         dialogControlID(hd,idValue++);
  966.                         dialogCheckB(hd,getcaption("標準値を使用",ic++),&data->fExist);
  967.                         //
  968.                         if (data->idi == INPUT_VALUE_PERCENT) dialogCheckB(hd,getcaption("%指定",ic++),&data->fPercent);
  969.                         if (data->idi == INPUT_VALUE_LOOP) dialogCheckB(hd,getcaption("無限ループ",ic++),&data->fInfinite);
  970.                         //
  971.                         if (fReferImgSize) {//2.99C 970325 
  972.                             dialogControlID(hd,IDD_REFERIMGSIZE);
  973.                             dialogButton(hd,getcaptionref("参照",ic++),NULL,11);
  974.                         }
  975.                     dialogSetV(hd);
  976.                     dialogLF(hd);
  977.                     break;
  978.                 }
  979.                 case INPUT_BOOL: {
  980.                     dialogCheckB(hd,getcaption(data->szAtr,ic++),&data->flag);
  981.                     break;
  982.                 }
  983.                 default: {
  984.                     dialogCaption(hd,data->szAtr);
  985.                     break;
  986.                 }
  987.             }
  988.         }
  989.         n = i;
  990.         context.ndata = n;
  991.         if (!atrCheckSupport(szTag,tdata,n,szErr)) fErr = TRUE;
  992.         if (n == 0) {//2.97A 970302 
  993.             szErr = szTag + "のアトリビュートには対応していません";
  994.             fErr = TRUE;
  995.         }
  996.     }
  997.     if (fErr) {
  998.         dialogTerm(hd);
  999.         HDIALOG hd = dialog(szTitle);
  1000.         szResult = szTag;
  1001.         dialogStr(hd,"タグ(&T):",szResult,16,40);
  1002.         dialogCaptionDynamic(hd,szErr,60);
  1003.         
  1004.         //2.99D 970402 HTMLタグプロパティにヘルプボタン追加
  1005.         dialogAddOkCancelHtmlhelp(hd,szTagName);
  1006.         
  1007.         if (dialogOpen(hd)) {
  1008.             ret = TRUE;
  1009.         }
  1010.     } else {
  1011.         int modeTable = (tag == TAG_TH);
  1012.         if (tag == TAG_TD || tag == TAG_TH) {//2.99 970319 <TD>,<TH>切り替えできるようにした
  1013.             dialogRadioID(hd,&modeTable,"<TD>タグ","<TH>タグ");
  1014.         }
  1015.         
  1016.         //2.99D 970402 HTMLタグプロパティにヘルプボタン追加
  1017.         dialogAddOkCancelHtmlhelp(hd,szTagName);
  1018.         
  1019.         if (dialogOpen(hd)) {
  1020.             ret = TRUE;
  1021.             szResult = "<";
  1022.             if (tag == TAG_TD || tag == TAG_TH) {//2.99 970319 
  1023.                 if (modeTable) {
  1024.                     szResult += "TH";
  1025.                 } else {
  1026.                     szResult += "TD";
  1027.                 }
  1028.             } else {
  1029.                 szResult += szTagName;
  1030.             }
  1031.             for (int i = 0;i < n;i++) {
  1032.                 ATRDATA* data = &tdata[i];
  1033.                 switch(data->idi) {
  1034.                     case INPUT_COLOR: {
  1035.                         data->fExist = (stricmp(data->szfilename,_szColorStd) != 0);
  1036.                         break;
  1037.                     }
  1038.                     case INPUT_STRWITHSEL://2.99C 970325 
  1039.                     case INPUT_STR:
  1040.                     case INPUT_URL: data->fExist = (data->szfilename[0] != 0);break;
  1041.                     case INPUT_SELSTR: data->fExist = (strcmp(data->szfilename,"標準") != 0);break;
  1042.                     case INPUT_BOOL: data->fExist = data->flag;break;
  1043.                     case INPUT_VALUE_BOOL: data->fExist = (data->value != 0);break;
  1044.                 }
  1045.                 if (data->fExist) {
  1046.                     mchar buff[20];
  1047.                     szResult += " ";
  1048.                     szResult += data->szAtr;
  1049.                     switch(data->idi) {
  1050.                         case INPUT_COLOR: {
  1051. #if 1//2.99C 970325 
  1052.                             if (data->szfilename[0] == '#') {
  1053.                                 szResult += "=";
  1054.                                 szResult += data->szfilename;
  1055.                             } else {
  1056.                                 mchar* p = strchr(data->szfilename,'(');
  1057.                                 if (p) *p = 0;
  1058.                                 szResult += "=";
  1059.                                 szResult += data->szfilename;
  1060.                             }
  1061. #else
  1062.                             if (!stricmp(data->szfilename,sbRead(sbColor,1))) {
  1063.                                 // 詳細で指定した色
  1064.                                 szResult += "\"";
  1065.                                 rgbPrint(data->rgb,buff);
  1066.                                 szResult += "\"";
  1067.                                 szResult += "=";
  1068.                                 szResult += buff;
  1069.                             } else {
  1070.                                 mchar* p = strchr(data->szfilename,'(');
  1071.                                 if (p) *p = 0;
  1072.                                 szResult += "=";
  1073.                                 szResult += data->szfilename;
  1074.                             }
  1075. #endif
  1076.                             break;
  1077.                         }
  1078.                         case INPUT_STRWITHSEL://2.99C 970325 
  1079.                         case INPUT_STR:
  1080.                         case INPUT_URL: {
  1081.                             szResult += "=\"";
  1082.                             szResult += data->szfilename;
  1083.                             szResult += "\"";
  1084.                             break;
  1085.                         }
  1086.                         case INPUT_SELSTR: {
  1087.                             szResult += "=";
  1088.                             szResult += data->szfilename;
  1089.                             break;
  1090.                         }
  1091.                         case INPUT_VALUE: {
  1092.                             sprintf(buff,"%ld",data->value);
  1093.                             szResult += "=";
  1094.                             szResult += buff;
  1095.                             break;
  1096.                         }
  1097.                         case INPUT_VALUE_LOOP: {
  1098.                             if (data->fInfinite) {
  1099.                                 szResult += "=INFINITE";
  1100.                             } else {
  1101.                                 sprintf(buff,"%ld",data->value);
  1102.                                 szResult += "=";
  1103.                                 szResult += buff;
  1104.                             }
  1105.                             break;
  1106.                         }
  1107.                         case INPUT_VALUE_BOOL: {
  1108.                             if (data->value >= 2) {
  1109.                                 sprintf(buff,"%ld",data->value);
  1110.                                 szResult += "=";
  1111.                                 szResult += buff;
  1112.                             }
  1113.                             break;
  1114.                         }
  1115.                         case INPUT_VALUE_PERCENT: {
  1116.                             sprintf(buff,"%ld",data->value);
  1117.                             szResult += "=";
  1118.                             szResult += buff;
  1119.                             if (data->fPercent) {
  1120.                                 szResult += "%";
  1121.                             }
  1122.                             break;
  1123.                         }
  1124.                     }
  1125.                 }
  1126.             }
  1127.             szResult += ">";
  1128. //            information("%s",szResult);
  1129.         }
  1130.     }
  1131.     // delete
  1132.     for (int i = 0;i < n;i++) {
  1133.         ATRDATA* data = &tdata[i];
  1134.         if (data->sbSelStr) {
  1135.             sbDelete(data->sbSelStr);
  1136.             data->sbSelStr = NULL;//2.99C 970326 
  1137.         }
  1138.     }
  1139.     if (ana) {//2.99C 970326 
  1140.         memcpy(ana->tdata,tdata,sizeof(ana->tdata));
  1141.         ana->ndata = n;
  1142.     }
  1143.     if (sbColor) {
  1144.         historyClose(_szhistColor,sbColor);
  1145.     }
  1146.     return ret;
  1147. }
  1148.  
  1149. #if 0//3.00A2 970505 txGetParaRear API化された
  1150. static int txGetParaRear(TX* text,txstr szpara)
  1151. {
  1152.     txstr szbuff(500);
  1153.     IFILE adr = txGetAddress(text);
  1154.     IFILE adrParatop = txGetParaTop(text);
  1155.     int ret = txGetPara(text,szbuff);
  1156.     IFILE d = adr - adrParatop;
  1157.     szpara = &szbuff[d];
  1158.     return ret - d;
  1159. }
  1160. #endif
  1161.  
  1162. static BOOL _uiPropertyTag(TX* text,BOOL fNoFlush)
  1163. {
  1164. // カーソル位置から最も近いタグのアトリビュートを編集。
  1165. // ダイアログでOKしたかどうか返す。
  1166.     BOOL ret = FALSE;
  1167.     txstr szResult(500);
  1168.     if (text->editmode) {
  1169.         if (txGetChar(text) == CHAR_PLUG) {
  1170.             LPVOID plug = txGetCurPlug(text);
  1171.             if (!plug) return FALSE;
  1172.             int modePlug = ((PLUGHEAD*)plug)->modePlug;
  1173.             mchar* szTag = NULL;
  1174.             switch(modePlug) {
  1175.                 case PLUG_HTML_TAG: szTag = ((PLUGHTMLTAG*)plug)->szTag;break;
  1176.                 case PLUG_TAB: szTag = ((PLUGTAB*)plug)->szTag;break;
  1177.                 case PLUG_IMG: szTag = ((PLUGIMG*)plug)->szTag;break;
  1178.                 case PLUG_IMG_LINK: szTag = ((PLUGIMG_LINK*)plug)->szTag;break;
  1179.                 case PLUG_HR: szTag = ((PLUGHR*)plug)->szTag;break;
  1180.             }
  1181.             if (szTag) {
  1182.                 UINT offSzTag = (LPBYTE)szTag - (LPBYTE)plug;
  1183.                 if (tagEditAtr(text,szTag,szResult,NULL)) {
  1184. //information(szResult);
  1185.                     int cch = strlen(szResult) + 1;
  1186.                     LPVOID plug1 = plugatrNewEx(text,modePlug,cch);
  1187.                     // plugatrNewExで、plugが無効になる可能性があるので
  1188.                     // Readし直す。
  1189.                     LPVOID plug0 = txGetCurPlug(text);
  1190.                     if (plug1) {
  1191.                         txSetUndisp(text);
  1192.                         {
  1193.                             memcpy(plug1,plug0,offSzTag);
  1194.                             *((WORD*)((LPBYTE)plug1 + offSzTag - 2)) = cch;
  1195.                             strcpy((LPBYTE)plug1 + offSzTag,szResult);
  1196.                             //
  1197.                             if (modePlug == PLUG_TAB) {
  1198.                                 //2.99 970319 TDのALIGNの変更がすぐに画面に反映されるようにした
  1199.                                 PLUGTAB* plug = plug1;
  1200.                                 int modeAlign = ALIGN_LEFT;
  1201.                                 mchar* p = stristr(szResult,"align");
  1202.                                 if (p) {
  1203.                                     p += strlen("align");
  1204.                                     if (*p == '=') {
  1205.                                         p++;
  1206.                                         if (strimatch(p,"right")) {
  1207.                                             modeAlign = ALIGN_RIGHT;
  1208.                                         } else if (strimatch(p,"center")) {
  1209.                                             modeAlign = ALIGN_CENTER;
  1210.                                         }
  1211.                                     }
  1212.                                 }
  1213.                                 plug->modeAlign = modeAlign;
  1214.                                 plug->cxIndent = 0;
  1215.                             }
  1216.                             //
  1217.                             txDeleteChar(text);
  1218.                             txInsertPlug(text,plug1);
  1219.                             txLeft(text);
  1220.                             //
  1221.                             if (!fNoFlush) htmlFlushCurTag(text);//2.97 970222 
  1222.                             ret = TRUE;
  1223.                         }
  1224.                         txSetDisp(text);
  1225.                     } else {
  1226.                         ////err
  1227.                     }
  1228.                 }
  1229.             }
  1230.         }
  1231.     } else {
  1232.         if (txGetChar(text) != '<') {
  1233.             if (!txSearchEx(text,"<",SEARCH_PREV|SEARCH_NOSELECT)) return FALSE;
  1234.         }
  1235.         txstr szline;
  1236.         txGetParaRear(text,szline);
  1237.         mchar* p = strchr(szline,'>');
  1238.         if (p) {
  1239.             p[1] = 0;
  1240. //            information(szline);
  1241.             if (tagEditAtr(text,szline,szResult,NULL)) {
  1242.                 txSetUndisp(text);
  1243.                 {
  1244.                     txDeleteBytes(text,strlen(szline));
  1245.                     txCurInsertBuff(text,szResult,strlen(szResult));
  1246.                     ret = TRUE;
  1247.                 }
  1248.                 txSetDisp(text);
  1249.             }
  1250.         }
  1251.     }
  1252.     return ret;
  1253. }
  1254.  
  1255. BOOL TXCMDBASE uiPropertyTag(TX* text)
  1256. {
  1257.     if (txGetCurPlugmode(text) == PLUG_LINK) {
  1258.         return call("word.txuiLink");
  1259.     } else {
  1260.         IFILE adr = txGetAddress(text);
  1261.         IFILE adrCurscreen = txGetAddressCurscreen(text);
  1262.         BOOL fMove = FALSE;
  1263.         PLUGTAB* plug;
  1264.         if (
  1265.             text->editmode &&
  1266.             !txIsCurReturn(text) && //2.99C 970326 表の改行の上では表のプロパティは開かないようにした
  1267.             (plug = txIsCurParaIncludeTable(text))
  1268.         ) {
  1269.             //2.99 970319 <TD>のプロパティがわかりにくかった
  1270.             if (txGetCurPlugmode(text) == PLUG_TAB) {
  1271.                 information("テーブルタグ<TD>,<TH>のプロパティを開くには、プロパティを開きたいセルの中の文字にカーソルを合わせて「書式|タグのプロパティ」を実行してください。");
  1272.                 return FALSE;// カーソルが縦線上なら何もしない。
  1273.             }
  1274.             PLUGHTMLTAG* plugNow = txGetCurPlug(text);//2.99C 970326 
  1275. #if 1//2.99H 970405 
  1276.             if (
  1277.                 plugNow &&
  1278.                 plugNow->head.modePlug == PLUG_HTML_TAG
  1279.             ) {
  1280.                 //2.99H 970405 表の中のHTMLタグのプロパティ編集ができなかった
  1281.             } else {
  1282.                 fMove = TRUE;
  1283.                 txSetUndisp(text);
  1284.                 text->fUndispCursor++;//2.99C 970326 
  1285.                 //
  1286.                 txJumpParaTop(text);
  1287.                 while(1) {
  1288.                     if (txIsCurReturn(text)) break;
  1289.                     if (txGetCurPlug(text) == plug) break;
  1290.                     if (!txRight(text)) break;
  1291.                 }
  1292.             }
  1293. #else
  1294.             if (
  1295.                 plugNow &&
  1296.                 plugNow->head.modePlug == PLUG_HTML_TAG &&
  1297.                 plugNow->tag == TAG_TR
  1298.             ) {
  1299.                 //2.99C 970326 <TR>タグの上で<TD>のプロパティが開くことがあった
  1300.             } else {
  1301.                 fMove = TRUE;
  1302.                 txSetUndisp(text);
  1303.                 text->fUndispCursor++;//2.99C 970326 
  1304.                 //
  1305.                 txJumpParaTop(text);
  1306.                 while(1) {
  1307.                     if (txIsCurReturn(text)) break;
  1308.                     if (txGetCurPlug(text) == plug) break;
  1309.                     if (!txRight(text)) break;
  1310.                 }
  1311.             }
  1312. #endif
  1313.         }
  1314.         BOOL ret = _uiPropertyTag(text,FALSE);
  1315.         if (fMove) {
  1316.             txJumpAddress(text,adr);
  1317.             txSetLyCurscreen(text,adrCurscreen);
  1318.             text->fUndispCursor--;//2.99C 970326 
  1319.             txSetDisp(text);
  1320.         }
  1321.         return ret;
  1322.     }
  1323. }
  1324.  
  1325. //## new html file
  1326.  
  1327. permanent txstr p_szNewpage(500,"<WZHTMLNEW ページタイトル=homepage>");
  1328.  
  1329. #define NP_TITLE        0    // ページタイトル
  1330. #define NP_BACKGROUND    1    // 背景画像
  1331. #define NP_BGCOLOR        2    // 背景色
  1332. #define NP_TEXT            3    // テキスト色
  1333. #define NP_LINK            4    // ホットテキスト色
  1334. #define NP_VLINK        5    // 参照済み色
  1335. #define NP_ALINK        6    // クリック時の色
  1336. #define NP_BASEFONT        7    // 基準フォントサイズ
  1337. #define NP_TARGET        8    // ターゲットフレーム
  1338. #define NP_URL            9    // 基準URL
  1339.  
  1340. #define data(i)            (ana->tdata[i].szfilename)
  1341. #define dataExist(i)    (ana->tdata[i].fExist)
  1342.  
  1343. static void datainsert(TX* text,mchar* szCaption,int id,TAGEDITATRARG* ana)
  1344. {
  1345.     if (dataExist(id)) {
  1346.         txInsertChar(text,' ');
  1347.         txInsert(text,szCaption);
  1348.         txInsert(text,"=\"");
  1349.         txInsert(text,data(id));
  1350.         txInsertChar(text,'"');
  1351.     }
  1352. }
  1353.  
  1354. BOOL TXAPI uiNewPage(TX* text)
  1355. {
  1356. //「新規作成 - HTML」ダイアログ
  1357. //2.99C 970326 new
  1358.     BOOL ret = FALSE;
  1359.     txstr szResult(500);
  1360.     TAGEDITATRARG _ana;
  1361.     TAGEDITATRARG* ana = &_ana;
  1362.     if (tagEditAtr(text,p_szNewpage,szResult,ana)) {
  1363.         p_szNewpage = szResult;
  1364. //information(szResult);
  1365.         //
  1366.         int editmode0 = text->editmode;
  1367.         txSetEditmode(text,0);
  1368.         txSetUndisp(text);
  1369.         //
  1370.         txInsertf(text,"<HTML>\n<HEAD>\n<!--MadeByWZ-->\n");
  1371.         txInsertf(text,"<TITLE>%s</TITLE>\n",data(NP_TITLE));
  1372.         //
  1373.         if (dataExist(NP_URL) || dataExist(NP_TARGET)) {
  1374.             txInsert(text, "<BASE");
  1375.             datainsert(text,"URL",NP_URL,ana);
  1376.             datainsert(text,"TARGET",NP_TARGET,ana);
  1377.             txInsert(text,">");
  1378.         }
  1379.         txInsert(text,"</HEAD>\n");
  1380.         //
  1381.         txInsert(text,"<BODY");
  1382.             datainsert(text,"BACKGROUND",NP_BACKGROUND,ana);
  1383.             datainsert(text,"BGCOLOR",NP_BGCOLOR,ana);
  1384.             datainsert(text,"TEXT",NP_TEXT,ana);
  1385.             datainsert(text,"LINK",NP_LINK,ana);
  1386.             datainsert(text,"VLINK",NP_VLINK,ana);
  1387.             datainsert(text,"ALINK",NP_ALINK,ana);
  1388.         txInsert(text, ">");
  1389.         //
  1390.         if (dataExist(NP_BASEFONT)) txInsertf(text,"<BASEFONT SIZE=%s>\n",data(NP_BASEFONT));
  1391.         txInsert(text,"\n\n</BODY>\n</HTML>\n");
  1392.         //
  1393.         txPrevPara(text);txPrevPara(text);txPrevPara(text);
  1394.         txSetEditmode(text,editmode0);
  1395.         if (editmode0) txCurInsertReturn(text);
  1396.         txSetDisp(text);
  1397.         ret = TRUE;
  1398.     }
  1399.     return ret;
  1400. }
  1401.  
  1402. //##tag base insert
  1403.  
  1404. BOOL TXAPI txInsertHtmlSzTag(TX* text,mchar* szTag,int tag)
  1405. {
  1406.     if (text->editmode) {
  1407.         int cch = strlen(szTag) + 1;
  1408.         PLUGHTMLTAG* plug = plugatrNewEx(text,PLUG_HTML_TAG,cch);
  1409.         if (plug) {
  1410.             plug->cchTagAlloc = cch;
  1411.             plug->tag = tag;
  1412.             if (tag == TAG_COMMENT) {
  1413.                 //2.99D 970331 <!-- -->は特別扱い
  1414.                 plug->fTagTop = (szTag[0] == '<');
  1415.             } else {
  1416.                 plug->fTagTop = (szTag[1] != '/');
  1417.             }
  1418.             strcpy(plug->szTag,szTag);
  1419.             txInsertPlug(text,plug);
  1420. ///            txDispAll(text);
  1421.             return TRUE;
  1422.         }
  1423.     } else {
  1424.         txInsert(text,szTag);
  1425.         return TRUE;
  1426.     }
  1427.     return FALSE;
  1428. }
  1429.  
  1430. BOOL TXAPI txInsertTag(TX* text,mchar* szline)
  1431. {
  1432. //2.99 970319 
  1433.     mchar* p = strchr(szline,'<');
  1434.     if (p) {
  1435.         int paramode = 0;//2.99 970319 
  1436.         // 1...シングルタグの場合はタグの前で改行。ペアタグの場合は、開始タグの前と終了タグの後で改行
  1437.         // 2...シングルタグの場合はタグの後で改行。
  1438.         // 3...シングルタグの場合はタグの前後で改行。ペアタグの場合、開始タグの前後、終了タグの前後で改行
  1439.         mchar *pend = strchr(szline,'>');
  1440.         if (pend) {
  1441.             BOOL fSingle = (pend[1] != '-');
  1442.             pend[1] = 0;
  1443.             mchar* szTag = p;
  1444.             txstr szBuff;//2.99C 970326 
  1445.             {//2.99C 970326 IMG_DYNSRC対応
  1446.                 mchar* p = strchr(szTag,'_');
  1447.                 if (p) {
  1448.                     szBuff = szTag;
  1449.                     szBuff[p - szTag] = ' ';
  1450.                     szBuff[pend - szTag] = 0;
  1451.                     szBuff += "=\"\">";
  1452.                     szTag = szBuff;
  1453.                 }
  1454.             }
  1455.             int tag = tagFromStr(szTag);
  1456.             mchar* szTagEnd = pend + 2;    // 終了タグ
  1457.             {//2.99 970320 for アルファベット順
  1458.                 mchar* p = strchr(szTagEnd,'>');
  1459.                 if (p) p[1] = 0;
  1460.             }
  1461.             switch(tag) {
  1462.                 case TAG_OL:
  1463.                 case TAG_DL:
  1464.                 case TAG_UL:
  1465.                 case TAG_BLOCKQUOTE:
  1466.                 case TAG_SCRIPT://2.99C 970326 
  1467.                 case TAG_IECOMMENT://2.99C 970326 
  1468.                 case TAG_MAP://2.99C 970326 
  1469.                 case TAG_APPLET://2.99C 970326 
  1470.                 case TAG_OBJECT://2.99C 970326 
  1471.                 case TAG_NOFRAME://2.99C 970326 
  1472.                 case TAG_IFRAME://2.99C 970326 
  1473.                 case TAG_SELECT: paramode = 3;break;
  1474.             }
  1475.             switch(tag) {
  1476.                 case TAG_P:
  1477.                 case TAG_H:
  1478.                 case TAG_LEFT:
  1479.                 case TAG_CENTER:
  1480.                 case TAG_RIGHT:
  1481.                 case TAG_OPTION: paramode = 1;break;
  1482.             }
  1483.             switch(tag) {//2.99D 970331 タグの挿入:<BR>の後で改行を入れるようにした
  1484.                 case TAG_BR: paramode = 2;break;
  1485.             }
  1486.             //
  1487.             txSetUndisp(text);
  1488.             if (fSingle) {
  1489.                 if (text->fClip) {
  1490.                     txSelectDelete(text);
  1491.                 }
  1492.                 if ((paramode == 1 || paramode == 3) && !txIsCurParaTop(text)) txInsertReturn(text);//2.99 970319 
  1493.                 txInsertHtmlSzTag(text,szTag,tag);
  1494.                 if (paramode >= 2 && !txIsCurReturn(text)) txInsertReturn(text);//2.99 970319 
  1495.             } else {
  1496.                 if (text->fClip) {
  1497.                     IFILE adr = txGetAddressSelectTop(text);
  1498.                     IFILE adrEnd = txGetAddressSelectEnd(text);
  1499.                     // 終了タグ
  1500.                     txJumpAddress(text,adrEnd);
  1501.                     if (paramode == 3) txInsertReturn(text);//2.99 970319 
  1502.                     txInsertHtmlSzTag(text,szTagEnd,tag);
  1503.                     if (paramode && !txIsCurParaTop(text)) {
  1504.                         //2.99 970319 
  1505.                         txInsertReturn(text);
  1506.                         txLeft(text);
  1507.                     }
  1508.                     txSelectEx(text,CLIP_CHAR);
  1509.                     // 開始タグ
  1510.                     txJumpAddress(text,adr);
  1511.                     if (paramode && !txIsCurParaTop(text)) txInsertReturn(text);//2.99 970319 
  1512.                     txInsertHtmlSzTag(text,szTag,tag);
  1513.                     if (paramode == 3) {
  1514.                         txInsertReturn(text);//2.99 970319 
  1515.                         txLeft(text);
  1516.                     }
  1517.                     txLeft(text);
  1518.                     //
  1519.                 } else {
  1520.                     // 開始タグ
  1521.                     if (paramode && !txIsCurParaTop(text)) txInsertReturn(text);//2.99 970319 
  1522.                     txInsertHtmlSzTag(text,szTag,tag);
  1523.                     if (paramode == 3) txInsertReturn(text);//2.99 970319 
  1524.                     //2.99C 970326 
  1525.                     IFILE adrCurscreen = txGetAddressCurscreen(text);
  1526.                     IFILE adr = txGetAddress(text);
  1527.                     // 終了タグ
  1528.                     if (paramode == 3 && !txIsCurParaTop(text)) txInsertReturn(text);//2.99 970319 
  1529.                     txInsertHtmlSzTag(text,szTagEnd,tag);
  1530.                     if (paramode && !txIsCurParaTop(text)) txInsertReturn(text);//2.99 970319 
  1531.                     //2.99C 970326 タグの挿入:開始タグと終了タグの間にカーソルを置くようにした
  1532.                     txJumpAddress(text,adr);
  1533.                     txSetLyCurscreen(text,adrCurscreen);
  1534.                 }
  1535.             }
  1536.             if (text->fClip) text->fClipMouse = TRUE;
  1537.             txSetDisp(text);
  1538.         }
  1539.     }
  1540.     return TRUE;
  1541. }
  1542.  
  1543. BOOL TXCMDBASE uiInsertTagComment(TX* text)
  1544. {
  1545. // コメントを挿入
  1546.     HDIALOG hd = dialog("コメント");
  1547.     txstr sz;
  1548.     dialogStr(hd,"コメント(&C):",sz,10,30);
  1549.     if (dialogOpen(hd)) {
  1550. #if 1//2.99D 970331 新コメントに対応
  1551.         txInsertHtmlSzTag(text,"<!--",TAG_COMMENT);
  1552.         txInsert(text,sz);
  1553.         txInsertHtmlSzTag(text,"-->",TAG_COMMENT);
  1554.         return TRUE;
  1555. #else
  1556.         sz = "<!-- " + sz;
  1557.         sz += " -->";
  1558.         return txInsertHtmlSzTag(text,sz,TAG_COMMENT);
  1559. #endif
  1560.     }
  1561.     return FALSE;
  1562. }
  1563.  
  1564. BOOL TXCMDBASE insertTag(mchar* szTag)
  1565. {
  1566. // シングルタグの挿入
  1567. // szTagは、"WBR"のように指定
  1568. // 「html.insertTag([WBR])」に様にコマンド指定してメニューに割り付けられます。
  1569. //2.99C 970326 new
  1570.     txstr szline;
  1571.     szline = "<";
  1572.     szline += szTag;
  1573.     szline += ">";
  1574.     return txInsertTag(text,szline);
  1575. }
  1576.  
  1577. BOOL TXCMDBASE insertTagContainer(mchar* szTag)
  1578. {
  1579. // コンテナタグの挿入
  1580. // szTagは、"P align=center"のように指定
  1581. // 「html.insertTagContainer([P align=center])」に様にコマンド指定してメニューに割り付けられます。
  1582. //2.99C 970326 new
  1583.     txstr szline;
  1584.     szline = "<";
  1585.     szline += szTag;
  1586.     szline += ">-</";
  1587.     {
  1588.         txstr sz;
  1589.         int len = strGetWordLen(szTag);
  1590.         txstrcpylen(sz,szTag,len);
  1591.         szline += sz;
  1592.         szline += ">";
  1593.     }
  1594. //information(szline);
  1595.     return txInsertTag(text,szline);
  1596. }
  1597.  
  1598. permanent BOOL p_modeUiInsertTag = 0;//2.99 970320 旧p_fAlphabetOrder
  1599. #define IT_CATEGORY    0
  1600. #define IT_LIST    1
  1601. #define IT_DIRECT    2
  1602.  
  1603. static BOOL _uiInsertTagDirect(TX* text,BOOL fSw)
  1604. {
  1605. //2.99C 970327 new
  1606.     HDIALOG hd = dialog("タグの挿入");
  1607.     static BOOL fPair = FALSE;
  1608.     static txstr szTag;
  1609.     dialogSetContexthelp(hd,TRUE);
  1610.     dialogControlHelp(hd,432);
  1611.     dialogStr(hd,"タグ(&T):",szTag,10,30);
  1612.     dialogControlHelp(hd,433);
  1613.     dialogCheck(hd,"閉タグも挿入(&P)",&fPair);
  1614.     //
  1615.     int iddCategory = 0;
  1616.     int iddList = 0;
  1617.     if (fSw) {
  1618.         int cx = 19;
  1619.         dialogLFV(hd);
  1620.         dialogOK(hd,cx);
  1621.         dialogCancel(hd,cx);
  1622.         iddCategory = dialogCmd(hd,"機能順(&C) >>",cx);
  1623.         iddList = dialogCmd(hd,"アルファベット順(&L) >>",cx);
  1624.     }
  1625.     int ret;
  1626.     if (ret = dialogOpen(hd)) {
  1627.         if (ret == iddCategory) {
  1628.             p_modeUiInsertTag = IT_CATEGORY;
  1629.             return -1;
  1630.         } else if (ret == iddList) {
  1631.             p_modeUiInsertTag = IT_LIST;
  1632.             return -1;
  1633.         } else {
  1634.             if (fPair) {
  1635.                 return insertTagContainer(szTag);
  1636.             } else {
  1637.                 return insertTag(szTag);
  1638.             }
  1639.         }
  1640.     }
  1641.     return FALSE;
  1642. }
  1643.  
  1644. //2.99C 970327 new
  1645. BOOL TXCMD uiInsertTagDirect(TX* text)
  1646. {
  1647. // タグを直接入力して挿入
  1648.     return _uiInsertTagDirect(text,FALSE);
  1649. }
  1650.  
  1651. //2.97B 970303 new
  1652. insertP
  1653. {
  1654. // <P>を挿入
  1655. #if 1///3.00A 970427 <P>の挿入を、改行+<P>に。テキスト->体裁時の<P>の変換と統一
  1656.     txInsertReturn(text);
  1657.     txInsertHtmlSzTag(text,"<P>",TAG_P);
  1658.     return TRUE;
  1659. #else
  1660.     txInsertHtmlSzTag(text,"<P>",TAG_P);
  1661.     txInsertReturn(text);
  1662.     return TRUE;
  1663. #endif
  1664. }
  1665.  
  1666. static BOOL IsCurParaIncludeTag(TX* text,int tag)
  1667. {
  1668. // 論理行頭からカーソル位置の手前までの間にtagがあるかどうか返す
  1669. //3.00A2 970503 new
  1670.     if (text->editmode == 0) return FALSE;
  1671.     IFILE paraTop = txGetParaTop(text);
  1672.     if (paraTop < text->temp1) paraTop = text->temp1;
  1673.     IMEM off = paraTop - text->temp1;
  1674.     {
  1675.         mchar* p = text->buff + off;
  1676.         IMEM cb = text->cur0 - off;
  1677.         for (;cb--;p++) {
  1678.             if (*p == CHAR_PLUG) {
  1679.                 CHARATR charatr;
  1680.                 charatrRead(text,text->temp1 + (p - text->buff),&charatr);
  1681.                 PLUGHTMLTAG* plug = plugatrRead(text,charatrGetPlug(charatr));
  1682.                 if (plug->head.modePlug == PLUG_HTML_TAG) {
  1683.                     if (plug->tag == tag) return TRUE;
  1684.                 }
  1685.             }
  1686.         }
  1687.     }
  1688.     return FALSE;
  1689. }
  1690.  
  1691.  
  1692. //2.97B 970303 new
  1693. insertBR
  1694. {
  1695. // <BR>を挿入
  1696.     txInsertHtmlSzTag(text,"<BR>",TAG_BR);
  1697.     if (text->editmode == 0 && !text->fOverWrite) {
  1698.         //2.99D 970401 insertBRでオートインデントが効くようにした
  1699.         txWriteReturn(text);
  1700.     } else {
  1701. #if 1//3.00A 970427 <BR>の挿入で、<Table>,<LI>内では改行しないようにした
  1702.         PARAATR paraatr;
  1703.         paraatrRead(text,text->npara,¶atr);
  1704.         if (
  1705.             paraatr.fArticle ||
  1706.             txIsCurParaIncludeTable(text) ||
  1707.             IsCurParaIncludeTag(text,TAG_DT) ||    //3.00A2 970503 <BR>の挿入で、<DT>,<DD>内では改行しないようにした
  1708.             IsCurParaIncludeTag(text,TAG_DD)    //3.00A2 970503 
  1709.         ) {
  1710.             // 改行しない
  1711.         } else {
  1712.             txInsertReturn(text);
  1713.         }
  1714. #else
  1715.         txInsertReturn(text);
  1716. #endif
  1717.     }
  1718.     return TRUE;
  1719. }
  1720.  
  1721. //2.99 970320 
  1722. extern "paraform" void TXAPI txInsertNspace(TX* text,int nspace,BOOL fJspace);
  1723.  
  1724. static BOOL _uiInsertTag(TX* textTarget)
  1725. {
  1726. // HTMLのタグを挿入します。
  1727. // 挿入したタグの解釈はしません。
  1728. //2.97A 970302 new
  1729. //2.99 970320 renew 機能順/アルファベット順が選択できるようにした
  1730.     static int _isel;
  1731.     int modeHtml = text->share->config.modeHtml;
  1732.     int lchLine = CCHWORD;//2.99 970320 
  1733.     int ret = 0;
  1734.     TX _txBody;
  1735.     TX* text = &_txBody;
  1736.     if (txInit(text,NULL)) {
  1737.         // 設定がなくても正常に動作するように
  1738.         strcpy(text->tsztitle[0],".");
  1739.         strcpy(text->tsztitle[1],"..");
  1740.         strcpy(text->tsztitle[2],"");
  1741.         //
  1742.         mchar* sz;
  1743.         for (int i = 0;sz = _tszfh[i];i++) {
  1744.             mchar* p = sz;
  1745.             if (*p == '.') {
  1746.                 if (p_modeUiInsertTag == IT_CATEGORY) {
  1747.                     txInsert(text,p);
  1748.                     txInsertReturn(text);
  1749.                 }
  1750.             } else {
  1751.                 if (*p == '[') {
  1752.                     if (!strnicmp(p,"[R]",3)) continue;
  1753.                     p += strGetWordLen(p);
  1754.                     p = strGetWordTop(p);
  1755.                 }
  1756.                 mchar szTag[CCHWORD];
  1757.                 int len = strGetWordLen(p);
  1758.                 sstrcpylen(szTag,p,len);
  1759.                 p += len;
  1760.                 p = strGetWordTop(p);
  1761.                 //
  1762.                 mchar szCaption[CCHWORD] = {0};
  1763.                 int len = strGetWordLen(p);
  1764.                 if (*p == '[' && len >= 2) {
  1765.                     sstrcpylen(szCaption,p+1,len-2);
  1766.                     p += len;
  1767.                 }
  1768.                 //
  1769.                 BOOL fEnable = TRUE;
  1770.                 BOOL fSingle = FALSE;
  1771.                 while(1) {
  1772.                     p = strGetWordTop(p);
  1773.                     int len = strGetWordLen(p);
  1774.                     if (!*p) break;
  1775.                     if (*p == '[') {
  1776.                         if (!strnicmp(p,"[IE]",4)) {
  1777. #if 1//2.99C 970326 
  1778.                             if (modeHtml == HTML_IE || modeHtml == HTML_IENN) {
  1779.                             } else {
  1780.                                 fEnable = FALSE;
  1781.                                 break;
  1782.                             }
  1783. #else
  1784.                             if (modeHtml != HTML_IE) {
  1785.                                 fEnable = FALSE;
  1786.                                 break;
  1787.                             }
  1788. #endif
  1789.                         } else if (!strnicmp(p,"[NN]",4)) {
  1790. #if 1//2.99C 970326 
  1791.                             if (modeHtml == HTML_NN || modeHtml == HTML_IENN) {
  1792.                             } else {
  1793.                                 fEnable = FALSE;
  1794.                                 break;
  1795.                             }
  1796. #else
  1797.                             if (modeHtml != HTML_NN) {
  1798.                                 fEnable = FALSE;
  1799.                                 break;
  1800.                             }
  1801. #endif
  1802.                         } else if (!strnicmp(p,"[!IE]",5)) {//2.99E 970403 
  1803.                             if (modeHtml == HTML_IE) {
  1804.                                 fEnable = FALSE;
  1805.                                 break;
  1806.                             }
  1807.                         } else if (!strnicmp(p,"[S]",3)) {
  1808.                             fSingle = TRUE;
  1809.                         }
  1810.                     }
  1811.                     p += len;
  1812.                 }
  1813.                 if (fEnable) {
  1814.                     if (p_modeUiInsertTag == IT_LIST) {
  1815.                         txInsertf(text,"%c <%s>",szTag[0],szTag);
  1816.                         if (!fSingle) {
  1817.                             txInsertf(text,"-</%s>",szTag);
  1818.                         }
  1819.                         txInsertf(text," %s",szCaption);
  1820.                         // sortを高速化するため、行の長さを一定に
  1821.                         int lch = txGetAddress(text) - txGetParaTop(text);
  1822.                         if (lch < lchLine) {
  1823.                             txInsertNspace(text,lchLine - lch,FALSE);
  1824.                         } else if (lch > lchLine) {
  1825.                             txJumpParaTop(text);
  1826.                             txJumpAddress(text,txGetAddress(text) + lchLine);
  1827.                             txDeleteParaEnd(text);
  1828.                             //
  1829.                             int lch = txGetAddress(text) - txGetParaTop(text);
  1830.                             txInsertNspace(text,lchLine - lch,FALSE);
  1831.                         }
  1832.                     } else {
  1833.                         txInsert(text,"..");
  1834.                         if (szCaption[0]) {
  1835.                             txInsertf(text,"%s <%s>",szCaption,szTag);
  1836.                         } else {
  1837.                             txInsertf(text,"%s <%s>",szTag,szTag);
  1838.                         }
  1839.                         if (!fSingle) {
  1840.                             txInsertf(text,"-</%s>",szTag);
  1841.                         }
  1842.                     }
  1843.                     txInsertReturn(text);
  1844.                 }
  1845.             }
  1846.         }
  1847.         if (p_modeUiInsertTag == IT_LIST) {
  1848.             SORTARG sort;
  1849.             structClear(sort);
  1850.             sort.sizeStruct = sizeof(sort);
  1851.             sort.lineTop = 1;
  1852.             sort.lchItem = 10;//2.99 970320 1だとH1,H2のソートが変
  1853.             sort.lchLine = lchLine + 2;
  1854.             txJumpFileEnd(text);
  1855.             sort.lineEnd = text->npara - 1;
  1856.             txSort(text,&sort);
  1857.         }
  1858.         //
  1859. //dialogaText(text,NULL);
  1860.         HDIALOG hd = dialog("タグの挿入");
  1861.         DTRECT r;
  1862.         dialogGetPos(hd,&r);
  1863.         r.cx = DTCX * 40;
  1864.         r.cy = DTCY * 12;
  1865.         if (p_modeUiInsertTag == IT_LIST) {
  1866.             dialogList(hd,NULL,text,40,12);
  1867.         } else {
  1868.             dialogAddTitle(hd,&r);
  1869.         }
  1870.         int cx = 19;
  1871.         int iddOrder;
  1872.         int iddDirect;
  1873.         dialogLFV(hd);
  1874.         dialogOK(hd,cx);
  1875.         dialogCancel(hd,cx);
  1876.         if (p_modeUiInsertTag == IT_LIST) {
  1877.             iddOrder = dialogCmd(hd,"機能順(&C) >>",cx);
  1878.         } else {
  1879.             iddOrder = dialogCmd(hd,"アルファベット順(&L) >>",cx);
  1880.         }
  1881.         iddDirect = dialogCmd(hd,"直接入力(&D) >>",cx);//2.99C 970327 
  1882.         if (p_modeUiInsertTag == IT_LIST) {
  1883.             txJumpNpara(text,_isel + 1);
  1884.             ret = dialogOpen(hd);
  1885.         } else {
  1886.             CHOOSEOUTLINE co;
  1887.             memset(&co,0,sizeof(CHOOSEOUTLINE));
  1888.             co.text = text;
  1889.             co.szhook = NULL;//"\m.dlgprocTemplate";
  1890.             co.iselFirst = _isel;
  1891.             co.fNoTitleHead = TRUE;
  1892.             ret = dialogSelectTitle(hd,&co);
  1893.         }
  1894.         if (ret) {
  1895.             if (ret == iddOrder) {
  1896.                 if (p_modeUiInsertTag == IT_LIST) {
  1897.                     p_modeUiInsertTag = IT_CATEGORY;
  1898.                 } else {
  1899.                     p_modeUiInsertTag = IT_LIST;
  1900.                 }
  1901.                 ret = -1;
  1902.             } else if (ret == iddDirect) {
  1903.                 p_modeUiInsertTag = IT_DIRECT;
  1904.                 ret = -1;
  1905.             } else {
  1906.                 _isel = text->npara - 1;
  1907.                 txstr szline;
  1908.                 txGetPara(text,szline);
  1909.                 mchar* p = szline;
  1910.                 p = strchr(szline,'<');
  1911.                 if (p) {
  1912.                     txInsertTag(textTarget,p);
  1913.                 }
  1914.             }
  1915.         }
  1916.         //
  1917.         txClose(text);
  1918.     }
  1919.     return ret;
  1920. }
  1921.  
  1922. BOOL TXCMDBASE uiInsertTag(TX* textTarget)
  1923. {
  1924. // タグを挿入
  1925. // タグの機能別、アルファベット順、直接入力ができます。
  1926.     int ret = FALSE;
  1927.     while(1) {
  1928.         if (p_modeUiInsertTag == IT_DIRECT) {
  1929.             ret = _uiInsertTagDirect(textTarget,TRUE);
  1930.         } else {
  1931.             ret = _uiInsertTag(textTarget);
  1932.         }
  1933.         if (ret == -1) continue;
  1934.         break;
  1935.     }
  1936.     return ret;
  1937. }
  1938.  
  1939. //##tag special insert
  1940.  
  1941. #define IschReturn(c)        (c==CHAR_LF||c==CHAR_CR||c==CHAR_FF||c==CHAR_EOF)
  1942.  
  1943. static mchar* szFindTagEnd(mchar* p)
  1944. {
  1945.     // pからタグのendを探して返す
  1946.     for (;;p++) {
  1947.         mchar c = *p;
  1948.         if (IschReturn(c)) break;
  1949.         if (c == '>') {
  1950.             p++;
  1951.             break;
  1952.         }
  1953.     }
  1954.     return p;
  1955. }
  1956.  
  1957. BOOL htmlTagInsert(TX* textTarget,mchar* szcmd)
  1958. {
  1959. // szcmdのタグを挿入して、解釈する。
  1960. // <WZSELTEXT>:選択されたテキストを挿入
  1961. // <WZCUR>:カーソルの位置を指定
  1962. // <WZTAGATR>:解釈が終わってから、カーソル位置のタグのプロパティダイアログを表示
  1963.     BOOL fTagPara = FALSE;// defaultはCHARATR tag
  1964.     TX _txBody;
  1965.     TX* text = &_txBody;
  1966.     BOOL fLI = FALSE;//2.99C 970325 <LI>用
  1967.     int len;
  1968.     if (len = strmatch(szcmd,"<WZLI>")) {//2.99C 970325 
  1969.         szcmd += len;
  1970.         fLI = TRUE;
  1971.     }
  1972.     if (txInit(text,NULL)) {
  1973.         BOOL fClip = (stristr(szcmd,"<WZSELTEXT>") && textTarget->fClip);
  1974.         IFILE adr = txGetAddress(textTarget);
  1975.         if (fClip) adr = txGetAddressSelectTop(textTarget);
  1976.         //
  1977.         IFILE adrJump = TXRECORD_ERROR;
  1978.         txInsert(text,szcmd);
  1979.         txJumpFileTop(text);
  1980.         //
  1981.         TX _textDst;
  1982.         TX* textDst = &_textDst;
  1983.         if (txInit(textDst,NULL)) {
  1984.             textDst->fHTML = TRUE;
  1985.             textDst->fForm = TRUE;
  1986.             textDst->fTxsemForceConvert = TRUE;
  1987.             textDst->fTxsemHtmlInside = TRUE;//2.97A 970303 
  1988.             textDst->fDispTag = TRUE;
  1989.             if (textTarget->editmode) txSetEditmode(textDst,1);
  1990.             if (fClip) {
  1991.                 txPrivatePush(textTarget);    // PushはtxInitの後に行う
  1992.             }
  1993.             BOOL fAbort = FALSE;
  1994.             while(1) {
  1995.                 mchar* p = text->buff + text->cur;
  1996.                 if (*p == '<') {
  1997.                     mchar* p1 = szFindTagEnd(p);
  1998.                     int lch = p1 - p;
  1999.                     if (!strnicmp(p,"<WZ",3)) {
  2000.                         // WZタグ
  2001.                         mchar szTag[CCHWORD];
  2002.                         int l = lch;
  2003.                         p += 3;l -= 3;
  2004.                         if (l && p[l-1] == '>') l--;
  2005.                         sstrcpylen(szTag,p,l);
  2006.                         txDeleteBytes(text,lch);
  2007.                         if (!stricmp(szTag,"SELTEXT")) {
  2008.                             if (fClip) {
  2009.                                 if (fLI) {//2.99C 970325 
  2010.                                     TX* text = textDst;
  2011.                                     IFILE adr = txGetAddress(text);
  2012.                                     txClipPaste(text,HCLIP_PRIVATE,TRUE,CLIP_CHAR);
  2013.                                     txJumpAddress(text,adr);
  2014.                                     while(1) {
  2015.                                         if (txIsCurEof(text)) break;
  2016.                                         if (!txInsertHtmlSzTag(text,"<LI>",TAG_LI)) break;
  2017.                                         if (!txNextPara(text)) break;
  2018.                                     }
  2019.                                     txJumpFileEnd(text);
  2020. //dialogaText(text,NULL);
  2021.                                 } else {
  2022.                                     txClipPaste(textDst,HCLIP_PRIVATE,TRUE,CLIP_CHAR);
  2023.                                 }
  2024. //dialogaText(textDst,NULL);
  2025.                             }
  2026.                         } else if (!stricmp(szTag,"CUR")) {
  2027.                             adrJump = txGetAddress(textTarget) + txGetAddress(textDst);
  2028.                         } else if (!stricmp(szTag,"TAGATR")) {
  2029.                             txLeft(textDst);
  2030. #if 1//3.00A2 970504 「書式|色とサイズ」のダイアログのバックに画面サイレントがかかっていた。
  2031.                             {
  2032.                                 int fUndisp = textTarget->fUndisp;
  2033.                                 textTarget->fUndisp = 0;
  2034.                                 txDispTextAll(textTarget);
  2035.                                 int ret = _uiPropertyTag(textDst,TRUE);
  2036.                                 textTarget->fUndisp = fUndisp;
  2037.                                 if (!ret) {
  2038.                                     fAbort = TRUE;
  2039.                                     break;
  2040.                                 }
  2041.                             }
  2042. #else
  2043.                             if (!_uiPropertyTag(textDst,TRUE)) {
  2044.                                 fAbort = TRUE;
  2045.                                 break;
  2046.                             }
  2047. #endif
  2048. #if 1//3.00A 970502 HTMLファイルでテキストモードで「書式|色とサイズ」が変だった
  2049.                             if (txIsWP(textDst)) {
  2050.                                 txRight(textDst);
  2051.                             } else {
  2052.                                 txSearchEx(textDst,">",0);
  2053.                                 txRight(textDst);
  2054.                             }
  2055. #else
  2056.                             txRight(textDst);
  2057. #endif
  2058.                         }
  2059.                     } else {
  2060.                         mchar szTag[CCHWORD];
  2061.                         sstrcpylen(szTag,p,lch);
  2062.                         int tag = tagFromStr(szTag);
  2063.                         if (tagIsParaatr(tag)) {
  2064.                             fTagPara = TRUE;    // PARAATR tag
  2065.                         }
  2066.                         if (!txInsertHtmlSzTag(textDst,szTag,tag)) {
  2067.                             ////err
  2068.                             break;
  2069.                         }
  2070.                         txRightBytes(text,lch);
  2071.                     }
  2072.                 } else {
  2073.                     TXCHAR ch = txReadChar(text);
  2074.                     if (ch == CHAR_EOF || ch == 0) break;
  2075.                     txInsertChar(textDst,ch);
  2076.                 }
  2077.             }
  2078.             if (!fAbort) {
  2079.                 txSelectDelete(textTarget);
  2080.                 txInsertText(textTarget,textDst);
  2081.             }
  2082.             txClose(textDst);
  2083.             //
  2084.             if (fClip) {
  2085.                 clipDeleteTop(HCLIP_PRIVATE);
  2086.             }
  2087. //dialogaText(textTarget,NULL);
  2088.             if (!fAbort) {
  2089.                 IFILE adrEnd = txGetAddress(textTarget);
  2090. #if 1//3.00A 970502 HTMLファイルでテキストモードで[太字]などを実行するとカーソルキーでカーソルが移動しなくなった
  2091.                 if (txIsWP(textTarget)) {
  2092.                     txHtmlFlushArea(textTarget,adr,adrEnd,fTagPara ? TAG_H : TAG_B,TRUE);
  2093.                 } else {
  2094.                     txSelectEx(textTarget,CLIP_CHAR);
  2095.                     txJumpAddress(textTarget,adr);
  2096.                 }
  2097. #else
  2098.                 txHtmlFlushArea(textTarget,adr,adrEnd,fTagPara ? TAG_H : TAG_B,TRUE);
  2099. #endif
  2100.                 if (!fClip) {
  2101.                     txSelectQuit(textTarget);
  2102.                     if (adrJump != TXRECORD_ERROR) txJumpAddress(textTarget,adrJump);
  2103.                 }
  2104.             }
  2105.             txSetDisp(textTarget);
  2106.             if (fClip) textTarget->fClipMouse = TRUE;//2.97A 970301 
  2107.         }
  2108.         txClose(text);
  2109.     }
  2110.     return TRUE;
  2111. }
  2112.  
  2113. static void txInsertTextAndSelect(TX* textTarget,TX* text)
  2114. {
  2115.     IFILE adr = txGetAddress(textTarget);
  2116.     txInsertText(textTarget,text);
  2117.     txSelectEx(textTarget,CLIP_CHAR);
  2118.     txJumpAddress(textTarget,adr);
  2119. }
  2120.  
  2121. #if 0
  2122. static int txGetCurTag(TX* text)
  2123. {
  2124.     if (text->editmode) {
  2125.         if (txGetChar(text) == CHAR_PLUG) {
  2126.             PLUGHTMLTAG* plug = txGetCurPlug(text);
  2127.             if (plug->head.modePlug == PLUG_HTML_TAG) {
  2128.                 return tagFromStr(plug->szTag);
  2129.             }
  2130.         }
  2131.         return 0;
  2132.     } else {
  2133.         if (txGetChar(text) == '<') {
  2134.             return tagFromStr(text->buff + text->cur);
  2135.         }
  2136.         return 0;
  2137.     }
  2138. }
  2139. #endif
  2140.  
  2141. static int _htmlTagDelete(TX* textTarget,mchar* szTag,BOOL fDeletePair)
  2142. {
  2143. // !fDeletePair : 範囲選択内のszTagをすべて削除
  2144. // fDeletePair  : 範囲選択内のszTagペアを一つ削除
  2145. // szTagは、"<P>"のように指定。
  2146. // szTagがNULLなら、全部削除
  2147. // 削除した個数を返す
  2148.     int tagDel = szTag ? tagFromStr(szTag) : 0;
  2149.     int nDel = 0;
  2150.     if (textTarget->fClip) {
  2151.         BOOL fDelTop = FALSE;
  2152.         BOOL fDelEnd = FALSE;
  2153.         TX _txBody;
  2154.         TX* text = &_txBody;
  2155.         if (txInit(text,NULL)) {
  2156.             text->fHTML = TRUE;
  2157.             text->fForm = TRUE;
  2158.             text->fTxsemForceConvert = TRUE;
  2159.             text->fTxsemHtmlInside = TRUE;//2.97A 970303 
  2160.             text->fDispTag = TRUE;
  2161. #if 1//3.00A2 970503 
  2162.             if (textTarget->editmode) {
  2163.                 txSetEditmode(text,1);
  2164.             }
  2165. #else
  2166.             txSetEditmode(text,1);
  2167. #endif
  2168.             //
  2169.             txPrivatePush(textTarget);// txInitの前にPushするとATRがPasteされない
  2170.             txClipPaste(text,HCLIP_PRIVATE,TRUE,CLIP_CHAR);
  2171.             clipDeleteTop(HCLIP_PRIVATE);
  2172. //dialogaText(text,NULL);
  2173.             txJumpFileTop(text);
  2174. #if 1//3.00A2 970503 テキストモードのHTMLファイル編集で、「題|本文」を指定しても<H1>が削除されなかった
  2175.             while(1) {
  2176.                 BOOL f = FALSE;
  2177.                 int tag = 0;
  2178.                 BOOL fTagTop;
  2179.                 if (text->editmode == 0) {
  2180.                     if (txGetChar(text) == '<') {
  2181.                         mchar* p = text->buff + text->cur;
  2182.                         tag = tagFromStr(p);
  2183.                         fTagTop = !(p[1] == '/');
  2184.                     }
  2185.                 } else {
  2186.                     if (txGetChar(text) == CHAR_PLUG) {
  2187.                         PLUGHTMLTAG* plug = txGetCurPlug(text);
  2188.                         if (plug->head.modePlug == PLUG_HTML_TAG) {
  2189.                             tag = tagFromStr(plug->szTag);
  2190.                             fTagTop = plug->fTagTop;
  2191.                         }
  2192.                     }
  2193.                 }
  2194.                 if (tag) {
  2195.                     if (tag == tagDel || tagDel == 0) {
  2196.                         if (fDeletePair) {
  2197.                             if (fTagTop) {
  2198.                                 if (!fDelTop) {
  2199.                                     fDelTop = TRUE;
  2200.                                     f = TRUE;
  2201.                                 }
  2202.                             } else {
  2203.                                 if (!fDelEnd) {
  2204.                                     fDelEnd = TRUE;
  2205.                                     f = TRUE;
  2206.                                 }
  2207.                             }
  2208.                         } else {
  2209.                             f = TRUE;
  2210.                         }
  2211.                     }
  2212.                 }
  2213.                 if (f) {
  2214.                     if (txGetChar(text) == CHAR_PLUG) {
  2215.                         txDeleteChar(text);
  2216.                     } else {
  2217.                         // テキストのタグを削除
  2218.                         while(1) {
  2219.                             if (txIsCurReturn(text)) break;
  2220.                             if (txGetChar(text) == '>') {
  2221.                                 txDeleteChar(text);
  2222.                                 break;
  2223.                             }
  2224.                             txDeleteChar(text);
  2225.                         }
  2226.                     }
  2227.                     nDel++;
  2228.                 } else {
  2229.                     if (!txRight(text)) break;
  2230.                 }
  2231.             }
  2232. #else
  2233.             while(1) {
  2234.                 BOOL f = FALSE;
  2235.                 if (txGetChar(text) == CHAR_PLUG) {
  2236.                     PLUGHTMLTAG* plug = txGetCurPlug(text);
  2237.                     if (plug->head.modePlug == PLUG_HTML_TAG) {
  2238.                         int tag = tagFromStr(plug->szTag);
  2239.                         if (tag == tagDel || tagDel == 0) {
  2240.                             if (fDeletePair) {
  2241.                                 if (plug->fTagTop) {
  2242.                                     if (!fDelTop) {
  2243.                                         fDelTop = TRUE;
  2244.                                         f = TRUE;
  2245.                                     }
  2246.                                 } else {
  2247.                                     if (!fDelEnd) {
  2248.                                         fDelEnd = TRUE;
  2249.                                         f = TRUE;
  2250.                                     }
  2251.                                 }
  2252.                             } else {
  2253.                                 f = TRUE;
  2254.                             }
  2255.                         }
  2256.                     }
  2257.                 }
  2258.                 if (f) {
  2259.                     txDeleteChar(text);
  2260.                     nDel++;
  2261.                 } else {
  2262.                     if (!txRight(text)) break;
  2263.                 }
  2264.             }
  2265. #endif
  2266. //dialogaText(text,NULL);
  2267.             if (nDel) {
  2268.                 txSelectDelete(textTarget);
  2269.                 txInsertTextAndSelect(textTarget,text);
  2270.             }
  2271.             txClose(text);
  2272.         }
  2273.     }
  2274.     return nDel;
  2275. }
  2276.  
  2277. static int htmlTagDelete(TX* textTarget,mchar* szTag)
  2278. {
  2279.     return _htmlTagDelete(textTarget,szTag,FALSE);
  2280. }
  2281.  
  2282. //2.99C 970327 new
  2283. BOOL TXCMDBASE clearTag(TX* text)
  2284. {
  2285. // 範囲内のすべてのタグを削除
  2286.     if (!text->fClip) {
  2287.         information("タグをクリアするには、範囲を選択してください");
  2288.         return FALSE;
  2289.     }
  2290.     txSetUndisp(text);
  2291.     IFILE adrCurscreen = txGetAddressCurscreen(text);
  2292.     BOOL ret = htmlTagDelete(text,NULL);
  2293.     txSetLyCurscreen(text,adrCurscreen);
  2294.     txSetDisp(text);
  2295.     return ret;
  2296. }
  2297.  
  2298. static BOOL htmlTagInsertEx(TX* text,mchar* szdel,mchar* szcmd,BOOL fSw)
  2299. {
  2300. // fSw=TRUE : szdelタグが存在したら、削除するだけで挿入しないでFALSEを返す
  2301. // そうでなければTRUEを返す
  2302.     BOOL ret = TRUE;
  2303.     txSetUndisp(text);
  2304.     IFILE adrCurscreen = txGetAddressCurscreen(text);
  2305.     int nDel = htmlTagDelete(text,szdel);
  2306.     if (fSw && nDel) {
  2307.         htmlTagInsert(text,"<WZSELTEXT>");
  2308.         ret = FALSE;
  2309.     } else {
  2310.         htmlTagInsert(text,szcmd);
  2311.     }
  2312.     txSetLyCurscreen(text,adrCurscreen);
  2313.     txSetDisp(text);
  2314.     return ret;
  2315. }
  2316.  
  2317. BOOL txHtmlSet(TX* text,int tag,int arg)
  2318. {
  2319.     BOOL ret = TRUE;
  2320.     BOOL fParaatrTag = tagIsParaatr(tag);
  2321.     if (tag == TAG_LI || tag == TAG_LINUM) fParaatrTag = TRUE;//2.99C 970326 
  2322.     //
  2323.     mchar szTag[CCHTAG];
  2324.     BOOL fClip = text->fClip;
  2325.     txSetUndisp(text);
  2326.     NPARA nparaTop;
  2327.     NPARA nparaEnd;
  2328.     IFILE adrCurscreen = txGetAddressCurscreen(text);
  2329.     if (fParaatrTag) {
  2330.         if (text->fClip) {
  2331.             // 段落単位の範囲選択に変換
  2332.             IFILE adrTop = txGetAddressSelectTop(text);
  2333.             IFILE adrEnd = txGetAddressSelectEnd(text);
  2334.             txJumpAddress(text,adrTop);
  2335.             txJumpParaTop(text);
  2336.             nparaTop = text->npara;
  2337.             txSelectEx(text,CLIP_CHAR);
  2338.             txJumpAddress(text,adrEnd);
  2339.             if (txIsCurParaTop(text)) {
  2340.                 txPrevPara(text);
  2341.             }
  2342.             txJumpParaEnd(text);
  2343.             nparaEnd = text->npara;
  2344.         } else {
  2345.             txJumpParaTop(text);
  2346.             txSelectEx(text,CLIP_CHAR);
  2347.             txJumpParaEnd(text);
  2348.             nparaTop = nparaEnd = text->npara;
  2349.         }
  2350.     }
  2351.     switch(tag) {
  2352.         case TAG_UL: {
  2353. //            htmlTagDelete(text,"<P>");
  2354. #if 1//3.00A2 970504 HTML体裁モードでの<UL>挿入を改良
  2355.             if (arg < 0) {
  2356.                 txParaatrSet(text,TAG_INDENTADD,(LPVOID)arg);
  2357.                 _htmlTagDelete(text,"<UL>",TRUE);
  2358.             } else {
  2359.                 PARAATR paraatr;
  2360.                 paraatrRead(text,nparaTop,¶atr);
  2361.                 //
  2362.                 txParaatrSet(text,TAG_INDENTADD,(LPVOID)arg);
  2363.                 //
  2364.                 txJumpNpara(text,nparaTop);
  2365.                 tagPrintEx(text,tag,arg,TAG_TOP,szTag);
  2366.                 txInsertHtmlSzTag(text,szTag,tag);
  2367.                 txInsertReturn(text);nparaEnd++;//2.99C 970325 字下げで<UL>に改行を付けるようにした
  2368.                 paraatrWrite(text,nparaTop,¶atr);
  2369.                 //
  2370.                 txJumpNpara(text,nparaEnd);
  2371.                 txJumpParaEnd(text);
  2372.                 txInsertReturn(text);nparaEnd++;//2.99C 970325 
  2373.                 tagPrintEx(text,tag,arg,TAG_END,szTag);
  2374.                 txInsertHtmlSzTag(text,szTag,tag);
  2375.                 paraatrWrite(text,nparaEnd,¶atr);
  2376.             }
  2377. #else
  2378.             txParaatrSet(text,TAG_INDENTADD,(LPVOID)arg);
  2379.             if (arg < 0) {
  2380.                 _htmlTagDelete(text,"<UL>",TRUE);
  2381.             } else {
  2382.                 txJumpNpara(text,nparaTop);
  2383.                 tagPrintEx(text,tag,arg,TAG_TOP,szTag);
  2384.                 txInsertHtmlSzTag(text,szTag,tag);
  2385.                 txInsertReturn(text);nparaEnd++;//2.99C 970325 字下げで<UL>に改行を付けるようにした
  2386.                 //
  2387.                 txJumpNpara(text,nparaEnd);
  2388.                 txJumpParaEnd(text);
  2389.                 tagPrintEx(text,tag,arg,TAG_END,szTag);
  2390.                 txInsertReturn(text);nparaEnd++;//2.99C 970325 
  2391.                 txInsertHtmlSzTag(text,szTag,tag);
  2392.             }
  2393. #endif
  2394.             break;
  2395.         }
  2396.         case TAG_H: {
  2397.             // 行末が<BR>なら、<BR>は次行に送るのはうまくいかなかった
  2398.             htmlTagDelete(text,"<H1>");    // <Hn>を削除
  2399.             //
  2400.             PARAATR paraatr;
  2401.             paraatr.modeTitle = arg;
  2402.             txParaatrSet(text,TAG_H,¶atr);
  2403.             //
  2404.             if (arg) {
  2405.                 if (txIsWP(text)) {//3.00A 970502 テキストモードのHTMLファイルで<H1>が2重になった
  2406.                     txJumpNpara(text,nparaTop);
  2407.                     tagPrintEx(text,tag,arg,TAG_TOP,szTag);
  2408.                     txInsertHtmlSzTag(text,szTag,tag);
  2409.                     //
  2410.                     txJumpNpara(text,nparaEnd);
  2411.                     txJumpParaEnd(text);
  2412.                     tagPrintEx(text,tag,arg,TAG_END,szTag);
  2413.                     txInsertHtmlSzTag(text,szTag,tag);
  2414.                 }
  2415.             }
  2416.             break;
  2417.         }
  2418.         case TAG_LEFT:
  2419.         case TAG_CENTER:
  2420.         case TAG_RIGHT: {
  2421. #if 1    //2.97A 970302 
  2422.     #if 1//2.99 970320 センタリングは<CENTER>を使う。ネスケでは<P align="center">ではちゃんと表示されないため。
  2423.             txParaatrSet(text,tag,0);
  2424.             htmlTagDelete(text,"<P>");
  2425.             htmlTagDelete(text,"<CENTER>");
  2426.             htmlTagDelete(text,"<DIV>");//2.99C 970326 
  2427.             if (tag != TAG_LEFT) {
  2428.                 txJumpNpara(text,nparaTop);
  2429.                 if (tag == TAG_CENTER) {
  2430.                     txInsertHtmlSzTag(text,"<CENTER>",TAG_CENTER);
  2431.                 } else {
  2432.         #if 1//2.99C 970326 右寄せは<DIV ALIGN=RIGHT>を使う。<P ALIGN=RIGHT>は文章しか揃えることができない
  2433.                     txInsertHtmlSzTag(text,"<DIV ALIGN=RIGHT>",TAG_DIV);
  2434.         #else
  2435.                     txInsertHtmlSzTag(text,"<P ALIGN=RIGHT>",TAG_P);
  2436.         #endif
  2437.                 }
  2438.                 //
  2439.                 txJumpNpara(text,nparaEnd);
  2440.                 txJumpParaEnd(text);
  2441.                 if (tag == TAG_CENTER) {
  2442.                     txInsertHtmlSzTag(text,"</CENTER>",TAG_CENTER);
  2443.                 } else {
  2444.         #if 1//2.99C 970326 
  2445.                     txInsertHtmlSzTag(text,"</DIV>",TAG_DIV);
  2446.         #else
  2447.                     txInsertHtmlSzTag(text,"</P>",TAG_P);
  2448.         #endif
  2449.                 }
  2450.             }
  2451.     #else
  2452.             txParaatrSet(text,tag,0);
  2453.             htmlTagDelete(text,"<P>");
  2454.             if (tag != TAG_LEFT) {
  2455.                 txJumpNpara(text,nparaTop);
  2456.                 txInsertHtmlSzTag(
  2457.                     text,
  2458.                     tag == TAG_CENTER ? "<P ALIGN=CENTER>" : "<P ALIGN=RIGHT>",
  2459.                     TAG_P
  2460.                 );
  2461.                 //
  2462.                 txJumpNpara(text,nparaEnd);
  2463.                 txJumpParaEnd(text);
  2464.                 txInsertHtmlSzTag(text,"</P>",TAG_P);
  2465.             }
  2466.     #endif
  2467. #else
  2468.             htmlTagInsertEx(text,"<P>","<P ALIGN=LEFT><WZSELTEXT></P>",FALSE);
  2469. #endif
  2470.             break;
  2471.         }
  2472.         case TAG_TABLE: {
  2473.             ret = FALSE;
  2474.             int x = LOWORD(arg);
  2475.             int y = HIWORD(arg);
  2476.             if (text->editmode) {
  2477.                 mchar *buff = malloc(100 + (x * 9 + 4) * y);
  2478.                 if (buff) {
  2479.                     txSetUndisp(text);
  2480.                     mchar* dst = buff;
  2481.                     strcpy(dst,"<TABLE BORDER>");dst += strlen(dst);
  2482. #if 1//2.99 970319 
  2483.                     for (;y--;) {
  2484.                         strcpy(dst,"<TR>");dst += strlen(dst);
  2485.                         for (int i = 0;i < x;i++) {
  2486.                             strcpy(dst,"<TD>");dst += strlen(dst);
  2487.                         }
  2488.                     }
  2489. #else
  2490.                     for (;y--;) {
  2491.                         for (int i = 0;i < x;i++) {
  2492.                             strcpy(dst,"<TD></TD>");dst += strlen(dst);
  2493.                         }
  2494.                         strcpy(dst,"<TR>");dst += strlen(dst);
  2495.                     }
  2496. #endif
  2497.                     strcpy(dst,"</TABLE>");dst += strlen(dst);
  2498.                     *dst = 0;
  2499.                     txInsertReturn(text);
  2500.                     BOOL ret = htmlTagInsert(text,buff);
  2501.                     txInsertReturn(text);
  2502.                     free(buff);
  2503.                     // 表の頭へ移動
  2504.                     txSelectQuit(text);
  2505.                     while(1) {
  2506.                         if (txIsCurParaIncludeTable(text)) {
  2507.                             break;
  2508.                         } else {
  2509.                             if (!txPrevPara(text)) break;
  2510.                         }
  2511.                     }
  2512.                     while(1) {
  2513.                         if (txIsCurParaIncludeTable(text)) {
  2514.                             if (!txPrevPara(text)) break;
  2515.                         } else {
  2516.                             txNextPara(text);
  2517.                             break;
  2518.                         }
  2519.                     }
  2520.                     txFlushTable(text);
  2521.                     txRight(text);
  2522.                     //
  2523.                     ret = TRUE;
  2524.                     txSetDisp(text);
  2525.                 }
  2526.             } else {
  2527.                 txSetUndisp(text);
  2528.                 {
  2529.                     txInsertReturn(text);
  2530.                     txInsertLine(text,"<TABLE BORDER>");
  2531.                     IFILE adr = txGetAddress(text);
  2532. #if 1//2.99 970319 
  2533.                     if (text->share->config.modeHtmlOutTable) {
  2534.                         for (;y--;) {
  2535.                             txInsert(text,"<TR>");txInsertReturn(text);
  2536.                             for (int i = 0;i < x;i++) {
  2537.                                 txInsertChar(text,CHAR_TAB);
  2538.                                 txInsert(text,"<TD></TD>");//3.00B1 970612 HTMLテキストモード「セルを1行毎に出力」のとき表を挿入すると、</TD>が<TD>として挿入された。
  2539.                                 txInsertReturn(text);
  2540.                             }
  2541.                         }
  2542.                     } else {
  2543.     #if 1//2.99D 970329 テキストモードでのHTMLの表の挿入改良
  2544.                         for (;y--;) {
  2545.                             txInsert(text,"<TR>");
  2546.                             for (int i = 0;i < x;i++) {
  2547.                                 txInsert(text,"<TD>");
  2548.                             }
  2549.                             txInsertReturn(text);
  2550.                         }
  2551.     #else
  2552.                         for (;y--;) {
  2553.                             txInsert(text,"<TR>");txInsertReturn(text);
  2554.                             for (int i = 0;i < x;i++) {
  2555.                                 txInsert(text,"<TD>");
  2556.                             }
  2557.                         }
  2558.     #endif
  2559.                     }
  2560. #else
  2561.                     for (;y--;) {
  2562.                         for (int i = 0;i < x;i++) {
  2563.                             txInsert(text,"<TD></TD>");
  2564.                         }
  2565.                         txInsert(text,"<TR>");txInsertReturn(text);
  2566.                     }
  2567. #endif
  2568.                     txInsertLine(text,"</TABLE>");
  2569.                     txJumpAddress(text,adr);
  2570.                 }
  2571.                 txSetDisp(text);
  2572.             }
  2573.             break;
  2574.         }
  2575.         case TAG_B: {
  2576.             // 選択されてないときに、タグが解釈されないのは仕様
  2577.             ret = htmlTagInsertEx(text,"<B>","<B><WZCUR><WZSELTEXT></B>",TRUE);
  2578.             break;
  2579.         }
  2580.         case TAG_I: {
  2581.             ret = htmlTagInsertEx(text,"<I>","<I><WZCUR><WZSELTEXT></I>",TRUE);
  2582.             break;
  2583.         }
  2584.         case TAG_U: {
  2585.             ret = htmlTagInsertEx(text,"<U>","<U><WZCUR><WZSELTEXT></U>",TRUE);
  2586.             break;
  2587.         }
  2588.         case TAG_FONT: {
  2589.             htmlTagInsertEx(text,"<FONT>","<FONT><WZTAGATR><WZCUR><WZSELTEXT></FONT>",FALSE);
  2590.             break;
  2591.         }
  2592.         case TAG_LI: {//2.99C 970325 
  2593.             htmlTagDelete(text,"<UL>");
  2594.             htmlTagDelete(text,"<OL>");
  2595.             ret = htmlTagInsertEx(text,"<LI>","<WZLI><UL><WZCUR><WZSELTEXT></UL>",TRUE);
  2596.             break;
  2597.         }
  2598.         case TAG_LINUM: {//2.99C 970325 
  2599.             htmlTagDelete(text,"<UL>");
  2600.             htmlTagDelete(text,"<OL>");
  2601.             ret = htmlTagInsertEx(text,"<LI>","<WZLI><OL><WZCUR><WZSELTEXT></OL>",TRUE);
  2602.             break;
  2603.         }
  2604.     }
  2605.     if (fParaatrTag) {
  2606.         if (fClip) {
  2607.             txJumpNpara(text,nparaEnd);
  2608.             txJumpParaEnd(text);
  2609.             txSelectEx(text,CLIP_CHAR);
  2610.             txJumpNpara(text,nparaTop);
  2611.             text->fClipMouse = TRUE;
  2612.         } else {
  2613.             txSelectQuit(text);
  2614.             txJumpNpara(text,nparaTop);
  2615.         }
  2616.     }
  2617.     txSetLyCurscreen(text,adrCurscreen);
  2618.     txSetDisp(text);
  2619.     return ret;
  2620. }
  2621.  
  2622. BOOL TXCMDBASE uiColor(TX* text)
  2623. {
  2624. // 文字列の色指定
  2625.     return txHtmlSet(text,TAG_FONT,0);
  2626. }
  2627.  
  2628. //2.99C 970326 new
  2629. insertArticleDisc
  2630. {
  2631. // 箇条書きの挿入
  2632.     if (htmlTagInsert(text,"<UL><LI><WZCUR></UL>")) {
  2633.         if (text->editmode) {txRight(text);txRight(text);}
  2634.         return TRUE;
  2635.     }
  2636.     return FALSE;
  2637. }
  2638.  
  2639. //2.99C 970326 new
  2640. insertArticleNum
  2641. {
  2642. // 番号付き箇条書きの挿入
  2643.     if (htmlTagInsert(text,"<OL><LI><WZCUR></OL>")) {
  2644.         if (text->editmode) {txRight(text);txRight(text);}
  2645.         return TRUE;
  2646.     }
  2647.     return FALSE;
  2648. }
  2649.  
  2650. //2.99C 970326 new
  2651. insertArticleDefine
  2652. {
  2653. // 定義型箇条書きの挿入
  2654.     if (htmlTagInsert(text,"<DL><DT><WZCUR><DD></DL>")) {
  2655.         if (text->editmode) {txRight(text);txRight(text);}
  2656.         return TRUE;
  2657.     }
  2658.     return FALSE;
  2659. }
  2660.  
  2661. //2.99C 970326 new
  2662. insertArticleTable
  2663. {
  2664. // 定義型箇条書きの挿入
  2665.     if (htmlTagInsert(text,"<TABLE><TR VALIGN=TOP><TD NOWRAP><WZCUR><TD></TABLE>")) {
  2666.         if (text->editmode) {txRight(text);txRight(text);}
  2667.         return TRUE;
  2668.     }
  2669.     return FALSE;
  2670. }
  2671.  
  2672. //2.99C 970326 HTML:「挿入|箇条書き」追加
  2673. BOOL TXCMDBASE insertArticle(TX* text)
  2674. {
  2675. // 箇条書きの形式を選んで挿入
  2676.     HDIALOG hd = dialog("箇条書きの挿入");
  2677.     static int mode;
  2678.     dialogControlRadioV(hd);
  2679.     dialogRadioID(hd,&mode,
  2680.         "箇条書き(&A)",
  2681.         "番号付き箇条書き(&N)",
  2682.         "定義型箇条書き(&D)",
  2683.         "表形式箇条書き(&T)"
  2684.     );
  2685.     if (dialogOpen(hd)) {
  2686.         switch(mode) {
  2687.             case 0:return insertArticleDisc();
  2688.             case 1:return insertArticleNum();
  2689.             case 2:return insertArticleDefine();
  2690.             case 3:return insertArticleTable();
  2691.         }
  2692.     }
  2693.     return FALSE;
  2694. }
  2695.  
  2696. //##tag delete
  2697.  
  2698. static int txSearchTag(TX* text,mchar* szTag,BOOL fPrev,int* pLeft)
  2699. {
  2700. // szTagは、"FONT"の様に指定する。
  2701. // 開始タグを見つけたらTAG_TOP,終了タグを見つけたらTAG_END,
  2702. // 見つからなかったら-1を返す
  2703. // カーソルは見つけたタグの'<'に設定する。
  2704. // pLeft:次を検索する前に、txLeftする回数を返す。
  2705.     *pLeft = 0;
  2706.     if (text->editmode) {
  2707.         int lch = strlen(szTag);
  2708.         SEARCHMODE mode = SEARCH_CUR|SEARCH_NOSELECT;
  2709.         if (fPrev) mode |= SEARCH_PREV;
  2710.         mchar szFind[2] = {CHAR_PLUG,0};
  2711.         while(1) {
  2712.             if (!txSearchEx(text,szFind,mode)) break;
  2713.             CHARATR charatr;
  2714.             charatrRead(text,txGetAddress(text),&charatr);
  2715.             PLUGHTMLTAG* plug = plugatrRead(text,charatrGetPlug(charatr));
  2716.             if (plug->head.modePlug == PLUG_HTML_TAG) {
  2717.                 int ret = TAG_TOP;
  2718.                 mchar* p = plug->szTag;
  2719.                 p++;
  2720.                 if (*p == '/') {
  2721.                     p++;
  2722.                     ret = TAG_END;
  2723.                 }
  2724.                 if (!strnicmp(szTag,p,lch) && !isalnum(szTag[lch])) {
  2725.                     return ret;
  2726.                 }
  2727.             }
  2728.             if (fPrev) {
  2729.                 if (!txLeft(text)) break;
  2730.             } else {
  2731.                 if (!txRight(text)) break;
  2732.             }
  2733.         }
  2734.         return -1;
  2735.     } else {
  2736.         SEARCHMODE mode = SEARCH_CUR|SEARCH_WORD|SEARCH_NOSELECT|SEARCH_NOSENSECASE;
  2737.         if (fPrev) mode |= SEARCH_PREV;
  2738.         //3.00A3 970508 *pLeft++ がpLeftの内容を+1してなかったので、呼び出し側で無限ループになることがあった
  2739.         // (*pLeft)++のように修正した
  2740.         while(1) {
  2741.             if (!txSearchEx(text,szTag,mode)) break;
  2742.             *pLeft = 0;
  2743.             if (!txLeft(text)) break;
  2744.             (*pLeft)++;
  2745.             mchar ch = txGetChar(text);
  2746.             if (ch == '<') {
  2747.                 return TAG_TOP;
  2748.             } else if (ch == '/') {
  2749.                 if (!txLeft(text)) break;
  2750.                 (*pLeft)++;
  2751.                 if (txGetChar(text) == '<') {
  2752.                     return TAG_END;
  2753.                 }
  2754.             }
  2755.             //
  2756.             while((*pLeft)--) txRight(text);
  2757.             *pLeft = 0;//3.00A3 970508 無限ループになった
  2758.             if (fPrev) {
  2759.                 if (!txLeft(text)) break;
  2760.             } else {
  2761.                 if (!txRight(text)) break;
  2762.             }
  2763.         }
  2764.         return -1;
  2765.     }
  2766. }
  2767.  
  2768. static BOOL txHtmlFlushArea(TX* textTarget,IFILE adrTop,IFILE adrEnd,int tag,BOOL fSelect)
  2769. {
  2770.     if (!textTarget->editmode) return TRUE;//2.97A 970302 
  2771.     if (adrTop > adrEnd) {
  2772.         IFILE tmp = adrTop;
  2773.         adrTop = adrEnd;
  2774.         adrEnd = tmp;
  2775.     }
  2776.     if (adrEnd > adrTop) {
  2777.         TX _txBody;
  2778.         TX* text = &_txBody;
  2779.         if (txInit(text,NULL)) {
  2780.             text->fHTML = TRUE;
  2781.             text->fForm = TRUE;
  2782.             text->fTxsemForceConvert = TRUE;
  2783.             text->fTxsemHtmlInside = TRUE;
  2784.             text->fTxsemNoUI = TRUE;
  2785. text->fSetWidthByWindow = TRUE;// for dialogaText
  2786. #if 0    // <H4 ALIGN=CENTER>...</H4>の変更が反映されない。
  2787.             text->fTxsemNoChangeReturn = TRUE;
  2788. #endif
  2789.             text->fDispTag = TRUE;
  2790.             txSetEditmode(text,1);
  2791.             //
  2792.             txJumpAddress(textTarget,adrTop);
  2793.             txSelectEx(textTarget,CLIP_CHAR);
  2794.             txJumpAddress(textTarget,adrEnd);
  2795.             //
  2796.             txPrivatePush(textTarget);
  2797.             txClipPaste(text,HCLIP_PRIVATE,TRUE,CLIP_CHAR);
  2798.             clipDeleteTop(HCLIP_PRIVATE);
  2799. //statprintf("%d",__LINE__);
  2800. //dialogaText(text,NULL);
  2801.             txSetEditmode(text,0);
  2802. //dialogaText(text,NULL);
  2803.             txSetEditmode(text,1);
  2804. //dialogaText(text,NULL);
  2805.             //
  2806.             txSelectDelete(textTarget);
  2807. //statprintf("%d",__LINE__);
  2808.             //
  2809.             NPARA nparaTop = textTarget->npara;
  2810.             PARAATR paraatrTop;
  2811.             paraatrRead(textTarget,nparaTop,¶atrTop);
  2812.             IFILE adr2Top = txGetAddress(textTarget);
  2813.             txInsertText(textTarget,text);
  2814.             IFILE adr2End = txGetAddress(textTarget);
  2815.             if (!tagIsParaatr(tag)) {
  2816.                 // 中央揃えなどがリセットされるので、復活させる
  2817.                 NPARA nparaEnd = textTarget->npara;
  2818.                 for (NPARA npara = nparaTop;npara <= nparaEnd;npara++) {
  2819.                     PARAATR paraatr;
  2820.                     paraatrRead(textTarget,npara,¶atr);
  2821.                     paraatr.modeAlign = paraatrTop.modeAlign;
  2822.                     paraatrWrite(textTarget,npara,¶atr);
  2823.                 }
  2824.             }
  2825. //statprintf("%d",__LINE__);
  2826.             if (fSelect) {
  2827.                 txJumpAddress(textTarget,adr2Top);
  2828.                 txSelectEx(textTarget,CLIP_CHAR);
  2829.                 txJumpAddress(textTarget,adr2End);
  2830.             }
  2831. //statprintf("%d",__LINE__);
  2832.             txDispAll(textTarget);
  2833.             txClose(text);
  2834.         }
  2835.     }
  2836.     return TRUE;
  2837. }
  2838.  
  2839. static BOOL tagIsPairAndSingle(int tag)
  2840. {
  2841. // tagがペアタグでも単独でも使われるものならTRUEを返す
  2842.     switch(tag) {
  2843.         case TAG_P:
  2844.         case TAG_LINK:
  2845.         case TAG_TD:
  2846.         case TAG_TH:
  2847.         case TAG_CENTER: return TRUE;
  2848.     }
  2849.     return FALSE;
  2850. }
  2851.  
  2852. static BOOL _htmlDeleteTag(TX* text,BOOL fFlush)
  2853. {
  2854. // タグの削除
  2855. // fFlush = 0:カーソル位置がタグのときは、タグと対応するペアタグを削除し、
  2856. // 間の文字列の属性を変更する。
  2857. // fFlush = 1:カーソル位置がタグのときは、対応するペアタグまでの文字列の属性を変更する。
  2858. // fFlush = 2:カーソル位置がタグのときは、対応するペアタグまでジャンプする
  2859.     mchar* p = text->buff + text->cur;
  2860.     int tag = 0;
  2861.     int lch = 0;
  2862.     BOOL fTagTop = FALSE;
  2863.     BOOL fAtrExist = TRUE;    // ATRがあるか?
  2864.     mchar szTag[CCHWORD];
  2865.     mchar* pTag;
  2866.     if (text->editmode) {
  2867.         if (*p == CHAR_PLUG) {
  2868. #if 1//2.99C 970326 
  2869.             PLUGHTMLTAG* plug = txGetCurPlug(text);
  2870.             if (text->fHTML && plug->head.modePlug == PLUG_HR && fFlush == 1) {
  2871.                 //2.99C 970326 HTML:水平線のプロパティを変更しても表示に反映されなかった
  2872.                 IFILE adrCurscreen = txGetAddressCurscreen(text);
  2873.                 IFILE adr = txGetAddress(text);
  2874.                 if (txHtmlFlushArea(text,adr,adr+1,0,FALSE)) {
  2875.                     // 余計な空白を削除
  2876.                     if (txIsCurReturn(text)) txDeleteChar(text);
  2877.                     //
  2878.                     txJumpAddress(text,adr);
  2879.                     txSetLyCurscreen(text,adrCurscreen);
  2880.                     return TRUE;
  2881.                 } else {
  2882.                     return FALSE;
  2883.                 }
  2884.             }
  2885.             if (plug->head.modePlug != PLUG_HTML_TAG) return FALSE;
  2886.             pTag = plug->szTag;
  2887.             lch = strlen(pTag);
  2888. #else
  2889.             CHARATR charatr;
  2890.             charatrRead(text,txGetAddress(text),&charatr);
  2891.             PLUGHTMLTAG* plug = plugatrRead(text,charatrGetPlug(charatr));
  2892.             if (plug->head.modePlug != PLUG_HTML_TAG) return FALSE;
  2893.             //
  2894.             pTag = plug->szTag;
  2895.             lch = strlen(pTag);
  2896. #endif
  2897.         } else {
  2898.             return FALSE;
  2899.         }
  2900.     } else if (*p == '<') {
  2901.         pTag = p;
  2902.         lch = szFindTagEnd(p) - p;
  2903.     } else {
  2904.         return FALSE;
  2905.     }
  2906.     tag = tagFromStr(pTag);
  2907.     fTagTop = !(pTag[1] == '/');
  2908.     int d = 1 + !fTagTop;
  2909.     sstrcpylen(szTag,pTag + d,lch - d);
  2910.     int l = strGetWordLen(szTag);
  2911.     if (l && szTag[l-1] == '>') {
  2912.         fAtrExist = FALSE;
  2913.         l--;
  2914.     }
  2915.     szTag[l] = 0;
  2916.     if (!fFlush && text->editmode && !text->fDispTag) {
  2917.         if (question(" %s タグを削除して良いですか?",szTag) != IDYES) return TRUE;
  2918.     }
  2919. //    information(szTag);
  2920.     if (tag == TAG_P) {
  2921.         if (!fTagTop || fAtrExist) {
  2922.             // OK
  2923.         } else {
  2924.             // <P>だけなら、閉タグなし。
  2925.             tag = 0;
  2926.         }
  2927.     }
  2928. #if 0    //3.00A3 970508 htmlDeleteTagが効いてなかった
  2929.     if (!fFlush) {
  2930.         //2.97A 970303 削除の場合はペアタグは見ない様にした。
  2931.         // 無限ループになる場合がある様だ。
  2932.         if (text->editmode) {
  2933.             txDeleteChar(text);
  2934.         } else {
  2935.             txDeleteBytes(text,lch);
  2936.         }
  2937.     } else 
  2938. #endif
  2939.     {
  2940.         switch(tag) {
  2941.             case TAG_P:
  2942.             case TAG_H:
  2943.             case TAG_UL:
  2944.             case TAG_B:
  2945.             case TAG_I:
  2946.             case TAG_U:
  2947.             case TAG_TT:
  2948.             case TAG_STRONG:
  2949.             case TAG_EM:
  2950.             case TAG_CITE:
  2951.             case TAG_CODE:
  2952.             case TAG_KBD:
  2953.             case TAG_SAMP:
  2954.             case TAG_VAR:
  2955.             case TAG_SUB:
  2956.             case TAG_SUP:
  2957.             case TAG_PRE:
  2958.             case TAG_FONT:
  2959.             case TAG_OL:
  2960.             case TAG_DL:
  2961.             case TAG_BLOCKQUOTE:
  2962.             case TAG_LINK:
  2963.             case TAG_ADDRESS:
  2964.             case TAG_TD:
  2965.             case TAG_TH:
  2966.             case TAG_CAPTION:
  2967.             case TAG_CENTER: {
  2968.                 // ペアタグも削除
  2969.                 BOOL fPandS = tagIsPairAndSingle(tag);//3.00A3 970508 
  2970.                 BOOL fPrev = !fTagTop;
  2971.                 int fEnd = fTagTop;
  2972.                 BOOL fFound = FALSE;
  2973.                 IFILE adr = txGetAddress(text);
  2974.                 int ly = text->ly;
  2975.                 txSetUndisp(text);
  2976.                 txMarkCur(text);
  2977.                 IFILE adrTop;
  2978.                 if (fFlush) {
  2979.                     // cursor move for search next
  2980.                     if (fPrev) {
  2981.                         adrTop = txGetAddress(text) + 1;
  2982.                         if (!txLeft(text)) break;
  2983.                     } else {
  2984.                         adrTop = txGetAddress(text);
  2985.                         if (!txRight(text)) break;
  2986.                     }
  2987.                 } else {
  2988.                     if (text->editmode) {
  2989.                         txDeleteChar(text);
  2990.                     } else {
  2991.                         txDeleteBytes(text,lch);
  2992.                     }
  2993.                     adrTop = txGetAddress(text);
  2994.                 }
  2995.                 while(1) {
  2996.                     int left;
  2997.                     int ret = txSearchTag(text,szTag,fPrev,&left);
  2998.                     if (ret == -1) break;
  2999.                     if (ret == TAG_TOP) {
  3000.                         fEnd++;
  3001.                         if (fPrev && fEnd == 1) {
  3002.                             fFound = TRUE;
  3003.                             break;
  3004.                         }
  3005.                         if (!fPrev && fPandS) {
  3006.                             break;//3.00A3 970508 for <TD>aaa<TD>bbb</TD>
  3007.                         }
  3008.                     } else {
  3009.                         fEnd--;
  3010.                         if (!fPrev && fEnd == 0) {
  3011.                             fFound = TRUE;
  3012.                             break;
  3013.                         }
  3014.                         if (fPrev && fPandS) {
  3015.                             break;//3.00A3 970508 for <TD>aaa<TD>bbb</TD>
  3016.                         }
  3017.                     }
  3018.                     //
  3019.                     while(left--) txRight(text);
  3020.                     if (fPrev) {
  3021.                         if (!txLeft(text)) break;
  3022.                     } else {
  3023.                         if (!txRight(text)) break;
  3024.                     }
  3025.                 }
  3026.                 if (fFound) {
  3027.                     if (fFlush == 2) {
  3028.                         //2.99 970313 
  3029.                     } else if (text->editmode) {
  3030.                         if (fFlush) {
  3031.                             if (!fPrev) {
  3032.                                 txRight(text);
  3033.                                 if (txIsCurReturn(text)) {
  3034.                                     //2.97 970223 <H4 ALIGN=CENTER>...</H4>の変更が反映される様に。
  3035.                                     txRight(text);
  3036.                                 }
  3037.                             }
  3038.                         } else {
  3039.                             txDeleteChar(text);
  3040.                         }
  3041.                         IFILE adrEnd = txGetAddress(text);
  3042.                         txHtmlFlushArea(text,adrTop,adrEnd,tag,FALSE);
  3043.                     } else {
  3044.                         mchar* p = text->buff + text->cur;
  3045.                         if (*p == '<') {
  3046.                             int lch = szFindTagEnd(p) - p;
  3047.                             txDeleteBytes(text,lch);
  3048.                         }
  3049.                     }
  3050.                 }
  3051.                 if (fFlush == 2) {
  3052.                     //2.99 970313 
  3053.                     if (fFound) {
  3054.                     } else {
  3055.                         txJumpAddress(text,adr);
  3056.                     }
  3057.                     txSetLy(text,ly);
  3058.                 } else if (fFlush) {
  3059.                     txJumpAddress(text,adr);
  3060.                     txSetLy(text,ly);
  3061.                 } else {
  3062.                     txJumpMarkCur(text);
  3063.                 }
  3064.                 txSetDisp(text);
  3065.                 break;
  3066.             }
  3067.             default: {
  3068.                 if (!fFlush) {
  3069.                     if (text->editmode) {
  3070.                         txDeleteChar(text);
  3071.                     } else {
  3072.                         txDeleteBytes(text,lch);
  3073.                     }
  3074.                 }
  3075.                 break;
  3076.             }
  3077.         }
  3078.     }
  3079.     return TRUE;
  3080. }
  3081.  
  3082. static BOOL htmlFlushCurTag(TX* text)
  3083. {
  3084. // 体裁モードのときに、カーソル位置にあるタグとペアタグの間の文字列を解釈。
  3085.     if (text->editmode) return _htmlDeleteTag(text,TRUE);
  3086.     return FALSE;
  3087. }
  3088.  
  3089. //2.99 970313 new
  3090. BOOL TXCMD TXAPI txHtmlJumpPairTag(TX* text)
  3091. {
  3092. // カーソル位置のHTMLタグのペアタグにジャンプ
  3093.     return _htmlDeleteTag(text,2);
  3094. }
  3095.  
  3096. BOOL TXCMD htmlDeleteTag(TX* text)
  3097. {
  3098. // タグの削除
  3099. // カーソル位置がタグのときは、タグと対応するペアタグを削除し、
  3100. // 間の文字列の属性を変更する。
  3101.     return _htmlDeleteTag(text,FALSE);
  3102. }
  3103.  
  3104. //##その他
  3105.  
  3106. #ifndef __FLAT__
  3107. extern "shell.dll" {
  3108.     HINSTANCE WINAPI ShellExecute(HWND,LPCSTR,LPCSTR,LPCSTR,LPCSTR,int);
  3109. }
  3110. #endif
  3111.  
  3112. #include "event.h"
  3113.  
  3114. BOOL TXCMDBASE htmlbrowser(TX* text)
  3115. {
  3116. // HTMLに関連付けられているブラウザで、現在編集中のHTMLテキストを表示
  3117.     if (text->fHTML) {
  3118.         if (text->fEdit) {
  3119.             int ret = question("%sは変更されています。\n保存しますか?",text->szfilename);
  3120.             if (ret == IDCANCEL) return FALSE;
  3121.             if (ret == IDYES) {
  3122.                 if (!txuiSave(text)) return FALSE;
  3123.             }
  3124.         }
  3125. #if 1//2.99C 970326 htmlbrowser:event.openURLを使うように変更
  3126.         return openURL(text,text->szfilename);
  3127. #else
  3128.         if (ShellExecute(text->hwndbase,"open",text->szfilename,NULL,NULL,SW_SHOW) <= 32) {
  3129.             return TRUE;
  3130.         }
  3131. #endif
  3132.     }
  3133.     return FALSE;
  3134. }
  3135.  
  3136. extern "word" BOOL txGetWordCaption(TX* text,txstr szCaption);
  3137.  
  3138. //2.99 970313 new
  3139. BOOL TXAPI TXCMDBASE txuiInsertAnchor(TX* text)
  3140. {
  3141. // アンカーの挿入
  3142.     BOOL fClip = FALSE;
  3143.     txstr szCaption;
  3144.     if (txGetWordCaption(text,szCaption)) {
  3145.         fClip = TRUE;
  3146.     } else {
  3147.         //2.99C 970325 キャプションのデフォルトはスペース一個が良い
  3148.         szCaption = " ";
  3149.     }
  3150.     //
  3151.     HDIALOG hd = dialog("アンカーの挿入");
  3152.     txstr szAnchor;
  3153.     dialogStr(hd,"アンカー(&A):",szAnchor,20,33);
  3154.     dialogStr(hd,"キャプション(&C):",szCaption,20,33);
  3155.     if (dialogOpen(hd)) {
  3156.         txSelectDelete(text);
  3157.         txstr sz = "<A NAME=\"";
  3158.         sz += szAnchor;
  3159.         sz += "\">";
  3160.         txInsertHtmlSzTag(text,sz,TAG_LINK);
  3161.         txInsert(text,szCaption);
  3162.         txInsertHtmlSzTag(text,"</A>",TAG_LINK);
  3163.         return TRUE;
  3164.     }
  3165.     return FALSE;
  3166. }
  3167.  
  3168. LfToBr
  3169. {
  3170. // 改行を<BR>に変換
  3171. //3.00A 970502 WZ2.0のword.txLfToBr復活
  3172.     if (!text->fClip) {
  3173.         information("範囲を選択してから実行してください。");
  3174.         return FALSE;
  3175.     } else {
  3176.         txWalkStart(text);
  3177.         while(txIsWalking(text)) {
  3178.             txJumpParaEnd(text);
  3179.             txInsertHtmlSzTag(text,"<BR>",TAG_BR);
  3180.             if (!txNextPara(text)) break;
  3181.         }
  3182.         txWalkEnd(text);
  3183.         return TRUE;
  3184.     }
  3185. }
  3186.  
  3187. main
  3188. {
  3189. }
  3190.